feat(FieldDofMap): Completed FieldDofMap migration

also removed legacy BarotropicPolytrope implementation
This commit is contained in:
2026-08-29 08:56:36 -04:00
parent 177ae8b38a
commit 36adfa1174
104 changed files with 26967 additions and 26916 deletions

View File

@@ -6,6 +6,32 @@ module mean_field;
import :mapping.coefficients;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
mfem::Array<int> make_domain_marker(
const mfem::Mesh &mesh,
const mean_field::utils::DOMAINS domain
) {
switch (domain) {
case mean_field::utils::DOMAINS::CORE:
return mean_field::utils::domain::make_attribute_marker<
mean_field::utils::domain::Core, DomainSchema>(mesh);
case mean_field::utils::DOMAINS::ENVELOPE:
return mean_field::utils::domain::make_attribute_marker<
mean_field::utils::domain::Envelope, DomainSchema>(mesh);
case mean_field::utils::DOMAINS::ALL:
return mean_field::utils::domain::make_attribute_marker<
mean_field::utils::domain::All, DomainSchema>(mesh);
case mean_field::utils::DOMAINS::STELLAR:
return mean_field::utils::domain::make_attribute_marker<
mean_field::utils::domain::Stellar, DomainSchema>(mesh);
case mean_field::utils::DOMAINS::VACUUM:
return mean_field::utils::domain::make_attribute_marker<
mean_field::utils::domain::Vacuum, DomainSchema>(mesh);
}
MFEM_ABORT("Unsupported integration domain.");
}
template <typename FormT>
const mfem::IntegrationRule &get_density_rule(
const mean_field::fem::FEM &fem,
@@ -36,14 +62,16 @@ namespace mean_field::analysis {
mfem::LinearForm lf(fem.densityFes.get());
mfem::GridFunctionCoefficient gf_c(&gf);
double local_integral;
mfem::Array<int> elem_markers;
populate_element_mask(fem.mesh.get(), domain, elem_markers);
mfem::Array<int> elem_markers = make_domain_marker(*fem.mesh, domain);
const mfem::ElementTransformation &representative_transformation = *fem.mesh->GetElementTransformation(0);
const mfem::IntegrationRule &integration_rule =
get_density_rule<field::Density::Form::MassConservation>(fem, representative_transformation, {}, domain);
if (fem.has_mapping() && coord_space == mapping::COORDINATE_SPACE::PHYSICAL) {
mapping::MappedScalarCoefficient mapped_gf_c(*fem.mapping, gf_c);
mapping::MappedScalarCoefficient mapped_gf_c(
*fem.domainMapperStateless, *fem.displacement,
*fem.compactificationCoordinate, gf_c
);
// ReSharper disable once CppDFAMemoryLeak // Disabled because MFEM
// takes ownership so memory is not leaked
@@ -78,12 +106,17 @@ namespace mean_field::analysis {
const mfem::GridFunction &rho
) {
const int dim = fem.mesh->Dimension();
mapping::GridFunctionMappingEvaluator mapping_evaluator(
*fem.domainMapperStateless, *fem.displacement,
*fem.compactificationCoordinate
);
mfem::Vector local_com(dim);
local_com = 0.0;
double local_mass = 0.0;
for (int i = 0; i < fem.mesh->GetNE(); ++i) {
if (fem.mesh->GetAttribute(i) == 3)
if (!DomainSchema::template attribute_belongs_to<utils::domain::Stellar>(
fem.mesh->GetAttribute(i)))
continue;
mfem::ElementTransformation *trans = fem.mesh->GetElementTransformation(i);
const mfem::IntegrationRule &ir = get_density_rule<field::Density::Form::CenterOfMass>(
@@ -94,18 +127,16 @@ namespace mean_field::analysis {
const mfem::IntegrationPoint &ip = ir.IntPoint(j);
trans->SetIntPoint(&ip);
double weight = trans->Weight() * ip.weight;
if (fem.has_mapping()) {
weight *= fem.mapping->ComputeDetJ(*trans, ip);
}
mapping::VolumeMappingContext mapping_context;
MFEM_VERIFY(
mapping_evaluator.EvaluateVolume(*trans, ip, mapping_context) ==
mapping::MappingStatus::valid,
"Center-of-mass integration encountered an invalid mapping."
);
const double weight = mapping_context.quadrature.weight;
double rho_val = rho.GetValue(i, ip);
mfem::Vector phys_point(dim);
if (fem.has_mapping()) {
fem.mapping->GetPhysicalPoint(*trans, ip, phys_point);
} else {
trans->Transform(ip, phys_point);
}
const mfem::Vector &phys_point = mapping_context.mapping.physical_position;
const double mass_term = rho_val * weight;
local_mass += mass_term;
@@ -151,7 +182,10 @@ namespace mean_field::analysis {
std::unique_ptr<mfem::Coefficient> s2_coeff;
if (fem.has_mapping()) {
s2_coeff = std::make_unique<mapping::PhysicalPositionFunctionCoefficient>(*fem.mapping, s2_func);
s2_coeff = std::make_unique<mapping::PhysicalPositionFunctionCoefficient>(
*fem.domainMapperStateless, *fem.displacement,
*fem.compactificationCoordinate, s2_func
);
} else {
s2_coeff = std::make_unique<mfem::FunctionCoefficient>(s2_func);
}
@@ -164,12 +198,15 @@ namespace mean_field::analysis {
const mfem::IntegrationRule &integration_rule = get_density_rule<field::Density::Form::Quadrupole>(
fem, representative_transformation, std::array<int, 1>{2}, utils::DOMAINS::STELLAR
);
mfem::Array<int> stellar_markers;
populate_element_mask(fem.mesh.get(), utils::DOMAINS::STELLAR, stellar_markers);
mfem::Array<int> stellar_markers =
utils::domain::make_attribute_marker<utils::domain::Stellar, DomainSchema>(*fem.mesh);
double local_I = 0.0;
if (fem.has_mapping()) {
mapping::MappedScalarCoefficient mapped_integrand(*fem.mapping, I_integrand);
mapping::MappedScalarCoefficient mapped_integrand(
*fem.domainMapperStateless, *fem.displacement,
*fem.compactificationCoordinate, I_integrand
);
auto *integrator = new mfem::DomainLFIntegrator(mapped_integrand);
integrator->SetIntRule(&integration_rule);
I_lf.AddDomainIntegrator(integrator, stellar_markers);
@@ -201,23 +238,21 @@ namespace mean_field::analysis {
}
double local_volume = 0.0;
mapping::GridFunctionMappingEvaluator mapping_evaluator(
*fem.domainMapperStateless, *fem.displacement,
*fem.compactificationCoordinate
);
for (int e = 0; e < mesh.GetNE(); ++e) {
const int attr = mesh.GetAttribute(e);
switch (domain) {
case utils::DOMAINS::ALL:
break;
case utils::DOMAINS::STELLAR:
if (attr == 3)
continue;
break;
case utils::DOMAINS::VACUUM:
if (attr != 3)
continue;
break;
default:
MFEM_ABORT("Unsupported domain type for volume computation.");
}
const bool selected =
domain == utils::DOMAINS::ALL ||
(domain == utils::DOMAINS::STELLAR &&
DomainSchema::template attribute_belongs_to<utils::domain::Stellar>(attr)) ||
(domain == utils::DOMAINS::VACUUM &&
DomainSchema::template attribute_belongs_to<utils::domain::Vacuum>(attr));
if (!selected)
continue;
mfem::ElementTransformation *T = mesh.GetElementTransformation(e);
const mfem::IntegrationRule &ir =
get_density_rule<field::Density::Form::MassConservation>(fem, *T, {}, domain);
@@ -229,7 +264,13 @@ namespace mean_field::analysis {
double dV = ip.weight * T->Weight();
if (physical) {
dV *= std::fabs(fem.mapping->ComputeDetJ(*T, ip));
mapping::VolumeMappingContext context;
MFEM_VERIFY(
mapping_evaluator.EvaluateVolume(*T, ip, context) ==
mapping::MappingStatus::valid,
"Mesh-volume integration encountered an invalid mapping."
);
dV = context.quadrature.weight;
}
local_volume += dV;