test(tests): added test suite
The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
This commit is contained in:
165
tests/equations/gravity_port_fixture.cpp
Normal file
165
tests/equations/gravity_port_fixture.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <stroid/stroid.h>
|
||||
#include "serif/tests/equations/gravity_port.hpp"
|
||||
|
||||
namespace serif::tests::equations::gravity_port {
|
||||
/// Project an old test polynomial into the same registered coefficient representation.
|
||||
Vector project_vector(const discretization::backend::mfem::DofMap& binding, std::function<void(const Vector&, Vector&)> function) {
|
||||
::mfem::VectorFunctionCoefficient coefficient(3, std::move(function));
|
||||
::mfem::GridFunction values(&binding.space());
|
||||
values.ProjectCoefficient(coefficient);
|
||||
return binding.gather(values);
|
||||
}
|
||||
Coefficients zeros(const GravityFixture& f) {
|
||||
return {constant(f.potential_binding.size(), 0.0),
|
||||
constant(f.density_binding.size(), 0.0), constant(f.displacement_binding.size(), 0.0)};
|
||||
}
|
||||
Vector sequence(int size, double scale, double phase) {
|
||||
Vector v(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
const double index = i + 1;
|
||||
v[i] = scale * (std::sin(0.31 * index + phase) + 0.37 * std::cos(0.17 * index - phase));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
Vector prepared_sequence(int size, double phase) {
|
||||
Vector v(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
const double index = i + 1;
|
||||
v[i] = std::sin(0.37 * index + phase) + 0.31 * std::cos(0.19 * index - 0.5 * phase);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
Vector operator_sequence(int size, double phase) {
|
||||
Vector v(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
const double index = i + 1;
|
||||
v[i] = 0.4 * std::sin(0.37 * index + phase) + 0.2 * std::cos(0.19 * index - phase);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
Coefficients state(GravityFixture& f, bool deformed) {
|
||||
return {sequence(f.potential_binding.size(), 0.3, 0.37),
|
||||
sequence(f.density_binding.size(), 0.7, 0.11), prepared_displacement(f, deformed ? 1.0 : 0.0)};
|
||||
}
|
||||
Coefficients direction(GravityFixture& f, int column) {
|
||||
auto d = zeros(f);
|
||||
if (column == 0) {
|
||||
d.density = sequence(d.density.Size(), 0.13, 0.19);
|
||||
} else {
|
||||
d.potential = sequence(d.potential.Size(), 0.09, 0.41);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
Vector prepared_displacement(GravityFixture& f, double scale) {
|
||||
return project_vector(f.displacement_binding, [scale](const Vector& x, Vector& u) {
|
||||
u.SetSize(3);
|
||||
u[0] = scale * (0.04 * x[0] + 0.01 * x[1] * x[2]);
|
||||
u[1] = scale * (-0.03 * x[1] + 0.008 * x[0] * x[2]);
|
||||
u[2] = scale * (0.02 * x[2] - 0.006 * x[0] * x[1]);
|
||||
});
|
||||
}
|
||||
Vector affine_displacement(GravityFixture& f, double scale) {
|
||||
return project_vector(f.displacement_binding, [scale](const Vector& x, Vector& u) {
|
||||
u = x;
|
||||
u *= scale;
|
||||
});
|
||||
}
|
||||
Vector kernel_displacement(GravityFixture& f) {
|
||||
return project_vector(f.displacement_binding, [](const Vector& x, Vector& u) {
|
||||
u.SetSize(3);
|
||||
u[0] = 0.025 * x[0] + 0.006 * x[1] * x[2];
|
||||
u[1] = -0.018 * x[1] + 0.005 * x[0] * x[2];
|
||||
u[2] = 0.014 * x[2] + 0.004 * x[0] * x[1];
|
||||
});
|
||||
}
|
||||
Vector geometry_direction(GravityFixture& f, int index) {
|
||||
return project_vector(f.displacement_binding, [index](const Vector& x, Vector& u) {
|
||||
u.SetSize(3);
|
||||
if (index == 0) {
|
||||
u[0] = 0.16 * x[0] + 0.03 * x[1];
|
||||
u[1] = -0.11 * x[1] + 0.02 * x[2];
|
||||
u[2] = 0.13 * x[2] - 0.025 * x[0];
|
||||
} else {
|
||||
u[0] = -0.07 * x[1] + 0.025 * x[2];
|
||||
u[1] = 0.09 * x[0] + 0.04 * x[2];
|
||||
u[2] = -0.08 * x[2] + 0.03 * x[0] * x[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
Vector kernel_density(GravityFixture& f, bool secondary) {
|
||||
return f.project(f.density_binding, [secondary](const Vector& x) {
|
||||
return secondary ? 0.8 - 0.11 * x[0] + 0.13 * x[1] - 0.06 * x[2] + 0.03 * x[1] * x[2]
|
||||
: 1.2 + 0.16 * x[0] - 0.09 * x[1] + 0.07 * x[2] + 0.04 * x[0] * x[1];
|
||||
});
|
||||
}
|
||||
Vector domain_density(GravityFixture& f, bool stellar) {
|
||||
Vector density(f.density_space.GetVSize());
|
||||
std::vector<bool> stellar_dofs(density.Size(), false);
|
||||
::mfem::Array<int> dofs;
|
||||
for (int element = 0; element < f.mesh.GetNE(); ++element) {
|
||||
if (!Schema::template domain_id_belongs_to<discretization::domain::StellarDomains>(f.mesh.GetAttribute(element))) {
|
||||
continue;
|
||||
}
|
||||
f.density_space.GetElementDofs(element, dofs);
|
||||
for (const int dof : dofs) {
|
||||
stellar_dofs[dof] = true;
|
||||
}
|
||||
}
|
||||
for (int dof = 0; dof < density.Size(); ++dof) {
|
||||
density[dof] = stellar_dofs[dof] == stellar ? 1.0 : 0.0;
|
||||
}
|
||||
return density;
|
||||
}
|
||||
std::unique_ptr<GravityFixture> stellar_fixture(int refinement_levels, int geometry_order) {
|
||||
stroid::config::MeshConfig config;
|
||||
config.refinement_levels = refinement_levels;
|
||||
config.order = geometry_order;
|
||||
config.include_external_domain = true;
|
||||
config.r_core = 0.25;
|
||||
config.r_star = 1.0;
|
||||
config.r_infinity = 4.0;
|
||||
config.flattening = 0.0;
|
||||
config.optimization_methods = stroid::config::OptimizationMethods{false, true};
|
||||
auto mesh = stroid::GenerateMesh(config);
|
||||
REQUIRE(mesh.exterior_coordinate != nullptr);
|
||||
REQUIRE(mesh.exterior_coordinate->values != nullptr);
|
||||
auto fixture = std::make_unique<GravityFixture>(::mfem::Mesh(*mesh.mesh));
|
||||
::mfem::GridFunctionCoefficient coordinate(mesh.exterior_coordinate->values.get());
|
||||
fixture->compactification.ProjectCoefficient(coordinate);
|
||||
return fixture;
|
||||
}
|
||||
Coefficients shifted(const Coefficients& v, const Coefficients& d, double scale) {
|
||||
auto result = v;
|
||||
result.potential.Add(scale, d.potential);
|
||||
result.density.Add(scale, d.density);
|
||||
result.displacement.Add(scale, d.displacement);
|
||||
return result;
|
||||
}
|
||||
double relative(const Vector& actual, const Vector& expected, double floor) {
|
||||
REQUIRE(actual.Size() == expected.Size());
|
||||
Vector difference(actual);
|
||||
difference -= expected;
|
||||
return difference.Norml2() / std::max(expected.Norml2(), floor);
|
||||
}
|
||||
double symmetric_relative(const Vector& first, const Vector& second) {
|
||||
REQUIRE(first.Size() == second.Size());
|
||||
Vector difference(first);
|
||||
difference -= second;
|
||||
return difference.Norml2() / std::max({first.Norml2(), second.Norml2(), 1.0e-14});
|
||||
}
|
||||
double prepared_relative(const Vector& actual, const Vector& expected) {
|
||||
return relative(actual, expected, std::numeric_limits<double>::epsilon());
|
||||
}
|
||||
double pairing_relative(double actual, double expected) {
|
||||
return std::abs(actual - expected) / std::max(std::abs(expected), std::numeric_limits<double>::epsilon());
|
||||
}
|
||||
Vector combination(const Vector& first, double a, const Vector& second, double b) {
|
||||
Vector result(first);
|
||||
result *= a;
|
||||
result.Add(b, second);
|
||||
return result;
|
||||
}
|
||||
} // namespace serif::tests::equations::gravity_port
|
||||
Reference in New Issue
Block a user