NGen
Loading...
Searching...
No Matches
Layer.hpp
1#ifndef __NGEN_LAYER__
2#define __NGEN_LAYER__
3
4#include <NGenConfig.h>
5
6#include "LayerData.hpp"
7#include "Simulation_Time.hpp"
8#include "State_Exception.hpp"
9
10#if NGEN_WITH_MPI
11#include "HY_Features_MPI.hpp"
12#else
13#include "HY_Features.hpp"
14#endif
15
16namespace ngen
17{
18
19 class Layer
20 {
21 public:
22
23 #if NGEN_WITH_MPI
24 using feature_type = hy_features::HY_Features_MPI;
25 #else
27 #endif
28
30 const LayerDescription& desc,
31 const std::vector<std::string>& p_u,
32 const Simulation_Time& s_t,
33 feature_type& f,
35 long idx) :
36 description(desc),
38 simulation_time(s_t),
39 features(f),
42 {
43
44 }
45
55 const LayerDescription& desc,
56 const Simulation_Time& s_t,
57 feature_type& f,
58 long idx) :
59 description(desc),
60 simulation_time(s_t),
61 features(f),
63 {
64
65 }
66
67 virtual ~Layer() {}
68
69
73
74
75
79
80
81
84 int get_id() const { return this->description.id; }
85
86
89 const std::string& get_name() const { return this->description.name; }
90
91
94 const double get_time_step() const { return this->description.time_step; }
95
96
99 const std::string& get_time_step_units() const { return this->description.time_step_units; }
100
101
104 virtual void update_models()
105 {
108
109 //std::cout<<"Output Time Index: "<<output_time_index<<std::endl;
110 if(output_time_index%100 == 0) std::cout<<"Running timestep " << output_time_index <<std::endl;
111 std::string current_timestamp = simulation_time.get_timestamp(output_time_index);
112 for(const auto& id : processing_units)
113 {
114 int sub_time = output_time_index;
115 //std::cout<<"Running cat "<<id<<std::endl;
116 auto r = features.catchment_at(id);
117 //TODO redesign to avoid this cast
118 auto r_c = std::dynamic_pointer_cast<realization::Catchment_Formulation>(r);
119 double response(0.0);
120 try{
121 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);
124 }
126 std::string msg = e.what();
127 msg = msg+" at timestep "+std::to_string(output_time_index)
128 +" ("+current_timestamp+")"
129 +" at feature id "+id;
131 }
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 }
139 std::string output = std::to_string(output_time_index)+","+current_timestamp+","+
140 r_c->get_output_line_for_timestep(output_time_index)+"\n";
141 r_c->write_output(output);
142 //TODO put this somewhere else. For now, just trying to ensure we get m^3/s into nexus output
143 double area;
144 try{
145 area = catchment_data->get_feature(id)->get_property("areasqkm").as_real_number();
146 }
147 catch(std::invalid_argument &e)
148 {
149 area = catchment_data->get_feature(id)->get_property("area_sqkm").as_real_number();
150 }
151 double response_m_s = response * (area * 1000000);
152 //TODO put this somewhere else as well, for now, an implicit assumption is that a module's get_response returns
153 //m/timestep
154 //since we are operating on a 1 hour (3600s) dt, we need to scale the output appropriately
155 //so no response is m^2/hr...m^2/hr * 1hr/3600s = m^3/hr
156 double response_m_h = response_m_s / 3600.0;
157 //update the nexus with this flow
158 for(auto& nexus : features.destination_nexuses(id)) {
159 //TODO in a DENDRITIC network, only one destination nexus per catchment
160 //If there is more than one, some form of catchment partitioning will be required.
161 //for now, only contribute to the first one in the list
162 if(nexus == nullptr){
163 throw std::runtime_error("Invalid (null) nexus instantiation downstream of "+id+". "+SOURCE_LOC);
164 }
165 nexus->add_upstream_flow(response_m_h, id, output_time_index);
166 /*std::cerr << "Add water to nexus ID = " << nexus->get_id() << " from catchment ID = " << id << " value = "
167 << response << ", ID = " << id << ", time-index = " << output_time_index << std::endl; */
168 break;
169 }
170
171 } //done catchments
172
175 {
177 }
178 }
179
180
181 protected:
182
184 //TODO is this really required at the top level?
185 //See "minimum" constructor above used for DomainLayer impl...
186 const std::vector<std::string> processing_units;
189 //TODO is this really required at the top level? or can this be moved to SurfaceLayer?
192
193 };
194}
195
196#endif
Simulation Time class providing time-series variables and methods to the model.
Definition Simulation_Time.hpp:48
int get_output_interval_seconds()
Accessor to the output_interval_seconds.
Definition Simulation_Time.hpp:90
int get_total_output_times()
Accessor to the total number of time steps.
Definition Simulation_Time.hpp:81
void advance_timestep()
move this simulation time object to represent the next time step as the current time
Definition Simulation_Time.hpp:155
time_t get_current_epoch_time()
Accessor to the the current simulation time.
Definition Simulation_Time.hpp:100
std::string get_timestamp(int current_output_time_index)
Accessor to the current timestamp string.
Definition Simulation_Time.hpp:109
int next_timestep_index(int epoch_time_seconds)
Definition Simulation_Time.hpp:129
time_t next_timestep_epoch_time(int epoch_time_seconds)
Definition Simulation_Time.hpp:139
Collection interface to HY_Features objects and their associated model formulations.
Definition HY_Features.hpp:41
std::vector< std::shared_ptr< HY_HydroNexus > > destination_nexuses(const std::string &id)
Get a vector of destination (downstream) nexus pointers.
Definition HY_Features.hpp:152
std::shared_ptr< HY_CatchmentRealization > catchment_at(std::string id)
Get the HY_CatchmentRealization pointer identified by id.
Definition HY_Features.hpp:82
Custom exception indicating bad external model state.
Definition State_Exception.hpp:18
virtual char const * what() const noexcept override
Definition State_Exception.hpp:32
Definition Layer.hpp:20
const double get_time_step() const
Return this time_step interval used for this layer.
Definition Layer.hpp:94
time_t current_timestep_epoch_time()
Return the last timestep that was processed by this layer in epoch time units.
Definition Layer.hpp:78
long output_time_index
Definition Layer.hpp:191
Layer(const LayerDescription &desc, const Simulation_Time &s_t, feature_type &f, long idx)
Construct a minimum layer object.
Definition Layer.hpp:54
feature_type & features
Definition Layer.hpp:188
const std::string & get_time_step_units() const
Return the units for the time_step value of this layer.
Definition Layer.hpp:99
const geojson::GeoJSON catchment_data
Definition Layer.hpp:190
const std::vector< std::string > processing_units
Definition Layer.hpp:186
const LayerDescription description
Definition Layer.hpp:183
virtual ~Layer()
Definition Layer.hpp:67
Simulation_Time simulation_time
Definition Layer.hpp:187
time_t next_timestep_epoch_time()
Return the next timestep that will be processed by this layer in epoch time units.
Definition Layer.hpp:72
int get_id() const
Return the numeric id of this layer.
Definition Layer.hpp:84
const std::string & get_name() const
Return the name of this layer.
Definition Layer.hpp:89
Layer(const LayerDescription &desc, const std::vector< std::string > &p_u, const Simulation_Time &s_t, feature_type &f, geojson::GeoJSON cd, long idx)
Definition Layer.hpp:29
virtual void update_models()
Run one simulation timestep for each model in this layer.
Definition Layer.hpp:104
std::shared_ptr< FeatureCollection > GeoJSON
Easy short-hand for a smart pointer to a FeatureCollection.
Definition FeatureBuilder.hpp:21
Definition DomainLayer.hpp:9
A simple structure to hold meta data related to a computational layer.
Definition LayerData.hpp:18
std::string time_step_units
Definition LayerData.hpp:20
double time_step
Definition LayerData.hpp:22
std::string name
Definition LayerData.hpp:19
int id
Definition LayerData.hpp:21