inputmodule.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. ///////////////////////////////////////////////////////////////////////////////////////
  2. /// \file inputmodule.h
  3. /// \brief Base class for input modules
  4. ///
  5. /// \author Joe Siltberg
  6. /// $Date: 2018-02-02 18:01:35 +0100 (ven, 02 fév 2018) $
  7. ///
  8. ///////////////////////////////////////////////////////////////////////////////////////
  9. #ifndef LPJ_GUESS_INPUT_MODULE_H
  10. #define LPJ_GUESS_INPUT_MODULE_H
  11. #include <map>
  12. #include <string>
  13. class Gridcell;
  14. /// Base class from which any input module must inherit
  15. /** An input module supplies LPJ-GUESS with the forcing data it needs. The
  16. * InputModule base class is an abstract class, meaning it only defines
  17. * the interface which subclasses must implement.
  18. *
  19. * To create a new input module, create a new class which inherits from
  20. * this one, implement all the member functions below, and register it
  21. * with the REGISTER_INPUT_MODULE macro (defined and documented below).
  22. */
  23. class InputModule {
  24. public:
  25. virtual ~InputModule() {}
  26. /// Called after the instruction file has been read
  27. /** Initialises the input module (e.g. opening files). Typically
  28. * reads in a gridlist.
  29. */
  30. virtual void init() = 0;
  31. /// Obtains coordinates and soil static parameters for the next grid cell to simulate
  32. /** The function should return false if no grid cells remain to be simulated,
  33. * otherwise true. Currently the following member variables of gridcell should be
  34. * initialised: longitude, latitude and climate.instype; the following members of
  35. * member soiltype: awc[0], awc[1], perc_base, perc_exp, thermdiff_0, thermdiff_15,
  36. * thermdiff_100. The soil parameters can be set indirectly based on an lpj soil
  37. * code (Sitch et al 2000) by a call to function soilparameters in the driver
  38. * module (driver.cpp):
  39. *
  40. * soilparameters(gridcell.soiltype,soilcode);
  41. *
  42. * If the model is to be driven by quasi-daily values of the climate variables
  43. * derived from monthly means, this function may be the appropriate place to
  44. * perform the required interpolations. The utility functions interp_monthly_means
  45. * and interp_monthly_totals in driver.cpp may be called for this purpose.
  46. */
  47. virtual bool getgridcell(Gridcell& gridcell) = 0;
  48. /// Obtains climate data (including atmospheric CO2 and insolation) for this day
  49. /** The function should return false if the simulation is complete for this grid cell,
  50. * otherwise true. This will normally require querying the year and day member
  51. * variables of the global class object date:
  52. *
  53. * if (date.day==0 && date.year==nyear_spinup) return false;
  54. * // else
  55. * return true;
  56. *
  57. * Currently the following member variables of the climate member of gridcell must be
  58. * initialised: co2, temp, prec, insol. If the model is to be driven by quasi-daily
  59. * values of the climate variables derived from monthly means, this day's values
  60. * will presumably be extracted from arrays containing the interpolated daily
  61. * values (see function getgridcell):
  62. *
  63. * gridcell.climate.temp=dtemp[date.day];
  64. * gridcell.climate.prec=dprec[date.day];
  65. * gridcell.climate.insol=dsun[date.day];
  66. *
  67. * Diurnal temperature range (dtr) added for calculation of leaf temperatures in
  68. * BVOC:
  69. * gridcell.climate.dtr=ddtr[date.day];
  70. *
  71. * If model is run in diurnal mode, which requires appropriate climate forcing data,
  72. * additional members of the climate must be initialised: temps, insols. Both of the
  73. * variables must be of type std::vector. The length of these vectors should be equal
  74. * to value of date.subdaily which also needs to be set either in getclimate or
  75. * getgridcell functions. date.subdaily is a number of sub-daily period in a single
  76. * day. Irrespective of the BVOC settings, climate.dtr variable is not required in
  77. * diurnal mode.
  78. */
  79. virtual bool getclimate(Gridcell& gridcell) = 0;
  80. /// Obtains land transitions for one year
  81. virtual void getlandcover(Gridcell& gridcell) = 0;
  82. /// Obtains land management data for one day
  83. virtual void getmanagement(Gridcell& gridcell) = 0;
  84. };
  85. /// Keeps track of registered input modules
  86. /** Input modules are registered with the REGISTER_INPUT_MODULE
  87. * macro defined below. The framework can then ask the registry
  88. * to create an input module by specifying its name.
  89. *
  90. * The InputModuleRegistry is a singleton, meaning there's only
  91. * one instance of this class, which is retrieved with the
  92. * get_instance() member function.
  93. */
  94. class InputModuleRegistry {
  95. public:
  96. /// Function pointer type
  97. /** For each registered input module, we have a function which
  98. * creates an instance of that input module. The function is
  99. * created by the REGISTER_INPUT_MODULE macro below.
  100. */
  101. typedef InputModule* (*InputModuleCreator)();
  102. /// Returns the one and only input module registry
  103. static InputModuleRegistry& get_instance();
  104. /// Registers an input module
  105. /** This function shouldn't be called directly, use the REGISTER_INPUT_MODULE
  106. * macro below instead.
  107. */
  108. void register_input_module(const char* name, InputModuleCreator imc);
  109. /// Creates an input module given its name
  110. /** Used by the framework to instantiate the chosen input module. */
  111. InputModule* create_input_module(const char* name) const;
  112. /// Retrieves a semi-colon-separated list of available input modules
  113. /** Used by LPJ-GUESS Windows Shell */
  114. void get_input_module_list(std::string& list);
  115. private:
  116. /// Private constructor to make sure we only have one instance
  117. InputModuleRegistry() {}
  118. /// Also private to prevent copying
  119. InputModuleRegistry(const InputModuleRegistry&);
  120. /// The modules and their names
  121. std::map<std::string, InputModuleCreator> modules;
  122. };
  123. /// A macro used to register input modules
  124. /** Each input module should use this macro somewhere in their
  125. * cpp file. For instance:
  126. *
  127. * REGISTER_INPUT_MODULE("cru_ncep", CRUInputModule)
  128. *
  129. * where "cru_ncep" is the name of the module (used when chosing which
  130. * input module to use), and CRUInputModule is the class to associate
  131. * with that name.
  132. */
  133. #define REGISTER_INPUT_MODULE(name, class_name) \
  134. namespace class_name##_registration { \
  135. \
  136. InputModule* class_name##_creator() {\
  137. return new class_name();\
  138. }\
  139. \
  140. int dummy() {\
  141. InputModuleRegistry::get_instance().register_input_module(name, class_name##_creator);\
  142. return 0;\
  143. }\
  144. \
  145. int x = dummy();\
  146. }
  147. #endif // LPJ_GUESS_INPUT_MODULE_H