Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -9,6 +9,7 @@ module;
|
||||
#include <utility>
|
||||
|
||||
#include <mpi.h>
|
||||
#include "interior_displacement_contractions.hpp"
|
||||
|
||||
module mean_field;
|
||||
|
||||
@@ -321,6 +322,7 @@ namespace mean_field::operators {
|
||||
const bool updateTargetMass = !m_isPrepared || dependencies.targetMass != m_preparedDependencies.targetMass ||
|
||||
state.targetMass != m_targetMass;
|
||||
|
||||
if (refreshGeometry || refreshDensity) m_jacobianRowsReady = false;
|
||||
m_isPrepared = false;
|
||||
|
||||
PreparedMassNormalizationReport report;
|
||||
@@ -603,7 +605,83 @@ namespace mean_field::operators {
|
||||
++m_residualApplicationCount;
|
||||
}
|
||||
|
||||
double PreparedMassNormalizationOperator::EvaluateDensityActionLocal(const mfem::Vector &densityVariation) const {
|
||||
bool PreparedMassNormalizationOperator::PrepareJacobianRows() const {
|
||||
VerifyPrepared();
|
||||
if (m_jacobianRowsReady) return m_jacobianRowsSupported;
|
||||
m_jacobianRowsSupported = false;
|
||||
const int dimension = m_fem.mesh->Dimension();
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
const auto &element = *m_fem.displacementFes->GetFE(data.elementId);
|
||||
if (dimension < 1 || dimension > 3 || 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;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
constexpr double zeroPosition[3]{0.0, 0.0, 0.0};
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
densityRow.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis->GetValues().MultTranspose(data.quadratureWeights, 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 < data.integrationRule->GetNPoints(); ++q) {
|
||||
data.mappingContexts.Load(q, mappingContext);
|
||||
add_interior_functional_row(
|
||||
basis->GetGradients(q), basis->GetValues(), q, mappingContext.quadrature.J_inv,
|
||||
data.density(q) * data.quadratureWeights(q), zeroPosition, 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);
|
||||
}
|
||||
validate_finite_vector(m_densityJacobianLocal, "Prepared mass density row is non-finite.");
|
||||
validate_finite_vector(m_displacementJacobianLocal, "Prepared mass displacement row is non-finite.");
|
||||
m_jacobianRowsSupported = true;
|
||||
m_jacobianRowsReady = true;
|
||||
++m_jacobianRowPreparationCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint64_t PreparedMassNormalizationOperator::GetJacobianRowPreparationCount() const noexcept {
|
||||
return m_jacobianRowPreparationCount;
|
||||
}
|
||||
|
||||
double PreparedMassNormalizationOperator::EvaluateDensityActionLocal(const mfem::Vector &direction) const {
|
||||
if (!PrepareJacobianRows()) return EvaluateDensityActionLocalReference(direction);
|
||||
true_to_local(*m_fem.densityFes, direction, m_densityVariationLocal);
|
||||
return m_densityJacobianLocal * m_densityVariationLocal;
|
||||
}
|
||||
|
||||
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocal(const mfem::Vector &direction) const {
|
||||
if (!PrepareJacobianRows()) return EvaluateDisplacementActionLocalReference(direction);
|
||||
true_to_local(*m_fem.displacementFes, direction, m_displacementVariationLocal);
|
||||
return m_displacementJacobianLocal * m_displacementVariationLocal;
|
||||
}
|
||||
|
||||
void PreparedMassNormalizationOperator::ApplyCompleteJacobianActionReference(
|
||||
const mfem::Vector &densityVariation, const mfem::Vector &displacementVariation, mfem::Vector &action
|
||||
) const {
|
||||
VerifyPrepared();
|
||||
validate_finite_vector(densityVariation, "Mass-normalization density direction is non-finite.");
|
||||
validate_finite_vector(displacementVariation, "Mass-normalization displacement direction is non-finite.");
|
||||
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
|
||||
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
|
||||
action.SetSize(1);
|
||||
action(0) = GlobalSum(EvaluateDensityActionLocalReference(m_densityVariationTrue) +
|
||||
EvaluateDisplacementActionLocalReference(m_displacementVariationTrue));
|
||||
}
|
||||
|
||||
double PreparedMassNormalizationOperator::EvaluateDensityActionLocalReference(const mfem::Vector &densityVariation) const {
|
||||
MFEM_VERIFY(
|
||||
densityVariation.Size() == m_fem.densityFes->GetTrueVSize(),
|
||||
"Mass-normalization density action received a vector with the "
|
||||
@@ -635,7 +713,7 @@ namespace mean_field::operators {
|
||||
return localAction;
|
||||
}
|
||||
|
||||
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocal(
|
||||
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocalReference(
|
||||
const mfem::Vector &displacementVariation
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
@@ -898,8 +976,18 @@ namespace mean_field::operators {
|
||||
VerifyPrepared();
|
||||
MFEM_VERIFY(std::isfinite(residualDual), "Mass-normalization transpose action received a non-finite dual.");
|
||||
|
||||
AssembleDensityTransposeAction(residualDual, densityDual);
|
||||
AssembleDisplacementTransposeAction(residualDual, displacementDual);
|
||||
if (PrepareJacobianRows()) {
|
||||
mfem::Vector trueDual;
|
||||
local_to_true(*m_fem.densityFes, m_densityJacobianLocal, trueDual);
|
||||
densityDual = m_gravityContext.GetDensityMap().gather(trueDual);
|
||||
densityDual *= residualDual;
|
||||
local_to_true(*m_fem.displacementFes, m_displacementJacobianLocal, trueDual);
|
||||
displacementDual = m_gravityContext.GetDisplacementMap().gather(trueDual);
|
||||
displacementDual *= residualDual;
|
||||
} else {
|
||||
AssembleDensityTransposeAction(residualDual, densityDual);
|
||||
AssembleDisplacementTransposeAction(residualDual, displacementDual);
|
||||
}
|
||||
++m_actionStatistics.transposeApplications;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user