perf(allocations): reduced overall allocations by 95%, increaseed jacobian applicatin by 2x
This commit uses global pre allocated work space to dramatically reduce memory usage and allocation time
This commit is contained in:
@@ -311,13 +311,12 @@ namespace mean_field::operators {
|
||||
const mfem::FiniteElement &densityElement = *m_fem.densityFes->GetFE(elementId);
|
||||
const mfem::IntegrationRule &integrationRule =
|
||||
get_moment_of_inertia_rule(m_fem, densityElement, *transformation);
|
||||
data.quadraturePoints.resize(integrationRule.GetNPoints());
|
||||
for (int quadraturePoint = 0; quadraturePoint < integrationRule.GetNPoints(); ++quadraturePoint) {
|
||||
QuadraturePointData &point = data.quadraturePoints[quadraturePoint];
|
||||
point.integrationPoint = integrationRule.IntPoint(quadraturePoint);
|
||||
point.densityShape.SetSize(densityElement.GetDof());
|
||||
densityElement.CalcShape(point.integrationPoint, point.densityShape);
|
||||
}
|
||||
data.integrationRule = &integrationRule;
|
||||
data.densityBasis = m_fem.GetReferenceTables().GetScalarTable(densityElement, integrationRule);
|
||||
data.mappingContexts.SetSize(integrationRule.GetNPoints(), m_fem.mesh->Dimension());
|
||||
data.density.SetSize(integrationRule.GetNPoints());
|
||||
data.quadratureWeights.SetSize(integrationRule.GetNPoints());
|
||||
data.cylindricalRadiusSquared.SetSize(integrationRule.GetNPoints());
|
||||
}
|
||||
int globalStellarElementCount = 0;
|
||||
MFEM_VERIFY(
|
||||
@@ -344,6 +343,7 @@ namespace mean_field::operators {
|
||||
return mapping::MappingStatus::non_finite_result;
|
||||
}
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
for (ElementPAData &data : m_elements) {
|
||||
displacementLocal.GetSubVector(data.displacementDofs, data.baseDisplacement);
|
||||
@@ -372,21 +372,24 @@ namespace mean_field::operators {
|
||||
.displacement = displacementData, .compactification = compactificationData
|
||||
};
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(data.elementId);
|
||||
for (QuadraturePointData &point : data.quadraturePoints) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
const mapping::MappingStatus status = m_domainMapper.EvaluateVolume(
|
||||
mappingData, *transformation, point.integrationPoint, workspace, point.mappingContext
|
||||
mappingData, *transformation, data.integrationRule->IntPoint(quadraturePoint), workspace,
|
||||
mappingContext
|
||||
);
|
||||
if (status != mapping::MappingStatus::valid) {
|
||||
return status;
|
||||
}
|
||||
if (point.mappingContext.mapping.compactified) {
|
||||
if (mappingContext.mapping.compactified) {
|
||||
return mapping::MappingStatus::at_compactified_infinity;
|
||||
}
|
||||
point.cylindricalRadiusSquared =
|
||||
CylindricalRadiusSquared(point.mappingContext.mapping.physical_position);
|
||||
if (!std::isfinite(point.cylindricalRadiusSquared)) {
|
||||
data.cylindricalRadiusSquared(quadraturePoint) =
|
||||
CylindricalRadiusSquared(mappingContext.mapping.physical_position);
|
||||
if (!std::isfinite(data.cylindricalRadiusSquared(quadraturePoint))) {
|
||||
return mapping::MappingStatus::non_finite_result;
|
||||
}
|
||||
data.mappingContexts.Store(quadraturePoint, mappingContext);
|
||||
data.quadratureWeights(quadraturePoint) = mappingContext.quadrature.weight;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
@@ -411,11 +414,9 @@ namespace mean_field::operators {
|
||||
if (!is_finite_vector(elementDensity)) {
|
||||
return false;
|
||||
}
|
||||
for (QuadraturePointData &point : data.quadraturePoints) {
|
||||
point.density = elementDensity * point.densityShape;
|
||||
if (!std::isfinite(point.density)) {
|
||||
return false;
|
||||
}
|
||||
data.densityBasis->GetValues().Mult(elementDensity, data.density);
|
||||
if (!is_finite_vector(data.density)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -424,9 +425,9 @@ namespace mean_field::operators {
|
||||
std::optional<AngularMomentumPreparationRejection> PreparedAngularMomentumOperator::TryAssembleResidual() {
|
||||
double localMomentOfInertia = 0.0;
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
localMomentOfInertia +=
|
||||
point.density * point.cylindricalRadiusSquared * point.mappingContext.quadrature.weight;
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.density.Size(); ++quadraturePoint) {
|
||||
localMomentOfInertia += data.density(quadraturePoint) * data.cylindricalRadiusSquared(quadraturePoint) *
|
||||
data.quadratureWeights(quadraturePoint);
|
||||
}
|
||||
}
|
||||
m_momentOfInertia = GlobalSum(localMomentOfInertia);
|
||||
@@ -472,15 +473,18 @@ namespace mean_field::operators {
|
||||
"Angular-momentum density action has the wrong true-vector size."
|
||||
);
|
||||
true_to_local(*m_fem.densityFes, densityVariation, m_densityVariationLocal);
|
||||
mfem::Vector quadratureDensityVariation;
|
||||
double localAction = 0.0;
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
m_densityVariationLocal.GetSubVector(data.densityDofs, m_elementDensityVariation);
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->InvTransformPrimal(m_elementDensityVariation);
|
||||
}
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
localAction += (m_elementDensityVariation * point.densityShape) * point.cylindricalRadiusSquared *
|
||||
point.mappingContext.quadrature.weight;
|
||||
quadratureDensityVariation.SetSize(data.integrationRule->GetNPoints());
|
||||
data.densityBasis->GetValues().Mult(m_elementDensityVariation, quadratureDensityVariation);
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadratureDensityVariation.Size(); ++quadraturePoint) {
|
||||
localAction += quadratureDensityVariation(quadraturePoint) *
|
||||
data.cylindricalRadiusSquared(quadraturePoint) * data.quadratureWeights(quadraturePoint);
|
||||
}
|
||||
}
|
||||
return localAction;
|
||||
@@ -496,6 +500,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.displacementFes, displacementVariation, m_displacementVariationLocal);
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingVariation variation;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
double localAction = 0.0;
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
m_displacementVariationLocal.GetSubVector(data.displacementDofs, m_elementDisplacementVariation);
|
||||
@@ -515,20 +520,22 @@ namespace mean_field::operators {
|
||||
.displacement = baseDisplacementData, .compactification = compactificationData
|
||||
};
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(data.elementId);
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
data.mappingContexts.Load(quadraturePoint, mappingContext);
|
||||
const mapping::MappingStatus status = m_domainMapper.EvaluateVolumeVariation(
|
||||
mappingData, directionData, *transformation, point.integrationPoint, point.mappingContext,
|
||||
workspace, variation
|
||||
mappingData, directionData, *transformation, data.integrationRule->IntPoint(quadraturePoint),
|
||||
mappingContext, workspace, variation
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
status == mapping::MappingStatus::valid,
|
||||
"Mapped angular-momentum variation is invalid. Element: " << data.elementId
|
||||
);
|
||||
const double radiusSquaredVariation = CylindricalRadiusSquaredVariation(
|
||||
point.mappingContext.mapping.physical_position, variation.mapping.physical_position_variation
|
||||
mappingContext.mapping.physical_position, variation.mapping.physical_position_variation
|
||||
);
|
||||
localAction += point.density * (radiusSquaredVariation * point.mappingContext.quadrature.weight +
|
||||
point.cylindricalRadiusSquared * variation.weight_variation);
|
||||
localAction += data.density(quadraturePoint) *
|
||||
(radiusSquaredVariation * data.quadratureWeights(quadraturePoint) +
|
||||
data.cylindricalRadiusSquared(quadraturePoint) * variation.weight_variation);
|
||||
}
|
||||
}
|
||||
return localAction;
|
||||
|
||||
@@ -450,8 +450,8 @@ namespace mean_field::operators {
|
||||
m_displacementMap.scatter(m_context.GetDisplacement(), m_baseDisplacementTrue);
|
||||
|
||||
m_isPrepared = false;
|
||||
m_elements.clear();
|
||||
m_elements.reserve(m_fem.mesh->GetNE());
|
||||
std::size_t preparedElementCount{0};
|
||||
|
||||
mfem::Vector baseDensityLocal;
|
||||
mfem::Vector baseEnthalpyLocal;
|
||||
@@ -462,6 +462,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.displacementFes, m_baseDisplacementTrue, displacementLocal);
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
mfem::Array<int> compactificationDofs;
|
||||
|
||||
@@ -485,8 +486,10 @@ namespace mean_field::operators {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_elements.emplace_back();
|
||||
ElementPAData &data = m_elements.back();
|
||||
if (preparedElementCount == m_elements.size()) {
|
||||
m_elements.emplace_back();
|
||||
}
|
||||
ElementPAData &data = m_elements[preparedElementCount++];
|
||||
data.elementId = elementId;
|
||||
|
||||
data.densityDofTransformation = m_fem.densityFes->GetElementDofs(elementId, data.densityDofs);
|
||||
@@ -533,13 +536,15 @@ namespace mean_field::operators {
|
||||
|
||||
const mfem::IntegrationRule &integrationRule =
|
||||
get_eos_rule(m_fem, m_equationOfState, densityElement, enthalpyElement, *transformation);
|
||||
data.integrationRule = &integrationRule;
|
||||
|
||||
const int quadraturePointCount = integrationRule.GetNPoints();
|
||||
const int densityDofCount = densityElement.GetDof();
|
||||
const int enthalpyDofCount = enthalpyElement.GetDof();
|
||||
|
||||
data.densityBasis.SetSize(quadraturePointCount, densityDofCount);
|
||||
data.enthalpyBasis.SetSize(quadraturePointCount, enthalpyDofCount);
|
||||
data.densityBasis = m_fem.GetReferenceTables().GetScalarTable(densityElement, integrationRule);
|
||||
data.enthalpyBasis = m_fem.GetReferenceTables().GetScalarTable(enthalpyElement, integrationRule);
|
||||
data.displacementBasis = m_fem.GetReferenceTables().GetScalarTable(displacementElement, integrationRule);
|
||||
data.inverseElementJacobians.SetSize(
|
||||
quadraturePointCount, m_fem.mesh->Dimension() * m_fem.mesh->Dimension()
|
||||
);
|
||||
@@ -555,8 +560,6 @@ namespace mean_field::operators {
|
||||
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolume(
|
||||
mappingData, *transformation, integrationPoint, workspace, mappingContext
|
||||
);
|
||||
@@ -585,8 +588,8 @@ namespace mean_field::operators {
|
||||
}
|
||||
}
|
||||
|
||||
densityElement.CalcShape(integrationPoint, densityShape);
|
||||
enthalpyElement.CalcShape(integrationPoint, enthalpyShape);
|
||||
data.densityBasis->GetValues().GetRow(quadraturePoint, densityShape);
|
||||
data.enthalpyBasis->GetValues().GetRow(quadraturePoint, enthalpyShape);
|
||||
|
||||
if (!vector_is_finite(densityShape) || !vector_is_finite(enthalpyShape)) {
|
||||
retain_higher_priority_rejection(
|
||||
@@ -595,13 +598,6 @@ namespace mean_field::operators {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int densityDof = 0; densityDof < densityDofCount; ++densityDof) {
|
||||
data.densityBasis(quadraturePoint, densityDof) = densityShape(densityDof);
|
||||
}
|
||||
for (int enthalpyDof = 0; enthalpyDof < enthalpyDofCount; ++enthalpyDof) {
|
||||
data.enthalpyBasis(quadraturePoint, enthalpyDof) = enthalpyShape(enthalpyDof);
|
||||
}
|
||||
|
||||
const double density = elementBaseDensity * densityShape;
|
||||
const double enthalpy = elementBaseEnthalpy * enthalpyShape;
|
||||
const double quadratureWeight = mappingContext.quadrature.weight;
|
||||
@@ -665,6 +661,7 @@ namespace mean_field::operators {
|
||||
data.weightedEnthalpyDerivative(quadraturePoint) = weightedEnthalpyDerivative;
|
||||
}
|
||||
}
|
||||
m_elements.resize(preparedElementCount);
|
||||
|
||||
if (auto globalRejection = synchronize_rejection(localRejection, m_fem.densityFes->GetComm());
|
||||
globalRejection.has_value()) {
|
||||
@@ -689,7 +686,7 @@ namespace mean_field::operators {
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
elementResidual.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis.MultTranspose(data.weightedResidual, elementResidual);
|
||||
data.densityBasis->GetValues().MultTranspose(data.weightedResidual, elementResidual);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->TransformDual(elementResidual);
|
||||
@@ -719,7 +716,7 @@ namespace mean_field::operators {
|
||||
elementDiagonal = 0.0;
|
||||
for (int trialDof = 0; trialDof < data.densityDofs.Size(); ++trialDof) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.quadratureWeights.Size(); ++quadraturePoint) {
|
||||
const double basis = data.densityBasis(quadraturePoint, trialDof);
|
||||
const double basis = data.densityBasis->GetValues()(quadraturePoint, trialDof);
|
||||
elementDiagonal(trialDof) += data.quadratureWeights(quadraturePoint) * basis * basis;
|
||||
}
|
||||
}
|
||||
@@ -842,8 +839,8 @@ namespace mean_field::operators {
|
||||
quadratureEnthalpyVariation.SetSize(data.quadratureWeights.Size());
|
||||
quadratureAction.SetSize(data.quadratureWeights.Size());
|
||||
|
||||
data.densityBasis.Mult(elementDensityVariation, quadratureDensityVariation);
|
||||
data.enthalpyBasis.Mult(elementEnthalpyVariation, quadratureEnthalpyVariation);
|
||||
data.densityBasis->GetValues().Mult(elementDensityVariation, quadratureDensityVariation);
|
||||
data.enthalpyBasis->GetValues().Mult(elementEnthalpyVariation, quadratureEnthalpyVariation);
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadratureAction.Size(); ++quadraturePoint) {
|
||||
quadratureAction(quadraturePoint) =
|
||||
@@ -852,7 +849,7 @@ namespace mean_field::operators {
|
||||
}
|
||||
|
||||
elementAction.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis.MultTranspose(quadratureAction, elementAction);
|
||||
data.densityBasis->GetValues().MultTranspose(quadratureAction, elementAction);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->TransformDual(elementAction);
|
||||
@@ -906,14 +903,14 @@ namespace mean_field::operators {
|
||||
"Prepared barotropic closure inverse-Jacobian data has an incompatible size."
|
||||
);
|
||||
|
||||
m_referenceDShape.SetSize(displacementElement.GetDof(), dimension);
|
||||
m_referenceDisplacementJacobian.SetSize(dimension, dimension);
|
||||
m_quadratureDisplacementAction.SetSize(integrationRule.GetNPoints());
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < integrationRule.GetNPoints(); ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = integrationRule.IntPoint(quadraturePoint);
|
||||
displacementElement.CalcDShape(integrationPoint, m_referenceDShape);
|
||||
mfem::MultAtB(directionDofs, m_referenceDShape, m_referenceDisplacementJacobian);
|
||||
mfem::MultAtB(
|
||||
directionDofs, data.displacementBasis->GetGradients(quadraturePoint),
|
||||
m_referenceDisplacementJacobian
|
||||
);
|
||||
|
||||
double logarithmicJacobianVariation{0.0};
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
@@ -933,7 +930,7 @@ namespace mean_field::operators {
|
||||
}
|
||||
|
||||
m_elementDisplacementAction.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis.MultTranspose(m_quadratureDisplacementAction, m_elementDisplacementAction);
|
||||
data.densityBasis->GetValues().MultTranspose(m_quadratureDisplacementAction, m_elementDisplacementAction);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->TransformDual(m_elementDisplacementAction);
|
||||
|
||||
@@ -13,6 +13,7 @@ module mean_field;
|
||||
|
||||
import :operators.kernels.gravity_displacement_force;
|
||||
import :operators.prepared_gravity_displacement_force;
|
||||
import :fem.reference_tables;
|
||||
|
||||
namespace {
|
||||
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
@@ -249,6 +250,17 @@ namespace mean_field::operators {
|
||||
const mfem::FiniteElement &displacementElement = *m_fem.displacementFes->GetFE(elementId);
|
||||
const mfem::FiniteElement &compactificationElement = *m_fem.compactificationFes->GetFE(elementId);
|
||||
data.integrationRule = &get_gravity_force_rule(m_fem, *transformation);
|
||||
data.densityReferenceTable =
|
||||
m_fem.GetReferenceTables().GetScalarTable(densityElement, *data.integrationRule);
|
||||
data.displacementReferenceTable =
|
||||
m_fem.GetReferenceTables().GetScalarTable(displacementElement, *data.integrationRule);
|
||||
if (gravityGradientElement.GetMapType() == mfem::FiniteElement::H_DIV &&
|
||||
gravityGradientElement.GetDim() == dimension && gravityGradientElement.GetRangeDim() == dimension &&
|
||||
transformation->GetSpaceDim() == dimension) {
|
||||
data.gravityReferenceTable =
|
||||
m_fem.GetReferenceTables().GetVectorTable(gravityGradientElement, *data.integrationRule);
|
||||
data.meshPiolaJacobians.SetSize(data.integrationRule->GetNPoints(), dimension * dimension);
|
||||
}
|
||||
|
||||
const mapping::ElementDisplacementData displacementData =
|
||||
mapping::ElementDisplacementDataFromElementVDofs(displacementElement, elementBaseDisplacement);
|
||||
@@ -282,13 +294,17 @@ namespace mean_field::operators {
|
||||
"Prepared gravity force encountered compactification on a stellar element."
|
||||
);
|
||||
|
||||
densityElement.CalcShape(integrationPoint, densityShape);
|
||||
for (int dof = 0; dof < densityElement.GetDof(); ++dof) {
|
||||
densityShape(dof) = data.densityReferenceTable->GetValues()(quadraturePoint, dof);
|
||||
}
|
||||
gravityGradientElement.CalcVShape(*transformation, gravityGradientShape);
|
||||
gravityGradientShape.MultTranspose(elementBaseGravityGradient, baseGravityReferenceValue);
|
||||
data.baseDensityValues(quadraturePoint) = elementBaseDensity * densityShape;
|
||||
data.referenceWeights(quadraturePoint) = integrationPoint.weight * transformation->Weight();
|
||||
|
||||
const mfem::DenseMatrix &inverseMeshJacobian = transformation->InverseJacobian();
|
||||
const mfem::DenseMatrix &meshJacobian = transformation->Jacobian();
|
||||
const double inverseMeshWeight = 1.0 / transformation->Weight();
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
data.baseGravityReferenceValues(quadraturePoint, row) = baseGravityReferenceValue(row);
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
@@ -296,6 +312,10 @@ namespace mean_field::operators {
|
||||
data.mappingJacobians(quadraturePoint, entry) =
|
||||
mappingContext.mapping.mapping_jacobian(row, column);
|
||||
data.inverseMeshJacobians(quadraturePoint, entry) = inverseMeshJacobian(row, column);
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
data.meshPiolaJacobians(quadraturePoint, entry) =
|
||||
inverseMeshWeight * meshJacobian(row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +328,9 @@ namespace mean_field::operators {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
const int entry = row * dimension + column;
|
||||
if (!std::isfinite(data.mappingJacobians(quadraturePoint, entry)) ||
|
||||
!std::isfinite(data.inverseMeshJacobians(quadraturePoint, entry))) {
|
||||
!std::isfinite(data.inverseMeshJacobians(quadraturePoint, entry)) ||
|
||||
(data.gravityReferenceTable != nullptr &&
|
||||
!std::isfinite(data.meshPiolaJacobians(quadraturePoint, entry)))) {
|
||||
return std::unexpected(non_finite_rejection());
|
||||
}
|
||||
}
|
||||
@@ -462,6 +484,10 @@ namespace mean_field::operators {
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
MFEM_VERIFY(data.integrationRule != nullptr, "Prepared gravity force has no integration rule.");
|
||||
MFEM_VERIFY(
|
||||
data.densityReferenceTable != nullptr && data.displacementReferenceTable != nullptr,
|
||||
"Prepared gravity force has no reference basis tables."
|
||||
);
|
||||
|
||||
m_densityVariationLocal.GetSubVector(data.densityDofs, m_elementDensityVariation);
|
||||
m_gravityGradientVariationLocal.GetSubVector(data.gravityGradientDofs, m_elementGravityGradientVariation);
|
||||
@@ -490,13 +516,14 @@ namespace mean_field::operators {
|
||||
m_densityShape.SetSize(densityElement.GetDof());
|
||||
m_displacementShape.SetSize(scalarDisplacementDofCount);
|
||||
m_gravityGradientShape.SetSize(gravityGradientElement.GetDof(), dimension);
|
||||
m_referenceDisplacementDShape.SetSize(scalarDisplacementDofCount, dimension);
|
||||
m_referenceDisplacementJacobian.SetSize(dimension, dimension);
|
||||
m_displacementJacobianVariation.SetSize(dimension, dimension);
|
||||
m_mappingJacobian.SetSize(dimension, dimension);
|
||||
m_inverseMeshJacobian.SetSize(dimension, dimension);
|
||||
m_meshPiolaJacobian.SetSize(dimension, dimension);
|
||||
m_baseGravityReferenceValue.SetSize(dimension);
|
||||
m_gravityVariationReferenceValue.SetSize(dimension);
|
||||
m_gravityVariationReferenceCellValue.SetSize(dimension);
|
||||
m_mappedBaseGravity.SetSize(dimension);
|
||||
m_mappedGravityVariation.SetSize(dimension);
|
||||
m_mappedGeometryVariation.SetSize(dimension);
|
||||
@@ -506,16 +533,28 @@ namespace mean_field::operators {
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = data.integrationRule->IntPoint(quadraturePoint);
|
||||
densityElement.CalcShape(integrationPoint, m_densityShape);
|
||||
displacementElement.CalcShape(integrationPoint, m_displacementShape);
|
||||
displacementElement.CalcDShape(integrationPoint, m_referenceDisplacementDShape);
|
||||
mfem::MultAtB(directionDofs, m_referenceDisplacementDShape, m_referenceDisplacementJacobian);
|
||||
const mfem::DenseMatrix &referenceDisplacementDShape =
|
||||
data.displacementReferenceTable->GetGradients(quadraturePoint);
|
||||
mfem::MultAtB(directionDofs, referenceDisplacementDShape, m_referenceDisplacementJacobian);
|
||||
const mfem::DenseMatrix &densityValues = data.densityReferenceTable->GetValues();
|
||||
const mfem::DenseMatrix &displacementValues = data.displacementReferenceTable->GetValues();
|
||||
for (int dof = 0; dof < densityElement.GetDof(); ++dof) {
|
||||
m_densityShape(dof) = densityValues(quadraturePoint, dof);
|
||||
}
|
||||
for (int dof = 0; dof < scalarDisplacementDofCount; ++dof) {
|
||||
m_displacementShape(dof) = displacementValues(quadraturePoint, dof);
|
||||
}
|
||||
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
gravityGradientElement.CalcVShape(*transformation, m_gravityGradientShape);
|
||||
m_gravityGradientShape.MultTranspose(
|
||||
m_elementGravityGradientVariation, m_gravityVariationReferenceValue
|
||||
);
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
data.gravityReferenceTable->GetValues(quadraturePoint)
|
||||
.MultTranspose(m_elementGravityGradientVariation, m_gravityVariationReferenceCellValue);
|
||||
} else {
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
gravityGradientElement.CalcVShape(*transformation, m_gravityGradientShape);
|
||||
m_gravityGradientShape.MultTranspose(
|
||||
m_elementGravityGradientVariation, m_gravityVariationReferenceValue
|
||||
);
|
||||
}
|
||||
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
m_baseGravityReferenceValue(row) = data.baseGravityReferenceValues(quadraturePoint, row);
|
||||
@@ -523,8 +562,14 @@ namespace mean_field::operators {
|
||||
const int entry = row * dimension + column;
|
||||
m_mappingJacobian(row, column) = data.mappingJacobians(quadraturePoint, entry);
|
||||
m_inverseMeshJacobian(row, column) = data.inverseMeshJacobians(quadraturePoint, entry);
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
m_meshPiolaJacobian(row, column) = data.meshPiolaJacobians(quadraturePoint, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
m_meshPiolaJacobian.Mult(m_gravityVariationReferenceCellValue, m_gravityVariationReferenceValue);
|
||||
}
|
||||
mfem::Mult(m_referenceDisplacementJacobian, m_inverseMeshJacobian, m_displacementJacobianVariation);
|
||||
m_mappingJacobian.Mult(m_baseGravityReferenceValue, m_mappedBaseGravity);
|
||||
m_mappingJacobian.Mult(m_gravityVariationReferenceValue, m_mappedGravityVariation);
|
||||
|
||||
@@ -182,19 +182,17 @@ namespace {
|
||||
.displacement = *m_displacement_data, .compactification = *m_compactification_data
|
||||
};
|
||||
|
||||
mean_field::mapping::VolumeMappingContext mapping_context;
|
||||
|
||||
const mean_field::mapping::MappingStatus status = m_domain_mapper.EvaluateVolume(
|
||||
mapping_data, transformation, integration_point, m_workspace, mapping_context
|
||||
mapping_data, transformation, integration_point, m_workspace, m_mapping_context
|
||||
);
|
||||
|
||||
if (status != mean_field::mapping::MappingStatus::valid) {
|
||||
m_mappingFailure = status;
|
||||
return 0.0;
|
||||
}
|
||||
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
|
||||
const double mapping_determinant = m_mapping_context.mapping.mapping_determinant;
|
||||
|
||||
m_inverse_element_jacobian = mapping_context.quadrature.J_inv;
|
||||
m_inverse_element_jacobian = m_mapping_context.quadrature.J_inv;
|
||||
|
||||
const double value = 4.0 * std::numbers::pi * mean_field::utils::G * mapping_determinant;
|
||||
if (!std::isfinite(value)) {
|
||||
@@ -269,6 +267,7 @@ namespace {
|
||||
std::unique_ptr<mean_field::mapping::ElementCompactificationData> m_compactification_data;
|
||||
|
||||
mean_field::mapping::DomainMapper::Workspace m_workspace;
|
||||
mean_field::mapping::VolumeMappingContext m_mapping_context;
|
||||
mfem::DenseMatrix m_inverse_element_jacobian;
|
||||
int m_cached_element_id{-1};
|
||||
mean_field::mapping::MappingStatus m_mappingFailure{mean_field::mapping::MappingStatus::valid};
|
||||
@@ -394,8 +393,8 @@ namespace mean_field::operators {
|
||||
m_has_variation_data = false;
|
||||
m_displacement_true.SetSize(m_displacement_map.full_size());
|
||||
m_displacement_map.scatter(displacement, m_displacement_true);
|
||||
m_elements.clear();
|
||||
m_elements.reserve(m_fem.mesh->GetNE());
|
||||
std::size_t prepared_element_count{0};
|
||||
|
||||
FrozenMappedGravitySourceCoefficient source_coefficient(m_fem, m_domain_mapper, m_displacement_true);
|
||||
bool localNonFiniteQuadrature = false;
|
||||
@@ -407,8 +406,10 @@ namespace mean_field::operators {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_elements.emplace_back();
|
||||
ElementPAData &data = m_elements.back();
|
||||
if (prepared_element_count == m_elements.size()) {
|
||||
m_elements.emplace_back();
|
||||
}
|
||||
ElementPAData &data = m_elements[prepared_element_count++];
|
||||
|
||||
data.element_id = element_id;
|
||||
|
||||
@@ -438,37 +439,59 @@ namespace mean_field::operators {
|
||||
|
||||
const int potential_dof_count = potential_element.GetDof();
|
||||
|
||||
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
|
||||
|
||||
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
|
||||
if (density_element.GetMapType() == mfem::FiniteElement::VALUE) {
|
||||
data.density_reference = m_fem.GetReferenceTables().GetScalarTable(density_element, integration_rule);
|
||||
data.density_basis.SetSize(0, 0);
|
||||
} else {
|
||||
data.density_reference.reset();
|
||||
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
|
||||
}
|
||||
if (potential_element.GetMapType() == mfem::FiniteElement::VALUE) {
|
||||
data.potential_reference =
|
||||
m_fem.GetReferenceTables().GetScalarTable(potential_element, integration_rule);
|
||||
data.potential_basis.SetSize(0, 0);
|
||||
} else {
|
||||
data.potential_reference.reset();
|
||||
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
|
||||
}
|
||||
|
||||
const int dimension = m_fem.mesh->Dimension();
|
||||
if (mode == PreparationMode::linearization) {
|
||||
data.inverse_element_jacobians.SetSize(quadrature_point_count, dimension * dimension);
|
||||
data.displacement_reference = m_fem.GetReferenceTables().GetScalarTable(
|
||||
*m_fem.displacementFes->GetFE(element_id), integration_rule
|
||||
);
|
||||
}
|
||||
|
||||
data.quadrature_data.SetSize(quadrature_point_count);
|
||||
|
||||
mfem::Vector density_shape(density_dof_count);
|
||||
mfem::Vector potential_shape(potential_dof_count);
|
||||
mfem::Vector density_shape;
|
||||
mfem::Vector potential_shape;
|
||||
if (!data.density_reference) {
|
||||
density_shape.SetSize(density_dof_count);
|
||||
}
|
||||
if (!data.potential_reference) {
|
||||
potential_shape.SetSize(potential_dof_count);
|
||||
}
|
||||
|
||||
for (int quadrature_point = 0; quadrature_point < quadrature_point_count; ++quadrature_point) {
|
||||
const mfem::IntegrationPoint &integration_point = integration_rule.IntPoint(quadrature_point);
|
||||
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
// CalcPhysShape matches the scalar mixed-mass discretization,
|
||||
// including the finite-element map type.
|
||||
density_element.CalcPhysShape(transformation, density_shape);
|
||||
|
||||
potential_element.CalcPhysShape(transformation, potential_shape);
|
||||
|
||||
for (int i = 0; i < density_dof_count; ++i) {
|
||||
data.density_basis(quadrature_point, i) = density_shape(i);
|
||||
// VALUE maps use the shared reference basis. Preserve the
|
||||
// physical-shape evaluation for every other scalar map type.
|
||||
if (!data.density_reference) {
|
||||
density_element.CalcPhysShape(transformation, density_shape);
|
||||
for (int i = 0; i < density_dof_count; ++i) {
|
||||
data.density_basis(quadrature_point, i) = density_shape(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < potential_dof_count; ++i) {
|
||||
data.potential_basis(quadrature_point, i) = potential_shape(i);
|
||||
if (!data.potential_reference) {
|
||||
potential_element.CalcPhysShape(transformation, potential_shape);
|
||||
for (int i = 0; i < potential_dof_count; ++i) {
|
||||
data.potential_basis(quadrature_point, i) = potential_shape(i);
|
||||
}
|
||||
}
|
||||
|
||||
const double coefficient_value = source_coefficient.Eval(transformation, integration_point);
|
||||
@@ -505,6 +528,7 @@ namespace mean_field::operators {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_elements.resize(prepared_element_count);
|
||||
|
||||
const bool localNonFiniteArithmetic = source_coefficient.HasNonFiniteArithmetic() || localNonFiniteQuadrature;
|
||||
auto preparationResult = synchronize_preparation_failure(
|
||||
@@ -555,7 +579,7 @@ namespace mean_field::operators {
|
||||
m_quadrature_action.SetSize(data.quadrature_data.Size());
|
||||
|
||||
// B_density * x_e
|
||||
data.density_basis.Mult(m_element_input, m_quadrature_action);
|
||||
data.GetDensityBasis().Mult(m_element_input, m_quadrature_action);
|
||||
|
||||
// D * B_density * x_e
|
||||
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
|
||||
@@ -565,7 +589,7 @@ namespace mean_field::operators {
|
||||
m_element_action.SetSize(data.potential_dofs.Size());
|
||||
|
||||
// B_potential^T * D * B_density * x_e
|
||||
data.potential_basis.MultTranspose(m_quadrature_action, m_element_action);
|
||||
data.GetPotentialBasis().MultTranspose(m_quadrature_action, m_element_action);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->TransformDual(m_element_action);
|
||||
@@ -641,15 +665,15 @@ namespace mean_field::operators {
|
||||
"Prepared gravity source inverse-Jacobian data has an incompatible size."
|
||||
);
|
||||
|
||||
m_reference_displacement_dshape.SetSize(displacement_element.GetDof(), dimension);
|
||||
m_reference_displacement_jacobian.SetSize(dimension, dimension);
|
||||
m_quadrature_variation_action.SetSize(data.integration_rule->GetNPoints());
|
||||
data.density_basis.Mult(m_element_density, m_quadrature_variation_action);
|
||||
data.GetDensityBasis().Mult(m_element_density, m_quadrature_variation_action);
|
||||
|
||||
for (int quadrature_point = 0; quadrature_point < data.integration_rule->GetNPoints(); ++quadrature_point) {
|
||||
const mfem::IntegrationPoint &integration_point = data.integration_rule->IntPoint(quadrature_point);
|
||||
displacement_element.CalcDShape(integration_point, m_reference_displacement_dshape);
|
||||
mfem::MultAtB(direction_dofs, m_reference_displacement_dshape, m_reference_displacement_jacobian);
|
||||
mfem::MultAtB(
|
||||
direction_dofs, data.displacement_reference->GetGradients(quadrature_point),
|
||||
m_reference_displacement_jacobian
|
||||
);
|
||||
|
||||
double logarithmic_jacobian_variation{0.0};
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
@@ -669,7 +693,7 @@ namespace mean_field::operators {
|
||||
}
|
||||
|
||||
m_element_variation_action.SetSize(data.potential_dofs.Size());
|
||||
data.potential_basis.MultTranspose(m_quadrature_variation_action, m_element_variation_action);
|
||||
data.GetPotentialBasis().MultTranspose(m_quadrature_variation_action, m_element_variation_action);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->TransformDual(m_element_variation_action);
|
||||
@@ -714,7 +738,7 @@ namespace mean_field::operators {
|
||||
|
||||
m_quadrature_action.SetSize(data.quadrature_data.Size());
|
||||
|
||||
data.potential_basis.Mult(m_element_input, m_quadrature_action);
|
||||
data.GetPotentialBasis().Mult(m_element_input, m_quadrature_action);
|
||||
|
||||
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
|
||||
m_quadrature_action(q) *= data.quadrature_data(q);
|
||||
@@ -722,7 +746,7 @@ namespace mean_field::operators {
|
||||
|
||||
m_element_action.SetSize(data.density_dofs.Size());
|
||||
|
||||
data.density_basis.MultTranspose(m_quadrature_action, m_element_action);
|
||||
data.GetDensityBasis().MultTranspose(m_quadrature_action, m_element_action);
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->TransformDual(m_element_action);
|
||||
|
||||
@@ -13,6 +13,8 @@ module;
|
||||
#include <mpi.h>
|
||||
|
||||
module mean_field;
|
||||
|
||||
import :fem.reference_tables;
|
||||
import :operators.prepared_hdiv_mass;
|
||||
|
||||
namespace {
|
||||
@@ -551,6 +553,15 @@ namespace mean_field::operators {
|
||||
);
|
||||
|
||||
data.integrationRule = &get_hdiv_mass_rule(m_fem, m_domain_mapper, gravityGradientElement, *transformation);
|
||||
const int dimension = m_domain_mapper.GetDimension();
|
||||
if (gravityGradientElement.GetMapType() == mfem::FiniteElement::H_DIV &&
|
||||
gravityGradientElement.GetDim() == dimension && gravityGradientElement.GetRangeDim() == dimension &&
|
||||
transformation->GetSpaceDim() == dimension) {
|
||||
data.gravityReferenceTable =
|
||||
m_fem.GetReferenceTables().GetVectorTable(gravityGradientElement, *data.integrationRule);
|
||||
data.meshPiolaJacobians.SetSize(data.integrationRule->GetNPoints(), dimension * dimension);
|
||||
data.referenceWeights.SetSize(data.integrationRule->GetNPoints());
|
||||
}
|
||||
data.frozenMappingData.SetSize(
|
||||
data.integrationRule->GetNPoints(), frozen_mapping_width(m_domain_mapper.GetDimension())
|
||||
);
|
||||
@@ -573,6 +584,25 @@ namespace mean_field::operators {
|
||||
return status;
|
||||
}
|
||||
freeze_mapping_context(mappingContext, quadraturePoint, data.frozenMappingData);
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
// CalcVShape_RT = reference_shape * J_mesh^T / Weight.
|
||||
// Cache only this small factor, never the mapped basis.
|
||||
const double meshWeight = transformation->Weight();
|
||||
const mfem::DenseMatrix &meshJacobian = transformation->Jacobian();
|
||||
const double inverseMeshWeight = 1.0 / meshWeight;
|
||||
data.referenceWeights(quadraturePoint) = integrationPoint.weight * meshWeight;
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
const double entry = inverseMeshWeight * meshJacobian(row, column);
|
||||
if (!std::isfinite(entry))
|
||||
return mapping::MappingStatus::non_finite_result;
|
||||
data.meshPiolaJacobians(quadraturePoint, row * dimension + column) = entry;
|
||||
}
|
||||
}
|
||||
if (!std::isfinite(data.referenceWeights(quadraturePoint))) {
|
||||
return mapping::MappingStatus::non_finite_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mapping::MappingStatus::valid;
|
||||
@@ -830,7 +860,10 @@ namespace mean_field::operators {
|
||||
m_elementVariationAction.SetSize(gravityGradientElement.GetDof());
|
||||
m_elementVariationAction = 0.0;
|
||||
m_gravityGradientValue.SetSize(dimension);
|
||||
m_gravityReferenceCellValue.SetSize(dimension);
|
||||
m_referenceCellDual.SetSize(dimension);
|
||||
m_massTensorVariationAction.SetSize(dimension);
|
||||
m_meshPiolaJacobian.SetSize(dimension, dimension);
|
||||
m_gravityGradientShape.SetSize(gravityGradientElement.GetDof(), dimension);
|
||||
m_massTensorVariation.SetSize(dimension, dimension);
|
||||
|
||||
@@ -853,12 +886,33 @@ namespace mean_field::operators {
|
||||
m_baseMappingContext.mapping, m_mappingVariation.mapping, m_massTensorVariation
|
||||
);
|
||||
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
gravityGradientElement.CalcVShape(*transformation, m_gravityGradientShape);
|
||||
m_gravityGradientShape.MultTranspose(m_elementGravityGradient, m_gravityGradientValue);
|
||||
m_massTensorVariation.Mult(m_gravityGradientValue, m_massTensorVariationAction);
|
||||
const double referenceWeight = integrationPoint.weight * transformation->Weight();
|
||||
m_gravityGradientShape.AddMult(m_massTensorVariationAction, m_elementVariationAction, referenceWeight);
|
||||
if (data.gravityReferenceTable != nullptr) {
|
||||
const mfem::DenseMatrix &referenceShape = data.gravityReferenceTable->GetValues(quadraturePoint);
|
||||
referenceShape.MultTranspose(m_elementGravityGradient, m_gravityReferenceCellValue);
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
m_meshPiolaJacobian(row, column) =
|
||||
data.meshPiolaJacobians(quadraturePoint, row * dimension + column);
|
||||
}
|
||||
}
|
||||
m_meshPiolaJacobian.Mult(m_gravityReferenceCellValue, m_gravityGradientValue);
|
||||
m_massTensorVariation.Mult(m_gravityGradientValue, m_massTensorVariationAction);
|
||||
// Move the test-side Piola transform onto the three-vector
|
||||
// dual before applying the reference basis transpose.
|
||||
m_meshPiolaJacobian.MultTranspose(m_massTensorVariationAction, m_referenceCellDual);
|
||||
referenceShape.AddMult(
|
||||
m_referenceCellDual, m_elementVariationAction, data.referenceWeights(quadraturePoint)
|
||||
);
|
||||
} else {
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
gravityGradientElement.CalcVShape(*transformation, m_gravityGradientShape);
|
||||
m_gravityGradientShape.MultTranspose(m_elementGravityGradient, m_gravityGradientValue);
|
||||
m_massTensorVariation.Mult(m_gravityGradientValue, m_massTensorVariationAction);
|
||||
const double referenceWeight = integrationPoint.weight * transformation->Weight();
|
||||
m_gravityGradientShape.AddMult(
|
||||
m_massTensorVariationAction, m_elementVariationAction, referenceWeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.gravityGradientDofTransformation != nullptr) {
|
||||
|
||||
@@ -488,9 +488,6 @@ namespace mean_field::operators {
|
||||
m_elements.clear();
|
||||
m_elements.reserve(m_fem.mesh->GetNE());
|
||||
|
||||
mfem::Vector enthalpyShape;
|
||||
mfem::Vector gravityPotentialShape;
|
||||
|
||||
for (int elementId = 0; elementId < m_fem.mesh->GetNE(); ++elementId) {
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(elementId);
|
||||
|
||||
@@ -528,34 +525,10 @@ namespace mean_field::operators {
|
||||
data.integrationRule =
|
||||
&get_hydrostatic_rule(m_fem, enthalpyElement, gravityPotentialElement, *transformation);
|
||||
|
||||
const int quadraturePointCount = data.integrationRule->GetNPoints();
|
||||
|
||||
const int enthalpyDofCount = enthalpyElement.GetDof();
|
||||
|
||||
const int gravityPotentialDofCount = gravityPotentialElement.GetDof();
|
||||
|
||||
data.enthalpyBasis.SetSize(quadraturePointCount, enthalpyDofCount);
|
||||
|
||||
data.gravityPotentialBasis.SetSize(quadraturePointCount, gravityPotentialDofCount);
|
||||
|
||||
enthalpyShape.SetSize(enthalpyDofCount);
|
||||
gravityPotentialShape.SetSize(gravityPotentialDofCount);
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = data.integrationRule->IntPoint(quadraturePoint);
|
||||
|
||||
enthalpyElement.CalcShape(integrationPoint, enthalpyShape);
|
||||
|
||||
gravityPotentialElement.CalcShape(integrationPoint, gravityPotentialShape);
|
||||
|
||||
for (int dof = 0; dof < enthalpyDofCount; ++dof) {
|
||||
data.enthalpyBasis(quadraturePoint, dof) = enthalpyShape(dof);
|
||||
}
|
||||
|
||||
for (int dof = 0; dof < gravityPotentialDofCount; ++dof) {
|
||||
data.gravityPotentialBasis(quadraturePoint, dof) = gravityPotentialShape(dof);
|
||||
}
|
||||
}
|
||||
const fem::ReferenceTableCache &referenceTables = m_fem.GetReferenceTables();
|
||||
data.enthalpyReferenceTable = referenceTables.GetScalarTable(enthalpyElement, *data.integrationRule);
|
||||
data.gravityPotentialReferenceTable =
|
||||
referenceTables.GetScalarTable(gravityPotentialElement, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,6 +538,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.displacementFes, m_context.GetDisplacementTrue(), displacementLocal);
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
mfem::Array<int> compactificationDofs;
|
||||
|
||||
@@ -615,16 +589,14 @@ namespace mean_field::operators {
|
||||
|
||||
data.quadratureWeights.SetSize(quadraturePointCount);
|
||||
|
||||
data.baseMappingContexts.resize(quadraturePointCount);
|
||||
data.baseMappingContexts.SetSize(quadraturePointCount, m_fem.mesh->Dimension());
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = data.integrationRule->IntPoint(quadraturePoint);
|
||||
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
|
||||
mapping::VolumeMappingContext &mappingContext = data.baseMappingContexts[quadraturePoint];
|
||||
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolume(
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolume(
|
||||
mappingData, *transformation, integrationPoint, workspace, mappingContext
|
||||
);
|
||||
|
||||
@@ -641,6 +613,7 @@ namespace mean_field::operators {
|
||||
return mapping::MappingStatus::non_positive_determinant;
|
||||
}
|
||||
|
||||
data.baseMappingContexts.Store(quadraturePoint, mappingContext);
|
||||
data.quadratureWeights(quadraturePoint) = quadratureWeight;
|
||||
|
||||
for (int component = 0; component < m_fem.mesh->Dimension(); ++component) {
|
||||
@@ -660,15 +633,17 @@ namespace mean_field::operators {
|
||||
|
||||
bool PreparedHydrostaticEquilibriumOperator::PrepareAlgebraicJacobianBlocks() {
|
||||
for (ElementPAData &data : m_elements) {
|
||||
const int quadraturePointCount = data.quadratureWeights.Size();
|
||||
const mfem::DenseMatrix &enthalpyBasis = data.GetEnthalpyBasis();
|
||||
const mfem::DenseMatrix &gravityPotentialBasis = data.GetGravityPotentialBasis();
|
||||
const int quadraturePointCount = data.quadratureWeights.Size();
|
||||
|
||||
const int enthalpyDofCount = data.enthalpyBasis.Width();
|
||||
const int enthalpyDofCount = enthalpyBasis.Width();
|
||||
|
||||
const int gravityPotentialDofCount = data.gravityPotentialBasis.Width();
|
||||
const int gravityPotentialDofCount = gravityPotentialBasis.Width();
|
||||
|
||||
MFEM_VERIFY(
|
||||
data.enthalpyBasis.Height() == quadraturePointCount &&
|
||||
data.gravityPotentialBasis.Height() == quadraturePointCount,
|
||||
enthalpyBasis.Height() == quadraturePointCount &&
|
||||
gravityPotentialBasis.Height() == quadraturePointCount,
|
||||
"Prepared hydrostatic algebraic Jacobian has "
|
||||
"inconsistent quadrature data."
|
||||
);
|
||||
@@ -687,18 +662,18 @@ namespace mean_field::operators {
|
||||
const double quadratureWeight = data.quadratureWeights(quadraturePoint);
|
||||
|
||||
for (int testDof = 0; testDof < enthalpyDofCount; ++testDof) {
|
||||
const double weightedTestBasis = quadratureWeight * data.enthalpyBasis(quadraturePoint, testDof);
|
||||
const double weightedTestBasis = quadratureWeight * enthalpyBasis(quadraturePoint, testDof);
|
||||
|
||||
data.bernoulliConstantJacobian(testDof) -= weightedTestBasis;
|
||||
|
||||
for (int trialDof = 0; trialDof < enthalpyDofCount; ++trialDof) {
|
||||
data.enthalpyJacobian(testDof, trialDof) +=
|
||||
weightedTestBasis * data.enthalpyBasis(quadraturePoint, trialDof);
|
||||
weightedTestBasis * enthalpyBasis(quadraturePoint, trialDof);
|
||||
}
|
||||
|
||||
for (int trialDof = 0; trialDof < gravityPotentialDofCount; ++trialDof) {
|
||||
data.gravityPotentialJacobian(testDof, trialDof) +=
|
||||
weightedTestBasis * data.gravityPotentialBasis(quadraturePoint, trialDof);
|
||||
weightedTestBasis * gravityPotentialBasis(quadraturePoint, trialDof);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -795,9 +770,9 @@ namespace mean_field::operators {
|
||||
|
||||
quadratureGravityPotential.SetSize(quadraturePointCount);
|
||||
|
||||
data.enthalpyBasis.Mult(elementEnthalpy, quadratureEnthalpy);
|
||||
data.GetEnthalpyBasis().Mult(elementEnthalpy, quadratureEnthalpy);
|
||||
|
||||
data.gravityPotentialBasis.Mult(elementGravityPotential, quadratureGravityPotential);
|
||||
data.GetGravityPotentialBasis().Mult(elementGravityPotential, quadratureGravityPotential);
|
||||
|
||||
MFEM_VERIFY(
|
||||
data.rotationPotential.Size() == quadraturePointCount, "Prepared hydrostatic base state has stale "
|
||||
@@ -836,7 +811,8 @@ namespace mean_field::operators {
|
||||
|
||||
MFEM_VERIFY(
|
||||
data.baseDisplacementData.has_value() && data.compactificationData.has_value() &&
|
||||
static_cast<int>(data.baseMappingContexts.size()) == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetPointCount() == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetDimension() == dimension &&
|
||||
data.rotationGradient.Height() == quadraturePointCount &&
|
||||
data.rotationGradient.Width() == dimension &&
|
||||
data.hydrostaticImbalance.Size() == quadraturePointCount,
|
||||
@@ -855,7 +831,7 @@ namespace mean_field::operators {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
elementResidual.SetSize(data.enthalpyDofs.Size());
|
||||
|
||||
data.enthalpyBasis.MultTranspose(data.weightedResidual, elementResidual);
|
||||
data.GetEnthalpyBasis().MultTranspose(data.weightedResidual, elementResidual);
|
||||
|
||||
if (data.enthalpyDofTransformation != nullptr) {
|
||||
data.enthalpyDofTransformation->TransformDual(elementResidual);
|
||||
@@ -1072,7 +1048,7 @@ namespace mean_field::operators {
|
||||
data.rotationPotential(quadraturePoint);
|
||||
}
|
||||
elementAction.SetSize(data.enthalpyDofs.Size());
|
||||
data.enthalpyBasis.MultTranspose(weightedVariation, elementAction);
|
||||
data.GetEnthalpyBasis().MultTranspose(weightedVariation, elementAction);
|
||||
if (data.enthalpyDofTransformation != nullptr) {
|
||||
data.enthalpyDofTransformation->TransformDual(elementAction);
|
||||
}
|
||||
@@ -1204,6 +1180,7 @@ namespace mean_field::operators {
|
||||
mfem::Vector elementDisplacementVariation;
|
||||
mfem::Vector weightedQuadratureVariation;
|
||||
mfem::Vector elementAction;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
mapping::VolumeMappingVariation variation;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
@@ -1239,7 +1216,7 @@ namespace mean_field::operators {
|
||||
const int quadraturePointCount = data.integrationRule->GetNPoints();
|
||||
|
||||
MFEM_VERIFY(
|
||||
static_cast<int>(data.baseMappingContexts.size()) == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetPointCount() == quadraturePointCount &&
|
||||
data.quadratureWeights.Size() == quadraturePointCount &&
|
||||
data.hydrostaticImbalance.Size() == quadraturePointCount &&
|
||||
data.rotationGradient.Height() == quadraturePointCount &&
|
||||
@@ -1252,10 +1229,10 @@ namespace mean_field::operators {
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = data.integrationRule->IntPoint(quadraturePoint);
|
||||
data.baseMappingContexts.Load(quadraturePoint, mappingContext);
|
||||
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolumeVariation(
|
||||
mappingData, directionData, *transformation, integrationPoint,
|
||||
data.baseMappingContexts[quadraturePoint], workspace, variation
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolumeVariation(
|
||||
mappingData, directionData, *transformation, integrationPoint, mappingContext, workspace, variation
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
@@ -1288,7 +1265,7 @@ namespace mean_field::operators {
|
||||
|
||||
elementAction.SetSize(data.enthalpyDofs.Size());
|
||||
|
||||
data.enthalpyBasis.MultTranspose(weightedQuadratureVariation, elementAction);
|
||||
data.GetEnthalpyBasis().MultTranspose(weightedQuadratureVariation, elementAction);
|
||||
|
||||
if (data.enthalpyDofTransformation != nullptr) {
|
||||
data.enthalpyDofTransformation->TransformDual(elementAction);
|
||||
|
||||
@@ -420,17 +420,12 @@ namespace mean_field::operators {
|
||||
|
||||
const mfem::IntegrationRule &integrationRule =
|
||||
get_mass_normalization_rule(m_fem, densityElement, *transformation);
|
||||
data.integrationRule = &integrationRule;
|
||||
|
||||
data.quadraturePoints.resize(integrationRule.GetNPoints());
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < integrationRule.GetNPoints(); ++quadraturePoint) {
|
||||
QuadraturePointData &point = data.quadraturePoints[quadraturePoint];
|
||||
|
||||
point.integrationPoint = integrationRule.IntPoint(quadraturePoint);
|
||||
|
||||
point.densityShape.SetSize(densityElement.GetDof());
|
||||
densityElement.CalcShape(point.integrationPoint, point.densityShape);
|
||||
}
|
||||
data.densityBasis = m_fem.GetReferenceTables().GetScalarTable(densityElement, integrationRule);
|
||||
data.mappingContexts.SetSize(integrationRule.GetNPoints(), m_fem.mesh->Dimension());
|
||||
data.density.SetSize(integrationRule.GetNPoints());
|
||||
data.quadratureWeights.SetSize(integrationRule.GetNPoints());
|
||||
}
|
||||
|
||||
int globalStellarElementCount = 0;
|
||||
@@ -459,6 +454,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.displacementFes, displacement, displacementLocal);
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
std::optional<MassNormalizationPreparationRejection> rejection;
|
||||
|
||||
for (ElementPAData &data : m_elements) {
|
||||
@@ -491,9 +487,10 @@ namespace mean_field::operators {
|
||||
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(data.elementId);
|
||||
|
||||
for (QuadraturePointData &point : data.quadraturePoints) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
const mapping::MappingStatus status = m_domainMapper.EvaluateVolume(
|
||||
mappingData, *transformation, point.integrationPoint, workspace, point.mappingContext
|
||||
mappingData, *transformation, data.integrationRule->IntPoint(quadraturePoint), workspace,
|
||||
mappingContext
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
@@ -505,6 +502,9 @@ namespace mean_field::operators {
|
||||
rejection, {.reason = MassNormalizationPreparationRejectionReason::mapping_failure,
|
||||
.mappingStatus = status}
|
||||
);
|
||||
} else {
|
||||
data.mappingContexts.Store(quadraturePoint, mappingContext);
|
||||
data.quadratureWeights(quadraturePoint) = mappingContext.quadrature.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -537,9 +537,9 @@ namespace mean_field::operators {
|
||||
data.densityDofTransformation->InvTransformPrimal(elementDensity);
|
||||
}
|
||||
|
||||
for (QuadraturePointData &point : data.quadraturePoints) {
|
||||
point.density = elementDensity * point.densityShape;
|
||||
if (!std::isfinite(point.density)) {
|
||||
data.densityBasis->GetValues().Mult(elementDensity, data.density);
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.density.Size(); ++quadraturePoint) {
|
||||
if (!std::isfinite(data.density(quadraturePoint))) {
|
||||
retain_higher_priority_rejection(
|
||||
rejection,
|
||||
{.reason = MassNormalizationPreparationRejectionReason::non_finite_density_interpolation}
|
||||
@@ -556,8 +556,8 @@ namespace mean_field::operators {
|
||||
std::optional<MassNormalizationPreparationRejection> localRejection;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
const double contribution = point.density * point.mappingContext.quadrature.weight;
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.density.Size(); ++quadraturePoint) {
|
||||
const double contribution = data.density(quadraturePoint) * data.quadratureWeights(quadraturePoint);
|
||||
if (!std::isfinite(contribution) || !std::isfinite(localMass + contribution)) {
|
||||
localRejection = {.reason = MassNormalizationPreparationRejectionReason::non_finite_assembled_mass};
|
||||
continue;
|
||||
@@ -615,6 +615,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.densityFes, densityVariation, densityVariationLocal);
|
||||
|
||||
mfem::Vector elementDensityVariation;
|
||||
mfem::Vector quadratureDensityVariation;
|
||||
double localAction = 0.0;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
@@ -624,8 +625,10 @@ namespace mean_field::operators {
|
||||
data.densityDofTransformation->InvTransformPrimal(elementDensityVariation);
|
||||
}
|
||||
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
localAction += (elementDensityVariation * point.densityShape) * point.mappingContext.quadrature.weight;
|
||||
quadratureDensityVariation.SetSize(data.integrationRule->GetNPoints());
|
||||
data.densityBasis->GetValues().Mult(elementDensityVariation, quadratureDensityVariation);
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadratureDensityVariation.Size(); ++quadraturePoint) {
|
||||
localAction += quadratureDensityVariation(quadraturePoint) * data.quadratureWeights(quadraturePoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,6 +653,7 @@ namespace mean_field::operators {
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingVariation variation;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
mfem::Vector elementDisplacementVariation;
|
||||
double localAction = 0.0;
|
||||
@@ -681,10 +685,11 @@ namespace mean_field::operators {
|
||||
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(data.elementId);
|
||||
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
data.mappingContexts.Load(quadraturePoint, mappingContext);
|
||||
const mapping::MappingStatus status = m_domainMapper.EvaluateVolumeVariation(
|
||||
mappingData, directionData, *transformation, point.integrationPoint, point.mappingContext,
|
||||
workspace, variation
|
||||
mappingData, directionData, *transformation, data.integrationRule->IntPoint(quadraturePoint),
|
||||
mappingContext, workspace, variation
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
@@ -694,7 +699,7 @@ namespace mean_field::operators {
|
||||
<< ", status: " << static_cast<int>(status)
|
||||
);
|
||||
|
||||
localAction += point.density * variation.weight_variation;
|
||||
localAction += data.density(quadraturePoint) * variation.weight_variation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,14 +794,13 @@ namespace mean_field::operators {
|
||||
localDual = 0.0;
|
||||
|
||||
mfem::Vector elementDual;
|
||||
mfem::Vector weightedDual;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
elementDual.SetSize(data.densityDofs.Size());
|
||||
elementDual = 0.0;
|
||||
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
elementDual.Add(residualDual * point.mappingContext.quadrature.weight, point.densityShape);
|
||||
}
|
||||
weightedDual = data.quadratureWeights;
|
||||
weightedDual *= residualDual;
|
||||
data.densityBasis->GetValues().MultTranspose(weightedDual, elementDual);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->TransformDual(elementDual);
|
||||
@@ -821,6 +825,7 @@ namespace mean_field::operators {
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingVariation variation;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
mfem::Vector elementDirection;
|
||||
mfem::Vector elementDual;
|
||||
|
||||
@@ -852,10 +857,11 @@ namespace mean_field::operators {
|
||||
|
||||
double elementDofAction = 0.0;
|
||||
|
||||
for (const QuadraturePointData &point : data.quadraturePoints) {
|
||||
for (int quadraturePoint = 0; quadraturePoint < data.integrationRule->GetNPoints(); ++quadraturePoint) {
|
||||
data.mappingContexts.Load(quadraturePoint, mappingContext);
|
||||
const mapping::MappingStatus status = m_domainMapper.EvaluateVolumeVariation(
|
||||
mappingData, directionData, *transformation, point.integrationPoint, point.mappingContext,
|
||||
workspace, variation
|
||||
mappingData, directionData, *transformation, data.integrationRule->IntPoint(quadraturePoint),
|
||||
mappingContext, workspace, variation
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
@@ -864,7 +870,7 @@ namespace mean_field::operators {
|
||||
<< data.elementId << ", status: " << static_cast<int>(status)
|
||||
);
|
||||
|
||||
elementDofAction += point.density * variation.weight_variation;
|
||||
elementDofAction += data.density(quadraturePoint) * variation.weight_variation;
|
||||
}
|
||||
|
||||
elementDual(elementDof) = residualDual * elementDofAction;
|
||||
|
||||
@@ -492,9 +492,6 @@ namespace mean_field::operators {
|
||||
|
||||
m_elements.reserve(m_fem.mesh->GetNE());
|
||||
|
||||
mfem::Vector enthalpyShape;
|
||||
mfem::DenseMatrix displacementDShape;
|
||||
|
||||
for (int elementId = 0; elementId < m_fem.mesh->GetNE(); ++elementId) {
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(elementId);
|
||||
|
||||
@@ -559,29 +556,11 @@ namespace mean_field::operators {
|
||||
"an unexpected vector DOF count."
|
||||
);
|
||||
|
||||
data.enthalpyBasis.SetSize(quadraturePointCount, enthalpyDofCount);
|
||||
|
||||
data.referenceTestGradients.resize(quadraturePointCount);
|
||||
|
||||
const fem::ReferenceTableCache &referenceTables = m_fem.GetReferenceTables();
|
||||
data.enthalpyReferenceTable = referenceTables.GetScalarTable(enthalpyElement, *data.integrationRule);
|
||||
data.displacementReferenceTable =
|
||||
referenceTables.GetScalarTable(displacementElement, *data.integrationRule);
|
||||
data.physicalTestGradients.resize(quadraturePointCount);
|
||||
|
||||
enthalpyShape.SetSize(enthalpyDofCount);
|
||||
|
||||
displacementDShape.SetSize(scalarDisplacementDofCount, dimension);
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
const mfem::IntegrationPoint &integrationPoint = data.integrationRule->IntPoint(quadraturePoint);
|
||||
|
||||
enthalpyElement.CalcShape(integrationPoint, enthalpyShape);
|
||||
|
||||
displacementElement.CalcDShape(integrationPoint, displacementDShape);
|
||||
|
||||
for (int enthalpyDof = 0; enthalpyDof < enthalpyDofCount; ++enthalpyDof) {
|
||||
data.enthalpyBasis(quadraturePoint, enthalpyDof) = enthalpyShape(enthalpyDof);
|
||||
}
|
||||
|
||||
data.referenceTestGradients[quadraturePoint] = displacementDShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,6 +570,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.displacementFes, m_baseDisplacementTrue, displacementLocal);
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
|
||||
mfem::Vector elementDisplacement;
|
||||
mfem::Vector elementCompactification;
|
||||
@@ -634,14 +614,15 @@ namespace mean_field::operators {
|
||||
const int quadraturePointCount = data.integrationRule->GetNPoints();
|
||||
|
||||
MFEM_VERIFY(
|
||||
static_cast<int>(data.referenceTestGradients.size()) == quadraturePointCount,
|
||||
data.displacementReferenceTable != nullptr &&
|
||||
data.displacementReferenceTable->GetPointCount() == quadraturePointCount,
|
||||
"Prepared pressure-force geometry has inconsistent "
|
||||
"static gradient data."
|
||||
);
|
||||
|
||||
data.quadratureWeights.SetSize(quadraturePointCount);
|
||||
|
||||
data.baseMappingContexts.resize(quadraturePointCount);
|
||||
data.baseMappingContexts.SetSize(quadraturePointCount, m_fem.mesh->Dimension());
|
||||
|
||||
data.physicalTestGradients.resize(quadraturePointCount);
|
||||
|
||||
@@ -650,9 +631,7 @@ namespace mean_field::operators {
|
||||
|
||||
transformation->SetIntPoint(&integrationPoint);
|
||||
|
||||
mapping::VolumeMappingContext &mappingContext = data.baseMappingContexts[quadraturePoint];
|
||||
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolume(
|
||||
const mapping::MappingStatus mappingStatus = m_domainMapper.EvaluateVolume(
|
||||
mappingData, *transformation, integrationPoint, workspace, mappingContext
|
||||
);
|
||||
|
||||
@@ -669,11 +648,13 @@ namespace mean_field::operators {
|
||||
return mapping_rejection(mapping::MappingStatus::non_positive_determinant);
|
||||
}
|
||||
|
||||
data.quadratureWeights(quadraturePoint) = quadratureWeight;
|
||||
data.baseMappingContexts.Store(quadraturePoint, mappingContext);
|
||||
data.quadratureWeights(quadraturePoint) = quadratureWeight;
|
||||
|
||||
const mfem::DenseMatrix &referenceTestGradient = data.referenceTestGradients[quadraturePoint];
|
||||
const mfem::DenseMatrix &referenceTestGradient =
|
||||
data.displacementReferenceTable->GetGradients(quadraturePoint);
|
||||
|
||||
mfem::DenseMatrix &physicalTestGradient = data.physicalTestGradients[quadraturePoint];
|
||||
mfem::DenseMatrix &physicalTestGradient = data.physicalTestGradients[quadraturePoint];
|
||||
|
||||
MFEM_VERIFY(
|
||||
referenceTestGradient.Width() == mappingContext.quadrature.J_inv.Height() &&
|
||||
@@ -714,9 +695,11 @@ namespace mean_field::operators {
|
||||
data.enthalpyDofTransformation->InvTransformPrimal(elementEnthalpy);
|
||||
}
|
||||
|
||||
const int quadraturePointCount = data.enthalpyBasis.Height();
|
||||
const mfem::DenseMatrix &enthalpyBasis = data.GetEnthalpyBasis();
|
||||
|
||||
const int enthalpyDofCount = data.enthalpyBasis.Width();
|
||||
const int quadraturePointCount = enthalpyBasis.Height();
|
||||
|
||||
const int enthalpyDofCount = enthalpyBasis.Width();
|
||||
|
||||
const mfem::FiniteElement &displacementElement = *m_fem.displacementFes->GetFE(data.elementId);
|
||||
|
||||
@@ -734,7 +717,7 @@ namespace mean_field::operators {
|
||||
|
||||
quadratureEnthalpy.SetSize(quadraturePointCount);
|
||||
|
||||
data.enthalpyBasis.Mult(elementEnthalpy, quadratureEnthalpy);
|
||||
enthalpyBasis.Mult(elementEnthalpy, quadratureEnthalpy);
|
||||
|
||||
data.pressure.SetSize(quadraturePointCount);
|
||||
|
||||
@@ -814,8 +797,8 @@ namespace mean_field::operators {
|
||||
data.elementResidual(vectorDof) -= residualContribution;
|
||||
|
||||
for (int enthalpyDof = 0; enthalpyDof < enthalpyDofCount; ++enthalpyDof) {
|
||||
const double jacobianContribution = pressureDerivative * weightedTestGradient *
|
||||
data.enthalpyBasis(quadraturePoint, enthalpyDof);
|
||||
const double jacobianContribution =
|
||||
pressureDerivative * weightedTestGradient * enthalpyBasis(quadraturePoint, enthalpyDof);
|
||||
if (!std::isfinite(jacobianContribution)) {
|
||||
materialFailure = non_finite_rejection();
|
||||
continue;
|
||||
@@ -841,8 +824,10 @@ namespace mean_field::operators {
|
||||
|
||||
MFEM_VERIFY(
|
||||
data.baseDisplacementData.has_value() && data.compactificationData.has_value() &&
|
||||
static_cast<int>(data.baseMappingContexts.size()) == quadraturePointCount &&
|
||||
static_cast<int>(data.referenceTestGradients.size()) == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetPointCount() == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetDimension() == dimension &&
|
||||
data.displacementReferenceTable != nullptr &&
|
||||
data.displacementReferenceTable->GetPointCount() == quadraturePointCount &&
|
||||
static_cast<int>(data.physicalTestGradients.size()) == quadraturePointCount &&
|
||||
data.quadratureWeights.Size() == quadraturePointCount &&
|
||||
data.pressure.Size() == quadraturePointCount,
|
||||
@@ -852,7 +837,7 @@ namespace mean_field::operators {
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
MFEM_VERIFY(
|
||||
data.referenceTestGradients[quadraturePoint].Width() == dimension &&
|
||||
data.displacementReferenceTable->GetGradients(quadraturePoint).Width() == dimension &&
|
||||
data.physicalTestGradients[quadraturePoint].Width() == dimension,
|
||||
"Prepared pressure-force displacement Jacobian has "
|
||||
"a gradient with the wrong dimension."
|
||||
@@ -978,6 +963,7 @@ namespace mean_field::operators {
|
||||
mfem::Vector elementAction;
|
||||
|
||||
mfem::DenseMatrix referenceDisplacementJacobian;
|
||||
mfem::DenseMatrix inverseElementJacobian;
|
||||
mfem::DenseMatrix inverseElementJacobianVariation;
|
||||
mfem::DenseMatrix matrixTemporary;
|
||||
mfem::DenseMatrix physicalTestGradientVariation;
|
||||
@@ -1016,7 +1002,7 @@ namespace mean_field::operators {
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
static_cast<int>(data.baseMappingContexts.size()) == quadraturePointCount &&
|
||||
data.baseMappingContexts.GetPointCount() == quadraturePointCount &&
|
||||
data.pressure.Size() == quadraturePointCount,
|
||||
"Prepared pressure-force displacement Jacobian has "
|
||||
"stale quadrature data."
|
||||
@@ -1032,12 +1018,12 @@ namespace mean_field::operators {
|
||||
physicalTestGradientVariation.SetSize(scalarDisplacementDofCount, dimension);
|
||||
|
||||
for (int quadraturePoint = 0; quadraturePoint < quadraturePointCount; ++quadraturePoint) {
|
||||
const mfem::DenseMatrix &referenceTestGradient = data.referenceTestGradients[quadraturePoint];
|
||||
const mfem::DenseMatrix &referenceTestGradient =
|
||||
data.displacementReferenceTable->GetGradients(quadraturePoint);
|
||||
|
||||
mfem::MultAtB(directionDofs, referenceTestGradient, referenceDisplacementJacobian);
|
||||
|
||||
const mfem::DenseMatrix &inverseElementJacobian =
|
||||
data.baseMappingContexts[quadraturePoint].quadrature.J_inv;
|
||||
data.baseMappingContexts.LoadInverseJacobian(quadraturePoint, inverseElementJacobian);
|
||||
mfem::Mult(inverseElementJacobian, referenceDisplacementJacobian, matrixTemporary);
|
||||
|
||||
double logarithmicJacobianVariation{0.0};
|
||||
|
||||
@@ -1068,6 +1068,29 @@ namespace mean_field::operators {
|
||||
return m_generatedVolumeDisplacement;
|
||||
}
|
||||
|
||||
void PreparedStellarEquilibriumOperator::BuildVolumeDisplacementDirection(
|
||||
const mfem::Vector &surfaceDeformationDirection,
|
||||
mfem::Vector &volumeDisplacementDirection
|
||||
) const {
|
||||
VerifyPrepared();
|
||||
MFEM_VERIFY(
|
||||
surfaceDeformationDirection.Size() == m_domainDeformation.parameterCount(),
|
||||
"PreparedStellarEquilibriumOperator received a surface-deformation direction with the wrong size."
|
||||
);
|
||||
validate_finite_vector(
|
||||
surfaceDeformationDirection,
|
||||
"PreparedStellarEquilibriumOperator received a non-finite surface-deformation direction."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
volumeDisplacementDirection.Size() == m_domainDeformation.volumeDisplacementSize(),
|
||||
"PreparedStellarEquilibriumOperator received a volume-displacement workspace with the wrong size."
|
||||
);
|
||||
|
||||
m_domainDeformation.applyJacobian(
|
||||
m_surfaceDeformationParameters, surfaceDeformationDirection, volumeDisplacementDirection
|
||||
);
|
||||
}
|
||||
|
||||
const mfem::Vector &PreparedStellarEquilibriumOperator::GetFullMechanicalResidual() const {
|
||||
VerifyPrepared();
|
||||
return m_fullMechanicalResidual;
|
||||
|
||||
Reference in New Issue
Block a user