From f8058f07a9ee5835906cb13d510917bd44868879 Mon Sep 17 00:00:00 2001 From: Nicholson Koukpaizan Date: Sun, 12 Apr 2026 21:04:04 -0400 Subject: [PATCH 01/14] Fix unit test README paths. --- tests/unit/opflow/gradient/README.md | 6 +++--- tests/unit/opflow/objective/README.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit/opflow/gradient/README.md b/tests/unit/opflow/gradient/README.md index 18c85660..cc8d6d59 100644 --- a/tests/unit/opflow/gradient/README.md +++ b/tests/unit/opflow/gradient/README.md @@ -1,5 +1,5 @@ -See [objective_function_g_test_design.md](./tests/unit/opflow/gradient/objective_function_g_test_design.md) for a description of how this unit test is formulated. +See [objective_function_g_test_design.md](./objective_function_g_test_design.md) for a description of how this unit test is formulated. -Please use the script [gen_network.py](./tests/unit/opflow/objective/gen_network.py) to generate a new network if necessary. The script takes either a command line argument, or prompts you for the desired network size. +Please use the script [gen_network.py](./gen_network.py) to generate a new network if necessary. The script takes either a command line argument, or prompts you for the desired network size. -The existing datafiles for this unit test is stored in [datafiles/unit/opflow/gradient](./datafiles/unit/opflow/gradient). +The existing datafiles for this unit test is stored in [datafiles/unit/opflow/gradient](../../../../datafiles/unit/opflow/gradient). diff --git a/tests/unit/opflow/objective/README.md b/tests/unit/opflow/objective/README.md index 08db26a6..2c9f7c29 100644 --- a/tests/unit/opflow/objective/README.md +++ b/tests/unit/opflow/objective/README.md @@ -1,5 +1,5 @@ -See [objective_function_test_design.md](./tests/unit/opflow/objective/objective_function_test_design.md) for a description of how this unit test is formulated. +See [objective_function_test_design.md](./objective_function_test_design.md) for a description of how this unit test is formulated. -Please use the script [gen_network.py](./tests/unit/opflow/objective/gen_network.py) to generate a new network if necessary. The script takes either a command line argument, or prompts you for the desired network size. +Please use the script [gen_network.py](./gen_network.py) to generate a new network if necessary. The script takes either a command line argument, or prompts you for the desired network size. -The existing datafiles for this unit test is stored in [datafiles/unit/opflow/objective](./datafiles/unit/opflow/objective). +The existing datafiles for this unit test is stored in [datafiles/unit/opflow/objective](../../../../datafiles/unit/opflow/objective). From 99b97c00c648b579d026e3945dcd71b8d20bdaca Mon Sep 17 00:00:00 2001 From: Nicholson Koukpaizan Date: Sun, 12 Apr 2026 21:18:03 -0400 Subject: [PATCH 02/14] Fix unit test Jacobian filename. --- .../equality/{Jacobian.JPG => Jacobian.jpg} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/unit/opflow/constraint_jacobian/equality/{Jacobian.JPG => Jacobian.jpg} (100%) diff --git a/tests/unit/opflow/constraint_jacobian/equality/Jacobian.JPG b/tests/unit/opflow/constraint_jacobian/equality/Jacobian.jpg similarity index 100% rename from tests/unit/opflow/constraint_jacobian/equality/Jacobian.JPG rename to tests/unit/opflow/constraint_jacobian/equality/Jacobian.jpg From d9fd5d251055af31c802d6db0e832a3b5f9e2f70 Mon Sep 17 00:00:00 2001 From: pelesh Date: Tue, 14 Apr 2026 15:44:24 -0400 Subject: [PATCH 03/14] Fix line constraint bug in HiOp MDS module. (#32) * Fix line constraint bug in HiOp MDS module. --------- Co-authored-by: pelesh --- .gitignore | 1 + .../test_validation/case118.m/G_valid.txt | 454 ++--- .../test_validation/case118.m/Hess_valid.bin | Bin 55056 -> 55056 bytes .../test_validation/case118.m/Jeq_valid.bin | Bin 25104 -> 25104 bytes .../case118.m/Lambda_valid.txt | 472 ++--- .../test_validation/case118.m/X_valid.txt | 686 +++---- .../test_validation/case118.m/grad_valid.txt | 108 +- .../case118.m/obj_value_valid.txt | 2 +- .../test_validation/case9mod.m/G_valid.txt | 72 +- .../test_validation/case9mod.m/Gl_valid.txt | 36 +- .../test_validation/case9mod.m/Hess_valid.bin | Bin 2128 -> 2128 bytes .../test_validation/case9mod.m/Jeq_valid.bin | Bin 1456 -> 1456 bytes .../case9mod.m/Jineq_valid.bin | Bin 952 -> 952 bytes .../case9mod.m/Lambda_valid.txt | 72 +- .../test_validation/case9mod.m/X_valid.txt | 46 +- .../test_validation/case9mod.m/grad_valid.txt | 6 +- .../case9mod.m/obj_value_valid.txt | 2 +- .../case_ACTIVSg200.m/G_valid.txt | 1692 ++++++++-------- .../case_ACTIVSg200.m/Gl_valid.txt | 980 ++++----- .../case_ACTIVSg200.m/Hess_valid.bin | Bin 44160 -> 44160 bytes .../case_ACTIVSg200.m/Jeq_valid.bin | Bin 35648 -> 35648 bytes .../case_ACTIVSg200.m/Jineq_valid.bin | Bin 25496 -> 25496 bytes .../case_ACTIVSg200.m/Lambda_valid.txt | 1780 ++++++++--------- .../case_ACTIVSg200.m/X_valid.txt | 950 ++++----- .../case_ACTIVSg200.m/grad_valid.txt | 62 +- .../case_ACTIVSg200.m/obj_value_valid.txt | 2 +- .../model/power_bal_hiop/pbpolhiopkernels.cpp | 4 +- .../power_bal_hiop/pbpolrajahiopkernels.cpp | 4 +- 28 files changed, 3716 insertions(+), 3715 deletions(-) diff --git a/.gitignore b/.gitignore index 080c11d0..17a5b464 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ myenv/ *.DS_Store launcher/config.yaml launcher/run.sh +*.warning diff --git a/datafiles/test_validation/case118.m/G_valid.txt b/datafiles/test_validation/case118.m/G_valid.txt index 6264dd0b..0c33e612 100644 --- a/datafiles/test_validation/case118.m/G_valid.txt +++ b/datafiles/test_validation/case118.m/G_valid.txt @@ -1,237 +1,237 @@ 236 -2.4424906541753444e-15 -7.8548278992229825e-15 --1.6653345369377348e-16 --1.6375789613221059e-15 --3.4416913763379853e-15 --3.1918911957973251e-15 --9.7699626167013776e-15 --4.3853809472693683e-14 -1.3322676295501878e-14 -2.8699265186560297e-14 --1.1102230246251565e-15 --2.0899948438568572e-14 +-6.5503158452884236e-14 +1.992850329202156e-14 +-2.3869795029440866e-15 +1.6125989432680399e-14 +3.4416913763379853e-15 +1.9900747716405931e-14 +-3.6637359812630166e-14 +3.6126657221302594e-13 +-3.9213077229760529e-13 +3.4267033655055457e-13 +8.6486373618299694e-13 +2.133015986061082e-13 -3.0531133177191805e-15 -1.1084883011491797e-14 -5.9828691112429055e-08 -3.1765439056918865e-07 --5.1173582260588546e-08 --6.2713603199426871e-07 --1.1455012050021196e-08 -3.096439040728427e-07 --1.5543122344752192e-15 --5.7454041524351851e-15 -4.1078251911130792e-15 -1.4432899320127035e-15 -1.27675647831893e-15 -1.6375789613221059e-15 -5.5511151231257827e-16 -3.767819389821625e-15 -6.6613381477509392e-16 -8.7152507433074788e-15 --1.1102230246251565e-15 -3.6082248300317588e-16 -6.4392935428259079e-15 -1.9290125052862095e-14 --4.9960036108132044e-16 --7.7715611723760958e-16 --1.6375789613221059e-15 -2.2759572004815709e-15 -1.609823385706477e-15 --1.1379786002407855e-15 -2.1094237467877974e-15 -3.4833247397614286e-15 --3.3306690738754696e-16 --7.0776717819853729e-16 -3.8333206386909069e-08 -1.2253454581556689e-07 --3.8339040275836567e-11 -1.3045120539345589e-15 --5.5277088240046623e-08 --4.6095156797099079e-07 --7.9029900401650366e-09 -2.7927213164247178e-07 -2.3173858276770432e-08 -5.8120155965735165e-08 -9.7144514654701197e-16 -5.0515147620444623e-15 --2.4424906541753444e-15 --8.021361352916756e-15 --6.6613381477509392e-16 --3.5527136788005009e-15 --1.7208456881689926e-15 --2.4980018054066022e-15 -3.1086244689504383e-15 -8.1878948066105295e-15 -3.0696085950854268e-09 -9.8633369527423298e-09 -4.2675200151442994e-08 -1.5246768239607356e-07 -6.9159228899273728e-09 -2.944569046925416e-08 -4.163336342344337e-15 -4.7989390239422391e-14 --5.8219135956605328e-08 --2.5625674549001332e-07 --2.6328057511904035e-09 -4.2206670158861925e-08 -4.3698453744411836e-09 -1.3036587490078411e-08 -3.1083929319386527e-09 -7.9625719073828094e-09 --1.1102230246251565e-16 -3.0253577421035516e-15 -1.7763568394002505e-15 --2.7755575615628914e-16 --1.6653345369377348e-16 -6.106226635438361e-16 -1.0824674490095276e-15 +2.0648413534551935e-13 +-9.0594198809412774e-14 +1.4560574967958928e-12 +1.4654943925052066e-13 +-1.4210854715202004e-14 +-8.8817841970012523e-14 +3.9979131116751887e-13 +-9.1038288019262836e-15 +3.1363800445660672e-15 +-6.0951244051921094e-14 +2.2570834090629432e-13 +-5.5344617777564054e-14 +6.1589622291080559e-14 +-7.6938455606523348e-14 +8.6368412421933272e-14 +5.4984905517585503e-12 +-2.4480972804497014e-12 +4.418687638008123e-14 +6.1645133442311817e-14 +3.9235281690253032e-13 +-2.9559688030644793e-14 +5.1356696673110491e-12 +3.8641867483590886e-12 +1.9720891586416656e-12 +5.6540994108900122e-11 +4.2460479576789112e-13 +-2.9559688030644793e-14 +1.8995915951336428e-13 +1.0588752097362431e-14 +2.206013149930186e-13 +-6.0368376963992887e-15 +2.4136248555350903e-13 +-1.0907941216942163e-14 1.429412144204889e-15 -4.4408920985006262e-16 -5.7315263646273706e-15 -1.1102230246251565e-16 -3.3029134982598407e-15 -1.4039219564665473e-08 -3.2171496577859671e-08 -5.5511151231257827e-17 -1.0408340855860843e-15 -7.4738799926699073e-08 -2.4616311994352102e-07 -5.5511151231257827e-16 -3.5180192092809648e-15 -2.7755575615628914e-15 --4.5102810375396984e-15 -7.2164496600635175e-16 -1.9567680809018384e-15 -2.7755575615628914e-17 -1.457167719820518e-15 -7.9158901655773661e-14 --1.4432899320127035e-15 -4.6185277824406512e-14 -1.0824674490095276e-15 -1.1102230246251565e-14 -5.0975890175664063e-13 -1.2212453270876722e-15 --2.0261570199409107e-15 -4.7739590058881731e-15 -6.3837823915946501e-16 -6.6613381477509392e-15 +2.5156265959225266e-13 +2.042810365310288e-14 +-1.7763568394002505e-15 -4.8849813083506888e-15 --2.2204460492503131e-16 -1.1296519275560968e-14 --1.1657341758564144e-15 -5.6621374255882984e-15 -9.0366552019105484e-09 -4.5447928670450111e-08 --4.4408920985006262e-16 +9.2814644858663087e-14 +-9.9920072216264089e-15 +1.0597078770047119e-13 +1.3405943022348765e-14 +-2.0539125955565396e-15 +2.5979218776228663e-14 +-6.2450045135165055e-15 +2.6600943670018751e-13 +2.3625545964023331e-13 +-1.8152146452621309e-14 +2.1338486533295509e-13 +1.9872992140790302e-14 +1.2234657731369225e-13 +1.0261236305098009e-13 +8.8068441428390543e-14 +4.3221537460169657e-11 +5.1473464379725442e-11 +1.5358325722303334e-11 +-1.2113365865928927e-12 +3.6712299866792364e-12 +2.1813234551970595e-10 +2.2084778450448539e-11 +-1.7597034940308731e-12 +-4.1744385725905886e-14 +4.4764192352886312e-13 +2.354560990625032e-12 +-3.2272795547072519e-13 +-7.6338935173225764e-13 +2.2842533420330824e-11 +1.2464473897466632e-12 +-1.0888512314011223e-13 +8.6886053907164751e-13 +9.943157408542902e-13 +3.3534286458802853e-13 +3.4361402612148595e-14 +2.5265900482907e-13 +3.3875680038875089e-14 +1.5165646516379638e-13 +9.0205620750793969e-15 +-4.2132963784524691e-14 +4.7450932072479191e-13 +1.3322676295501878e-15 +1.7763568394002505e-15 +5.1625370645069779e-15 +4.7045700668491008e-15 +2.2777335573209712e-12 +-1.3662404541037176e-12 +2.8187452372208099e-12 +-3.3843067237526725e-13 +2.5345281429167699e-12 +-3.5534075681908917e-13 +7.7210460247556512e-13 +-1.8367252163642434e-13 +4.3523518122867699e-13 +-6.5156213757688874e-14 +1.4069889697765348e-10 +2.4766633188733067e-11 +9.20234999313152e-11 +3.4102165535898621e-12 +2.2624457862718828e-11 +9.0389434825866033e-10 +3.2395197635537443e-12 +-3.9016012642889564e-13 +3.6511904610847523e-12 +-5.5713766933251918e-13 +1.0738299138779439e-11 +-1.2378986724570495e-12 +1.7985612998927536e-14 +3.3029134982598407e-15 +1.3988810110276972e-14 +-3.1252778143198157e-14 +-1.5765166949677223e-14 +2.2737367544323206e-13 +9.9920072216264089e-15 +7.1054273576010019e-15 +-3.9968028886505635e-15 +-1.4210854715202004e-14 +6.3060667798708891e-14 +3.4061642395499803e-13 +1.9872992140790302e-14 -3.5527136788005009e-15 -3.3306690738754696e-15 -1.4210854715202004e-14 -1.3535342846537901e-09 -2.975817872119535e-07 --1.0641273817668662e-07 --6.5472079735506838e-07 -2.6523071960937727e-08 -9.8561244221695432e-08 -9.9670196540557754e-09 -2.8585239775225091e-07 --1.3314838231970327e-07 --5.7684568810500991e-07 -2.6049245149817324e-08 -7.3168364367326433e-08 -2.4424906541753444e-15 +1.1102230246251565e-15 +5.0515147620444623e-15 +1.2456702336294256e-13 +-2.4868995751603507e-14 +1.6875389974302379e-14 +8.4376949871511897e-15 +1.9761969838327786e-14 +1.9378942894832107e-13 +3.5527136788005009e-14 -6.2172489379008766e-15 -4.3021142204224816e-16 -1.9914625504213745e-15 --1.8735013540549517e-16 --4.891920202254596e-15 --8.8817841970012523e-16 --1.0602629885170245e-14 -3.2329554366938851e-08 -7.0652755312927695e-08 --1.8873791418627661e-15 --6.2727600891321345e-15 -1.125471977836412e-07 -3.1083419271826784e-07 --1.1546319456101628e-14 --1.9317880628477724e-14 -2.8670041340994601e-08 -1.0987524567962481e-07 --1.7138208097122742e-07 --8.0154368337082005e-07 -5.6796399527936359e-10 -2.2921460285374451e-07 +1.9331758416285538e-14 +1.0533240946131173e-14 +4.6976311729451936e-15 +2.9171109972025988e-14 +-4.4408920985006262e-15 +-7.382983113757291e-15 +6.8833827526759706e-15 +1.4432899320127035e-15 +4.1078251911130792e-15 +1.1934897514720433e-15 +1.532107773982716e-14 +2.0616841567289157e-13 2.6645352591003757e-15 -1.1435297153639112e-14 --1.4988010832439613e-15 --5.134781488891349e-15 --7.7715611723760958e-16 -1.4988010832439613e-15 -6.8485304094423327e-09 -5.8712512879255385e-08 -5.8286708792820718e-16 -1.2490009027033011e-15 --6.9388939039072284e-17 +9.1038288019262836e-15 +1.6653345369377348e-15 +-1.1712852909795402e-14 +6.6724403779971908e-14 +9.4535490546832079e-14 +-5.9299787302791174e-14 +7.1054273576010019e-15 +2.6645352591003757e-14 +4.4686476741162551e-15 +4.4020342926387457e-14 +-6.2866378769399489e-15 +1.6542323066914832e-14 +-4.7184478546569153e-15 +3.5837999234900053e-13 +-5.0709436649754025e-14 +4.6876391657235672e-13 +5.0986992405910314e-14 +-2.8809593599632422e-13 +3.5785957530620749e-12 +2.1760371282653068e-14 3.6082248300317588e-16 -3.5550524968286368e-08 -1.4038331955235073e-07 --1.7782608963123891e-07 --6.1924752886577394e-07 -4.601924352698461e-08 -1.464605403067587e-07 --6.2589338989393895e-09 -3.6377151291233645e-15 -6.5693034789759963e-08 -2.5901755673629623e-07 -3.3306690738754696e-16 --2.7755575615628914e-16 --1.609823385706477e-15 -4.3298697960381105e-15 -2.7200464103316335e-15 --2.2759572004815709e-15 -1.0111191550699061e-08 -4.2622062851327414e-08 -1.8713332744502154e-08 -8.3925519117622471e-08 -1.8042963512154842e-08 -7.2410083193363839e-08 -4.9979361205210182e-09 -3.7955695496305619e-08 -1.1779466291272911e-13 -9.1593399531575415e-15 -2.4980018054066022e-16 --2.1371793224034263e-15 --1.1657341758564144e-15 +4.7739590058881731e-14 +-9.1593399531575415e-16 +3.1086244689504383e-15 +6.7168492989821971e-15 +7.4940054162198066e-16 +8.0317696937726168e-16 +3.5416114485542494e-14 +1.0658141036401503e-14 +-1.1102230246251565e-16 +-3.8302694349567901e-15 +3.5471625636773751e-14 +3.1863400806741993e-14 +3.6082248300317588e-15 +8.3821838359199319e-15 +3.0753177782116836e-14 +2.3619994848900205e-14 +1.8735013540549517e-14 +1.3877787807814457e-16 +5.1458837191376006e-14 +3.1905034170165436e-14 +5.2513549064769904e-14 +3.8212488728817107e-14 +7.0678130015267016e-11 +-4.9527049128528233e-12 +1.2240208846492351e-14 +6.744604874597826e-15 +6.6058269965196814e-15 +2.4147350785597155e-15 +8.7599927311998727e-11 +-2.3894108913680157e-11 +2.1494250823650418e-11 +2.2908781815988988e-09 +3.8540337587988915e-10 +-1.1009332334666055e-10 +1.8318679906315083e-15 +3.5388358909926865e-14 +-3.0492275371329924e-13 +1.1102230246251565e-13 +1.3752887717544127e-14 +9.0951551845463996e-15 +2.3911428392864309e-14 +4.1910919179599659e-15 +-1.103006574965093e-13 +6.8267613784200876e-13 +-2.7366997557010109e-14 +-1.8091734707570417e-13 +7.3274719625260332e-14 +-2.1077584122508597e-13 +-1.3539169785303784e-13 +1.3937184739631903e-12 +4.3715031594615539e-15 -1.1379786002407855e-15 -1.4210854715202004e-13 --2.2704060853584451e-14 -5.0459636469213365e-14 -3.6820824167449473e-12 -6.1728400169158704e-13 --1.2023715356690445e-13 -7.2164496600635175e-16 --2.8033131371785203e-15 --2.2204460492503131e-16 -1.1102230246251565e-16 --4.8988590961585032e-15 --8.6684132094561051e-15 +1.890154699424329e-14 +-2.7755575615628914e-16 +-2.8421709430404007e-14 +7.9644624229047167e-13 +2.0539125955565396e-15 -9.5756735873919752e-16 -6.3837823915946501e-16 --3.6637359812630166e-15 --1.0103029524088925e-14 -1.8873791418627661e-15 -4.0093796338513954e-15 -2.1649348980190553e-15 -1.3045120539345589e-15 --2.5118795932144167e-15 -8.174017018802715e-15 -1.7069679003611782e-15 --8.2434059578417873e-15 -2.4702462297909733e-15 -1.2156942119645464e-14 --6.5075942412562426e-09 --7.5786599218474748e-14 -5.5511151231257827e-17 -8.1878948066105295e-16 -3.4972025275692431e-15 -1.4155343563970746e-15 +5.2735593669694936e-15 +8.5209617139980764e-15 diff --git a/datafiles/test_validation/case118.m/Hess_valid.bin b/datafiles/test_validation/case118.m/Hess_valid.bin index b902f68a48256a93afbdd8aa22a349f2e4702bd6..3de7059100e34be1ddf7b98aaff3db0652c52a11 100644 GIT binary patch literal 55056 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 z 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 diff --git a/datafiles/test_validation/case118.m/Jeq_valid.bin b/datafiles/test_validation/case118.m/Jeq_valid.bin index 93b98980652c2d46677a925f26f9650866fcd4e7..fd4f7a1037262cf5f1319b36dbe5029bbc2ca6a2 100644 GIT binary patch delta 16229 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 diff --git a/datafiles/test_validation/case118.m/Lambda_valid.txt b/datafiles/test_validation/case118.m/Lambda_valid.txt index 54fde11d..57fe02a7 100644 --- a/datafiles/test_validation/case118.m/Lambda_valid.txt +++ b/datafiles/test_validation/case118.m/Lambda_valid.txt @@ -1,237 +1,237 @@ 236 -4052.9781708333267 -28.143883065761599 -4049.0371949806304 -16.812326405496126 -4030.2535307602502 -22.710834557040421 -3933.2757687677372 -1.1823174748104821e-07 -3922.1086276737924 -6.6079183430585022 -3997.2201946836126 -2.6820604217937249e-06 -4008.9958150917641 -0.31775465569133943 -3923.0331858750615 --1.3165043893810264e-07 -3855.3265421209112 --13.679932857232192 -3786.1090144713053 --1.2485367781584201e-06 -4012.9371919230834 -10.429487368174621 -4018.678448857504 -2.8573750522366113e-07 -4063.9743619861083 -24.183402575944225 -4041.0114073391705 --3.0400475677201211 -4041.7677603202706 -9.3181102035136438e-06 -4028.6453520122741 -5.8369321266968557 -3967.116213747076 --4.4555773090482216 -4026.4522956452406 -2.0792442227533833e-06 -4043.1665388307406 -0.69652885809859455 -4054.0853754621708 -12.283117555767992 -4036.5821011978619 -20.166755413775647 -3993.7688358843193 -18.361346779260984 -3900.11415210322 -2.8215548183116868 -3929.5646503296734 --1.1397229742723228e-08 -3761.9439547781794 --13.222632609608754 -3781.9248937246361 --3.8728778460859444e-09 -4019.844966048649 -4.0103631525916647e-08 -4060.3521012450519 -6.124544155751078 -4080.8357428360587 -3.5417392472902272 -3945.8453232922411 --1.7360402144698912 -4070.9344324561812 -4.2741473047454168e-08 -4029.7251621203586 -1.5203281935727666e-06 -4051.3874838948345 -6.7025297288630732 -4009.77561076244 --0.42844028242442833 -4020.633753752702 -0.63203298060629853 -4021.3254107387684 -1.4269428837252772e-05 -3991.1994332851036 --3.0934243254396079 -3966.5451686813053 -1.5997510992090964 -4082.7505211351872 -7.5298568105327943 -4098.6436528133854 -4.525871714415221e-08 -4124.7691383031442 -6.5534629545872027 -4081.9899258453825 -3.4643307391553232e-08 -4084.1727917088674 -1.7204493746040743 -4112.3657911187929 --2.4028262352724163 -4094.7845683772498 -8.204562744284928 -4004.1018200130347 --5.8252238997009184e-08 -3935.506855570492 --1.5637264564461726 -3939.8913116304661 --7.899280612959136 -3895.4148255577866 --3.0161382604524307e-07 -3969.2655648411569 -5.2544996430503144 -4065.9001777854173 -21.456984385246983 -4101.4654062526779 -23.899283217624365 -4109.1883743473136 -19.457089825989588 -4064.26297065683 -5.4990151978521918e-08 -4064.2684448533591 -2.0686763044234675e-05 -4065.1203422798199 -0.26314695937619786 -4042.8652630591564 -3.629389084169818 -4079.3859401329696 -13.371327428394141 -3931.6749358395887 -3.8128577368055361e-07 -3874.4371641174421 -0.32877033514645104 -3855.1852650866367 --2.6993025481466592e-07 -3874.523296475179 -3.1092270337040083e-07 -3896.2256746823059 -0.3963768737593617 -3859.501295577028 --2.4619667173747501 -3801.7199343075022 --0.58451254742662084 -3779.8895377480676 --21.50505302269849 -3846.3667621865279 --6.4710462969951967 -3794.4727339373494 -0.33917149805372709 -3757.0335326414756 --2.0075626440164008e-07 -3972.6641043457103 -2.0667542027361414e-05 -3976.1970933229031 --1.0215172701598003 -3974.307174695492 --7.3187520844362821e-08 -3980.0270552428983 --3.1166585804837432e-08 -4033.8625148332749 -22.911043021902927 -4003.5520295420429 -25.995838936897254 -4045.7060611145284 -44.464040505376602 -3894.2822977336582 -1.4548429648916106 -3904.6745545055537 -9.0755958496188622 -3890.239781288124 -10.218831509439214 -3806.4615696966166 --2.0860694592611096e-07 -3798.3448421127077 -1.5536019085150565 -3912.6084641449011 -11.674348458769101 -3890.0142570421481 -9.4361804382346417 -3829.6642546838957 -18.197940022081699 -3777.3715188587316 -10.367889970763914 -3820.2509601851666 -11.738684271125839 -3813.1048437277282 --6.0723896186576282e-07 -3730.679602150642 -11.670665673257487 -3653.5226975533328 --1.6071668476693689e-07 -3828.6300150649759 -7.5488277680394296e-08 -3812.4456651523101 -2.184481575575655e-08 -3760.8709940698627 -10.912424960718615 -3826.7949266982305 -24.483136011150478 -3865.4101186234848 -26.105722842504758 -3899.6707081933878 -42.090533472009497 -3889.9357899629449 -23.725510154560528 -3858.2559261817105 -17.032318351856979 -3852.4890705227313 -4.7814951267953667 -3864.8722940549674 --4.4584678997132653e-08 -3835.6706501776575 --9.0442337419730529e-08 -3830.3466619766464 -19.070088435592179 -3786.7371200676239 -14.544176213793186 -3912.3115249795196 --1.4823223434547134e-07 -3988.6169210714293 -0.43172087940023124 -4010.3261697689736 -1.0123443028188306e-06 -4021.5524879543591 -9.3557453668404253 -4058.0550406979573 -1.1430744811647788e-08 -4020.9075339143915 -0.82160944598409591 -4023.5735806935636 -1.455155761107793 -4014.0681939299157 -1.8569377633153272e-05 -3957.8799685097074 --6.3325103765305921e-07 -4072.9644595233813 --5.6535351525267232e-07 -3978.4734535666389 --4.4788677558421686e-07 -4041.6594364438492 -4.33038632895465 -4042.3140654807221 -4.7159845376393665 -3799.0927604274993 -9.0038647239925962e-10 -4068.4332788732781 -16.517680719325245 -4043.7163848163505 -43.502549091649747 +4052.9780135367537 +28.14388753082331 +4049.0369669322422 +16.812322630300734 +4030.2533288306822 +22.710816220422952 +3933.2755230740886 +1.5318599682461511e-06 +3922.1083731975696 +6.6078752091429713 +3997.2197893957882 +3.4749061074089642e-05 +4008.9954534495268 +0.31776732344539593 +3923.0329531351103 +-1.7057119525455135e-06 +3855.3263179658002 +-13.679883678786007 +3786.108797566761 +-1.6176505029082751e-05 +4012.9369351844821 +10.429481695605167 +4018.6781735506961 +3.7021080569730936e-06 +4063.9741499622669 +24.183420927503231 +4041.0111696223894 +-3.0400473160681556 +4041.7676420874359 +0.00012074067826136515 +4028.6451173329165 +5.8369143111735919 +3967.116059840494 +-4.4555580972760476 +4026.4521821606281 +2.6941634934618132e-05 +4043.1664392360922 +0.69699601113371523 +4054.0852804703004 +12.283442755893718 +4036.5819897386937 +20.166991565841538 +3993.7686998967579 +18.361487281873416 +3900.1139999532834 +2.8215698833220522 +3929.5644684811105 +-1.4766633494615744e-07 +3761.9438338862847 +-13.222576388802766 +3781.9247647731277 +-5.0178053669738563e-08 +4019.8448672551026 +5.1959894381686211e-07 +4060.3520024852501 +6.1245287984859855 +4080.8356420707291 +3.541728420054302 +3945.845155457399 +-1.7360567453726123 +4070.934327510498 +5.5377610463985401e-07 +4029.7250589741184 +1.9697827132044224e-05 +4051.3873418307526 +6.7023835242961969 +4009.7754470263699 +-0.42897080295400591 +4020.6335978087332 +0.63210365865729246 +4021.3252569719398 +0.00018594950597414017 +3991.1992745417556 +-3.0937869535341687 +3966.5450300716684 +1.5995608931711605 +4082.7504186624619 +7.5297123346462325 +4098.6435907634495 +5.8638653318391232e-07 +4124.769095627913 +6.5534591975435017 +4081.9898922642346 +4.4885248364632998e-07 +4084.1726325870604 +1.720014219949439 +4112.3656885504379 +-2.4030272988069861 +4094.7844882472959 +8.204466560668271 +4004.1017402090843 +-7.5474949936436746e-07 +3935.5067776722399 +-1.5637449285413476 +3939.8912335130608 +-7.899302015655465 +3895.4147538619791 +-3.9078330485643252e-06 +3969.2654969635337 +5.2546197445619249 +4065.900156539652 +21.457183206410324 +4101.465400926093 +23.899436022723105 +4109.18836957653 +19.457149042977374 +4064.262951376098 +7.1254523370100386e-07 +4064.2684278682013 +0.00026949912219590051 +4065.1203257735669 +0.26373131088387991 +4042.8652257797339 +3.6297703278876483 +4079.3859288259277 +13.37168976865993 +3931.6748598301051 +4.9401131184844155e-06 +3874.43707977535 +0.32876433208207051 +3855.1851782706585 +-3.497349926632914e-06 +3874.5232140287508 +4.0282407048826059e-06 +3896.2255936457918 +0.39639125919154022 +3859.5012118572104 +-2.4619656426728498 +3801.7198633155563 +-0.58458082185339566 +3779.8894787014428 +-21.505015878225425 +3846.3666865477799 +-6.4710535198439505 +3794.4726583263287 +0.33916064585985184 +3757.0334556285061 +-2.6010683051126212e-06 +3972.6639479898381 +0.00026774985364286957 +3976.1968960247391 +-1.0214096696038557 +3974.3069243410432 +-9.4824514830321944e-07 +3980.0268293857794 +-4.0378023506467058e-07 +4033.8624506082865 +22.911291955596557 +4003.5519579085872 +25.996047122296911 +4045.7060300010571 +44.464280710374787 +3894.2822172303277 +1.4550347379658601 +3904.6744789624313 +9.0757540812283946 +3890.2397039416187 +10.218942622783061 +3806.4614910952751 +-2.7027589284056723e-06 +3798.3447644057419 +1.5535989270194746 +3912.6083566543871 +11.67438205449292 +3890.0141355904852 +9.4361869496584951 +3829.6641003835102 +18.197918518447995 +3777.3713513220328 +10.36787274250403 +3820.2507107801648 +11.738820269016957 +3813.1045080738977 +-7.8676602393014391e-06 +3730.6794579576508 +11.670630153347496 +3653.5225823691876 +-2.0822886849131659e-06 +3828.6298825133167 +9.7805685532277724e-07 +3812.4455122459653 +2.83024418563602e-07 +3760.8708353145953 +10.912394984379361 +3826.7947605786244 +24.483098528181461 +3865.4099525819415 +26.105700517773627 +3899.6705694430825 +42.090511671099733 +3889.9356709268277 +23.725481588263289 +3858.2558224615923 +17.032283804908317 +3852.4889220447158 +4.7814313693033048 +3864.8720921870618 +-5.776729287307108e-07 +3835.6704077047775 +-1.1717936566619643e-06 +3830.3464519538088 +19.07004057597101 +3786.7369388695538 +14.544119915372098 +3912.3112990845971 +-1.9193757284992271e-06 +3988.6167655949098 +0.43323617127932462 +4010.3260469734523 +1.3156046369416962e-05 +4021.5523793065367 +9.3557588083835217 +4058.0549900026035 +1.4810173586725449e-07 +4020.9074146028975 +0.82168916465369946 +4023.573464830688 +1.4552701399581971 +4014.0680769671035 +0.00024056603388397503 +3957.8797788274392 +-8.2046542864710138e-06 +4072.9644269490814 +-7.3249470495050187e-06 +3978.4732722231283 +-5.8030118934518438e-06 +4041.6593357926349 +4.3303814001942849 +4042.3139654408355 +4.7159782259688265 +3799.0926845657141 +1.1664974994931771e-08 +4068.4330131474449 +16.517658864516665 +4043.7163411651832 +43.502775494729136 diff --git a/datafiles/test_validation/case118.m/X_valid.txt b/datafiles/test_validation/case118.m/X_valid.txt index a8fe7f58..d07a401b 100644 --- a/datafiles/test_validation/case118.m/X_valid.txt +++ b/datafiles/test_validation/case118.m/X_valid.txt @@ -1,345 +1,345 @@ 344 -0.29835425287410255 -1.0331697033016569 -0.26489086263838546 -0.14999998506907955 -0.3000514816042073 -1.0387967945707413 -0.30611500796805713 -1.0380037651724436 -0.35138837493530251 -1.0599999978438677 -5.1571483535978252e-10 -0.71517739665337055 -0.35911307532081782 -1.0574525055459874 -0.31914492646123305 -1.0526943509844715 -2.424063783197273e-07 -0.33285903416511503 -0.31394852756652353 -1.0510172953106192 -0.43113652036308475 -1.0409882257186989 -0 --0.78632437911854747 -0.54015616230668584 -1.0600000000000001 -0.65708686805309091 -1.0529795615027151 -4.0187452859062232 --0.99676503929616689 -0.31681494195659743 -1.0460055501259766 -0.31121371540058312 -1.0499550340762787 -0.85793833952452359 -0.54439509565320399 -0.29727090861885069 -1.0344770184035015 -0.30142763541029988 -1.0488068316776593 -0.30071311018018632 -1.0485625928934612 -0.20883881396594398 -0.23840567341669983 -0.30616911704353783 -1.0461369563363305 -0.33340453959720801 -1.0599999943002061 -0.30590511710597434 -1.0503238421750103 -0.13226150070842196 -0.30453617746616951 -0.2994474747119496 -1.0477868474329799 -0.21583270593439088 -0.23999900264533242 -0.30490403917410569 -1.0361853570117543 -0.32318827400403943 -1.0313270495958318 -0.35575651644455702 -1.0345717224562545 -0.42246810998926604 -1.0487436017846368 -0.41338686245074313 -1.0462081752270054 -0 --0.073051955806020946 -0.53307572822774574 -1.0600000000000001 -1.9381383481044354 --0.46999995693545543 -0.56136670747432438 -1.0267818673979581 -2.7976220790279505 --0.27577253991374295 -0.34634239728528199 -1.0413721147572215 -0.099224861705238546 -0.25533848386361674 -0.32207294436275258 -1.0348811867084466 -0.30911918911234193 -1.0354315009177124 -0.40106030658752967 -1.0311990205323283 -0.31165149024846239 -1.0385626047618532 -0.072482705377674442 -0.27186810836959668 -0.33903901044454077 -1.0410403352020723 -0.14862583008576669 -0.21829629257098865 -0.29175319398360888 -1.0461533194864272 -0.30211003393058544 -1.0559212136974845 -0.048878121899405221 --0.079998372005584156 -0.29625852625153437 -1.0539852219168742 -0.29646699822675526 -1.0542609456202092 -0.10662708266904343 -0.19821342466733688 -0.30913104885228304 -1.0600000000000001 -0.37142920820558761 -1.0150293554310879 -0.27975413518448677 -1.0424525338969253 -0.27627277872717643 -1.0424887083849785 -0.49321826425730003 -0.28759590024346654 -0.2687480206545893 -1.0354647709506435 -0.29142362062027122 -1.0406221179101391 -0.4099496318390054 -0.22097683268265542 -0.2895786318303406 -1.0399686234002909 -0.31126617747362201 -1.0309005433115765 -0.33448045031733842 -1.0252648981437733 -0.37501495086474335 -1.0377211010707492 -0.1903896733560145 --0.041439435254253393 -0.40707672479568879 -1.0450156194816873 -0.39965156688610404 -1.0473020752878484 -0.41675561686152945 -1.0495620387036246 -1.9333231234937538 -0.1967997092964312 -0.38525577879406847 -1.0392119143053034 -0.34578253676344495 -1.0222158055519004 -0.33123480978441566 -1.0166493410863782 -0.31810010247414877 -1.0162984149774303 -0.3334462964602945 -1.0312457822083672 -0.49542311391918642 -0.34793157611129316 -0.33237710215093957 -1.0311699461992618 -0.32134223001491213 -0.19974972596445989 -0.33336050965208081 -1.0308952303301153 -0.32560171697174234 -0.14999733859757025 -0.34887950829557213 -1.0317509174322703 -0.33585888598732627 -1.0238559223338883 -0.37881541156014531 -1.046781894451992 -1.4970480758710056 -0.95668772298557681 -0.42944924481195307 -1.045740692771379 -0.44271681730939194 -1.0481190796342295 -1.4841482119444771 -0.31962880904426838 -0.43385116348379688 -1.0438410825366571 -0 -0.0088452435615244563 -0.42516680848907051 -1.0156705377671027 -0.45039086982873927 -1.0227094807270507 -0.49932709158338523 -1.015561892119712 -3.5223624668861233 --0.66999880959345903 -0.50387550531359515 -1.0600000000000001 -3.4885834909078888 --0.66999997737264561 -0.45820844515664877 -1.0465561486792343 -0.4887452013216681 -1.014644420731551 +0.29835432085008595 +1.0331694724037841 +0.26489017744779098 +0.14999968698512062 +0.30005157706609481 +1.0387965694826591 +0.30611509129432474 +1.0380035546855699 +0.35138848829703784 +1.0599998453020569 +1.2624542792473826e-07 +0.71517743723357274 +0.35911318956007887 +1.0574523572716725 +0.319145122838349 +1.0526941282164581 +3.2626258315138611e-06 +0.33285677229779254 +0.31394869283378057 +1.0510170742182623 +0.43113661711906953 +1.040988165123012 +1.0811425956570941e-07 +-0.78632195760697898 +0.54015624975175647 +1.0599999964219746 +0.65708693529672502 +1.0529795953375878 +4.0187447898248152 +-0.99676359346042365 +0.31681505137571692 +1.0460053508812566 +0.31121383167045436 +1.049954815056463 +0.85793822308098344 +0.54439428731526562 +0.29727099408532653 +1.0344767952997633 +0.30142772660367667 +1.0488065936716897 +0.30071314264071919 +1.0485623069799814 +0.20883837063844374 +0.23840716332010858 +0.30616920232262596 +1.0461367430324524 +0.33340457301907894 +1.0599997992758916 +0.30590513162358918 +1.0503236275621879 +0.13226120209292358 +0.30454110810165025 +0.29944754019270653 +1.0477863873388336 +0.21583234881628893 +0.2399868198629318 +0.30490409020119663 +1.036184982592995 +0.32318832289778876 +1.0313267400436859 +0.35575656584684928 +1.0345714905951784 +0.42246815363865786 +1.0487435000602974 +0.41338691911263681 +1.0462080841804238 +1.1906703050501758e-07 +-0.073051495800033658 +0.53307575317744993 +1.0600000025453371 +1.9381382125715674 +-0.46999932247081144 +0.56136673255807545 +1.0267819124266198 +2.7976218714702661 +-0.27576942201018767 +0.34634240918829617 +1.0413719674992252 +0.099224743910764274 +0.25533826825435019 +0.32207295357361221 +1.0348810250898377 +0.30911919936441984 +1.0354313253384617 +0.40106035637548981 +1.0311989263562438 +0.31165150351810234 +1.0385624250060805 +0.072482705461172289 +0.27186798276052859 +0.3390390271223549 +1.0410401671850225 +0.14862554731362287 +0.21829568664944413 +0.29175319056223509 +1.0461531136483764 +0.30210997969024916 +1.0559211602129215 +0.04887811729850159 +-0.079977267157200577 +0.29625854304839272 +1.0539848862679961 +0.29646702654435209 +1.0542605639008615 +0.10662666027638147 +0.19819590440671933 +0.30913101550342359 +1.0599998921764593 +0.37142921021160502 +1.01502928537007 +0.27975410163239739 +1.0424523249585034 +0.27627274856169137 +1.0424884450162599 +0.49321795628390086 +0.28759381604580547 +0.26874798259096738 +1.0354645137961551 +0.29142358117548184 +1.0406218856595959 +0.40994949516456464 +0.2209765078342372 +0.28957858212806092 +1.039968543627515 +0.31126614061597618 +1.0309004284073384 +0.33448042143969497 +1.0252647732295876 +0.37501493817120951 +1.0377209597119397 +0.19038966916339189 +-0.041439936866558648 +0.40707671194552825 +1.0450155138370567 +0.39965155153927018 +1.0473019584639773 +0.41675560193572819 +1.0495619304453208 +1.9333230470579144 +0.19679986580822231 +0.3852557766549411 +1.0392117399846421 +0.34578252967216117 +1.0222155932473456 +0.33123479203158501 +1.0166491428850226 +0.31810007035966731 +1.0162982610987183 +0.33344626194362154 +1.0312456650751782 +0.49542311131089395 +0.34796148735270765 +0.33237709732642784 +1.0311697009360212 +0.32134221381603323 +0.19975611089760445 +0.33336054644910224 +1.0308948567495089 +0.32560170106936592 +0.1499570772229728 +0.34887952787657694 +1.0317506263242915 +0.33585889581264583 +1.0238556402976788 +0.37881539361509803 +1.0467817640895274 +1.4970480151319421 +0.95668861734533572 +0.42944923528386236 +1.0457405772607358 +0.44271681055633472 +1.0481189634103594 +1.4841481409991519 +0.31962559261915507 +0.43385115402634794 +1.0438409772541959 +6.2450911583474268e-08 +0.0088448004581737141 +0.42516680145754882 +1.0156704658750721 +0.45039086410278856 +1.0227094394114227 +0.4993270733776683 +1.0155619818611175 +3.5223623209337549 +-0.66998445764050052 +0.50387548192491038 +1.0600000046036602 +3.4885833684026828 +-0.66999958726565245 +0.45820842856477773 +1.0465560966651837 +0.48874519612986123 +1.0146444240939116 0.52359877559829882 -1.0600000000000001 -4.5366605723631466 --1.1109652770152652 -0.41354120340057071 -1.0392651958119046 -1.5667821795297655e-08 -0.28877700969441394 -0.40971778802833569 -1.039458588177915 -0.40113081166055115 -1.0397961704788763 -1.7309292562908183e-08 --0.052012553237442243 -0.40732094311996797 -1.03826211839864 -2.5130162528866573e-08 --0.02219845747722226 -0.39981338172749081 -1.0219247791182777 -0.1693125906636869 -0.08999997937490567 -0.41497668973981916 -1.0241578424879751 -0.39974577507452896 -1.0118090296707247 -0.22853031637655555 -0.22999999421976608 -0.45589905517664076 -1.047058986448 -0 -0.69999952771246943 -0.4511129076904733 -1.042379848980614 -0.45590404882538121 -1.0436901751956706 -0.49307823392070654 -1.0600000000000001 -4.3084108402986834 --0.094332084755208087 -0.49060036612800606 -1.0107505674494499 -0.44459705037480945 -1.0377017639630275 -0.45236360549546861 -1.0400159487306027 -0.47424506713452025 -1.0427402649146671 -0.48983631482360385 -1.0505035926809094 -0 -0.22999994232443194 -0.47038420739734521 -1.0443220901443755 -0.47565261231358752 -1.0571042248517577 -0.036262097247563421 -0.035415368010693088 -0.5265177536313288 -1.0481492130713954 -0.58174276094342636 -1.0600000000000001 -5.0184413803382082 --0.24016116167420515 -0.48726367047532204 -1.0417816917295524 -0 -0.47214682394585805 -0.49246574295231932 -1.0456496026064612 -0 -0.015562910291431557 -0.5134952033649679 -1.0500035723854402 -0 -0.089999945701494083 -0.48424577603263885 -1.040008993257969 -0.46585019488540658 -1.0378903237971575 -0.45284380200688029 -1.0267611579007991 -0.45332036771476747 -1.0354646250021247 -0.46717205635864117 -1.0431441808034363 -0.46577739547397284 -1.0519319560744156 -0.45718776873667988 -1.0540449951208133 -0 --0.031739169228046669 -0.47378229643318731 -1.0584504938988741 -2.3129450178559554 -0.45758071551438961 -0.47693602085257508 -1.0427932497464698 -0.49972328503755664 -1.0468424200329551 -0.43818908190220635 -1.0514003713689282 -0.38246230522490549 -0.11701840544162181 -0.4007063712798366 -1.0426391686232916 -5.1639941294557807e-08 -0.22999836765432699 -0.39147931363106409 -1.0403414558618951 -0.051630913094523348 -0.092120205923378357 -0.38706599648683132 -1.0342727371002263 -0.37071694342002698 -1.03416035146106 -0.2902752106326536 -0.032573688018865482 -0.38627624093566609 -1.0393142896207124 -0.3847171780086428 -1.0390038923025147 -0.38584890066451105 -1.0414258495624991 -0.070341015750958941 -0.19675368021262765 -0.41003246985804676 -1.0491249540140826 -0.35241839428283928 --0.0024821409163338208 -0.36698071709880603 -1.0340802583369555 -0.36482230170999314 -0.10279865099785082 -0.33320524818238806 -1.0553786223108599 -2.259476984451187e-08 --0.10232896766086093 -0.33364309177435919 -1.0366516441882696 -0.33345436776955734 -1.0362836708646035 -0.48145726583660703 -1.0145939272301987 -0 -0.064159166363670764 -0.28728847460754525 -1.0350708619705065 -0.40072554415700734 -1.012346432487486 +1.0599999996162099 +4.5366603721284617 +-1.1109608265618025 +0.41354127960715692 +1.0392650005472026 +3.2256026017516831e-07 +0.28877280692180085 +0.40971786751199446 +1.0394584551962629 +0.40113090322348399 +1.0397960784900693 +3.4382614631994449e-07 +-0.052012393932720488 +0.4073210278961133 +1.0382620538212062 +4.4515380283730775e-07 +-0.022196971068819987 +0.39981342216751337 +1.0219246039183696 +0.16931246678767384 +0.089999613213682092 +0.41497672529953122 +1.0241576928327369 +0.39974580076221067 +1.0118088643979963 +0.22853028998529992 +0.22999980554592028 +0.45589908598316448 +1.0470588373683918 +7.5992221706672763e-08 +0.69999376190285079 +0.45111293237227562 +1.0423797121648692 +0.45590406710702386 +1.0436900641369966 +0.49307823537027146 +1.0599999749082432 +4.3084106437890464 +-0.094323809739913667 +0.49060036412222885 +1.0107505577362768 +0.44459707535952164 +1.0377015867223924 +0.45236363417444431 +1.0400157554931684 +0.47424510606445147 +1.0427400494441694 +0.48983636084644044 +1.0505033684082403 +3.0834405394913829e-08 +0.2299991331679096 +0.47038431084804261 +1.0443216056072042 +0.47565277889946533 +1.0571033174749438 +0.036262094994336518 +0.035413201565139704 +0.52651778450358033 +1.0481491167548485 +0.58174277901880056 +1.0600000031223575 +5.0184410234171404 +-0.24015433417187368 +0.48726369678077891 +1.0417816299956482 +4.3048386239845161e-08 +0.47214646623172163 +0.49246577999334301 +1.0456494992813132 +3.8470758637664756e-08 +0.015562573260373554 +0.51349524274239 +1.0500034457650795 +2.8016728592408594e-08 +0.089999176924778462 +0.48424581822860474 +1.0400088177659992 +0.46585023985551788 +1.037890107431271 +0.45284383439399828 +1.0267609622738945 +0.45332039060688356 +1.0354644602798324 +0.46717206891868879 +1.0431440798200227 +0.46577742406862283 +1.0519318062901895 +0.45718783278602071 +1.0540446947933457 +5.7276315837130054e-08 +-0.031740003657319014 +0.47378238147041268 +1.0584501543919043 +2.3129447081530281 +0.45758157805299998 +0.47693608212850613 +1.0427929979079571 +0.49972333218690301 +1.0468422515663414 +0.43818916228588745 +1.0513999577661055 +0.38246226278396023 +0.11702353575262611 +0.40070662602745488 +1.042637976003316 +7.8860828198782319e-07 +0.22996869239232917 +0.39147936382807674 +1.040340993290509 +0.051631067310145509 +0.092140881993002147 +0.38706603587196553 +1.0342722873017316 +0.37071695861323339 +1.0341598845378941 +0.29027504255901243 +0.032573739671296044 +0.38627629469294938 +1.0393137679982336 +0.3847172333652053 +1.0390033469488467 +0.38584896533155055 +1.0414252442745395 +0.070340982144528955 +0.19674973238608426 +0.41003253572982246 +1.0491244332668423 +0.35241836292619527 +-0.0024810033424443258 +0.36698072741265736 +1.034079717792622 +0.36482218777718145 +0.10279985170983824 +0.33320529050462716 +1.0553784256569165 +4.1230618463889958e-07 +-0.10232926411618698 +0.33364310393827112 +1.0366514839728793 +0.33345437938825961 +1.0362835120686025 +0.4814572621984809 +1.0145939128707631 +3.5249265019535526e-08 +0.064154722862809238 +0.28728858096992332 +1.0350706384958028 +0.40072557299085715 +1.0123462744242362 diff --git a/datafiles/test_validation/case118.m/grad_valid.txt b/datafiles/test_validation/case118.m/grad_valid.txt index 5a54fea8..be26b7c8 100644 --- a/datafiles/test_validation/case118.m/grad_valid.txt +++ b/datafiles/test_validation/case118.m/grad_valid.txt @@ -1,7 +1,7 @@ 344 0 0 -4052.9781725276771 +4052.9780354895579 0 0 0 @@ -9,31 +9,31 @@ 0 0 0 -4000.0000001031431 +4000.0000252490859 0 0 0 0 0 -4000.0000484812758 +4000.0006525251665 0 0 0 0 0 -4000 +4000.0000216228523 0 0 0 0 0 -3786.1090141722125 +3786.1087936915865 0 0 0 0 0 -4018.6784489680731 +4018.6781749832717 0 0 0 @@ -41,7 +41,7 @@ 0 0 0 -4041.7677627931889 +4041.7676741276887 0 0 0 @@ -49,11 +49,11 @@ 0 0 0 -4026.4523001416842 +4026.4522404185846 0 0 0 -4043.1665411868785 +4043.1664697632577 0 0 0 @@ -65,19 +65,19 @@ 0 0 0 -4000 +4000.0000238134062 0 0 0 -3761.9439545841578 +3761.94383137246 0 0 0 -3781.9248934527463 +3781.9247612504 0 0 0 -4019.8449723410477 +4019.8449487821526 0 0 0 @@ -87,23 +87,23 @@ 0 0 0 -4070.9344414330617 +4070.9344438187145 0 0 0 -4029.7251660171532 +4029.725109462724 0 0 0 0 0 -4009.7756243798813 +4009.7756234597 0 0 0 0 0 -4021.3254165338085 +4021.3253320552767 0 0 0 @@ -113,13 +113,13 @@ 0 0 0 -4098.6436528514605 +4098.6435912567795 0 0 0 0 0 -4081.9899263678012 +4081.9898990329129 0 0 0 @@ -129,7 +129,7 @@ 0 0 0 -4004.1018229964607 +4004.1017788635913 0 0 0 @@ -137,7 +137,7 @@ 0 0 0 -3895.4148252866958 +3895.4147503495983 0 0 0 @@ -149,15 +149,15 @@ 0 0 0 -4064.2629713604565 +4064.2629604925701 0 0 0 -4064.2684460029827 +4064.2684427632071 0 0 0 -4065.1203433943488 +4065.1203402138735 0 0 0 @@ -165,17 +165,17 @@ 0 0 0 -3931.6749356419123 +3931.6748572689262 0 0 0 0 0 -3855.1852649305965 +3855.18517624894 0 0 0 -4000 +4000.0000124901826 0 0 0 @@ -183,11 +183,11 @@ 0 0 0 -3801.7199340010548 +3801.7198593451126 0 0 0 -3779.8895374590147 +3779.8894749563588 0 0 0 @@ -195,35 +195,35 @@ 0 0 0 -3757.0335325965411 +3757.0334550463144 0 0 0 -4000.0000031335644 +4000.0000645120522 0 0 0 0 0 -4000.0000034618588 +4000.0000687652296 0 0 0 -4000.0000050260323 +4000.0000890307601 0 0 0 -4033.8625181327375 +4033.8624933575347 0 0 0 0 0 -4045.7060632753114 +4045.7060579970603 0 0 0 -4000 +4000.0000151984445 0 0 0 @@ -231,7 +231,7 @@ 0 0 0 -3806.4615693794126 +3806.461486985434 0 0 0 @@ -243,31 +243,31 @@ 0 0 0 -4000 +4000.0000061668816 0 0 0 0 0 -3813.1048623781708 +3813.1047497168256 0 0 0 0 0 -3653.5226973511385 +3653.5225797494691 0 0 0 -4000 +4000.0000086096775 0 0 0 -4000 +4000.0000076941519 0 0 0 -4000 +4000.0000056033459 0 0 0 @@ -283,11 +283,11 @@ 0 0 0 -4000 +4000.0000114552636 0 0 0 -3835.6706498997228 +3835.6704041037488 0 0 0 @@ -295,21 +295,21 @@ 0 0 0 -3912.3115261245275 +3912.3113139198013 0 0 0 -4000.0000103279881 +4000.0001577216567 0 0 0 -4010.3261826189046 +4010.3262134620295 0 0 0 0 0 -4058.0550421265307 +4058.0550085118025 0 0 0 @@ -317,19 +317,19 @@ 0 0 0 -4014.0682031501919 +4014.068196428906 0 0 0 -3957.8799698042999 +3957.879795600722 0 0 0 -4072.9644603419983 +4072.9644375554367 0 0 0 -4000.0000045189536 +4000.0000824612371 0 0 0 @@ -337,7 +337,7 @@ 0 0 0 -4000 +4000.0000070498531 0 0 0 diff --git a/datafiles/test_validation/case118.m/obj_value_valid.txt b/datafiles/test_validation/case118.m/obj_value_valid.txt index 6baf451e..b2193628 100644 --- a/datafiles/test_validation/case118.m/obj_value_valid.txt +++ b/datafiles/test_validation/case118.m/obj_value_valid.txt @@ -1 +1 @@ -129660.69419396459 +129660.69434043927 diff --git a/datafiles/test_validation/case9mod.m/G_valid.txt b/datafiles/test_validation/case9mod.m/G_valid.txt index e2e4c3c1..5dabfda3 100644 --- a/datafiles/test_validation/case9mod.m/G_valid.txt +++ b/datafiles/test_validation/case9mod.m/G_valid.txt @@ -1,37 +1,37 @@ 36 --4.674038933671909e-13 -1.7784662631470383e-12 --1.0130456917778474e-08 -1.756370559477527e-07 --7.0574276422874505e-09 -1.8736264773000499e-07 -1.1590728377086634e-13 -5.3290705182007514e-14 -1.6903453747829644e-08 -6.3813931028278148e-08 -1.8120373312946469e-08 -6.0348277652888527e-08 --3.1255916632666469e-08 --3.9143376806549668e-07 -3.9270550145076299e-08 -2.5640788015035554e-07 --2.7431972915437086e-08 --3.5765027917022962e-07 -0.53547468107454055 -0.53260342008402439 -1.3038182501273037 -1.315131401151246 -0.69849833874804679 -0.7158208467197722 -0.088128842463233673 -0.16403463423120926 -0.20126473747328963 -0.21191008842859441 -0.26305975751436789 -0.24053218661116582 -0.23947661709898585 -0.2645345033726002 -0.44370700318366701 -0.46396293219461243 -0.15105063481862782 -0.11663436794787219 +-6.1165511544558626e-09 +2.3394322395953182e-08 +-1.4666801106955063e-10 +2.5782811441388276e-09 +-7.6664119497138472e-11 +2.1129044347478754e-09 +1.5161090161086577e-09 +6.1101168569166475e-10 +2.8274371732806003e-09 +3.4195668519032552e-10 +3.5045738533412418e-09 +-1.1101503050170436e-10 +1.1911723829527432e-09 +-6.3573146746875864e-11 +2.4602542225693469e-13 +1.6292522886374172e-12 +9.1255680789714688e-10 +-7.8041573203790904e-11 +0.53546194255442514 +0.53259524800884794 +1.3038132395966704 +1.315119137627212 +0.69847595311137944 +0.71579443921300812 +0.088120787347156906 +0.16400622492710837 +0.2012677512693615 +0.21189738568216121 +0.26307958581099539 +0.24051804234977969 +0.23949411357491232 +0.26451365423146944 +0.44370853972198282 +0.46396442700286333 +0.15105001400817544 +0.11663358959576239 diff --git a/datafiles/test_validation/case9mod.m/Gl_valid.txt b/datafiles/test_validation/case9mod.m/Gl_valid.txt index 33548402..32e4324b 100644 --- a/datafiles/test_validation/case9mod.m/Gl_valid.txt +++ b/datafiles/test_validation/case9mod.m/Gl_valid.txt @@ -17,21 +17,21 @@ 0 0 0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 diff --git a/datafiles/test_validation/case9mod.m/Hess_valid.bin b/datafiles/test_validation/case9mod.m/Hess_valid.bin index e5d7ee8c14bd9c521f728ad6960f060bef12a512..21447fb1a32f16663c710a7aeb1f6e09b1da459d 100644 GIT binary patch literal 2128 zcmZP&st#aaV32^~6+oJeM9c+L55nmB(8XbVpi%}#AZ7w$W+3JPVqPEy0cwb|0L@_q zVvu{-fmjHLg@Kq_;v7J;IDr`CA8sHP17dL?rj|I+D6HYY2NdTAVgVo)1Y!`t7GCJ; zVBrfBhlK|rahN?Y|H0Iwi=&4tx;-L5cZvcrvFc#%gXx3Wk4qdq++prR*H4r>2kw3A zy5@8}vzs}epL^a)6Hp){g9C8+-V+utB9&n39N6}9$sfy9Lsko7?}M6ifbAbsNotT5 zy1awO%4ho~EcHhhCztQQwtix|s&|szj^%Gc9a@Xf%{c&>8H+NYB~T@=fFBy`j}xPhWqwG%{jp8zlvpd^$HZjfE)+!^5pxsop+&&lgo#t zkA3It<>FdfveC_PC|^H$>GnODb{$vr#H6Yk4kV|D9q-_j-#^*G=*RkX*$1+FL{IMd z+i5>pu0P3#y?VdwZmBa{wyWSuKQMC~ir1Ath7QP z_{md+>qqxLaINa=c=R1+9!#A>-sfVWW2fuwCp&n@J~+1UK#cJ1=ZxQ7Vea2Q`TXal zEf#Ye$}U!&S-zcT-%8%@$ddbS4kU@)KR>CU&wkS5%~JRFoA!6VCo!- z1B(hdMVt0dmWy>a4Vic#&RJE&W9~9o`rUVZ|6d;FRkzT?7v_HZ$uqZ-*gsh)Bep1Yr9F4vnMcmv;RL&JCfWR>ea=LPFw_SsM7-Jsvc73@$Lx>oSrv)gtH>zr>E yM%CFXYEL;R92JKvf7s7BB=cp%?><=g@9);sogeuB49q<+a~yIy?PTvinhpR-dc4m7 literal 2128 zcmZP&st#aaV32^~6+oJeM9c+L55nmB(8XbVpi%}#AZ7w$W+3JPVqPEy0cwb|0L@_q zVvu{-fmjHLg@Kq_;v7J;IDr`CA8sHP17dL?rj|I+D6HYY2NdTAVgVo)1Y!`t7GCJ; zVBrfBhlK|rahN?Y|H0Iwi=&4tx;-L5cZvcrvFc#%gXx3Wk4qdq++prR*H4r>2kt#q zejZDg?yE?W_{i}o4iw19-~e2{#3X>1;{;5d1KVDfz>=S!bb$iwpynK4`+a$mLEv;0 zNg&6;W974b6PEg;i<8TDU|XO6ecevxeQ8{;PM>&UfNstKn0)G;HetvxPMil|*>g}NB9ANdIwIMkg!#oG?^5pxsop+(@BbN_PA17l^ z>}^~MDt}ObL;3o-Vp{LE?Q7aG)53RU$bsY(`Czs6r}s~`$(eRy{(=M9J(};oadX;F zmRfA|_~PdMGH0%8#@(HTEB(OCaVTDw(s}u%vHhgCrgv->*B?koaCpA0`P%+TZ`G0> zeGWa4E_J>^sb&exKKq_#w!H@Jd=5qI3*3_z->|C=QW2Q@bmf7B)r!^&ra#|5>4Es$ zCmXEyKX5)F`q=gv%siMnhrG`TYLnw;+E2DgJ!C(-;y{e>RR^hFKA8LWPd)VL3IDYgv@>XJD6bZgQ;^U4$OL9 zFtum@WT{oFL;r*vh;x>2sEFDOPrnz7|0=GV;*1iwKn~3P_LD6#L%*Il=1_b^Y4hsd zo%>49&h?qv#d08RQCjx(6D#&l<~!G_ZNqKPwRZJ~kH@=krSJU{Y9Dnf9-apCAIuzw zg3#nm7ChNNe<;Y@^*nYU=`ovM2Ol@geEW%k9J@ssDjkY5>UJ=C*w{7ey?=gf`?3QG zded37j-LmHukhKQUeoqpDC?>{zp)CYAEwTsAoA56FYj{u$$UrNZuU?(5Y3q3vpv88 zp8mhM3v!AIxMKJp8ov7{E2`K|EI0wP&weuJ-r7x4e;o=#*T*J3oV~Av{m2cbwkmr? tk+v^CEkEJPANDi$v#*+zn+*&9{oM-bf&2$sVeWyMxx-uR9N-Y+Di-KO%}T?;6+>HU9Gay7n))<_+VH-o%DzDh{=j(a@_dEugfo9l5 zAq3UI>LO%KxfZfQq9+}G{|yKo|GR}>-v3JYDP(0?sABdmEMT9w)Nn@R>&PVs!P-qz z)1e$JNIs?wI^2fl*7vz2=dSxY@VSG+8rRhxkU> z)Z^BDAhdtoo{@>tX+YLoj+{bWvlSj|<$j|qa|5UT z(ZKTYWb}8cU7F7jLsZ=I@shSWh%PQCls~CR&pV@B=9k+EENqYFCX~%%zuFc1KRp@@ z5pLt90cj7p=qPj}x*U0(0cY$PCxPwlTxgtULa33_b7i3e$K&0u<0?J!p7o!py2@w`uuz!rmL=HA8>SbhI}S)nWu^BwKI%@d*MAJxsoL)ZFY-9+L;H;oPgaZ7$O zKb@S5{9sQ?aU-n%aky!MYbKwl7^^Fr1vtIJl(-FZaj=a&d0o>F{2GX@X?RFJcP0h& zzC6|Q?henGxE|s(X+2uvyB74U-@13rOZ~HAaavuMuK7eYa(@5e z)zhEzfrr({Zg$NAKf7a{L8k=DFV>)hfEb)aIbvG5Y9;pjRo}79+zC>?WzmlT)?mkl27Fe(?6y>8zK} z74l~7z-OdQr)Kf;35Z}koz1PUCmj@NSzgQ#L^X^J6==7T_Q-A{wOWbODqrL=#abNL zZh7+Ji=$}P=>L`WbScE&IuNE9@}RkoL_h0C2O-Rs6>&E@3_1Qxa^2oi4y@ynSNFV2 VV?fY^;_`UZ8#v`68rDm${0oU&x_$rv delta 924 zcmXxie^3*27{_rKGG|L=ONB8v^*UfE$Y4{B7<|8DDTIpNL=Q_SnGpD+U|7nc%{WAf zf=xRjG!j81soOvf9n!uJIh=+U5i-;Az#p8>_sIEOij9+kWOV zt`Z9p)%!ZO*^q6$sqs;!((Az6tsz_2NO$=mTd%4Fra3rTrQnLPt_r=7EIlAv+4kLC z);%mdqSp`Z+m0;PG_P;#|H$jW+b0eb_P*9}8Cf*^1GkGuam@bwl%!Tpa^!KaX&zxc@I1yi#IAvrCYHhQd=-wt8FBKk6y&)Ubn5K)9|G&d zTvNk?EZ~jRPKw>T!EYgG(Jvz#3n=5UU)|Y@{qrvM4ZL~^f|F!)*HjaE-ujDcb(v~4 z_8+(JX}X*bp*kyb!v-TT2TqRsXpF;rYj~%hJr=ON>GIc>n!f-B=8}aYB zsIMqSKPHxzi?y{+2(TIMh=)UnSSeXj?ztKWD;s9gOoYsGx`zu=ld+`euk(kpIN1Nz zxZm!15t=gjh8i0pAg1T-$ks{^vgO97#dhaIkVRVT!zf4AIgxMFTaO{6Mz-d-gSr!z SkA7e~x-f&qS~TehxbhFY$-NT* diff --git a/datafiles/test_validation/case9mod.m/Jineq_valid.bin b/datafiles/test_validation/case9mod.m/Jineq_valid.bin index 063e9d3c20220a07907df9351aff0729b06e2c63..62d7f3de58477003bd0544154a00045f514cb514 100644 GIT binary patch delta 586 zcmdnNzJq;36=VIZCn4`zHaPISdC63^ukC;xgunmSk&UGd8;l(63iiL~RI71dvpQ_Y$&UkD8WLxVj`Q5J$K=}>=Nk7hS5aM%i6TP}#qHx~+ z-!J|p2lswB0OdPK2~Rk`ymFgEy@NJ~j&9tV}ptZx^*zvdvK#$dJM%9#UD{sBSr^RjD%nhuCdCq_I9%sRle?ap>rnFI$Y z-$CHrTVJsS{|?A#?Uzd}J7xcJ;p3%Jic=k6{B7%Zre0rDf8cA`~oGIv^z zzP0~!Kxj7WIpNX{2Poe`Wd3t8HTeq%6l8)JJ{0QPUppmq{*?rq1B}1P%XRVc%nbm@ Cpcm!< delta 586 zcmdnNzJq;36=VHu1?QA?0S-K01UtTEpF3a&;qU)-nX$RSMvv>p3@ zf0!jQ!-($yly^D))ZJFLV3=lz)K3(`LdXzQqnw zEu}xxHe7K~s5G4TRap4|lz%{;_j-HZ8R>clwVN~6WpiG%|I~Ti#m%(v0F=M~cA>{D zhRbUlR5ml-vpd-6Afhg_Dk_ob0F-|~(Bk>y+Rpp~;?nc4E;2Sdz_oQJTk=FH2Poe` z;9X#c;ETcoGFq>dJHr3izg)hz=zR4T2N-`_%Sl7`S@j7AL@l37JN526z^=)xH+9(} z2Pofx_h#jj4I6hIkmiwHPufot09 ziQCz84?y|*e=pd)#N!24)UB&J9aO9eE`ZoAkh{+X_3>i@B=b;x_`7P zuRkC(n`PFeJI5WMdE6T0d{++q7`r_^_y+gsxR<8Sg(Tps#{0RUS; B3J3rI diff --git a/datafiles/test_validation/case9mod.m/Lambda_valid.txt b/datafiles/test_validation/case9mod.m/Lambda_valid.txt index 0e40ad3e..d2041b6b 100644 --- a/datafiles/test_validation/case9mod.m/Lambda_valid.txt +++ b/datafiles/test_validation/case9mod.m/Lambda_valid.txt @@ -1,37 +1,37 @@ 36 -2102.9086663512744 -6.1306946295948432e-10 -2059.179541044316 --4.62748272565405e-10 -2065.1543262166392 --2.1285785324908794e-09 -2103.1654286550606 -0.073878039131393805 -2113.4551625514218 -7.2897208384013279 -2129.8491696453198 -1.6170337692196257 -2059.5677508172553 --0.040574380927577681 -2079.3366384601891 -2.993779243335001 -2065.4281022443943 --0.091959905314282178 --7.2802605626985914e-08 --7.3211447539374619e-08 --2.2900140694230898e-08 --2.2613826444279118e-08 --5.3162360001513064e-08 --5.1747432531114327e-08 --4.5348736891177274e-07 --2.4051127647719883e-07 --1.9475039806504457e-07 --1.846175922102021e-07 --1.4735860533921016e-07 --1.6181803004742765e-07 --1.491427698468234e-07 --1.3284902323843737e-07 --8.4395884589172149e-08 --8.038196184696344e-08 --2.4910572117722817e-07 --3.2862313230871992e-07 +2102.9079634210389 +6.1220377665946746e-08 +2059.1797960654344 +-4.6224401917281595e-08 +2065.1547679563073 +-2.1281063325811355e-07 +2103.1648320715931 +0.076586327725526218 +2113.4551660418597 +7.2926695064320874 +2129.8495497014083 +1.6195230784287684 +2059.5680126881643 +-0.040509810555207589 +2079.3369863656708 +2.9938200241221296 +2065.4285464563391 +-0.091928930753423954 +2.9155816558962288e-07 +2.9149805905007038e-07 +8.1969101022843035e-07 +8.2156903328103992e-07 +4.883692207718736e-07 +4.8939026342424309e-07 +6.5796414008143865e-07 +6.661687238108096e-07 +6.7027270808254565e-07 +6.7145274700404157e-07 +6.7719334866254405e-07 +6.746507886323467e-07 +2.016638764707258e-06 +2.0420514337907957e-06 +6.9826153581018147e-07 +7.0070616787085982e-07 +1.9316612285223102e-06 +1.900498148919173e-06 diff --git a/datafiles/test_validation/case9mod.m/X_valid.txt b/datafiles/test_validation/case9mod.m/X_valid.txt index e3b4b1cd..b1945343 100644 --- a/datafiles/test_validation/case9mod.m/X_valid.txt +++ b/datafiles/test_validation/case9mod.m/X_valid.txt @@ -1,25 +1,25 @@ 24 0 -1.0999999739148179 -0.72859484836415755 -0.068001676539553579 -0.068551873482099845 -1.0952499275309213 -1.1406938476832171 --0.051340404468459271 -0.037005604170935118 -1.0865624663659503 -0.80210380663388758 --0.23479335901176734 --0.034778693883437885 -1.0970331503629294 --0.053398521299280348 -1.0793820389889608 --0.068534875725253394 -1.0868304611653803 -0.0093373471108720227 -1.1000000000000001 --0.030016945043488549 -1.089474581127974 --0.0023502874332940672 -1.1000000000000001 +1.0999836660729239 +0.72859453109464656 +0.067911394838317735 +0.068548922053077901 +1.0952528500726237 +1.1406939986945643 +-0.051287830310427385 +0.037002550344052247 +1.0865650279112309 +0.80210398840604913 +-0.23474485299886796 +-0.034779569929213293 +1.097021541545258 +-0.053400220727804731 +1.0793740853777092 +-0.068536896941845754 +1.0868225805490532 +0.0093345452746387055 +1.0999999148509831 +-0.030019822318232293 +1.0894744859549679 +-0.0023532564357853255 +1.0999999221032057 diff --git a/datafiles/test_validation/case9mod.m/grad_valid.txt b/datafiles/test_validation/case9mod.m/grad_valid.txt index b0baf8be..d9980d94 100644 --- a/datafiles/test_validation/case9mod.m/grad_valid.txt +++ b/datafiles/test_validation/case9mod.m/grad_valid.txt @@ -1,15 +1,15 @@ 24 0 0 -2102.9086664011465 +2102.9079684082221 0 0 0 -2059.1795410614691 +2059.1797977807596 0 0 0 -2065.1543262530245 +2065.15477159482 0 0 0 diff --git a/datafiles/test_validation/case9mod.m/obj_value_valid.txt b/datafiles/test_validation/case9mod.m/obj_value_valid.txt index 63aa194d..50e6099b 100644 --- a/datafiles/test_validation/case9mod.m/obj_value_valid.txt +++ b/datafiles/test_validation/case9mod.m/obj_value_valid.txt @@ -1 +1 @@ -4144.4605338128149 +4144.4605529712244 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/G_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/G_valid.txt index 32019fd7..5fbf35ed 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/G_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/G_valid.txt @@ -1,891 +1,891 @@ 890 -2.2204460492503131e-16 --1.1013412404281553e-13 -1.9456658506555868e-14 --1.5005358067199381e-14 --7.1054273576010019e-15 --2.8421709430404007e-14 -4.0939474033052647e-15 -1.1186364334836441e-14 -9.7699626167013776e-15 --4.2632564145606011e-14 +7.1054273576010019e-15 +-6.5725203057809267e-14 +-8.9650509238481391e-15 +-7.1848776928007396e-14 +1.4210854715202004e-14 +7.460698725481052e-14 4.0939474033052647e-15 +-4.5657054525971574e-14 +-5.773159728050814e-15 +4.9737991503207013e-14 +1.8304802118507268e-14 -6.8122590901609215e-14 -5.3290705182007514e-15 --4.9737991503207013e-14 --8.0768725041480138e-15 --5.8938964819787998e-14 -1.7763568394002505e-14 -4.2632564145606011e-14 -1.4155343563970746e-14 +4.6629367034256575e-14 +1.3145040611561853e-13 +2.0344836926255994e-14 +-2.095545958979983e-15 +4.4408920985006262e-15 +3.1974423109204508e-14 +3.5471625636773751e-14 -8.1878948066105295e-16 -3.9968028886505635e-15 -4.6185277824406512e-14 -1.4097230327525523e-14 --1.4552161559100441e-15 -1.8873791418627661e-15 +6.7723604502134549e-14 +1.7408297026122455e-13 +6.991802969924521e-15 +5.5388202704897971e-14 +1.609823385706477e-14 4.5201689613527662e-14 -4.4408920985006262e-15 --7.1054273576010019e-15 -1.1102230246251565e-16 --7.9491968563161208e-14 --1.5543122344752192e-14 -8.4210416417818124e-14 --2.8421709430404007e-14 --1.0480505352461478e-13 -1.2993946196804274e-14 --9.5496527352523231e-15 -2.149842803778057e-14 -9.7497964562931472e-14 -1.5676696052402406e-14 -1.2114484762570932e-13 --2.6922908347160046e-15 +7.6538775317658292e-13 +-3.5527136788005009e-14 +-7.6605388699135801e-15 +3.6082248300317588e-15 +2.2604140781368187e-13 +2.7366997557010109e-14 +-3.8191672047105385e-14 +-3.3217872896784684e-13 +5.8885188392032717e-15 +4.7293766125555692e-14 +7.2875733225785666e-15 +4.0654545702123457e-14 +1.465841337200402e-15 +7.4580099040932879e-15 +4.4131365228849972e-15 4.829470157119431e-14 --1.3988810110276972e-14 -1.1368683772161603e-13 --1.3324411018977855e-14 --1.3278614319212068e-13 --9.0899510141184692e-16 +1.7763568394002505e-15 +-1.9539925233402755e-14 +1.5097298411426152e-14 +3.7744113390303369e-14 +1.3301859613790157e-14 1.6375789613221059e-15 -7.1054273576010019e-15 --1.7763568394002505e-14 +2.3536728122053319e-14 +8.1712414612411521e-14 -7.6154360595381831e-15 -4.4201187848758039e-14 --2.1094237467877974e-15 -3.0198066269804258e-14 --2.7408630920433552e-14 --1.3715157481941631e-13 +-2.8421709430404007e-14 +-1.4654943925052066e-13 +1.0130785099704553e-15 +-2.3464737097800281e-14 +1.1102230246251565e-14 +-7.815970093361102e-14 +2.3536728122053319e-14 +-1.9650947535865271e-14 9.7699626167013776e-15 --7.460698725481052e-14 --4.8849813083506888e-15 -3.7192471324942744e-14 --2.6645352591003757e-15 -1.6697754290362354e-13 -8.3336115785925813e-15 +-1.1368683772161603e-13 +1.5439038936193583e-14 3.5470324594166769e-14 --6.2311267257086911e-15 -1.4460654895742664e-14 --1.2878587085651816e-14 --8.5265128291212022e-14 --1.354472090042691e-14 --8.940070905794073e-14 --4.4408920985006262e-15 --2.4868995751603507e-14 --5.620504062164855e-15 --1.1123046927963287e-13 -1.9428902930940239e-15 --9.3217100705089706e-14 -5.7176485768195562e-15 -3.1408903256036069e-14 --9.298117831235686e-15 +1.5085155347094314e-14 +-4.2382763965065351e-14 +-3.5527136788005009e-15 +-1.0658141036401503e-14 +4.3298697960381105e-14 +2.4286128663675299e-14 +9.7699626167013776e-15 +-2.8421709430404007e-14 +-2.6936786134967861e-14 +-5.4387050418824856e-14 +5.1680881796301037e-14 +1.3415657473814235e-13 +3.0531133177191805e-15 +8.8252322116844084e-14 +-2.350897254643769e-14 -2.2010171463193728e-14 -6.0813441005169722e-08 -3.8827006570985034e-07 -8.0491169285323849e-16 --3.9933334416986099e-15 -1.1934897514720433e-15 +2.7200464103316335e-15 +2.4980018054066022e-15 +-6.5225602696727947e-15 +3.1120939159023919e-15 +6.9805272673306717e-14 3.0921445959286586e-15 --9.7144514654701197e-16 -8.552186736565659e-16 -4.1078251911130792e-15 -2.1316282072803006e-14 -9.9920072216264089e-16 -3.1051550219984847e-15 --5.2735593669694936e-16 --1.1060596882828122e-14 -2.2204460492503131e-16 -5.6794846603480664e-15 --9.9827700689170129e-09 -5.126107871511465e-16 --9.9827688060383224e-09 -8.5348395018058909e-16 --9.9827700272836495e-09 -4.640385298237959e-16 --9.982768833793898e-09 -7.4506373293203865e-16 --9.9827811017583201e-09 -1.1952244749480201e-15 -2.9420910152566648e-15 -7.0568551002736513e-15 -8.2156503822261584e-15 -2.3092638912203256e-14 --3.8857805861880479e-16 --1.6245685352522798e-14 --8.8817841970012523e-16 --6.2241878318047839e-15 -1.1102230246251565e-15 --2.2204460492503131e-16 -1.1102230246251565e-16 -1.2663481374630692e-15 -8.3266726846886741e-16 --5.027228633380787e-15 -2.2204460492503131e-16 +-1.5404344466674047e-14 +1.1513359710058069e-14 +2.9676261448230434e-13 +3.1974423109204508e-14 +2.6478819137309983e-14 +6.6578687007989856e-15 +5.2458037913538647e-15 +3.1502578323738817e-15 +6.1617377866696188e-15 +-7.1991024253037494e-15 +-6.5746019739520989e-16 +2.4921037455882811e-14 +1.3704315460216776e-16 +4.4235448637408581e-17 +-4.0766001685454967e-16 +1.32836450172924e-14 +-2.9490299091605721e-17 +-1.4814538484841933e-15 +-5.863365348801608e-16 +1.3318339486811936e-14 +2.0261570199409107e-14 +1.4162282457874653e-14 +1.7205126212616051e-12 +-1.5809575870662229e-13 +3.8857805861880479e-16 +5.0705967202802071e-15 +1.2434497875801753e-14 +7.9866668833972199e-15 +1.3322676295501878e-14 +-3.7747582837255322e-15 +3.6637359812630166e-15 +6.5954186556638206e-15 +1.6653345369377348e-16 +7.4072692424209663e-15 +2.1538326677728037e-14 -1.9775847626135601e-15 --1.0547118733938987e-15 --1.0602629885170245e-14 -1.3877787807814457e-16 +1.2712053631958042e-14 +-3.4972025275692431e-15 +2.656208586415687e-14 -2.1649348980190553e-15 -7.7715611723760958e-16 -3.5527136788005009e-15 -9.9684488441553754e-09 -2.2412627309620348e-15 --1.9428902930940239e-15 -1.3322676295501878e-14 --9.9826087378990236e-09 -2.3852447794681098e-16 --9.9826533428437614e-09 -9.4368957093138306e-16 --9.98265012319699e-09 -2.7269853042355408e-15 --9.9826534538660638e-09 -2.1233015345956119e-15 --9.9826488464405116e-09 -1.4363510381087963e-15 --9.9826490684851166e-09 --3.4902636336653359e-15 --9.9826535648883663e-09 -5.6898930012039273e-16 --6.3837823915946501e-16 --3.2127078775090467e-15 -1.1657341758564144e-15 --6.4184768611141862e-16 --9.9870768772991614e-09 -1.506607338885857e-15 --9.9870678220426168e-09 -1.4415552085367267e-15 +9.9920072216264089e-15 +-1.7763568394002505e-15 +-2.3647750424515834e-14 +6.4628857820991925e-14 +9.2703622556200571e-15 +1.5099033134902129e-14 +-8.3839185593959087e-15 +3.9494449377563967e-14 +-2.1316282072803006e-14 +3.7039815659056785e-14 +-2.0206059048177849e-14 +2.3835100559921329e-14 +-2.0969337377607644e-14 +3.4514058278034554e-14 +-1.9581558596826198e-14 +2.4376334284426093e-14 +-1.9761969838327786e-14 +2.5070223674816816e-14 +-2.0969337377607644e-14 +3.4042213492568862e-14 +8.2434059578417873e-15 +3.4000580129145419e-16 +8.0435658134092591e-14 +5.6864235542519737e-15 +-3.6255720647915268e-15 +3.3091585027733572e-14 +-4.1101670678056479e-14 +1.987987899298993e-12 +-1.1102230246251565e-16 0 0 --2.7755575615628914e-17 -1.7763568394002505e-15 -1.0388899601698753e-08 -7.7585842653271619e-08 -3.8857805861880479e-16 --2.1316282072803006e-14 -1.4988010832439613e-15 --2.7200464103316335e-15 -7.7715611723760958e-16 --7.679620828149325e-15 -3.6082248300317588e-16 --3.4833247397614286e-15 --1.1102230246251565e-15 -1.8735013540549517e-16 --4.4408920985006262e-16 --1.2732870313669764e-14 -1.0769163338864018e-14 --2.1316282072803006e-14 -7.1054273576010019e-15 -1.8596235662471372e-14 --4.4408920985006262e-16 --1.8041124150158794e-15 --9.9870947102564944e-09 -1.9849573373864615e-15 --9.9871041436827568e-09 -5.2562121322097255e-16 --5.5511151231257827e-17 --4.4408920985006262e-16 --1.3877787807814457e-17 --4.5935477643865852e-15 --9.9826421851023639e-09 --2.9397331409442007e-09 -6.3837823915946501e-16 --1.9984014443252818e-15 --7.2164496600635175e-16 --7.0707328880814657e-15 -5.5511151231257827e-16 --2.8067825841304739e-15 --7.7715611723760958e-16 +0 +-5.8286708792820718e-16 +-2.6506574712925612e-15 +1.8268719870206951e-13 +-2.4868995751603507e-14 +4.9960036108132044e-16 +1.149080830487037e-14 +3.4416913763379853e-15 +-5.7419347054832315e-16 +8.0296880256014447e-14 +-1.0588752097362431e-14 +-7.7715611723760958e-15 +-3.3653635433950058e-15 +5.773159728050814e-15 +-2.0747292772682613e-15 +1.2673195826096162e-12 +-3.1974423109204508e-13 +1.0266232308708823e-12 +1.9623191960249642e-13 +1.7319479184152442e-14 +-1.8013368574543165e-14 +-1.0113437864944785e-15 +1.1304152058855266e-13 +1.4918621893400541e-16 +-3.7201144942322628e-15 +0 +0 +1.5806800313100666e-14 +-1.0408340855860843e-15 +-1.181693631835401e-14 +3.2786273695961654e-15 +5.9674487573602164e-15 +-8.3821838359199319e-15 +6.106226635438361e-16 +-1.5952517085082718e-14 +-6.106226635438361e-15 +2.5222879340702775e-15 +-8.1046280797636427e-15 -7.1054273576010019e-15 -1.6653345369377348e-15 --1.8596235662471372e-14 --1.4340685405844766e-07 --9.8289376060378686e-07 --1.2212453270876722e-15 --2.8477220581635265e-14 -7.7715611723760958e-15 -1.7763568394002505e-15 -1.1102230246251565e-15 -3.5527136788005009e-15 -9.9685624199707945e-09 -5.8928556478932137e-15 -1.544855576796067e-08 -5.1209037010835345e-15 -9.4368957093138306e-16 -3.0921445959286586e-15 -1.5543122344752192e-15 --9.6866958898544908e-15 -3.8857805861880479e-16 --1.4883927423881005e-15 -3.3306690738754696e-16 +7.9936057773011271e-15 +2.7200464103316335e-15 +9.6589403142388619e-15 +-8.992806499463768e-15 +3.219646771412954e-15 +-4.2688075296837269e-14 +3.3533176235778228e-12 +-2.6822988274943782e-13 +1.0658141036401503e-14 +-3.5527136788005009e-15 +-1.4976908602193362e-13 +6.454618090012687e-12 +-1.1666223542761145e-12 +2.222992623313047e-11 +3.1641356201816961e-15 +-4.6056908287184228e-16 +4.1144865292608301e-13 +1.5182299861749016e-14 +1.3933298959045715e-14 +1.1761425167122752e-15 +2.55351295663786e-15 2.2828960943854781e-15 -3.5110803153770576e-15 -2.5826563110342704e-14 --1.3877787807814457e-15 -1.6514567491299204e-15 -5.0626169922907138e-14 -7.5495165674510645e-15 -7.7715611723760958e-16 -3.5527136788005009e-15 -9.9686693483258537e-09 -3.2397435428821453e-13 -1.3318624869640416e-08 --5.6621374255882984e-15 -8.8817841970012523e-16 --7.1054273576010019e-15 -3.3306690738754696e-16 --1.8818280267396403e-14 --1.1102230246251565e-16 +8.840150833577809e-15 +-9.7005736776623053e-15 +8.3266726846886741e-16 +-1.9012569296705806e-15 +1.028617191423109e-09 +-7.3005601564091194e-11 +1.9839685450051547e-13 +8.5265128291212022e-14 +-4.2159780874739816e-11 +7.1900172083499969e-09 +-1.3763212791673141e-11 +3.0796171168745445e-10 +-3.3306690738754696e-14 +0 +5.5511151231257827e-14 +4.2743586448068527e-15 +-1.4432899320127035e-15 4.7878367936959876e-15 -1.5820678100908481e-15 --7.0776717819853729e-16 -1.1102230246251565e-15 -3.0045410603918299e-15 -2.6645352591003757e-15 -1.0658141036401503e-14 -3.3306690738754696e-16 --7.5842110369706006e-15 --2.2204460492503131e-16 --3.3750779948604759e-14 --6.2172489379008766e-15 --2.1316282072803006e-14 --9.9829260968853362e-09 -3.8719027983802334e-15 --9.982908055761186e-09 -9.2703622556200571e-15 --9.9829040034471461e-09 -1.0408340855860843e-14 +9.5756735873919752e-15 +-6.0368376963992887e-15 +-4.2188474935755949e-15 +1.2281842209915794e-15 +7.0077277314339881e-13 +-1.0658141036401503e-14 +5.0959236830294685e-14 +-5.8078541975703502e-15 +-2.886579864025407e-15 +0 +8.8817841970012523e-16 +0 +-1.7985612998927536e-14 +-9.5479180117763462e-15 +-2.9531932455029164e-14 +1.4910295220715852e-13 +-5.6621374255882984e-15 +-1.4402368186949843e-13 +2.4908963780490012e-12 +-2.1671553440683056e-13 +5.7309712531150581e-13 +5.1125770283988459e-14 +4.1910919179599659e-15 +-3.7296554733501353e-15 +1.9317880628477724e-14 +1.9706458687096529e-14 +1.0919043447188415e-13 +-1.1088352458443751e-14 +4.454214774796128e-13 +0 +-1.0436096431476471e-14 -1.7763568394002505e-15 --5.6843418860808015e-14 -2.886579864025407e-15 -1.2045919817182948e-14 -5.2735593669694936e-16 --1.7694179454963432e-16 -3.3306690738754696e-15 --1.5820678100908481e-14 -1.9428902930940239e-15 -1.3461454173580023e-15 --2.6645352591003757e-15 --3.5527136788005009e-14 --2.2204460492503131e-15 -1.5987211554602254e-14 --1.3375442087237843e-08 -1.1379786002407855e-14 --1.3375441199059424e-08 -1.0436096431476471e-14 -8.3266726846886741e-16 +-2.6867397195928788e-14 +-1.3977707880030721e-13 +-1.7541523789077473e-14 +-1.149080830487037e-13 +1.1934897514720433e-14 5.863365348801608e-16 -1.3045120539345589e-15 -1.0430892261048541e-14 -1.2212453270876722e-15 -4.5900783174346316e-15 --4.9960036108132044e-16 --4.0800696154974503e-15 +1.1934897514720433e-15 +4.2136433231476644e-15 +4.7739590058881731e-15 +1.9255430583342559e-15 +1.7208456881689926e-15 +-2.3037127760971998e-15 2.2204460492503131e-16 -6.0021432268797525e-15 -1.9428902930940239e-15 -1.301736496372996e-14 -4.4408920985006262e-16 -1.8041124150158794e-16 -4.3021142204224816e-16 --1.1553258350005535e-15 -1.9984014443252818e-15 -6.3976601794024646e-15 -4.4408920985006262e-16 --8.8817841970012523e-15 -9.9686036092450081e-09 -9.5479180117763462e-15 +-1.5314138845923253e-14 +2.4591439995447217e-14 +1.6570078642530461e-14 2.4424906541753444e-15 --7.4801276284119922e-15 -2.2791601939076145e-11 --5.375699885235008e-13 -6.6613381477509392e-16 -1.2434497875801753e-14 --9.9869905505201029e-09 -4.8834357998378541e-10 --9.9827934807450447e-09 -6.867340029970137e-12 --9.9826915067602329e-09 -1.7763082671429231e-12 --9.9827008326336397e-09 -4.7695597471530959e-12 --9.9826947541625799e-09 -4.6053993951744587e-12 --6.6613381477509392e-15 --1.4210854715202004e-14 -7.7715611723760958e-16 -5.7454041524351851e-15 --1.6653345369377348e-15 --2.5590640717609858e-14 -4.163336342344337e-16 -1.2875117638699862e-14 --2.7755575615628914e-17 -5.3290705182007514e-15 +-2.4841240175987878e-15 +1.1088352458443751e-14 +4.1737446832001979e-15 +3.9901415505028126e-13 +4.6213033400022141e-15 +-7.5495165674510645e-15 +-8.8817841970012523e-15 +-1.4432899320127035e-14 +-2.5451862839531714e-14 +2.4202861936828413e-14 +3.1780134079895106e-15 +2.414962285701705e-09 +-5.4845017416482733e-11 +-2.2204460492503131e-16 +3.2152058793144533e-13 +-4.7910440198473125e-10 +5.1889360099498238e-08 +-1.4601875264474984e-11 +7.0504583421504563e-10 +-2.9923563626965688e-12 +1.6886886680667068e-10 +-5.1829096570088495e-12 +4.8648163275544221e-10 +-4.5613790522480713e-12 +4.6898091660141361e-10 +-2.2537527399890678e-14 +2.4868995751603507e-14 +3.091971123581061e-14 +3.9690473130349346e-15 +2.9420910152566648e-14 +-2.4980018054066022e-15 -2.7755575615628914e-17 --1.7763568394002505e-15 -9.298117831235686e-16 -2.4494295480792516e-15 --1.8318679906315083e-15 -1.0602629885170245e-14 -3.3306690738754696e-16 +-8.4411644341031433e-15 +-1.3045120539345589e-15 +1.7763568394002505e-15 +2.7755575615628914e-17 +1.7763568394002505e-15 +2.0400348077487251e-15 +6.7307270867900115e-16 +5.440092820663267e-15 +-6.7168492989821971e-15 +2.2204460492503131e-16 3.5527136788005009e-15 -1.3877787807814457e-17 -4.4408920985006262e-16 +2.7755575615628914e-17 +8.8817841970012523e-16 2.7755575615628914e-17 4.4408920985006262e-16 --9.9870907065147119e-09 --6.6358995728932335e-09 +4.5102810375396984e-17 +-9.4195484745540625e-16 1.3877787807814457e-17 0 -1.3877787807814457e-17 -0 --9.9870918444933121e-09 --6.6064395828902001e-09 --5.8286708792820718e-16 --4.1772141301521515e-15 --2.9143354396410359e-16 -1.0200174038743626e-15 -7.2164496600635175e-16 -9.540979117872439e-16 -2.0146041002089277e-08 -1.55851092670245e-07 -2.7755575615628914e-16 -2.2898349882893854e-15 -2.0816681711721685e-15 -1.9706458687096529e-15 -1.3322676295501878e-15 -2.2204460492503131e-15 +2.7755575615628914e-17 +8.8817841970012523e-16 +-4.5102810375396984e-17 +1.1032841307212493e-15 +1.3850032232198828e-14 +6.4809269062493513e-15 +3.7470027081099033e-16 +-4.3090531143263888e-15 +1.1657341758564144e-15 +6.2831684299879953e-15 +2.3869795029440866e-15 +2.4147350785597155e-15 +-2.3869795029440866e-15 +-1.2628786905111156e-15 +4.1064374123322978e-13 +1.2628786905111156e-14 +3.8413716652030416e-14 +3.9968028886505635e-15 +7.9047879353311146e-14 +3.5527136788005009e-15 +6.2172489379008766e-15 +1.8290924330699454e-14 +1.3100631690576847e-14 +-8.8956619848090668e-15 +3.1115110488144637e-12 +-2.3875346144563991e-13 +-4.2063574845485618e-14 +7.4022246665528257e-12 +-8.4654505627668186e-16 +1.5977077300055598e-11 +1.6431300764452317e-14 +-3.524958103184872e-15 +2.4835689060864752e-13 +-4.8364090510233382e-15 +4.7462034302725442e-15 +-7.3344108564299404e-15 +2.3803181647963356e-13 +2.4868995751603507e-14 1.7763568394002505e-15 +1.7763568394002505e-15 +-4.0412118096355698e-14 +2.5146551507759796e-14 +9.8254737679326354e-15 +-2.2759572004815709e-15 +2.0289325775024736e-14 +4.8572257327350599e-17 +4.4086956307864966e-13 +-1.9206858326015208e-14 +5.3290705182007514e-15 +-3.1516456111546631e-14 +2.8189117706745037e-12 +-1.6925350010410511e-13 +1.1199374760906267e-14 +9.7699626167013776e-15 +1.1102230246251565e-16 0 -3.0074815970948521e-08 -2.3461430539994943e-07 --6.6613381477509392e-16 --5.3429483060085659e-15 -2.2037927038809357e-14 --1.7152945730458669e-14 --9.9824707597284679e-09 -8.0361065024625589e-14 --9.9824834787209937e-09 -1.8224310949221945e-13 -1.9560853381506149e-08 -1.3005906754348651e-07 -1.4432899320127035e-15 -2.2690183065776637e-15 -5.2735593669694936e-16 --1.0887124535230441e-14 +2.7755575615628914e-17 +1.7763568394002505e-15 +7.4662498406041777e-15 +1.9081958235744878e-15 8.8817841970012523e-16 -1.7763568394002505e-14 -6.6613381477509392e-16 -0 --4.4408920985006262e-16 -2.5091040356528538e-14 -9.4368957093138306e-16 -1.27675647831893e-15 -3.0531133177191805e-16 -2.7131075164277263e-15 -3.3306690738754696e-16 --1.4432899320127035e-15 --2.2204460492503131e-15 --3.8621883469147633e-14 -2.4702462297909733e-14 -6.6058269965196814e-15 --2.1094237467877974e-15 --7.9936057773011271e-15 --1.1102230246251565e-16 --3.5527136788005009e-15 -0 --8.8817841970012523e-16 -1.3877787807814457e-16 --5.1972315340265141e-15 -0 -6.6613381477509392e-16 -1.1657341758564144e-15 -3.3757718842508666e-15 -0.0059034402651635363 -0.0059022099999977533 -0.015235302565741559 -0.015932603561970488 -0.16785660030169333 -0.16805694767011917 -0.0451000225577005 -0.045653840399253867 -0.00031205408221509148 -0.00031203999999975348 -0.018144625925236701 -0.018032249954923762 -0.022941911874240412 -0.023094106610910266 -0.0068325551275924207 -0.006831010000002428 -0.074504614332013649 -0.07422727861383617 -0.12435597626081132 -0.12484294117275072 -0.060981329869108855 -0.060942050000011808 -0.016240566115970682 -0.015946453022374487 -0.064001796791108331 -0.06366754603932373 -0.01789752720240104 -0.018555695478868692 -0.1971976767042467 -0.19694479999998812 -0.16658328439475711 -0.16695669900943358 -0.0001395378940148183 -6.7281683782974627e-05 -0.00094954527433982136 -0.0010524861220133272 -0.0051261789817331673 -0.0049568008647685189 +-5.5511151231257827e-15 +-1.3711254354120683e-14 +-1.7694179454963432e-16 +0.0059034402694266297 +0.0059022100000043418 +0.015235248269158225 +0.015932423541641462 +0.16785626444488322 +0.16805662751850906 +0.045100158582678983 +0.045653980621624249 +0.00031205408221206716 +0.00031204000000029916 +0.018144621332452843 +0.018032358654602162 +0.022941972081351354 +0.023094084472451298 +0.0068325551265819148 +0.0068310100000001685 +0.074504534211583498 +0.074227243907456691 +0.12435608162283611 +0.12484300863646847 +0.060981330007882098 +0.060942049999990609 +0.016240543894786713 +0.015946434658006565 +0.064001844870990449 +0.063667594492880147 +0.017897530288008213 +0.018555696807128829 +0.1971976776022602 +0.19694479999996994 +0.16658317782946991 +0.16695660970913501 +0.00013953112961220809 +6.7279268934465996e-05 +0.00094954050672607193 +0.0010524761436223697 +0.0051261974171171228 +0.0049568157603876581 9.810080165468711e-06 -9.809999999918037e-06 -0.00068692879521433726 -0.00068687999999925402 -0.023202987053044945 -0.021962394245765047 -0.0008639011381652191 -0.00019330599938838483 -0.01523798730348391 -0.016871186073409601 -0.37991235159664838 -0.38290288660941335 -1.8331132882768872 -1.8715240132167277 -0.573738501904418 -0.58621678286681234 -0.21686902604883382 -0.21662751999999241 -5.4411083450682811e-05 -5.4409999999853683e-05 -6.4131199667900011e-05 -6.4129999999239945e-05 -0.00013793426171274944 -0.00013792999999887037 -0.0022971411758447163 -0.0022968199999989828 -0.10310050077296426 -0.10336387158634018 -0.061466216947393203 -0.061391138779951497 -0.00021481796710913498 -0.00021481000000143802 -0.0006222799503184962 -0.0006222400000000215 -0.000969859137146034 -0.00032964601301410087 -0.00086741710794188275 -0.0017383834447276148 -0.00019746683494141975 +9.8099999998583516e-06 +0.00068692879515800049 +0.0006868799999985378 +0.023202655165267989 +0.021962163438582597 +0.00086391017842574766 +0.00019330712160760963 +0.015237515249591507 +0.016870643853374258 +0.37991409457625497 +0.38290471408720517 +1.8331186104093415 +1.8715299606514442 +0.57373893869135562 +0.58621589577860156 +0.21686902587170859 +0.21662751999979066 +5.4411083452980852e-05 +5.4409999999727197e-05 +6.413119967027619e-05 +6.4129999999708889e-05 +0.00013793426172226437 +0.00013792999999991912 +0.0022971411765544342 +0.0022968199999983279 +0.10310003805779237 +0.10336345373145882 +0.061465959239365882 +0.061390813994752498 +0.00021481796709710299 +0.0002148099999992723 +0.00062227995025777871 +0.00062223999999933932 +0.00096984155627709615 +0.00032963848669910934 +0.00086740509368810168 +0.0017383621608870019 +0.00019746683493557007 0.00019746000000055042 -0.27581182630879675 -0.27702499196419667 -0.26326591151299727 -0.26107793815056696 -0.00058782055023761813 -0.00058778000000311512 -0.001856622989659819 -0.00087456294030249522 -0.00023667029386528749 -0.0018600094322058067 -0.37813967124914766 -0.37752136999999325 -0.14488115399236146 -0.14485726377638725 -0.05494121798011161 -0.054247550734197188 -2.8260452881843549e-05 -2.8259999999808591e-05 -0.0044867068593387634 -0.0044859200000002706 -0.027918733798954664 -0.026075221547835294 -0.010709081692451796 -0.012487332184138555 -0.04663006023966447 -0.046602400000016211 -0.13938827375781709 -0.13970528728027251 -0.02694834234678262 -0.026679173954242609 -0.0013786569943125943 -0.0013785300000026702 -0.096170940651152476 -0.096088610000014674 -0.010028925105626099 -0.0077628083378534808 -0.080706713805021424 -0.08101025595224419 -0.00044982250030876946 -0.00044980000000063473 -0.032747404568248928 -0.032659237336969675 -0.007542285133326972 -0.0073849022520561577 -0.13050013174828562 -0.12819659130460404 -0.018627484513624074 -0.019738259553785387 -0.072769899488432141 -0.075040791686327657 -0.020431463605814621 -0.020465677028566553 -0.0018223758697709042 -0.0014721295687635449 -0.040399061658843154 -0.040479209424335263 -0.032405133993029654 -0.032444430493596729 -0.03404410076662865 -0.03429729831801271 -0.097904877804962695 -0.097744552328622211 -0.063379329083757319 -0.059361152543442736 -0.033963252233842368 -0.033157199867985619 -0.14628067777780104 -0.15772233553137521 -0.0082544546060806228 -0.0086689929186934741 -0.026324768227510339 -0.025750061900247163 -0.015930676791462095 -0.016152376912685649 -0.020154924541404447 -0.019993452446681562 -0.00021158898178723787 -0.0002127449103011673 -0.00022665370479990328 -0.00022780429663420111 -0.00021158895911933237 -0.00021290130824138295 -0.00022665371337645654 -0.00022774162705946837 -0.0007829386179897728 -0.00078906597860955031 -0.11324831296849744 -0.11298228342209211 -0.0751078887073654 -0.075015544724707645 -0.0043570035385465571 -0.0043512226537710582 -0.58081956648759514 -0.56423120441081909 -0.86266249416547969 -0.86646759376887617 -0.0049857882948470223 -0.008819862790328304 -0.078538625588559993 -0.082835261415843228 -0.0027859414216297959 -0.0028125737341130408 -0.011295263159913945 -0.011244336243458646 -0.02460196220526489 -0.020643341780664487 -0.015362807444692133 -0.01827480150953956 -0.0027888318018209281 -0.0032375255777687085 -0.010344131349331352 -0.010004280680411207 -0.1253770027809932 -0.12478422681828401 -0.15414104819573143 -0.15489967236794461 -0.014557102117761695 -0.01414350208662412 -0.031607766757661721 -0.031693084907185351 -0.0044737468409261705 -0.0034861995920560567 -0.01434997386351565 -0.017181103551734422 -0.012375640017273483 -0.0074237167240053378 -0.76026563829118776 -0.75069451722052516 -0.00023151365055083383 -0.00023129962949239007 -0.0083110707112485412 -0.0081852476356770679 -0.0082267299656167431 -0.0081852477576683583 -0.0082768168956743448 -0.0081852476349728778 -0.0082210858262132328 -0.0081852477958595966 -0.0082176337525328661 -0.0081852477955576593 -0.0082496478327178414 -0.0081852476344871795 -0.020051041525313989 -0.018251282979823771 -0.022417513479191072 -0.021922258933891593 -0.00016978330523043607 -0.00017108958938080786 -5.7757135955867932e-05 -5.8355034634858681e-05 +0.27581133155140125 +0.27702451348679208 +0.26326540015726652 +0.26107741944741691 +0.00058782055017462013 +0.00058778000000026724 +0.0018565772116224803 +0.00087456855410253745 +0.00023665892944170963 +0.0018599776710890939 +0.37813967344888194 +0.37752136999997882 +0.14488103370164135 +0.14485715497031612 +0.054941287283437744 +0.054247620396963708 +2.8260452882717551e-05 +2.8259999999736116e-05 +0.004486706861490425 +0.0044859199999996166 +0.027918735236950605 +0.02607523773060335 +0.010709054280841988 +0.012487290824018841 +0.046630060209503908 +0.046602399999979151 +0.13938899872707833 +0.13970598173184412 +0.026948269774636158 +0.026679196275799566 +0.0013786569946491814 +0.0013785300000030325 +0.096170940867472729 +0.096088609999946367 +0.010029469984645319 +0.0077632745923225839 +0.080706646610556043 +0.081010240580329171 +0.00044982250033358506 +0.00044980000000121456 +0.032747146163662894 +0.032659043575767981 +0.0075422962439966011 +0.0073848507442327233 +0.13049962973748366 +0.12819608575804572 +0.018628167682850506 +0.019738959312694745 +0.072769230046957484 +0.075040055257282259 +0.020431262945784148 +0.020465550695469785 +0.0018224514685547749 +0.0014721516758491174 +0.040399050256807817 +0.040479174837931849 +0.032405108726508848 +0.032444439206523866 +0.034043867014960379 +0.034297149370891247 +0.09790494844481186 +0.097744634721984941 +0.063377048046544288 +0.059359986043980212 +0.033962931349766183 +0.033157611787375675 +0.14627633135974757 +0.15771587544706239 +0.0082545555233229841 +0.0086691423407570436 +0.026325055215805082 +0.025750236472962727 +0.015930743349985118 +0.016152473717787698 +0.020155010432275342 +0.019993503610980314 +0.00021159168089340753 +0.00021274767402632862 +0.00022664607624363616 +0.00022779653435833587 +0.00021158932046347407 +0.00021290167827772824 +0.00022664697804105049 +0.00022773478048311417 +0.00078293759117000514 +0.00078906487523096053 +0.11324844784843636 +0.11298245195348008 +0.075108226268057077 +0.075015831021827864 +0.0043570050950738626 +0.004351224659300457 +0.58082182623207868 +0.56423245110147302 +0.86266088450287326 +0.8664657173323832 +0.0049856727622154505 +0.0088221429542606374 +0.078538933654034276 +0.082836970889243633 +0.0027859460816415625 +0.0028125726034545747 +0.011295264035186268 +0.011244440541041118 +0.02460396537553345 +0.020645213800771167 +0.015363235156546414 +0.018275328415757623 +0.0027888829530444441 +0.0032376556961565333 +0.010344267660263168 +0.010004349495528718 +0.1253765345301294 +0.12478371425494265 +0.15414048373490916 +0.15489912630715941 +0.014556941137303861 +0.014143386366913729 +0.031607750969021922 +0.031693029235704669 +0.0044735238428200976 +0.0034860162196598569 +0.014349334040361303 +0.017180373140241637 +0.012374842640013473 +0.0074230828319869881 +0.76026420617953694 +0.75069391885827907 +0.00023149348923485078 +0.00023127958992754416 +0.0083109249557763252 +0.0081851120088841899 +0.0082266032214608348 +0.0081851242004255167 +0.0082766736922437797 +0.0081851119381297355 +0.008220963393792179 +0.0081851280175824648 +0.0082175115242423564 +0.0081851279873300289 +0.0082495066629361975 +0.008185111889219783 +0.020049851101836252 +0.018250136029336231 +0.022417337827143908 +0.021922153103499924 +0.00016977346163280248 +0.00017107945355223714 +5.7749221505442059e-05 +5.8346687329670786e-05 +3.0814879110195774e-33 +1.2325951644078309e-32 0 0 -3.0814879110195774e-33 -3.1562139928618021e-30 -0.016010376911529307 -0.016411600201472913 -0.020588200101851077 -0.020612285217172035 -0.01071422953955262 -0.0070172232373595291 -0.012261750252370094 -0.016870413951416148 -0.13982980322674934 -0.13902978528767418 -0.16486057166576953 -0.1469270271167582 -0.086591982172828541 -0.086743285947201335 -0.32862551788622413 -0.33040488225725717 -0.066162831479438106 -0.065941173518649282 -0.057035205473808671 -0.057128076376569151 -0.052763196785589786 -0.052684807386956169 -0.0072701193228718814 -0.0070274868738785289 -0.00016297211385327007 -0.00024468676672041788 -0.014001312362476556 -0.013431656422235193 -0.42859198849672919 -0.42803695686936305 -0.42859198849671559 -0.42930013679962109 -0.066921243302352287 -0.066624468757348135 -0.08897529601622936 -0.089261928425634227 -0.042277125174532901 -0.040752508272740871 -0.00010654854269766011 -0.00010511973718211866 -0.00025631013710487708 -0.00025524960975086632 -7.9579425302080585e-31 -2.0029671421627253e-31 -0.047880445624398922 -0.04337087512974494 -0.39246883522999831 -0.39554748969290826 -0.003433428112191684 -0.0033999990512230114 -0.0010192659647076463 -6.0012885339848485e-05 -0.083524361927789254 -0.084957883752438706 -0.12473437261553517 -0.12281793787340914 -0.0098610088612316339 -0.0093982200254878676 -0.077937304085221246 -0.077675439435924976 -0.27425226578388318 -0.27222542098357705 -0.27425226578388584 -0.2622839948098532 -0.15625322367625577 -0.15597248539483133 -0.058484614175039404 -0.061555554120153913 -0.17048914114233529 -0.17247440446431431 -0.021518956947132333 -0.02487962883523135 -0.00017366909747962327 -0.0001366625464088364 -0.14340871500433949 -0.14363350334120881 -0.0010076378903878767 -0.0009482554441440996 -0.11077313578725061 -0.11049353577817266 -0.45655086082995194 -0.45704055727077492 -2.393369117495654 -2.4004608916911438 -0.60969215573044733 -0.60855773069517682 -0.071861306113485665 -0.071618353375061714 -0.061002462065094062 -0.060849412920648348 -0.077393842072330396 -0.076740279011276863 -0.10698902632932249 -0.1070110654396248 -0.0050596507278534777 -0.0047834674823237647 -0.0010423487171669224 -0.0019666911725144706 -0.13991812805765289 -0.1404196441482658 -0.01095727274897831 -0.010648744510836899 -0.0068276142944595757 -0.0066793864307276097 -0.00016981559470328396 -4.5882396745670983e-05 -0.86267264273741684 -0.84492984943240723 -0.00020461577882725316 -0.00020536508694049909 -1.7966405813284441 -1.8379745287698064 -0.25979506315319101 -0.26015825835478179 -0.16626451820814467 -0.16604350287348507 -0.54266036657422356 -0.53617183220073961 -0.54266036657422501 -0.52897336309301624 -0.010578476766071473 -0.012237797739856955 -0.0096665260956382421 -0.0093745163957369669 -0.094270332934996995 -0.09501992053024598 -0.13163831569517009 -0.13178554520778343 -0.001268362618364231 -0.00071293947668388225 -0.078160538135969057 -0.078148676487012764 -0.50501031482864012 -0.46850565125003846 -5.5147120693574454 -5.5241899574912665 -2.763436322517796 -2.7269064693468565 -0.15431703289259349 -0.15633988152071418 -0.17507595161553502 -0.17832441716211925 -0.20245092583987156 -0.20506146455657842 -0.58781274097940783 -0.58724941210403681 -0.031993072777782287 -0.031555700873924536 -0.20511957876731535 -0.20420418292185613 -1.3008086869753013 -1.2709967294534752 -0.25335978244640811 -0.22146318405027457 -0.041103995211717981 -0.041032171265332214 -1.4699355561025833 -1.4637489613564847 -1.8376462991310702 -1.864548743381796 -1.8376463316258889 -1.8596255652495044 -0.22013492259699355 -0.22136932392770761 -0.10066896166738577 -0.10124489865858669 -0.019198558024612303 -0.019942467094091414 -0.028516282154973566 -0.028986950695414761 -0.036001131244235512 -0.036171059115408938 -0.03766105488124509 -0.038709465439081006 -0.021962261056616365 -0.021697754038938193 -0.012463014362940047 -0.012375239967879864 -0.010768161932376426 -0.01034361451286943 -0.0061971075456920422 -0.0057243559197935924 -0.85184651191606708 -0.86613226710726676 -0.12152806515460372 -0.12116272724636183 -1.0836276046537168 -1.0856034149922515 -0.00030611362324909583 -0.00030412178132722002 -0.057278938005897298 -0.056529941151955927 -0.054317244344686828 -0.054033841149815832 -0.057278936451082355 -0.056740564816422374 -0.057278936318270246 -0.056757768661037294 -0.034259185797255697 -0.035135788440944976 -0.3814935451273625 -0.38110902467316754 -0.086102774206592944 -0.085837084063382779 +0.016010345985020356 +0.016411542261680193 +0.02058821407643719 +0.020612234232745556 +0.010714359652552847 +0.0070173052750418692 +0.012261861182590114 +0.016870561551465768 +0.13982984968371448 +0.13902983584865755 +0.16486263445425237 +0.14692765905681865 +0.086592030298704617 +0.086743329240379224 +0.32862527338103525 +0.33040462125078113 +0.066162755276726548 +0.065941090284576911 +0.057035196854139873 +0.057128048966108645 +0.052762864921197646 +0.052684533742546301 +0.007270140916645274 +0.0070275031190782412 +0.00016298049159970196 +0.00024470111203860095 +0.01400131913398658 +0.013431665103441319 +0.42859264569615968 +0.42803738548717657 +0.42859264569450839 +0.42930044263038425 +0.066921353871859809 +0.066624564197773295 +0.088975268573657229 +0.089261900407607495 +0.04227380903497796 +0.040749263956359139 +0.00010653339066995157 +0.00010510560739333783 +0.0002562898373572347 +0.00025522979116822695 +0 +0 +0.047877431445647094 +0.04336795719784603 +0.39246889106238469 +0.39554758433452508 +0.0034333960380787693 +0.0033999684844131083 +0.0010191795635004083 +6.0015492599576439e-05 +0.083524434117727669 +0.084957972149270283 +0.12473439284000275 +0.1228179401233746 +0.0098610207377622487 +0.0093982247832814485 +0.07793697908735292 +0.077675049982980221 +0.27425204339063031 +0.2722252019818765 +0.27425204339064035 +0.26228389349567111 +0.15625306268325764 +0.15597230892632377 +0.058484956919915232 +0.06155592421857814 +0.17049063835068928 +0.17247589126524115 +0.021518234715063478 +0.024878809571961868 +0.00017366215746847304 +0.00013665795106784369 +0.14340891572353934 +0.14363370195832137 +0.0010076265742236881 +0.00094824943956493444 +0.11077314538508502 +0.11049354205508886 +0.45655043941203799 +0.45704068235625672 +2.3933672046859331 +2.400463071585953 +0.60969130945863503 +0.60855828870890627 +0.07186129743552494 +0.071618379369885299 +0.061002458426004935 +0.060849443443835437 +0.07739366422241746 +0.076740117228817725 +0.10698912023463061 +0.10701114770592884 +0.0050595713582163443 +0.0047834001762438452 +0.0010423519532841215 +0.0019666243253964356 +0.13991756379952275 +0.1404191107808066 +0.010957247206164474 +0.010648723763799516 +0.0068276280493499821 +0.0066793953776975064 +0.00016980802441958834 +4.5881711059375121e-05 +0.86267217196144186 +0.84492934544578113 +0.0002041803515723105 +0.00020491690070721305 +1.7966492878208706 +1.8379896115342726 +0.25979449890585415 +0.26015684288095081 +0.16626429497990958 +0.16604327164378516 +0.54265980758624377 +0.53617131254070993 +0.54265980758629107 +0.52897303786135619 +0.010578357436630619 +0.012237634054098287 +0.0096666095348451435 +0.0093744992188169642 +0.094270292457048113 +0.095019866693052749 +0.13163847883447344 +0.13178571502730299 +0.0012683064723409462 +0.00071291147938468916 +0.078160389741476349 +0.078148500461634296 +0.50500961748462447 +0.46850547872077142 +5.514719362475792 +5.5241970683764725 +2.7634332471648131 +2.7269035527356631 +0.15431682191972065 +0.15633961769922194 +0.17507330006901956 +0.17832155485097495 +0.20245062145505605 +0.20506115821413101 +0.58781320839456186 +0.58724967069541878 +0.031993138641189557 +0.031555706671358132 +0.20511940520062361 +0.20420399460264552 +1.3008098136722366 +1.2709975450748072 +0.25335527312776318 +0.22146140988498109 +0.041103963611633765 +0.041032255719912716 +1.4699324856214124 +1.4637460137937297 +1.8376436506043514 +1.8645455094926242 +1.8376469165589682 +1.8596263571104803 +0.2201349357959374 +0.22136953714237334 +0.10066906664416203 +0.10124499733482724 +0.019198410604622681 +0.019942207145073949 +0.028516316302865771 +0.028987144276275689 +0.036001205004132994 +0.036171073938587525 +0.037661059052651852 +0.038709463389537041 +0.021962256405527555 +0.021697751403208732 +0.012462975623782574 +0.012375242148078334 +0.010768151962510962 +0.01034360850974957 +0.0061971170735556419 +0.0057243600781081219 +0.851845979287988 +0.86613076734234995 +0.12152798409937239 +0.12116259328978352 +1.0836260214086533 +1.0856011434495338 +0.00030175185336121985 +0.00029989952409609271 +0.05728956626370843 +0.056539193050478442 +0.054319656091536966 +0.054035473181623835 +0.05728940441967266 +0.056750047140365939 +0.057289390626519672 +0.056767268336683996 +0.034259195224605431 +0.035135804055431714 +0.38148915090123586 +0.38110452300543463 +0.086102870713273744 +0.085837166865821907 3.1562139928618021e-30 3.1562139928618021e-30 -0.0034861995920553966 -0.0029992519689337471 -3.1677695725281255e-30 -1.2732708048332894e-29 -1.9740781929969167e-31 +0.0034860162196599541 +0.0029990916713624354 +1.2325951644078309e-32 +1.2671078290112502e-29 1.9740781929969167e-31 +7.896312771987667e-31 1.9798559828300785e-31 1.9798559828300785e-31 -0.00090610053253868412 -0.000903399574754939 -1.9259299443872359e-34 +0.00090609355584781706 +0.00090339271914250004 1.9259299443872359e-34 1.9259299443872359e-34 1.9259299443872359e-34 -0.00090876436395945931 -0.00090339957414210662 -0.24155171772217593 -0.24271713007876067 -0.0029657531180686146 -0.0044375607269470036 -0.015342949112477404 -0.01348224319499244 -0.0054492325601215247 -0.0046095836982332026 -0.01486058494605624 -0.017020703876281268 -0.029037786996659185 -0.028202106535581476 -0.0064671621285548424 -0.0068290160268569162 -0.17520418264924595 -0.17889510661997535 -1.1401038957162022 -1.1494500292628442 -0.0044172742208171637 -0.0045603040457376431 -0.11535264158643917 -0.11795952355144391 -0.0028188524624426742 -0.0028342028226287313 -0.0067327110160213567 -0.0067635351951383987 -0.14703430063867659 -0.14660665198148315 -1.2889436252359978 -1.2964455201807235 -14.991404178762776 -14.917646331646601 -1.2634100435180267e-29 -1.2634100435180267e-29 -7.8886090522101181e-31 -7.8886090522101181e-31 +7.896312771987667e-31 +0.00090875721160419256 +0.00090339265787726659 +0.24155165263932021 +0.24271706446610117 +0.0029654221046543439 +0.0044371465034269732 +0.015342471105311796 +0.01348185706599395 +0.005449203283631833 +0.0046095740972933574 +0.014860571640957925 +0.017020660366994553 +0.02903775550221345 +0.028202087898531982 +0.0064671516305345629 +0.0068289977012555327 +0.17520449147956635 +0.17889542918936868 +1.1401055742680835 +1.1494521085430132 +0.0044173197089566038 +0.0045602493719361682 +0.11535237656206544 +0.11795922988673828 +0.0028187369851003495 +0.0028340761480721518 +0.0067319832660693371 +0.0067627784385408717 +0.14704341373493721 +0.14661572824674876 +1.2889435859452087 +1.2964453033090237 +14.991383553918126 +14.917629422482641 +1.2325951644078309e-32 +1.2325951644078309e-32 +7.8905349821545053e-31 +3.1562139928618021e-30 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/Gl_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/Gl_valid.txt index d59990a7..fcbb97e9 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/Gl_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/Gl_valid.txt @@ -399,493 +399,493 @@ 0 0 0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 +-4.4942328371557893e+307 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/Hess_valid.bin b/datafiles/test_validation/case_ACTIVSg200.m/Hess_valid.bin index 1170318adfba4e894e6b3d403e2df79635847171..7d56bc8b506b6af317736e23d8787cea6f7e5abd 100644 GIT binary patch literal 44160 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 delta 22873 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 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/Jineq_valid.bin b/datafiles/test_validation/case_ACTIVSg200.m/Jineq_valid.bin index 3cb19748cb48cacf55dd500cbc466f3b269af2cf..6bf1732c610db60a1174c6fe28d1af68e1845c31 100644 GIT binary patch literal 25496 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 literal 25496 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 G%l|*>C0-{0 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/Lambda_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/Lambda_valid.txt index bfb66dc6..22a9453f 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/Lambda_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/Lambda_valid.txt @@ -1,891 +1,891 @@ 890 -685.31458123204459 -1.0862008296050825 -685.37431070619107 -1.103187074470575 -694.86888854762685 -0.0064505331187552726 -694.88081850442995 -0.0098195965895053802 -673.73949335125405 -0.10823254029600178 -673.80391439163191 -0.12656098768498997 -687.85335519966418 -1.8580128620108773 -688.03783222744084 -1.9107458571090168 -686.70142076355637 -1.5664589139787084 -687.00628845082599 -1.65378691604788 -686.88473774917247 --2.3695919653587065 -686.88654955707455 --2.3690484090468762 -686.90267882458147 --2.3644645140224791 -685.67287024967538 --1.7485004547851828 -685.83460528338617 --2.2186983899860233 -686.11741863839802 --2.1377217771597188 -689.37523377243974 -0.86353534179144342 -689.37955620803916 -0.86475303652581215 -689.38001525435061 -0.86490157969043657 -689.38374334645516 -0.86594541728622743 -689.40985633359492 -0.87337951412911019 -687.85553146758696 --2.3871130358697066 -687.86561029099596 --2.3842533953468066 -687.87472400869876 --2.3816739228710109 -674.48171320365316 --1.5787954136040006 -674.4911072504508 --1.576081239798947 -687.65943599335446 --2.6808642727247136 -687.67513292705007 --2.6763492771166382 -685.2843763254599 -1.3850554570339351 -685.77917779553979 -1.5268767459767258 -679.83562899291894 -0.86513781728383965 -679.83965968801226 -0.86632338521402996 -679.87613286978399 -0.87671889808369918 -692.33971356047914 --0.31184182450885312 -692.48480106697718 --0.27036751005215753 -681.80010295043064 -0.02869369039967563 -681.82317408814015 -0.035287865897724889 -682.03416430504114 -0.095648898675682825 -696.57291094483321 -0.78537301476503474 -696.58567892533563 -0.78900386200287798 -685.80974764659265 --7.2364721261621812 -698.52799756818422 -0.40691008965910969 -681.81884351015094 -1.3742583659575165 -696.58737791742112 -0.5800184387438343 -673.63732015164658 --0.25851634559074754 -673.62274283329157 --0.32497602039601725 -688.46890627996299 --1.1217425572042301 -675.92220584966844 -0.16467016150275721 -675.48948006238311 --6.261666645543779e-07 -675.57596664168909 --3.0208089564531547e-07 -675.48948005655859 --6.2222409802524477e-07 -675.57596663625179 --3.0325536626648361e-07 -675.2464246951439 --5.6689557380075261e-07 -689.50134301740241 --0.89781310206620635 -674.35212841101554 --0.23639054438185919 -673.71433532342064 --0.13438299948813368 -696.31440953265371 -0.29043590465303898 -680.90048230727518 --1.2492313935521926 -687.80724883168227 -0.54448246337238437 -684.23652155506079 -0.46207067046794237 -674.47407787047598 --0.001123723737727312 -699.26227998251568 -0.67304984461387818 -687.76583827867591 --3.7445924756313502 -670.27438986797688 --0.1711546916096171 -669.00088252554303 --6.9431103194215097e-08 -687.20622068325986 --1.3269424804129872 -686.8579689079246 --1.1853984444278238 -686.55826139894134 --1.0483135993487898 -686.78128242316677 --1.1505170268406479 -686.54825453649244 --1.0477762242809967 -686.86756006881183 --1.1867384236146175 -686.86635768437918 --1.1864428024870441 -686.54016819012031 --1.0474057540087107 -679.31272790552384 -0.4702705496664914 -683.37466063036675 -0.22865625557860766 -682.83593849501813 --8.0856450021955396e-07 -682.7014786411894 --1.8307843998672787e-06 -683.37466062229771 -0.22865608425654937 -683.37466062028045 -0.22865599324544009 -684.10320840912595 --6.7691806774156351 -678.91603061672424 --1.7512893004688599 -679.0096170703265 --1.5260684697736342 -678.85136679143704 -0.19363329681882163 -679.60532755226018 -1.1718751636544424 -694.64908669205977 -0.86100164441883609 -687.34116398489243 -1.719631652586191 -695.36453680656973 --0.12795899595040341 -696.14164758794982 -0.01629076698462259 -680.63126973817361 --1.3117869597638949 -680.00249821361115 --1.0622970886641321 -680.21822185160784 --1.1572529429905616 -680.63126971760198 --1.3117873409355831 -686.73487168586416 --3.2420798649434452 -686.13792106588244 --2.9896546543486631 -680.90733858664771 --3.2180128807433563 -676.95932640943693 --1.6205140270302307 -689.23250380563195 -0.75787950098205248 -684.15279676986108 -0.84770026634107121 -684.33790121063032 -0.93116479563148147 -685.00116025011005 --9.8444238536660329 -686.72350689560676 -1.5857144644833348 -673.06012244354906 --0.062156496103178471 -673.72895710184775 --0.076270189541431457 -671.4440446102675 --3.6078260858507362e-08 -671.35109590940863 --1.2935137609331253e-09 -675.84377079451065 -0.093400500513622212 -679.41210532601849 -1.4694167102826288 -684.78060899013826 -0.39722126909009253 -685.60503486067807 -0.67404743305641479 -686.74766248478136 -1.5784888154587384 -686.21707570204546 --6.2794924438276398 -674.80159801689138 -0.20542785821361068 -677.35530759025119 -0.94346067903750808 -673.83888066726411 -3.5352061218556723e-05 -672.84743650433472 -2.0644272925099745e-07 -683.55695197623709 -0.94549032298247437 -684.14557936087022 -1.099556138791342 -684.75336193986186 -0.93386694730639008 -688.35497808557307 -1.0125688708830169 -692.4728622212067 -0.85240347374508463 -675.04530969646498 --0.7953784134669748 -674.81109463243047 --0.77272496663540913 -681.60110817528187 -0.25974225742184637 -682.57607882590605 -0.57184775730907678 -679.58485582206026 --5.588391178524435e-08 -680.93307422052578 --1.8447258283159666e-08 -681.14953467535452 -1.7747698839110342e-09 -675.53913988978002 -0.2487679004458439 -676.99989464317457 -0.95529444193287016 -677.59980639153332 -0.23631599865306208 -686.95009831731647 -1.5937450770884003 -684.81483027741479 -1.6923633925626602 -680.22679641251113 -0.10621620517937716 -680.2230118879512 -0.11485397195083484 -679.5637867848759 --1.4380546251622773e-08 -679.56378678686656 --1.4745512465829493e-08 -693.74871024728634 --0.15476761202328015 -681.93326499527564 --0.97204489014224982 -686.78870457763776 -0.14864290753166165 -683.52594431833757 -0.93299961147640254 -686.84844101458282 -1.5853785959003641 -687.47393309466077 -1.7760039101675686 -682.83674709747856 --3.2052554141640042 -682.16788276168495 -0.7182468799835765 -698.58933092189034 -0.58022499697427476 -675.07469291920404 -0.10712616896544302 -672.44232380773269 -1.2254897740541447e-07 -689.24330622911316 -2.2033346106413587 -694.03105685456853 --0.18230655401198939 -694.52057471257285 --0.21659873904342056 -693.58611595641923 --0.00032179648610663884 -693.33243665705209 --4.6532173315732141e-07 -692.49349206164368 --2.2372005912929703e-07 -693.33243665137252 --4.9127895848835268e-07 -693.33243665087991 --4.9347026573343963e-07 -681.32555211327167 -0.21753330235846433 -681.39183652131544 -0.22143343691553471 -687.51585512086081 --1.9639603433631201 -697.33563439016416 -0.5514412014294805 -698.93096529298782 -0.28648232976008103 -698.93096529236891 -0.28648229401525699 -682.83203213735192 -0.77203936484916813 -685.73497914581867 --6.3804806404363461 -685.73497913382005 --6.3804808056575464 -685.73497913499989 --6.3804810814604913 -685.73497912188861 --6.3804811990320403 -685.45146608140828 --6.2743793003768209 -685.73497911950278 --6.3804813582561275 -685.73497912188884 --6.3804812200001262 -685.3115164010386 --6.219913562851735 -681.16220376126876 --0.34158314765667308 -682.76028909710294 --4.7423908407625612 -685.45435375519867 --6.3201171530596367 -682.71782595995364 --6.5788724644276506 -686.17895602849376 --6.2566227643765897 -697.51207445416514 -0.34600550375096306 -679.03805648256889 -0.15650869565797754 -681.88832738090889 --3.8150537467697134 -682.54712371944447 --5.8661631458882271 -683.78444975743832 --5.3285499961713674 -698.74553990454012 -0.10918218038442939 -698.03745337598832 --4.0817271398008735e-07 -698.29215555806366 --2.0015639912214231e-07 -686.99631259851844 --7.2295315099121211 -697.56083996689711 -0.35572338049345986 -681.72610617329553 -0.34296449931183304 -672.30783028901976 --0.3082259131480502 -674.81606591309253 --1.3266600401439383 -671.00000000143814 --0.11479073517698846 -681.12790605364626 -0.28941429099239552 -686.36937683658994 --4.346112860702485 -679.95258919413425 -1.4672270982759381 -686.33464393226564 -1.4511237469112246 -696.81781945582634 --0.77705424082368035 -680.13134136965573 --1.1975918310852236 -680.13134136725091 --1.1975918817495761 -680.13134136725091 --1.1975919926730991 -685.20759000254645 -0.71768577167009351 -679.68258506983216 --3.5425138486875087 -693.48569322342473 -0.81433354690037718 --3.5542477205191114e-06 --3.5549930237784847e-06 --1.3811125383394679e-06 --1.3204766351065577e-06 --1.2127689028441593e-07 --1.2112679162997631e-07 --4.6366105700550517e-07 --4.5798311248620278e-07 --6.7617790470548325e-05 --6.7620842884552187e-05 --1.1589668920263004e-06 --1.1662169317953017e-06 --9.1570996020704323e-07 --9.0964638652965295e-07 --3.0680221295572996e-06 --3.0687209344082913e-06 --2.7892226169250678e-07 --2.7998103243140673e-07 --1.6530537155045141e-07 --1.6464284423811435e-07 --3.2365486776791625e-07 --3.2387890629753865e-07 --1.2953551612797176e-06 --1.3193265867959985e-06 --3.2542300191449583e-07 --3.2715472487406727e-07 --1.1750281870084913e-06 --1.1331957940038436e-06 --8.0745645105972765e-08 --8.0891361142301421e-08 --1.2223928512941889e-07 --1.2195553454382029e-07 --0.00015125374088213349 --0.0003136705129130226 --2.2224692931674255e-05 --2.005055199530806e-05 --4.1132924042166618e-06 --4.253994694255714e-06 --0.0021494188531807081 --0.0021494363999893288 --3.0706029748119136e-05 --3.0708212541194081e-05 --9.0535832518119704e-07 --9.5674545327993709e-07 --2.4428250728336253e-05 --0.00010918302472079776 --1.3808694975186423e-06 --1.2467751205507438e-06 --5.3110657969015192e-08 --5.2675880402493469e-08 --1.0044383881882447e-08 --9.8041157545059085e-09 --3.5438004532666361e-08 --3.4653793800807405e-08 --7.0376193718441957e-08 --7.0493009908951348e-08 --0.00038783726129945157 --0.00038784498319057966 --0.00032906024331812904 --0.00032906639841487085 --0.00015299484285725691 --0.00015299957034416783 --9.1674739542798047e-06 --9.1687588476040705e-06 --2.0031818741166841e-07 --1.997963010297762e-07 --3.3902988224372985e-07 --3.3944989175138732e-07 --9.8232727882001015e-05 --9.8236371859369482e-05 --3.3898232560491413e-05 --3.3900410285746618e-05 --2.1759088403238244e-05 --6.402500332042538e-05 --2.432932481914395e-05 --1.2137732555371248e-05 --0.00010686571735690611 --0.00010686941698475232 --7.1953271043603747e-08 --7.1616925280836716e-08 --7.5612678591882827e-08 --7.6286756432066439e-08 --3.5886630400292794e-05 --3.5889107592235924e-05 --1.1364459286684922e-05 --2.4130519020133517e-05 --8.9177724045737866e-05 --1.134376579059282e-05 --2.1876990614034199e-08 --2.2002126740992785e-08 --1.4123987135464999e-07 --1.4126392176733431e-07 --3.798195528386859e-07 --3.847327978484718e-07 --0.00074661258790815685 --0.00074662454886830799 --4.6832778647674769e-06 --4.6841030758709989e-06 --7.516969898700567e-07 --8.0515046634467616e-07 --1.9666779451569481e-06 --1.6859967738284235e-06 --4.3052218951453654e-07 --4.3079150352033865e-07 --1.4698624613619936e-07 --1.4664232731883624e-07 --7.7892201316200594e-07 --7.8682478319388948e-07 --1.528906703938327e-05 --1.5290477453596148e-05 --1.9612714240827894e-07 --1.9631732499278652e-07 --2.1003556879112488e-06 --2.7147558361005853e-06 --2.5714520598683824e-07 --2.5616497351689691e-07 --4.6902288124602782e-05 --4.6904635318415312e-05 --6.4021270313814382e-07 --6.4195291522187799e-07 --2.7942495223501572e-06 --2.8538897912490444e-06 --1.5730787000575045e-07 --1.6021635681916631e-07 --1.1288132796262397e-06 --1.0650441372320983e-06 --2.8567734015649393e-07 --2.7689743172337164e-07 --1.0287592639851674e-06 --1.02703241136708e-06 --1.1578148302406771e-05 --1.4333782609529394e-05 --5.1812534829822781e-07 --5.1709076834075475e-07 --6.4702130681238274e-07 --6.462323694834476e-07 --6.1566110894536716e-07 --6.1108381083037096e-07 --2.0702061276380861e-07 --2.0737480045324392e-07 --3.3172751090793534e-07 --3.5427150269704195e-07 --6.2017831588849215e-07 --6.3528789470353572e-07 --1.4297971525692733e-07 --1.3251105048625132e-07 --2.5527987848615339e-06 --2.4305215291710718e-06 --7.9747714120753659e-07 --8.1537290306390527e-07 --1.3206376573188109e-06 --1.3024516505965153e-06 --1.0429351773186432e-06 --1.051393258660253e-06 --9.9500123050367888e-05 --9.8958149890539661e-05 --9.2866816874919136e-05 --9.2396491027311884e-05 --9.9394719826870477e-05 --9.8779854181869873e-05 --9.2764951172715971e-05 --9.2320120643538423e-05 --2.6788696479248181e-05 --2.6579341090996445e-05 --1.8196378649839129e-07 --1.8240289709844952e-07 --2.7664619273468809e-07 --2.7699221743893215e-07 --4.8362682873256999e-06 --4.8427045834060215e-06 --3.4988878551881475e-08 --3.6058739306909575e-08 --2.3090870291214761e-08 --2.2983076654041942e-08 --4.2322506023506855e-06 --2.3919121830364285e-06 --2.6744514629482787e-07 --2.5350472513086625e-07 --7.5721481182146612e-06 --7.5004060237437268e-06 --1.8643891598779698e-06 --1.872853585879336e-06 --8.5363028635131987e-07 --1.0181606999354209e-06 --1.3696158588350994e-06 --1.1506821283588123e-06 --7.5643014011436738e-06 --6.5153633042798912e-06 --2.0362178850571778e-06 --2.1055359134766468e-06 --1.6392210370446601e-07 --1.6472239903587992e-07 --1.3247896050470259e-07 --1.318075938728964e-07 --1.4456586895030014e-06 --1.4880615178414832e-06 --6.634538689786512e-07 --6.6165605246844467e-07 --4.71378492502896e-06 --6.0502960374112695e-06 --1.4665854701947194e-06 --1.2242033323709698e-06 --1.7012458162650712e-06 --2.838933368164149e-06 --2.0869581820934032e-08 --2.1245041314413147e-08 --9.0933155938796277e-05 --9.1017511951272688e-05 --2.4994645464133634e-06 --2.5385143419781051e-06 --2.5225556050120872e-06 --2.5355622446579826e-06 --2.5070245514566669e-06 --2.5355621640437576e-06 --2.5210255701399035e-06 --2.532270705235857e-06 --2.5221044821274364e-06 --2.5322707050372142e-06 --2.5076566339006657e-06 --2.5277953048744125e-06 --1.0483613267351641e-06 --1.1521692945943589e-06 --9.3723227349673619e-07 --9.5850421005182469e-07 --0.00012395651451464166 --0.00012300742991230975 --0.00036149889592047347 --0.00035775541289411806 --2.1107672227682843 --2.1107672227682843 --2.1107672179932782 --2.1107672179932782 --1.3140417902199118e-06 --1.2818105729745281e-06 --1.0208948691010664e-06 --1.0196971629760583e-06 --1.9657294651553045e-06 --3.0036508379343142e-06 --1.7170946277038714e-06 --1.246831982470667e-06 --1.4749807718532419e-07 --1.4836715470402554e-07 --1.2671635757318707e-07 --1.4234521301595519e-07 --2.3936443607700026e-07 --2.3893911360780819e-07 --5.9601182625132031e-08 --5.9253469947931011e-08 --3.1464900909417639e-07 --3.1572159700746865e-07 --3.6571262016972596e-07 --3.6511090385155188e-07 --3.9568020889814834e-07 --3.9627552968090473e-07 --2.8990182405075868e-06 --2.9992596244237756e-06 --0.00012950514813390982 --8.6256463215629451e-05 --1.5032183948532272e-06 --1.5671561718703007e-06 --4.7463335156657523e-08 --4.7527276302086315e-08 --4.7909627234789626e-08 --4.782832396641165e-08 --3.110329327279958e-07 --3.1243816976313691e-07 --2.3283282564285238e-07 --2.3207078279002243e-07 --4.9490885427069336e-07 --5.135884207598566e-07 --0.00019518870259967825 --0.00019788145913215001 --8.2142016266611837e-05 --8.2484156490132462e-05 --2.1107671033360482 --2.1107671033360482 --4.3647929845523949e-07 --4.8232041923418373e-07 --4.9087065578589504e-08 --4.8665250719052582e-08 --6.0924507563568382e-06 --6.1528999231412756e-06 --2.0703996766344507e-05 --0.00035165824411518659 --2.4831988085094897e-07 --2.4405446826890345e-07 --1.6479010509142227e-07 --1.674323870769276e-07 --2.1361899833672779e-06 --2.2415939535482106e-06 --2.6644099977619444e-07 --2.6735425927580437e-07 --7.343221367645958e-08 --7.4006447340187451e-08 --7.5638169855690811e-08 --7.9151129277821417e-08 --1.3062593122608433e-07 --1.3086933994066184e-07 --3.565395748589663e-07 --3.3853139973869192e-07 --1.1933268834803841e-07 --1.1790573284161534e-07 --9.7654650581542837e-07 --8.4404861923973898e-07 --0.000121528113675018 --0.00015443523016042665 --1.4273712112267288e-07 --1.4250656323923394e-07 --2.0943141026593045e-05 --2.2254919223134318e-05 --1.8711047764273905e-07 --1.8759281185315298e-07 --2.9120182326455068e-08 --2.9063849101124428e-08 --3.9853722882747175e-09 --3.9514538463510805e-09 --3.326538793955314e-08 --3.3330025274831155e-08 --2.8934565946611118e-07 --2.903423065814942e-07 --3.4164102515420562e-07 --3.4251146834083096e-07 --2.6834332937525676e-07 --2.7066665305638805e-07 --1.9287376828533543e-07 --1.9283311544478927e-07 --4.1674316978795669e-06 --4.408296353988803e-06 --2.0245586037279695e-05 --1.072822380625655e-05 --1.4641223156206771e-07 --1.4587296948762905e-07 --1.9220325560428191e-06 --1.9778456268900504e-06 --3.0871869749786422e-06 --3.1557932557309959e-06 --0.00012428581410063174 --0.00045993370518230929 --2.2614154701417365e-08 --2.3130840086552334e-08 --0.00010261747083115068 --0.00010224100949142055 --2.168643692555719e-09 --1.7212882166534902e-09 --7.9922325216414251e-08 --7.9808861057705558e-08 --1.2248251485482063e-07 --1.2265170605631186e-07 --3.6400870225597823e-08 --3.6873495180189681e-08 --3.7547633995776226e-08 --3.8555251276000353e-08 --1.9910114483342402e-06 --1.7204623879754064e-06 --2.1792561042691325e-06 --2.2472724324973134e-06 --2.1950307748461144e-07 --2.1773605385200285e-07 --1.559086644389155e-07 --1.5572939117410102e-07 --1.6637253632261728e-05 --2.9601867886505294e-05 --2.6467320322384563e-07 --2.64714201595728e-07 --4.0450729837647861e-08 --4.3710527710520695e-08 --1.8501559553101251e-09 --1.8418317799561393e-09 --6.0435481508947986e-09 --6.1502588100793176e-09 --1.2906551809406989e-07 --1.2729002311085046e-07 --1.1278818146014989e-07 --1.105826172816004e-07 --9.640678367371217e-08 --9.5071854923647692e-08 --3.4555916597799354e-08 --3.4590411177605421e-08 --6.5845115413071293e-07 --6.675954925769093e-07 --9.8397311858951767e-08 --9.8859485868982216e-08 --1.1961704552963814e-08 --1.2367844162979188e-08 --8.1986463630949948e-08 --9.3988149522438532e-08 --5.0916418918867473e-07 --5.1006319030896065e-07 --1.2906898645900815e-08 --1.2968208384716812e-08 --1.082253908376381e-08 --1.0656248757068106e-08 --1.0822539508674859e-08 --1.0686322433698917e-08 --9.4563385181185898e-08 --9.4028608502211124e-08 --2.0526549212887468e-07 --2.0407221903957285e-07 --1.0951046399201894e-06 --1.0540915661110465e-06 --7.3585384600296598e-07 --7.2383483690460028e-07 --5.8195586175623766e-07 --5.7920126495391403e-07 --5.5611272497793623e-07 --5.409321269799078e-07 --9.5675058705344386e-07 --9.6846698787828795e-07 --1.6892945016932123e-06 --1.7013072285567961e-06 --1.9558633382377321e-06 --2.0363185622875e-06 --3.4017242510763744e-06 --3.6830155788313041e-06 --5.6387904847952802e-11 -7.7300616934818375e-10 --1.6925768776977081e-07 --1.6978173188352756e-07 --1.8063643103891226e-08 --1.8028002629377186e-08 --6.8261920073270016e-05 --6.8716521315750196e-05 --3.4612719735984637e-07 --3.5102638237390426e-07 --3.6628223185635191e-07 --3.6832630393464659e-07 --3.4612717638039372e-07 --3.4963563527673889e-07 --3.4612717458826407e-07 --3.495224918315232e-07 --6.1176873371945082e-07 --5.9639646744153669e-07 --5.0645680085447287e-08 --5.070190174347653e-08 --2.4277708438204327e-07 --2.4353595118827388e-07 --2.1107672662270116 --2.1107672662270116 --6.0502960374102835e-06 --7.0332992708982566e-06 --2.1107672101973232 --2.1107672101973232 --2.1107672227682843 --2.1107672227682843 --2.1107671530692693 --2.1107671530692693 --2.3174528633287774e-05 --2.32441759231857e-05 --2.1107671408043256 --2.1107671408043256 --2.1107671408043256 --2.1107671408043256 --2.3058770561877095e-05 --2.3196705794213841e-05 --8.284140814451035e-08 --8.2420693933122589e-08 --7.112760244255954e-06 --4.7522427648442756e-06 --1.3713905046120575e-06 --1.561257748080772e-06 --3.8691837530350536e-06 --4.5747527800493677e-06 --1.4160477707265469e-06 --1.2357839705142612e-06 --7.2255974434901723e-07 --7.4409997949221289e-07 --3.2594942448058491e-06 --3.0865518740970525e-06 --1.1599640177979836e-07 --1.1350728521030424e-07 --1.4383071969011187e-08 --1.4224968035893142e-08 --4.7741100362538415e-06 --4.6242284260078631e-06 --1.7856171320914236e-07 --1.7451539128132904e-07 --7.4294657964815084e-06 --7.3889040499548792e-06 --3.0842782055368566e-06 --3.0699853210138679e-06 --1.3910553911912279e-07 --1.3952469218525391e-07 --1.4941129775639312e-08 --1.4845637959280105e-08 --8.7722263792708163e-10 --8.8516676977643763e-10 --2.1107672452836677 --2.1107672452836677 --2.1107672452836677 --2.1107672452836677 +685.31456837708481 +1.086204891282698 +685.37429969704817 +1.103191473384898 +694.86887468781094 +0.0062774073975816226 +694.88080934035463 +0.0096476577324609812 +673.73951446512433 +0.1082250348210726 +673.80393706850805 +0.12655372037959184 +687.85335129408156 +1.8580179804866201 +688.03783139200834 +1.910751711273893 +686.70141179299151 +1.5664631078264943 +687.00628516884456 +1.653792542987043 +686.88474783151662 +-2.3697423722884059 +686.88658540213578 +-2.3691914092942787 +686.9026921121432 +-2.3646143320106772 +685.67287390422359 +-1.7486398754866757 +685.83460706775247 +-2.2188351441488186 +686.11742477017253 +-2.1378576620658216 +689.37521113426635 +0.86343927357800321 +689.37954462109769 +0.86465986867477629 +689.38000279399967 +0.86480825464920763 +689.3837276964781 +0.86585115035481541 +689.40983578639828 +0.87328382920786973 +687.85554696749148 +-2.3872889010947911 +687.86563137291807 +-2.38442791982497 +687.87474286074166 +-2.3818490670141208 +674.48174826258412 +-1.5787101762166194 +674.49114813836798 +-1.5759945772231623 +687.65945138273241 +-2.6810294292382029 +687.67515175902975 +-2.676513771335522 +685.28436233728917 +1.3850615236484354 +685.77917361474783 +1.5268854571291697 +679.83561779516094 +0.86517058865190977 +679.83966373576311 +0.86636041474337155 +679.87612351637404 +0.87675198373441321 +692.33971246295653 +-0.3120257161956082 +692.48480173482619 +-0.27055105810939462 +681.80008432624186 +0.028689474363367835 +681.82315796258206 +0.03528410130784581 +682.03414924696665 +0.095645433052884823 +696.57288727306673 +0.78522977706050479 +696.58565922982382 +0.78886163010908283 +685.80985438286314 +-7.2359802989662869 +698.5279634445069 +0.40679727602458277 +681.81883771784237 +1.3742961124986377 +696.58734971074875 +0.5799208201492061 +673.63730995645881 +-0.2584887937391121 +673.62273534188353 +-0.32494743230012563 +688.4689225409204 +-1.1219218985444466 +675.92222273885011 +0.16465656395848563 +675.48948885130449 +-6.2609334697466556e-05 +675.57597576061823 +-3.0220157633786729e-05 +675.48948826506455 +-6.2220876208962628e-05 +675.57597521767946 +-3.0335981182631783e-05 +675.24643630253263 +-5.6691322581965497e-05 +689.50135471345118 +-0.89799349358223701 +674.35211462240682 +-0.23634296509785088 +673.71431923087312 +-0.13436034191835813 +696.31438947799359 +0.29027424018427023 +680.9004680842072 +-1.2492306700022862 +687.80725529261736 +0.5444854640157013 +684.23649487926582 +0.46204990660765538 +674.47406839953135 +-0.0011020748118095287 +699.26225080802419 +0.67291107611047396 +687.76589014354215 +-3.7445355311699742 +670.27441871794008 +-0.17114674059284907 +669.00091073279634 +-6.9425875725178527e-06 +687.20624294765878 +-1.3271185982840346 +686.85798482709822 +-1.1856246916838018 +686.55829002487394 +-1.0485198981107846 +686.78130549728473 +-1.1507079878190229 +686.54828108814195 +-1.0479796711767879 +686.86758252884783 +-1.1869263354073305 +686.86637995398223 +-1.1866303170978743 +686.54019290435212 +-1.0476065306625786 +679.31274337898083 +0.47026482070371345 +683.37463262802862 +0.22863324075903971 +682.83589639946263 +-8.0882346360269813e-05 +682.70141592652965 +-0.00018321958745197458 +683.3746318212269 +0.22861611076715888 +683.37463161952644 +0.22860701083079904 +684.10329315986769 +-6.7687634569687569 +678.91604301547352 +-1.7511915356280923 +679.00962966062309 +-1.5260039677597246 +678.85133527219477 +0.19363669233359257 +679.60531998005979 +1.1719240861439455 +694.64906428252937 +0.86087026962302959 +687.34115819259989 +1.7196365083841092 +695.3645079198883 +-0.12825282299337329 +696.14160800041589 +0.015990830176840658 +680.63127336392495 +-1.3117762385673088 +680.00248574676243 +-1.0625713022727239 +680.21821746564717 +-1.1573357738187509 +680.63127130683267 +-1.3118143546262921 +686.73489387676818 +-3.2421760324006099 +686.1379435785384 +-2.9897807293403136 +680.90733261327466 +-3.2180169466357165 +676.95934300663498 +-1.6204180297735074 +689.23248136962104 +0.75783133460207208 +684.15277568235047 +0.84770602710677678 +684.337880873372 +0.93117123018517234 +685.00128781570027 +-9.8437759611741864 +686.72349767662934 +1.585720285910474 +673.06010474712116 +-0.062129855298826198 +673.72894207439663 +-0.076251738416929671 +671.44401925341833 +-3.6070104131348831e-06 +671.35107179965564 +-1.2894865670238354e-07 +675.84375526612928 +0.093407383202979824 +679.41210266410246 +1.4694727266308059 +684.78058799908933 +0.397197493372691 +685.60501115372392 +0.67398915406271764 +686.74765779016161 +1.578491656479573 +686.21717623183656 +-6.2790560669229096 +674.80157799295534 +0.20552830170452827 +677.35529780316506 +0.94352166276260985 +673.83878728214256 +0.0051554983464614573 +672.84740022556548 +2.0648149398498251e-05 +683.55693223889455 +0.94549500039287682 +684.14556365529256 +1.0995659687104375 +684.75334747119109 +0.93386146703113393 +688.35498289637064 +1.0125716251561614 +692.47284002828042 +0.85228647110307165 +675.0453175348274 +-0.79536469673795718 +674.81110010048087 +-0.77269596626561265 +681.60107900493892 +0.25975039830308216 +682.5760548520941 +0.57185538253679402 +679.58481671638162 +-5.5885012299662639e-06 +680.93304033426421 +-1.8450089416203822e-06 +681.14950222911875 +1.7744360015251314e-07 +675.53912286999832 +0.24883423984956438 +676.99988699718745 +0.95534835166074805 +677.59979108262598 +0.23631761050386232 +686.95009529254457 +1.5937429056719374 +684.81482662116355 +1.6923882907103052 +680.22676342041359 +0.10622279994068545 +680.22297965765529 +0.1148568087509316 +679.56375069382273 +-1.4380818498815067e-06 +679.5637508942458 +-1.4745495418304993e-06 +693.74870164726792 +-0.15494676105349856 +681.93327570859867 +-0.97201103649156351 +686.78871207548195 +0.14864945827265133 +683.52592341974798 +0.9330027740243958 +686.84843463318725 +1.5853832946457427 +687.47392358093907 +1.776012362333842 +682.83679726659352 +-3.2050285406816328 +682.16786783756811 +0.71824311899098547 +698.58928328027412 +0.57991517755782318 +675.07465011375859 +0.10715331691935326 +672.44225820761051 +1.2253194433530882e-05 +689.24330842456766 +2.2033404456388106 +694.0310328942287 +-0.18261200055813054 +694.5205403964784 +-0.21690604686805726 +693.58625237667957 +-0.010012902795595482 +693.33241368206689 +-4.6645025818310582e-05 +692.49346885763862 +-2.238869633714449e-05 +693.33241311984818 +-4.9249820193079153e-05 +693.33241307095068 +-4.9469710639309344e-05 +681.32552164934657 +0.21753931644027594 +681.39180669429891 +0.22141738632692071 +687.51587106863087 +-1.9641287919468857 +697.33561050391859 +0.55129224285444756 +698.93093119925413 +0.28635353318020124 +698.93093113737189 +0.28634995879384539 +682.83201702853091 +0.7720366555516297 +685.73507709811304 +-6.3800330499220443 +685.73507589824919 +-6.3800495719932151 +685.7350760162326 +-6.380077152199874 +685.73507470511015 +-6.3800889093179958 +685.45155458687327 +-6.2739569859456834 +685.73507446651161 +-6.3801048316764 +685.73507470511015 +-6.3800910061195495 +685.31160029209093 +-6.2195088108822141 +681.16221802958967 +-0.34156146262388731 +682.76035205668052 +-4.7421439754202117 +685.45444261590001 +-6.3197014231195938 +682.71790555129996 +-6.5784521162277905 +686.1790483730947 +-6.2562017641836087 +697.51203045427633 +0.34570126157989112 +679.03803566559441 +0.1565301990118301 +681.88837287322474 +-3.8148513082389224 +682.54719684631084 +-5.8657419285193724 +683.78452224041462 +-5.3282526419925524 +698.74550287959062 +0.10906105955773089 +698.03741296801502 +-4.0836198124317503e-05 +698.29211536912476 +-2.0033755393231442e-05 +686.99641239085543 +-7.2291420073230093 +697.56079470329064 +0.35541180904160879 +681.72607825320733 +0.34294304197148257 +672.30783196422612 +-0.30821652655554566 +674.81607418888814 +-1.3265840306423156 +671.00000014378668 +-0.114788088579303 +681.1279215427262 +0.28942066094562691 +686.3694254371502 +-4.3460449914557628 +679.95258686855686 +1.4672804264671921 +686.33463470573759 +1.4511280902308166 +696.81777989659565 +-0.77730690843965056 +680.13135348463084 +-1.1975472172524488 +680.13135324413577 +-1.1975522835149233 +680.13135324413577 +-1.1975633754889627 +685.20757680813006 +0.71767054976622902 +679.68263595199562 +-3.5423235218307307 +693.48567049644714 +0.81425966904155411 +2.1232809305781285e-06 +2.1232783028352456e-06 +4.3310909634537164e-07 +4.3317106909096612e-07 +4.4711237136599649e-07 +4.471313502210877e-07 +4.3577981023910639e-07 +4.3582964766481689e-07 +2.1114050230836762e-06 +2.1114049933408448e-06 +4.3336783197884058e-07 +4.333578423291846e-07 +4.3379514358275802e-07 +4.3380870654382714e-07 +2.125267293965809e-06 +2.125263987539943e-06 +4.3844171588034736e-07 +4.3841646151727043e-07 +4.4302972836041753e-07 +4.4307501559122279e-07 +2.2478226442096723e-06 +2.247728618794926e-06 +4.3319846367850581e-07 +4.3317231450421832e-07 +4.3748720879543098e-07 +4.374568996021351e-07 +4.3334584521377504e-07 +4.3340441394379066e-07 +2.6292279459259931e-06 +2.6284000101322023e-06 +4.4699181919190774e-07 +4.4702717373980182e-07 +4.3177155521289494e-07 +4.3176517327436267e-07 +4.3184311545297136e-07 +4.318522109739249e-07 +4.3221247928219921e-07 +4.321974876714794e-07 +2.1107668509457517e-06 +2.1107668507765378e-06 +2.112197087432249e-06 +2.1121969842953752e-06 +4.3381838355247111e-07 +4.3370779814921633e-07 +4.3183554996297962e-07 +4.3177630533572819e-07 +4.3310929526293891e-07 +4.3325449365513635e-07 +2.448450447367177e-07 +2.4493002731013275e-07 +1.4700676032556962e-07 +1.4740119995988385e-07 +1.3514915960738462e-07 +1.3525725213157359e-07 +2.6952716538514704e-06 +2.6944407220084154e-06 +2.1108609993282088e-06 +2.1108609970410416e-06 +2.1108815186633332e-06 +2.1108815161307834e-06 +2.1110373312311868e-06 +2.1110373222331982e-06 +2.1156060381291287e-06 +2.1156053570750424e-06 +4.4106177346669369e-07 +4.4108605422613744e-07 +4.3725736591210753e-07 +4.3725055896827014e-07 +2.1111996720983446e-06 +2.1111996552744263e-06 +2.1120604499403506e-06 +2.1120603655096032e-06 +4.3184490935691073e-07 +4.3178834814222013e-07 +4.3183585819746942e-07 +4.3191282681998649e-07 +2.1111630327928855e-06 +2.1111630183602305e-06 +4.5757700832287175e-07 +4.5769739215743838e-07 +4.5633578082302757e-07 +4.5612000294387332e-07 +2.1119876260703199e-06 +2.1119875403776102e-06 +4.3192327599122574e-07 +4.3183649112229616e-07 +4.3178013474170538e-07 +4.3192357648948374e-07 +3.3942575567429686e-06 +3.3908860449442247e-06 +4.4494673782811859e-07 +4.4494449792474962e-07 +4.366670973774966e-07 +4.3660443727838832e-07 +2.1108057968705568e-06 +2.1108057959145717e-06 +2.1202592201465902e-06 +2.1202575442620457e-06 +4.3423931621927381e-07 +4.3407467600384981e-07 +4.3270718010078686e-07 +4.3286499054333216e-07 +2.2139853996621659e-06 +2.2139211663458457e-06 +4.4443216296444815e-07 +4.4446183026878337e-07 +4.341526407401223e-07 +4.3412861167316819e-07 +2.1136601854168949e-06 +2.1136599166201535e-06 +2.3353400184539618e-06 +2.3351273070140137e-06 +4.3264690937225791e-07 +4.3244601619044206e-07 +4.390073351925725e-07 +4.3903505988408086e-07 +2.1116960418255589e-06 +2.1116959942898366e-06 +4.3467114177440683e-07 +4.3466325463944465e-07 +4.3242643631227723e-07 +4.3241248758860623e-07 +4.4360179727614723e-07 +4.4338712605126196e-07 +4.3341086000966254e-07 +4.3350974554679714e-07 +4.3828372342246942e-07 +4.3849050002652348e-07 +4.3357140442443328e-07 +4.3357445802061737e-07 +4.3192025915348111e-07 +4.3188929821067333e-07 +4.3535722643571083e-07 +4.3536442151419537e-07 +4.3464052377141829e-07 +4.3464404497486926e-07 +4.3478725616159365e-07 +4.3480994302956136e-07 +8.5728423714856982e-07 +8.5722841876531755e-07 +1.308712347511019e-07 +1.3083863594152421e-07 +1.3063291699001549e-07 +1.3062640443074164e-07 +1.3154759422850648e-07 +1.316414775757974e-07 +4.3248955010336135e-07 +4.3252629553702188e-07 +4.3409698751292147e-07 +4.3404567199287023e-07 +4.3317091966357885e-07 +4.3319063318498532e-07 +4.3354679910816404e-07 +4.3353241614398937e-07 +2.5336457097605408e-05 +2.5336808665624341e-05 +2.5696430481464304e-05 +2.5696790383394864e-05 +3.5874550517150715e-05 +3.5875350705784113e-05 +3.5883734133196517e-05 +3.5884397745319811e-05 +1.7046205307130474e-05 +1.7047048843622538e-05 +4.4199915918503295e-07 +4.4197453864479851e-07 +4.3849670714002655e-07 +4.3848828989632332e-07 +8.259030357627159e-07 +8.2590116761370576e-07 +1.3521049535166021e-07 +1.3506691922496774e-07 +1.3769724411649533e-07 +1.3773144176303935e-07 +1.3039898821572178e-07 +1.3042990743593934e-07 +1.3099441501122381e-07 +1.3102937501325166e-07 +4.3200544058745535e-07 +4.3200779525472235e-07 +4.3275919988002676e-07 +4.3275468990498458e-07 +4.3394337327606057e-07 +4.3359045628069689e-07 +4.3312046948613001e-07 +4.3337945963428509e-07 +4.3200570043119179e-07 +4.3204538735030742e-07 +4.3267482925144302e-07 +4.3264468049926163e-07 +4.4312465091165049e-07 +4.4306950413665501e-07 +4.4581700423044795e-07 +4.4588845721717066e-07 +4.3304881837500158e-07 +4.3301207542440686e-07 +4.3456916611899447e-07 +4.3457679677566295e-07 +4.3215471753817723e-07 +4.3206735346314376e-07 +4.3303037528276664e-07 +4.3328204895068992e-07 +4.3285502147369996e-07 +4.3241587783929618e-07 +6.8937542233368017e-07 +6.8722725479836978e-07 +2.3513426240436775e-05 +2.3513370212235647e-05 +4.0236372971899387e-06 +4.022672527691281e-06 +4.3182566322640736e-06 +4.317890217588849e-06 +4.3186990283695462e-06 +4.3178901130817918e-06 +4.6474131916807636e-06 +4.6470465310675619e-06 +4.6473778702807331e-06 +4.6470465307337412e-06 +5.0953674694127786e-06 +5.0945755191476778e-06 +4.3353742968772849e-07 +4.3337721666860884e-07 +4.3374837240609459e-07 +4.3370423530199672e-07 +3.5849072871714422e-05 +3.5849868058310795e-05 +0.00038956553023377082 +0.00038960849642453418 +4.9958776444415563e-06 +4.9958776444415563e-06 +5.4733782922699092e-06 +5.4733782922699092e-06 +4.3317799691810817e-07 +4.3321366908661936e-07 +4.3358538268859192e-07 +4.3358752282851645e-07 +4.3270765854341027e-07 +4.3237992738598583e-07 +4.3284498689554267e-07 +4.3325448863752064e-07 +3.4543036220791798e-07 +3.4538513754695611e-07 +1.3170019274751407e-07 +1.3155293303569075e-07 +4.3954542308039926e-07 +4.3955927345509578e-07 +4.628770342734061e-07 +4.63057735448051e-07 +4.3768325798548604e-07 +4.376631394963698e-07 +4.3685635520994878e-07 +4.3686475092584167e-07 +4.364703797999586e-07 +4.3646330923657828e-07 +4.324023250524514e-07 +4.323808311249037e-07 +4.317736265494216e-07 +4.3178084518276638e-07 +4.3299945413132712e-07 +4.3294885571586026e-07 +1.785335407171757e-07 +1.7852515480372436e-07 +1.3390432868471823e-07 +1.3391034385094186e-07 +4.3775212088757398e-07 +4.3772517600749774e-07 +4.3976369107618634e-07 +4.3978995684559156e-07 +4.3552569707196301e-07 +4.3538872374056473e-07 +0.00028956363418288373 +0.00028950692700125053 +2.0664658807478224e-05 +2.0664444350218764e-05 +1.6939101293887749e-05 +1.6939101293887742e-05 +4.3602985461512302e-07 +4.3562401364230601e-07 +4.6945015209561957e-07 +4.6977184493716718e-07 +5.5225461993236543e-06 +5.5220632423889426e-06 +4.3184926976114168e-07 +4.3176453163747802e-07 +4.3926479447774379e-07 +4.3939589149050773e-07 +4.430649131151566e-07 +4.4288673310380111e-07 +4.3263196927422022e-07 +4.325909311472206e-07 +4.3875456978962909e-07 +4.3873068074652856e-07 +3.5320116022234015e-07 +3.5308139571801941e-07 +1.3260555488591529e-07 +1.3250589469018698e-07 +4.4601603021739812e-07 +4.4598956952616047e-07 +4.3698748325588211e-07 +4.3726551271875274e-07 +4.4736202758206357e-07 +4.4755035675320015e-07 +4.3366824410130358e-07 +4.3396790599967992e-07 +4.3177456997727989e-07 +4.3177130138501069e-07 +4.4480869387676697e-07 +4.4482976736313843e-07 +4.3184824799814086e-07 +4.3184300143722667e-07 +3.4379535356418263e-07 +3.4377969561875686e-07 +1.7112506944714906e-06 +1.7119309031369754e-06 +4.8336451554567168e-07 +4.841511718685214e-07 +1.3546108475274776e-07 +1.354512304539923e-07 +4.3820110058998493e-07 +4.381790009013124e-07 +4.3721538001818296e-07 +4.3720152164239469e-07 +4.3870501930268328e-07 +4.3864543028913149e-07 +4.4142052933271047e-07 +4.4142256298593303e-07 +4.3220658167512561e-07 +4.3218213971509123e-07 +4.3185131643298281e-07 +4.319330038084783e-07 +4.4448163858711319e-07 +4.4452859176126503e-07 +4.327292071035832e-07 +4.3270183586163012e-07 +4.3236312674583263e-07 +4.3234999780738918e-07 +4.3177422961969205e-07 +4.3176328328055245e-07 +1.8533996700899843e-07 +1.8505160013459209e-07 +5.3040113868172521e-05 +5.3041102410237757e-05 +9.57957281509115e-07 +9.7627332664444965e-07 +1.3248518536559755e-07 +1.324882016215014e-07 +4.4696164031850185e-07 +4.4694072063611896e-07 +2.4955703164024081e-07 +2.4936570162705202e-07 +1.348806686384719e-07 +1.3476276812858056e-07 +4.3269559052820588e-07 +4.3284283227629437e-07 +4.3261472913878297e-07 +4.3258882755576819e-07 +4.4024941175305276e-07 +4.4031825819938668e-07 +4.4370800149584938e-07 +4.4372173637055172e-07 +4.3187128373758079e-07 +4.3182220823639464e-07 +5.3818735300663159e-07 +5.3818572171937764e-07 +1.3455683940341085e-07 +1.342443461058409e-07 +1.9771552799728354e-07 +1.9789124993734261e-07 +1.5944374961015354e-07 +1.590048768663554e-07 +7.7154749594859004e-07 +7.7211842469119075e-07 +7.7744640156099758e-07 +7.7837771270502912e-07 +7.8536618039296046e-07 +7.8612980194814865e-07 +1.3527109694514837e-07 +1.3526621029479244e-07 +1.3061698869307906e-07 +1.3061345196979179e-07 +4.5066995530371589e-07 +4.5058188117267317e-07 +4.2646629491300452e-07 +4.2391266032578153e-07 +1.3243163899844105e-07 +1.3216708415826944e-07 +4.3542053797505558e-07 +4.3541409661799364e-07 +1.452478160395148e-07 +1.4518599112273198e-07 +6.6350302346461865e-08 +6.6406493817210539e-08 +6.6350308865976311e-08 +6.6396211433186697e-08 +1.3215610471016051e-07 +1.3216632425314292e-07 +4.4083781548448928e-07 +4.4089085277445519e-07 +4.334616232487537e-07 +4.3352784872264401e-07 +4.3429272306737542e-07 +4.3433480262163489e-07 +4.3496264111862085e-07 +4.3497786884928541e-07 +4.3511148258564987e-07 +4.3520554704253777e-07 +4.3370780860616603e-07 +4.3368423606926063e-07 +4.328628410138481e-07 +4.3285505241561532e-07 +4.327124313256498e-07 +4.3267477086015933e-07 +4.3230728788661219e-07 +4.3226542953007569e-07 +2.4722111004799037e-06 +2.5142777834129135e-06 +4.4276687861731104e-07 +4.4273294107082087e-07 +1.41485621174099e-07 +1.4150436201204016e-07 +5.3171329155621104e-05 +5.3168812196241668e-05 +2.2390148072603243e-06 +2.2372346603350946e-06 +2.231987106773416e-06 +2.2313169038023966e-06 +2.239014424919729e-06 +2.2377346007181852e-06 +2.2390143924723511e-06 +2.237775442839671e-06 +4.3480654191315357e-07 +4.3488507950834644e-07 +4.6830652981648804e-07 +4.6826656818479574e-07 +2.3677400206535477e-07 +2.3676694396181681e-07 +6.5000496140688701e-07 +6.5000496140688701e-07 +4.3206735346314376e-07 +4.3202428861216433e-07 +6.2529737886491926e-06 +6.2529737886491926e-06 +4.9958776444415563e-06 +4.9958776444415563e-06 +1.1965779079794794e-05 +1.1965779079794794e-05 +1.2027559763342132e-05 +1.2027374662763779e-05 +1.3192273522354311e-05 +1.3192273522354311e-05 +1.3192273522354311e-05 +1.3192273522354311e-05 +1.6775098951864492e-05 +1.6774383787404159e-05 +4.542033766332504e-07 +4.5431732001713847e-07 +4.3202131323749139e-07 +4.321515012602062e-07 +4.3311862858653252e-07 +4.3295331546937968e-07 +4.3224107065696392e-07 +4.3216675726112133e-07 +4.3307579817468007e-07 +4.3326783919073537e-07 +4.3433932654561071e-07 +4.3426464397071663e-07 +4.3233120088407917e-07 +4.3236324819455523e-07 +4.478094682486135e-07 +4.4816043339262232e-07 +4.1305341936293231e-07 +4.138103588130683e-07 +4.3214974456510283e-07 +4.321623931168695e-07 +4.4219399503124578e-07 +4.4243564162943998e-07 +5.8503788276280541e-06 +5.8506276020097437e-06 +5.0767710476872452e-06 +5.0771471597020409e-06 +4.4514952905056434e-07 +4.4510937858164303e-07 +1.4346058330627995e-07 +1.4353378733618318e-07 +5.3055097032110677e-08 +5.2956845199158783e-08 +2.7443393900898944e-06 +2.7443393900898944e-06 +2.7443393900898944e-06 +2.7443393900898944e-06 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/X_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/X_valid.txt index e30638b2..b7efa03b 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/X_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/X_valid.txt @@ -1,477 +1,477 @@ 476 --0.11441771903263417 -1.0726248741977866 --0.11461992543566139 -1.0725131019328886 --0.16070526633175852 -1.0650954162055417 --0.16075234009352701 -1.0650713833967718 --0.055775036220483763 -1.0748185307513589 --0.055991126762469243 -1.0746969930810129 --0.12556650233466371 -1.0670332839777581 --0.12619394132888553 -1.0666895748514795 --0.12051564060335671 -1.0695401148595598 --0.12193446946700269 -1.0688541317734366 --0.12145535820403862 -1.0818099930737601 --0.12146400413255833 -1.0818055729229852 --0.12152919954363957 -1.0817715698135846 --0.099787663673378338 -1.0818517470728626 --0.11371815135195872 -1.0861013768061432 --0.11487320192233076 -1.0854964653483321 --0.13374504744004265 -1.0711662224437462 --0.13376846467551773 -1.0711555576859413 --0.13376472477027751 -1.0711562035295141 --0.13377619415711398 -1.0711496745634945 --0.13389628029166598 -1.0710913370277371 --0.12798033601340508 -1.078626863704315 --0.12801726713817191 -1.0786068616125772 --0.12803959034133525 -1.0785922392734781 --0.0633009584982199 -1.0807050939462539 --0.063334419744914161 -1.0806863905055497 --0.12728613617266815 -1.0801134827464938 --0.12736193587183439 -1.0800762268099025 --0.11394396562071414 -1.0717232114075133 --0.11545421449171619 -1.0708466584450147 --0.094386728443270881 -1.0731571572466141 --0.09440305960704852 -1.0731485583872062 --0.094581798929392155 -1.0730630502787712 --0.1491005672785938 -1.0661896271167535 --0.14974177427212981 -1.0658733565053566 --0.100087248208274 -1.0793720914136589 --0.10018439853256006 -1.0793223773534077 --0.10093708994980342 -1.0789099745113138 --0.16851330670805764 -1.0637634116365888 --0.16856665957570918 -1.0637368063613497 --0.12813150632207612 -1.0903246530668882 --0.17767744751877027 -1.0656776329181119 --0.10335255216442159 -1.0695937091609773 --0.16696817003183581 -1.0673994753830447 --0.033914538267287866 -1.0847835826621914 --0.046977561646806006 -1.0838950176207507 --0.13047294402555215 -1.0714288393250861 --0.066086336650561725 -1.0734499428625024 --0.059948042988096216 -1.0763781230267393 -0.013600000000000001 -0.0052711651304439425 --0.061451252246763913 -1.0761711408846497 -0.013600000000000001 -0.0065455762286754995 --0.059001219390139838 -1.0767737539607547 -0.013600000000000001 -0.0052859795471249327 --0.061737231582201527 -1.0760230815564433 -0.013600000000000001 -0.0065407873066375731 --0.05265804440662103 -1.0776422230626739 -0.027200000000000002 -0.0070161614628460305 --0.13538931854123698 -1.0700120563984077 --0.037830458688311697 -1.085076023928957 --0.044795574774589321 -1.0843559440102923 --0.16761889786207246 -1.064223708833582 --0.097657186897735143 -1.0853545547767174 --0.12387203662904826 -1.0702875572807815 --0.10606414606029628 -1.0792975470359876 --0.0505128432543306 -1.0822642992884508 --0.18172880295484356 -1.0621172892224613 --0.13151088653451962 -1.0793746785890179 --0.039151311470906031 -1.0780287239864026 -0.037057771475449107 -1.0712214828351143 -0.86499999999999999 --0.049694063781390095 --0.12471525265612986 -1.0728526304105859 --0.12283699158662049 -1.072356620465734 -0.0141 --0.0056999921931402296 --0.10506735746612401 -1.0647005862375192 -0.083800000000000013 --0.034099989864657287 --0.11765092138995793 -1.0701443526526333 -0.083800000000000013 --0.034099991653380242 --0.10990747926277611 -1.066901456574342 -0.083800000000000013 --0.034099989854333393 --0.11866063690950131 -1.0705116428601182 -0.083800000000000013 --0.034099992213364787 --0.11916854985631152 -1.0707364701543292 -0.083800000000000013 --0.034099992208933179 --0.11380786552260941 -1.0686568579079734 -0.083800000000000013 --0.034099989847210424 --0.081796865582216605 -1.0697056130942653 --0.09908532041240864 -1.0814463758045232 --0.091238902564830887 -1.0855986375298921 -0.012 -0.0052047890514926231 --0.085832908797074753 -1.087029500510196 -0.0071999999999999998 -0.0025524847597053774 --0.09908532041240864 -1.0814463758045232 --0.099085320412408653 -1.0814463758045234 --0.11692894912195032 -1.0924284080564211 --0.063157922217858459 -1.0847974787614594 --0.076336121274082097 -1.0816897638099374 --0.083821276953801205 -1.0821866969449949 --0.094361212643984477 -1.071081687765983 --0.15893177401430589 -1.0657757733668647 --0.12305200702089211 -1.0681730981907553 --0.14820833171052275 -1.0688036160253933 --0.16780361317847389 -1.0681113352462752 --0.096758005879525821 -1.0831898736844254 --0.07779045506808184 -1.0759026258835285 -0.0095999999999999992 --0.0035999901297436442 --0.090192986512358589 -1.0809466084380692 -0.014999999999999999 --0.0054999917603480702 --0.096758005879525835 -1.0831898736844252 --0.12318302127807376 -1.0831958971885567 --0.11000378556054578 -1.0779098112326593 -0.054000000000000006 --0.022000000000000002 --0.099357705607616323 -1.0940265145341064 --0.074493186103517878 -1.0845909678556951 --0.13001788083115551 -1.0738614700805547 --0.092479144455483275 -1.0793536680286686 --0.10571543312150623 -1.0753578225386893 --0.12638610593875538 -1.1000000000000001 --0.12073932514070709 -1.0691170310913565 --0.030742727427333649 -1.0854509707174085 --0.046125887777957522 -1.0840802238725247 -0.019583626873771853 -1.0860329420443573 -0.67599999999999993 -0.0080339151898959262 -0.047236376951635455 -1.0870579270488405 -1.548 -0.064473590425956781 --0.058446172446393357 -1.0821253883541253 --0.095237972639081819 -1.067806366893373 --0.10662199193929091 -1.0791869275282284 --0.11495918793866203 -1.075501105059167 --0.12086598002418991 -1.0691775227605793 --0.12992093748760947 -1.0868866610566734 --0.039509585458265425 -1.0839771149740314 --0.0849440342817291 -1.0727719935502273 --0.034503792054512893 -1.0859600769079922 -0.013999999999999999 -0.0030601973491386379 -0.030805701659961781 -1.0963753311181124 -1.335 -0.23611330587046664 --0.08792485434421532 -1.0792081689757436 --0.10926392349207859 -1.0727367756339585 --0.10934749882851533 -1.075375239510908 --0.12704486318448027 -1.0687584889368424 --0.14890581592852833 -1.0681169163934092 --0.041053076975681245 -1.0836299072288389 --0.056059585212480854 -1.0835476782321554 --0.078355980872450423 -1.0847253485239439 --0.10223083046543587 -1.077532007333452 --0.044140696638147493 -1.0918117056278256 -0.39020000000000005 -0.063905002240740708 --0.056854423463410499 -1.09474242285197 -0.39020000000000005 -0.1614570684509587 --0.068107425565612029 -1.091696537649155 -0.39020000000000005 -0.22979432618589993 --0.043504931773819228 -1.0832106265781778 --0.085400857407034236 -1.0707261616068731 --0.06851668699306146 -1.0804452375246543 --0.12071374905926192 -1.0696658266034287 --0.11518949539583963 -1.0673032091822374 --0.071649852048877055 -1.0862217692956593 --0.085198285211987954 -1.0839335398898224 --0.033975593315529212 -1.094143817881954 -1.3391999999999999 -0.26663109197273654 --0.040734545181430659 -1.092698357842248 -1.3391999999999999 -0.25723328142812485 --0.15558908949141778 -1.0656554671834451 --0.091927747789911418 -1.0781048458402298 --0.11856043358201114 -1.0719810952373974 --0.10350329520416329 -1.0762386183709816 --0.12129893176568307 -1.0691550755936001 --0.12280649054782466 -1.0680101656045138 --0.10548638217172952 -1.0823591588306816 --0.095913857523302073 -1.0754276203372859 --0.17913008494523061 -1.0635342511753101 --0.065887700771190036 -1.0853000129869541 -0.013165410622254995 -1.0943626001280369 -0.92400000000000004 -0.11115866446339173 --0.13180231632871692 -1.0643403836668166 --0.14157996094205305 -1.069820565693187 --0.15997204266477089 -1.0707954392941064 --0.1325686904716637 -1.0663342929366901 -0.016200000000000003 --0.006456168462119819 --0.11258605954628055 -1.0628028989973286 -0.23170000000000002 --0.053339064284208371 --0.10401170373352539 -1.0670259920420992 -0.23170000000000002 --0.018680358022836026 --0.12051939154991928 -1.0647810095991996 -0.23170000000000002 --0.055278200431391908 --0.12115384713968091 -1.0649424203895075 -0.23170000000000002 --0.055433593492831806 --0.077164493175545995 -1.0850056505051779 --0.088448497999990605 -1.083330338424751 --0.12590364910032431 -1.0768547335194334 --0.17244381492604843 -1.0635643006227655 --0.18036490724484255 -1.0649426413111809 --0.18036490724484255 -1.0649426413111809 --0.10060795580844932 -1.0748925562635894 --0.12761600502923207 -1.087602644202829 --0.12761600502923207 -1.0876026442028293 --0.12761600502923207 -1.087602644202829 --0.12761600502923207 -1.087602644202829 --0.12283218557622341 -1.0859804394307253 -0.028199999999999999 --0.0104 --0.12761600502923207 -1.087602644202829 --0.12761600502923207 -1.087602644202829 --0.11850733555589341 -1.0843876213933694 -0.028199999999999999 --0.0104 --0.08905788887023415 -1.0734333555889823 --0.10804363960457795 -1.0858895203050412 --0.12601647708396957 -1.0886326257936472 --0.11237411403453058 -1.0931575657468295 --0.12964318448612683 -1.0872315157009091 --0.17394738329653212 -1.0654950331765207 --0.088412018214107213 -1.0794940835317235 --0.078917495432068288 -1.0864259573963535 --0.11130782924931025 -1.0908699197308345 --0.11436857701233735 -1.0869719323713198 --0.17958919656423328 -1.0662927236083399 --0.16596276424557255 -1.0691920868540414 -0.052499999999999998 -0.008829148927651095 --0.17166913340487377 -1.0687308250283041 -0.07980000000000001 -0.019887101054085587 --0.13309988679847162 -1.0899325305989442 --0.17431287791223696 -1.0655530087972003 --0.09594587279831604 -1.080275391849848 --0.025711301075463835 -1.0834336987069768 --0.068868807368146823 -1.0865820186097583 +-0.11441766680749052 +1.072623018478658 +-0.11461987391025616 +1.0725112460202693 +-0.16070537177346192 +1.0650955642131916 +-0.16075244552214715 +1.0650715314077617 +-0.055775191990762196 +1.0748188786027475 +-0.055991282392861975 +1.0746973409717608 +-0.12556648951786953 +1.0670314015643196 +-0.12619393072661234 +1.0666876918305512 +-0.12051560734654462 +1.0695382217163614 +-0.12193444123624395 +1.068852237410634 +-0.12145551345037668 +1.0818106252136237 +-0.12146415936879214 +1.0818062050654318 +-0.12152935470367843 +1.0817722019759053 +-0.099787777645800144 +1.0818520423690761 +-0.11371826489795253 +1.0861017736426313 +-0.11487331462379496 +1.0854968624066175 +-0.13374503627207082 +1.0711650402482253 +-0.13376845355923553 +1.0711543754786494 +-0.13376471364574005 +1.0711550213229353 +-0.13377618305789366 +1.0711484923497088 +-0.13389626945753511 +1.07109015474953 +-0.12798051581450665 +1.0786276654195774 +-0.12801744688437253 +1.0786076633427082 +-0.12803977005434963 +1.0785930410144804 +-0.063301122973723145 +1.080705552678233 +-0.063334584192010032 +1.0806868492454689 +-0.12728631246329328 +1.0801142605219902 +-0.12736211205329109 +1.0800770046122332 +-0.11394390639405287 +1.0717213115062305 +-0.11545416062406454 +1.0708447569829302 +-0.094386663922041911 +1.0731556862613139 +-0.094402995130590528 +1.073147087390119 +-0.094581734942980583 +1.0730615791643991 +-0.14910071777634332 +1.0661902071117126 +-0.14974192407205392 +1.0658739366727041 +-0.10008717307432144 +1.0793706759128812 +-0.10018432365342785 +1.0793209617874149 +-0.10093701704579584 +1.0789085584029678 +-0.16851336413124546 +1.0637628177891001 +-0.16856671705846721 +1.0637362124990062 +-0.12813157767480976 +1.0903246667994742 +-0.17767747291960342 +1.0656767959789257 +-0.10335251213775794 +1.0695921027897888 +-0.16696818989654288 +1.0673984244556389 +-0.033914465301068078 +1.0847828845218146 +-0.046977513702847605 +1.0838943858612142 +-0.13047314342623595 +1.0714297169826483 +-0.06608646382850504 +1.0734501215826413 +-0.059948178200408923 +1.0763784283998432 +0.013599991722998561 +0.0052714228781662355 +-0.061451368189804755 +1.0761710956699961 +0.01359999172312021 +0.006544979716499766 +-0.059001348849510457 +1.0767739495476396 +0.013599991722998561 +0.005286010160032756 +-0.061737348985444945 +1.0760230742793884 +0.01359999172312021 +0.006540260362875177 +-0.05265817306040313 +1.0776423556892627 +0.027199991721892355 +0.007016076222490235 +-0.13538950403852129 +1.0700128570676515 +-0.037830351442485088 +1.0850750831835498 +-0.044795485729083866 +1.0843550600937157 +-0.16761897962343991 +1.0642235526192771 +-0.097657133661029571 +1.0853533639518882 +-0.12387205586811788 +1.0702861583270451 +-0.10606404419389939 +1.0792958586349082 +-0.050512782249996502 +1.0822635429203447 +-0.18172885380066797 +1.0621167499219735 +-0.1315110532162109 +1.0793753564528159 +-0.039151510768163908 +1.0780292833258192 +0.037057444548462229 +1.071222620649591 +0.86500000684489631 +-0.049688097333826745 +-0.12471546886341343 +1.0728535873103588 +-0.12283724344071702 +1.072357815971934 +0.014099991739109087 +-0.0056982298027796457 +-0.10506762986101045 +1.0647020511085883 +0.083799991734696072 +-0.034097996922915555 +-0.11765115813191228 +1.0701454736914473 +0.083799991735014068 +-0.034098175693753806 +-0.10990773894865627 +1.0669027941411215 +0.083799991734681806 +-0.034097995885430929 +-0.1186608699878627 +1.0705127363345845 +0.083799991735137122 +-0.034098231666442165 +-0.11916878191173368 +1.0707375519497697 +0.083799991735135415 +-0.034098231222840371 +-0.11380811583629898 +1.0686580932398539 +0.083799991734670273 +-0.03409799516826191 +-0.081796966577053681 +1.0697056262276128 +-0.099085185525199085 +1.081444220696097 +-0.091238698582684089 +1.085595787252476 +0.011999991292297913 +0.0052038123079867146 +-0.08583256709638476 +1.0870240653400089 +0.0071999912932143488 +0.002550845486845121 +-0.099085185525199099 +1.081444220696097 +-0.099085185525199085 +1.081444220696097 +-0.11692900823526545 +1.0924282788307085 +-0.06315789394636652 +1.0847968247657764 +-0.076336115251317976 +1.0816891286869825 +-0.083821132117418443 +1.0821850929458252 +-0.094361158688304733 +1.071080151886185 +-0.15893181643231205 +1.0657749812239379 +-0.12305198477379628 +1.0681712117016684 +-0.14820847719952868 +1.0688042087488265 +-0.16780374576068843 +1.0681116434498579 +-0.09675803716489062 +1.0831894286075447 +-0.077790643603364587 +1.0759063758926242 +0.0095999912905300848 +-0.0035980237097491749 +-0.090193054917102583 +1.0809470053314618 +0.014999991289583754 +-0.0054981862900954073 +-0.09675803716489062 +1.0831894286075447 +-0.12318317973133169 +1.0831965453008754 +-0.11000396808278215 +1.0779106456137495 +0.053999991735796844 +-0.021999304010545454 +-0.099357698004402348 +1.0940257109889011 +-0.074493212538598794 +1.0845906596354546 +-0.1300178384193568 +1.073859964878517 +-0.092479011576343306 +1.0793517352921089 +-0.10571534645672588 +1.0753559004097157 +-0.12638617398586718 +1.0999999934047902 +-0.12073929626096971 +1.0691151603335158 +-0.030742619439301302 +1.0854501154511345 +-0.046125803756896309 +1.0840793535139781 +0.019583769520197723 +1.0860327361650217 +0.6760000068563764 +0.0080419578794266276 +0.047236527214564082 +1.0870579984978277 +1.5480000123359412 +0.064490568260974726 +-0.058446093611934494 +1.0821243919598103 +-0.095237936333225248 +1.0678049325933641 +-0.10662189020150124 +1.0791848243972639 +-0.11495912940185743 +1.0754997076511899 +-0.12086595071357362 +1.0691756473758194 +-0.12992100155225111 +1.0868866148574692 +-0.039509405717595932 +1.0839756553908122 +-0.084943965071669514 +1.0727705218249515 +-0.034499685988742666 +1.0859290328667768 +0.014000006867549269 +0.0029860788094578216 +0.030805918075115291 +1.0963756968497393 +1.3350000102129331 +0.23614526071264125 +-0.087924719365595455 +1.0792063229245179 +-0.10926386368590228 +1.07273497330858 +-0.10934742187567288 +1.0753733343834575 +-0.12704487585827551 +1.0687569115201578 +-0.14890583822731251 +1.0681159609957647 +-0.041053094907119468 +1.0836297225661526 +-0.056059594444304382 +1.0835473018730153 +-0.078355797131371072 +1.0847234103707386 +-0.10223073011207733 +1.0775301053643322 +-0.044140377095413297 +1.0918095799333767 +0.39019999170770853 +0.063902927714944324 +-0.05685414198196919 +1.0947399708623047 +0.39019999170957331 +0.16144820011631833 +-0.068107204638077151 +1.09169459227679 +0.39019999170987307 +0.22979365675278465 +-0.043504787610228975 +1.0832093705517027 +-0.085400808866557057 +1.0707247999035936 +-0.068516613325315973 +1.0804441303663384 +-0.1207137149529223 +1.0696639249576174 +-0.11518947402852842 +1.0673015015330134 +-0.07164965434100902 +1.0862198958029519 +-0.085198126467631502 +1.0839317110706943 +-0.033975257816562486 +1.094141770352377 +1.3391999882647976 +0.26662501931427351 +-0.040734242974362608 +1.0926965319177426 +1.3391999882647976 +0.25723481207284615 +-0.15558921437592835 +1.0656558141514949 +-0.091927753932472267 +1.0781040761853107 +-0.11856045328130528 +1.0719798528318412 +-0.10350319905947644 +1.0762367463995213 +-0.12129890301107576 +1.0691531939449239 +-0.12280646657062309 +1.068008263532457 +-0.10548643008172996 +1.0823589230800621 +-0.095913803045656276 +1.0754261527152622 +-0.17913021293404432 +1.0635345764431028 +-0.065887490384336875 +1.0852982945279108 +0.013165929619937814 +1.0943602619715864 +0.92400000686104322 +0.11115194403686482 +-0.13180232499190825 +1.0643384936275087 +-0.1415801235518295 +1.0698212544942407 +-0.15997218660517409 +1.070795790691238 +-0.13257720447277224 +1.0665326057006697 +0.016199991748682023 +-0.0061204936186555889 +-0.11258575209124042 +1.0627919535481118 +0.23169999173592032 +-0.053425714428115646 +-0.10401143777644142 +1.0670191049342923 +0.23169999173472344 +-0.018723969116172193 +-0.12051922910620901 +1.0647733716228254 +0.23169999173592032 +-0.055363896414623803 +-0.12115369409918528 +1.0649350440075047 +0.23169999173592032 +-0.0555192058701049 +-0.077164307155504139 +1.0850037262509298 +-0.088448348952087322 +1.0833283325420375 +-0.12590383691619866 +1.0768555615112618 +-0.17244387832984634 +1.0635638753323782 +-0.18036493804341017 +1.0649420017775764 +-0.18036493804341017 +1.0649420017775764 +-0.10060790065569981 +1.0748909815906651 +-0.12761606951522153 +1.087602608290092 +-0.12761606951522153 +1.0876026082900923 +-0.12761606951522153 +1.0876026082900923 +-0.12761606951522153 +1.0876026082900923 +-0.12283225275338283 +1.0859804638466337 +0.028199991290928771 +-0.010399673568627978 +-0.12761606951522153 +1.087602608290092 +-0.12761606951522153 +1.0876026082900923 +-0.11850740467458844 +1.0843877019411419 +0.028199991290818283 +-0.01039967062339308 +-0.089057935530736931 +1.0734329774592011 +-0.10804374963159893 +1.085889786196766 +-0.12601653890572712 +1.0886325465520865 +-0.11237417184925913 +1.0931574574152654 +-0.12964324773145003 +1.0872314529184606 +-0.17394751294817701 +1.0654953468451018 +-0.088411917925969488 +1.0794926022016298 +-0.078917522491602027 +1.0864256363675111 +-0.11130787599357246 +1.0908697810119372 +-0.11436867848219728 +1.0869721488699726 +-0.17958921607982473 +1.0662920288909239 +-0.16596267085597097 +1.0691893967269495 +0.052499991753037809 +0.0088219620196941725 +-0.17166905007166941 +1.0687281000175111 +0.079799991751819635 +0.019868058644861551 +-0.13309999391809849 +1.0899328153038097 +-0.17431301060935925 +1.065553346692967 +-0.095945759503760872 +1.0802738092759883 +-0.025711303660724008 +1.0834334818618063 +-0.068868832732008625 +1.0865817268128994 0 -1.0807651604459552 -3.8340367243876217 --0.4666998261127413 --0.089782553615058783 -1.0696654670526065 --0.12439882290995571 -1.085017663932083 --0.096783770622815027 -1.0681670070766971 --0.11905879563790212 -1.0701991791001311 --0.1715721883021617 -1.0719935938331673 --0.082708020970910998 -1.0794781329354688 --0.082708020970910998 -1.0794781329354688 --0.082708020970910998 -1.0794781329354688 --0.11074504092668087 -1.0764984554124375 --0.091445520564687049 -1.084021108786293 --0.15056801086060331 -1.06970559947663 +1.0807650750574289 +3.8340367351568299 +-0.46668162161256205 +-0.089782629588481461 +1.0696652943823433 +-0.12439895216784046 +1.0850181254033016 +-0.096783731402019721 +1.0681655489267543 +-0.1190587584847291 +1.0701972974760092 +-0.17157228949871361 +1.0719936160806764 +-0.082708027964779482 +1.079477509101858 +-0.082708027964779482 +1.079477509101858 +-0.082708027964779482 +1.0794775091018582 +-0.11074496469105133 +1.0764964895159834 +-0.091445648648123434 +1.0840214443784923 +-0.15056801026757227 +1.0697042983497047 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/grad_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/grad_valid.txt index 4c8cb328..3d3b4540 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/grad_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/grad_valid.txt @@ -97,23 +97,23 @@ 0 0 0 -1900.5440000000001 +1900.5439996689197 0 0 0 -1900.5440000000001 +1900.5439996689247 0 0 0 -1900.5440000000001 +1900.5439996689197 0 0 0 -1900.5440000000001 +1900.5439996689247 0 0 0 -1901.088 +1901.0879996688757 0 0 0 @@ -145,31 +145,31 @@ 0 0 0 -1900.5639999999999 +1900.5639996695643 0 0 0 -1903.3519999999999 +1903.3519996693879 0 0 0 -1903.3519999999999 +1903.3519996694004 0 0 0 -1903.3519999999999 +1903.3519996693872 0 0 0 -1903.3519999999999 +1903.3519996694054 0 0 0 -1903.3519999999999 +1903.3519996694054 0 0 0 -1903.3519999999999 +1903.3519996693869 0 0 0 @@ -177,11 +177,11 @@ 0 0 0 -2316.1799999999998 +2316.179999651692 0 0 0 -2314.8880000000004 +2314.8879996517289 0 0 0 @@ -209,11 +209,11 @@ 0 0 0 -2315.5840000000003 +2315.5839996516215 0 0 0 -2317 +2316.9999996515835 0 0 0 @@ -221,7 +221,7 @@ 0 0 0 -1902.1599999999999 +1902.159999669432 0 0 0 @@ -293,15 +293,15 @@ 0 0 0 -1915.6079999999999 +1915.6079996683084 0 0 0 -1915.6079999999999 +1915.6079996683829 0 0 0 -1915.6079999999999 +1915.607999668395 0 0 0 @@ -319,11 +319,11 @@ 0 0 0 -1953.568 +1953.567999530592 0 0 0 -1953.568 +1953.567999530592 0 0 0 @@ -357,23 +357,23 @@ 0 0 0 -1900.6479999999999 +1900.6479996699472 0 0 0 -1909.268 +1909.2679996694369 0 0 0 -1909.268 +1909.2679996693889 0 0 0 -1909.268 +1909.2679996694369 0 0 0 -1909.268 +1909.2679996694369 0 0 0 @@ -399,7 +399,7 @@ 0 0 0 -2320.5279999999998 +2320.5279996516369 0 0 0 @@ -407,7 +407,7 @@ 0 0 0 -2320.5279999999998 +2320.5279996516329 0 0 0 @@ -433,11 +433,11 @@ 0 0 0 -1902.1000000000001 +1902.0999996701214 0 0 0 -1903.192 +1903.1919996700728 0 0 0 diff --git a/datafiles/test_validation/case_ACTIVSg200.m/obj_value_valid.txt b/datafiles/test_validation/case_ACTIVSg200.m/obj_value_valid.txt index b8f9eb90..6aebfcb6 100644 --- a/datafiles/test_validation/case_ACTIVSg200.m/obj_value_valid.txt +++ b/datafiles/test_validation/case_ACTIVSg200.m/obj_value_valid.txt @@ -1 +1 @@ -27557.571048064096 +27557.570526047872 diff --git a/src/opflow/model/power_bal_hiop/pbpolhiopkernels.cpp b/src/opflow/model/power_bal_hiop/pbpolhiopkernels.cpp index 7f396acb..c1f6e70c 100644 --- a/src/opflow/model/power_bal_hiop/pbpolhiopkernels.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolhiopkernels.cpp @@ -170,10 +170,10 @@ PetscErrorCode OPFLOWSetConstraintBoundsArray_PBPOLHIOP(OPFLOW opflow, /* Inequality constraints */ for (i = 0; i < lineparams->nlinelim; i++) { int j = lineparams->linelimidx[i]; - gl[lineparams->gbineqidx[i]] = 0.0; + gl[lineparams->gbineqidx[i]] = PETSC_NINFINITY; gu[lineparams->gbineqidx[i]] = (lineparams->rateA[j] / ps->MVAbase) * (lineparams->rateA[j] / ps->MVAbase); - gl[lineparams->gbineqidx[i] + 1] = 0.0; + gl[lineparams->gbineqidx[i] + 1] = PETSC_NINFINITY; gu[lineparams->gbineqidx[i] + 1] = (lineparams->rateA[j] / ps->MVAbase) * (lineparams->rateA[j] / ps->MVAbase); } diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopkernels.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopkernels.cpp index 0aa506bb..37772894 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopkernels.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopkernels.cpp @@ -75,9 +75,9 @@ PetscErrorCode OPFLOWSetConstraintBoundsArray_PBPOLRAJAHIOP(OPFLOW opflow, RAJA::RangeSegment(0, lineparams->nlinelim), RAJA_LAMBDA(RAJA::Index_type i) { int j = linelimidx[i]; - gl_dev[gbineqidx[i]] = 0.0; + gl_dev[gbineqidx[i]] = PETSC_NINFINITY; gu_dev[gbineqidx[i]] = (rateA[j] / MVAbase) * (rateA[j] / MVAbase); - gl_dev[gbineqidx[i] + 1] = 0.0; + gl_dev[gbineqidx[i] + 1] = PETSC_NINFINITY; gu_dev[gbineqidx[i] + 1] = (rateA[j] / MVAbase) * (rateA[j] / MVAbase); }); From 9da737ea4faad6f4a099a960c9214ca94b1eb9e8 Mon Sep 17 00:00:00 2001 From: pelesh Date: Wed, 15 Apr 2026 11:39:33 -0400 Subject: [PATCH 04/14] A placeholder for implementing Jacobian unit tests. (#33) --- .../objective/{OF_unittestx3.m => testx3.m} | 0 .../{OF_unittestx600.m => testx600.m} | 0 tests/unit/opflow/CMakeLists.txt | 1 + .../opflow/constraint_jacobian/CMakeLists.txt | 2 + .../equality/CMakeLists.txt | 97 ++++++++++ ...ints_jacobian_test_design.md => README.md} | 0 .../equality/jac_eq_acopf.cpp | 166 +++++++++++++++++ .../inequality/CMakeLists.txt | 92 ++++++++++ ...ints_jacobian_test_design.md => README.md} | 0 .../inequality/jac_ineq_acopf.cpp | 167 ++++++++++++++++++ tests/unit/opflow/objective/CMakeLists.txt | 4 +- tests/unit/utils/test_base.h | 2 +- 12 files changed, 528 insertions(+), 3 deletions(-) rename datafiles/unit/opflow/objective/{OF_unittestx3.m => testx3.m} (100%) rename datafiles/unit/opflow/objective/{OF_unittestx600.m => testx600.m} (100%) create mode 100644 tests/unit/opflow/constraint_jacobian/CMakeLists.txt create mode 100644 tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt rename tests/unit/opflow/constraint_jacobian/equality/{compute_equality_constraints_jacobian_test_design.md => README.md} (100%) create mode 100644 tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp create mode 100644 tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt rename tests/unit/opflow/constraint_jacobian/inequality/{compute_inequality_constraints_jacobian_test_design.md => README.md} (100%) create mode 100644 tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp diff --git a/datafiles/unit/opflow/objective/OF_unittestx3.m b/datafiles/unit/opflow/objective/testx3.m similarity index 100% rename from datafiles/unit/opflow/objective/OF_unittestx3.m rename to datafiles/unit/opflow/objective/testx3.m diff --git a/datafiles/unit/opflow/objective/OF_unittestx600.m b/datafiles/unit/opflow/objective/testx600.m similarity index 100% rename from datafiles/unit/opflow/objective/OF_unittestx600.m rename to datafiles/unit/opflow/objective/testx600.m diff --git a/tests/unit/opflow/CMakeLists.txt b/tests/unit/opflow/CMakeLists.txt index 2f09e12f..a312cf31 100644 --- a/tests/unit/opflow/CMakeLists.txt +++ b/tests/unit/opflow/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(objective) +add_subdirectory(constraint_jacobian) diff --git a/tests/unit/opflow/constraint_jacobian/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/CMakeLists.txt new file mode 100644 index 00000000..5a69e533 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(equality) +add_subdirectory(inequality) diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt new file mode 100644 index 00000000..4c9e1630 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -0,0 +1,97 @@ +if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) + set_source_files_properties(jac_eq_acopf.cpp PROPERTIES LANGUAGE CUDA) +endif() + +add_executable( + jac_eq_acopf jac_eq_acopf.cpp + ${CMAKE_SOURCE_DIR}/tests/unit/utils/test_acopf_utils.cpp +) +target_link_libraries(jac_eq_acopf ExaGO::OPFLOW) +target_include_directories( + jac_eq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/utils +) +target_include_directories( + jac_eq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/opflow +) + +# Network files to run on - doing 3 and 600 bus examples. +set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) +set(obj_network_files testx3.m testx600.m) +# Map num_copies to a specific netfile +set(num_copies 3 600) + +list(TRANSFORM obj_network_files PREPEND ${prefix}) + +set(solvers "") +set(models "") +set(dependencies "") + +# Set up Ipopt solver tests if enabled +if(EXAGO_ENABLE_IPOPT) + list(APPEND solvers IPOPT) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies IPOPT) +endif() + +# Set up HIOP solver tests if enabled (deprecated) +if(EXAGO_ENABLE_HIOP) + list(APPEND solvers HIOP) + list(APPEND models POWER_BALANCE_HIOP) + list(APPEND dependencies HIOP) +endif() + +# Set up HIOPSPARSE solver tests if enabled +if(TARGET HiOp::SPARSE) + list(APPEND solvers HIOPSPARSE) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies HIOP_SPARSE) +endif() + +# Set up RAJA support tests if enabled (deprecated) +if(EXAGO_ENABLE_RAJA) + list(APPEND solvers HIOP) + list(APPEND models PBPOLRAJAHIOP) + list(APPEND dependencies HIOP) +endif() + +if(EXAGO_RUN_TESTS) + foreach( + model + solver + dependency + IN + ZIP_LISTS + models + solvers + dependencies + ) + # Iterate over networks, matching network file to num_copies + foreach(network num IN ZIP_LISTS obj_network_files num_copies) + get_filename_component(net ${network} NAME) + set(testname + "UNIT_TESTS_EQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + ) + message(STATUS "Setting up test: ${testname}") + exago_add_test( + NAME + ${testname} + DEPENDS + ${dependency} + COMMAND + ${RUNCMD} + $ + -opflow_model + ${model} + -opflow_solver + ${solver} + -netfile + ${network} + -num_copies + ${num} + -validation + ${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv + ) + set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) + endforeach() + endforeach() +endif() diff --git a/tests/unit/opflow/constraint_jacobian/equality/compute_equality_constraints_jacobian_test_design.md b/tests/unit/opflow/constraint_jacobian/equality/README.md similarity index 100% rename from tests/unit/opflow/constraint_jacobian/equality/compute_equality_constraints_jacobian_test_design.md rename to tests/unit/opflow/constraint_jacobian/equality/README.md diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp new file mode 100644 index 00000000..2b09eea4 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -0,0 +1,166 @@ +#include +#include +#include + +#include +#include +#include + +#include "opflow_tests.h" +#include "test_acopf_utils.h" + +/** + * @brief Unit test driver for objective function + * @see opflow/OpflowTests.hpp for kernel tested by this driver + * + * You can pass two options to the objectiveAcopf executatable through the + * command line (implemented using PETSc options): + * + * ~ -netfile : Specifies the input data file to test against. + * Default value is `//datafiles/case9/case9mod.m`. See directory + * datafiles for other potential inputs. + * + * ~ -num_copies : Specifies the number of replications of the + * network given through `-netfile`. If this is not set properly, test may fail + * + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + Vec X; + int fail = 0; + double obj_value; + char file_c_str[PETSC_MAX_PATH_LEN]; + char validation_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + int num_copies = 0; + + char help[] = "Unit tests for equality constraint Jacobians running opflow\n"; + + /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); + return ierr; + } + + /* Get network data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + + /* Get num_copies from command line */ + ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); + CHKERRQ(ierr); + + if (!flg) { + file = "../datafiles/case9/case9mod.m"; + } else { + file.assign(file_c_str); + } + + // Set obj_value as reference solution, and run as usual + /* Get validation data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + readFromFile(&obj_value, validation_c_str); + + obj_value = obj_value * num_copies; + + OPFLOW opflowtest; + exago::tests::TestOpflow test; + + /* Set up test opflow */ + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflowtest, &X); + CHKERRQ(ierr); + + // If we are using HIOP, need to convert X + // The string lengths must be 65 + std::string modelname; + std::string solvername; + ierr = OPFLOWGetModel(opflowtest, &modelname); + ierr = OPFLOWGetSolver(opflowtest, &solvername); + + if (solvername == "HIOP") { +#if defined(EXAGO_ENABLE_HIOP) + double *x_ref; + ierr = VecGetArray(X, &x_ref); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + // If we are running using the CPU model, nothing needs to be done + if (modelname == "POWER_BALANCE_HIOP") { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref, obj_value); + } else // Using model PBPOLRAJAHIOP + { +#if defined(EXAGO_ENABLE_RAJA) + // Get resource manager instance + auto &resmgr = umpire::ResourceManager::getInstance(); + + // Get Allocator + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Register array xref with umpire + umpire::util::AllocationRecord record_x{ + x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_ref, record_x); + // Allocate and copy xref to device + double *x_ref_dev; + +#ifdef EXAGO_ENABLE_GPU + + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); + CHKERRQ(ierr); + + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_ref_dev = + static_cast(d_allocator.allocate(nx * sizeof(double))); +#else + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); + CHKERRQ(ierr); + x_ref_dev = x_ref; +#endif + resmgr.copy(x_ref_dev, x_ref); + + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_ref_dev); +#endif +#endif + } + + ierr = VecRestoreArray(X, &x_ref); + CHKERRQ(ierr); + + ierr = PetscFree(x_ref); + CHKERRQ(ierr); +#endif // End #ifdefined(EXAGO_ENABLE_HIOP) + } else { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, X, obj_value); + } + ierr = OPFLOWDestroy(&opflowtest); + CHKERRQ(ierr); + + // Temporarily skip the test + fail = exago::tests::SKIP_TEST; + + ExaGOFinalize(); + return fail; +} diff --git a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt new file mode 100644 index 00000000..18177699 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt @@ -0,0 +1,92 @@ +if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) + set_source_files_properties(jac_ineq_acopf.cpp PROPERTIES LANGUAGE CUDA) +endif() + +add_executable( + jac_ineq_acopf jac_ineq_acopf.cpp + ${CMAKE_SOURCE_DIR}/tests/unit/utils/test_acopf_utils.cpp +) +target_link_libraries(jac_ineq_acopf ExaGO::OPFLOW) +target_include_directories( + jac_ineq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/utils +) +target_include_directories( + jac_ineq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/opflow +) + +# Network files to run on - doing 3 and 600 bus examples. +set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) +set(obj_network_files testx3.m testx600.m) +# Map num_copies to a specific netfile +set(num_copies 3 600) + +list(TRANSFORM obj_network_files PREPEND ${prefix}) + +# Set up Ipopt solver tests if enabled +if(EXAGO_ENABLE_IPOPT) + list(APPEND solvers IPOPT) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies IPOPT) +endif() + +# Set up HIOP solver tests if enabled (deprecated) +if(EXAGO_ENABLE_HIOP) + list(APPEND solvers HIOP) + list(APPEND models POWER_BALANCE_HIOP) + list(APPEND dependencies HIOP) +endif() + +# Set up HIOPSPARSE solver tests if enabled +if(TARGET HiOp::SPARSE) + list(APPEND solvers HIOPSPARSE) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies HIOP_SPARSE) +endif() + +# Set up RAJA support tests if enabled (deprecated) +if(EXAGO_ENABLE_RAJA) + list(APPEND solvers HIOP) + list(APPEND models PBPOLRAJAHIOP) + list(APPEND dependencies HIOP) +endif() + +if(EXAGO_RUN_TESTS) + foreach( + model + solver + dependency + IN + ZIP_LISTS + models + solvers + dependencies + ) + # Iterate over networks, matching network file to num_copies + foreach(network num IN ZIP_LISTS obj_network_files num_copies) + get_filename_component(net ${network} NAME) + set(testname + "UNIT_TESTS_INEQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + ) + exago_add_test( + NAME + ${testname} + DEPENDS + ${dependency} + COMMAND + ${RUNCMD} + $ + -opflow_model + ${model} + -opflow_solver + ${solver} + -netfile + ${network} + -num_copies + ${num} + -validation + ${CMAKE_CURRENT_SOURCE_DIR}/cicj.csv + ) + set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) + endforeach() + endforeach() +endif() diff --git a/tests/unit/opflow/constraint_jacobian/inequality/compute_inequality_constraints_jacobian_test_design.md b/tests/unit/opflow/constraint_jacobian/inequality/README.md similarity index 100% rename from tests/unit/opflow/constraint_jacobian/inequality/compute_inequality_constraints_jacobian_test_design.md rename to tests/unit/opflow/constraint_jacobian/inequality/README.md diff --git a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp new file mode 100644 index 00000000..4a6fc30c --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp @@ -0,0 +1,167 @@ +#include +#include +#include + +#include +#include +#include + +#include "opflow_tests.h" +#include "test_acopf_utils.h" + +/** + * @brief Unit test driver for objective function + * @see opflow/OpflowTests.hpp for kernel tested by this driver + * + * You can pass two options to the objectiveAcopf executatable through the + * command line (implemented using PETSc options): + * + * ~ -netfile : Specifies the input data file to test against. + * Default value is `//datafiles/case9/case9mod.m`. See directory + * datafiles for other potential inputs. + * + * ~ -num_copies : Specifies the number of replications of the + * network given through `-netfile`. If this is not set properly, test may fail + * + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + Vec X; + int fail = 0; + double obj_value; + char file_c_str[PETSC_MAX_PATH_LEN]; + char validation_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + int num_copies = 0; + + char help[] = + "Unit tests for inequality constraint Jacobians running opflow\n"; + + /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); + return ierr; + } + + /* Get network data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + + /* Get num_copies from command line */ + ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); + CHKERRQ(ierr); + + if (!flg) { + file = "../datafiles/case9/case9mod.m"; + } else { + file.assign(file_c_str); + } + + // Set obj_value as reference solution, and run as usual + /* Get validation data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + readFromFile(&obj_value, validation_c_str); + + obj_value = obj_value * num_copies; + + OPFLOW opflowtest; + exago::tests::TestOpflow test; + + /* Set up test opflow */ + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflowtest, &X); + CHKERRQ(ierr); + + // If we are using HIOP, need to convert X + // The string lengths must be 65 + std::string modelname; + std::string solvername; + ierr = OPFLOWGetModel(opflowtest, &modelname); + ierr = OPFLOWGetSolver(opflowtest, &solvername); + + if (solvername == "HIOP") { +#if defined(EXAGO_ENABLE_HIOP) + double *x_ref; + ierr = VecGetArray(X, &x_ref); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + // If we are running using the CPU model, nothing needs to be done + if (modelname == "POWER_BALANCE_HIOP") { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref, obj_value); + } else // Using model PBPOLRAJAHIOP + { +#if defined(EXAGO_ENABLE_RAJA) + // Get resource manager instance + auto &resmgr = umpire::ResourceManager::getInstance(); + + // Get Allocator + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Register array xref with umpire + umpire::util::AllocationRecord record_x{ + x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_ref, record_x); + // Allocate and copy xref to device + double *x_ref_dev; + +#ifdef EXAGO_ENABLE_GPU + + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); + CHKERRQ(ierr); + + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_ref_dev = + static_cast(d_allocator.allocate(nx * sizeof(double))); +#else + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); + CHKERRQ(ierr); + x_ref_dev = x_ref; +#endif + resmgr.copy(x_ref_dev, x_ref); + + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_ref_dev); +#endif +#endif + } + + ierr = VecRestoreArray(X, &x_ref); + CHKERRQ(ierr); + + ierr = PetscFree(x_ref); + CHKERRQ(ierr); +#endif // End #ifdefined(EXAGO_ENABLE_HIOP) + } else { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, X, obj_value); + } + ierr = OPFLOWDestroy(&opflowtest); + CHKERRQ(ierr); + + // Temporarily skip the test + fail = exago::tests::SKIP_TEST; + + ExaGOFinalize(); + return fail; +} diff --git a/tests/unit/opflow/objective/CMakeLists.txt b/tests/unit/opflow/objective/CMakeLists.txt index 0b89bff6..07b52079 100644 --- a/tests/unit/opflow/objective/CMakeLists.txt +++ b/tests/unit/opflow/objective/CMakeLists.txt @@ -11,7 +11,7 @@ target_include_directories(objective_acopf PRIVATE ../) # Network files to run on - doing 3 and 600 bus examples. set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) -set(obj_network_files OF_unittestx3.m OF_unittestx600.m) +set(obj_network_files testx3.m testx600.m) # Map num_copies to a specific netfile set(num_copies 3 600) @@ -40,7 +40,7 @@ if(EXAGO_RUN_TESTS) # Iterate over networks, matching network file to num_copies foreach(network num IN ZIP_LISTS obj_network_files num_copies) get_filename_component(net ${network} NAME) - set(testname "UNIT_TESTS_OBJECTIVE_SIZE_${net}_${solver}_${model}") + set(testname "UNIT_TESTS_OBJECTIVE_${net}_${solver}_${model}") exago_add_test( NAME ${testname} diff --git a/tests/unit/utils/test_base.h b/tests/unit/utils/test_base.h index f03dc5bf..0e2d018c 100644 --- a/tests/unit/utils/test_base.h +++ b/tests/unit/utils/test_base.h @@ -35,7 +35,7 @@ static const RealType three = 3.0; // static const RealType eps = 10*std::numeric_limits::epsilon(); static const RealType eps = 1e-8; -static const LocalOrdinalType SKIP_TEST = -1; +static const LocalOrdinalType SKIP_TEST = 2; /** @brief Base class for all testing classes. Each child class will call the From cbae7cec8c4585498db8082ada822c44f9a76dec Mon Sep 17 00:00:00 2001 From: Nicholson Koukpaizan <72402802+nkoukpaizan@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:52:59 -0400 Subject: [PATCH 05/14] Testing for RAJAHIOPSPARSE equality and inequality constraint Jacobians (#31) * test_acopf with PBPOLRAJAHIOPSPARSE (verify equality constraint Jacobian) + bug fix for PBPOL. Co-authored-by: William A Perkins * Cleanup changes to RAJAHIOPSPARSE nnz computation. * Workaround for RAJAHIOPSPARSE inequality constraint verification. * Handling cases where IPOPT or HIOP are not available in test_acopt + bug fixes. * HiOp-compatible checks for constraint Jacobian allocations. Will need a smarter way to verify the stacked inequality constraints. * Fix for inequality constraint offsets. --------- Co-authored-by: William A Perkins Co-authored-by: nkoukpaizan --- .gitignore | 1 + .../power_bal_hiop/pbpolrajahiopsparse.cpp | 157 ++++++++++++++++- .../pbpolrajahiopsparsekernels.cpp | 14 +- tests/unit/opflow/opflow_tests.h | 159 +++++++++++++++--- tests/unit/test_acopf.cpp | 45 ++++- 5 files changed, 327 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 17a5b464..b73002fa 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ myenv/ launcher/config.yaml launcher/run.sh *.warning +*ipynb diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp index fa609378..9624445b 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp @@ -99,8 +99,8 @@ PetscErrorCode OPFLOWSolutionToPS_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { if (opflow->include_powerimbalance_variables) { loc = bus->startxpimbloc; - bus->pimb = x[loc]; - bus->qimb = x[loc + 1]; + bus->pimb = x[loc] - x[loc + 1]; + bus->qimb = x[loc + 2] - x[loc + 3]; } for (k = 0; k < bus->ngen; k++) { @@ -115,7 +115,7 @@ PetscErrorCode OPFLOWSolutionToPS_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { gen->pg = x[loc]; gen->qg = x[loc + 1]; - if (opflow->has_gensetpoint) { + if (opflow->has_gensetpoint && !gen->isrenewable) { gloc += gen->nconeq; } } @@ -125,8 +125,8 @@ PetscErrorCode OPFLOWSolutionToPS_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { ierr = PSBUSGetLoad(bus, k, &load); CHKERRQ(ierr); loc = load->startxloadlossloc; - load->pl = load->pl - x[loc]; - load->ql = load->ql - x[loc + 1]; + load->pl_loss = x[loc]; + load->ql_loss = x[loc + 1]; } } } @@ -223,10 +223,149 @@ PetscErrorCode OPFLOWModelSetUp_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { /* Need to compute the number of nonzeros in equality, inequality constraint * Jacobians and Hessian */ - int nnz_eqjacsp = 0, nnz_ineqjacsp = 0, nnz_hesssp = 0; - opflow->nnz_eqjacsp = nnz_eqjacsp; - opflow->nnz_ineqjacsp = nnz_ineqjacsp; - opflow->nnz_hesssp = nnz_hesssp; + int nnz_eqjac = 0, nnz_ineqjac = 0, nnz_hess = 0; + + // Find nonzero entries in equality constraint Jacobian by row. Using + // OPFLOWComputeEqualityConstraintJacobian_PBPOL() as a guide. + + PS ps = (PS)opflow->ps; + + for (int ibus = 0; ibus < ps->nbus; ++ibus) { + + PSBUS bus = &(ps->bus[ibus]); + + // Nonzero entries used by each *bus* starts here + + // no matter what, each bus uses 2 rows and 2 columns + // row 1 = real, row2 = reactive + nnz_eqjac += 2; + nnz_eqjac += 2; + + if (bus->ide == ISOLATED_BUS) { + continue; + } + + if (opflow->include_powerimbalance_variables) { + // 2 more entries on both real and reactive + nnz_eqjac += 4; + } + + if (opflow->has_gensetpoint) { + for (int bgen = 0; bgen < bus->ngen; ++bgen) { + PSGEN gen; + ierr = PSBUSGetGen(bus, bgen, &gen); + CHKERRQ(ierr); + + if (!gen->status || gen->isrenewable) + continue; + + // each generator uses 2 rows, 3 columns real, 1 column reactive + nnz_eqjac += 4; + } + } + } + + // Go through the lines + for (int iline = 0; iline <= ps->nline; ++iline) { + PSLINE line = &(ps->line[iline]); + + if (!line->status) + continue; + + // each line adds 4 (off-diagonal) entries for the to bus and 4 + // entries for the from bus. Each line also modifies 4 existing + // to and from bus entries. + nnz_eqjac += 4; + nnz_eqjac += 4; + } + + // if there are lines, non-zeros were over counted + if (ps->nline > 0) { + nnz_eqjac -= 8; + } + + if (opflow->has_gensetpoint) { + for (int ibus = 0; ibus < ps->nbus; ++ibus) { + PSBUS bus = &(ps->bus[ibus]); + for (int bgen = 0; bgen < bus->ngen; ++bgen) { + PSGEN gen; + ierr = PSBUSGetGen(bus, bgen, &gen); + CHKERRQ(ierr); + + if (!gen->status) + continue; + + nnz_ineqjac += 6; + } + } + } + + if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { + for (int ibus = 0; ibus < ps->nbus; ++ibus) { + PSBUS bus = &(ps->bus[ibus]); + if (bus->ide == PV_BUS || bus->ide == REF_BUS) { + nnz_ineqjac += 2; + } + } + } + + for (int iline = 0; iline < opflow->nlinesmon; ++iline) { + nnz_ineqjac += 8; + } + + for (int ibus = 0; ibus < ps->nbus; ++ibus) { + // reserve 2 real and 2 reactive entries for each bus + // 3 upper triangular + nnz_hess += 3; + + if (opflow->include_powerimbalance_variables) { + nnz_hess += 2; + } + } + + for (int i = 0; i < ps->ngen; ++i) { + PSGEN gen = &(ps->gen[i]); + + if (!gen->status) + continue; + + nnz_hess += 2; + + if (opflow->has_gensetpoint) { + if (gen->isrenewable) + continue; + + // later ... + // if (opflow->use_agc) { + // nnz_hess += 5; + // } + } + if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { + nnz_hess += 2; + } + } + + for (int iline = 0; iline < ps->nline; ++iline) { + PSLINE line = &(ps->line[iline]); + + if (!line->status) + continue; + + // 3 diagonal entries for on the from-bus rows (already defined) + // 3 diagonal entries for on the to-bus rows (already defined) + // 4 off-diagonal entries in upper part + nnz_hess += 4; + } + + if (opflow->include_loadloss_variables) { + for (int iload = 0; iload < ps->nload; ++iload) { + nnz_hess += 2; + } + } + + opflow->nnz_eqjacsp = nnz_eqjac; + opflow->nnz_ineqjacsp = nnz_ineqjac; + opflow->nnz_hesssp = nnz_hess; ierr = busparams->copy(opflow); ierr = genparams->copy(opflow); diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp index adc10c8e..e18ba20c 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp @@ -487,7 +487,7 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; - if (MJacS_dev == NULL) { + if (iJacS_dev != NULL && jJacS_dev != NULL) { /* Set locations only */ if (opflow->Nconineq) { @@ -540,7 +540,9 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( ierr = PetscLogEventEnd(opflow->ineqconsjaclogger, 0, 0, 0, 0); CHKERRQ(ierr); } - } else { + } + + if (MJacS_dev != NULL) { if (opflow->Nconineq) { ierr = PetscLogEventBegin(opflow->ineqconsjaclogger, 0, 0, 0, 0); CHKERRQ(ierr); @@ -607,7 +609,7 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; - if (MJacS_dev == NULL) { + if (iJacS_dev != NULL && jJacS_dev != NULL) { /* Set locations only */ roffset = 0; @@ -651,7 +653,9 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( // Copy over i_jaceq and j_jaceq arrays to device resmgr.copy(iJacS_dev, pbpolrajahiopsparse->i_jaceq); resmgr.copy(jJacS_dev, pbpolrajahiopsparse->j_jaceq); - } else { + } + + if (MJacS_dev != NULL) { ierr = PetscLogEventBegin(opflow->eqconsjaclogger, 0, 0, 0, 0); CHKERRQ(ierr); @@ -688,7 +692,7 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( CHKERRQ(ierr); } - // Copy over val_ineq to device + // Copy over val_jaceq to device resmgr.copy(MJacS_dev, pbpolrajahiopsparse->val_jaceq); ierr = PetscLogEventEnd(opflow->eqconsjaclogger, 0, 0, 0, 0); diff --git a/tests/unit/opflow/opflow_tests.h b/tests/unit/opflow/opflow_tests.h index e061a41e..12572d39 100644 --- a/tests/unit/opflow/opflow_tests.h +++ b/tests/unit/opflow/opflow_tests.h @@ -447,13 +447,20 @@ class TestOpflow : public TestBase { Vec temp1, temp2; PetscInt nrow, ncol; + // Create constraint Jacobian matrices to compare against ierr = MatDuplicate(Jeqref, MAT_DO_NOT_COPY_VALUES, &Jeq); CHKERRQ(ierr); - ierr = MatDuplicate(Jineqref, MAT_DO_NOT_COPY_VALUES, &Jineq); - CHKERRQ(ierr); + std::cout << "opflow->Nconineq: " << opflow->Nconineq << "\n"; + if (opflow->Nconineq) { + ierr = MatDuplicate(Jineqref, MAT_DO_NOT_COPY_VALUES, &Jineq); + CHKERRQ(ierr); + } + + // Compute constraint Jacobians ierr = OPFLOWComputeConstraintJacobian(opflow, X, Jeq, Jineq); CHKERRQ(ierr); + // Verify equality constraint Jacobian ierr = MatGetSize(Jeq, &nrow, &ncol); CHKERRQ(ierr); ierr = VecCreate(MPI_COMM_SELF, &temp1); @@ -480,36 +487,40 @@ class TestOpflow : public TestBase { ierr = VecDestroy(&temp2); CHKERRQ(ierr); - ierr = MatGetSize(Jineq, &nrow, &ncol); - CHKERRQ(ierr); - ierr = VecCreate(MPI_COMM_SELF, &temp1); - CHKERRQ(ierr); - ierr = VecSetSizes(temp1, nrow, nrow); + ierr = MatDestroy(&Jeq); CHKERRQ(ierr); - ierr = VecSetFromOptions(temp1); - ierr = VecDuplicate(temp1, &temp2); - CHKERRQ(ierr); + if (opflow->Nconineq) { + // Verify inequality constraint Jacobian + ierr = MatGetSize(Jineq, &nrow, &ncol); + CHKERRQ(ierr); + ierr = VecCreate(MPI_COMM_SELF, &temp1); + CHKERRQ(ierr); + ierr = VecSetSizes(temp1, nrow, nrow); + CHKERRQ(ierr); + ierr = VecSetFromOptions(temp1); - ierr = VecSet(temp1, 0.0); - ierr = VecSet(temp2, 0.0); + ierr = VecDuplicate(temp1, &temp2); + CHKERRQ(ierr); - ierr = MatMult(Jineq, X, temp1); - CHKERRQ(ierr); - ierr = MatMult(Jineqref, X, temp2); - CHKERRQ(ierr); + ierr = VecSet(temp1, 0.0); + ierr = VecSet(temp2, 0.0); - fail += verifyAnswer(temp1, temp2); + ierr = MatMult(Jineq, X, temp1); + CHKERRQ(ierr); + ierr = MatMult(Jineqref, X, temp2); + CHKERRQ(ierr); - ierr = VecDestroy(&temp1); - CHKERRQ(ierr); - ierr = VecDestroy(&temp2); - CHKERRQ(ierr); + fail += verifyAnswer(temp1, temp2); - ierr = MatDestroy(&Jeq); - CHKERRQ(ierr); - ierr = MatDestroy(&Jineq); - CHKERRQ(ierr); + ierr = VecDestroy(&temp1); + CHKERRQ(ierr); + ierr = VecDestroy(&temp2); + CHKERRQ(ierr); + + ierr = MatDestroy(&Jineq); + CHKERRQ(ierr); + } cleanup(fail, opflow); } @@ -691,8 +702,103 @@ class TestOpflow : public TestBase { } #if defined(EXAGO_ENABLE_RAJA) +#if defined(EXAGO_ENABLE_HIOP_SPARSE) /** * @brief Specific test for computing the constraint Jacobian using HiOp + * Sparse + * + * @param x is in sparse-dense ordering + * @param Jeqref is in application ordering + * @param Jineqref is in application ordering + * + * @pre The flag _opflow_->nconineq determines the presence of inequality + * constraints. If the flag is set, checking against Jineqref_nat can be + * skipped entirely. + * @pre _Jeqref_nat_ and _Jineqref_nat_ have the same number of columns, but + * not the same number of rows + */ + LocalOrdinalType computeConstraintJacobian(OPFLOW opflow, double *x_dev, + Mat Jeqref_nat, Mat Jineqref_nat, + umpire::ResourceManager &resmgr) { + PetscErrorCode ierr; + LocalOrdinalType fail = 0; + + // Get allocators + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Get the hiop sparse matrix solution to test against + int *iRow, *jCol, *iRow_dev, *jCol_dev; + double *values, *values_dev; + int nnz = opflow->nnz_eqjacsp + opflow->nnz_ineqjacsp; + + iRow = static_cast(h_allocator.allocate(nnz * sizeof(int))); + jCol = static_cast(h_allocator.allocate(nnz * sizeof(int))); + values = static_cast(h_allocator.allocate(nnz * sizeof(double))); + +#ifdef EXAGO_ENABLE_GPU + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + iRow_dev = static_cast(d_allocator.allocate(nnz * sizeof(int))); + jCol_dev = static_cast(d_allocator.allocate(nnz * sizeof(int))); + values_dev = + static_cast(d_allocator.allocate(nnz * sizeof(double))); +#else + iRow_dev = iRow; + jCol_dev = jCol; + values_dev = values; +#endif + + // Compute equality constraints + ierr = (*opflow->modelops.computesparseequalityconstraintjacobianhiop)( + opflow, x_dev, iRow_dev, jCol_dev, values_dev); + CHKERRQ(ierr); + + // Checking for the presence of inequality constraints on the given problem + // Compute inequality constraints + if (opflow->Nconineq) { + ierr = (*opflow->modelops.computesparseinequalityconstraintjacobianhiop)( + opflow, x_dev, iRow_dev, jCol_dev, values_dev); + CHKERRQ(ierr); + } + + // Copy from device to host + resmgr.copy(iRow, iRow_dev); + resmgr.copy(jCol, jCol_dev); + resmgr.copy(values, values_dev); + + // Verify equality constraints + fail += verifyAnswer(Jeqref_nat, opflow->nnz_eqjacsp, iRow, jCol, values); + + // Checking for the presence of inequality constraints on the given problem + // Verify inequality constraints + if (opflow->Nconineq) { + // The equality and inequality constraint Jacobians are stacked one after + // the other. Offset row and nnz + int nnz_offset = opflow->nnz_eqjacsp; + int row_offset = opflow->nconeq; + for (int i = 0; i < opflow->nnz_ineqjacsp; i++) { + iRow[i + nnz_offset] -= row_offset; + } + + fail += + verifyAnswer(Jineqref_nat, opflow->nnz_ineqjacsp, iRow + nnz_offset, + jCol + nnz_offset, values + nnz_offset); + } + + // Cleanup + h_allocator.deallocate(iRow); + h_allocator.deallocate(jCol); + h_allocator.deallocate(values); +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(iRow_dev); + d_allocator.deallocate(jCol_dev); + d_allocator.deallocate(values_dev); +#endif + cleanup(fail, opflow); + } + +#else + /** + * @brief Specific test for computing the constraint Jacobian using HiOp MDS * * @param x is in sparse-dense ordering * @param Jeqref is in application ordering @@ -915,7 +1021,8 @@ class TestOpflow : public TestBase { #endif cleanup(fail, opflow); } -#endif +#endif // EXAGO_ENABLE_HIOP_SPARSE +#endif // EXAGO_ENABLE_RAJA LocalOrdinalType computeHessian(OPFLOW opflow, Vec X, Vec Lambda, PetscScalar obj_factor, Mat Hessref) { diff --git a/tests/unit/test_acopf.cpp b/tests/unit/test_acopf.cpp index 2849e442..835a829f 100644 --- a/tests/unit/test_acopf.cpp +++ b/tests/unit/test_acopf.cpp @@ -65,12 +65,25 @@ void spdensetonatural(const double *xin, double *xout, int *idxn2sd_map, * */ int main(int argc, char **argv) { - const bool isTestOpflowModelPBPOL = false; + bool testOpflowModelPBPOL = false; + bool testOpflowModelPBPOLHIOP = false; + bool testOpflowModelPBPOLRAJAHIOP = false; + bool testOpflowModelPBPOLRAJAHIOPSPARSE = false; + +#if defined(EXAGO_ENABLE_IPOPT) + testOpflowModelPBPOL = true; +#endif + +#if defined(EXAGO_ENABLE_HIOP) + testOpflowModelPBPOLHIOP = true; +#endif + #if defined(EXAGO_ENABLE_RAJA) - const bool isTestOpflowModelPBPOLRAJAHIOP = true; - const bool isTestOpflowModelPBPOLHIOP = false; +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + testOpflowModelPBPOLRAJAHIOPSPARSE = true; #else - const bool isTestOpflowModelPBPOLHIOP = true; + testOpflowModelPBPOLRAJAHIOP = true; +#endif #endif PetscErrorCode ierr; PetscBool flg, gen_test_data, write_test_data; @@ -245,13 +258,13 @@ int main(int argc, char **argv) { ierr = PetscLogStagePush(stages[1]); CHKERRQ(ierr); - if (isTestOpflowModelPBPOLHIOP) { + if (testOpflowModelPBPOLHIOP) { OPFLOW opflowtest; exago::tests::TestOpflow test; std::cout << "\nTesting custom power balance model in polar coordinates for HIOP" - << "(componentwise assembly) ... \n"; + << " (componentwise assembly) ... \n"; // Create optimal power flow model ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); @@ -372,13 +385,17 @@ int main(int argc, char **argv) { } #if defined(EXAGO_ENABLE_RAJA) - if (isTestOpflowModelPBPOLRAJAHIOP) { + if (testOpflowModelPBPOLRAJAHIOP || testOpflowModelPBPOLRAJAHIOPSPARSE) { OPFLOW opflowtest; exago::tests::TestOpflow test; std::cout << "\nTesting custom power balance model in polar coordinates " "for HIOP using RAJA" - << "(PBPOLHIOPRAJA) ... \n"; +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + << " (PBPOLRAJAHIOPSPARSE) ... \n"; +#else + << " (PBPOLRAJAHIOP) ... \n"; +#endif // Create optimal power flow model ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); @@ -389,11 +406,19 @@ int main(int argc, char **argv) { CHKERRQ(ierr); /* Set opflow model type to custom model for hiop using RAJA */ +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + ierr = OPFLOWSetModel(opflowtest, OPFLOWMODEL_PBPOLRAJAHIOPSPARSE); +#else ierr = OPFLOWSetModel(opflowtest, OPFLOWMODEL_PBPOLRAJAHIOP); +#endif CHKERRQ(ierr); /* Set solver to HIOP */ +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + ierr = OPFLOWSetSolver(opflowtest, OPFLOWSOLVER_HIOPSPARSEGPU); +#else ierr = OPFLOWSetSolver(opflowtest, OPFLOWSOLVER_HIOP); +#endif CHKERRQ(ierr); /* Set up */ @@ -505,6 +530,7 @@ int main(int argc, char **argv) { fail += test.computeConstraintJacobian(opflowtest, x_ref_dev, Jeq, Jineq, resmgr); +#ifndef EXAGO_ENABLE_HIOP_SPARSE // skip hessian test for now with HIOP_SPARSE int nxdense = 2 * opflowtest->ps->nbus; double *hess_dense, *hess_dense_dev; @@ -527,6 +553,7 @@ int main(int argc, char **argv) { d_allocator.deallocate(x_ref_dev); d_allocator.deallocate(lambda_ref_dev); d_allocator.deallocate(hess_dense_dev); +#endif #endif ierr = PetscFree(x_ref); @@ -563,7 +590,7 @@ int main(int argc, char **argv) { } #endif - if (isTestOpflowModelPBPOL) { + if (testOpflowModelPBPOL) { OPFLOW opflowtest; exago::tests::TestOpflow test; From d2efd8f3ff2bde4dcdfde3a9364560fe5cb8a68c Mon Sep 17 00:00:00 2001 From: pelesh Date: Mon, 20 Apr 2026 11:28:29 -0400 Subject: [PATCH 06/14] Add more comments to HIOPRAJASPARSE implementation. (#36) * Add more comments to HIOPRAJASPARSE implementation. * [skip ci] Add headers to the matpower file for Jacobian test. --------- Co-authored-by: pelesh --- .../power_bal_hiop/pbpolrajahiopsparse.cpp | 61 +++++- .../pbpolrajahiopsparsekernels.cpp | 196 ++++++++++++++++-- .../pbpolrajahiopsparsekernels.hpp | 4 +- .../equality/CECJ_unittest1.m | 23 +- 4 files changed, 243 insertions(+), 41 deletions(-) diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp index 9624445b..b574e4bb 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp @@ -6,11 +6,20 @@ #include #include "pbpolrajahiopsparsekernels.hpp" -/* Initialization is done on the host through this function. Copying over values +/** + * @brief `extern` initial guess function from PBPOL model. + * + * Initialization is done on the host through this function. Copying over values * to the device is done in OPFLOWSetInitialGuessArray_PBPOLRAJAHIOPSPARSE */ extern PetscErrorCode OPFLOWSetInitialGuess_PBPOL(OPFLOW, Vec, Vec); +/** + * @brief Set the initial guess for the PBPOL model with Raja and HiOp sparse. + * + * This function sets the initial guess by calling the same function from + * the PBPOL model. + */ PetscErrorCode OPFLOWSetInitialGuess_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, Vec X, Vec Lambda) { PetscErrorCode ierr; @@ -23,9 +32,14 @@ PetscErrorCode OPFLOWSetInitialGuess_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, Vec X, PetscFunctionReturn(0); } +/// @brief `extern` constraint bounds function from PBPOL model. extern PetscErrorCode OPFLOWSetConstraintBounds_PBPOL(OPFLOW, Vec, Vec); -/* The constraint bounds are also calculated on the host. +/** + * @brief Set the constraint bounds for the PBPOLHIOPSPARSE model. + * + * The constraint bounds are also calculated on the host by matching function + * from PBPOL model. */ PetscErrorCode OPFLOWSetConstraintBounds_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, Vec Gl, Vec Gu) { @@ -37,9 +51,14 @@ PetscErrorCode OPFLOWSetConstraintBounds_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, PetscFunctionReturn(0); } +/// @brief `extern` variable bounds function from PBPOL model. extern PetscErrorCode OPFLOWSetVariableBounds_PBPOL(OPFLOW, Vec, Vec); -/* The variable bounds are also calculated on the host. +/** + * @brief Set the variable bounds for the PBPOLHIOPSPARSE model. + * + * The variable bounds are also calculated on the host by matching function + * from PBPOL model. */ PetscErrorCode OPFLOWSetVariableBounds_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, Vec Xl, Vec Xu) { @@ -51,6 +70,10 @@ PetscErrorCode OPFLOWSetVariableBounds_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, PetscFunctionReturn(0); } +/** + * @brief Store PBPOLRAJAHIOPSPARSE solution to the PS structure. + * + */ PetscErrorCode OPFLOWSolutionToPS_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { PetscErrorCode ierr; PS ps = (PS)opflow->ps; @@ -199,10 +222,20 @@ PetscErrorCode OPFLOWSolutionToPS_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { } /* Reuse PBPOL model set up for obtaining locations */ +/// @brief `extern` set up function from PBPOL model. extern PetscErrorCode OPFLOWModelSetUp_PBPOL(OPFLOW); +/** @brief Set up the PBPOLRAJAHIOPSPARSE model. + * + * This function initializes the host objects for the PBPOLRAJAHIOPSPARSE + * model by calling the corresponding function from the PBPOL model, and then + * allocates structures with device data, defined in `paramsrajahiop.cpp`. + */ PetscErrorCode OPFLOWModelSetUp_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { PetscErrorCode ierr; + + // This struct is defined in `paramsrajahiop.h`. It inherits from + // _p_FormPBPOLRAJAHIOP, which is unwise mixture of C and C++ approaches. PbpolModelRajaHiop *pbpolrajahiopsparse = reinterpret_cast(opflow->model); @@ -272,9 +305,9 @@ PetscErrorCode OPFLOWModelSetUp_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { if (!line->status) continue; - // each line adds 4 (off-diagonal) entries for the to bus and 4 - // entries for the from bus. Each line also modifies 4 existing - // to and from bus entries. + // each line adds 4 (off-diagonal) entries for the "to" bus and 4 + // entries for the "from" bus. Each line also modifies 4 existing + // "to" and "from" bus entries. nnz_eqjac += 4; nnz_eqjac += 4; } @@ -375,6 +408,10 @@ PetscErrorCode OPFLOWModelSetUp_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { PetscFunctionReturn(0); } +/** + * @brief Destructor for the PBPOLRAJAHIOPSPARSE model. + * + */ PetscErrorCode OPFLOWModelDestroy_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { PbpolModelRajaHiop *pbpolrajahiopsparse = reinterpret_cast(opflow->model); @@ -403,10 +440,22 @@ extern PetscErrorCode OPFLOWSolutionCallback_PBPOLRAJAHIOPSPARSE( OPFLOW, const double *, const double *, const double *, const double *, const double *, double); +/** + * @brief Constructor for the PBPOLRAJAHIOPSPARSE model. + * + * This function creates a new PBPOLRAJAHIOPSPARSE model and sets pointers + * to the model's methods implementations. + * + * @param opflow The pointer to the object to instantiate. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWModelCreate_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { PetscFunctionBegin; + // This may be confusing: The class PbpolModelRajaHiop is a sparse model + // using HiOp solver, but is implemented in file with HiOp mixed dense-sparse + // model implementation. PbpolModelRajaHiop *pbpolrajahiopsparse = new PbpolModelRajaHiop(); opflow->model = pbpolrajahiopsparse; diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp index e18ba20c..7a9d9983 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp @@ -15,6 +15,15 @@ #include "pbpolrajahiopsparsekernels.hpp" #include "pbpolrajahiopsparse.hpp" +/** + * @brief Set the initial guess array for the PBPOLRAJAHIOPSPARSE model. + * + * Sets the inital guess on the host and copies it to `x0_dev`. + * + * @param opflow The OPFLOW object. + * @param x0_dev The device array for the initial guess. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWSetInitialGuessArray_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, double *x0_dev) { PetscErrorCode ierr; @@ -43,6 +52,17 @@ PetscErrorCode OPFLOWSetInitialGuessArray_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, PetscFunctionReturn(0); } +/** + * @brief Set the variable bounds arrays for the PBPOLRAJAHIOPSPARSE model. + * + * Sets lower and upper variable bounds on the host and copies them to `xl_dev` + * and `xu_dev`, respectively. + * + * @param opflow The OPFLOW object. + * @param xl_dev The device array for the lower constraint bounds. + * @param xu_dev The device array for the upper constraint bounds. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWSetVariableBoundsArray_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, double *xl_dev, double *xu_dev) { @@ -75,6 +95,17 @@ OPFLOWSetVariableBoundsArray_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, double *xl_dev, PetscFunctionReturn(0); } +/** + * @brief Set the constraint bounds arrays for the PBPOLRAJAHIOPSPARSE model. + * + * Sets the constraint bounds on the host and copies them to `gl_dev` and + * `gu_dev`. + * + * @param opflow The OPFLOW object. + * @param gl_dev The device array for the lower constraint bounds. + * @param gu_dev The device array for the upper constraint bounds. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWSetConstraintBoundsArray_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, double *gl_dev, double *gu_dev) { @@ -110,11 +141,24 @@ PetscErrorCode OPFLOWSetConstraintBoundsArray_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } -/** EQUALITY CONSTRAINTS */ +/** + * @brief Compute the equality constraints residual for the PBPOLRAJAHIOPSPARSE + * model. + * + * Computes the equality constraints on the device using the current iterate + * `x_dev` and stores the result in `ge_dev`. + * + * @param opflow The OPFLOW object. + * @param x_dev The device array for the current solutioniterate. + * @param ge_dev The device array for the equality constraint residuals. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeEqualityConstraintsArray_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, double *ge_dev) { PbpolModelRajaHiop *pbpolrajahiopsparse = reinterpret_cast(opflow->model); + + // Get device pointers for model parameters BUSParamsRajaHiop *busparams = &pbpolrajahiopsparse->busparams; GENParamsRajaHiop *genparams = &pbpolrajahiopsparse->genparams; LOADParamsRajaHiop *loadparams = &pbpolrajahiopsparse->loadparams; @@ -128,7 +172,7 @@ PetscErrorCode OPFLOWComputeEqualityConstraintsArray_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; // PetscPrintf(MPI_COMM_SELF,"Entered Equality constraints\n"); - // Zero out array + // Zero out array with constraint residuals auto &resmgr = umpire::ResourceManager::getInstance(); resmgr.memset(ge_dev, 0, opflow->nconeq * sizeof(double)); @@ -263,7 +307,18 @@ PetscErrorCode OPFLOWComputeEqualityConstraintsArray_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } -/** INEQUALITY CONSTRAINTS **/ +/** + * @brief Compute the inequality constraints residual for the + * PBPOLRAJAHIOPSPARSE model. + * + * Computes the inequality constraints on the device using the current solution + * iterate `x_dev` and stores the result in `gi_dev`. + * + * @param opflow The OPFLOW object. + * @param x_dev The device array for the current solution iterate. + * @param gi_dev The device array for the inequality constraint residuals. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeInequalityConstraintsArray_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, double *gi_dev) { PbpolModelRajaHiop *pbpolrajahiopsparse = @@ -275,7 +330,7 @@ PetscErrorCode OPFLOWComputeInequalityConstraintsArray_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; // PetscPrintf(MPI_COMM_SELF,"Entered Inequality Constraints\n"); - // Zero out array + // Zero out residual array auto &resmgr = umpire::ResourceManager::getInstance(); resmgr.memset(gi_dev, 0, opflow->nconineq * sizeof(double)); @@ -329,10 +384,24 @@ PetscErrorCode OPFLOWComputeInequalityConstraintsArray_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } -/** OBJECTIVE FUNCTION **/ -// Note: This kernel (and all the kernels for this model assume that the data -// has been already allocated on the device. x_dev is pointer to array on the -// GPU +/** @brief Compute the objective function value for the PBPOLRAJAHIOPSPARSE + * model. + * + * Computes the objective function value on the device using the current + * solution iterate `x_dev` and stores the result in `obj`. + * + * @param[inout] opflow The OPFLOW object. + * @param[in] x_dev The device array for the current solution iterate. + * @param[out] obj The pointer to the scalar with the objective function value. + * @return PetscErrorCode indicating success or failure. + * + * @note This kernel (and all the kernels for this model assume that the data + * has been already allocated on the device. x_dev is pointer to array on the + * GPU. + * + * @todo We need to figure out how to manage PetscScalar vs double types in + * these kernels. + */ PetscErrorCode OPFLOWComputeObjectiveArray_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, double *obj) { PbpolModelRajaHiop *pbpolrajahiopsparse = @@ -356,10 +425,10 @@ PetscErrorCode OPFLOWComputeObjectiveArray_PBPOLRAJAHIOPSPARSE( int *l_xidx = loadparams->xidx_dev_; int *b_xidxpimb = busparams->xidxpimb_dev_; - /* Generator objective function contributions */ // Set up reduce sum object RAJA::ReduceSum obj_val_sum(0.0); - // Compute reduction on CUDA device + + // Generation cost contributions to the objective function RAJA::forall( RAJA::RangeSegment(0, genparams->ngenON), RAJA_LAMBDA(RAJA::Index_type i) { @@ -368,6 +437,7 @@ PetscErrorCode OPFLOWComputeObjectiveArray_PBPOLRAJAHIOPSPARSE( cost_beta[i] * Pg + cost_gamma[i]); }); + // Load loss contributions to the objective function if (opflow->include_loadloss_variables) { RAJA::forall( RAJA::RangeSegment(0, loadparams->nload), @@ -392,6 +462,7 @@ PetscErrorCode OPFLOWComputeObjectiveArray_PBPOLRAJAHIOPSPARSE( }); } + // Copy value of the sum reduction to the output value. *obj = static_cast(obj_val_sum.get()); ierr = PetscLogFlops(genparams->ngenON * 8.0); CHKERRQ(ierr); @@ -400,7 +471,17 @@ PetscErrorCode OPFLOWComputeObjectiveArray_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } -/** GRADIENT **/ +/** @brief Compute the gradient of the objective function for the + * PBPOLRAJAHIOPSPARSE model. + * + * Computes the objective function gradient on the device using the + * current solution iterate `x_dev` and stores the result in `grad_dev`. + * + * @param opflow The OPFLOW object. + * @param x_dev The device array with the current solution iterate. + * @param grad_dev The device array for the objective function gradient. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeGradientArray_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, double *grad_dev) { PbpolModelRajaHiop *pbpolrajahiopsparse = @@ -468,6 +549,23 @@ PetscErrorCode OPFLOWComputeGradientArray_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } +/** + * @brief Compute the Jacobian of the inequality constraints for the + * PBPOLRAJAHIOPSPARSE model. + * + * Takes current iterate of the solution vector x_dev and computes the + * Jacobian of the inequality constraints. The solution is stored in triplet + * format on the device in vectors iJacS_dev, jJacS_dev, and MJacS_dev, + * respectively. + * + * @param[inout] opflow The OPFLOW object. + * @param[in] x_dev The device array with the current solution iterate. + * @param[out] iJacS_dev The device array for the row indices of the Jacobian. + * @param[out] jJacS_dev The device array for the column indices of the + * Jacobian. + * @param[out] MJacS_dev The device array for the values of the Jacobian. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, int *iJacS_dev, int *jJacS_dev, @@ -487,11 +585,11 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; + // If sparsity pattern does not exist, create it! if (iJacS_dev != NULL && jJacS_dev != NULL) { - /* Set locations only */ + // Create arrays on host to store i,j, and val arrays if (opflow->Nconineq) { - // Create arrays on host to store i,j, and val arrays umpire::Allocator h_allocator_ = resmgr.getAllocator("HOST"); pbpolrajahiopsparse->i_jacineq = @@ -542,6 +640,8 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( } } + // TODO: This is bad! If MJacS_dev is NULL, this function will quietly do + // nothing. We should at least throw an error or warning. if (MJacS_dev != NULL) { if (opflow->Nconineq) { ierr = PetscLogEventBegin(opflow->ineqconsjaclogger, 0, 0, 0, 0); @@ -558,7 +658,9 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( ierr = VecRestoreArray(opflow->X, &x); CHKERRQ(ierr); - /* Compute inequality constraint jacobian */ + // Compute inequality constraint jacobian on the host + // The function pointer computeinequalityconstraintjacobian points to + // OPFLOWComputeInequalityConstraintJacobian_PBPOL ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( opflow, opflow->X, opflow->Jac_Gi); CHKERRQ(ierr); @@ -567,7 +669,8 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( CHKERRQ(ierr); values = pbpolrajahiopsparse->val_jacineq; - /* Copy over values */ + // Unpack PETSc matrix and copy values to the array `values` in + // PbpolModelRajaHiop struct. for (i = 0; i < nrow; i++) { ierr = MatGetRow(opflow->Jac_Gi, i, &nvals, &cols, &vals); CHKERRQ(ierr); @@ -590,6 +693,23 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } +/** + * @brief Compute the Jacobian of the equality constraints for the + * PBPOLRAJAHIOPSPARSE model. + * + * Takes current iterate of the solution vector x_dev and computes the + * Jacobian of the equality constraints. The solution is stored in triplet + * format on the device in vectors iJacS_dev, jJacS_dev, and MJacS_dev, + * respectively. + * + * @param[inout] opflow The OPFLOW object. + * @param[in] x_dev The device array with the current solution iterate. + * @param[out] iJacS_dev The device array for the row indices of the Jacobian. + * @param[out] jJacS_dev The device array for the column indices of the + * Jacobian. + * @param[out] MJacS_dev The device array for the values of the Jacobian. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, int *iJacS_dev, int *jJacS_dev, @@ -609,13 +729,16 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionBegin; + // If sparsity pattern has not been created, create it. + // This only needs to be done once since the sparsity pattern of the Jacobian + // does not change during the optimization. if (iJacS_dev != NULL && jJacS_dev != NULL) { /* Set locations only */ roffset = 0; coffset = 0; - // Create arrays on host to store i,j, and val arrays + // Create arrays on the host to store i, j, and val arrays umpire::Allocator h_allocator_ = resmgr.getAllocator("HOST"); pbpolrajahiopsparse->i_jaceq = @@ -628,6 +751,9 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( iRowstart = pbpolrajahiopsparse->i_jaceq; jColstart = pbpolrajahiopsparse->j_jaceq; + // Function pointer computeequalityconstraintjacobian points to + // OPFLOWComputeEqualityConstraintJacobian_PBPOL function. + // Use function from PBPOL model to create the sparsity pattern. ierr = (*opflow->modelops.computeequalityconstraintjacobian)( opflow, opflow->X, opflow->Jac_Ge); CHKERRQ(ierr); @@ -670,7 +796,10 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( ierr = VecRestoreArray(opflow->X, &x); CHKERRQ(ierr); - /* Compute equality constraint jacobian */ + // Compute equality constraint jacobian on the host + // Function pointer computeequalityconstraintjacobian points to the + // implementation OPFLOWComputeEqualityConstraintJacobian_PBPOL in the + // PBPOL model. ierr = (*opflow->modelops.computeequalityconstraintjacobian)( opflow, opflow->X, opflow->Jac_Ge); CHKERRQ(ierr); @@ -680,7 +809,8 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( values = pbpolrajahiopsparse->val_jaceq; - /* Copy over values */ + // Unpack PETSc matrix and copy values to the host array in the + // PbpolModelRajaHiop struct. for (i = 0; i < nrow; i++) { ierr = MatGetRow(opflow->Jac_Ge, i, &nvals, &cols, &vals); CHKERRQ(ierr); @@ -702,6 +832,19 @@ OPFLOWComputeSparseEqualityConstraintJacobian_PBPOLRAJAHIOPSPARSE( PetscFunctionReturn(0); } +/** + * @brief Compute the Hessian of the Lagrangian for the PBPOLRAJAHIOPSPARSE + * model. + * + * @param[inout] opflow The OPFLOW object. + * @param[in] x_dev The device array with the current solution iterate. + * @param[out] lambda_dev The device array with the current Lagrange + * multipliers. + * @param[out] iHSS_dev The device array for the row indices of the Hessian. + * @param[out] jHSS_dev The device array for the column indices of the Hessian. + * @param[out] MHSS_dev The device array for the values of the Hessian. + * @return PetscErrorCode indicating success or failure. + */ PetscErrorCode OPFLOWComputeSparseHessian_PBPOLRAJAHIOPSPARSE( OPFLOW opflow, const double *x_dev, const double *lambda_dev, int *iHSS_dev, int *jHSS_dev, double *MHSS_dev) { @@ -735,16 +878,19 @@ PetscErrorCode OPFLOWComputeSparseHessian_PBPOLRAJAHIOPSPARSE( iRow = pbpolrajahiopsparse->i_hess; jCol = pbpolrajahiopsparse->j_hess; + // Function pointer computehessian points to the function + // OPFLOWComputeHessian_PBPOL in PBPOL model. ierr = (*opflow->modelops.computehessian)( opflow, opflow->X, opflow->Lambdae, opflow->Lambdai, opflow->Hes); CHKERRQ(ierr); ierr = MatGetSize(opflow->Hes, &nrow, &nrow); CHKERRQ(ierr); - /* Copy over locations to triplet format */ - /* Note that HIOP requires a upper triangular Hessian as oppposed - to IPOPT which requires a lower triangular Hessian - */ + // Copy over locations to triplet format + // + // Note that HIOP requires a upper triangular Hessian as oppposed + // to IPOPT which requires a lower triangular Hessian + // for (i = 0; i < nrow; i++) { ierr = MatGetRow(opflow->Hes, i, &nvals, &cols, &vals); CHKERRQ(ierr); @@ -792,7 +938,9 @@ PetscErrorCode OPFLOWComputeSparseHessian_PBPOLRAJAHIOPSPARSE( CHKERRQ(ierr); } - /* Compute Hessian */ + // Compute Hessian on the host + // Function pointer computehessian points to the function + // OPFLOWComputeHessian_PBPOL in PBPOL model. ierr = (*opflow->modelops.computehessian)( opflow, opflow->X, opflow->Lambdae, opflow->Lambdai, opflow->Hes); CHKERRQ(ierr); @@ -807,6 +955,8 @@ PetscErrorCode OPFLOWComputeSparseHessian_PBPOLRAJAHIOPSPARSE( ierr = VecRestoreArray(opflow->Lambda, &lambda); CHKERRQ(ierr); + // It does not seem that computeauxhessian is set, so this if + // condition will evaluate to false. if (opflow->modelops.computeauxhessian) { ierr = VecGetArray(opflow->X, &x); CHKERRQ(ierr); diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.hpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.hpp index 9b941f3e..2392748b 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.hpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.hpp @@ -13,9 +13,9 @@ /** @brief Takes a raw pointer to some data and registers it with the - allocator and resource manager. + Umpire allocator and resource manager. - TODO: Ensure that we do not have to deregister the allocation with + @todo Ensure that we do not have to deregister the allocation with the resource manager. This is done with `resmgr.deregisterAllocation(T* ptr)`, but must we do this with ever allocation? Will we incurr a memory leak if not? diff --git a/tests/unit/opflow/constraint_jacobian/equality/CECJ_unittest1.m b/tests/unit/opflow/constraint_jacobian/equality/CECJ_unittest1.m index 223e8ba3..854dd4e3 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CECJ_unittest1.m +++ b/tests/unit/opflow/constraint_jacobian/equality/CECJ_unittest1.m @@ -4,17 +4,19 @@ mpc.baseMVA = 100.00; %% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin mpc.bus = [ -1 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 -2 1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900 -3 3 0.00 0.00 0.00 0.00 1 2.0000000 30.000000 13.80 1 1.100 0.900 -4 1 -3.40 8.80 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 -5 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 + 1 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 + 2 1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900 + 3 3 0.00 0.00 0.00 0.00 1 2.0000000 30.000000 13.80 1 1.100 0.900 + 4 1 -3.40 8.80 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 + 5 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900 ]; %% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf mpc.gen = [ -3 1.60 -2.20 9900.00 -9900.00 2.0000 100.00 1 1.60 1.60 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 0 10.0000 + 3 1.60 -2.20 9900.00 -9900.00 2.0000 100.00 1 1.60 1.60 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 0 10.0000 ]; %% generator cost data @@ -23,11 +25,12 @@ ]; %% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax mpc.branch = [ -1 2 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 -2 3 2.000000 1.000000 1.20000 0.00 0.00 0.00 2.00000 60.000 1 0.00 0.00 0.00 0.00 0.00 0.00 -2 4 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 -4 5 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 + 1 2 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 + 2 3 2.000000 1.000000 1.20000 0.00 0.00 0.00 2.00000 60.000 1 0.00 0.00 0.00 0.00 0.00 0.00 + 2 4 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 + 4 5 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00 ]; %% bus names From ccb46cfd4fb3f657d58533507e34903e83ace70e Mon Sep 17 00:00:00 2001 From: pelesh Date: Mon, 20 Apr 2026 16:59:22 -0400 Subject: [PATCH 07/14] Port sparse inequality constraint Jacobian to GPU (#40) * I am not going to lie, Cursor agent heavily helped me with this. Replace PETSc-based inequality Jacobian with GPU RAJA kernels Move the inequality constraint Jacobian computation for the HiOp sparse GPU solver entirely to the device, eliminating the per-iteration host back and forth (copy to host, PETSc compute, MatGetRow extraction, values copy back to device). Elimiate PETSc use from this part of the code. Three RAJA kernels now compute directly into device memory: - Generator set-point constraints (AGC) - Voltage-reactive-power bounds (FIXED_WITHIN_QBOUNDS) - Line flow limits (Sf^2/St^2 derivatives + slack variables) Supporting changes: - Analytical NNZ counting replaces PETSc MatGetInfo at solver setup - New device-side parameter fields (apf, vs, xpdevidx, xslackidx, bus-to-gen mapping) added to *ParamsRajaHiop structs - Sparse position indices assigned at model setup for all three contribution types Includes validation test (test_ineqjac_gpu) that solves with IPOPT, then compares PETSc and GPU Jacobian values at the converged solution. Optional -benchmark flag for performance comparison. Made-with: Cursor --------- Co-authored-by: kswirydo Co-authored-by: pelesh Co-authored-by: Nicholson Koukpaizan --- src/opflow/CMakeLists.txt | 5 +- .../model/power_bal_hiop/paramsrajahiop.cpp | 82 ++++ .../model/power_bal_hiop/paramsrajahiop.h | 41 +- .../power_bal_hiop/pbpolrajahiopsparse.cpp | 185 +++----- .../pbpolrajahiopsparse_gpu.cpp | 244 +++++++++++ .../pbpolrajahiopsparse_gpu.hpp | 30 ++ .../pbpolrajahiopsparsekernels.cpp | 43 +- .../solver/hiop/opflow_hiopsparsegpu.cpp | 18 +- tests/unit/CMakeLists.txt | 27 ++ .../equality/CMakeLists.txt | 1 - tests/unit/test_ineqjac_gpu.cpp | 406 ++++++++++++++++++ 11 files changed, 895 insertions(+), 187 deletions(-) create mode 100644 src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp create mode 100644 src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.hpp create mode 100644 tests/unit/test_ineqjac_gpu.cpp diff --git a/src/opflow/CMakeLists.txt b/src/opflow/CMakeLists.txt index d0553657..863f45f4 100644 --- a/src/opflow/CMakeLists.txt +++ b/src/opflow/CMakeLists.txt @@ -20,6 +20,7 @@ if(EXAGO_ENABLE_RAJA) set(OPFLOW_FORM_SRC ${OPFLOW_FORM_SRC} model/power_bal_hiop/pbpolrajahiopsparse.cpp model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp + model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp ) endif() endif() @@ -39,8 +40,8 @@ set_source_files_properties(${OPFLOW_SRC} PROPERTIES LANGUAGE CXX) if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) set_source_files_properties( model/power_bal_hiop/pbpolrajahiopkernels.cpp - model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp PROPERTIES LANGUAGE - CUDA + model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp + model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp PROPERTIES LANGUAGE CUDA ) endif() diff --git a/src/opflow/model/power_bal_hiop/paramsrajahiop.cpp b/src/opflow/model/power_bal_hiop/paramsrajahiop.cpp index 27e2cfa0..fbe44e4e 100644 --- a/src/opflow/model/power_bal_hiop/paramsrajahiop.cpp +++ b/src/opflow/model/power_bal_hiop/paramsrajahiop.cpp @@ -27,6 +27,11 @@ int BUSParamsRajaHiop::destroy(OPFLOW opflow) { h_allocator_.deallocate(jacsp_idx); h_allocator_.deallocate(jacsq_idx); } + h_allocator_.deallocate(ispv); + h_allocator_.deallocate(gineqidx); + h_allocator_.deallocate(ineqjacsp_idx); + h_allocator_.deallocate(genoffset); + h_allocator_.deallocate(ngenONbus); #ifdef EXAGO_ENABLE_GPU d_allocator_.deallocate(isref_dev_); @@ -46,6 +51,11 @@ int BUSParamsRajaHiop::destroy(OPFLOW opflow) { d_allocator_.deallocate(jacsp_idx_dev_); d_allocator_.deallocate(jacsq_idx_dev_); } + d_allocator_.deallocate(ispv_dev_); + d_allocator_.deallocate(gineqidx_dev_); + d_allocator_.deallocate(ineqjacsp_idx_dev_); + d_allocator_.deallocate(genoffset_dev_); + d_allocator_.deallocate(ngenONbus_dev_); #endif return 0; @@ -80,6 +90,11 @@ int BUSParamsRajaHiop::copy(OPFLOW opflow) { resmgr.copy(jacsq_idx_dev_, jacsq_idx); resmgr.copy(powerimbalance_penalty_dev_, powerimbalance_penalty); } + resmgr.copy(ispv_dev_, ispv); + resmgr.copy(gineqidx_dev_, gineqidx); + resmgr.copy(ineqjacsp_idx_dev_, ineqjacsp_idx); + resmgr.copy(genoffset_dev_, genoffset); + resmgr.copy(ngenONbus_dev_, ngenONbus); #else isref_dev_ = isref; isisolated_dev_ = isisolated; @@ -96,6 +111,11 @@ int BUSParamsRajaHiop::copy(OPFLOW opflow) { jacsp_idx_dev_ = jacsp_idx; jacsq_idx_dev_ = jacsq_idx; powerimbalance_penalty_dev_ = powerimbalance_penalty; + ispv_dev_ = ispv; + gineqidx_dev_ = gineqidx; + ineqjacsp_idx_dev_ = ineqjacsp_idx; + genoffset_dev_ = genoffset; + ngenONbus_dev_ = ngenONbus; #endif return 0; } @@ -132,18 +152,31 @@ int BUSParamsRajaHiop::allocate(OPFLOW opflow) { jacsp_idx = paramAlloc(h_allocator_, nbus); jacsq_idx = paramAlloc(h_allocator_, nbus); } + ispv = paramAlloc(h_allocator_, nbus); + gineqidx = paramAlloc(h_allocator_, nbus); + ineqjacsp_idx = paramAlloc(h_allocator_, nbus); + genoffset = paramAlloc(h_allocator_, nbus); + ngenONbus = paramAlloc(h_allocator_, nbus); /* Memzero arrays */ resmgr.memset(isref, 0, nbus * sizeof(int)); resmgr.memset(ispvpq, 0, nbus * sizeof(int)); resmgr.memset(isisolated, 0, nbus * sizeof(int)); + resmgr.memset(ispv, 0, nbus * sizeof(int)); + resmgr.memset(gineqidx, 0, nbus * sizeof(int)); + resmgr.memset(ineqjacsp_idx, 0, nbus * sizeof(int)); + resmgr.memset(genoffset, 0, nbus * sizeof(int)); + resmgr.memset(ngenONbus, 0, nbus * sizeof(int)); + int genoff = 0; for (int i = 0; i < nbus; i++) { bus = &ps->bus[i]; loc = bus->startxVloc; xidx[i] = opflow->idxn2sd_map[loc]; gidx[i] = bus->starteqloc; + genoffset[i] = genoff; + genoff += bus->ngenON; if (bus->ide == REF_BUS) isref[i] = 1; @@ -152,6 +185,12 @@ int BUSParamsRajaHiop::allocate(OPFLOW opflow) { else ispvpq[i] = 1; + if (bus->ide == PV_BUS) + ispv[i] = 1; + + ngenONbus[i] = bus->ngenON; + gineqidx[i] = bus->startineqloc; + if (opflow->genbusvoltagetype == FIXED_AT_SETPOINT) { if (bus->ide == REF_BUS || bus->ide == PV_BUS) { /* Hold voltage at reference and PV buses */ @@ -200,6 +239,11 @@ int BUSParamsRajaHiop::allocate(OPFLOW opflow) { jacsp_idx_dev_ = paramAlloc(d_allocator_, nbus); jacsq_idx_dev_ = paramAlloc(d_allocator_, nbus); } + ispv_dev_ = paramAlloc(d_allocator_, nbus); + gineqidx_dev_ = paramAlloc(d_allocator_, nbus); + ineqjacsp_idx_dev_ = paramAlloc(d_allocator_, nbus); + genoffset_dev_ = paramAlloc(d_allocator_, nbus); + ngenONbus_dev_ = paramAlloc(d_allocator_, nbus); #endif return 0; } @@ -231,6 +275,8 @@ int LINEParamsRajaHiop::copy(OPFLOW opflow) { resmgr.copy(gineqidx_dev_, gineqidx); resmgr.copy(gbineqidx_dev_, gbineqidx); resmgr.copy(linelimidx_dev_, linelimidx); + resmgr.copy(ineqjacsp_idx_dev_, ineqjacsp_idx); + resmgr.copy(xslackidx_dev_, xslackidx); } #else Gff_dev_ = Gff; @@ -250,6 +296,8 @@ int LINEParamsRajaHiop::copy(OPFLOW opflow) { gineqidx_dev_ = gineqidx; gbineqidx_dev_ = gbineqidx; linelimidx_dev_ = linelimidx; + ineqjacsp_idx_dev_ = ineqjacsp_idx; + xslackidx_dev_ = xslackidx; } #endif return 0; @@ -277,6 +325,8 @@ int LINEParamsRajaHiop::destroy(OPFLOW opflow) { h_allocator_.deallocate(gineqidx); h_allocator_.deallocate(gbineqidx); h_allocator_.deallocate(linelimidx); + h_allocator_.deallocate(ineqjacsp_idx); + h_allocator_.deallocate(xslackidx); } #ifdef EXAGO_ENABLE_GPU @@ -301,6 +351,8 @@ int LINEParamsRajaHiop::destroy(OPFLOW opflow) { d_allocator_.deallocate(gineqidx_dev_); d_allocator_.deallocate(gbineqidx_dev_); d_allocator_.deallocate(linelimidx_dev_); + d_allocator_.deallocate(ineqjacsp_idx_dev_); + d_allocator_.deallocate(xslackidx_dev_); } #endif @@ -348,6 +400,8 @@ int LINEParamsRajaHiop::allocate(OPFLOW opflow) { linelimidx = paramAlloc(h_allocator_, nlinelim); gineqidx = paramAlloc(h_allocator_, nlinelim); gbineqidx = paramAlloc(h_allocator_, nlinelim); + ineqjacsp_idx = paramAlloc(h_allocator_, nlinelim); + xslackidx = paramAlloc(h_allocator_, nlinelim); } PetscInt j = 0; @@ -391,6 +445,9 @@ int LINEParamsRajaHiop::allocate(OPFLOW opflow) { gbineqidx[j] = opflow->nconeq + line->startineqloc; gineqidx[j] = line->startineqloc; linelimidx[j] = linei; + if (opflow->allow_lineflow_violation) { + xslackidx[j] = opflow->idxn2sd_map[line->startxslackloc]; + } j++; } @@ -420,6 +477,8 @@ int LINEParamsRajaHiop::allocate(OPFLOW opflow) { gineqidx_dev_ = paramAlloc(d_allocator_, nlinelim); gbineqidx_dev_ = paramAlloc(d_allocator_, nlinelim); linelimidx_dev_ = paramAlloc(d_allocator_, nlinelim); + ineqjacsp_idx_dev_ = paramAlloc(d_allocator_, nlinelim); + xslackidx_dev_ = paramAlloc(d_allocator_, nlinelim); } #endif return 0; @@ -558,7 +617,10 @@ int GENParamsRajaHiop::destroy(OPFLOW opflow) { h_allocator_.deallocate(qt); h_allocator_.deallocate(qb); h_allocator_.deallocate(isrenewable); + h_allocator_.deallocate(apf); + h_allocator_.deallocate(vs); h_allocator_.deallocate(xidx); + h_allocator_.deallocate(xpdevidx); h_allocator_.deallocate(gidxbus); h_allocator_.deallocate(eqjacspbus_idx); h_allocator_.deallocate(eqjacsqbus_idx); @@ -581,7 +643,10 @@ int GENParamsRajaHiop::destroy(OPFLOW opflow) { d_allocator_.deallocate(qt_dev_); d_allocator_.deallocate(qb_dev_); d_allocator_.deallocate(isrenewable_dev_); + d_allocator_.deallocate(apf_dev_); + d_allocator_.deallocate(vs_dev_); d_allocator_.deallocate(xidx_dev_); + d_allocator_.deallocate(xpdevidx_dev_); d_allocator_.deallocate(gidxbus_dev_); d_allocator_.deallocate(eqjacspbus_idx_dev_); d_allocator_.deallocate(eqjacsqbus_idx_dev_); @@ -615,8 +680,11 @@ int GENParamsRajaHiop::copy(OPFLOW opflow) { resmgr.copy(qt_dev_, qt); resmgr.copy(qb_dev_, qb); resmgr.copy(isrenewable_dev_, isrenewable); + resmgr.copy(apf_dev_, apf); + resmgr.copy(vs_dev_, vs); resmgr.copy(xidx_dev_, xidx); + resmgr.copy(xpdevidx_dev_, xpdevidx); resmgr.copy(gidxbus_dev_, gidxbus); resmgr.copy(eqjacspbus_idx_dev_, eqjacspbus_idx); @@ -639,7 +707,10 @@ int GENParamsRajaHiop::copy(OPFLOW opflow) { qt_dev_ = qt; qb_dev_ = qb; isrenewable_dev_ = isrenewable; + apf_dev_ = apf; + vs_dev_ = vs; xidx_dev_ = xidx; + xpdevidx_dev_ = xpdevidx; gidxbus_dev_ = gidxbus; eqjacspbus_idx_dev_ = eqjacspbus_idx; eqjacsqbus_idx_dev_ = eqjacsqbus_idx; @@ -682,8 +753,11 @@ int GENParamsRajaHiop::allocate(OPFLOW opflow) { qt = paramAlloc(h_allocator_, ngenON); qb = paramAlloc(h_allocator_, ngenON); isrenewable = paramAlloc(h_allocator_, ngenON); + apf = paramAlloc(h_allocator_, ngenON); + vs = paramAlloc(h_allocator_, ngenON); xidx = paramAlloc(h_allocator_, ngenON); + xpdevidx = paramAlloc(h_allocator_, ngenON); gidxbus = paramAlloc(h_allocator_, ngenON); eqjacspbus_idx = paramAlloc(h_allocator_, ngenON); @@ -720,11 +794,16 @@ int GENParamsRajaHiop::allocate(OPFLOW opflow) { qt[geni] = gen->qt; qb[geni] = gen->qb; isrenewable[geni] = (int)gen->isrenewable; + apf[geni] = gen->apf; + vs[geni] = gen->vs; if (opflow->has_gensetpoint) { pgs[geni] = gen->pgs; } xidx[geni] = opflow->idxn2sd_map[loc]; + xpdevidx[geni] = (opflow->has_gensetpoint && !gen->isrenewable) + ? opflow->idxn2sd_map[gen->startxpdevloc] + : -1; gidxbus[geni] = gloc; if (opflow->has_gensetpoint) { geqidxgen[geni] = gen->starteqloc; @@ -748,8 +827,11 @@ int GENParamsRajaHiop::allocate(OPFLOW opflow) { qt_dev_ = paramAlloc(d_allocator_, ngenON); qb_dev_ = paramAlloc(d_allocator_, ngenON); isrenewable_dev_ = paramAlloc(d_allocator_, ngenON); + apf_dev_ = paramAlloc(d_allocator_, ngenON); + vs_dev_ = paramAlloc(d_allocator_, ngenON); xidx_dev_ = paramAlloc(d_allocator_, ngenON); + xpdevidx_dev_ = paramAlloc(d_allocator_, ngenON); gidxbus_dev_ = paramAlloc(d_allocator_, ngenON); eqjacspbus_idx_dev_ = paramAlloc(d_allocator_, ngenON); diff --git a/src/opflow/model/power_bal_hiop/paramsrajahiop.h b/src/opflow/model/power_bal_hiop/paramsrajahiop.h index 91f1fb9f..d274f990 100644 --- a/src/opflow/model/power_bal_hiop/paramsrajahiop.h +++ b/src/opflow/model/power_bal_hiop/paramsrajahiop.h @@ -28,7 +28,12 @@ struct BUSParamsRajaHiop { vector */ int *jacsp_idx; /* Location number in the sparse Jacobian for Pimb */ int *jacsq_idx; /* Location number in the sparse Jacobian for Qimb */ - int *hesssp_idx; /* Location number in the Hessian */ + int *hesssp_idx; /* KS: Hessian indices */ + int *ispv; /* KS: ispv[i] = 1 if bus is PV bus */ + int *gineqidx; /* KS: starting position of bus ineq constraints */ + int *ineqjacsp_idx; /* KS: index in flat sparse ineq Jacobian array */ + int *genoffset; /* KS: Offset into flattened gen array for this bus */ + int *ngenONbus; /* KS: Number of ON generators on this bus */ // Device data int *isref_dev_; /* isref[i] = 1 if bus is reference bus */ @@ -46,9 +51,14 @@ struct BUSParamsRajaHiop { X vector */ int *gidx_dev_; /* starting locations for bus balance equations in constraint vector */ - int *jacsp_idx_dev_; /* Location number in the sparse Jacobian for Pimb */ - int *jacsq_idx_dev_; /* Location number in the sparse Jacobian for Qimb */ - int *hesssp_idx_dev_; /* Location number in the Hessian */ + int *jacsp_idx_dev_; /* Location number in the sparse Jacobian for Pimb */ + int *jacsq_idx_dev_; /* Location number in the sparse Jacobian for Qimb */ + int *hesssp_idx_dev_; /* Location number in the Hessian */ + int *ispv_dev_; /* KS: dev counterpart of ispv */ + int *gineqidx_dev_; /* KS: dev counterpart of gineqidx */ + int *ineqjacsp_idx_dev_; /* KS: device counterpart of ineqjacsp_idx_ */ + int *genoffset_dev_; /* KS: dev counterpart of genoffset */ + int *ngenONbus_dev_; /* KS: dev counterpart of ngenONbus */ int allocate(OPFLOW); int destroy(OPFLOW); @@ -72,9 +82,12 @@ struct GENParamsRajaHiop { double *qt; /* min. reactive power gen. limits */ double *qb; /* max. reactive power gen. limits */ double *pgs; /* real power output setpoint */ + double *apf; /* generator AGC participation factor */ + double *vs; /* voltage setpoint */ int *isrenewable; /* Is renewable generator? */ - int *xidx; /* starting locations in X vector */ + int *xidx; /* starting locations in X vector */ + int *xpdevidx; /* KS: tarting locations of deviation variables in X vector */ int * gidxbus; /* starting locations in constraint vector for bus constraints */ int *geqidxgen; /* starting locations in equality constraint vector for gen @@ -104,9 +117,12 @@ struct GENParamsRajaHiop { double *qt_dev_; /* min. reactive power gen. limits */ double *qb_dev_; /* max. reactive power gen. limits */ double *pgs_dev_; /* real power output setpoint */ + double *apf_dev_; /* KS: device counterpart of apf */ + double *vs_dev_; /* KS: device counterpart of vs */ int *isrenewable_dev_; /* Is renewable generator? */ int *xidx_dev_; /* starting locations in X vector */ + int *xpdevidx_dev_; /* KS: device coutnerpart of xpdevidx*/ int *gidxbus_dev_; /* starting locations in constraint vector for bus constraints */ int *geqidxgen_dev_; /* starting locations in equality constraint vector for @@ -143,7 +159,7 @@ struct LOADParamsRajaHiop { double *pl; /* active power demand */ double *ql; /* reactive power demand */ double *loadloss_penalty; /* Penalty for load loss */ - int *xidx; /* starting location in X vector */ + int *xidx; /* KS: starting location in X vector */ int *gidx; /* starting location in constraint vector */ /* The following members are only used with HIOP */ @@ -192,9 +208,11 @@ struct LINEParamsRajaHiop { contribution in constraints vector */ int *gineqidx; /* Starting location to insert contribution to inequality constraint */ - int *gbineqidx; /* Starting location to insert contribution to inequality - constraint bound */ - int *linelimidx; /* Indices for subset of lines that have finite limits */ + int *gbineqidx; /* Starting location to insert contribution to inequality + constraint bound */ + int *linelimidx; /* Indices for subset of lines that have finite limits */ + int *ineqjacsp_idx; /* KS: Position in flat sparse ineq Jacobian array */ + int *xslackidx; /* Starting location of slack variables in X vector */ // Device data double *Gff_dev_; /* From side self conductance */ @@ -218,6 +236,8 @@ struct LINEParamsRajaHiop { constraint bound */ int * linelimidx_dev_; /* Indices for subset of lines that have finite limits */ + int *ineqjacsp_idx_dev_; /* KS: Position in flat sparse ineq Jacobian array */ + int *xslackidx_dev_; /* Starting location of slack variables in X vector */ int allocate(OPFLOW); int destroy(OPFLOW); @@ -248,6 +268,9 @@ struct PbpolModelRajaHiop : public _p_FormPBPOLRAJAHIOP { LINEParamsRajaHiop lineparams; BUSParamsRajaHiop busparams; + int agc_xidx; /* KS: X-vector index for the AGC delta-P variable + (ps->startxloc) */ + // Arrays to store Jacobian and Hessian indices and entries on CPU (used with // GPU sparse model) int *i_jaceq, diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp index b574e4bb..cac87986 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse.cpp @@ -254,151 +254,88 @@ PetscErrorCode OPFLOWModelSetUp_PBPOLRAJAHIOPSPARSE(OPFLOW opflow) { LOADParamsRajaHiop *loadparams = &pbpolrajahiopsparse->loadparams; LINEParamsRajaHiop *lineparams = &pbpolrajahiopsparse->lineparams; - /* Need to compute the number of nonzeros in equality, inequality constraint - * Jacobians and Hessian */ - int nnz_eqjac = 0, nnz_ineqjac = 0, nnz_hess = 0; - - // Find nonzero entries in equality constraint Jacobian by row. Using - // OPFLOWComputeEqualityConstraintJacobian_PBPOL() as a guide. - - PS ps = (PS)opflow->ps; - - for (int ibus = 0; ibus < ps->nbus; ++ibus) { - - PSBUS bus = &(ps->bus[ibus]); - - // Nonzero entries used by each *bus* starts here - - // no matter what, each bus uses 2 rows and 2 columns - // row 1 = real, row2 = reactive - nnz_eqjac += 2; - nnz_eqjac += 2; + PS ps = opflow->ps; + PSBUS bus; + PSGEN gen; + PSLINE line; + PetscInt i, k; - if (bus->ide == ISOLATED_BUS) { - continue; - } + /* KS: Store the AGC variable index (scalar) */ + if (opflow->use_agc) { + pbpolrajahiopsparse->agc_xidx = opflow->idxn2sd_map[ps->startxloc]; + } else { + pbpolrajahiopsparse->agc_xidx = -1; + } - if (opflow->include_powerimbalance_variables) { - // 2 more entries on both real and reactive - nnz_eqjac += 4; - } + /* KS: Compute the number of nonzeros in equality, inequality constraint + * Jacobians and Hessian. Equality and Hessian counts are still obtained + * from PETSc via get_sparse_blocks_info; inequality count is computed + * axplicitly so we can skip PETSc */ + int nnz_eqjacsp = 0, nnz_ineqjacsp = 0, nnz_hesssp = 0; - if (opflow->has_gensetpoint) { - for (int bgen = 0; bgen < bus->ngen; ++bgen) { - PSGEN gen; - ierr = PSBUSGetGen(bus, bgen, &gen); - CHKERRQ(ierr); - - if (!gen->status || gen->isrenewable) - continue; + /* + * KS: Count inequality Jacobian non-zeros. The traversal order must match + * the startineqloc assignment in OPFLOWModelSetUp_PBPOL: for each bus + * (bus ineq, then gen ineq), then for each line. + */ + int geni = 0, gi; + for (i = 0; i < ps->nbus; i++) { + bus = &ps->bus[i]; - // each generator uses 2 rows, 3 columns real, 1 column reactive - nnz_eqjac += 4; + /* Bus voltage-Q-bounds constraints (FIXED_WITHIN_QBOUNDS) */ + if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { + if (bus->ide == PV_BUS || bus->ide == REF_BUS) { + busparams->ineqjacsp_idx[i] = nnz_ineqjacsp; + /* 2 rows, each with ngenON + 1 entries (one per gen Qg + one for V) */ + nnz_ineqjacsp += 2 * (bus->ngenON + 1); } } - } - - // Go through the lines - for (int iline = 0; iline <= ps->nline; ++iline) { - PSLINE line = &(ps->line[iline]); - - if (!line->status) - continue; - - // each line adds 4 (off-diagonal) entries for the "to" bus and 4 - // entries for the "from" bus. Each line also modifies 4 existing - // "to" and "from" bus entries. - nnz_eqjac += 4; - nnz_eqjac += 4; - } - // if there are lines, non-zeros were over counted - if (ps->nline > 0) { - nnz_eqjac -= 8; - } - - if (opflow->has_gensetpoint) { - for (int ibus = 0; ibus < ps->nbus; ++ibus) { - PSBUS bus = &(ps->bus[ibus]); - for (int bgen = 0; bgen < bus->ngen; ++bgen) { - PSGEN gen; - ierr = PSBUSGetGen(bus, bgen, &gen); + /* KS: Generator set-point constraints */ + gi = 0; + if (opflow->has_gensetpoint) { + for (k = 0; k < bus->ngen; k++) { + ierr = PSBUSGetGen(bus, k, &gen); CHKERRQ(ierr); - if (!gen->status) continue; - - nnz_ineqjac += 6; - } - } - } - - if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { - for (int ibus = 0; ibus < ps->nbus; ++ibus) { - PSBUS bus = &(ps->bus[ibus]); - if (bus->ide == PV_BUS || bus->ide == REF_BUS) { - nnz_ineqjac += 2; + if (!gen->isrenewable) { + genparams->ineqjacspgen_idx[geni + gi] = nnz_ineqjacsp; + if (opflow->use_agc) { + nnz_ineqjacsp += 6; /* 2 rows x 3 entries (Pg, delPg, delP) */ + } + } + gi++; } } - } - - for (int iline = 0; iline < opflow->nlinesmon; ++iline) { - nnz_ineqjac += 8; - } - - for (int ibus = 0; ibus < ps->nbus; ++ibus) { - // reserve 2 real and 2 reactive entries for each bus - // 3 upper triangular - nnz_hess += 3; - - if (opflow->include_powerimbalance_variables) { - nnz_hess += 2; - } - } - - for (int i = 0; i < ps->ngen; ++i) { - PSGEN gen = &(ps->gen[i]); - - if (!gen->status) - continue; - - nnz_hess += 2; - - if (opflow->has_gensetpoint) { - if (gen->isrenewable) - continue; - // later ... - // if (opflow->use_agc) { - // nnz_hess += 5; - // } - } - if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { - nnz_hess += 2; - } + geni += bus->ngenON; } - for (int iline = 0; iline < ps->nline; ++iline) { - PSLINE line = &(ps->line[iline]); - + /* Line flow constraints */ + int linej = 0; + for (i = 0; i < ps->nline; i++) { + line = &ps->line[i]; if (!line->status) continue; + if (line->isdcline) + continue; - // 3 diagonal entries for on the from-bus rows (already defined) - // 3 diagonal entries for on the to-bus rows (already defined) - // 4 off-diagonal entries in upper part - nnz_hess += 4; - } - - if (opflow->include_loadloss_variables) { - for (int iload = 0; iload < ps->nload; ++iload) { - nnz_hess += 2; + if (linej < opflow->nlinesmon && opflow->linesmon[linej] == i) { + lineparams->ineqjacsp_idx[linej] = nnz_ineqjacsp; + /* 2 rows x 4 entries (thetaf, Vmf, thetat, Vmt) */ + int entries_per_line = 8; + if (opflow->allow_lineflow_violation) { + entries_per_line += 2; /* 1 slack entry per row */ + } + nnz_ineqjacsp += entries_per_line; + linej++; } } - opflow->nnz_eqjacsp = nnz_eqjac; - opflow->nnz_ineqjacsp = nnz_ineqjac; - opflow->nnz_hesssp = nnz_hess; + opflow->nnz_eqjacsp = nnz_eqjacsp; + opflow->nnz_ineqjacsp = nnz_ineqjacsp; + opflow->nnz_hesssp = nnz_hesssp; ierr = busparams->copy(opflow); ierr = genparams->copy(opflow); diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp new file mode 100644 index 00000000..05705a35 --- /dev/null +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.cpp @@ -0,0 +1,244 @@ + +#include + +#if defined(EXAGO_ENABLE_RAJA) +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + +#include +#include + +#include "pbpolrajahiopsparse_gpu.hpp" + +void ComputeIneqJacValuesGPU_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, + const double *x_dev, + double *jacd_dev) { + PbpolModelRajaHiop *pbpolrajahiopsparse = + reinterpret_cast(opflow->model); + GENParamsRajaHiop *genparams = &pbpolrajahiopsparse->genparams; + BUSParamsRajaHiop *busparams = &pbpolrajahiopsparse->busparams; + + /* + * Generator set-point inequality Jacobian (has_gensetpoint && use_agc). + * + * PETSc reference (pbpol.cpp:1191-1232): + * Row gloc: [apf*delP - delPg, -(Pg - pt), apf*(Pg - pt)] + * Row gloc+1: [apf*delP - delPg, (pb - Pg), -apf*(pb - Pg)] + * + * Flat array layout per generator (6 entries): + * [0..2] = row 0 values (Pg, delPg, delP columns) + * [3..5] = row 1 values (Pg, delPg, delP columns) + */ + if (opflow->has_gensetpoint && opflow->use_agc) { + int *g_ineqjacsp_idx = genparams->ineqjacspgen_idx_dev_; + int *g_xidx = genparams->xidx_dev_; + int *g_xpdevidx = genparams->xpdevidx_dev_; + int *g_isrenewable = genparams->isrenewable_dev_; + double *g_apf = genparams->apf_dev_; + double *g_pt = genparams->pt_dev_; + double *g_pb = genparams->pb_dev_; + int agc_xidx = pbpolrajahiopsparse->agc_xidx; + + RAJA::forall( + RAJA::RangeSegment(0, genparams->ngenON), + RAJA_LAMBDA(RAJA::Index_type i) { + if (g_isrenewable[i]) + return; + + int base = g_ineqjacsp_idx[i]; + double Pg = x_dev[g_xidx[i]]; + double delPg = x_dev[g_xpdevidx[i]]; + double delP = x_dev[agc_xidx]; + double apf = g_apf[i]; + double pt = g_pt[i]; + double pb = g_pb[i]; + + double apf_delP_minus_delPg = apf * delP - delPg; + + /* Row 0: d/d{Pg, delPg, delP} of (apf*delP - delPg)*(Pg - pt) */ + jacd_dev[base + 0] = apf_delP_minus_delPg; + jacd_dev[base + 1] = -(Pg - pt); + jacd_dev[base + 2] = apf * (Pg - pt); + + /* Row 1: d/d{Pg, delPg, delP} of (delPg - apf*delP)*(pb - Pg) */ + jacd_dev[base + 3] = apf_delP_minus_delPg; + jacd_dev[base + 4] = pb - Pg; + jacd_dev[base + 5] = -apf * (pb - Pg); + }); + } + + /* + * FIXED_WITHIN_QBOUNDS voltage constraint Jacobian. + * + * PETSc reference (pbpol.cpp:1235-1278): + * For each PV/REF bus with ngenON generators: + * Row 0 (gloc): [Vset_0-V, Vset_1-V, ..., Qmax-Q] + * Row 1 (gloc+1): [Vset_0-V, Vset_1-V, ..., Qmin-Q] + * + * Flat array layout per bus (2 * (ngenON + 1) entries): + * Row 0: ngenON Qg derivative entries + 1 V derivative entry + * Row 1: ngenON Qg derivative entries + 1 V derivative entry + * + * This kernel parallelizes over buses. The inner loop over generators + * is sequential within each thread (variable-length per bus). + */ + if (opflow->genbusvoltagetype == FIXED_WITHIN_QBOUNDS) { + int *b_ispv = busparams->ispv_dev_; + int *b_isref = busparams->isref_dev_; + int *b_xidx = busparams->xidx_dev_; + int *b_ineqjacsp_idx = busparams->ineqjacsp_idx_dev_; + int *b_genoffset = busparams->genoffset_dev_; + int *b_ngenONbus = busparams->ngenONbus_dev_; + int *g_xidx = genparams->xidx_dev_; + double *g_qt = genparams->qt_dev_; + double *g_qb = genparams->qb_dev_; + double *g_vs = genparams->vs_dev_; + + RAJA::forall( + RAJA::RangeSegment(0, busparams->nbus), + RAJA_LAMBDA(RAJA::Index_type i) { + if (!b_ispv[i] && !b_isref[i]) + return; + + int base = b_ineqjacsp_idx[i]; + int ngen = b_ngenONbus[i]; + int goff = b_genoffset[i]; + double V = x_dev[b_xidx[i] + 1]; + + double Q = 0.0, Qmax = 0.0, Qmin = 0.0; + double Vset = 0.0; + + /* Row 0 and Row 1: Qg derivative entries */ + for (int k = 0; k < ngen; k++) { + int gidx = goff + k; + double Qg = x_dev[g_xidx[gidx] + 1]; + Q += Qg; + Qmax += g_qt[gidx]; + Qmin += g_qb[gidx]; + Vset = g_vs[gidx]; + + double dQg = Vset - V; + /* Row 0 entry for this gen's Qg */ + jacd_dev[base + k] = dQg; + /* Row 1 entry for this gen's Qg */ + jacd_dev[base + ngen + 1 + k] = dQg; + } + + /* Row 0: V derivative entry (last in this row) */ + jacd_dev[base + ngen] = Qmax - Q; + /* Row 1: V derivative entry (last in this row) */ + jacd_dev[base + ngen + 1 + ngen] = Qmin - Q; + }); + } + + /* + * Line flow constraint Jacobian. + * + * Computes dSf2/d{thetaf,Vmf,thetat,Vmt} and dSt2/d{thetaf,Vmf,thetat,Vmt} + * for each monitored line, plus optional slack variable entries (-1.0). + * + * Flat array layout per line (8 entries without slack, 10 with): + * Row 0 (Sf2): [dSf2_dthetaf, dSf2_dVmf, dSf2_dthetat, dSf2_dVmt, + * (-1.0 if slack)] + * Row 1 (St2): [dSt2_dthetaf, dSt2_dVmf, dSt2_dthetat, dSt2_dVmt, + * (-1.0 if slack)] + */ + LINEParamsRajaHiop *lineparams = &pbpolrajahiopsparse->lineparams; + + if (lineparams->nlinelim) { + double *Gff_arr = lineparams->Gff_dev_; + double *Bff_arr = lineparams->Bff_dev_; + double *Gft_arr = lineparams->Gft_dev_; + double *Bft_arr = lineparams->Bft_dev_; + double *Gtf_arr = lineparams->Gtf_dev_; + double *Btf_arr = lineparams->Btf_dev_; + double *Gtt_arr = lineparams->Gtt_dev_; + double *Btt_arr = lineparams->Btt_dev_; + int *linelimidx = lineparams->linelimidx_dev_; + int *xidxf = lineparams->xidxf_dev_; + int *xidxt = lineparams->xidxt_dev_; + int *ineqjacsp_idx = lineparams->ineqjacsp_idx_dev_; + int has_slack = (int)opflow->allow_lineflow_violation; + int row_stride = 4 + has_slack; + + RAJA::forall( + RAJA::RangeSegment(0, lineparams->nlinelim), + RAJA_LAMBDA(RAJA::Index_type i) { + int j = linelimidx[i]; + int base = ineqjacsp_idx[i]; + + double thetaf = x_dev[xidxf[j]]; + double Vmf = x_dev[xidxf[j] + 1]; + double thetat = x_dev[xidxt[j]]; + double Vmt = x_dev[xidxt[j] + 1]; + double thetaft = thetaf - thetat; + double thetatf = thetat - thetaf; + + double Gff = Gff_arr[j], Bff = Bff_arr[j]; + double Gft = Gft_arr[j], Bft = Bft_arr[j]; + double Gtf = Gtf_arr[j], Btf = Btf_arr[j]; + double Gtt = Gtt_arr[j], Btt = Btt_arr[j]; + + double sin_ft = sin(thetaft), cos_ft = cos(thetaft); + double sin_tf = sin(thetatf), cos_tf = cos(thetatf); + + double Pf = + Gff * Vmf * Vmf + Vmf * Vmt * (Gft * cos_ft + Bft * sin_ft); + double Qf = + -Bff * Vmf * Vmf + Vmf * Vmt * (-Bft * cos_ft + Gft * sin_ft); + double Pt = + Gtt * Vmt * Vmt + Vmt * Vmf * (Gtf * cos_tf + Btf * sin_tf); + double Qt = + -Btt * Vmt * Vmt + Vmt * Vmf * (-Btf * cos_tf + Gtf * sin_tf); + + double dSf2_dPf = 2 * Pf, dSf2_dQf = 2 * Qf; + double dSt2_dPt = 2 * Pt, dSt2_dQt = 2 * Qt; + + double dPf_dthetaf = Vmf * Vmt * (-Gft * sin_ft + Bft * cos_ft); + double dPf_dVmf = 2 * Gff * Vmf + Vmt * (Gft * cos_ft + Bft * sin_ft); + double dPf_dthetat = Vmf * Vmt * (Gft * sin_ft - Bft * cos_ft); + double dPf_dVmt = Vmf * (Gft * cos_ft + Bft * sin_ft); + + double dQf_dthetaf = Vmf * Vmt * (Bft * sin_ft + Gft * cos_ft); + double dQf_dVmf = + -2 * Bff * Vmf + Vmt * (-Bft * cos_ft + Gft * sin_ft); + double dQf_dthetat = Vmf * Vmt * (-Bft * sin_ft - Gft * cos_ft); + double dQf_dVmt = Vmf * (-Bft * cos_ft + Gft * sin_ft); + + double dPt_dthetat = Vmt * Vmf * (-Gtf * sin_tf + Btf * cos_tf); + double dPt_dVmt = 2 * Gtt * Vmt + Vmf * (Gtf * cos_tf + Btf * sin_tf); + double dPt_dthetaf = Vmt * Vmf * (Gtf * sin_tf - Btf * cos_tf); + double dPt_dVmf = Vmt * (Gtf * cos_tf + Btf * sin_tf); + + double dQt_dthetat = Vmt * Vmf * (Btf * sin_tf + Gtf * cos_tf); + double dQt_dVmt = + -2 * Btt * Vmt + Vmf * (-Btf * cos_tf + Gtf * sin_tf); + double dQt_dthetaf = Vmt * Vmf * (-Btf * sin_tf - Gtf * cos_tf); + double dQt_dVmf = Vmt * (-Btf * cos_tf + Gtf * sin_tf); + + /* Row 0 (Sf2): derivatives w.r.t. thetaf, Vmf, thetat, Vmt */ + jacd_dev[base + 0] = dSf2_dPf * dPf_dthetaf + dSf2_dQf * dQf_dthetaf; + jacd_dev[base + 1] = dSf2_dPf * dPf_dVmf + dSf2_dQf * dQf_dVmf; + jacd_dev[base + 2] = dSf2_dPf * dPf_dthetat + dSf2_dQf * dQf_dthetat; + jacd_dev[base + 3] = dSf2_dPf * dPf_dVmt + dSf2_dQf * dQf_dVmt; + + /* Row 1 (St2): derivatives w.r.t. thetaf, Vmf, thetat, Vmt */ + jacd_dev[base + row_stride + 0] = + dSt2_dPt * dPt_dthetaf + dSt2_dQt * dQt_dthetaf; + jacd_dev[base + row_stride + 1] = + dSt2_dPt * dPt_dVmf + dSt2_dQt * dQt_dVmf; + jacd_dev[base + row_stride + 2] = + dSt2_dPt * dPt_dthetat + dSt2_dQt * dQt_dthetat; + jacd_dev[base + row_stride + 3] = + dSt2_dPt * dPt_dVmt + dSt2_dQt * dQt_dVmt; + + /* Slack variable entries (Step 5) */ + if (has_slack) { + jacd_dev[base + 4] = -1.0; + jacd_dev[base + row_stride + 4] = -1.0; + } + }); + } +} + +#endif // EXAGO_ENABLE_HIOP_SPARSE +#endif // EXAGO_ENABLE_RAJA diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.hpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.hpp new file mode 100644 index 00000000..938686a7 --- /dev/null +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparse_gpu.hpp @@ -0,0 +1,30 @@ +#include + +#if defined(EXAGO_ENABLE_RAJA) +#if defined(EXAGO_ENABLE_HIOP_SPARSE) + +#pragma once + +#include +#include "pbpolrajahiopsparse.hpp" + +/** + * GPU-only (PETSc-free) computation of inequality constraint Jacobian values. + * + * Replaces the PETSc-based path that calls + * opflow->modelops.computeinequalityconstraintjacobian followed by + * MatGetRow extraction. Writes directly into device memory using RAJA + * kernels, without PETSc Mat/Vec operations; no H2D, D2H copies back and forth. + * + * @param opflow The OPFLOW problem context + * @param x_dev Device array of variable values + * @param jacd_dev Device output array for inequality Jacobian values + * (points to the ineq portion of the sparse Jacobian, + * i.e. MJacS_dev + nnz_eqjacsp) + */ +void ComputeIneqJacValuesGPU_PBPOLRAJAHIOPSPARSE(OPFLOW opflow, + const double *x_dev, + double *jacd_dev); + +#endif // EXAGO_ENABLE_HIOP_SPARSE +#endif // EXAGO_ENABLE_RAJA diff --git a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp index 7a9d9983..efddb6f6 100644 --- a/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp +++ b/src/opflow/model/power_bal_hiop/pbpolrajahiopsparsekernels.cpp @@ -14,6 +14,7 @@ #include #include "pbpolrajahiopsparsekernels.hpp" #include "pbpolrajahiopsparse.hpp" +#include "pbpolrajahiopsparse_gpu.hpp" /** * @brief Set the initial guess array for the PBPOLRAJAHIOPSPARSE model. @@ -647,43 +648,11 @@ OPFLOWComputeSparseInequalityConstraintJacobian_PBPOLRAJAHIOPSPARSE( ierr = PetscLogEventBegin(opflow->ineqconsjaclogger, 0, 0, 0, 0); CHKERRQ(ierr); - ierr = VecGetArray(opflow->X, &x); - CHKERRQ(ierr); - - // Copy from device to host - umpire::Allocator h_allocator_ = resmgr.getAllocator("HOST"); - registerWith(x, opflow->nx, resmgr, h_allocator_); - resmgr.copy((double *)x, (double *)x_dev); - - ierr = VecRestoreArray(opflow->X, &x); - CHKERRQ(ierr); - - // Compute inequality constraint jacobian on the host - // The function pointer computeinequalityconstraintjacobian points to - // OPFLOWComputeInequalityConstraintJacobian_PBPOL - ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( - opflow, opflow->X, opflow->Jac_Gi); - CHKERRQ(ierr); - - ierr = MatGetSize(opflow->Jac_Gi, &nrow, &ncol); - CHKERRQ(ierr); - - values = pbpolrajahiopsparse->val_jacineq; - // Unpack PETSc matrix and copy values to the array `values` in - // PbpolModelRajaHiop struct. - for (i = 0; i < nrow; i++) { - ierr = MatGetRow(opflow->Jac_Gi, i, &nvals, &cols, &vals); - CHKERRQ(ierr); - for (j = 0; j < nvals; j++) { - values[j] = vals[j]; - } - values += nvals; - ierr = MatRestoreRow(opflow->Jac_Gi, i, &nvals, &cols, &vals); - CHKERRQ(ierr); - } - // Copy over val_jacineq to device - resmgr.copy(MJacS_dev + opflow->nnz_eqjacsp, - pbpolrajahiopsparse->val_jacineq); + /* KS: Compute inequality constraint Jacobian directly on device. + No H2D, D2H copies: x_dev is already on device, output goes + straight into the ineq portion of MJacS_dev. */ + ComputeIneqJacValuesGPU_PBPOLRAJAHIOPSPARSE( + opflow, x_dev, MJacS_dev + opflow->nnz_eqjacsp); ierr = PetscLogEventEnd(opflow->ineqconsjaclogger, 0, 0, 0, 0); CHKERRQ(ierr); diff --git a/src/opflow/solver/hiop/opflow_hiopsparsegpu.cpp b/src/opflow/solver/hiop/opflow_hiopsparsegpu.cpp index d7a9539d..d768e738 100644 --- a/src/opflow/solver/hiop/opflow_hiopsparsegpu.cpp +++ b/src/opflow/solver/hiop/opflow_hiopsparsegpu.cpp @@ -69,20 +69,10 @@ bool OPFLOWHIOPSPARSEGPUInterface::get_sparse_blocks_info( nnz_sparse_Jaceq = opflow->nnz_eqjacsp = info_eq.nz_used; - nnz_sparse_Jacineq = 0; - if (opflow->Nconineq) { - ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( - opflow, opflow->X, opflow->Jac_Gi); - CHKERRQ(ierr); - ierr = - MatSetOption(opflow->Jac_Gi, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE); - CHKERRQ(ierr); - - ierr = MatGetInfo(opflow->Jac_Gi, MAT_LOCAL, &info_ineq); - CHKERRQ(ierr); - - nnz_sparse_Jacineq = opflow->nnz_ineqjacsp = info_ineq.nz_used; - } + /* KS: Use pre-computed nnz_ineqjacsp from model setup (avoids PETSc Mat + assembly just for counting non-zeros -- not sure if faster or if it scales + but hey no PETSc!). */ + nnz_sparse_Jacineq = opflow->nnz_ineqjacsp; /* Compute non-zeros for Hessian */ ierr = (*opflow->modelops.computehessian)(opflow, opflow->X, opflow->Lambdae, diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index ace550c4..b052d727 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -13,6 +13,17 @@ add_executable(test_pflow test_pflow.cpp utils/test_acopf_utils.cpp) target_link_libraries(test_pflow ExaGO::PFLOW) target_include_directories(test_pflow PRIVATE ./utils) +if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_HIOP_SPARSE) + if(EXAGO_ENABLE_CUDA) + set_source_files_properties(test_ineqjac_gpu.cpp PROPERTIES LANGUAGE CUDA) + endif() + add_executable(test_ineqjac_gpu test_ineqjac_gpu.cpp) + target_link_libraries(test_ineqjac_gpu ExaGO::OPFLOW) + target_include_directories( + test_ineqjac_gpu PRIVATE ${CMAKE_SOURCE_DIR}/src/opflow + ) +endif() + add_executable(test_error_handler test_error_handler.cpp) target_link_libraries(test_error_handler ExaGO::UTILS) @@ -49,6 +60,22 @@ if(EXAGO_RUN_TESTS) ${network_files} ) + if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_HIOP_SPARSE) + exago_add_test( + NAME + "UNIT_TEST_INEQJAC_GPU" + DEPENDS + HIOP + COMMAND + ${RUNCMD} + $ + -opflow_genbusvoltage + VARIABLE_WITHIN_BOUNDS + NETFILES + ${network_files} + ) + endif() + exago_add_test( NAME UNIT_TESTS_UTILS COMMAND $ ) diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt index 4c9e1630..cd2f33b2 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -71,7 +71,6 @@ if(EXAGO_RUN_TESTS) set(testname "UNIT_TESTS_EQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" ) - message(STATUS "Setting up test: ${testname}") exago_add_test( NAME ${testname} diff --git a/tests/unit/test_ineqjac_gpu.cpp b/tests/unit/test_ineqjac_gpu.cpp new file mode 100644 index 00000000..bc473c70 --- /dev/null +++ b/tests/unit/test_ineqjac_gpu.cpp @@ -0,0 +1,406 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(EXAGO_ENABLE_RAJA) +#include +#include +#include +#include +#endif + +#include "model/power_bal_hiop/paramsrajahiop.h" +#include "model/power_bal_hiop/pbpolrajahiopsparse_gpu.hpp" + +static const double TOL = 1e-8; + +static int compare_arrays(const double *ref, const double *gpu, int n, + const char *label) { + int fail = 0; + for (int i = 0; i < n; i++) { + if (std::abs(ref[i] - gpu[i]) / (1.0 + std::abs(ref[i])) > TOL) { + std::cout << " MISMATCH " << label << "[" << i << "]: PETSc=" << ref[i] + << " GPU=" << gpu[i] << " diff=" << std::abs(ref[i] - gpu[i]) + << std::endl; + fail++; + } + } + return fail; +} + +/** + * @brief Validate GPU inequality constraint Jacobian values against PETSc. + * + * First solves with IPOPT/PBPOL to obtain a realistic solution, then + * sets up the PBPOLRAJAHIOPSPARSE model and evaluates the inequality + * Jacobian at the converged solution using both the PETSc reference + * path and the GPU RAJA kernel. Compares element-by-element. + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + char file_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + char help[] = "Test 8: GPU ineq Jacobian validation\n"; + int fail = 0; + + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO.\n"); + return ierr; + } + + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + if (!flg) + file = "../datafiles/case9/case9mod.m"; + else + file.assign(file_c_str); + + std::cout << "=== Test 8: GPU Inequality Jacobian Validation ===" + << std::endl; + std::cout << "Network file: " << file << std::endl; + + /* ------------------------------------------------------------------ + * Step 1: Solve with IPOPT/PBPOL to get a realistic solution + * ------------------------------------------------------------------ */ + OPFLOW opflow_ref; + Vec Xsol; + + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflow_ref); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflow_ref, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetModel(opflow_ref, OPFLOWMODEL_PBPOL); + CHKERRQ(ierr); + ierr = OPFLOWSetSolver(opflow_ref, OPFLOWSOLVER_IPOPT); + CHKERRQ(ierr); + ierr = OPFLOWSolve(opflow_ref); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflow_ref, &Xsol); + CHKERRQ(ierr); + + std::cout << "IPOPT solve complete." << std::endl; + + /* Get the solution array (natural ordering) */ + PetscInt nx_ref; + ierr = VecGetSize(Xsol, &nx_ref); + CHKERRQ(ierr); + double *xsol_nat; + ierr = VecGetArray(Xsol, &xsol_nat); + CHKERRQ(ierr); + + /* ------------------------------------------------------------------ + * Step 2: Create the PBPOLRAJAHIOPSPARSE model and set up + * ------------------------------------------------------------------ */ + OPFLOW opflow; + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflow); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflow, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetModel(opflow, OPFLOWMODEL_PBPOLRAJAHIOPSPARSE); + CHKERRQ(ierr); + ierr = OPFLOWSetSolver(opflow, OPFLOWSOLVER_HIOPSPARSEGPU); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflow); + CHKERRQ(ierr); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflow, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + std::cout << "nx=" << nx << " nconeq=" << nconeq << " nconineq=" << nconineq + << " nnz_ineqjacsp=" << opflow->nnz_ineqjacsp << std::endl; + + if (!nconineq) { + std::cout << "No inequality constraints -- nothing to test. PASS." + << std::endl; + ierr = VecRestoreArray(Xsol, &xsol_nat); + CHKERRQ(ierr); + ierr = OPFLOWDestroy(&opflow_ref); + CHKERRQ(ierr); + ierr = OPFLOWDestroy(&opflow); + CHKERRQ(ierr); + ExaGOFinalize(); + return 0; + } + + /* ------------------------------------------------------------------ + * Step 3: Copy IPOPT solution into opflow->X (natural ordering) + * ------------------------------------------------------------------ */ + double *x_nat; + ierr = VecGetArray(opflow->X, &x_nat); + CHKERRQ(ierr); + for (int i = 0; i < nx; i++) + x_nat[i] = xsol_nat[i]; + ierr = VecRestoreArray(opflow->X, &x_nat); + CHKERRQ(ierr); + + ierr = VecRestoreArray(Xsol, &xsol_nat); + CHKERRQ(ierr); + + std::cout << "Evaluating Jacobian at IPOPT-converged solution." << std::endl; + + /* ------------------------------------------------------------------ + * Step 4: Compute reference inequality Jacobian via PETSc. + * The first call establishes the sparsity pattern, the second + * computes the actual values at the converged solution. + * ------------------------------------------------------------------ */ + ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( + opflow, opflow->X, opflow->Jac_Gi); + CHKERRQ(ierr); + ierr = MatSetOption(opflow->Jac_Gi, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE); + CHKERRQ(ierr); + ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( + opflow, opflow->X, opflow->Jac_Gi); + CHKERRQ(ierr); + + int nnz = opflow->nnz_ineqjacsp; + + auto &resmgr = umpire::ResourceManager::getInstance(); + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + double *ref_vals = + static_cast(h_allocator.allocate(nnz * sizeof(double))); + + PetscInt nrow, ncol; + ierr = MatGetSize(opflow->Jac_Gi, &nrow, &ncol); + CHKERRQ(ierr); + + double *vptr = ref_vals; + for (int i = 0; i < nrow; i++) { + PetscInt nvals; + const PetscInt *cols; + const PetscScalar *vals; + ierr = MatGetRow(opflow->Jac_Gi, i, &nvals, &cols, &vals); + CHKERRQ(ierr); + for (int j = 0; j < nvals; j++) + vptr[j] = vals[j]; + vptr += nvals; + ierr = MatRestoreRow(opflow->Jac_Gi, i, &nvals, &cols, &vals); + CHKERRQ(ierr); + } + + int ref_count = (int)(vptr - ref_vals); + std::cout << "PETSc extracted " << ref_count << " ineq Jacobian values" + << " (expected " << nnz << ")" << std::endl; + + if (ref_count != nnz) { + std::cout << "FAIL: NNZ mismatch! PETSc=" << ref_count + << " analytical=" << nnz << std::endl; + fail++; + } + + /* ------------------------------------------------------------------ + * Step 5: Compute GPU inequality Jacobian at the same solution + * ------------------------------------------------------------------ */ + double *x_host; + ierr = VecGetArray(opflow->X, &x_host); + CHKERRQ(ierr); + + double *x_sd = + static_cast(h_allocator.allocate(nx * sizeof(double))); + for (int i = 0; i < nx; i++) + x_sd[opflow->idxn2sd_map[i]] = x_host[i]; + + ierr = VecRestoreArray(opflow->X, &x_host); + CHKERRQ(ierr); + + double *gpu_vals; + double *x_dev, *gpu_vals_dev; + +#ifdef EXAGO_ENABLE_GPU + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_dev = static_cast(d_allocator.allocate(nx * sizeof(double))); + gpu_vals_dev = + static_cast(d_allocator.allocate(nnz * sizeof(double))); + resmgr.memset(gpu_vals_dev, 0, nnz * sizeof(double)); +#else + x_dev = x_sd; + gpu_vals_dev = + static_cast(h_allocator.allocate(nnz * sizeof(double))); + memset(gpu_vals_dev, 0, nnz * sizeof(double)); +#endif + + umpire::util::AllocationRecord rec_x{x_sd, sizeof(double) * nx, + h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_sd, rec_x); +#ifdef EXAGO_ENABLE_GPU + resmgr.copy(x_dev, x_sd); +#endif + + std::cout << "Running RAJA GPU inequality Jacobian kernel..." << std::endl; + ComputeIneqJacValuesGPU_PBPOLRAJAHIOPSPARSE(opflow, x_dev, gpu_vals_dev); + + gpu_vals = static_cast(h_allocator.allocate(nnz * sizeof(double))); +#ifdef EXAGO_ENABLE_GPU + resmgr.copy(gpu_vals, gpu_vals_dev); +#else + memcpy(gpu_vals, gpu_vals_dev, nnz * sizeof(double)); +#endif + + /* ------------------------------------------------------------------ + * Step 6: Compare + * ------------------------------------------------------------------ */ + std::cout << "Comparing " << nnz << " inequality Jacobian values..." + << std::endl; + int cmp_fail = compare_arrays(ref_vals, gpu_vals, nnz, "ineqjac"); + fail += cmp_fail; + + if (cmp_fail == 0) + std::cout << "PASS: All " << nnz + << " inequality Jacobian values match within tol=" << TOL + << std::endl; + else + std::cout << "FAIL: " << cmp_fail << " of " << nnz << " values differ" + << std::endl; + + /* ------------------------------------------------------------------ + * Step 7: Performance comparison (enabled with -benchmark flag) + * ------------------------------------------------------------------ */ + PetscBool run_benchmark = PETSC_FALSE; + ierr = PetscOptionsGetBool(NULL, NULL, "-benchmark", NULL, &run_benchmark); + CHKERRQ(ierr); + + if (run_benchmark) { + int niters = 1000; + PetscInt bench_nrow, bench_ncol; + ierr = MatGetSize(opflow->Jac_Gi, &bench_nrow, &bench_ncol); + CHKERRQ(ierr); + + double *bench_vals = + static_cast(h_allocator.allocate(nnz * sizeof(double))); + + std::cout << "\n=== Performance Benchmark (" << niters + << " iterations) ===" << std::endl; + + /* --- PETSc path: compute + MatGetRow extraction + copy to device --- */ + { + double *bench_dev; + size_t nnz_bytes = nnz * sizeof(double); +#ifdef EXAGO_ENABLE_GPU + bench_dev = static_cast(d_allocator.allocate(nnz_bytes)); +#else + bench_dev = static_cast(h_allocator.allocate(nnz_bytes)); +#endif + + auto t0 = std::chrono::high_resolution_clock::now(); + for (int iter = 0; iter < niters; iter++) { + ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( + opflow, opflow->X, opflow->Jac_Gi); + + double *vp = bench_vals; + for (int i = 0; i < bench_nrow; i++) { + PetscInt nv; + const PetscInt *c; + const PetscScalar *v; + MatGetRow(opflow->Jac_Gi, i, &nv, &c, &v); + for (int j = 0; j < nv; j++) + vp[j] = v[j]; + vp += nv; + MatRestoreRow(opflow->Jac_Gi, i, &nv, &c, &v); + } +#ifdef EXAGO_ENABLE_GPU + resmgr.copy(bench_dev, bench_vals); +#else + memcpy(bench_dev, bench_vals, nnz_bytes); +#endif + } + auto t1 = std::chrono::high_resolution_clock::now(); + double petsc_us = + std::chrono::duration(t1 - t0).count() / niters; + std::cout << " PETSc path (compute + MatGetRow + copy): " << petsc_us + << " us/iter" << std::endl; + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(bench_dev); +#else + h_allocator.deallocate(bench_dev); +#endif + } + + /* --- PETSc path: CPU compute only --- */ + { + auto t0 = std::chrono::high_resolution_clock::now(); + + for (int iter = 0; iter < niters; iter++) { + ierr = (*opflow->modelops.computeinequalityconstraintjacobian)( + opflow, opflow->X, opflow->Jac_Gi); + } + + auto t1 = std::chrono::high_resolution_clock::now(); + + double petsc_us = + std::chrono::duration(t1 - t0).count() / niters; + std::cout << " PETSc path (compute only): " << petsc_us + << " us/iter" << std::endl; + } + + /* --- GPU path: RAJA kernels, no copies --- */ + { + double *bench_dev; +#ifdef EXAGO_ENABLE_GPU + bench_dev = + static_cast(d_allocator.allocate(nnz * sizeof(double))); +#else + bench_dev = + static_cast(h_allocator.allocate(nnz * sizeof(double))); +#endif + +#ifdef EXAGO_ENABLE_HIP + (void)hipDeviceSynchronize(); +#endif + auto t0 = std::chrono::high_resolution_clock::now(); + for (int iter = 0; iter < niters; iter++) { + ComputeIneqJacValuesGPU_PBPOLRAJAHIOPSPARSE(opflow, x_dev, bench_dev); + } +#ifdef EXAGO_ENABLE_HIP + (void)hipDeviceSynchronize(); +#endif + auto t1 = std::chrono::high_resolution_clock::now(); + double gpu_us = + std::chrono::duration(t1 - t0).count() / niters; + std::cout << " GPU path (RAJA kernels, no copies): " << gpu_us + << " us/iter" << std::endl; + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(bench_dev); +#else + h_allocator.deallocate(bench_dev); +#endif + } + + h_allocator.deallocate(bench_vals); + std::cout << "=== End Benchmark ===" << std::endl; + } + + /* ------------------------------------------------------------------ + * Cleanup + * ------------------------------------------------------------------ */ + h_allocator.deallocate(ref_vals); + h_allocator.deallocate(gpu_vals); + h_allocator.deallocate(x_sd); +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_dev); + d_allocator.deallocate(gpu_vals_dev); +#else + h_allocator.deallocate(gpu_vals_dev); +#endif + + ierr = OPFLOWDestroy(&opflow); + CHKERRQ(ierr); + ierr = OPFLOWDestroy(&opflow_ref); + CHKERRQ(ierr); + ExaGOFinalize(); + + return fail; +} From 7d757d8ceb76fbe8377e9fd33504a3433603b636 Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Thu, 16 Apr 2026 16:10:57 -0400 Subject: [PATCH 08/14] Fill in equality constraint Jacobian test --- .../equality/CMakeLists.txt | 25 +- .../equality/gen_network.py | 133 ++++++++++ .../equality/jac_eq_acopf.cpp | 236 ++++++++++-------- 3 files changed, 280 insertions(+), 114 deletions(-) create mode 100644 tests/unit/opflow/constraint_jacobian/equality/gen_network.py diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt index cd2f33b2..18928c99 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -1,3 +1,8 @@ +find_package(Python) +if(NOT Python_FOUND) + return() +endif() + if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) set_source_files_properties(jac_eq_acopf.cpp PROPERTIES LANGUAGE CUDA) endif() @@ -16,9 +21,16 @@ target_include_directories( # Network files to run on - doing 3 and 600 bus examples. set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) -set(obj_network_files testx3.m testx600.m) +set(obj_network_files testx1.m testx3.m testx600.m) # Map num_copies to a specific netfile -set(num_copies 3 600) +set(num_copies 1 3 600) + +foreach(n IN LISTS num_copies) + execute_process( + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_network.py ${n} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) +endforeach() list(TRANSFORM obj_network_files PREPEND ${prefix}) @@ -66,10 +78,9 @@ if(EXAGO_RUN_TESTS) dependencies ) # Iterate over networks, matching network file to num_copies - foreach(network num IN ZIP_LISTS obj_network_files num_copies) - get_filename_component(net ${network} NAME) + foreach(num IN LISTS num_copies) set(testname - "UNIT_TESTS_EQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + "UNIT_TESTS_EQUALITY_CONSTRAINT_JACOBIAN_${num}_${solver}_${model}" ) exago_add_test( NAME @@ -83,12 +94,8 @@ if(EXAGO_RUN_TESTS) ${model} -opflow_solver ${solver} - -netfile - ${network} -num_copies ${num} - -validation - ${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv ) set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) endforeach() diff --git a/tests/unit/opflow/constraint_jacobian/equality/gen_network.py b/tests/unit/opflow/constraint_jacobian/equality/gen_network.py new file mode 100644 index 00000000..254306f9 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/gen_network.py @@ -0,0 +1,133 @@ +#!/usr/bin/python + +import sys + + +def header(bus_size): + output = [] + output.append("function mpc = CECJ_unittestx" + bus_size + "\n") + output.append("mpc.version = '2';\n") + output.append("mpc.baseMVA = 100.00;\n") + output.append("\n") + return output + + +def bus(bus_size): + output = [] + output.append("%% bus data\n") + output.append("mpc.bus = [\n") + output.append( "1 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "2 1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "3 3 0.00 0.00 0.00 0.00 1 2.0000000 30.000000 13.80 1 1.100 0.900\n") + output.append( "4 1 -3.40 8.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "5 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + for i in range(1, int(bus_size)): + bus_idx = (i + 1) * 4 + output.append(f"{bus_idx - 2} " + + "1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append(f"{bus_idx - 1} " + + "2 0.00 0.00 0.00 0.00 1 2.0000000 30.000000 13.80 1 1.100 0.900\n") + output.append(f"{bus_idx} " + + "1 -3.40 8.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append(f"{bus_idx + 1} " + + "1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append("];\n") + output.append("\n") + return output + + +def generator(bus_size): + output = [] + output.append("%% generator data\n") + output.append("mpc.gen = [\n") + for i in range(3, int(bus_size) * 4, 4): + output.append( + f"{i} 1.60 -2.20 9900.00 -9900.00 2.0000 100.00 1 1.60 1.60 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 10.0000\n") + output.append("];\n") + output.append("\n") + return output + + +def gen_cost(bus_size): + output = [] + output.append("%% generator cost data\n") + output.append("mpc.gencost = [\n") + for _ in range(int(bus_size)): + output.append("2 0 0 3 0.010 0.100 8.00 0.0000 \n") + output.append("];\n") + output.append("\n") + return output + + +def branch(bus_size): + output = [] + output.append("%% branch data\n") + output.append("mpc.branch = [\n") + for i in range(int(bus_size)): + bus_idx = (4 * i + 1) + output.append(f"{bus_idx} {bus_idx + 1} " + + "2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00\n") + output.append(f"{bus_idx + 1} {bus_idx + 2} " + + "2.000000 1.000000 1.20000 0.00 0.00 0.00 2.00000 60.000 1 0.00 0.00 0.00 0.00 0.00 0.00\n") + output.append(f"{bus_idx + 1} {bus_idx + 3} " + + "2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00\n") + output.append(f"{bus_idx + 3} {bus_idx + 4} " + + "2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 0.00 0.00 0.00\n") + output.append("];\n") + output.append("\n") + return output + + +def bus_names(bus_size): + output = [] + output.append("%% bus names\n") + output.append("mpc.bus_name = {\n") + for i in range(int(bus_size) * 4 + 1): + output.append(f"'{i + 1}';\n") + output.append("};\n") + output.append("\n") + return output + + +def gen_types(bus_size): + output = [] + output.append("%% Generator Unit Types\n") + output.append("mpc.gentype = {\n") + for i in range(int(bus_size)): + output.append("'UN';\n") + output.append("};\n") + output.append("\n") + return output + + +def gen_fuel(bus_size): + output = [] + output.append("%% Generator Fuel Types\n") + output.append("mpc.genfuel = {\n") + for i in range(int(bus_size)): + output.append("'unknown';\n") + output.append("};\n") + return output + + +if __name__ == '__main__': + network_length = 0 + + # Script can be called with CLI argument + if (len(sys.argv) < 2): + network_length = input('Enter a network size: ') + else: + network_length = sys.argv[1] + + print(f'Generating a network of size {network_length}') + + output_filename = 'CECJ_unittestx' + network_length + '.m' + + f = open(output_filename, "w+") + + # Loop over file component functions and append to file + for section in [header, bus, generator, gen_cost, branch, bus_names, gen_types, gen_fuel]: + for line in section(network_length): + f.write(line) + + f.close() diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index 2b09eea4..c2cf3c0b 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -1,14 +1,19 @@ #include #include +#include #include #include #include #include +#include -#include "opflow_tests.h" +// #include "opflow_tests.h" #include "test_acopf_utils.h" +PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies); +PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies); + /** * @brief Unit test driver for objective function * @see opflow/OpflowTests.hpp for kernel tested by this driver @@ -27,16 +32,9 @@ int main(int argc, char **argv) { PetscErrorCode ierr; PetscBool flg; - Vec X; - int fail = 0; - double obj_value; - char file_c_str[PETSC_MAX_PATH_LEN]; - char validation_c_str[PETSC_MAX_PATH_LEN]; - std::string file; - char appname[] = "opflow"; MPI_Comm comm = MPI_COMM_WORLD; - int num_copies = 0; + char appname[] = "opflow"; char help[] = "Unit tests for equality constraint Jacobians running opflow\n"; /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ @@ -46,44 +44,28 @@ int main(int argc, char **argv) { return ierr; } - /* Get network data file from command line */ - ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, - PETSC_MAX_PATH_LEN, &flg); - CHKERRQ(ierr); - /* Get num_copies from command line */ - ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); - CHKERRQ(ierr); + int num_copies = 1; + PetscCall(PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg)); - if (!flg) { - file = "../datafiles/case9/case9mod.m"; - } else { - file.assign(file_c_str); - } - - // Set obj_value as reference solution, and run as usual - /* Get validation data file from command line */ - ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, - PETSC_MAX_PATH_LEN, &flg); - CHKERRQ(ierr); - readFromFile(&obj_value, validation_c_str); + // std::string netfile = "CECJ_unittestx" + std::to_string(num_copies) + ".m"; + std::string netfile = "CECJ_unittest1.m"; - obj_value = obj_value * num_copies; + Mat J_eq_ref; + ConstructReferenceJacobian(&J_eq_ref, num_copies); + Vec X; OPFLOW opflowtest; - exago::tests::TestOpflow test; + // exago::tests::TestOpflow test; /* Set up test opflow */ - ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); - CHKERRQ(ierr); - ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); - CHKERRQ(ierr); - ierr = OPFLOWSetUp(opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWGetSolution(opflowtest, &X); - CHKERRQ(ierr); + PetscCall(OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest)); + PetscCall(OPFLOWReadMatPowerData(opflowtest, netfile.c_str())); + PetscCall(OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE)); + PetscCall(OPFLOWSetUp(opflowtest)); + // PetscCall(OPFLOWGetSolution(opflowtest, &X)); + + ConstructSolutionVector(&X, num_copies); // If we are using HIOP, need to convert X // The string lengths must be 65 @@ -92,75 +74,119 @@ int main(int argc, char **argv) { ierr = OPFLOWGetModel(opflowtest, &modelname); ierr = OPFLOWGetSolver(opflowtest, &solvername); - if (solvername == "HIOP") { -#if defined(EXAGO_ENABLE_HIOP) - double *x_ref; - ierr = VecGetArray(X, &x_ref); - - int nx, nconeq, nconineq; - ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); - CHKERRQ(ierr); - - // If we are running using the CPU model, nothing needs to be done - if (modelname == "POWER_BALANCE_HIOP") { - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, x_ref, obj_value); - } else // Using model PBPOLRAJAHIOP - { -#if defined(EXAGO_ENABLE_RAJA) - // Get resource manager instance - auto &resmgr = umpire::ResourceManager::getInstance(); - - // Get Allocator - umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); - - // Register array xref with umpire - umpire::util::AllocationRecord record_x{ - x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; - resmgr.registerAllocation(x_ref, record_x); - // Allocate and copy xref to device - double *x_ref_dev; - -#ifdef EXAGO_ENABLE_GPU - - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); - CHKERRQ(ierr); - - umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); - x_ref_dev = - static_cast(d_allocator.allocate(nx * sizeof(double))); -#else - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); - CHKERRQ(ierr); - x_ref_dev = x_ref; -#endif - resmgr.copy(x_ref_dev, x_ref); - - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); - -#ifdef EXAGO_ENABLE_GPU - d_allocator.deallocate(x_ref_dev); -#endif -#endif + int fail = 0; + // if (solvername == "IPOPT") { + Mat J_eq; + Mat J_ineq = nullptr; + PetscCall(MatDuplicate(J_eq_ref, MAT_SHARE_NONZERO_PATTERN, &J_eq)); + PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); + + PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); + PetscCall(MatView(J_eq_ref, PETSC_VIEWER_STDOUT_SELF)); + PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); + PetscCall(MatView(J_eq, PETSC_VIEWER_STDOUT_SELF)); + + PetscCall(MatAXPY(J_eq, -1.0, J_eq_ref, SAME_NONZERO_PATTERN)); + PetscReal norm = 0.0; + PetscCall(MatNorm(J_eq, NORM_INFINITY, &norm)); + std::cout << "Error norm: " << norm << std::endl; + if (norm >= exago::tests::eps) { + ++fail; + ExaGOLog( + EXAGO_LOG_INFO, + "Error between Equality Constraint Jacobians ({}) exceeds tolerance {}", + norm, exago::tests::eps); + } + // } + // TODO: handle other solver types specially as necessary + // else if (solvername == "HIOP") { + // } + // else if (solvername == "HIOPSPARSE") { + // } + // else { + // throw ExaGOError("Unsupported solver name: " + solvername); + // } + PetscCall(OPFLOWDestroy(&opflowtest)); + + PetscCall(VecDestroy(&X)); + PetscCall(MatDestroy(&J_eq_ref)); + PetscCall(MatDestroy(&J_eq)); + // PetscCall(MatDestroy(&J_ineq)); + + ExaGOFinalize(); + return fail; +} + +PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies) { + PetscFunctionBeginUser; + std::vector x_base = {0, 2, 0, 2, 30, 2, 1.6, -2.2, 0, 2, 0, 2}; + int nvals_base = 12; + int nvals = (nvals_base - 2) * num_copies + 2; + std::vector x; + x.reserve(nvals); + x.assign(begin(x_base), end(x_base)); + std::vector is(nvals); + std::iota(begin(is), end(is), 0); + + for (int n = 1; n < num_copies; ++n) { + for (int i = 2; i < nvals_base; ++i) { + x.push_back(x_base[i]); } + } - ierr = VecRestoreArray(X, &x_ref); - CHKERRQ(ierr); + PetscCall(VecCreateSeq(PETSC_COMM_WORLD, nvals, X)); + PetscCall(VecSetValues(*X, is.size(), is.data(), x.data(), ADD_VALUES)); + PetscCall(VecAssemblyBegin(*X)); + PetscCall(VecAssemblyEnd(*X)); - ierr = PetscFree(x_ref); - CHKERRQ(ierr); -#endif // End #ifdefined(EXAGO_ENABLE_HIOP) - } else { - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, X, obj_value); + PetscFunctionReturn(PETSC_SUCCESS); +} + +PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies) { + PetscFunctionBeginUser; + std::vector i_base = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9}; + std::vector j_base = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, + 8, 9, 0, 1, 2, 3, 4, 5, 8, 9, 2, 3, 4, 5, + 6, 2, 3, 4, 5, 7, 2, 3, 8, 9, 10, 11, 2, 3, + 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11}; + std::vector v_base = { + 0.8, 0.8, -0.8, -0.8, -1.6, -2.0, 1.6, -0.4, -0.8, -0.8, 0.8, + 2.8, 0.8, -0.2, -0.8, -0.8, 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, + 1.6, -0.4, -0.8, 0.2, 0.8, 1.8, -1.0, -0.4, -0.4, 0.4, -2.0, + -1.0, -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, 1.6, -0.4, -3.2, -4.0, + 1.6, -0.4, -0.8, -0.8, 0.8, 0.8, 1.6, -0.4, -1.6, -2.0}; + + int nrows_base = 10; + int ncols_base = 12; + int nrows = (nrows_base - 2) * num_copies + 2; + int ncols = (ncols_base - 2) * num_copies + 2; + + std::vector i_coo; + i_coo.reserve(i_base.size() * num_copies); + i_coo.assign(begin(i_base), end(i_base)); + std::vector j_coo; + j_coo.reserve(j_base.size() * num_copies); + j_coo.assign(begin(j_base), end(j_base)); + std::vector v_coo; + v_coo.reserve(v_base.size() * num_copies); + v_coo.assign(begin(v_base), end(v_base)); + + for (int n = 1; n < num_copies; ++n) { + auto row_start = n * (nrows_base - 2); + auto col_start = n * (ncols_base - 2); + for (std::size_t c = 0; c < v_base.size(); ++c) { + i_coo.push_back(row_start + i_base[c]); + j_coo.push_back(col_start + j_base[c]); + v_coo.push_back(v_base[c]); + } } - ierr = OPFLOWDestroy(&opflowtest); - CHKERRQ(ierr); - // Temporarily skip the test - fail = exago::tests::SKIP_TEST; + PetscCall(MatCreateSeqAIJFromTriple(PETSC_COMM_WORLD, nrows, ncols, + i_coo.data(), j_coo.data(), v_coo.data(), + J, v_coo.size(), PETSC_FALSE)); - ExaGOFinalize(); - return fail; + PetscFunctionReturn(PETSC_SUCCESS); } From 8c757e7657cf3d5d6db085668a36727df0acf90a Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Fri, 17 Apr 2026 13:59:45 -0400 Subject: [PATCH 09/14] Fix angle value and read base Jac from CSV --- .../equality/CMakeLists.txt | 5 +- .../constraint_jacobian/equality/README.md | 4 +- .../constraint_jacobian/equality/cecj.cpp | 210 ++++++++++++++++++ .../equality/jac_eq_acopf.cpp | 91 +++++--- 4 files changed, 273 insertions(+), 37 deletions(-) create mode 100644 tests/unit/opflow/constraint_jacobian/equality/cecj.cpp diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt index 18928c99..6fd7cefc 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -21,10 +21,11 @@ target_include_directories( # Network files to run on - doing 3 and 600 bus examples. set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) -set(obj_network_files testx1.m testx3.m testx600.m) # Map num_copies to a specific netfile set(num_copies 1 3 600) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv + ${CMAKE_CURRENT_BINARY_DIR}/cecj.csv COPYONLY) foreach(n IN LISTS num_copies) execute_process( COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_network.py ${n} @@ -32,8 +33,6 @@ foreach(n IN LISTS num_copies) ) endforeach() -list(TRANSFORM obj_network_files PREPEND ${prefix}) - set(solvers "") set(models "") set(dependencies "") diff --git a/tests/unit/opflow/constraint_jacobian/equality/README.md b/tests/unit/opflow/constraint_jacobian/equality/README.md index 895238cb..2bd2dbe8 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/README.md +++ b/tests/unit/opflow/constraint_jacobian/equality/README.md @@ -73,7 +73,7 @@ In general, solution vector has following elements per bus: For the 5-bus system **CECJ-unittestx1.m**, solution vector is: - +
0 2 0 2 30 2 1.6 -2.2 0 2 0 20 2 0 2 30*PI/180.0 2 1.6 -2.2 0 2 0 2
@@ -170,7 +170,7 @@ To scale the solution vector, following needs to be done: For N=3 the solution vector is: - +
0 2 0 2 30 2 1.6 -2.2 0 2 0 2 0 2 30 2 1.6 -2.2 0 2 0 20 2 30 2 1.6 -2.2 0 2 0 20 2 0 2 30*PI/180.0 2 1.6 -2.2 0 2 0 2 0 2 30*PI/180.0 2 1.6 -2.2 0 2 0 20 2 30*PI/180.0 2 1.6 -2.2 0 2 0 2
diff --git a/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp b/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp new file mode 100644 index 00000000..d7ec72cb --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp @@ -0,0 +1,210 @@ +#include +#include +#include + +#include +#include +#include + +#include "opflow_tests.h" +#include "test_acopf_utils.h" + +PetscErrorCode ConstructReferenceJacobian(Mat* J, int num_copies) +{ + PetscFunctionBeginUser; + std::vector i_base = { + 0, 0, 0, 0, + 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, + 9, 9, 9, 9 + }; + std::vector j_base = { + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 1, 2, 3, 4, 5, 8, 9, + 0, 1, 2, 3, 4, 5, 8, 9, + 2, 3, 4, 5, 6, + 2, 3, 4, 5, 7, + 2, 3, 8, 9, 10, 11, + 2, 3, 8, 9, 10, 11, + 8, 9, 10, 11, + 8, 9, 10, 11 + }; + std::vector v_base = { + 0.8, 0.8, -0.8, -0.8, + -1.6, -2.0, 1.6, -0.4, + -0.8, -0.8, 0.8, 2.8, 0.8, -0.2, -0.8, -0.8, + 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, 1.6, -0.4, + -0.8, 0.2, 0.8, 1.8, -1.0, + -0.4, -0.4, 0.4, -2.0, -1.0, + -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, + 1.6, -0.4, -3.2, -4.0, 1.6, -0.4, + -0.8, -0.8, 0.8, 0.8, + 1.6, -0.4, -1.6, -2.0 + }; + + int nrows_base = 10; + int ncols_base = 12; + int nrows = (nrows_base - 2) * num_copies + 2; + int ncols = (ncols_base - 2) * num_copies + 2; + + std::vector i_coo = i_base; + std::vector j_coo = j_base; + std::vector v_coo = v_base; + + for (int n = 1; n < num_copies; ++n) { + auto row_start = n * (nrows_base - 2); + auto col_start = n * (ncols_base - 2); + for (int c = 0; c < v_base.size(); ++c) { + i_coo.push_back(row_start + i_base[c]); + j_coo.push_back(col_start + j_base[c]); + v_coo.push_back(v_base[c]); + } + } + + PetscCall(MatCreate(PETSC_COMM_WORLD, J)); + PetscCall(MatSetSizes(*J, nrows, ncols, PETSC_DECIDE, PETSC_DECIDE)); + PetscCall(MatSetType(*J, MATSEQAIJ)); + PetscCall(MatSetPreallocationCOO(*J, v_coo.size(), i_coo.data(), j_coo.data())); + PetscCall(MatSetValuesCOO(*J, v_coo.data(), ADD_VALUES)); + PetscFunctionReturn(PETSC_SUCCESS); +} + +/** + * @brief Unit test driver for the "compute equality constraint jacobian" + * @see opflow/OpflowTests.hpp for kernel tested by this driver + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + Vec X; + int fail = 0; + double obj_value; + char file_c_str[PETSC_MAX_PATH_LEN]; + char validation_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + int num_copies = 0; + + char help[] = "Unit tests for comparing GPU- and CPU-computed equality constraint jacobians\n"; + + /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); + return ierr; + } + + /* Get network data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + + /* Get num_copies from command line */ + ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); + CHKERRQ(ierr); + + Mat J_eq_ref; + ConstructReferenceJacobian(&J_ref, num_copies); + + if (!flg) { + file = "CECJ_unittest1.m"; + } else { + file.assign(file_c_str); + } + + OPFLOW opflowtest; + exago::tests::TestOpflow test; + + /* Set up test opflow */ + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflowtest, &X); + CHKERRQ(ierr); + + // If we are using HIOP, need to convert X + // The string lengths must be 65 + std::string modelname; + std::string solvername; + ierr = OPFLOWGetModel(opflowtest, &modelname); + ierr = OPFLOWGetSolver(opflowtest, &solvername); + + if (solvername == "HIOP") { +#if defined(EXAGO_ENABLE_HIOP) + double *x_ref; + ierr = VecGetArray(X, &x_ref); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + // If we are running using the CPU model, nothing needs to be done + if (modelname == "POWER_BALANCE_HIOP") { + fail += test.computeConstraintJacobian(opflowtest, x_ref, J_eq_ref); + } else // Using model PBPOLRAJAHIOP + { +#if defined(EXAGO_ENABLE_RAJA) + // Get resource manager instance + auto &resmgr = umpire::ResourceManager::getInstance(); + + // Get Allocator + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Register array xref with umpire + umpire::util::AllocationRecord record_x{ + x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_ref, record_x); + // Allocate and copy xref to device + double *x_ref_dev; + +#ifdef EXAGO_ENABLE_GPU + + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); + CHKERRQ(ierr); + + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_ref_dev = + static_cast(d_allocator.allocate(nx * sizeof(double))); +#else + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); + CHKERRQ(ierr); + x_ref_dev = x_ref; +#endif + resmgr.copy(x_ref_dev, x_ref); + + fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_ref_dev); +#endif +#endif + } + + ierr = VecRestoreArray(X, &x_ref); + CHKERRQ(ierr); + + ierr = PetscFree(x_ref); + CHKERRQ(ierr); +#endif // End #ifdefined(EXAGO_ENABLE_HIOP) + } else { + fail += test.computeObjective(opflowtest, X, obj_value); + } + ierr = OPFLOWDestroy(&opflowtest); + CHKERRQ(ierr); + + ExaGOFinalize(); + return fail; +} diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index c2cf3c0b..f9e4a718 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include @@ -11,6 +13,8 @@ // #include "opflow_tests.h" #include "test_acopf_utils.h" +inline constexpr double PI = 3.14159265358979323846; + PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies); PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies); @@ -30,15 +34,14 @@ PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies); * */ int main(int argc, char **argv) { - PetscErrorCode ierr; PetscBool flg; - MPI_Comm comm = MPI_COMM_WORLD; char appname[] = "opflow"; char help[] = "Unit tests for equality constraint Jacobians running opflow\n"; /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ - ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + PetscErrorCode ierr = ExaGOInitialize(MPI_COMM_WORLD, + &argc, &argv, appname, help); if (ierr) { fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); return ierr; @@ -48,8 +51,8 @@ int main(int argc, char **argv) { int num_copies = 1; PetscCall(PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg)); - // std::string netfile = "CECJ_unittestx" + std::to_string(num_copies) + ".m"; - std::string netfile = "CECJ_unittest1.m"; + std::string netfile = "CECJ_unittestx" + std::to_string(num_copies) + ".m"; + // std::string netfile = "CECJ_unittest1.m"; Mat J_eq_ref; ConstructReferenceJacobian(&J_eq_ref, num_copies); @@ -71,8 +74,8 @@ int main(int argc, char **argv) { // The string lengths must be 65 std::string modelname; std::string solvername; - ierr = OPFLOWGetModel(opflowtest, &modelname); - ierr = OPFLOWGetSolver(opflowtest, &solvername); + PetscCall(OPFLOWGetModel(opflowtest, &modelname)); + PetscCall(OPFLOWGetSolver(opflowtest, &solvername)); int fail = 0; // if (solvername == "IPOPT") { @@ -106,6 +109,7 @@ int main(int argc, char **argv) { // else { // throw ExaGOError("Unsupported solver name: " + solvername); // } + PetscCall(OPFLOWDestroy(&opflowtest)); PetscCall(VecDestroy(&X)); @@ -119,13 +123,14 @@ int main(int argc, char **argv) { PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies) { PetscFunctionBeginUser; - std::vector x_base = {0, 2, 0, 2, 30, 2, 1.6, -2.2, 0, 2, 0, 2}; + + std::vector x_base = {0, 2, 0, 2, 30*PI/180.0, 2, 1.6, -2.2, 0, 2, 0, 2}; int nvals_base = 12; int nvals = (nvals_base - 2) * num_copies + 2; - std::vector x; + std::vector x; x.reserve(nvals); x.assign(begin(x_base), end(x_base)); - std::vector is(nvals); + std::vector is(nvals); std::iota(begin(is), end(is), 0); for (int n = 1; n < num_copies; ++n) { @@ -144,34 +149,56 @@ PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies) { PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies) { PetscFunctionBeginUser; - std::vector i_base = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, - 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9}; - std::vector j_base = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, - 8, 9, 0, 1, 2, 3, 4, 5, 8, 9, 2, 3, 4, 5, - 6, 2, 3, 4, 5, 7, 2, 3, 8, 9, 10, 11, 2, 3, - 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11}; - std::vector v_base = { - 0.8, 0.8, -0.8, -0.8, -1.6, -2.0, 1.6, -0.4, -0.8, -0.8, 0.8, - 2.8, 0.8, -0.2, -0.8, -0.8, 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, - 1.6, -0.4, -0.8, 0.2, 0.8, 1.8, -1.0, -0.4, -0.4, 0.4, -2.0, - -1.0, -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, 1.6, -0.4, -3.2, -4.0, - 1.6, -0.4, -0.8, -0.8, 0.8, 0.8, 1.6, -0.4, -1.6, -2.0}; - - int nrows_base = 10; - int ncols_base = 12; + + // Read base Jacobian from file + std::ifstream ifs("cecj.csv"); + if (!ifs) { + throw ExaGOError("Unable to open file: cecj.csv"); + } + std::string line; + int nrows_base, ncols_base; + std::vector i_base; + std::vector j_base; + std::vector v_base; + // Read matrix dimensions + std::getline(ifs, line); + std::istringstream iss(line); + std::string dimstr; + std::getline(iss, dimstr, ','); + std::istringstream(dimstr) >> nrows_base; + std::getline(iss, dimstr, ','); + std::istringstream(dimstr) >> ncols_base; + // Read triples + std::string estr; + while (std::getline(ifs, line)) { + PetscInt i, j; + PetscReal v; + iss = std::istringstream(line); + std::getline(iss, estr, ','); + std::istringstream(estr) >> i; + std::getline(iss, estr, ','); + std::istringstream(estr) >> j; + std::getline(iss, estr, ','); + std::istringstream(estr) >> v; + i_base.push_back(i - 1); + j_base.push_back(j - 1); + v_base.push_back(v); + } + int nrows = (nrows_base - 2) * num_copies + 2; int ncols = (ncols_base - 2) * num_copies + 2; std::vector i_coo; - i_coo.reserve(i_base.size() * num_copies); - i_coo.assign(begin(i_base), end(i_base)); std::vector j_coo; - j_coo.reserve(j_base.size() * num_copies); - j_coo.assign(begin(j_base), end(j_base)); std::vector v_coo; - v_coo.reserve(v_base.size() * num_copies); + + std::size_t ncoo = i_base.size() * num_copies; + i_coo.reserve(ncoo); + j_coo.reserve(ncoo); + v_coo.reserve(ncoo); + + i_coo.assign(begin(i_base), end(i_base)); + j_coo.assign(begin(j_base), end(j_base)); v_coo.assign(begin(v_base), end(v_base)); for (int n = 1; n < num_copies; ++n) { From af906a8fa35742abb8e7eb0932a342711c02d8c0 Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Fri, 17 Apr 2026 21:36:36 -0400 Subject: [PATCH 10/14] Add cicj test --- .../equality/CMakeLists.txt | 6 +- .../constraint_jacobian/equality/cecj.cpp | 57 ++-- .../equality/jac_eq_acopf.cpp | 11 +- .../inequality/CMakeLists.txt | 32 ++- .../constraint_jacobian/inequality/README.md | 4 +- .../constraint_jacobian/inequality/cicj.csv | 19 -- .../inequality/gen_network.py | 133 +++++++++ .../inequality/jac_ineq_acopf.cpp | 272 +++++++++++------- 8 files changed, 345 insertions(+), 189 deletions(-) create mode 100644 tests/unit/opflow/constraint_jacobian/inequality/gen_network.py diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt index 6fd7cefc..52409dd8 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -24,8 +24,10 @@ set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) # Map num_copies to a specific netfile set(num_copies 1 3 600) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv - ${CMAKE_CURRENT_BINARY_DIR}/cecj.csv COPYONLY) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv ${CMAKE_CURRENT_BINARY_DIR}/cecj.csv + COPYONLY +) foreach(n IN LISTS num_copies) execute_process( COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_network.py ${n} diff --git a/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp b/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp index d7ec72cb..3eefe636 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp @@ -9,45 +9,22 @@ #include "opflow_tests.h" #include "test_acopf_utils.h" -PetscErrorCode ConstructReferenceJacobian(Mat* J, int num_copies) -{ +PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies) { PetscFunctionBeginUser; - std::vector i_base = { - 0, 0, 0, 0, - 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, - 9, 9, 9, 9 - }; - std::vector j_base = { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, 4, 5, 8, 9, - 0, 1, 2, 3, 4, 5, 8, 9, - 2, 3, 4, 5, 6, - 2, 3, 4, 5, 7, - 2, 3, 8, 9, 10, 11, - 2, 3, 8, 9, 10, 11, - 8, 9, 10, 11, - 8, 9, 10, 11 - }; + std::vector i_base = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9}; + std::vector j_base = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, + 8, 9, 0, 1, 2, 3, 4, 5, 8, 9, 2, 3, 4, 5, + 6, 2, 3, 4, 5, 7, 2, 3, 8, 9, 10, 11, 2, 3, + 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11}; std::vector v_base = { - 0.8, 0.8, -0.8, -0.8, - -1.6, -2.0, 1.6, -0.4, - -0.8, -0.8, 0.8, 2.8, 0.8, -0.2, -0.8, -0.8, - 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, 1.6, -0.4, - -0.8, 0.2, 0.8, 1.8, -1.0, - -0.4, -0.4, 0.4, -2.0, -1.0, - -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, - 1.6, -0.4, -3.2, -4.0, 1.6, -0.4, - -0.8, -0.8, 0.8, 0.8, - 1.6, -0.4, -1.6, -2.0 - }; + 0.8, 0.8, -0.8, -0.8, -1.6, -2.0, 1.6, -0.4, -0.8, -0.8, 0.8, + 2.8, 0.8, -0.2, -0.8, -0.8, 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, + 1.6, -0.4, -0.8, 0.2, 0.8, 1.8, -1.0, -0.4, -0.4, 0.4, -2.0, + -1.0, -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, 1.6, -0.4, -3.2, -4.0, + 1.6, -0.4, -0.8, -0.8, 0.8, 0.8, 1.6, -0.4, -1.6, -2.0}; int nrows_base = 10; int ncols_base = 12; @@ -71,7 +48,8 @@ PetscErrorCode ConstructReferenceJacobian(Mat* J, int num_copies) PetscCall(MatCreate(PETSC_COMM_WORLD, J)); PetscCall(MatSetSizes(*J, nrows, ncols, PETSC_DECIDE, PETSC_DECIDE)); PetscCall(MatSetType(*J, MATSEQAIJ)); - PetscCall(MatSetPreallocationCOO(*J, v_coo.size(), i_coo.data(), j_coo.data())); + PetscCall( + MatSetPreallocationCOO(*J, v_coo.size(), i_coo.data(), j_coo.data())); PetscCall(MatSetValuesCOO(*J, v_coo.data(), ADD_VALUES)); PetscFunctionReturn(PETSC_SUCCESS); } @@ -93,7 +71,8 @@ int main(int argc, char **argv) { MPI_Comm comm = MPI_COMM_WORLD; int num_copies = 0; - char help[] = "Unit tests for comparing GPU- and CPU-computed equality constraint jacobians\n"; + char help[] = "Unit tests for comparing GPU- and CPU-computed equality " + "constraint jacobians\n"; /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index f9e4a718..7e1d1681 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -40,8 +40,8 @@ int main(int argc, char **argv) { char help[] = "Unit tests for equality constraint Jacobians running opflow\n"; /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ - PetscErrorCode ierr = ExaGOInitialize(MPI_COMM_WORLD, - &argc, &argv, appname, help); + PetscErrorCode ierr = + ExaGOInitialize(MPI_COMM_WORLD, &argc, &argv, appname, help); if (ierr) { fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); return ierr; @@ -81,7 +81,7 @@ int main(int argc, char **argv) { // if (solvername == "IPOPT") { Mat J_eq; Mat J_ineq = nullptr; - PetscCall(MatDuplicate(J_eq_ref, MAT_SHARE_NONZERO_PATTERN, &J_eq)); + PetscCall(OPFLOWGetConstraintJacobian(opflowtest, &J_eq, &J_ineq)); PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); @@ -114,8 +114,6 @@ int main(int argc, char **argv) { PetscCall(VecDestroy(&X)); PetscCall(MatDestroy(&J_eq_ref)); - PetscCall(MatDestroy(&J_eq)); - // PetscCall(MatDestroy(&J_ineq)); ExaGOFinalize(); return fail; @@ -124,7 +122,8 @@ int main(int argc, char **argv) { PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies) { PetscFunctionBeginUser; - std::vector x_base = {0, 2, 0, 2, 30*PI/180.0, 2, 1.6, -2.2, 0, 2, 0, 2}; + std::vector x_base = {0, 2, 0, 2, 30 * PI / 180.0, 2, 1.6, -2.2, + 0, 2, 0, 2}; int nvals_base = 12; int nvals = (nvals_base - 2) * num_copies + 2; std::vector x; diff --git a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt index 18177699..dd75a8e3 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt @@ -1,3 +1,8 @@ +find_package(Python) +if(NOT Python_FOUND) + return() +endif() + if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) set_source_files_properties(jac_ineq_acopf.cpp PROPERTIES LANGUAGE CUDA) endif() @@ -16,11 +21,23 @@ target_include_directories( # Network files to run on - doing 3 and 600 bus examples. set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) -set(obj_network_files testx3.m testx600.m) # Map num_copies to a specific netfile -set(num_copies 3 600) +set(num_copies 1 3 600) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cicj.csv ${CMAKE_CURRENT_BINARY_DIR}/cicj.csv + COPYONLY +) +foreach(n IN LISTS num_copies) + execute_process( + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_network.py ${n} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) +endforeach() -list(TRANSFORM obj_network_files PREPEND ${prefix}) +set(solvers "") +set(models "") +set(dependencies "") # Set up Ipopt solver tests if enabled if(EXAGO_ENABLE_IPOPT) @@ -62,10 +79,9 @@ if(EXAGO_RUN_TESTS) dependencies ) # Iterate over networks, matching network file to num_copies - foreach(network num IN ZIP_LISTS obj_network_files num_copies) - get_filename_component(net ${network} NAME) + foreach(num IN LISTS num_copies) set(testname - "UNIT_TESTS_INEQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + "UNIT_TESTS_INEQUALITY_CONSTRAINT_JACOBIAN_${num}_${solver}_${model}" ) exago_add_test( NAME @@ -79,12 +95,8 @@ if(EXAGO_RUN_TESTS) ${model} -opflow_solver ${solver} - -netfile - ${network} -num_copies ${num} - -validation - ${CMAKE_CURRENT_SOURCE_DIR}/cicj.csv ) set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) endforeach() diff --git a/tests/unit/opflow/constraint_jacobian/inequality/README.md b/tests/unit/opflow/constraint_jacobian/inequality/README.md index a65c5176..82329b6f 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/README.md +++ b/tests/unit/opflow/constraint_jacobian/inequality/README.md @@ -107,7 +107,7 @@ In general, solution vector has following elements per bus: 3. Generator MW (if generator bus) 4. Generator MVar (if generator bus) -For the 5-bus system **CEC-unittestx1.m**, solution vector is: +For the 5-bus system **CICJ-unittestx1.m**, solution vector is: @@ -190,7 +190,7 @@ With the parameters of the example network the matrix is: - +
0 2 0 2 30*PI/180.0 2 1.6 -2.2 0 2 0 2Sf45 0 0 0 0 0 0 0 0 15.36 19.2 -15.36 3.84
St45 0 0 0 0 0 0 0 0 -15.36 3.94 15.36 19.2St45 0 0 0 0 0 0 0 0 -15.36 3.84 15.36 19.2
diff --git a/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv b/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv index 97fbb421..2da4e29c 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv +++ b/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv @@ -12,7 +12,6 @@ 4,3,7.68 4,4,9.6 5,3,-0.32 -5,4,-4.44089209850062e-17 5,5,0.32 5,6,0.32 6,3,-1.28 @@ -35,21 +34,3 @@ 10,10,3.84 10,11,15.36 10,12,19.2 -7,9,1.6 -7,10,1.6 -7,11,-0.8 -7,12,-0.8 -8,3,1.6 -8,4,-0.4 -8,9,-3.2 -8,10,-4 -8,11,1.6 -8,12,-0.4 -9,9,-0.8 -9,10,-0.8 -9,11,0.8 -9,12,0.8 -10,9,1.6 -10,10,-0.4 -10,11,-1.6 -10,12,-2 diff --git a/tests/unit/opflow/constraint_jacobian/inequality/gen_network.py b/tests/unit/opflow/constraint_jacobian/inequality/gen_network.py new file mode 100644 index 00000000..ffa8f4d1 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/inequality/gen_network.py @@ -0,0 +1,133 @@ +#!/usr/bin/python + +import sys + + +def header(bus_size): + output = [] + output.append("function mpc = CICJ_unittestx" + bus_size + "\n") + output.append("mpc.version = '2';\n") + output.append("mpc.baseMVA = 100.00;\n") + output.append("\n") + return output + + +def bus(bus_size): + output = [] + output.append("%% bus data\n") + output.append("mpc.bus = [\n") + output.append( "1 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "2 1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "3 3 0.00 0.00 0.00 0.00 1 0.5000000 30.000000 13.80 1 1.100 0.900\n") + output.append( "4 1 -3.40 8.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append( "5 1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + for i in range(1, int(bus_size)): + bus_idx = (i + 1) * 4 + output.append(f"{bus_idx - 2} " + + "1 0.00 0.00 0.25 -0.05 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append(f"{bus_idx - 1} " + + "2 0.00 0.00 0.00 0.00 1 0.5000000 30.000000 13.80 1 1.100 0.900\n") + output.append(f"{bus_idx} " + + "1 -3.40 8.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append(f"{bus_idx + 1} " + + "1 0.00 0.00 0.00 0.00 1 2.0000000 0.000000 138.00 1 1.100 0.900\n") + output.append("];\n") + output.append("\n") + return output + + +def generator(bus_size): + output = [] + output.append("%% generator data\n") + output.append("mpc.gen = [\n") + for i in range(3, int(bus_size) * 4, 4): + output.append( + f"{i} 1.60 -2.20 197.80 -202.20 0.5000 100.00 1 1.60 1.60 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 10.0000\n") + output.append("];\n") + output.append("\n") + return output + + +def gen_cost(bus_size): + output = [] + output.append("%% generator cost data\n") + output.append("mpc.gencost = [\n") + for _ in range(int(bus_size)): + output.append("2 0 0 3 0.010 0.100 8.00 0.0000 \n") + output.append("];\n") + output.append("\n") + return output + + +def branch(bus_size): + output = [] + output.append("%% branch data\n") + output.append("mpc.branch = [\n") + for i in range(int(bus_size)): + bus_idx = (4 * i + 1) + output.append(f"{bus_idx} {bus_idx + 1} " + + "2.000000 1.000000 1.20000 230.00 230.00 230.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00\n") + output.append(f"{bus_idx + 1} {bus_idx + 2} " + + "2.000000 1.000000 1.20000 230.00 230.00 230.00 2.00000 60.000 1 0.00 0.00 0.00 -140.00 200.00 -240.00\n") + output.append(f"{bus_idx + 1} {bus_idx + 3} " + + "2.000000 1.000000 1.20000 230.00 230.00 230.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00\n") + output.append(f"{bus_idx + 3} {bus_idx + 4} " + + "2.000000 1.000000 1.20000 230.00 230.00 230.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00\n") + output.append("];\n") + output.append("\n") + return output + + +def bus_names(bus_size): + output = [] + output.append("%% bus names\n") + output.append("mpc.bus_name = {\n") + for i in range(int(bus_size) * 4 + 1): + output.append(f"'{i + 1}';\n") + output.append("};\n") + output.append("\n") + return output + + +def gen_types(bus_size): + output = [] + output.append("%% Generator Unit Types\n") + output.append("mpc.gentype = {\n") + for i in range(int(bus_size)): + output.append("'UN';\n") + output.append("};\n") + output.append("\n") + return output + + +def gen_fuel(bus_size): + output = [] + output.append("%% Generator Fuel Types\n") + output.append("mpc.genfuel = {\n") + for i in range(int(bus_size)): + output.append("'unknown';\n") + output.append("};\n") + return output + + +if __name__ == '__main__': + network_length = 0 + + # Script can be called with CLI argument + if (len(sys.argv) < 2): + network_length = input('Enter a network size: ') + else: + network_length = sys.argv[1] + + print(f'Generating a network of size {network_length}') + + output_filename = 'CICJ_unittestx' + network_length + '.m' + + f = open(output_filename, "w+") + + # Loop over file component functions and append to file + for section in [header, bus, generator, gen_cost, branch, bus_names, gen_types, gen_fuel]: + for line in section(network_length): + f.write(line) + + f.close() diff --git a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp index 4a6fc30c..172e38a0 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp @@ -1,14 +1,23 @@ +#include #include #include +#include +#include #include #include #include #include +#include -#include "opflow_tests.h" +// #include "opflow_tests.h" #include "test_acopf_utils.h" +inline constexpr double PI = 3.14159265358979323846; + +PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies); +PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies); + /** * @brief Unit test driver for objective function * @see opflow/OpflowTests.hpp for kernel tested by this driver @@ -25,143 +34,184 @@ * */ int main(int argc, char **argv) { - PetscErrorCode ierr; PetscBool flg; - Vec X; - int fail = 0; - double obj_value; - char file_c_str[PETSC_MAX_PATH_LEN]; - char validation_c_str[PETSC_MAX_PATH_LEN]; - std::string file; - char appname[] = "opflow"; - MPI_Comm comm = MPI_COMM_WORLD; - int num_copies = 0; + char appname[] = "opflow"; char help[] = "Unit tests for inequality constraint Jacobians running opflow\n"; /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ - ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + PetscErrorCode ierr = + ExaGOInitialize(PETSC_COMM_WORLD, &argc, &argv, appname, help); if (ierr) { fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); return ierr; } - /* Get network data file from command line */ - ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, - PETSC_MAX_PATH_LEN, &flg); - CHKERRQ(ierr); - /* Get num_copies from command line */ - ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); - CHKERRQ(ierr); + int num_copies = 1; + PetscCall(PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg)); - if (!flg) { - file = "../datafiles/case9/case9mod.m"; - } else { - file.assign(file_c_str); - } + std::string netfile = "CICJ_unittestx" + std::to_string(num_copies) + ".m"; - // Set obj_value as reference solution, and run as usual - /* Get validation data file from command line */ - ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, - PETSC_MAX_PATH_LEN, &flg); - CHKERRQ(ierr); - readFromFile(&obj_value, validation_c_str); - - obj_value = obj_value * num_copies; + Mat J_ineq_ref; + ConstructReferenceJacobian(&J_ineq_ref, num_copies); + Vec X; OPFLOW opflowtest; - exago::tests::TestOpflow test; + // exago::tests::TestOpflow test; /* Set up test opflow */ - ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); - CHKERRQ(ierr); - ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); - CHKERRQ(ierr); - ierr = OPFLOWSetUp(opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWGetSolution(opflowtest, &X); - CHKERRQ(ierr); + PetscCall(OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest)); + PetscCall(OPFLOWReadMatPowerData(opflowtest, netfile.c_str())); + // PetscCall(OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE)); + PetscCall(OPFLOWSetGenBusVoltageType(opflowtest, FIXED_WITHIN_QBOUNDS)); + PetscCall(OPFLOWSetUp(opflowtest)); + // PetscCall(OPFLOWGetSolution(opflowtest, &X)); + + ConstructSolutionVector(&X, num_copies); // If we are using HIOP, need to convert X // The string lengths must be 65 std::string modelname; std::string solvername; - ierr = OPFLOWGetModel(opflowtest, &modelname); - ierr = OPFLOWGetSolver(opflowtest, &solvername); - - if (solvername == "HIOP") { -#if defined(EXAGO_ENABLE_HIOP) - double *x_ref; - ierr = VecGetArray(X, &x_ref); - - int nx, nconeq, nconineq; - ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); - CHKERRQ(ierr); - - // If we are running using the CPU model, nothing needs to be done - if (modelname == "POWER_BALANCE_HIOP") { - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, x_ref, obj_value); - } else // Using model PBPOLRAJAHIOP - { -#if defined(EXAGO_ENABLE_RAJA) - // Get resource manager instance - auto &resmgr = umpire::ResourceManager::getInstance(); - - // Get Allocator - umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); - - // Register array xref with umpire - umpire::util::AllocationRecord record_x{ - x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; - resmgr.registerAllocation(x_ref, record_x); - // Allocate and copy xref to device - double *x_ref_dev; - -#ifdef EXAGO_ENABLE_GPU - - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); - CHKERRQ(ierr); - - umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); - x_ref_dev = - static_cast(d_allocator.allocate(nx * sizeof(double))); -#else - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); - CHKERRQ(ierr); - x_ref_dev = x_ref; -#endif - resmgr.copy(x_ref_dev, x_ref); - - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); - -#ifdef EXAGO_ENABLE_GPU - d_allocator.deallocate(x_ref_dev); -#endif -#endif - } + PetscCall(OPFLOWGetModel(opflowtest, &modelname)); + PetscCall(OPFLOWGetSolver(opflowtest, &solvername)); - ierr = VecRestoreArray(X, &x_ref); - CHKERRQ(ierr); - - ierr = PetscFree(x_ref); - CHKERRQ(ierr); -#endif // End #ifdefined(EXAGO_ENABLE_HIOP) - } else { - // TODO: Replace with inequality Jacobian test once implemented - // fail += test.computeObjective(opflowtest, X, obj_value); + int fail = 0; + // if (solvername == "IPOPT") { + Mat J_eq; + Mat J_ineq; + PetscCall(OPFLOWGetConstraintJacobian(opflowtest, &J_eq, &J_ineq)); + PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); + + PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); + PetscCall(MatView(J_ineq_ref, PETSC_VIEWER_STDOUT_SELF)); + PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); + PetscCall(MatView(J_ineq, PETSC_VIEWER_STDOUT_SELF)); + + PetscCall(MatAXPY(J_ineq, -1.0, J_ineq_ref, SAME_NONZERO_PATTERN)); + PetscReal norm = 0.0; + PetscCall(MatNorm(J_ineq, NORM_INFINITY, &norm)); + std::cout << "Error norm: " << norm << std::endl; + if (norm >= exago::tests::eps) { + ++fail; + ExaGOLog(EXAGO_LOG_INFO, + "Error between Inequality Constraint Jacobians ({}) exceeds " + "tolerance {}", + norm, exago::tests::eps); } - ierr = OPFLOWDestroy(&opflowtest); - CHKERRQ(ierr); + // } + // TODO: handle other solver types specially as necessary + + PetscCall(OPFLOWDestroy(&opflowtest)); - // Temporarily skip the test - fail = exago::tests::SKIP_TEST; + PetscCall(VecDestroy(&X)); + PetscCall(MatDestroy(&J_ineq_ref)); ExaGOFinalize(); return fail; } + +PetscErrorCode ConstructSolutionVector(Vec *X, int num_copies) { + PetscFunctionBeginUser; + + std::vector x_base = {0, 2, 0, 2, 30 * PI / 180.0, 2, 1.6, -2.2, + 0, 2, 0, 2}; + int nvals_base = 12; + int nvals = (nvals_base - 2) * num_copies + 2; + std::vector x; + x.reserve(nvals); + x.assign(begin(x_base), end(x_base)); + std::vector is(nvals); + std::iota(begin(is), end(is), 0); + + for (int n = 1; n < num_copies; ++n) { + for (int i = 2; i < nvals_base; ++i) { + x.push_back(x_base[i]); + } + } + + PetscCall(VecCreateSeq(PETSC_COMM_WORLD, nvals, X)); + PetscCall(VecSetValues(*X, is.size(), is.data(), x.data(), ADD_VALUES)); + PetscCall(VecAssemblyBegin(*X)); + PetscCall(VecAssemblyEnd(*X)); + PetscFunctionReturn(PETSC_SUCCESS); +} + +PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies) { + PetscFunctionBeginUser; + + // Read base Jacobian from file + std::ifstream ifs("cicj.csv"); + if (!ifs) { + throw ExaGOError("Unable to open file: cicj.csv"); + } + std::string line; + int nrows_base, ncols_base; + std::vector i_base; + std::vector j_base; + std::vector v_base; + // Read matrix dimensions + std::getline(ifs, line); + std::istringstream iss(line); + std::string dimstr; + std::getline(iss, dimstr, ','); + std::istringstream(dimstr) >> nrows_base; + std::getline(iss, dimstr, ','); + std::istringstream(dimstr) >> ncols_base; + // Read triples + std::string estr; + while (std::getline(ifs, line)) { + PetscInt i, j; + PetscReal v; + iss = std::istringstream(line); + std::getline(iss, estr, ','); + std::istringstream(estr) >> i; + std::getline(iss, estr, ','); + std::istringstream(estr) >> j; + std::getline(iss, estr, ','); + std::istringstream(estr) >> v; + i_base.push_back(i - 1); + j_base.push_back(j - 1); + v_base.push_back(v); + } + + int nrows = (nrows_base - 2) * num_copies + 2; + int ncols = (ncols_base - 2) * num_copies + 2; + + std::vector i_coo; + std::vector j_coo; + std::vector v_coo; + + std::size_t ncoo = i_base.size() * num_copies; + i_coo.reserve(ncoo); + j_coo.reserve(ncoo); + v_coo.reserve(ncoo); + + i_coo.assign(begin(i_base), end(i_base)); + j_coo.assign(begin(j_base), end(j_base)); + v_coo.assign(begin(v_base), end(v_base)); + + for (int n = 1; n < num_copies; ++n) { + auto row_start_top = n * 2; + auto row_start = n * (nrows_base - 2); + auto col_start = n * (ncols_base - 2); + for (std::size_t c = 0; c < v_base.size(); ++c) { + auto i = i_base[c]; + if (i < 2) { + i_coo.push_back(row_start_top + i); + } else { + i_coo.push_back(row_start + i_base[c]); + } + j_coo.push_back(col_start + j_base[c]); + v_coo.push_back(v_base[c]); + } + } + + PetscCall(MatCreateSeqAIJFromTriple(PETSC_COMM_WORLD, nrows, ncols, + i_coo.data(), j_coo.data(), v_coo.data(), + J, v_coo.size(), PETSC_FALSE)); + + PetscFunctionReturn(PETSC_SUCCESS); +} From e71c2d23f07a4710b1700cb39b31d2e7bed86f39 Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Thu, 23 Apr 2026 12:20:49 -0400 Subject: [PATCH 11/14] Update cicj script and values --- .../inequality/CICJ_unittest1.m | 6 +++--- .../constraint_jacobian/inequality/README.md | 10 +++++----- .../constraint_jacobian/inequality/Untitled.m | 13 ++++++------ .../constraint_jacobian/inequality/cicj.csv | 20 +++++++++---------- .../inequality/jac_ineq_acopf.cpp | 2 +- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/tests/unit/opflow/constraint_jacobian/inequality/CICJ_unittest1.m b/tests/unit/opflow/constraint_jacobian/inequality/CICJ_unittest1.m index a3f80557..7e2fb943 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/CICJ_unittest1.m +++ b/tests/unit/opflow/constraint_jacobian/inequality/CICJ_unittest1.m @@ -24,10 +24,10 @@ %% branch data mpc.branch = [ -1 2 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 +1 2 2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 2 3 2.000000 1.000000 1.20000 0.00 0.00 0.00 2.00000 60.000 1 0.00 0.00 0.00 -140.00 200.00 -240.00 -2 4 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 -4 5 2.000000 1.000000 1.20000 0.00 0.00 0.00 0.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 +2 4 2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 +4 5 2.000000 1.000000 1.20000 0.00 0.00 0.00 1.00000 0.000 1 0.00 0.00 0.00 -240.00 0.00 -240.00 ]; %% bus names diff --git a/tests/unit/opflow/constraint_jacobian/inequality/README.md b/tests/unit/opflow/constraint_jacobian/inequality/README.md index 82329b6f..deb47feb 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/README.md +++ b/tests/unit/opflow/constraint_jacobian/inequality/README.md @@ -163,10 +163,10 @@ With the parameters of the example network the matrix is: theta1 Vm1 theta2 Vm2 theta3 Vm3 Pg3 Qg3 theta4 Vm4 theta5 Vm5 -IEC1 0 0 0 0 0 200 0 -1.5 0 0 0 0 +IEC1 0 0 0 0 0 4.178 0 -1.5 0 0 0 0 -IEC2 0 0 0 0 0 -200 0 -1.5 0 0 0 0 +IEC2 0 0 0 0 0 0.178 0 -1.5 0 0 0 0 Sf12 7.68 9.6 -7.68 1.92 0 0 0 0 0 0 0 0 @@ -184,13 +184,13 @@ With the parameters of the example network the matrix is: Sf24 0 0 7.68 9.6 0 0 0 0 -7.68 1.92 0 0 -St24 0 0 -7.68 1.92 0 0 0 0 7.68 9.6 1.6 -0.4 +St24 0 0 -7.68 1.92 0 0 0 0 7.68 9.6 0 0 -Sf45 0 0 0 0 0 0 0 0 15.36 19.2 -15.36 3.84 +Sf45 0 0 0 0 0 0 0 0 7.68 9.6 -7.68 1.92 -St45 0 0 0 0 0 0 0 0 -15.36 3.84 15.36 19.2 +St45 0 0 0 0 0 0 0 0 -7.68 1.92 7.68 9.6 diff --git a/tests/unit/opflow/constraint_jacobian/inequality/Untitled.m b/tests/unit/opflow/constraint_jacobian/inequality/Untitled.m index a88021f1..09862ada 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/Untitled.m +++ b/tests/unit/opflow/constraint_jacobian/inequality/Untitled.m @@ -12,6 +12,7 @@ theta4=deg2rad(0); theta5=deg2rad(0); +mvabase=100; R=2; X=1; @@ -25,8 +26,8 @@ Pg=1.6; Qg=-2.2; -Qmax=197.8; -Qmin=-202.2; +Qmax=197.8 / mvabase; +Qmin=-202.2 = mvabase; Pd=-3.4; Qd=8.8; @@ -247,10 +248,10 @@ Sf45 = Pf45*Pf45 + Qf45*Qf45; St45 = Pt45*Pt45 + Qt45*Qt45; -dSf45dPf45 = 4*Pf45; -dSf45dQf45 = 4*Qf45; -dSt45dPt45 = 4*Pt45; -dSt45dQt45 = 4*Qt45; +dSf45dPf45 = 2*Pf45; +dSf45dQf45 = 2*Qf45; +dSt45dPt45 = 2*Pt45; +dSt45dQt45 = 2*Qt45; dSf45dVm4 = (dSf45dPf45*dPf45dVm4+ dSf45dQf45*dQf45dVm4)*multiplier; dSf45dVm5 = (dSf45dPf45*dPf45dVm5+ dSf45dQf45*dQf45dVm5)*multiplier; diff --git a/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv b/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv index 2da4e29c..539bcfb4 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv +++ b/tests/unit/opflow/constraint_jacobian/inequality/cicj.csv @@ -1,7 +1,7 @@ 10,12,0 -1,6,200 +1,6,4.178 1,8,-1.5 -2,6,-200 +2,6,0.178 2,8,-1.5 3,1,7.68 3,2,9.6 @@ -26,11 +26,11 @@ 8,4,1.92 8,9,7.68 8,10,9.6 -9,9,15.36 -9,10,19.2 -9,11,-15.36 -9,12,3.84 -10,9,-15.36 -10,10,3.84 -10,11,15.36 -10,12,19.2 +9,9,7.68 +9,10,9.6 +9,11,-7.68 +9,12,1.92 +10,9,-7.68 +10,10,1.92 +10,11,7.68 +10,12,9.6 diff --git a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp index 172e38a0..bcbf4baa 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp @@ -90,7 +90,7 @@ int main(int argc, char **argv) { PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatView(J_ineq, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(MatAXPY(J_ineq, -1.0, J_ineq_ref, SAME_NONZERO_PATTERN)); + PetscCall(MatAXPY(J_ineq, -1.0, J_ineq_ref, UNKNOWN_NONZERO_PATTERN)); PetscReal norm = 0.0; PetscCall(MatNorm(J_ineq, NORM_INFINITY, &norm)); std::cout << "Error norm: " << norm << std::endl; From 0c7dd9a171a5419e7670a3be947de08856235a50 Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Thu, 23 Apr 2026 14:04:45 -0400 Subject: [PATCH 12/14] Update cecj script and values --- tests/unit/opflow/constraint_jacobian/equality/README.md | 4 ++-- tests/unit/opflow/constraint_jacobian/equality/Untitled.m | 5 +++-- tests/unit/opflow/constraint_jacobian/equality/cecj.csv | 4 ++-- .../opflow/constraint_jacobian/equality/jac_eq_acopf.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/unit/opflow/constraint_jacobian/equality/README.md b/tests/unit/opflow/constraint_jacobian/equality/README.md index 2bd2dbe8..1a7cd6f8 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/README.md +++ b/tests/unit/opflow/constraint_jacobian/equality/README.md @@ -132,10 +132,10 @@ With the parameters of the example network the matrix is: Q1 -1.6 -2.0 1.6 -0.4 0 0 0 0 0 0 0 0 -P2 -0.8 -0.8 0.8 2.8 0.8 -0.2 0 0 -0.8 -0.8 0 0 +P2 -0.8 -0.8 0.8 1.81 0.8 -0.2 0 0 -0.8 -0.8 0 0 -Q2 1.6 -0.4 -3.6 -3.8 0.4 0.4 0 0 1.6 -0.4 0 0 +Q2 1.6 -0.4 -3.6 -3.998 0.4 0.4 0 0 1.6 -0.4 0 0 P3 0 0 -0.8 0.2 0.8 1.8 -1 0 0 0 0 0 diff --git a/tests/unit/opflow/constraint_jacobian/equality/Untitled.m b/tests/unit/opflow/constraint_jacobian/equality/Untitled.m index 643f3bef..dc40f4f5 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/Untitled.m +++ b/tests/unit/opflow/constraint_jacobian/equality/Untitled.m @@ -11,6 +11,7 @@ theta4=deg2rad(0); theta5=deg2rad(0); +mvabase = 100; R=2; X=1; @@ -28,8 +29,8 @@ Pd=-3.4; Qd=8.8; -Gl=0.25; -Bl=-0.05; +Gl=0.25 / mvabase; +Bl=-0.05 / mvabase; theta12=theta1-theta2; diff --git a/tests/unit/opflow/constraint_jacobian/equality/cecj.csv b/tests/unit/opflow/constraint_jacobian/equality/cecj.csv index b6c4eb6d..a1591b6f 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/cecj.csv +++ b/tests/unit/opflow/constraint_jacobian/equality/cecj.csv @@ -10,7 +10,7 @@ 3,1,-0.8 3,2,-0.8 3,3,0.8 -3,4,2.8 +3,4,1.81 3,5,0.8 3,6,-0.2 3,9,-0.8 @@ -18,7 +18,7 @@ 4,1,1.6 4,2,-0.4 4,3,-3.6 -4,4,-3.8 +4,4,-3.998 4,5,0.4 4,6,0.4 4,9,1.6 diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index 7e1d1681..5fec55df 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -89,7 +89,7 @@ int main(int argc, char **argv) { PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatView(J_eq, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(MatAXPY(J_eq, -1.0, J_eq_ref, SAME_NONZERO_PATTERN)); + PetscCall(MatAXPY(J_eq, -1.0, J_eq_ref, UNKNOWN_NONZERO_PATTERN)); PetscReal norm = 0.0; PetscCall(MatNorm(J_eq, NORM_INFINITY, &norm)); std::cout << "Error norm: " << norm << std::endl; From 3061e6d6248ab2800d4762ce0266550142b0cf51 Mon Sep 17 00:00:00 2001 From: Philip Fackler Date: Mon, 27 Apr 2026 17:38:47 -0400 Subject: [PATCH 13/14] Remove unwanted test parameters --- .../equality/CMakeLists.txt | 14 -- .../constraint_jacobian/equality/cecj.cpp | 189 ------------------ .../equality/jac_eq_acopf.cpp | 8 +- .../inequality/CMakeLists.txt | 14 -- .../inequality/jac_ineq_acopf.cpp | 8 +- 5 files changed, 8 insertions(+), 225 deletions(-) delete mode 100644 tests/unit/opflow/constraint_jacobian/equality/cecj.cpp diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt index 52409dd8..8288f4ce 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -46,13 +46,6 @@ if(EXAGO_ENABLE_IPOPT) list(APPEND dependencies IPOPT) endif() -# Set up HIOP solver tests if enabled (deprecated) -if(EXAGO_ENABLE_HIOP) - list(APPEND solvers HIOP) - list(APPEND models POWER_BALANCE_HIOP) - list(APPEND dependencies HIOP) -endif() - # Set up HIOPSPARSE solver tests if enabled if(TARGET HiOp::SPARSE) list(APPEND solvers HIOPSPARSE) @@ -60,13 +53,6 @@ if(TARGET HiOp::SPARSE) list(APPEND dependencies HIOP_SPARSE) endif() -# Set up RAJA support tests if enabled (deprecated) -if(EXAGO_ENABLE_RAJA) - list(APPEND solvers HIOP) - list(APPEND models PBPOLRAJAHIOP) - list(APPEND dependencies HIOP) -endif() - if(EXAGO_RUN_TESTS) foreach( model diff --git a/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp b/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp deleted file mode 100644 index 3eefe636..00000000 --- a/tests/unit/opflow/constraint_jacobian/equality/cecj.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include "opflow_tests.h" -#include "test_acopf_utils.h" - -PetscErrorCode ConstructReferenceJacobian(Mat *J, int num_copies) { - PetscFunctionBeginUser; - std::vector i_base = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, - 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9}; - std::vector j_base = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, - 8, 9, 0, 1, 2, 3, 4, 5, 8, 9, 2, 3, 4, 5, - 6, 2, 3, 4, 5, 7, 2, 3, 8, 9, 10, 11, 2, 3, - 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11}; - std::vector v_base = { - 0.8, 0.8, -0.8, -0.8, -1.6, -2.0, 1.6, -0.4, -0.8, -0.8, 0.8, - 2.8, 0.8, -0.2, -0.8, -0.8, 1.6, -0.4, -3.6, -3.8, 0.4, 0.4, - 1.6, -0.4, -0.8, 0.2, 0.8, 1.8, -1.0, -0.4, -0.4, 0.4, -2.0, - -1.0, -0.8, -0.8, 1.6, 1.6, -0.8, -0.8, 1.6, -0.4, -3.2, -4.0, - 1.6, -0.4, -0.8, -0.8, 0.8, 0.8, 1.6, -0.4, -1.6, -2.0}; - - int nrows_base = 10; - int ncols_base = 12; - int nrows = (nrows_base - 2) * num_copies + 2; - int ncols = (ncols_base - 2) * num_copies + 2; - - std::vector i_coo = i_base; - std::vector j_coo = j_base; - std::vector v_coo = v_base; - - for (int n = 1; n < num_copies; ++n) { - auto row_start = n * (nrows_base - 2); - auto col_start = n * (ncols_base - 2); - for (int c = 0; c < v_base.size(); ++c) { - i_coo.push_back(row_start + i_base[c]); - j_coo.push_back(col_start + j_base[c]); - v_coo.push_back(v_base[c]); - } - } - - PetscCall(MatCreate(PETSC_COMM_WORLD, J)); - PetscCall(MatSetSizes(*J, nrows, ncols, PETSC_DECIDE, PETSC_DECIDE)); - PetscCall(MatSetType(*J, MATSEQAIJ)); - PetscCall( - MatSetPreallocationCOO(*J, v_coo.size(), i_coo.data(), j_coo.data())); - PetscCall(MatSetValuesCOO(*J, v_coo.data(), ADD_VALUES)); - PetscFunctionReturn(PETSC_SUCCESS); -} - -/** - * @brief Unit test driver for the "compute equality constraint jacobian" - * @see opflow/OpflowTests.hpp for kernel tested by this driver - */ -int main(int argc, char **argv) { - PetscErrorCode ierr; - PetscBool flg; - Vec X; - int fail = 0; - double obj_value; - char file_c_str[PETSC_MAX_PATH_LEN]; - char validation_c_str[PETSC_MAX_PATH_LEN]; - std::string file; - char appname[] = "opflow"; - MPI_Comm comm = MPI_COMM_WORLD; - int num_copies = 0; - - char help[] = "Unit tests for comparing GPU- and CPU-computed equality " - "constraint jacobians\n"; - - /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ - ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); - if (ierr) { - fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); - return ierr; - } - - /* Get network data file from command line */ - ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, - PETSC_MAX_PATH_LEN, &flg); - CHKERRQ(ierr); - - /* Get num_copies from command line */ - ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); - CHKERRQ(ierr); - - Mat J_eq_ref; - ConstructReferenceJacobian(&J_ref, num_copies); - - if (!flg) { - file = "CECJ_unittest1.m"; - } else { - file.assign(file_c_str); - } - - OPFLOW opflowtest; - exago::tests::TestOpflow test; - - /* Set up test opflow */ - ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); - CHKERRQ(ierr); - ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); - CHKERRQ(ierr); - ierr = OPFLOWSetUp(opflowtest); - CHKERRQ(ierr); - ierr = OPFLOWGetSolution(opflowtest, &X); - CHKERRQ(ierr); - - // If we are using HIOP, need to convert X - // The string lengths must be 65 - std::string modelname; - std::string solvername; - ierr = OPFLOWGetModel(opflowtest, &modelname); - ierr = OPFLOWGetSolver(opflowtest, &solvername); - - if (solvername == "HIOP") { -#if defined(EXAGO_ENABLE_HIOP) - double *x_ref; - ierr = VecGetArray(X, &x_ref); - - int nx, nconeq, nconineq; - ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); - CHKERRQ(ierr); - - // If we are running using the CPU model, nothing needs to be done - if (modelname == "POWER_BALANCE_HIOP") { - fail += test.computeConstraintJacobian(opflowtest, x_ref, J_eq_ref); - } else // Using model PBPOLRAJAHIOP - { -#if defined(EXAGO_ENABLE_RAJA) - // Get resource manager instance - auto &resmgr = umpire::ResourceManager::getInstance(); - - // Get Allocator - umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); - - // Register array xref with umpire - umpire::util::AllocationRecord record_x{ - x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; - resmgr.registerAllocation(x_ref, record_x); - // Allocate and copy xref to device - double *x_ref_dev; - -#ifdef EXAGO_ENABLE_GPU - - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); - CHKERRQ(ierr); - - umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); - x_ref_dev = - static_cast(d_allocator.allocate(nx * sizeof(double))); -#else - ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); - CHKERRQ(ierr); - x_ref_dev = x_ref; -#endif - resmgr.copy(x_ref_dev, x_ref); - - fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); - -#ifdef EXAGO_ENABLE_GPU - d_allocator.deallocate(x_ref_dev); -#endif -#endif - } - - ierr = VecRestoreArray(X, &x_ref); - CHKERRQ(ierr); - - ierr = PetscFree(x_ref); - CHKERRQ(ierr); -#endif // End #ifdefined(EXAGO_ENABLE_HIOP) - } else { - fail += test.computeObjective(opflowtest, X, obj_value); - } - ierr = OPFLOWDestroy(&opflowtest); - CHKERRQ(ierr); - - ExaGOFinalize(); - return fail; -} diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index 5fec55df..c3c2a8ab 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -84,10 +84,10 @@ int main(int argc, char **argv) { PetscCall(OPFLOWGetConstraintJacobian(opflowtest, &J_eq, &J_ineq)); PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); - PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); - PetscCall(MatView(J_eq_ref, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(MatView(J_eq, PETSC_VIEWER_STDOUT_SELF)); +// PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); +// PetscCall(MatView(J_eq_ref, PETSC_VIEWER_STDOUT_SELF)); +// PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); +// PetscCall(MatView(J_eq, PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatAXPY(J_eq, -1.0, J_eq_ref, UNKNOWN_NONZERO_PATTERN)); PetscReal norm = 0.0; diff --git a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt index dd75a8e3..63d9a252 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt +++ b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt @@ -46,13 +46,6 @@ if(EXAGO_ENABLE_IPOPT) list(APPEND dependencies IPOPT) endif() -# Set up HIOP solver tests if enabled (deprecated) -if(EXAGO_ENABLE_HIOP) - list(APPEND solvers HIOP) - list(APPEND models POWER_BALANCE_HIOP) - list(APPEND dependencies HIOP) -endif() - # Set up HIOPSPARSE solver tests if enabled if(TARGET HiOp::SPARSE) list(APPEND solvers HIOPSPARSE) @@ -60,13 +53,6 @@ if(TARGET HiOp::SPARSE) list(APPEND dependencies HIOP_SPARSE) endif() -# Set up RAJA support tests if enabled (deprecated) -if(EXAGO_ENABLE_RAJA) - list(APPEND solvers HIOP) - list(APPEND models PBPOLRAJAHIOP) - list(APPEND dependencies HIOP) -endif() - if(EXAGO_RUN_TESTS) foreach( model diff --git a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp index bcbf4baa..933c33de 100644 --- a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp @@ -85,10 +85,10 @@ int main(int argc, char **argv) { PetscCall(OPFLOWGetConstraintJacobian(opflowtest, &J_eq, &J_ineq)); PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); - PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); - PetscCall(MatView(J_ineq_ref, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); - PetscCall(MatView(J_ineq, PETSC_VIEWER_STDOUT_SELF)); + // PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); + // PetscCall(MatView(J_ineq_ref, PETSC_VIEWER_STDOUT_SELF)); + // PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); + // PetscCall(MatView(J_ineq, PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatAXPY(J_ineq, -1.0, J_ineq_ref, UNKNOWN_NONZERO_PATTERN)); PetscReal norm = 0.0; From abc871a293462da4846f25416695e2c60fb2eb71 Mon Sep 17 00:00:00 2001 From: PhilipFackler Date: Mon, 27 Apr 2026 21:56:16 +0000 Subject: [PATCH 14/14] Apply pre-commmit fixes --- .../opflow/constraint_jacobian/equality/jac_eq_acopf.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp index c3c2a8ab..c441fb4a 100644 --- a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -84,10 +84,11 @@ int main(int argc, char **argv) { PetscCall(OPFLOWGetConstraintJacobian(opflowtest, &J_eq, &J_ineq)); PetscCall(OPFLOWComputeConstraintJacobian(opflowtest, X, J_eq, J_ineq)); -// PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); -// PetscCall(MatView(J_eq_ref, PETSC_VIEWER_STDOUT_SELF)); -// PetscCall(VecView(X, PETSC_VIEWER_STDOUT_SELF)); -// PetscCall(MatView(J_eq, PETSC_VIEWER_STDOUT_SELF)); + // PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, + // PETSC_VIEWER_ASCII_DENSE); PetscCall(MatView(J_eq_ref, + // PETSC_VIEWER_STDOUT_SELF)); PetscCall(VecView(X, + // PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatView(J_eq, + // PETSC_VIEWER_STDOUT_SELF)); PetscCall(MatAXPY(J_eq, -1.0, J_eq_ref, UNKNOWN_NONZERO_PATTERN)); PetscReal norm = 0.0;