The BioCro C++ Library
multilayer_canopy_photosynthesis.h
Go to the documentation of this file.
1#ifndef MULTILAYER_CANOPY_PHOTOSYNTHESIS_H
2#define MULTILAYER_CANOPY_PHOTOSYNTHESIS_H
3
4#include <algorithm> // for std::find
5#include "../framework/module.h"
6#include "../framework/state_map.h"
7
8namespace MLCP // helping functions for the MultiLayer Canopy Photosynthesis module
9{
15template <typename leaf_module_type>
16string_vector get_leaf_input_subset(string_vector reference_names)
17{
18 string_vector leaf_inputs = leaf_module_type::get_inputs();
19 string_vector result_vector;
20 for (std::string const& name : reference_names) {
21 if (std::find(leaf_inputs.begin(),
22 leaf_inputs.end(),
23 name) != leaf_inputs.end()) {
24 result_vector.push_back(name);
25 }
26 }
27 return result_vector;
28}
29
35template <typename canopy_module_type, typename leaf_module_type>
37{
38 return get_leaf_input_subset<leaf_module_type>(
39 canopy_module_type::define_multiclass_multilayer_outputs());
40}
41
47template <typename canopy_module_type, typename leaf_module_type>
49{
50 return get_leaf_input_subset<leaf_module_type>(
51 canopy_module_type::define_pure_multilayer_outputs());
52}
53
66template <typename canopy_module_type, typename leaf_module_type>
67string_vector get_other_leaf_inputs()
68{
69 string_vector layered_canopy_outputs;
70
71 std::vector<string_vector> quantities_that_change =
72 {canopy_module_type::define_multiclass_multilayer_outputs(),
73 canopy_module_type::define_pure_multilayer_outputs()};
74
75 for (string_vector const& sv : quantities_that_change) {
76 for (std::string const& name : sv) {
77 layered_canopy_outputs.push_back(name);
78 }
79 }
80
81 string_vector leaf_inputs_constant_through_canopy;
82
83 string_vector all_leaf_inputs = leaf_module_type::get_inputs();
84
85 for (std::string const& name : all_leaf_inputs) {
86 if (std::find(layered_canopy_outputs.begin(),
87 layered_canopy_outputs.end(),
88 name) == layered_canopy_outputs.end()) {
89 leaf_inputs_constant_through_canopy.push_back(name);
90 }
91 }
92
93 return leaf_inputs_constant_through_canopy;
94}
95} // namespace MLCP
96
97namespace standardBML
98{
155template <typename canopy_module_type, typename leaf_module_type>
156class multilayer_canopy_photosynthesis : public direct_module
157{
158 public:
160 const int& nlayers,
161 state_map const& input_quantities,
162 state_map* output_quantities);
163
164 private:
165 // Number of layers
166 const int nlayers;
167
168 // Leaf photosynthesis module
169 state_map leaf_module_quantities;
170 state_map leaf_module_output_map;
171 std::unique_ptr<module> leaf_module;
172
173 // Pointers to input parameters
174 std::vector<std::vector<std::pair<double*, const double*>>> leaf_input_ptr_pairs;
175
176 // Pointers to output parameters
177 std::vector<std::vector<std::pair<double*, const double*>>> leaf_output_ptr_pairs;
178
179 protected:
180 static string_vector generate_inputs(int nlayers);
181 static string_vector generate_outputs(int nlayers);
182 void run() const;
183};
184
190template <typename canopy_module_type, typename leaf_module_type>
192 const int& nlayers,
193 state_map const& input_quantities,
194 state_map* output_quantities)
195 : direct_module{},
196 nlayers(nlayers)
197{
198 // Define a lambda for making quantity maps from vectors of inputs and outputs
199 auto make_quantity_map = [](string_vector input_names, string_vector output_names) -> state_map {
200 state_map result;
201 for (string_vector const& sv : {input_names, output_names}) {
202 for (std::string const& quantity_name : sv) {
203 result[quantity_name] = 0.0;
204 }
205 }
206 return result;
207 };
208
209 // Form a quantity state_map to pass to the leaf photosynthesis module
210 leaf_module_quantities =
211 make_quantity_map(
212 leaf_module_type::get_inputs(),
213 leaf_module_type::get_outputs());
214
215 leaf_module_output_map = leaf_module_quantities;
216
217 // Create the leaf photosynthesis module
218 leaf_module =
219 std::unique_ptr<module>(new leaf_module_type(
220 leaf_module_quantities,
221 &leaf_module_output_map));
222
223 // Find subsets of the leaf model's inputs
224 string_vector multiclass_multilayer_leaf_inputs =
225 MLCP::get_multiclass_multilayer_leaf_inputs<canopy_module_type, leaf_module_type>();
226
227 string_vector multilayer_leaf_inputs =
228 MLCP::get_pure_multilayer_leaf_inputs<canopy_module_type, leaf_module_type>();
229
230 string_vector other_leaf_inputs =
231 MLCP::get_other_leaf_inputs<canopy_module_type, leaf_module_type>();
232
233 // Create vectors of pointer pairs which will be used for passing inputs to
234 // and getting outputs from the leaf module
235 for (std::string const& class_name : canopy_module_type::define_leaf_classes()) {
236 for (int i = 0; i < nlayers; ++i) {
237 // Get pointer pairs for the leaf module inputs and store them
238 std::vector<std::pair<double*, const double*>> input_ptr_pairs;
239
240 for (std::string const& name : multiclass_multilayer_leaf_inputs) {
241 std::string specific_name =
242 add_class_prefix_to_quantity_name(
243 class_name,
244 add_layer_suffix_to_quantity_name(nlayers, i, name));
245
246 std::pair<double*, const double*> temporary(
247 get_op(&leaf_module_quantities, name),
248 get_ip(input_quantities, specific_name));
249
250 input_ptr_pairs.push_back(temporary);
251 }
252
253 for (std::string const& name : multilayer_leaf_inputs) {
254 std::string specific_name =
255 add_layer_suffix_to_quantity_name(nlayers, i, name);
256
257 std::pair<double*, const double*> temporary(
258 get_op(&leaf_module_quantities, name),
259 get_ip(input_quantities, specific_name));
260
261 input_ptr_pairs.push_back(temporary);
262 }
263
264 for (std::string const& name : other_leaf_inputs) {
265 std::pair<double*, const double*> temporary(
266 get_op(&leaf_module_quantities, name),
267 get_ip(input_quantities, name));
268
269 input_ptr_pairs.push_back(temporary);
270 }
271
272 leaf_input_ptr_pairs.push_back(input_ptr_pairs);
273
274 // Get pointer pairs to the leaf module outputs and store them
275 std::vector<std::pair<double*, const double*>> output_ptr_pairs;
276
277 for (std::string const& name : leaf_module_type::get_outputs()) {
278 std::string specific_name =
279 add_class_prefix_to_quantity_name(
280 class_name,
281 add_layer_suffix_to_quantity_name(nlayers, i, name));
282
283 std::pair<double*, const double*> temporary(
284 get_op(output_quantities, specific_name),
285 get_ip(leaf_module_output_map, name));
286
287 output_ptr_pairs.push_back(temporary);
288 }
289
290 leaf_output_ptr_pairs.push_back(output_ptr_pairs);
291 }
292 }
293}
294
295template <typename canopy_module_type, typename leaf_module_type>
297{
298 // Find subsets of the leaf model's inputs
299 string_vector multiclass_multilayer_leaf_inputs =
300 MLCP::get_multiclass_multilayer_leaf_inputs<canopy_module_type, leaf_module_type>();
301
302 string_vector multilayer_leaf_inputs =
303 MLCP::get_pure_multilayer_leaf_inputs<canopy_module_type, leaf_module_type>();
304
305 string_vector other_leaf_inputs =
306 MLCP::get_other_leaf_inputs<canopy_module_type, leaf_module_type>();
307
308 // Generate the full list of inputs
309 string_vector multilayer_inputs = generate_multiclass_quantity_names(
310 canopy_module_type::define_leaf_classes(),
311 multiclass_multilayer_leaf_inputs);
312
313 for (std::string const& name : multilayer_leaf_inputs) {
314 multilayer_inputs.push_back(name);
315 }
316
317 string_vector inputs = generate_multilayer_quantity_names(nlayers, multilayer_inputs);
318
319 for (std::string const& name : other_leaf_inputs) {
320 inputs.push_back(name);
321 }
322
323 return inputs;
324}
325
326template <typename canopy_module_type, typename leaf_module_type>
328{
329 // Just add prefixes and suffixes to the leaf module outputs
330 return generate_multilayer_quantity_names(
331 nlayers,
332 generate_multiclass_quantity_names(
333 canopy_module_type::define_leaf_classes(),
334 leaf_module_type::get_outputs()));
335}
336
337template <typename canopy_module_type, typename leaf_module_type>
339{
340 // For each combination of leaf class and layer number:
341 for (size_t i = 0; i < leaf_input_ptr_pairs.size(); ++i) {
342 // Update the inputs to the leaf module
343 for (auto const& x : leaf_input_ptr_pairs[i]) {
344 *x.first = *x.second;
345 }
346
347 // Run the leaf module
348 leaf_module->run();
349
350 // Update the outputs from the leaf module
351 for (auto const& x : leaf_output_ptr_pairs[i]) {
352 *x.first = *x.second;
353 }
354 }
355}
356
357} // namespace standardBML
358#endif
Applies a leaf photosynthesis module to each layer and leaf class of a multilayer canopy.
multilayer_canopy_photosynthesis(const int &nlayers, state_map const &input_quantities, state_map *output_quantities)
Constructor for a multilayer canopy photosynthesis module, which initializes the leaf module and prep...
string_vector get_pure_multilayer_leaf_inputs()
A helping function for the multlayer canopy photosynthesis module that returns inputs to the leaf mod...
string_vector get_leaf_input_subset(string_vector reference_names)
A helping function for the multilayer canopy photosynthesis module that returns inputs to the leaf mo...
string_vector get_multiclass_multilayer_leaf_inputs()
A helping function for the multlayer canopy photosynthesis module that returns inputs to the leaf mod...
string_vector get_other_leaf_inputs()
A helping function for the multlayer canopy photosynthesis module that returns inputs to the leaf mod...
This is the standard BioCro module library; it includes the essential modules used in typical BioCro ...
Definition: aba_decay.h:8