Skip to content

Commit

Permalink
Merge implementations of Interval, Rectangle, and Brick domains
Browse files Browse the repository at this point in the history
I needed different boundary conditions in each direction in 2D, but it was
only supported in 3D. Also, only the 1D domain supported log/inverse grid point
distributions. So I merged the three implementations into one.
  • Loading branch information
nilsvu committed Apr 1, 2024
1 parent 497c208 commit b0274ae
Show file tree
Hide file tree
Showing 98 changed files with 1,338 additions and 2,009 deletions.
111 changes: 111 additions & 0 deletions src/Domain/CoordinateMaps/Distribution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Options/Options.hpp"
#include "Options/ParseOptions.hpp"
#include "Options/String.hpp"
#include "Utilities/ErrorHandling/Error.hpp"

namespace domain::CoordinateMaps {
Expand All @@ -29,6 +30,12 @@ std::ostream& operator<<(std::ostream& os, const Distribution distribution) {
}
}

bool operator==(const DistributionAndSingularityPosition& lhs,
const DistributionAndSingularityPosition& rhs) {
return lhs.distribution == rhs.distribution and
lhs.singularity_position == rhs.singularity_position;
}

} // namespace domain::CoordinateMaps

template <>
Expand All @@ -50,4 +57,108 @@ Options::create_from_yaml<domain::CoordinateMaps::Distribution>::create<void>(
PARSE_ERROR(options.context(),
"Distribution must be 'Linear', 'Equiangular', 'Logarithmic', "
"'Inverse', or 'Projective'.");
}

// The helper classes exist to create a nested level of options like this:
// Distribution:
// Logarithmic:
// SingularityPosition: 0.
namespace domain::CoordinateMaps::detail {

struct SingularityPositionImpl {
static constexpr Options::String help = {
"Position of coordinate singularity."};
struct SingularityPosition {
using type = double;
static constexpr Options::String help = {
"Position of coordinate singularity. "
"Must be outside the domain. "
"A singularity position close to the lower or upper bound of the "
"interval leads to very small grid spacing near that end, and "
"placing the singularity further away from the domain increases the "
"grid spacing. See the documentation of "
"'domain::CoordinateMap::Distribution' for details."};
};
using options = tmpl::list<SingularityPosition>;
double value;
};

template <Distribution Dist>
struct DistAndSingularityPositionImpl {
static_assert(Dist == Distribution::Logarithmic or
Dist == Distribution::Inverse,
"Singularity position is only required for 'Logarithmic' and "
"'Inverse' grid point distributions.");
static constexpr Options::String help = {
"The singularity position for the 'Logarithmic' or 'Inverse' "
"distribution."};
struct DistAndSingularityPos {
static std::string name() {
if constexpr (Dist == Distribution::Logarithmic) {
return "Logarithmic";

} else {
return "Inverse";
}
}
using type = SingularityPositionImpl;
static constexpr Options::String help{
"The singularity position for the 'Logarithmic' or 'Inverse' "
"distribution."};
};
using options = tmpl::list<DistAndSingularityPos>;
SingularityPositionImpl singularity_position;
};

} // namespace domain::CoordinateMaps::detail

template <>
domain::CoordinateMaps::DistributionAndSingularityPosition
Options::create_from_yaml<
domain::CoordinateMaps::DistributionAndSingularityPosition>::
create<void>(const Options::Option& options) {
const auto dist = options.parse_as<std::variant<
domain::CoordinateMaps::Distribution,
domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Logarithmic>,
domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Inverse>>>();
if (std::holds_alternative<domain::CoordinateMaps::Distribution>(dist)) {
const auto distribution =
std::get<domain::CoordinateMaps::Distribution>(dist);
if (distribution == domain::CoordinateMaps::Distribution::Linear or
distribution == domain::CoordinateMaps::Distribution::Projective or
distribution == domain::CoordinateMaps::Distribution::Equiangular) {
return {distribution, std::nullopt};
} else {
PARSE_ERROR(
options.context(),
"The distribution '"
<< distribution
<< "' requires a singularity position. Specify it like this:\n "
<< distribution << ":\n SingularityPosition: 0.0");
}
} else if (std::holds_alternative<
domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Logarithmic>>(
dist)) {
const auto& dist_and_singularity_position =
std::get<domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Logarithmic>>(dist);
return {domain::CoordinateMaps::Distribution::Logarithmic,
dist_and_singularity_position.singularity_position.value};
} else if (std::holds_alternative<
domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Inverse>>(dist)) {
const auto& dist_and_singularity_position =
std::get<domain::CoordinateMaps::detail::DistAndSingularityPositionImpl<
domain::CoordinateMaps::Distribution::Inverse>>(dist);
return {domain::CoordinateMaps::Distribution::Inverse,
dist_and_singularity_position.singularity_position.value};
} else {
PARSE_ERROR(options.context(),
"Failed to parse distribution. Specify either a distribution "
"such as 'Linear', or a distribution with its singularity "
"position such as 'Logarithmic: SingularityPosition: 0.0'.");
}
}
41 changes: 41 additions & 0 deletions src/Domain/CoordinateMaps/Distribution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#pragma once

#include <optional>
#include <ostream>

/// \cond
Expand Down Expand Up @@ -32,6 +33,31 @@ enum class Distribution {

std::ostream& operator<<(std::ostream& os, Distribution distribution);

/*!
* \brief A `Distribution` and the corresponding singularity position
*
* The `singularity_position` is only meaningful for `Distribution::Logarithmic`
* and `Distribution::Inverse`.
*
* This class can be option-created like so:
* - Just the name of the distribution for `Linear`, `Equiangular`, and
* `Projective`.
* - The name of the distribution and the singularity position for
* `Logarithmic` and `Inverse`:
*
* ```yaml
* Logarithmic:
* SingularityPosition: 0.0
* ```
*/
struct DistributionAndSingularityPosition {
Distribution distribution = Distribution::Linear;
std::optional<double> singularity_position = std::nullopt;
};

bool operator==(const DistributionAndSingularityPosition& lhs,
const DistributionAndSingularityPosition& rhs);

} // namespace domain::CoordinateMaps

template <>
Expand All @@ -46,3 +72,18 @@ template <>
domain::CoordinateMaps::Distribution
Options::create_from_yaml<domain::CoordinateMaps::Distribution>::create<void>(
const Options::Option& options);

template <>
struct Options::create_from_yaml<
domain::CoordinateMaps::DistributionAndSingularityPosition> {
template <typename Metavariables>
static domain::CoordinateMaps::DistributionAndSingularityPosition create(
const Options::Option& options) {
return create<void>(options);
}
};
template <>
domain::CoordinateMaps::DistributionAndSingularityPosition
Options::create_from_yaml<
domain::CoordinateMaps::DistributionAndSingularityPosition>::
create<void>(const Options::Option& options);
9 changes: 8 additions & 1 deletion src/Domain/CoordinateMaps/Python/Bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See LICENSE.txt for details.

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "Domain/CoordinateMaps/Distribution.hpp"
#include "Domain/CoordinateMaps/Python/CoordinateMap.hpp"
Expand All @@ -19,7 +20,13 @@ PYBIND11_MODULE(_Pybindings, m) { // NOLINT
.value("Linear", CoordinateMaps::Distribution::Linear)
.value("Equiangular", CoordinateMaps::Distribution::Equiangular)
.value("Logarithmic", CoordinateMaps::Distribution::Logarithmic)
.value("Inverse", CoordinateMaps::Distribution::Inverse);
.value("Inverse", CoordinateMaps::Distribution::Inverse)
.value("Projective", CoordinateMaps::Distribution::Projective);
py::class_<CoordinateMaps::DistributionAndSingularityPosition>(
m, "DistributionAndSingularityPosition")
.def(py::init<CoordinateMaps::Distribution, std::optional<double>>(),
py::arg("distribution"),
py::arg("singularity_position") = std::nullopt);
// Order is important: The base class `CoordinateMap` needs to have its
// bindings set up before the derived classes
py_bindings::bind_coordinate_map(m);
Expand Down
4 changes: 0 additions & 4 deletions src/Domain/Creators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ spectre_target_sources(
Disk.cpp
ExpandOverBlocks.cpp
FrustalCloak.cpp
Interval.cpp
Rectangle.cpp
Rectilinear.cpp
RegisterDerivedWithCharm.cpp
RotatedBricks.cpp
Expand Down Expand Up @@ -47,9 +45,7 @@ spectre_target_headers(
Factory2D.hpp
Factory3D.hpp
FrustalCloak.hpp
Interval.hpp
OptionTags.hpp
Rectangle.hpp
Rectilinear.hpp
RegisterDerivedWithCharm.hpp
RotatedBricks.hpp
Expand Down
2 changes: 1 addition & 1 deletion src/Domain/Creators/Factory1D.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "Domain/Creators/AlignedLattice.hpp"
#include "Domain/Creators/Factory.hpp"
#include "Domain/Creators/Interval.hpp"
#include "Domain/Creators/Rectilinear.hpp"
#include "Domain/Creators/RotatedIntervals.hpp"
#include "Utilities/TMPL.hpp"

Expand Down
2 changes: 1 addition & 1 deletion src/Domain/Creators/Factory2D.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "Domain/Creators/AlignedLattice.hpp"
#include "Domain/Creators/Disk.hpp"
#include "Domain/Creators/Factory.hpp"
#include "Domain/Creators/Rectangle.hpp"
#include "Domain/Creators/Rectilinear.hpp"
#include "Domain/Creators/RotatedRectangles.hpp"
#include "Utilities/TMPL.hpp"

Expand Down
Loading

0 comments on commit b0274ae

Please sign in to comment.