PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
PCFactory.hh
Go to the documentation of this file.
1 // Copyright (C) 2011, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 PISM Authors
2 //
3 // This file is part of PISM.
4 //
5 // PISM is free software; you can redistribute it and/or modify it under the
6 // terms of the GNU General Public License as published by the Free Software
7 // Foundation; either version 3 of the License, or (at your option) any later
8 // version.
9 //
10 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with PISM; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 #ifndef _PCFACTORY_H_
20 #define _PCFACTORY_H_
21 
22 #include <memory>
23 #include <map>
24 
25 #include "pism/util/Grid.hh"
26 #include "pism/util/error_handling.hh"
27 #include "pism/util/pism_utilities.hh"
28 #include "pism/util/ConfigInterface.hh"
29 #include "pism/util/Context.hh"
30 
31 namespace pism {
32 
33 template <class Model>
34 class PCFactory {
35 public:
36 
37  PCFactory<Model>(std::shared_ptr<const Grid> g, const std::string &parameter)
38  : m_parameter(parameter), m_grid(g) {}
39  ~PCFactory<Model>() {}
40 
41  //! Creates a boundary model. Processes command-line options.
42  virtual std::shared_ptr<Model> create() {
43 
44  auto choices = m_grid->ctx()->config()->get_string(m_parameter);
45 
46  return create(choices);
47  }
48 
49  void validate(const std::string &list) const {
50 
51  auto choices = split(list, ',');
52 
53  auto doc = m_grid->ctx()->config()->doc(m_parameter);
54  auto opt = m_grid->ctx()->config()->option(m_parameter);
55 
56  if (choices.empty()) {
58  "Parameter %s (%s) cannot be empty (got '%s')",
59  m_parameter.c_str(), doc.c_str(), list.c_str());
60  }
61 
62  auto model1 = m_models.begin()->first;
63 
64  if (m_models.find(choices[0]) == m_models.end() and
65  m_modifiers.find(choices[0]) != m_modifiers.end()) {
67  "The first item on the list %s\n"
68  "(%s)\n"
69  "has to be a 'model' (one of %s),\n"
70  "while the rest have to be 'modifiers' (one of %s).\n"
71  "Got %s='%s'.\n"
72  "To use %s you also have to select a model, e.g. using the command-line option\n"
73  "'-%s %s,%s'.",
74  m_parameter.c_str(), doc.c_str(), key_list(m_models).c_str(),
75  key_list(m_modifiers).c_str(),
76  m_parameter.c_str(), list.c_str(), list.c_str(),
77  opt.c_str(), model1.c_str(), list.c_str());
78  }
79  }
80 
81  //! Creates a boundary model.
82  virtual std::shared_ptr<Model> create(const std::string &type) {
83  validate(type);
84 
85  std::vector<std::string> choices = split(type, ',');
86 
87  // the first element has to be an *actual* model (not a modifier)
88  auto j = choices.begin();
89 
90  auto result = model(*j);
91 
92  ++j;
93 
94  // process remaining arguments:
95  for (;j != choices.end(); ++j) {
96  result = modifier(*j, result);
97  }
98 
99  return result;
100  }
101 
102 protected:
103  //! Adds a boundary model to the dictionary.
104  template <class M>
105  void add_model(const std::string &name) {
106  m_models[name].reset(new SpecificModelCreator<M>);
107  }
108 
109  template <class M>
110  void add_modifier(const std::string &name) {
111  m_modifiers[name].reset(new SpecificModifierCreator<M>);
112  }
113 
114  template <typename T>
115  std::string key_list(std::map<std::string, T> list) const {
116  std::vector<std::string> keys;
117 
118  for (const auto &i : list) {
119  keys.push_back(i.first);
120  }
121 
122  return "[" + join(keys, ", ") + "]";
123  }
124 
125  std::shared_ptr<Model> model(const std::string &type) {
126  if (m_models.find(type) == m_models.end()) {
128  "cannot allocate %s \"%s\".\n"
129  "Available models: %s\n",
130  m_parameter.c_str(), type.c_str(), key_list(m_models).c_str());
131  }
132 
133  return m_models[type]->create(m_grid);
134  }
135 
136  template <class T>
137  std::shared_ptr<Model> modifier(const std::string &type, std::shared_ptr<T> input) {
138  if (m_modifiers.find(type) == m_modifiers.end()) {
140  "cannot allocate %s modifier \"%s\".\n"
141  "Available modifiers: %s\n",
142  m_parameter.c_str(), type.c_str(),
143  key_list(m_modifiers).c_str());
144  }
145 
146  return m_modifiers[type]->create(m_grid, input);
147  }
148 
149  // virtual base class that allows storing different model creators
150  // in the same dictionary
151  class ModelCreator {
152  public:
153  virtual std::shared_ptr<Model> create(std::shared_ptr<const Grid> g) = 0;
154  virtual ~ModelCreator() = default;
155  };
156 
157  // Creator for a specific model class M.
158  template <class M>
160  public:
161  std::shared_ptr<Model> create(std::shared_ptr<const Grid> g) {
162  return std::shared_ptr<Model>(new M(g));
163  }
164  };
165 
166  // virtual base class that allows storing different modifier
167  // creators in the same dictionary
169  public:
170  virtual std::shared_ptr<Model> create(std::shared_ptr<const Grid> g,
171  std::shared_ptr<Model> input) = 0;
172 
173  virtual ~ModifierCreator() = default;
174  };
175 
176  // Creator for a specific modifier class M.
177  template <class M>
179  public:
180  std::shared_ptr<Model> create(std::shared_ptr<const Grid> g, std::shared_ptr<Model> input) {
181  return std::shared_ptr<Model>(new M(g, input));
182  }
183  };
184 
185  std::string m_parameter;
186  std::map<std::string, std::shared_ptr<ModelCreator> > m_models;
187  std::map<std::string, std::shared_ptr<ModifierCreator> > m_modifiers;
188  std::shared_ptr<const Grid> m_grid;
189 };
190 
191 } // end of namespace pism
192 
193 #endif /* _PCFACTORY_H_ */
virtual ~ModelCreator()=default
virtual std::shared_ptr< Model > create(std::shared_ptr< const Grid > g)=0
virtual std::shared_ptr< Model > create(std::shared_ptr< const Grid > g, std::shared_ptr< Model > input)=0
virtual ~ModifierCreator()=default
std::shared_ptr< Model > create(std::shared_ptr< const Grid > g)
Definition: PCFactory.hh:161
std::shared_ptr< Model > create(std::shared_ptr< const Grid > g, std::shared_ptr< Model > input)
Definition: PCFactory.hh:180
std::shared_ptr< Model > modifier(const std::string &type, std::shared_ptr< T > input)
Definition: PCFactory.hh:137
std::shared_ptr< Model > model(const std::string &type)
Definition: PCFactory.hh:125
void add_model(const std::string &name)
Adds a boundary model to the dictionary.
Definition: PCFactory.hh:105
void add_modifier(const std::string &name)
Definition: PCFactory.hh:110
void validate(const std::string &list) const
Definition: PCFactory.hh:49
std::shared_ptr< const Grid > m_grid
Definition: PCFactory.hh:188
std::map< std::string, std::shared_ptr< ModifierCreator > > m_modifiers
Definition: PCFactory.hh:187
std::string key_list(std::map< std::string, T > list) const
Definition: PCFactory.hh:115
std::string m_parameter
Definition: PCFactory.hh:185
virtual std::shared_ptr< Model > create(const std::string &type)
Creates a boundary model.
Definition: PCFactory.hh:82
std::map< std::string, std::shared_ptr< ModelCreator > > m_models
Definition: PCFactory.hh:186
virtual std::shared_ptr< Model > create()
Creates a boundary model. Processes command-line options.
Definition: PCFactory.hh:42
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
#define PISM_ERROR_LOCATION
static const double g
Definition: exactTestP.cc:36
std::string join(const std::vector< std::string > &strings, const std::string &separator)
Concatenate strings, inserting separator between elements.
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.