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:
345
libmeanfield/impl/deformation/nodal_radial_surface.cpp
Normal file
345
libmeanfield/impl/deformation/nodal_radial_surface.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
module;
|
||||
|
||||
#include <cmath>
|
||||
#include <format>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
module mean_field;
|
||||
|
||||
import :deformation.nodal_radial_surface;
|
||||
|
||||
namespace mean_field::deformation {
|
||||
namespace {
|
||||
[[nodiscard]] SurfaceDeformationDescriptor nodalRadialDescriptor(const int spatialDimension) noexcept {
|
||||
return {
|
||||
.name = "NodalRadialSurface",
|
||||
.spatialDimension = spatialDimension,
|
||||
.motionKind = SurfaceMotionKind::Radial,
|
||||
.linearOnReferenceGeometry = true,
|
||||
.requiresStarShapedReferenceSurface = true,
|
||||
.hasExactDerivativeTranspose = true,
|
||||
.hasExactPullbackDerivative = true,
|
||||
.translationTreatment = GeometricGaugeTreatment::Retained,
|
||||
.orientationTreatment = GeometricGaugeTreatment::Retained
|
||||
};
|
||||
}
|
||||
|
||||
void requireFiniteVector(
|
||||
const mfem::Vector &vector,
|
||||
const char *message
|
||||
) {
|
||||
for (int index = 0; index < vector.Size(); ++index) {
|
||||
if (!std::isfinite(vector(index))) {
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SurfaceDeformationCompilationContext::SurfaceDeformationCompilationContext(
|
||||
mfem::ParFiniteElementSpace &scalarFiniteElementSpace,
|
||||
field::ScalarBoundaryDofMap surfaceDofMap
|
||||
)
|
||||
: m_scalarFiniteElementSpace(&scalarFiniteElementSpace),
|
||||
m_surfaceDofMap(std::move(surfaceDofMap)) {
|
||||
if (scalarFiniteElementSpace.Nonconforming()) {
|
||||
throw std::invalid_argument(
|
||||
"Surface deformation compilation currently requires a conforming scalar finite-element space."
|
||||
);
|
||||
}
|
||||
if (scalarFiniteElementSpace.GetVDim() != 1) {
|
||||
throw std::invalid_argument("Surface deformation compilation requires a scalar finite-element space.");
|
||||
}
|
||||
if (scalarFiniteElementSpace.GetMesh() == nullptr) {
|
||||
throw std::invalid_argument("Surface deformation compilation requires a finite-element mesh.");
|
||||
}
|
||||
if (m_surfaceDofMap.volume_true_dof_size() != scalarFiniteElementSpace.GetTrueVSize()) {
|
||||
throw std::invalid_argument(
|
||||
"The surface DOF map and scalar finite-element space have incompatible true-DOF sizes."
|
||||
);
|
||||
}
|
||||
if (m_surfaceDofMap.global_size() <= 0) {
|
||||
throw std::invalid_argument("Surface deformation compilation requires at least one surface coordinate.");
|
||||
}
|
||||
}
|
||||
|
||||
mfem::ParFiniteElementSpace &SurfaceDeformationCompilationContext::scalarFiniteElementSpace() const noexcept {
|
||||
return *m_scalarFiniteElementSpace;
|
||||
}
|
||||
|
||||
const field::ScalarBoundaryDofMap &SurfaceDeformationCompilationContext::surfaceDofMap() const noexcept {
|
||||
return m_surfaceDofMap;
|
||||
}
|
||||
|
||||
NodalRadialSurface::NodalRadialSurface(mfem::Vector referenceCenter)
|
||||
: m_referenceCenter(std::move(referenceCenter)) {
|
||||
validate();
|
||||
}
|
||||
|
||||
const mfem::Vector &NodalRadialSurface::referenceCenter() const noexcept {
|
||||
return m_referenceCenter;
|
||||
}
|
||||
|
||||
SurfaceDeformationDescriptor NodalRadialSurface::descriptor() const noexcept {
|
||||
return nodalRadialDescriptor(m_referenceCenter.Size());
|
||||
}
|
||||
|
||||
void NodalRadialSurface::validate() const {
|
||||
if (m_referenceCenter.Size() <= 0) {
|
||||
throw std::invalid_argument("NodalRadialSurface requires a non-empty reference center.");
|
||||
}
|
||||
requireFiniteVector(m_referenceCenter, "NodalRadialSurface reference-center coordinates must be finite.");
|
||||
}
|
||||
|
||||
PreparedNodalRadialSurface::PreparedNodalRadialSurface(
|
||||
const SurfaceDeformationDescriptor descriptor,
|
||||
mfem::Vector referenceCenter,
|
||||
field::ScalarBoundaryDofMap surfaceDofMap,
|
||||
mfem::Vector radialDirections,
|
||||
mfem::Vector referenceRadii
|
||||
)
|
||||
: m_descriptor(descriptor),
|
||||
m_referenceCenter(std::move(referenceCenter)),
|
||||
m_surfaceDofMap(std::move(surfaceDofMap)),
|
||||
m_radialDirections(std::move(radialDirections)),
|
||||
m_referenceRadii(std::move(referenceRadii)) {
|
||||
}
|
||||
|
||||
SurfaceDeformationDescriptor PreparedNodalRadialSurface::descriptor() const noexcept {
|
||||
return m_descriptor;
|
||||
}
|
||||
|
||||
int PreparedNodalRadialSurface::parameterCount() const noexcept {
|
||||
return m_surfaceDofMap.local_size();
|
||||
}
|
||||
|
||||
long long PreparedNodalRadialSurface::globalParameterCount() const noexcept {
|
||||
return m_surfaceDofMap.global_size();
|
||||
}
|
||||
|
||||
long long PreparedNodalRadialSurface::globalParameterOffset() const noexcept {
|
||||
return m_surfaceDofMap.global_offset();
|
||||
}
|
||||
|
||||
int PreparedNodalRadialSurface::spatialDimension() const noexcept {
|
||||
return m_descriptor.spatialDimension;
|
||||
}
|
||||
|
||||
int PreparedNodalRadialSurface::surfaceDisplacementSize() const noexcept {
|
||||
return spatialDimension() * parameterCount();
|
||||
}
|
||||
|
||||
long long PreparedNodalRadialSurface::globalSurfaceDisplacementSize() const noexcept {
|
||||
return static_cast<long long>(spatialDimension()) * globalParameterCount();
|
||||
}
|
||||
|
||||
long long PreparedNodalRadialSurface::globalSurfaceDisplacementOffset() const noexcept {
|
||||
return static_cast<long long>(spatialDimension()) * globalParameterOffset();
|
||||
}
|
||||
|
||||
int PreparedNodalRadialSurface::surfaceDisplacementDof(
|
||||
const int parameterDof,
|
||||
const int component
|
||||
) const {
|
||||
if (parameterDof < 0 || parameterDof >= parameterCount()) {
|
||||
throw std::out_of_range("Parameter DOF is outside PreparedNodalRadialSurface.");
|
||||
}
|
||||
if (component < 0 || component >= spatialDimension()) {
|
||||
throw std::out_of_range("Surface-displacement component is outside PreparedNodalRadialSurface.");
|
||||
}
|
||||
return spatialDimension() * parameterDof + component;
|
||||
}
|
||||
|
||||
double PreparedNodalRadialSurface::radialDirection(
|
||||
const int parameterDof,
|
||||
const int component
|
||||
) const {
|
||||
return m_radialDirections(surfaceDisplacementDof(parameterDof, component));
|
||||
}
|
||||
|
||||
double PreparedNodalRadialSurface::referenceRadius(const int parameterDof) const {
|
||||
if (parameterDof < 0 || parameterDof >= parameterCount()) {
|
||||
throw std::out_of_range("Parameter DOF is outside PreparedNodalRadialSurface.");
|
||||
}
|
||||
return m_referenceRadii(parameterDof);
|
||||
}
|
||||
|
||||
const mfem::Vector &PreparedNodalRadialSurface::referenceCenter() const noexcept {
|
||||
return m_referenceCenter;
|
||||
}
|
||||
|
||||
const field::ScalarBoundaryDofMap &PreparedNodalRadialSurface::surfaceDofMap() const noexcept {
|
||||
return m_surfaceDofMap;
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::buildSurfaceDisplacement(
|
||||
const mfem::Vector ¶meters,
|
||||
mfem::Vector &surfaceDisplacement
|
||||
) const {
|
||||
requireParameterSize(parameters);
|
||||
requireSurfaceDisplacementSize(surfaceDisplacement);
|
||||
|
||||
for (int parameterDof = 0; parameterDof < parameterCount(); ++parameterDof) {
|
||||
for (int component = 0; component < spatialDimension(); ++component) {
|
||||
const int surfaceDof = spatialDimension() * parameterDof + component;
|
||||
surfaceDisplacement(surfaceDof) = parameters(parameterDof) * m_radialDirections(surfaceDof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::applyJacobian(
|
||||
const mfem::Vector ¶meters,
|
||||
const mfem::Vector ¶meterDirection,
|
||||
mfem::Vector &surfaceDisplacementDirection
|
||||
) const {
|
||||
requireParameterSize(parameters);
|
||||
requireParameterSize(parameterDirection);
|
||||
requireSurfaceDisplacementSize(surfaceDisplacementDirection);
|
||||
|
||||
for (int parameterDof = 0; parameterDof < parameterCount(); ++parameterDof) {
|
||||
for (int component = 0; component < spatialDimension(); ++component) {
|
||||
const int surfaceDof = spatialDimension() * parameterDof + component;
|
||||
surfaceDisplacementDirection(surfaceDof) =
|
||||
parameterDirection(parameterDof) * m_radialDirections(surfaceDof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::applyJacobianTranspose(
|
||||
const mfem::Vector ¶meters,
|
||||
const mfem::Vector &surfaceDisplacementDual,
|
||||
mfem::Vector ¶meterDual
|
||||
) const {
|
||||
requireParameterSize(parameters);
|
||||
requireSurfaceDisplacementSize(surfaceDisplacementDual);
|
||||
requireParameterSize(parameterDual);
|
||||
|
||||
for (int parameterDof = 0; parameterDof < parameterCount(); ++parameterDof) {
|
||||
double radialWork = 0.0;
|
||||
for (int component = 0; component < spatialDimension(); ++component) {
|
||||
const int surfaceDof = spatialDimension() * parameterDof + component;
|
||||
radialWork += m_radialDirections(surfaceDof) * surfaceDisplacementDual(surfaceDof);
|
||||
}
|
||||
parameterDual(parameterDof) = radialWork;
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::applyPullbackDerivative(
|
||||
const mfem::Vector ¶meters,
|
||||
const mfem::Vector ¶meterDirection,
|
||||
const mfem::Vector &surfaceDisplacementDual,
|
||||
mfem::Vector ¶meterDualAction
|
||||
) const {
|
||||
requireParameterSize(parameters);
|
||||
requireParameterSize(parameterDirection);
|
||||
requireSurfaceDisplacementSize(surfaceDisplacementDual);
|
||||
requireParameterSize(parameterDualAction);
|
||||
|
||||
parameterDualAction = 0.0;
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::requireParameterSize(const mfem::Vector ¶meters) const {
|
||||
if (parameters.Size() != parameterCount()) {
|
||||
throw std::invalid_argument(
|
||||
std::format(
|
||||
"Nodal radial parameter vector has size {}, but the prepared surface requires {}.",
|
||||
parameters.Size(), parameterCount()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedNodalRadialSurface::requireSurfaceDisplacementSize(const mfem::Vector &surfaceDisplacement) const {
|
||||
if (surfaceDisplacement.Size() != surfaceDisplacementSize()) {
|
||||
throw std::invalid_argument(
|
||||
std::format(
|
||||
"Surface displacement vector has size {}, but the prepared nodal radial surface requires {}.",
|
||||
surfaceDisplacement.Size(), surfaceDisplacementSize()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PreparedNodalRadialSurface compileSurfaceDeformationPrescription(
|
||||
const NodalRadialSurface &prescription,
|
||||
const SurfaceDeformationCompilationContext &context
|
||||
) {
|
||||
prescription.validate();
|
||||
|
||||
mfem::ParFiniteElementSpace &scalarSpace = context.scalarFiniteElementSpace();
|
||||
const mfem::Mesh *mesh = scalarSpace.GetMesh();
|
||||
|
||||
if (mesh == nullptr) {
|
||||
throw std::invalid_argument("Nodal radial surface compilation requires a reference mesh.");
|
||||
}
|
||||
if (prescription.referenceCenter().Size() != mesh->SpaceDimension()) {
|
||||
throw std::invalid_argument(
|
||||
std::format(
|
||||
"NodalRadialSurface reference center has dimension {}, but the reference mesh has spatial "
|
||||
"dimension {}.",
|
||||
prescription.referenceCenter().Size(), mesh->SpaceDimension()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const field::ScalarBoundaryDofMap &surfaceDofMap = context.surfaceDofMap();
|
||||
const int parameterCount = surfaceDofMap.local_size();
|
||||
const int spatialDimension = mesh->SpaceDimension();
|
||||
|
||||
mfem::Vector referencePositions(spatialDimension * parameterCount);
|
||||
mfem::ParGridFunction coordinateField(&scalarSpace);
|
||||
|
||||
for (int component = 0; component < spatialDimension; ++component) {
|
||||
mfem::FunctionCoefficient coordinateCoefficient([component](const mfem::Vector &position) {
|
||||
return position(component);
|
||||
});
|
||||
|
||||
coordinateField.ProjectCoefficient(coordinateCoefficient);
|
||||
|
||||
mfem::Vector coordinateTrueDofs;
|
||||
coordinateField.GetTrueDofs(coordinateTrueDofs);
|
||||
const mfem::Vector surfaceCoordinates = surfaceDofMap.gather(coordinateTrueDofs);
|
||||
|
||||
for (int parameterDof = 0; parameterDof < parameterCount; ++parameterDof) {
|
||||
referencePositions(spatialDimension * parameterDof + component) = surfaceCoordinates(parameterDof);
|
||||
}
|
||||
}
|
||||
|
||||
mfem::Vector radialDirections(referencePositions.Size());
|
||||
mfem::Vector referenceRadii(parameterCount);
|
||||
|
||||
for (int parameterDof = 0; parameterDof < parameterCount; ++parameterDof) {
|
||||
double radiusSquared = 0.0;
|
||||
|
||||
for (int component = 0; component < spatialDimension; ++component) {
|
||||
const int surfaceDof = spatialDimension * parameterDof + component;
|
||||
const double radialCoordinate =
|
||||
referencePositions(surfaceDof) - prescription.referenceCenter()(component);
|
||||
|
||||
radialDirections(surfaceDof) = radialCoordinate;
|
||||
radiusSquared += radialCoordinate * radialCoordinate;
|
||||
}
|
||||
|
||||
const double radius = std::sqrt(radiusSquared);
|
||||
if (!std::isfinite(radius) || radius <= 0.0) {
|
||||
throw std::invalid_argument(
|
||||
"Every nodal radial surface coordinate must have a finite positive distance from the reference "
|
||||
"center."
|
||||
);
|
||||
}
|
||||
|
||||
referenceRadii(parameterDof) = radius;
|
||||
for (int component = 0; component < spatialDimension; ++component) {
|
||||
radialDirections(spatialDimension * parameterDof + component) /= radius;
|
||||
}
|
||||
}
|
||||
|
||||
return PreparedNodalRadialSurface(
|
||||
nodalRadialDescriptor(spatialDimension), prescription.referenceCenter(), surfaceDofMap,
|
||||
std::move(radialDirections), std::move(referenceRadii)
|
||||
);
|
||||
}
|
||||
} // namespace mean_field::deformation
|
||||
1061
libmeanfield/impl/deformation/radial_extensions.cpp
Normal file
1061
libmeanfield/impl/deformation/radial_extensions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -2,6 +2,7 @@ module;
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -21,29 +22,23 @@ namespace {
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] mfem::Vector make_computational_origin(const mfem::ParMesh &mesh) {
|
||||
mfem::Vector origin(mesh.SpaceDimension());
|
||||
origin = 0.0;
|
||||
return origin;
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::StellarEquilibriumLayout make_layout(
|
||||
const mean_field::field::FieldDofMap &densityMap,
|
||||
const mean_field::field::FieldDofMap &displacementMap,
|
||||
const int surfaceDeformationParameterCount,
|
||||
const mean_field::field::FieldDofMap &gravityFluxMap,
|
||||
const mean_field::field::FieldDofMap &gravityPotentialMap,
|
||||
const mean_field::field::FieldDofMap &enthalpyMap
|
||||
) {
|
||||
using Form = mean_field::utils::blocks::barotropic_equilibrium_form;
|
||||
using Form = mean_field::utils::blocks::surface_deformed_stellar_equilibrium_form;
|
||||
|
||||
const std::array<int, Form::value_block_count> valueSizes{
|
||||
densityMap.reduced_size(), displacementMap.reduced_size(), gravityFluxMap.reduced_size(),
|
||||
gravityPotentialMap.reduced_size(), enthalpyMap.reduced_size(), 1
|
||||
densityMap.reduced_size(), surfaceDeformationParameterCount, gravityFluxMap.reduced_size(),
|
||||
gravityPotentialMap.reduced_size(), enthalpyMap.reduced_size(), 1
|
||||
};
|
||||
|
||||
const std::array<int, Form::residual_block_count> residualSizes{
|
||||
gravityFluxMap.reduced_size(), gravityPotentialMap.reduced_size(), densityMap.reduced_size(),
|
||||
displacementMap.reduced_size(), enthalpyMap.reduced_size(), 1
|
||||
gravityFluxMap.reduced_size(), gravityPotentialMap.reduced_size(), densityMap.reduced_size(),
|
||||
surfaceDeformationParameterCount, enthalpyMap.reduced_size(), 1
|
||||
};
|
||||
|
||||
return {valueSizes, residualSizes};
|
||||
@@ -182,11 +177,13 @@ namespace {
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::context::gravity_field::GravityFieldRevisions
|
||||
make_gravity_revisions(const mean_field::operators::StellarEquilibriumDependencies &dependencies) {
|
||||
[[nodiscard]] mean_field::operators::context::gravity_field::GravityFieldRevisions make_gravity_revisions(
|
||||
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
|
||||
const mean_field::operators::StellarEquilibriumDependencyStamp &generatedDisplacement
|
||||
) {
|
||||
return {
|
||||
.discretization = {.value = dependencies.discretization.revision},
|
||||
.displacement = {.value = dependencies.displacement.revision},
|
||||
.displacement = {.value = generatedDisplacement.revision},
|
||||
.density = {.value = dependencies.density.revision},
|
||||
.gravity_gradient = {.value = dependencies.gravityGradient.revision},
|
||||
.gravity_potential = {.value = dependencies.gravityPotential.revision}
|
||||
@@ -194,26 +191,28 @@ namespace {
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::context::barotropic::BarotropicClosureDependencies
|
||||
make_barotropic_closure_dependencies(const mean_field::operators::StellarEquilibriumDependencies &dependencies) {
|
||||
make_barotropic_closure_dependencies(
|
||||
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
|
||||
const mean_field::operators::StellarEquilibriumDependencyStamp &generatedDisplacement
|
||||
) {
|
||||
return {
|
||||
.discretization =
|
||||
{.identity = dependencies.discretization.identity, .revision = dependencies.discretization.revision},
|
||||
.density = {.identity = dependencies.density.identity, .revision = dependencies.density.revision},
|
||||
.enthalpy = {.identity = dependencies.enthalpy.identity, .revision = dependencies.enthalpy.revision},
|
||||
.displacement = {
|
||||
.identity = dependencies.displacement.identity, .revision = dependencies.displacement.revision
|
||||
}
|
||||
.displacement = {.identity = generatedDisplacement.identity, .revision = generatedDisplacement.revision}
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::DisplacementResidualDependencies
|
||||
make_displacement_dependencies(const mean_field::operators::StellarEquilibriumDependencies &dependencies) {
|
||||
[[nodiscard]] mean_field::operators::DisplacementResidualDependencies make_displacement_dependencies(
|
||||
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
|
||||
const mean_field::operators::StellarEquilibriumDependencyStamp &generatedDisplacement
|
||||
) {
|
||||
return {
|
||||
.discretization =
|
||||
{.identity = dependencies.discretization.identity, .revision = dependencies.discretization.revision},
|
||||
.density = {.identity = dependencies.density.identity, .revision = dependencies.density.revision},
|
||||
.displacement =
|
||||
{.identity = dependencies.displacement.identity, .revision = dependencies.displacement.revision},
|
||||
.density = {.identity = dependencies.density.identity, .revision = dependencies.density.revision},
|
||||
.displacement = {.identity = generatedDisplacement.identity, .revision = generatedDisplacement.revision},
|
||||
.gravityGradient =
|
||||
{.identity = dependencies.gravityGradient.identity, .revision = dependencies.gravityGradient.revision},
|
||||
.enthalpy = {.identity = dependencies.enthalpy.identity, .revision = dependencies.enthalpy.revision},
|
||||
@@ -222,7 +221,10 @@ namespace {
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::context::hydrostatic::HydrostaticEquilibriumDependencies
|
||||
make_hydrostatic_dependencies(const mean_field::operators::StellarEquilibriumDependencies &dependencies) {
|
||||
make_hydrostatic_dependencies(
|
||||
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
|
||||
const mean_field::operators::StellarEquilibriumDependencyStamp &generatedDisplacement
|
||||
) {
|
||||
return {
|
||||
.discretization =
|
||||
{.identity = dependencies.discretization.identity, .revision = dependencies.discretization.revision},
|
||||
@@ -230,44 +232,48 @@ namespace {
|
||||
.gravityPotential =
|
||||
{.identity = dependencies.gravityPotential.identity,
|
||||
.revision = dependencies.gravityPotential.revision},
|
||||
.displacement =
|
||||
{.identity = dependencies.displacement.identity, .revision = dependencies.displacement.revision},
|
||||
.rotation = {.identity = dependencies.rotation.identity, .revision = dependencies.rotation.revision},
|
||||
.displacement = {.identity = generatedDisplacement.identity, .revision = generatedDisplacement.revision},
|
||||
.rotation = {.identity = dependencies.rotation.identity, .revision = dependencies.rotation.revision},
|
||||
.bernoulliConstant = {
|
||||
.identity = dependencies.bernoulliConstant.identity, .revision = dependencies.bernoulliConstant.revision
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::MassNormalizationDependencies
|
||||
make_mass_dependencies(const mean_field::operators::StellarEquilibriumDependencies &dependencies) {
|
||||
[[nodiscard]] mean_field::operators::MassNormalizationDependencies make_mass_dependencies(
|
||||
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
|
||||
const mean_field::operators::StellarEquilibriumDependencyStamp &generatedDisplacement
|
||||
) {
|
||||
return {
|
||||
.discretization =
|
||||
{.identity = dependencies.discretization.identity, .revision = dependencies.discretization.revision},
|
||||
.density = {.identity = dependencies.density.identity, .revision = dependencies.density.revision},
|
||||
.displacement =
|
||||
{.identity = dependencies.displacement.identity, .revision = dependencies.displacement.revision},
|
||||
.targetMass = {.identity = dependencies.targetMass.identity, .revision = dependencies.targetMass.revision}
|
||||
.density = {.identity = dependencies.density.identity, .revision = dependencies.density.revision},
|
||||
.displacement = {.identity = generatedDisplacement.identity, .revision = generatedDisplacement.revision},
|
||||
.targetMass = {.identity = dependencies.targetMass.identity, .revision = dependencies.targetMass.revision}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace mean_field::operators {
|
||||
struct PreparedStellarEquilibriumOperator::ConstructionData {
|
||||
deformation::PreparedDomainDeformationRuntime domainDeformation;
|
||||
field::FieldDofMap densityMap;
|
||||
field::FieldDofMap displacementMap;
|
||||
field::FieldDofMap gravityFluxMap;
|
||||
field::FieldDofMap gravityPotentialMap;
|
||||
field::FieldDofMap enthalpyMap;
|
||||
field::FieldBoundaryDofMap pressureSurfaceRows;
|
||||
field::FieldPointDofMap centerDisplacementRows;
|
||||
|
||||
StellarEquilibriumLayout layout;
|
||||
mfem::Array<int> gravityStateOffsets;
|
||||
mfem::Array<int> gravityResidualOffsets;
|
||||
|
||||
explicit ConstructionData(fem::FEM &f)
|
||||
: densityMap(
|
||||
ConstructionData(
|
||||
fem::FEM &f,
|
||||
deformation::PreparedDomainDeformationRuntime preparedDomainDeformation
|
||||
)
|
||||
: domainDeformation(std::move(preparedDomainDeformation)),
|
||||
densityMap(
|
||||
field::make_field_dof_map<
|
||||
field::Density,
|
||||
DomainSchema>(*f.densityFes)
|
||||
@@ -301,17 +307,9 @@ namespace mean_field::operators {
|
||||
enthalpyMap
|
||||
)
|
||||
),
|
||||
centerDisplacementRows(
|
||||
field::make_field_point_dof_map<field::Displacement>(
|
||||
*f.displacementFes,
|
||||
displacementMap,
|
||||
make_computational_origin(*f.mesh),
|
||||
1.0e-12
|
||||
)
|
||||
),
|
||||
layout(make_layout(
|
||||
densityMap,
|
||||
displacementMap,
|
||||
domainDeformation.parameterCount(),
|
||||
gravityFluxMap,
|
||||
gravityPotentialMap,
|
||||
enthalpyMap
|
||||
@@ -329,10 +327,12 @@ namespace mean_field::operators {
|
||||
}
|
||||
};
|
||||
|
||||
PreparedStellarEquilibriumOperator::ConstructionData
|
||||
PreparedStellarEquilibriumOperator::MakeConstructionData(fem::FEM &f) {
|
||||
PreparedStellarEquilibriumOperator::ConstructionData PreparedStellarEquilibriumOperator::MakeConstructionData(
|
||||
fem::FEM &f,
|
||||
deformation::PreparedDomainDeformationRuntime domainDeformation
|
||||
) {
|
||||
verify_coupled_discretization(f);
|
||||
return ConstructionData(f);
|
||||
return ConstructionData(f, std::move(domainDeformation));
|
||||
}
|
||||
|
||||
PreparedStellarEquilibriumOperator::PreparedStellarEquilibriumOperator(
|
||||
@@ -340,7 +340,8 @@ namespace mean_field::operators {
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
const double targetMass,
|
||||
const PressureSurfaceConstraintView surfaceConstraint
|
||||
const PressureSurfaceConstraintView surfaceConstraint,
|
||||
deformation::PreparedDomainDeformationRuntime domainDeformation
|
||||
)
|
||||
: PreparedStellarEquilibriumOperator(
|
||||
f,
|
||||
@@ -348,7 +349,10 @@ namespace mean_field::operators {
|
||||
equationOfState,
|
||||
targetMass,
|
||||
surfaceConstraint,
|
||||
MakeConstructionData(f)
|
||||
MakeConstructionData(
|
||||
f,
|
||||
std::move(domainDeformation)
|
||||
)
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -408,7 +412,7 @@ namespace mean_field::operators {
|
||||
constructionData.pressureSurfaceRows,
|
||||
surfaceConstraint
|
||||
),
|
||||
m_centeringConstraintOperator(constructionData.centerDisplacementRows),
|
||||
m_domainDeformation(std::move(constructionData.domainDeformation)),
|
||||
m_targetMass(targetMass) {
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(m_targetMass) && m_targetMass > 0.0,
|
||||
@@ -420,12 +424,35 @@ namespace mean_field::operators {
|
||||
"PreparedStellarEquilibriumOperator has inconsistent block dimensions."
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
m_domainDeformation.volumeDisplacementSize() == constructionData.displacementMap.reduced_size(),
|
||||
"The domain-deformation output does not match the coupled displacement discretization."
|
||||
);
|
||||
|
||||
m_generatedDisplacementDependency.identity =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&m_domainDeformation));
|
||||
|
||||
m_gravityState.SetSize(m_gravityStateOffsets.Last());
|
||||
|
||||
m_gravityDirection.SetSize(m_gravityStateOffsets.Last());
|
||||
|
||||
m_gravityState = 0.0;
|
||||
m_gravityDirection = 0.0;
|
||||
m_surfaceDeformationParameters.SetSize(m_domainDeformation.parameterCount());
|
||||
m_generatedVolumeDisplacement.SetSize(m_domainDeformation.volumeDisplacementSize());
|
||||
m_fullMechanicalResidual.SetSize(m_domainDeformation.volumeDisplacementSize());
|
||||
m_volumeDisplacementDirection.SetSize(m_domainDeformation.volumeDisplacementSize());
|
||||
m_fullMechanicalAction.SetSize(m_domainDeformation.volumeDisplacementSize());
|
||||
m_surfaceShapeAction.SetSize(m_domainDeformation.parameterCount());
|
||||
m_pullbackDerivativeAction.SetSize(m_domainDeformation.parameterCount());
|
||||
|
||||
m_gravityState = 0.0;
|
||||
m_gravityDirection = 0.0;
|
||||
m_surfaceDeformationParameters = 0.0;
|
||||
m_generatedVolumeDisplacement = 0.0;
|
||||
m_fullMechanicalResidual = 0.0;
|
||||
m_volumeDisplacementDirection = 0.0;
|
||||
m_fullMechanicalAction = 0.0;
|
||||
m_surfaceShapeAction = 0.0;
|
||||
m_pullbackDerivativeAction = 0.0;
|
||||
}
|
||||
|
||||
PreparedStellarEquilibriumReport PreparedStellarEquilibriumOperator::Prepare(
|
||||
@@ -448,8 +475,8 @@ namespace mean_field::operators {
|
||||
m_preparedDependencies.density, dependencies.density, "The density revision cannot move backwards."
|
||||
);
|
||||
validate_dependency_transition(
|
||||
m_preparedDependencies.displacement, dependencies.displacement,
|
||||
"The displacement revision cannot move backwards."
|
||||
m_preparedDependencies.surfaceDeformation, dependencies.surfaceDeformation,
|
||||
"The surface-deformation revision cannot move backwards."
|
||||
);
|
||||
validate_dependency_transition(
|
||||
m_preparedDependencies.gravityGradient, dependencies.gravityGradient,
|
||||
@@ -477,10 +504,10 @@ namespace mean_field::operators {
|
||||
|
||||
m_isPrepared = false;
|
||||
|
||||
using Form = utils::blocks::barotropic_equilibrium_form;
|
||||
using Form = utils::blocks::surface_deformed_stellar_equilibrium_form;
|
||||
constexpr auto densityValue = utils::blocks::get_value_block<Form>(utils::blocks::density_field.mass_term);
|
||||
constexpr auto displacementValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::displacement_field.geometry_term);
|
||||
constexpr auto surfaceDeformationValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::surface_deformation_field.parameters_term);
|
||||
constexpr auto gravityGradientValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::gravity_field.gradient_term);
|
||||
constexpr auto gravityPotentialValue =
|
||||
@@ -490,49 +517,65 @@ namespace mean_field::operators {
|
||||
constexpr auto bernoulliValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::barotropic_constant_field.mass_normalization_term);
|
||||
|
||||
const mfem::Vector reducedDensity = make_value_view(state, m_layout, densityValue);
|
||||
const mfem::Vector displacement = make_value_view(state, m_layout, displacementValue);
|
||||
const mfem::Vector gravityGradient = make_value_view(state, m_layout, gravityGradientValue);
|
||||
const mfem::Vector gravityPotential = make_value_view(state, m_layout, gravityPotentialValue);
|
||||
const mfem::Vector reducedEnthalpy = make_value_view(state, m_layout, enthalpyValue);
|
||||
const mfem::Vector bernoulli = make_value_view(state, m_layout, bernoulliValue);
|
||||
const mfem::Vector reducedDensity = make_value_view(state, m_layout, densityValue);
|
||||
const mfem::Vector surfaceDeformationParameters = make_value_view(state, m_layout, surfaceDeformationValue);
|
||||
const mfem::Vector gravityGradient = make_value_view(state, m_layout, gravityGradientValue);
|
||||
const mfem::Vector gravityPotential = make_value_view(state, m_layout, gravityPotentialValue);
|
||||
const mfem::Vector reducedEnthalpy = make_value_view(state, m_layout, enthalpyValue);
|
||||
const mfem::Vector bernoulli = make_value_view(state, m_layout, bernoulliValue);
|
||||
|
||||
pack_gravity_vector(
|
||||
m_gravityState, m_gravityStateOffsets, reducedDensity, displacement, gravityGradient, gravityPotential
|
||||
);
|
||||
const bool generatedGeometryChanged =
|
||||
!wasPrepared || dependencies.discretization != m_preparedDependencies.discretization ||
|
||||
dependencies.surfaceDeformation != m_preparedDependencies.surfaceDeformation;
|
||||
|
||||
PreparedStellarEquilibriumReport report;
|
||||
if (generatedGeometryChanged) {
|
||||
m_surfaceDeformationParameters = surfaceDeformationParameters;
|
||||
m_generatedGeometryReport = m_domainDeformation.buildValidatedVolumeDisplacement(
|
||||
m_surfaceDeformationParameters, m_generatedVolumeDisplacement
|
||||
);
|
||||
++m_generatedDisplacementDependency.revision;
|
||||
++m_statistics.generatedGeometryBuilds;
|
||||
report.generatedVolumeDisplacement = true;
|
||||
}
|
||||
report.generatedGeometry = m_generatedGeometryReport;
|
||||
report.generatedDisplacement = m_generatedDisplacementDependency;
|
||||
|
||||
report.gravity = m_gravityOperator.Prepare(m_gravityState, make_gravity_revisions(dependencies));
|
||||
pack_gravity_vector(
|
||||
m_gravityState, m_gravityStateOffsets, reducedDensity, m_generatedVolumeDisplacement, gravityGradient,
|
||||
gravityPotential
|
||||
);
|
||||
|
||||
report.gravity = m_gravityOperator.Prepare(
|
||||
m_gravityState, make_gravity_revisions(dependencies, m_generatedDisplacementDependency)
|
||||
);
|
||||
|
||||
report.barotropicClosure = m_barotropicClosureOperator.Prepare(
|
||||
{.density = reducedDensity, .enthalpy = reducedEnthalpy, .displacement = displacement},
|
||||
make_barotropic_closure_dependencies(dependencies)
|
||||
{.density = reducedDensity, .enthalpy = reducedEnthalpy, .displacement = m_generatedVolumeDisplacement},
|
||||
make_barotropic_closure_dependencies(dependencies, m_generatedDisplacementDependency)
|
||||
);
|
||||
|
||||
report.hydrostatic = m_hydrostaticOperator.Prepare(
|
||||
{.enthalpy = reducedEnthalpy,
|
||||
.gravityPotential = gravityPotential,
|
||||
.displacement = displacement,
|
||||
.displacement = m_generatedVolumeDisplacement,
|
||||
.bernoulliConstant = bernoulli(0)},
|
||||
make_hydrostatic_dependencies(dependencies), rotation
|
||||
make_hydrostatic_dependencies(dependencies, m_generatedDisplacementDependency), rotation
|
||||
);
|
||||
|
||||
report.displacement = m_displacementOperator.Prepare(
|
||||
{.enthalpy = reducedEnthalpy}, make_displacement_dependencies(dependencies), rotation
|
||||
{.enthalpy = reducedEnthalpy},
|
||||
make_displacement_dependencies(dependencies, m_generatedDisplacementDependency), rotation
|
||||
);
|
||||
|
||||
report.massNormalization =
|
||||
m_massNormalizationOperator.Prepare({.targetMass = m_targetMass}, make_mass_dependencies(dependencies));
|
||||
report.massNormalization = m_massNormalizationOperator.Prepare(
|
||||
{.targetMass = m_targetMass}, make_mass_dependencies(dependencies, m_generatedDisplacementDependency)
|
||||
);
|
||||
|
||||
report.surfaceConstraint = m_surfaceConstraintOperator.Prepare(
|
||||
reducedEnthalpy, !wasPrepared || dependencies.enthalpy != m_preparedDependencies.enthalpy
|
||||
);
|
||||
|
||||
report.centeringConstraint = m_centeringConstraintOperator.Prepare(
|
||||
displacement, !wasPrepared || dependencies.displacement != m_preparedDependencies.displacement
|
||||
);
|
||||
|
||||
const bool dependenciesChanged = !wasPrepared || dependencies != m_preparedDependencies;
|
||||
if (dependenciesChanged || report.DidAnyChildWork()) {
|
||||
AssembleResidual();
|
||||
@@ -545,7 +588,7 @@ namespace mean_field::operators {
|
||||
}
|
||||
|
||||
void PreparedStellarEquilibriumOperator::AssembleResidual() {
|
||||
using Form = utils::blocks::barotropic_equilibrium_form;
|
||||
using Form = utils::blocks::surface_deformed_stellar_equilibrium_form;
|
||||
|
||||
constexpr auto gravityGradientResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::gravity_field.gradient_term);
|
||||
@@ -553,8 +596,8 @@ namespace mean_field::operators {
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::gravity_field.poisson_term);
|
||||
constexpr auto densityResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::density_field.mass_term);
|
||||
constexpr auto displacementResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::displacement_field.geometry_term);
|
||||
constexpr auto surfaceShapeResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::surface_deformation_field.shape_equilibrium_term);
|
||||
constexpr auto enthalpyResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::enthalpy_field.specific_term);
|
||||
constexpr auto massResidual =
|
||||
@@ -562,14 +605,17 @@ namespace mean_field::operators {
|
||||
|
||||
mfem::Vector gravity;
|
||||
mfem::Vector closure;
|
||||
mfem::Vector displacement;
|
||||
mfem::Vector surfaceShape;
|
||||
mfem::Vector hydrostatic;
|
||||
mfem::Vector mass;
|
||||
|
||||
m_gravityOperator.Mult(m_gravityState, gravity);
|
||||
m_barotropicClosureOperator.BuildResidual(closure);
|
||||
m_displacementOperator.BuildResidual(displacement);
|
||||
m_centeringConstraintOperator.ApplyResidualRows(displacement);
|
||||
m_displacementOperator.BuildResidual(m_fullMechanicalResidual);
|
||||
surfaceShape.SetSize(m_domainDeformation.parameterCount());
|
||||
m_domainDeformation.applyJacobianTranspose(
|
||||
m_surfaceDeformationParameters, m_fullMechanicalResidual, surfaceShape
|
||||
);
|
||||
m_hydrostaticOperator.BuildResidual(hydrostatic);
|
||||
m_surfaceConstraintOperator.ApplyResidualRows(hydrostatic);
|
||||
m_massNormalizationOperator.BuildResidual(mass);
|
||||
@@ -599,8 +645,8 @@ namespace mean_field::operators {
|
||||
m_cachedResidual, m_layout, densityResidual, closure, "The closure residual has the wrong size."
|
||||
);
|
||||
assign_residual_block(
|
||||
m_cachedResidual, m_layout, displacementResidual, displacement,
|
||||
"The displacement residual has the wrong size."
|
||||
m_cachedResidual, m_layout, surfaceShapeResidual, surfaceShape,
|
||||
"The surface-shape residual has the wrong size."
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
@@ -633,11 +679,11 @@ namespace mean_field::operators {
|
||||
direction, "PreparedStellarEquilibriumOperator received a non-finite Jacobian direction."
|
||||
);
|
||||
|
||||
using Form = utils::blocks::barotropic_equilibrium_form;
|
||||
using Form = utils::blocks::surface_deformed_stellar_equilibrium_form;
|
||||
|
||||
constexpr auto densityValue = utils::blocks::get_value_block<Form>(utils::blocks::density_field.mass_term);
|
||||
constexpr auto displacementValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::displacement_field.geometry_term);
|
||||
constexpr auto surfaceDeformationValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::surface_deformation_field.parameters_term);
|
||||
constexpr auto gravityGradientValue =
|
||||
utils::blocks::get_value_block<Form>(utils::blocks::gravity_field.gradient_term);
|
||||
constexpr auto gravityPotentialValue =
|
||||
@@ -653,51 +699,61 @@ namespace mean_field::operators {
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::gravity_field.poisson_term);
|
||||
constexpr auto densityResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::density_field.mass_term);
|
||||
constexpr auto displacementResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::displacement_field.geometry_term);
|
||||
constexpr auto surfaceShapeResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::surface_deformation_field.shape_equilibrium_term);
|
||||
constexpr auto enthalpyResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::enthalpy_field.specific_term);
|
||||
constexpr auto massResidual =
|
||||
utils::blocks::get_residual_block<Form>(utils::blocks::barotropic_constant_field.mass_normalization_term);
|
||||
|
||||
const mfem::Vector reducedDensityDirection = make_value_view(direction, m_layout, densityValue);
|
||||
const mfem::Vector displacementDirection = make_value_view(direction, m_layout, displacementValue);
|
||||
const mfem::Vector gravityGradientDirection = make_value_view(direction, m_layout, gravityGradientValue);
|
||||
const mfem::Vector gravityPotentialDirection = make_value_view(direction, m_layout, gravityPotentialValue);
|
||||
const mfem::Vector reducedEnthalpyDirection = make_value_view(direction, m_layout, enthalpyValue);
|
||||
const mfem::Vector bernoulliDirection = make_value_view(direction, m_layout, bernoulliValue);
|
||||
const mfem::Vector reducedDensityDirection = make_value_view(direction, m_layout, densityValue);
|
||||
const mfem::Vector surfaceDeformationDirection = make_value_view(direction, m_layout, surfaceDeformationValue);
|
||||
const mfem::Vector gravityGradientDirection = make_value_view(direction, m_layout, gravityGradientValue);
|
||||
const mfem::Vector gravityPotentialDirection = make_value_view(direction, m_layout, gravityPotentialValue);
|
||||
const mfem::Vector reducedEnthalpyDirection = make_value_view(direction, m_layout, enthalpyValue);
|
||||
const mfem::Vector bernoulliDirection = make_value_view(direction, m_layout, bernoulliValue);
|
||||
|
||||
m_domainDeformation.applyJacobian(
|
||||
m_surfaceDeformationParameters, surfaceDeformationDirection, m_volumeDisplacementDirection
|
||||
);
|
||||
|
||||
pack_gravity_vector(
|
||||
m_gravityDirection, m_gravityStateOffsets, reducedDensityDirection, displacementDirection,
|
||||
m_gravityDirection, m_gravityStateOffsets, reducedDensityDirection, m_volumeDisplacementDirection,
|
||||
gravityGradientDirection, gravityPotentialDirection
|
||||
);
|
||||
|
||||
mfem::Vector gravityAction;
|
||||
mfem::Vector closureAction;
|
||||
mfem::Vector displacementAction;
|
||||
mfem::Vector hydrostaticAction;
|
||||
mfem::Vector massAction;
|
||||
|
||||
m_gravityJacobianOperator.Mult(m_gravityDirection, gravityAction);
|
||||
|
||||
m_barotropicClosureOperator.Mult(
|
||||
reducedDensityDirection, reducedEnthalpyDirection, displacementDirection, closureAction
|
||||
reducedDensityDirection, reducedEnthalpyDirection, m_volumeDisplacementDirection, closureAction
|
||||
);
|
||||
|
||||
m_displacementOperator.ApplyCompleteJacobianAction(
|
||||
reducedDensityDirection, displacementDirection, gravityGradientDirection, reducedEnthalpyDirection,
|
||||
displacementAction
|
||||
reducedDensityDirection, m_volumeDisplacementDirection, gravityGradientDirection, reducedEnthalpyDirection,
|
||||
m_fullMechanicalAction
|
||||
);
|
||||
m_centeringConstraintOperator.ApplyJacobianRows(displacementDirection, displacementAction);
|
||||
m_domainDeformation.applyJacobianTranspose(
|
||||
m_surfaceDeformationParameters, m_fullMechanicalAction, m_surfaceShapeAction
|
||||
);
|
||||
m_domainDeformation.applyPullbackDerivative(
|
||||
m_surfaceDeformationParameters, surfaceDeformationDirection, m_fullMechanicalResidual,
|
||||
m_pullbackDerivativeAction
|
||||
);
|
||||
m_surfaceShapeAction += m_pullbackDerivativeAction;
|
||||
|
||||
m_hydrostaticOperator.ApplyCompleteJacobianAction(
|
||||
reducedEnthalpyDirection, gravityPotentialDirection, bernoulliDirection(0), displacementDirection,
|
||||
reducedEnthalpyDirection, gravityPotentialDirection, bernoulliDirection(0), m_volumeDisplacementDirection,
|
||||
hydrostaticAction
|
||||
);
|
||||
m_surfaceConstraintOperator.ApplyJacobianRows(reducedEnthalpyDirection, hydrostaticAction);
|
||||
|
||||
m_massNormalizationOperator.ApplyCompleteJacobianAction(
|
||||
reducedDensityDirection, displacementDirection, massAction
|
||||
reducedDensityDirection, m_volumeDisplacementDirection, massAction
|
||||
);
|
||||
|
||||
action.SetSize(Height());
|
||||
@@ -725,8 +781,8 @@ namespace mean_field::operators {
|
||||
action, m_layout, densityResidual, closureAction, "The closure Jacobian action has the wrong size."
|
||||
);
|
||||
assign_residual_block(
|
||||
action, m_layout, displacementResidual, displacementAction,
|
||||
"The displacement Jacobian action has the wrong size."
|
||||
action, m_layout, surfaceShapeResidual, m_surfaceShapeAction,
|
||||
"The surface-shape Jacobian action has the wrong size."
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
@@ -743,8 +799,7 @@ namespace mean_field::operators {
|
||||
bool PreparedStellarEquilibriumOperator::IsPrepared() const noexcept {
|
||||
return m_isPrepared && m_gravityContext.IsPrepared() && m_barotropicClosureOperator.IsPrepared() &&
|
||||
m_hydrostaticOperator.IsPrepared() && m_displacementOperator.IsPrepared() &&
|
||||
m_massNormalizationOperator.IsPrepared() && m_surfaceConstraintOperator.IsPrepared() &&
|
||||
m_centeringConstraintOperator.IsPrepared();
|
||||
m_massNormalizationOperator.IsPrepared() && m_surfaceConstraintOperator.IsPrepared();
|
||||
}
|
||||
|
||||
double PreparedStellarEquilibriumOperator::GetTargetMass() const noexcept {
|
||||
@@ -808,9 +863,30 @@ namespace mean_field::operators {
|
||||
return m_surfaceConstraintOperator;
|
||||
}
|
||||
|
||||
const PreparedCenteringConstraint &
|
||||
PreparedStellarEquilibriumOperator::GetCenteringConstraintOperator() const noexcept {
|
||||
return m_centeringConstraintOperator;
|
||||
const deformation::PreparedDomainDeformationRuntime &
|
||||
PreparedStellarEquilibriumOperator::GetDomainDeformation() const noexcept {
|
||||
return m_domainDeformation;
|
||||
}
|
||||
|
||||
const mfem::Vector &PreparedStellarEquilibriumOperator::GetSurfaceDeformationParameters() const {
|
||||
VerifyPrepared();
|
||||
return m_surfaceDeformationParameters;
|
||||
}
|
||||
|
||||
const mfem::Vector &PreparedStellarEquilibriumOperator::GetGeneratedVolumeDisplacement() const {
|
||||
VerifyPrepared();
|
||||
return m_generatedVolumeDisplacement;
|
||||
}
|
||||
|
||||
const mfem::Vector &PreparedStellarEquilibriumOperator::GetFullMechanicalResidual() const {
|
||||
VerifyPrepared();
|
||||
return m_fullMechanicalResidual;
|
||||
}
|
||||
|
||||
const StellarEquilibriumDependencyStamp &
|
||||
PreparedStellarEquilibriumOperator::GetGeneratedDisplacementDependency() const {
|
||||
VerifyPrepared();
|
||||
return m_generatedDisplacementDependency;
|
||||
}
|
||||
|
||||
void PreparedStellarEquilibriumOperator::VerifyPrepared() const {
|
||||
|
||||
Reference in New Issue
Block a user