123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- ///////////////////////////////////////////////////////////////////////////////////////
- /// \file inputmodule.h
- /// \brief Base class for input modules
- ///
- /// \author Joe Siltberg
- /// $Date: 2018-02-02 18:01:35 +0100 (ven, 02 fév 2018) $
- ///
- ///////////////////////////////////////////////////////////////////////////////////////
- #ifndef LPJ_GUESS_INPUT_MODULE_H
- #define LPJ_GUESS_INPUT_MODULE_H
- #include <map>
- #include <string>
- class Gridcell;
- /// Base class from which any input module must inherit
- /** An input module supplies LPJ-GUESS with the forcing data it needs. The
- * InputModule base class is an abstract class, meaning it only defines
- * the interface which subclasses must implement.
- *
- * To create a new input module, create a new class which inherits from
- * this one, implement all the member functions below, and register it
- * with the REGISTER_INPUT_MODULE macro (defined and documented below).
- */
- class InputModule {
- public:
- virtual ~InputModule() {}
- /// Called after the instruction file has been read
- /** Initialises the input module (e.g. opening files). Typically
- * reads in a gridlist.
- */
- virtual void init() = 0;
- /// Obtains coordinates and soil static parameters for the next grid cell to simulate
- /** The function should return false if no grid cells remain to be simulated,
- * otherwise true. Currently the following member variables of gridcell should be
- * initialised: longitude, latitude and climate.instype; the following members of
- * member soiltype: awc[0], awc[1], perc_base, perc_exp, thermdiff_0, thermdiff_15,
- * thermdiff_100. The soil parameters can be set indirectly based on an lpj soil
- * code (Sitch et al 2000) by a call to function soilparameters in the driver
- * module (driver.cpp):
- *
- * soilparameters(gridcell.soiltype,soilcode);
- *
- * If the model is to be driven by quasi-daily values of the climate variables
- * derived from monthly means, this function may be the appropriate place to
- * perform the required interpolations. The utility functions interp_monthly_means
- * and interp_monthly_totals in driver.cpp may be called for this purpose.
- */
- virtual bool getgridcell(Gridcell& gridcell) = 0;
- /// Obtains climate data (including atmospheric CO2 and insolation) for this day
- /** The function should return false if the simulation is complete for this grid cell,
- * otherwise true. This will normally require querying the year and day member
- * variables of the global class object date:
- *
- * if (date.day==0 && date.year==nyear_spinup) return false;
- * // else
- * return true;
- *
- * Currently the following member variables of the climate member of gridcell must be
- * initialised: co2, temp, prec, insol. If the model is to be driven by quasi-daily
- * values of the climate variables derived from monthly means, this day's values
- * will presumably be extracted from arrays containing the interpolated daily
- * values (see function getgridcell):
- *
- * gridcell.climate.temp=dtemp[date.day];
- * gridcell.climate.prec=dprec[date.day];
- * gridcell.climate.insol=dsun[date.day];
- *
- * Diurnal temperature range (dtr) added for calculation of leaf temperatures in
- * BVOC:
- * gridcell.climate.dtr=ddtr[date.day];
- *
- * If model is run in diurnal mode, which requires appropriate climate forcing data,
- * additional members of the climate must be initialised: temps, insols. Both of the
- * variables must be of type std::vector. The length of these vectors should be equal
- * to value of date.subdaily which also needs to be set either in getclimate or
- * getgridcell functions. date.subdaily is a number of sub-daily period in a single
- * day. Irrespective of the BVOC settings, climate.dtr variable is not required in
- * diurnal mode.
- */
- virtual bool getclimate(Gridcell& gridcell) = 0;
- /// Obtains land transitions for one year
- virtual void getlandcover(Gridcell& gridcell) = 0;
- /// Obtains land management data for one day
- virtual void getmanagement(Gridcell& gridcell) = 0;
- };
- /// Keeps track of registered input modules
- /** Input modules are registered with the REGISTER_INPUT_MODULE
- * macro defined below. The framework can then ask the registry
- * to create an input module by specifying its name.
- *
- * The InputModuleRegistry is a singleton, meaning there's only
- * one instance of this class, which is retrieved with the
- * get_instance() member function.
- */
- class InputModuleRegistry {
- public:
- /// Function pointer type
- /** For each registered input module, we have a function which
- * creates an instance of that input module. The function is
- * created by the REGISTER_INPUT_MODULE macro below.
- */
- typedef InputModule* (*InputModuleCreator)();
- /// Returns the one and only input module registry
- static InputModuleRegistry& get_instance();
- /// Registers an input module
- /** This function shouldn't be called directly, use the REGISTER_INPUT_MODULE
- * macro below instead.
- */
- void register_input_module(const char* name, InputModuleCreator imc);
- /// Creates an input module given its name
- /** Used by the framework to instantiate the chosen input module. */
- InputModule* create_input_module(const char* name) const;
- /// Retrieves a semi-colon-separated list of available input modules
- /** Used by LPJ-GUESS Windows Shell */
- void get_input_module_list(std::string& list);
- private:
- /// Private constructor to make sure we only have one instance
- InputModuleRegistry() {}
- /// Also private to prevent copying
- InputModuleRegistry(const InputModuleRegistry&);
- /// The modules and their names
- std::map<std::string, InputModuleCreator> modules;
- };
- /// A macro used to register input modules
- /** Each input module should use this macro somewhere in their
- * cpp file. For instance:
- *
- * REGISTER_INPUT_MODULE("cru_ncep", CRUInputModule)
- *
- * where "cru_ncep" is the name of the module (used when chosing which
- * input module to use), and CRUInputModule is the class to associate
- * with that name.
- */
- #define REGISTER_INPUT_MODULE(name, class_name) \
- namespace class_name##_registration { \
- \
- InputModule* class_name##_creator() {\
- return new class_name();\
- }\
- \
- int dummy() {\
- InputModuleRegistry::get_instance().register_input_module(name, class_name##_creator);\
- return 0;\
- }\
- \
- int x = dummy();\
- }
- #endif // LPJ_GUESS_INPUT_MODULE_H
|