diff --git a/include/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.h b/include/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.h
new file mode 100644
index 000000000..19a072880
--- /dev/null
+++ b/include/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.h
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_FEATURES_CONTINENTAL_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+#define WORLD_BUILDER_FEATURES_CONTINENTAL_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+
+
+#include "world_builder/features/continental_plate_models/grains/interface.h"
+#include "world_builder/objects/surface.h"
+
+namespace WorldBuilder
+{
+ class Parameters;
+
+ namespace Features
+ {
+ namespace ContinentalPlateModels
+ {
+ namespace Grains
+ {
+ /**
+ * This class represents a continental plate and can implement
+ * submodules for temperature and grains. These submodules determine
+ * what the returned temperature or grains of the temperature and grains
+ * functions of this class will be.
+ */
+ class RandomUniformDistributionDeflected final : public Interface
+ {
+ public:
+ /**
+ * constructor
+ */
+ RandomUniformDistributionDeflected(WorldBuilder::World *world);
+
+ /**
+ * Destructor
+ */
+ ~RandomUniformDistributionDeflected() override final;
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_grain_size_model_entries(
+ Parameters &prm, const std::string &parent_name,
+ const std::vector &required_entries);
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void
+ declare_fixed_size_model_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ void parse_entries(Parameters &prm, const std::vector> &coordinates) override final;
+
+ /**
+ * Returns a grains based on the given position, composition (e.g.
+ * olivine and/or enstatite)depth in the model, gravity and current grains.
+ */
+ WorldBuilder::grains
+ get_grains(const Point<3> &position,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains,
+ const double feature_min_depth,
+ const double feature_max_depth) const override final;
+
+ private:
+ double min_depth;
+ Objects::Surface min_depth_surface;
+ double max_depth;
+ Objects::Surface max_depth_surface;
+ std::vector grains;
+ std::vector compositions;
+ std::string operation;
+ std::vector grain_sizes;
+ std::vector normalize_grain_sizes;
+ std::vector deflections;
+ };
+ } // namespace Grains
+ } // namespace ContinentalPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
+#endif
\ No newline at end of file
diff --git a/include/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.h b/include/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.h
new file mode 100644
index 000000000..ce72d5c87
--- /dev/null
+++ b/include/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_FEATURES_FAULT_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+#define WORLD_BUILDER_FEATURES_FAULT_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+
+
+#include "world_builder/features/fault_models/grains/interface.h"
+
+namespace WorldBuilder
+{
+
+ namespace Features
+ {
+ using namespace FeatureUtilities;
+ namespace FaultModels
+ {
+ namespace Grains
+ {
+ /**
+ * This class represents a fault and can implement
+ * submodules for temperature and grains. These submodules determine
+ * what the returned temperature or grains of the temperature and grains
+ * functions of this class will be.
+ */
+ class RandomUniformDistributionDeflected final: public Interface
+ {
+ public:
+ /**
+ * constructor
+ */
+ RandomUniformDistributionDeflected(WorldBuilder::World *world);
+
+ /**
+ * Destructor
+ */
+ ~RandomUniformDistributionDeflected() override final;
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_grain_size_model_entries(
+ Parameters &prm, const std::string &parent_name,
+ const std::vector &required_entries);
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void
+ declare_fixed_size_model_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ void parse_entries(Parameters &prm) override final;
+
+ /**
+ * Returns a grains based on the given position, composition (e.g.
+ * olivine and/or enstatite)depth in the model, gravity and current grains.
+ */
+ WorldBuilder::grains
+ get_grains(const Point<3> &position,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains,
+ const double feature_min_depth,
+ const double feature_max_depth,
+ const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes &distance_from_planes,
+ const AdditionalParameters &additional_parameters) const override final;
+
+ private:
+ double min_depth;
+ double max_depth;
+ std::vector grains;
+ std::vector compositions;
+ std::string operation;
+ std::vector grain_sizes;
+ std::vector normalize_grain_sizes;
+ std::vector deflections;
+ };
+ } // namespace Grains
+ } // namespace FaultModels
+ } // namespace Features
+} // namespace WorldBuilder
+
+#endif
\ No newline at end of file
diff --git a/include/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.h b/include/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.h
new file mode 100644
index 000000000..960e06f59
--- /dev/null
+++ b/include/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.h
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_FEATURES_MANTLE_LAYER_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+#define WORLD_BUILDER_FEATURES_MANTLE_LAYER_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+
+
+#include "world_builder/features/mantle_layer_models/grains/interface.h"
+#include "world_builder/objects/surface.h"
+
+namespace WorldBuilder
+{
+
+ namespace Features
+ {
+ namespace MantleLayerModels
+ {
+ namespace Grains
+ {
+ /**
+ * This class represents a mantle layer and can implement
+ * submodules for temperature and grains. These submodules determine
+ * what the returned temperature or grains of the temperature and grains
+ * functions of this class will be.
+ */
+ class RandomUniformDistributionDeflected final: public Interface
+ {
+ public:
+ /**
+ * constructor
+ */
+ RandomUniformDistributionDeflected(WorldBuilder::World *world);
+
+ /**
+ * Destructor
+ */
+ ~RandomUniformDistributionDeflected() override final;
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_grain_size_model_entries(
+ Parameters &prm, const std::string &parent_name,
+ const std::vector &required_entries);
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void
+ declare_fixed_size_model_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ void parse_entries(Parameters &prm, const std::vector> &coordinates) override final;
+
+ /**
+ * Returns a grains based on the given position, composition (e.g.
+ * olivine and/or enstatite)depth in the model, gravity and current grains.
+ */
+ WorldBuilder::grains
+ get_grains(const Point<3> &position,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains,
+ const double feature_min_depth,
+ const double feature_max_depth) const override final;
+
+ private:
+ double min_depth;
+ Objects::Surface min_depth_surface;
+ double max_depth;
+ Objects::Surface max_depth_surface;
+ std::vector grains;
+ std::vector compositions;
+ std::string operation;
+ std::vector grain_sizes;
+ std::vector normalize_grain_sizes;
+ std::vector deflections;
+ };
+ } // namespace Grains
+ } // namespace MantleLayerModels
+ } // namespace Features
+} // namespace WorldBuilder
+
+#endif
\ No newline at end of file
diff --git a/include/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.h b/include/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.h
new file mode 100644
index 000000000..4aa03e6f2
--- /dev/null
+++ b/include/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.h
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_FEATURES_OCEANIC_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+#define WORLD_BUILDER_FEATURES_OCEANIC_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+
+
+#include "world_builder/features/oceanic_plate_models/grains/interface.h"
+#include "world_builder/objects/surface.h"
+
+namespace WorldBuilder
+{
+
+ namespace Features
+ {
+ namespace OceanicPlateModels
+ {
+ namespace Grains
+ {
+ /**
+ * This class represents a continental plate and can implement
+ * submodules for temperature and grains. These submodules determine
+ * what the returned temperature or grains of the temperature and grains
+ * functions of this class will be.
+ */
+ class RandomUniformDistributionDeflected final: public Interface
+ {
+ public:
+ /**
+ * constructor
+ */
+ RandomUniformDistributionDeflected(WorldBuilder::World *world);
+
+ /**
+ * Destructor
+ */
+ ~RandomUniformDistributionDeflected() override final;
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_grain_size_model_entries(
+ Parameters &prm, const std::string &parent_name,
+ const std::vector &required_entries);
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void
+ declare_fixed_size_model_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ void parse_entries(Parameters &prm, const std::vector> &coordinates) override final;
+
+ /**
+ * Returns a grains based on the given position, composition (e.g.
+ * olivine and/or enstatite)depth in the model, gravity and current grains.
+ */
+ WorldBuilder::grains
+ get_grains(const Point<3> &position,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains,
+ const double feature_min_depth,
+ const double feature_max_depth) const override final;
+
+ private:
+ double min_depth;
+ Objects::Surface min_depth_surface;
+ double max_depth;
+ Objects::Surface max_depth_surface;
+ std::vector grains;
+ std::vector compositions;
+ std::string operation;
+ std::vector grain_sizes;
+ std::vector normalize_grain_sizes;
+ std::vector deflections;
+ };
+ } // namespace Grains
+ } // namespace OceanicPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
+#endif
\ No newline at end of file
diff --git a/include/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.h b/include/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.h
new file mode 100644
index 000000000..cc746b0f3
--- /dev/null
+++ b/include/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_FEATURES_SUBDUCTING_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+#define WORLD_BUILDER_FEATURES_SUBDUCTING_PLATE_MODELS_GRAINS_RANDOM_UNIFORM_DISTRIBUTION_DEFLECTED_H
+
+
+#include "world_builder/features/subducting_plate_models/grains/interface.h"
+
+namespace WorldBuilder
+{
+
+ namespace Features
+ {
+ namespace SubductingPlateModels
+ {
+ namespace Grains
+ {
+ /**
+ * This class represents a subducting plate and can implement
+ * submodules for temperature and grains. These submodules determine
+ * what the returned temperature or grains of the temperature and grains
+ * functions of this class will be.
+ */
+ class RandomUniformDistributionDeflected final: public Interface
+ {
+ public:
+ /**
+ * constructor
+ */
+ RandomUniformDistributionDeflected(WorldBuilder::World *world);
+
+ /**
+ * Destructor
+ */
+ ~RandomUniformDistributionDeflected() override final;
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void declare_grain_size_model_entries(
+ Parameters &prm, const std::string &parent_name,
+ const std::vector &required_entries);
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ static void
+ declare_fixed_size_model_entries(Parameters &prm,
+ const std::string &parent_name = "");
+
+ /**
+ * declare and read in the world builder file into the parameters
+ * class
+ */
+ void parse_entries(Parameters &prm) override final;
+
+ /**
+ * Returns a grains based on the given position, composition (e.g.
+ * olivine and/or enstatite)depth in the model, gravity and current grains.
+ */
+ WorldBuilder::grains
+ get_grains(const Point<3> &position,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains,
+ const double feature_min_depth,
+ const double feature_max_depth,
+ const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes &distance_from_planes,
+ const AdditionalParameters &additional_parameters) const override final;
+
+ private:
+ double min_depth;
+ double max_depth;
+ std::vector grains;
+ std::vector compositions;
+ std::string operation;
+ std::vector grain_sizes;
+ std::vector normalize_grain_sizes;
+ std::vector deflections;
+
+ };
+ } // namespace Grains
+ } // namespace SubductingPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
+#endif
\ No newline at end of file
diff --git a/include/world_builder/parameters.h b/include/world_builder/parameters.h
index 7c8df6e33..9be8762c6 100644
--- a/include/world_builder/parameters.h
+++ b/include/world_builder/parameters.h
@@ -26,6 +26,7 @@
#include "rapidjson/schema.h"
#include "world_builder/point.h"
+#include "world_builder/types/unsigned_int.h"
namespace WorldBuilder
{
@@ -40,6 +41,7 @@ namespace WorldBuilder
class Array;
class Bool;
class UnsignedInt;
+ class Int;
} // namespace Types
namespace Features
diff --git a/include/world_builder/types/int.h b/include/world_builder/types/int.h
new file mode 100644
index 000000000..73d236f69
--- /dev/null
+++ b/include/world_builder/types/int.h
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef WORLD_BUILDER_TYPES_INT_H
+#define WORLD_BUILDER_TYPES_INT_H
+
+
+#include "world_builder/types/interface.h"
+
+
+namespace WorldBuilder
+{
+ class Parameters;
+
+ namespace Types
+ {
+
+ /**
+ * This class represents a bool value with documentation
+ */
+ class Int final: public Interface
+ {
+ public:
+ /**
+ * A constructor for the load_entry function
+ */
+ Int(int default_value = 0);
+
+ /**
+ * Copy constructor
+ */
+ Int(Int const &other);
+
+ /**
+ * Destructor
+ */
+ ~Int() override final;
+
+
+ /**
+ * Todo
+ */
+ void write_schema(Parameters &prm,
+ const std::string &name,
+ const std::string &documentation) const override final;
+
+ unsigned int value {0};
+ unsigned int default_value;
+
+ protected:
+ /**
+ * This implements the actual cloneing for the clone function in the base class.
+ */
+ Int *clone_impl() const override final
+ {
+ return new Int(*this);
+ };
+ private:
+
+ };
+ } // namespace Types
+} // namespace WorldBuilder
+
+#endif
diff --git a/source/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.cc b/source/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.cc
new file mode 100644
index 000000000..9b9643310
--- /dev/null
+++ b/source/world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.cc
@@ -0,0 +1,234 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "world_builder/features/continental_plate_models/grains/random_uniform_distribution_deflected.h"
+
+#include
+
+#include "world_builder/nan.h"
+#include "world_builder/types/array.h"
+#include "world_builder/types/bool.h"
+#include "world_builder/types/double.h"
+#include "world_builder/types/object.h"
+#include "world_builder/types/one_of.h"
+#include "world_builder/types/unsigned_int.h"
+#include "world_builder/types/value_at_points.h"
+#include "world_builder/utilities.h"
+#include "world_builder/world.h"
+
+#include "world_builder/kd_tree.h"
+
+namespace WorldBuilder
+{
+ using namespace Utilities;
+
+ namespace Features
+ {
+ namespace ContinentalPlateModels
+ {
+ namespace Grains
+ {
+ RandomUniformDistributionDeflected::RandomUniformDistributionDeflected(WorldBuilder::World *world_)
+ :
+ min_depth(NaN::DSNAN),
+ max_depth(NaN::DSNAN)
+
+ {
+ this->world = world_;
+ this->name = "random uniform distribution deflected";
+ }
+
+ RandomUniformDistributionDeflected::~RandomUniformDistributionDeflected()
+ = default;
+
+ void
+ RandomUniformDistributionDeflected::declare_entries(Parameters &prm, const std::string & /*unused*/)
+ {
+ // Document plugin and require entries if needed.
+ // Add compositions to the required parameters.
+ prm.declare_entry("", Types::Object({"compositions"}),
+ "Random uniform distribution grains model. The size of the grains can be independently set "
+ "to a single value or to a random distribution.");
+
+ // Declare entries of this plugin
+ prm.declare_entry("min depth", Types::OneOf(Types::Double(0),Types::Array(Types::ValueAtPoints(0., 2.))),
+ "The depth in meters from which the composition of this feature is present.");
+ prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits::max(), 2.))),
+ "The depth in meters to which the composition of this feature is present.");
+
+ prm.declare_entry("compositions", Types::Array(Types::UnsignedInt(),0),
+ "A list with the integer labels of the composition which are present there.");
+
+ prm.declare_entry("orientation operation", Types::String("replace", std::vector {"replace"}),
+ "Whether the value should replace any value previously defined at this location (replace) or "
+ "add the value to the previously define value (add, not implemented). Replacing implies that all values not "
+ "explicitly defined are set to zero.");
+
+ prm.declare_entry("grain sizes",
+ Types::Array(Types::Double(1),0),
+ "A list of the size of all of the grains in each composition. If set to <0, the size will be randomized between 0 and 1.");
+
+ prm.declare_entry("normalize grain sizes",
+ Types::Array(Types::Bool(true),0),
+ "A list of whether the sizes of the grains should be normalized or not. If normalized, the total of the grains of a composition will be equal to 1.");
+
+ prm.declare_entry("deflections",
+ Types::Array(Types::Double(1),0),
+ "A list of the deflections of all of the grains in each composition between 0 and 1.");
+
+
+
+ }
+
+ void
+ RandomUniformDistributionDeflected::parse_entries(Parameters &prm, const std::vector> &coordinates)
+ {
+ min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
+ min_depth = min_depth_surface.minimum;
+ max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
+ max_depth = max_depth_surface.maximum;
+ compositions = prm.get_vector("compositions");
+
+ operation = prm.get("orientation operation");
+ grain_sizes = prm.get_vector("grain sizes");
+ normalize_grain_sizes = prm.get_vector("normalize grain sizes");
+ deflections = prm.get_vector("deflections");
+
+ WBAssertThrow(compositions.size() == grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and grain_sizes (" << grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == normalize_grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and normalize_grain_sizes (" << normalize_grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == deflections.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and deflections (" << deflections.size() << ").");
+ }
+
+
+ WorldBuilder::grains
+ RandomUniformDistributionDeflected::get_grains(const Point<3> & /*position_in_cartesian_coordinates*/,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains_,
+ const double /*feature_min_depth*/,
+ const double /*feature_max_depth*/) const
+ {
+ WorldBuilder::grains grains_local = grains_;
+ if (depth <= max_depth && depth >= min_depth)
+ {
+ 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;
+ 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;
+ if (depth <= max_depth_local && depth >= min_depth_local)
+ {
+ for (unsigned int i =0; i < compositions.size(); ++i)
+ {
+ if (compositions[i] == composition_number)
+ {
+ std::uniform_real_distribution<> dist(0.0,1.0);
+ for (auto &&it_rotation_matrices : grains_local.rotation_matrices)
+ {
+ // set a uniform random a_cosine_matrix per grain
+ // This function is based on an article in Graphic Gems III, written by James Arvo, Cornell University (p 116-120).
+ // The original code can be found on http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/rand_rotation.c
+ // and is licenend accourding to this website with the following licence:
+ //
+ // "The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and
+ // resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit
+ // is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems
+ // code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically,
+ // don't be a jerk, and remember that anything free comes with no guarantee.""
+ //
+ // The book saids in the preface the following: "As in the first two volumes, all of the C and C++ code in this book is in
+ // the public domain, and is yours to study, modify, and use."
+
+ // first generate three random numbers between 0 and 1 and multiply them with 2 PI or 2 for z. Note that these are not the same as phi_1, theta and phi_2.
+ const double one = dist(world->get_random_number_engine());
+ const double two = dist(world->get_random_number_engine());
+ const double three = dist(world->get_random_number_engine());
+
+ const double theta = 2.0 * Consts::PI * one * deflections[i]; // Rotation about the pole (Z)
+ const double phi = 2.0 * Consts::PI * two; // For direction of pole deflection.
+ const double z = 2.0* three * deflections[i]; //For magnitude of pole deflection.
+
+ // Compute a vector V used for distributing points over the sphere
+ // via the reflection I - V Transpose(V). This formulation of V
+ // will guarantee that if x[1] and x[2] are uniformly distributed,
+ // the reflected points will be uniform on the sphere. Note that V
+ // has length sqrt(2) to eliminate the 2 in the Householder matrix.
+
+ const double r = std::sqrt( z );
+ const double Vx = std::sin( phi ) * r;
+ const double Vy = std::cos( phi ) * r;
+ const double Vz = std::sqrt( 2.F - z );
+
+ // Compute the row vector S = Transpose(V) * R, where R is a simple
+ // rotation by theta about the z-axis. No need to compute Sz since
+ // it's just Vz.
+
+ const double st = std::sin( theta );
+ const double ct = std::cos( theta );
+ const double Sx = Vx * ct - Vy * st;
+ const double Sy = Vx * st + Vy * ct;
+
+ // Construct the rotation matrix ( V Transpose(V) - I ) R, which
+ // is equivalent to V S - R.
+
+ it_rotation_matrices[0][0] = Vx * Sx - ct;
+ it_rotation_matrices[0][1] = Vx * Sy - st;
+ it_rotation_matrices[0][2] = Vx * Vz;
+
+ it_rotation_matrices[1][0] = Vy * Sx + st;
+ it_rotation_matrices[1][1] = Vy * Sy - ct;
+ it_rotation_matrices[1][2] = Vy * Vz;
+
+ it_rotation_matrices[2][0] = Vz * Sx;
+ it_rotation_matrices[2][1] = Vz * Sy;
+ it_rotation_matrices[2][2] = 1.0 - z; // This equals Vz * Vz - 1.0
+ }
+
+ double total_size = 0;
+ for (auto &&it_sizes : grains_local.sizes)
+ {
+ it_sizes = grain_sizes[i] < 0 ? dist(world->get_random_number_engine()) : grain_sizes[i];
+ total_size += it_sizes;
+ }
+
+ if (normalize_grain_sizes[i])
+ {
+ const double one_over_total_size = 1/total_size;
+ std::transform(grains_local.sizes.begin(), grains_local.sizes.end(), grains_local.sizes.begin(),
+ [one_over_total_size](double sizes) -> double { return sizes *one_over_total_size; });
+ }
+
+
+ return grains_local;
+ }
+ }
+ }
+ }
+ return grains_local;
+ }
+ WB_REGISTER_FEATURE_CONTINENTAL_PLATE_GRAINS_MODEL(RandomUniformDistributionDeflected, random uniform distribution deflected)
+ } // namespace Grains
+ } // namespace ContinentalPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.cc b/source/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.cc
new file mode 100644
index 000000000..f0928421c
--- /dev/null
+++ b/source/world_builder/features/fault_models/grains/random_uniform_distribution_deflected.cc
@@ -0,0 +1,223 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "world_builder/features/fault_models/grains/random_uniform_distribution_deflected.h"
+
+#include
+
+#include "world_builder/nan.h"
+#include "world_builder/types/array.h"
+#include "world_builder/types/bool.h"
+#include "world_builder/types/double.h"
+#include "world_builder/types/object.h"
+#include "world_builder/types/unsigned_int.h"
+#include "world_builder/utilities.h"
+#include "world_builder/world.h"
+
+namespace WorldBuilder
+{
+ using namespace Utilities;
+
+ namespace Features
+ {
+ namespace FaultModels
+ {
+ namespace Grains
+ {
+ RandomUniformDistributionDeflected::RandomUniformDistributionDeflected(WorldBuilder::World *world_)
+ :
+ min_depth(NaN::DSNAN),
+ max_depth(NaN::DSNAN)
+
+ {
+ this->world = world_;
+ this->name = "random uniform distribution deflected";
+ }
+
+ RandomUniformDistributionDeflected::~RandomUniformDistributionDeflected()
+ = default;
+
+ void
+ RandomUniformDistributionDeflected::declare_entries(Parameters &prm, const std::string & /*unused*/)
+ {
+ // Document plugin and require entries if needed.
+ // Add compositions to the required parameters.
+ prm.declare_entry("", Types::Object({"compositions"}),
+ "Random uniform distribution grains model. The size of the grains can be independently set "
+ "to a single value or to a random distribution.");
+
+ // Declare entries of this plugin
+ prm.declare_entry("min distance fault center", Types::Double(0),
+ "The distance from the fault center in meters from which the composition of this feature is present.");
+ prm.declare_entry("max distance fault center", Types::Double(std::numeric_limits::max()),
+ "The distance from the fault in meters to which the composition of this feature is present.");
+
+ prm.declare_entry("compositions", Types::Array(Types::UnsignedInt(),0),
+ "A list with the integer labels of the composition which are present there.");
+
+ prm.declare_entry("orientation operation", Types::String("replace", std::vector {"replace"}),
+ "Whether the value should replace any value previously defined at this location (replace) or "
+ "add the value to the previously define value (add, not implemented). Replacing implies that all values not "
+ "explicitly defined are set to zero.");
+
+ prm.declare_entry("grain sizes",
+ Types::Array(Types::Double(1),0),
+ "A list of the size of all of the grains in each composition. If set to <0, the size will be randomized between 0 and 1.");
+
+ prm.declare_entry("normalize grain sizes",
+ Types::Array(Types::Bool(true),0),
+ "A list of whether the sizes of the grains should be normalized or not. If normalized, the total of the grains of a composition will be equal to 1.");
+
+ prm.declare_entry("deflections",
+ Types::Array(Types::Double(1),0),
+ "A list of the deflections of all of the grains in each composition between 0 and 1.");
+
+
+
+ }
+
+ void
+ RandomUniformDistributionDeflected::parse_entries(Parameters &prm)
+ {
+ min_depth = prm.get("min distance fault center");
+ max_depth = prm.get("max distance fault center");
+ compositions = prm.get_vector("compositions");
+
+ operation = prm.get("orientation operation");
+ grain_sizes = prm.get_vector("grain sizes");
+ normalize_grain_sizes = prm.get_vector("normalize grain sizes");
+ deflections = prm.get_vector("deflections");
+
+ WBAssertThrow(compositions.size() == grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and grain_sizes (" << grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == normalize_grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and normalize_grain_sizes (" << normalize_grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == deflections.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and deflections (" << deflections.size() << ").");
+ }
+
+
+ WorldBuilder::grains
+ RandomUniformDistributionDeflected::get_grains(const Point<3> & /*position_in_cartesian_coordinates*/,
+ const double /*depth*/,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains_,
+ const double /*feature_min_depth*/,
+ const double /*feature_max_depth*/,
+ const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes &distance_from_planes,
+ const AdditionalParameters & /*additional_parameters*/) const
+ {
+ WorldBuilder::grains grains_local = grains_;
+ if (std::fabs(distance_from_planes.distance_from_plane) <= max_depth && std::fabs(distance_from_planes.distance_from_plane) >= min_depth)
+ {
+ for (unsigned int i =0; i < compositions.size(); ++i)
+ {
+ if (compositions[i] == composition_number)
+ {
+ std::uniform_real_distribution<> dist(0.0,1.0);
+ for (auto &&it_rotation_matrices : grains_local.rotation_matrices)
+ {
+ // set a uniform random a_cosine_matrix per grain
+ // This function is based on an article in Graphic Gems III, written by James Arvo, Cornell University (p 116-120).
+ // The original code can be found on http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/rand_rotation.c
+ // and is licenend accourding to this website with the following licence:
+ //
+ // "The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and
+ // resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit
+ // is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems
+ // code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically,
+ // don't be a jerk, and remember that anything free comes with no guarantee.""
+ //
+ // The book saids in the preface the following: "As in the first two volumes, all of the C and C++ code in this book is in
+ // the public domain, and is yours to study, modify, and use."
+
+ // first generate three random numbers between 0 and 1 and multiply them with 2 PI or 2 for z. Note that these are not the same as phi_1, theta and phi_2.
+ const double one = dist(world->get_random_number_engine());
+ const double two = dist(world->get_random_number_engine());
+ const double three = dist(world->get_random_number_engine());
+
+ const double theta = 2.0 * Consts::PI * one * deflections[i]; // Rotation about the pole (Z).
+ const double phi = 2.0 * Consts::PI * two; // For direction of pole deflection.
+ const double z = 2.0* three * deflections[i]; //For magnitude of pole deflection.
+
+ // Compute a vector V used for distributing points over the sphere
+ // via the reflection I - V Transpose(V). This formulation of V
+ // will guarantee that if x[1] and x[2] are uniformly distributed,
+ // the reflected points will be uniform on the sphere. Note that V
+ // has length sqrt(2) to eliminate the 2 in the Householder matrix.
+
+ const double r = std::sqrt( z );
+ const double Vx = std::sin( phi ) * r;
+ const double Vy = std::cos( phi ) * r;
+ const double Vz = std::sqrt( 2.F - z );
+
+ // Compute the row vector S = Transpose(V) * R, where R is a simple
+ // rotation by theta about the z-axis. No need to compute Sz since
+ // it's just Vz.
+
+ const double st = std::sin( theta );
+ const double ct = std::cos( theta );
+ const double Sx = Vx * ct - Vy * st;
+ const double Sy = Vx * st + Vy * ct;
+
+ // Construct the rotation matrix ( V Transpose(V) - I ) R, which
+ // is equivalent to V S - R.
+
+ it_rotation_matrices[0][0] = Vx * Sx - ct;
+ it_rotation_matrices[0][1] = Vx * Sy - st;
+ it_rotation_matrices[0][2] = Vx * Vz;
+
+ it_rotation_matrices[1][0] = Vy * Sx + st;
+ it_rotation_matrices[1][1] = Vy * Sy - ct;
+ it_rotation_matrices[1][2] = Vy * Vz;
+
+ it_rotation_matrices[2][0] = Vz * Sx;
+ it_rotation_matrices[2][1] = Vz * Sy;
+ it_rotation_matrices[2][2] = 1.0 - z; // This equals Vz * Vz - 1.0
+ }
+
+ double total_size = 0;
+ for (auto &&it_sizes : grains_local.sizes)
+ {
+ it_sizes = grain_sizes[i] < 0 ? dist(world->get_random_number_engine()) : grain_sizes[i];
+ total_size += it_sizes;
+ }
+
+ if (normalize_grain_sizes[i])
+ {
+ const double one_over_total_size = 1/total_size;
+ std::transform(grains_local.sizes.begin(), grains_local.sizes.end(), grains_local.sizes.begin(),
+ [one_over_total_size](double sizes) -> double { return sizes *one_over_total_size; });
+ }
+
+ return grains_local;
+ }
+ }
+ }
+ return grains_local;
+ }
+ WB_REGISTER_FEATURE_FAULT_GRAINS_MODEL(RandomUniformDistributionDeflected, random uniform distribution deflected)
+ } // namespace Grains
+ } // namespace FaultModels
+ } // namespace Features
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.cc b/source/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.cc
new file mode 100644
index 000000000..aa740daba
--- /dev/null
+++ b/source/world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.cc
@@ -0,0 +1,232 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "world_builder/features/mantle_layer_models/grains/random_uniform_distribution_deflected.h"
+
+#include
+
+#include "world_builder/nan.h"
+#include "world_builder/types/array.h"
+#include "world_builder/types/bool.h"
+#include "world_builder/types/double.h"
+#include "world_builder/types/object.h"
+#include "world_builder/types/one_of.h"
+#include "world_builder/types/unsigned_int.h"
+#include "world_builder/types/value_at_points.h"
+#include "world_builder/utilities.h"
+#include "world_builder/world.h"
+
+namespace WorldBuilder
+{
+ using namespace Utilities;
+
+ namespace Features
+ {
+ namespace MantleLayerModels
+ {
+ namespace Grains
+ {
+ RandomUniformDistributionDeflected::RandomUniformDistributionDeflected(WorldBuilder::World *world_)
+ :
+ min_depth(NaN::DSNAN),
+ max_depth(NaN::DSNAN)
+
+ {
+ this->world = world_;
+ this->name = "random uniform distribution deflected";
+ }
+
+ RandomUniformDistributionDeflected::~RandomUniformDistributionDeflected()
+ = default;
+
+ void
+ RandomUniformDistributionDeflected::declare_entries(Parameters &prm, const std::string & /*unused*/)
+ {
+ // Document plugin and require entries if needed.
+ // Add compositions to the required parameters.
+ prm.declare_entry("", Types::Object({"compositions"}),
+ "Random uniform distribution grains model. The size of the grains can be independently set "
+ "to a single value or to a random distribution.");
+
+ // Declare entries of this plugin
+ prm.declare_entry("min depth", Types::OneOf(Types::Double(0),Types::Array(Types::ValueAtPoints(0., 2.))),
+ "The depth in meters from which the composition of this feature is present.");
+ prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits::max(), 2.))),
+ "The depth in meters to which the composition of this feature is present.");
+
+ prm.declare_entry("compositions", Types::Array(Types::UnsignedInt(),0),
+ "A list with the integer labels of the composition which are present there.");
+
+ prm.declare_entry("orientation operation", Types::String("replace", std::vector {"replace"}),
+ "Whether the value should replace any value previously defined at this location (replace) or "
+ "add the value to the previously define value (add, not implemented). Replacing implies that all values not "
+ "explicitly defined are set to zero.");
+
+ prm.declare_entry("grain sizes",
+ Types::Array(Types::Double(1),0),
+ "A list of the size of all of the grains in each composition. If set to <0, the size will be randomized between 0 and 1.");
+
+ prm.declare_entry("normalize grain sizes",
+ Types::Array(Types::Bool(true),0),
+ "A list of whether the sizes of the grains should be normalized or not. If normalized, the total of the grains of a composition will be equal to 1.");
+
+ prm.declare_entry("deflections",
+ Types::Array(Types::Double(1),0),
+ "A list of the deflections of all of the grains in each composition between 0 and 1.");
+
+
+
+ }
+
+ void
+ RandomUniformDistributionDeflected::parse_entries(Parameters &prm, const std::vector> &coordinates)
+ {
+ min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
+ min_depth = min_depth_surface.minimum;
+ max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
+ max_depth = max_depth_surface.maximum;
+ compositions = prm.get_vector("compositions");
+
+ operation = prm.get("orientation operation");
+ grain_sizes = prm.get_vector("grain sizes");
+ normalize_grain_sizes = prm.get_vector("normalize grain sizes");
+ deflections = prm.get_vector("deflections");
+
+ WBAssertThrow(compositions.size() == grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and grain_sizes (" << grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == normalize_grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and normalize_grain_sizes (" << normalize_grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == deflections.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and deflections (" << deflections.size() << ").");
+ }
+
+
+ WorldBuilder::grains
+ RandomUniformDistributionDeflected::get_grains(const Point<3> & /*position_in_cartesian_coordinates*/,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains_,
+ const double /*feature_min_depth*/,
+ const double /*feature_max_depth*/) const
+ {
+ WorldBuilder::grains grains_local = grains_;
+ if (depth <= max_depth && depth >= min_depth)
+ {
+ 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;
+ 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;
+ if (depth <= max_depth_local && depth >= min_depth_local)
+ {
+ for (unsigned int i =0; i < compositions.size(); ++i)
+ {
+ if (compositions[i] == composition_number)
+ {
+ std::uniform_real_distribution<> dist(0.0,1.0);
+ for (auto &&it_rotation_matrices : grains_local.rotation_matrices)
+ {
+ // set a uniform random a_cosine_matrix per grain
+ // This function is based on an article in Graphic Gems III, written by James Arvo, Cornell University (p 116-120).
+ // The original code can be found on http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/rand_rotation.c
+ // and is licenend accourding to this website with the following licence:
+ //
+ // "The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and
+ // resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit
+ // is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems
+ // code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically,
+ // don't be a jerk, and remember that anything free comes with no guarantee.""
+ //
+ // The book saids in the preface the following: "As in the first two volumes, all of the C and C++ code in this book is in
+ // the public domain, and is yours to study, modify, and use."
+
+ // first generate three random numbers between 0 and 1 and multiply them with 2 PI or 2 for z. Note that these are not the same as phi_1, theta and phi_2.
+ const double one = dist(world->get_random_number_engine());
+ const double two = dist(world->get_random_number_engine());
+ const double three = dist(world->get_random_number_engine());
+
+ // the distribution is restricted by the deflection (between 0 and 1)
+ const double theta = 2.0 * Consts::PI * one * deflections[i]; // Rotation about the pole (Z)
+ const double phi = 2.0 * Consts::PI * two; // For direction of pole deflection.
+ const double z = 2.0* three * deflections[i]; //For magnitude of pole deflection.
+
+ // Compute a vector V used for distributing points over the sphere
+ // via the reflection I - V Transpose(V). This formulation of V
+ // will guarantee that if x[1] and x[2] are uniformly distributed,
+ // the reflected points will be uniform on the sphere. Note that V
+ // has length sqrt(2) to eliminate the 2 in the Householder matrix.
+
+ const double r = std::sqrt( z );
+ const double Vx = std::sin( phi ) * r;
+ const double Vy = std::cos( phi ) * r;
+ const double Vz = std::sqrt( 2.F - z );
+
+ // Compute the row vector S = Transpose(V) * R, where R is a simple
+ // rotation by theta about the z-axis. No need to compute Sz since
+ // it's just Vz.
+
+ const double st = std::sin( theta );
+ const double ct = std::cos( theta );
+ const double Sx = Vx * ct - Vy * st;
+ const double Sy = Vx * st + Vy * ct;
+
+ // Construct the rotation matrix ( V Transpose(V) - I ) R, which
+ // is equivalent to V S - R.
+
+ it_rotation_matrices[0][0] = Vx * Sx - ct;
+ it_rotation_matrices[0][1] = Vx * Sy - st;
+ it_rotation_matrices[0][2] = Vx * Vz;
+
+ it_rotation_matrices[1][0] = Vy * Sx + st;
+ it_rotation_matrices[1][1] = Vy * Sy - ct;
+ it_rotation_matrices[1][2] = Vy * Vz;
+
+ it_rotation_matrices[2][0] = Vz * Sx;
+ it_rotation_matrices[2][1] = Vz * Sy;
+ it_rotation_matrices[2][2] = 1.0 - z; // This equals Vz * Vz - 1.0
+ }
+
+ double total_size = 0;
+ for (auto &&it_sizes : grains_local.sizes)
+ {
+ it_sizes = grain_sizes[i] < 0 ? dist(world->get_random_number_engine()) : grain_sizes[i];
+ total_size += it_sizes;
+ }
+
+ if (normalize_grain_sizes[i])
+ {
+ const double one_over_total_size = 1/total_size;
+ std::transform(grains_local.sizes.begin(), grains_local.sizes.end(), grains_local.sizes.begin(),
+ [one_over_total_size](double sizes) -> double { return sizes *one_over_total_size; });
+ }
+
+ return grains_local;
+ }
+ }
+ }
+ }
+ return grains_local;
+ }
+ WB_REGISTER_FEATURE_MANTLE_LAYER_GRAINS_MODEL(RandomUniformDistributionDeflected, random uniform distribution deflected)
+ } // namespace Grains
+ } // namespace MantleLayerModels
+ } // namespace Features
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.cc b/source/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.cc
new file mode 100644
index 000000000..ee9eb1a80
--- /dev/null
+++ b/source/world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.cc
@@ -0,0 +1,232 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "world_builder/features/oceanic_plate_models/grains/random_uniform_distribution_deflected.h"
+
+#include
+
+#include "world_builder/kd_tree.h"
+#include "world_builder/nan.h"
+#include "world_builder/types/array.h"
+#include "world_builder/types/bool.h"
+#include "world_builder/types/double.h"
+#include "world_builder/types/object.h"
+#include "world_builder/types/one_of.h"
+#include "world_builder/types/unsigned_int.h"
+#include "world_builder/types/value_at_points.h"
+#include "world_builder/utilities.h"
+#include "world_builder/world.h"
+
+namespace WorldBuilder
+{
+ using namespace Utilities;
+
+ namespace Features
+ {
+ namespace OceanicPlateModels
+ {
+ namespace Grains
+ {
+ RandomUniformDistributionDeflected::RandomUniformDistributionDeflected(WorldBuilder::World *world_)
+ :
+ min_depth(NaN::DSNAN),
+ max_depth(NaN::DSNAN)
+
+ {
+ this->world = world_;
+ this->name = "random uniform distribution deflected";
+ }
+
+ RandomUniformDistributionDeflected::~RandomUniformDistributionDeflected()
+ = default;
+
+ void
+ RandomUniformDistributionDeflected::declare_entries(Parameters &prm, const std::string & /*unused*/)
+ {
+ // Document plugin and require entries if needed.
+ // Add compositions to the required parameters.
+ prm.declare_entry("", Types::Object({"compositions"}),
+ "Random uniform distribution grains model. The size of the grains can be independently set "
+ "to a single value or to a random distribution.");
+
+ // Declare entries of this plugin
+ prm.declare_entry("min depth", Types::OneOf(Types::Double(0),Types::Array(Types::ValueAtPoints(0., 2.))),
+ "The depth in meters from which the composition of this feature is present.");
+ prm.declare_entry("max depth", Types::OneOf(Types::Double(std::numeric_limits::max()),Types::Array(Types::ValueAtPoints(std::numeric_limits::max(), 2.))),
+ "The depth in meters to which the composition of this feature is present.");
+
+ prm.declare_entry("compositions", Types::Array(Types::UnsignedInt(),0),
+ "A list with the integer labels of the composition which are present there.");
+
+ prm.declare_entry("orientation operation", Types::String("replace", std::vector {"replace"}),
+ "Whether the value should replace any value previously defined at this location (replace) or "
+ "add the value to the previously define value (add, not implemented). Replacing implies that all values not "
+ "explicitly defined are set to zero.");
+
+ prm.declare_entry("grain sizes",
+ Types::Array(Types::Double(1),0),
+ "A list of the size of all of the grains in each composition. If set to <0, the size will be randomized between 0 and 1.");
+
+ prm.declare_entry("normalize grain sizes",
+ Types::Array(Types::Bool(true),0),
+ "A list of whether the sizes of the grains should be normalized or not. If normalized, the total of the grains of a composition will be equal to 1.");
+
+ prm.declare_entry("deflections",
+ Types::Array(Types::Double(1),0),
+ "A list of the deflections of all of the grains in each composition between 0 and 1.");
+
+
+
+ }
+
+ void
+ RandomUniformDistributionDeflected::parse_entries(Parameters &prm, const std::vector> &coordinates)
+ {
+ min_depth_surface = Objects::Surface(prm.get("min depth",coordinates));
+ min_depth = min_depth_surface.minimum;
+ max_depth_surface = Objects::Surface(prm.get("max depth",coordinates));
+ max_depth = max_depth_surface.maximum;
+ compositions = prm.get_vector("compositions");
+
+ operation = prm.get("orientation operation");
+ grain_sizes = prm.get_vector("grain sizes");
+ normalize_grain_sizes = prm.get_vector("normalize grain sizes");
+ deflections = prm.get_vector("deflections");
+
+ WBAssertThrow(compositions.size() == grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and grain_sizes (" << grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == normalize_grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and normalize_grain_sizes (" << normalize_grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == deflections.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and deflections (" << deflections.size() << ").");
+ }
+
+
+ WorldBuilder::grains
+ RandomUniformDistributionDeflected::get_grains(const Point<3> & /*position_in_cartesian_coordinates*/,
+ const Objects::NaturalCoordinate &position_in_natural_coordinates,
+ const double depth,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains_,
+ const double /*feature_min_depth*/,
+ const double /*feature_max_depth*/) const
+ {
+ WorldBuilder::grains grains_local = grains_;
+ if (depth <= max_depth && depth >= min_depth)
+ {
+ 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;
+ 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;
+ if (depth <= max_depth_local && depth >= min_depth_local)
+ {
+ for (unsigned int i =0; i < compositions.size(); ++i)
+ {
+ if (compositions[i] == composition_number)
+ {
+ std::uniform_real_distribution<> dist(0.0,1.0);
+ for (auto &&it_rotation_matrices : grains_local.rotation_matrices)
+ {
+ // set a uniform random a_cosine_matrix per grain
+ // This function is based on an article in Graphic Gems III, written by James Arvo, Cornell University (p 116-120).
+ // The original code can be found on http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/rand_rotation.c
+ // and is licenend accourding to this website with the following licence:
+ //
+ // "The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and
+ // resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit
+ // is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems
+ // code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically,
+ // don't be a jerk, and remember that anything free comes with no guarantee.""
+ //
+ // The book saids in the preface the following: "As in the first two volumes, all of the C and C++ code in this book is in
+ // the public domain, and is yours to study, modify, and use."
+
+ // first generate three random numbers between 0 and 1 and multiply them with 2 PI or 2 for z. Note that these are not the same as phi_1, theta and phi_2.
+ const double one = dist(world->get_random_number_engine());
+ const double two = dist(world->get_random_number_engine());
+ const double three = dist(world->get_random_number_engine());
+
+ const double theta = 2.0 * Consts::PI * one * deflections[i]; // Rotation about the pole (Z)
+ const double phi = 2.0 * Consts::PI * two; // For direction of pole deflection.
+ const double z = 2.0* three * deflections[i]; //For magnitude of pole deflection.
+
+ // Compute a vector V used for distributing points over the sphere
+ // via the reflection I - V Transpose(V). This formulation of V
+ // will guarantee that if x[1] and x[2] are uniformly distributed,
+ // the reflected points will be uniform on the sphere. Note that V
+ // has length sqrt(2) to eliminate the 2 in the Householder matrix.
+
+ const double r = std::sqrt( z );
+ const double Vx = std::sin( phi ) * r;
+ const double Vy = std::cos( phi ) * r;
+ const double Vz = std::sqrt( 2.F - z );
+
+ // Compute the row vector S = Transpose(V) * R, where R is a simple
+ // rotation by theta about the z-axis. No need to compute Sz since
+ // it's just Vz.
+
+ const double st = std::sin( theta );
+ const double ct = std::cos( theta );
+ const double Sx = Vx * ct - Vy * st;
+ const double Sy = Vx * st + Vy * ct;
+
+ // Construct the rotation matrix ( V Transpose(V) - I ) R, which
+ // is equivalent to V S - R.
+
+ it_rotation_matrices[0][0] = Vx * Sx - ct;
+ it_rotation_matrices[0][1] = Vx * Sy - st;
+ it_rotation_matrices[0][2] = Vx * Vz;
+
+ it_rotation_matrices[1][0] = Vy * Sx + st;
+ it_rotation_matrices[1][1] = Vy * Sy - ct;
+ it_rotation_matrices[1][2] = Vy * Vz;
+
+ it_rotation_matrices[2][0] = Vz * Sx;
+ it_rotation_matrices[2][1] = Vz * Sy;
+ it_rotation_matrices[2][2] = 1.0 - z; // This equals Vz * Vz - 1.0
+ }
+
+ double total_size = 0;
+ for (auto &&it_sizes : grains_local.sizes)
+ {
+ it_sizes = grain_sizes[i] < 0 ? dist(world->get_random_number_engine()) : grain_sizes[i];
+ total_size += it_sizes;
+ }
+
+ if (normalize_grain_sizes[i])
+ {
+ const double one_over_total_size = 1/total_size;
+ std::transform(grains_local.sizes.begin(), grains_local.sizes.end(), grains_local.sizes.begin(),
+ [one_over_total_size](double sizes) -> double { return sizes *one_over_total_size; });
+ }
+
+ return grains_local;
+ }
+ }
+ }
+ }
+ return grains_local;
+ }
+ WB_REGISTER_FEATURE_OCEANIC_PLATE_GRAINS_MODEL(RandomUniformDistributionDeflected, random uniform distribution deflected)
+ } // namespace Grains
+ } // namespace OceanicPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.cc b/source/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.cc
new file mode 100644
index 000000000..d998fc0ae
--- /dev/null
+++ b/source/world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.cc
@@ -0,0 +1,223 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "world_builder/features/subducting_plate_models/grains/random_uniform_distribution_deflected.h"
+
+#include
+
+#include "world_builder/nan.h"
+#include "world_builder/types/array.h"
+#include "world_builder/types/bool.h"
+#include "world_builder/types/double.h"
+#include "world_builder/types/object.h"
+#include "world_builder/types/unsigned_int.h"
+#include "world_builder/utilities.h"
+#include "world_builder/world.h"
+
+namespace WorldBuilder
+{
+ using namespace Utilities;
+
+ namespace Features
+ {
+ namespace SubductingPlateModels
+ {
+ namespace Grains
+ {
+ RandomUniformDistributionDeflected::RandomUniformDistributionDeflected(WorldBuilder::World *world_)
+ :
+ min_depth(NaN::DSNAN),
+ max_depth(NaN::DSNAN)
+
+ {
+ this->world = world_;
+ this->name = "random uniform distribution deflected";
+ }
+
+ RandomUniformDistributionDeflected::~RandomUniformDistributionDeflected()
+ = default;
+
+ void
+ RandomUniformDistributionDeflected::declare_entries(Parameters &prm, const std::string & /*unused*/)
+ {
+ // Document plugin and require entries if needed.
+ // Add compositions to the required parameters.
+ prm.declare_entry("", Types::Object({"compositions"}),
+ "Random uniform distribution grains model. The size of the grains can be independently set "
+ "to a single value or to a random distribution.");
+
+ // Declare entries of this plugin
+ prm.declare_entry("min distance slab top", Types::Double(0),
+ "The distance from the slab top in meters from which the composition of this feature is present.");
+ prm.declare_entry("max distance slab top", Types::Double(std::numeric_limits::max()),
+ "The distance from the slab top in meters to which the composition of this feature is present.");
+
+ prm.declare_entry("compositions", Types::Array(Types::UnsignedInt(),0),
+ "A list with the integer labels of the composition which are present there.");
+
+ prm.declare_entry("orientation operation", Types::String("replace", std::vector {"replace"}),
+ "Whether the value should replace any value previously defined at this location (replace) or "
+ "add the value to the previously define value (add, not implemented). Replacing implies that all values not "
+ "explicitly defined are set to zero.");
+
+ prm.declare_entry("grain sizes",
+ Types::Array(Types::Double(1),0),
+ "A list of the size of all of the grains in each composition. If set to <0, the size will be randomized between 0 and 1.");
+
+ prm.declare_entry("normalize grain sizes",
+ Types::Array(Types::Bool(true),0),
+ "A list of whether the sizes of the grains should be normalized or not. If normalized, the total of the grains of a composition will be equal to 1.");
+
+ prm.declare_entry("deflections",
+ Types::Array(Types::Double(1),0),
+ "A list of the deflections of all of the grains in each composition between 0 and 1.");
+
+
+
+ }
+
+ void
+ RandomUniformDistributionDeflected::parse_entries(Parameters &prm)
+ {
+ min_depth = prm.get("min distance slab top");
+ max_depth = prm.get("max distance slab top");
+ compositions = prm.get_vector("compositions");
+
+ operation = prm.get("orientation operation");
+ grain_sizes = prm.get_vector("grain sizes");
+ normalize_grain_sizes = prm.get_vector("normalize grain sizes");
+ deflections = prm.get_vector("deflections");
+
+ WBAssertThrow(compositions.size() == grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and grain_sizes (" << grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == normalize_grain_sizes.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and normalize_grain_sizes (" << normalize_grain_sizes.size() << ").");
+ WBAssertThrow(compositions.size() == deflections.size(),
+ "There are not the same amount of compositions (" << compositions.size()
+ << ") and deflections (" << deflections.size() << ").");
+ }
+
+
+ WorldBuilder::grains
+ RandomUniformDistributionDeflected::get_grains(const Point<3> & /*position_in_cartesian_coordinates*/,
+ const double /*depth*/,
+ const unsigned int composition_number,
+ WorldBuilder::grains grains_,
+ const double /*feature_min_depth*/,
+ const double /*feature_max_depth*/,
+ const WorldBuilder::Utilities::PointDistanceFromCurvedPlanes &distance_from_planes,
+ const AdditionalParameters & /*additional_parameters*/) const
+ {
+ WorldBuilder::grains grains_local = grains_;
+ if (distance_from_planes.distance_from_plane <= max_depth && distance_from_planes.distance_from_plane >= min_depth)
+ {
+ for (unsigned int i =0; i < compositions.size(); ++i)
+ {
+ if (compositions[i] == composition_number)
+ {
+ std::uniform_real_distribution<> dist(0.0,1.0);
+ for (auto &&it_rotation_matrices : grains_local.rotation_matrices)
+ {
+ // set a uniform random a_cosine_matrix per grain
+ // This function is based on an article in Graphic Gems III, written by James Arvo, Cornell University (p 116-120).
+ // The original code can be found on http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/rand_rotation.c
+ // and is licenend accourding to this website with the following licence:
+ //
+ // "The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and
+ // resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit
+ // is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems
+ // code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically,
+ // don't be a jerk, and remember that anything free comes with no guarantee.""
+ //
+ // The book saids in the preface the following: "As in the first two volumes, all of the C and C++ code in this book is in
+ // the public domain, and is yours to study, modify, and use."
+
+ // first generate three random numbers between 0 and 1 and multiply them with 2 PI or 2 for z. Note that these are not the same as phi_1, theta and phi_2.
+ const double one = dist(world->get_random_number_engine());
+ const double two = dist(world->get_random_number_engine());
+ const double three = dist(world->get_random_number_engine());
+
+ const double theta = 2.0 * Consts::PI * one * deflections[i]; // Rotation about the pole (Z)
+ const double phi = 2.0 * Consts::PI * two; // For direction of pole deflection.
+ const double z = 2.0* three * deflections[i]; //For magnitude of pole deflection.
+
+ // Compute a vector V used for distributing points over the sphere
+ // via the reflection I - V Transpose(V). This formulation of V
+ // will guarantee that if x[1] and x[2] are uniformly distributed,
+ // the reflected points will be uniform on the sphere. Note that V
+ // has length sqrt(2) to eliminate the 2 in the Householder matrix.
+
+ const double r = std::sqrt( z );
+ const double Vx = std::sin( phi ) * r;
+ const double Vy = std::cos( phi ) * r;
+ const double Vz = std::sqrt( 2.F - z );
+
+ // Compute the row vector S = Transpose(V) * R, where R is a simple
+ // rotation by theta about the z-axis. No need to compute Sz since
+ // it's just Vz.
+
+ const double st = std::sin( theta );
+ const double ct = std::cos( theta );
+ const double Sx = Vx * ct - Vy * st;
+ const double Sy = Vx * st + Vy * ct;
+
+ // Construct the rotation matrix ( V Transpose(V) - I ) R, which
+ // is equivalent to V S - R.
+
+ it_rotation_matrices[0][0] = Vx * Sx - ct;
+ it_rotation_matrices[0][1] = Vx * Sy - st;
+ it_rotation_matrices[0][2] = Vx * Vz;
+
+ it_rotation_matrices[1][0] = Vy * Sx + st;
+ it_rotation_matrices[1][1] = Vy * Sy - ct;
+ it_rotation_matrices[1][2] = Vy * Vz;
+
+ it_rotation_matrices[2][0] = Vz * Sx;
+ it_rotation_matrices[2][1] = Vz * Sy;
+ it_rotation_matrices[2][2] = 1.0 - z; // This equals Vz * Vz - 1.0
+ }
+
+ double total_size = 0;
+ for (auto &&it_sizes : grains_local.sizes)
+ {
+ it_sizes = grain_sizes[i] < 0 ? dist(world->get_random_number_engine()) : grain_sizes[i];
+ total_size += it_sizes;
+ }
+
+ if (normalize_grain_sizes[i])
+ {
+ const double one_over_total_size = 1/total_size;
+ std::transform(grains_local.sizes.begin(), grains_local.sizes.end(), grains_local.sizes.begin(),
+ [one_over_total_size](double sizes) -> double { return sizes *one_over_total_size; });
+ }
+
+ return grains_local;
+ }
+ }
+ }
+ return grains_local;
+ }
+ WB_REGISTER_FEATURE_SUBDUCTING_PLATE_GRAINS_MODEL(RandomUniformDistributionDeflected, random uniform distribution deflected)
+ } // namespace Grains
+ } // namespace SubductingPlateModels
+ } // namespace Features
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/parameters.cc b/source/world_builder/parameters.cc
index 920cd5c21..f3519efe6 100644
--- a/source/world_builder/parameters.cc
+++ b/source/world_builder/parameters.cc
@@ -296,6 +296,40 @@ namespace WorldBuilder
const std::string base = this->get_full_json_path();
const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
+#ifdef debug
+ bool required = false;
+ if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
+ {
+ for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
+ {
+ if (v.GetString() == name)
+ {
+ required = true;
+ }
+ }
+ }
+
+ WBAssert(value != NULL || required == false,
+ "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
+#endif
+ if (value == nullptr)
+ {
+ value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
+ WBAssertThrow(value != nullptr,
+ "internal error: could not retrieve the default value at: "
+ << base + "/" + name + "/default value");
+ }
+
+ return value->GetUint();
+ }
+
+ template<>
+ int
+ Parameters::get(const std::string &name)
+ {
+ const std::string base = this->get_full_json_path();
+ const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
+
#ifdef debug
bool required = false;
if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
diff --git a/source/world_builder/types/int.cc b/source/world_builder/types/int.cc
new file mode 100644
index 000000000..155bececb
--- /dev/null
+++ b/source/world_builder/types/int.cc
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2018 - 2021 by the authors of the World Builder code.
+
+ This file is part of the World Builder.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+#include "world_builder/types/int.h"
+
+#include "world_builder/parameters.h"
+
+namespace WorldBuilder
+{
+ namespace Types
+ {
+ Int::Int(int default_value_)
+ :
+
+ default_value(default_value_)
+ {
+ this->type_name = Types::type::Int;
+ }
+
+
+ Int::Int(Int const &other)
+ :
+ value(other.value),
+ default_value(other.default_value)
+ {
+ this->type_name = Types::type::Int;
+ }
+
+ Int::~Int ()
+ = default;
+
+
+ void
+ Int::write_schema(Parameters &prm,
+ const std::string &name,
+ const std::string &documentation) const
+ {
+ using namespace rapidjson;
+ Document &declarations = prm.declarations;
+
+ const std::string base = prm.get_full_json_path() + "/" + name;
+ Pointer((base + "/default value").c_str()).Set(declarations,default_value);
+ Pointer((base + "/type").c_str()).Set(declarations,"integer");
+ Pointer((base + "/description").c_str()).Set(declarations,documentation.c_str());
+
+ }
+ } // namespace Types
+} // namespace WorldBuilder
+
diff --git a/source/world_builder/world.cc b/source/world_builder/world.cc
index b8dec8659..2a826696c 100644
--- a/source/world_builder/world.cc
+++ b/source/world_builder/world.cc
@@ -30,6 +30,7 @@
#include "world_builder/types/object.h"
#include "world_builder/types/plugin_system.h"
#include "world_builder/types/point.h"
+#include "world_builder/types/int.h"
#include
#include
@@ -143,6 +144,9 @@ namespace WorldBuilder
prm.declare_entry("features", Types::PluginSystem("",Features::Interface::declare_entries, {"model"}),"A list of features.");
+ prm.declare_entry("random number seed", Types::Int(-1),
+ "Use random number seed input to generate random numbers.");
+
}
prm.leave_subsection();
@@ -240,6 +244,14 @@ namespace WorldBuilder
maximum_distance_between_coordinates = prm.get("maximum distance between coordinates");
interpolation = prm.get("interpolation");
+ /**
+ * Local random number seed parameter
+ */
+ const int local_seed = prm.get("random number seed");
+
+ if (local_seed>=0)
+ random_number_engine.seed(local_seed);
+
/**
* Now load the features. Some features use for example temperature values,
* so it is important that this is parsed the last.
diff --git a/tests/gwb-dat/random_uniform_texture_all_features.dat b/tests/gwb-dat/random_uniform_texture_all_features.dat
new file mode 100644
index 000000000..d0c093e2e
--- /dev/null
+++ b/tests/gwb-dat/random_uniform_texture_all_features.dat
@@ -0,0 +1,20 @@
+# This is a comment in the data
+# file.
+# Now define parameters:
+# dim = 3
+# compositions = 5
+# grain compositions = 1
+# number of grains = 1
+# x y z d c1 c2 c3 c4
+300e3 500e3 0 50e3
+1400e3 500e3 0 50e3
+1600e3 500e3 0 50e3
+1800e3 500e3 0 50e3
+500e3 500e3 0 300e3
+2000e3 500e3 0 400e3
+1500e3 500e3 0 50e3
+1400e3 500e3 0 200e3
+950e3 500e3 0 50e3
+1050e3 500e3 0 50e3
+950e3 500e3 0 210e3
+1050e3 500e3 0 210e3
diff --git a/tests/gwb-dat/random_uniform_texture_all_features.wb b/tests/gwb-dat/random_uniform_texture_all_features.wb
new file mode 100644
index 000000000..9372d2ea5
--- /dev/null
+++ b/tests/gwb-dat/random_uniform_texture_all_features.wb
@@ -0,0 +1,54 @@
+{
+ "version": "0.6",
+ "coordinate system":{"model":"cartesian"},
+ "random number seed":1000,
+ "features":
+ [
+ {
+ "model":"continental plate", "name":"Overriding Plate", "max depth":100e3,
+ "coordinates":[[0,0],[0,1000e3],[1500e3,1000e3],[1500e3,0]],
+ "temperature models":[{"model":"uniform", "temperature":293}],
+ "composition models":[{"model":"uniform", "compositions":[0]}],
+ "grains models": [{"model":"random uniform distribution deflected", "compositions":[0], "grain sizes":[-1],
+ "normalize grain sizes":[true], "deflections":[0.1]}]
+ },
+
+ {
+ "model":"oceanic plate", "name":"Subducting Plate", "max depth":100e3,
+ "coordinates":[[1500e3,0],[1500e3,1000e3],[2500e3,1000e3],[2500e3,0]],
+ "temperature models":[{"model":"uniform", "temperature":293}],
+ "composition models":[{"model":"uniform", "compositions":[1]}],
+ "grains models": [{"model":"random uniform distribution deflected", "compositions":[0], "grain sizes":[-1],
+ "normalize grain sizes":[true], "deflections":[0.2]}]
+ },
+
+ {
+ "model":"mantle layer", "name":"Mantle", "min depth":100e3,
+ "coordinates":[[0,0],[0,1000e3],[2500e3,1000e3],[2500e3,0]],
+ "temperature models":[{"model":"uniform", "temperature":293}],
+ "composition models":[{"model":"uniform", "compositions":[2]}],
+ "grains models": [{"model":"random uniform distribution deflected", "compositions":[0], "grain sizes":[-1],
+ "normalize grain sizes":[true], "deflections":[0.3]}]
+ },
+
+ {
+ "model":"subducting plate", "name":"Slab", "min depth":0e3,
+ "coordinates":[[1500e3,0],[1500e3,500e3],[1500e3,1000e3]], "dip point":[10, 10],
+ "segments":[{"length":500e3, "thickness":[100e3], "angle":[50]}],
+ "temperature models":[{"model":"uniform", "temperature":10}],
+ "composition models":[{"model":"uniform", "compositions":[3]}],
+ "grains models": [{"model":"random uniform distribution deflected", "compositions":[0], "grain sizes":[-1],
+ "normalize grain sizes":[true], "deflections":[0.4]}]
+ },
+
+ {
+ "model":"fault", "name":"Fault", "min depth":0e3,
+ "coordinates":[[1000e3,0],[1000e3,500e3],[1000e3,1000e3]], "dip point":[10, 10],
+ "segments":[{"length":200e3, "thickness":[200e3], "angle":[90]}],
+ "temperature models":[{"model":"uniform", "temperature":10}],
+ "composition models":[{"model":"uniform", "compositions":[4]}],
+ "grains models": [{"model":"random uniform distribution deflected", "compositions":[0], "grain sizes":[-1],
+ "normalize grain sizes":[true], "deflections":[0.5]}]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/gwb-dat/random_uniform_texture_all_features/screen-output.log b/tests/gwb-dat/random_uniform_texture_all_features/screen-output.log
new file mode 100644
index 000000000..3ecc83849
--- /dev/null
+++ b/tests/gwb-dat/random_uniform_texture_all_features/screen-output.log
@@ -0,0 +1,13 @@
+# x y z d g T c0 c1 c2 c3 c4 gs0-0 gm0-0[0:0] gm0-0[0:1] gm0-0[0:2] gm0-0[1:0] gm0-0[1:1] gm0-0[1:2] gm0-0[2:0] gm0-0[2:1] gm0-0[2:2] tag
+300e3 500e3 0 50e3 293 1 0 0 0 0 1 -0.990972 -0.127666 -0.0409292 0.129618 -0.990341 -0.0492332 -0.0342484 -0.0540939 0.997948 0
+1400e3 500e3 0 50e3 293 1 0 0 0 0 1 -0.863294 -0.503742 0.0311121 0.479282 -0.798937 0.363301 -0.158154 0.328547 0.931152 0
+1600e3 500e3 0 50e3 293 0 1 0 0 0 1 -0.55876 -0.762818 -0.325417 0.720801 -0.252629 -0.645465 0.410162 -0.595221 0.690999 1
+1800e3 500e3 0 50e3 293 0 1 0 0 0 1 -0.994372 -0.0277444 0.102248 0.0963064 -0.638921 0.76322 0.0441535 0.768772 0.637997 1
+500e3 500e3 0 300e3 293 0 0 1 0 0 1 -0.88545 -0.216658 -0.411142 0.0819602 -0.943615 0.32074 -0.45745 0.250302 0.853281 2
+2000e3 500e3 0 400e3 293 0 0 1 0 0 1 -0.505877 -0.721112 -0.473377 0.730473 -0.65 0.209545 -0.4588 -0.239785 0.855573 2
+1500e3 500e3 0 50e3 10 0 0 0 1 0 1 0.277217 -0.320014 -0.905948 0.59042 0.800607 -0.102137 0.757994 -0.506575 0.410885 3
+1400e3 500e3 0 200e3 10 0 0 0 1 0 1 0.784316 -0.497925 -0.370026 0.616522 0.559361 0.55409 -0.0689168 -0.662711 0.745697 3
+950e3 500e3 0 50e3 10 0 0 0 0 1 1 -0.459173 -0.634613 -0.621632 -0.305909 -0.544008 0.781329 -0.834014 0.548928 0.05566 4
+1050e3 500e3 0 50e3 10 0 0 0 0 1 1 0.615449 -0.728911 0.299852 0.271936 0.553452 0.787237 -0.739779 -0.402964 0.538839 4
+950e3 500e3 0 210e3 293 0 0 1 0 0 1 -0.577637 -0.64995 -0.493863 0.410363 -0.754211 0.51261 -0.705647 0.0934395 0.702375 2
+1050e3 500e3 0 210e3 293 0 0 1 0 0 1 0.248301 -0.967981 0.0368649 0.636139 0.134242 -0.759807 0.73053 0.212112 0.649103 2