Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : /// \file 5 : /// Declares functions for interpolating data in volume files to target points. 6 : /// This file is intended to be included in external programs, so it 7 : /// intentionally has no dependencies on any other headers. 8 : 9 : #pragma once 10 : 11 : #include <array> 12 : #include <cstddef> 13 : #include <limits> 14 : #include <optional> 15 : #include <string> 16 : #include <variant> 17 : #include <vector> 18 : 19 : /// Functions that are intended to be used by external programs, e.g. to 20 : /// interpolate data in volume files to target points. 21 0 : namespace spectre::Exporter { 22 : 23 : /// Identifies an observation by its ID in the volume data file. 24 1 : struct ObservationId { 25 0 : ObservationId() = default; 26 0 : explicit ObservationId(size_t local_value) : value(local_value) {} 27 0 : size_t value; 28 : }; 29 : 30 : /// Identifies an observation by its index in the ordered list of observations. 31 : /// Negative indices are counted from the end of the list. 32 1 : struct ObservationStep { 33 0 : ObservationStep() = default; 34 0 : explicit ObservationStep(int local_value) : value(local_value) {} 35 0 : int value; 36 : }; 37 : 38 : /// Identifies an observation by its value (e.g. the time), selecting the 39 : /// observation whose value is closest to `value` within `epsilon`. This is the 40 : /// same selection as a bare `double`, but with a configurable tolerance. 41 1 : struct ObservationValue { 42 0 : ObservationValue() = default; 43 0 : explicit ObservationValue(double local_value, double local_epsilon = 1e-12) 44 : : value(local_value), epsilon(local_epsilon) {} 45 0 : double value = std::numeric_limits<double>::signaling_NaN(); 46 0 : double epsilon = 1e-12; 47 : }; 48 : 49 0 : using ObservationVariant = 50 : std::variant<ObservationId, ObservationStep, double, ObservationValue>; 51 : 52 : /*! 53 : * \brief Interpolate data in volume files to target points 54 : * 55 : * \tparam Dim Dimension of the domain 56 : * \param volume_files_or_glob The list of H5 files, or a glob pattern 57 : * \param subfile_name The name of the subfile in the H5 files containing the 58 : * volume data 59 : * \param observation Either the observation ID as a `size_t`, or the index of 60 : * the observation in the volume files to interpolate as an `int` (a value of 0 61 : * would be the first observation, and a value of -1 would be the last 62 : * observation). 63 : * \param tensor_components The tensor components to interpolate, e.g. 64 : * "Lapse", "Shift_x", "Shift_y", "Shift_z", "SpatialMetric_xx", etc. 65 : * Look into the H5 file to see what components are available. 66 : * \param target_points The points to interpolate to, in inertial coordinates. 67 : * \param extrapolate_into_excisions Enables extrapolation into excision regions 68 : * of the domain (default is `false`). This can be useful to fill the excision 69 : * region with (constraint-violating but smooth) data so it can be imported into 70 : * moving puncture codes. Specifically, we implement the strategy used in 71 : * \cite Etienne2008re adjusted for distorted excisions: we choose uniformly 72 : * spaced radial anchor points spaced as $\Delta r = 0.3 r_\mathrm{AH}$ in the 73 : * grid frame (where the excision is spherical), then map the anchor points to 74 : * the distorted frame (where we have the target point) and do a 7th order 75 : * polynomial extrapolation into the excision region. 76 : * \param error_on_missing_points If `true`, an error will be thrown if any of 77 : * the target points are outside the domain. If `false`, the result will be 78 : * filled with NaNs for points outside the domain (default is `false`). 79 : * \param num_threads The number of threads to use if OpenMP is linked in. If 80 : * not specified, OpenMP will determine the number of threads automatically. 81 : * It's also possible to set the number of threads using the environment 82 : * variable OMP_NUM_THREADS. It's an error to specify num_threads if OpenMP is 83 : * not linked in. Set num_threads to 1 to disable OpenMP. 84 : * \return std::vector<std::vector<double>> The interpolated data. The first 85 : * dimension corresponds to the selected tensor components, and the second 86 : * dimension corresponds to the target points. 87 : */ 88 : template <size_t Dim> 89 1 : std::vector<std::vector<double>> interpolate_to_points( 90 : const std::variant<std::vector<std::string>, std::string>& 91 : volume_files_or_glob, 92 : const std::string& subfile_name, const ObservationVariant& observation, 93 : const std::vector<std::string>& tensor_components, 94 : const std::array<std::vector<double>, Dim>& target_points, 95 : bool extrapolate_into_excisions = false, 96 : bool error_on_missing_points = false, 97 : std::optional<size_t> num_threads = std::nullopt); 98 : 99 : } // namespace spectre::Exporter