World Builder  1.1.0-pre
A geodynamic initial conditions generator
mantle_layer.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2018-2024 by the authors of the World Builder code.
3 
4  This file is part of the World Builder.
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19 
21 
22 
34 #include "world_builder/world.h"
35 
36 
37 namespace WorldBuilder
38 {
39  using namespace Utilities;
40 
41  namespace Features
42  {
43  MantleLayer::MantleLayer(WorldBuilder::World *world_)
44  {
45  this->world = world_;
46  this->name = "mantle layer";
47  }
48 
49  MantleLayer::~MantleLayer()
50  = default;
51 
52 
53 
54  void MantleLayer::make_snippet(Parameters &prm)
55  {
56  using namespace rapidjson;
57  Document &declarations = prm.declarations;
58 
59  const std::string path = prm.get_full_json_path();
60 
61  Pointer((path + "/body").c_str()).Set(declarations,"object");
62  Pointer((path + "/body/model").c_str()).Set(declarations,"mantle layer");
63  Pointer((path + "/body/name").c_str()).Set(declarations,"${1:My Mantle Layer}");
64  Pointer((path + "/body/coordinates").c_str()).Create(declarations).SetArray();
65  Pointer((path + "/body/temperature models").c_str()).Create(declarations).SetArray();
66  Pointer((path + "/body/composition models").c_str()).Create(declarations).SetArray();
67  }
68 
69 
70 
71  void
72  MantleLayer::declare_entries(Parameters &prm,
73  const std::string &/*parent_name*/,
74  const std::vector<std::string> &required_entries)
75  {
76  prm.declare_entry("", Types::Object(required_entries), "Mantle layer object. Requires properties `model` and `coordinates`.");
77 
79  "The depth from which this feature is present");
80  prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits<double>::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits<double>::max(), 2.))),
81  "The depth to which this feature is present");
82  prm.declare_entry("temperature models",
84  "A list of temperature models.");
85  prm.declare_entry("composition models",
87  "A list of composition models.");
88  prm.declare_entry("grains models",
90  "A list of grains models.");
91  prm.declare_entry("velocity models",
93  "A list of velocity models.");
94  }
95 
96  void
97  MantleLayer::parse_entries(Parameters &prm)
98  {
99  const CoordinateSystem coordinate_system = prm.coordinate_system->natural_coordinate_system();
100 
101  this->name = prm.get<std::string>("name");
102 
103  std::string tag = prm.get<std::string>("tag");
104  if (tag == "")
105  {
106  tag = "mantle layer";
107  }
108  this->tag_index = FeatureUtilities::add_vector_unique(this->world->feature_tags,tag);
109 
110  this->get_coordinates("coordinates", prm, coordinate_system);
111 
112  min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
113  min_depth = min_depth_surface.minimum;
114 
115  max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
116  max_depth = max_depth_surface.maximum;
117 
118 
119  prm.get_unique_pointers<Features::MantleLayerModels::Temperature::Interface>("temperature models", temperature_models);
120 
121  prm.enter_subsection("temperature models");
122  {
123  for (unsigned int i = 0; i < temperature_models.size(); ++i)
124  {
125  prm.enter_subsection(std::to_string(i));
126  {
127  temperature_models[i]->parse_entries(prm,coordinates);
128  }
129  prm.leave_subsection();
130  }
131  }
132  prm.leave_subsection();
133 
134 
135  prm.get_unique_pointers<Features::MantleLayerModels::Composition::Interface>("composition models", composition_models);
136 
137  prm.enter_subsection("composition models");
138  {
139  for (unsigned int i = 0; i < composition_models.size(); ++i)
140  {
141  prm.enter_subsection(std::to_string(i));
142  {
143  composition_models[i]->parse_entries(prm,coordinates);
144  }
145  prm.leave_subsection();
146  }
147  }
148  prm.leave_subsection();
149 
150 
151  prm.get_unique_pointers<Features::MantleLayerModels::Grains::Interface>("grains models", grains_models);
152 
153  prm.enter_subsection("grains models");
154  {
155  for (unsigned int i = 0; i < grains_models.size(); ++i)
156  {
157  prm.enter_subsection(std::to_string(i));
158  {
159  grains_models[i]->parse_entries(prm,coordinates);
160  }
161  prm.leave_subsection();
162  }
163  }
164  prm.leave_subsection();
165 
166  prm.get_unique_pointers<Features::MantleLayerModels::Velocity::Interface>("velocity models", velocity_models);
167 
168  prm.enter_subsection("velocity models");
169  {
170  for (unsigned int i = 0; i < velocity_models.size(); ++i)
171  {
172  prm.enter_subsection(std::to_string(i));
173  {
174  velocity_models[i]->parse_entries(prm,coordinates);
175  }
176  prm.leave_subsection();
177  }
178  }
179  prm.leave_subsection();
180  }
181 
182 
183  void
184  MantleLayer::properties(const Point<3> &position_in_cartesian_coordinates,
185  const Objects::NaturalCoordinate &position_in_natural_coordinates,
186  const double depth,
187  const std::vector<std::array<unsigned int,3>> &properties,
188  const double gravity_norm,
189  const std::vector<size_t> &entry_in_output,
190  std::vector<double> &output) const
191  {
192  if (depth <= max_depth && depth >= min_depth &&
193  WorldBuilder::Utilities::polygon_contains_point(coordinates, Point<2>(position_in_natural_coordinates.get_surface_coordinates(),
194  world->parameters.coordinate_system->natural_coordinate_system())))
195  {
196  const double min_depth_local = min_depth_surface.constant_value ? min_depth : min_depth_surface.local_value(position_in_natural_coordinates.get_surface_point()).interpolated_value;
197  const double max_depth_local = max_depth_surface.constant_value ? max_depth : max_depth_surface.local_value(position_in_natural_coordinates.get_surface_point()).interpolated_value;
198  if (depth <= max_depth_local && depth >= min_depth_local)
199  {
200  for (unsigned int i_property = 0; i_property < properties.size(); ++i_property)
201  {
202  switch (properties[i_property][0])
203  {
204  case 1: // temperature
205  {
206  for (const auto &temperature_model: temperature_models)
207  {
208  output[entry_in_output[i_property]] = temperature_model->get_temperature(position_in_cartesian_coordinates,
209  position_in_natural_coordinates,
210  depth,
211  gravity_norm,
212  output[entry_in_output[i_property]],
213  min_depth_local,
214  max_depth_local);
215 
216  WBAssert(!std::isnan(output[entry_in_output[i_property]]), "Temperature is not a number: " << output[entry_in_output[i_property]]
217  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
218  WBAssert(std::isfinite(output[entry_in_output[i_property]]), "Temperature is not a finite: " << output[entry_in_output[i_property]]
219  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
220 
221  }
222  break;
223  }
224  case 2: // composition
225  {
226  for (const auto &composition_model: composition_models)
227  {
228  output[entry_in_output[i_property]] = composition_model->get_composition(position_in_cartesian_coordinates,
229  position_in_natural_coordinates,
230  depth,
231  properties[i_property][1],
232  output[entry_in_output[i_property]],
233  min_depth_local,
234  max_depth_local);
235 
236  WBAssert(!std::isnan(output[entry_in_output[i_property]]), "Composition is not a number: " << output[entry_in_output[i_property]]
237  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
238  WBAssert(std::isfinite(output[entry_in_output[i_property]]), "Composition is not a finite: " << output[entry_in_output[i_property]]
239  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
240 
241  }
242 
243  break;
244  }
245  case 3: // grains
246  {
247  WorldBuilder::grains grains(output,properties[i_property][2],entry_in_output[i_property]);
248  for (const auto &grains_model: grains_models)
249  {
250  grains = grains_model->get_grains(position_in_cartesian_coordinates,
251  position_in_natural_coordinates,
252  depth,
253  properties[i_property][1],
254  grains,
255  min_depth_local,
256  max_depth_local);
257 
258  }
259  grains.unroll_into(output,entry_in_output[i_property]);
260  break;
261  }
262  case 4:
263  {
264  output[entry_in_output[i_property]] = static_cast<double>(tag_index);
265  break;
266  }
267  case 5: // velocity
268  {
269  std::array<double, 3> velocity = {{0,0,0}};
270  for (const auto &velocity_model: velocity_models)
271  {
272  velocity = velocity_model->get_velocity(position_in_cartesian_coordinates,
273  position_in_natural_coordinates,
274  depth,
275  gravity_norm,
276  velocity,
277  min_depth_local,
278  max_depth_local);
279 
280  //WBAssert(!std::isnan(output[entry_in_output[i_property]]), "Velocity is not a number: " << output[entry_in_output[i_property]]
281  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
282  //WBAssert(std::isfinite(output[entry_in_output[i_property]]), "Velocity is not a finite: " << output[entry_in_output[i_property]]
283  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
284  }
285 
286  output[entry_in_output[i_property]] = velocity[0];
287  output[entry_in_output[i_property]+1] = velocity[1];
288  output[entry_in_output[i_property]+2] = velocity[2];
289  break;
290  }
291  break;
292  default:
293  {
294  WBAssertThrow(false,
295  "Internal error: Unimplemented property provided. " <<
296  "Only temperature (1), composition (2), grains (3) or tag (4) are allowed. "
297  "Provided property number was: " << properties[i_property][0]);
298  }
299  }
300  }
301  }
302  }
303  }
304 
305  WB_REGISTER_FEATURE(MantleLayer, mantle layer)
306 
307  } // namespace Features
308 } // namespace WorldBuilder
std::array< double, 2 > get_surface_coordinates() const
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:42
size_t add_vector_unique(std::vector< std::string > &vector, const std::string &add_string)
#define WB_REGISTER_FEATURE(classname, name)
Definition: interface.h:212
void enter_subsection(const std::string &name)
Definition: parameters.cc:1871
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:41
#define WBAssert(condition, message)
Definition: assert.h:27
std::string get_full_json_path(size_t max_size=std::numeric_limits< size_t >::max()) const
Definition: parameters.cc:1933
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:40
#define WBAssertThrow(condition, message)
Definition: assert.h:40
bool get_unique_pointers(const std::string &name, std::vector< std::unique_ptr< T > > &vector)
Definition: parameters.cc:1770
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:41
std::unique_ptr< WorldBuilder::CoordinateSystems::Interface > coordinate_system
Definition: parameters.h:268
bool polygon_contains_point(const std::vector< Point< 2 > > &point_list, const Point< 2 > &point)
Definition: utilities.cc:46
void declare_entry(const std::string &name, const Types::Interface &type, const std::string &documentation)
Definition: parameters.cc:197
T get(const std::string &name)
rapidjson::Document declarations
Definition: parameters.h:248
void unroll_into(std::vector< double > &vector, const size_t start_entry=0) const
Definition: grains.cc:58