feat(libmeanfield): centrifugal + pressure
This commit is contained in:
@@ -3,8 +3,11 @@
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -15,51 +18,104 @@ import test_helpers;
|
||||
using namespace mean_field;
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
concept HasRuntimeSpaceOrders = requires(T value) { value.space_orders; };
|
||||
|
||||
static_assert(mean_field::field::FieldTag<field::Gravity>);
|
||||
static_assert(mean_field::field::FieldTag<field::Displacement>);
|
||||
static_assert(mean_field::field::FieldTag<field::Density>);
|
||||
static_assert(mean_field::field::FieldTag<field::Enthalpy>);
|
||||
static_assert(mean_field::field::FieldTag<field::BarotropicConstant>);
|
||||
static_assert(field::Gravity::constraintsAreValid);
|
||||
static_assert(std::same_as<
|
||||
field::RelationTargetT<field::Gravity::Flux>,
|
||||
field::Gravity::Potential>);
|
||||
static_assert(!HasRuntimeSpaceOrders<utils::Args>);
|
||||
|
||||
std::string_view get_term_name(const quadrature::Term term) {
|
||||
switch (term) {
|
||||
case quadrature::Term::gravity_hdiv_mass: return "gravity_hdiv_mass";
|
||||
case quadrature::Term::gravity_divergence: return "gravity_divergence";
|
||||
case quadrature::Term::gravity_source: return "gravity_source";
|
||||
case quadrature::Term::gravity_boundary: return "gravity_boundary";
|
||||
case quadrature::Term::density_projection: return "density_projection";
|
||||
case quadrature::Term::mass_conservation: return "mass_conservation";
|
||||
case quadrature::Term::center_of_mass: return "center_of_mass";
|
||||
case quadrature::Term::quadrupole: return "quadrupole";
|
||||
case quadrature::Term::gravitational_energy: return "gravitational_energy";
|
||||
case quadrature::Term::virial: return "virial";
|
||||
case quadrature::Term::error_norm: return "error_norm";
|
||||
case quadrature::Term::gravity_hdiv_mass:
|
||||
return "gravity_hdiv_mass";
|
||||
case quadrature::Term::gravity_divergence:
|
||||
return "gravity_divergence";
|
||||
case quadrature::Term::gravity_source:
|
||||
return "gravity_source";
|
||||
case quadrature::Term::gravity_boundary:
|
||||
return "gravity_boundary";
|
||||
case quadrature::Term::centrifugal:
|
||||
return "centrifugal";
|
||||
case quadrature::Term::density_projection:
|
||||
return "density_projection";
|
||||
case quadrature::Term::eos_closure:
|
||||
return "eos_closure";
|
||||
case quadrature::Term::hydrostatic_equilibrium:
|
||||
return "hydrostatic_equilibrium";
|
||||
case quadrature::Term::isobaric_surface:
|
||||
return "isobaric_surface";
|
||||
case quadrature::Term::mesh_extension:
|
||||
return "mesh_extension";
|
||||
case quadrature::Term::mass_conservation:
|
||||
return "mass_conservation";
|
||||
case quadrature::Term::mass_normalization:
|
||||
return "mass_normalization";
|
||||
case quadrature::Term::center_of_mass:
|
||||
return "center_of_mass";
|
||||
case quadrature::Term::quadrupole:
|
||||
return "quadrupole";
|
||||
case quadrature::Term::gravitational_energy:
|
||||
return "gravitational_energy";
|
||||
case quadrature::Term::pressure_integral:
|
||||
return "pressure_integral";
|
||||
case quadrature::Term::virial:
|
||||
return "virial";
|
||||
case quadrature::Term::error_norm:
|
||||
return "error_norm";
|
||||
case quadrature::Term::pressure_force:
|
||||
return "pressure_force";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
quadrature::Query make_query(const quadrature::Term term, const int base_order) {
|
||||
quadrature::Query make_query(
|
||||
const quadrature::Term term,
|
||||
const int base_order
|
||||
) {
|
||||
return {.term = term, .base_order = base_order};
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Policy Computes Base Orders", tags::unit & tags::quadrature) {
|
||||
const quadrature::Policy policy(quadrature::make_rule_set(quadrature::Mode::production));
|
||||
template <typename FieldT, typename QuantityT>
|
||||
concept CanMakeFec = requires { FieldT::template make_fec<QuantityT>(3); };
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Quadrature Policy Computes Base Orders",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
const quadrature::Policy policy(
|
||||
quadrature::make_rule_set(quadrature::Mode::production)
|
||||
);
|
||||
|
||||
quadrature::Query generic_query = {
|
||||
.term = quadrature::Term::gravitational_energy,
|
||||
.trial_order = 3,
|
||||
.test_order = 4,
|
||||
.coefficient_order = 2,
|
||||
.term = quadrature::Term::gravitational_energy,
|
||||
.trial_order = 3,
|
||||
.test_order = 4,
|
||||
.coefficient_order = 2,
|
||||
.geometry_weight_order = 5
|
||||
};
|
||||
|
||||
const quadrature::Resolution generic_resolution = policy.resolve(generic_query);
|
||||
const quadrature::Resolution generic_resolution =
|
||||
policy.resolve(generic_query);
|
||||
CHECK(generic_resolution.base_order == 14);
|
||||
CHECK(generic_resolution.boost == 0);
|
||||
CHECK(generic_resolution.order == 14);
|
||||
CHECK_FALSE(generic_resolution.used_fixed_order);
|
||||
|
||||
quadrature::Query divergence_query = {
|
||||
.term = quadrature::Term::gravity_divergence,
|
||||
.trial_order = 3,
|
||||
.test_order = 2,
|
||||
.coefficient_order = 1,
|
||||
.term = quadrature::Term::gravity_divergence,
|
||||
.trial_order = 3,
|
||||
.test_order = 2,
|
||||
.coefficient_order = 1,
|
||||
.geometry_weight_order = 4
|
||||
};
|
||||
|
||||
@@ -69,147 +125,218 @@ TEST_CASE("Quadrature Policy Computes Base Orders", tags::unit & tags::quadratur
|
||||
CHECK(policy.resolve(divergence_query).base_order == 7);
|
||||
|
||||
quadrature::Query explicit_query = {
|
||||
.term = quadrature::Term::gravity_hdiv_mass,
|
||||
.trial_order = 20,
|
||||
.test_order = 20,
|
||||
.coefficient_order = 20,
|
||||
.term = quadrature::Term::gravity_hdiv_mass,
|
||||
.trial_order = 20,
|
||||
.test_order = 20,
|
||||
.coefficient_order = 20,
|
||||
.geometry_weight_order = 20,
|
||||
.base_order = 11
|
||||
.base_order = 11
|
||||
};
|
||||
|
||||
CHECK(policy.resolve(explicit_query).base_order == 11);
|
||||
CHECK(policy.resolve(explicit_query).order == 11);
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Policy Composes Global and Term Boosts", tags::unit & tags::quadrature) {
|
||||
quadrature::RuleSet rule_set = quadrature::make_rule_set(quadrature::Mode::production, 3);
|
||||
TEST_CASE(
|
||||
"Quadrature Policy Composes Global and Term Boosts",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
quadrature::RuleSet rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production, 3);
|
||||
rule_set.gravity_hdiv_mass.boost = 5;
|
||||
rule_set.error_norm.boost = 2;
|
||||
rule_set.error_norm.boost = 2;
|
||||
const quadrature::Policy policy(rule_set);
|
||||
|
||||
const quadrature::Resolution mass_resolution = policy.resolve(make_query(quadrature::Term::gravity_hdiv_mass, 7));
|
||||
const quadrature::Resolution mass_resolution =
|
||||
policy.resolve(make_query(quadrature::Term::gravity_hdiv_mass, 7));
|
||||
CHECK(mass_resolution.base_order == 7);
|
||||
CHECK(mass_resolution.boost == 8);
|
||||
CHECK(mass_resolution.order == 15);
|
||||
CHECK_FALSE(mass_resolution.used_fixed_order);
|
||||
|
||||
const quadrature::Resolution error_resolution = policy.resolve(make_query(quadrature::Term::error_norm, 7));
|
||||
const quadrature::Resolution error_resolution =
|
||||
policy.resolve(make_query(quadrature::Term::error_norm, 7));
|
||||
CHECK(error_resolution.boost == 5);
|
||||
CHECK(error_resolution.order == 12);
|
||||
|
||||
const quadrature::Resolution source_resolution = policy.resolve(make_query(quadrature::Term::gravity_source, 7));
|
||||
const quadrature::Resolution source_resolution =
|
||||
policy.resolve(make_query(quadrature::Term::gravity_source, 7));
|
||||
CHECK(source_resolution.boost == 3);
|
||||
CHECK(source_resolution.order == 10);
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Fixed Orders Have Defined Precedence", tags::unit & tags::quadrature) {
|
||||
quadrature::RuleSet rule_set = quadrature::make_rule_set(quadrature::Mode::production, 4);
|
||||
rule_set.fallback.fixed_order = 17;
|
||||
TEST_CASE(
|
||||
"Quadrature Fixed Orders Have Defined Precedence",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
quadrature::RuleSet rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production, 4);
|
||||
rule_set.fallback.fixed_order = 17;
|
||||
rule_set.gravity_hdiv_mass.fixed_order = 23;
|
||||
rule_set.gravity_hdiv_mass.boost = 100;
|
||||
rule_set.gravity_source.boost = 100;
|
||||
rule_set.gravity_hdiv_mass.boost = 100;
|
||||
rule_set.gravity_source.boost = 100;
|
||||
const quadrature::Policy policy(rule_set);
|
||||
|
||||
const quadrature::Resolution term_resolution = policy.resolve(make_query(quadrature::Term::gravity_hdiv_mass, 8));
|
||||
const quadrature::Resolution term_resolution =
|
||||
policy.resolve(make_query(quadrature::Term::gravity_hdiv_mass, 8));
|
||||
CHECK(term_resolution.base_order == 8);
|
||||
CHECK(term_resolution.boost == 0);
|
||||
CHECK(term_resolution.order == 23);
|
||||
CHECK(term_resolution.used_fixed_order);
|
||||
|
||||
const quadrature::Resolution fallback_resolution = policy.resolve(make_query(quadrature::Term::gravity_source, 8));
|
||||
const quadrature::Resolution fallback_resolution =
|
||||
policy.resolve(make_query(quadrature::Term::gravity_source, 8));
|
||||
CHECK(fallback_resolution.base_order == 8);
|
||||
CHECK(fallback_resolution.boost == 0);
|
||||
CHECK(fallback_resolution.order == 17);
|
||||
CHECK(fallback_resolution.used_fixed_order);
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Modes Apply Their Expected Baseline Boosts", tags::unit & tags::quadrature) {
|
||||
constexpr int base_order = 6;
|
||||
TEST_CASE(
|
||||
"Quadrature Modes Apply Their Expected Baseline Boosts",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
constexpr int base_order = 6;
|
||||
constexpr int global_boost = 3;
|
||||
|
||||
for (const quadrature::Mode mode : {quadrature::Mode::fast, quadrature::Mode::production, quadrature::Mode::convergence}) {
|
||||
const quadrature::Policy policy(quadrature::make_rule_set(mode, global_boost));
|
||||
const quadrature::Resolution resolution = policy.resolve(make_query(quadrature::Term::error_norm, base_order));
|
||||
for (const quadrature::Mode mode :
|
||||
{quadrature::Mode::fast, quadrature::Mode::production,
|
||||
quadrature::Mode::convergence}) {
|
||||
const quadrature::Policy policy(
|
||||
quadrature::make_rule_set(mode, global_boost)
|
||||
);
|
||||
const quadrature::Resolution resolution = policy.resolve(
|
||||
make_query(quadrature::Term::error_norm, base_order)
|
||||
);
|
||||
CHECK(resolution.boost == global_boost);
|
||||
CHECK(resolution.order == base_order + global_boost);
|
||||
}
|
||||
|
||||
const quadrature::Policy reference_policy(quadrature::make_rule_set(quadrature::Mode::reference, global_boost));
|
||||
const quadrature::Resolution reference_resolution = reference_policy.resolve(make_query(quadrature::Term::error_norm, base_order));
|
||||
const quadrature::Policy reference_policy(
|
||||
quadrature::make_rule_set(quadrature::Mode::reference, global_boost)
|
||||
);
|
||||
const quadrature::Resolution reference_resolution =
|
||||
reference_policy.resolve(
|
||||
make_query(quadrature::Term::error_norm, base_order)
|
||||
);
|
||||
CHECK(reference_resolution.boost == global_boost + 8);
|
||||
CHECK(reference_resolution.order == base_order + global_boost + 8);
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Policy Routes Every Term to Its Control", tags::unit & tags::quadrature) {
|
||||
TEST_CASE(
|
||||
"Quadrature Policy Routes Every Term to Its Control",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
quadrature::RuleSet rule_set;
|
||||
rule_set.gravity_hdiv_mass.boost = 1;
|
||||
rule_set.gravity_divergence.boost = 2;
|
||||
rule_set.gravity_source.boost = 3;
|
||||
rule_set.gravity_boundary.boost = 4;
|
||||
rule_set.density_projection.boost = 5;
|
||||
rule_set.mass_conservation.boost = 6;
|
||||
rule_set.center_of_mass.boost = 7;
|
||||
rule_set.quadrupole.boost = 8;
|
||||
rule_set.gravitational_energy.boost = 9;
|
||||
rule_set.virial.boost = 10;
|
||||
rule_set.error_norm.boost = 11;
|
||||
rule_set.gravity_hdiv_mass.boost = 1;
|
||||
rule_set.gravity_divergence.boost = 2;
|
||||
rule_set.gravity_source.boost = 3;
|
||||
rule_set.gravity_boundary.boost = 4;
|
||||
rule_set.centrifugal.boost = 18;
|
||||
rule_set.density_projection.boost = 5;
|
||||
rule_set.eos_closure.boost = 6;
|
||||
rule_set.hydrostatic_equilibrium.boost = 7;
|
||||
rule_set.isobaric_surface.boost = 8;
|
||||
rule_set.mesh_extension.boost = 9;
|
||||
rule_set.mass_conservation.boost = 10;
|
||||
rule_set.mass_normalization.boost = 11;
|
||||
rule_set.center_of_mass.boost = 12;
|
||||
rule_set.quadrupole.boost = 13;
|
||||
rule_set.gravitational_energy.boost = 14;
|
||||
rule_set.pressure_integral.boost = 15;
|
||||
rule_set.virial.boost = 16;
|
||||
rule_set.error_norm.boost = 17;
|
||||
const quadrature::Policy policy(rule_set);
|
||||
|
||||
const std::array<std::pair<quadrature::Term, int>, 11> cases = {{
|
||||
{quadrature::Term::gravity_hdiv_mass, 1},
|
||||
{quadrature::Term::gravity_divergence, 2},
|
||||
{quadrature::Term::gravity_source, 3},
|
||||
{quadrature::Term::gravity_boundary, 4},
|
||||
{quadrature::Term::density_projection, 5},
|
||||
{quadrature::Term::mass_conservation, 6},
|
||||
{quadrature::Term::center_of_mass, 7},
|
||||
{quadrature::Term::quadrupole, 8},
|
||||
{quadrature::Term::gravitational_energy, 9},
|
||||
{quadrature::Term::virial, 10},
|
||||
{quadrature::Term::error_norm, 11}
|
||||
}};
|
||||
const std::array<std::pair<quadrature::Term, int>, 18> cases = {
|
||||
{{quadrature::Term::gravity_hdiv_mass, 1},
|
||||
{quadrature::Term::gravity_divergence, 2},
|
||||
{quadrature::Term::gravity_source, 3},
|
||||
{quadrature::Term::gravity_boundary, 4},
|
||||
{quadrature::Term::centrifugal, 18},
|
||||
{quadrature::Term::density_projection, 5},
|
||||
{quadrature::Term::eos_closure, 6},
|
||||
{quadrature::Term::hydrostatic_equilibrium, 7},
|
||||
{quadrature::Term::isobaric_surface, 8},
|
||||
{quadrature::Term::mesh_extension, 9},
|
||||
{quadrature::Term::mass_conservation, 10},
|
||||
{quadrature::Term::mass_normalization, 11},
|
||||
{quadrature::Term::center_of_mass, 12},
|
||||
{quadrature::Term::quadrupole, 13},
|
||||
{quadrature::Term::gravitational_energy, 14},
|
||||
{quadrature::Term::pressure_integral, 15},
|
||||
{quadrature::Term::virial, 16},
|
||||
{quadrature::Term::error_norm, 17}}
|
||||
};
|
||||
|
||||
for (const auto& [term, expected_boost] : cases) {
|
||||
for (const auto &[term, expected_boost] : cases) {
|
||||
DYNAMIC_SECTION(get_term_name(term)) {
|
||||
const quadrature::Resolution resolution = policy.resolve(make_query(term, 20));
|
||||
const quadrature::Resolution resolution =
|
||||
policy.resolve(make_query(term, 20));
|
||||
CHECK(resolution.boost == expected_boost);
|
||||
CHECK(resolution.order == 20 + expected_boost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Quadrature Policy Rejects Invalid Orders", tags::unit & tags::quadrature) {
|
||||
const quadrature::Policy policy(quadrature::make_rule_set(quadrature::Mode::production));
|
||||
TEST_CASE(
|
||||
"Quadrature Policy Rejects Invalid Orders",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
const quadrature::Policy policy(
|
||||
quadrature::make_rule_set(quadrature::Mode::production)
|
||||
);
|
||||
|
||||
quadrature::Query negative_component_query = {
|
||||
.term = quadrature::Term::error_norm,
|
||||
.trial_order = -1
|
||||
.term = quadrature::Term::error_norm, .trial_order = -1
|
||||
};
|
||||
REQUIRE_THROWS_AS(policy.resolve(negative_component_query), std::invalid_argument);
|
||||
REQUIRE_THROWS_AS(
|
||||
policy.resolve(negative_component_query), std::invalid_argument
|
||||
);
|
||||
|
||||
quadrature::Query negative_base_query = {
|
||||
.term = quadrature::Term::error_norm,
|
||||
.base_order = -1
|
||||
.term = quadrature::Term::error_norm, .base_order = -1
|
||||
};
|
||||
REQUIRE_THROWS_AS(policy.resolve(negative_base_query), std::invalid_argument);
|
||||
REQUIRE_THROWS_AS(
|
||||
policy.resolve(negative_base_query), std::invalid_argument
|
||||
);
|
||||
|
||||
quadrature::RuleSet negative_fixed_rule_set;
|
||||
negative_fixed_rule_set.error_norm.fixed_order = -1;
|
||||
const quadrature::Policy negative_fixed_policy(negative_fixed_rule_set);
|
||||
REQUIRE_THROWS_AS(negative_fixed_policy.resolve(make_query(quadrature::Term::error_norm, 3)), std::invalid_argument);
|
||||
REQUIRE_THROWS_AS(
|
||||
negative_fixed_policy.resolve(
|
||||
make_query(quadrature::Term::error_norm, 3)
|
||||
),
|
||||
std::invalid_argument
|
||||
);
|
||||
|
||||
quadrature::RuleSet negative_resolved_rule_set;
|
||||
negative_resolved_rule_set.fallback.boost = -4;
|
||||
const quadrature::Policy negative_resolved_policy(negative_resolved_rule_set);
|
||||
REQUIRE_THROWS_AS(negative_resolved_policy.resolve(make_query(quadrature::Term::error_norm, 3)), std::invalid_argument);
|
||||
const quadrature::Policy negative_resolved_policy(
|
||||
negative_resolved_rule_set
|
||||
);
|
||||
REQUIRE_THROWS_AS(
|
||||
negative_resolved_policy.resolve(
|
||||
make_query(quadrature::Term::error_norm, 3)
|
||||
),
|
||||
std::invalid_argument
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("MFEM Rule Factory Returns the Resolved Rule", tags::unit & tags::quadrature) {
|
||||
quadrature::RuleSet rule_set = quadrature::make_rule_set(quadrature::Mode::production, 2);
|
||||
TEST_CASE(
|
||||
"MFEM Rule Factory Returns the Resolved Rule",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
quadrature::RuleSet rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production, 2);
|
||||
rule_set.error_norm.boost = 3;
|
||||
const quadrature::RuleFactory factory{quadrature::Policy(rule_set)};
|
||||
const quadrature::MfemRule selected_rule = factory.get(make_query(quadrature::Term::error_norm, 4), mfem::Geometry::CUBE);
|
||||
const mfem::IntegrationRule& expected_rule = mfem::IntRules.Get(mfem::Geometry::CUBE, 9);
|
||||
const quadrature::MfemRule selected_rule = factory.get(
|
||||
make_query(quadrature::Term::error_norm, 4), mfem::Geometry::CUBE
|
||||
);
|
||||
const mfem::IntegrationRule &expected_rule =
|
||||
mfem::IntRules.Get(mfem::Geometry::CUBE, 9);
|
||||
|
||||
REQUIRE(selected_rule.integration_rule != nullptr);
|
||||
CHECK(selected_rule.resolution.base_order == 4);
|
||||
@@ -219,47 +346,85 @@ TEST_CASE("MFEM Rule Factory Returns the Resolved Rule", tags::unit & tags::quad
|
||||
CHECK(selected_rule.integration_rule->GetNPoints() > 0);
|
||||
}
|
||||
|
||||
TEST_CASE("MFEM Quadrature Rule Integrates Tensor Polynomial Exactly", tags::unit & tags::quadrature) {
|
||||
TEST_CASE(
|
||||
"MFEM Quadrature Rule Integrates Tensor Polynomial Exactly",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
constexpr int polynomial_degree = 7;
|
||||
const quadrature::RuleFactory factory{quadrature::Policy(quadrature::make_rule_set(quadrature::Mode::production))};
|
||||
const quadrature::MfemRule selected_rule = factory.get(make_query(quadrature::Term::error_norm, polynomial_degree), mfem::Geometry::CUBE);
|
||||
const quadrature::RuleFactory factory{quadrature::Policy(
|
||||
quadrature::make_rule_set(quadrature::Mode::production)
|
||||
)};
|
||||
const quadrature::MfemRule selected_rule = factory.get(
|
||||
make_query(quadrature::Term::error_norm, polynomial_degree),
|
||||
mfem::Geometry::CUBE
|
||||
);
|
||||
double numerical_integral = 0.0;
|
||||
|
||||
for (int i = 0; i < selected_rule.integration_rule->GetNPoints(); ++i) {
|
||||
const mfem::IntegrationPoint& integration_point = selected_rule.integration_rule->IntPoint(i);
|
||||
numerical_integral += integration_point.weight * std::pow(integration_point.x, polynomial_degree) * std::pow(integration_point.y, polynomial_degree) * std::pow(integration_point.z, polynomial_degree);
|
||||
const mfem::IntegrationPoint &integration_point =
|
||||
selected_rule.integration_rule->IntPoint(i);
|
||||
numerical_integral += integration_point.weight *
|
||||
std::pow(integration_point.x, polynomial_degree) *
|
||||
std::pow(integration_point.y, polynomial_degree) *
|
||||
std::pow(integration_point.z, polynomial_degree);
|
||||
}
|
||||
|
||||
const double one_dimensional_integral = 1.0 / static_cast<double>(polynomial_degree + 1);
|
||||
const double analytic_integral = one_dimensional_integral * one_dimensional_integral * one_dimensional_integral;
|
||||
CHECK_THAT(numerical_integral, Catch::Matchers::WithinAbs(analytic_integral, 5.0e-14));
|
||||
const double one_dimensional_integral =
|
||||
1.0 / static_cast<double>(polynomial_degree + 1);
|
||||
const double analytic_integral = one_dimensional_integral *
|
||||
one_dimensional_integral *
|
||||
one_dimensional_integral;
|
||||
CHECK_THAT(
|
||||
numerical_integral,
|
||||
Catch::Matchers::WithinAbs(analytic_integral, 5.0e-14)
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Policy Controlled Hdiv Mass Assembly Matches Overintegrated Reference", tags::quadrature & tags::solver & tags::integration) {
|
||||
mfem::Mesh mesh = mfem::Mesh::MakeCartesian3D(1, 1, 1, mfem::Element::HEXAHEDRON, 1.0, 1.0, 1.0);
|
||||
TEST_CASE(
|
||||
"Policy Controlled Hdiv Mass Assembly Matches Overintegrated Reference",
|
||||
tags::quadrature &tags::solver &tags::integration
|
||||
) {
|
||||
mfem::Mesh mesh = mfem::Mesh::MakeCartesian3D(
|
||||
1, 1, 1, mfem::Element::HEXAHEDRON, 1.0, 1.0, 1.0
|
||||
);
|
||||
mfem::RT_FECollection rt_collection(2, 3);
|
||||
mfem::FiniteElementSpace rt_space(&mesh, &rt_collection);
|
||||
const mfem::FiniteElement* rt_element = rt_space.GetTypicalFE();
|
||||
mfem::ElementTransformation* transformation = mesh.GetElementTransformation(0);
|
||||
const int base_order = 2 * rt_element->GetOrder() + transformation->OrderW();
|
||||
const mfem::FiniteElement *rt_element = rt_space.GetTypicalFE();
|
||||
mfem::ElementTransformation *transformation =
|
||||
mesh.GetElementTransformation(0);
|
||||
const int base_order =
|
||||
2 * rt_element->GetOrder() + transformation->OrderW();
|
||||
|
||||
const quadrature::RuleFactory production_factory{quadrature::Policy(quadrature::make_rule_set(quadrature::Mode::production))};
|
||||
const quadrature::MfemRule production_rule = production_factory.get(make_query(quadrature::Term::gravity_hdiv_mass, base_order), rt_element->GetGeomType());
|
||||
const quadrature::RuleFactory production_factory{quadrature::Policy(
|
||||
quadrature::make_rule_set(quadrature::Mode::production)
|
||||
)};
|
||||
const quadrature::MfemRule production_rule = production_factory.get(
|
||||
make_query(quadrature::Term::gravity_hdiv_mass, base_order),
|
||||
rt_element->GetGeomType()
|
||||
);
|
||||
|
||||
quadrature::RuleSet reference_rule_set = quadrature::make_rule_set(quadrature::Mode::production);
|
||||
quadrature::RuleSet reference_rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production);
|
||||
reference_rule_set.gravity_hdiv_mass.boost = 8;
|
||||
const quadrature::RuleFactory reference_factory{quadrature::Policy(reference_rule_set)};
|
||||
const quadrature::MfemRule reference_rule = reference_factory.get(make_query(quadrature::Term::gravity_hdiv_mass, base_order), rt_element->GetGeomType());
|
||||
const quadrature::RuleFactory reference_factory{
|
||||
quadrature::Policy(reference_rule_set)
|
||||
};
|
||||
const quadrature::MfemRule reference_rule = reference_factory.get(
|
||||
make_query(quadrature::Term::gravity_hdiv_mass, base_order),
|
||||
rt_element->GetGeomType()
|
||||
);
|
||||
|
||||
mfem::BilinearForm production_mass(&rt_space);
|
||||
auto* production_integrator = new mfem::VectorFEMassIntegrator();
|
||||
production_integrator->SetIntegrationRule(*production_rule.integration_rule);
|
||||
auto *production_integrator = new mfem::VectorFEMassIntegrator();
|
||||
production_integrator->SetIntegrationRule(
|
||||
*production_rule.integration_rule
|
||||
);
|
||||
production_mass.AddDomainIntegrator(production_integrator);
|
||||
production_mass.Assemble();
|
||||
production_mass.Finalize();
|
||||
|
||||
mfem::BilinearForm reference_mass(&rt_space);
|
||||
auto* reference_integrator = new mfem::VectorFEMassIntegrator();
|
||||
auto *reference_integrator = new mfem::VectorFEMassIntegrator();
|
||||
reference_integrator->SetIntegrationRule(*reference_rule.integration_rule);
|
||||
reference_mass.AddDomainIntegrator(reference_integrator);
|
||||
reference_mass.Assemble();
|
||||
@@ -277,55 +442,417 @@ TEST_CASE("Policy Controlled Hdiv Mass Assembly Matches Overintegrated Reference
|
||||
|
||||
mfem::Vector difference(production_output);
|
||||
difference -= reference_output;
|
||||
const double relative_difference = difference.Norml2() / reference_output.Norml2();
|
||||
const double relative_difference =
|
||||
difference.Norml2() / reference_output.Norml2();
|
||||
INFO("Production quadrature order = " << production_rule.resolution.order);
|
||||
INFO("Reference quadrature order = " << reference_rule.resolution.order);
|
||||
INFO("Relative operator difference = " << relative_difference);
|
||||
CHECK_THAT(relative_difference, Catch::Matchers::WithinAbs(0.0, 1.0e-12));
|
||||
}
|
||||
|
||||
TEST_CASE("HDiv Mass Helper Resolves the MFEM Baseline", tags::unit & tags::quadrature & tags::solver) {
|
||||
mfem::Mesh mesh = mfem::Mesh::MakeCartesian3D(1, 1, 1, mfem::Element::HEXAHEDRON);
|
||||
TEST_CASE(
|
||||
"HDiv Mass Helper Resolves the MFEM Baseline",
|
||||
tags::unit &tags::quadrature &tags::solver
|
||||
) {
|
||||
mfem::Mesh mesh =
|
||||
mfem::Mesh::MakeCartesian3D(1, 1, 1, mfem::Element::HEXAHEDRON);
|
||||
mfem::RT_FECollection rt_collection(2, 3);
|
||||
mfem::FiniteElementSpace rt_space(&mesh, &rt_collection);
|
||||
|
||||
quadrature::RuleSet rule_set = quadrature::make_rule_set(quadrature::Mode::production);
|
||||
quadrature::RuleSet rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production);
|
||||
rule_set.gravity_hdiv_mass.boost = 3;
|
||||
quadrature::RuleFactory factory{quadrature::Policy(std::move(rule_set))};
|
||||
|
||||
const mfem::FiniteElement& element = *rt_space.GetTypicalFE();
|
||||
const mfem::ElementTransformation& transformation = *mesh.GetElementTransformation(0);
|
||||
const mfem::FiniteElement &element = *rt_space.GetTypicalFE();
|
||||
const mfem::ElementTransformation &transformation =
|
||||
*mesh.GetElementTransformation(0);
|
||||
mfem::VectorFEMassIntegrator integrator;
|
||||
|
||||
const quadrature::Resolution resolution = factory.configure_gravity_hdiv_mass(integrator, quadrature::QuadratureRole::discretization, element, transformation);
|
||||
const int expected_base_order = 2 * element.GetOrder() + transformation.OrderW();
|
||||
const quadrature::Resolution resolution =
|
||||
factory.configure_gravity_hdiv_mass(
|
||||
integrator, quadrature::QuadratureRole::discretization, element,
|
||||
transformation
|
||||
);
|
||||
const int expected_base_order =
|
||||
2 * element.GetOrder() + transformation.OrderW();
|
||||
|
||||
CHECK(resolution.base_order == expected_base_order);
|
||||
CHECK(resolution.boost == 3);
|
||||
CHECK(resolution.order == expected_base_order + 3);
|
||||
}
|
||||
|
||||
TEST_CASE("Gravity Divergence Helper Resolves Preconditioner Rule", tags::unit & tags::quadrature & tags::solver) {
|
||||
mfem::Mesh mesh = mfem::Mesh::MakeCartesian3D(1, 1, 1, mfem::Element::HEXAHEDRON);
|
||||
TEST_CASE(
|
||||
"Gravity Divergence Helper Resolves Preconditioner Rule",
|
||||
tags::unit &tags::quadrature &tags::solver
|
||||
) {
|
||||
mfem::Mesh mesh =
|
||||
mfem::Mesh::MakeCartesian3D(1, 1, 1, mfem::Element::HEXAHEDRON);
|
||||
mfem::RT_FECollection rt_collection(2, 3);
|
||||
mfem::L2_FECollection l2_collection(2, 3);
|
||||
mfem::FiniteElementSpace rt_space(&mesh, &rt_collection);
|
||||
mfem::FiniteElementSpace l2_space(&mesh, &l2_collection);
|
||||
|
||||
quadrature::RuleSet rule_set = quadrature::make_rule_set(quadrature::Mode::production);
|
||||
rule_set.gravity_divergence.boost = 2;
|
||||
quadrature::RuleSet rule_set =
|
||||
quadrature::make_rule_set(quadrature::Mode::production);
|
||||
rule_set.gravity_divergence.boost = 2;
|
||||
rule_set.roles.preconditioner.boost = 3;
|
||||
quadrature::RuleFactory factory{quadrature::Policy(std::move(rule_set))};
|
||||
|
||||
const mfem::FiniteElement& trial_element = *rt_space.GetTypicalFE();
|
||||
const mfem::FiniteElement& test_element = *l2_space.GetTypicalFE();
|
||||
const mfem::ElementTransformation& transformation = *mesh.GetElementTransformation(0);
|
||||
const mfem::FiniteElement &trial_element = *rt_space.GetTypicalFE();
|
||||
const mfem::FiniteElement &test_element = *l2_space.GetTypicalFE();
|
||||
const mfem::ElementTransformation &transformation =
|
||||
*mesh.GetElementTransformation(0);
|
||||
mfem::VectorFEDivergenceIntegrator integrator;
|
||||
|
||||
const quadrature::Resolution resolution = factory.configure_gravity_divergence(integrator, quadrature::QuadratureRole::preconditioner, trial_element, test_element, transformation);
|
||||
const int expected_base_order = std::max(0, trial_element.GetOrder() - 1) + test_element.GetOrder() + transformation.OrderW();
|
||||
const quadrature::Resolution resolution =
|
||||
factory.configure_gravity_divergence(
|
||||
integrator, quadrature::QuadratureRole::preconditioner,
|
||||
trial_element, test_element, transformation
|
||||
);
|
||||
const int expected_base_order = std::max(0, trial_element.GetOrder() - 1) +
|
||||
test_element.GetOrder() +
|
||||
transformation.OrderW();
|
||||
|
||||
CHECK(resolution.base_order == expected_base_order);
|
||||
CHECK(resolution.boost == 5);
|
||||
CHECK(resolution.order == expected_base_order + 5);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Field Registry Encodes Spaces Orders And Stable Pair Constraints",
|
||||
tags::unit &tags::quadrature &tags::initialization
|
||||
) {
|
||||
CHECK(mean_field::field::Density::Scalar::familyOrder == 2);
|
||||
CHECK(mean_field::field::Gravity::Potential::familyOrder == 2);
|
||||
CHECK(mean_field::field::Gravity::Flux::familyOrder == 2);
|
||||
CHECK(mean_field::field::Displacement::Vector::familyOrder == 3);
|
||||
CHECK(mean_field::field::Enthalpy::Scalar::familyOrder == 3);
|
||||
|
||||
CHECK((std::same_as<
|
||||
mean_field::field::Density::Scalar::Space, mean_field::field::L2>));
|
||||
CHECK((
|
||||
std::same_as<
|
||||
mean_field::field::Gravity::Potential::Space, mean_field::field::L2>
|
||||
));
|
||||
CHECK((std::same_as<
|
||||
mean_field::field::Gravity::Flux::Space, mean_field::field::RT>));
|
||||
CHECK((std::same_as<
|
||||
mean_field::field::Displacement::Vector::Space,
|
||||
mean_field::field::H1>));
|
||||
CHECK((std::same_as<
|
||||
mean_field::field::Enthalpy::Scalar::Space, mean_field::field::H1>));
|
||||
|
||||
CHECK(mean_field::field::Density::Scalar::rankValue == 0);
|
||||
CHECK(mean_field::field::Gravity::Potential::rankValue == 0);
|
||||
CHECK(mean_field::field::Gravity::Flux::rankValue == 1);
|
||||
CHECK(mean_field::field::Displacement::Vector::rankValue == 1);
|
||||
CHECK(mean_field::field::Enthalpy::Scalar::rankValue == 0);
|
||||
CHECK(
|
||||
mean_field::field::Gravity::Flux::familyOrder ==
|
||||
mean_field::field::Gravity::Potential::familyOrder
|
||||
);
|
||||
|
||||
CHECK(
|
||||
std::is_empty_v<mean_field::field::Field<mean_field::field::Gravity>>
|
||||
);
|
||||
CHECK(
|
||||
std::is_empty_v<
|
||||
mean_field::field::Field<mean_field::field::Displacement>>
|
||||
);
|
||||
CHECK(
|
||||
std::is_empty_v<mean_field::field::Field<mean_field::field::Density>>
|
||||
);
|
||||
CHECK(
|
||||
std::is_empty_v<mean_field::field::Field<mean_field::field::Enthalpy>>
|
||||
);
|
||||
|
||||
STATIC_CHECK(field::RegisteredQuantity<field::BarotropicConstant::Scalar>);
|
||||
STATIC_CHECK(
|
||||
field::GlobalScalarQuantity<field::BarotropicConstant::Scalar>
|
||||
);
|
||||
STATIC_CHECK_FALSE(field::FieldQuantity<field::BarotropicConstant::Scalar>);
|
||||
|
||||
STATIC_CHECK(
|
||||
field::BarotropicConstant::Scalar::storageKind ==
|
||||
field::StorageKind::global_scalar
|
||||
);
|
||||
STATIC_CHECK(field::BarotropicConstant::Scalar::staticBlockSize == 1);
|
||||
|
||||
STATIC_CHECK(
|
||||
field::Enthalpy::Scalar::storageKind ==
|
||||
field::StorageKind::finite_element
|
||||
);
|
||||
STATIC_CHECK(
|
||||
field::Enthalpy::Scalar::staticBlockSize == field::dynamicBlockSize
|
||||
);
|
||||
|
||||
STATIC_CHECK_FALSE(
|
||||
CanMakeFec<
|
||||
field::Field<field::BarotropicConstant>,
|
||||
field::BarotropicConstant::Scalar>
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Field Forms Produce Typed Quadrature Queries",
|
||||
tags::unit &tags::quadrature
|
||||
) {
|
||||
using GravityField = field::Field<field::Gravity>;
|
||||
using DensityField = field::Field<field::Density>;
|
||||
using EnthalpyField = field::Field<field::Enthalpy>;
|
||||
|
||||
constexpr quadrature::Query hdiv_query =
|
||||
GravityField::make_query<field::Gravity::Form::HDivMass>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::ALL, quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query divergence_query =
|
||||
GravityField::make_query<field::Gravity::Form::DivergenceCoupling>(
|
||||
quadrature::QuadratureRole::preconditioner, 2
|
||||
);
|
||||
constexpr quadrature::Query source_query =
|
||||
GravityField::make_query<field::Gravity::Form::SourceProjection>(
|
||||
quadrature::QuadratureRole::projection, 2, {},
|
||||
utils::DOMAINS::STELLAR
|
||||
);
|
||||
constexpr quadrature::Query center_of_mass_query =
|
||||
DensityField::make_query<field::Density::Form::CenterOfMass>(
|
||||
quadrature::QuadratureRole::diagnostic, 2, std::array<int, 1>{1},
|
||||
utils::DOMAINS::STELLAR
|
||||
);
|
||||
constexpr quadrature::Query eos_closure_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::EosClosureSource>(
|
||||
quadrature::QuadratureRole::discretization, 2,
|
||||
std::array<int, 1>{6}, utils::DOMAINS::STELLAR,
|
||||
quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query equilibrium_gravity_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::EquilibriumGravity>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
|
||||
constexpr quadrature::Query equilibrium_constant_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::EquilibriumConstant>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query rotation_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::EquilibriumRotation>(
|
||||
quadrature::QuadratureRole::discretization, 2,
|
||||
std::array<int, 1>{2}, utils::DOMAINS::STELLAR,
|
||||
quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query isobaric_surface_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::IsobaricSurface>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query mesh_extension_query =
|
||||
field::Field<field::Displacement>::make_query<
|
||||
field::Displacement::Form::MeshExtension>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::ALL, quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query mass_normalization_query =
|
||||
DensityField::make_query<field::Density::Form::MassNormalization>(
|
||||
quadrature::QuadratureRole::discretization, 2, {},
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
constexpr quadrature::Query pressure_integral_query =
|
||||
EnthalpyField::make_query<field::Enthalpy::Form::PressureIntegral>(
|
||||
quadrature::QuadratureRole::diagnostic, 2, std::array<int, 1>{9},
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
|
||||
STATIC_CHECK(
|
||||
mean_field::field::Gravity::Form::SourceProjection::dynamicOrderCount ==
|
||||
0
|
||||
);
|
||||
STATIC_CHECK(hdiv_query.base_order.has_value());
|
||||
STATIC_CHECK(*hdiv_query.base_order == 8);
|
||||
STATIC_CHECK(*divergence_query.base_order == 6);
|
||||
STATIC_CHECK(*source_query.base_order == 6);
|
||||
STATIC_CHECK(*center_of_mass_query.base_order == 5);
|
||||
STATIC_CHECK(*eos_closure_query.base_order == 13);
|
||||
STATIC_CHECK(*equilibrium_gravity_query.base_order == 7);
|
||||
STATIC_CHECK(*rotation_query.base_order == 7);
|
||||
STATIC_CHECK(*isobaric_surface_query.base_order == 8);
|
||||
STATIC_CHECK(*mesh_extension_query.base_order == 6);
|
||||
STATIC_CHECK(*mass_normalization_query.base_order == 4);
|
||||
STATIC_CHECK(*pressure_integral_query.base_order == 14);
|
||||
STATIC_CHECK(*equilibrium_constant_query.base_order == 5);
|
||||
|
||||
CHECK(
|
||||
equilibrium_constant_query.term ==
|
||||
quadrature::Term::hydrostatic_equilibrium
|
||||
);
|
||||
CHECK(hdiv_query.term == mean_field::quadrature::Term::gravity_hdiv_mass);
|
||||
CHECK(
|
||||
hdiv_query.role ==
|
||||
mean_field::quadrature::QuadratureRole::discretization
|
||||
);
|
||||
CHECK(hdiv_query.domain == mean_field::utils::DOMAINS::ALL);
|
||||
CHECK(hdiv_query.mapping == mean_field::quadrature::MappingKind::general);
|
||||
CHECK(source_query.term == mean_field::quadrature::Term::gravity_source);
|
||||
CHECK(
|
||||
center_of_mass_query.term ==
|
||||
mean_field::quadrature::Term::center_of_mass
|
||||
);
|
||||
CHECK(eos_closure_query.term == mean_field::quadrature::Term::eos_closure);
|
||||
CHECK(
|
||||
equilibrium_gravity_query.term ==
|
||||
mean_field::quadrature::Term::hydrostatic_equilibrium
|
||||
);
|
||||
CHECK(
|
||||
rotation_query.term ==
|
||||
mean_field::quadrature::Term::hydrostatic_equilibrium
|
||||
);
|
||||
CHECK(
|
||||
isobaric_surface_query.term ==
|
||||
mean_field::quadrature::Term::isobaric_surface
|
||||
);
|
||||
CHECK(
|
||||
mesh_extension_query.term ==
|
||||
mean_field::quadrature::Term::mesh_extension
|
||||
);
|
||||
CHECK(
|
||||
mass_normalization_query.term ==
|
||||
mean_field::quadrature::Term::mass_normalization
|
||||
);
|
||||
CHECK(
|
||||
pressure_integral_query.term ==
|
||||
mean_field::quadrature::Term::pressure_integral
|
||||
);
|
||||
|
||||
CHECK_THROWS_AS(
|
||||
(GravityField::make_query<mean_field::field::Gravity::Form::HDivMass>(
|
||||
mean_field::quadrature::QuadratureRole::discretization, -1
|
||||
)),
|
||||
std::invalid_argument
|
||||
);
|
||||
CHECK_THROWS_AS(
|
||||
(DensityField::make_query<
|
||||
mean_field::field::Density::Form::CenterOfMass>(
|
||||
mean_field::quadrature::QuadratureRole::diagnostic, 2,
|
||||
std::array<int, 1>{-1}
|
||||
)),
|
||||
std::invalid_argument
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Field Factories Construct The Registered MFEM Collections",
|
||||
tags::unit &tags::quadrature &tags::initialization
|
||||
) {
|
||||
using GravityField = field::Field<field::Gravity>;
|
||||
using DisplacementField = field::Field<field::Displacement>;
|
||||
using DensityField = field::Field<field::Density>;
|
||||
using EnthalpyField = field::Field<field::Enthalpy>;
|
||||
|
||||
std::unique_ptr<mfem::FiniteElementCollection> density_collection =
|
||||
DensityField::make_fec<field::Density::Scalar>(3);
|
||||
std::unique_ptr<mfem::FiniteElementCollection> potential_collection =
|
||||
GravityField::make_fec<field::Gravity::Potential>(3);
|
||||
std::unique_ptr<mfem::FiniteElementCollection> flux_collection =
|
||||
GravityField::make_fec<field::Gravity::Flux>(3);
|
||||
std::unique_ptr<mfem::FiniteElementCollection> displacement_collection =
|
||||
DisplacementField::make_fec<field::Displacement::Vector>(3);
|
||||
std::unique_ptr<mfem::FiniteElementCollection> enthalpy_collection =
|
||||
EnthalpyField::make_fec<field::Enthalpy::Scalar>(3);
|
||||
|
||||
CHECK(
|
||||
dynamic_cast<mfem::L2_FECollection *>(density_collection.get()) !=
|
||||
nullptr
|
||||
);
|
||||
CHECK(
|
||||
dynamic_cast<mfem::L2_FECollection *>(potential_collection.get()) !=
|
||||
nullptr
|
||||
);
|
||||
CHECK(
|
||||
dynamic_cast<mfem::RT_FECollection *>(flux_collection.get()) != nullptr
|
||||
);
|
||||
CHECK(
|
||||
dynamic_cast<mfem::H1_FECollection *>(displacement_collection.get()) !=
|
||||
nullptr
|
||||
);
|
||||
CHECK(
|
||||
dynamic_cast<mfem::H1_FECollection *>(enthalpy_collection.get()) !=
|
||||
nullptr
|
||||
);
|
||||
|
||||
CHECK_THROWS_AS(
|
||||
(DensityField::make_fec<mean_field::field::Density::Scalar>(0)),
|
||||
std::invalid_argument
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"FEM Setup Realizes Every Registered Field Independently",
|
||||
tags::integration &tags::initialization &tags::solver
|
||||
) {
|
||||
const utils::Args args = test_utils::setup_args();
|
||||
const fem::FEM fem = fem::setup_fem(args.mesh_file, args, 0);
|
||||
|
||||
REQUIRE(fem.okay());
|
||||
REQUIRE(fem.mesh != nullptr);
|
||||
REQUIRE(fem.densityFes != nullptr);
|
||||
REQUIRE(fem.gravityPotentialFes != nullptr);
|
||||
REQUIRE(fem.gravityFluxFes != nullptr);
|
||||
REQUIRE(fem.displacementFes != nullptr);
|
||||
REQUIRE(fem.enthalpyFes != nullptr);
|
||||
|
||||
CHECK(fem.densityFes.get() != fem.gravityPotentialFes.get());
|
||||
CHECK(fem.densityFec.get() != fem.gravityPotentialFec.get());
|
||||
|
||||
CHECK(
|
||||
fem.densityFes->GetMaxElementOrder() ==
|
||||
mean_field::field::Density::Scalar::familyOrder
|
||||
);
|
||||
CHECK(
|
||||
fem.gravityPotentialFes->GetMaxElementOrder() ==
|
||||
mean_field::field::Gravity::Potential::familyOrder
|
||||
);
|
||||
CHECK(
|
||||
fem.gravityFluxFes->GetMaxElementOrder() ==
|
||||
mean_field::field::Gravity::Flux::familyOrder + 1
|
||||
);
|
||||
CHECK(
|
||||
fem.displacementFes->GetMaxElementOrder() ==
|
||||
mean_field::field::Displacement::Vector::familyOrder
|
||||
);
|
||||
CHECK(
|
||||
fem.enthalpyFes->GetMaxElementOrder() ==
|
||||
mean_field::field::Enthalpy::Scalar::familyOrder
|
||||
);
|
||||
|
||||
CHECK(fem.densityFes->GetVDim() == 1);
|
||||
CHECK(fem.gravityPotentialFes->GetVDim() == 1);
|
||||
CHECK(fem.gravityFluxFes->GetVDim() == 1);
|
||||
CHECK(fem.displacementFes->GetVDim() == fem.mesh->SpaceDimension());
|
||||
CHECK(fem.displacementFes->GetOrdering() == mfem::Ordering::byNODES);
|
||||
CHECK(fem.enthalpyFes->GetVDim() == 1);
|
||||
|
||||
REQUIRE(fem.blockTrueOffsets.Size() == 3);
|
||||
CHECK(fem.blockTrueOffsets[0] == 0);
|
||||
CHECK(fem.blockTrueOffsets[1] == fem.displacementFes->GetTrueVSize());
|
||||
CHECK(
|
||||
fem.blockTrueOffsets[2] ==
|
||||
fem.displacementFes->GetTrueVSize() + fem.densityFes->GetTrueVSize()
|
||||
);
|
||||
|
||||
REQUIRE(fem.gravityBlockTrueOffsets.Size() == 3);
|
||||
CHECK(fem.gravityBlockTrueOffsets[0] == 0);
|
||||
CHECK(fem.gravityBlockTrueOffsets[1] == fem.gravityFluxFes->GetTrueVSize());
|
||||
CHECK(
|
||||
fem.gravityBlockTrueOffsets[2] ==
|
||||
fem.gravityFluxFes->GetTrueVSize() +
|
||||
fem.gravityPotentialFes->GetTrueVSize()
|
||||
);
|
||||
|
||||
CHECK(
|
||||
fem.gravityContext.source_form->Height() ==
|
||||
fem.gravityPotentialFes->GetTrueVSize()
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user