NGen
Loading...
Searching...
No Matches
formulation.hpp
1#ifndef NGEN_REALIZATION_CONFIG_FORMULATION_H
2#define NGEN_REALIZATION_CONFIG_FORMULATION_H
3
4#include <NGenConfig.h>
5#include <boost/property_tree/ptree.hpp>
6#include <string>
7
8#include "JSONProperty.hpp"
9
10#if NGEN_WITH_MPI
11#include <mpi.h>
12#endif
13
14namespace realization{
15 namespace config{
16
18 std::string type;
19 //Formulation parameters, object as a PropertyMap
21 //List of nested formulations (used for multi bmi representations)
22 std::vector<Formulation> nested;
23
29 Formulation() = default;
30
37 Formulation(std::string type, geojson::PropertyMap params):type(std::move(type)), parameters(params){}
38
47 Formulation(const boost::property_tree::ptree& tree){
48 type = tree.get<std::string>("name");
49 for (std::pair<std::string, boost::property_tree::ptree> setting : tree.get_child("params")) {
50 //Construct the geoJSON PropertyMap from each key, value pair in "params"
51 parameters.emplace(
52 setting.first,
53 geojson::JSONProperty(setting.first, setting.second)
54 );
55 }
56 if(type=="bmi_multi"){
57 for(auto& module : tree.get_child("params.modules")){
58 //Create the nested formulations in order of definition
59 nested.push_back(Formulation(module.second));
60 }
61 // If running MPI job, output with only one processor
62 #if NGEN_WITH_MPI
63 int mpi_rank;
64 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
65 if (mpi_rank == 0)
66 #endif
67 {
69 }
70 }
71 }
72
80
81 if(type == "bmi_multi"){
82 std::vector<geojson::JSONProperty> tmp;
83 for(auto& n : nested){
84 //Iterate and link any nested modules with this feature
85 if(n.parameters.count("model_params")){
86 n.link_external(feature);
87 }
88 //Need a temporary map to hold the updated formulation properties in
89 geojson::PropertyMap map = {};
90 map.emplace("name", geojson::JSONProperty("name", n.type));
91 map.emplace("params", geojson::JSONProperty("", n.parameters));
92 tmp.push_back(geojson::JSONProperty("", map));
93 }
94 //Reset the bmi_multi modules with the now linked module definitions
95 parameters.at("modules") = geojson::JSONProperty("modules", tmp);
96 return;
97 }
98 //Short circut
99 if(parameters.count("model_params") < 1 ) return;
100 //Have some model params, check to see if any should be linked to the hyrdofabric feature
101 geojson::PropertyMap attr = parameters.at("model_params").get_values();
102 for (decltype(auto) param : attr) {
103 // Check for type to short-circuit. If param.second is not an object, `.has_key()` will throw
104 if (param.second.get_type() != geojson::PropertyType::Object || !param.second.has_key("source")) {
105 attr.emplace(param.first, param.second);
106 continue;
107 }
108
109 decltype(auto) param_source = param.second.at("source");
110 decltype(auto) param_source_name = param_source.as_string();
111 if (param_source_name != "hydrofabric") {
112 // TODO: temporary until the logic for alternative sources is designed
113 throw std::logic_error("ERROR: 'model_params' source `" + param_source_name + "` not currently supported. Only `hydrofabric` is supported.");
114 }
115
116 // Property name in the feature properties is either
117 // the value of key "from", or has the same name as
118 // the expected model parameter key
119 decltype(auto) param_name = param.second.has_key("from")
120 ? param.second.at("from").as_string()
121 : param.first;
122
123 if (feature->has_property(param_name)) {
124 auto catchment_attribute = feature->get_property(param_name);
125
126 // Use param.first in the `.emplace` calls instead of param_name since
127 // the expected name is given by the key of the model_params values.
128 switch (catchment_attribute.get_type()) {
131 // TODO: Should list/object values be passed to model parameters?
132 // Typically, feature properties *should* be scalars.
133 std::cerr << "WARNING: property type " << static_cast<int>(catchment_attribute.get_type()) << " not allowed as model parameter. "
134 << "Must be one of: Natural (int), Real (double), Boolean, or String" << '\n';
135 break;
136 default:
137 attr.at(param.first) = geojson::JSONProperty(param.first, catchment_attribute);
138 }
139 }
140 }
141 parameters.at("model_params") = geojson::JSONProperty("model_params", attr);
142 }
143 };
144
145 }//end namespace config
146}//end namespace realization
147#endif //NGEN_REALIZATION_CONFIG_FORMULATION_H
@TODO: Convert JSONProperty into a variant of the supported types
Definition JSONProperty.hpp:165
static void print_property(const geojson::JSONProperty &p, int tab=0, bool newline=true)
Pretty print the property to standard out stream.
Definition JSONProperty.hpp:441
std::map< std::string, JSONProperty > PropertyMap
Shorthand for a mapping between strings and properties.
Definition JSONProperty.hpp:21
std::shared_ptr< FeatureBase > Feature
An easy name for a smart pointer for FeatureBase and its children.
Definition FeatureBase.hpp:34
Definition Bmi_C_Formulation.hpp:11
Definition formulation.hpp:17
geojson::PropertyMap parameters
Definition formulation.hpp:20
std::string type
Definition formulation.hpp:18
Formulation()=default
Construct a new default Formulation object.
Formulation(std::string type, geojson::PropertyMap params)
Construct a new Formulation object.
Definition formulation.hpp:37
Formulation(const boost::property_tree::ptree &tree)
Construct a new Formulation object from a boost property tree.
Definition formulation.hpp:47
std::vector< Formulation > nested
Definition formulation.hpp:22
void link_external(geojson::Feature feature)
Link formulation parameters to hydrofabric data held in feature.
Definition formulation.hpp:79