Skip to content

Commit

Permalink
Merge pull request #453 from lhy11009/distance_to_feature_plane
Browse files Browse the repository at this point in the history
interface for the distance to a feature's plane
  • Loading branch information
MFraters authored Dec 27, 2022
2 parents 2257914 + 8fd0518 commit 2cafd31
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Added a cmake target to update the reference test results called `update_test_references`. \[Menno Fraters; 2022-04-12; [#404](github.com/GeodynamicWorldBuilder/WorldBuilder/issues/404)\]
- Added a new multi property query interface called properties to the world. This allows to ask for different properties at the same time, which significantly improve performance. Internally all other interface now use this properties function to reduce complexity. \[Menno Fraters; 2022-04-18; [#409](github.com/GeodynamicWorldBuilder/WorldBuilder/issues/409) and [#410](github.com/GeodynamicWorldBuilder/WorldBuilder/issues/410)\]
- Added a new compositional model for fault models such that ensures a smooth transition of compositional value from the fault trace until a particular user-determined distance. This feature can be helpful for model that uses composition of fault to compute other material properties, e.g., viscosity. \[Arushi Saxena; 2022-05-19; [#356](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/356)
- Added an interface to compute the distance of a query point to a feature's plane. For example, the distance of a point to a subducting slab could be duely computed. This interface simply calls the previously implemented interfaces of the feature objects and wrap them up. Thus it only takes variables like coordinates and depth in the model and could be called from ASPECT directly.
\[Haoyuan Li; 2022-12-23; [#453](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/453)

### Changed
- The World Builder Visualizer will now use zlib compression for vtu files by default. If zlib is not available binary output will be used. \[Menno Fraters; 2021-06-26; [#282](github.com/GeodynamicWorldBuilder/WorldBuilder/pull/282)\]
Expand Down
12 changes: 12 additions & 0 deletions include/world_builder/features/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "world_builder/grains.h"
#include "world_builder/utilities.h"
#include "world_builder/objects/distance_from_surface.h"

namespace WorldBuilder
{
Expand Down Expand Up @@ -107,6 +108,17 @@ namespace WorldBuilder
*/
static std::unique_ptr<Interface> create(const std::string &name, WorldBuilder::World *world);

/**
* Returns a PlaneDistances object that has the distance from and along a feature plane,
* caculated from the coordinates and the depth of the point.
*/
virtual
Objects::PlaneDistances
distance_to_feature_plane(const Point<3> &position_in_cartesian_coordinates,
const Objects::NaturalCoordinate &position_in_natural_coordinates,
const double depth) const;


protected:
/**
* A pointer to the world class to retrieve variables.
Expand Down
11 changes: 11 additions & 0 deletions include/world_builder/features/subducting_plate.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "world_builder/features/subducting_plate_models/temperature/interface.h"
#include "world_builder/types/segment.h"
#include "world_builder/bounding_box.h"
#include "world_builder/objects/distance_from_surface.h"


namespace WorldBuilder
Expand Down Expand Up @@ -129,6 +130,16 @@ namespace WorldBuilder
const std::vector<size_t> &entry_in_output,
std::vector<double> &output) const override final;

/**
* Returns a PlaneDistances object that has the distance from and along a subducting plate plane,
* caculated from the coordinates and the depth of the point.
*/
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;


private:
std::vector<std::shared_ptr<Features::SubductingPlateModels::Temperature::Interface> > default_temperature_models;
std::vector<std::shared_ptr<Features::SubductingPlateModels::Composition::Interface> > default_composition_models;
Expand Down
64 changes: 64 additions & 0 deletions include/world_builder/objects/distance_from_surface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright (C) 2018 - 2022 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 <https://www.gnu.org/licenses/>.
*/

#ifndef WORLD_BUILDER_OBJECTSS_DISTANCE_FROM_SURFACE_H
#define WORLD_BUILDER_OBJECTSS_DISTANCE_FROM_SURFACE_H

namespace WorldBuilder
{
namespace Objects
{
class PlaneDistances
{
public:

/**
* Constructor to create an PlaneDistances object from the distance
* from and along the surface of plane
*/
PlaneDistances(const double distance_from_surface_, const double distance_along_surface_)
:
distance_from_surface(distance_from_surface_),
distance_along_surface(distance_along_surface_)
{}

/**
* Function to get the distance from the surface
*/
double get_distance_from_surface();

/**
* Function to get the distance along the surface
*/
double get_distance_along_surface();

private:
/**
* the distance from the surface of the plane
*/
double distance_from_surface;
/**
* the distance along the surface of the plane
*/
double distance_along_surface;
};
}
}

#endif
14 changes: 14 additions & 0 deletions include/world_builder/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "world_builder/grains.h"
#include "world_builder/parameters.h"
#include "world_builder/utilities.h"
#include "world_builder/objects/distance_from_surface.h"

#include <random>

Expand All @@ -30,6 +32,7 @@
*/
namespace WorldBuilder
{

namespace Features
{
class Interface;
Expand Down Expand Up @@ -188,6 +191,17 @@ namespace WorldBuilder
const double depth,
const unsigned int composition_number,
size_t number_of_grains) const;
/**
* Returns a PlaneDistances object that has the distance from and along a feature plane,
* caculated from the coordinates and the depth of the point.
\param point the coordinates in the cartesian geometry
\param depth the depth of the point
\param name the name of the feature (i.e. the string provided to the key word "name" in the wb file)
*/
Objects::PlaneDistances
distance_to_plane(const std::array<double, 3> &point,
const double depth,
const std::string name) const;

/**
* The MPI rank. Set to zero if MPI is not available.
Expand Down
8 changes: 8 additions & 0 deletions source/world_builder/features/interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ namespace WorldBuilder
return get_factory_map().at(lower_case_name)->create(world);
}

Objects::PlaneDistances
Interface::distance_to_feature_plane(const Point<3> &,
const Objects::NaturalCoordinate &,
const double) const
{
WBAssertThrow(false, "The distance_to_feature_plane is not yet implemented for the desinated object");
}

} // namespace Features
} // namespace WorldBuilder

34 changes: 34 additions & 0 deletions source/world_builder/features/subducting_plate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,40 @@ namespace WorldBuilder

}

Objects::PlaneDistances
SubductingPlate::distance_to_feature_plane(const Point<3> &position_in_cartesian_coordinates,
const Objects::NaturalCoordinate &position_in_natural_coordinates,
const double depth) const
{
// The depth variable is the distance from the surface to the position, the depth
// coordinate is the distance from the bottom of the model to the position and
// the starting radius is the distance from the bottom of the model to the surface.
const double starting_radius = position_in_natural_coordinates.get_depth_coordinate() + depth - starting_depth;

WBAssert(std::abs(starting_radius) > std::numeric_limits<double>::epsilon(), "World Builder error: starting_radius can not be zero. "
<< "Position = " << position_in_cartesian_coordinates[0] << ':' << position_in_cartesian_coordinates[1] << ':' << position_in_cartesian_coordinates[2]
<< ", natural_coordinate.get_depth_coordinate() = " << position_in_natural_coordinates.get_depth_coordinate()
<< ", depth = " << depth
<< ", starting_depth " << starting_depth
);

WorldBuilder::Utilities::PointDistanceFromCurvedPlanes distance_from_planes =
WorldBuilder::Utilities::distance_point_from_curved_planes(position_in_cartesian_coordinates,
position_in_natural_coordinates,
reference_point,
coordinates,
slab_segment_lengths,
slab_segment_angles,
starting_radius,
this->world->parameters.coordinate_system,
false,
this->x_spline,
this->y_spline);

Objects::PlaneDistances plane_distances(distance_from_planes.distance_from_plane, distance_from_planes.distance_along_plane);
return plane_distances;
}

/**
* Register plugin
*/
Expand Down
36 changes: 36 additions & 0 deletions source/world_builder/objects/distance_from_surface.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright (C) 2018 - 2022 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 <https://www.gnu.org/licenses/>.
*/

#include "world_builder/objects/distance_from_surface.h"

namespace WorldBuilder
{
namespace Objects
{
double PlaneDistances::get_distance_from_surface()
{
return this->distance_from_surface;
}

double PlaneDistances::get_distance_along_surface()
{
return this->distance_along_surface;
}
}
}
32 changes: 32 additions & 0 deletions source/world_builder/world.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
#include "world_builder/types/plugin_system.h"
#include "world_builder/types/point.h"
#include "world_builder/gravity_model/interface.h"
#include "world_builder/features/subducting_plate.h"

#include <iostream>
#include <world_builder/coordinate_system.h>
#include <world_builder/objects/distance_from_surface.h>

#ifdef WB_WITH_MPI
#define OMPI_SKIP_MPICXX 1
Expand Down Expand Up @@ -413,5 +415,35 @@ namespace WorldBuilder
return random_number_engine;
}

Objects::PlaneDistances
World::distance_to_plane(const std::array<double, 3> &point_,
const double depth,
const std::string name) const
{
// We receive the cartesian points from the user.
Point<3> point(point_,cartesian);

WBAssert(!this->limit_debug_consistency_checks || this->parameters.coordinate_system->natural_coordinate_system() == cartesian
|| approx(depth, this->parameters.coordinate_system->max_model_depth()-sqrt(point_[0]*point_[0]+point_[1]*point_[1]+point_[2]*point_[2])),
"Inconsistent input. Please check whether the radius in the sperhical coordiantes is consistent with the radius of the planet as defined "
<< "in the program that uses the Geodynamic World Builder. "
<< "Depth = " << depth << ", radius = " << this->parameters.coordinate_system->max_model_depth()
<< ", point = " << point_[0] << " " << point_[1] << " " << point_[2]
<< ", radius-point.norm() = " << this->parameters.coordinate_system->max_model_depth()-sqrt(point_[0]*point_[0]+point_[1]*point_[1]+point_[2]*point_[2]));

Objects::NaturalCoordinate natural_coordinate = Objects::NaturalCoordinate(point,*(this->parameters.coordinate_system));

Objects::PlaneDistances plane_distances(0.0, 0.0);
for (auto &&it : this->parameters.features)
{
if (it->get_name() == name)
{
plane_distances = it->distance_to_feature_plane(point, natural_coordinate, depth);
break;
}
}
return plane_distances;
}

} // namespace WorldBuilder

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Test


[0] = 7141.78
[1] = 70.7107
[2] = 618.443
[3] = 13.5623
[4] = inf
[5] = inf

54 changes: 54 additions & 0 deletions tests/unit_tests/unit_test_world_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,60 @@ TEST_CASE("WorldBuilder Features: Interface")

}

TEST_CASE("WorldBuilder Features: Distance to Feature Plane")
{
std::vector<double> approval_tests;

// call the distance_to_plane to a subducting plate feature,
std::string file_name = WorldBuilder::Data::WORLD_BUILDER_SOURCE_DIR + "/tests/data/subducting_plate_constant_angles_cartesian.wb";
WorldBuilder::World world1(file_name);
{
std::unique_ptr<Features::Interface> subducting_plate = Features::Interface::create("Subducting Plate", &world1);

world1.parameters.enter_subsection("features");
world1.parameters.enter_subsection("2");
subducting_plate->parse_entries(world1.parameters);
world1.parameters.leave_subsection();
world1.parameters.leave_subsection();
const std::array<double, 3> point1 = {250e3,495e3,800e3};
const double depth1 = 5.1e3;
auto plane_distances1 = world1.distance_to_plane(point1, depth1, "First subducting plate");
approval_tests.emplace_back(plane_distances1.get_distance_from_surface());
approval_tests.emplace_back(plane_distances1.get_distance_along_surface());
const std::array<double, 3> point2 = {502e3,500e3,800e3};
const double depth2 = 0.45e3;
auto plane_distances2 = world1.distance_to_plane(point2, depth2, "First subducting plate");
approval_tests.emplace_back(plane_distances2.get_distance_from_surface());
approval_tests.emplace_back(plane_distances2.get_distance_along_surface());
const std::array<double, 3> point3 = {502e3,500e3,800e3}; // point 3, shallower than point2, thus distance from plane = inf
const double depth3 = 0.43e3;
auto plane_distances3 = world1.distance_to_plane(point3, depth3, "First subducting plate");
approval_tests.emplace_back(plane_distances3.get_distance_from_surface());
approval_tests.emplace_back(plane_distances3.get_distance_along_surface());

ApprovalTests::Approvals::verifyAll("Test", approval_tests);
}

// call the distance_to_plane to a fault feature, as this is not implemented yet, we should be
// informed by the assertion error message.
std::string file_name2 = WorldBuilder::Data::WORLD_BUILDER_SOURCE_DIR + "/tests/data/fault_constant_angles_cartesian.wb";
WorldBuilder::World world2(file_name2);
{
std::unique_ptr<Features::Interface> fault = Features::Interface::create("Fault", &world2);

world2.parameters.enter_subsection("features");
world2.parameters.enter_subsection("2");
fault->parse_entries(world2.parameters);
world2.parameters.leave_subsection();
world2.parameters.leave_subsection();
const std::array<double, 3> point = {50e3,230e3,800e3};
const double depth = 10e3;
CHECK_THROWS_WITH(world2.distance_to_plane(point, depth, "First fault"),
Contains("The distance_to_feature_plane is not yet implemented for the desinated object"));
}
}


TEST_CASE("WorldBuilder Features: Continental Plate")
{
std::vector<double> approval_tests;
Expand Down

0 comments on commit 2cafd31

Please sign in to comment.