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.
49 lines
2.9 KiB
C++
49 lines
2.9 KiB
C++
#include <cmath>
|
|
#include <print>
|
|
|
|
#include "serif/eos/evaluation.hpp"
|
|
#include "serif/eos/models/polytropic.hpp"
|
|
#include "serif/equations/barotropic_density.hpp"
|
|
#include "serif/equations/surface_potential.hpp"
|
|
|
|
/** @brief Evaluate manufactured interior and surface samples and inspect their exact derivatives. */
|
|
int main() {
|
|
namespace equations = serif::equations;
|
|
namespace dimensions = serif::dimensions;
|
|
|
|
const serif::eos::models::Polytrope eos{1.0, 0.8};
|
|
const double density = 0.5, angular_velocity = 0.3, surface_level = 1.2;
|
|
const dimensions::PressureValue surface_pressure{0.0};
|
|
const equations::BarotropicDensityBalance density_balance{eos, surface_pressure};
|
|
const equations::SurfacePotentialBalance surface;
|
|
using Balance = decltype(density_balance);
|
|
|
|
// Density supplies the pressure potential through the EOS; it is not another solved field.
|
|
const auto surface_density = serif::eos::evaluate<dimensions::MassDensity>(eos, surface_pressure);
|
|
const double pressure_potential = serif::eos::evaluate<dimensions::BarotropicPressurePotential>(eos, dimensions::DensityValue{density}).value();
|
|
const double surface_pressure_potential = serif::eos::evaluate<dimensions::BarotropicPressurePotential>(eos, surface_density).value();
|
|
equations::EquationPoint<Balance::Operands> mechanics;
|
|
mechanics.position = {0.3, 0.4, 0.0};
|
|
mechanics.fields.get<Balance::Density>() = density;
|
|
mechanics.fields.get<Balance::AngularVelocity>() = angular_velocity;
|
|
mechanics.fields.get<Balance::SurfaceLevel>() = surface_level;
|
|
mechanics.fields.get<Balance::Potential>() = surface_level - pressure_potential + surface_pressure_potential +
|
|
angular_velocity * angular_velocity * density_balance.rotation().centrifugal_potential(mechanics.position);
|
|
const auto interior_balance = density_balance.evaluate(mechanics);
|
|
|
|
equations::EquationPoint<decltype(surface)::Operands> boundary;
|
|
boundary.position = mechanics.position;
|
|
boundary.fields.get<decltype(surface)::Potential>() = surface_level +
|
|
angular_velocity * angular_velocity * surface.rotation().centrifugal_potential(boundary.position);
|
|
boundary.fields.get<decltype(surface)::SurfaceLevel>() = surface_level;
|
|
boundary.fields.get<decltype(surface)::AngularVelocity>() = angular_velocity;
|
|
const auto surface_balance = surface.evaluate(boundary);
|
|
|
|
std::println("Density balance residual = {:.3e}; angular-velocity derivative = {}",
|
|
interior_balance.residual, interior_balance.field_derivatives.get<Balance::AngularVelocity>());
|
|
std::println("Surface potential residual = {:.3e}; derivative with respect to surface level = {}",
|
|
surface_balance.residual, surface_balance.field_derivatives.get<decltype(surface)::SurfaceLevel>());
|
|
// complete_sandbox assembles these same physical equations on its finite-element mesh.
|
|
return std::abs(interior_balance.residual) < 1.0e-12 && std::abs(surface_balance.residual) < 1.0e-12 ? 0 : 1;
|
|
}
|