43 using namespace Utilities;
49 min_depth(NaN::
DSNAN),
68 Pointer((path +
"/body").c_str()).Set(declarations,
"object");
69 Pointer((path +
"/body/model").c_str()).Set(declarations,
"plume");
70 Pointer((path +
"/body/name").c_str()).Set(declarations,
"${1:My Plume}");
71 Pointer((path +
"/body/coordinates").c_str()).Create(declarations).SetArray();
72 Pointer((path +
"/body/temperature models").c_str()).Create(declarations).SetArray();
73 Pointer((path +
"/body/composition models").c_str()).Create(declarations).SetArray();
81 const std::vector<std::string> &required_entries)
86 "The depth from which this feature is present, in other words, the " 87 "depth of the tip of the plume. If the first entry in the cross " 88 "section depths has a greater depth, an ellipsoidal plume head will " 89 "be added in between. Units: m.");
91 "The depth to which this feature is present. Units: m.");
93 "The depths of the elliptic cross section of the plume. Units: m.");
95 "The lengths of the semi-major axes of the elliptic cross sections of the plume. " 96 "In spherical coordinates, this is in degrees, otherwise in meters.");
98 "The eccentricities of the cross sections.");
100 "The directions that the semi-major axis of the elliptic cross-sections " 101 "are pointing to, in degrees. This direction is expressed as the angle from " 102 "geographic North in spherical coordinates, or as the angle from the Y axis " 103 "(clockwise) in Cartesian coordinates. " 104 "The angle should be between 0 and 360 degrees.");
108 "A list of temperature models.");
111 "A list of composition models.");
114 "A list of grains models.");
117 "A list of velocity models.");
125 this->
name = prm.
get<std::string>(
"name");
127 std::string tag = prm.
get<std::string>(
"tag");
144 for (
unsigned int i = 0; i < depths.size()-1; ++i)
146 "The depths of the elliptic cross sections of the plume need to be listed in ascending order.");
149 "The cross section depths array needs to have the same number of entries as there are coordinates. At the moment there are: " 151 <<
" depth entries but " 156 "The semi-major axis array needs to have the same number of entries as there are coordinates. At the moment there are: " 157 << semi_major_axis_lengths.size()
158 <<
" semi-major axis entries but " 163 "The eccentricity array needs to have the same number of entries as there are coordinates. At the moment there are: " 164 << eccentricities.size()
165 <<
" eccentricity entries but " 170 "The rotation angles array needs to have the same number of entries as there are coordinates. At the moment there are: " 171 << rotation_angles.size()
172 <<
" rotation angle entries but " 178 for (
double &rotation_angle : rotation_angles)
183 for (
double &semi_major_axis_length : semi_major_axis_lengths)
257 const std::vector<std::array<unsigned int,3>> &
properties,
258 const double gravity_norm,
259 const std::vector<size_t> &entry_in_output,
260 std::vector<double> &output)
const 263 auto upper = std::upper_bound(
depths.begin(),
depths.end(), depth);
266 double semi_major_axis_length;
268 double rotation_angle;
272 else if (upper -
depths.begin() == 0)
283 const double y = (1. - fraction) * a;
286 semi_major_axis_length = std::sqrt((1 - std::pow(y/a,2)) * b*b);
288 else if (upper -
depths.end() == 0)
297 const unsigned int index =
static_cast<unsigned int>(std::distance(
depths.begin(), upper));
298 const double fraction = (depth -
depths[index-1]) / (
depths[index] -
depths[index-1]);
314 double relative_distance_from_center =
316 semi_major_axis_length,
325 const double b = a * std::sqrt(1 - std::pow(eccentricity, 2));
328 const double x = (surface_point[0] - plume_center[0]) *
std::cos(rotation_angle) + (surface_point[1] - plume_center[1])*
std::sin(rotation_angle);
329 const double y = -(surface_point[0] - plume_center[0]) *
std::sin(rotation_angle) + (surface_point[1] - plume_center[1])*
std::cos(rotation_angle);
330 const double z =
depths.front() - depth;
333 relative_distance_from_center = (x*x)/(a*a) + (y*y)/(b*b) + (z*z)/(c*c);
336 if (depth <= max_depth && depth >=
min_depth && relative_distance_from_center <= 1.)
339 for (
unsigned int i_property = 0; i_property <
properties.size(); ++i_property)
347 output[entry_in_output[i_property]] = temperature_model->get_temperature(position_in_cartesian_coordinates,
348 position_in_natural_coordinates,
351 output[entry_in_output[i_property]],
354 relative_distance_from_center);
356 WBAssert(!std::isnan(output[entry_in_output[i_property]]),
"Temperature is not a number: " << output[entry_in_output[i_property]]
357 <<
", based on a temperature model with the name " << temperature_model->get_name() <<
", in feature " << this->
name);
358 WBAssert(std::isfinite(output[entry_in_output[i_property]]),
"Temperature is not finite: " << output[entry_in_output[i_property]]
359 <<
", based on a temperature model with the name " << temperature_model->get_name() <<
", in feature " << this->
name);
367 output[entry_in_output[i_property]] = composition_model->get_composition(position_in_cartesian_coordinates,
368 position_in_natural_coordinates,
371 output[entry_in_output[i_property]],
375 WBAssert(!std::isnan(output[entry_in_output[i_property]]),
"Composition is not a number: " << output[entry_in_output[i_property]]
376 <<
", based on a composition model with the name " << composition_model->get_name() <<
", in feature " << this->
name);
377 WBAssert(std::isfinite(output[entry_in_output[i_property]]),
"Composition is not finite: " << output[entry_in_output[i_property]]
378 <<
", based on a composition model with the name " << composition_model->get_name() <<
", in feature " << this->
name);
389 grains = grains_model->get_grains(position_in_cartesian_coordinates,
390 position_in_natural_coordinates,
398 grains.
unroll_into(output,entry_in_output[i_property]);
403 output[entry_in_output[i_property]] =
static_cast<double>(
tag_index);
408 std::array<double, 3> velocity = {{0,0,0}};
411 velocity = velocity_model->get_velocity(position_in_cartesian_coordinates,
412 position_in_natural_coordinates,
418 relative_distance_from_center);
426 output[entry_in_output[i_property]] = velocity[0];
427 output[entry_in_output[i_property]+1] = velocity[1];
428 output[entry_in_output[i_property]+2] = velocity[2];
434 "Internal error: Unimplemented property provided. " <<
435 "Only temperature (1), composition (2), grains (3), tag (4) or velocity (5) are allowed. " 436 "Provided property number was: " <<
properties[i_property][0]);
std::vector< double > rotation_angles
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
std::vector< std::unique_ptr< Features::PlumeModels::Temperature::Interface > > temperature_models
std::vector< double > semi_major_axis_lengths
std::vector< std::unique_ptr< Features::PlumeModels::Velocity::Interface > > velocity_models
std::array< double, 2 > get_surface_coordinates() const
size_t add_vector_unique(std::vector< std::string > &vector, const std::string &add_string)
#define WB_REGISTER_FEATURE(classname, name)
void enter_subsection(const std::string &name)
std::vector< std::unique_ptr< Features::PlumeModels::Composition::Interface > > composition_models
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
void parse_entries(Parameters &prm) override final
std::vector< std::unique_ptr< Features::PlumeModels::Grains::Interface > > grains_models
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
#define WBAssert(condition, message)
std::string get_full_json_path(size_t max_size=std::numeric_limits< size_t >::max()) const
void get_coordinates(const std::string &name, Parameters &prm, const CoordinateSystem coordinate_system)
std::vector< double > eccentricities
double cos(const double angle)
static void make_snippet(Parameters &prm)
std::vector< std::string > feature_tags
WorldBuilder::World * world
#define WBAssertThrow(condition, message)
bool get_unique_pointers(const std::string &name, std::vector< std::unique_ptr< T > > &vector)
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
std::unique_ptr< WorldBuilder::CoordinateSystems::Interface > coordinate_system
double fraction_from_ellipse_center(const Point< 2 > &ellipse_center, const double semi_major_axis, const double eccentricity, const double theta, const Point< 2 > &point)
double sin(const double raw_angle)
static void declare_entries(Parameters &prm, const std::string &parent_name, const std::vector< std::string > &required_entries)
void declare_entry(const std::string &name, const Types::Interface &type, const std::string &documentation)
static void declare_entries(Parameters &prm, const std::string &parent_name="", const std::vector< std::string > &required_entries={})
std::vector< T > get_vector(const std::string &name)
T get(const std::string &name)
rapidjson::Document declarations
std::vector< double > depths
void unroll_into(std::vector< double > &vector, const size_t start_entry=0) const
double interpolate_angle_across_zero(const double angle_1, const double angle_2, const double fraction)
std::vector< Point< 2 > > coordinates