World Builder  1.1.0-pre
A geodynamic initial conditions generator
chapman.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 
23 #include "world_builder/nan.h"
29 #include "world_builder/world.h"
30 
31 
32 namespace WorldBuilder
33 {
34  using namespace Utilities;
35 
36  namespace Features
37  {
38  using namespace FeatureUtilities;
39  namespace ContinentalPlateModels
40  {
41  namespace Temperature
42  {
43  Chapman::Chapman(WorldBuilder::World *world_)
44  :
45  top_temperature(NaN::DSNAN),
46  top_heat_flux(NaN::DSNAN),
47  thermal_conductivity(NaN::DSNAN),
48  heat_production_per_unit_volume(NaN::DSNAN),
49  min_depth(NaN::DSNAN),
50  max_depth(NaN::DSNAN),
51  operation(Operations::REPLACE)
52  {
53  this->world = world_;
54  this->name = "chapman";
55  }
56 
58  = default;
59 
60  void
61  Chapman::declare_entries(Parameters &prm, const std::string & /*unused*/)
62  {
63  // Declare entries of this plugin
64  prm.declare_entry("", Types::Object(),
65  "Continental geotherm using the steady-state 1-D heat conduction equation from Chapman (1986).");
66 
67  prm.declare_entry("top temperature", Types::Double(293.15),
68  "The temperature at the top surface in K of this feature."
69  "If the value is below zero, then an adiabatic temperature is used.");
70 
71  prm.declare_entry("top heat flux", Types::Double(0.055),
72  "The heat flux at the top surface in W m^(-2) of this feature."
73  "The default value is 0.055.");
74 
75  prm.declare_entry("thermal conductivity", Types::Double(2.5),
76  "The thermal conductivity in W m^(-1) K^(-1) of this feature."
77  "The default value is 2.5.");
78 
79  prm.declare_entry("heat generation per unit volume", Types::Double(1.e-6),
80  "The heat generation per unit volume in W m^(-3) of this feature."
81  "The default value is 1e-6.");
82 
84  "The depth in m from which the composition of this feature is present.");
85 
86  prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits<double>::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits<double>::max(), 2.))),
87  "The depth in m to which the composition of this feature is present.");
88 
89  }
90 
91  void
92  Chapman::parse_entries(Parameters &prm, const std::vector<Point<2>> &coordinates)
93  {
94  min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
96  max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
98  WBAssert(max_depth >= min_depth, "max depth needs to be larger or equal to min depth.");
99  operation = string_operations_to_enum(prm.get<std::string>("operation"));
100  thermal_conductivity = prm.get<double>("thermal conductivity");
101  heat_production_per_unit_volume = prm.get<double>("heat generation per unit volume");
102  top_heat_flux = prm.get<double>("top heat flux");
103  top_temperature = prm.get<double>("top temperature");
104  WBAssert(!std::isnan(top_temperature), "Top surface temperature is not a number: " << top_temperature
105  << ", based on a temperature model with the name " << this->name);
106  }
107 
108 
109  double
110  Chapman::get_temperature(const Point<3> & /*position_in_cartesian_coordinates*/,
111  const Objects::NaturalCoordinate &position_in_natural_coordinates,
112  const double depth,
113  const double gravity_norm,
114  double temperature_,
115  const double feature_min_depth,
116  const double /*feature_max_depth*/) const
117  {
118  if (depth <= max_depth && depth >= min_depth)
119  {
120  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;
121  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;
122  if (depth <= max_depth_local && depth >= min_depth_local)
123  {
124  const double min_depth_local_local = std::max(feature_min_depth, min_depth_local);
125 
126  double top_temperature_local = top_temperature;
127 
128  // use adiabatic temperature if top temperature is below zero
129  if (top_temperature_local < 0)
130  {
131  top_temperature_local = this->world->potential_mantle_temperature *
132  std::exp(((this->world->thermal_expansion_coefficient * gravity_norm) /
133  this->world->specific_heat) * min_depth_local_local);
134  }
135 
136  // calculate the temperature at depth z using steady-state 1-D heat conduction equation:
137  // T(z) = t_top + (q_top / k) * (Δz) - (A / (2 * k)) * (Δz)^2
138  const double new_temperature = top_temperature + (top_heat_flux / thermal_conductivity) * (depth-min_depth_local_local) - heat_production_per_unit_volume / (2. * thermal_conductivity) * (depth-min_depth_local_local)*(depth-min_depth_local_local);
139 
140  WBAssert(!std::isnan(new_temperature), "Temperature is not a number: " << new_temperature
141  << ", based on a temperature model with the name " << this->name);
142  WBAssert(std::isfinite(new_temperature), "Temperature is not a finite: " << new_temperature
143  << ", based on a temperature model with the name " << this->name
144  << ", top_temperature_local = " << top_temperature_local
145  << ", depth = " << depth
146  << ", min_depth_local = " << min_depth_local
147  << ", top_heat_flux = " << top_heat_flux
148  << ", thermal_conductivity=" << thermal_conductivity
149  << ", min_depth_local_local =" << min_depth_local_local);
150 
151  return apply_operation(operation,temperature_,new_temperature);
152  }
153  }
154 
155 
156  return temperature_;
157  }
158 
160  } // namespace Temperature
161  } // namespace ContinentalPlateModels
162  } // namespace Features
163 } // namespace WorldBuilder
164 
const double DSNAN
Definition: nan.h:41
double potential_mantle_temperature
Definition: world.h:268
Operations string_operations_to_enum(const std::string &operation)
#define WBAssert(condition, message)
Definition: assert.h:27
static void declare_entries(Parameters &prm, const std::string &parent_name="")
Definition: chapman.cc:61
void parse_entries(Parameters &prm, const std::vector< Point< 2 >> &coordinates) override final
Definition: chapman.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: chapman.cc:110
SurfaceValueInfo local_value(const Point< 2 > &check_point) const
Definition: surface.cc:149
double thermal_expansion_coefficient
Definition: world.h:283
double apply_operation(const Operations operation, const double old_value, const double new_value)
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)
#define WB_REGISTER_FEATURE_CONTINENTAL_PLATE_TEMPERATURE_MODEL(classname, name)
Definition: interface.h:151