Skip to content

Commit 7d5c585

Browse files
committed
feat(ngen): add mass balance check for all bmi modules during runtime
1 parent 9e2330a commit 7d5c585

File tree

7 files changed

+33
-0
lines changed

7 files changed

+33
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ add_subdirectory("src/forcing")
321321
add_subdirectory("src/utilities/mdarray")
322322
add_subdirectory("src/utilities/mdframe")
323323
add_subdirectory("src/utilities/logging")
324+
add_subdirectory("src/utilities/bmi")
324325

325326
target_link_libraries(ngen
326327
PUBLIC
@@ -333,6 +334,7 @@ target_link_libraries(ngen
333334
NGen::forcing
334335
NGen::core_mediator
335336
NGen::logging
337+
NGen::bmi_protocols
336338
)
337339

338340
if(NGEN_WITH_SQLITE)

include/core/Layer.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ namespace ngen
119119
double response(0.0);
120120
try{
121121
response = r_c->get_response(output_time_index, simulation_time.get_output_interval_seconds());
122+
// Check mass balance if able
123+
r_c->check_mass_balance(output_time_index, simulation_time.get_total_output_times(), current_timestamp);
122124
}
123125
catch(models::external::State_Exception& e){
124126
std::string msg = e.what();
@@ -127,6 +129,13 @@ namespace ngen
127129
+" at feature id "+id;
128130
throw models::external::State_Exception(msg);
129131
}
132+
catch(std::exception& e){
133+
std::string msg = e.what();
134+
msg = msg+" at timestep "+std::to_string(output_time_index)
135+
+" ("+current_timestamp+")"
136+
+" at feature id "+id;
137+
throw std::runtime_error(msg);
138+
}
130139
std::string output = std::to_string(output_time_index)+","+current_timestamp+","+
131140
r_c->get_output_line_for_timestep(output_time_index)+"\n";
132141
r_c->write_output(output);

include/realizations/catchment/Bmi_Module_Formulation.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "Bmi_Adapter.hpp"
88
#include <DataProvider.hpp>
99
#include "bmi_utilities.hpp"
10+
#include "bmi/protocols.hpp"
1011

1112
using data_access::MEAN;
1213
using data_access::SUM;
@@ -250,6 +251,12 @@ namespace realization {
250251
const std::vector<std::string> get_bmi_input_variables() const override;
251252
const std::vector<std::string> get_bmi_output_variables() const override;
252253

254+
virtual void check_mass_balance(const int& iteration, const int& total_steps, const std::string& timestamp) const override {
255+
//Create the protocol context, each member is const, and cannot change during the check
256+
models::bmi::protocols::Context ctx{iteration, total_steps, timestamp, id};
257+
bmi_protocols.mass_balance.run(ctx);
258+
}
259+
253260
protected:
254261

255262
/**
@@ -419,6 +426,7 @@ namespace realization {
419426
int next_time_step_index = 0;
420427

421428
private:
429+
models::bmi::protocols::NgenBmiProtocols bmi_protocols;
422430
/**
423431
* Whether model ``Update`` calls are allowed and handled in some way by the backing model for time steps after
424432
* the model's ``end_time``.

include/realizations/catchment/Bmi_Multi_Formulation.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ namespace realization {
4242

4343
virtual ~Bmi_Multi_Formulation() {};
4444

45+
virtual void check_mass_balance(const int& iteration, const int& total_steps, const std::string& timestamp) const final {
46+
for( const auto &module : modules ) {
47+
// TODO may need to check on outputs form each module indepdently???
48+
// Right now, the assumption is that if each component is mass balanced
49+
// then the entire formulation is mass balanced
50+
module->check_mass_balance(iteration, total_steps, timestamp);
51+
}
52+
};
53+
4554
/**
4655
* Convert a time value from the model to an epoch time in seconds.
4756
*

include/realizations/catchment/Formulation.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace realization {
4444
virtual void create_formulation(boost::property_tree::ptree &config, geojson::PropertyMap *global = nullptr) = 0;
4545
virtual void create_formulation(geojson::PropertyMap properties) = 0;
4646

47+
virtual void check_mass_balance(const int& iteration, const int& total_steps, const std::string& timestamp) const = 0;
4748
protected:
4849

4950
virtual const std::vector<std::string>& get_required_parameters() const = 0;

src/realizations/catchment/Bmi_Module_Formulation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ namespace realization {
382382
if (bmi_var_names_map.find(output_var_name) != bmi_var_names_map.end())
383383
available_forcings.push_back(bmi_var_names_map[output_var_name]);
384384
}
385+
//Initialize all NgenBmiProtocols with the valid adapter pointer and any properties
386+
//provided in the read configuration.
387+
bmi_protocols = models::bmi::protocols::NgenBmiProtocols(get_bmi_model(), properties);
385388
}
386389
}
387390
/**

src/realizations/catchment/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ target_link_libraries(realizations_catchment PUBLIC
2121
NGen::geojson
2222
NGen::logging
2323
NGen::ngen_bmi
24+
NGen::bmi_protocols
2425
)
2526

0 commit comments

Comments
 (0)