diff --git a/.gitignore b/.gitignore index d75b9abf4b..26cee02d54 100644 --- a/.gitignore +++ b/.gitignore @@ -97,7 +97,6 @@ CMakeCache.txt /cmake-build-debug /cmake_build /build -/cmake_build* # Static Headers include/bmi.hpp diff --git a/data/catchment_data_multilayer.geojson b/data/catchment_data_multilayer.geojson new file mode 100644 index 0000000000..aa79fc9eab --- /dev/null +++ b/data/catchment_data_multilayer.geojson @@ -0,0 +1,11 @@ +{ +"type": "FeatureCollection", +"name": "catchment_data", +"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, +"features": [ +{ "type": "Feature", "properties": { "layer": 20, "agg": 0, "areasqkm": 55.356841159445864, "id": "agg-1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -80.715617203572421, 35.162592318783524 ], [ -80.715461282861213, 35.163159749477792 ], [ -80.715345548657382, 35.164061070133094 ], [ -80.714744503892121, 35.165247080610385 ], [ -80.714185954379701, 35.166247633685273 ], [ -80.714122357235766, 35.166746278867357 ], [ -80.713350316345355, 35.16725203276151 ], [ -80.71127537436891, 35.167714484462437 ], [ -80.710280990889572, 35.168541154094569 ], [ -80.709413988957323, 35.169583974587987 ], [ -80.707284761222155, 35.170680219969363 ], [ -80.707112899301862, 35.171300479557914 ], [ -80.707044705715447, 35.171834735555464 ], [ -80.70675493882689, 35.172883152946092 ], [ -80.706629183206999, 35.173874595904771 ], [ -80.705609029659414, 35.175287826337588 ], [ -80.708048306543091, 35.175904322998562 ], [ -80.710733331192245, 35.177613967732675 ], [ -80.711601991486617, 35.17664136346712 ], [ -80.714003725354672, 35.176412687826499 ], [ -80.714872330568838, 35.175440058317818 ], [ -80.717380397112109, 35.174682063580804 ], [ -80.717761483257135, 35.174460362912669 ], [ -80.720783411888206, 35.177843384761864 ], [ -80.7220418909816, 35.178279670935723 ], [ -80.723309270567, 35.180346618536326 ], [ -80.726429052207365, 35.181569552573457 ], [ -80.727643443958669, 35.183901074949894 ], [ -80.729467909127507, 35.185643970383488 ], [ -80.729752611282052, 35.186831198746511 ], [ -80.734326891012756, 35.187490901526644 ], [ -80.735532469279477, 35.188191669911511 ], [ -80.737375635695301, 35.185716843366968 ], [ -80.745415345333683, 35.187582214420011 ], [ -80.746283678603476, 35.186609363664083 ], [ -80.749447726375919, 35.185936382627936 ], [ -80.749606985128651, 35.185142468888891 ], [ -80.749004152907474, 35.184792157314988 ], [ -80.750031659014738, 35.183025361586083 ], [ -80.752983237543475, 35.183410838319567 ], [ -80.755004039102047, 35.183403140756802 ], [ -80.756484640516632, 35.184411158747039 ], [ -80.757777003140788, 35.183892505924078 ], [ -80.758106114862386, 35.184860309047203 ], [ -80.760039015642377, 35.187718143175104 ], [ -80.760184131536008, 35.188568678926856 ], [ -80.760429719770585, 35.189126965684167 ], [ -80.760687733326364, 35.189886322485677 ], [ -80.760859465773336, 35.191915600499783 ], [ -80.761480202066721, 35.192951306184256 ], [ -80.763536432972458, 35.194564758423539 ], [ -80.763176765363241, 35.194810514904738 ], [ -80.762237232560082, 35.195273594843755 ], [ -80.761629460885786, 35.196023763836756 ], [ -80.761421404581398, 35.198097005125454 ], [ -80.760783392001628, 35.198747876895908 ], [ -80.760828463789935, 35.200582582893027 ], [ -80.760813049184506, 35.202207833455311 ], [ -80.758868451327814, 35.204612374528828 ], [ -80.756630018078724, 35.206280628476456 ], [ -80.756217195673699, 35.206790996741951 ], [ -80.755757803202826, 35.207259379067928 ], [ -80.756011318135052, 35.211030676986631 ], [ -80.757075093301935, 35.212584641881072 ], [ -80.757144693341289, 35.213011626897732 ], [ -80.755183284442552, 35.213610770690806 ], [ -80.754493447671365, 35.214990791544444 ], [ -80.754414400757312, 35.215778262563624 ], [ -80.754335791738299, 35.216039564457191 ], [ -80.75415787380723, 35.217817700729405 ], [ -80.752663318764888, 35.219341012746945 ], [ -80.752377209873472, 35.219993132870037 ], [ -80.752160936334079, 35.220075338497637 ], [ -80.751391745997637, 35.221495983024838 ], [ -80.750751757445471, 35.222063889179523 ], [ -80.750248059910206, 35.222776614733384 ], [ -80.750335007758807, 35.223916755586636 ], [ -80.748365545549277, 35.224671674399318 ], [ -80.747762622701273, 35.225526229186201 ], [ -80.746921216215043, 35.22627149585454 ], [ -80.746353229465527, 35.227514717016625 ], [ -80.746083800966304, 35.227861536767925 ], [ -80.745362205585366, 35.228350876648904 ], [ -80.742221738305361, 35.229905391509512 ], [ -80.740055047557362, 35.230776559201892 ], [ -80.739475109490016, 35.231489856207183 ], [ -80.738988846733236, 35.231986367731402 ], [ -80.73885642532781, 35.233299434937237 ], [ -80.738538784929588, 35.234344201947366 ], [ -80.738468966727638, 35.235045675089651 ], [ -80.738903765440597, 35.23601069695372 ], [ -80.738928988291363, 35.237431250572648 ], [ -80.737521588447748, 35.237731105659385 ], [ -80.737341611920343, 35.23785393929758 ], [ -80.7357381659873, 35.236445672049015 ], [ -80.734527232932351, 35.236225914023585 ], [ -80.733553485181204, 35.236501813090406 ], [ -80.731235739114581, 35.234196295956693 ], [ -80.73082530827314, 35.231825880977155 ], [ -80.729800441212291, 35.231021461207405 ], [ -80.727747656193046, 35.229662634107562 ], [ -80.726739363410942, 35.22865877863584 ], [ -80.725918547429828, 35.225099486721305 ], [ -80.725759267985282, 35.223181876804951 ], [ -80.725312437140957, 35.223102329786663 ], [ -80.723568809450484, 35.223780177318353 ], [ -80.722436100624961, 35.224100966261716 ], [ -80.721580664984515, 35.224116428593007 ], [ -80.720368130651096, 35.225710403614173 ], [ -80.71661457296068, 35.22556309402934 ], [ -80.714567781804305, 35.225119076636453 ], [ -80.714018939303273, 35.225505624890701 ], [ -80.713973943121886, 35.226108674827671 ], [ -80.713800701371596, 35.226631273885495 ], [ -80.712296684614401, 35.22734455318502 ], [ -80.7117634243845, 35.22772045915476 ], [ -80.709969534442791, 35.227718943651759 ], [ -80.70804917677394, 35.226841748151742 ], [ -80.707088422213644, 35.226058454963912 ], [ -80.704544996716479, 35.224356694426376 ], [ -80.701757770899164, 35.22347419863133 ], [ -80.700636187462777, 35.221871616191095 ], [ -80.699581038708075, 35.221336598966666 ], [ -80.697985145723464, 35.218615376113917 ], [ -80.697231461743826, 35.217941779556796 ], [ -80.697284750794637, 35.217677173368372 ], [ -80.69630054169086, 35.21754822827269 ], [ -80.695820254515084, 35.217360068422003 ], [ -80.693461844635948, 35.2154851723108 ], [ -80.692302201788394, 35.215666349721261 ], [ -80.691591669142809, 35.216203317853704 ], [ -80.690814758394893, 35.216195039824349 ], [ -80.687851280819743, 35.215377767288203 ], [ -80.687290712134001, 35.214544722719836 ], [ -80.686637481120698, 35.214535428612727 ], [ -80.686316895902252, 35.214455373765631 ], [ -80.685813148339761, 35.214448774651082 ], [ -80.685012637675953, 35.214243926235191 ], [ -80.684335616528571, 35.214235724360449 ], [ -80.68355141507601, 35.213975968847961 ], [ -80.683049388244186, 35.213751099888846 ], [ -80.681600210335759, 35.213633168044083 ], [ -80.678359155821596, 35.213046595496039 ], [ -80.676589829651576, 35.213733383852052 ], [ -80.674338461924535, 35.213051713706449 ], [ -80.673656947270601, 35.21105685968557 ], [ -80.670860922635995, 35.20826661621102 ], [ -80.670353172619798, 35.207627189590319 ], [ -80.670331945906625, 35.207172335621209 ], [ -80.669966580861143, 35.206218428623892 ], [ -80.670398783231931, 35.205731956199848 ], [ -80.670150016358861, 35.204736014644062 ], [ -80.670376412775084, 35.201096968464306 ], [ -80.669588509873691, 35.200581902044725 ], [ -80.669409481512716, 35.200154612563793 ], [ -80.669063563612809, 35.200667799621229 ], [ -80.667780253158313, 35.199845646126008 ], [ -80.66665237274367, 35.198331067379954 ], [ -80.665775195821482, 35.196851505538511 ], [ -80.664349073666799, 35.196320479356892 ], [ -80.662868677878507, 35.195092718365458 ], [ -80.659529655045475, 35.194526729556195 ], [ -80.658217857967415, 35.194354376662218 ], [ -80.658014975243532, 35.193183930808075 ], [ -80.657733282335087, 35.192533676555243 ], [ -80.657360385625964, 35.191436553653013 ], [ -80.655295952480145, 35.188752416542442 ], [ -80.654714893564176, 35.186511576426312 ], [ -80.653364076866993, 35.185451267336049 ], [ -80.652148669363214, 35.185232039757544 ], [ -80.65111375027567, 35.185146985728487 ], [ -80.650745281113998, 35.184680552444021 ], [ -80.650869501743443, 35.183022510885465 ], [ -80.649472722898849, 35.182282943651821 ], [ -80.648259549667642, 35.181219525542772 ], [ -80.647297554190828, 35.180708823564871 ], [ -80.647718894410048, 35.179665077605001 ], [ -80.648192714542077, 35.179544800117988 ], [ -80.648916253233793, 35.178736057342043 ], [ -80.650522876943654, 35.177941423427832 ], [ -80.652408304343737, 35.176665842342203 ], [ -80.653768094894374, 35.174996399956399 ], [ -80.654018436962502, 35.171801570477449 ], [ -80.65536902072084, 35.170920112215391 ], [ -80.657344609977258, 35.171801812484773 ], [ -80.658440688900825, 35.171568027556333 ], [ -80.660111410392503, 35.170845393763571 ], [ -80.661353020501465, 35.170034662562706 ], [ -80.663055117034091, 35.169443474681849 ], [ -80.664304847330158, 35.168408646118955 ], [ -80.665028843456525, 35.16661724679463 ], [ -80.666631770925207, 35.165410305421112 ], [ -80.66774481581551, 35.16360451651488 ], [ -80.670280731941318, 35.16186218617618 ], [ -80.670789451901243, 35.157839992873825 ], [ -80.671403501363372, 35.156566795449017 ], [ -80.671362745705224, 35.155882403363279 ], [ -80.672028591036863, 35.15552622095403 ], [ -80.675520144518003, 35.152757380625886 ], [ -80.675971621409431, 35.152513062430202 ], [ -80.677704159679521, 35.15279789769815 ], [ -80.678598618668644, 35.152885760275566 ], [ -80.679796348227953, 35.15213249951676 ], [ -80.680164651607356, 35.149704646657263 ], [ -80.680741062555271, 35.147416378098214 ], [ -80.680325128436493, 35.145528378084528 ], [ -80.681537307561939, 35.144507809125379 ], [ -80.6822942382977, 35.142510620403286 ], [ -80.682790377549793, 35.141769359916019 ], [ -80.683349608754597, 35.13980144127828 ], [ -80.683746426759285, 35.139501339404603 ], [ -80.684184715860496, 35.140157329172702 ], [ -80.684607250972675, 35.140238143464963 ], [ -80.685909182831892, 35.139855241453098 ], [ -80.687611257088477, 35.141294545095299 ], [ -80.687853477799521, 35.1421411675556 ], [ -80.688481312238181, 35.141985745920756 ], [ -80.689070154314336, 35.141541220109737 ], [ -80.690677542519722, 35.141558986176221 ], [ -80.692426706094125, 35.14223180168559 ], [ -80.69471509662614, 35.142769801002288 ], [ -80.695978622885221, 35.143255724931315 ], [ -80.698282555184178, 35.145834843394269 ], [ -80.704510130145138, 35.146651307868318 ], [ -80.704731473157352, 35.147223525592473 ], [ -80.705768005049649, 35.147087781044625 ], [ -80.710312276270145, 35.149584479982714 ], [ -80.712455873644743, 35.152309695861248 ], [ -80.712473179219856, 35.155571127789813 ], [ -80.713350239552838, 35.156229203669419 ], [ -80.712650071222185, 35.158038665114191 ], [ -80.713801797625308, 35.159004303746563 ], [ -80.713642222579907, 35.159798188918124 ], [ -80.716211705732931, 35.16040628617953 ], [ -80.716601465769671, 35.161815290821401 ], [ -80.715617203572421, 35.162592318783524 ] ], [ [ -80.669409481512716, 35.200154612563793 ], [ -80.670549670260229, 35.19846311766527 ], [ -80.669352444757394, 35.200018262975142 ], [ -80.669409481512716, 35.200154612563793 ] ], [ [ -80.724526012315437, 35.205501866863663 ], [ -80.72454198695246, 35.206036550908649 ], [ -80.725063842491295, 35.206698956395634 ], [ -80.724526012315437, 35.205501866863663 ] ] ] } }, +{"type": "Feature", "id": "cat-67", "properties": {"layer":0, "areasqkm": 14.756535022220804, "toid": "nex-68"}, "geometry": {"type": "MultiPolygon", "coordinates": [[[[-80.75777700314079, 35.18389250592408], [-80.75810611486239, 35.1848603090472], [-80.76003901564238, 35.187718143175104], [-80.76018413153601, 35.188568678926856], [-80.76042971977058, 35.18912696568417], [-80.76068773332636, 35.18988632248568], [-80.76085946577334, 35.19191560049978], [-80.76148020206672, 35.192951306184256], [-80.76353643297246, 35.19456475842354], [-80.76317676536324, 35.19481051490474], [-80.76223723256008, 35.195273594843755], [-80.76162946088579, 35.196023763836756], [-80.7614214045814, 35.198097005125454], [-80.76078339200163, 35.19874787689591], [-80.76082846378993, 35.20058258289303], [-80.7608130491845, 35.20220783345531], [-80.75886845132781, 35.20461237452883], [-80.75663001807872, 35.206280628476456], [-80.7562171956737, 35.20679099674195], [-80.75575780320283, 35.20725937906793], [-80.75601131813505, 35.21103067698663], [-80.75707509330194, 35.21258464188107], [-80.75714469334129, 35.21301162689773], [-80.75518328444255, 35.213610770690806], [-80.75449344767136, 35.214990791544444], [-80.75441440075731, 35.215778262563624], [-80.7543357917383, 35.21603956445719], [-80.75415787380723, 35.217817700729405], [-80.75266331876489, 35.219341012746945], [-80.75237720987347, 35.21999313287004], [-80.75216093633408, 35.22007533849764], [-80.75139174599764, 35.22149598302484], [-80.75075175744547, 35.22206388917952], [-80.7502480599102, 35.222776614733384], [-80.7503350077588, 35.223916755586636], [-80.74836554554928, 35.22467167439932], [-80.74776262270127, 35.2255262291862], [-80.74692121621504, 35.22627149585454], [-80.74635322946553, 35.227514717016625], [-80.7460838009663, 35.227861536767925], [-80.74536220558537, 35.2283508766489], [-80.74222173830536, 35.22990539150951], [-80.74005504755736, 35.23077655920189], [-80.73947510949002, 35.23148985620718], [-80.73898884673324, 35.2319863677314], [-80.73885642532781, 35.23329943493724], [-80.73853878492959, 35.234344201947366], [-80.73846896672764, 35.23504567508965], [-80.7389037654406, 35.23601069695372], [-80.73892898829136, 35.23743125057265], [-80.73752158844775, 35.237731105659385], [-80.73734161192034, 35.23785393929758], [-80.7357381659873, 35.236445672049015], [-80.73452723293235, 35.236225914023585], [-80.7335534851812, 35.236501813090406], [-80.73123573911458, 35.23419629595669], [-80.73082530827314, 35.231825880977155], [-80.72980044121229, 35.231021461207405], [-80.72774765619305, 35.22966263410756], [-80.72673936341094, 35.22865877863584], [-80.72591854742983, 35.225099486721305], [-80.72575926798528, 35.22318187680495], [-80.72531243714096, 35.22310232978666], [-80.72356880945048, 35.22378017731835], [-80.72243610062496, 35.224100966261716], [-80.72158066498451, 35.22411642859301], [-80.7211145060318, 35.22368642034355], [-80.72074273965856, 35.22250049897515], [-80.72046317440251, 35.221901770864974], [-80.7213088113704, 35.21935787562199], [-80.72072641034856, 35.21702218048747], [-80.72131472945011, 35.21539121856291], [-80.7216853788768, 35.21477765632368], [-80.72287605212085, 35.213564948465645], [-80.72316300997122, 35.20987463204784], [-80.72427529288194, 35.20708798049849], [-80.7250638424913, 35.206698956395634], [-80.72452601231544, 35.20550186686366], [-80.72618792000482, 35.204677572727775], [-80.72670524844105, 35.202979974795994], [-80.72629344934451, 35.20243818376059], [-80.72433323444952, 35.202050235437646], [-80.72326622164341, 35.201980669569856], [-80.72218392325884, 35.20094136323369], [-80.72203343642354, 35.19869411060445], [-80.72240476606557, 35.197473803873024], [-80.72258571719085, 35.19565796653196], [-80.72488120361596, 35.19452190066924], [-80.72547498310766, 35.19379116746099], [-80.72677829031477, 35.192591067694586], [-80.72685423974872, 35.19182216938071], [-80.72758443862824, 35.18999337824186], [-80.72856218290306, 35.18978600853656], [-80.72889692584329, 35.18868190918505], [-80.72893964298866, 35.188273788489035], [-80.72975261128205, 35.18683119874651], [-80.73432689101276, 35.187490901526644], [-80.73553246927948, 35.18819166991151], [-80.7373756356953, 35.18571684336697], [-80.74541534533368, 35.18758221442001], [-80.74628367860348, 35.18660936366408], [-80.74944772637592, 35.185936382627936], [-80.74960698512865, 35.18514246888889], [-80.74900415290747, 35.18479215731499], [-80.75003165901474, 35.18302536158608], [-80.75298323754348, 35.18341083831957], [-80.75500403910205, 35.1834031407568], [-80.75648464051663, 35.18441115874704], [-80.75777700314079, 35.18389250592408]]]]}}, +{"type": "Feature", "id": "cat-27", "properties": {"layer":0, "areasqkm": 18.92205293111518, "toid": "nex-26"}, "geometry": {"type": "MultiPolygon", "coordinates": [[[[-80.72946790912751, 35.18564397038349], [-80.72975261128205, 35.18683119874651], [-80.72893964298866, 35.188273788489035], [-80.72889692584329, 35.18868190918505], [-80.72856218290306, 35.18978600853656], [-80.72758443862824, 35.18999337824186], [-80.72685423974872, 35.19182216938071], [-80.72677829031477, 35.192591067694586], [-80.72547498310766, 35.19379116746099], [-80.72488120361596, 35.19452190066924], [-80.72258571719085, 35.19565796653196], [-80.72240476606557, 35.197473803873024], [-80.72203343642354, 35.19869411060445], [-80.72218392325884, 35.20094136323369], [-80.72326622164341, 35.201980669569856], [-80.72433323444952, 35.202050235437646], [-80.72629344934451, 35.20243818376059], [-80.72670524844105, 35.202979974795994], [-80.72618792000482, 35.204677572727775], [-80.72452601231544, 35.20550186686366], [-80.72454198695246, 35.20603655090865], [-80.7250638424913, 35.206698956395634], [-80.72427529288194, 35.20708798049849], [-80.72316300997122, 35.20987463204784], [-80.72287605212085, 35.213564948465645], [-80.7216853788768, 35.21477765632368], [-80.72131472945011, 35.21539121856291], [-80.72072641034856, 35.21702218048747], [-80.7213088113704, 35.21935787562199], [-80.72046317440251, 35.221901770864974], [-80.72074273965856, 35.22250049897515], [-80.7211145060318, 35.22368642034355], [-80.72158066498451, 35.22411642859301], [-80.7203681306511, 35.22571040361417], [-80.71661457296068, 35.22556309402934], [-80.7145677818043, 35.22511907663645], [-80.71401893930327, 35.2255056248907], [-80.71397394312189, 35.22610867482767], [-80.7138007013716, 35.226631273885495], [-80.7122966846144, 35.22734455318502], [-80.7117634243845, 35.22772045915476], [-80.70996953444279, 35.22771894365176], [-80.70804917677394, 35.22684174815174], [-80.70708842221364, 35.22605845496391], [-80.70454499671648, 35.224356694426376], [-80.70175777089916, 35.22347419863133], [-80.70063618746278, 35.221871616191095], [-80.69958103870808, 35.221336598966666], [-80.69798514572346, 35.21861537611392], [-80.69723146174383, 35.217941779556796], [-80.69728475079464, 35.21767717336837], [-80.69630054169086, 35.21754822827269], [-80.69582025451508, 35.217360068422], [-80.69346184463595, 35.2154851723108], [-80.6923022017884, 35.21566634972126], [-80.69159166914281, 35.216203317853704], [-80.6908147583949, 35.21619503982435], [-80.68785128081974, 35.2153777672882], [-80.687290712134, 35.214544722719836], [-80.6866374811207, 35.21453542861273], [-80.68631689590225, 35.21445537376563], [-80.68581314833976, 35.21444877465108], [-80.68501263767595, 35.21424392623519], [-80.68433561652857, 35.21423572436045], [-80.68355141507601, 35.21397596884796], [-80.68304938824419, 35.213751099888846], [-80.68160021033576, 35.21363316804408], [-80.6783591558216, 35.21304659549604], [-80.67658982965158, 35.21373338385205], [-80.67433846192453, 35.21305171370645], [-80.6736569472706, 35.21105685968557], [-80.670860922636, 35.20826661621102], [-80.6703531726198, 35.20762718959032], [-80.67033194590663, 35.20717233562121], [-80.66996658086114, 35.20621842862389], [-80.67039878323193, 35.20573195619985], [-80.67059801573924, 35.205630756749926], [-80.67177841457134, 35.20468238425277], [-80.6733743199286, 35.203550733229946], [-80.67491306083075, 35.20215505078978], [-80.67584839975643, 35.200321356086974], [-80.67668461451515, 35.199448493163665], [-80.6779958755478, 35.19899677473522], [-80.67913768850855, 35.198552385941596], [-80.68004537279869, 35.197075969681634], [-80.68077081420435, 35.19602106539493], [-80.68267822918273, 35.1958086635977], [-80.68367115794709, 35.19552728426538], [-80.68580151457986, 35.193595583815984], [-80.6865724667587, 35.191413753581685], [-80.68707742553893, 35.19068208024061], [-80.68812780481943, 35.187883240048215], [-80.68782934599146, 35.18658357352836], [-80.69020942609288, 35.183488027737866], [-80.69087998324167, 35.18182957307456], [-80.69252329406433, 35.18098219212587], [-80.69549287463391, 35.18064997395927], [-80.69894390178752, 35.179101565176026], [-80.70010304020761, 35.17770659010988], [-80.70173223150607, 35.17654733040429], [-80.70258699815237, 35.176703701678896], [-80.70560902965941, 35.17528782633759], [-80.70804830654309, 35.17590432299856], [-80.71073333119224, 35.177613967732675], [-80.71160199148662, 35.17664136346712], [-80.71400372535467, 35.1764126878265], [-80.71487233056884, 35.17544005831782], [-80.71738039711211, 35.1746820635808], [-80.71776148325714, 35.17446036291267], [-80.7207834118882, 35.177843384761864], [-80.7220418909816, 35.17827967093572], [-80.723309270567, 35.180346618536326], [-80.72642905220737, 35.18156955257346], [-80.72764344395867, 35.183901074949894], [-80.72946790912751, 35.18564397038349]]]]}}, +{"type": "Feature", "id": "cat-52", "properties": {"layer":0, "areasqkm": 21.67825320610988, "toid": "nex-34"}, "geometry": {"type": "MultiPolygon", "coordinates": [[[[-80.71561720357242, 35.162592318783524], [-80.71546128286121, 35.16315974947779], [-80.71534554865738, 35.164061070133094], [-80.71474450389212, 35.165247080610385], [-80.7141859543797, 35.16624763368527], [-80.71412235723577, 35.16674627886736], [-80.71335031634536, 35.16725203276151], [-80.71127537436891, 35.16771448446244], [-80.71028099088957, 35.16854115409457], [-80.70941398895732, 35.16958397458799], [-80.70728476122216, 35.17068021996936], [-80.70711289930186, 35.171300479557914], [-80.70704470571545, 35.171834735555464], [-80.70675493882689, 35.17288315294609], [-80.706629183207, 35.17387459590477], [-80.70560902965941, 35.17528782633759], [-80.70258699815237, 35.176703701678896], [-80.70173223150607, 35.17654733040429], [-80.70010304020761, 35.17770659010988], [-80.69894390178752, 35.179101565176026], [-80.69549287463391, 35.18064997395927], [-80.69252329406433, 35.18098219212587], [-80.69087998324167, 35.18182957307456], [-80.69020942609288, 35.183488027737866], [-80.68782934599146, 35.18658357352836], [-80.68812780481943, 35.187883240048215], [-80.68707742553893, 35.19068208024061], [-80.6865724667587, 35.191413753581685], [-80.68580151457986, 35.193595583815984], [-80.68367115794709, 35.19552728426538], [-80.68267822918273, 35.1958086635977], [-80.68077081420435, 35.19602106539493], [-80.68004537279869, 35.197075969681634], [-80.67913768850855, 35.198552385941596], [-80.6779958755478, 35.19899677473522], [-80.67668461451515, 35.199448493163665], [-80.67584839975643, 35.200321356086974], [-80.67491306083075, 35.20215505078978], [-80.6733743199286, 35.203550733229946], [-80.67177841457134, 35.20468238425277], [-80.67059801573924, 35.205630756749926], [-80.67039878323193, 35.20573195619985], [-80.67015001635886, 35.20473601464406], [-80.67037641277508, 35.201096968464306], [-80.66958850987369, 35.200581902044725], [-80.66940948151272, 35.20015461256379], [-80.66906356361281, 35.20066779962123], [-80.66778025315831, 35.19984564612601], [-80.66665237274367, 35.198331067379954], [-80.66577519582148, 35.19685150553851], [-80.6643490736668, 35.19632047935689], [-80.6628686778785, 35.19509271836546], [-80.65952965504547, 35.194526729556195], [-80.65821785796741, 35.19435437666222], [-80.65801497524353, 35.193183930808075], [-80.65773328233509, 35.19253367655524], [-80.65736038562596, 35.19143655365301], [-80.65529595248015, 35.18875241654244], [-80.65471489356418, 35.18651157642631], [-80.65336407686699, 35.18545126733605], [-80.65214866936321, 35.185232039757544], [-80.65111375027567, 35.18514698572849], [-80.650745281114, 35.18468055244402], [-80.65086950174344, 35.183022510885465], [-80.64947272289885, 35.18228294365182], [-80.64825954966764, 35.18121952554277], [-80.64729755419083, 35.18070882356487], [-80.64771889441005, 35.179665077605], [-80.64819271454208, 35.17954480011799], [-80.64891625323379, 35.17873605734204], [-80.65052287694365, 35.17794142342783], [-80.65240830434374, 35.1766658423422], [-80.65376809489437, 35.1749963999564], [-80.6540184369625, 35.17180157047745], [-80.65536902072084, 35.17092011221539], [-80.65734460997726, 35.17180181248477], [-80.65844068890082, 35.17156802755633], [-80.6601114103925, 35.17084539376357], [-80.66135302050147, 35.170034662562706], [-80.66305511703409, 35.16944347468185], [-80.66430484733016, 35.168408646118955], [-80.66502884345653, 35.16661724679463], [-80.6666317709252, 35.16541030542111], [-80.66774481581551, 35.16360451651488], [-80.67028073194132, 35.16186218617618], [-80.67078945190124, 35.157839992873825], [-80.67140350136337, 35.15656679544902], [-80.67136274570522, 35.15588240336328], [-80.67202859103686, 35.15552622095403], [-80.675520144518, 35.152757380625886], [-80.67597162140943, 35.1525130624302], [-80.67770415967952, 35.15279789769815], [-80.67859861866864, 35.152885760275566], [-80.67979634822795, 35.15213249951676], [-80.68016465160736, 35.14970464665726], [-80.68074106255527, 35.147416378098214], [-80.6803251284365, 35.14552837808453], [-80.68153730756194, 35.14450780912538], [-80.6822942382977, 35.142510620403286], [-80.6827903775498, 35.14176935991602], [-80.6833496087546, 35.13980144127828], [-80.68374642675928, 35.1395013394046], [-80.6841847158605, 35.1401573291727], [-80.68460725097268, 35.14023814346496], [-80.68590918283189, 35.1398552414531], [-80.68761125708848, 35.1412945450953], [-80.68785347779952, 35.1421411675556], [-80.68848131223818, 35.141985745920756], [-80.68907015431434, 35.14154122010974], [-80.69067754251972, 35.14155898617622], [-80.69242670609412, 35.14223180168559], [-80.69471509662614, 35.14276980100229], [-80.69597862288522, 35.143255724931315], [-80.69828255518418, 35.14583484339427], [-80.70451013014514, 35.14665130786832], [-80.70473147315735, 35.14722352559247], [-80.70576800504965, 35.147087781044625], [-80.71031227627014, 35.149584479982714], [-80.71245587364474, 35.15230969586125], [-80.71247317921986, 35.15557112778981], [-80.71335023955284, 35.15622920366942], [-80.71265007122219, 35.15803866511419], [-80.71380179762531, 35.15900430374656], [-80.7136422225799, 35.159798188918124], [-80.71621170573293, 35.16040628617953], [-80.71660146576967, 35.1618152908214], [-80.71561720357242, 35.162592318783524]], [[-80.66940948151272, 35.20015461256379], [-80.67054967026023, 35.19846311766527], [-80.6693524447574, 35.20001826297514], [-80.66940948151272, 35.20015461256379]]]]}} +] +} diff --git a/data/example_multilevel_realization_config.json b/data/example_multilevel_realization_config.json new file mode 100644 index 0000000000..a0916354f1 --- /dev/null +++ b/data/example_multilevel_realization_config.json @@ -0,0 +1,196 @@ +{ + "global": { + "formulations": [ + { + "name": "tshirt_c", + "params": { + "maxsmc": 0.439, + "wltsmc": 0.066, + "satdk": 0.00000338, + "satpsi": 0.355, + "slope": 1.0, + "scaled_distribution_fn_shape_parameter": 4.05, + "multiplier": 0.0, + "alpha_fc": 0.33, + "Klf": 0.01, + "Kn": 0.03, + "nash_n": 2, + "Cgw": 0.01, + "expon": 6.0, + "max_groundwater_storage_meters": 1.0, + "nash_storage": [ + 0.0, + 0.0 + ], + "soil_storage_percentage": 0.667, + "groundwater_storage_percentage": 0.5, + "timestep": 3600, + "giuh": { + "giuh_path": "./test/data/giuh/GIUH.json", + "crosswalk_path": "./data/crosswalk.json" + } + } + } + ], + "forcing": { + "file_pattern": ".*{{id}}.*.csv", + "path": "./data/forcing/" + } + }, + "time": { + "start_time": "2015-12-01 00:00:00", + "end_time": "2015-12-30 23:00:00", + "output_interval": 3600 + }, + "catchments": { + "cat-27": { + "formulations": [ + { + "name":"tshirt_c", + "params": { + "maxsmc": 0.439, + "wltsmc": 0.066, + "satdk": 0.00000338, + "satpsi": 0.355, + "slope": 1.0, + "scaled_distribution_fn_shape_parameter": 4.05, + "multiplier": 0.0, + "alpha_fc": 0.33, + "Klf": 0.01, + "Kn": 0.03, + "nash_n": 2, + "Cgw": 0.01, + "expon": 6.0, + "max_groundwater_storage_meters": 1.0, + "nash_storage": [ + 0.0, + 0.0 + ], + "soil_storage_percentage": 0.667, + "groundwater_storage_percentage": 0.5, + "timestep": 3600, + "giuh": { + "giuh_path": "./test/data/giuh/GIUH.json", + "crosswalk_path": "./data/crosswalk.json", + "cdf_ordinates": [ + 0.1, + 0.35, + 0.2, + 0.14, + 0.1, + 0.06, + 0.05 + ] + } + } + } + ], + "forcing": { + "path": "./data/forcing/cat-27_2015-12-01 00_00_00_2015-12-30 23_00_00.csv" + } + }, + "cat-52": { + "formulations": [ + { + "name": "simple_lumped", + "params": { + "sr": [ + 1.0, + 1.0, + 1.0 + ], + "storage": 1.0, + "gw_storage": 1.0, + "gw_max_storage": 10.0, + "nash_max_storage": 2.0, + "smax": 5, + "a": 1.0, + "b": 10.0, + "Ks": 0.1, + "Kq": 0.01, + "n": 3, + "t": 0 + } + } + ], + "forcing": { + "path": "./data/forcing/cat-52_2015-12-01 00_00_00_2015-12-30 23_00_00.csv" + } + }, + "cat-67": { + "formulations": [ + { + "name":"tshirt_c", + "params": { + "maxsmc": 0.439, + "wltsmc": 0.066, + "satdk": 0.00000338, + "satpsi": 0.355, + "slope": 1.0, + "scaled_distribution_fn_shape_parameter": 4.05, + "multiplier": 0.0, + "alpha_fc": 0.33, + "Klf": 0.01, + "Kn": 0.03, + "nash_n": 2, + "Cgw": 0.01, + "expon": 6.0, + "max_groundwater_storage_meters": 1.0, + "nash_storage": [ + 0.0, + 0.0 + ], + "soil_storage_percentage": 0.667, + "groundwater_storage_percentage": 0.5, + "timestep": 3600, + "giuh": { + "giuh_path": "./test/data/giuh/GIUH.json", + "crosswalk_path": "./data/crosswalk.json", + "cdf_ordinates": [ + 0.1, + 0.35, + 0.2, + 0.14, + 0.1, + 0.06, + 0.05 + ] + } + } + } + ], + "forcing": { + "path": "./data/forcing/cat-67_2015-12-01 00_00_00_2015-12-30 23_00_00.csv" + } + }, + "agg-1": { + "formulations": [ + { + "name": "bmi_fortran", + "params": { + "model_type_name": "bmi_fortran_noahowp", + "library_file": "./extern/noah-owp-modular/cmake_build/libsurfacebmi.so", + "forcing_file": "", + "init_config": "./data/bmi/fortran/noah-owp-modular-init-agg-1.namelist.input", + "allow_exceed_end_time": true, + "main_output_variable": "QINSUR", + "variables_names_map": { + "PRCPNONC": "atmosphere_water__liquid_equivalent_precipitation_rate", + "Q2": "atmosphere_air_water~vapor__relative_saturation", + "SFCTMP": "land_surface_air__temperature", + "UU": "land_surface_wind__x_component_of_velocity", + "VV": "land_surface_wind__y_component_of_velocity", + "LWDN": "land_surface_radiation~incoming~longwave__energy_flux", + "SOLDN": "land_surface_radiation~incoming~shortwave__energy_flux", + "SFCPRS": "land_surface_air__pressure" + }, + "uses_forcing_file": false + } + } + ], + "forcing": { + "path": "./data/forcing/agg-1_2015-12-01 00_00_00_2015-12-30 23_00_00.csv" + } + } + } +} diff --git a/include/core/HY_Features.hpp b/include/core/HY_Features.hpp index 0f4d5b2c00..19961f4712 100644 --- a/include/core/HY_Features.hpp +++ b/include/core/HY_Features.hpp @@ -2,6 +2,7 @@ #define HY_FEATURES_H #include +#include #include #include @@ -65,18 +66,7 @@ namespace hy_features { * @param network * @param formulations */ - HY_Features( network::Network network, std::shared_ptr formulations); - /** - * @brief Construct a new HY_Features object From a GeoJSON feature collection and a set of formulations. - * - * Constructs the network::Network index from the GeoJSON feature collection and link_key and then - * \copydetails HY_Features::HY_Features(network::Network,std::shared_ptr) - * - * @param catchments - * @param link_key - * @param formulations - */ HY_Features( geojson::GeoJSON catchments, std::string* link_key, std::shared_ptr formulations); /** @@ -116,6 +106,21 @@ namespace hy_features { */ inline auto catchments(){return network.filter("cat");} + /** + * @brief An iterator of only the catchment feature ids from only the specified layer + * + * @return auto + */ + inline auto catchments(long lv) { + return network.filter("cat",lv); + } + + /** + * @brief Return a set of levels that contain a catchment + */ + + inline const auto& levels() { return hf_levels; } + /** * @brief An iterator of only the nexus feature ids * @@ -180,6 +185,8 @@ namespace hy_features { private: + void init(); + /** * @brief Internal mapping of catchment id -> HY_Catchment pointer. * @@ -204,6 +211,13 @@ namespace hy_features { */ std::shared_ptr formulations; + /** + * @brief The set of levels that contain at least one catchment + */ + std::set hf_levels; + + geojson::GeoJSON fabric; + }; } diff --git a/include/core/HY_Features_MPI.hpp b/include/core/HY_Features_MPI.hpp index cd92e5584a..af63ead7e9 100644 --- a/include/core/HY_Features_MPI.hpp +++ b/include/core/HY_Features_MPI.hpp @@ -4,6 +4,7 @@ #ifdef NGEN_MPI_ACTIVE #include +#include #include #include @@ -32,6 +33,16 @@ namespace hy_features { inline bool is_remote_sender_nexus(const std::string& id) { return _nexuses.find(id) != _nexuses.end() && _nexuses[id]->is_remote_sender(); } + + inline auto catchments(long lv) { + return network.filter("cat",lv); + } + + /** + * @brief Return a set of levels that contain a catchment + */ + + inline const auto& levels() { return hf_levels; } inline std::vector> destination_nexuses(const std::string& id) { std::vector> downstream; @@ -77,6 +88,7 @@ namespace hy_features { std::unordered_map> _nexuses; network::Network network; std::shared_ptr formulations; + std::set hf_levels; int mpi_rank; int mpi_num_procs; diff --git a/include/core/Layer.hpp b/include/core/Layer.hpp new file mode 100644 index 0000000000..c68224160f --- /dev/null +++ b/include/core/Layer.hpp @@ -0,0 +1,147 @@ +#ifndef __NGEN_LAYER__ +#define __NGEN_LAYER__ + +#include "LayerData.hpp" +#include "Simulation_Time.hpp" + +#ifdef NGEN_MPI_ACTIVE +#include "HY_Features_MPI.hpp" +#else +#include "HY_Features.hpp" +#endif + +#include "Pdm03.h" + +namespace ngen +{ + + class Layer + { + public: + + #ifdef NGEN_MPI_ACTIVE + typedef hy_features::HY_Features_MPI feature_type; + #else + typedef hy_features::HY_Features feature_type; + #endif + + Layer( + const LayerDescription& desc, + const std::vector& p_u, + const Simulation_Time& s_t, + feature_type& f, + geojson::GeoJSON cd, + std::shared_ptr pdmd, + long idx) : + description(desc), + processing_units(p_u), + simulation_time(s_t), + features(f), + catchment_data(cd), + pdm_et_data(pdmd), + output_time_index(idx) + { + + } + + virtual ~Layer() {} + + /*** + * @brief Return the next timestep that will be processed by this layer in epoc time units + */ + time_t next_timestep_epoch_time() { return simulation_time.next_timestep_epoch_time(); } + + + /*** + * @brief Return the last timesteo that was processed by this layer in epoc time units + */ + time_t current_timestep_epoch_time() { return simulation_time.get_current_epoc_time(); } + + + /*** + * @brief Return the numeric id of this layer + */ + int get_id() const { return this->description.id; } + + /*** + * @brief Return the name of this layer + */ + const std::string& get_name() const { return this->description.name; } + + /*** + * @brief Return this time_step interval used for this layer + */ + const double get_time_step() const { return this->description.time_step; } + + /*** + * @brief Return the units for the time_step value of this layer + */ + const std::string& get_time_step_units() const { return this->description.time_step_units; } + + /*** + * @breif Run one simulation timestep for each model in this layer + */ + virtual void update_models() + { + auto idx = simulation_time.next_timestep_index(); + auto step = simulation_time.get_output_interval_seconds(); + + //std::cout<<"Output Time Index: "<(r); + r_c->set_et_params(pdm_et_data); + double response = r_c->get_response(output_time_index, description.time_step); + std::string output = std::to_string(output_time_index)+","+current_timestamp+","+ + r_c->get_output_line_for_timestep(output_time_index)+"\n"; + r_c->write_output(output); + //TODO put this somewhere else. For now, just trying to ensure we get m^3/s into nexus output + try{ + response *= (catchment_data->get_feature(id)->get_property("areasqkm").as_real_number() * 1000000); + }catch(std::invalid_argument &e) + { + response *= (catchment_data->get_feature(id)->get_property("area_sqkm").as_real_number() * 1000000); + } + //TODO put this somewhere else as well, for now, an implicit assumption is that a modules get_response returns + //m/timestep + //since we are operating on a 1 hour (3600s) dt, we need to scale the output appropriately + //so no response is m^2/hr...m^2/hr * 1hr/3600s = m^3/hr + response /= 3600.0; + //update the nexus with this flow + for(auto& nexus : features.destination_nexuses(id)) { + //TODO in a DENDRIDIC network, only one destination nexus per catchment + //If there is more than one, some form of catchment partitioning will be required. + //for now, only contribute to the first one in the list + nexus->add_upstream_flow(response, id, output_time_index); + std::cerr << "Add water to nexus ID = " << nexus->get_id() << " from catchment ID = " << id << " value = " + << response << ", ID = " << id << ", time-index = " << output_time_index << std::endl; + break; + } + + } //done catchments + + ++output_time_index; + simulation_time.advance_timestep(); + } + + + protected: + + LayerDescription description; + std::vector processing_units; + Simulation_Time simulation_time; + feature_type& features; + geojson::GeoJSON catchment_data; + std::shared_ptr pdm_et_data; + long output_time_index; + + }; +} + +#endif \ No newline at end of file diff --git a/include/core/LayerData.hpp b/include/core/LayerData.hpp new file mode 100644 index 0000000000..4184b69916 --- /dev/null +++ b/include/core/LayerData.hpp @@ -0,0 +1,59 @@ +#ifndef __NGEN_LAYER_DATA__ +#define __NGEN_LAYER_DATA__ + +#include +#include +#include + +namespace ngen +{ + /** + * @brief A simple structure to hold meta data realated to a computational layer + */ + + struct LayerDescription + { + std::string name; //> The name of the computational layer + std::string time_step_units; //> The time units that time_step is expressed in + int id; //> The layer id which determins the order that this layer will be processed in + double time_step; //> The time step that will be used for models in this layer + }; + + /** + * @brief A class to hold a manage layer metadata for the system + */ + + class LayerDataStorage + { + public: + + LayerDataStorage() {} + + ~LayerDataStorage() {} + + const LayerDescription& get_layer(int id) const + { + return stored_layers.at(id); + } + + void put_layer(const LayerDescription& desc, int id) + { + stored_layers[id] = desc; + keys.push_back(id); + } + + bool exists(int id) + { + return stored_layers.find(id) != stored_layers.end(); + } + + std::vector& get_keys() { return keys; } + + private: + + std::unordered_map stored_layers; + std::vector keys; + }; +} + +#endif \ No newline at end of file diff --git a/include/core/Partition_Parser.hpp b/include/core/Partition_Parser.hpp index 541147d97c..9c0e740bfb 100644 --- a/include/core/Partition_Parser.hpp +++ b/include/core/Partition_Parser.hpp @@ -93,29 +93,37 @@ class Partitions_Parser { } part_data.nexus_ids = nexus_ids; nexus_ids.clear(); - if( part.at("remote-connections").get_type() == geojson::PropertyType::List ) { + + if( part.at("remote-connections").get_type() == geojson::PropertyType::List ) + { //It is valid to have no remote connections, but the backend property tree parser - //can't represent empty lists/objects, so it turns into an ampty string (which is iterable) + //can't represent empty lists/objects, so it turns into an empty string (which is iterable) //so we check to ensure the remote connections are a list type (not string) before we attempt //to process the remote-connections. If they are empty, this step gets skipped entirely. //Get remote-connections and set the corresponding part_data struct member + for (auto &remote_conn : part.at("remote-connections").as_list()) { - remote_mpi_rank = remote_conn.at("mpi-rank").as_natural_number(); - remote_nex_id = remote_conn.at("nex-id").as_string(); - remote_cat_id = remote_conn.at("cat-id").as_string(); - direction = remote_conn.at("cat-direction").as_string(); - tmp_tuple = std::make_tuple(remote_mpi_rank, remote_nex_id, remote_cat_id, direction); - remote_conn_vec.push_back(tmp_tuple); + if ( remote_conn.get_type() != geojson::PropertyType::String ) + { + remote_mpi_rank = remote_conn.at("mpi-rank").as_natural_number(); + remote_nex_id = remote_conn.at("nex-id").as_string(); + remote_cat_id = remote_conn.at("cat-id").as_string(); + direction = remote_conn.at("cat-direction").as_string(); + tmp_tuple = std::make_tuple(remote_mpi_rank, remote_nex_id, remote_cat_id, direction); + remote_conn_vec.push_back(tmp_tuple); + } } } + part_data.remote_connections = remote_conn_vec; remote_conn_vec.clear(); //Push part_data struct the vector partition_ranks.push_back(part_data); - part_counter++; + part_counter++; + } }; @@ -158,7 +166,7 @@ class Partitions_Parser { */ return part_data; - }; + } //This example function shows how to get a specific member of the struct int get_mpi_rank(int part_id) @@ -170,7 +178,7 @@ class Partitions_Parser { std::cout << "mpi_world_rank: " << mpi_world_rank << std::endl; return mpi_world_rank; - }; + } // partition_ranks is a vector of struct: PartitionData std::vector partition_ranks; diff --git a/include/core/SurfaceLayer.hpp b/include/core/SurfaceLayer.hpp new file mode 100644 index 0000000000..a17cf8a1eb --- /dev/null +++ b/include/core/SurfaceLayer.hpp @@ -0,0 +1,87 @@ +#ifndef __NGEN_SURFACE_LAYER__ +#define __NGEN_SURFACE_LAYER__ + +#include "Layer.hpp" + +namespace ngen +{ + class SurfaceLayer : public Layer + { + public: + + SurfaceLayer( + const LayerDescription& desc, + const std::vector& p_u, + const Simulation_Time& s_t, + feature_type& f, + geojson::GeoJSON cd, + std::shared_ptr pdmd, + long idx, + const std::vector& n_u, + std::unordered_map& output_files) : + Layer(desc,p_u,s_t,f,cd,pdmd,idx), + nexus_ids(n_u), + nexus_outfiles(output_files) + { + + } + + /*** + * @breif Run one simulation timestep for each model in this layer + */ + virtual void update_models() + { + long current_time_index = output_time_index; + + Layer::update_models(); + + //At this point, could make an internal routing pass, extracting flows from nexuses and routing + //across the flowpath to the next nexus. + //Once everything is updated for this timestep, dump the nexus output + for(const auto& id : features.nexuses()) + { + std::string current_timestamp = simulation_time.get_timestamp(current_time_index); + + #ifdef NGEN_MPI_ACTIVE + if (!features.is_remote_sender_nexus(id)) { //Ensures only one side of the dual sided remote nexus actually doing this... + #endif + + //Get the correct "requesting" id for downstream_flow + const auto& nexus = features.nexus_at(id); + const auto& cat_ids = nexus->get_receiving_catchments(); + std::string cat_id; + if( cat_ids.size() > 0 ) { + //Assumes dendridic, e.g. only a single downstream...it will consume 100% of the available flow + cat_id = cat_ids[0]; + } + else { + //This is a terminal node, SHOULDN'T be remote, so ID shouldn't matter too much + cat_id = "terminal"; + } + + std::cerr << "Requesting water from nexus, id = " << id << " at time = " < nexus_ids; + std::unordered_map& nexus_outfiles; + }; +} + +#endif \ No newline at end of file diff --git a/include/core/catchment/HY_Catchment.hpp b/include/core/catchment/HY_Catchment.hpp index d31660dba9..d8649c87a6 100644 --- a/include/core/catchment/HY_Catchment.hpp +++ b/include/core/catchment/HY_Catchment.hpp @@ -21,7 +21,7 @@ class HY_Catchment : public HY_HydroFeature public: HY_Catchment(); - HY_Catchment(std::string id, Nexuses inflows, Nexuses outflows, std::shared_ptr realization): + HY_Catchment(std::string id, Nexuses inflows, Nexuses outflows, std::shared_ptr realization, long lv = 0): id(std::move(id)), inflows(std::move(inflows)), outflows(std::move(outflows)), @@ -30,10 +30,40 @@ class HY_Catchment : public HY_HydroFeature conjoint_catchment({}), upper_catchment({}), lower_catchment({}), - realization(realization){} + realization(realization), + level(lv){} virtual ~HY_Catchment(); const Nexuses& get_outflow_nexuses(){ return outflows; } std::shared_ptr realization; + + /*! \brief get the hydrofabric level of this catchment + * + * The hydrofabric is divided into multiple level which are intended to be processed in decreasing numeric order. + * The current defined levels are: + * 80 -- Atmospheric Models (high) + * 60 -- Atmospeheric Models (low) + * 40 -- Canopy Models + * 20 -- Snow melt models + * 0 -- Surface water processes + * -20 -- Ground Water (Shallow) + * -40 -- Ground Water (Deep) + */ + long get_level() { return level; } + + /*! \brief set the level of this catchment + * + * This function changes the level of a catchment. It should only be used if the type of model being used in the catchment changes. + */ + void set_level(long lv) { level = lv; } + + const long ATMOSPHERIC_LEVEL_HIGH = 80; //!< This is the catchment level for high air atmospheric models + const long ATMOSPHERIC_LEVEL_LOW = 60; //!< This is the catchment level for low air atmospheric models + const long CANOPY_LEVEL = 40; //!< This is the catchment level for canopy level models + const long SNOW_LEVEL = 20; //!< This is the catchment level for surface snow models + const long SURFACE_LEVEL = 0; //!< This is the catchment level for surface water models + const long GROUND_WATER_SHALLOW_LEVEL = -20; //!< This is the catchment level for shallow groundwater models + const long GROUND_WATER_DEEP_LEVEL = -40; //!< This is the catchment level for deep groundwater models + protected: private: @@ -47,6 +77,8 @@ class HY_Catchment : public HY_HydroFeature Catchment upper_catchment; Catchment lower_catchment; + long level; + }; #endif // HY_CATCHMENT_H diff --git a/include/core/network.hpp b/include/core/network.hpp index 728bc3ebde..2434cef6bb 100644 --- a/include/core/network.hpp +++ b/include/core/network.hpp @@ -18,6 +18,9 @@ #include namespace network { + + const static int DEFAULT_LAYER_ID = 0; + /** * @brief Selector for using different traversal orders for linear return */ @@ -206,12 +209,53 @@ namespace network { | boost::adaptors::transformed([this](int const& i) { return get_id(i); }) | boost::adaptors::filtered([type](std::string const& s) { if(type == "nex"){ - return s.substr(0,3) == type || s.substr(0,3) == "tnx"; + return s.substr(0,3) == type || s.substr(0,3) == "tnx" || s.substr(0,4) == "tnex"; + } + if(type == "cat"){ + return s.substr(0,3) == type || s.substr(0,3) == "agg"; } return s.substr(0,3) == type; }); } + + /** + * @brief Provides a boost transform_iterator, filtered by @p type , to the topologically ordered graph vertex string id's + * + * This function is useful when only interested in a single type of feature. + * It returns the a topologically ordered set of feature ids. For example, to print all catchments + * in the network: + * @code {.cpp} + * for( auto catchment : network.filter('cat') ){ + * std::cout << catchment; + * } + * @endcode + * + * @param type The type of feature to filter for, i.e. 'cat', 'nex' + * @param target_level The level that filtered results should be in + * @param order What order to return results in + * @return auto + */ + auto filter(std::string type, int target_level, SortOrder order = SortOrder::Topological) + { + //todo need to worry about valivdating input??? + //if type isn't found as a prefix, this iterator range should be empty, + //which is a reasonable semantic + return get_sorted_index(order) | boost::adaptors::reversed + | boost::adaptors::transformed([this](int const& i) { return get_id(i); }) + | boost::adaptors::filtered([this,type,target_level](std::string const& s) { + if(type == "nex"){ + return (s.substr(0,3) == type || s.substr(0,3) == "tnx" || s.substr(0,4) == "tnex") && + (this->level_map.find(s) != this->level_map.end() && this->level_map[s] == target_level); + } + if(type == "cat"){ + return (s.substr(0,3) == type || s.substr(0,3) == "agg") && + (this->level_map.find(s) != this->level_map.end() && this->level_map[s] == target_level); + } + return (s.substr(0,3) == type) && + (this->level_map.find(s) != this->level_map.end() && (this->level_map[s] == target_level)); + }); + } /** * @brief Get the string id of a given graph vertex_descriptor @p idx * @@ -316,6 +360,12 @@ namespace network { * */ std::unordered_map descriptor_map; + + /** + * @brief Mapping of identifier to hydrofabric level + * + */ + std::unordered_map level_map; /** * @brief Get an index of the graph in a particular order. diff --git a/include/geojson/features/FeatureBase.hpp b/include/geojson/features/FeatureBase.hpp index 7df0c8a423..c888d5983a 100644 --- a/include/geojson/features/FeatureBase.hpp +++ b/include/geojson/features/FeatureBase.hpp @@ -384,7 +384,11 @@ namespace geojson { return bounding_box; } - PropertyMap get_properties() const { + const PropertyMap& get_properties() const { + return properties; + } + + PropertyMap& get_properties() { return properties; } diff --git a/include/realizations/catchment/Formulation_Manager.hpp b/include/realizations/catchment/Formulation_Manager.hpp index 2c947767f6..a3465fad13 100644 --- a/include/realizations/catchment/Formulation_Manager.hpp +++ b/include/realizations/catchment/Formulation_Manager.hpp @@ -15,10 +15,11 @@ #include "features/Features.hpp" #include #include "Formulation_Constructors.hpp" -#include "Simulation_Time.h" +#include "Simulation_Time.hpp" #include "GIUH.hpp" #include "GiuhJsonReader.h" #include "routing/Routing_Params.h" +#include "LayerData.hpp" namespace realization { @@ -129,6 +130,62 @@ namespace realization { */ this->Simulation_Time_Object = std::make_shared(simulation_time_config); + /** + * Read the layer descriptions + */ + + // try to get the json node + auto layers_json_array = tree.get_child_optional("layers"); + + // check to see if the node existed + if (!layers_json_array) { + // layer description struct + ngen::LayerDescription layer_desc; + + // extract and store layer data from the json + layer_desc.name = "surface layer"; + layer_desc.id = 0; + layer_desc.time_step = 3600; + layer_desc.time_step_units = "s"; + + // add the layer to storage + layer_storage.put_layer(layer_desc, layer_desc.id); + } + else + { + for (std::pair layer_config : *layers_json_array) + { + // layer description struct + ngen::LayerDescription layer_desc; + + // extract and store layer data from the json + layer_desc.name = layer_config.second.get("name"); + layer_desc.id = layer_config.second.get("id"); + layer_desc.time_step = layer_config.second.get("time_step"); + boost::optional layer_units = layer_config.second.get_optional("time_step_units"); + if (*layer_units == "") layer_units = "s"; + layer_desc.time_step_units = *layer_units; + + // check to see if this layer was allready defined + if (layer_storage.exists(layer_desc.id) ) + { + std::string message = "A layer with id = "; + message += std::to_string(layer_desc.id); + message += " was defined more than once"; + + std::runtime_error r_error(message); + + throw r_error; + } + + // add the layer to storage + layer_storage.put_layer(layer_desc, layer_desc.id); + + // debuggin print to see parsed data + std::cout << layer_desc.name << ", " << layer_desc.id << ", " << layer_desc.time_step << ", " << layer_desc.time_step_units << "\n"; + } + } + /** * Read routing configurations from configuration file */ @@ -250,6 +307,13 @@ namespace realization { return ""; } + /** + * @brief return the layer storage used for formulations + * @return a reference to the LayerStorageObject + */ + + ngen::LayerDataStorage& get_layer_metadata() { return layer_storage; } + protected: std::shared_ptr construct_formulation_from_tree( @@ -474,6 +538,8 @@ namespace realization { std::shared_ptr routing_config; bool using_routing = false; + + ngen::LayerDataStorage layer_storage; }; } #endif // NGEN_FORMULATION_MANAGER_H diff --git a/include/simulation_time/Simulation_Time.h b/include/simulation_time/Simulation_Time.hpp similarity index 69% rename from include/simulation_time/Simulation_Time.h rename to include/simulation_time/Simulation_Time.hpp index adebf0bd21..d41c2f1ae9 100644 --- a/include/simulation_time/Simulation_Time.h +++ b/include/simulation_time/Simulation_Time.hpp @@ -3,6 +3,7 @@ #include #include +#include using namespace std; @@ -68,6 +69,12 @@ class Simulation_Time total_output_times = simulation_total_time_seconds / output_interval_seconds + 1; } + Simulation_Time(const Simulation_Time& t, int interval) : Simulation_Time(t) + { + output_interval_seconds = interval; + total_output_times = simulation_total_time_seconds / output_interval_seconds + 1; + } + /** * @brief Accessor to the total number of time steps * @return total_output_times @@ -86,12 +93,23 @@ class Simulation_Time return output_interval_seconds; } + /** + * @brief Accessor to the the current simulation time + * @return current_date_time_epoch + */ + + time_t get_current_epoc_time() + { + return current_date_time_epoch; + } + /** * @brief Accessor to the current timestamp string * @return current_timestamp */ std::string get_timestamp(int current_output_time_index) { + // "get" method mutates state! current_date_time_epoch = start_date_time_epoch + current_output_time_index * output_interval_seconds; struct tm *temp_gmtime_struct; @@ -109,6 +127,42 @@ class Simulation_Time return current_timestamp; } + inline int next_timestep_index(int epoch_time_seconds) + { + return int(epoch_time_seconds - start_date_time_epoch) / output_interval_seconds; + } + + inline int next_timestep_index() + { + return next_timestep_index(current_date_time_epoch); + } + + inline time_t next_timestep_epoch_time(int epoch_time_seconds){ + return start_date_time_epoch + ( next_timestep_index(epoch_time_seconds) * output_interval_seconds ); + } + + inline time_t next_timestep_epoch_time(){ + return next_timestep_epoch_time(current_date_time_epoch); + } + + inline int diff(const Simulation_Time& other){ + return start_date_time_epoch - other.start_date_time_epoch; + } + + /** + * @brief move this simulation time object to represent the next time step as the current time + */ + + inline void advance_timestep(){ + current_date_time_epoch += output_interval_seconds; + + if (current_date_time_epoch > end_date_time_epoch) + { + throw std::runtime_error("Simulation time objects current time exceeded the end_date_time_epoch value for that object"); + } + } + + private: int total_output_times; diff --git a/models/kernels/Pdm03.h.gch b/models/kernels/Pdm03.h.gch new file mode 100644 index 0000000000..4274054834 Binary files /dev/null and b/models/kernels/Pdm03.h.gch differ diff --git a/src/NGen.cpp b/src/NGen.cpp index 5734820960..d929d3a8c1 100644 --- a/src/NGen.cpp +++ b/src/NGen.cpp @@ -12,6 +12,7 @@ #include #include +#include #ifdef WRITE_PID_FILE_FOR_GDB_SERVER #include @@ -46,6 +47,9 @@ int mpi_rank; int mpi_num_procs; #endif +#include +#include + std::unordered_map nexus_outfiles; //Note: Use below if developing in-memory transfer of nexus flows to routing @@ -298,11 +302,11 @@ int main(int argc, char *argv[]) { #endif //NGEN_ROUTING_ACTIVE std::string link_key = "toid"; - #ifdef NGEN_MPI_ACTIVE nexus_collection->link_features_from_property(nullptr, &link_key); + #ifdef NGEN_MPI_ACTIVE hy_features::HY_Features_MPI features = hy_features::HY_Features_MPI(local_data, nexus_collection, manager, mpi_rank, mpi_num_procs); #else - hy_features::HY_Features features = hy_features::HY_Features(catchment_collection, &link_key, manager); + hy_features::HY_Features features = hy_features::HY_Features(nexus_collection, manager); #endif //validate dendritic connections @@ -327,74 +331,99 @@ int main(int argc, char *argv[]) { std::shared_ptr pdm_et_data = std::make_shared(get_et_params()); + // check the time loops for the existing layers + ngen::LayerDataStorage& layer_meta_data = manager->get_layer_metadata(); + + // get the keys for the existing layers + std::vector& keys = layer_meta_data.get_keys(); + + // get the converted time steps for layers + double min_time_step; + double max_time_step; + std::vector time_steps; + for(int i = 0; i < keys.size(); ++i) + { + auto& m_data = layer_meta_data.get_layer(keys[i]); + double c_value = UnitsHelper::get_converted_value(m_data.time_step_units,m_data.time_step,"s"); + time_steps.push_back(c_value); + } + + std::vector output_time_index; + output_time_index.resize(keys.size()); + std::fill(output_time_index.begin(), output_time_index.end(),0); + + // now create the layer objects + + // first make sure that the layer are listed in decreasing order + boost::range::sort(keys, std::greater()); + + std::vector > layers; + layers.resize(keys.size()); + + for(long i = 0; i < keys.size(); ++i) + { + auto& desc = layer_meta_data.get_layer(keys[i]); + std::vector cat_ids; + + // make a new simulation time object with a different output interval + Simulation_Time sim_time(*manager->Simulation_Time_Object, time_steps[i]); + + for ( std::string id : features.catchments(keys[i]) ) { cat_ids.push_back(id); } + if (keys[i] != 0 ) + { + layers[i] = make_shared(desc, cat_ids, sim_time, features, catchment_collection, pdm_et_data, 0); + } + else + { + layers[i] = make_shared(desc, cat_ids, sim_time, features, catchment_collection, pdm_et_data, 0, nexus_subset_ids, nexus_outfiles); + } + + } + //Now loop some time, iterate catchments, do stuff for total number of output times - for(int output_time_index = 0; output_time_index < manager->Simulation_Time_Object->get_total_output_times(); output_time_index++) { - //std::cout<<"Output Time Index: "<Simulation_Time_Object->get_timestamp(output_time_index); - for(const auto& id : features.catchments()) { - //std::cout<<"Running cat "<(r); - r_c->set_et_params(pdm_et_data); - double response = r_c->get_response(output_time_index, 3600.0); - std::string output = std::to_string(output_time_index)+","+current_timestamp+","+ - r_c->get_output_line_for_timestep(output_time_index)+"\n"; - r_c->write_output(output); - //TODO put this somewhere else. For now, just trying to ensure we get m^3/s into nexus output - try{ - response *= (catchment_collection->get_feature(id)->get_property("areasqkm").as_real_number() * 1000000); - }catch(std::invalid_argument &e) + for( int count = 0; count < manager->Simulation_Time_Object->get_total_output_times(); count++) + { + // The Inner loop will advance all layers unless doing so will break one of two constraints + // 1) A layer may not proceed ahead of the master simulation object's current time + // 2) A layer may not proceed ahead of any layer that is computed before it + // The do while loop ensures that all layers are tested at least once while allowing + // layers with small time steps to be updated more than once + // If a layer with a large time step is after a layer with a small time step the + // layer with the large time step will wait for multiple timesteps from the preceeding + // layer. + + // this is the time that layers are trying to reach (or get as close as possible) + auto next_time = manager->Simulation_Time_Object->next_timestep_epoch_time(); + + // this is the time that the layer above the current layer is at + auto prev_layer_time = next_time; + + // this is the time that the least advanced layer is at + auto layer_min_next_time = next_time; + do + { + for ( auto& layer : layers ) { - response *= (catchment_collection->get_feature(id)->get_property("area_sqkm").as_real_number() * 1000000); - } - //TODO put this somewhere else as well, for now, an implicit assumption is that a modules get_response returns - //m/timestep - //since we are operating on a 1 hour (3600s) dt, we need to scale the output appropriately - //so no response is m^2/hr...m^2/hr * 1hr/3600s = m^3/hr - response /= 3600.0; - //update the nexus with this flow - for(auto& nexus : features.destination_nexuses(id)) { - //TODO in a dendritic network, only one destination nexus per catchment - //If there is more than one, some form of catchment partitioning will be required. - //for now, only contribute to the first one in the list - nexus->add_upstream_flow(response, id, output_time_index); - break; - } - } //done catchments - //At this point, could make an internal routing pass, extracting flows from nexuses and routing - //across the flowpath to the next nexus. - //Once everything is updated for this timestep, dump the nexus output - for(const auto& id : features.nexuses()) { - #ifdef NGEN_MPI_ACTIVE - if (!features.is_remote_sender_nexus(id)) { //Ensures only one side of the dual sided remote nexus actually doing this... - #endif - //Get the correct "requesting" id for downstream_flow - const auto& nexus = features.nexus_at(id); - const auto& cat_ids = nexus->get_receiving_catchments(); - std::string cat_id; - if( cat_ids.size() > 0 ) { - //Assumes dendritic, e.g. only a single downstream...it will consume 100% of the available flow - cat_id = cat_ids[0]; + auto layer_next_time = layer->next_timestep_epoch_time(); + + // only advance if you would not pass the master next time and the previous layer next time + if ( layer_next_time <= next_time && layer_next_time <= prev_layer_time) + { + layer->update_models(); + prev_layer_time = layer_next_time; } - else { - //This is a terminal node, SHOULDN'T be remote, so ID shouldn't matter too much - cat_id = "terminal"; + else + { + layer_min_next_time = prev_layer_time = layer->current_timestep_epoch_time(); } - double contribution_at_t = features.nexus_at(id)->get_downstream_flow(cat_id, output_time_index, 100.0); - if(nexus_outfiles[id].is_open()) { - nexus_outfiles[id] << output_time_index << ", " << current_timestamp << ", " << contribution_at_t << std::endl; + + if ( layer_min_next_time > layer_next_time) + { + layer_min_next_time = layer_next_time; } - #ifdef NGEN_MPI_ACTIVE - } - #endif - //std::cout<<"\tNexus "<Simulation_Time_Object->get_total_output_times()<<" timesteps."< formulations) - :HY_Features(network::Network(fabric), formulations) +HY_Features::HY_Features(geojson::GeoJSON linked_hydro_fabric, std::shared_ptr formulations) + :network(linked_hydro_fabric), formulations(formulations), fabric(linked_hydro_fabric) { - /* If you nest the constuctor calls like this, then the network, while valid in the next constructor, - is empty once the collection is fully instansiated... - HY_Features(network::Network(fabric)); - */ + init(); } -HY_Features::HY_Features(network::Network network, std::shared_ptr formulations) - :network(network), formulations(formulations) +HY_Features::HY_Features( geojson::GeoJSON catchments, std::string* link_key, std::shared_ptr formulations) + : network(catchments, link_key), formulations(formulations), fabric(catchments) { - std::string feat_id; - std::string feat_type; - std::vector origins, destinations; - - for(const auto& feat_idx : network){ - feat_id = network.get_id(feat_idx);//feature->get_id(); - feat_type = feat_id.substr(0, 3); - - destinations = network.get_destination_ids(feat_id); - if(feat_type == "cat") - { - //Find and prepare formulation - auto formulation = formulations->get_formulation(feat_id); - formulation->set_output_stream(feat_id+".csv"); - // TODO: add command line or config option to have this be omitted - //FIXME why isn't default param working here??? get_output_header_line() fails. - formulation->write_output("Time Step,""Time,"+formulation->get_output_header_line(",")+"\n"); - //Find upstream nexus ids - origins = network.get_origination_ids(feat_id); - //Create the HY_Catchment with the formulation realization - std::shared_ptr c = std::make_shared( - HY_Catchment(feat_id, origins, destinations, formulation) - ); - - _catchments.emplace(feat_id, c); - } - else if(feat_type == "nex" || feat_type == "tnx") - { - _nexuses.emplace(feat_id, std::make_unique( - HY_PointHydroNexus(feat_id, destinations) )); - } - else - { - std::cerr<<"HY_Features::HY_Features unknown feature identifier type "< formulations): - HY_Features(network::Network(catchments, link_key), formulations){ +void HY_Features::init() +{ + std::string feat_id; + std::string feat_type; + std::vector origins, destinations; + + for(const auto& feat_idx : network) + { + feat_id = network.get_id(feat_idx);//feature->get_id(); + feat_type = feat_id.substr(0, 3); + + destinations = network.get_destination_ids(feat_id); + if(feat_type == "cat" || feat_type == "agg") + { + //Find and prepare formulation + auto formulation = formulations->get_formulation(feat_id); + formulation->set_output_stream(feat_id+".csv"); + // TODO: add command line or config option to have this be omitted + //FIXME why isn't default param working here??? get_output_header_line() fails. + formulation->write_output("Time Step,""Time,"+formulation->get_output_header_line(",")+"\n"); + //Find upstream nexus ids + origins = network.get_origination_ids(feat_id); + + // get the catchment level from the hydro fabric + const auto& cat_json_node = fabric->get_feature(feat_id); + long lv = cat_json_node->has_key("level") ? cat_json_node->get_property("level").as_natural_number() : 0; + + // add this level to the set of levels if needed + if (hf_levels.find(lv) == hf_levels.end() ) + { + hf_levels.insert(lv); + } + + //Create the HY_Catchment with the formulation realization + std::shared_ptr c = std::make_shared( + HY_Catchment(feat_id, origins, destinations, formulation, lv) + ); + _catchments.emplace(feat_id, c); + } + else if(feat_type == "nex" || feat_type == "tnx") + { + _nexuses.emplace(feat_id, std::make_unique( + HY_PointHydroNexus(feat_id, destinations) )); + } + else + { + std::cerr<<"HY_Features::HY_Features unknown feature identifier type "<get_formulation(feat_id); @@ -42,9 +42,20 @@ HY_Features_MPI::HY_Features_MPI( PartitionData partition_data, geojson::GeoJSON // TODO: add command line or config option to have this be omitted //FIXME why isn't default param working here??? get_output_header_line() fails. formulation->write_output("Time Step,""Time,"+formulation->get_output_header_line(",")+"\n"); + + // get the catchment level from the hydro fabric + const auto& cat_json_node = linked_hydro_fabric->get_feature(feat_id); + long lv = cat_json_node->has_key("level") ? cat_json_node->get_property("level").as_natural_number() : 0; + + // add this level to the set of levels if needed + if (hf_levels.find(lv) == hf_levels.end() ) + { + hf_levels.insert(lv); + } + //Create the HY_Catchment with the formulation realization std::shared_ptr c = std::make_shared( - HY_Catchment(feat_id, origins, destinations, formulation) + HY_Catchment(feat_id, origins, destinations, formulation, lv) ); _catchments.emplace(feat_id, c); diff --git a/src/core/network.cpp b/src/core/network.cpp index 9dfcf39f5c..e5c36c2094 100644 --- a/src/core/network.cpp +++ b/src/core/network.cpp @@ -33,6 +33,7 @@ Network::Network( geojson::GeoJSON fabric ){ for(auto& feature: *fabric) { feature_id = feature->get_id(); + if( this->descriptor_map.find( feature_id ) == this->descriptor_map.end() ) { //Haven't visited this feature yet, add it to graph @@ -43,6 +44,20 @@ Network::Network( geojson::GeoJSON fabric ){ else{ v1 = this->descriptor_map[ feature_id]; } + + if ( this->level_map.find(feature_id) == this->level_map.end() ) + { + if ( feature->has_property("level") ) + { + const auto& prop = feature->get_property("level"); + this->level_map.emplace( feature_id, prop.as_natural_number() ); + } + else + { + this->level_map.emplace( feature_id, DEFAULT_LAYER_ID); + } + } + //Add the downstream features/edges for( auto& downstream: feature->destination_features() ) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 722da840d2..524e0c3777 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -135,6 +135,19 @@ endif() ) #endif() +########################## MultiLevel Tests + add_test( + test_multilevel + 1 + core/multilayer/MultiLayerParserTest.cpp + NGen::core + NGen::geojson + NGen::realizations_catchment + NGen::core_mediator + NGen::forcing +) + + ########################## BMI C++ Tests add_test( test_bmi_cpp @@ -356,7 +369,7 @@ add_test( # All automated tests add_test( test_all - 18 + 19 models/hymod/include/HymodTest.cpp models/hymod/include/Reservoir_Test.cpp models/hymod/include/Reservoir_Timeless_Test.cpp @@ -374,6 +387,7 @@ add_test( core/mediator/UnitsHelper_Tests.cpp realizations/Formulation_Manager_Test.cpp core/nexus/NexusTests.cpp + core/multilayer/MultiLayerParserTest.cpp utils/Partition_Test.cpp NGen::core gmock diff --git a/test/core/multilayer/MultiLayerParserTest.cpp b/test/core/multilayer/MultiLayerParserTest.cpp new file mode 100644 index 0000000000..98f4af4b6e --- /dev/null +++ b/test/core/multilayer/MultiLayerParserTest.cpp @@ -0,0 +1,61 @@ + +#include "gtest/gtest.h" +#include + +class MultiLayerParserTest : public ::testing::Test { + protected: + + MultiLayerParserTest() : + nexus_data_path("../data/multilayer/nexus_data.geojson"), + catchment_data_path("../data/multilayer/nexus_data.geojson"), + realization_config_path("../data/multilayer/realization_config.json") + { + + } + + ~MultiLayerParserTest() override { + + } + + void SetUp() override { + nexus_collection = geojson::read(nexus_data_path.c_str()); + std::cout << "Building Catchment collection" << std::endl; + + catchment_collection = geojson::read(catchment_data_path.c_str()); + + // add the catchments to the nexus collection + for(auto& feature: *catchment_collection) + { + nexus_collection->add_feature(feature); + } + } + + void TearDown() override { + + } + + geojson::GeoJSON nexus_collection; + geojson::GeoJSON catchment_collection; + std::shared_ptr manager; + + std::string nexus_data_path; + std::string catchment_data_path; + std::string realization_config_path; + + +}; + +TEST_F(MultiLayerParserTest, TestInit0) +{ + manager = std::make_shared(realization_config_path.c_str()); + + ASSERT_TRUE(true); +} + +TEST_F(MultiLayerParserTest, TestRead0) +{ + manager = std::make_shared(realization_config_path.c_str()); + manager->read(nexus_collection, utils::getStdOut()); + + ASSERT_TRUE(true); +} \ No newline at end of file diff --git a/test/simulation_time/Simulation_Time_Test.cpp b/test/simulation_time/Simulation_Time_Test.cpp index 6e2951356b..aab9efc77b 100644 --- a/test/simulation_time/Simulation_Time_Test.cpp +++ b/test/simulation_time/Simulation_Time_Test.cpp @@ -1,5 +1,5 @@ #include "gtest/gtest.h" -#include "Simulation_Time.h" +#include "Simulation_Time.hpp" #include #include #include @@ -70,4 +70,55 @@ TEST_F(SimulationTimeTest, TestSimulationTime) } +TEST_F(SimulationTimeTest, TestSimTimeNextIndex) +{ + simulation_time_params other_stp("2015-12-14 21:00:00", "2015-12-30 23:00:00", 3600); + + int next_index; + + // for 2.5h in the future + next_index = Simulation_Time_Object1->next_timestep_index(other_stp.start_t + (3600 * 2.5)); + + EXPECT_EQ(2, next_index); + + // for 2.0h in the future + next_index = Simulation_Time_Object1->next_timestep_index(other_stp.start_t + (3600 * 2.00)); + + EXPECT_EQ(2, next_index); + +} + +TEST_F(SimulationTimeTest, TestSimTimeNextEpochTime) +{ + simulation_time_params other_stp("2015-12-14 21:00:00", "2015-12-30 23:00:00", 3600); + + int next_time; + + // for 2.5h in the future + next_time = Simulation_Time_Object1->next_timestep_epoch_time(other_stp.start_t + (3600 * 2.5)); + + EXPECT_EQ(other_stp.start_t + (3600 * 2.0), next_time); + + // for 2.0h in the future + next_time = Simulation_Time_Object1->next_timestep_epoch_time(other_stp.start_t + (3600 * 2.00)); + + EXPECT_EQ(other_stp.start_t + (3600 * 2.0), next_time); + +} + +TEST_F(SimulationTimeTest, TestSimTimeDiff) +{ + simulation_time_params other_stp("2015-12-14 23:00:00", "2015-12-30 23:00:00", 3600); + Simulation_Time other_st(other_stp); + int diff; + + diff = other_st.diff(*Simulation_Time_Object1); + + EXPECT_EQ(7200, diff); + + diff = Simulation_Time_Object1->diff(other_st); + + EXPECT_EQ(-7200, diff); + +}