Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -11,6 +11,7 @@ module;
|
||||
|
||||
#include <mfem.hpp>
|
||||
#include <mpi.h>
|
||||
#include "interior_displacement_contractions.hpp"
|
||||
|
||||
module mean_field;
|
||||
|
||||
@@ -228,6 +229,7 @@ namespace mean_field::operators {
|
||||
const bool updateAngularVelocity = !m_isPrepared || dependencies.rotation != m_preparedDependencies.rotation ||
|
||||
angularVelocity != m_angularVelocity;
|
||||
|
||||
if (refreshGeometry || refreshDensity) m_jacobianRowsReady = false;
|
||||
m_isPrepared = false;
|
||||
if (synchronize_non_finite_failure(
|
||||
!std::isfinite(angularVelocity), m_fem.mesh->GetComm(), "angular-velocity validity"
|
||||
@@ -466,8 +468,99 @@ namespace mean_field::operators {
|
||||
++m_residualApplicationCount;
|
||||
}
|
||||
|
||||
bool PreparedAngularMomentumOperator::PrepareJacobianRows() const {
|
||||
VerifyPrepared();
|
||||
if (m_jacobianRowsReady) return m_jacobianRowsSupported;
|
||||
m_jacobianRowsSupported = false;
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
const auto &element = *m_fem.displacementFes->GetFE(data.elementId);
|
||||
if (element.GetMapType() != mfem::FiniteElement::VALUE ||
|
||||
element.GetDerivType() != mfem::FiniteElement::GRAD ||
|
||||
m_domainMapper.IsCompactifiedElement(*m_fem.mesh->GetElementTransformation(data.elementId))) {
|
||||
m_jacobianRowsReady = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_densityJacobianLocal.SetSize(m_fem.densityFes->GetVSize());
|
||||
m_displacementJacobianLocal.SetSize(m_fem.displacementFes->GetVSize());
|
||||
m_densityJacobianLocal = 0.0;
|
||||
m_displacementJacobianLocal = 0.0;
|
||||
mfem::Vector densityRow, displacementRow, weightedRadius;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
const auto &axis = m_constraint.specification().axis();
|
||||
const auto ¢er = m_constraint.specification().center();
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
const int nq = data.integrationRule->GetNPoints();
|
||||
weightedRadius.SetSize(nq);
|
||||
for (int q = 0; q < nq; ++q)
|
||||
weightedRadius(q) = data.quadratureWeights(q) * data.cylindricalRadiusSquared(q);
|
||||
densityRow.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis->GetValues().MultTranspose(weightedRadius, densityRow);
|
||||
displacementRow.SetSize(data.displacementDofs.Size());
|
||||
displacementRow = 0.0;
|
||||
const auto basis = m_fem.GetReferenceTables().GetScalarTable(
|
||||
*m_fem.displacementFes->GetFE(data.elementId), *data.integrationRule);
|
||||
for (int q = 0; q < nq; ++q) {
|
||||
data.mappingContexts.Load(q, mappingContext);
|
||||
double relative[3], positionCoefficient[3], axialPosition = 0.0;
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
relative[c] = mappingContext.mapping.physical_position(c) - center[c];
|
||||
axialPosition += axis[c] * relative[c];
|
||||
}
|
||||
for (int c = 0; c < 3; ++c)
|
||||
positionCoefficient[c] = 2.0 * data.density(q) * data.quadratureWeights(q) *
|
||||
(relative[c] - axis[c] * axialPosition);
|
||||
add_interior_functional_row(
|
||||
basis->GetGradients(q), basis->GetValues(), q, mappingContext.quadrature.J_inv,
|
||||
data.density(q) * weightedRadius(q), positionCoefficient, displacementRow);
|
||||
}
|
||||
if (data.densityDofTransformation) data.densityDofTransformation->TransformDual(densityRow);
|
||||
if (data.displacementDofTransformation) data.displacementDofTransformation->TransformDual(displacementRow);
|
||||
m_densityJacobianLocal.AddElementVector(data.densityDofs, densityRow);
|
||||
m_displacementJacobianLocal.AddElementVector(data.displacementDofs, displacementRow);
|
||||
}
|
||||
verify_finite_vector(m_densityJacobianLocal, "Prepared angular-momentum density row is non-finite.");
|
||||
verify_finite_vector(m_displacementJacobianLocal, "Prepared angular-momentum displacement row is non-finite.");
|
||||
m_jacobianRowsSupported = true;
|
||||
m_jacobianRowsReady = true;
|
||||
++m_jacobianRowPreparationCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint64_t PreparedAngularMomentumOperator::GetJacobianRowPreparationCount() const noexcept {
|
||||
return m_jacobianRowPreparationCount;
|
||||
}
|
||||
|
||||
double PreparedAngularMomentumOperator::EvaluateDensityMomentActionLocal(const mfem::Vector &direction) const {
|
||||
if (!PrepareJacobianRows()) return EvaluateDensityMomentActionLocalReference(direction);
|
||||
true_to_local(*m_fem.densityFes, direction, m_densityVariationLocal);
|
||||
return m_densityJacobianLocal * m_densityVariationLocal;
|
||||
}
|
||||
|
||||
double PreparedAngularMomentumOperator::EvaluateDisplacementMomentActionLocal(const mfem::Vector &direction) const {
|
||||
if (!PrepareJacobianRows()) return EvaluateDisplacementMomentActionLocalReference(direction);
|
||||
true_to_local(*m_fem.displacementFes, direction, m_displacementVariationLocal);
|
||||
return m_displacementJacobianLocal * m_displacementVariationLocal;
|
||||
}
|
||||
|
||||
void PreparedAngularMomentumOperator::ApplyCompleteJacobianActionReference(
|
||||
const mfem::Vector &densityVariation, const mfem::Vector &displacementVariation,
|
||||
const double angularVelocityVariation, mfem::Vector &action
|
||||
) const {
|
||||
VerifyPrepared();
|
||||
verify_finite_vector(densityVariation, "Angular-momentum density direction is non-finite.");
|
||||
verify_finite_vector(displacementVariation, "Angular-momentum displacement direction is non-finite.");
|
||||
MFEM_VERIFY(std::isfinite(angularVelocityVariation), "Angular-velocity direction is non-finite.");
|
||||
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
|
||||
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
|
||||
action.SetSize(1);
|
||||
action(0) = m_angularVelocity * GlobalSum(EvaluateDensityMomentActionLocalReference(m_densityVariationTrue) +
|
||||
EvaluateDisplacementMomentActionLocalReference(m_displacementVariationTrue)) +
|
||||
m_momentOfInertia * angularVelocityVariation;
|
||||
}
|
||||
|
||||
double
|
||||
PreparedAngularMomentumOperator::EvaluateDensityMomentActionLocal(const mfem::Vector &densityVariation) const {
|
||||
PreparedAngularMomentumOperator::EvaluateDensityMomentActionLocalReference(const mfem::Vector &densityVariation) const {
|
||||
MFEM_VERIFY(
|
||||
densityVariation.Size() == m_fem.densityFes->GetTrueVSize(),
|
||||
"Angular-momentum density action has the wrong true-vector size."
|
||||
@@ -490,7 +583,7 @@ namespace mean_field::operators {
|
||||
return localAction;
|
||||
}
|
||||
|
||||
double PreparedAngularMomentumOperator::EvaluateDisplacementMomentActionLocal(
|
||||
double PreparedAngularMomentumOperator::EvaluateDisplacementMomentActionLocalReference(
|
||||
const mfem::Vector &displacementVariation
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
|
||||
Reference in New Issue
Block a user