feat(libmeanfield): variadic refactor
also added normaliztion operator
This commit is contained in:
@@ -3,6 +3,7 @@ module;
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -133,21 +134,15 @@ namespace {
|
||||
|
||||
namespace mean_field::seed::detail {
|
||||
ProjectedRadialFields projectRadialFields(
|
||||
const equilibrium::StellarDiscretization &discretization,
|
||||
fem::FEM &finiteElementModel,
|
||||
const RadialProfile &profile,
|
||||
const dimensions::MassValue targetMass,
|
||||
const dimensions::PressureValue targetSurfacePressure,
|
||||
const StellarEquilibriumProjectionOptions &options
|
||||
) {
|
||||
validate_profile(profile);
|
||||
if (!std::isfinite(options.surfaceRadiusRelativeTolerance) || options.surfaceRadiusRelativeTolerance < 0.0) {
|
||||
throw std::invalid_argument("The surface-radius projection tolerance must be finite and nonnegative.");
|
||||
}
|
||||
if (targetSurfacePressure.value() != 0.0) {
|
||||
throw std::invalid_argument("A Lane-Emden radial seed requires a zero-pressure isobaric surface.");
|
||||
}
|
||||
|
||||
fem::FEM &finiteElementModel = discretization.finiteElementModel();
|
||||
const SurfaceRadiusRange surfaceRadius = measure_surface_radius(finiteElementModel);
|
||||
const double targetRadius = profile.stellarRadius.value();
|
||||
const double comparisonScale = std::max({targetRadius, surfaceRadius.maximum, 1.0e-300});
|
||||
@@ -185,6 +180,20 @@ namespace mean_field::seed::detail {
|
||||
const physics::GravitySolution gravitySolution =
|
||||
physics::solve_gravity_field(finiteElementModel, options.gravity, densityField, displacementField);
|
||||
|
||||
double radialMomentIntegral = 0.0;
|
||||
for (int index = 0; index + 1 < profile.radius.Size(); ++index) {
|
||||
const double leftRadius = profile.radius(index);
|
||||
const double rightRadius = profile.radius(index + 1);
|
||||
const double leftIntegrand = profile.density(index) * std::pow(leftRadius, 4);
|
||||
const double rightIntegrand = profile.density(index + 1) * std::pow(rightRadius, 4);
|
||||
radialMomentIntegral +=
|
||||
0.5 * (rightRadius - leftRadius) * (leftIntegrand + rightIntegrand);
|
||||
}
|
||||
const double sphericalMomentOfInertia = (8.0 * std::numbers::pi / 3.0) * radialMomentIntegral;
|
||||
if (!std::isfinite(sphericalMomentOfInertia) || sphericalMomentOfInertia <= 0.0) {
|
||||
throw std::runtime_error("The radial profile has no finite, positive moment of inertia.");
|
||||
}
|
||||
|
||||
const field::FieldDofGridFunctionAdapter densityAdapter =
|
||||
field::make_field_dof_grid_function_adapter<field::Density, DomainSchema>(*finiteElementModel.densityFes);
|
||||
const field::FieldDofGridFunctionAdapter enthalpyAdapter =
|
||||
@@ -203,7 +212,8 @@ namespace mean_field::seed::detail {
|
||||
.gravityGradient = gravityFluxAdapter.gather(gravitySolution.gradPhi),
|
||||
.gravityPotential = gravityPotentialAdapter.gather(gravitySolution.phi),
|
||||
.specificEnthalpy = enthalpyAdapter.gather(enthalpyField),
|
||||
.bernoulliConstant = -utils::G * targetMass.value() / targetRadius
|
||||
.bernoulliConstant = -utils::G * targetMass.value() / targetRadius,
|
||||
.sphericalMomentOfInertia = sphericalMomentOfInertia
|
||||
};
|
||||
}
|
||||
} // namespace mean_field::seed::detail
|
||||
|
||||
Reference in New Issue
Block a user