perf(jacobian-action): major updates to jacobian action application by removing redudant quadrature work. ~5x increase in speed
This commit is contained in:
@@ -287,7 +287,6 @@ namespace mean_field::operators {
|
||||
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
|
||||
mfem::Array<int> displacementDofs;
|
||||
mfem::Array<int> compactificationDofs;
|
||||
|
||||
mfem::Vector elementBaseDensity;
|
||||
@@ -311,18 +310,19 @@ namespace mean_field::operators {
|
||||
|
||||
m_elements.emplace_back();
|
||||
ElementPAData &data = m_elements.back();
|
||||
data.elementId = elementId;
|
||||
|
||||
data.densityDofTransformation = m_fem.densityFes->GetElementDofs(elementId, data.densityDofs);
|
||||
data.enthalpyDofTransformation = m_fem.enthalpyFes->GetElementDofs(elementId, data.enthalpyDofs);
|
||||
|
||||
mfem::DofTransformation *displacementDofTransformation =
|
||||
m_fem.displacementFes->GetElementVDofs(elementId, displacementDofs);
|
||||
data.displacementDofTransformation =
|
||||
m_fem.displacementFes->GetElementVDofs(elementId, data.displacementDofs);
|
||||
mfem::DofTransformation *compactificationDofTransformation =
|
||||
m_fem.compactificationFes->GetElementDofs(elementId, compactificationDofs);
|
||||
|
||||
baseDensityLocal.GetSubVector(data.densityDofs, elementBaseDensity);
|
||||
baseEnthalpyLocal.GetSubVector(data.enthalpyDofs, elementBaseEnthalpy);
|
||||
displacementLocal.GetSubVector(displacementDofs, elementDisplacement);
|
||||
displacementLocal.GetSubVector(data.displacementDofs, elementDisplacement);
|
||||
m_fem.compactificationCoordinate->GetSubVector(compactificationDofs, elementCompactification);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
@@ -331,8 +331,8 @@ namespace mean_field::operators {
|
||||
if (data.enthalpyDofTransformation != nullptr) {
|
||||
data.enthalpyDofTransformation->InvTransformPrimal(elementBaseEnthalpy);
|
||||
}
|
||||
if (displacementDofTransformation != nullptr) {
|
||||
displacementDofTransformation->InvTransformPrimal(elementDisplacement);
|
||||
if (data.displacementDofTransformation != nullptr) {
|
||||
data.displacementDofTransformation->InvTransformPrimal(elementDisplacement);
|
||||
}
|
||||
if (compactificationDofTransformation != nullptr) {
|
||||
compactificationDofTransformation->InvTransformPrimal(elementCompactification);
|
||||
@@ -363,6 +363,9 @@ namespace mean_field::operators {
|
||||
|
||||
data.densityBasis.SetSize(quadraturePointCount, densityDofCount);
|
||||
data.enthalpyBasis.SetSize(quadraturePointCount, enthalpyDofCount);
|
||||
data.inverseElementJacobians.SetSize(
|
||||
quadraturePointCount, m_fem.mesh->Dimension() * m_fem.mesh->Dimension()
|
||||
);
|
||||
data.weightedResidual.SetSize(quadraturePointCount);
|
||||
data.quadratureWeights.SetSize(quadraturePointCount);
|
||||
data.weightedEnthalpyDerivative.SetSize(quadraturePointCount);
|
||||
@@ -388,6 +391,18 @@ namespace mean_field::operators {
|
||||
<< ", quadrature point: " << quadraturePoint << ", status: " << static_cast<int>(mappingStatus)
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
!mappingContext.mapping.compactified,
|
||||
"Prepared barotropic closure support unexpectedly includes a compactified element."
|
||||
);
|
||||
|
||||
for (int row = 0; row < m_fem.mesh->Dimension(); ++row) {
|
||||
for (int column = 0; column < m_fem.mesh->Dimension(); ++column) {
|
||||
data.inverseElementJacobians(quadraturePoint, row * m_fem.mesh->Dimension() + column) =
|
||||
mappingContext.quadrature.J_inv(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
densityElement.CalcShape(integrationPoint, densityShape);
|
||||
enthalpyElement.CalcShape(integrationPoint, enthalpyShape);
|
||||
|
||||
@@ -401,7 +416,7 @@ namespace mean_field::operators {
|
||||
const double density = elementBaseDensity * densityShape;
|
||||
const double enthalpy = elementBaseEnthalpy * enthalpyShape;
|
||||
const double quadratureWeight = mappingContext.quadrature.weight;
|
||||
const eos::SpecificEnthalpyValue specificEnthalpy{enthalpy};
|
||||
const dimensions::SpecificEnthalpyValue specificEnthalpy{enthalpy};
|
||||
const double eosDensity =
|
||||
eos::evaluate<eos::quantity::Density>(m_equationOfState, specificEnthalpy).value();
|
||||
const double enthalpyDerivative =
|
||||
@@ -485,10 +500,7 @@ namespace mean_field::operators {
|
||||
|
||||
ApplyThermodynamicActionFull(m_densityVariationTrue, m_enthalpyVariationTrue, m_fullThermodynamicAction);
|
||||
|
||||
kernels::apply_barotropic_closure_displacement_action(
|
||||
m_fem, m_domainMapper, m_equationOfState, m_baseDensityTrue, m_baseEnthalpyTrue, m_baseDisplacementTrue,
|
||||
m_displacementVariationTrue, m_fullDisplacementAction
|
||||
);
|
||||
ApplyDisplacementActionFull(m_displacementVariationTrue, m_fullDisplacementAction);
|
||||
|
||||
MFEM_VERIFY(
|
||||
m_fullThermodynamicAction.Size() == m_densityMap.full_size() &&
|
||||
@@ -589,6 +601,86 @@ namespace mean_field::operators {
|
||||
local_to_true(*m_fem.densityFes, localAction, actionTrue);
|
||||
}
|
||||
|
||||
void PreparedBarotropicClosureOperator::ApplyDisplacementActionFull(
|
||||
const mfem::Vector &displacementVariationTrue,
|
||||
mfem::Vector &actionTrue
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
displacementVariationTrue.Size() == m_displacementMap.full_size(),
|
||||
"The full displacement variation has the wrong size."
|
||||
);
|
||||
|
||||
true_to_local(*m_fem.displacementFes, displacementVariationTrue, m_displacementVariationLocal);
|
||||
|
||||
m_localDisplacementAction.SetSize(m_fem.densityFes->GetVSize());
|
||||
m_localDisplacementAction = 0.0;
|
||||
|
||||
const int dimension = m_fem.mesh->Dimension();
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
m_displacementVariationLocal.GetSubVector(data.displacementDofs, m_elementDisplacementVariation);
|
||||
if (data.displacementDofTransformation != nullptr) {
|
||||
data.displacementDofTransformation->InvTransformPrimal(m_elementDisplacementVariation);
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &displacementElement = *m_fem.displacementFes->GetFE(data.elementId);
|
||||
const mapping::ElementDisplacementData directionData =
|
||||
mapping::ElementDisplacementDataFromElementVDofs(displacementElement, m_elementDisplacementVariation);
|
||||
const mfem::DenseMatrix &directionDofs = directionData.GetDofMatrix();
|
||||
mfem::ElementTransformation *transformation = m_fem.mesh->GetElementTransformation(data.elementId);
|
||||
MFEM_VERIFY(
|
||||
transformation != nullptr,
|
||||
"Prepared barotropic closure displacement action received a null element transformation."
|
||||
);
|
||||
const mfem::FiniteElement &densityElement = *m_fem.densityFes->GetFE(data.elementId);
|
||||
const mfem::FiniteElement &enthalpyElement = *m_fem.enthalpyFes->GetFE(data.elementId);
|
||||
const mfem::IntegrationRule &integrationRule =
|
||||
get_eos_rule(m_fem, m_equationOfState, densityElement, enthalpyElement, *transformation);
|
||||
|
||||
MFEM_VERIFY(
|
||||
data.inverseElementJacobians.Height() == integrationRule.GetNPoints() &&
|
||||
data.inverseElementJacobians.Width() == dimension * dimension,
|
||||
"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);
|
||||
|
||||
double logarithmicJacobianVariation{0.0};
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
logarithmicJacobianVariation +=
|
||||
data.inverseElementJacobians(quadraturePoint, row * dimension + column) *
|
||||
m_referenceDisplacementJacobian(column, row);
|
||||
}
|
||||
}
|
||||
|
||||
m_quadratureDisplacementAction(quadraturePoint) =
|
||||
data.weightedResidual(quadraturePoint) * logarithmicJacobianVariation;
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(m_quadratureDisplacementAction(quadraturePoint)),
|
||||
"Prepared barotropic closure displacement action encountered a non-finite quadrature value."
|
||||
);
|
||||
}
|
||||
|
||||
m_elementDisplacementAction.SetSize(data.densityDofs.Size());
|
||||
data.densityBasis.MultTranspose(m_quadratureDisplacementAction, m_elementDisplacementAction);
|
||||
|
||||
if (data.densityDofTransformation != nullptr) {
|
||||
data.densityDofTransformation->TransformDual(m_elementDisplacementAction);
|
||||
}
|
||||
m_localDisplacementAction.AddElementVector(data.densityDofs, m_elementDisplacementAction);
|
||||
}
|
||||
|
||||
local_to_true(*m_fem.densityFes, m_localDisplacementAction, actionTrue);
|
||||
}
|
||||
|
||||
bool PreparedBarotropicClosureOperator::IsPrepared() const noexcept {
|
||||
return m_isPrepared && m_context.IsPrepared();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user