diff --git a/data/nested_cubes.geo b/data/nested_cubes.geo new file mode 100644 index 0000000000..9809f4a5e2 --- /dev/null +++ b/data/nested_cubes.geo @@ -0,0 +1,131 @@ +// Define the cube sizes +L_outer = 1.0; +L_inner = 0.5; + +// Set mesh size and algorithm +mesh_size = 0.2; +Mesh.Algorithm3D = 1; // Delaunay algorithm for 3D mesh +Mesh.CharacteristicLengthFactor = 1.0; +Mesh.MshFileVersion = 2.2; + +// Define center point for concentric cubes +cx = 0.5; +cy = 0.5; +cz = 0.5; + +// Define the points (vertices of the outer cube) +Point(1) = {cx-L_outer/2, cy-L_outer/2, cz-L_outer/2, mesh_size}; +Point(2) = {cx+L_outer/2, cy-L_outer/2, cz-L_outer/2, mesh_size}; +Point(3) = {cx+L_outer/2, cy+L_outer/2, cz-L_outer/2, mesh_size}; +Point(4) = {cx-L_outer/2, cy+L_outer/2, cz-L_outer/2, mesh_size}; +Point(5) = {cx-L_outer/2, cy-L_outer/2, cz+L_outer/2, mesh_size}; +Point(6) = {cx+L_outer/2, cy-L_outer/2, cz+L_outer/2, mesh_size}; +Point(7) = {cx+L_outer/2, cy+L_outer/2, cz+L_outer/2, mesh_size}; +Point(8) = {cx-L_outer/2, cy+L_outer/2, cz+L_outer/2, mesh_size}; + +// Define the points (vertices of the inner cube) +Point(9) = {cx-L_inner/2, cy-L_inner/2, cz-L_inner/2, mesh_size}; +Point(10) = {cx+L_inner/2, cy-L_inner/2, cz-L_inner/2, mesh_size}; +Point(11) = {cx+L_inner/2, cy+L_inner/2, cz-L_inner/2, mesh_size}; +Point(12) = {cx-L_inner/2, cy+L_inner/2, cz-L_inner/2, mesh_size}; +Point(13) = {cx-L_inner/2, cy-L_inner/2, cz+L_inner/2, mesh_size}; +Point(14) = {cx+L_inner/2, cy-L_inner/2, cz+L_inner/2, mesh_size}; +Point(15) = {cx+L_inner/2, cy+L_inner/2, cz+L_inner/2, mesh_size}; +Point(16) = {cx-L_inner/2, cy+L_inner/2, cz+L_inner/2, mesh_size}; + +// Define the lines (edges of the outer cube) +Line(1) = {1, 2}; +Line(2) = {2, 3}; +Line(3) = {3, 4}; +Line(4) = {4, 1}; +Line(5) = {5, 6}; +Line(6) = {6, 7}; +Line(7) = {7, 8}; +Line(8) = {8, 5}; +Line(9) = {1, 5}; +Line(10) = {2, 6}; +Line(11) = {3, 7}; +Line(12) = {4, 8}; + +// Define the lines (edges of the inner cube) +Line(13) = {9, 10}; +Line(14) = {10, 11}; +Line(15) = {11, 12}; +Line(16) = {12, 9}; +Line(17) = {13, 14}; +Line(18) = {14, 15}; +Line(19) = {15, 16}; +Line(20) = {16, 13}; +Line(21) = {9, 13}; +Line(22) = {10, 14}; +Line(23) = {11, 15}; +Line(24) = {12, 16}; + +// Define the surfaces (faces of the outer cube) +Line Loop(1) = {1, 2, 3, 4}; +Plane Surface(1) = {1}; + +Line Loop(2) = {5, 6, 7, 8}; +Plane Surface(2) = {2}; + +Line Loop(3) = {9, 5, -10, -1}; +Plane Surface(3) = {3}; + +Line Loop(4) = {10, 6, -11, -2}; +Plane Surface(4) = {4}; + +Line Loop(5) = {11, 7, -12, -3}; +Plane Surface(5) = {5}; + +Line Loop(6) = {12, 8, -9, -4}; +Plane Surface(6) = {6}; + +// Define the surfaces (faces of the inner cube) +Line Loop(7) = {13, 14, 15, 16}; +Plane Surface(7) = {7}; + +Line Loop(8) = {17, 18, 19, 20}; +Plane Surface(8) = {8}; + +Line Loop(9) = {21, 17, -22, -13}; +Plane Surface(9) = {9}; + +Line Loop(10) = {22, 18, -23, -14}; +Plane Surface(10) = {10}; + +Line Loop(11) = {23, 19, -24, -15}; +Plane Surface(11) = {11}; + +Line Loop(12) = {24, 20, -21, -16}; +Plane Surface(12) = {12}; + +// Define the volumes +Surface Loop(1) = {1, 2, 3, 4, 5, 6}; +Surface Loop(2) = {7, 8, 9, 10, 11, 12}; +Volume(1) = {1, 2}; // Outer volume with inner hole +Volume(2) = {2}; // Inner volume + +// Assign physical groups +Physical Volume(1) = {1}; // Outer volume +Physical Volume(2) = {2}; // Inner volume + +// Outer cube surfaces +Physical Surface(1) = {1}; // Outer bottom +Physical Surface(2) = {2}; // Outer top +Physical Surface(3) = {3}; // Outer front +Physical Surface(4) = {4}; // Outer right +Physical Surface(5) = {5}; // Outer back +Physical Surface(6) = {6}; // Outer left + +// Inner cube surfaces +Physical Surface(7) = {7}; // Inner bottom (-xy) +Physical Surface(8) = {8}; // Inner top (+xy) +Physical Surface(9) = {9}; // Inner front (-xz) +Physical Surface(10) = {10}; // Inner right (+yz) +Physical Surface(11) = {11}; // Inner back (+xz) +Physical Surface(12) = {12}; // Inner left (-yz) + +// Mesh control +Mesh.OptimizeNetgen = 1; +Mesh.Optimize = 1; +Mesh.ElementOrder = 1; diff --git a/data/nested_cubes.msh b/data/nested_cubes.msh new file mode 100644 index 0000000000..b9c97b42f8 --- /dev/null +++ b/data/nested_cubes.msh @@ -0,0 +1,2300 @@ +$MeshFormat +2.2 0 8 +$EndMeshFormat +$Nodes +348 +1 0 0 0 +2 1 0 0 +3 1 1 0 +4 0 1 0 +5 0 0 1 +6 1 0 1 +7 1 1 1 +8 0 1 1 +9 0.25 0.25 0.25 +10 0.75 0.25 0.25 +11 0.75 0.75 0.25 +12 0.25 0.75 0.25 +13 0.25 0.25 0.75 +14 0.75 0.25 0.75 +15 0.75 0.75 0.75 +16 0.25 0.75 0.75 +17 0.1999999999995579 0 0 +18 0.3999999999989749 0 0 +19 0.5999999999989468 0 0 +20 0.7999999999994734 0 0 +21 1 0.1999999999995579 0 +22 1 0.3999999999989749 0 +23 1 0.5999999999989468 0 +24 1 0.7999999999994734 0 +25 0.7999999999999998 1 0 +26 0.6000000000013869 1 0 +27 0.4000000000016644 1 0 +28 0.2000000000008322 1 0 +29 0 0.7999999999999998 0 +30 0 0.6000000000013869 0 +31 0 0.4000000000016644 0 +32 0 0.2000000000008322 0 +33 0.1999999999995579 0 1 +34 0.3999999999989749 0 1 +35 0.5999999999989468 0 1 +36 0.7999999999994734 0 1 +37 1 0.1999999999995579 1 +38 1 0.3999999999989749 1 +39 1 0.5999999999989468 1 +40 1 0.7999999999994734 1 +41 0.7999999999999998 1 1 +42 0.6000000000013869 1 1 +43 0.4000000000016644 1 1 +44 0.2000000000008322 1 1 +45 0 0.7999999999999998 1 +46 0 0.6000000000013869 1 +47 0 0.4000000000016644 1 +48 0 0.2000000000008322 1 +49 0 0 0.1999999999995579 +50 0 0 0.3999999999989749 +51 0 0 0.5999999999989468 +52 0 0 0.7999999999994734 +53 1 0 0.1999999999995579 +54 1 0 0.3999999999989749 +55 1 0 0.5999999999989468 +56 1 0 0.7999999999994734 +57 1 1 0.1999999999995579 +58 1 1 0.3999999999989749 +59 1 1 0.5999999999989468 +60 1 1 0.7999999999994734 +61 0 1 0.1999999999995579 +62 0 1 0.3999999999989749 +63 0 1 0.5999999999989468 +64 0 1 0.7999999999994734 +65 0.4166666666671291 0.25 0.25 +66 0.5833333333335646 0.25 0.25 +67 0.75 0.4166666666671291 0.25 +68 0.75 0.5833333333335646 0.25 +69 0.5833333333342582 0.75 0.25 +70 0.4166666666675914 0.75 0.25 +71 0.25 0.5833333333342582 0.25 +72 0.25 0.4166666666675914 0.25 +73 0.4166666666671291 0.25 0.75 +74 0.5833333333335646 0.25 0.75 +75 0.75 0.4166666666671291 0.75 +76 0.75 0.5833333333335646 0.75 +77 0.5833333333342582 0.75 0.75 +78 0.4166666666675914 0.75 0.75 +79 0.25 0.5833333333342582 0.75 +80 0.25 0.4166666666675914 0.75 +81 0.25 0.25 0.4166666666671291 +82 0.25 0.25 0.5833333333335646 +83 0.75 0.25 0.4166666666671291 +84 0.75 0.25 0.5833333333335646 +85 0.75 0.75 0.4166666666671291 +86 0.75 0.75 0.5833333333335646 +87 0.25 0.75 0.4166666666671291 +88 0.25 0.75 0.5833333333335646 +89 0.1637066120482703 0.4886650857430957 0 +90 0.8353496491682408 0.4902996892628636 0 +91 0.4939184515862498 0.1323760430705655 0 +92 0.4983653964791732 0.827738658027235 0 +93 0.3007481903591385 0.8307029123438383 0 +94 0.3961598772770956 0.670734446840082 0 +95 0.6002015905170176 0.6755188916874412 0 +96 0.5000000000025092 0.4803847577304367 0 +97 0.830576912698845 0.3001844933888438 0 +98 0.8146996124644995 0.6891493782611213 0 +99 0.1693821434765657 0.3001135766065062 0 +100 0.1881896957092664 0.6836414884284229 0 +101 0.3157845613177837 0.1865278143482666 0 +102 0.694476072991297 0.8409994610768936 0 +103 0.6859211635201188 0.1724872797865501 0 +104 0.3214614339243645 0.3873807148762196 0 +105 0.6685228257598594 0.3853248791658106 0 +106 0.4768832689941644 0.3174113279240561 0 +107 0.1464101615147966 0.8535898384854262 0 +108 0.8535898384857052 0.8535898384855642 0 +109 0.1464101615145241 0.1464101615148656 0 +110 0.8535898384865049 0.1464101615132356 0 +111 0.310303028765564 0.5417981355851316 0 +112 0.6896969712339486 0.5417981355822887 0 +113 0.1637066120482703 0.4886650857430957 1 +114 0.8353496491682408 0.4902996892628636 1 +115 0.4939184515862498 0.1323760430705655 1 +116 0.4983653964791732 0.827738658027235 1 +117 0.3007481903591385 0.8307029123438383 1 +118 0.3961598772770956 0.670734446840082 1 +119 0.6002015905170176 0.6755188916874412 1 +120 0.5000000000025092 0.4803847577304367 1 +121 0.830576912698845 0.3001844933888438 1 +122 0.8146996124644995 0.6891493782611213 1 +123 0.1693821434765657 0.3001135766065062 1 +124 0.1881896957092664 0.6836414884284229 1 +125 0.3157845613177837 0.1865278143482666 1 +126 0.694476072991297 0.8409994610768936 1 +127 0.6859211635201188 0.1724872797865501 1 +128 0.3214614339243645 0.3873807148762196 1 +129 0.6685228257598594 0.3853248791658106 1 +130 0.4768832689941644 0.3174113279240561 1 +131 0.1464101615147966 0.8535898384854262 1 +132 0.8535898384857052 0.8535898384855642 1 +133 0.1464101615145241 0.1464101615148656 1 +134 0.8535898384865049 0.1464101615132356 1 +135 0.310303028765564 0.5417981355851316 1 +136 0.6896969712339486 0.5417981355822887 1 +137 0.132376043070332 0 0.5060815484120404 +138 0.8277386580269728 0 0.5016346035215296 +139 0.4886650857404938 0 0.8362933879515394 +140 0.4902996892629923 0 0.1646503508318973 +141 0.830702912343411 0 0.6992518096417444 +142 0.6707344468389502 0 0.603840122723256 +143 0.6755188916871792 0 0.3997984094834469 +144 0.4803847577297647 0 0.499999999998517 +145 0.3001844933888483 0 0.1694230873013571 +146 0.300113576604068 0 0.8306178565235275 +147 0.6891493782612514 0 0.1853003875356531 +148 0.6836414884271127 0 0.8118103042908406 +149 0.1865278143471139 0 0.6842154386815414 +150 0.8409994610768514 0 0.3055239270088661 +151 0.1724872797861845 0 0.3140788364787562 +152 0.3873807148745535 0 0.6785385660753565 +153 0.3853248791655679 0 0.3314771742399999 +154 0.3174113279233923 0 0.5231167310049954 +155 0.8535898384857058 0 0.1464101615140347 +156 0.8535898384858706 0 0.8535898384858706 +157 0.1464101615134316 0 0.1464101615134316 +158 0.1464101615132356 0 0.8535898384865049 +159 0.5417981355826432 0 0.6896969712334735 +160 0.5417981355823797 0 0.3103030287659322 +161 1 0.132376043070332 0.5060815484120404 +162 1 0.8277386580269728 0.5016346035215296 +163 1 0.4886650857404938 0.8362933879515394 +164 1 0.4902996892629923 0.1646503508318973 +165 1 0.830702912343411 0.6992518096417444 +166 1 0.6707344468389502 0.603840122723256 +167 1 0.6755188916871792 0.3997984094834469 +168 1 0.4803847577297647 0.499999999998517 +169 1 0.3001844933888483 0.1694230873013571 +170 1 0.300113576604068 0.8306178565235275 +171 1 0.6891493782612514 0.1853003875356531 +172 1 0.6836414884271127 0.8118103042908406 +173 1 0.1865278143471139 0.6842154386815414 +174 1 0.8409994610768514 0.3055239270088661 +175 1 0.1724872797861845 0.3140788364787562 +176 1 0.3873807148745535 0.6785385660753565 +177 1 0.3853248791655679 0.3314771742399999 +178 1 0.3174113279233923 0.5231167310049954 +179 1 0.8535898384857058 0.1464101615140347 +180 1 0.8535898384858706 0.8535898384858706 +181 1 0.1464101615134316 0.1464101615134316 +182 1 0.1464101615132356 0.8535898384865049 +183 1 0.5417981355826432 0.6896969712334735 +184 1 0.5417981355823797 0.3103030287659322 +185 0.5118616330511603 1 0.1580808106225993 +186 0.4983653964791491 1 0.8277386580273275 +187 0.1627551561804241 1 0.4903320945045406 +188 0.8363011050364915 1 0.4919666980268533 +189 0.3007481903592759 1 0.8307029123438127 +190 0.3961510017805308 1 0.6707475526387774 +191 0.6002089867643424 1 0.6755341817865503 +192 0.5000000000022617 1 0.4803847577307706 +193 0.3180797153176176 1 0.1916013298809237 +194 0.6999218203955905 1 0.1482630627082204 +195 0.8148028884947371 1 0.6893290653691591 +196 0.188044897945855 1 0.6838927383356037 +197 0.6944945183708917 1 0.8410319572781051 +198 0.1619694349440737 1 0.3061901991990804 +199 0.8086055710888786 1 0.294576500268227 +200 0.3204336302739758 1 0.3895300118228731 +201 0.6641620538137978 1 0.4005576545893526 +202 0.4695476994135115 1 0.3267949192435416 +203 0.8535898384857353 1 0.8535898384855942 +204 0.1464101615147883 1 0.8535898384852936 +205 0.1464101615145383 1 0.1464101615141969 +206 0.8535898384865941 1 0.1464101615132874 +207 0.3102497757859662 1 0.5418767703783816 +208 0.6880178165220481 1 0.5433547225650606 +209 0.6092224884824112 1 0.2727742661388043 +210 0 0.5118616330511603 0.1580808106225993 +211 0 0.4983653964791491 0.8277386580273275 +212 0 0.1627551561804241 0.4903320945045406 +213 0 0.8363011050364915 0.4919666980268533 +214 0 0.3007481903592759 0.8307029123438127 +215 0 0.3961510017805308 0.6707475526387774 +216 0 0.6002089867643424 0.6755341817865503 +217 0 0.5000000000022617 0.4803847577307706 +218 0 0.3180797153176176 0.1916013298809237 +219 0 0.6999218203955905 0.1482630627082204 +220 0 0.8148028884947371 0.6893290653691591 +221 0 0.188044897945855 0.6838927383356037 +222 0 0.6944945183708917 0.8410319572781051 +223 0 0.1619694349440737 0.3061901991990804 +224 0 0.8086055710888786 0.294576500268227 +225 0 0.3204336302739758 0.3895300118228731 +226 0 0.6641620538137978 0.4005576545893526 +227 0 0.4695476994135115 0.3267949192435416 +228 0 0.8535898384857353 0.8535898384855942 +229 0 0.1464101615147883 0.8535898384852936 +230 0 0.1464101615145383 0.1464101615141969 +231 0 0.8535898384865941 0.1464101615132874 +232 0 0.3102497757859662 0.5418767703783816 +233 0 0.6880178165220481 0.5433547225650606 +234 0 0.6092224884824112 0.2727742661388043 +235 0.5992761924351406 0.5000000000003489 0.25 +236 0.3985666893404116 0.5000000000007354 0.25 +237 0.4996404802960919 0.373719959142143 0.25 +238 0.4996404802964234 0.6262800408582622 0.25 +239 0.3711598774264825 0.6288401225740224 0.25 +240 0.371159877425882 0.3711598774260083 0.25 +241 0.6288401225744236 0.3711598774257657 0.25 +242 0.6288401225746559 0.6288401225744665 0.25 +243 0.5992761924351406 0.5000000000003489 0.75 +244 0.3985666893404116 0.5000000000007354 0.75 +245 0.4996404802960919 0.373719959142143 0.75 +246 0.4996404802964234 0.6262800408582622 0.75 +247 0.3711598774264825 0.6288401225740224 0.75 +248 0.371159877425882 0.3711598774260083 0.75 +249 0.6288401225744236 0.3711598774257657 0.75 +250 0.6288401225746559 0.6288401225744665 0.75 +251 0.5992761924350478 0.25 0.5000000000002408 +252 0.3985666893404578 0.25 0.500000000000287 +253 0.499640480296097 0.25 0.3737199591420422 +254 0.4996404802960283 0.25 0.626280040858159 +255 0.3711598774259597 0.25 0.3711598774259597 +256 0.3711598774258666 0.25 0.6288401225743229 +257 0.6288401225741044 0.25 0.6288401225741044 +258 0.6288401225744236 0.25 0.3711598774257658 +259 0.75 0.5000000000002407 0.5992761924350478 +260 0.75 0.500000000000287 0.3985666893404578 +261 0.75 0.3737199591420421 0.4996404802960971 +262 0.75 0.6262800408581591 0.4996404802960283 +263 0.75 0.3711598774259598 0.3711598774259598 +264 0.75 0.6288401225743229 0.3711598774258665 +265 0.75 0.6288401225741043 0.6288401225741043 +266 0.75 0.3711598774257658 0.6288401225744237 +267 0.5992761924352215 0.75 0.5000000000002759 +268 0.3985666893405871 0.75 0.5000000000002924 +269 0.4996404802964467 0.75 0.3737199591420557 +270 0.4996404802964466 0.75 0.626280040858164 +271 0.3711598774262678 0.75 0.3711598774261416 +272 0.3711598774263659 0.75 0.6288401225739497 +273 0.6288401225747541 0.75 0.3711598774256247 +274 0.6288401225746559 0.75 0.6288401225744665 +275 0.25 0.5992761924352215 0.5000000000002759 +276 0.25 0.3985666893405871 0.5000000000002924 +277 0.25 0.4996404802964467 0.3737199591420557 +278 0.25 0.4996404802964466 0.626280040858164 +279 0.25 0.3711598774262678 0.3711598774261416 +280 0.25 0.3711598774263659 0.6288401225739497 +281 0.25 0.6288401225747541 0.3711598774256247 +282 0.25 0.6288401225746559 0.6288401225744665 +283 0.3119616518394711 0.9010284154813043 0.9010352551624986 +284 0.09808726641727275 0.4974818634394728 0.8978462182471361 +285 0.9008152141457402 0.4973842456437976 0.09918633356326059 +286 0.6853343737589362 0.9038796669631077 0.9039328700870516 +287 0.9007647302822038 0.4971814709384674 0.901318156384596 +288 0.8947778717595229 0.9010713335769276 0.6835730548520513 +289 0.09832121377921646 0.8995656365624847 0.5142161828307892 +290 0.3156698639604323 0.9014184800393725 0.1071094441293657 +291 0.8727873737676635 0.09335585527113388 0.4498196307014093 +292 0.551426710155882 0.09519317754137827 0.131264828146284 +293 0.7164498486866168 0.8997524644077883 0.14230156118081 +294 0.5504782119058711 0.09508581253025442 0.8688588599095672 +295 0.1054626454205513 0.7015665480167667 0.1355162545615531 +296 0.09477598255742753 0.2827040579279901 0.1038886763141691 +297 0.8866302227128426 0.9035034192623553 0.276312260388072 +298 0.08848258989555439 0.1011224469666767 0.4592740821703157 +299 0.4988158396813867 0.8983326230993298 0.8983359590129811 +300 0.8994601511321615 0.7131664317404441 0.8981605126933918 +301 0.8876537692469896 0.8970579019336683 0.1134302968951015 +302 0.1040759863123409 0.7154517963654562 0.9073232114186928 +303 0.1092121108280766 0.1068838899041324 0.1068442433702476 +304 0.1055858984704815 0.8859968426239964 0.1132204881697278 +305 0.7200524756256578 0.0970587113254848 0.8974343633261492 +306 0.8990558185436137 0.7150265826438587 0.1008684005607349 +307 0.09636964431303721 0.280639431830447 0.9034924068638299 +308 0.3160878801800472 0.1051709727603094 0.9014409067170824 +309 0.3162249609277002 0.1050990647608995 0.0986678679368133 +310 0.5458622388388001 0.8706396798134294 0.1021379853058123 +311 0.09921976449050003 0.4602535428107727 0.09863084663624319 +312 0.8976141636055056 0.8724933008987038 0.4559657895052981 +313 0.1029148469784167 0.1051397757165229 0.6819484953862597 +314 0.7209289378989345 0.09708010181911768 0.1014155260016273 +315 0.9037081535295804 0.2805918596951891 0.09630821988231754 +316 0.9035752422317462 0.2805936282555974 0.9036916081416617 +317 0.1013630138799248 0.8997987999567157 0.7147596801122958 +318 0.9009518294054997 0.1048899266395993 0.6834695330939755 +319 0.09797011085025742 0.8878763034748807 0.2789583690389103 +320 0.09808870142001308 0.0935875941946847 0.2791449351565644 +321 0.9070111947794535 0.09919596680780536 0.2771993847495282 +322 0.890552944069698 0.892118770412245 0.8905367406835931 +323 0.1095046238418262 0.1072272209265222 0.890341059817952 +324 0.8931548827920728 0.1069595839097432 0.8910525642095892 +325 0.1085678336809069 0.8927288272677599 0.89251009811148 +326 0.8937483133697692 0.1062803586086174 0.1059081380558236 +327 0.478708725468739 0.4182164726993839 0.5476841387841291 +328 0.5415945078264262 0.5830853093057138 0.4154275620644178 +329 0.4958957147101553 0.3152145091741961 0.678399553963919 +330 0.4916477894957504 0.3515699907797985 0.3560290419480865 +331 0.505011291679053 0.6837744039730386 0.315898687762515 +332 0.4909683480076309 0.604286654047807 0.6482163483520499 +333 0.6554955371712985 0.4643111213007727 0.6618077116936049 +334 0.3682959885446299 0.6146670906666549 0.5168535558907257 +335 0.3298756214257418 0.3292974747606303 0.4960625966336104 +336 0.6687661970201751 0.5381291908191458 0.3224327032011914 +337 0.3502766224014454 0.5029144623089025 0.6466407465962936 +338 0.6675735080759542 0.6835010153463738 0.4592904005071918 +339 0.6453856094062125 0.3542390881876538 0.4998504608362304 +340 0.3617600818670145 0.4885854836495122 0.3758076467748428 +341 0.3525476646612073 0.6540947070171234 0.65843796006775 +342 0.3511092315553163 0.6486342654201749 0.3506137086749549 +343 0.6563984166458919 0.3392918243916224 0.6529297783518891 +344 0.6602750245063472 0.6689315534882371 0.3304778413828625 +345 0.3476195233377799 0.3500535096250754 0.3496562259543969 +346 0.6301703278743752 0.3926080832649276 0.3518389363462509 +347 0.3443938011728104 0.3325772197434613 0.6613973417187416 +348 0.6350667702509261 0.6338273235673252 0.6107090988574787 +$EndNodes +$Elements +1943 +1 2 2 1 1 1 17 109 +2 2 2 1 1 32 1 109 +3 2 2 1 1 20 2 110 +4 2 2 1 1 2 21 110 +5 2 2 1 1 24 3 108 +6 2 2 1 1 3 25 108 +7 2 2 1 1 28 4 107 +8 2 2 1 1 4 29 107 +9 2 2 1 1 17 18 101 +10 2 2 1 1 17 101 109 +11 2 2 1 1 18 19 91 +12 2 2 1 1 18 91 101 +13 2 2 1 1 19 20 103 +14 2 2 1 1 91 19 103 +15 2 2 1 1 103 20 110 +16 2 2 1 1 21 22 97 +17 2 2 1 1 21 97 110 +18 2 2 1 1 22 23 90 +19 2 2 1 1 22 90 97 +20 2 2 1 1 23 24 98 +21 2 2 1 1 90 23 98 +22 2 2 1 1 98 24 108 +23 2 2 1 1 25 26 102 +24 2 2 1 1 25 102 108 +25 2 2 1 1 26 27 92 +26 2 2 1 1 26 92 102 +27 2 2 1 1 27 28 93 +28 2 2 1 1 92 27 93 +29 2 2 1 1 93 28 107 +30 2 2 1 1 29 30 100 +31 2 2 1 1 29 100 107 +32 2 2 1 1 30 31 89 +33 2 2 1 1 30 89 100 +34 2 2 1 1 31 32 99 +35 2 2 1 1 89 31 99 +36 2 2 1 1 99 32 109 +37 2 2 1 1 89 99 104 +38 2 2 1 1 100 89 111 +39 2 2 1 1 89 104 111 +40 2 2 1 1 97 90 105 +41 2 2 1 1 90 98 112 +42 2 2 1 1 105 90 112 +43 2 2 1 1 101 91 106 +44 2 2 1 1 91 103 106 +45 2 2 1 1 92 93 94 +46 2 2 1 1 92 94 95 +47 2 2 1 1 92 95 102 +48 2 2 1 1 94 93 100 +49 2 2 1 1 100 93 107 +50 2 2 1 1 95 94 96 +51 2 2 1 1 96 94 111 +52 2 2 1 1 94 100 111 +53 2 2 1 1 95 96 112 +54 2 2 1 1 95 98 102 +55 2 2 1 1 98 95 112 +56 2 2 1 1 96 104 106 +57 2 2 1 1 104 96 111 +58 2 2 1 1 105 96 106 +59 2 2 1 1 96 105 112 +60 2 2 1 1 103 97 105 +61 2 2 1 1 97 103 110 +62 2 2 1 1 102 98 108 +63 2 2 1 1 99 101 104 +64 2 2 1 1 101 99 109 +65 2 2 1 1 104 101 106 +66 2 2 1 1 103 105 106 +67 2 2 2 2 5 33 133 +68 2 2 2 2 48 5 133 +69 2 2 2 2 36 6 134 +70 2 2 2 2 6 37 134 +71 2 2 2 2 40 7 132 +72 2 2 2 2 7 41 132 +73 2 2 2 2 44 8 131 +74 2 2 2 2 8 45 131 +75 2 2 2 2 33 34 125 +76 2 2 2 2 33 125 133 +77 2 2 2 2 34 35 115 +78 2 2 2 2 34 115 125 +79 2 2 2 2 35 36 127 +80 2 2 2 2 115 35 127 +81 2 2 2 2 127 36 134 +82 2 2 2 2 37 38 121 +83 2 2 2 2 37 121 134 +84 2 2 2 2 38 39 114 +85 2 2 2 2 38 114 121 +86 2 2 2 2 39 40 122 +87 2 2 2 2 114 39 122 +88 2 2 2 2 122 40 132 +89 2 2 2 2 41 42 126 +90 2 2 2 2 41 126 132 +91 2 2 2 2 42 43 116 +92 2 2 2 2 42 116 126 +93 2 2 2 2 43 44 117 +94 2 2 2 2 116 43 117 +95 2 2 2 2 117 44 131 +96 2 2 2 2 45 46 124 +97 2 2 2 2 45 124 131 +98 2 2 2 2 46 47 113 +99 2 2 2 2 46 113 124 +100 2 2 2 2 47 48 123 +101 2 2 2 2 113 47 123 +102 2 2 2 2 123 48 133 +103 2 2 2 2 113 123 128 +104 2 2 2 2 124 113 135 +105 2 2 2 2 113 128 135 +106 2 2 2 2 121 114 129 +107 2 2 2 2 114 122 136 +108 2 2 2 2 129 114 136 +109 2 2 2 2 125 115 130 +110 2 2 2 2 115 127 130 +111 2 2 2 2 116 117 118 +112 2 2 2 2 116 118 119 +113 2 2 2 2 116 119 126 +114 2 2 2 2 118 117 124 +115 2 2 2 2 124 117 131 +116 2 2 2 2 119 118 120 +117 2 2 2 2 120 118 135 +118 2 2 2 2 118 124 135 +119 2 2 2 2 119 120 136 +120 2 2 2 2 119 122 126 +121 2 2 2 2 122 119 136 +122 2 2 2 2 120 128 130 +123 2 2 2 2 128 120 135 +124 2 2 2 2 129 120 130 +125 2 2 2 2 120 129 136 +126 2 2 2 2 127 121 129 +127 2 2 2 2 121 127 134 +128 2 2 2 2 126 122 132 +129 2 2 2 2 123 125 128 +130 2 2 2 2 125 123 133 +131 2 2 2 2 128 125 130 +132 2 2 2 2 127 129 130 +133 2 2 3 3 17 1 157 +134 2 2 3 3 1 49 157 +135 2 2 3 3 2 20 155 +136 2 2 3 3 53 2 155 +137 2 2 3 3 5 33 158 +138 2 2 3 3 52 5 158 +139 2 2 3 3 36 6 156 +140 2 2 3 3 6 56 156 +141 2 2 3 3 18 17 145 +142 2 2 3 3 145 17 157 +143 2 2 3 3 19 18 140 +144 2 2 3 3 140 18 145 +145 2 2 3 3 20 19 147 +146 2 2 3 3 19 140 147 +147 2 2 3 3 20 147 155 +148 2 2 3 3 33 34 146 +149 2 2 3 3 33 146 158 +150 2 2 3 3 34 35 139 +151 2 2 3 3 34 139 146 +152 2 2 3 3 35 36 148 +153 2 2 3 3 139 35 148 +154 2 2 3 3 148 36 156 +155 2 2 3 3 49 50 151 +156 2 2 3 3 49 151 157 +157 2 2 3 3 50 51 137 +158 2 2 3 3 50 137 151 +159 2 2 3 3 51 52 149 +160 2 2 3 3 137 51 149 +161 2 2 3 3 149 52 158 +162 2 2 3 3 54 53 150 +163 2 2 3 3 150 53 155 +164 2 2 3 3 55 54 138 +165 2 2 3 3 138 54 150 +166 2 2 3 3 56 55 141 +167 2 2 3 3 55 138 141 +168 2 2 3 3 56 141 156 +169 2 2 3 3 137 149 154 +170 2 2 3 3 151 137 154 +171 2 2 3 3 141 138 142 +172 2 2 3 3 142 138 143 +173 2 2 3 3 143 138 150 +174 2 2 3 3 146 139 152 +175 2 2 3 3 139 148 159 +176 2 2 3 3 152 139 159 +177 2 2 3 3 140 145 153 +178 2 2 3 3 147 140 160 +179 2 2 3 3 140 153 160 +180 2 2 3 3 141 142 148 +181 2 2 3 3 141 148 156 +182 2 2 3 3 142 143 144 +183 2 2 3 3 142 144 159 +184 2 2 3 3 148 142 159 +185 2 2 3 3 144 143 160 +186 2 2 3 3 147 143 150 +187 2 2 3 3 143 147 160 +188 2 2 3 3 152 144 154 +189 2 2 3 3 144 152 159 +190 2 2 3 3 144 153 154 +191 2 2 3 3 153 144 160 +192 2 2 3 3 145 151 153 +193 2 2 3 3 151 145 157 +194 2 2 3 3 149 146 152 +195 2 2 3 3 146 149 158 +196 2 2 3 3 147 150 155 +197 2 2 3 3 149 152 154 +198 2 2 3 3 153 151 154 +199 2 2 4 4 21 2 181 +200 2 2 4 4 2 53 181 +201 2 2 4 4 3 24 179 +202 2 2 4 4 57 3 179 +203 2 2 4 4 6 37 182 +204 2 2 4 4 56 6 182 +205 2 2 4 4 40 7 180 +206 2 2 4 4 7 60 180 +207 2 2 4 4 22 21 169 +208 2 2 4 4 169 21 181 +209 2 2 4 4 23 22 164 +210 2 2 4 4 164 22 169 +211 2 2 4 4 24 23 171 +212 2 2 4 4 23 164 171 +213 2 2 4 4 24 171 179 +214 2 2 4 4 37 38 170 +215 2 2 4 4 37 170 182 +216 2 2 4 4 38 39 163 +217 2 2 4 4 38 163 170 +218 2 2 4 4 39 40 172 +219 2 2 4 4 163 39 172 +220 2 2 4 4 172 40 180 +221 2 2 4 4 53 54 175 +222 2 2 4 4 53 175 181 +223 2 2 4 4 54 55 161 +224 2 2 4 4 54 161 175 +225 2 2 4 4 55 56 173 +226 2 2 4 4 161 55 173 +227 2 2 4 4 173 56 182 +228 2 2 4 4 58 57 174 +229 2 2 4 4 174 57 179 +230 2 2 4 4 59 58 162 +231 2 2 4 4 162 58 174 +232 2 2 4 4 60 59 165 +233 2 2 4 4 59 162 165 +234 2 2 4 4 60 165 180 +235 2 2 4 4 161 173 178 +236 2 2 4 4 175 161 178 +237 2 2 4 4 165 162 166 +238 2 2 4 4 166 162 167 +239 2 2 4 4 167 162 174 +240 2 2 4 4 170 163 176 +241 2 2 4 4 163 172 183 +242 2 2 4 4 176 163 183 +243 2 2 4 4 164 169 177 +244 2 2 4 4 171 164 184 +245 2 2 4 4 164 177 184 +246 2 2 4 4 165 166 172 +247 2 2 4 4 165 172 180 +248 2 2 4 4 166 167 168 +249 2 2 4 4 166 168 183 +250 2 2 4 4 172 166 183 +251 2 2 4 4 168 167 184 +252 2 2 4 4 171 167 174 +253 2 2 4 4 167 171 184 +254 2 2 4 4 176 168 178 +255 2 2 4 4 168 176 183 +256 2 2 4 4 168 177 178 +257 2 2 4 4 177 168 184 +258 2 2 4 4 169 175 177 +259 2 2 4 4 175 169 181 +260 2 2 4 4 173 170 176 +261 2 2 4 4 170 173 182 +262 2 2 4 4 171 174 179 +263 2 2 4 4 173 176 178 +264 2 2 4 4 177 175 178 +265 2 2 5 5 25 3 206 +266 2 2 5 5 3 57 206 +267 2 2 5 5 4 28 205 +268 2 2 5 5 61 4 205 +269 2 2 5 5 7 41 203 +270 2 2 5 5 60 7 203 +271 2 2 5 5 44 8 204 +272 2 2 5 5 8 64 204 +273 2 2 5 5 26 25 194 +274 2 2 5 5 194 25 206 +275 2 2 5 5 27 26 185 +276 2 2 5 5 185 26 194 +277 2 2 5 5 28 27 193 +278 2 2 5 5 27 185 193 +279 2 2 5 5 28 193 205 +280 2 2 5 5 41 42 197 +281 2 2 5 5 41 197 203 +282 2 2 5 5 42 43 186 +283 2 2 5 5 42 186 197 +284 2 2 5 5 43 44 189 +285 2 2 5 5 186 43 189 +286 2 2 5 5 189 44 204 +287 2 2 5 5 57 58 199 +288 2 2 5 5 57 199 206 +289 2 2 5 5 58 59 188 +290 2 2 5 5 58 188 199 +291 2 2 5 5 59 60 195 +292 2 2 5 5 188 59 195 +293 2 2 5 5 195 60 203 +294 2 2 5 5 62 61 198 +295 2 2 5 5 198 61 205 +296 2 2 5 5 63 62 187 +297 2 2 5 5 187 62 198 +298 2 2 5 5 64 63 196 +299 2 2 5 5 63 187 196 +300 2 2 5 5 64 196 204 +301 2 2 5 5 193 185 202 +302 2 2 5 5 185 194 209 +303 2 2 5 5 202 185 209 +304 2 2 5 5 186 189 190 +305 2 2 5 5 186 190 191 +306 2 2 5 5 186 191 197 +307 2 2 5 5 196 187 207 +308 2 2 5 5 187 198 200 +309 2 2 5 5 187 200 207 +310 2 2 5 5 188 195 208 +311 2 2 5 5 199 188 201 +312 2 2 5 5 201 188 208 +313 2 2 5 5 190 189 196 +314 2 2 5 5 196 189 204 +315 2 2 5 5 191 190 192 +316 2 2 5 5 192 190 207 +317 2 2 5 5 190 196 207 +318 2 2 5 5 191 192 208 +319 2 2 5 5 191 195 197 +320 2 2 5 5 195 191 208 +321 2 2 5 5 192 200 202 +322 2 2 5 5 200 192 207 +323 2 2 5 5 201 192 202 +324 2 2 5 5 192 201 208 +325 2 2 5 5 198 193 200 +326 2 2 5 5 193 198 205 +327 2 2 5 5 200 193 202 +328 2 2 5 5 199 194 206 +329 2 2 5 5 194 199 209 +330 2 2 5 5 197 195 203 +331 2 2 5 5 199 201 209 +332 2 2 5 5 201 202 209 +333 2 2 6 6 1 32 230 +334 2 2 6 6 49 1 230 +335 2 2 6 6 29 4 231 +336 2 2 6 6 4 61 231 +337 2 2 6 6 48 5 229 +338 2 2 6 6 5 52 229 +339 2 2 6 6 8 45 228 +340 2 2 6 6 64 8 228 +341 2 2 6 6 30 29 219 +342 2 2 6 6 219 29 231 +343 2 2 6 6 31 30 210 +344 2 2 6 6 210 30 219 +345 2 2 6 6 32 31 218 +346 2 2 6 6 31 210 218 +347 2 2 6 6 32 218 230 +348 2 2 6 6 45 46 222 +349 2 2 6 6 45 222 228 +350 2 2 6 6 46 47 211 +351 2 2 6 6 46 211 222 +352 2 2 6 6 47 48 214 +353 2 2 6 6 211 47 214 +354 2 2 6 6 214 48 229 +355 2 2 6 6 50 49 223 +356 2 2 6 6 223 49 230 +357 2 2 6 6 51 50 212 +358 2 2 6 6 212 50 223 +359 2 2 6 6 52 51 221 +360 2 2 6 6 51 212 221 +361 2 2 6 6 52 221 229 +362 2 2 6 6 61 62 224 +363 2 2 6 6 61 224 231 +364 2 2 6 6 62 63 213 +365 2 2 6 6 62 213 224 +366 2 2 6 6 63 64 220 +367 2 2 6 6 213 63 220 +368 2 2 6 6 220 64 228 +369 2 2 6 6 218 210 227 +370 2 2 6 6 210 219 234 +371 2 2 6 6 227 210 234 +372 2 2 6 6 211 214 215 +373 2 2 6 6 211 215 216 +374 2 2 6 6 211 216 222 +375 2 2 6 6 221 212 232 +376 2 2 6 6 212 223 225 +377 2 2 6 6 212 225 232 +378 2 2 6 6 213 220 233 +379 2 2 6 6 224 213 226 +380 2 2 6 6 226 213 233 +381 2 2 6 6 215 214 221 +382 2 2 6 6 221 214 229 +383 2 2 6 6 216 215 217 +384 2 2 6 6 217 215 232 +385 2 2 6 6 215 221 232 +386 2 2 6 6 216 217 233 +387 2 2 6 6 216 220 222 +388 2 2 6 6 220 216 233 +389 2 2 6 6 217 225 227 +390 2 2 6 6 225 217 232 +391 2 2 6 6 226 217 227 +392 2 2 6 6 217 226 233 +393 2 2 6 6 223 218 225 +394 2 2 6 6 218 223 230 +395 2 2 6 6 225 218 227 +396 2 2 6 6 224 219 231 +397 2 2 6 6 219 224 234 +398 2 2 6 6 222 220 228 +399 2 2 6 6 224 226 234 +400 2 2 6 6 226 227 234 +401 2 2 7 7 9 65 240 +402 2 2 7 7 72 9 240 +403 2 2 7 7 66 10 241 +404 2 2 7 7 10 67 241 +405 2 2 7 7 68 11 242 +406 2 2 7 7 11 69 242 +407 2 2 7 7 70 12 239 +408 2 2 7 7 12 71 239 +409 2 2 7 7 65 66 237 +410 2 2 7 7 65 237 240 +411 2 2 7 7 237 66 241 +412 2 2 7 7 67 68 235 +413 2 2 7 7 67 235 241 +414 2 2 7 7 235 68 242 +415 2 2 7 7 69 70 238 +416 2 2 7 7 69 238 242 +417 2 2 7 7 238 70 239 +418 2 2 7 7 71 72 236 +419 2 2 7 7 71 236 239 +420 2 2 7 7 236 72 240 +421 2 2 7 7 235 236 237 +422 2 2 7 7 236 235 238 +423 2 2 7 7 235 237 241 +424 2 2 7 7 238 235 242 +425 2 2 7 7 237 236 240 +426 2 2 7 7 236 238 239 +427 2 2 8 8 13 73 248 +428 2 2 8 8 80 13 248 +429 2 2 8 8 74 14 249 +430 2 2 8 8 14 75 249 +431 2 2 8 8 76 15 250 +432 2 2 8 8 15 77 250 +433 2 2 8 8 78 16 247 +434 2 2 8 8 16 79 247 +435 2 2 8 8 73 74 245 +436 2 2 8 8 73 245 248 +437 2 2 8 8 245 74 249 +438 2 2 8 8 75 76 243 +439 2 2 8 8 75 243 249 +440 2 2 8 8 243 76 250 +441 2 2 8 8 77 78 246 +442 2 2 8 8 77 246 250 +443 2 2 8 8 246 78 247 +444 2 2 8 8 79 80 244 +445 2 2 8 8 79 244 247 +446 2 2 8 8 244 80 248 +447 2 2 8 8 243 244 245 +448 2 2 8 8 244 243 246 +449 2 2 8 8 243 245 249 +450 2 2 8 8 246 243 250 +451 2 2 8 8 245 244 248 +452 2 2 8 8 244 246 247 +453 2 2 9 9 65 9 255 +454 2 2 9 9 9 81 255 +455 2 2 9 9 10 66 258 +456 2 2 9 9 83 10 258 +457 2 2 9 9 13 73 256 +458 2 2 9 9 82 13 256 +459 2 2 9 9 74 14 257 +460 2 2 9 9 14 84 257 +461 2 2 9 9 66 65 253 +462 2 2 9 9 253 65 255 +463 2 2 9 9 66 253 258 +464 2 2 9 9 73 74 254 +465 2 2 9 9 73 254 256 +466 2 2 9 9 254 74 257 +467 2 2 9 9 81 82 252 +468 2 2 9 9 81 252 255 +469 2 2 9 9 252 82 256 +470 2 2 9 9 84 83 251 +471 2 2 9 9 251 83 258 +472 2 2 9 9 84 251 257 +473 2 2 9 9 252 251 253 +474 2 2 9 9 251 252 254 +475 2 2 9 9 253 251 258 +476 2 2 9 9 251 254 257 +477 2 2 9 9 252 253 255 +478 2 2 9 9 254 252 256 +479 2 2 10 10 67 10 263 +480 2 2 10 10 10 83 263 +481 2 2 10 10 11 68 264 +482 2 2 10 10 85 11 264 +483 2 2 10 10 14 75 266 +484 2 2 10 10 84 14 266 +485 2 2 10 10 76 15 265 +486 2 2 10 10 15 86 265 +487 2 2 10 10 68 67 260 +488 2 2 10 10 260 67 263 +489 2 2 10 10 68 260 264 +490 2 2 10 10 75 76 259 +491 2 2 10 10 75 259 266 +492 2 2 10 10 259 76 265 +493 2 2 10 10 83 84 261 +494 2 2 10 10 83 261 263 +495 2 2 10 10 261 84 266 +496 2 2 10 10 86 85 262 +497 2 2 10 10 262 85 264 +498 2 2 10 10 86 262 265 +499 2 2 10 10 259 260 261 +500 2 2 10 10 260 259 262 +501 2 2 10 10 259 261 266 +502 2 2 10 10 262 259 265 +503 2 2 10 10 261 260 263 +504 2 2 10 10 260 262 264 +505 2 2 11 11 69 11 273 +506 2 2 11 11 11 85 273 +507 2 2 11 11 12 70 271 +508 2 2 11 11 87 12 271 +509 2 2 11 11 15 77 274 +510 2 2 11 11 86 15 274 +511 2 2 11 11 78 16 272 +512 2 2 11 11 16 88 272 +513 2 2 11 11 70 69 269 +514 2 2 11 11 269 69 273 +515 2 2 11 11 70 269 271 +516 2 2 11 11 77 78 270 +517 2 2 11 11 77 270 274 +518 2 2 11 11 270 78 272 +519 2 2 11 11 85 86 267 +520 2 2 11 11 85 267 273 +521 2 2 11 11 267 86 274 +522 2 2 11 11 88 87 268 +523 2 2 11 11 268 87 271 +524 2 2 11 11 88 268 272 +525 2 2 11 11 267 268 269 +526 2 2 11 11 268 267 270 +527 2 2 11 11 267 269 273 +528 2 2 11 11 270 267 274 +529 2 2 11 11 269 268 271 +530 2 2 11 11 268 270 272 +531 2 2 12 12 9 72 279 +532 2 2 12 12 81 9 279 +533 2 2 12 12 71 12 281 +534 2 2 12 12 12 87 281 +535 2 2 12 12 80 13 280 +536 2 2 12 12 13 82 280 +537 2 2 12 12 16 79 282 +538 2 2 12 12 88 16 282 +539 2 2 12 12 72 71 277 +540 2 2 12 12 277 71 281 +541 2 2 12 12 72 277 279 +542 2 2 12 12 79 80 278 +543 2 2 12 12 79 278 282 +544 2 2 12 12 278 80 280 +545 2 2 12 12 82 81 276 +546 2 2 12 12 276 81 279 +547 2 2 12 12 82 276 280 +548 2 2 12 12 87 88 275 +549 2 2 12 12 87 275 281 +550 2 2 12 12 275 88 282 +551 2 2 12 12 275 276 277 +552 2 2 12 12 276 275 278 +553 2 2 12 12 275 277 281 +554 2 2 12 12 278 275 282 +555 2 2 12 12 277 276 279 +556 2 2 12 12 276 278 280 +557 4 2 1 1 69 238 70 95 +558 4 2 1 1 246 78 119 77 +559 4 2 1 1 191 78 270 77 +560 4 2 1 1 101 240 104 9 +561 4 2 1 1 125 248 13 128 +562 4 2 1 1 116 283 299 78 +563 4 2 1 1 79 216 278 80 +564 4 2 1 1 116 283 78 117 +565 4 2 1 1 116 286 77 299 +566 4 2 1 1 149 256 13 152 +567 4 2 1 1 262 86 167 85 +568 4 2 1 1 173 266 14 176 +569 4 2 1 1 102 310 69 293 +570 4 2 1 1 116 286 299 42 +571 4 2 1 1 11 69 293 102 +572 4 2 1 1 284 123 307 80 +573 4 2 1 1 143 291 138 150 +574 4 2 1 1 287 170 75 163 +575 4 2 1 1 285 169 164 67 +576 4 2 1 1 15 195 86 274 +577 4 2 1 1 88 282 16 220 +578 4 2 1 1 264 68 11 171 +579 4 2 1 1 11 68 242 98 +580 4 2 1 1 187 289 198 87 +581 4 2 1 1 114 121 75 287 +582 4 2 1 1 284 123 80 113 +583 4 2 1 1 90 97 285 67 +584 4 2 1 1 318 138 84 291 +585 4 2 1 1 74 129 14 249 +586 4 2 1 1 66 241 10 105 +587 4 2 1 1 102 310 293 26 +588 4 2 1 1 283 16 78 117 +589 4 2 1 1 74 14 148 257 +590 4 2 1 1 115 294 73 74 +591 4 2 1 1 98 285 306 68 +592 4 2 1 1 15 126 286 77 +593 4 2 1 1 81 153 9 255 +594 4 2 1 1 307 123 13 80 +595 4 2 1 1 103 292 314 66 +596 4 2 1 1 292 91 65 66 +597 4 2 1 1 174 312 297 85 +598 4 2 1 1 316 75 14 121 +599 4 2 1 1 315 97 10 67 +600 4 2 1 1 82 221 13 280 +601 4 2 1 1 10 177 263 83 +602 4 2 1 1 247 16 79 124 +603 4 2 1 1 95 310 92 70 +604 4 2 1 1 16 272 88 196 +605 4 2 1 1 162 165 288 86 +606 4 2 1 1 137 81 298 82 +607 4 2 1 1 88 187 289 196 +608 4 2 1 1 78 299 116 77 +609 4 2 1 1 122 287 76 300 +610 4 2 1 1 288 188 86 195 +611 4 2 1 1 127 294 74 305 +612 4 2 1 1 311 72 89 71 +613 4 2 1 1 93 92 290 70 +614 4 2 1 1 78 116 119 77 +615 4 2 1 1 95 310 70 69 +616 4 2 1 1 191 186 78 77 +617 4 2 1 1 290 185 193 70 +618 4 2 1 1 89 295 311 71 +619 4 2 1 1 160 251 258 253 +620 4 2 1 1 72 9 279 218 +621 4 2 1 1 113 284 79 80 +622 4 2 1 1 319 213 87 289 +623 4 2 1 1 143 291 150 83 +624 4 2 1 1 318 161 291 84 +625 4 2 1 1 87 187 289 88 +626 4 2 1 1 98 285 68 90 +627 4 2 1 1 160 251 253 144 +628 4 2 1 1 167 312 162 174 +629 4 2 1 1 159 251 254 257 +630 4 2 1 1 100 12 295 71 +631 4 2 1 1 12 198 319 87 +632 4 2 1 1 75 114 287 76 +633 4 2 1 1 11 273 85 201 +634 4 2 1 1 281 87 12 226 +635 4 2 1 1 167 312 174 85 +636 4 2 1 1 68 90 285 67 +637 4 2 1 1 216 79 211 80 +638 4 2 1 1 308 73 13 125 +639 4 2 1 1 9 309 101 65 +640 4 2 1 1 174 11 85 297 +641 4 2 1 1 137 313 82 298 +642 4 2 1 1 251 83 84 143 +643 4 2 1 1 165 15 288 86 +644 4 2 1 1 311 99 72 296 +645 4 2 1 1 167 312 85 86 +646 4 2 1 1 143 291 83 84 +647 4 2 1 1 246 78 118 119 +648 4 2 1 1 238 94 70 95 +649 4 2 1 1 190 78 270 191 +650 4 2 1 1 122 287 300 39 +651 4 2 1 1 89 295 71 100 +652 4 2 1 1 289 220 213 88 +653 4 2 1 1 168 264 260 262 +654 4 2 1 1 290 12 93 70 +655 4 2 1 1 159 251 257 142 +656 4 2 1 1 217 282 278 275 +657 4 2 1 1 192 274 270 267 +658 4 2 1 1 120 250 243 246 +659 4 2 1 1 96 242 238 235 +660 4 2 1 1 311 218 296 72 +661 4 2 1 1 66 253 65 160 +662 4 2 1 1 159 254 73 74 +663 4 2 1 1 141 84 14 318 +664 4 2 1 1 216 215 278 80 +665 4 2 1 1 16 79 124 302 +666 4 2 1 1 73 13 256 152 +667 4 2 1 1 192 272 268 270 +668 4 2 1 1 217 280 276 278 +669 4 2 1 1 120 247 246 244 +670 4 2 1 1 96 239 236 238 +671 4 2 1 1 293 108 11 102 +672 4 2 1 1 273 69 269 209 +673 4 2 1 1 296 72 9 99 +674 4 2 1 1 147 258 160 143 +675 4 2 1 1 101 240 9 65 +676 4 2 1 1 125 248 128 130 +677 4 2 1 1 168 265 262 259 +678 4 2 1 1 167 166 86 262 +679 4 2 1 1 279 9 81 225 +680 4 2 1 1 286 126 15 132 +681 4 2 1 1 239 94 12 70 +682 4 2 1 1 247 78 16 118 +683 4 2 1 1 11 69 273 209 +684 4 2 1 1 16 78 272 190 +685 4 2 1 1 240 104 9 72 +686 4 2 1 1 248 80 13 128 +687 4 2 1 1 277 281 71 234 +688 4 2 1 1 149 256 152 154 +689 4 2 1 1 199 293 209 194 +690 4 2 1 1 12 200 87 271 +691 4 2 1 1 14 134 316 121 +692 4 2 1 1 45 325 302 228 +693 4 2 1 1 9 223 81 225 +694 4 2 1 1 209 70 269 202 +695 4 2 1 1 242 69 11 95 +696 4 2 1 1 250 119 15 77 +697 4 2 1 1 274 15 191 77 +698 4 2 1 1 133 307 13 323 +699 4 2 1 1 14 266 75 176 +700 4 2 1 1 283 131 16 117 +701 4 2 1 1 122 250 136 119 +702 4 2 1 1 173 266 176 178 +703 4 2 1 1 200 198 12 87 +704 4 2 1 1 80 13 215 280 +705 4 2 1 1 71 281 12 234 +706 4 2 1 1 152 73 13 146 +707 4 2 1 1 224 295 234 219 +708 4 2 1 1 65 9 153 255 +709 4 2 1 1 79 216 16 282 +710 4 2 1 1 265 86 15 166 +711 4 2 1 1 257 14 142 84 +712 4 2 1 1 16 325 228 302 +713 4 2 1 1 320 230 223 9 +714 4 2 1 1 199 293 194 206 +715 4 2 1 1 224 295 219 231 +716 4 2 1 1 195 15 191 274 +717 4 2 1 1 216 16 282 220 +718 4 2 1 1 95 11 242 98 +719 4 2 1 1 264 11 167 171 +720 4 2 1 1 264 167 11 85 +721 4 2 1 1 83 258 10 143 +722 4 2 1 1 209 70 202 185 +723 4 2 1 1 102 11 69 95 +724 4 2 1 1 15 119 126 77 +725 4 2 1 1 15 197 191 77 +726 4 2 1 1 72 104 9 99 +727 4 2 1 1 80 123 13 128 +728 4 2 1 1 306 68 11 98 +729 4 2 1 1 137 313 298 51 +730 4 2 1 1 234 72 277 227 +731 4 2 1 1 297 179 11 301 +732 4 2 1 1 321 155 10 326 +733 4 2 1 1 286 203 15 197 +734 4 2 1 1 302 228 16 222 +735 4 2 1 1 176 75 14 170 +736 4 2 1 1 249 129 14 75 +737 4 2 1 1 241 67 10 105 +738 4 2 1 1 10 177 67 263 +739 4 2 1 1 294 159 139 73 +740 4 2 1 1 100 239 111 94 +741 4 2 1 1 316 182 14 170 +742 4 2 1 1 308 158 13 146 +743 4 2 1 1 296 109 9 303 +744 4 2 1 1 133 307 323 48 +745 4 2 1 1 45 325 228 8 +746 4 2 1 1 309 157 145 9 +747 4 2 1 1 12 94 93 70 +748 4 2 1 1 117 16 78 118 +749 4 2 1 1 190 16 78 189 +750 4 2 1 1 225 279 9 218 +751 4 2 1 1 145 9 153 65 +752 4 2 1 1 318 156 324 14 +753 4 2 1 1 288 180 322 15 +754 4 2 1 1 290 107 12 304 +755 4 2 1 1 283 204 189 16 +756 4 2 1 1 273 11 209 201 +757 4 2 1 1 234 281 12 226 +758 4 2 1 1 79 16 216 222 +759 4 2 1 1 193 271 202 200 +760 4 2 1 1 172 265 166 183 +761 4 2 1 1 291 175 83 161 +762 4 2 1 1 16 88 317 196 +763 4 2 1 1 256 144 254 152 +764 4 2 1 1 292 160 65 140 +765 4 2 1 1 85 167 11 174 +766 4 2 1 1 10 83 143 150 +767 4 2 1 1 122 15 300 76 +768 4 2 1 1 215 214 13 80 +769 4 2 1 1 293 209 194 185 +770 4 2 1 1 37 324 316 182 +771 4 2 1 1 234 72 227 210 +772 4 2 1 1 215 13 221 280 +773 4 2 1 1 272 16 190 196 +774 4 2 1 1 142 148 14 257 +775 4 2 1 1 16 247 118 124 +776 4 2 1 1 149 313 13 82 +777 4 2 1 1 324 182 14 316 +778 4 2 1 1 306 179 11 171 +779 4 2 1 1 317 228 220 16 +780 4 2 1 1 212 81 232 82 +781 4 2 1 1 86 165 15 166 +782 4 2 1 1 14 142 84 141 +783 4 2 1 1 75 129 14 121 +784 4 2 1 1 67 97 10 105 +785 4 2 1 1 169 10 177 67 +786 4 2 1 1 37 324 182 6 +787 4 2 1 1 116 283 117 43 +788 4 2 1 1 113 79 135 80 +789 4 2 1 1 89 72 111 71 +790 4 2 1 1 295 234 219 210 +791 4 2 1 1 288 180 15 165 +792 4 2 1 1 116 283 43 299 +793 4 2 1 1 100 295 12 107 +794 4 2 1 1 88 87 187 207 +795 4 2 1 1 254 73 256 152 +796 4 2 1 1 298 223 212 81 +797 4 2 1 1 297 179 301 57 +798 4 2 1 1 208 86 85 188 +799 4 2 1 1 233 87 213 88 +800 4 2 1 1 308 13 133 125 +801 4 2 1 1 309 109 9 101 +802 4 2 1 1 103 292 66 91 +803 4 2 1 1 318 156 14 141 +804 4 2 1 1 76 163 75 183 +805 4 2 1 1 124 131 16 302 +806 4 2 1 1 254 144 256 252 +807 4 2 1 1 152 254 73 159 +808 4 2 1 1 81 298 151 137 +809 4 2 1 1 237 105 235 241 +810 4 2 1 1 306 11 108 98 +811 4 2 1 1 308 158 323 13 +812 4 2 1 1 326 110 10 315 +813 4 2 1 1 308 158 33 323 +814 4 2 1 1 33 5 323 158 +815 4 2 1 1 326 314 155 10 +816 4 2 1 1 15 132 300 322 +817 4 2 1 1 20 326 314 155 +818 4 2 1 1 20 326 155 2 +819 4 2 1 1 177 261 260 263 +820 4 2 1 1 90 68 112 67 +821 4 2 1 1 136 114 75 76 +822 4 2 1 1 164 184 68 67 +823 4 2 1 1 124 284 46 302 +824 4 2 1 1 296 109 303 32 +825 4 2 1 1 168 266 259 261 +826 4 2 1 1 245 120 249 243 +827 4 2 1 1 237 235 105 96 +828 4 2 1 1 237 240 236 96 +829 4 2 1 1 245 244 248 120 +830 4 2 1 1 177 260 261 168 +831 4 2 1 1 279 277 217 276 +832 4 2 1 1 268 269 271 192 +833 4 2 1 1 290 107 304 28 +834 4 2 1 1 98 285 90 23 +835 4 2 1 1 49 303 230 320 +836 4 2 1 1 160 251 144 143 +837 4 2 1 1 160 251 143 258 +838 4 2 1 1 196 317 16 204 +839 4 2 1 1 151 9 320 81 +840 4 2 1 1 116 286 42 126 +841 4 2 1 1 300 132 15 122 +842 4 2 1 1 118 78 116 119 +843 4 2 1 1 94 92 70 95 +844 4 2 1 1 78 190 186 191 +845 4 2 1 1 127 294 305 35 +846 4 2 1 1 159 251 142 144 +847 4 2 1 1 201 85 11 199 +848 4 2 1 1 87 224 12 226 +849 4 2 1 1 227 279 277 217 +850 4 2 1 1 269 202 271 192 +851 4 2 1 1 74 245 130 249 +852 4 2 1 1 159 251 144 254 +853 4 2 1 1 253 65 153 255 +854 4 2 1 1 116 286 126 77 +855 4 2 1 1 215 216 211 80 +856 4 2 1 1 251 84 142 143 +857 4 2 1 1 10 83 150 321 +858 4 2 1 1 66 258 253 160 +859 4 2 1 1 74 159 254 257 +860 4 2 1 1 253 153 65 160 +861 4 2 1 1 209 70 185 69 +862 4 2 1 1 168 264 262 167 +863 4 2 1 1 166 86 162 167 +864 4 2 1 1 142 84 138 143 +865 4 2 1 1 111 72 236 71 +866 4 2 1 1 79 244 135 80 +867 4 2 1 1 82 81 232 276 +868 4 2 1 1 233 275 87 88 +869 4 2 1 1 208 86 267 85 +870 4 2 1 1 96 242 235 112 +871 4 2 1 1 120 250 246 119 +872 4 2 1 1 217 282 275 233 +873 4 2 1 1 192 274 267 208 +874 4 2 1 1 147 258 143 10 +875 4 2 1 1 120 247 244 135 +876 4 2 1 1 96 239 238 94 +877 4 2 1 1 192 272 270 190 +878 4 2 1 1 217 280 278 215 +879 4 2 1 1 168 265 259 183 +880 4 2 1 1 68 235 112 67 +881 4 2 1 1 136 75 243 76 +882 4 2 1 1 259 76 75 183 +883 4 2 1 1 122 287 39 114 +884 4 2 1 1 127 129 14 74 +885 4 2 1 1 10 66 105 103 +886 4 2 1 1 234 72 210 71 +887 4 2 1 1 184 260 68 67 +888 4 2 1 1 88 268 87 207 +889 4 2 1 1 288 165 162 59 +890 4 2 1 1 63 289 187 196 +891 4 2 1 1 285 315 67 97 +892 4 2 1 1 130 115 73 74 +893 4 2 1 1 65 91 106 66 +894 4 2 1 1 202 271 70 269 +895 4 2 1 1 122 250 119 15 +896 4 2 1 1 288 188 195 59 +897 4 2 1 1 223 212 81 225 +898 4 2 1 1 146 152 73 139 +899 4 2 1 1 153 9 151 81 +900 4 2 1 1 287 170 163 38 +901 4 2 1 1 97 22 90 285 +902 4 2 1 1 98 285 23 306 +903 4 2 1 1 200 187 198 87 +904 4 2 1 1 10 177 83 175 +905 4 2 1 1 266 75 176 259 +906 4 2 1 1 217 282 233 216 +907 4 2 1 1 192 274 208 191 +908 4 2 1 1 284 123 113 47 +909 4 2 1 1 72 240 104 236 +910 4 2 1 1 248 244 80 128 +911 4 2 1 1 277 72 279 227 +912 4 2 1 1 314 66 10 103 +913 4 2 1 1 168 264 167 184 +914 4 2 1 1 287 114 121 38 +915 4 2 1 1 246 78 247 118 +916 4 2 1 1 70 239 94 238 +917 4 2 1 1 272 78 270 190 +918 4 2 1 1 120 250 119 136 +919 4 2 1 1 96 242 112 95 +920 4 2 1 1 99 72 104 89 +921 4 2 1 1 113 123 80 128 +922 4 2 1 1 81 279 225 276 +923 4 2 1 1 284 123 47 307 +924 4 2 1 1 124 284 302 79 +925 4 2 1 1 170 176 75 163 +926 4 2 1 1 82 137 81 154 +927 4 2 1 1 200 87 271 268 +928 4 2 1 1 80 215 278 280 +929 4 2 1 1 305 127 14 74 +930 4 2 1 1 250 246 119 77 +931 4 2 1 1 238 69 242 95 +932 4 2 1 1 274 191 270 77 +933 4 2 1 1 166 265 86 262 +934 4 2 1 1 96 239 94 111 +935 4 2 1 1 120 247 135 118 +936 4 2 1 1 84 178 161 83 +937 4 2 1 1 192 272 190 207 +938 4 2 1 1 217 280 215 232 +939 4 2 1 1 153 140 145 65 +940 4 2 1 1 168 265 183 166 +941 4 2 1 1 320 157 9 151 +942 4 2 1 1 100 239 94 12 +943 4 2 1 1 27 93 92 290 +944 4 2 1 1 122 287 114 76 +945 4 2 1 1 244 135 80 128 +946 4 2 1 1 111 72 104 236 +947 4 2 1 1 195 15 197 191 +948 4 2 1 1 220 216 16 222 +949 4 2 1 1 172 265 183 76 +950 4 2 1 1 282 79 216 278 +951 4 2 1 1 102 11 95 98 +952 4 2 1 1 119 122 15 126 +953 4 2 1 1 174 167 11 171 +954 4 2 1 1 143 147 10 150 +955 4 2 1 1 259 75 176 183 +956 4 2 1 1 290 310 70 92 +957 4 2 1 1 92 93 94 70 +958 4 2 1 1 117 78 116 118 +959 4 2 1 1 78 190 189 186 +960 4 2 1 1 126 119 116 77 +961 4 2 1 1 95 310 69 102 +962 4 2 1 1 191 197 186 77 +963 4 2 1 1 232 81 225 276 +964 4 2 1 1 193 271 200 12 +965 4 2 1 1 241 235 67 105 +966 4 2 1 1 75 249 129 243 +967 4 2 1 1 321 155 326 53 +968 4 2 1 1 305 134 324 14 +969 4 2 1 1 230 303 9 320 +970 4 2 1 1 217 225 279 276 +971 4 2 1 1 268 271 200 192 +972 4 2 1 1 236 240 104 96 +973 4 2 1 1 128 248 244 120 +974 4 2 1 1 259 176 266 168 +975 4 2 1 1 289 317 88 196 +976 4 2 1 1 167 264 262 85 +977 4 2 1 1 200 87 268 207 +978 4 2 1 1 90 97 67 105 +979 4 2 1 1 121 75 129 114 +980 4 2 1 1 177 164 169 67 +981 4 2 1 1 67 177 260 263 +982 4 2 1 1 11 209 201 199 +983 4 2 1 1 234 12 224 226 +984 4 2 1 1 211 214 215 80 +985 4 2 1 1 216 79 222 211 +986 4 2 1 1 225 9 223 218 +987 4 2 1 1 12 193 198 200 +988 4 2 1 1 173 176 14 170 +989 4 2 1 1 152 13 149 146 +990 4 2 1 1 104 101 9 99 +991 4 2 1 1 125 13 123 128 +992 4 2 1 1 144 254 152 159 +993 4 2 1 1 192 269 202 201 +994 4 2 1 1 226 227 277 217 +995 4 2 1 1 130 129 74 249 +996 4 2 1 1 150 291 138 54 +997 4 2 1 1 139 152 73 159 +998 4 2 1 1 209 70 69 269 +999 4 2 1 1 86 162 165 166 +1000 4 2 1 1 138 84 142 141 +1001 4 2 1 1 167 312 86 162 +1002 4 2 1 1 143 291 84 138 +1003 4 2 1 1 73 245 130 74 +1004 4 2 1 1 106 237 65 66 +1005 4 2 1 1 103 292 91 19 +1006 4 2 1 1 292 160 140 147 +1007 4 2 1 1 212 81 225 232 +1008 4 2 1 1 297 293 199 206 +1009 4 2 1 1 319 295 224 231 +1010 4 2 1 1 221 214 13 215 +1011 4 2 1 1 196 16 190 189 +1012 4 2 1 1 153 81 252 255 +1013 4 2 1 1 101 240 65 106 +1014 4 2 1 1 125 248 130 73 +1015 4 2 1 1 14 148 142 141 +1016 4 2 1 1 165 172 15 166 +1017 4 2 1 1 94 100 12 93 +1018 4 2 1 1 118 117 16 124 +1019 4 2 1 1 87 281 275 226 +1020 4 2 1 1 85 273 267 201 +1021 4 2 1 1 102 310 26 92 +1022 4 2 1 1 87 200 187 207 +1023 4 2 1 1 89 72 104 111 +1024 4 2 1 1 80 135 113 128 +1025 4 2 1 1 234 72 71 277 +1026 4 2 1 1 262 167 166 168 +1027 4 2 1 1 95 238 94 96 +1028 4 2 1 1 120 246 118 119 +1029 4 2 1 1 49 303 320 157 +1030 4 2 1 1 115 308 294 34 +1031 4 2 1 1 217 216 215 278 +1032 4 2 1 1 270 190 191 192 +1033 4 2 1 1 235 112 67 105 +1034 4 2 1 1 136 75 129 243 +1035 4 2 1 1 226 275 87 233 +1036 4 2 1 1 85 267 208 201 +1037 4 2 1 1 202 200 271 192 +1038 4 2 1 1 227 225 279 217 +1039 4 2 1 1 213 233 88 220 +1040 4 2 1 1 86 208 195 188 +1041 4 2 1 1 163 176 75 183 +1042 4 2 1 1 260 184 177 67 +1043 4 2 1 1 91 309 18 292 +1044 4 2 1 1 68 112 98 90 +1045 4 2 1 1 136 122 114 76 +1046 4 2 1 1 184 68 171 164 +1047 4 2 1 1 149 256 154 82 +1048 4 2 1 1 244 246 120 243 +1049 4 2 1 1 235 236 238 96 +1050 4 2 1 1 262 259 260 168 +1051 4 2 1 1 276 275 217 278 +1052 4 2 1 1 267 268 270 192 +1053 4 2 1 1 305 134 14 127 +1054 4 2 1 1 173 266 178 84 +1055 4 2 1 1 294 159 73 74 +1056 4 2 1 1 142 257 84 251 +1057 4 2 1 1 236 239 111 71 +1058 4 2 1 1 79 244 247 135 +1059 4 2 1 1 276 232 82 280 +1060 4 2 1 1 226 87 213 233 +1061 4 2 1 1 208 85 201 188 +1062 4 2 1 1 275 233 282 88 +1063 4 2 1 1 208 86 274 267 +1064 4 2 1 1 68 235 242 112 +1065 4 2 1 1 243 250 136 76 +1066 4 2 1 1 265 76 259 183 +1067 4 2 1 1 153 140 65 160 +1068 4 2 1 1 318 138 291 55 +1069 4 2 1 1 68 260 184 264 +1070 4 2 1 1 232 221 212 82 +1071 4 2 1 1 88 272 268 207 +1072 4 2 1 1 127 294 35 115 +1073 4 2 1 1 95 310 102 92 +1074 4 2 1 1 84 178 83 261 +1075 4 2 1 1 193 202 70 185 +1076 4 2 1 1 62 289 198 187 +1077 4 2 1 1 309 157 9 303 +1078 4 2 1 1 249 120 129 243 +1079 4 2 1 1 306 179 301 11 +1080 4 2 1 1 124 79 135 113 +1081 4 2 1 1 111 100 89 71 +1082 4 2 1 1 130 245 248 120 +1083 4 2 1 1 240 237 106 96 +1084 4 2 1 1 168 178 266 261 +1085 4 2 1 1 87 213 224 226 +1086 4 2 1 1 85 201 188 199 +1087 4 2 1 1 89 295 100 30 +1088 4 2 1 1 187 88 207 196 +1089 4 2 1 1 252 254 144 251 +1090 4 2 1 1 252 144 253 251 +1091 4 2 1 1 172 163 76 183 +1092 4 2 1 1 258 83 251 143 +1093 4 2 1 1 253 144 153 160 +1094 4 2 1 1 218 227 72 210 +1095 4 2 1 1 311 99 296 31 +1096 4 2 1 1 203 15 197 195 +1097 4 2 1 1 228 220 16 222 +1098 4 2 1 1 199 293 11 209 +1099 4 2 1 1 224 295 12 234 +1100 4 2 1 1 67 112 90 105 +1101 4 2 1 1 114 75 129 136 +1102 4 2 1 1 184 164 177 67 +1103 4 2 1 1 102 108 11 98 +1104 4 2 1 1 179 174 11 171 +1105 4 2 1 1 126 122 15 132 +1106 4 2 1 1 150 147 10 155 +1107 4 2 1 1 192 274 191 270 +1108 4 2 1 1 217 282 216 278 +1109 4 2 1 1 153 252 81 154 +1110 4 2 1 1 174 312 162 58 +1111 4 2 1 1 168 264 184 260 +1112 4 2 1 1 120 250 136 243 +1113 4 2 1 1 96 242 95 238 +1114 4 2 1 1 311 99 31 89 +1115 4 2 1 1 9 230 223 218 +1116 4 2 1 1 12 193 205 198 +1117 4 2 1 1 120 245 244 243 +1118 4 2 1 1 237 236 235 96 +1119 4 2 1 1 259 260 168 261 +1120 4 2 1 1 217 277 275 276 +1121 4 2 1 1 269 268 267 192 +1122 4 2 1 1 120 247 118 246 +1123 4 2 1 1 96 239 111 236 +1124 4 2 1 1 192 272 207 268 +1125 4 2 1 1 217 280 232 276 +1126 4 2 1 1 115 308 34 125 +1127 4 2 1 1 168 265 166 262 +1128 4 2 1 1 91 309 292 65 +1129 4 2 1 1 182 173 14 170 +1130 4 2 1 1 13 158 149 146 +1131 4 2 1 1 101 109 9 99 +1132 4 2 1 1 133 13 123 125 +1133 4 2 1 1 89 295 30 311 +1134 4 2 1 1 65 237 106 240 +1135 4 2 1 1 248 73 245 130 +1136 4 2 1 1 318 138 55 141 +1137 4 2 1 1 229 214 13 221 +1138 4 2 1 1 16 196 204 189 +1139 4 2 1 1 14 148 141 156 +1140 4 2 1 1 180 172 15 165 +1141 4 2 1 1 93 100 12 107 +1142 4 2 1 1 117 131 16 124 +1143 4 2 1 1 319 213 289 62 +1144 4 2 1 1 178 84 266 261 +1145 4 2 1 1 125 248 73 13 +1146 4 2 1 1 101 240 106 104 +1147 4 2 1 1 127 14 129 121 +1148 4 2 1 1 105 97 10 103 +1149 4 2 1 1 10 169 177 175 +1150 4 2 1 1 153 151 9 145 +1151 4 2 1 1 174 312 58 297 +1152 4 2 1 1 149 256 82 13 +1153 4 2 1 1 173 266 84 14 +1154 4 2 1 1 137 313 51 149 +1155 4 2 1 1 306 179 24 301 +1156 4 2 1 1 183 176 259 168 +1157 4 2 1 1 236 104 111 96 +1158 4 2 1 1 244 135 128 120 +1159 4 2 1 1 252 82 81 154 +1160 4 2 1 1 225 217 232 276 +1161 4 2 1 1 207 268 200 192 +1162 4 2 1 1 251 142 144 143 +1163 4 2 1 1 66 91 106 103 +1164 4 2 1 1 115 130 127 74 +1165 4 2 1 1 96 237 106 105 +1166 4 2 1 1 168 177 178 261 +1167 4 2 1 1 137 313 149 82 +1168 4 2 1 1 101 91 106 65 +1169 4 2 1 1 115 73 125 130 +1170 4 2 1 1 151 81 137 154 +1171 4 2 1 1 248 128 130 120 +1172 4 2 1 1 240 106 104 96 +1173 4 2 1 1 176 178 266 168 +1174 4 2 1 1 154 144 256 152 +1175 4 2 1 1 130 129 127 74 +1176 4 2 1 1 105 66 106 103 +1177 4 2 1 1 103 292 19 314 +1178 4 2 1 1 83 178 161 175 +1179 4 2 1 1 291 175 161 54 +1180 4 2 1 1 144 256 252 154 +1181 4 2 1 1 149 137 82 154 +1182 4 2 1 1 81 151 153 154 +1183 4 2 1 1 178 84 161 173 +1184 4 2 1 1 83 177 178 175 +1185 4 2 1 1 298 320 81 151 +1186 4 2 1 1 14 127 134 121 +1187 4 2 1 1 103 97 10 110 +1188 4 2 1 1 10 169 175 181 +1189 4 2 1 1 151 157 9 145 +1190 4 2 1 1 112 235 96 105 +1191 4 2 1 1 136 129 120 243 +1192 4 2 1 1 184 260 177 168 +1193 4 2 1 1 298 50 151 137 +1194 4 2 1 1 127 294 115 74 +1195 4 2 1 1 252 256 82 154 +1196 4 2 1 1 192 208 267 201 +1197 4 2 1 1 275 226 217 233 +1198 4 2 1 1 313 158 52 149 +1199 4 2 1 1 306 179 171 24 +1200 4 2 1 1 252 153 144 154 +1201 4 2 1 1 300 132 122 40 +1202 4 2 1 1 317 325 16 204 +1203 4 2 1 1 110 315 21 97 +1204 4 2 1 1 134 37 316 121 +1205 4 2 1 1 133 307 48 123 +1206 4 2 1 1 283 44 131 117 +1207 4 2 1 1 306 108 24 98 +1208 4 2 1 1 313 158 149 13 +1209 4 2 1 1 126 286 41 132 +1210 4 2 1 1 204 196 317 64 +1211 4 2 1 1 293 206 301 25 +1212 4 2 1 1 110 315 97 10 +1213 4 2 1 1 283 325 16 131 +1214 4 2 1 1 316 182 170 37 +1215 4 2 1 1 133 307 123 13 +1216 4 2 1 1 206 25 3 301 +1217 4 2 1 1 286 203 197 41 +1218 4 2 1 1 319 205 61 198 +1219 4 2 1 1 288 180 165 60 +1220 4 2 1 1 288 180 60 322 +1221 4 2 1 1 321 155 53 150 +1222 4 2 1 1 293 25 108 102 +1223 4 2 1 1 17 109 309 101 +1224 4 2 1 1 308 133 33 125 +1225 4 2 1 1 318 156 141 56 +1226 4 2 1 1 319 205 198 12 +1227 4 2 1 1 309 303 9 109 +1228 4 2 1 1 318 156 56 324 +1229 4 2 1 1 308 158 146 33 +1230 4 2 1 1 297 179 57 174 +1231 4 2 1 1 296 109 32 99 +1232 4 2 1 1 290 107 28 93 +1233 4 2 1 1 296 109 99 9 +1234 4 2 1 1 290 107 93 12 +1235 4 2 1 1 297 179 174 11 +1236 4 2 1 1 293 301 11 108 +1237 4 2 1 1 302 228 222 45 +1238 4 2 1 1 124 45 131 302 +1239 4 2 1 1 314 110 20 103 +1240 4 2 1 1 305 134 127 36 +1241 4 2 1 1 314 110 103 10 +1242 4 2 1 1 299 43 116 42 +1243 4 2 1 1 29 295 100 107 +1244 4 2 1 1 320 49 157 151 +1245 4 2 1 1 306 24 23 98 +1246 4 2 1 1 295 304 12 107 +1247 4 2 1 1 305 134 36 324 +1248 4 2 1 1 97 21 22 315 +1249 4 2 1 1 37 316 121 38 +1250 4 2 1 1 307 123 47 48 +1251 4 2 1 1 63 317 196 64 +1252 4 2 1 1 149 52 313 51 +1253 4 2 1 1 39 300 122 40 +1254 4 2 1 1 44 283 43 117 +1255 4 2 1 1 321 155 150 10 +1256 4 2 1 1 165 288 60 59 +1257 4 2 1 1 309 18 17 101 +1258 4 2 1 1 308 33 34 125 +1259 4 2 1 1 318 141 55 56 +1260 4 2 1 1 46 47 284 113 +1261 4 2 1 1 296 32 31 99 +1262 4 2 1 1 93 27 28 290 +1263 4 2 1 1 319 198 61 62 +1264 4 2 1 1 92 26 27 310 +1265 4 2 1 1 58 174 297 57 +1266 4 2 1 1 38 287 114 39 +1267 4 2 1 1 90 22 23 285 +1268 4 2 1 1 302 124 45 46 +1269 4 2 1 1 312 59 162 58 +1270 4 2 1 1 40 322 300 132 +1271 4 2 1 1 297 293 206 301 +1272 4 2 1 1 295 231 304 29 +1273 4 2 1 1 4 29 304 231 +1274 4 2 1 1 319 295 231 304 +1275 4 2 1 1 21 326 315 110 +1276 4 2 1 1 283 204 325 44 +1277 4 2 1 1 325 204 8 44 +1278 4 2 1 1 295 30 29 100 +1279 4 2 1 1 286 42 126 41 +1280 4 2 1 1 89 30 31 311 +1281 4 2 1 1 187 62 289 63 +1282 4 2 1 1 26 25 293 102 +1283 4 2 1 1 20 19 314 103 +1284 4 2 1 1 305 127 35 36 +1285 4 2 1 1 55 138 291 54 +1286 4 2 1 1 49 320 50 151 +1287 4 2 1 1 321 54 150 53 +1288 4 2 1 1 132 41 7 322 +1289 4 2 1 1 131 325 8 44 +1290 4 2 1 1 5 48 133 323 +1291 4 2 1 1 301 25 3 108 +1292 4 2 1 1 37 324 6 134 +1293 4 2 1 1 21 326 110 2 +1294 4 2 1 1 50 298 51 137 +1295 4 2 1 1 155 53 2 326 +1296 4 2 1 1 49 303 157 1 +1297 4 2 1 1 292 19 18 91 +1298 4 2 1 1 34 35 294 115 +1299 4 2 1 1 57 301 3 179 +1300 4 2 1 1 304 61 319 205 +1301 4 2 1 1 60 180 7 322 +1302 4 2 1 1 3 24 301 108 +1303 4 2 1 1 20 326 2 110 +1304 4 2 1 1 156 324 6 56 +1305 4 2 1 1 1 17 109 303 +1306 4 2 1 1 33 5 133 323 +1307 4 2 1 1 64 204 8 325 +1308 4 2 1 1 323 52 313 158 +1309 4 2 1 1 45 325 8 131 +1310 4 2 1 1 40 322 132 7 +1311 4 2 1 1 4 29 107 304 +1312 4 2 1 1 36 6 324 134 +1313 4 2 1 1 28 4 107 304 +1314 4 2 1 1 109 32 1 303 +1315 4 2 1 1 147 258 10 66 +1316 4 2 1 1 147 258 66 160 +1317 4 2 1 1 193 271 12 70 +1318 4 2 1 1 193 271 70 202 +1319 4 2 1 1 220 282 233 88 +1320 4 2 1 1 220 233 282 216 +1321 4 2 1 1 195 274 208 86 +1322 4 2 1 1 208 274 195 191 +1323 4 2 1 1 242 98 112 95 +1324 4 2 1 1 112 98 242 68 +1325 4 2 1 1 122 250 15 76 +1326 4 2 1 1 122 250 76 136 +1327 4 2 1 1 171 264 184 167 +1328 4 2 1 1 171 184 264 68 +1329 4 2 1 1 277 234 226 281 +1330 4 2 1 1 226 234 277 227 +1331 4 2 1 1 269 209 201 273 +1332 4 2 1 1 201 209 269 202 +1333 4 2 1 1 218 279 227 225 +1334 4 2 1 1 218 227 279 72 +1335 4 2 1 1 257 148 159 142 +1336 4 2 1 1 257 159 148 74 +1337 4 2 1 1 280 221 232 82 +1338 4 2 1 1 280 232 221 215 +1339 4 2 1 1 100 239 12 71 +1340 4 2 1 1 100 239 71 111 +1341 4 2 1 1 247 124 135 118 +1342 4 2 1 1 135 124 247 79 +1343 4 2 1 1 196 272 207 190 +1344 4 2 1 1 196 207 272 88 +1345 4 2 1 1 172 265 76 15 +1346 4 2 1 1 172 265 15 166 +1347 4 2 1 1 277 226 275 281 +1348 4 2 1 1 277 275 226 217 +1349 4 2 1 1 201 269 267 192 +1350 4 2 1 1 201 267 269 273 +1351 4 2 1 1 124 284 79 113 +1352 4 2 1 1 124 284 113 46 +1353 4 2 1 1 91 309 65 101 +1354 4 2 1 1 91 309 101 18 +1355 4 2 1 1 115 308 125 73 +1356 4 2 1 1 115 308 73 294 +1357 4 2 1 1 105 237 66 241 +1358 4 2 1 1 105 66 237 106 +1359 4 2 1 1 130 249 120 129 +1360 4 2 1 1 120 249 130 245 +1361 4 2 1 1 261 177 83 263 +1362 4 2 1 1 261 83 177 178 +1363 4 2 1 1 153 252 253 255 +1364 4 2 1 1 253 252 153 144 +1365 4 2 1 1 186 189 78 283 +1366 4 2 1 1 189 16 78 283 +1367 4 2 1 1 283 325 131 44 +1368 4 2 1 1 189 186 43 283 +1369 4 2 1 1 283 204 44 189 +1370 4 2 1 1 44 189 43 283 +1371 4 2 1 1 211 284 214 80 +1372 4 2 1 1 284 211 79 80 +1373 4 2 1 1 222 46 211 284 +1374 4 2 1 1 47 211 284 214 +1375 4 2 1 1 46 47 211 284 +1376 4 2 1 1 284 222 79 211 +1377 4 2 1 1 285 315 97 22 +1378 4 2 1 1 285 171 68 164 +1379 4 2 1 1 68 285 164 67 +1380 4 2 1 1 23 171 285 164 +1381 4 2 1 1 285 169 22 164 +1382 4 2 1 1 285 22 23 164 +1383 4 2 1 1 197 286 186 77 +1384 4 2 1 1 15 286 197 77 +1385 4 2 1 1 286 322 41 132 +1386 4 2 1 1 42 286 186 197 +1387 4 2 1 1 286 322 132 15 +1388 4 2 1 1 197 42 286 41 +1389 4 2 1 1 287 316 38 121 +1390 4 2 1 1 172 163 287 76 +1391 4 2 1 1 75 287 163 76 +1392 4 2 1 1 39 163 287 172 +1393 4 2 1 1 287 316 121 75 +1394 4 2 1 1 38 163 287 39 +1395 4 2 1 1 288 312 59 162 +1396 4 2 1 1 288 15 195 86 +1397 4 2 1 1 195 203 15 288 +1398 4 2 1 1 288 312 162 86 +1399 4 2 1 1 60 203 195 288 +1400 4 2 1 1 288 195 60 59 +1401 4 2 1 1 289 319 62 198 +1402 4 2 1 1 289 317 196 63 +1403 4 2 1 1 87 289 213 88 +1404 4 2 1 1 289 220 63 213 +1405 4 2 1 1 289 319 198 87 +1406 4 2 1 1 289 62 213 63 +1407 4 2 1 1 290 310 92 27 +1408 4 2 1 1 193 12 290 70 +1409 4 2 1 1 193 290 12 205 +1410 4 2 1 1 290 185 27 193 +1411 4 2 1 1 193 28 290 205 +1412 4 2 1 1 290 27 28 193 +1413 4 2 1 1 291 321 54 150 +1414 4 2 1 1 318 138 141 84 +1415 4 2 1 1 84 161 291 83 +1416 4 2 1 1 291 321 150 83 +1417 4 2 1 1 318 161 84 173 +1418 4 2 1 1 55 291 161 54 +1419 4 2 1 1 292 160 147 66 +1420 4 2 1 1 292 160 66 65 +1421 4 2 1 1 292 140 19 147 +1422 4 2 1 1 309 140 18 292 +1423 4 2 1 1 140 19 18 292 +1424 4 2 1 1 309 140 292 65 +1425 4 2 1 1 293 209 185 69 +1426 4 2 1 1 293 209 69 11 +1427 4 2 1 1 293 301 108 25 +1428 4 2 1 1 26 194 185 293 +1429 4 2 1 1 293 206 25 194 +1430 4 2 1 1 26 25 194 293 +1431 4 2 1 1 294 159 74 148 +1432 4 2 1 1 294 159 148 139 +1433 4 2 1 1 308 139 294 34 +1434 4 2 1 1 294 35 139 148 +1435 4 2 1 1 34 35 139 294 +1436 4 2 1 1 308 139 34 146 +1437 4 2 1 1 295 234 210 71 +1438 4 2 1 1 295 234 71 12 +1439 4 2 1 1 295 304 107 29 +1440 4 2 1 1 30 219 210 295 +1441 4 2 1 1 295 231 29 219 +1442 4 2 1 1 219 30 29 295 +1443 4 2 1 1 311 99 89 72 +1444 4 2 1 1 218 72 9 296 +1445 4 2 1 1 218 9 230 296 +1446 4 2 1 1 311 218 72 210 +1447 4 2 1 1 218 230 32 296 +1448 4 2 1 1 218 32 31 296 +1449 4 2 1 1 85 188 297 199 +1450 4 2 1 1 297 11 85 199 +1451 4 2 1 1 297 293 301 11 +1452 4 2 1 1 188 58 297 199 +1453 4 2 1 1 206 199 297 57 +1454 4 2 1 1 58 297 199 57 +1455 4 2 1 1 298 81 212 82 +1456 4 2 1 1 313 212 82 298 +1457 4 2 1 1 298 320 151 50 +1458 4 2 1 1 313 212 298 51 +1459 4 2 1 1 298 223 50 212 +1460 4 2 1 1 50 212 51 298 +1461 4 2 1 1 299 283 186 78 +1462 4 2 1 1 299 286 77 186 +1463 4 2 1 1 299 286 186 42 +1464 4 2 1 1 78 186 299 77 +1465 4 2 1 1 299 283 43 186 +1466 4 2 1 1 186 43 299 42 +1467 4 2 1 1 300 287 76 172 +1468 4 2 1 1 300 287 172 39 +1469 4 2 1 1 300 15 172 76 +1470 4 2 1 1 300 172 15 180 +1471 4 2 1 1 172 300 40 180 +1472 4 2 1 1 39 172 300 40 +1473 4 2 1 1 297 293 11 199 +1474 4 2 1 1 297 301 206 57 +1475 4 2 1 1 283 204 16 325 +1476 4 2 1 1 36 6 156 324 +1477 4 2 1 1 57 206 3 301 +1478 4 2 1 1 16 79 302 222 +1479 4 2 1 1 305 324 36 156 +1480 4 2 1 1 302 284 46 222 +1481 4 2 1 1 302 284 222 79 +1482 4 2 1 1 305 324 156 14 +1483 4 2 1 1 222 302 45 46 +1484 4 2 1 1 296 303 9 230 +1485 4 2 1 1 320 303 9 157 +1486 4 2 1 1 296 303 230 32 +1487 4 2 1 1 49 303 1 230 +1488 4 2 1 1 303 32 1 230 +1489 4 2 1 1 290 304 12 205 +1490 4 2 1 1 319 12 304 205 +1491 4 2 1 1 290 304 205 28 +1492 4 2 1 1 304 61 205 4 +1493 4 2 1 1 28 4 304 205 +1494 4 2 1 1 305 294 74 148 +1495 4 2 1 1 305 294 148 35 +1496 4 2 1 1 148 305 14 74 +1497 4 2 1 1 148 14 305 156 +1498 4 2 1 1 305 148 156 36 +1499 4 2 1 1 148 305 35 36 +1500 4 2 1 1 306 285 171 68 +1501 4 2 1 1 171 68 11 306 +1502 4 2 1 1 306 301 24 108 +1503 4 2 1 1 306 285 23 171 +1504 4 2 1 1 306 301 108 11 +1505 4 2 1 1 171 24 23 306 +1506 4 2 1 1 284 307 214 80 +1507 4 2 1 1 214 307 13 80 +1508 4 2 1 1 13 307 214 229 +1509 4 2 1 1 284 307 47 214 +1510 4 2 1 1 48 214 307 229 +1511 4 2 1 1 214 307 47 48 +1512 4 2 1 1 146 73 13 308 +1513 4 2 1 1 308 323 33 133 +1514 4 2 1 1 308 139 146 73 +1515 4 2 1 1 308 139 73 294 +1516 4 2 1 1 308 323 133 13 +1517 4 2 1 1 146 33 34 308 +1518 4 2 1 1 9 145 309 65 +1519 4 2 1 1 309 303 109 17 +1520 4 2 1 1 309 140 65 145 +1521 4 2 1 1 309 157 17 145 +1522 4 2 1 1 145 18 17 309 +1523 4 2 1 1 309 140 145 18 +1524 4 2 1 1 310 293 185 69 +1525 4 2 1 1 69 310 70 185 +1526 4 2 1 1 290 185 70 310 +1527 4 2 1 1 310 293 26 185 +1528 4 2 1 1 310 26 27 185 +1529 4 2 1 1 290 185 310 27 +1530 4 2 1 1 210 72 311 71 +1531 4 2 1 1 311 295 210 71 +1532 4 2 1 1 311 218 210 31 +1533 4 2 1 1 311 295 30 210 +1534 4 2 1 1 311 30 31 210 +1535 4 2 1 1 311 218 31 296 +1536 4 2 1 1 297 312 188 85 +1537 4 2 1 1 85 86 312 188 +1538 4 2 1 1 297 312 58 188 +1539 4 2 1 1 188 59 312 58 +1540 4 2 1 1 288 188 59 312 +1541 4 2 1 1 288 188 312 86 +1542 4 2 1 1 313 212 51 221 +1543 4 2 1 1 313 221 13 82 +1544 4 2 1 1 13 229 221 313 +1545 4 2 1 1 313 212 221 82 +1546 4 2 1 1 221 229 52 313 +1547 4 2 1 1 313 52 221 51 +1548 4 2 1 1 314 292 147 66 +1549 4 2 1 1 147 66 10 314 +1550 4 2 1 1 10 147 314 155 +1551 4 2 1 1 314 292 19 147 +1552 4 2 1 1 314 147 20 155 +1553 4 2 1 1 20 19 147 314 +1554 4 2 1 1 169 315 10 67 +1555 4 2 1 1 10 315 169 181 +1556 4 2 1 1 285 169 67 315 +1557 4 2 1 1 169 315 21 181 +1558 4 2 1 1 315 21 22 169 +1559 4 2 1 1 285 169 315 22 +1560 4 2 1 1 170 75 14 316 +1561 4 2 1 1 60 322 7 203 +1562 4 2 1 1 288 322 60 203 +1563 4 2 1 1 37 170 316 38 +1564 4 2 1 1 287 170 38 316 +1565 4 2 1 1 287 170 316 75 +1566 4 2 1 1 16 88 220 317 +1567 4 2 1 1 317 325 204 64 +1568 4 2 1 1 289 220 88 317 +1569 4 2 1 1 317 228 64 220 +1570 4 2 1 1 63 220 317 64 +1571 4 2 1 1 289 220 317 63 +1572 4 2 1 1 318 84 14 173 +1573 4 2 1 1 14 318 173 182 +1574 4 2 1 1 318 161 173 55 +1575 4 2 1 1 318 173 182 56 +1576 4 2 1 1 173 318 55 56 +1577 4 2 1 1 318 161 55 291 +1578 4 2 1 1 12 319 224 87 +1579 4 2 1 1 319 295 304 12 +1580 4 2 1 1 319 61 231 224 +1581 4 2 1 1 224 319 61 62 +1582 4 2 1 1 319 213 62 224 +1583 4 2 1 1 319 213 224 87 +1584 4 2 1 1 320 9 223 81 +1585 4 2 1 1 288 322 203 15 +1586 4 2 1 1 298 223 81 320 +1587 4 2 1 1 320 230 49 223 +1588 4 2 1 1 49 223 50 320 +1589 4 2 1 1 298 223 320 50 +1590 4 2 1 1 10 83 321 175 +1591 4 2 1 1 175 321 10 181 +1592 4 2 1 1 321 175 53 181 +1593 4 2 1 1 175 54 321 53 +1594 4 2 1 1 291 175 54 321 +1595 4 2 1 1 291 175 321 83 +1596 4 2 1 1 21 326 2 181 +1597 4 2 1 1 181 326 10 315 +1598 4 2 1 1 322 41 7 203 +1599 4 2 1 1 286 203 41 322 +1600 4 2 1 1 286 203 322 15 +1601 4 2 1 1 323 307 13 229 +1602 4 2 1 1 323 307 229 48 +1603 4 2 1 1 158 323 13 313 +1604 4 2 1 1 323 52 158 5 +1605 4 2 1 1 5 48 323 229 +1606 4 2 1 1 326 53 2 181 +1607 4 2 1 1 321 326 181 53 +1608 4 2 1 1 20 326 110 314 +1609 4 2 1 1 326 110 314 10 +1610 4 2 1 1 21 326 181 315 +1611 4 2 1 1 321 326 10 181 +1612 4 2 1 1 323 52 5 229 +1613 4 2 1 1 304 61 4 231 +1614 4 2 1 1 319 295 12 224 +1615 4 2 1 1 304 61 231 319 +1616 4 2 1 1 313 323 13 229 +1617 4 2 1 1 15 300 180 322 +1618 4 2 1 1 323 52 229 313 +1619 4 2 1 1 40 322 7 180 +1620 4 2 1 1 40 322 180 300 +1621 4 2 1 1 318 324 182 14 +1622 4 2 1 1 324 316 14 134 +1623 4 2 1 1 318 324 56 182 +1624 4 2 1 1 37 324 134 316 +1625 4 2 1 1 324 182 6 56 +1626 4 2 1 1 16 325 302 131 +1627 4 2 1 1 317 228 16 325 +1628 4 2 1 1 45 325 131 302 +1629 4 2 1 1 64 325 8 228 +1630 4 2 1 1 317 228 325 64 +1631 4 2 1 1 309 157 303 17 +1632 4 2 1 1 1 17 303 157 +1633 4 2 1 1 3 24 179 301 +1634 4 2 2 2 340 275 334 281 +1635 4 2 2 2 76 348 259 333 +1636 4 2 2 2 328 330 346 327 +1637 4 2 2 2 337 332 334 341 +1638 4 2 2 2 328 330 327 340 +1639 4 2 2 2 239 340 328 342 +1640 4 2 2 2 346 339 330 258 +1641 4 2 2 2 330 339 346 327 +1642 4 2 2 2 330 339 253 258 +1643 4 2 2 2 76 348 333 250 +1644 4 2 2 2 259 348 327 333 +1645 4 2 2 2 330 255 253 327 +1646 4 2 2 2 247 332 341 78 +1647 4 2 2 2 339 333 327 343 +1648 4 2 2 2 333 266 75 343 +1649 4 2 2 2 334 340 342 328 +1650 4 2 2 2 334 271 328 342 +1651 4 2 2 2 239 340 342 71 +1652 4 2 2 2 76 259 348 265 +1653 4 2 2 2 328 330 340 237 +1654 4 2 2 2 346 260 336 328 +1655 4 2 2 2 340 330 327 345 +1656 4 2 2 2 253 339 330 327 +1657 4 2 2 2 328 330 237 346 +1658 4 2 2 2 237 340 328 236 +1659 4 2 2 2 341 334 337 282 +1660 4 2 2 2 334 271 342 87 +1661 4 2 2 2 266 343 14 75 +1662 4 2 2 2 328 332 334 327 +1663 4 2 2 2 237 340 236 240 +1664 4 2 2 2 339 328 346 327 +1665 4 2 2 2 262 348 328 259 +1666 4 2 2 2 253 339 251 258 +1667 4 2 2 2 346 235 328 336 +1668 4 2 2 2 340 335 327 276 +1669 4 2 2 2 340 335 276 279 +1670 4 2 2 2 276 337 280 327 +1671 4 2 2 2 339 328 327 259 +1672 4 2 2 2 334 282 341 88 +1673 4 2 2 2 329 245 249 327 +1674 4 2 2 2 328 332 327 348 +1675 4 2 2 2 329 248 245 327 +1676 4 2 2 2 16 341 282 88 +1677 4 2 2 2 337 334 332 327 +1678 4 2 2 2 329 257 254 327 +1679 4 2 2 2 329 256 327 254 +1680 4 2 2 2 251 339 253 327 +1681 4 2 2 2 348 332 333 250 +1682 4 2 2 2 334 270 328 268 +1683 4 2 2 2 337 332 341 247 +1684 4 2 2 2 255 252 253 327 +1685 4 2 2 2 333 332 348 327 +1686 4 2 2 2 335 252 255 327 +1687 4 2 2 2 257 339 327 343 +1688 4 2 2 2 244 248 337 327 +1689 4 2 2 2 334 270 268 272 +1690 4 2 2 2 340 330 345 240 +1691 4 2 2 2 331 239 238 328 +1692 4 2 2 2 339 333 343 266 +1693 4 2 2 2 257 339 343 84 +1694 4 2 2 2 335 280 327 276 +1695 4 2 2 2 331 271 328 269 +1696 4 2 2 2 259 339 260 261 +1697 4 2 2 2 276 337 327 334 +1698 4 2 2 2 249 243 333 327 +1699 4 2 2 2 334 276 340 327 +1700 4 2 2 2 256 252 335 327 +1701 4 2 2 2 268 271 269 328 +1702 4 2 2 2 239 236 238 328 +1703 4 2 2 2 259 339 261 266 +1704 4 2 2 2 270 268 267 328 +1705 4 2 2 2 235 236 237 328 +1706 4 2 2 2 245 243 249 327 +1707 4 2 2 2 254 257 251 327 +1708 4 2 2 2 276 337 334 278 +1709 4 2 2 2 256 254 252 327 +1710 4 2 2 2 244 245 248 327 +1711 4 2 2 2 259 262 260 328 +1712 4 2 2 2 339 328 259 260 +1713 4 2 2 2 332 244 327 243 +1714 4 2 2 2 253 252 251 327 +1715 4 2 2 2 245 244 243 327 +1716 4 2 2 2 254 251 252 327 +1717 4 2 2 2 269 267 268 328 +1718 4 2 2 2 238 236 235 328 +1719 4 2 2 2 338 264 328 344 +1720 4 2 2 2 329 245 74 249 +1721 4 2 2 2 237 66 346 330 +1722 4 2 2 2 331 238 69 242 +1723 4 2 2 2 250 332 246 77 +1724 4 2 2 2 336 264 328 260 +1725 4 2 2 2 237 65 330 240 +1726 4 2 2 2 329 248 73 245 +1727 4 2 2 2 247 332 78 246 +1728 4 2 2 2 238 70 239 331 +1729 4 2 2 2 333 266 259 75 +1730 4 2 2 2 337 334 278 282 +1731 4 2 2 2 329 257 327 343 +1732 4 2 2 2 335 345 327 255 +1733 4 2 2 2 335 280 276 82 +1734 4 2 2 2 334 271 87 268 +1735 4 2 2 2 235 346 67 336 +1736 4 2 2 2 336 264 260 68 +1737 4 2 2 2 330 258 253 66 +1738 4 2 2 2 329 343 327 249 +1739 4 2 2 2 331 273 69 269 +1740 4 2 2 2 83 346 339 263 +1741 4 2 2 2 329 256 254 73 +1742 4 2 2 2 340 330 240 237 +1743 4 2 2 2 332 244 243 246 +1744 4 2 2 2 331 271 269 70 +1745 4 2 2 2 238 242 331 328 +1746 4 2 2 2 338 264 344 85 +1747 4 2 2 2 337 282 278 79 +1748 4 2 2 2 339 260 261 263 +1749 4 2 2 2 348 86 262 338 +1750 4 2 2 2 338 264 85 262 +1751 4 2 2 2 331 273 269 328 +1752 4 2 2 2 242 235 336 328 +1753 4 2 2 2 243 75 249 333 +1754 4 2 2 2 76 243 250 333 +1755 4 2 2 2 272 334 88 268 +1756 4 2 2 2 335 81 255 252 +1757 4 2 2 2 82 335 256 252 +1758 4 2 2 2 334 271 268 328 +1759 4 2 2 2 235 67 346 241 +1760 4 2 2 2 336 68 235 242 +1761 4 2 2 2 247 244 79 337 +1762 4 2 2 2 264 260 262 328 +1763 4 2 2 2 262 348 259 265 +1764 4 2 2 2 80 337 244 248 +1765 4 2 2 2 338 264 262 328 +1766 4 2 2 2 83 346 263 10 +1767 4 2 2 2 80 347 280 337 +1768 4 2 2 2 347 280 337 327 +1769 4 2 2 2 80 347 337 248 +1770 4 2 2 2 345 340 72 279 +1771 4 2 2 2 9 279 345 72 +1772 4 2 2 2 340 335 279 345 +1773 4 2 2 2 331 273 344 69 +1774 4 2 2 2 333 332 243 250 +1775 4 2 2 2 76 75 243 333 +1776 4 2 2 2 334 268 87 88 +1777 4 2 2 2 235 68 336 67 +1778 4 2 2 2 335 82 81 252 +1779 4 2 2 2 339 83 84 251 +1780 4 2 2 2 262 338 86 85 +1781 4 2 2 2 236 72 340 71 +1782 4 2 2 2 337 244 79 80 +1783 4 2 2 2 330 65 237 66 +1784 4 2 2 2 73 329 245 74 +1785 4 2 2 2 331 238 70 69 +1786 4 2 2 2 78 246 332 77 +1787 4 2 2 2 14 74 249 343 +1788 4 2 2 2 346 241 10 66 +1789 4 2 2 2 345 65 9 240 +1790 4 2 2 2 342 239 12 70 +1791 4 2 2 2 341 78 16 247 +1792 4 2 2 2 13 347 248 73 +1793 4 2 2 2 344 69 11 242 +1794 4 2 2 2 348 77 332 250 +1795 4 2 2 2 9 345 240 72 +1796 4 2 2 2 345 81 9 255 +1797 4 2 2 2 80 347 248 13 +1798 4 2 2 2 13 82 347 256 +1799 4 2 2 2 239 342 12 71 +1800 4 2 2 2 247 79 16 341 +1801 4 2 2 2 241 10 67 346 +1802 4 2 2 2 83 346 10 258 +1803 4 2 2 2 14 257 343 84 +1804 4 2 2 2 12 87 342 271 +1805 4 2 2 2 11 344 264 85 +1806 4 2 2 2 242 68 11 344 +1807 4 2 2 2 16 272 341 88 +1808 4 2 2 2 343 249 14 75 +1809 4 2 2 2 15 86 265 348 +1810 4 2 2 2 76 348 250 15 +1811 4 2 2 2 273 267 269 328 +1812 4 2 2 2 238 235 242 328 +1813 4 2 2 2 258 339 251 83 +1814 4 2 2 2 331 273 328 344 +1815 4 2 2 2 348 267 328 270 +1816 4 2 2 2 328 332 348 270 +1817 4 2 2 2 346 235 241 237 +1818 4 2 2 2 346 235 237 328 +1819 4 2 2 2 240 340 236 72 +1820 4 2 2 2 240 340 72 345 +1821 4 2 2 2 257 339 84 251 +1822 4 2 2 2 257 339 251 327 +1823 4 2 2 2 348 262 86 265 +1824 4 2 2 2 243 332 333 327 +1825 4 2 2 2 239 340 71 236 +1826 4 2 2 2 239 340 236 328 +1827 4 2 2 2 337 332 247 244 +1828 4 2 2 2 337 341 79 247 +1829 4 2 2 2 259 348 328 327 +1830 4 2 2 2 262 348 338 328 +1831 4 2 2 2 329 343 249 74 +1832 4 2 2 2 329 347 73 248 +1833 4 2 2 2 329 257 74 254 +1834 4 2 2 2 329 347 248 327 +1835 4 2 2 2 73 254 329 74 +1836 4 2 2 2 237 346 66 241 +1837 4 2 2 2 330 345 240 65 +1838 4 2 2 2 276 337 278 280 +1839 4 2 2 2 330 255 65 253 +1840 4 2 2 2 253 65 330 66 +1841 4 2 2 2 331 342 70 239 +1842 4 2 2 2 331 344 328 242 +1843 4 2 2 2 331 342 239 328 +1844 4 2 2 2 331 344 242 69 +1845 4 2 2 2 269 331 70 69 +1846 4 2 2 2 328 332 270 334 +1847 4 2 2 2 270 341 334 332 +1848 4 2 2 2 77 270 348 332 +1849 4 2 2 2 270 341 332 78 +1850 4 2 2 2 78 332 270 77 +1851 4 2 2 2 273 69 11 344 +1852 4 2 2 2 333 343 75 249 +1853 4 2 2 2 333 343 249 327 +1854 4 2 2 2 278 334 275 282 +1855 4 2 2 2 76 75 333 259 +1856 4 2 2 2 340 334 327 328 +1857 4 2 2 2 334 341 272 88 +1858 4 2 2 2 340 275 281 277 +1859 4 2 2 2 334 282 88 275 +1860 4 2 2 2 87 281 334 275 +1861 4 2 2 2 275 334 87 88 +1862 4 2 2 2 335 345 255 81 +1863 4 2 2 2 335 347 82 256 +1864 4 2 2 2 335 279 81 276 +1865 4 2 2 2 335 347 256 327 +1866 4 2 2 2 276 82 81 335 +1867 4 2 2 2 334 276 275 340 +1868 4 2 2 2 336 344 68 242 +1869 4 2 2 2 260 67 346 336 +1870 4 2 2 2 336 344 242 328 +1871 4 2 2 2 336 68 260 67 +1872 4 2 2 2 331 271 342 328 +1873 4 2 2 2 337 332 244 327 +1874 4 2 2 2 337 280 80 278 +1875 4 2 2 2 278 337 79 80 +1876 4 2 2 2 329 257 343 74 +1877 4 2 2 2 273 338 267 328 +1878 4 2 2 2 267 86 348 338 +1879 4 2 2 2 338 273 267 85 +1880 4 2 2 2 338 267 86 85 +1881 4 2 2 2 348 267 270 274 +1882 4 2 2 2 339 260 263 346 +1883 4 2 2 2 339 333 266 259 +1884 4 2 2 2 261 83 84 339 +1885 4 2 2 2 263 339 83 261 +1886 4 2 2 2 339 266 84 261 +1887 4 2 2 2 340 276 275 277 +1888 4 2 2 2 340 276 277 279 +1889 4 2 2 2 334 276 278 275 +1890 4 2 2 2 340 72 277 71 +1891 4 2 2 2 340 72 279 277 +1892 4 2 2 2 71 340 281 277 +1893 4 2 2 2 270 341 78 272 +1894 4 2 2 2 270 341 272 334 +1895 4 2 2 2 331 271 70 342 +1896 4 2 2 2 271 342 12 70 +1897 4 2 2 2 272 78 16 341 +1898 4 2 2 2 334 342 340 281 +1899 4 2 2 2 14 74 343 257 +1900 4 2 2 2 342 340 281 71 +1901 4 2 2 2 337 282 79 341 +1902 4 2 2 2 342 281 12 71 +1903 4 2 2 2 341 79 16 282 +1904 4 2 2 2 339 333 259 327 +1905 4 2 2 2 343 339 266 84 +1906 4 2 2 2 329 256 347 327 +1907 4 2 2 2 14 343 266 84 +1908 4 2 2 2 329 256 73 347 +1909 4 2 2 2 76 348 15 265 +1910 4 2 2 2 13 256 347 73 +1911 4 2 2 2 348 77 250 15 +1912 4 2 2 2 348 77 15 274 +1913 4 2 2 2 338 344 328 273 +1914 4 2 2 2 338 344 273 85 +1915 4 2 2 2 336 264 344 328 +1916 4 2 2 2 336 264 68 344 +1917 4 2 2 2 11 273 344 85 +1918 4 2 2 2 344 68 11 264 +1919 4 2 2 2 340 335 345 327 +1920 4 2 2 2 260 346 67 263 +1921 4 2 2 2 279 81 9 345 +1922 4 2 2 2 335 279 345 81 +1923 4 2 2 2 243 332 246 250 +1924 4 2 2 2 83 346 258 339 +1925 4 2 2 2 258 346 10 66 +1926 4 2 2 2 330 258 66 346 +1927 4 2 2 2 332 244 246 247 +1928 4 2 2 2 347 337 248 327 +1929 4 2 2 2 80 347 13 280 +1930 4 2 2 2 13 82 280 347 +1931 4 2 2 2 335 280 82 347 +1932 4 2 2 2 335 280 347 327 +1933 4 2 2 2 330 255 327 345 +1934 4 2 2 2 334 342 281 87 +1935 4 2 2 2 12 87 281 342 +1936 4 2 2 2 346 10 67 263 +1937 4 2 2 2 339 328 260 346 +1938 4 2 2 2 77 348 270 274 +1939 4 2 2 2 267 348 86 274 +1940 4 2 2 2 330 255 345 65 +1941 4 2 2 2 15 86 348 274 +1942 4 2 2 2 348 267 338 328 +1943 4 2 2 2 255 65 9 345 +$EndElements diff --git a/fem/pfespace.cpp b/fem/pfespace.cpp index a08861b46e..24ae5b4052 100644 --- a/fem/pfespace.cpp +++ b/fem/pfespace.cpp @@ -1118,6 +1118,14 @@ void ParFiniteElementSpace::Synchronize(Array &ldof_marker) const gcomm->Bcast(ldof_marker); } +void ParFiniteElementSpace::SynchronizeBC(Array &bc_values) const +{ + + // Use the MaxAbs reduction mode + gcomm->Reduce(bc_values, GroupCommunicator::MaxAbs); + gcomm->Bcast(bc_values); +} + void ParFiniteElementSpace::GetEssentialVDofs(const Array &bdr_attr_is_ess, Array &ess_dofs, int component) const @@ -1255,6 +1263,372 @@ void ParFiniteElementSpace::GetExteriorVDofs(Array &ext_dofs, Synchronize(ext_dofs); } +void ParFiniteElementSpace::GetBoundaryEdgeDoFs(const Array + &boundary_element_indices, + Array &ess_tdof_list, + Array &ldof_marker, + std::unordered_set &boundary_edge_dofs_out, + std::unordered_map *dof_to_edge, + std::unordered_map *dof_to_orientation, + std::unordered_map *dof_to_boundary_element_out, + Array *ess_edge_list) +{ + // Data structures for boundary edge DoFs + std::unordered_set boundary_edge_dofs; + std::unordered_map dof_to_edge_map; + std::unordered_map dof_to_boundary_element; + std::unordered_map dof_to_edge_orientation; + + // Collect boundary edge DoFs using a toggle approach + Array edges, edge_orientations, edge_dofs; + for (int i = 0; i < boundary_element_indices.Size(); ++i) + { + int boundary_element_idx = boundary_element_indices[i]; + int face_index, face_orientation; + pmesh->GetBdrElementFace(boundary_element_idx, &face_index, &face_orientation); + pmesh->GetFaceEdges(face_index, edges, edge_orientations); + + for (int j = 0; j < edges.Size(); ++j) + { + GetEdgeDofs(edges[j], edge_dofs); + for (int k = 0; k < edge_dofs.Size(); ++k) + { + int dof = edge_dofs[k]; + if (!boundary_edge_dofs.count(dof)) + { + boundary_edge_dofs.insert(dof); + dof_to_edge_map[dof] = edges[j]; + dof_to_boundary_element[dof] = boundary_element_idx; + dof_to_edge_orientation[dof] = edge_orientations[j]; + } + else + { + // DoF appears twice - interior to boundary, remove it + boundary_edge_dofs.erase(dof); + dof_to_edge_map.erase(dof); + dof_to_boundary_element.erase(dof); + dof_to_edge_orientation.erase(dof); + } + } + } + } + + // Build edge sharing lookup table + std::unordered_map edge_to_group_size; + int num_groups = pmesh->GetNGroups(); + + int total_shared_edges = 0; + for (int group = 1; group < num_groups; group++) + { + total_shared_edges += pmesh->GroupNEdges(group); + } + edge_to_group_size.reserve(total_shared_edges); + + for (int group = 1; group < num_groups; group++) + { + int group_size = pmesh->gtopo.GetGroupSize(group); + int num_edges_in_group = pmesh->GroupNEdges(group); + + for (int i = 0; i < num_edges_in_group; i++) + { + edge_to_group_size.emplace(pmesh->GroupEdge(group, i), group_size); + } + } + + // Get global indices + Array global_edge_indices; + pmesh->GetGlobalEdgeIndices(global_edge_indices); + + Array global_face_indices; + pmesh->GetGlobalFaceIndices(global_face_indices); + + // Pre-compute face indices for boundary elements + std::unordered_map boundary_element_to_face; + for (int i = 0; i < boundary_element_indices.Size(); ++i) + { + int boundary_element_idx = boundary_element_indices[i]; + int face_index, face_orientation; + pmesh->GetBdrElementFace(boundary_element_idx, &face_index, &face_orientation); + boundary_element_to_face[boundary_element_idx] = face_index; + } + + // Collect shared boundary edge-face pairs + std::vector local_data; + local_data.reserve(boundary_edge_dofs.size() * 2); + + std::unordered_set processed_edges; + processed_edges.reserve(boundary_edge_dofs.size()); + + for (const auto& pair : dof_to_edge_map) + { + int local_edge = pair.second; + + // Skip if already processed this edge + if (!processed_edges.insert(local_edge).second) { continue; } + + // Check if edge is shared (fast lookup) + auto it = edge_to_group_size.find(local_edge); + if (it != edge_to_group_size.end() && it->second > 1) + { + // Get boundary element and face index directly from pre-computed map + int dof = pair.first; + int boundary_element_idx = dof_to_boundary_element[dof]; + int face_index = boundary_element_to_face[boundary_element_idx]; + + // Store edge-face pair + local_data.push_back(global_edge_indices[local_edge]); + local_data.push_back(global_face_indices[face_index]); + } + } + + // MPI communication + int num_procs = pmesh->GetNRanks(); + int local_size = local_data.size(); + + std::vector mpi_arrays(num_procs * 4); + int* all_sizes = mpi_arrays.data(); + int* displs = all_sizes + num_procs; + int* byte_sizes = displs + num_procs; + int* byte_displs = byte_sizes + num_procs; + + MPI_Allgather(&local_size, 1, MPI_INT, all_sizes, 1, MPI_INT, pmesh->GetComm()); + + int total_size = 0; + constexpr int hypre_size = sizeof(HYPRE_BigInt); + for (int i = 0; i < num_procs; i++) + { + displs[i] = total_size; + byte_displs[i] = total_size * hypre_size; + total_size += all_sizes[i]; + byte_sizes[i] = all_sizes[i] * hypre_size; + } + + std::unordered_set dofs_to_remove; + + if (total_size > 0) + { + std::vector all_data(total_size); + MPI_Allgatherv(local_data.data(), local_size * hypre_size, MPI_BYTE, + all_data.data(), byte_sizes, byte_displs, MPI_BYTE, pmesh->GetComm()); + + // Build global-to-local edge mapping + std::unordered_map global_to_local_edge; + global_to_local_edge.reserve(global_edge_indices.Size()); + for (int i = 0; i < global_edge_indices.Size(); ++i) + { + global_to_local_edge[global_edge_indices[i]] = i; + } + + // Process collected data + std::unordered_map> + edge_to_faces; + edge_to_faces.reserve(total_size / 2); + + for (size_t i = 0; i < all_data.size(); i += 2) + { + edge_to_faces[all_data[i]].insert(all_data[i + 1]); + } + + // Mark DoFs from artificial edges for removal + dofs_to_remove.reserve(local_data.size() / 4); + + for (size_t i = 0; i < local_data.size(); i += 2) + { + HYPRE_BigInt global_edge_id = local_data[i]; + + // If this edge appears in 2+ distinct faces, it's artificial + if (edge_to_faces[global_edge_id].size() >= 2) + { + // Fast lookup using pre-built map + auto it = global_to_local_edge.find(global_edge_id); + if (it != global_to_local_edge.end()) + { + int local_edge = it->second; + Array local_edge_dofs; + GetEdgeDofs(local_edge, local_edge_dofs); + + // Mark boundary DoFs of this edge for removal + for (int k = 0; k < local_edge_dofs.Size(); ++k) + { + int dof = local_edge_dofs[k]; + if (boundary_edge_dofs.count(dof)) + { + dofs_to_remove.insert(dof); + } + } + } + } + } + } + + // Remove artificial DoFs + for (int dof : dofs_to_remove) + { + boundary_edge_dofs.erase(dof); + dof_to_edge_map.erase(dof); + dof_to_boundary_element.erase(dof); + dof_to_edge_orientation.erase(dof); + } + + // Copy boundary edge dofs to output parameter + boundary_edge_dofs_out = boundary_edge_dofs; + + // Convert to true DoFs and output + ess_tdof_list.SetSize(0); + ess_tdof_list.Reserve(boundary_edge_dofs.size()); + // initialize ldof_marker + ldof_marker.SetSize(GetVSize()); + ldof_marker = 0; + + // Build parallel arrays for DOFs and corresponding edges + std::vector> tdof_edge_pairs; + tdof_edge_pairs.reserve(boundary_edge_dofs.size()); + + for (int dof : boundary_edge_dofs) + { + ldof_marker[dof] = 1; // Mark all boundary edge dofs + int tdof = GetLocalTDofNumber(dof); + if (tdof >= 0) + { + int edge = dof_to_edge_map[dof]; + tdof_edge_pairs.push_back({tdof, edge}); + } + } + + // Sort by true DOF index to maintain consistent ordering + std::sort(tdof_edge_pairs.begin(), tdof_edge_pairs.end()); + + // Extract sorted true DOFs and edges + for (const auto& pair : tdof_edge_pairs) + { + ess_tdof_list.Append(pair.first); + if (ess_edge_list) + { + ess_edge_list->Append(pair.second); + } + } + + // Set optional output parameters + if (dof_to_edge) + { + *dof_to_edge = dof_to_edge_map; + } + if (dof_to_orientation) + { + *dof_to_orientation = dof_to_edge_orientation; + } + if (dof_to_boundary_element_out) + { + *dof_to_boundary_element_out = dof_to_boundary_element; + } +} + +void ParFiniteElementSpace::GetBoundaryElementsByAttribute( + const Array &bdr_attrs, + std::unordered_map> &attr_to_elements) +{ + // Initialize arrays for each attribute + for (int i = 0; i < bdr_attrs.Size(); ++i) + { + attr_to_elements[bdr_attrs[i]] = Array(); + } + + // Find boundary elements for each attribute + for (int i = 0; i < pmesh->GetNBE(); ++i) + { + int attr = pmesh->GetBdrElement(i)->GetAttribute(); + auto it = attr_to_elements.find(attr); + if (it != attr_to_elements.end()) + { + it->second.Append(i); + } + } +} + +void ParFiniteElementSpace::GetBoundaryElementsByAttribute(int bdr_attr, + Array &boundary_elements) +{ + boundary_elements.SetSize(0); + + for (int i = 0; i < pmesh->GetNBE(); ++i) + { + if (pmesh->GetBdrElement(i)->GetAttribute() == bdr_attr) + { + boundary_elements.Append(i); + } + } +} + +void ParFiniteElementSpace::ComputeLoopEdgeOrientations( + const std::unordered_map& dof_to_edge, + const std::unordered_map& dof_to_boundary_element, + const Vector& loop_normal, + std::unordered_map& edge_loop_orientations) +{ + // Process each edge locally + for (const auto& pair : dof_to_boundary_element) + { + int dof = pair.first; + int bdr_elem_idx = pair.second; + + // Check if this DOF has a corresponding edge + auto edge_it = dof_to_edge.find(dof); + if (edge_it == dof_to_edge.end()) { continue; } + + int edge_id = edge_it->second; + + // Get edge vertices + Array edge_verts; + pmesh->GetEdgeVertices(edge_id, edge_verts); + + const double *v0 = pmesh->GetVertex(edge_verts[0]); + const double *v1 = pmesh->GetVertex(edge_verts[1]); + + // Get boundary element vertices + Array bdr_elem_verts; + pmesh->GetBdrElement(bdr_elem_idx)->GetVertices(bdr_elem_verts); + + // Find the third vertex (not part of the edge) + int third_vertex = -1; + for (int i = 0; i < bdr_elem_verts.Size(); i++) + { + int v = bdr_elem_verts[i]; + if (v != edge_verts[0] && v != edge_verts[1]) + { + third_vertex = v; + break; + } + } + + if (third_vertex == -1) { continue; } // No third vertex found, skip this edge + + const double *v2 = pmesh->GetVertex(third_vertex); + + // Edge vector + Vector edge_vec(3); + for (int i = 0; i < 3; i++) { edge_vec[i] = v1[i] - v0[i]; } + + // Vector from third vertex to edge (use edge midpoint) + Vector to_edge_vec(3); + for (int i = 0; i < 3; i++) + { + double edge_midpoint = (v0[i] + v1[i]) * 0.5; + to_edge_vec[i] = edge_midpoint - v2[i]; + } + + // Cross product: to_edge × edge + Vector cross_product(3); + cross_product[0] = to_edge_vec[1] * edge_vec[2] - to_edge_vec[2] * edge_vec[1]; + cross_product[1] = to_edge_vec[2] * edge_vec[0] - to_edge_vec[0] * edge_vec[2]; + cross_product[2] = to_edge_vec[0] * edge_vec[1] - to_edge_vec[1] * edge_vec[0]; + + // Check alignment with loop normal + double dot_product = cross_product * loop_normal; + edge_loop_orientations[edge_id] = (dot_product > 0) ? 1 : -1; + } +} + + void ParFiniteElementSpace::GetExteriorTrueDofs(Array &ext_tdof_list, int component) const { diff --git a/fem/pfespace.hpp b/fem/pfespace.hpp index 90c06e1beb..34ada3385d 100644 --- a/fem/pfespace.hpp +++ b/fem/pfespace.hpp @@ -20,6 +20,8 @@ #include "../mesh/pmesh.hpp" #include "../mesh/nurbs.hpp" #include "fespace.hpp" +#include +#include namespace mfem { @@ -420,6 +422,10 @@ public: "partially conforming") space. */ void Synchronize(Array &ldof_marker) const; + /** @brief Given a vector of boundary condition values on the local true + dofs, perform a reduction across all processors. */ + void SynchronizeBC(Array &bc_values) const; + /// Determine the boundary degrees of freedom void GetEssentialVDofs(const Array &bdr_attr_is_ess, Array &ess_dofs, @@ -448,6 +454,49 @@ public: void GetExteriorTrueDofs(Array &ext_tdof_list, int component = -1) const override; + /** Get a list of edge degrees of freedom on the boundary with the specified + attributes. This function handles parallel meshes by removing + artificial boundary edges that appear at processor boundaries. + @param[in] boundary_element_indices Array of boundary element indices + @param[out] ess_tdof_list Array of essential true DOF indices + @param[out] ldof_marker Array marking which local DOFs are boundary edge DOFs + @param[out] boundary_edge_dofs_out set of boundary edge DOFs + @param[out] dof_to_edge Optional map from DOFs to edge indices + @param[out] dof_to_orientation Optional map from DOFs to edge orientations + @param[out] dof_to_boundary_element_out Optional map from DOFs to boundary elements + @param[out] ess_edge_list Optional array of edge indices */ + void GetBoundaryEdgeDoFs(const Array &boundary_element_indices, + Array &ess_tdof_list, + Array &ldof_marker, + std::unordered_set &boundary_edge_dofs_out, + std::unordered_map *dof_to_edge = nullptr, + std::unordered_map *dof_to_orientation = nullptr, + std::unordered_map *dof_to_boundary_element_out = nullptr, + Array *ess_edge_list = nullptr); + + /** Find the boundary elements marked with specified boundary attributes + @param[in] bdr_attrs list of boundary attributes to search for + @param[out] attr_to_elements map from boundary attribute to the list of + boundary elements with that attribute */ + void GetBoundaryElementsByAttribute(const Array &bdr_attrs, + std::unordered_map> &attr_to_elements); + + /// @brief Simplified interface for single boundary attribute + void GetBoundaryElementsByAttribute(int bdr_attr, + Array &boundary_elements); + + /** Compute edge orientations relative to a loop direction defined by a normal vector. + This is useful for applying circulation boundary conditions. + @param[in] dof_to_edge Map from DOFs to edge indices + @param[in] dof_to_boundary_element Map from DOFs to boundary elements + @param[in] loop_normal Normal vector defining the loop direction + @param[out] edge_loop_orientations Map from edge indices to orientations (+1 or -1) */ + void ComputeLoopEdgeOrientations(const std::unordered_map& + dof_to_edge, + const std::unordered_map& dof_to_boundary_element, + const Vector& loop_normal, + std::unordered_map& edge_loop_orientations); + /** If the given ldof is owned by the current processor, return its local tdof number, otherwise return -1 */ int GetLocalTDofNumber(int ldof) const; diff --git a/general/communication.cpp b/general/communication.cpp index e2f3222a45..6f20f5b27b 100644 --- a/general/communication.cpp +++ b/general/communication.cpp @@ -1108,6 +1108,116 @@ void GroupCommunicator::ReduceEnd(T *ldata, int layout, num_requests = 0; } +template +void GroupCommunicator::ReduceMarked(T *ldata, const Array &marker, + int layout, + void (*Op)(OpData)) const +{ + if (comm_lock == 0) { return; } + // The above also handles the case (group_buf_size == 0). + MFEM_VERIFY(comm_lock == 2, "object is NOT locked for Reduce"); + + switch (mode) + { + case byGroup: // ***** Communication by groups ***** + { + OpData opd; + opd.ldata = ldata; + Array group_num_req(group_ldof.Size()); + for (int gr = 1; gr < group_ldof.Size(); gr++) + { + group_num_req[gr] = + gtopo.IAmMaster(gr) ? gtopo.GetGroupSize(gr)-1 : 0; + } + int idx; + while (MPI_Waitany(num_requests, requests, &idx, MPI_STATUS_IGNORE), + idx != MPI_UNDEFINED) + { + int gr = request_marker[idx]; + if (gr == -1) { continue; } // skip send requests + + // Delay the processing of a group until all receive requests, for + // that group, are done: + if ((--group_num_req[gr]) != 0) { continue; } + + opd.nldofs = group_ldof.RowSize(gr); + // groups without dofs are skipped, so here nldofs > 0. + + opd.buf = (T *)group_buf.GetData() + buf_offsets[gr]; + opd.ldofs = (layout == 0) ? + group_ldof.GetRow(gr) : group_ltdof.GetRow(gr); + opd.nb = gtopo.GetGroupSize(gr)-1; + + // Apply operation only to marked DoFs + for (int i = 0; i < opd.nldofs; i++) + { + if (marker[opd.ldofs[i]]) + { + // Create a temporary OpData with just this one DoF + OpData single_opd; + single_opd.ldata = ldata; + single_opd.buf = opd.buf + i; + single_opd.ldofs = opd.ldofs + i; + single_opd.nldofs = 1; + single_opd.nb = opd.nb; + + // Apply the operation + Op(single_opd); + } + } + } + break; + } + + case byNeighbor: // ***** Communication by neighbors ***** + { + MPI_Waitall(num_requests, requests, MPI_STATUSES_IGNORE); + + for (int nbr = 1; nbr < nbr_send_groups.Size(); nbr++) + { + // In Reduce operation: send_groups <--> recv_groups + const int num_recv_groups = nbr_send_groups.RowSize(nbr); + if (num_recv_groups > 0) + { + const int *grp_list = nbr_send_groups.GetRow(nbr); + const T *buf = (T*)group_buf.GetData() + buf_offsets[nbr]; + for (int i = 0; i < num_recv_groups; i++) + { + // Custom version of ReduceGroupFromBuffer that checks marker + int gr = grp_list[i]; + const int *ldofs = (layout == 0) ? + group_ldof.GetRow(gr) : group_ltdof.GetRow(gr); + const int nldofs = group_ldof.RowSize(gr); + + for (int j = 0; j < nldofs; j++) + { + if (marker[ldofs[j]]) + { + // Create a temporary OpData with just this one DoF + OpData opd; + opd.ldata = ldata; + opd.buf = const_cast(buf) + j; + opd.ldofs = ldofs + j; + opd.nldofs = 1; + opd.nb = 1; + + // Apply the operation + Op(opd); + } + } + + buf += nldofs; + } + } + } + break; + } + } + + comm_lock = 0; // 0 - no lock + num_requests = 0; +} + template void GroupCommunicator::Sum(OpData opd) { @@ -1182,6 +1292,31 @@ void GroupCommunicator::BitOR(OpData opd) } } +template +void GroupCommunicator::MaxAbs(OpData opd) +{ + for (int i = 0; i < opd.nldofs; i++) + { + T data = opd.ldata[opd.ldofs[i]]; + T abs_data = std::abs(data); + + for (int j = 0; j < opd.nb; j++) + { + T b = opd.buf[j*opd.nldofs+i]; + T abs_b = std::abs(b); + + if (abs_data < abs_b) + { + data = b; + abs_data = abs_b; + } + } + + opd.ldata[opd.ldofs[i]] = data; + } +} + + void GroupCommunicator::PrintInfo(std::ostream &os) const { char c = '\0'; @@ -1318,18 +1453,24 @@ template void GroupCommunicator::BcastEnd(int *, int) const; template void GroupCommunicator::ReduceBegin(const int *) const; template void GroupCommunicator::ReduceEnd( int *, int, void (*)(OpData)) const; +template void GroupCommunicator::ReduceMarked( + int*, const Array&, int, void (*)(OpData)) const; template void GroupCommunicator::BcastBegin(double *, int) const; template void GroupCommunicator::BcastEnd(double *, int) const; template void GroupCommunicator::ReduceBegin(const double *) const; template void GroupCommunicator::ReduceEnd( double *, int, void (*)(OpData)) const; +template void GroupCommunicator::ReduceMarked( + double*, const Array&, int, void (*)(OpData)) const; template void GroupCommunicator::BcastBegin(float *, int) const; template void GroupCommunicator::BcastEnd(float *, int) const; template void GroupCommunicator::ReduceBegin(const float *) const; template void GroupCommunicator::ReduceEnd( float *, int, void (*)(OpData)) const; +template void GroupCommunicator::ReduceMarked( + float*, const Array&, int, void (*)(OpData)) const; // @endcond @@ -1338,14 +1479,17 @@ template void GroupCommunicator::Sum(OpData); template void GroupCommunicator::Min(OpData); template void GroupCommunicator::Max(OpData); template void GroupCommunicator::BitOR(OpData); +template void GroupCommunicator::MaxAbs(OpData); template void GroupCommunicator::Sum(OpData); template void GroupCommunicator::Min(OpData); template void GroupCommunicator::Max(OpData); +template void GroupCommunicator::MaxAbs(OpData); template void GroupCommunicator::Sum(OpData); template void GroupCommunicator::Min(OpData); template void GroupCommunicator::Max(OpData); +template void GroupCommunicator::MaxAbs(OpData); #ifdef __bgq__ diff --git a/general/communication.hpp b/general/communication.hpp index 58b14f55b5..7201d59f40 100644 --- a/general/communication.hpp +++ b/general/communication.hpp @@ -416,6 +416,43 @@ public: template static void Max(OpData); /// Reduce operation bitwise OR, instantiated for int only template static void BitOR(OpData); + /// Reduce operation max absolute value, instantiated for int and double + template static void MaxAbs(OpData); + + /** @brief Finalize reduction operation started with ReduceBegin(), but only apply + the reduction to DoFs marked in the marker array. + */ + template + void ReduceMarked(T *ldata, const Array &marker, int layout, + void (*Op)(OpData)) const; + + /** @brief Reduce within each group where the master is the root, but only for marked DoFs. */ + template + void Reduce(T *ldata, const Array &marker, void (*Op)(OpData)) const + { + ReduceBegin(ldata); + ReduceMarked(ldata, marker, 0, Op); + } + + // Enum for reduction operations + enum ReduceOp { Sum_Op, Min_Op, Max_Op, BitOR_Op, MaxAbs_Op }; + + // Add specialized versions for common operations + template + void Reduce(Array &ldata, const Array &marker, ReduceOp op) + { + void (*Op)(OpData); + switch (op) + { + case Sum_Op: Op = GroupCommunicator::Sum; break; + case Min_Op: Op = GroupCommunicator::Min; break; + case Max_Op: Op = GroupCommunicator::Max; break; + case BitOR_Op: Op = GroupCommunicator::BitOR; break; + case MaxAbs_Op: Op = GroupCommunicator::MaxAbs; break; + default: Op = GroupCommunicator::Sum; break; + } + Reduce(ldata.GetData(), marker, Op); + } /// Print information about the GroupCommunicator from all MPI ranks. void PrintInfo(std::ostream &out = mfem::out) const; diff --git a/tests/unit/fem/test_bdr_edgedof.cpp b/tests/unit/fem/test_bdr_edgedof.cpp new file mode 100644 index 0000000000..f1d7bd8640 --- /dev/null +++ b/tests/unit/fem/test_bdr_edgedof.cpp @@ -0,0 +1,337 @@ +// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-806117. +// +// This file is part of the MFEM library. For more information and source code +// availability visit https://mfem.org. +// +// MFEM is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#include "unit_tests.hpp" +#include "mfem.hpp" +#include "../mesh/mesh_test_utils.hpp" + +using namespace mfem; + +#ifdef MFEM_USE_MPI + +namespace boundary_edge_dof_test +{ + +// Generate all possible partitionings of n_elements into num_procs +void GeneratePartitionings(int n_elements, int num_procs, + std::vector>& all_partitionings) +{ + std::vector partition(n_elements); + + std::function generate = [&](int elem) + { + if (elem == n_elements) + { + all_partitionings.push_back(partition); + return; + } + + for (int proc = 0; proc < num_procs; proc++) + { + partition[elem] = proc; + generate(elem + 1); + } + }; + + generate(0); +} + +} // namespace boundary_edge_dof_test + +TEST_CASE("BoundaryEdgeDoFsPartitionInvariant", + "[Parallel], [ParMesh], [BoundaryEdgeDoFs]") +{ + const int orientation = 3; + const int order = 1; + + // Adapt to actual number of MPI processes (1 or 2) + const int available_procs = Mpi::WorldSize(); + const int test_num_procs = std::min(available_procs, 2); + + // Create base mesh + Mesh base_mesh = OrientedTriFaceMesh(orientation, true); + base_mesh.UniformRefinement(); + const int n_elements = base_mesh.GetNE(); + + // Generate all partitionings for available processes + std::vector> all_partitionings; + boundary_edge_dof_test::GeneratePartitionings(n_elements, test_num_procs, + all_partitionings); + + // Create reusable FEC + ND_FECollection fec(order, 3); + + std::vector all_results; + all_results.reserve(all_partitionings.size()); + + // Test each partitioning + for (const auto& partition : all_partitionings) + { + // Create parallel mesh with current partitioning + Mesh test_mesh = OrientedTriFaceMesh(orientation, true); + test_mesh.UniformRefinement(); + // For single process, use default partitioning; for multiple, use custom partition + ParMesh pmesh = (test_num_procs == 1) ? + ParMesh(MPI_COMM_WORLD, test_mesh) : + ParMesh(MPI_COMM_WORLD, test_mesh, partition.data()); + + // Create finite element space + ParFiniteElementSpace fespace(&pmesh, &fec); + + // Extract boundary edge DoFs + Array ess_tdof_list; + std::unordered_set boundary_edge_ldofs; + Array ldof_marker; + std::unordered_map> attr_to_elements; + + // Select the shared face to be the tested boundary + int bdr_attr = pmesh.bdr_attributes.Max(); + Array bdr_attrs(1); + bdr_attrs[0] = bdr_attr; + + fespace.GetBoundaryElementsByAttribute(bdr_attrs, attr_to_elements); + Array boundary_elements = attr_to_elements[bdr_attr]; + + std::unordered_map dof_to_edge, dof_to_orientation; + std::unordered_map dof_to_boundary_element; + Array ess_edge_list; + + fespace.GetBoundaryEdgeDoFs(boundary_elements, ess_tdof_list, ldof_marker, + boundary_edge_ldofs, &dof_to_edge, &dof_to_orientation, + &dof_to_boundary_element, &ess_edge_list); + + // Collect total boundary edge DoFs + int local_dofs = boundary_edge_ldofs.size(); + int total_dofs; + MPI_Allreduce(&local_dofs, &total_dofs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + + all_results.push_back(total_dofs); + } + + // Verify all results are identical + REQUIRE(!all_results.empty()); + int expected = all_results[0]; + for (int result : all_results) + { + REQUIRE(result == expected); + } +} + +TEST_CASE("BoundaryEdgeDoFsBasicFunctionality", + "[Parallel][ParMesh][BoundaryEdgeDoFs]") +{ + const int orientation = GENERATE(1, 3, 5); + const int order = GENERATE(1, 2); + + CAPTURE(orientation, order); + + // Create test mesh + Mesh mesh = OrientedTriFaceMesh(orientation, true); + mesh.UniformRefinement(); + ParMesh pmesh(MPI_COMM_WORLD, mesh); + + // Create finite element space + ND_FECollection fec(order, 3); + ParFiniteElementSpace fespace(&pmesh, &fec); + + // Test boundary edge DOF extraction + Array ess_tdof_list; + std::unordered_set boundary_edge_ldofs; + Array ldof_marker; + std::unordered_map> attr_to_elements; + + // Get boundary elements for the shared face + int bdr_attr = pmesh.bdr_attributes.Max(); + Array bdr_attrs(1); + bdr_attrs[0] = bdr_attr; + + fespace.GetBoundaryElementsByAttribute(bdr_attrs, attr_to_elements); + Array boundary_elements = attr_to_elements[bdr_attr]; + + std::unordered_map dof_to_edge, dof_to_orientation; + std::unordered_map dof_to_boundary_element; + Array ess_edge_list; + + fespace.GetBoundaryEdgeDoFs(boundary_elements, ess_tdof_list, ldof_marker, + boundary_edge_ldofs, &dof_to_edge, &dof_to_orientation, + &dof_to_boundary_element, &ess_edge_list); + + // Basic validation + REQUIRE(boundary_edge_ldofs.size() >= 0); + REQUIRE(ldof_marker.Size() == fespace.GetVSize()); + REQUIRE(ess_tdof_list.Size() >= 0); + + // Verify consistency between different outputs + REQUIRE(boundary_edge_ldofs.size() == dof_to_edge.size()); + REQUIRE(dof_to_edge.size() == dof_to_orientation.size()); + REQUIRE(dof_to_edge.size() == dof_to_boundary_element.size()); + + // Verify all boundary edge DOFs are marked in ldof_marker + for (int dof : boundary_edge_ldofs) + { + REQUIRE(ldof_marker[dof] == 1); + } +} + +// Helper function to compute boundary loop length +double ComputeBoundaryLoopLength(ParMesh* pmesh, + const std::unordered_map& dof_to_edge) +{ + double local_length = 0.0; + std::unordered_set processed_edges; + + for (const auto& pair : dof_to_edge) + { + int edge_id = pair.second; + if (!processed_edges.insert(edge_id).second) { continue; } + + Array edge_verts; + pmesh->GetEdgeVertices(edge_id, edge_verts); + const double* v0 = pmesh->GetVertex(edge_verts[0]); + const double* v1 = pmesh->GetVertex(edge_verts[1]); + + double edge_length = 0.0; + for (int i = 0; i < pmesh->SpaceDimension(); i++) + { + double diff = v1[i] - v0[i]; + edge_length += diff * diff; + } + local_length += sqrt(edge_length); + } + return local_length; +} + +TEST_CASE("BoundaryEdgeDoFsNestedCubes", + "[Parallel][ParMesh][BoundaryEdgeDoFs]") +{ + const int order = GENERATE(1, 2); + + // Expected processor-invariant results for nested cubes mesh (1 refinement) + // order=1: 24 tdofs, sum=24.0, length=2.0 + // order=2: 48 tdofs, sum=48.0, length=2.0 + int exp_tdofs = (order == 1) ? 24 : 48; + double exp_sum = (order == 1) ? 24.0 : 48.0; + double exp_length = 2.0; + + struct BoundaryTest + { + int attr_value; + Vector normal; + std::string name; + }; + + std::vector boundary_tests = + { + {7, Vector({0, 0, -1}), "-z"}, + {8, Vector({0, 0, 1}), "+z"}, + {9, Vector({0, -1, 0}), "-y"}, + {10, Vector({1, 0, 0}), "+x"}, + {11, Vector({0, 1, 0}), "+y"}, + {12, Vector({-1, 0, 0}), "-x"} + }; + + const char* mesh_file = "../../data/nested_cubes.msh"; + Mesh mesh(mesh_file, 1, 1); + mesh.UniformRefinement(); + ParMesh pmesh(MPI_COMM_WORLD, mesh); + + ND_FECollection fec(order, 3); + ParFiniteElementSpace fespace(&pmesh, &fec); + + int num_procs; + MPI_Comm_size(MPI_COMM_WORLD, &num_procs); + + for (const auto& test : boundary_tests) + { + CAPTURE(test.name, test.attr_value, order, num_procs); + + std::unordered_map> attr_to_elements; + Array bdr_attrs(1); + bdr_attrs[0] = test.attr_value; + + fespace.GetBoundaryElementsByAttribute(bdr_attrs, attr_to_elements); + if (attr_to_elements.find(test.attr_value) == attr_to_elements.end()) + { + continue; + } + + Array boundary_elements = attr_to_elements[test.attr_value]; + + Array ess_tdof_list; + Array ldof_marker; + std::unordered_set boundary_edge_ldofs; + std::unordered_map dof_to_edge, dof_to_orientation; + std::unordered_map dof_to_boundary_element; + Array ess_edge_list; + + fespace.GetBoundaryEdgeDoFs(boundary_elements, ess_tdof_list, ldof_marker, + boundary_edge_ldofs, &dof_to_edge, &dof_to_orientation, + &dof_to_boundary_element, &ess_edge_list); + + std::unordered_map edge_loop_orientation; + fespace.ComputeLoopEdgeOrientations(dof_to_edge, dof_to_boundary_element, + test.normal, edge_loop_orientation); + + ParGridFunction x(&fespace); + x = 0.0; + for (int dof : boundary_edge_ldofs) + { + int edge = dof_to_edge[dof]; + int orientation = edge_loop_orientation[edge]; + x(dof) = 1.0 * orientation; + } + + GroupCommunicator *gc = fespace.ScalarGroupComm(); + Array global_marker(ldof_marker); + gc->Reduce(global_marker.GetData(), GroupCommunicator::BitOR); + gc->Bcast(global_marker); + + Array values(x.GetData(), x.Size()); + gc->ReduceBegin(values.GetData()); + gc->ReduceMarked(values.GetData(), global_marker, 0, + GroupCommunicator::MaxAbs); + gc->Bcast(values.GetData()); + delete gc; + + Vector x_true; + x.GetTrueDofs(x_true); + + int local_nonzero_tdofs = 0; + double local_tdof_sum = 0.0; + for (int tdof = 0; tdof < x_true.Size(); tdof++) + { + double tdof_value = x_true(tdof); + if (abs(tdof_value) > 1e-12) + { + local_nonzero_tdofs++; + local_tdof_sum += abs(tdof_value); + } + } + + double local_length = ComputeBoundaryLoopLength(&pmesh, dof_to_edge); + + int global_nonzero_tdofs; + double global_tdof_sum, total_length; + MPI_Allreduce(&local_nonzero_tdofs, &global_nonzero_tdofs, 1, MPI_INT, MPI_SUM, + MPI_COMM_WORLD); + MPI_Allreduce(&local_tdof_sum, &global_tdof_sum, 1, MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); + MPI_Allreduce(&local_length, &total_length, 1, MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); + + // Verify processor-invariant results match expected values + REQUIRE(global_nonzero_tdofs == exp_tdofs); + REQUIRE(abs(global_tdof_sum - exp_sum) < 1e-12); + REQUIRE(abs(total_length - exp_length) < 1e-12); + } +} + +#endif // MFEM_USE_MPI \ No newline at end of file