World Builder  1.1.0-pre
A geodynamic initial conditions generator
plate_model.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 #include "world_builder/nan.h"
30 #include "world_builder/world.h"
31 
32 
33 namespace WorldBuilder
34 {
35  using namespace Utilities;
36 
37  namespace Features
38  {
39  namespace OceanicPlateModels
40  {
41  namespace Temperature
42  {
43  PlateModel::PlateModel(WorldBuilder::World *world_)
44  :
45  min_depth(NaN::DSNAN),
46  max_depth(NaN::DSNAN),
47  top_temperature(NaN::DSNAN),
48  bottom_temperature(NaN::DSNAN),
49  operation(Operations::REPLACE)
50  {
51  this->world = world_;
52  this->name = "plate model";
53  }
54 
56  = default;
57 
58  void
59  PlateModel::declare_entries(Parameters &prm, const std::string & /*unused*/)
60  {
61  // Document plugin and require entries if needed.
62  // Add temperature to the required parameters.
63  prm.declare_entry("", Types::Object({"max depth"}),
64  "Plate model.");
65 
66  // Declare entries of this plugin
68  "The depth in meters from which the temperature of this feature is present.");
69 
70  prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits<double>::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits<double>::max(), 2.))),
71  "The depth in meters to which the temperature of this feature is present.");
72 
73  prm.declare_entry("top temperature", Types::Double(293.15),
74  "The temperature in degree Kelvin which this feature should have");
75 
76  prm.declare_entry("bottom temperature", Types::Double(-1),
77  "The temperature in degree Kelvin which this feature should have");
78 
79  prm.declare_entry("spreading velocity", Types::OneOf(Types::Double(0.05),Types::Array(Types::ValueAtPoints(0.05, std::numeric_limits<uint64_t>::max()))),
80  "The spreading velocity of the plate in meter per year. "
81  "This is the velocity with which one side moves away from the ridge.");
82 
83  prm.declare_entry("ridge coordinates", Types::Array(Types::Array(Types::Point<2>(), 2),1),
84  "An list of ridges. Each ridge is a lists of at least 2 2d points which "
85  "define the location of the ridge. You need to define at least one ridge."
86  "So the an example with two ridges is "
87  "[[[10,20],[20,30],[10,40]],[[50,10],[60,10]]].");
88 
89  }
90 
91  void
92  PlateModel::parse_entries(Parameters &prm, const std::vector<Point<2>> &coordinates)
93  {
94 
95  min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
97  max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
99  operation = string_operations_to_enum(prm.get<std::string>("operation"));
100  top_temperature = prm.get<double>("top temperature");
101  bottom_temperature = prm.get<double>("bottom temperature");
102  spreading_velocities = prm.get_value_at_array("spreading velocity");
103 
104  mid_oceanic_ridges = prm.get_vector<std::vector<Point<2>>>("ridge coordinates");
105  const double dtr = prm.coordinate_system->natural_coordinate_system() == spherical ? Consts::PI / 180.0 : 1.0;
106  for (auto &ridge_coordinates : mid_oceanic_ridges)
107  for (auto &ridge_coordinate : ridge_coordinates)
108  {
109  ridge_coordinate *= dtr;
110  }
111 
112  unsigned int ridge_point_index = 0;
113  for (const auto &mid_oceanic_ridge : mid_oceanic_ridges)
114  {
115  std::vector<double> spreading_rates_for_ridge;
116  for (unsigned int index_y = 0; index_y < mid_oceanic_ridge.size(); index_y++)
117  {
118  if (spreading_velocities.second.size() <= 1)
119  {
120  spreading_rates_for_ridge.push_back(spreading_velocities.second[0]);
121  }
122  else
123  {
124  spreading_rates_for_ridge.push_back(spreading_velocities.second[ridge_point_index]);
125  }
126  ridge_point_index += 1;
127  }
128  spreading_velocities_at_each_ridge_point.push_back(spreading_rates_for_ridge);
129  }
130  }
131 
132 
133  double
135  const Objects::NaturalCoordinate &position_in_natural_coordinates,
136  const double depth,
137  const double gravity_norm,
138  double temperature_,
139  const double /*feature_min_depth*/,
140  const double /*feature_max_depth*/) const
141  {
142  if (depth <= max_depth && depth >= min_depth)
143  {
144  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;
145  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;
146  if (depth <= max_depth_local && depth >= min_depth_local)
147  {
148  Objects::NaturalCoordinate position_in_natural_coordinates_at_min_depth = Objects::NaturalCoordinate(position,
150  position_in_natural_coordinates_at_min_depth.get_ref_depth_coordinate() += depth-min_depth;
151  std::vector<std::vector<double>> subducting_plate_velocities = {{0}};
152  std::vector<double> ridge_migration_times = {0.0};
153  double bottom_temperature_local = bottom_temperature;
154 
155  if (bottom_temperature_local < 0)
156  {
157  bottom_temperature_local = this->world->potential_mantle_temperature *
158  std::exp(((this->world->thermal_expansion_coefficient* gravity_norm) /
159  this->world->specific_heat) * depth);
160  }
161 
162  const int summation_number = 100;
163 
164  std::vector<double> ridge_parameters = Utilities::calculate_ridge_distance_and_spreading(mid_oceanic_ridges,
167  position_in_natural_coordinates_at_min_depth,
168  subducting_plate_velocities,
169  ridge_migration_times);
170 
171  const double thermal_diffusivity = this->world->thermal_diffusivity;
172  const double age = ridge_parameters[1] / ridge_parameters[0];
173  double temperature = top_temperature + (bottom_temperature_local - top_temperature) * (depth / max_depth);
174 
175  // This formula addresses the horizontal heat transfer by having the spreading velocity and distance to the ridge in it.
176  // (Chapter 7 Heat, Fowler M. The solid earth: an introduction to global geophysics[M]. Cambridge University Press, 1990)
177  for (int i = 1; i<summation_number+1; ++i)
178  {
179  temperature = temperature + (bottom_temperature_local - top_temperature) *
180  ((2 / (double(i) * Consts::PI)) * std::sin((double(i) * Consts::PI * depth) / max_depth) *
181  std::exp((((ridge_parameters[0] * max_depth)/(2 * thermal_diffusivity)) -
182  std::sqrt(((ridge_parameters[0]*ridge_parameters[0]*max_depth*max_depth) /
183  (4*thermal_diffusivity*thermal_diffusivity)) + double(i) * double(i) * Consts::PI * Consts::PI)) *
184  ((ridge_parameters[0] * age) / max_depth)));
185 
186  }
187 
188  WBAssert(!std::isnan(temperature), "Temperature inside plate model is not a number: " << temperature
189  << ". Relevant variables: bottom_temperature_local = " << bottom_temperature_local
190  << ", top_temperature = " << top_temperature
191  << ", max_depth = " << max_depth
192  << ", spreading_velocity = " << ridge_parameters[0]
193  << ", thermal_diffusivity = " << thermal_diffusivity
194  << ", age = " << age << '.');
195  WBAssert(std::isfinite(temperature), "Temperature inside plate model is not a finite: " << temperature << ". Relevant variables: bottom_temperature_local = " << bottom_temperature_local
196  << ", top_temperature = " << top_temperature
197  << ", spreading_velocity = " << ridge_parameters[0]
198  << ", thermal_diffusivity = " << thermal_diffusivity
199  << ", age = " << age << '.');
200 
201 
202  return apply_operation(operation,temperature_,temperature);
203 
204  }
205  }
206  return temperature_;
207  }
208 
210  } // namespace Temperature
211  } // namespace OceanicPlateModels
212  } // namespace Features
213 } // namespace WorldBuilder
214 
const double DSNAN
Definition: nan.h:41
double potential_mantle_temperature
Definition: world.h:268
std::pair< std::vector< double >, std::vector< double > > spreading_velocities
Definition: plate_model.h:96
Operations string_operations_to_enum(const std::string &operation)
static void declare_entries(Parameters &prm, const std::string &parent_name="")
Definition: plate_model.cc:59
std::vector< double > calculate_ridge_distance_and_spreading(std::vector< std::vector< Point< 2 >>> mid_oceanic_ridges, std::vector< std::vector< double >> mid_oceanic_spreading_velocities, const std::unique_ptr< WorldBuilder::CoordinateSystems::Interface > &coordinate_system, const Objects::NaturalCoordinate &position_in_natural_coordinates_at_min_depth, const std::vector< std::vector< double >> &subducting_plate_velocities, const std::vector< double > &ridge_migration_times)
Definition: utilities.cc:1290
#define WBAssert(condition, message)
Definition: assert.h:27
#define WB_REGISTER_FEATURE_OCEANIC_PLATE_TEMPERATURE_MODEL(classname, name)
Definition: interface.h:151
double thermal_diffusivity
Definition: world.h:293
void parse_entries(Parameters &prm, const std::vector< Point< 2 >> &coordinates) override final
Definition: plate_model.cc:92
double get_temperature(const Point< 3 > &position, const Objects::NaturalCoordinate &position_in_natural_coordinates, const double depth, const double gravity, double temperature, const double feature_min_depth, const double feature_max_depth) const override final
Definition: plate_model.cc:134
std::vector< std::vector< Point< 2 > > > mid_oceanic_ridges
Definition: plate_model.h:97
SurfaceValueInfo local_value(const Point< 2 > &check_point) const
Definition: surface.cc:149
std::unique_ptr< WorldBuilder::CoordinateSystems::Interface > coordinate_system
Definition: parameters.h:268
double thermal_expansion_coefficient
Definition: world.h:283
std::pair< std::vector< double >, std::vector< double > > get_value_at_array(const std::string &name)
Definition: parameters.cc:719
double apply_operation(const Operations operation, const double old_value, const double new_value)
double sin(const double raw_angle)
Definition: point.h:81
constexpr double PI
Definition: consts.h:30
void declare_entry(const std::string &name, const Types::Interface &type, const std::string &documentation)
Definition: parameters.cc:197
Parameters parameters
Definition: world.h:253
std::vector< T > get_vector(const std::string &name)
T get(const std::string &name)
std::vector< std::vector< double > > spreading_velocities_at_each_ridge_point
Definition: plate_model.h:98