World Builder  1.1.0-pre
A geodynamic initial conditions generator
fault.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 "glm/glm.h"
31 #include "world_builder/world.h"
32 #include <algorithm>
33 
34 using namespace std;
35 
36 namespace WorldBuilder
37 {
38  using namespace Utilities;
39 
40  namespace Features
41  {
42  Fault::Fault(WorldBuilder::World *world_)
43  :
44  reference_point(0,0,cartesian)
45  {
46  this->world = world_;
47  this->name = "fault";
48  }
49 
51  = default;
52 
53 
54 
56  {
57  using namespace rapidjson;
58  Document &declarations = prm.declarations;
59 
60  const std::string path = prm.get_full_json_path();
61 
62  Pointer((path + "/body").c_str()).Set(declarations,"object");
63  Pointer((path + "/body/model").c_str()).Set(declarations,"fault");
64  Pointer((path + "/body/name").c_str()).Set(declarations,"${1:My Fault}");
65  Pointer((path + "/body/coordinates").c_str()).Create(declarations).SetArray();
66  Pointer((path + "/body/segments").c_str()).Create(declarations).SetArray();
67  Pointer((path + "/body/sections").c_str()).Create(declarations).SetArray();
68  }
69 
70 
71 
72  void
74  const std::string &parent_name,
75  const std::vector<std::string> &required_entries)
76  {
77 
78  // This statement is needed because of the recursion associated with
79  // the sections entry.
80  if (parent_name == "items")
81  {
82  prm.enter_subsection("properties");
83  }
84  else
85  {
86  prm.declare_entry("", Types::Object(required_entries), "Fault object. Requires properties `model` and `coordinates`.");
87  }
88  prm.declare_entry("min depth", Types::Double(0),
89  "The depth to which this feature is present");
90  prm.declare_entry("max depth", Types::Double(std::numeric_limits<double>::max()),
91  "The depth to which this feature is present");
92  prm.declare_entry("dip point", Types::Point<2>(),
93  "The depth to which this feature is present");
94 
100  "The depth to which this feature is present");
101 
102  prm.declare_entry("temperature models",
104  "A list of temperature models.");
105  prm.declare_entry("composition models",
107  "A list of composition models.");
108  prm.declare_entry("grains models",
110  "A list of grains models.");
111  prm.declare_entry("velocity models",
113  "A list of velocity models.");
114 
115  if (parent_name != "items")
116  {
117  // This only happens if we are not in sections
118  prm.declare_entry("sections", Types::Array(Types::PluginSystem("",Features::Fault::declare_entries, {"coordinate"}, false)),"A list of feature properties for a coordinate.");
119  }
120  else
121  {
122 
123  // this only happens in sections
124  prm.declare_entry("coordinate", Types::UnsignedInt(0),
125  "The coordinate which should be overwritten");
126 
127  prm.leave_subsection();
128  }
129  }
130 
131  void
133  {
134  const CoordinateSystem coordinate_system = prm.coordinate_system->natural_coordinate_system();
135 
136  this->name = prm.get<std::string>("name");
137 
138  std::string tag = prm.get<std::string>("tag");
139  if (tag == "")
140  {
141  tag = "fault";
142  }
144 
145  this->get_coordinates("coordinates", prm, coordinate_system);
146 
147 
148  starting_depth = prm.get<double>("min depth");
149  maximum_depth = prm.get<double>("max depth");
150 
151  const size_t n_sections = this->original_number_of_coordinates;
152 
153  reference_point = prm.get<Point<2> >("dip point");
154 
155  if (coordinate_system == spherical)
156  {
157  // When spherical, input is in degrees, so change to radians for internal use.
158  reference_point *= (Consts::PI/180);
159  }
160 
161  default_temperature_models.resize(0);
162  default_composition_models.resize(0);
163  default_grains_models.resize(0);
164  default_velocity_models.resize(0);
169 
170  // get the default segments.
175 
176 
177  // This vector stores segments to this coordinate/section.
178  // First used (raw) pointers to the segment relevant to this coordinate/section,
179  // but I do not trust it won't fail when memory is moved. So storing the all the data now.
180  segment_vector.resize(0);
181  segment_vector.resize(n_sections, default_segment_vector);
182 
183 
184  // now search whether a section is present, if so, replace the default segments.
185  std::vector<std::unique_ptr<Features::Fault> > sections_vector;
186  prm.get_unique_pointers("sections", sections_vector);
187 
188  prm.enter_subsection("sections");
189  for (unsigned int i_section = 0; i_section < n_sections; ++i_section)
190  {
191  // first check whether this section/coordinate has a a special overwrite
192  for (unsigned int i_sector = 0; i_sector < sections_vector.size(); ++i_sector)
193  {
194  prm.enter_subsection(std::to_string(i_sector));
195  {
196  const unsigned int change_coord_number = prm.get<unsigned int>("coordinate");
197 
198  WBAssertThrow(segment_vector.size() > change_coord_number, "Error: for subducting plate with name: '" << this->name
199  << "', trying to change the section of coordinate " << change_coord_number
200  << " while only " << segment_vector.size() << " coordinates are defined.");
201 
202  std::vector<std::shared_ptr<Features::FaultModels::Temperature::Interface> > local_default_temperature_models;
203  std::vector<std::shared_ptr<Features::FaultModels::Composition::Interface> > local_default_composition_models;
204  std::vector<std::shared_ptr<Features::FaultModels::Grains::Interface> > local_default_grains_models;
205  std::vector<std::shared_ptr<Features::FaultModels::Velocity::Interface> > local_default_velocity_models;
206 
207  if (!prm.get_shared_pointers<Features::FaultModels::Temperature::Interface>("temperature models", local_default_temperature_models))
208  {
209  // no local temperature model, use global default
210  local_default_temperature_models = default_temperature_models;
211  }
212 
213  if (!prm.get_shared_pointers<Features::FaultModels::Composition::Interface>("composition models", local_default_composition_models))
214  {
215  // no local composition model, use global default
216  local_default_composition_models = default_composition_models;
217  }
218 
219  if (!prm.get_shared_pointers<Features::FaultModels::Grains::Interface>("grains models", local_default_grains_models))
220  {
221  // no local grains model, use global default
222  local_default_grains_models = default_grains_models;
223  }
224 
225  if (!prm.get_shared_pointers<Features::FaultModels::Velocity::Interface>("velocity models", local_default_velocity_models))
226  {
227  // no local velocity model, use global default
228  local_default_velocity_models = default_velocity_models;
229  }
230 
231  segment_vector[change_coord_number] = prm.get_vector<Objects::Segment<Features::FaultModels::Temperature::Interface,
232  Features::FaultModels::Composition::Interface,
233  Features::FaultModels::Grains::Interface,
234  Features::FaultModels::Velocity::Interface> >("segments", local_default_temperature_models, local_default_composition_models, local_default_grains_models, local_default_velocity_models);
235 
236  WBAssertThrow(segment_vector[change_coord_number].size() == default_segment_vector.size(),
237  "Error: There are not the same amount of segments in section with coordinate " << change_coord_number
238  << " (" << segment_vector[change_coord_number].size() << " segments) as in the default segment ("
239  << default_segment_vector.size() << " segments). This is not allowed.");
240 
241  prm.enter_subsection("segments");
242  {
243  for (unsigned int i = 0; i < segment_vector[change_coord_number].size(); ++i)
244  {
245  prm.enter_subsection(std::to_string(i));
246  {
247  prm.enter_subsection("temperature models");
248  {
249  for (unsigned int j = 0; j < segment_vector[change_coord_number][i].temperature_systems.size(); ++j)
250  {
251  prm.enter_subsection(std::to_string(j));
252  {
253  segment_vector[change_coord_number][i].temperature_systems[j]->parse_entries(prm);
254  }
255  prm.leave_subsection();
256  }
257  }
258  prm.leave_subsection();
259 
260 
261  prm.enter_subsection("composition models");
262  {
263  for (unsigned int j = 0; j < segment_vector[change_coord_number][i].composition_systems.size(); ++j)
264  {
265  prm.enter_subsection(std::to_string(j));
266  {
267  segment_vector[change_coord_number][i].composition_systems[j]->parse_entries(prm);
268  }
269  prm.leave_subsection();
270  }
271  }
272  prm.leave_subsection();
273 
274 
275  prm.enter_subsection("grains models");
276  {
277  for (unsigned int j = 0; j < segment_vector[change_coord_number][i].grains_systems.size(); ++j)
278  {
279  prm.enter_subsection(std::to_string(j));
280  {
281  segment_vector[change_coord_number][i].grains_systems[j]->parse_entries(prm);
282  }
283  prm.leave_subsection();
284  }
285  }
286  prm.leave_subsection();
287 
288  prm.enter_subsection("velocity models");
289  {
290  for (unsigned int j = 0; j < segment_vector[change_coord_number][i].velocity_systems.size(); ++j)
291  {
292  prm.enter_subsection(std::to_string(j));
293  {
294  segment_vector[change_coord_number][i].velocity_systems[j]->parse_entries(prm);
295  }
296  prm.leave_subsection();
297  }
298  }
299  prm.leave_subsection();
300  }
301  prm.leave_subsection();
302  }
303  }
304  prm.leave_subsection();
305 
306  }
307  prm.leave_subsection();
308  }
309 
310  }
311  prm.leave_subsection();
312 
313 
314  prm.enter_subsection("segments");
315  {
316  for (unsigned int i = 0; i < default_segment_vector.size(); ++i)
317  {
318  prm.enter_subsection(std::to_string(i));
319  {
320  prm.enter_subsection("temperature models");
321  {
322  for (unsigned int j = 0; j < default_segment_vector[i].temperature_systems.size(); ++j)
323  {
324  prm.enter_subsection(std::to_string(j));
325  {
326  default_segment_vector[i].temperature_systems[j]->parse_entries(prm);
327  }
328  prm.leave_subsection();
329  }
330  }
331  prm.leave_subsection();
332 
333 
334  prm.enter_subsection("composition models");
335  {
336  for (unsigned int j = 0; j < default_segment_vector[i].composition_systems.size(); ++j)
337  {
338  prm.enter_subsection(std::to_string(j));
339  {
340  default_segment_vector[i].composition_systems[j]->parse_entries(prm);
341  }
342  prm.leave_subsection();
343  }
344  }
345  prm.leave_subsection();
346 
347 
348  prm.enter_subsection("grains models");
349  {
350  for (unsigned int j = 0; j < default_segment_vector[i].grains_systems.size(); ++j)
351  {
352  prm.enter_subsection(std::to_string(j));
353  {
354  default_segment_vector[i].grains_systems[j]->parse_entries(prm);
355  }
356  prm.leave_subsection();
357  }
358  }
359  prm.leave_subsection();
360 
361  prm.enter_subsection("velocity models");
362  {
363  for (unsigned int j = 0; j < default_segment_vector[i].velocity_systems.size(); ++j)
364  {
365  prm.enter_subsection(std::to_string(j));
366  {
367  default_segment_vector[i].velocity_systems[j]->parse_entries(prm);
368  }
369  prm.leave_subsection();
370  }
371  }
372  prm.leave_subsection();
373  }
374  prm.leave_subsection();
375  }
376  }
377  prm.leave_subsection();
378 
379 
387 
388  for (unsigned int i = 0; i < segment_vector.size(); ++i)
389  {
390  double local_total_fault_length = 0;
391  fault_segment_lengths[i].resize(segment_vector[i].size());
394  fault_segment_angles[i].resize(segment_vector[i].size(), Point<2>(invalid));
395 
396  for (unsigned int j = 0; j < segment_vector[i].size(); ++j)
397  {
398  fault_segment_lengths[i][j] = segment_vector[i][j].value_length;
399  local_total_fault_length += segment_vector[i][j].value_length;
400 
401  fault_segment_thickness[i][j] = segment_vector[i][j].value_thickness;
404  fault_segment_top_truncation[i][j] = segment_vector[i][j].value_top_truncation;
405 
406  fault_segment_angles[i][j] = segment_vector[i][j].value_angle * (Consts::PI/180);
407  }
408  total_fault_length[i] = local_total_fault_length;
409  maximum_total_fault_length = std::max(maximum_total_fault_length, local_total_fault_length);
410  }
411 
412 
413  // Find minimal and maximal coordinates. Do this by finding the
414  // leftmost/rightmost point with regard to either the [0] or [1]
415  // coordinate, and then takes its [0] or [1] element.
416  auto compare_x_coordinate = [](auto p1, auto p2)
417  {
418  return p1[0]<p2[0];
419  };
420 
421  min_along_x = (*std::min_element(coordinates.begin(), coordinates.end(), compare_x_coordinate)) [0];
422  max_along_x = (*std::max_element(coordinates.begin(), coordinates.end(), compare_x_coordinate)) [0];
423 
424 
425  auto compare_y_coordinate = [](auto p1, auto p2)
426  {
427  return p1[1]<p2[1];
428  };
429 
430  min_along_y = (*std::min_element(coordinates.begin(), coordinates.end(), compare_y_coordinate)) [1];
431  max_along_y = (*std::max_element(coordinates.begin(), coordinates.end(), compare_y_coordinate)) [1];
432 
435 
436 
437  // Compute the surface bounding box
439  if (world->parameters.coordinate_system->natural_coordinate_system() == CoordinateSystem::spherical)
440  {
441  const double starting_radius_inv = 1 / (world->parameters.coordinate_system->max_model_depth());
442  std::pair<Point<2>, Point<2> > &spherical_bounding_box = surface_bounding_box.get_boundary_points();
443 
444  const double buffer_around_fault_spherical = 2 * Consts::PI * buffer_around_fault_cartesian * starting_radius_inv;
445 
446  spherical_bounding_box.first = {(min_along_x - buffer_around_fault_spherical * min_lat_cos_inv) ,
447  (min_along_y - buffer_around_fault_spherical), spherical
448  } ;
449 
450  spherical_bounding_box.second = {(max_along_x + buffer_around_fault_spherical * max_lat_cos_inv) ,
451  (max_along_y + buffer_around_fault_spherical), spherical
452  };
453  }
454  else if (world->parameters.coordinate_system->natural_coordinate_system() == CoordinateSystem::cartesian)
455  {
456  std::pair<Point<2>, Point<2> > &bounding_box = surface_bounding_box.get_boundary_points();
457  bounding_box.first = {min_along_x, min_along_y, cartesian};
458  bounding_box.second = {max_along_x, max_along_y, cartesian};
460  }
461  }
462 
463 
464  const BoundingBox<2> &
466  {
467  return surface_bounding_box;
468  }
469 
470 
471  void
472  Fault::properties(const Point<3> &position_in_cartesian_coordinates,
473  const Objects::NaturalCoordinate &position_in_natural_coordinates,
474  const double depth,
475  const std::vector<std::array<unsigned int,3>> &properties,
476  const double gravity_norm,
477  const std::vector<size_t> &entry_in_output,
478  std::vector<double> &output) const
479  {
480  // The 'depth coordinate' is the z-coordinate in Cartesian coordinates, and radius in spherical coordinates.
481  // The depth input parameter is the distance from the surface to the position,
482  // the starting radius is the distance from the bottom of the model to the surface.
483  const double starting_radius = position_in_natural_coordinates.get_depth_coordinate() + depth - starting_depth;
484 
485  WBAssert(std::abs(starting_radius) > std::numeric_limits<double>::epsilon(), "World Builder error: starting_radius can not be zero. "
486  << "Position = " << position_in_cartesian_coordinates[0] << ':' << position_in_cartesian_coordinates[1] << ':' << position_in_cartesian_coordinates[2]
487  << ", position_in_natural_coordinates.get_depth_coordinate() = " << position_in_natural_coordinates.get_depth_coordinate()
488  << ", depth = " << depth
489  << ", starting_depth " << starting_depth
490  );
491 
492  // todo: explain and check -starting_depth
493  if (depth <= maximum_depth && depth >= starting_depth && depth <= maximum_total_fault_length + maximum_fault_thickness &&
494  get_surface_bounding_box().point_inside(Point<2>(position_in_natural_coordinates.get_surface_coordinates(),
495  world->parameters.coordinate_system->natural_coordinate_system())))
496  {
497  // todo: explain
498  const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes distance_from_planes =
499  WorldBuilder::Utilities::distance_point_from_curved_planes(position_in_cartesian_coordinates,
500  position_in_natural_coordinates,
502  coordinates,
505  starting_radius,
507  true,
508  this->bezier_curve);
509 
510  const double distance_from_plane = distance_from_planes.distance_from_plane;
511  const double distance_along_plane = distance_from_planes.distance_along_plane;
512  const double section_fraction = distance_from_planes.fraction_of_section;
513  const size_t current_section = distance_from_planes.section;
514  const size_t next_section = current_section + 1;
515  const size_t current_segment = distance_from_planes.segment;
516  const double segment_fraction = distance_from_planes.fraction_of_segment;
517 
518  if (abs(distance_from_plane) < std::numeric_limits<double>::infinity() || (distance_along_plane) < std::numeric_limits<double>::infinity())
519  {
520  // We want to do both section (horizontal) and segment (vertical) interpolation.
521  // first for thickness
522  const double thickness_up = fault_segment_thickness[current_section][current_segment][0]
523  + section_fraction
524  * (fault_segment_thickness[next_section][current_segment][0]
525  - fault_segment_thickness[current_section][current_segment][0]);
526  const double thickness_down = fault_segment_thickness[current_section][current_segment][1]
527  + section_fraction
528  * (fault_segment_thickness[next_section][current_segment][1]
529  - fault_segment_thickness[current_section][current_segment][1]);
530  const double thickness_local = thickness_up + segment_fraction * (thickness_down - thickness_up);
531 
532 
533  // if the thickness is zero, we don't need to compute anything, so return.
534  if (std::fabs(thickness_local) < 2.0 * std::numeric_limits<double>::epsilon())
535  return;
536 
537  // secondly for top truncation
538  const double top_truncation_up = fault_segment_top_truncation[current_section][current_segment][0]
539  + section_fraction
540  * (fault_segment_top_truncation[next_section][current_segment][0]
541  - fault_segment_top_truncation[current_section][current_segment][0]);
542  const double top_truncation_down = fault_segment_top_truncation[current_section][current_segment][1]
543  + section_fraction
544  * (fault_segment_top_truncation[next_section][current_segment][1]
545  - fault_segment_top_truncation[current_section][current_segment][1]);
546  const double top_truncation_local = top_truncation_up + segment_fraction * (top_truncation_down - top_truncation_up);
547 
548  // if the thickness is smaller than what is truncated off at the top, we don't need to compute anything, so return.
549  if (thickness_local < top_truncation_local)
550  return;
551 
552 
553 
554  const double max_fault_length = total_fault_length[current_section] +
555  section_fraction *
556  (total_fault_length[next_section] - total_fault_length[current_section]);
557  const AdditionalParameters additional_parameters = {max_fault_length,thickness_local};
558 
559  // Check if we are inside the fault.
560  // Every distance from -thickness/2 to +thickness/2 is inside the fault.
561  if (std::fabs(distance_from_plane) <= thickness_local * 0.5 &&
562  distance_along_plane > 0 &&
563  distance_along_plane <= max_fault_length)
564  {
565  for (unsigned int i_property = 0; i_property < properties.size(); ++i_property)
566  {
567  switch (properties[i_property][0])
568  {
569  case 1: // temperature
570  {
571  double temperature_current_section = output[entry_in_output[i_property]];
572  double temperature_next_section = output[entry_in_output[i_property]];
573 
574  for (const auto &temperature_model: segment_vector[current_section][current_segment].temperature_systems)
575  {
576  temperature_current_section = temperature_model->get_temperature(position_in_cartesian_coordinates,
577  depth,
578  gravity_norm,
579  temperature_current_section,
580  starting_depth,
582  distance_from_planes,
583  additional_parameters);
584 
585  WBAssert(!std::isnan(temperature_current_section), "Temperature is not a number: " << temperature_current_section
586  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
587  WBAssert(std::isfinite(temperature_current_section), "Temperature is not finite: " << temperature_current_section
588  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
589 
590  }
591 
592  for (const auto &temperature_model: segment_vector[next_section][current_segment].temperature_systems)
593  {
594  temperature_next_section = temperature_model->get_temperature(position_in_cartesian_coordinates,
595  depth,
596  gravity_norm,
597  temperature_next_section,
598  starting_depth,
600  distance_from_planes,
601  additional_parameters);
602 
603  WBAssert(!std::isnan(temperature_next_section), "Temperature is not a number: " << temperature_next_section
604  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
605  WBAssert(std::isfinite(temperature_next_section), "Temperature is not a finite: " << temperature_next_section
606  << ", based on a temperature model with the name " << temperature_model->get_name() << ", in feature " << this->name);
607 
608  }
609 
610  // linear interpolation between current and next section temperatures
611  output[entry_in_output[i_property]] = temperature_current_section + section_fraction * (temperature_next_section - temperature_current_section);
612  break;
613  }
614  case 2: // composition
615  {
616  double composition_current_section = output[entry_in_output[i_property]];
617  double composition_next_section = output[entry_in_output[i_property]];
618 
619  for (const auto &composition_model: segment_vector[current_section][current_segment].composition_systems)
620  {
621  composition_current_section = composition_model->get_composition(position_in_cartesian_coordinates,
622  depth,
623  properties[i_property][1],
624  composition_current_section,
625  starting_depth,
627  distance_from_planes,
628  additional_parameters);
629 
630  WBAssert(!std::isnan(composition_current_section), "Composition_current_section is not a number: " << composition_current_section
631  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
632  WBAssert(std::isfinite(composition_current_section), "Composition_current_section is not finite: " << composition_current_section
633  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
634 
635  }
636 
637  for (const auto &composition_model: segment_vector[next_section][current_segment].composition_systems)
638  {
639  composition_next_section = composition_model->get_composition(position_in_cartesian_coordinates,
640  depth,
641  properties[i_property][1],
642  composition_next_section,
643  starting_depth,
645  distance_from_planes,
646  additional_parameters);
647 
648  WBAssert(!std::isnan(composition_next_section), "Composition_next_section is not a number: " << composition_next_section
649  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
650  WBAssert(std::isfinite(composition_next_section), "Composition_next_section is not finite: " << composition_next_section
651  << ", based on a composition model with the name " << composition_model->get_name() << ", in feature " << this->name);
652 
653  }
654 
655  // linear interpolation between current and next section temperatures
656  output[entry_in_output[i_property]] = composition_current_section + section_fraction * (composition_next_section - composition_current_section);
657  break;
658  }
659  case 3: // grains
660  {
661  WorldBuilder::grains grains(output,properties[i_property][2],entry_in_output[i_property]);
662  WorldBuilder::grains grains_current_section = grains;
663  WorldBuilder::grains grains_next_section = grains;
664 
665  for (const auto &grains_model: segment_vector[current_section][current_segment].grains_systems)
666  {
667  grains_current_section = grains_model->get_grains(position_in_cartesian_coordinates,
668  depth,
669  properties[i_property][1],
670  grains_current_section,
671  starting_depth,
673  distance_from_planes,
674  additional_parameters);
675 
676  }
677 
678  for (const auto &grains_model: segment_vector[next_section][current_segment].grains_systems)
679  {
680  grains_next_section = grains_model->get_grains(position_in_cartesian_coordinates,
681  depth,
682  properties[i_property][1],
683  grains_next_section,
684  starting_depth,
686  distance_from_planes,
687  additional_parameters);
688 
689  }
690 
691  // linear interpolation between current and next section temperatures
692  for (size_t i = 0; i < grains.sizes.size(); i++)
693  {
694  grains.sizes[i] = grains_current_section.sizes[i] + section_fraction * (grains_next_section.sizes[i] - grains_current_section.sizes[i]);
695  }
696 
697  // average two rotations matrices through quaternions.
698  for (size_t i = 0; i < grains_current_section.rotation_matrices.size(); i++)
699  {
700  const glm::quaternion::quat quat_current = glm::quaternion::quat_cast(grains_current_section.rotation_matrices[i]);
701  const glm::quaternion::quat quat_next = glm::quaternion::quat_cast(grains_next_section.rotation_matrices[i]);
702 
703  const glm::quaternion::quat quat_average = glm::quaternion::slerp(quat_current,quat_next,section_fraction);
704 
705  grains.rotation_matrices[i] = glm::quaternion::mat3_cast(quat_average);
706  }
707 
708  grains.unroll_into(output,entry_in_output[i_property]);
709  break;
710  }
711  case 4:
712  {
713  output[entry_in_output[i_property]] = static_cast<double>(tag_index);
714  break;
715  }
716  case 5: // velocity
717  {
718  std::array<double,3> velocity_current_section;// = Point<3>(cartesian);
719  velocity_current_section[0] = output[entry_in_output[i_property]];
720  velocity_current_section[1] = output[entry_in_output[i_property]+1];
721  velocity_current_section[2] = output[entry_in_output[i_property]]+2;
722  std::array<double,3> velocity_next_section = velocity_current_section;// output[entry_in_output[i_property]];
723 
724  for (const auto &velocity_model: segment_vector[current_section][current_segment].velocity_systems)
725  {
726  velocity_current_section = velocity_model->get_velocity(position_in_cartesian_coordinates,
727  depth,
728  gravity_norm,
729  velocity_current_section,
730  starting_depth,
732  distance_from_planes,
733  additional_parameters);
734 
735  //WBAssert(!std::isnan(velocity_current_section), "Velocity is not a number: " << velocity_current_section
736  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
737  //WBAssert(std::isfinite(velocity_current_section), "Velocity is not a finite: " << velocity_current_section
738  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
739 
740  }
741 
742  for (const auto &velocity_model: segment_vector[next_section][current_segment].velocity_systems)
743  {
744  velocity_next_section = velocity_model->get_velocity(position_in_cartesian_coordinates,
745  depth,
746  gravity_norm,
747  velocity_next_section,
748  starting_depth,
750  distance_from_planes,
751  additional_parameters);
752 
753  //WBAssert(!std::isnan(velocity_next_section), "Velocity is not a number: " << velocity_next_section
754  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
755  //WBAssert(std::isfinite(velocity_next_section), "Velocity is not a finite: " << velocity_next_section
756  // << ", based on a velocity model with the name " << velocity_model->get_name() << ", in feature " << this->name);
757 
758  }
759 
760  // linear interpolation between current and next section velocitys
761  output[entry_in_output[i_property]] = velocity_current_section[0] + section_fraction * (velocity_next_section[0] - velocity_current_section[0]);
762  output[entry_in_output[i_property]+1] = velocity_current_section[1] + section_fraction * (velocity_next_section[1] - velocity_current_section[1]);
763  output[entry_in_output[i_property]+2] = velocity_current_section[2] + section_fraction * (velocity_next_section[2] - velocity_current_section[2]);
764  break;
765  }
766  default:
767  {
768  WBAssertThrow(false,
769  "Internal error: Unimplemented property provided. " <<
770  "Only temperature (1), composition (2), grains (3) or tag (4) are allowed. "
771  "Provided property number was: " << properties[i_property][0]);
772  }
773  }
774  }
775 
776  }
777  }
778  }
779 
780  }
781 
783  Fault::distance_to_feature_plane(const Point<3> &position_in_cartesian_coordinates,
784  const Objects::NaturalCoordinate &position_in_natural_coordinates,
785  const double depth) const
786  {
787  // The depth variable is the distance from the surface to the position, the depth
788  // coordinate is the distance from the bottom of the model to the position and
789  // the starting radius is the distance from the bottom of the model to the surface.
790  const double starting_radius = position_in_natural_coordinates.get_depth_coordinate() + depth - starting_depth;
791 
792  WBAssert(std::abs(starting_radius) > std::numeric_limits<double>::epsilon(), "World Builder error: starting_radius can not be zero. "
793  << "Position = " << position_in_cartesian_coordinates[0] << ':' << position_in_cartesian_coordinates[1] << ':' << position_in_cartesian_coordinates[2]
794  << ", natural_coordinate.get_depth_coordinate() = " << position_in_natural_coordinates.get_depth_coordinate()
795  << ", depth = " << depth
796  << ", starting_depth " << starting_depth
797  );
798 
799  const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes distance_from_planes =
800  WorldBuilder::Utilities::distance_point_from_curved_planes(position_in_cartesian_coordinates,
801  position_in_natural_coordinates,
803  coordinates,
806  starting_radius,
808  false,
809  this->bezier_curve);
810 
811  Objects::PlaneDistances plane_distances(distance_from_planes.distance_from_plane, distance_from_planes.distance_along_plane);
812  return plane_distances;
813  }
814 
818  WB_REGISTER_FEATURE(Fault, fault)
819  } // namespace Features
820 } // namespace WorldBuilder
821 
std::vector< std::shared_ptr< Features::FaultModels::Grains::Interface > > default_grains_models
Definition: fault.h:156
std::vector< std::vector< Point< 2 > > > fault_segment_top_truncation
Definition: fault.h:220
static void declare_entries(Parameters &prm, const std::string &parent_name="", const std::vector< std::string > &required_entries={})
Definition: fault.cc:73
BoundingBox< 2 > surface_bounding_box
Definition: fault.h:211
std::array< double, 2 > get_surface_coordinates() const
std::vector< std::vector< Objects::Segment< Features::FaultModels::Temperature::Interface, Features::FaultModels::Composition::Interface, Features::FaultModels::Grains::Interface, Features::FaultModels::Velocity::Interface > > > segment_vector
Definition: fault.h:175
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)
WorldBuilder::Point< 2 > reference_point
Definition: fault.h:216
#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:42
std::vector< std::vector< double > > fault_segment_lengths
Definition: fault.h:218
bool get_shared_pointers(const std::string &name, std::vector< std::shared_ptr< T > > &)
Definition: parameters.cc:1845
void properties(const Point< 3 > &position_in_cartesian_coordinates, const Objects::NaturalCoordinate &position_in_natural_coordinates, const double depth, const std::vector< std::array< unsigned int, 3 >> &properties, const double gravity, const std::vector< size_t > &entry_in_output, std::vector< double > &output) const override final
Definition: fault.cc:472
void parse_entries(Parameters &prm) override final
Definition: fault.cc:132
std::vector< double > sizes
Definition: grains.h:47
const BoundingBox< 2 > & get_surface_bounding_box() const
Definition: fault.cc:465
std::pair< Point< spacedim >, Point< spacedim > > & get_boundary_points()
Definition: bounding_box.h:318
void extend(const double amount)
Definition: bounding_box.h:355
#define WBAssert(condition, message)
Definition: assert.h:27
std::vector< std::shared_ptr< Features::FaultModels::Velocity::Interface > > default_velocity_models
Definition: fault.h:157
std::string get_full_json_path(size_t max_size=std::numeric_limits< size_t >::max()) const
Definition: parameters.cc:1933
void get_coordinates(const std::string &name, Parameters &prm, const CoordinateSystem coordinate_system)
Definition: interface.cc:140
Objects::PlaneDistances distance_to_feature_plane(const Point< 3 > &position_in_cartesian_coordinates, const Objects::NaturalCoordinate &position_in_natural_coordinates, const double depth) const override
Definition: fault.cc:783
std::vector< std::shared_ptr< Features::FaultModels::Composition::Interface > > default_composition_models
Definition: fault.h:155
double cos(const double angle)
Definition: point.h:97
double buffer_around_fault_cartesian
Definition: fault.h:232
std::vector< Objects::Segment< Features::FaultModels::Temperature::Interface, Features::FaultModels::Composition::Interface, Features::FaultModels::Grains::Interface, Features::FaultModels::Velocity::Interface > > default_segment_vector
Definition: fault.h:162
PointDistanceFromCurvedPlanes distance_point_from_curved_planes(const Point< 3 > &check_point, const Objects::NaturalCoordinate &natural_coordinate, const Point< 2 > &reference_point, const std::vector< Point< 2 > > &point_list, const std::vector< std::vector< double > > &plane_segment_lengths, const std::vector< std::vector< Point< 2 > > > &plane_segment_angles, const double start_radius, const std::unique_ptr< CoordinateSystems::Interface > &coordinate_system, const bool only_positive, const Objects::BezierCurve &bezier_curve)
Definition: utilities.cc:380
std::vector< std::string > feature_tags
Definition: world.h:308
WorldBuilder::World * world
Definition: interface.h:127
#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
std::vector< std::vector< Point< 2 > > > fault_segment_thickness
Definition: fault.h:219
static void make_snippet(Parameters &prm)
Definition: fault.cc:55
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:40
std::unique_ptr< WorldBuilder::CoordinateSystems::Interface > coordinate_system
Definition: parameters.h:268
std::size_t original_number_of_coordinates
Definition: interface.h:149
std::vector< std::array< std::array< double, 3 >, 3 > > rotation_matrices
Definition: grains.h:51
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
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
Definition: interface.cc:42
std::vector< T > get_vector(const std::string &name)
std::vector< std::vector< Point< 2 > > > fault_segment_angles
Definition: fault.h:221
T get(const std::string &name)
rapidjson::Document declarations
Definition: parameters.h:248
std::vector< double > total_fault_length
Definition: fault.h:222
void unroll_into(std::vector< double > &vector, const size_t start_entry=0) const
Definition: grains.cc:58
std::vector< std::shared_ptr< Features::FaultModels::Temperature::Interface > > default_temperature_models
Definition: fault.h:154
std::vector< Point< 2 > > coordinates
Definition: interface.h:154
bool point_inside(const Point< spacedim > &p, const double tolerance=std::numeric_limits< double >::epsilon()) const
Definition: bounding_box.h:371