-
Notifications
You must be signed in to change notification settings - Fork 192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extrapolate from nearest element #6382
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ template <size_t VolumeDim> | |
class Domain; | ||
template <size_t VolumeDim> | ||
class Block; | ||
template <size_t VolumeDim> | ||
class ExcisionSphere; | ||
/// \endcond | ||
|
||
template <size_t Dim> | ||
|
@@ -69,10 +71,32 @@ auto block_logical_coordinates( | |
const domain::FunctionsOfTimeMap& functions_of_time = {}) | ||
-> std::vector<BlockLogicalCoords<Dim>>; | ||
|
||
/// \par Extrapolation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doxygen does not seem to handle adding combining this with the documentation from the enclosing |
||
/// If `allow_extrapolation` is `true` (default is `false`), then the function | ||
/// can return block-logical coordinates outside of [-1, 1]. This is useful for | ||
/// extrapolating into excision regions. | ||
template <size_t Dim, typename Fr> | ||
std::optional<tnsr::I<double, Dim, ::Frame::BlockLogical>> | ||
block_logical_coordinates_single_point( | ||
const tnsr::I<double, Dim, Fr>& input_point, const Block<Dim>& block, | ||
double time = std::numeric_limits<double>::signaling_NaN(), | ||
const domain::FunctionsOfTimeMap& functions_of_time = {}); | ||
const domain::FunctionsOfTimeMap& functions_of_time = {}, | ||
bool allow_extrapolation = false); | ||
/// @} | ||
|
||
/*! | ||
* \brief Finds the block-logical coordinates of a point in an excision sphere. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't showing up in the documentation. Maybe needs an |
||
* | ||
* The point will be reported to belong to the nearest block that abuts the | ||
* excision sphere and will have a logical coordinate outside the range [-1, 1] | ||
* in the radial direction. This is useful for extrapolating into excision | ||
* regions using the Lagrange polynomial basis of the nearest element. If the | ||
* point is not within the excision sphere, the return value is std::nullopt. | ||
*/ | ||
template <size_t Dim, typename Frame> | ||
BlockLogicalCoords<Dim> block_logical_coordinates_in_excision( | ||
const tnsr::I<double, Dim, Frame>& input_point, | ||
const ExcisionSphere<Dim>& excision_sphere, | ||
const std::vector<Block<Dim>>& blocks, | ||
double time = std::numeric_limits<double>::signaling_NaN(), | ||
const domain::FunctionsOfTimeMap& functions_of_time = {}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,10 +65,12 @@ std::optional<double> SphereTransition::original_radius_over_radius( | |
if ((original_radius + eps_) >= r_min_ and | ||
(original_radius - eps_) <= r_max_) { | ||
return std::optional<double>{original_radius / mag}; | ||
} else if ((a_ > 0.0 and mag > r_max_) or (a_ < 0.0 and mag < r_min_)) { | ||
} else if ((a_ > 0.0 and original_radius > r_max_) or | ||
(a_ < 0.0 and original_radius < r_min_)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it easy to add a test for this? |
||
// a_ being positive is a sentinel for reverse (see constructor) | ||
return {1.0 + radial_distortion / mag}; | ||
} else if ((a_ < 0.0 and mag > r_max_) or (a_ > 0.0 and mag < r_min_)) { | ||
} else if ((a_ < 0.0 and original_radius > r_max_) or | ||
(a_ > 0.0 and original_radius < r_min_)) { | ||
return {1.0}; | ||
} else { | ||
return std::nullopt; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ target_link_libraries( | |
FunctionsOfTime | ||
H5 | ||
Interpolation | ||
Options | ||
Serialization | ||
Utilities | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,13 +21,68 @@ | |
#include "IO/H5/VolumeData.hpp" | ||
#include "NumericalAlgorithms/Interpolation/IrregularInterpolant.hpp" | ||
#include "NumericalAlgorithms/Interpolation/PolynomialInterpolation.hpp" | ||
#include "Options/Context.hpp" | ||
#include "Options/Options.hpp" | ||
#include "Utilities/FileSystem.hpp" | ||
#include "Utilities/GenerateInstantiations.hpp" | ||
#include "Utilities/GetOutput.hpp" | ||
#include "Utilities/Gsl.hpp" | ||
#include "Utilities/Overloader.hpp" | ||
#include "Utilities/Serialization/Serialize.hpp" | ||
|
||
namespace spectre::Exporter { | ||
|
||
std::ostream& operator<<(std::ostream& os, | ||
const ExcisionExtrapolationMode& mode) { | ||
switch (mode) { | ||
case ExcisionExtrapolationMode::NoExtrapolation: | ||
os << "NoExtrapolation"; | ||
break; | ||
case ExcisionExtrapolationMode::NearestElement: | ||
os << "NearestElement"; | ||
break; | ||
case ExcisionExtrapolationMode::RadialAnchors: | ||
os << "RadialAnchors"; | ||
break; | ||
default: | ||
os << "Unknown"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
break; | ||
} | ||
return os; | ||
} | ||
|
||
} // namespace spectre::Exporter | ||
|
||
template <> | ||
spectre::Exporter::ExcisionExtrapolationMode | ||
Options::create_from_yaml<spectre::Exporter::ExcisionExtrapolationMode>::create< | ||
void>(const Options::Option& options) { | ||
const auto type_read = options.parse_as<std::string>(); | ||
for (const auto value : | ||
{spectre::Exporter::ExcisionExtrapolationMode::NoExtrapolation, | ||
spectre::Exporter::ExcisionExtrapolationMode::NearestElement, | ||
spectre::Exporter::ExcisionExtrapolationMode::RadialAnchors}) { | ||
if (type_read == get_output(value)) { | ||
return value; | ||
} | ||
} | ||
PARSE_ERROR( | ||
options.context(), | ||
"Failed to convert \"" | ||
<< type_read | ||
<< "\" to spectre::Exporter::ExcisionExtrapolationMode.\nMust be one " | ||
"of " | ||
<< get_output( | ||
spectre::Exporter::ExcisionExtrapolationMode::NoExtrapolation) | ||
<< ", " | ||
<< get_output( | ||
spectre::Exporter::ExcisionExtrapolationMode::NearestElement) | ||
<< ", or " | ||
<< get_output( | ||
spectre::Exporter::ExcisionExtrapolationMode::RadialAnchors) | ||
<< "."); | ||
} | ||
|
||
// Ignore OpenMP pragmas when OpenMP is not enabled | ||
#pragma GCC diagnostic push | ||
#pragma GCC diagnostic ignored "-Wunknown-pragmas" | ||
|
@@ -329,7 +384,7 @@ std::vector<std::vector<double>> interpolate_to_points( | |
const std::variant<ObservationId, ObservationStep>& observation, | ||
const std::vector<std::string>& tensor_components, | ||
const std::array<std::vector<double>, Dim>& target_points, | ||
const bool extrapolate_into_excisions, | ||
const ExcisionExtrapolationMode excision_extrapolation_mode, | ||
const std::optional<size_t> num_threads) { | ||
domain::creators::register_derived_with_charm(); | ||
domain::creators::time_dependence::register_derived_with_charm(); | ||
|
@@ -446,19 +501,37 @@ std::vector<std::vector<double>> interpolate_to_points( | |
} | ||
} // for blocks | ||
if (block_logical_coords[s].has_value() or | ||
not extrapolate_into_excisions) { | ||
excision_extrapolation_mode == | ||
ExcisionExtrapolationMode::NoExtrapolation) { | ||
continue; | ||
} | ||
// The point wasn't found in any block. Check if it's in an excision and | ||
// set up extrapolation if requested. | ||
// The point wasn't found in any block. Extrapolate if requested. | ||
for (const auto& [name, excision_sphere] : domain.excision_spheres()) { | ||
if (add_extrapolation_anchors( | ||
make_not_null(&extra_block_logical_coords), | ||
make_not_null(&extra_extrapolation_info), excision_sphere, | ||
domain, target_point, time, functions_of_time, | ||
extrapolation_spacing)) { | ||
extra_extrapolation_info.back().target_index = s; | ||
break; | ||
if (excision_extrapolation_mode == | ||
ExcisionExtrapolationMode::NearestElement) { | ||
// Get the block-logical coordinates for the nearest element (the | ||
// coordinates will be outside [-1, 1], so Lagrange extrapolation will | ||
// happen) | ||
block_logical_coords[s] = block_logical_coordinates_in_excision( | ||
target_point, excision_sphere, domain.blocks(), time, | ||
functions_of_time); | ||
if (block_logical_coords[s].has_value()) { | ||
break; | ||
} | ||
} else if (excision_extrapolation_mode == | ||
ExcisionExtrapolationMode::RadialAnchors) { | ||
// Set up extrapolation anchors for this point | ||
if (add_extrapolation_anchors( | ||
make_not_null(&extra_block_logical_coords), | ||
make_not_null(&extra_extrapolation_info), excision_sphere, | ||
domain, target_point, time, functions_of_time, | ||
extrapolation_spacing)) { | ||
extra_extrapolation_info.back().target_index = s; | ||
break; | ||
} | ||
} else { | ||
ERROR("Invalid excision extrapolation mode: " | ||
<< excision_extrapolation_mode); | ||
} | ||
} | ||
} // omp for target points | ||
|
@@ -503,7 +576,7 @@ std::vector<std::vector<double>> interpolate_to_points( | |
} | ||
} | ||
|
||
if (extrapolate_into_excisions) { | ||
if (excision_extrapolation_mode == ExcisionExtrapolationMode::RadialAnchors) { | ||
// Extrapolate into excisions from the anchor points | ||
#pragma omp parallel for num_threads(resolved_num_threads) | ||
for (const auto& extrapolation : extrapolation_info) { | ||
|
@@ -540,7 +613,7 @@ std::vector<std::vector<double>> interpolate_to_points( | |
const std::variant<ObservationId, ObservationStep>& observation, \ | ||
const std::vector<std::string>& tensor_components, \ | ||
const std::array<std::vector<double>, DIM(data)>& target_points, \ | ||
bool extrapolate_into_excisions, \ | ||
ExcisionExtrapolationMode excision_extrapolation_mode, \ | ||
const std::optional<size_t> num_threads); | ||
|
||
GENERATE_INSTANTIATIONS(INSTANTIATE, (1, 2, 3)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to handle points on extrapolations of block boundaries?