diff --git a/FracData_test_with_inter.txt b/FracData_test_with_inter.txt new file mode 100644 index 0000000..a443bf5 --- /dev/null +++ b/FracData_test_with_inter.txt @@ -0,0 +1,2534 @@ + 0.00000 92.34190 5.86904 90.62971 + 4.55505 237.97193 4.73143 238.02816 + 4.55505 237.97193 5.62488 253.76520 + 5.62488 253.76520 9.19098 270.83240 + 5.86904 90.62971 10.63822 90.38555 + 9.19098 270.83240 10.46492 297.06979 + 10.46492 297.06979 12.24797 326.36417 + 10.63822 90.38555 14.55091 88.91829 + 12.24797 326.36417 15.05001 341.39338 + 12.59456 113.49510 18.34114 112.15030 + 12.71010 471.43656 18.85410 469.95312 + 14.55091 88.91829 21.12855 87.82921 + 15.05001 341.39338 15.55912 355.40360 + 15.55912 355.40360 20.67643 377.98786 + 18.23947 860.92065 18.85102 859.82079 + 18.34114 112.15030 21.88721 110.68304 + 18.85102 859.82079 24.72007 857.37535 + 18.85256 440.00484 19.46026 458.85355 + 18.85256 440.00484 20.42858 430.72310 + 18.85410 469.95312 21.23369 469.88883 + 19.46026 458.85355 21.23369 469.88883 + 20.19582 907.99545 23.49696 903.96029 + 20.42842 430.72297 20.42858 430.72310 + 20.42858 430.72310 20.67643 429.26341 + 20.42858 430.72310 27.11698 436.37327 + 20.55243 889.56882 25.87693 887.65175 + 20.67643 377.98786 23.10800 389.94545 + 20.67643 429.26341 23.10800 414.26578 + 20.78657 94.42071 21.27566 85.00560 + 20.78657 94.42071 21.88721 104.44661 + 21.23369 469.88883 21.28413 470.20267 + 21.23369 469.88883 24.90810 469.78955 + 21.27566 85.00560 23.23201 76.93528 + 21.88721 104.44661 26.28899 116.55208 + 21.88721 110.68304 23.86821 109.89588 + 23.10800 389.94545 23.71647 404.94309 + 23.10800 414.26578 23.71647 404.94309 + 23.23201 69.59898 23.23201 76.93528 + 23.49696 903.96029 27.65459 900.90408 + 23.93830 712.44699 30.29488 715.54403 + 24.72007 857.37535 32.54545 854.31837 + 24.90800 469.78984 24.90810 469.78955 + 24.90810 469.78955 26.69336 469.74132 + 24.90810 469.78955 27.85792 460.94931 + 24.94343 68.98820 26.65562 70.33299 + 25.87693 887.65175 27.93571 883.46332 + 26.28899 116.55208 31.30156 127.55615 + 26.65562 70.33299 32.03557 73.02259 + 26.69336 469.74132 33.42126 468.87893 + 27.11698 436.37327 29.44688 440.92833 + 27.65459 900.90408 31.44482 898.33618 + 27.85792 460.94931 29.97679 456.39425 + 27.93571 883.46332 29.28513 880.48105 + 29.28513 880.48105 31.69899 878.20891 + 29.44688 440.92833 30.50669 448.76758 + 29.97679 456.39425 30.08308 456.60606 + 30.08308 456.60606 30.50669 448.76758 + 30.08308 456.60606 31.35393 459.04225 + 30.29488 715.54403 35.18421 716.68472 + 30.50669 448.76758 32.83737 452.26282 + 31.30156 127.55615 33.99192 131.22469 + 31.35393 459.04225 32.01092 469.05967 + 31.44482 898.33618 36.60910 896.63709 + 31.69899 878.20891 34.46791 875.36913 + 32.03557 73.02259 33.86945 76.93528 + 32.23891 128.83394 36.07073 130.36821 + 32.46381 383.68360 33.76779 391.50899 + 32.46381 383.68360 34.09359 373.57529 + 32.54545 854.31837 38.27584 853.17152 + 32.83737 452.26282 33.68460 457.34778 + 33.42119 468.87867 33.42126 468.87893 + 33.42126 468.87893 34.95546 468.68227 + 33.42126 468.87893 35.42144 476.23115 + 33.68460 457.34778 34.21374 460.31388 + 33.76779 391.50899 36.21322 404.55105 + 33.86945 76.93528 37.29306 81.82615 + 33.99192 131.22469 37.90461 137.90015 + 34.09359 373.57529 36.37651 359.16379 + 34.21374 460.31388 38.34518 462.11464 + 34.46791 875.36913 35.95905 873.16785 + 34.95546 468.68227 39.93413 468.15236 + 35.18421 716.68472 41.19035 716.84569 + 35.42144 476.23115 36.07304 485.84960 + 35.79807 481.78749 42.26865 483.73074 + 35.85122 928.11117 35.95213 923.92043 + 35.85122 928.11117 36.86944 927.60206 + 35.95212 923.92043 35.95213 923.92043 + 35.95213 923.92043 36.60910 896.63709 + 35.95213 923.92043 44.05941 925.14430 + 35.95905 873.16785 37.84762 863.81743 + 36.07073 130.36821 37.75875 130.98273 + 36.07304 485.84960 36.48049 492.20773 + 36.21322 404.55105 37.19139 416.61493 + 36.37651 359.16379 36.86559 353.94712 + 36.48049 492.20773 37.05121 501.66367 + 36.60910 896.63709 36.60911 896.63709 + 36.60910 896.63709 36.86944 885.82557 + 36.74159 891.14468 41.63862 893.72182 + 36.80706 504.76147 37.05121 501.66367 + 36.80706 504.76147 37.21450 508.83668 + 36.86559 353.94712 39.14774 341.06758 + 36.86944 885.82557 37.84775 863.81475 + 37.19139 416.61493 38.00628 432.59228 + 37.21450 508.83668 37.29614 512.91266 + 37.29306 81.82615 41.45069 84.14989 + 37.29614 512.91266 37.94775 515.19481 + 37.53799 113.81320 37.65968 126.28453 + 37.53799 113.81320 38.27124 104.15316 + 37.62194 518.53755 37.94775 515.19481 + 37.62194 518.53755 37.94775 520.33061 + 37.65968 126.28453 37.75875 130.98273 + 37.75875 130.98273 37.75904 130.98284 + 37.75875 130.98273 37.90461 137.90015 + 37.84762 863.81743 37.84775 863.81475 + 37.84775 863.81475 37.85224 863.72424 + 37.84775 863.81475 37.88844 862.89934 + 37.88844 862.89934 38.27584 853.17152 + 37.90461 137.90015 40.22758 158.00200 + 37.94775 520.33061 38.84505 531.00887 + 38.00628 432.59228 40.61500 451.34087 + 38.27124 104.15316 39.98342 93.75987 + 38.27584 853.17152 38.27586 853.17152 + 38.27584 853.17152 39.59838 819.96217 + 38.27586 853.17152 45.91408 857.41540 + 38.34518 462.11464 42.45274 465.05532 + 38.49614 199.66835 38.75108 199.92252 + 38.75108 199.92252 42.01659 182.79784 + 38.76340 537.36700 38.84505 531.00887 + 38.76340 537.36700 39.25249 542.17623 + 39.14774 341.06758 40.77829 333.07891 + 39.25249 542.17623 39.65993 548.61600 + 39.58522 543.15363 45.32564 544.30202 + 39.59832 819.96214 39.59838 819.96217 + 39.59838 819.96217 40.63965 793.81563 + 39.59838 819.96217 48.20008 823.69075 + 39.65993 548.61600 40.06738 556.03394 + 39.87097 154.91267 42.83168 154.29495 + 39.93413 468.15236 42.73463 467.15416 + 39.98342 93.75987 41.45069 84.14989 + 40.06738 556.03394 41.20884 557.90865 + 40.22758 158.00200 40.59421 165.82739 + 40.33387 748.88126 40.63965 774.55793 + 40.33387 748.88126 41.19035 716.84569 + 40.59421 165.82739 41.69484 176.09821 + 40.61500 451.34087 42.73463 467.15416 + 40.63965 774.55793 40.63965 793.81563 + 40.77829 333.07891 43.54952 321.50411 + 41.06789 700.09427 41.31205 708.53121 + 41.06789 700.09427 42.67764 690.59829 + 41.19035 716.84569 41.31205 708.53121 + 41.20884 557.90865 41.94208 561.90299 + 41.63862 893.72182 48.67377 898.43323 + 41.69484 176.09821 41.83747 179.06816 + 41.83733 179.06816 41.83747 179.06816 + 41.83747 179.06816 42.01659 182.79784 + 41.83747 179.06816 50.16798 179.23838 + 41.94208 561.90299 42.94105 566.37948 + 42.01659 182.79784 42.01679 182.79678 + 42.01659 182.79784 42.42886 191.38237 + 42.26865 483.73074 46.09971 482.75257 + 42.42886 191.38237 43.65119 207.76639 + 42.67764 690.59829 43.08508 679.59345 + 42.73463 467.15416 51.37491 469.84761 + 42.83168 154.29495 49.02113 154.38351 + 42.94105 566.37948 54.24550 565.23109 + 42.98341 664.41173 43.08508 652.79534 + 42.98341 664.41173 43.08508 679.59345 + 43.03040 671.39143 49.14899 677.19731 + 43.08123 345.37540 45.22166 351.79437 + 43.08123 345.37540 50.41753 325.50615 + 43.08508 652.79534 45.65991 637.23699 + 43.54952 321.50411 44.36441 312.86306 + 43.65119 207.76639 43.89612 241.29387 + 43.89612 241.29387 44.38521 249.73004 + 44.05941 925.14430 46.13822 925.14430 + 44.36441 312.86306 44.44605 299.08776 + 44.38521 249.73004 44.65016 276.26319 + 44.44605 299.08776 45.05760 285.43338 + 44.65016 276.26319 45.05760 285.43338 + 45.22166 351.79437 53.16874 360.04800 + 45.32564 544.30202 52.74358 545.36107 + 45.65991 637.23699 46.71742 634.02827 + 45.91408 857.41540 51.45655 864.26262 + 46.04194 773.71532 46.24913 782.62132 + 46.04194 773.71532 47.49226 763.98057 + 46.09971 482.75257 51.47966 481.04038 + 46.13822 925.14430 50.05091 925.38846 + 46.24913 782.62132 47.95593 788.98253 + 46.71742 634.02827 47.43449 631.67295 + 47.28507 800.01895 47.95593 788.98253 + 47.43449 629.59106 47.43449 631.67295 + 47.43449 629.59106 48.28789 627.50840 + 47.49226 763.98057 50.18493 755.69536 + 47.95593 788.98253 51.54205 792.48701 + 48.20008 823.69075 59.44908 829.55979 + 48.28789 627.50840 49.83063 625.16232 + 48.67377 898.43323 56.48298 904.04810 + 49.02113 154.38353 49.02113 154.38351 + 49.02113 154.38353 50.65707 169.61993 + 49.02113 154.38351 49.67890 142.39358 + 49.02113 154.38351 54.24396 154.45824 + 49.14899 677.19731 49.97774 689.41678 + 49.14899 677.19731 56.08478 670.43328 + 49.14899 783.44930 49.35618 779.09990 + 49.14899 783.44930 51.22010 787.38510 + 49.35618 779.09990 51.01291 768.74435 + 49.56336 722.55607 51.22010 733.74114 + 49.56336 722.55607 52.67041 705.36563 + 49.83063 625.16232 51.13460 621.08634 + 49.97774 689.41678 52.67041 705.36563 + 50.05091 925.38846 61.54407 927.22311 + 50.16798 179.23838 50.33127 178.91258 + 50.18493 755.69536 51.01291 768.74435 + 50.18493 755.69536 51.22010 733.74114 + 50.33127 185.92231 50.65707 169.61993 + 50.33127 185.92231 52.61342 202.71455 + 50.41753 325.50615 53.16874 305.63690 + 50.48993 177.98370 53.62394 174.86510 + 51.13460 621.08634 53.58004 612.12026 + 51.13460 621.08634 58.67501 628.85088 + 51.22010 787.38510 51.54205 792.48701 + 51.37491 469.84761 58.12200 472.52564 + 51.45655 864.26262 54.22856 873.55527 + 51.47966 481.04038 54.18774 482.11637 + 51.54205 792.48701 58.30839 797.86697 + 52.61342 202.71455 54.18485 212.06299 + 52.74358 545.36107 57.94868 545.94801 + 53.16874 305.63690 57.44883 286.37920 + 53.16874 360.04800 57.14306 371.96939 + 53.58004 612.12026 55.37387 599.24072 + 53.62394 174.86510 55.51944 171.93058 + 53.78029 500.45674 54.18774 482.11637 + 53.78029 500.45674 55.81828 524.50363 + 53.91739 454.91082 54.76463 449.40301 + 53.91739 454.91082 55.82368 460.41940 + 54.18466 212.06265 54.18485 212.06299 + 54.18485 212.06299 55.87451 222.11473 + 54.18485 212.06299 58.95152 220.35248 + 54.18774 482.11637 60.70915 466.22066 + 54.22856 873.55527 56.02162 882.03303 + 54.24396 154.45824 64.67807 153.48006 + 54.24550 565.23109 55.12817 560.90402 + 54.24550 565.23109 58.92533 565.93815 + 54.76463 449.40301 56.24729 444.63614 + 55.12817 560.90402 55.92303 558.69658 + 55.37387 599.24072 56.02547 586.68698 + 55.51944 171.93058 58.57643 165.44998 + 55.56951 556.57695 55.92303 558.69658 + 55.56951 556.57695 56.27656 553.22112 + 55.81828 524.50363 57.68013 536.04628 + 55.82368 460.41940 56.35358 465.82169 + 55.87451 222.11473 57.67758 245.57088 + 56.02162 882.03303 56.50326 885.70637 + 56.02547 586.68698 56.35204 573.48164 + 56.08478 670.43328 62.76948 670.43328 + 56.24729 444.63614 59.42520 441.88185 + 56.27656 553.22112 56.89428 548.80547 + 56.35204 573.48164 56.59928 565.58693 + 56.35358 465.82169 58.12200 472.52564 + 56.48298 904.04810 59.71018 907.21060 + 56.50301 885.70619 56.50326 885.70637 + 56.50326 885.70637 57.32560 891.97805 + 56.50326 885.70637 61.23829 889.04353 + 56.89428 548.80547 57.94868 545.94801 + 57.03368 532.03788 57.83779 529.94906 + 57.14306 371.96939 59.28271 392.75597 + 57.32560 891.97805 59.60851 897.68381 + 57.44883 286.37920 57.98223 279.23024 + 57.67758 245.57088 58.97694 265.89840 + 57.67990 536.04608 57.68013 536.04628 + 57.68013 536.04628 57.85627 537.13825 + 57.68013 536.04628 60.09760 538.15724 + 57.83779 529.94906 59.22341 525.30312 + 57.85627 537.13825 60.22700 545.89945 + 57.94868 545.94801 57.94870 545.94797 + 57.94868 545.94801 59.01391 546.06813 + 57.94870 545.94797 60.22697 545.89945 + 57.98182 279.23006 57.98223 279.23024 + 57.98223 279.23024 58.54726 271.65728 + 57.98223 279.23024 84.85772 290.86263 + 58.30839 797.86697 62.54689 801.94295 + 58.54716 271.65730 58.54726 271.65728 + 58.54726 271.65728 58.97694 265.89840 + 58.54726 271.65728 67.28140 269.71944 + 58.57643 165.44998 62.30581 158.96939 + 58.67501 628.85088 62.13944 633.33431 + 58.92533 565.93815 65.10708 566.55586 + 58.95152 220.35248 63.53661 229.77761 + 59.01391 546.06813 60.22697 545.89945 + 59.22341 525.30312 59.71249 520.00481 + 59.28271 392.75597 60.19927 408.65091 + 59.42520 441.88185 61.05481 436.17438 + 59.44908 829.55979 64.50323 831.67942 + 59.60851 897.68381 63.98950 907.53717 + 59.71018 907.21060 62.67859 909.21162 + 59.71249 520.00481 63.70683 506.79946 + 60.09760 538.15724 61.32070 541.52000 + 60.19927 408.65091 61.11660 433.20769 + 60.22697 545.89945 60.22700 545.89945 + 60.22697 545.89945 60.22700 545.89945 + 60.22700 545.89945 60.22700 545.89945 + 60.22700 545.89945 62.19336 545.62602 + 60.70915 452.77116 60.70915 466.22066 + 60.70915 452.77116 61.05481 436.17438 + 61.05481 436.17438 61.05498 436.17379 + 61.05481 436.17438 61.11660 433.20769 + 61.23829 889.04353 67.27062 889.69590 + 61.32070 541.52000 62.19336 545.62602 + 61.32378 574.43978 61.93534 587.38017 + 61.32378 574.43978 61.96075 566.24161 + 61.54407 927.22311 65.33507 927.34481 + 61.93534 587.38017 62.85266 597.56935 + 62.13944 633.33431 69.88319 640.26317 + 62.19336 545.62602 67.84520 546.15593 + 62.30581 158.96939 64.67807 153.48006 + 62.54689 606.84198 62.85266 597.56935 + 62.54689 606.84198 63.87166 615.29894 + 62.54689 801.94295 67.43776 805.20327 + 62.67859 909.21162 64.85753 910.59801 + 62.76948 670.43328 68.47524 668.80273 + 63.29323 933.30396 63.64984 927.29089 + 63.52506 868.60586 65.23725 862.98098 + 63.53661 229.77761 71.68780 233.34371 + 63.70683 506.79946 65.25573 500.03312 + 63.98950 907.53717 65.19181 904.38468 + 63.98950 907.53717 66.31324 915.72919 + 64.50323 831.67942 71.18716 831.02705 + 64.67807 153.48006 74.94890 150.70806 + 65.10708 566.55586 72.17227 566.20310 + 65.19181 904.38468 71.81489 890.62863 + 65.23725 862.98098 66.45958 858.66084 + 65.25573 500.03312 67.45624 493.34919 + 65.33507 927.34481 72.91553 926.85572 + 66.31324 915.72919 68.75867 922.20978 + 66.45958 858.66084 66.94867 854.66650 + 66.94867 854.66650 67.43776 848.06422 + 67.09039 434.94375 67.86908 442.40560 + 67.09039 434.94375 71.01849 415.73843 + 67.27062 889.69590 71.81489 890.62863 + 67.28140 269.71944 79.76274 271.75743 + 67.43776 805.20327 74.36661 810.33906 + 67.43776 848.06422 68.66086 841.37952 + 67.45624 493.34919 69.33094 484.13818 + 67.47935 899.63476 78.23464 905.15259 + 67.84520 546.15593 72.43722 547.12794 + 67.86908 442.40560 70.17048 448.87310 + 68.47524 668.80273 74.67008 665.70492 + 68.66086 841.37952 71.18716 831.02705 + 68.75867 922.20978 70.47009 926.61156 + 69.33094 484.13818 69.90167 474.68225 + 69.88319 640.26317 79.46082 649.22925 + 69.90167 474.68225 71.20401 468.74743 + 70.17048 448.87310 71.48601 459.72466 + 70.19667 546.43860 71.72554 505.88522 + 71.01849 415.73843 75.82001 392.16830 + 71.15713 470.24735 71.20401 468.74743 + 71.15713 470.24735 72.54043 489.17462 + 71.18716 831.02705 75.09986 817.82171 + 71.18716 831.02705 76.24132 835.42960 + 71.20401 468.74743 71.20411 468.74697 + 71.20401 468.74743 71.48601 459.72466 + 71.48601 459.72466 75.39331 435.47674 + 71.68780 233.34371 81.36787 239.96679 + 71.72554 505.88522 72.54043 489.17462 + 71.81489 890.62863 76.65492 878.40146 + 72.17227 566.20310 78.79535 563.64213 + 72.43722 547.12794 82.50471 551.63139 + 72.91553 926.85572 85.75425 926.24494 + 74.36661 810.33906 77.54529 812.60504 + 74.67008 665.70492 81.07747 663.74936 + 74.94890 150.70806 81.46954 150.54554 + 75.09986 817.82171 77.54529 812.60504 + 75.39331 435.47674 85.17505 423.24957 + 75.82001 392.16830 78.87545 354.63030 + 76.24132 835.42960 83.90342 841.46116 + 76.65492 878.40146 78.69291 865.15530 + 77.54529 812.60504 79.17584 807.22508 + 77.54529 812.60504 79.66493 814.25176 + 78.23464 905.15259 84.34784 910.65501 + 78.69291 865.15530 81.24002 851.14508 + 78.79535 563.64213 82.06338 563.72994 + 78.87545 354.63030 95.46204 325.38599 + 79.15042 837.71945 82.33064 833.90458 + 79.17584 807.22508 81.80458 793.10241 + 79.46082 649.22925 81.09136 652.89778 + 79.66493 814.25176 86.91958 818.32774 + 79.76274 271.75743 84.60278 273.54048 + 81.05054 680.04171 81.07747 663.74936 + 81.05054 680.04171 81.90625 749.28871 + 81.07747 663.74936 81.07750 663.74935 + 81.07747 663.74936 81.09136 655.34322 + 81.09136 652.89778 81.09136 655.34322 + 81.09136 655.34322 90.97169 652.83848 + 81.24002 851.14508 83.90342 841.46116 + 81.36787 239.96679 93.34010 243.53289 + 81.46954 150.54554 86.84950 153.15349 + 81.80458 793.10241 83.23102 783.42311 + 81.90625 749.28871 83.43513 759.37622 + 82.06338 563.72994 83.82948 562.22879 + 82.21203 582.79508 89.14089 579.94220 + 82.33064 833.90458 84.89854 828.52462 + 82.50471 551.63139 86.82849 553.74451 + 83.23102 783.42311 83.53680 769.87117 + 83.43513 759.37622 83.53680 769.87117 + 83.53064 55.92380 84.54963 64.27910 + 83.82948 562.22879 84.44796 559.31429 + 83.90342 841.46116 92.38118 845.53714 + 84.34784 910.65501 92.29569 918.60286 + 84.44796 559.31429 85.59558 555.34075 + 84.54963 64.27910 86.03937 66.35974 + 84.60278 273.54048 91.99068 270.73844 + 84.85772 290.86263 91.99068 295.44772 + 84.89854 828.52462 86.48749 823.63375 + 85.17505 423.24957 99.84765 415.30249 + 85.59558 555.34075 86.76246 553.71252 + 85.75425 926.24494 91.25667 925.87754 + 86.03923 66.36022 86.03937 66.35974 + 86.03937 66.35974 87.30700 68.13018 + 86.03937 66.35974 88.93139 56.12791 + 86.48749 823.63375 86.91958 818.32774 + 86.76246 553.71252 86.82849 553.74451 + 86.82849 553.74451 86.83717 553.74872 + 86.82849 553.74451 94.25050 557.37181 + 86.84950 153.15349 89.78402 153.48006 + 86.91958 818.32774 94.33753 822.15879 + 87.30700 68.13018 87.94705 80.92885 + 87.94705 80.92885 88.25628 84.94988 + 88.25591 84.95091 88.25628 84.94988 + 88.25591 84.95091 88.47276 87.76475 + 88.25628 84.94988 88.47276 87.76475 + 88.25628 84.94988 90.60353 78.52501 + 88.47276 87.76475 88.47927 87.84923 + 88.47276 87.76475 88.59488 89.35272 + 88.59480 89.35270 88.59488 89.35272 + 88.59488 89.35272 88.90674 93.40788 + 88.59488 89.35272 97.80673 91.45560 + 88.90674 93.40788 90.18684 125.72612 + 89.14089 579.94220 99.83995 580.85876 + 89.78402 153.48006 92.04152 151.86184 + 90.18684 125.72612 91.46617 143.00436 + 90.60353 78.52501 93.04896 84.39405 + 90.60353 78.52501 93.90544 72.04441 + 90.97169 652.83848 104.47203 645.96045 + 91.25667 925.87754 95.53599 926.36663 + 91.46617 143.00436 93.06667 167.64279 + 91.88824 600.92364 100.85509 603.77652 + 91.99068 270.73844 93.26385 266.91740 + 91.99068 295.44772 105.64891 302.81329 + 92.29569 918.60286 97.49233 923.18795 + 92.38118 845.53714 97.92442 846.35203 + 92.53831 159.50700 96.75370 158.86772 + 93.04896 84.39405 94.63868 88.67337 + 93.06667 167.64279 96.50267 193.16757 + 93.26385 266.91740 102.33083 264.28095 + 93.34010 243.53289 100.24737 242.03637 + 93.90544 72.04441 99.89617 63.97487 + 94.25050 557.37181 106.34904 562.58232 + 94.33753 822.15879 99.06511 825.50076 + 94.63868 88.67337 97.80673 91.45560 + 95.46204 325.38599 105.86534 314.51132 + 95.53599 926.36663 100.79348 926.61156 + 96.50261 193.16773 96.50267 193.16757 + 96.50267 193.16757 97.54625 200.91995 + 96.50267 193.16757 100.98757 181.11231 + 96.75370 158.86772 99.32390 154.90111 + 97.49233 923.18795 100.79348 926.61156 + 97.54625 200.91995 99.79855 235.20453 + 97.80673 91.45560 97.80735 91.45615 + 97.80673 91.45560 102.31003 92.48362 + 97.92442 846.35203 102.16292 846.51531 + 99.06511 825.50076 103.14109 828.43528 + 99.32390 154.90111 104.35957 149.60434 + 99.42865 637.60515 104.93107 631.69529 + 99.79836 235.20455 99.79855 235.20453 + 99.79855 235.20453 100.24737 242.03637 + 99.79855 235.20453 111.68124 234.10776 + 99.83995 580.85876 107.88947 584.01741 + 99.84765 415.30249 112.58470 410.12048 + 99.89617 63.97487 102.09745 55.90455 +100.24737 242.03637 100.24739 242.03636 +100.24737 242.03637 100.42608 244.75676 +100.42608 244.75676 105.54571 297.23308 +100.79348 926.61156 103.22099 926.95967 +100.85509 603.77652 111.85916 606.83351 +100.98757 181.11231 102.48333 173.83609 +102.16292 846.51531 105.58653 847.33020 +102.31003 92.48362 110.65997 97.17333 +102.43172 938.26877 103.22099 926.95967 +102.48333 173.83609 105.49681 167.36785 +103.14109 828.43528 111.88970 833.44230 +103.22099 926.95967 103.22120 926.95970 +103.22099 926.95967 103.65483 920.74329 +103.65483 920.74329 108.23992 868.12602 +104.35957 149.60434 112.00088 144.48164 +104.47203 645.96045 114.15209 639.33737 +104.93107 631.69529 105.33852 625.58209 +105.33852 625.58209 109.61783 620.89456 +105.49641 167.36782 105.49681 167.36785 +105.49681 167.36785 106.57009 165.06411 +105.49681 167.36785 118.73102 168.35370 +105.54571 297.23308 105.86534 314.51132 +105.58653 847.33020 108.84685 848.63495 +105.86534 314.51132 107.14544 336.84603 +106.34904 562.58232 114.38547 567.17434 +106.57009 165.06411 110.55673 160.77786 +107.14544 336.84603 107.46508 352.52454 +107.46508 352.52454 111.62502 381.00248 +107.71155 680.17650 115.69715 689.46684 +107.88947 584.01741 115.53155 586.56529 +108.23992 868.12602 111.29690 843.46757 +108.23992 868.12602 122.23550 875.73190 +108.84685 848.63495 110.56135 849.39977 +108.87458 346.68476 118.84656 334.03551 +109.61783 620.89456 112.67482 618.04168 +110.55673 160.77786 114.74362 157.28955 +110.65994 97.17346 110.65997 97.17333 +110.65997 97.17333 112.24581 91.11880 +110.65997 97.17333 124.62471 105.01657 +111.29690 843.46757 111.88970 833.44230 +111.62502 381.00248 112.58470 397.96109 +111.68124 234.10776 120.34231 233.85359 +111.85916 606.83351 117.76902 612.13182 +111.88970 833.44230 111.88997 833.44245 +111.88970 833.44230 113.53823 805.56296 +112.00088 144.48164 117.38392 137.62210 +112.00165 66.90939 112.85736 74.73478 +112.00165 66.90939 113.71307 61.52943 +112.24581 91.11880 113.46891 82.68263 +112.30281 392.97086 117.19367 376.41662 +112.48920 396.27200 121.12716 395.22220 +112.58470 397.96109 112.58470 410.12048 +112.58470 410.12048 122.18390 436.99869 +112.67482 618.04168 117.76902 612.33592 +112.85736 74.73478 113.46891 82.68263 +112.88201 585.64796 114.51255 579.33065 +113.20627 566.50040 120.74360 567.88063 +113.53823 805.56296 116.18777 774.18053 +114.15209 639.33737 126.57764 634.55138 +114.38547 567.17434 114.92000 572.60590 +114.38547 567.17434 121.18493 573.26752 +114.51255 579.33065 114.92000 572.60590 +114.74362 157.28955 117.13591 152.90317 +114.80986 938.39740 121.65322 901.50254 +115.53155 586.56529 117.77288 588.39917 +115.53463 700.87527 117.16441 705.76460 +115.69715 689.46684 119.77236 692.40059 +116.18777 774.18053 116.79932 756.04350 +116.55902 361.39357 117.19367 376.41662 +116.55902 361.39357 119.94488 352.92967 +116.79932 756.04350 119.09148 740.86101 +117.00112 735.10211 117.75131 749.73620 +117.00112 735.10211 118.30509 726.62666 +117.13591 152.90317 120.52486 147.22206 +117.16441 705.76460 119.28327 709.83981 +117.38392 137.62210 121.37825 125.98722 +117.76902 612.13182 117.76902 612.33592 +117.76902 612.33592 121.33897 607.14775 +117.77288 588.39917 119.50509 594.00326 +117.77288 588.39917 119.70920 584.83307 +117.90766 425.02415 131.99721 432.46366 +118.30509 726.62666 119.28327 717.82540 +118.73102 168.35370 124.21265 168.45305 +118.84656 334.03551 127.24884 328.86429 +119.09148 740.86101 121.63936 718.95377 +119.28327 709.83981 119.28327 717.82540 +119.50509 594.00326 120.42242 595.12392 +119.70920 584.83307 121.84886 582.48931 +119.77236 692.40059 123.77439 695.15642 +119.94488 352.92967 123.19520 349.46285 +120.34231 233.85359 127.51687 235.10981 +120.42242 595.12392 121.54308 598.79246 +120.52486 147.22206 121.62164 141.44006 +120.74360 567.88063 125.24782 568.32273 +121.12716 395.22220 129.17129 393.35751 +121.18493 573.26752 125.68915 578.56660 +121.33897 607.14775 121.54308 604.39654 +121.33897 607.14775 127.69787 601.53288 +121.37825 125.98722 123.98312 117.56492 +121.54308 598.79246 121.54308 604.39654 +121.62164 141.44006 122.59442 138.33609 +121.63936 718.95377 123.77491 695.15644 +121.63936 718.95377 136.15869 704.50838 +121.65322 901.50254 125.72997 886.65201 +121.84886 582.48931 124.29429 582.08186 +122.06375 131.96795 122.79776 140.77151 +122.06375 131.96795 122.92023 126.09890 +122.18390 436.99869 122.82395 464.83658 +122.23550 875.73190 125.72997 886.65201 +122.75617 121.53307 122.92023 126.09890 +122.79776 140.77151 124.02009 147.12964 +122.82395 464.83658 126.98388 483.07452 +122.88480 877.76064 134.46576 876.80943 +123.04192 178.74929 125.85475 171.21736 +123.19519 349.46293 123.19520 349.46285 +123.19520 349.46285 124.38672 339.57490 +123.19520 349.46285 126.29300 346.15870 +123.77439 695.15642 123.77491 695.15644 +123.77491 695.15644 125.20545 679.21527 +123.77491 695.15644 133.30581 695.54153 +123.98312 117.56492 126.91456 106.56470 +124.02009 147.12964 124.50918 153.48777 +124.21265 168.45305 126.22676 169.72930 +124.38672 339.57490 124.94050 333.75824 +124.50918 153.48777 126.83292 158.50110 +124.62471 105.01657 141.14818 116.18741 +124.66399 331.17262 124.94050 333.75824 +124.73023 174.22967 127.70172 174.03557 +125.20545 679.21527 126.22445 647.62874 +125.24782 568.32273 128.83293 566.99882 +125.68915 578.56660 126.66039 581.12756 +125.85475 171.21736 127.32201 165.34831 +126.22445 647.62874 126.57764 634.55138 +126.29300 346.15870 136.44906 340.44525 +126.57764 634.55138 126.57798 634.55125 +126.57764 634.55138 126.73356 628.77848 +126.66039 581.12756 127.27887 586.16092 +126.73356 628.77848 127.81231 598.30567 +126.83292 158.50110 127.32201 165.34831 +126.98388 483.07452 127.62393 502.91373 +127.10173 592.87258 127.27887 586.16092 +127.10173 592.87258 127.81397 598.25873 +127.24267 491.09169 148.35967 488.59388 +127.24884 328.86429 133.89734 323.04762 +127.51687 235.10981 132.29529 253.42938 +127.51687 235.10981 138.77665 225.70394 +127.62393 502.91373 129.54331 515.71240 +127.70172 174.03557 131.68913 175.73005 +127.81032 598.35420 127.81231 598.30567 +127.81231 598.30567 127.81397 598.25873 +127.81231 598.30567 127.81417 598.26024 +127.81397 598.25873 127.81417 598.26024 +127.81397 598.25873 128.77155 571.20873 +128.77155 571.20873 128.83293 566.99882 +128.80544 568.89654 139.20104 568.74712 +128.83163 567.08808 128.83317 566.99873 +128.83293 566.99882 128.83317 566.99873 +128.83293 566.99882 128.85580 565.42968 +128.85551 565.42980 128.85580 565.42968 +128.85580 565.42968 129.54331 518.27259 +128.85580 565.42968 150.58868 556.88503 +128.97720 107.95879 130.34202 101.94033 +129.17129 393.35751 138.73121 393.59011 +129.54331 515.71240 129.54331 518.27259 +129.73047 51.19776 130.64780 69.53813 +129.73047 51.19776 131.25935 38.05327 +129.84985 314.87101 131.07296 304.17195 +129.84985 314.87101 134.54355 321.47792 +130.22572 597.42532 144.89832 622.08377 +130.34202 101.94033 132.17590 93.07515 +130.64780 69.53813 132.17590 81.76530 +131.07296 304.17195 133.51839 281.55226 +131.68913 175.73005 133.98129 177.52388 +131.99721 432.46366 144.01027 440.74887 +132.17590 81.76530 132.17590 93.07515 +132.29529 253.42938 133.51839 281.55226 +133.30581 695.54153 134.04603 689.62085 +133.30581 695.54153 136.15869 704.50838 +133.89734 323.04762 134.54355 321.47792 +133.98129 177.52388 136.41055 178.42349 +134.04599 689.62088 134.04603 689.62085 +134.04603 689.62085 134.93636 682.49947 +134.04603 689.62085 144.71809 680.86893 +134.46576 876.80943 149.89933 877.77066 +134.54355 321.47792 139.52915 320.46201 +134.93636 682.49947 135.75125 667.41942 +135.75125 667.41942 141.04956 647.04106 +136.41055 178.42349 138.04110 174.67331 +136.41055 178.42349 139.50836 182.17290 +136.44906 340.44525 146.81770 330.50022 +138.04110 148.42591 139.01927 155.43641 +138.04110 148.42591 141.79050 142.88267 +138.04110 174.67331 139.01927 161.95706 +138.33840 611.05891 152.43873 608.22606 +138.73121 393.59011 149.92321 393.93979 +138.77665 225.70394 141.80188 222.53428 +139.01927 155.43641 139.01927 161.95706 +139.20104 568.74712 156.44077 564.00259 +139.50836 182.17290 140.48653 190.16158 +139.52915 320.46201 148.76249 320.92414 +140.45033 36.95263 140.93942 47.06016 +140.48653 190.16158 141.13890 200.92149 +140.93942 47.06016 141.91759 60.75460 +141.04956 647.04106 147.67264 638.17588 +141.14814 116.18777 141.14818 116.18741 +141.14818 116.18741 142.40668 103.63172 +141.14818 116.18741 146.32784 119.68917 +141.52170 222.21409 141.80188 222.53428 +141.79050 142.88267 150.43155 131.14459 +141.80188 222.53428 144.76200 219.43284 +141.80188 222.53428 152.22076 234.44126 +141.91759 60.75460 143.05828 69.55893 +142.40668 103.63172 143.22156 94.99144 +142.41977 64.62955 146.31937 60.42879 +143.05828 69.55893 145.34120 77.05775 +143.22156 94.99144 144.36302 89.61149 +143.52580 681.84710 148.78329 690.28173 +144.01027 440.74887 154.98738 448.82611 +144.36302 89.61149 144.65848 87.83872 +144.36302 89.61149 147.46006 98.57757 +144.65802 87.83999 144.65848 87.83872 +144.65848 87.83872 145.83028 80.80793 +144.65848 87.83872 157.91265 51.33871 +144.71809 680.86893 150.83129 671.90285 +144.76200 219.43284 146.05134 211.85700 +144.76200 219.43284 153.74117 207.60310 +144.89832 622.08377 150.78967 626.70594 +145.34120 77.05775 145.83028 80.80793 +146.05134 211.85700 149.71910 195.65629 +146.31937 60.42879 147.94915 53.58158 +146.32784 119.68917 174.14495 143.53196 +146.81770 330.50022 154.96304 324.10644 +147.46006 98.57757 151.53604 109.66405 +147.65261 120.82447 151.53604 109.66405 +147.67264 638.17588 150.78967 626.70594 +147.94915 53.58158 149.09061 44.94130 +148.35967 488.59388 159.54397 488.80030 +148.76249 320.92414 154.96304 324.10644 +148.78329 690.28173 152.53193 700.54947 +149.09061 44.94130 150.88367 38.58317 +149.71910 195.65629 153.38764 170.59040 +149.89933 877.77066 151.72551 874.53113 +149.89933 877.77066 168.68104 878.70185 +149.92321 393.93979 167.52725 389.62658 +150.43155 131.14459 153.41383 125.76309 +150.58868 556.88503 167.51262 548.66067 +150.78967 626.70594 150.78970 626.70583 +150.78967 626.70594 158.14449 632.47629 +150.83129 671.90285 168.35755 653.56171 +150.88367 38.58317 150.88367 33.69231 +151.72551 874.53113 172.81709 842.74049 +151.99432 180.11103 158.90854 182.17290 +152.22076 234.44126 158.02896 250.03119 +152.43873 608.22606 174.04020 605.37318 +152.53193 700.54947 154.48751 705.60209 +152.69444 711.63210 154.48751 705.60209 +152.69444 711.63210 154.97659 718.15198 +153.16659 32.55085 157.91265 51.33871 +153.38764 170.59040 157.97273 150.41538 +153.74117 207.60310 163.00532 193.06606 +154.96304 324.10644 154.96350 324.10667 +154.96304 324.10644 166.49594 315.05355 +154.97659 718.15198 158.56195 721.73733 +154.98738 448.82611 163.06540 464.15340 +155.77454 72.00436 155.77454 75.75377 +155.77454 72.00436 158.54654 67.60258 +155.77454 75.75377 159.36143 82.76427 +156.44077 564.00259 161.47644 580.54220 +156.44077 564.00259 170.67589 557.83394 +156.54013 55.11970 158.54654 67.60258 +157.87183 79.85209 159.85052 79.17738 +157.91265 51.33871 167.69439 54.02907 +158.02896 250.03119 164.14216 263.48147 +158.14449 632.47629 163.61610 622.72613 +158.14449 632.47629 174.85508 640.22081 +158.54654 67.60258 163.11084 74.28651 +158.56195 721.73733 162.96219 730.21201 +158.90854 182.17290 167.34509 185.83279 +159.36143 82.76427 160.50289 85.86131 +159.54397 488.80030 171.51620 484.96925 +159.85052 79.17738 163.27412 85.04642 +161.31855 725.40124 168.95292 717.31013 +161.47644 580.54220 164.22765 593.99247 +161.73446 428.72426 162.34524 413.13433 +161.73446 428.72426 167.54189 447.67618 +162.34524 413.13433 163.87412 401.51871 +162.69954 612.94440 162.92522 606.84121 +162.69954 612.94440 163.61610 622.72613 +162.96219 730.21201 163.28876 737.54677 +163.00532 193.06606 167.34509 185.83279 +163.01610 357.05494 165.76731 376.31264 +163.06540 464.15340 167.84766 475.18751 +163.11084 74.28651 170.93623 87.00277 +163.27412 85.04642 164.90467 89.93729 +163.53138 282.43339 164.14216 263.48147 +163.53138 282.43339 166.89337 299.85720 +163.87412 401.51871 167.52725 389.62658 +164.14216 263.48147 169.64458 270.20622 +164.14216 263.48147 176.98088 258.28482 +164.22765 593.99247 166.88798 606.31746 +164.90467 89.93729 167.51262 95.31724 +165.76731 376.31264 168.19419 389.45690 +166.49594 315.05355 166.89337 299.85720 +166.49594 315.05355 172.41965 309.73424 +167.34509 185.83279 167.34548 185.83296 +167.34509 185.83279 170.27384 180.95134 +167.34548 185.83296 167.43175 185.68893 +167.51262 95.31724 170.93623 104.60989 +167.51262 548.66067 175.44504 545.54775 +167.52725 389.62658 168.19419 389.45690 +167.54189 447.67618 170.90465 459.59758 +167.69439 54.02907 179.31078 57.81930 +167.84766 475.18751 171.51620 484.96925 +167.84766 475.18751 172.73853 463.26611 +168.04176 705.23161 168.58013 712.36841 +168.19419 389.45690 169.43585 396.18189 +168.19419 389.45690 180.81732 386.24534 +168.35755 653.56171 174.85508 640.22081 +168.49696 712.52401 168.58013 712.36841 +168.58013 712.36841 168.95292 717.31013 +168.58013 712.36841 172.02993 705.91479 +168.68104 878.70185 205.08065 888.31183 +169.43585 396.18189 179.82914 426.75020 +169.64458 270.20622 170.86768 276.93097 +170.27384 180.95134 174.40682 172.25792 +170.45638 708.85856 176.13210 711.27087 +170.67589 557.83394 174.65666 555.11691 +170.86768 276.93097 171.47846 285.79615 +170.90465 459.59758 172.73853 463.26611 +170.93623 104.60989 172.40349 114.88072 +171.08180 280.03648 186.45684 283.65572 +171.47846 285.79615 172.41965 309.73424 +171.51620 484.96925 173.65586 501.16996 +172.02993 705.91479 172.82711 697.93844 +172.40349 114.88072 172.40349 114.71743 +172.41965 309.73424 172.41966 309.73445 +172.41965 309.73424 187.23245 296.43282 +172.68924 947.94807 175.44045 938.47211 +172.81709 842.74049 187.18469 822.87124 +172.82711 697.93844 174.87896 683.58008 +173.54495 83.74245 173.87075 81.62281 +173.54495 83.74245 178.43582 95.31724 +173.65586 501.16996 175.18397 509.42359 +173.87075 81.62281 175.17549 71.02619 +174.04020 605.37318 196.25321 607.20706 +174.14495 143.53196 185.93540 133.30273 +174.14495 143.53196 190.34566 158.20457 +174.40682 172.25792 174.60168 171.83353 +174.60168 555.15436 174.65666 555.11691 +174.60168 555.15436 175.44504 545.54775 +174.65666 555.11691 174.74417 555.05731 +174.65666 555.11691 180.64017 551.03294 +174.85508 640.22081 176.36008 649.73605 +174.85508 640.22081 179.46328 634.50812 +174.85508 640.22081 186.47147 647.35300 +174.87896 683.58008 178.06919 665.46154 +175.17549 71.02619 179.31078 57.81930 +175.18397 509.42359 176.71284 531.12672 +175.44045 938.47211 179.10898 925.02184 +175.44504 545.54775 175.44507 545.54746 +175.44504 545.54775 175.81275 545.40345 +175.44507 545.54746 175.81275 545.40345 +175.81275 545.40345 176.27690 545.22166 +175.81275 545.40345 176.27691 545.22130 +176.13210 711.27087 183.08330 711.84083 +176.27690 545.22166 176.27691 545.22130 +176.27691 545.22130 176.71284 531.12672 +176.27691 545.22130 180.00706 543.75748 +176.36008 649.73605 178.18318 659.30828 +176.98088 258.28482 184.92873 256.45094 +178.06919 665.46154 178.18318 659.30828 +178.43582 95.31724 179.33034 100.38618 +179.10898 925.02184 184.91641 914.01777 +179.10898 925.02184 186.36364 927.00899 +179.31078 57.81930 190.19315 58.79748 +179.33004 100.38603 179.33034 100.38618 +179.33034 100.38618 179.90308 103.63172 +179.33034 100.38618 190.33718 105.91387 +179.46328 634.50812 191.07967 632.67346 +179.82914 426.75020 186.45530 414.03779 +179.82914 426.75020 188.38777 448.45333 +179.90308 103.63172 183.48997 118.30432 +180.00706 543.75748 191.07890 537.27304 +180.64017 551.03294 186.26358 547.26409 +180.81732 386.24534 196.90558 382.74856 +182.27457 496.13891 187.16544 477.79854 +182.27457 496.13891 188.99932 523.65024 +183.08330 711.84083 189.46453 713.89191 +183.48997 118.30432 184.95723 127.27117 +184.91641 914.01777 191.33615 903.62448 +184.92873 256.45094 197.15590 257.97905 +184.95723 127.27117 185.93540 133.30273 +185.93540 133.30273 187.62697 134.89771 +186.26352 547.26350 186.26358 547.26409 +186.26358 547.26409 188.37622 567.09270 +186.26358 547.26409 195.50764 541.06866 +186.36364 927.00899 194.00572 930.06598 +186.45530 414.03779 193.90867 401.95080 +186.45684 283.65572 196.33177 284.28730 +186.47147 647.35300 195.43755 647.96455 +187.16544 477.79854 193.89019 460.68050 +187.18469 822.87124 199.35050 803.38105 +187.23245 296.43282 192.52306 294.31704 +187.62680 134.89785 187.62697 134.89771 +187.62697 134.89771 191.64116 138.68269 +187.62697 134.89771 193.27171 130.20569 +188.37622 567.09270 193.26708 590.62971 +188.38777 448.45333 193.89019 460.68050 +188.99932 523.65024 195.50764 541.06866 +189.46453 713.89191 192.76953 715.25905 +190.13924 782.54507 191.76979 770.11379 +190.13924 782.54507 193.80778 792.12270 +190.19315 58.79748 199.48580 59.28656 +190.33718 105.91387 202.72687 112.76108 +190.34566 158.20457 200.12739 164.92932 +190.34566 158.20457 213.86496 143.07907 +190.34874 606.71951 193.26708 590.62971 +191.07967 632.67346 200.24986 618.30664 +191.33615 903.62448 198.67246 893.84274 +191.64116 138.68269 199.46655 147.64953 +191.76979 770.11379 192.22061 760.98188 +192.22036 760.98212 192.22061 760.98188 +192.22061 760.98188 192.58467 753.60730 +192.22061 760.98188 199.67220 753.80602 +192.52306 294.31704 196.33177 284.28730 +192.52306 294.31704 196.94717 325.26430 +192.58467 753.60730 195.64166 726.70753 +192.76876 751.98831 201.30197 748.42606 +192.76953 715.25905 196.73381 721.82588 +192.76953 715.25905 199.37566 710.01696 +193.27171 130.20569 200.28144 127.59697 +193.48737 191.03500 194.40469 225.88263 +193.48737 191.03500 194.85835 161.30699 +193.80778 792.12270 199.35025 803.38094 +193.90867 401.95080 198.13947 392.68357 +194.00572 930.06598 202.25858 930.37098 +194.13435 20.54165 232.34397 36.84403 +194.40469 225.88263 197.15590 248.50309 +195.43755 647.96455 201.55152 645.31501 +195.50764 541.06866 215.11964 530.31337 +195.64166 726.70753 196.73381 721.82588 +196.25321 607.20706 204.22252 610.14335 +196.33177 284.28730 199.08221 275.82340 +196.73381 721.82588 196.73382 721.82590 +196.73381 721.82588 199.71764 708.48885 +196.90558 382.74856 197.25295 361.94581 +196.90558 382.74856 198.13947 392.68357 +196.90558 382.74856 208.44726 379.95037 +196.94717 325.26430 197.25295 348.80131 +197.15590 248.50309 197.15590 251.55930 +197.15590 251.55930 197.15590 257.97905 +197.15590 251.55930 219.03156 254.04017 +197.15590 257.97905 197.15590 268.98312 +197.15590 268.98312 197.34383 281.17255 +197.25295 348.80131 197.25295 361.94581 +198.67246 893.84274 205.08065 888.31183 +199.08221 275.82340 206.48783 266.93665 +199.35025 803.38094 199.35050 803.38105 +199.35050 803.38105 216.83568 775.36897 +199.35050 803.38105 224.37070 814.73314 +199.46655 147.64953 201.42290 149.60588 +199.48580 59.28656 215.25828 63.81081 +199.67220 753.80602 206.35613 748.58935 +199.71764 708.48885 200.12508 686.68405 +199.71764 708.48885 212.35225 709.79360 +200.12508 686.68405 204.81184 662.43305 +200.12739 164.92932 219.69087 176.23993 +200.24986 618.30664 204.22252 610.14335 +200.28144 127.59697 208.43340 124.49917 +201.30197 748.42606 207.00850 745.81812 +201.55152 645.31501 204.81184 645.92656 +202.25858 930.37098 207.76100 930.98253 +202.72687 112.76108 207.78102 115.36980 +204.22252 610.14335 204.22263 610.14312 +204.22252 610.14335 209.52169 612.09584 +204.81184 645.92656 204.81184 662.43305 +204.81184 645.92656 207.25728 633.69939 +204.81184 645.92656 211.79154 652.83462 +205.08065 888.31183 223.67444 893.61006 +206.35613 748.58935 207.00850 745.81812 +206.48783 266.93665 215.37535 258.47276 +207.00850 745.81812 209.12736 744.35085 +207.25728 633.69939 209.52169 612.09584 +207.76100 930.98253 213.26342 931.28831 +208.43340 124.49917 216.74787 121.40213 +208.44726 379.95037 225.93500 375.52009 +209.12736 744.35085 213.52914 742.39451 +209.52169 612.09584 209.52171 612.09562 +209.52169 612.09584 215.61258 614.34003 +211.79154 652.83462 220.70755 656.40149 +212.35225 709.79360 226.20920 715.70346 +213.26342 931.28831 220.68136 932.35814 +213.52914 742.39451 222.82179 741.74213 +213.86496 143.07907 229.15219 139.31580 +215.11964 530.31337 234.73163 520.50776 +215.17894 970.87430 215.79050 970.87430 +215.17894 970.87430 216.40205 962.31490 +215.25828 63.81081 230.54243 67.47858 +215.37535 258.47276 222.35812 250.00886 +215.61258 614.34003 248.82966 633.22802 +216.40205 962.31490 218.54170 947.03074 +216.74787 121.40213 223.59509 120.91304 +216.83568 775.36897 234.36116 742.25356 +217.65057 615.35825 232.32317 595.38733 +218.54170 947.03074 220.68136 932.35814 +218.82437 254.29126 219.03156 254.04017 +219.69087 176.23993 235.01818 182.67371 +220.68136 932.35814 221.90370 925.32761 +220.70755 656.40149 221.98072 668.88283 +221.29291 909.73768 221.90370 925.32761 +221.29291 909.73768 223.67442 893.61014 +221.98072 668.88283 226.05670 678.81784 +222.31422 495.82851 228.96195 497.64160 +222.35812 250.00886 228.89418 245.80670 +222.78020 32.76343 224.02256 28.61350 +222.82179 741.74213 229.01741 741.41633 +223.59509 120.91304 225.38815 120.74976 +223.67442 893.61014 223.67444 893.61006 +223.67444 893.61006 225.68930 885.87409 +223.67444 893.61006 232.16220 896.02862 +224.02256 28.61350 226.14219 22.74446 +224.37070 814.73314 242.45612 805.30802 +224.57326 109.17496 225.38815 120.74976 +224.57326 109.17496 228.48596 106.56624 +225.38815 120.74976 227.50624 131.30479 +225.68930 885.87409 228.28416 875.14730 +225.93500 375.52009 235.44020 372.90098 +226.05670 678.81784 226.05670 692.06401 +226.05670 692.06401 231.66078 701.99825 +226.14219 22.74446 228.26182 16.87542 +226.20920 715.70346 232.11906 721.61255 +227.50624 131.30479 228.11453 134.26519 +227.50624 131.30479 229.46259 129.02264 +228.11394 134.26396 228.11453 134.26519 +228.11453 134.26519 229.15229 139.31572 +228.11453 134.26519 230.16541 138.54511 +228.26182 16.87542 232.01123 13.77838 +228.28416 875.14730 228.71625 865.97789 +228.48596 106.56624 232.21226 104.26099 +228.71625 865.97789 231.83100 841.84319 +228.89417 245.80656 228.89418 245.80670 +228.89418 245.80670 229.73756 257.87969 +228.89418 245.80670 231.24487 244.29540 +228.96195 497.64160 239.03483 498.64904 +229.01741 741.41633 232.76681 739.62250 +229.15219 139.31580 229.15229 139.31572 +229.15229 139.31572 229.95168 143.20616 +229.15229 139.31572 230.16541 138.54511 +229.46259 129.02264 232.56040 122.66451 +229.46259 129.02264 235.58041 120.17826 +229.46259 148.42283 229.95168 143.20616 +229.46259 148.42283 231.09314 160.16091 +229.73756 257.87969 231.04230 270.27015 +230.16541 138.54511 230.16580 138.54482 +230.16541 138.54511 233.14114 144.75506 +230.54243 67.47858 234.78742 69.04752 +230.60405 85.00483 231.90802 93.80839 +231.04230 270.27015 232.34628 279.72531 +231.09314 160.16091 232.07131 166.51904 +231.24487 244.29540 236.53933 241.97859 +231.43819 838.71226 231.83100 841.84319 +231.66078 701.99825 235.22688 704.03624 +231.90802 93.80839 232.39711 110.59986 +231.97503 96.10286 232.73758 94.44087 +232.01123 13.77838 232.66361 9.53912 +232.07131 166.51904 234.66925 160.03845 +232.07131 166.51904 235.01815 182.67354 +232.11906 721.61255 242.07333 727.51240 +232.16220 896.02862 266.52305 906.07454 +232.23383 90.71059 232.23383 90.54730 +232.23383 90.71059 233.86437 85.65643 +232.32317 595.38733 238.64048 585.40226 +232.34397 36.84403 256.79831 47.54309 +232.34628 279.72531 232.52728 284.73248 +232.39711 110.59986 232.56040 122.66451 +232.52728 284.73248 233.29133 301.03486 +232.52728 284.73248 235.32932 275.56153 +232.73755 94.44074 232.73758 94.44087 +232.73758 94.44087 235.45795 106.60552 +232.73758 94.44087 242.94135 72.20156 +232.76681 739.62250 235.04896 735.54729 +233.14114 144.75506 234.66925 160.03845 +233.29133 301.03486 235.67713 317.34061 +233.75808 931.42310 233.86668 931.45236 +233.75808 931.42310 234.70314 928.43235 +233.86437 85.65643 234.67926 72.12529 +234.36116 742.25356 239.25203 733.08337 +234.67926 72.12529 234.78742 69.04752 +234.70314 928.43235 235.69979 924.75996 +234.73163 520.50776 244.06356 516.71136 +234.78742 69.04752 235.00583 62.83264 +234.78742 69.04752 241.79143 71.63620 +234.94652 359.90320 234.94652 366.58713 +234.94652 359.90320 235.92470 353.54507 +234.94652 366.58713 235.44020 372.90098 +235.00583 62.83264 239.24433 51.58364 +235.01815 182.67354 235.01818 182.67371 +235.01818 182.67371 237.11237 196.08530 +235.01818 182.67371 244.45098 186.63322 +235.04896 735.54729 239.25203 733.08337 +235.09518 317.50361 235.67713 317.34061 +235.22688 704.03624 237.26487 713.97125 +235.22688 704.03624 237.46205 696.22394 +235.32932 275.56153 238.64048 255.69228 +235.44020 372.90098 235.44023 372.90136 +235.44020 372.90098 242.51078 370.95272 +235.45795 106.60552 235.58041 120.17826 +235.58041 120.17826 254.77649 129.83753 +235.67713 317.34061 237.16320 327.49715 +235.67713 317.34061 271.07271 307.42688 +235.69979 924.75996 236.53933 921.71684 +235.92470 353.54507 236.41378 346.69786 +236.34755 230.47388 236.60249 245.75804 +236.34755 230.47388 237.11237 212.64262 +236.41378 346.69786 238.60120 339.20982 +236.53933 921.71684 237.06385 918.83161 +236.60249 245.75804 238.64048 255.69228 +237.06385 918.83161 237.58836 916.20826 +237.11237 196.08530 237.11237 212.64262 +237.16320 327.49715 239.30286 344.92020 +237.26487 713.97125 238.79298 720.33939 +237.46205 696.22394 237.58297 687.38033 +237.58297 687.38033 243.63995 676.59885 +237.58836 916.20826 238.27000 915.26398 +238.27000 915.26398 239.63406 910.75205 +238.64048 585.40226 246.38422 577.45441 +238.79298 720.33939 243.89621 723.91304 +239.03483 498.64904 245.68256 499.25366 +239.24433 51.58364 242.83122 42.29099 +239.25203 733.08337 250.26611 711.33711 +239.25203 733.08337 251.37535 731.42519 +239.30286 344.92020 242.35985 350.11684 +239.63406 910.75205 241.10363 905.19110 +240.11313 800.67209 242.45612 805.30802 +240.11313 800.67209 242.86434 785.08216 +241.10363 905.19110 241.99554 901.67583 +241.10363 905.19110 252.81860 907.73127 +241.79143 71.63620 242.94135 72.20156 +241.99554 901.67583 242.97602 899.19035 +242.05407 367.84643 242.35985 350.11684 +242.05407 367.84643 242.51078 370.95272 +242.45612 805.30802 256.72129 811.16705 +242.51078 370.95272 242.51081 370.95271 +242.51078 370.95272 243.58218 378.23972 +242.86434 785.08216 245.92055 770.40955 +242.94135 72.20156 242.94136 72.20154 +242.94135 72.20156 256.46403 78.85004 +243.28026 725.12936 243.89621 723.91304 +243.28026 725.12936 243.89643 723.91319 +243.58218 378.23972 246.02761 405.13949 +243.63995 676.59885 245.82043 671.02557 +243.89621 723.91304 243.89643 723.91319 +243.89621 723.91304 243.94957 723.80767 +244.06356 516.71136 250.56264 515.49211 +244.45098 186.63322 262.48635 192.44064 +245.14572 395.43632 264.38921 399.60543 +245.68256 499.25366 251.92130 498.58280 +245.92055 770.40955 247.14366 751.15186 +246.02761 405.13949 251.22426 439.68135 +246.38422 577.45441 251.85846 570.05172 +247.14366 751.15186 249.28331 737.70158 +247.77215 416.73509 264.38921 399.60543 +248.60013 613.83707 249.20398 606.43916 +248.60013 613.83707 251.27509 617.94386 +248.82966 633.22802 249.14106 631.28176 +248.82966 633.22802 252.70153 643.82464 +248.90206 545.38495 250.26072 552.02805 +248.90206 545.38495 251.01553 533.60912 +249.14082 631.28168 249.14106 631.28176 +249.14106 631.28176 251.27509 617.94386 +249.14106 631.28176 256.24760 633.80106 +249.20398 606.43916 251.77034 588.17119 +249.28331 737.70158 251.37535 731.42519 +249.35494 508.09419 250.56264 515.49211 +249.35494 508.09419 251.92130 498.58280 +250.26072 552.02805 251.31745 563.71376 +250.26611 711.33711 256.12283 696.08299 +250.53646 733.94216 257.16493 745.37755 +250.56264 515.49211 252.52515 523.94677 +250.74056 920.56999 251.47381 934.38689 +250.74056 920.56999 252.08536 913.11122 +251.01553 533.60912 252.52515 523.94677 +251.11720 775.30042 252.34030 770.40955 +251.22426 439.68135 254.28124 464.13569 +251.27509 617.94386 270.02368 623.76515 +251.31745 563.71376 251.85846 570.05172 +251.37535 731.42519 251.37599 731.42510 +251.37535 731.42519 255.39651 719.36121 +251.37599 731.42510 257.52693 742.81119 +251.47381 934.38689 252.79785 946.19274 +251.77034 588.17119 252.37419 576.09344 +251.85846 570.05172 251.85892 570.05110 +251.85846 570.05172 252.37419 576.09344 +251.92130 498.58280 253.12444 484.76120 +252.08536 913.11122 252.81860 907.73127 +252.34030 770.40955 255.70229 755.73695 +252.64453 252.24017 260.67557 249.62298 +252.70153 643.82464 252.90564 654.42127 +252.79781 946.19275 252.79785 946.19274 +252.79785 946.19274 252.94107 947.46977 +252.79785 946.19274 260.13103 944.57607 +252.90564 654.42127 254.35210 669.66152 +252.94107 947.46977 254.53079 955.66178 +253.12438 484.76129 253.12444 484.76120 +253.12444 484.76120 254.28124 471.47199 +253.12444 484.76120 264.39802 467.97213 +253.44710 821.26842 256.72129 811.16705 +254.21577 681.91873 254.35210 669.66152 +254.21577 681.91873 256.39471 693.35951 +254.28124 464.13569 254.28124 471.47199 +254.53079 955.66178 257.20036 967.93978 +254.77649 129.83753 281.55457 143.16534 +255.39651 719.36121 256.61962 703.46551 +255.70229 755.73695 259.37083 729.75450 +255.70229 755.73695 265.75794 765.18877 +256.00807 808.61994 256.92539 798.22666 +256.12283 696.08299 256.39471 693.35951 +256.12283 696.08299 256.61962 703.46551 +256.12283 696.08299 260.32358 684.82937 +256.12283 696.08299 269.15256 701.32585 +256.24760 633.80106 261.95336 634.77923 +256.46403 78.85004 258.20936 79.46462 +256.72129 811.16705 280.66651 826.19626 +256.79831 47.54309 276.15844 52.12818 +256.92539 798.22666 260.89893 780.80284 +257.20036 967.93978 263.56850 975.83680 +258.20934 79.46467 258.20936 79.46462 +258.20936 79.46462 260.76569 71.67779 +258.20936 79.46462 273.82700 84.96401 +259.37083 729.75450 263.95592 710.80181 +259.55029 165.33753 264.82780 203.28066 +259.55029 165.33753 278.65548 158.45951 +260.13103 944.57607 268.20135 944.20944 +260.32358 684.82937 264.88788 669.50440 +260.35054 837.45450 261.78468 831.04939 +260.67557 249.62298 266.45065 249.71309 +260.76569 71.67779 264.67838 64.99386 +260.89893 780.80284 263.34437 767.65834 +261.74694 680.05096 268.82137 692.97055 +261.78468 831.04939 263.02781 823.21013 +261.95336 634.77923 267.33331 633.63854 +263.02781 823.21013 265.98852 816.98371 +263.34437 767.65834 265.75794 765.18877 +263.34437 767.65834 265.75822 765.18903 +263.56850 975.83680 266.37054 977.61985 +263.95592 710.80181 269.15256 701.32585 +264.38921 399.60543 264.38955 399.60550 +264.38921 399.60543 272.06627 391.69155 +264.39802 467.97213 280.90451 452.99375 +264.67838 64.99386 269.51379 50.55463 +264.82780 203.28066 271.02265 234.41970 +264.88788 669.50440 266.68171 664.12444 +265.75794 765.18877 265.75822 765.18903 +265.75794 765.18877 276.48886 754.20884 +266.19262 642.93119 266.84423 654.01690 +266.19262 642.93119 267.33331 633.63854 +266.45065 249.71309 271.31829 251.53615 +266.52305 906.07454 290.31383 913.34727 +266.68171 664.12444 266.84423 654.01690 +266.82266 465.77240 273.14767 474.62602 +267.33331 633.63854 276.13688 631.19311 +267.99878 879.63227 269.05012 871.79302 +268.20135 944.20944 277.12660 946.65488 +268.82137 692.97055 273.53737 697.53950 +269.05012 871.79302 269.43292 866.53552 +269.15256 701.32585 273.53737 697.53950 +269.43292 866.53552 271.15358 859.17458 +270.02368 623.76515 274.46243 599.82223 +270.02368 623.76515 281.09513 629.59735 +270.55435 258.81242 270.86013 287.85262 +270.55435 258.81242 271.31829 251.53615 +270.86013 287.85262 271.02965 303.44330 +271.02265 234.41970 272.45671 240.69304 +271.02958 303.44333 271.02965 303.44330 +271.02965 303.44330 271.16591 315.97473 +271.02965 303.44330 286.75507 297.94014 +271.15358 859.17458 271.34460 852.96048 +271.16591 315.97473 272.38824 341.95795 +271.16591 355.71323 272.38824 341.95795 +271.16591 355.71323 272.98901 378.73497 +271.31829 251.53615 271.31841 251.53619 +271.31829 251.53615 272.45671 240.69304 +271.34460 852.96048 272.77874 845.31301 +271.49787 388.09231 272.06627 391.69155 +271.49787 388.09231 274.85986 366.99996 +272.06627 391.69155 272.06629 391.69153 +272.06627 391.69155 274.25909 405.57698 +272.39594 831.83347 272.49145 825.71488 +272.39594 831.83347 272.87424 838.71611 +272.45671 240.69304 272.45679 240.69233 +272.45671 240.69304 276.24009 257.24349 +272.49145 825.71488 272.92277 821.33620 +272.77874 845.31301 272.87424 838.71611 +273.09915 567.86831 275.06782 557.72226 +273.09915 567.86831 278.55150 575.28933 +273.14767 474.62602 273.14767 488.38130 +273.14767 488.38130 276.20389 499.38614 +273.14767 545.54361 273.75845 532.39911 +273.14767 545.54361 275.06782 557.72226 +273.53737 697.53950 273.53740 697.53947 +273.53737 697.53950 276.97256 700.86757 +273.75845 532.39911 276.20389 499.38614 +273.82700 84.96401 286.29833 88.38762 +274.25909 405.57698 280.29065 438.01999 +274.25909 405.57698 284.16329 407.62960 +274.46243 599.82223 279.76305 584.52730 +274.85986 366.99996 279.11241 349.18112 +275.45524 880.66513 275.55074 880.47334 +275.55074 880.47334 279.08834 863.36147 +276.13688 631.19311 281.09513 629.59735 +276.15844 52.12818 288.89473 49.58108 +276.24009 257.24349 277.21826 262.29765 +276.48886 754.20884 283.21362 740.75857 +276.97256 700.86757 289.96455 714.11374 +277.12660 946.65488 282.38486 949.58940 +277.21826 262.29765 281.86420 281.73865 +278.55150 575.28933 280.52017 576.80358 +278.65548 158.45951 290.37354 146.48728 +279.08834 863.36147 280.61799 857.24365 +279.11222 349.18103 279.11241 349.18112 +279.11241 349.18112 281.27961 340.10019 +279.11241 349.18112 283.02183 351.05882 +279.31710 432.78176 285.58434 423.60541 +279.76305 584.52730 280.52017 576.80358 +280.29065 438.01999 281.75791 448.77990 +280.55021 975.75593 282.75149 967.93054 +280.61799 857.24365 283.00720 849.11787 +280.66651 826.19626 289.20817 831.12418 +280.90451 452.99375 299.55143 433.73605 +281.09513 629.59735 281.09552 629.59722 +281.09513 629.59735 292.84747 635.78822 +281.27961 340.10019 289.27829 321.73902 +281.55457 143.16534 286.93453 146.09986 +281.86420 281.73865 286.75507 297.94014 +282.75149 967.93054 285.80847 961.57241 +283.00720 849.11787 286.54480 838.69763 +283.02183 351.05882 285.14147 364.42667 +283.21362 740.75857 290.23976 730.88466 +284.16329 407.62960 292.96685 409.09686 +285.14147 364.42667 286.44544 374.86078 +285.14840 631.73226 296.69855 589.14397 +285.58434 423.60541 294.02051 418.95947 +285.80847 961.57241 290.44748 955.42532 +286.29833 88.38762 295.71344 90.71059 +286.44544 374.86078 287.09781 382.03380 +286.54480 838.69763 289.20817 831.12418 +286.75507 297.94014 289.27829 321.73902 +286.93453 146.09986 290.37354 146.48728 +286.93453 381.54471 287.09781 382.03380 +286.94300 299.71163 291.90011 297.06132 +288.89473 49.58108 301.07183 39.49896 +288.89473 49.58108 304.63870 49.94308 +289.20817 831.12418 289.20820 831.12410 +289.20817 831.12418 300.06727 837.38909 +289.27829 321.73902 301.01638 302.66464 +289.62797 924.45727 290.31383 913.34727 +289.62797 932.81256 289.62797 924.45727 +289.62797 932.81256 291.25775 940.76042 +289.96455 714.11374 294.80382 720.48188 +289.96455 714.11374 297.30086 688.37082 +290.03541 950.94960 291.25775 940.76042 +290.03541 950.94960 291.46185 966.43709 +290.23952 730.88441 290.23976 730.88466 +290.23976 730.88466 294.52423 724.86363 +290.23976 730.88466 295.53783 736.41301 +290.28882 831.74720 299.03686 822.94506 +290.31383 913.34727 290.64697 907.95078 +290.31383 913.34727 294.62359 914.66475 +290.37354 146.48728 298.68262 142.01306 +290.64697 907.95078 292.27674 890.42453 +291.90011 297.06132 298.25823 290.86648 +292.27674 890.42453 294.11139 871.06516 +292.84747 635.78822 309.76217 641.49397 +292.96685 409.09686 304.32482 415.02885 +293.75247 969.12668 293.93887 965.03376 +293.93887 960.94083 293.93887 965.03376 +293.93887 960.94083 295.42692 955.91749 +294.02051 418.95947 304.32482 415.02885 +294.11139 871.06516 296.14861 857.81900 +294.12449 926.33582 294.31088 937.49856 +294.12449 926.33582 294.62359 914.66475 +294.28546 813.10337 295.30446 799.24565 +294.28546 813.10337 299.03686 822.94506 +294.31088 937.49856 295.61331 942.14989 +294.52423 724.86363 295.12115 721.03181 +294.62359 914.66475 315.58962 921.07140 +294.80382 720.48188 295.12115 721.03181 +295.12115 721.03181 303.69442 710.19103 +295.30446 799.24565 296.73090 784.98049 +295.42692 949.40532 295.42692 955.91749 +295.42692 949.40532 295.61331 942.14989 +295.42692 949.40532 298.40381 954.05665 +295.42692 955.91749 295.98533 961.87048 +295.53783 736.41301 299.61304 740.99811 +295.71344 90.71059 307.35371 91.68876 +295.98533 961.87048 298.03179 970.05710 +296.14861 857.81900 298.59405 844.16539 +296.48674 27.78090 301.07183 39.49896 +296.69855 589.14397 303.21919 562.44753 +296.73090 784.98049 300.60277 768.26990 +297.19457 475.17981 297.32165 487.01879 +297.19457 475.17981 300.75912 469.32309 +297.19457 475.17981 304.63254 477.37723 +297.30086 688.37082 305.86026 664.52726 +297.32165 487.01879 300.12216 499.11348 +297.39790 90.85231 297.42717 90.85462 +297.42717 90.85462 298.91677 138.88602 +298.03179 970.05710 298.59020 971.73155 +298.25823 290.86648 303.96399 282.71529 +298.40381 954.05665 303.42715 957.40554 +298.59405 844.16539 300.06727 837.38909 +298.68262 142.01310 298.68262 142.01306 +298.68262 142.01310 301.07183 196.66913 +298.68262 142.01306 298.91677 138.88602 +298.68262 142.01306 310.24279 135.78822 +299.03686 822.94506 299.03692 822.94518 +299.03686 822.94506 300.37787 821.59576 +299.55143 433.73605 313.40914 422.52788 +299.61304 740.99811 303.94397 744.56420 +300.06727 837.38909 300.53576 837.65938 +300.06727 837.38909 301.10492 832.61627 +300.12216 499.11348 304.95988 514.13576 +300.37787 821.59576 301.10492 832.61627 +300.37787 821.59576 301.65103 830.10433 +300.37787 821.59576 307.25512 814.97268 +300.60277 768.26990 303.94397 744.56420 +300.75912 469.32309 309.33316 457.57884 +301.01638 302.66464 316.17807 275.27578 +301.07183 39.49896 304.63870 49.94308 +301.07183 196.66913 319.92748 195.29352 +301.10492 832.61627 301.10495 832.61678 +301.10492 832.61627 301.65103 830.10433 +301.10495 832.61678 306.23613 844.16539 +301.37684 24.10774 305.70776 33.78781 +303.21919 562.44753 312.08976 535.95674 +303.42715 957.40554 305.10160 960.56882 +303.42715 957.40554 310.86897 947.54525 +303.69442 710.19103 308.58528 697.65808 +303.94397 744.56420 305.72701 748.64018 +303.94397 744.56420 309.36628 729.75450 +303.96399 282.71529 310.97449 274.40081 +304.32482 415.02885 304.32522 415.02906 +304.32482 415.02885 305.88106 414.43522 +304.63254 477.37723 311.35729 480.73922 +304.63870 49.94308 306.95628 68.27344 +304.95988 514.13576 308.90646 520.11957 +305.10160 960.56882 307.70647 965.59139 +305.70776 33.78781 310.54702 52.63806 +305.72701 748.64018 308.27412 756.53720 +305.86026 664.52726 313.63944 642.96354 +305.88106 414.43522 311.60761 409.74846 +305.88106 414.43522 315.54110 413.45705 +306.23613 844.16539 315.66125 859.19460 +306.49107 841.36334 306.74601 841.10840 +306.74601 841.10840 307.76500 835.50431 +306.95628 68.27344 307.97527 79.58405 +307.25512 814.97268 310.82122 809.11365 +307.70647 965.59139 307.70647 967.26584 +307.76500 835.50431 309.54805 828.37212 +307.97527 79.58405 308.79016 94.76577 +308.10544 82.00715 311.82096 98.69387 +308.27412 756.53720 310.05717 763.41446 +308.58528 697.65808 315.31003 683.90203 +308.79016 94.76577 309.30004 103.22274 +308.90646 520.11957 311.58065 526.79040 +309.30004 103.22274 310.11061 112.79745 +309.30235 811.60915 310.05717 821.23915 +309.33316 457.57884 313.00093 447.38966 +309.36628 729.75450 314.66459 727.10573 +309.54805 828.37212 310.05717 821.23915 +309.76217 641.49397 329.12154 648.83027 +310.05717 763.41446 311.84021 770.54742 +310.11031 112.79728 310.11061 112.79745 +310.11061 112.79745 311.44971 128.61520 +310.11061 112.79745 315.50721 115.85889 +310.54702 52.63806 315.64200 68.43133 +310.82122 784.81258 311.84021 770.54742 +310.82122 809.11365 310.82122 784.81258 +310.86897 947.54525 317.56677 936.38251 +310.97449 274.40081 317.65842 264.29250 +311.35729 480.73922 316.24816 488.38130 +311.44971 128.61520 313.56935 139.21182 +311.58065 526.79040 312.08976 535.95674 +311.60761 409.74846 324.64967 402.90125 +311.77860 430.27162 313.00093 447.38966 +311.77860 430.27162 313.58190 422.21269 +311.82096 98.69387 316.50772 108.27150 +312.08976 535.95674 324.61732 509.05542 +313.40914 422.12043 313.58190 422.21269 +313.40914 422.52788 313.40914 422.12043 +313.56935 139.21182 314.87332 150.78662 +313.58190 422.21269 315.54110 413.45705 +313.58190 422.21269 318.99937 425.10579 +314.66459 727.10573 315.90090 717.05751 +314.87332 150.78662 317.31876 167.74214 +315.25997 153.46620 321.42940 152.43565 +315.31003 683.90203 325.09177 673.50875 +315.50721 115.85889 320.58370 121.92511 +315.54110 413.45705 330.33540 410.52253 +315.58962 921.07140 326.44037 923.53463 +315.64200 68.43133 326.08612 83.46055 +315.66125 859.19460 326.36032 874.22382 +315.90079 717.05750 315.90090 717.05751 +315.90090 717.05751 316.29437 713.85957 +315.90090 717.05751 324.35236 718.16045 +316.17807 275.27578 320.74119 262.61211 +316.24816 488.38130 323.58446 503.35968 +316.29437 713.85957 318.53647 703.87372 +316.50772 108.27150 322.41758 113.36647 +317.31876 167.74214 318.29693 177.68640 +317.56677 936.38251 326.44037 923.53463 +317.65842 264.29250 320.74119 262.61211 +318.29693 177.68640 321.55802 180.78420 +318.53647 703.87372 321.59345 689.60856 +318.99937 425.10579 319.91669 449.25435 +319.04250 405.84501 322.20423 389.69590 +319.92748 195.29352 320.57985 200.67348 +319.92748 195.29352 322.53620 193.33717 +320.57985 200.67348 321.72054 206.47782 +320.58370 121.92511 324.79678 133.50838 +320.58370 121.92511 334.25484 117.80991 +320.74119 262.61211 320.74159 262.61189 +320.74119 262.61211 322.69871 257.17956 +321.42940 152.43565 333.85374 151.73861 +321.55802 180.78420 321.86928 184.52053 +321.59345 689.60856 330.59419 666.17245 +321.72054 206.47782 324.16597 210.22723 +321.86919 184.52052 321.86928 184.52053 +321.86928 184.52053 322.37291 190.56594 +321.86928 184.52053 328.57237 185.51101 +322.20423 389.69590 324.81295 365.07828 +322.37291 190.56594 322.53620 193.33717 +322.41758 113.36647 331.38443 115.20036 +322.69871 257.17956 324.81834 240.22481 +323.58446 503.35968 324.61732 509.05542 +323.61604 787.27804 324.07278 795.66184 +324.07278 795.66184 326.66455 808.77091 +324.16597 210.22723 325.30743 218.05262 +324.35236 718.16045 332.45041 722.20870 +324.38933 211.75842 333.05657 239.15883 +324.61732 509.05542 334.80650 492.75304 +324.64967 402.90125 337.85501 394.74929 +324.79678 133.50838 325.95749 137.80464 +324.81295 365.07828 326.60601 347.30787 +324.81834 226.20381 324.81834 240.22481 +324.81834 226.20381 325.30743 218.05262 +325.09177 673.50875 330.59419 666.17245 +325.43991 789.35762 330.94233 794.86004 +325.59857 803.37786 335.04295 802.96502 +325.95749 137.80464 327.93156 141.17202 +326.08612 83.46055 333.21831 104.34879 +326.36032 874.22382 333.23834 881.86589 +326.44037 923.53463 326.44042 923.53455 +326.44037 923.53463 342.52560 927.18614 +326.60601 347.30787 328.39985 329.21165 +326.66455 808.77091 331.23732 818.06972 +327.50255 338.26862 336.55104 331.00549 +327.93156 141.17202 329.90562 144.07496 +328.57237 185.51101 334.60470 192.03166 +329.12154 648.83027 340.94126 651.68315 +329.67378 150.69342 329.90562 144.07496 +330.33540 410.52253 344.51892 407.22139 +330.59419 666.17245 334.00316 650.00870 +330.59419 666.17245 340.23960 678.48203 +330.63655 503.59845 342.86372 519.18761 +330.94233 794.86004 335.83320 797.30548 +331.23732 818.06972 338.40186 831.94053 +331.38443 115.20036 334.25484 117.80991 +332.45041 722.20870 344.77309 727.49007 +333.05657 239.15883 338.39362 276.51882 +333.21831 104.34879 339.07734 114.79291 +333.23834 881.86589 341.59364 888.28487 +333.85374 151.73861 343.60775 151.62230 +334.25484 117.80991 334.25502 117.80985 +334.25484 117.80991 335.86786 119.27634 +334.60470 192.03166 339.21792 195.66602 +334.80650 492.75304 346.62623 474.41190 +335.04295 802.96502 343.19415 804.74807 +335.83320 797.30548 338.58364 799.75091 +335.86786 119.27634 336.68274 119.27634 +335.97877 259.61421 337.60007 217.14453 +336.55104 331.00549 348.71890 336.29147 +336.68274 119.27634 342.21443 129.67656 +337.60007 202.87937 337.60007 217.14453 +337.60007 202.87937 339.21792 195.66602 +337.85501 394.74929 350.57204 381.05486 +338.39339 276.51890 338.39362 276.51882 +338.39362 276.51882 339.78132 286.23286 +338.39362 276.51882 364.94657 267.66143 +338.40186 831.94053 342.66963 842.30609 +338.58364 799.75091 346.53149 803.11367 +339.07734 114.79291 351.04957 125.74615 +339.21792 195.66602 339.21829 195.66631 +339.21792 195.66602 343.71327 175.62299 +339.36309 967.14338 339.44936 972.71897 +339.36309 967.14338 339.53485 959.93878 +339.53485 959.93878 340.82111 945.27157 +339.78132 286.23286 346.81185 325.66558 +340.23960 678.48203 344.51892 701.71327 +340.49916 877.68824 345.64728 886.61196 +340.82111 945.27157 343.65165 936.69368 +340.94126 651.68315 350.64164 653.30039 +341.40108 150.22899 342.21443 129.67656 +341.59364 888.28487 348.92994 891.95341 +342.21443 129.67656 366.34126 124.26891 +342.52560 927.18614 348.97777 929.16132 +342.66963 842.30609 349.22416 858.92117 +342.86372 519.18761 349.58847 546.39316 +343.19415 804.74807 349.28270 805.86488 +343.29658 742.98064 344.51892 759.48713 +343.29658 742.98064 344.77309 727.49007 +343.52226 882.92725 349.59464 879.40428 +343.60775 151.62230 351.27139 151.39047 +343.65165 936.69368 346.56846 931.11886 +343.71327 175.62299 351.27139 151.39047 +344.51892 407.22139 352.83339 405.87659 +344.51892 701.71327 344.77309 727.49007 +344.51892 759.48713 346.04779 772.32585 +344.65678 760.64399 351.50246 754.91898 +345.64728 886.61196 354.16124 894.25096 +346.53149 803.11367 349.28270 805.86488 +346.56846 931.11886 346.89195 928.52324 +346.62623 474.41190 357.45931 461.98062 +346.81185 325.66558 351.09116 349.50914 +348.56486 919.21749 349.42288 921.96331 +348.56486 919.21749 350.79617 909.43576 +348.92994 891.95341 354.16124 894.25096 +348.97769 929.16174 348.97777 929.16132 +348.97777 929.16132 349.59464 925.73891 +348.97777 929.16132 356.79384 931.55403 +349.22416 858.92117 355.42902 872.54012 +349.28270 805.86488 353.25624 807.69877 +349.42288 921.96331 349.59464 925.73891 +349.58847 546.39316 356.31323 573.59871 +349.59464 879.40428 353.71298 874.59891 +350.53122 543.26916 351.34611 543.26916 +350.53122 543.26916 352.97665 533.07998 +350.57204 381.05486 352.99283 378.45153 +350.64136 653.30060 350.64164 653.30039 +350.64164 653.30039 355.61387 654.12936 +350.64164 653.30039 359.87470 646.56969 +350.79617 909.43576 351.67786 905.74893 +351.09116 349.50914 352.16099 374.12600 +351.27139 151.39047 356.26393 152.78379 +351.50246 754.91898 357.28986 748.88665 +351.67730 905.74950 351.67786 905.74893 +351.67786 905.74893 352.68397 901.54182 +351.67786 905.74893 359.10988 898.14902 +352.03391 605.69513 353.86779 594.69106 +352.03391 605.69513 363.68027 621.61987 +352.16099 374.12600 352.99287 378.45156 +352.68397 901.54182 354.16124 894.25096 +352.83339 405.87659 355.58682 405.63706 +352.97665 533.07998 355.01387 506.58765 +352.99283 378.45153 352.99287 378.45156 +352.99287 378.45156 356.23697 395.32002 +352.99287 378.45156 361.11321 384.03944 +353.25624 807.69877 361.20409 813.20118 +353.71298 874.59891 355.42902 872.54012 +353.86779 594.69106 356.31323 573.59871 +354.16124 894.25096 357.31682 883.69438 +355.01387 506.58765 357.45931 473.57391 +355.42209 403.87942 355.58682 405.63706 +355.42209 403.87942 356.23697 395.32002 +355.42902 872.54012 358.86187 875.80045 +355.58682 405.63706 355.58691 405.63705 +355.58682 405.63706 356.64442 416.92148 +355.61387 654.12936 368.65670 654.74014 +356.26393 152.78379 360.32836 151.85491 +356.28550 489.42802 360.07727 481.79981 +356.64442 416.92148 357.45931 444.22870 +356.79384 931.55403 368.71139 931.93430 +357.28986 748.88665 362.26237 745.95213 +357.31682 883.69438 358.86187 875.80045 +357.45931 444.22870 357.45931 461.98062 +357.45931 461.98062 357.45931 473.57391 +357.45931 461.98062 368.12480 451.55726 +358.85879 615.02706 361.35583 609.75185 +358.86187 875.80045 361.09407 876.90991 +359.10988 898.14902 363.83746 893.58472 +359.87470 646.56969 362.20229 633.45061 +360.07727 481.79981 360.90602 473.30818 +360.32836 151.85491 370.68853 149.91474 +360.69498 64.86832 361.96815 36.84788 +360.69498 64.86832 362.22309 92.12470 +360.90602 473.30818 363.80588 465.23016 +361.09395 876.91033 361.09407 876.90991 +361.09407 876.90991 363.86596 867.07776 +361.09407 876.90991 365.07751 878.88978 +361.11321 384.03944 371.26234 392.73825 +361.20409 813.20118 369.45772 815.03507 +361.35583 609.75185 366.22282 598.53751 +361.96815 36.84788 363.49702 14.17659 +362.20229 633.45061 363.68027 621.61987 +362.22309 92.12470 364.26108 113.52206 +362.26237 745.95213 373.34808 746.19706 +363.68027 621.61987 363.68034 621.61933 +363.68027 621.61987 363.68666 621.62861 +363.68034 621.61933 363.68666 621.62861 +363.68666 621.62861 363.69189 621.63628 +363.68666 621.62861 367.01229 626.17593 +363.80588 465.23016 368.15529 458.80965 +363.83746 893.58472 370.95425 887.89360 +363.86596 867.07776 364.65235 858.90038 +364.26108 113.52206 366.34126 124.26891 +364.65235 858.90038 365.87545 844.63522 +364.94657 267.66143 380.43637 265.13974 +365.07751 878.88978 372.54629 879.65229 +365.87545 844.63522 369.74732 827.31307 +366.22282 598.53751 370.03153 589.01534 +366.34126 124.26891 366.34143 124.26887 +366.34126 124.26891 367.31806 129.31532 +367.01229 626.17593 381.68489 650.93604 +367.31806 129.31532 369.98025 145.58495 +368.12448 451.55807 368.12480 451.55726 +368.12480 451.55726 369.60483 450.11083 +368.12480 451.55726 378.09723 426.49911 +368.15529 458.80965 371.88313 452.59632 +368.65670 654.74014 378.84588 652.90625 +368.71138 931.93452 368.71139 931.93430 +368.71139 931.93430 369.05413 925.86445 +368.71139 931.93430 370.48057 931.99075 +369.05413 925.86445 369.38070 919.17975 +369.38070 919.17975 369.54322 907.27915 +369.45772 815.03507 371.41406 815.80842 +369.54322 907.27915 370.35887 890.97600 +369.60483 450.11083 371.73371 447.88730 +369.74732 827.31307 371.41406 815.80842 +369.97993 145.58459 369.98025 145.58495 +369.98025 145.58495 371.90316 157.33653 +369.98025 145.58495 387.62942 165.12803 +370.03153 589.01534 374.26310 569.12530 +370.35887 890.97600 372.54629 879.65229 +370.48057 931.99075 377.18144 932.58766 +371.26234 392.73825 382.23945 399.15877 +371.41406 815.80842 371.41407 815.80836 +371.41406 815.80842 380.18759 819.27664 +371.73371 447.88722 371.73371 447.88730 +371.73371 447.88730 371.88313 452.59632 +371.73371 447.88730 378.92521 440.37608 +371.90316 157.33653 374.47568 171.39759 +372.14192 48.15464 372.14192 51.92485 +372.14192 48.15464 375.80969 23.29286 +372.14192 51.92485 372.14192 73.01643 +372.14192 51.92485 381.07720 53.26500 +372.14192 73.01643 374.99480 102.76908 +372.54629 879.65229 379.17394 878.15346 +373.34808 746.19706 379.70756 750.42234 +374.26310 569.12530 378.07181 546.27300 +374.47568 171.39759 375.59634 185.76442 +374.58736 117.44168 374.99480 102.76908 +374.58736 117.44168 376.62535 130.89196 +374.80687 991.42288 376.02997 956.77859 +374.80687 991.42288 376.02997 991.83032 +375.29133 193.71227 375.59634 185.76442 +375.29133 193.71227 375.80045 201.66012 +375.59634 198.47143 382.33110 187.54438 +375.80045 201.66012 376.12178 204.61084 +375.80969 23.29286 381.92366 6.58226 +376.02997 956.77859 377.25230 931.10192 +376.12163 204.61082 376.12178 204.61084 +376.12178 204.61084 376.92111 211.95097 +376.12178 204.61084 390.13416 206.91530 +376.62535 130.89196 376.62535 150.86287 +376.76861 941.26645 386.23918 940.05798 +376.92111 211.95097 377.53266 217.65750 +377.25230 931.10192 378.47540 904.60959 +377.25230 931.10192 383.18296 938.83565 +377.53266 217.65750 378.48003 234.10237 +378.07181 546.27300 385.47820 535.48152 +378.09723 426.49911 383.48258 413.03651 +378.29055 230.80662 389.23531 221.05184 +378.47540 904.60959 379.17394 878.15346 +378.48003 234.10237 379.78477 242.90593 +378.84588 652.90625 381.68489 650.93604 +378.92521 440.37608 386.79604 430.84852 +379.17394 878.15346 379.17399 878.15345 +379.17394 878.15346 379.17646 878.05770 +379.17399 878.15345 379.17646 878.05770 +379.17646 878.05770 379.18631 877.67669 +379.17646 878.05770 379.23946 875.67182 +379.23946 875.67182 379.54523 849.99438 +379.23946 875.67182 388.78089 878.58555 +379.54523 753.40012 379.70756 750.42234 +379.54523 753.40012 381.37912 776.01980 +379.54523 849.99438 379.85101 820.34339 +379.61532 843.20493 388.29180 839.13280 +379.70756 750.42234 379.70775 750.42246 +379.70756 750.42234 380.46179 736.58708 +379.78477 242.90593 380.43637 265.13974 +379.85101 820.34339 380.18759 819.27664 +379.85101 820.34339 381.68489 814.53597 +379.85101 820.34339 384.71107 825.12258 +380.15679 719.16404 380.46179 736.58708 +380.15679 719.16404 382.90722 698.68324 +380.43637 265.13974 383.69747 289.26751 +380.46179 736.58708 393.36367 737.81866 +381.07719 53.26502 381.07720 53.26500 +381.07720 53.26500 383.99785 42.74080 +381.07720 53.26500 384.36909 53.75873 +381.37912 776.01980 382.29644 803.22535 +381.68489 650.93604 384.43610 668.97141 +381.68489 814.53597 382.29644 803.22535 +382.23945 399.15877 384.31056 400.19471 +382.23945 399.15877 385.69060 399.39291 +382.33110 187.54438 386.81453 171.64945 +382.90722 698.68324 384.43610 668.97141 +382.90722 698.68324 394.94415 701.67014 +383.48258 413.03651 384.72493 403.09457 +383.69747 289.26751 387.28359 318.12363 +383.99785 42.74080 386.15148 34.01207 +384.36909 53.75873 395.65117 58.49693 +384.71107 825.12258 391.74160 830.62500 +384.72493 403.09457 385.69060 399.39291 +384.72493 403.09457 390.93826 402.68020 +385.47820 535.48152 392.24917 521.72701 +385.69060 399.39291 385.69078 399.39292 +385.69060 399.39291 387.21042 393.56701 +386.15137 34.01194 386.15148 34.01207 +386.15148 34.01207 386.81530 31.32158 +386.15148 34.01207 391.77703 40.45557 +386.23918 940.05798 401.21756 942.19764 +386.79604 430.84852 392.80295 423.59925 +386.81453 171.64945 387.62942 165.12803 +386.81530 31.32158 387.55702 21.38657 +387.21042 393.56701 393.75696 387.09748 +387.28359 318.12363 391.35957 343.06706 +387.62942 165.12803 390.27896 153.10497 +388.29180 839.13280 394.64993 836.52408 +388.78089 878.58555 396.11719 882.66153 +389.23531 221.05184 391.88486 212.28910 +389.41323 157.03384 393.92285 161.58658 +390.13416 206.91530 391.96650 202.99645 +390.13416 206.91530 401.84066 211.17226 +390.27896 153.10497 394.15083 139.85880 +390.67100 34.58421 392.59885 44.81653 +390.67100 34.58421 392.68888 22.51083 +390.93826 402.68020 395.18101 402.84039 +391.29795 17.17889 392.52028 3.72938 +391.29795 17.17889 392.68888 22.51083 +391.35957 343.06706 393.15263 363.60871 +391.74160 830.62500 409.77696 839.18363 +391.88486 212.28910 392.14596 207.64701 +391.96650 202.99645 394.08613 197.12740 +392.24917 521.72701 399.28663 511.51703 +392.59885 44.81653 395.65117 58.49693 +392.68888 22.51083 392.68896 22.51032 +392.68888 22.51083 393.74339 26.55318 +392.80295 423.59925 396.68869 419.50786 +392.82683 376.81482 393.15263 363.60871 +392.82683 376.81482 393.75696 387.09748 +393.36367 737.81866 401.78295 740.69880 +393.43915 332.41806 408.29276 309.68823 +393.59704 192.88814 394.08613 197.12740 +393.59704 192.88814 395.71591 181.47663 +393.74339 26.55318 397.41115 35.52003 +393.75696 387.09748 393.75725 387.09720 +393.75696 387.09748 395.18101 402.84039 +393.92285 161.58658 397.34645 174.46613 +394.15083 139.85880 397.81860 132.72584 +394.64993 836.52408 399.17186 834.15105 +394.94415 701.67014 408.83422 701.84189 +394.97188 106.35828 395.41629 103.83737 +395.18101 402.84039 395.18138 402.84040 +395.18101 402.84039 396.68869 419.50786 +395.41629 103.83737 398.67893 87.22844 +395.65117 58.49693 395.65121 58.49709 +395.65117 58.49693 395.65123 58.49695 +395.65121 58.49709 395.65123 58.49695 +395.65123 58.49695 397.00371 47.33975 +395.65123 58.49695 399.65325 60.17770 +395.71591 181.47663 397.34645 174.46613 +396.11719 882.66153 405.89893 888.69385 +396.68869 419.50786 397.13503 428.72918 +397.00371 47.33975 397.41115 35.52003 +397.13464 428.72965 397.13503 428.72918 +397.13503 428.72918 397.60602 438.45978 +397.13503 428.72918 405.38442 418.68681 +397.37418 59.22110 398.23374 71.21258 +397.60602 438.45978 398.73377 487.48373 +397.81860 132.72584 406.17389 128.03908 +397.88560 628.06295 398.14055 657.61227 +397.88560 628.06295 398.64966 600.29669 +397.88560 628.06295 411.53998 631.96718 +398.14055 657.61227 402.44528 688.55491 +398.23374 71.21258 398.67893 87.22844 +398.64966 600.29669 400.94259 563.61518 +398.64966 600.29669 407.07427 612.69485 +398.73361 487.48400 398.73377 487.48373 +398.73377 487.48373 399.28663 511.51703 +398.73377 487.48373 409.05296 470.04093 +399.28663 511.51703 400.94259 537.12284 +399.28663 511.51703 435.79751 504.13537 +399.65325 60.17770 405.76645 67.81978 +400.94259 537.12284 400.94259 563.61518 +400.94259 563.61518 415.52508 569.12530 +401.04349 189.70330 402.28199 184.20011 +401.04349 189.70330 402.96980 195.89352 +401.21756 942.19764 425.06112 946.17195 +401.78289 740.69849 401.78295 740.69880 +401.78295 740.69880 403.59367 750.12593 +401.78295 740.69880 408.37671 742.95445 +401.84066 211.17228 401.84066 211.17226 +401.84066 211.17226 403.24476 204.01005 +401.84066 211.17226 406.44116 212.84519 +402.44528 688.55491 404.56491 696.86938 +402.96980 195.89352 403.24476 204.01005 +403.48738 607.41502 411.53998 609.87432 +403.59367 750.12593 406.73230 759.13745 +404.56491 696.86938 418.42263 713.00925 +405.15490 115.40446 406.17389 128.03908 +405.15490 115.40446 412.28786 109.08639 +405.22422 0.00000 417.79259 1.09833 +405.38442 418.68681 409.05296 435.19330 +405.38442 418.68681 414.55461 411.96129 +405.76645 67.81978 410.04577 90.33857 +405.89893 888.69385 413.72432 896.03016 +406.44116 212.84519 423.40823 221.24670 +406.73230 759.13745 411.28889 773.11070 +407.07427 612.69485 414.12560 623.97619 +407.82986 452.31134 409.05296 435.19330 +407.82986 452.31134 409.05296 470.04093 +408.29276 309.68823 419.09426 299.33654 +408.37671 742.95445 421.80850 749.47356 +409.77696 839.18363 424.94408 844.10266 +409.86091 3.90499 421.20850 4.63670 +410.04577 90.33857 412.28786 109.08639 +411.28889 773.11070 414.32585 781.71709 +411.53998 609.87432 418.59131 615.75029 +411.53998 631.96718 418.12148 636.19797 +413.72432 896.03016 420.57153 901.41011 +414.12560 623.97619 423.68397 630.01237 +414.32585 781.71709 419.28758 793.36043 +414.55461 411.96129 423.11401 409.51586 +415.47193 464.84429 418.83469 443.75194 +415.52508 569.12530 424.62363 579.49317 +415.52508 569.12530 430.10988 570.39461 +417.79259 1.09833 429.87188 3.66083 +417.82494 668.93521 418.79310 696.22240 +417.82494 668.93521 420.27038 653.24361 +418.12148 636.19797 422.67468 636.88110 +418.42263 713.00925 418.79310 696.22240 +418.42263 713.00925 433.39793 714.22773 +418.42263 713.00925 434.39921 727.35605 +418.59131 615.75029 423.98975 622.57440 +418.83469 443.75194 421.28013 428.77433 +419.07192 219.09934 420.71556 211.96175 +419.09426 299.33654 423.82030 294.15992 +419.28758 793.36043 423.13481 800.95476 +419.55870 939.75221 427.20078 922.32839 +420.27038 653.24361 422.67468 636.88110 +420.57153 901.41011 427.97065 907.11869 +420.71556 211.96175 422.50400 205.35870 +421.20850 4.63670 427.92016 9.88340 +421.28013 428.77433 422.65517 414.33433 +421.40336 195.04089 422.50400 205.35870 +421.40336 195.04089 422.64187 182.10974 +421.80850 749.47356 424.75534 748.04019 +422.64187 182.10974 424.56741 171.79194 +422.65496 414.33433 422.65517 414.33433 +422.65517 414.33433 423.11401 409.51586 +422.65517 414.33433 433.20152 414.40673 +422.67468 636.88110 422.67499 636.88115 +422.67468 636.88110 423.68397 630.01237 +423.11401 409.51586 443.01638 406.36645 +423.13481 800.95476 425.56484 810.16885 +423.40823 221.24670 426.08088 212.51169 +423.40823 221.24670 446.46926 238.70672 +423.68397 630.01237 423.98975 622.57440 +423.68397 630.01237 432.45827 632.43701 +423.77101 717.81231 425.66651 723.13219 +423.82030 294.15992 429.89653 282.45803 +423.98975 622.57440 427.04673 613.60755 +424.35021 771.53099 425.05881 758.26711 +424.35021 771.53099 426.17254 775.98591 +424.56741 171.79194 428.28216 163.26257 +424.62363 579.49317 429.67163 589.43434 +424.75534 748.04019 424.87458 748.04563 +424.85624 747.02812 424.87458 748.04563 +424.85624 747.02812 425.66651 734.37117 +424.87458 748.04563 425.05881 758.26711 +424.87458 748.04563 426.98280 748.14186 +424.94404 844.10300 424.94408 844.10266 +424.94404 844.10300 427.50655 871.89160 +424.94408 844.10266 427.28627 826.24786 +424.94408 844.10266 432.39742 846.51994 +425.06112 946.17195 451.65512 951.06282 +425.56484 810.16885 427.99487 819.05867 +425.66651 723.13219 425.66651 734.37117 +426.08088 212.51169 433.50961 192.15181 +426.17254 775.98591 427.07775 784.10005 +426.98280 748.14186 431.94376 753.81141 +427.04673 613.60755 428.06573 600.87050 +427.07754 784.10013 427.07775 784.10005 +427.07775 784.10005 427.89397 791.41641 +427.07775 784.10005 435.08316 781.02851 +427.20078 922.32839 427.97065 907.11869 +427.28627 826.24786 427.99487 819.05867 +427.50655 871.89160 428.42311 898.17983 +427.55584 547.07095 427.75995 543.09741 +427.55584 547.07095 430.61283 554.30558 +427.75995 543.09741 430.51116 534.43633 +427.89397 791.41641 431.43773 803.56733 +427.92016 9.88340 438.53604 25.62430 +427.97065 907.11869 427.97099 907.11895 +427.97065 907.11869 428.42311 898.17983 +427.99487 819.05867 433.56430 815.61581 +428.06573 600.87050 430.15851 585.96853 +428.29987 606.95366 440.27210 612.55775 +429.17792 161.95398 433.04979 146.05827 +429.87188 3.66083 440.48776 7.07751 +429.89653 282.45803 437.32295 272.33124 +429.89653 282.45803 452.40124 286.70881 +430.00128 573.86905 430.61283 554.30558 +430.00128 573.86905 430.61283 582.73346 +430.12528 570.39461 430.27625 565.08321 +430.15840 585.96837 430.15851 585.96853 +430.15851 585.96853 430.61283 582.73346 +430.15851 585.96853 437.31910 596.84458 +430.27625 565.08321 442.18609 564.25831 +430.51116 534.43633 433.66981 527.81325 +431.43773 803.56733 433.05749 810.55318 +431.58715 152.06364 434.47623 161.95398 +431.94376 753.81141 439.23385 758.67147 +432.39742 846.51994 459.60297 853.24469 +432.45827 632.43701 445.85462 640.89859 +433.04979 146.05827 438.95965 112.22964 +433.05749 810.55318 433.56430 815.61581 +433.20152 414.40673 442.00740 423.23879 +433.39793 714.22773 433.74453 704.69092 +433.39793 714.22773 437.15889 713.99281 +433.50961 192.15181 437.08649 181.14620 +433.66981 527.81325 434.25518 523.29979 +433.74453 704.69092 435.57918 696.43729 +434.25518 523.29979 434.76506 512.85567 +434.39921 727.35605 458.20195 745.28898 +434.76506 512.85567 435.79751 504.13537 +435.08316 781.02851 440.55015 780.01568 +435.54991 131.74921 443.68955 138.22518 +435.57918 696.43729 436.49574 686.96133 +435.79751 504.13537 435.79792 504.13529 +435.79751 504.13537 437.05722 493.49553 +436.23540 230.95835 440.38763 218.56481 +436.49574 686.96133 438.32962 668.92597 +437.05722 493.49553 439.60510 478.72126 +437.08649 181.14620 437.46323 178.13257 +437.15889 713.99281 442.79918 711.40720 +437.31910 596.84458 440.28134 606.36676 +437.32295 272.33124 445.42484 264.00444 +437.46313 178.13235 437.46323 178.13257 +437.46323 178.13257 438.18713 172.34187 +437.46323 178.13257 440.80047 185.82372 +438.18713 172.34187 440.38763 160.23639 +438.47981 485.24883 448.07747 483.14460 +438.53604 25.62430 445.36862 39.16854 +438.95965 112.02630 438.95965 112.22964 +438.95965 112.02630 439.38943 111.47713 +438.95965 112.22964 441.27646 112.29664 +439.23385 758.67147 450.16937 764.34180 +439.35015 464.96521 439.46824 471.33667 +439.35015 464.96521 440.36915 455.54008 +439.38943 111.47713 440.85438 104.40039 +439.42486 197.79210 440.25054 193.39032 +439.42486 197.79210 440.25054 209.76048 +439.46800 471.33720 439.46824 471.33667 +439.46824 471.33667 439.60510 478.72126 +439.46824 471.33667 442.77915 463.98858 +440.25054 193.39032 440.80047 185.82372 +440.25054 209.76048 440.38763 218.56481 +440.27210 612.55775 440.28134 606.36676 +440.27210 612.55775 458.35830 623.25604 +440.36915 455.54008 441.64309 438.01460 +440.38763 160.23639 443.41458 150.19356 +440.48776 7.07751 450.37194 9.64002 +440.55015 780.01568 442.47415 780.01568 +440.85438 104.40039 444.39275 82.72961 +441.27646 112.29664 453.24869 119.42884 +441.64309 430.62746 441.64309 438.01460 +441.64309 430.62746 442.27277 417.87714 +442.18609 564.25831 453.61223 563.20080 +442.27235 417.87655 442.27277 417.87714 +442.27277 417.87714 442.66208 409.99416 +442.27277 417.87714 449.30057 427.63287 +442.66208 409.99416 444.09083 395.37932 +442.77915 463.98858 449.30057 458.68949 +442.79918 711.40720 457.77528 716.69312 +443.41458 150.19356 443.68955 138.22518 +444.09083 395.37932 451.57963 375.14037 +444.39275 82.72961 446.58864 55.64114 +445.36862 39.16854 446.58864 55.64114 +445.42484 264.00444 450.14626 257.59240 +445.85462 640.89859 460.42633 648.18406 +446.46926 238.70672 468.21244 257.81499 +448.07747 483.14460 453.57988 484.36694 +448.92393 241.94162 449.29055 250.50025 +449.29055 250.50025 450.14626 257.59240 +449.29287 345.38618 450.93650 353.27704 +449.29287 345.38618 452.58014 315.63353 +449.29287 345.38618 460.05278 340.06938 +449.30057 427.63287 453.57988 436.39561 +449.30057 458.68949 465.27715 454.31698 +450.14626 257.59240 450.39119 263.82806 +450.16937 764.34180 458.26973 767.07606 +450.39119 263.82806 451.59427 277.16820 +450.39581 26.96062 459.77011 40.81834 +450.44357 363.63258 450.93650 353.27704 +450.44357 363.63258 452.90903 366.75581 +451.57963 375.14037 456.91428 369.21295 +451.59427 277.16820 452.08721 280.94918 +451.65512 951.06282 471.83014 955.03636 +452.08721 280.94918 452.40124 286.70881 +452.40124 286.70881 452.40145 286.70885 +452.40124 286.70881 453.07308 299.03076 +452.58014 315.63353 453.07308 299.03076 +452.90903 366.75581 453.60530 372.88903 +453.24869 119.42884 468.53285 126.56103 +453.57988 436.39561 461.93518 448.82688 +453.57988 484.36694 460.71285 482.94050 +453.61223 563.20080 474.13694 561.93071 +456.91415 369.21279 456.91428 369.21295 +456.91428 369.21295 464.58472 378.84588 +456.91428 369.21295 467.97290 356.92555 +457.77525 716.69319 457.77528 716.69312 +457.77528 716.69312 461.56163 705.60748 +457.77528 716.69312 462.77703 718.45852 +458.20195 745.28898 470.26023 751.48172 +458.26973 767.07606 463.02889 773.25242 +458.35830 623.25604 475.67968 631.91711 +459.60297 853.24469 485.27964 862.10987 +459.77011 40.81834 466.69896 61.60414 +460.03352 654.25336 460.33853 663.11854 +460.03352 654.25336 464.20484 649.30955 +460.05278 340.06938 461.62787 329.04221 +460.05278 340.06938 470.85505 342.09505 +460.33853 663.11854 461.86740 677.79115 +460.42633 648.18406 464.20484 649.30955 +460.53031 183.34594 460.53031 216.01771 +460.53031 183.34594 462.19474 157.33345 +460.53031 216.01771 462.19474 234.74704 +460.59116 251.11720 462.19474 234.74704 +460.71285 482.94050 468.65993 480.08762 +460.94623 124.45372 462.19474 157.33345 +461.00399 989.20004 467.73876 969.46019 +461.56163 705.60748 463.08973 692.76953 +461.62787 329.04221 467.47919 316.43994 +461.86740 677.79115 463.08973 692.76953 +461.93518 448.82688 463.13447 450.79703 +462.77703 718.45852 473.11794 724.56941 +463.02889 773.25242 468.09074 774.95306 +463.13441 450.79710 463.13447 450.79703 +463.13447 450.79703 468.67536 459.89938 +463.13447 450.79703 470.02833 443.42566 +464.20484 649.30955 464.20501 649.30935 +464.20484 649.30955 471.47276 651.47442 +464.58472 378.84588 470.69792 400.44734 +466.69896 61.60414 474.03527 80.35273 +466.82605 412.67451 468.04915 425.30990 +467.47919 316.43994 475.13051 306.31238 +467.73876 969.46019 474.79239 955.43841 +467.97290 356.92555 486.59286 338.71072 +468.04915 425.30990 468.51301 428.91791 +468.09074 774.95306 473.45761 775.25729 +468.21244 257.81499 481.71971 270.66296 +468.51282 428.91836 468.51301 428.91791 +468.51301 428.91791 469.27148 427.14378 +468.51301 428.91791 469.88304 439.57429 +468.53285 126.56103 477.44886 131.91095 +468.65993 480.08762 476.92582 476.56622 +468.67534 459.89950 468.67536 459.89938 +468.67536 459.89938 470.29048 450.37502 +468.67536 459.89938 470.49459 462.88794 +469.27148 427.14378 470.69792 425.10579 +469.88304 439.57429 470.02833 443.42566 +469.97546 751.45378 470.26023 751.48172 +469.97546 751.45378 470.26583 751.48459 +470.02833 443.42566 470.02861 443.42536 +470.02833 443.42566 470.29048 450.37502 +470.26023 751.48172 470.26583 751.48459 +470.26023 751.48172 479.37363 752.37573 +470.49459 462.88794 475.58879 473.89201 +470.69792 400.44734 470.90203 416.75049 +470.69792 425.10579 470.90203 416.75049 +470.85505 342.09505 477.36876 347.73380 +471.33489 129.61802 479.23191 147.44928 +471.47276 651.47442 486.40697 656.51770 +471.83014 955.03636 489.86473 957.48180 +473.11794 724.56941 481.34153 736.21507 +473.45761 775.25729 477.10226 774.44702 +474.03527 80.35273 480.14847 92.57990 +474.13694 561.93071 491.20645 563.25471 +475.13051 306.31238 479.40675 296.63539 +475.13590 858.60770 478.83294 876.89030 +475.58879 473.89201 476.92582 476.56622 +475.67968 631.91711 483.57670 633.95510 +476.92582 476.56622 476.92589 476.56619 +476.92582 476.56622 481.90610 486.52739 +477.36876 347.73380 477.37646 347.72609 +477.44886 131.91095 492.70101 134.19842 +477.99803 815.63121 498.14224 806.39941 +478.83294 876.89030 484.23831 893.44454 +479.23191 147.44928 489.77799 171.06409 +479.37363 752.37573 480.64757 741.24843 +479.37363 752.37573 485.07939 756.28842 +479.40675 296.63539 481.88222 286.73350 +480.14847 92.57990 489.11532 104.39962 +480.64757 741.24843 481.86990 732.38402 +481.71971 270.66296 481.88222 286.73350 +481.71971 270.66296 488.80338 280.87601 +481.71971 270.66296 490.18514 244.24842 +481.86990 732.38402 485.23266 710.98666 +481.90610 486.52739 500.62459 506.77707 +483.57670 633.95510 484.31533 649.85081 +483.57670 633.95510 484.45628 615.14105 +483.57670 633.95510 494.02082 637.77614 +484.23831 893.44454 489.13765 907.80367 +484.31533 649.85081 486.40697 656.51770 +484.45628 615.14105 486.29016 600.10182 +485.03240 308.11314 490.65883 299.11086 +485.07939 756.28842 489.15537 757.75568 +485.23266 710.98666 487.98387 684.69767 +485.27964 862.10987 524.40659 874.03126 +485.64626 605.38550 500.48832 606.91746 +486.29016 600.10182 489.17847 581.80612 +486.40697 656.51770 486.40724 656.51779 +486.40697 656.51770 489.20620 665.43997 +486.59286 338.71072 517.15270 318.26920 +487.77976 797.29007 488.69709 809.21147 +487.77976 797.29007 490.22520 778.03238 +487.98387 684.69767 489.20620 665.43997 +487.98387 684.69767 494.09707 690.81164 +488.15563 862.98560 491.78411 842.46937 +488.35126 171.64945 489.77799 171.06409 +488.80338 280.87601 496.05111 289.11193 +489.11532 104.39962 492.70101 134.19842 +489.13765 907.80367 493.86754 927.06137 +489.15537 757.75568 493.89373 757.85735 +489.17847 581.80612 490.46627 570.98768 +489.77799 171.06409 490.94920 173.68667 +489.77799 171.06409 504.24620 165.12803 +489.86473 957.48180 501.48112 958.09335 +490.18514 244.24842 496.29911 223.86929 +490.22520 778.03238 493.89373 757.85735 +490.46627 570.98768 491.52609 559.91737 +490.65883 299.11086 494.52223 287.37586 +490.94920 173.68667 496.55329 197.12278 +491.52609 559.91737 496.48782 525.80530 +491.52609 559.91737 504.41719 563.55279 +491.78411 842.46937 494.35201 820.21631 +491.80491 688.51871 498.98794 689.58854 +492.70101 134.19842 492.73225 134.20311 +492.70101 134.19842 492.73225 134.45805 +492.73225 134.20311 492.73225 134.45805 +492.73225 134.45805 496.04417 149.64054 +493.86754 927.06137 498.76689 943.61638 +493.89373 757.85735 494.52561 755.54427 +494.02082 637.77614 506.24799 649.74837 +494.09707 690.81164 497.45983 702.12148 +494.35201 820.21631 498.14224 806.39941 +494.52531 755.54440 494.52561 755.54427 +494.52561 755.54427 498.09680 742.47153 +494.52561 755.54427 504.80614 751.23427 +495.63673 149.64054 496.04417 149.64054 +496.05111 289.11193 497.47715 280.85518 +496.05111 289.11193 499.83980 305.74935 +496.29911 223.86929 496.55329 197.12278 +496.48782 525.80530 500.62459 506.77707 +497.47677 280.85522 497.47715 280.85518 +497.47715 280.85518 499.02876 271.87142 +497.47715 280.85518 507.88359 279.77156 +498.09680 742.47153 499.62491 730.24436 +498.14224 806.39941 500.09859 799.42973 +498.14224 806.39941 514.06799 806.46026 +498.76689 943.61638 501.48112 958.09335 +498.98794 689.58854 507.32765 694.73578 +499.02876 271.87142 500.68587 259.21724 +499.62491 730.24436 503.19100 713.17715 +499.83980 305.74935 522.34857 319.57780 +500.09859 799.42973 506.45672 783.77895 +500.48832 606.91746 511.08571 608.05892 +500.62459 506.77707 500.62464 506.77713 +500.62459 506.77707 502.69036 497.27498 +500.68549 259.21678 500.68587 259.21724 +500.68587 259.21724 501.31784 254.39138 +500.68587 259.21724 505.96147 265.57953 +501.13915 414.59928 504.24081 445.92086 +501.13915 414.59928 508.89214 388.86022 +501.31784 254.39138 503.85201 244.00992 +501.48112 958.09335 511.56787 958.09335 +502.69036 497.27498 510.13295 476.18725 +503.19100 713.17715 507.32765 694.73578 +503.85185 244.00965 503.85201 244.00992 +503.85201 244.00992 507.76916 227.96298 +503.85201 244.00992 509.78790 253.87688 +504.24081 445.92086 507.96172 453.36345 +504.24620 165.12803 522.17989 163.49749 +504.41719 563.55279 516.64436 562.32969 +504.80614 751.23427 512.14245 747.48486 +505.96147 265.57953 507.88359 279.77156 +506.24799 649.74837 515.41817 658.91933 +506.45672 783.77895 511.22589 768.61726 +507.32765 694.73578 507.32783 694.73589 +507.32765 694.73578 509.30497 685.92077 +507.76916 227.96298 514.42768 200.70120 +507.88359 279.77156 507.88393 279.77152 +507.88359 279.77156 508.88752 287.18408 +507.96172 453.36345 513.23384 462.35649 +508.88752 287.18408 513.61356 304.96219 +508.89214 388.86022 516.93637 364.17947 +509.30497 685.92077 516.43717 665.79658 +509.46980 58.85833 526.58784 57.32945 +509.78790 253.87688 512.71318 266.25501 +510.13295 476.18725 513.23384 462.35649 +510.13295 476.18725 519.05975 500.08318 +511.08571 608.05892 522.11597 603.09796 +511.22589 768.61726 515.26028 754.18959 +511.56787 958.09335 525.01814 965.12387 +511.83128 164.43869 517.96605 176.97780 +512.14245 747.48486 521.72337 742.71558 +512.71318 266.25501 512.93808 277.28219 +512.93808 277.28219 513.16298 284.93351 +513.16298 284.93351 519.46489 291.45954 +513.23384 462.35649 518.45898 443.99763 +513.61356 304.96219 516.35553 315.89540 +514.06799 806.46026 526.29593 809.51724 +514.42768 200.70120 517.96605 176.97780 +515.26028 754.18959 517.46155 746.48589 +515.26028 754.18959 522.88772 749.16624 +515.41817 658.91933 516.43717 665.79658 +515.41817 658.91933 524.53128 665.21655 +516.64436 562.32969 527.00683 561.52481 +516.93627 364.17944 516.93637 364.17947 +516.93637 364.17947 522.53727 346.99516 +516.93637 364.17947 525.44561 366.42846 +517.46155 746.48589 521.72337 742.71558 +518.45898 443.99763 522.40018 434.73502 +518.65308 661.15449 523.95524 657.39969 +519.05975 500.08318 526.70106 525.76063 +519.46489 291.45954 526.21582 308.33804 +521.72337 742.71558 521.72470 742.71492 +521.72337 742.71558 526.99836 738.04895 +522.11597 603.09796 523.03406 606.40450 +522.11597 603.09796 524.56140 582.92294 +522.17989 163.49749 540.52027 165.20968 +522.34857 319.57780 529.65249 325.68648 +522.40018 434.73502 526.34214 425.07806 +522.53727 346.99516 529.65249 325.68648 +522.88772 749.16624 533.21477 751.80808 +523.03406 606.40450 525.67436 610.87329 +523.39144 649.74452 524.53128 665.21655 +523.39144 649.74452 526.75420 628.24935 +524.40659 874.03126 539.69074 880.45024 +524.53128 665.21655 524.53136 665.21661 +524.53128 665.21655 528.22146 715.30680 +524.56140 582.92294 527.00683 561.52481 +525.01814 965.12387 536.24236 969.28068 +525.44561 366.42846 533.63377 365.56120 +525.67436 610.87329 529.93982 616.66223 +526.29593 809.51724 537.05122 813.37798 +526.34214 425.07806 528.31235 413.84524 +526.37988 335.48737 531.85996 346.64240 +526.58784 57.32945 534.84147 57.02367 +526.70106 525.76063 527.00683 561.52481 +526.75420 628.24935 531.66664 625.59981 +526.99836 738.04895 528.95471 727.04488 +527.52442 405.17338 528.31235 413.84524 +527.52442 405.17338 529.88898 399.06403 +528.22146 715.30680 528.47058 719.29474 +528.47024 719.29498 528.47058 719.29474 +528.47058 719.29474 528.95471 727.04488 +528.47058 719.29474 540.08740 711.14918 +529.65249 325.68648 529.65252 325.68638 +529.65249 325.68648 539.16083 333.63885 +529.88898 399.06403 532.25431 382.31262 +529.88898 399.06403 534.66663 405.91202 +529.93982 616.66223 532.68255 620.01343 +531.55419 277.08809 531.96163 254.67174 +531.55419 277.08809 533.79551 295.22513 +531.66664 625.59981 532.68255 620.01343 +531.85996 346.64240 532.00810 348.22246 +531.96163 254.67174 532.98063 230.21740 +532.00784 348.22211 532.00810 348.22246 +532.00810 348.22246 533.63377 365.56120 +532.00810 348.22246 537.92695 355.98434 +532.04867 995.38641 536.24236 969.28068 +532.25431 382.31262 532.91154 374.33159 +532.68255 620.01343 547.81652 618.76568 +532.91131 374.33165 532.91154 374.33159 +532.91154 374.33159 533.63377 365.56120 +532.91154 374.33159 540.78060 372.28749 +532.98063 230.21740 538.89049 202.70607 +533.21477 751.80808 542.58136 756.37084 +533.79551 295.22513 536.03684 319.06869 +534.66663 405.91202 536.90872 423.03006 +534.84147 57.02367 558.21520 61.07423 +536.03684 319.06869 538.07483 326.60833 +536.24236 969.28068 536.24249 969.28073 +536.24236 969.28068 539.01068 952.04785 +536.24249 969.28073 549.47248 968.18086 +536.90872 423.03006 539.35416 431.38536 +537.05044 813.37833 537.05122 813.37798 +537.05122 813.37798 538.21732 813.79656 +537.05122 813.37798 545.07455 809.76217 +537.92695 355.98434 541.90126 364.33964 +538.07483 326.60833 539.16083 333.63885 +538.89049 202.70607 541.53926 184.56904 +539.01064 952.04793 539.01068 952.04785 +539.01068 952.04785 543.19599 943.64102 +539.01068 952.04785 544.27584 919.27218 +539.16083 333.63885 558.11353 350.14611 +539.35416 431.38536 545.67147 442.79764 +539.69074 880.45024 549.53718 882.12236 +540.08740 711.14918 552.76053 706.65805 +540.52027 165.20968 541.53926 184.56904 +540.52027 165.20968 563.51351 166.43201 +540.78060 372.28749 545.67147 373.50983 +541.90126 364.33964 542.00293 371.98172 +542.58136 756.37084 551.70687 759.01268 +543.19599 943.64102 544.49997 935.48906 +544.27584 919.27218 548.06607 881.87283 +544.49997 935.48906 544.93822 930.78613 +544.93822 930.78613 545.75311 924.57049 +545.07455 809.76217 550.12870 809.10980 +545.67147 373.50983 550.86811 371.98172 +545.67147 442.79764 548.32024 455.22815 +545.75311 924.57049 548.30098 910.71277 +547.81652 618.76568 564.01800 623.65655 +548.30098 910.71277 550.64398 894.40962 +548.32024 455.22815 554.84165 469.69741 +548.58211 341.84396 549.24835 333.37390 +549.04501 313.81043 549.24835 333.37390 +549.04501 313.81043 549.99028 291.90473 +549.47248 968.18086 564.14508 970.62629 +549.53718 882.12237 549.53718 882.12236 +549.53718 882.12236 550.71561 866.87057 +549.53718 882.12236 552.47329 882.62098 +549.71510 298.29135 586.98351 327.74978 +549.99006 291.90473 549.99028 291.90473 +549.99028 291.90473 550.26734 285.48421 +549.99028 291.90473 570.27369 292.29061 +550.12870 809.10980 558.46008 810.90516 +550.26734 285.48421 552.71278 274.27604 +550.64398 894.40962 552.47324 882.62147 +550.71561 866.87057 554.87246 838.50353 +550.86811 371.98172 559.83419 367.90574 +551.70687 759.01268 556.99055 759.97313 +552.47324 882.62147 552.47329 882.62098 +552.47329 882.62098 554.38337 863.44696 +552.47329 882.62098 555.89146 883.20145 +552.71278 274.27604 555.76976 259.60343 +552.76053 706.65805 558.69581 705.21390 +554.38337 863.44696 556.46218 848.40696 +554.87246 838.50353 557.68529 817.10541 +555.15821 97.14497 555.56565 79.82282 +555.15821 97.14497 560.45652 107.53748 +555.24216 93.60274 582.12037 99.70439 +555.56565 79.82282 558.21520 61.07423 +555.76976 259.60343 556.99286 240.85485 +555.89146 883.20145 572.09294 886.56421 +556.46218 848.40696 558.78515 831.28892 +556.99055 759.97313 564.98077 759.58803 +556.99286 240.85485 560.25319 215.38151 +557.68529 817.10541 558.46008 810.90516 +558.11353 350.14611 568.68619 356.93258 +558.21520 61.07423 587.50957 66.30169 +558.46008 810.90516 558.46012 810.90517 +558.46008 810.90516 558.90762 807.32367 +558.66346 831.28892 558.78515 831.28892 +558.69581 705.21390 570.74044 712.17664 +558.90762 807.32367 564.53250 763.28121 +559.83419 367.90574 564.92916 361.79254 +560.25319 215.38151 565.55150 196.38877 +560.45652 107.53748 560.86474 119.96876 +560.86474 119.96876 564.93995 139.93968 +563.51351 166.43201 564.73661 188.03347 +563.51351 166.43201 564.93995 139.93968 +564.01800 623.65655 572.88241 633.13251 +564.14508 970.62629 574.23260 971.84862 +564.53250 763.28121 572.32169 699.16000 +564.53250 763.28121 574.28266 769.33973 +564.73661 188.03347 565.55150 196.38877 +564.92916 361.79254 568.68619 356.93258 +564.93995 139.93968 568.02774 133.06242 +568.02774 133.06242 572.91861 129.96462 +568.68619 356.93258 568.68627 356.93248 +568.68619 356.93258 581.44720 365.12372 +570.27369 292.29061 585.35374 291.88316 +572.09294 886.56421 583.40278 888.39809 +572.32169 699.16000 573.85057 685.40473 +572.88241 633.13251 576.24517 648.11089 +572.91861 129.96462 575.89395 129.88297 +573.85057 685.40473 575.09925 663.68694 +574.23260 971.84862 576.98381 973.37750 +574.28266 769.33973 594.93599 780.62723 +575.09909 663.68696 575.09925 663.68694 +575.09925 663.68694 575.35326 659.26900 +575.09925 663.68694 592.75166 660.94961 +575.35326 659.26900 576.24517 648.11089 +575.65903 1000.00000 587.27465 912.57515 +575.89395 129.88297 578.33938 118.26735 +578.33938 118.26735 581.50651 102.71901 +581.44720 365.12372 604.88255 372.76580 +581.50651 102.71901 581.50651 102.71901 +581.50651 102.71901 585.06414 85.25361 +581.50651 102.71901 622.58210 122.16618 +583.40278 888.39809 589.51675 892.06663 +585.06414 85.25361 587.50957 66.30169 +585.35374 291.88316 601.65612 297.18147 +586.98351 327.74978 608.23915 357.13196 +587.27465 912.57515 594.61096 856.33017 +587.50957 66.30169 617.86684 68.08088 +591.35063 887.17576 598.38116 893.59473 +592.75166 660.94961 603.75649 661.56039 +594.61096 856.33017 601.33648 787.24646 +594.93599 780.62723 608.86533 788.07214 +598.38116 893.59473 616.72230 899.40293 +599.52647 579.99304 623.79904 583.48905 +601.65612 297.18147 612.59459 298.80738 +603.75649 661.56039 617.81755 661.56039 +604.88255 372.76580 606.97987 373.15530 +606.97985 373.15553 606.97987 373.15530 +606.97987 373.15530 610.18086 332.43655 +606.97987 373.15530 640.54507 379.38888 +608.86533 788.07214 622.79468 797.67826 +609.74569 897.19318 609.92207 897.24941 +609.74569 897.19318 613.15543 870.39970 +610.18086 332.43655 612.59459 298.80738 +612.59459 298.80738 612.59472 298.80740 +612.59459 298.80738 613.23785 289.84517 +613.23785 289.84517 615.27584 271.70814 +614.51024 709.59180 615.90356 684.74234 +615.27584 271.70814 618.12872 230.01329 +615.88662 60.95254 618.94360 71.95661 +615.90356 684.74234 618.45760 674.75650 +616.72230 899.40293 637.20233 900.62526 +617.81755 661.25462 618.45760 674.75650 +617.81755 661.25462 619.61908 634.58052 +617.81755 661.56039 617.81755 661.25462 +618.12872 230.01329 619.75849 188.64502 +618.92204 496.44854 620.31536 488.08785 +618.92204 496.44854 623.56721 523.15499 +618.94360 71.95661 620.77749 87.44487 +619.61908 634.58052 621.24501 596.49413 +619.75849 188.64502 621.38904 171.73032 +620.08352 488.08785 620.31536 488.08785 +620.77749 87.44487 623.01958 115.28200 +621.24501 596.49413 623.79904 583.48905 +621.38904 171.73032 622.40803 147.07264 +622.20393 128.11995 622.40803 147.07264 +622.20393 128.11995 623.01958 115.28200 +622.79468 797.67826 625.67683 802.72163 +623.56721 523.15499 625.88941 538.48228 +623.79904 583.48905 626.58568 557.75769 +625.67683 802.72163 625.91713 802.96194 +625.88941 538.48228 626.58568 557.75769 +637.20233 900.62526 657.68313 901.54259 diff --git a/LICENSE b/LICENSE index e18140a..8bb1439 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,8 @@ MIT License -Copyright (c) 2021 MakeLikePaperrr +Copyright (c) 2021 Stephan de Hoop S.dehoop-1@tudelft.nl + Denis Voskov D.V.Voskov@tudelft.nl + Delft University of Technology, the Netherlands Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/calc_intersections_segm.py b/calc_intersections_segm.py new file mode 100644 index 0000000..8428243 --- /dev/null +++ b/calc_intersections_segm.py @@ -0,0 +1,141 @@ +""" +This file describes the function calc_intersections_segm, which is called in the main cleaning function. This +function finds the intersections of the fractures in act_frac_sys, and splits these fractures at the intersection +points. The list act_frac_sys is then returned with the updated fractures. + +Author: Ole de Koning + +Last updated: 12/12/2020 by Ole de Koning +""" + +import numpy as np +import time +from find_parametric_intersect import find_parametric_intersect + + +def calc_intersections_segm(act_frac_sys,frac_order_vec, tolerance_intersect, tolerance_zero): + """ + :param act_frac_sys: A list where all rows describe a fracture in the system, and the four columns + describe the following: Column 0 = X value of the start of a fracture + Column 1 = Y value of the start of a fracture + Column 2 = X value of the end of a fracture + Column 3 = Y value of the end of a fracture + + :param frac_set_vec: This is a list where groups of fractures are defined that are close to each other. + + :param frac_order_vec: Array of order identifiers of the fractures, determined in change_order_discr. + :param tolerance_intersect: A value that was set to determine whether two fractures intersect of not. + If t and s, the parametric distances along fracture 1 and 2 respectively are + smaller than this tolerance, it is counted as an intersection. + + :param tolerance_zero: This tolerance is used to check whether a segment is non-zero. In this case, the + length of the segment must be larger than this value. + + :return: act_frac_sys: This returned matrix is similar to the input act_frac_sys, except that it now takes + all intersection into account. + + :return: frac_set_vec: This returned matrix is similar to the input frac_set_vec, except that it now takes + all intersection into account. The groups formed in this list will thus differ from the + ones in the input. + """ + + # Allocate large array for new points: + n_fracs = act_frac_sys.shape[0] + max_new_pts = 10000 + max_length_new_segm = n_fracs + max_new_pts * 2 + + # Segment list global: + new_frac_order_vec = np.zeros(max_length_new_segm*2) + new_points = np.zeros((max_new_pts, 2)) + ith_jj = np.zeros(max_new_pts) + new_fract_sys = np.zeros((max_length_new_segm, 4)) + + ith_pt = -1 + glob_segm_count = 0 + + for ii in range(0, n_fracs): + + # Obtaining the x and y coords of the start and end of the frac + ith_old = ith_pt + 1 + ii_frac = act_frac_sys[ii, :] + + for jj in range(ii+1, n_fracs): + jj_frac = act_frac_sys[jj, :] + + if np.min(jj_frac[[0, 2]]) > np.max(ii_frac[[0, 2]]) or np.max(jj_frac[[0, 2]]) < np.min(ii_frac[[0, 2]]): + continue + elif np.min(jj_frac[[1, 3]]) > np.max(ii_frac[[1, 3]]) or np.max(jj_frac[[1, 3]]) < np.min(ii_frac[[1, 3]]): + continue + + # Only store intersections of segments that don't already share a node: + if not (np.linalg.norm(ii_frac[:2] - jj_frac[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[:2] - jj_frac[2:]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_frac[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_frac[2:]) < tolerance_intersect): + + t, s, int_coord = find_parametric_intersect(ii_frac, jj_frac) + + if (t >= (0 - tolerance_intersect) and t <= (1 + tolerance_intersect)) and \ + (s >= (0 - tolerance_intersect) and s <= (1 + tolerance_intersect)): + + ith_pt = ith_pt + 1 + new_points[ith_pt, :] = int_coord + ith_jj[ith_pt] = jj + + if ii != 0: + prev_jj_int = new_points[np.where(ith_jj == ii), :][0] + else: + prev_jj_int = np.zeros((0, 2)) + + new_ii_int = new_points[ith_old:ith_pt+1, :] + + num_prev_int = prev_jj_int.shape[0] + num_new_int = new_ii_int.shape[0] + + # Check if there even are fractures. If not, we go on to the next fracture ii. + if num_prev_int == 0 and num_new_int == 0: + glob_segm_count += 1 + new_fract_sys[glob_segm_count:(glob_segm_count + 1), :] = ii_frac + new_frac_order_vec[glob_segm_count: (glob_segm_count + 1)] = frac_order_vec[ii] + glob_segm_count += 1 + continue + + tot_new_pts = 2 + num_new_int + num_prev_int + + tot_loc_pts_list = np.zeros((tot_new_pts, 2)) + tot_loc_pts_list[0, :] = act_frac_sys[ii, :2] + tot_loc_pts_list[-1, :] = act_frac_sys[ii, 2:] + tot_loc_pts_list[1:num_prev_int+1, :] = prev_jj_int + tot_loc_pts_list[num_prev_int+1:num_new_int+num_prev_int+1, :] = new_ii_int + + tot_loc_pts_list = tot_loc_pts_list[np.lexsort((tot_loc_pts_list[:, 1], tot_loc_pts_list[:, 0]))] + + tot_new_segm = tot_loc_pts_list.shape[0] - 1 + # Now, we have an array with all x and y value of the points where the fracture ii should be split at. + tot_loc_segm_list = np.zeros((tot_new_segm, 4)) + for mm in range(0, tot_new_segm): + tot_loc_segm_list[mm, :] = [tot_loc_pts_list[mm, 0], + tot_loc_pts_list[mm, 1], + tot_loc_pts_list[mm + 1, 0], + tot_loc_pts_list[mm + 1, 1]] + + new_fract_sys[glob_segm_count:(glob_segm_count + tot_new_segm), :] = tot_loc_segm_list + + new_frac_order_vec[glob_segm_count: (glob_segm_count + tot_new_segm)] = frac_order_vec[ii] + + glob_segm_count += tot_new_segm + + act_frac_sys = new_fract_sys[:glob_segm_count, :] + new_frac_order_vec = new_frac_order_vec[:glob_segm_count] + + # Determine length of new "main" segments: + len_segm_new = np.sqrt((act_frac_sys[:, 0] - act_frac_sys[:, 2])*(act_frac_sys[:, 0] - act_frac_sys[:, 2]) + + (act_frac_sys[:, 1] - act_frac_sys[:, 3])*(act_frac_sys[:, 1] - act_frac_sys[:, 3])) + + # Remove non-zero fracture segments: This comment does not make sense, probably meant the opposite + nonzero_segm = np.where(len_segm_new > tolerance_zero)[0] + act_frac_sys = act_frac_sys[nonzero_segm, :] + + frac_order_vec = new_frac_order_vec[nonzero_segm] + + return act_frac_sys, frac_order_vec diff --git a/calc_intersections_segm_parallel.py b/calc_intersections_segm_parallel.py new file mode 100644 index 0000000..d5bdfeb --- /dev/null +++ b/calc_intersections_segm_parallel.py @@ -0,0 +1,62 @@ +from calc_intersections_segm import calc_intersections_segm +from partition_domain import partition_domain +from merge_domain import merge_domain + +import numpy as np +import multiprocessing as mp + + +def calc_intersections_worker(partition, send_end, act_frac_sys, frac_order_vec, tolerance_intersect, tolerance_zero): + act_frac_sys, frac_order_vec = calc_intersections_segm(act_frac_sys, frac_order_vec, tolerance_intersect, tolerance_zero) + send_end.send((act_frac_sys, frac_order_vec)) + + +def calc_intersections_segm_parallel(act_frac_sys, frac_order_vec, tolerance_intersect, tolerance_zero, number_partitions_x, number_partitions_y): + """ + + :param act_frac_sys: + :param frac_set_vec: + :param tolerance_intersect: + :param tolerance_zero: + :param number_partitions_x: + :param number_partitions_y: + :return: + """ + number_partitions = number_partitions_x * number_partitions_y + + if number_partitions > 1: + act_frac_sys_list, frac_order_vec_list, partition_lines = partition_domain(act_frac_sys, frac_order_vec, + tolerance_intersect, number_partitions_x, + number_partitions_y) + + jobs = [] + pipe_list = [] + for partition in range(number_partitions): + recv_end, send_end = mp.Pipe(False) + p = mp.Process(target=calc_intersections_worker, args=(partition, + send_end, + act_frac_sys_list[partition], + frac_order_vec_list[partition], + tolerance_intersect, + tolerance_zero,)) + jobs.append(p) + pipe_list.append(recv_end) + p.start() + + act_frac_sys_list = [] + frac_order_vec_list = [] + for p in pipe_list: + recv = p.recv() + act_frac_sys_list.append(recv[0]) + frac_order_vec_list.append(recv[1]) + + for p in jobs: + p.join() + + for p in jobs: + p.terminate() + + return act_frac_sys_list, frac_order_vec_list, partition_lines + else: + act_frac_sys, frac_order_vec = calc_intersections_segm(act_frac_sys, frac_order_vec, tolerance_intersect, tolerance_zero) + return [act_frac_sys], [frac_order_vec], [] \ No newline at end of file diff --git a/cleaning_methods.py b/cleaning_methods.py new file mode 100644 index 0000000..367eb4a --- /dev/null +++ b/cleaning_methods.py @@ -0,0 +1,603 @@ +""" +MIT License + +Copyright (c) 2021 Stephan de Hoop S.dehoop-1@tudelft.nl + Denis Voskov D.V.Voskov@tudelft.nl + Delft University of Technology, the Netherlands + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" +import numpy as np +import sys +from itertools import combinations +# from numba import jit +import os +from scipy import sparse +from scipy.sparse import csr_matrix + + +# @jit(nopython=True) +def segment_large_fracture(act_frac_sys, char_len, length_segms, order_discr, decimals): + # Perform partitioning into smaller subsegments (around lc size): + num_new_segms = int(np.sum(np.round(length_segms / char_len)) + np.sum(np.round(length_segms / char_len) == 0)) + act_frac_sys_new = np.zeros((num_new_segms, 4)) + order_discr_new = np.zeros((num_new_segms,)) + ith_segm = 0 + + for ii in order_discr: + size_segm = int(max(1, np.round(length_segms[ii] / char_len))) + id_vec = np.arange(0, size_segm) + act_frac_sys_new[ith_segm:(ith_segm + size_segm), 0] = act_frac_sys[ii, 0] + id_vec / size_segm * ( + act_frac_sys[ii, 2] - act_frac_sys[ii, 0]) + act_frac_sys_new[ith_segm:(ith_segm + size_segm), 1] = act_frac_sys[ii, 1] + id_vec / size_segm * ( + act_frac_sys[ii, 3] - act_frac_sys[ii, 1]) + act_frac_sys_new[ith_segm:(ith_segm + size_segm), 2] = act_frac_sys[ii, 0] + (id_vec + 1) / size_segm * ( + act_frac_sys[ii, 2] - act_frac_sys[ii, 0]) + act_frac_sys_new[ith_segm:(ith_segm + size_segm), 3] = act_frac_sys[ii, 1] + (id_vec + 1) / size_segm * ( + act_frac_sys[ii, 3] - act_frac_sys[ii, 1]) + + # Update order of fractures: + order_discr_new[ith_segm:(ith_segm + size_segm)] = np.arange(0, size_segm) + ith_segm + + ith_segm += size_segm + + act_frac_sys_new = np.round(act_frac_sys_new * 10 ** decimals) * 10 ** (-decimals) + return act_frac_sys_new, order_discr_new + + +# @jit(nopython=True) +def create_graph(act_frac_sys_new, unique_nodes, order_discr_new, tolerance_zero, full_graph=False): + # Store for each node to which segments it belongs and what its degree is: + num_unq_nodes = unique_nodes.shape[0] + num_segm_small = act_frac_sys_new.shape[0] + incidence_matrix = np.zeros((num_segm_small * 2, 2), dtype=int) + order_discr_nodes = np.ones((num_unq_nodes,), dtype=int) * (num_unq_nodes + 1) + non_zero_count = 0 + + for ii in range(num_unq_nodes): + # Determine which segments the node belongs to (check unique both verses left en right node of each segment): + ids_1, = np.where(((act_frac_sys_new[:, 0] - unique_nodes[ii, 0]) ** 2 + + (act_frac_sys_new[:, 1] - unique_nodes[ii, 1]) ** 2) ** (1/2) < tolerance_zero) + ids_2, = np.where(((act_frac_sys_new[:, 2] - unique_nodes[ii, 0]) ** 2 + + (act_frac_sys_new[:, 3] - unique_nodes[ii, 1]) ** 2) ** (1/2) < tolerance_zero) + connected_segms = np.union1d(ids_1, ids_2) + + # Store each nonzero entry: + for jj in connected_segms: + incidence_matrix[non_zero_count, :] = [ii, jj] + non_zero_count += 1 + + # Determine order of node: + order_discr_nodes[ii] = int(np.min(np.append(order_discr_new[ids_1], order_discr_new[ids_2]))) + + order_discr_nodes_new = np.argsort(order_discr_nodes) + + if full_graph: + # Translate incidence matrix to sparse matrix: + unique, node_degrees = np.unique(incidence_matrix[:, 0], return_counts=True) + degree_matrix = sparse.diags(node_degrees) + incidence_matrix_csr = csr_matrix((np.ones((incidence_matrix.shape[0])), (incidence_matrix[:, 0], incidence_matrix[:, 1]))) + adjacency_matrix_csr = np.dot(incidence_matrix_csr, incidence_matrix_csr.T) - degree_matrix + laplacian_matrix = degree_matrix - adjacency_matrix_csr + return incidence_matrix, order_discr_nodes_new, degree_matrix, adjacency_matrix_csr, laplacian_matrix + else: + return incidence_matrix, order_discr_nodes_new + +def reorder_incidence_and_nodes(incidence_matrix, unique_nodes, order_discr): + incidence_matrix = incidence_matrix[np.where(incidence_matrix[:, 0] != -99999)[0], :] + + unique_node_list = np.unique(incidence_matrix[:, 0]) + unique_segm_list = np.unique(incidence_matrix[:, 1]) + + node_mapping = np.ones((unique_node_list.shape[0],), dtype=int) * (-1) + segm_mapping = np.ones((unique_segm_list.shape[0],), dtype=int) * (-1) + + incidence_matrix_new = np.zeros((incidence_matrix.shape[0], 2), dtype=int) + node_counter = 0 + segm_counter = 0 + + for ii, row in enumerate(incidence_matrix): + # if not np.equal(row, incidence_matrix_new).all(axis=1).any(): + # # The + if row[0] not in node_mapping: + node_mapping[node_counter] = row[0] + node_counter += 1 + + if row[1] not in segm_mapping: + segm_mapping[segm_counter] = row[1] + segm_counter += 1 + + # Add entry to the incidence list: + incidence_matrix_new[ii, :] = [np.where(node_mapping == row[0])[0][0], np.where(segm_mapping == row[1])[0][0]] + + unique_nodes_new = unique_nodes[node_mapping, :] + + # Re-map the order of the node back to the new ordering: + order_discr_new = np.zeros((unique_nodes_new.shape[0],), dtype=int) + + for ii, node in enumerate(order_discr): + order_discr_new[ii] = np.where(node == node_mapping)[0] + + return incidence_matrix_new, unique_nodes_new, order_discr_new + + +# @jit(nopython=True) +def closest_point_method(incidence_matrix, char_len, order_discr_nodes, unique_nodes, merge_threshold): + # Loop over all unique nodes (except the first): + num_unq_nodes = unique_nodes.shape[0] + order_mask = np.ones((num_unq_nodes,), dtype=bool) + count = 0 + for new_node in order_discr_nodes[1:]: + # Check if node is within lc/2 radius of any [1, ..., N] node: + # Then select smallest distance if true and merge incidence matrix and distance for that node + + count += 1 + # Compute distance matrix: + # id_min_node = np.argmin(dist_mat_order[ii, :ii]) + dist_vec_temp = np.linalg.norm(unique_nodes[new_node, :] - unique_nodes[order_discr_nodes[:count], :], axis=1) + argmin_id = np.argmin(dist_vec_temp) + fixed_node = order_discr_nodes[argmin_id] + + if dist_vec_temp[argmin_id] < (char_len * merge_threshold): + # Record shift in order of node-importance: + order_mask[np.where(order_discr_nodes == new_node)[0]] = False + + # Todo: Check if merging nodes is still compatible with old way of solving + # Todo: What does it mean to take the union of the rows of the incidence matrix in the case of the list approach + # Todo: Simply replacing the node with new node into which it merges still doesn't take care of the segments that might get merged + # Todo: How to identify merged and collapsed segments in this new approach? + # Take the union of incidency matrix (this preserves connection that existed at the node which is removed, + # basically it means, keep all remaining connections and add new ones due to new node merge): + # In the list approach, this means updating the entries which the new_node was part of with the vertex of + # the fixed node: + old_connections = incidence_matrix[:, 0] == new_node + incidence_matrix[old_connections, 0] = fixed_node + edges_to_node = incidence_matrix[old_connections, 1] + + # Now check for all those entries if the node has been collapsed, merged or simply extended: + for edge in edges_to_node: + nodes_on_edge = incidence_matrix[np.where(incidence_matrix[:, 1] == edge)[0], 0] + + if nodes_on_edge.shape[0] != 2: + print('Edge has more than two vertices, something is wrong here!!!') + sys.exit(0) + + if nodes_on_edge[0] == nodes_on_edge[1]: + # Means that the segment has collapsed and therefore has zero length --> needs to be removed! + incidence_matrix[np.where(incidence_matrix[:, 1] == edge)[0], :] = -99999 + + else: + # Check if the intersection of the set of edges on the two node exceeds 1: + # Two nodes can only share an edge if they are ON(!) the same edge, this means that if there are two + # edges that satisfy this condition, there is a double/merged segment and need to keep one segment + # and remove the other(s)! + edges_1 = incidence_matrix[np.where(incidence_matrix[:, 0] == nodes_on_edge[0])[0], 1] + edges_2 = incidence_matrix[np.where(incidence_matrix[:, 0] == nodes_on_edge[1])[0], 1] + common_edges = np.intersect1d(edges_1, edges_2) + + if common_edges.shape[0] > 1: + # Remove all edges in excess of 1: + for remove_edge in common_edges[1:]: + incidence_matrix[np.where(incidence_matrix[:, 1] == remove_edge)[0], :] = -99999 + + unique_nodes[new_node, :] = -99999 # node doesn't exist anymore! + + # Make sure ordering of nodes is preserved + order_discr_nodes = order_discr_nodes[order_mask] + incidence_matrix, unique_nodes, order_discr_nodes = reorder_incidence_and_nodes(incidence_matrix, unique_nodes, order_discr_nodes) + + return incidence_matrix, unique_nodes, order_discr_nodes + + +# @jit(nopython=True) +def straighten_fractures(incidence_matrix, unique_nodes, angle_tol_straighten, order_discr_nodes): + unique_node_tot = unique_nodes.shape[0] + unique_node_list, degree_nodes = np.unique(incidence_matrix[:, 0], return_counts=True) + unique_edges, counts = np.unique(incidence_matrix[:, 1], return_counts=True) + num_segm_tot = unique_edges.shape[0] + + # Straighten fractures: + # Take only the degree-2 nodes to straighten: + nodes_to_straighten = unique_node_list[np.where(degree_nodes == 2)[0]] + order_mask = np.ones((unique_node_tot,), dtype=bool) + for ii, node in enumerate(nodes_to_straighten): + # Check the angle between two-segments that this node is on: + segms = incidence_matrix[np.where(incidence_matrix[:, 0] == node)[0], 1] + if len(segms) > 2: + a = 0 + nodes_segm1 = incidence_matrix[np.where(incidence_matrix[:, 1] == segms[0])[0], 0] + nodes_segm2 = incidence_matrix[np.where(incidence_matrix[:, 1] == segms[1])[0], 0] + vec_m = unique_nodes[nodes_segm1[0], :] - unique_nodes[nodes_segm1[1], :] + vec_p = unique_nodes[nodes_segm2[0], :] - unique_nodes[nodes_segm2[1], :] + dot_product = min(1, max(-1, np.dot(vec_m / np.linalg.norm(vec_m), vec_p / np.linalg.norm(vec_p)))) + angle = np.arccos(np.abs(dot_product)) * 180 / np.pi + + # If the angle is below threshold, add node to remove nodes and make sure to take the union of + if angle < angle_tol_straighten: + # Always keep segms[0] and remove segms[1] (removing segment in this context is equal to saying the segment + # doesn't contain any nodes --> setting col segms[1] to zeros, also remember to set row to zeros of node which + # we remove (and finally record which cols and rows to delete) + order_mask[np.where(order_discr_nodes == node)[0]] = False + + # Remove node to straight edges --> means from 2 segments to 1 --> 1 segment goes from node [i, j] and + # [j, k] to [i, k] basically: take union, remove common node --> make one segm these nodes, remove the other + # segment with -99999 + incidence_matrix[np.where(incidence_matrix[:, 0] == node)[0], :] = -99999 + + # Keep segms[0] comes down to adding segms[0] to other node segms[1], where other means not the shared node! + # It means finding row of incidence matrix with contains the node nodes_segm2 != node and the segm segms[1] + row_id = np.intersect1d(np.where(incidence_matrix[:, 0] == nodes_segm2[nodes_segm2 != node])[0], + np.where(incidence_matrix[:, 1] == segms[1])[0]) + incidence_matrix[row_id, 1] = segms[0] + + order_discr_nodes = order_discr_nodes[order_mask] + incidence_matrix, unique_nodes, order_discr_nodes = reorder_incidence_and_nodes(incidence_matrix, unique_nodes, order_discr_nodes) + + return incidence_matrix, unique_nodes, order_discr_nodes + + +# @jit(nopython=True) +def remove_small_angles(incidence_matrix, unique_nodes, tolerance_zero, angle_tol_remove_segm, order_discr_nodes): + unique_edges, counts = np.unique(incidence_matrix[:, 1], return_counts=True) + num_segm_tot = unique_edges.shape[0] + new_unique_node_tot = unique_nodes.shape[0] + merge_list = np.ones((new_unique_node_tot,), dtype=int) * -1 + order_mask = np.ones((new_unique_node_tot,), dtype=bool) + merge_list_segm = np.ones((num_segm_tot,), dtype=int) * -1 + + for ii in range(new_unique_node_tot): + if merge_list[ii] < 0: # note sure if this is necessary with the new checks!!! todo: check tomorrow if necessary + # Determine which segments belong to the current node: + segms = incidence_matrix[np.where(incidence_matrix[:, 0] == ii)[0], 1] + + # Remove segments from segms-list that have been removed/merged: + segms = segms[np.where(merge_list_segm[segms] < 0)[0]] + + # Loop over all segment combinations to determine the angle between them: + permutations = list(combinations(segms, 2)) + angles_perm = np.ones((len(permutations),)) * 180 + for jj, segm_pair in enumerate(permutations): + # Removed segments are either segments that after merging have only one node left (since the original node is + # merged and therefore doesn't exist anymore in the incidence matrix) (this check is necessary because a + # segment that is merged like this can happen outside of the two segments that are investiated on their angle, + # it can be attached to the node which is getting merged and another node) + removed_segm = False + nodes_semg1 = incidence_matrix[np.where(incidence_matrix[:, 1] == segm_pair[0])[0], 0] + nodes_semg2 = incidence_matrix[np.where(incidence_matrix[:, 1] == segm_pair[1])[0], 0] + + if len(nodes_semg1) < 2: + # Segment has been removed: + merge_list_segm[segm_pair[0]] = 1 + incidence_matrix[np.where(incidence_matrix[:, 1] == segm_pair[0])[0], :] = -99999 + removed_segm = True + + if len(nodes_semg2) < 2: + # Segment has been removed: + merge_list_segm[segm_pair[1]] = 1 + incidence_matrix[np.where(incidence_matrix[:, 1] == segm_pair[1])[0], :] = -99999 + removed_segm = True + + if not removed_segm: + # If the segment is not removed (removed meaning merged into another segment and it's original node is + # removed which causes it to have less than two nodes): + vec_m = unique_nodes[ii, :] - unique_nodes[nodes_semg1[nodes_semg1 != ii][0], :] + vec_p = unique_nodes[ii, :] - unique_nodes[nodes_semg2[nodes_semg2 != ii][0], :] + dot_product = min(1, max(-1, np.dot(vec_m / np.linalg.norm(vec_m), vec_p / np.linalg.norm(vec_p)))) + angles_perm[jj] = np.arccos(dot_product) * 180 / np.pi + else: + angles_perm[jj] = 180 + + for jj in range(angles_perm.shape[0]): + if angles_perm[jj] < np.max([tolerance_zero, 1e-5]): + # If angle is zero, means we have a segment which is overlapping, set angle to 180 and set column of + # incidence matrix to zero (for one of the segments): + segm_to_remove = permutations[jj][0] # since segments are overlapping, no difference between segments + incidence_matrix[np.where(incidence_matrix[:, 1] == segm_to_remove)[0], :] = -99999 + merge_list_segm[segm_to_remove] = 1 + angles_perm[jj] = 180 + + # Also set angles for all other pairs with this segment to 180: + for kk in permutations: + if segm_to_remove == kk[0] or segm_to_remove == kk[1]: + angles_perm[jj] = 180 + + if any(angles_perm < angle_tol_remove_segm): + # There exists a very small angle between some of the segments in the array: + # Determine the smallest angle and solve the issue, fix the issue and recalculate the angles + id_small_pair = np.argmin(angles_perm) + + nodes_semg1 = incidence_matrix[np.where(incidence_matrix[:, 1] == permutations[id_small_pair][0])[0], 0] + nodes_semg2 = incidence_matrix[np.where(incidence_matrix[:, 1] == permutations[id_small_pair][1])[0], 0] + + vec_m = unique_nodes[ii, :] - unique_nodes[nodes_semg1[nodes_semg1 != ii][0], :] + vec_p = unique_nodes[ii, :] - unique_nodes[nodes_semg2[nodes_semg2 != ii][0], :] + length_m = np.linalg.norm(vec_m) + length_p = np.linalg.norm(vec_p) + + # Merge non-shared node of smaller segment in one of the nodes of the larger segment (the closest node to be + # precise) + if length_m < length_p: + merge_node_id = nodes_semg1[nodes_semg1 != ii][0] + else: + merge_node_id = nodes_semg2[nodes_semg2 != ii][0] + + possible_merge_ids = np.union1d(nodes_semg1, nodes_semg2) + possible_merge_ids = possible_merge_ids[possible_merge_ids != merge_node_id] + + # Determine which node to merge into (the closest node of the large segment): + dist_nodes = np.linalg.norm(unique_nodes[possible_merge_ids, :] - unique_nodes[merge_node_id, :], + axis=1) + merge_target_id = possible_merge_ids[np.argmin(dist_nodes)] + + # Record also the node which it gets merged into, this is important to preserve connections in incidence matrix) + merge_list[merge_node_id] = merge_target_id + order_mask[np.where(order_discr_nodes == merge_node_id)[0]] = False + + old_connections = incidence_matrix[:, 0] == merge_node_id + incidence_matrix[old_connections, 0] = merge_target_id + edges_to_node = incidence_matrix[old_connections, 1] + + # Now check for all those entries if the node has been collapsed, merged or simply extended: + for edge in edges_to_node: + nodes_on_edge = incidence_matrix[np.where(incidence_matrix[:, 1] == edge)[0], 0] + + if nodes_on_edge.shape[0] != 2: + print('Edge has more than two vertices, something is wrong here!!!') + sys.exit(0) + + if nodes_on_edge[0] == nodes_on_edge[1]: + # Means that the segment has collapsed and therefore has zero length --> needs to be removed! + incidence_matrix[np.where(incidence_matrix[:, 1] == edge)[0], :] = -99999 + + else: + # Check if the intersection of the set of edges on the two node exceeds 1: + # Two nodes can only share an edge if they are ON(!) the same edge, this means that if there are two + # edges that satisfy this condition, there is a double/merged segment and need to keep one segment + # and remove the other(s)! + edges_1 = incidence_matrix[np.where(incidence_matrix[:, 0] == nodes_on_edge[0])[0], 1] + edges_2 = incidence_matrix[np.where(incidence_matrix[:, 0] == nodes_on_edge[1])[0], 1] + common_edges = np.intersect1d(edges_1, edges_2) + + if common_edges.shape[0] > 1: + # Remove all edges in excess of 1: + for remove_edge in common_edges[1:]: + incidence_matrix[np.where(incidence_matrix[:, 1] == remove_edge)[0], :] = -99999 + merge_list_segm[remove_edge] = 1 + + unique_nodes[merge_node_id, :] = -99999 # node doesn't exist anymore! + + # Make sure ordering of nodes is preserved + order_discr_nodes = order_discr_nodes[order_mask] + incidence_matrix, unique_nodes, order_discr_nodes = reorder_incidence_and_nodes(incidence_matrix, unique_nodes, + order_discr_nodes) + return incidence_matrix, unique_nodes, order_discr_nodes + +# @jit(nopython=True) +def reconstruct_act_frac_sys(incidence_matrix, unique_nodes): + # Reconstruct the m x 4 matrix containing each segment of the fracture network: + unique_segm_list, count_segment = np.unique(incidence_matrix[:, 1], return_counts=True) + segm_count = 0 + act_frac_sys = np.zeros((unique_segm_list.shape[0], 4)) + for ii in unique_segm_list: + nodes_on_segm = incidence_matrix[np.where(incidence_matrix[:, 1] == ii)[0], 0] + + if nodes_on_segm.shape[0] != 2: + print('THERE IS A SEGMENT WITH MORE THAN 2 NODES!!!') + sys.exit(0) + + act_frac_sys[segm_count, :] = np.hstack((unique_nodes[nodes_on_segm[0], :], + unique_nodes[nodes_on_segm[1], :])) + segm_count += 1 + return act_frac_sys + + +def write_new_frac_sys(act_frac_sys_new, filename): + f = open(filename, "w+") + for frac in act_frac_sys_new: + f.write('{:9.5f} {:9.5f} {:9.5f} {:9.5f}\n'.format(frac[0], frac[1], frac[2], frac[3])) + f.close() + return 0 + + +def create_geo_file(act_frac_sys, unique_nodes, incidence_matrix, filename, decimals, + height_res, char_len, box_data, char_len_boundary): + act_frac_sys = np.round(act_frac_sys * 10 ** decimals) * 10 ** (-decimals) + num_segm_tot = act_frac_sys.shape[0] + num_nodes_tot = unique_nodes.shape[0] + f = open(filename, "w+") + + # Note: always end statement in GMSH with ";" + # Note: comments in GMSH are as in C(++) "//" + f.write('// Geo file which meshes the input mesh from act_frac_sys.\n') + f.write('// Change mesh-elements size by varying "lc" below.\n\n') + + # Can specify the type of meshing algorithm for 2D meshing here: + # f.write('// Specify meshing algorithm:\n') + # f.write('-algo meshadapt;\n\n') + + # Set some parameters in the model: + f.write('lc = {:1.3f};\n'.format(char_len)) + f.write('lc_box = {:1.3f};\n'.format(char_len_boundary)) + f.write('height_res = {:4.3f};\n\n'.format(height_res)) + + # Allocate memory for points_created array and counters: + points_created = np.zeros((num_nodes_tot,)) + line_count = 0 + point_count = 0 + + unique_segm_list, segm_count = np.unique(incidence_matrix[:, 1], return_counts=True) + + for ii in unique_segm_list: + # Take two points per segment and write to .geo file: + # e.g. point: Point(1) = {.1, 0, 0, lc}; + nodes = incidence_matrix[np.where(incidence_matrix[:, 1] == ii)[0], 0] + + if len(nodes) != 2: + print('There exists a segment with an amount of nodes unequal to 2!!!') + sys.exit(0) + + # Check if first point is already created, if not, add it: + if points_created[nodes[0]] == 0: + points_created[nodes[0]] = 1 + point_count += 1 + f.write('Point({:d}) = {{{:8.5f}, {:8.5f}, 0, lc}};\n'.format(nodes[0] + 1, + unique_nodes[nodes[0], 0], + unique_nodes[nodes[0], 1])) + + if points_created[nodes[1]] == 0: + points_created[nodes[1]] = 1 + point_count += 1 + f.write('Point({:d}) = {{{:8.5f}, {:8.5f}, 0, lc}};\n'.format(nodes[1] + 1, + unique_nodes[nodes[1], 0], + unique_nodes[nodes[1], 1])) + + line_count += 1 + f.write('Line({:d}) = {{{:d}, {:d}}};\n\n'.format(line_count, nodes[0] + 1, nodes[1] + 1)) + + # Store some internal variables for gmsh (used later after extrude): + f.write('num_points_frac = newp - 1;\n') + f.write('num_lines_frac = newl - 1;\n\n') + + # Write the box_data (box around fracture network in which we embed the fractures) + f.write('// Extra points for boundary of domain:\n') + for ii in range(4): + # For every corner of the box: + point_count += 1 + f.write('Point({:d}) = {{{:8.5f}, {:8.5f}, 0, lc_box}};\n'.format(point_count, + box_data[ii, 0], box_data[ii, 1])) + + # Add four lines for each side of the box: + f.write('\n// Extra lines for boundary of domain:\n') + line_count += 1 + f.write('Line({:d}) = {{{:d}, {:d}}};\n'.format(line_count, point_count - 3, point_count - 2)) + + line_count += 1 + f.write('Line({:d}) = {{{:d}, {:d}}};\n'.format(line_count, point_count - 2, point_count - 1)) + + line_count += 1 + f.write('Line({:d}) = {{{:d}, {:d}}};\n'.format(line_count, point_count - 1, point_count - 0)) + + line_count += 1 + f.write('Line({:d}) = {{{:d}, {:d}}};\n'.format(line_count, point_count - 0, point_count - 3)) + + # Make Curve loop for the boundary: + f.write('\n// Create line loop for boundary surface:\n') + f.write('Curve Loop(1) = {{{:d}, {:d}, {:d}, {:d}}};\n'.format(line_count - 3, line_count - 2, + line_count - 1, line_count)) + f.write('Plane Surface(1) = {1};\n\n') + f.write('Curve{1:num_lines_frac} In Surface{1};\n') + + # Extrude model to pseuo-3D: + f.write('\n// Extrude surface with embedded features\n') + f.write('Extrude {0, 0, height_res}{ Surface {1}; Layers{1}; Recombine;}\n') + f.write('Physical Volume("matrix", 9991) = {1};\n') + + f.write('num_surfaces_before = news;\n') + f.write('Extrude {0, 0, height_res}{ Line {1:num_lines_frac}; Layers{1}; Recombine;}\n') + f.write('num_surfaces_after = news - 1;\n') + f.write('num_surfaces_fracs = num_surfaces_after - num_surfaces_before;\n\n') + f.write('Physical Surface("fracture", 99991) = {num_surfaces_before:num_surfaces_after};\n') + + # Create mesh and perform coherency check: + f.write('Mesh 3; // Generalte 3D mesh\n') + f.write('Coherence Mesh; // Remove duplicate entities\n') + f.write('Mesh.MshFileVersion = 2.1;\n') + f.close() + return 0 + + +def mesh_geo_file(filename_in, filename_out): + # subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt']) + # subprocess.call("'gmsh ' {:s} ' -o ' {:s} ' -save'".format(filename_in, filename_out)) + os.system("gmsh {:s} -o {:s} -save".format(filename_in, filename_out)) + return 0 + + +def extract_unique_nodes(act_frac_sys, remove_small_segms=True, tolerance_zero=1e-5): + # Extract unique indices: + dummy_sys = np.array(act_frac_sys, copy=True) + indices = np.where(act_frac_sys[:, 0] > act_frac_sys[:, 2])[0] + dummy_sys[indices, 0:2] = act_frac_sys[indices, 2:] + dummy_sys[indices, 2:] = act_frac_sys[indices, :2] + dummy_sys = np.unique(dummy_sys, axis=0) + + if remove_small_segms: + len_segm = np.sqrt((dummy_sys[:, 0] - dummy_sys[:, 2])**2 + (dummy_sys[:, 1] - dummy_sys[:, 3])**2) + dummy_sys = dummy_sys[len_segm > tolerance_zero, :] + return dummy_sys + + +# Full cleaning method: +# @jit(nopython=True) +def full_cleaning(act_frac_sys, char_len, decimals, tolerance_zero, angle_tol_straighten, + angle_tol_remove_segm, straighten_first, merge_threshold): + act_frac_sys = np.round(act_frac_sys * 10 ** decimals) * 10 ** (-decimals) + + # Calculate the length of segments: + length_segms = ((act_frac_sys[:, 0] - act_frac_sys[:, 2]) ** 2 + + (act_frac_sys[:, 1] - act_frac_sys[:, 3]) ** 2) ** (1 / 2) + order_discr = np.argsort(-length_segms) # larger fractures first, smaller fractures last + + # Perform segmentation large fractures into fracture segments of length char_len: + act_frac_sys_segm, order_discr_segm = segment_large_fracture(act_frac_sys, char_len, length_segms, order_discr, + decimals) + + # Find unique nodes: + unique_nodes = np.unique(np.vstack((act_frac_sys_segm[:, :2], act_frac_sys_segm[:, 2:])), axis=0) + + incidence_matrix, order_discr_nodes = create_graph(act_frac_sys_segm, unique_nodes, order_discr_segm, + tolerance_zero) + + # # First calculate distance matrix + # dist_vec_order = pdist(unique_nodes[order_discr_nodes, :], metric='euclidean') + # dist_mat_order = squareform(dist_vec_order) + + num_inner_iter = 2 + for kk in range(num_inner_iter): + # Perform merging algorithm (closest point method): + incidence_matrix, unique_nodes, order_discr_nodes = \ + closest_point_method(incidence_matrix, char_len, order_discr_nodes, unique_nodes, merge_threshold) + + # The order of these two matters (not sure how much, todo: check how much the order influences the results): + remove_angle_iters = 5 + if straighten_first: + # Perform straightening of fractures: + incidence_matrix, unique_nodes, order_discr_nodes = \ + straighten_fractures(incidence_matrix, unique_nodes, angle_tol_straighten, order_discr_nodes) + + # Remove small angle fracture intersections: + for kk in range(remove_angle_iters): + incidence_matrix, unique_nodes, order_discr_nodes = \ + remove_small_angles(incidence_matrix, unique_nodes, tolerance_zero, angle_tol_remove_segm, + order_discr_nodes) + else: + # Remove small angle fracture intersections: + for kk in range(remove_angle_iters): + incidence_matrix, unique_nodes, order_discr_nodes = \ + remove_small_angles(incidence_matrix, unique_nodes, tolerance_zero, angle_tol_remove_segm, + order_discr_nodes) + + # Perform straightening of fractures: + incidence_matrix, unique_nodes, order_discr_nodes = \ + straighten_fractures(incidence_matrix, unique_nodes, angle_tol_straighten, order_discr_nodes) + + # Re-calculate act_frac_sys from incidence matrix and unique node array: + act_frac_sys = reconstruct_act_frac_sys(incidence_matrix, unique_nodes) + + return act_frac_sys, unique_nodes, incidence_matrix \ No newline at end of file diff --git a/find_parametric_intersect.py b/find_parametric_intersect.py new file mode 100644 index 0000000..9aa61ad --- /dev/null +++ b/find_parametric_intersect.py @@ -0,0 +1,54 @@ +""" +Module that calculates the intersection point of two given line segments +Rewritten from a matlab script by Stephan de Hoop + +Author: Joey Herbold +Date: 22/11/2020 +""" + +import numpy as np + + +def find_parametric_intersect(ii_frac, jj_frac): + """ + This function calculates the intersection point of two fractures + + :param ii_frac: Fracture 1 + :param jj_frac: Fracture 2 + :return t: Parametric distance along fracture 1 value between 0 and 1 + :return s: Parametric distance along fracture 2 value between 0 and 1 + :return int_coord: Coordinates of the intersection + """ + P_0 = np.array([ii_frac[0], + ii_frac[1]]) + + P = np.array([ii_frac[2] - ii_frac[0], + ii_frac[3] - ii_frac[1]]) + + Q_0 = np.array([jj_frac[0], + jj_frac[1]]) + + Q = np.array([jj_frac[2] - jj_frac[0], + jj_frac[3] - jj_frac[1]]) + + A = np.zeros((2, 2)) + A[:, 0] = P + A[:, 1] = -Q + + if abs(np.linalg.det(A)) < 1e-16: + # Check if the lines are parallel by looking at the determinant + t = -1 + s = -1 + int_coord = np.array([]) + else: + # Calculate the intersection point of the two lines + rhs = P_0 - Q_0 + + solution = np.linalg.solve(-A, rhs) + + t = solution[0] + s = solution[1] + + int_coord = P_0 + t * P + + return t, s, int_coord diff --git a/main.py b/main.py new file mode 100644 index 0000000..2a56d3e --- /dev/null +++ b/main.py @@ -0,0 +1,50 @@ +import numpy as np +from multiprocessing import freeze_support +from preprocessing import frac_preprocessing + + +def main(): + # File names and directories: + output_dir = 'FracData_test_with_inter' + filename_base = 'FracData_test_with_inter' + frac_data_raw = np.genfromtxt(filename_base + '.txt') + + # Some constants: + tolerance_zero = 1e-15 + tolerance_intersect = 1e-15 + decimals = 7 + char_len_vec = np.array([10, 20, 40]) + angle_tol_straighten = 5 + merge_threshold = 0.86 # 0.5, 0.75, 0.86 + angle_tol_remove_segm = np.arctan(0.35) * 180 / np.pi # (anywhere between 15-25 degrees should be fine) + + reuse_clean = True + straighten_first = True + mesh_clean = True + mesh_raw = True + num_partition_x = 1 + num_partition_y = 1 + + # Reservoir properties: + height_res = 50 + origin_x = 0 + origin_y = 0 + margin = 25 + length_x = np.max(frac_data_raw[:, [0, 2]]) + length_y = np.max(frac_data_raw[:, [1, 3]]) + + box_data = np.array([[origin_x - margin, origin_y - margin], + [length_x + margin, origin_y - margin], + [length_x + margin, length_y + margin], + [origin_x - margin, length_y + margin]]) + + frac_preprocessing(frac_data_raw, char_len_vec, output_dir, filename_base, height_res, box_data, + angle_tol_straighten, merge_threshold, angle_tol_remove_segm, + tolerance_zero, tolerance_intersect, decimals, reuse_clean, + straighten_first, mesh_clean, mesh_raw, + num_partition_x, num_partition_y) + + +if __name__ == "__main__": + freeze_support() + main() diff --git a/merge_domain.py b/merge_domain.py new file mode 100644 index 0000000..d33ebee --- /dev/null +++ b/merge_domain.py @@ -0,0 +1,82 @@ +""" +Function that merges the domain partitions +""" + +import numpy as np + +def merge_domain(act_frac_sys_list, frac_set_vec, partition_lines, number_partitions_x): + """ + + :param act_frac_sys_list: Array of fractures that were once partitioned, and must now be merged back together. + :param frac_set_vec_list: Array of grouping identifiers. + :param frac_order_vec_list: Array of priority identifiers. + :param partition_lines: Lines over which the domain was partitioned at the start of parallelizing. + :param number_partitions_x: The numbers of partitions in x-direction. + :return: + """ + + act_frac_sys = np.vstack(act_frac_sys_list)[:, :4] + uniq_inds = np.unique(act_frac_sys, return_index=True, axis=0)[1] + act_frac_sys = act_frac_sys[uniq_inds] + + merge_tolerance = 1e-5 + + for i in range(partition_lines.shape[0]): + if i < number_partitions_x - 1: + direction = 0 + other_dir = 1 + else: + direction = 1 + other_dir = 0 + + partition_line = partition_lines[i] + + # Each line will have one constant value, either on the x- or y-axis. + const_value_par_line = partition_line[direction] + + inds_left = np.where(np.abs(act_frac_sys[:, direction + 2] - const_value_par_line) <= merge_tolerance) + inds_right = np.where(np.abs(act_frac_sys[:, direction] - const_value_par_line) <= merge_tolerance) + inds_afs = np.hstack((inds_left, inds_right)) + + segments_left = act_frac_sys[inds_left] + segments_right = act_frac_sys[inds_right] + + segments_left_slope = np.abs((segments_left[:, 1] - segments_left[:, 3]) / (segments_left[:, 0] - segments_left[:, 2])) + segments_right_slope = np.abs((segments_right[:, 1] - segments_right[:, 3]) / (segments_right[:, 0] - segments_right[:, 2])) + # Delete intersection information, it is not needed and stands in the way of merging segments. + segments_left = np.hstack((segments_left, segments_left_slope.reshape((len(segments_left_slope), 1)))) + segments_right = np.hstack((segments_right, segments_right_slope.reshape((len(segments_right_slope), 1)))) + + # Grouping the left and right part or bottom and top part of the newly merged fracture together. + if segments_left.shape[0] >= segments_right.shape[0]: + restored_fracs = np.zeros((segments_left.shape[0], 4)) + i = 0 + for segm in segments_left: + inds_val = np.where(segments_right[:, other_dir] == segm[other_dir + 2])[0] + inds_slope = np.where(np.abs(segments_right[:, 4] - segm[4] < merge_tolerance))[0] + inds_restore = np.intersect1d(inds_val, inds_slope) + if len(inds_restore) == 1: + restored_fracs[i, :2] = segm[:2] + restored_fracs[i, 2:] = segments_right[inds_restore, 2:4] + i += 1 + + else: + restored_fracs = np.zeros((segments_right.shape[0], 4)) + i = 0 + for segm in segments_right: + inds_val = np.where(segments_left[:, other_dir + 2] == segm[other_dir])[0] + inds_slope = np.where(np.abs(segments_left[:, 4] - segm[4] < merge_tolerance))[0] + inds_restore = np.intersect1d(inds_val, inds_slope) + if len(inds_restore) == 1: + restored_fracs[i, :2] = segments_left[inds_restore, :2] + restored_fracs[i, 2:] = segm[2:4] + i += 1 + + + # Deleting the previous fractures that are now merged and adding the fractures to act_frac_sys. + act_frac_sys = np.delete(act_frac_sys, inds_afs, axis=0) + act_frac_sys = np.vstack((act_frac_sys, restored_fracs)) + + # Update frac_set_vec + + return act_frac_sys, frac_set_vec diff --git a/partition_domain.py b/partition_domain.py new file mode 100644 index 0000000..744ddca --- /dev/null +++ b/partition_domain.py @@ -0,0 +1,189 @@ +""" +Function that partitions the domain +""" +import numpy as np +import math +from find_parametric_intersect import find_parametric_intersect + + +def partition_domain(act_frac_sys, frac_order_vec, tolerance_intersect, number_partitions_x, number_partitions_y): + """ + + :param frac_order_vec: + :param act_frac_sys: + :param tolerance_intersect: + :param number_partitions_x: + :param number_partitions_y: + :return: + """ + + # Define lowest and highest possible x and y values. + xmin = act_frac_sys[:, [0,2]].min(axis=None) + xmax = act_frac_sys[:, [0,2]].max(axis=None) + ymin = act_frac_sys[:, [1,3]].min(axis=None) + ymax = act_frac_sys[:, [1,3]].max(axis=None) + interval_x = (xmax - xmin) / number_partitions_x + interval_y = (ymax - ymin) / number_partitions_y + + # Assume the maximum values found above define the domain. + # Then, to partition the domain: + partitions_x = np.zeros((number_partitions_x - 1, 4)) + for i in range(1, number_partitions_x): + x_part = xmin + interval_x * i + partitions_x[i - 1, :] = np.array([x_part, ymin, x_part, ymax]) + + partitions_y = np.zeros((number_partitions_y - 1, 4)) + for j in range(1, number_partitions_y): + y_part = ymin + interval_y * j + partitions_y[j - 1, :] = np.array([xmin, y_part, xmax, y_part]) + + # This array will contain information about the partitioning lines which which can be used to find intersections. + # [x0, y0, x1, y1] + partitions = np.vstack((partitions_x, partitions_y)) + + # We use this little trick to make sure the subdomains are determined correctly. + act_frac_sys[np.where(act_frac_sys == xmax)] = xmax - 0.01 + act_frac_sys[np.where(act_frac_sys == ymax)] = ymax - 0.01 + + # Variables used to store information in an array later in the program. + old_index = 0 + new_index = 0 + + subdomain_sys = np.transpose([np.floor((act_frac_sys[:, 0] - xmin) / interval_x), + np.floor((act_frac_sys[:, 1] - ymin) / interval_y), + np.floor((act_frac_sys[:, 2] - xmin) / interval_x), + np.floor((act_frac_sys[:, 3] - ymin) / interval_y)]) + + # Change back what we did to get the right subdomains + act_frac_sys[np.where(act_frac_sys == xmax - 0.01)] = xmax + act_frac_sys[np.where(act_frac_sys == ymax - 0.01)] = ymax + + fracs_to_part_x = np.where(subdomain_sys[:, 0] != subdomain_sys[:, 2])[0] + fracs_to_part_y = np.where(subdomain_sys[:, 1] != subdomain_sys[:, 3])[0] + + # An array of indices referring to fractures that must be split due to partitioning. + fracs_to_part = np.union1d(fracs_to_part_x, fracs_to_part_y) + part_frac_sys = act_frac_sys[fracs_to_part] + part_frac_subdomains = subdomain_sys[fracs_to_part] + + # CHECK + tot_new_fracs = np.sum(np.abs(subdomain_sys[fracs_to_part, 2] - subdomain_sys[fracs_to_part, 0]) + \ + np.abs(subdomain_sys[fracs_to_part, 3] - subdomain_sys[fracs_to_part, 1]), dtype=int) + len(fracs_to_part) + + # Array where all newly found partitioned fractures will be stored. The number of rows is pretty arbitrary. + part_fracs = np.zeros((tot_new_fracs, 5)) + + # Arrays where all information is stored to, in the end, form frac_order_vec_list. + part_frac_order_vec = np.zeros(tot_new_fracs) + + # To clear some memory, the subdomains which are in part_frac_subdomains can now be deleted from the original array. + subdomain_sys = np.delete(subdomain_sys, fracs_to_part, axis=0) + + ii = -1 + + for ii_frac in part_frac_sys: + + ii += 1 + + # The subdomains of points in this fracture + ii_subdomains = part_frac_subdomains[ii, :] + + # I do not expect a fracture to cross more than 6 partition lines. Still an estimate though. + num_ints = int(abs(ii_subdomains[2] - ii_subdomains[0]) + abs(ii_subdomains[3] - ii_subdomains[1])) + part_int = np.zeros((num_ints, 2)) + + # Counts the amount of intersections between the given ii fracture and all partitioning lines. + int_counter = 0 + + # Partition IDs. [subdomain xmin, subdomain xmax, subdomain ymin, subdomain ymax] + # (an offset was added to subdomains of y to establish the difference between x and y) + partition_ids = [int(min(ii_subdomains[0], ii_subdomains[2])), + int(max(ii_subdomains[0], ii_subdomains[2])), + int(number_partitions_x - 1 + min(ii_subdomains[1], ii_subdomains[3])), + int(number_partitions_x - 1 + max(ii_subdomains[1], ii_subdomains[3]))] + + # x partitions + for jj_part in partitions[partition_ids[0]:partition_ids[1]]: + t, s, int_coord = find_parametric_intersect(ii_frac, jj_part) + + if (t >= (0 - tolerance_intersect) and t <= (1 + tolerance_intersect)) and \ + (s >= (0 - tolerance_intersect) and s <= (1 + tolerance_intersect)): + + # Only store intersections of segments that don't already share a node: + if not (np.linalg.norm(ii_frac[:2] - jj_part[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[:2] - jj_part[2:]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_part[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_part[2:]) < tolerance_intersect): + + # Store the intersection coordinates in part_int + part_int[int_counter, :] = np.array([int_coord[0], int_coord[1]]) + int_counter += 1 + + # y partitions + for jj_part in partitions[partition_ids[2]:partition_ids[3]]: + + t, s, int_coord = find_parametric_intersect(ii_frac, jj_part) + + if (t >= (0 - tolerance_intersect) and t <= (1 + tolerance_intersect)) and \ + (s >= (0 - tolerance_intersect) and s <= (1 + tolerance_intersect)): + + # Only store intersections of segments that don't already share a node: + if not (np.linalg.norm(ii_frac[:2] - jj_part[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[:2] - jj_part[2:]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_part[:2]) < tolerance_intersect or + np.linalg.norm(ii_frac[2:] - jj_part[2:]) < tolerance_intersect): + + # Store the intersection coordinates in part_int + part_int[int_counter, :] = np.array([int_coord[0], int_coord[1]]) + int_counter += 1 + + # Add x0 and y0 of fracture ii to start of part_int, and x1 and y1 to the end of it. + part_int = np.vstack((np.vstack((ii_frac[:2], part_int)), ii_frac[2:])) + + # Sort on x values + part_int = part_int[np.lexsort((part_int[:, 1], part_int[:, 0]))] + + # Initialization of the array that will contain the information about the new fractures. + new_fracs = np.zeros((num_ints+1, 5)) + for mm in range(0, num_ints + 1): + x0, y0, x1, y1 = part_int[mm, 0], part_int[mm, 1], part_int[mm + 1, 0], part_int[mm + 1, 1] + + # This is how we find out in which subdomain the fracture will be. We add this ID to new_fracs + subdomain_id = math.floor((((x0 + x1) / 2) - xmin) / interval_x) + \ + math.floor((((y0 + y1) / 2) - ymin) / interval_y) * number_partitions_x + + new_fracs[mm, :] = np.array([x0, y0, x1, y1, subdomain_id]) + + new_index += num_ints+1 + + # Add fractures to the array that combines them all + part_fracs[old_index:new_index] = new_fracs + + part_frac_order_vec[old_index:new_index] = np.ones(new_index - old_index) * frac_order_vec[fracs_to_part[ii]] + + old_index = new_index + + act_frac_sys = np.delete(act_frac_sys, fracs_to_part, axis=0) + + num_old_fracs = len(subdomain_sys[:, 0]) + + subdomains_old = subdomain_sys[:, 0] + subdomain_sys[:, 1] * number_partitions_x + + subdomains_old = subdomains_old.reshape((num_old_fracs,1)) + + act_frac_sys = np.hstack((act_frac_sys, subdomains_old)) + act_frac_sys = np.vstack((act_frac_sys, part_fracs)) + + frac_order_vec = np.delete(frac_order_vec, fracs_to_part, axis=0) + + frac_order_vec = np.hstack((frac_order_vec, part_frac_order_vec)) + + act_frac_sys_list = [] + frac_order_vec_list = [] + num_subdomains = number_partitions_x * number_partitions_y + for p in range(0, num_subdomains): + indices = np.where(act_frac_sys[:, 4] == p) + act_frac_sys_list.append(act_frac_sys[indices, :4][0]) + frac_order_vec_list.append(frac_order_vec[indices]) + + return act_frac_sys_list, frac_order_vec_list, partitions diff --git a/preprocessing.py b/preprocessing.py new file mode 100644 index 0000000..2a3bcde --- /dev/null +++ b/preprocessing.py @@ -0,0 +1,166 @@ +""" +MIT License + +Copyright (c) 2021 Stephan de Hoop S.dehoop-1@tudelft.nl + Denis Voskov D.V.Voskov@tudelft.nl + Delft University of Technology, the Netherlands + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" +from cleaning_methods import * +import numpy as np +from calc_intersections_segm_parallel import calc_intersections_segm_parallel +import os + + +def frac_preprocessing(frac_data_raw, char_len_vec, output_dir, filename_base, height_res, box_data, + angle_tol_straighten=7.5, merge_threshold=0.86, angle_tol_remove_segm=15, + tolerance_zero=1e-15, tolerance_intersect=1e-15, decimals=7, reuse_clean=True, + straighten_first=True, mesh_clean=True, mesh_raw=True, + num_partition_x=1, num_partition_y=1): + print('--------------------------------------') + print('START preprocessing fracture network') + tot_partitions = num_partition_x * num_partition_y + + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + frac_data_raw = np.round(frac_data_raw * 10 ** decimals) * 10 ** (-decimals) + len_raw_sys = np.sqrt((frac_data_raw[:, 0] - frac_data_raw[:, 2]) ** 2 + + (frac_data_raw[:, 1] - frac_data_raw[:, 3]) ** 2) + print('Remove segments of zero length') + frac_data_raw = frac_data_raw[np.where(len_raw_sys > tolerance_zero)[0]] + frac_data_raw = extract_unique_nodes(frac_data_raw) + + print('Number of fracture segments: {:}'.format(frac_data_raw.shape[0])) + print('Min fracture segment length: {:}'.format(np.min(len_raw_sys))) + print('Max fracture segment length: {:}'.format(np.max(len_raw_sys))) + print('Mean fracture segment length: {:}'.format(np.mean(len_raw_sys))) + print('Cleaning length(s): {:}\n'.format(char_len_vec)) + + print('START calculating initial intersections raw input fracture network') + print('\tNOTE: unoptimized!, can take long for very large networks') + # First find all intersections: + system_out_par, frac_order_vec_par, partition_lines = \ + calc_intersections_segm_parallel(frac_data_raw, np.zeros_like(frac_data_raw[:, 0]), tolerance_intersect, tolerance_zero, + num_partition_x, num_partition_y) + + # Stack output from all domain together: + act_frac_sys = system_out_par[0] + for ii in range(1, tot_partitions): + act_frac_sys = np.vstack((act_frac_sys, system_out_par[ii])) + + print('DONE calculating initial intersections raw input fracture network') + if act_frac_sys.shape != frac_data_raw.shape: + num_intersections = int((act_frac_sys.shape[0] - frac_data_raw.shape[0])/2) + print('\tFound {:} intersections in raw input fracture network\n'.format(num_intersections)) + else: + print('\tNo intersections found in raw input fracture network\n') + + print('Remove duplicated segments\n') + act_frac_sys = extract_unique_nodes(act_frac_sys) + act_frac_sys_cln = act_frac_sys + act_frac_sys_raw = np.array(act_frac_sys, copy=True) + + # Perform loop for all characteristic lengths: + for jj, char_len in enumerate(char_len_vec): + print('START main cleaning loop for l_f={:}'.format(char_len)) + print('\tNOTE: unoptimized!, can take long for very large networks or very small l_f') + + # Start from old network or from previously cleaned: + if reuse_clean: + act_frac_sys = act_frac_sys_cln + + act_frac_sys_cln, unique_nodes_cln, incidence_matrix_cln = \ + full_cleaning(act_frac_sys, char_len, decimals, tolerance_zero, angle_tol_straighten, angle_tol_remove_segm, + straighten_first, merge_threshold) + + print('DONE main cleaning loop for l_f={:}\n'.format(char_len)) + + print('START calculating intersections clean fracture network for coherent mesh') + print('\tNOTE: unoptimized!, can take long for very large networks') + # Make sure to catch all the intersections after procedure for coherent mesh: + system_out_par, frac_order_vec_par, partition_lines = \ + calc_intersections_segm_parallel(act_frac_sys_cln, np.zeros_like(act_frac_sys_cln[:, 0]), + tolerance_intersect, tolerance_zero, + num_partition_x, num_partition_y) + + # Stack output from all domain together: + act_frac_sys_cln = system_out_par[0] + for ii in range(1, tot_partitions): + act_frac_sys_cln = np.vstack((act_frac_sys_cln, system_out_par[ii])) + act_frac_sys_cln = extract_unique_nodes(act_frac_sys_cln) + print('DONE calculating intersections clean fracture network for coherent mesh\n') + + print('START writing fracture network and geo-file for cleaned network') + # Find unique nodes: + unique_nodes_cln = np.unique(np.vstack((act_frac_sys_cln[:, :2], act_frac_sys_cln[:, 2:])), axis=0) + incidence_matrix_cln, order_discr_nodes_cln = create_graph(act_frac_sys_cln, unique_nodes_cln, + np.arange(act_frac_sys_cln.shape[0]), tolerance_zero) + + # Write final result to file (frac_sys, geo-file, and mesh final results as well): + char_len_boundary = char_len * 1 + + # Write fracture system to .txt for later use: + filename_clean = os.path.join(output_dir, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.txt') + write_new_frac_sys(act_frac_sys_cln, filename_clean) + + # Filenames for meshing: + filename_geo_cln = os.path.join(output_dir, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.geo') + filename_out_cln = os.path.join(output_dir, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.msh') + filename_geo_raw = os.path.join(output_dir, filename_base + '_raw_lc_' + str(char_len) + '.geo') + filename_out_raw = os.path.join(output_dir, filename_base + '_raw_lc_' + str(char_len) + '.msh') + + # Create geo-file and mesh result (clean): + create_geo_file(act_frac_sys_cln, unique_nodes_cln, incidence_matrix_cln, filename_geo_cln, decimals, + height_res, char_len, box_data, char_len_boundary) + print('DONE writing fracture network and geo-file for cleaned network\n') + + if mesh_clean: + print('START meshing cleaned network') + mesh_geo_file(filename_geo_cln, filename_out_cln) + print('DONE meshing cleaned network\n') + + print('START writing geo-file for raw network') + # Create geo-file and mesh result (raw): + order_discr_org = np.arange(act_frac_sys_raw.shape[0]) + unique_nodes_org = np.unique(np.vstack((act_frac_sys_raw[:, :2], act_frac_sys_raw[:, 2:])), axis=0) + incidence_matrix_org, order_discr_nodes_org = create_graph(act_frac_sys_raw, unique_nodes_org, order_discr_org, + tolerance_zero) + + unique_segm_list, segm_count = np.unique(incidence_matrix_org[:, 1], return_counts=True) + mask_2 = segm_count != 2 + + if any(mask_2): + print('SEGMENT WITH MORE THAN 2 NODES, PROBABLY TO LOOSE ZERO FOR FINDING SIMILAR NODES!!!') + sys.exit(0) + + create_geo_file(act_frac_sys_raw, unique_nodes_org, incidence_matrix_org, filename_geo_raw, decimals, + height_res, char_len, box_data, char_len_boundary) + print('DONE writing geo-file for raw network\n') + + if mesh_raw: + print('START meshing raw network') + print('\tNOTE: unoptimized!, can take long for very large raw networks') + mesh_geo_file(filename_geo_raw, filename_out_raw) + print('DONE meshing raw network\n') + + print('Preprocessing succesfully finished') + print('-----------------------------------') + return 0 diff --git a/preprocessing_main.py b/preprocessing_main.py new file mode 100644 index 0000000..7ad5f3f --- /dev/null +++ b/preprocessing_main.py @@ -0,0 +1,146 @@ +from cleaning_methods import * +import numpy as np +from calc_intersections_segm_parallel import calc_intersections_segm_parallel +from multiprocessing import Process, freeze_support +import os + + +def main(): + # Some constants: + tolerance_zero = 1e-15 + tolerance_intersect = 1e-15 + decimals = 7 + inf_value = np.inf + # char_len_vec = np.array([4, 8, 16, 32, 64, 128]) + char_len_vec = np.array([10, 20, 40]) + angle_tol_straighten = 5 + merge_threshold = 0.86 # 0.5, 0.75, 0.86 + angle_tol_remove_segm = np.arctan(0.35) * 180 / np.pi # (anywhere between 15-25 degrees should be fine) + + # angle_tol_straighten = 0 + # angle_tol_remove_segm = 0 + + # angle_tol_remove_segm = 45 + + reuse_clean = True + straighten_first = True + mesh_raw = True + num_partition_x = 1 + num_partition_y = 1 + tot_partitions = num_partition_x * num_partition_y + + # Filename for input array: + # filename_base = 'Whitby_norm' + # filename_base = 'Brejoes_norm_with_inter' # Brejoes_fracdata_norm_with_intersections + filename_base = 'FracData_test_with_inter' + filename_raw = filename_base + '.txt' + + if not os.path.exists(filename_base): + os.makedirs(filename_base) + + # Load fracture data set: + act_frac_sys_raw = np.genfromtxt(filename_raw) + act_frac_sys_raw = np.round(act_frac_sys_raw * 10 ** decimals) * 10 ** (-decimals) + len_raw_sys = np.sqrt((act_frac_sys_raw[:, 0] - act_frac_sys_raw[:, 2]) ** 2 + + (act_frac_sys_raw[:, 1] - act_frac_sys_raw[:, 3]) ** 2) + act_frac_sys_raw = act_frac_sys_raw[np.where(len_raw_sys > tolerance_zero)[0]] + act_frac_sys_raw = extract_unique_nodes(act_frac_sys_raw) + + # Reservoir properties: + height_res = 50 + origin_x = 0 + origin_y = 0 + margin = 25 + length_x = np.max(act_frac_sys_raw[:, [0, 2]]) + length_y = np.max(act_frac_sys_raw[:, [1, 3]]) + + box_data = np.array([[origin_x - margin, origin_y - margin], + [length_x + margin, origin_y - margin], + [length_x + margin, length_y + margin], + [origin_x - margin, length_y + margin]]) + + # First find all intersections: + system_out_par, frac_order_vec_par, partition_lines = \ + calc_intersections_segm_parallel(act_frac_sys_raw, np.zeros_like(act_frac_sys_raw[:, 0]), tolerance_intersect, tolerance_zero, + num_partition_x, num_partition_y) + + # Stack output from all domain together: + act_frac_sys = system_out_par[0] + for ii in range(1, tot_partitions): + act_frac_sys = np.vstack((act_frac_sys, system_out_par[ii])) + + act_frac_sys = extract_unique_nodes(act_frac_sys) + # + # act_frac_sys = np.array(act_frac_sys_raw, copy=True) + # act_frac_sys_raw_int = np.array(act_frac_sys, copy=False) + + # Perform loop for all characteristic lengths: + for jj, char_len in enumerate(char_len_vec): + # Start from old network or from previously cleaned: + if reuse_clean and jj > 0: + act_frac_sys = act_frac_sys_cln + + act_frac_sys_cln, unique_nodes_cln, incidence_matrix_cln = \ + full_cleaning(act_frac_sys, char_len, decimals, tolerance_zero, angle_tol_straighten, angle_tol_remove_segm, + straighten_first, merge_threshold) + + # Make sure to catch all the intersections after procedure for coherent mesh: + system_out_par, frac_order_vec_par, partition_lines = \ + calc_intersections_segm_parallel(act_frac_sys_cln, np.zeros_like(act_frac_sys_cln[:, 0]), + tolerance_intersect, tolerance_zero, + num_partition_x, num_partition_y) + + # Stack output from all domain together: + act_frac_sys_cln = system_out_par[0] + for ii in range(1, tot_partitions): + act_frac_sys_cln = np.vstack((act_frac_sys_cln, system_out_par[ii])) + + act_frac_sys_cln = extract_unique_nodes(act_frac_sys_cln) + + # Find unique nodes: + unique_nodes_cln = np.unique(np.vstack((act_frac_sys_cln[:, :2], act_frac_sys_cln[:, 2:])), axis=0) + incidence_matrix_cln, order_discr_nodes_cln = create_graph(act_frac_sys_cln, unique_nodes_cln, + np.arange(act_frac_sys_cln.shape[0]), tolerance_zero) + + # Write final result to file (frac_sys, geo-file, and mesh final results as well): + char_len_boundary = char_len * 1 + + # Write fracture system to .txt for later use: + filename_clean = os.path.join(filename_base, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.txt') + write_new_frac_sys(act_frac_sys_cln, filename_clean) + + # Filenames for meshing: + filename_geo_cln = os.path.join(filename_base, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.geo') + filename_out_cln = os.path.join(filename_base, filename_base + '_mergefac_' + str(merge_threshold) + '_clean_lc_' + str(char_len) + '.msh') + filename_geo_raw = os.path.join(filename_base, filename_base + '_raw_lc_' + str(char_len) + '.geo') + filename_out_raw = os.path.join(filename_base, filename_base + '_raw_lc_' + str(char_len) + '.msh') + + # Create geo-file and mesh result (clean): + create_geo_file(act_frac_sys_cln, unique_nodes_cln, incidence_matrix_cln, filename_geo_cln, decimals, + height_res, char_len, box_data, char_len_boundary) + + mesh_geo_file(filename_geo_cln, filename_out_cln) + + if mesh_raw: + # Create geo-file and mesh result (raw): + order_discr_org = np.arange(act_frac_sys_raw.shape[0]) + unique_nodes_org = np.unique(np.vstack((act_frac_sys_raw[:, :2], act_frac_sys_raw[:, 2:])), axis=0) + incidence_matrix_org, order_discr_nodes_org = create_graph(act_frac_sys_raw, unique_nodes_org, order_discr_org, + tolerance_zero) + + unique_segm_list, segm_count = np.unique(incidence_matrix_org[:, 1], return_counts=True) + mask_2 = segm_count != 2 + + if any(mask_2): + print('SEGMENT WITH MORE THAN 2 NODES, PROBABLY TO LOOSE ZERO FOR FINDING SIMILAR NODES!!!') + sys.exit(0) + + create_geo_file(act_frac_sys_raw, unique_nodes_org, incidence_matrix_org, filename_geo_raw, decimals, + height_res, char_len, box_data, char_len_boundary) + + mesh_geo_file(filename_geo_raw, filename_out_raw) + + +if __name__ == "__main__": + freeze_support() + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6bad103 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy +scipy