Add native spherical harmonic surface coordinates to coupled equilibrium
This commit is contained in:
@@ -17,6 +17,8 @@ module;
|
||||
|
||||
export module mean_field:preconditioning.material_surface;
|
||||
|
||||
import :deformation.surface_metric;
|
||||
|
||||
export import :operators.prepared_stellar_equilibrium;
|
||||
export import :operators.stellar_equilibrium_problem;
|
||||
export import :preconditioning.backend_implementations;
|
||||
@@ -1440,6 +1442,14 @@ export namespace mean_field::preconditioning {
|
||||
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
|
||||
const fem::FEM &finiteElements = operation.GetHydrostaticOperator().GetFEM();
|
||||
if (!operation.GetDomainDeformation().hasNodalRadialParameters()) {
|
||||
// The inverse acts on the parameter dual, not an ambient
|
||||
// nodal trace. Keep the existing diagonal approximation but
|
||||
// form it in the prescription's actual coordinate space.
|
||||
return deformation::assembleSurfaceParameterMassDiagonal(
|
||||
finiteElements, operation.GetDomainDeformation()
|
||||
);
|
||||
}
|
||||
MFEM_VERIFY(
|
||||
finiteElements.mesh != nullptr && finiteElements.surfaceDeformationFes != nullptr,
|
||||
"The material/free-surface Riesz surrogate requires the surface finite-element space."
|
||||
@@ -1492,10 +1502,26 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
const fem::FEM &finiteElements = m_operation->GetHydrostaticOperator().GetFEM();
|
||||
const field::ScalarBoundaryDofMap surfaceMap =
|
||||
field::make_stellar_surface_scalar_dof_map<DomainSchema>(*finiteElements.surfaceDeformationFes);
|
||||
if (surfaceMap.local_size() != m_surfaceDiagonal.Size()) {
|
||||
throw std::logic_error("Surface Riesz calibration received an incompatible boundary coordinate map.");
|
||||
const bool nodal = m_operation->GetDomainDeformation().hasNodalRadialParameters();
|
||||
field::ScalarBoundaryDofMap surfaceMap;
|
||||
if (nodal) {
|
||||
surfaceMap =
|
||||
field::make_stellar_surface_scalar_dof_map<DomainSchema>(*finiteElements.surfaceDeformationFes);
|
||||
if (surfaceMap.local_size() != m_surfaceDiagonal.Size()) {
|
||||
throw std::logic_error(
|
||||
"Surface Riesz calibration received an incompatible boundary coordinate map."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
int ranks = 0;
|
||||
if (MPI_Comm_size(Communicator(*m_operation), &ranks) != MPI_SUCCESS || ranks != 1) {
|
||||
throw std::invalid_argument(
|
||||
"Surface parameter calibration currently requires one MPI rank for nonnodal coordinates."
|
||||
);
|
||||
}
|
||||
if (m_surfaceDiagonal.Size() != m_operation->GetDomainDeformation().parameterCount()) {
|
||||
throw std::logic_error("Surface Riesz calibration received an incompatible parameter metric.");
|
||||
}
|
||||
}
|
||||
|
||||
mfem::Vector probe(m_surfaceDiagonal.Size());
|
||||
@@ -1513,7 +1539,11 @@ export namespace mean_field::preconditioning {
|
||||
double localDenominator = 0.0;
|
||||
for (int sample = 0; sample < calibration.probeCount; ++sample) {
|
||||
for (int index = 0; index < probe.Size(); ++index) {
|
||||
std::uint64_t value = static_cast<std::uint64_t>(surfaceMap.global_boundary_dof(index));
|
||||
// Preserve nodal probes exactly. Nonnodal serial probes
|
||||
// use the immutable ordered parameter index instead of
|
||||
// pretending that each coefficient owns a boundary node.
|
||||
std::uint64_t value =
|
||||
static_cast<std::uint64_t>(nodal ? surfaceMap.global_boundary_dof(index) : index);
|
||||
value += 0x9e3779b97f4a7c15ULL * static_cast<std::uint64_t>(sample + 1);
|
||||
value = (value ^ (value >> 30U)) * 0xbf58476d1ce4e5b9ULL;
|
||||
value = (value ^ (value >> 27U)) * 0x94d049bb133111ebULL;
|
||||
@@ -1871,6 +1901,12 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
[[nodiscard]] static field::ScalarBoundaryDofMap
|
||||
SurfaceMap(const operators::PreparedStellarEquilibriumOperator &operation) {
|
||||
if (!operation.GetDomainDeformation().hasNodalRadialParameters()) {
|
||||
throw std::invalid_argument(
|
||||
"SurfaceH1MassStiffness requires nodal radial parameters; a parameter-space H1 surrogate "
|
||||
"has not been implemented for this surface prescription."
|
||||
);
|
||||
}
|
||||
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
const fem::FEM &finiteElements = operation.GetHydrostaticOperator().GetFEM();
|
||||
return field::make_stellar_surface_scalar_dof_map<DomainSchema>(*finiteElements.surfaceDeformationFes);
|
||||
|
||||
Reference in New Issue
Block a user