feat(surface): surface deformation prescriptions
restricted the unknown state vector to surface deformation and implemented one prescription, NodalRadialSurface, while the full volumetric displacment field is reconstructed analytically from that. This reduced the number of degrees of freedom in the system by a factor of 80 while also removing many null vectors from the system.
This commit is contained in:
@@ -45,15 +45,33 @@ namespace mean_field::fem {
|
||||
stroid::refinement::UniformRefinement(fem.smesh, extraRefine);
|
||||
}
|
||||
|
||||
if (fem.smesh.mesh == nullptr || fem.smesh.reference_mesh == nullptr) {
|
||||
throw std::runtime_error("A STROID mesh requires paired physical and logical reference meshes.");
|
||||
}
|
||||
|
||||
int mpiSize = 1;
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
|
||||
|
||||
const std::unique_ptr<int[]> meshPartitioning(fem.smesh.mesh->GeneratePartitioning(mpiSize, 1));
|
||||
|
||||
fem.mesh = std::make_unique<mfem::ParMesh>(MPI_COMM_WORLD, *fem.smesh.mesh, meshPartitioning.get(), 1);
|
||||
fem.logicalReferenceMesh =
|
||||
std::make_unique<mfem::ParMesh>(MPI_COMM_WORLD, *fem.smesh.reference_mesh, meshPartitioning.get(), 1);
|
||||
|
||||
fem.mesh->EnsureNodes();
|
||||
|
||||
if (fem.logicalReferenceMesh->GetNE() != fem.mesh->GetNE()) {
|
||||
throw std::runtime_error("The physical and logical reference meshes have incompatible local elements.");
|
||||
}
|
||||
for (int element = 0; element < fem.mesh->GetNE(); ++element) {
|
||||
if (fem.logicalReferenceMesh->GetElementGeometry(element) != fem.mesh->GetElementGeometry(element) ||
|
||||
fem.logicalReferenceMesh->GetAttribute(element) != fem.mesh->GetAttribute(element)) {
|
||||
throw std::runtime_error(
|
||||
"The physical and logical reference meshes do not preserve element correspondence."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// Section 2: Exterior compactification coordinate
|
||||
// =====================================================================
|
||||
@@ -185,21 +203,32 @@ namespace mean_field::fem {
|
||||
|
||||
*fem.displacement = 0.0;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Surface deformation: scalar H1 coordinates on StellarSurface.
|
||||
//
|
||||
// This ambient scalar space exists only to define the surface basis
|
||||
// and owned true-DOF topology. Interior scalar DOFs are not nonlinear
|
||||
// unknowns.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
fem.surfaceDeformationFes =
|
||||
std::make_unique<mfem::ParFiniteElementSpace>(fem.mesh.get(), fem.displacementFec.get());
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Density: scalar discontinuous L2
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
fem.densityFec = DensityField::make_fec<DensityScalar>(dimension);
|
||||
fem.densityFec = DensityField::make_fec<DensityScalar>(dimension);
|
||||
|
||||
fem.densityFes = DensityField::make_fespace<DensityScalar>(*fem.mesh, *fem.densityFec);
|
||||
fem.densityFes = DensityField::make_fespace<DensityScalar>(*fem.mesh, *fem.densityFec);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Specific enthalpy: scalar continuous H1
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
fem.enthalpyFec = EnthalpyField::make_fec<EnthalpyScalar>(dimension);
|
||||
fem.enthalpyFec = EnthalpyField::make_fec<EnthalpyScalar>(dimension);
|
||||
|
||||
fem.enthalpyFes = EnthalpyField::make_fespace<EnthalpyScalar>(*fem.mesh, *fem.enthalpyFec);
|
||||
fem.enthalpyFes = EnthalpyField::make_fespace<EnthalpyScalar>(*fem.mesh, *fem.enthalpyFec);
|
||||
|
||||
// =====================================================================
|
||||
// Section 4: Multipole data
|
||||
|
||||
Reference in New Issue
Block a user