PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PCFactory.hh

Go to the documentation of this file.
00001 // Copyright (C) 2010, 2011 Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 // Implementation of "surface", "atmosphere" and "ocean" model factories: C++
00020 // classes processing -surface, -atmosphere and -ocean command-line options,
00021 // creating corresponding models and stringing them together to get requested
00022 // data-flow.
00023 
00024 #include "PISMAtmosphere.hh"
00025 #include "PISMSurface.hh"
00026 #include "PISMOcean.hh"
00027 #include <map>
00028 
00029 template <class Model, class Modifier>
00030 class PCFactory {
00031 public:
00032   PCFactory<Model,Modifier>(IceGrid& g, const NCConfigVariable& conf)
00033   : grid(g), config(conf) {}
00034   virtual ~PCFactory<Model,Modifier>() {}
00035 
00037   virtual PetscErrorCode set_default(string name) {
00038     void (*func) (IceGrid&, const NCConfigVariable&, Model*&);
00039 
00040     func = models[name];
00041     if (!func) {
00042       SETERRQ1(1,"ERROR: type %s is not registered", name.c_str());
00043     } else {
00044       default_type = name;
00045     }
00046     return 0;
00047   }
00048 
00050   virtual PetscErrorCode create(Model* &result) {
00051     void (*F) (IceGrid&, const NCConfigVariable&, Model*&);
00052     PetscErrorCode ierr;
00053     vector<string> choices;
00054     string model_list, modifier_list, descr;
00055     bool flag = false;
00056 
00057     // build a list of available models:
00058     typename map<string,void(*)(IceGrid&, const NCConfigVariable&, Model*&)>::iterator k;
00059     k = models.begin();
00060     model_list = "[" + (k++)->first;
00061     for(; k != models.end(); k++) {
00062       model_list += ", " + k->first;
00063     }
00064     model_list += "]";
00065 
00066     // build a list of available modifiers:
00067     typename map<string,void(*)(IceGrid&, const NCConfigVariable&, Model*, Modifier*&)>::iterator p;
00068     p = modifiers.begin();
00069     modifier_list = "[" + (p++)->first;
00070     for(; p != modifiers.end(); p++) {
00071       modifier_list += ", " + p->first;
00072     }
00073     modifier_list += "]";
00074 
00075     descr =  "Sets up the PISM " + option + " model. Available models: " + model_list +
00076       " Available modifiers: " + modifier_list;
00077   
00078     // Get the command-line option:
00079     ierr = PISMOptionsStringArray("-" + option, descr, default_type.c_str(), choices, flag); CHKERRQ(ierr);
00080 
00081     if (choices.empty()) {
00082       if (flag) {
00083         PetscPrintf(grid.com, "ERROR: option -%s requires an argument.\n", option.c_str());
00084         PISMEnd();
00085       }
00086       choices.push_back(default_type);
00087     }
00088 
00089     // the first element has to be an *actual* model (not a modifier), so we
00090     // create it:
00091     vector<string>::iterator j = choices.begin();
00092   
00093     F = models[*j];
00094     if (!F) {
00095       PetscPrintf(grid.com,
00096                   "ERROR: %s model \"%s\" is not available.\n"
00097                   "  Available models:    %s\n"
00098                   "  Available modifiers: %s\n",
00099                   option.c_str(), j->c_str(),
00100                   model_list.c_str(), modifier_list.c_str());
00101       PISMEnd();
00102     }
00103 
00104     (*F)(grid, config, result);
00105 
00106     ++j;
00107 
00108     // process remaining arguments:
00109     while (j != choices.end()) {
00110       void (*M) (IceGrid&, const NCConfigVariable&, Model*, Modifier*&);
00111       Modifier *mod;
00112 
00113       M = modifiers[*j];
00114       if (!M) {
00115         PetscPrintf(grid.com,
00116                     "ERROR: %s modifier \"%s\" is not available.\n"
00117                     "  Available modifiers: %s\n",
00118                     option.c_str(), j->c_str(), modifier_list.c_str());
00119         PISMEnd();
00120       }
00121 
00122       (*M)(grid, config, result, mod);
00123 
00124       result = mod;
00125 
00126       ++j;
00127     }
00128 
00129     return 0;
00130   }
00131 
00133   virtual void add_model(string name, void(*func)(IceGrid&, const NCConfigVariable&, Model*&)) {
00134     models[name] = func;
00135   }
00136 
00137   virtual void add_modifier(string name, void(*func)(IceGrid&, const NCConfigVariable&, Model*, Modifier*&)) {
00138     modifiers[name] = func;
00139   }
00140 
00142   virtual void remove_model(string name) {
00143     models.erase(name);
00144   }
00145 
00146   virtual void remove_modifier(string name) {
00147     modifiers.erase(name);
00148   }
00149 
00151   virtual void clear_models() {
00152     models.clear();
00153   }
00154 
00155   virtual void clear_modifiers() {
00156     modifiers.clear();
00157   }
00158 protected:
00159   virtual void add_standard_types() {}
00160   string default_type, option;
00161   map<string,void(*)(IceGrid&, const NCConfigVariable&, Model*&)> models;
00162   map<string,void(*)(IceGrid&, const NCConfigVariable&, Model*, Modifier*&)> modifiers;
00163   IceGrid& grid;
00164   const NCConfigVariable& config;
00165 };
00166 
00167 class PAFactory : public PCFactory<PISMAtmosphereModel,PAModifier> {
00168 public:
00169   PAFactory(IceGrid& g, const NCConfigVariable& conf)
00170     : PCFactory<PISMAtmosphereModel,PAModifier>(g, conf)
00171   {
00172     add_standard_types();
00173     option = "atmosphere";
00174   }
00175   virtual ~PAFactory() {}
00176   virtual void add_standard_types();
00177 };
00178 
00179 class PSFactory : public PCFactory<PISMSurfaceModel,PSModifier> {
00180 public:
00181   PSFactory(IceGrid& g, const NCConfigVariable& conf)
00182     : PCFactory<PISMSurfaceModel,PSModifier>(g, conf)
00183   {
00184     add_standard_types();
00185     option = "surface";
00186   }
00187 
00188   virtual ~PSFactory() {}
00189   virtual void add_standard_types();
00190 };
00191 
00192 class POFactory : public PCFactory<PISMOceanModel,POModifier> {
00193 public:
00194   POFactory(IceGrid& g, const NCConfigVariable& conf)
00195     : PCFactory<PISMOceanModel,POModifier>(g, conf)
00196   {
00197     add_standard_types();
00198     option = "ocean";
00199   }
00200   virtual ~POFactory() {}
00201   virtual void add_standard_types();
00202 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines