feat(libmeanfield): centrifugal + pressure

This commit is contained in:
2026-08-04 14:24:55 -04:00
parent 9bc4f2758a
commit dc912fd15e
115 changed files with 260058 additions and 163261 deletions

View File

@@ -25,4 +25,4 @@ export namespace mean_field::integrators {
private:
const mapping::DomainMapper &m_map;
};
}
} // namespace mean_field::integrators

View File

@@ -1,14 +1,19 @@
module;
#include <mfem.hpp>
export module mean_field:integrators.centrifugal;
import :mapping.domain_mapper;
export import :mapping.domain_mapper;
export namespace mean_field::integrators {
class CentrifugalForceIntegrator : public mfem::BlockNonlinearFormIntegrator {
class CentrifugalForceIntegrator
: public mfem::BlockNonlinearFormIntegrator {
public:
CentrifugalForceIntegrator(const mapping::DomainMapper& map, const mfem::Vector& omega);
CentrifugalForceIntegrator(
const mapping::DomainMapper &map,
const mfem::Vector &omega
);
void SetOmega(const mfem::Vector& omega);
void SetOmega(const mfem::Vector &omega);
void SetIntegrationRule(const mfem::IntegrationRule &ir);
void AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
@@ -25,8 +30,9 @@ export namespace mean_field::integrators {
) override;
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
mfem::Vector m_omega;
const mfem::IntegrationRule *m_ir = nullptr;
};
}
} // namespace mean_field::integrators

View File

@@ -3,26 +3,32 @@ module;
export module mean_field:integrators.coriolis;
import :mapping.domain_mapper;
export namespace mean_field::integrators {
class CoriolisIntegrator : public mfem::BlockNonlinearFormIntegrator {
public:
CoriolisIntegrator(const mapping::DomainMapper& map, const mfem::Vector& omega);
CoriolisIntegrator(
const mapping::DomainMapper &map,
const mfem::Vector &omega
);
void AssembleElementVector(const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec) override;
void AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec
) override;
void AssembleElementGrad(const mfem::Array<const mfem::FiniteElement*> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats) override;
void AssembleElementGrad(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
mfem::Vector m_omega;
mfem::DenseMatrix m_omega_mat;
};
}
} // namespace mean_field::integrators

View File

@@ -1,14 +1,29 @@
module;
#include <cstdint>
#include <mfem.hpp>
export module mean_field:integrators.gravity;
import :mapping.domain_mapper;
export namespace mean_field::integrators {
class GravityForceIntegrator : public mfem::BlockNonlinearFormIntegrator {
public:
GravityForceIntegrator(const mapping::DomainMapper& map, const mfem::GridFunction& phi);
enum class GravityForceJacobianMode : std::uint8_t {
minimal,
field_coupled,
exact
};
void SetPotential(const mfem::GridFunction& phi);
class GravityMomentumIntegrator
: public mfem::BlockNonlinearFormIntegrator {
public:
explicit GravityMomentumIntegrator(
const mapping::DomainMapper &map,
GravityForceJacobianMode jacobian_mode =
GravityForceJacobianMode::field_coupled
);
void SetJacobianMode(GravityForceJacobianMode jacobian_mode);
void SetIntegrationRule(const mfem::IntegrationRule &integration_rule);
[[nodiscard]] GravityForceJacobianMode GetJacobianMode() const;
void AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
@@ -16,7 +31,6 @@ export namespace mean_field::integrators {
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec
) override;
void AssembleElementGrad(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
@@ -24,9 +38,9 @@ export namespace mean_field::integrators {
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
private:
const mapping::DomainMapper& m_map;
const mfem::GridFunction* m_phi;
const mapping::DomainMapper &m_map;
GravityForceJacobianMode m_jacobian_mode;
const mfem::IntegrationRule *m_integration_rule{nullptr};
};
}
} // namespace mean_field::integrators

View File

@@ -4,9 +4,10 @@ export module mean_field:integrators.mass_continuity;
import :mapping.domain_mapper;
export namespace mean_field::integrators {
class ContinuityVolumeIntegrator : public mfem::BlockNonlinearFormIntegrator {
class ContinuityVolumeIntegrator
: public mfem::BlockNonlinearFormIntegrator {
public:
explicit ContinuityVolumeIntegrator(const mapping::DomainMapper& map);
explicit ContinuityVolumeIntegrator(const mapping::DomainMapper &map);
void AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
@@ -21,13 +22,14 @@ export namespace mean_field::integrators {
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
};
class ContinuityFaceIntegrator : public mfem::BlockNonlinearFormIntegrator {
public:
explicit ContinuityFaceIntegrator(const mapping::DomainMapper& map);
explicit ContinuityFaceIntegrator(const mapping::DomainMapper &map);
void AssembleFaceVector(
const mfem::Array<const mfem::FiniteElement *> &el1,
@@ -44,19 +46,20 @@ export namespace mean_field::integrators {
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
private:
static bool skip_face(const mfem::FaceElementTransformations& Tr);
static bool skip_face(const mfem::FaceElementTransformations &Tr);
static double compute_u_n(
const mfem::Vector& v_dofs,
const mfem::Vector& shape_v_minus,
const mfem::Vector& n_unit,
const mfem::Vector &v_dofs,
const mfem::Vector &shape_v_minus,
const mfem::Vector &n_unit,
int dof_v_minus,
int dim
);
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
};
}
} // namespace mean_field::integrators

View File

@@ -1,36 +1,47 @@
module;
#include <mfem.hpp>
#include "xad_promote_polyfill.h"
#include <XAD/XAD.hpp>
#include <mfem.hpp>
export module mean_field:integrators.pressure_gradient;
import :mapping.domain_mapper;
import :utils.misc;
export namespace mean_field::integrators {
template <utils::is_xad EOS_T>
class PressureGradientIntegrator : public mfem::BlockNonlinearFormIntegrator {
class PressureGradientIntegrator
: public mfem::BlockNonlinearFormIntegrator {
public:
PressureGradientIntegrator(const mapping::DomainMapper& map, utils::EOS_P<EOS_T> eos);
PressureGradientIntegrator(
const mapping::DomainMapper &map,
utils::EOS_P<EOS_T> eos
);
void AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec
) override;
void AssembleElementGrad(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
void AssembleElementVector(const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec) override;
void AssembleElementGrad(const mfem::Array<const mfem::FiniteElement*> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats) override;
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
utils::EOS_P<EOS_T> m_eos;
};
template <utils::is_xad EOS_T>
PressureGradientIntegrator<EOS_T>::PressureGradientIntegrator(
const mapping::DomainMapper& map,
const mapping::DomainMapper &map,
utils::EOS_P<EOS_T> eos
) : m_map(map), m_eos(std::move(eos)) {}
)
: m_map(map),
m_eos(std::move(eos)) {
}
template <utils::is_xad EOS_T>
void PressureGradientIntegrator<EOS_T>::AssembleElementVector(
@@ -43,16 +54,16 @@ export namespace mean_field::integrators {
return;
}
const mfem::FiniteElement* fe_v = el[0];
const mfem::FiniteElement* fe_rho = el[1];
const mfem::FiniteElement *fe_v = el[0];
const mfem::FiniteElement *fe_rho = el[1];
const int dof_v = fe_v->GetDof();
const int dof_rho = fe_rho->GetDof();
const int dim = Tr.GetSpaceDim();
const int dof_v = fe_v->GetDof();
const int dof_rho = fe_rho->GetDof();
const int dim = Tr.GetSpaceDim();
const mfem::Vector& rho_dofs = *elfun[1];
const mfem::Vector &rho_dofs = *elfun[1];
mfem::Vector& r_v = *elvec[0];
mfem::Vector &r_v = *elvec[0];
r_v.SetSize(dof_v * dim);
r_v = 0.0;
if (elvec[1]) {
@@ -63,10 +74,11 @@ export namespace mean_field::integrators {
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
mfem::Vector shape_rho(dof_rho);
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
const mfem::IntegrationRule *ir =
&mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
for (int q = 0; q < ir->GetNPoints(); ++q) {
const mfem::IntegrationPoint& ip = ir->IntPoint(q);
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetIntPoint(&ip);
auto [J_inv, detJ, weight] = m_map.GetQuadratureContext(Tr, ip);
@@ -76,13 +88,15 @@ export namespace mean_field::integrators {
fe_rho->CalcShape(ip, shape_rho);
double rho_val = 0.0;
for (int i = 0; i < dof_rho; ++i) rho_val += rho_dofs(i) * shape_rho(i);
for (int i = 0; i < dof_rho; ++i)
rho_val += rho_dofs(i) * shape_rho(i);
// Guard against negative density from Newton solver overshoots
if (rho_val < 1e-15) rho_val = 1e-15;
if (rho_val < 1e-15)
rho_val = 1e-15;
// Evaluate the exact Equation of State Pressure
EOS_T x_rho = rho_val;
EOS_T x_rho = rho_val;
double P_val = m_eos(x_rho, EOS_T(0.0)).value();
for (int i = 0; i < dof_v; ++i) {
@@ -95,36 +109,40 @@ export namespace mean_field::integrators {
template <utils::is_xad EOS_T>
void PressureGradientIntegrator<EOS_T>::AssembleElementGrad(
const mfem::Array<const mfem::FiniteElement*> &el,
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) {
const mfem::FiniteElement* fe_v = el[0];
const mfem::FiniteElement* fe_rho = el[1];
const mfem::FiniteElement *fe_v = el[0];
const mfem::FiniteElement *fe_rho = el[1];
const int dof_v = fe_v->GetDof();
const int dof_rho = fe_rho->GetDof();
const int dim = Tr.GetSpaceDim();
const int dof_v = fe_v->GetDof();
const int dof_rho = fe_rho->GetDof();
const int dim = Tr.GetSpaceDim();
const mfem::Vector& rho_dofs = *elfun[1];
const mfem::Vector &rho_dofs = *elfun[1];
mfem::DenseMatrix* dv_dv = elmats(0, 0);
mfem::DenseMatrix* dv_drho = elmats(0, 1);
mfem::DenseMatrix *dv_dv = elmats(0, 0);
mfem::DenseMatrix *dv_drho = elmats(0, 1);
if (dv_dv) *dv_dv = 0.0;
if (dv_drho) *dv_drho = 0.0;
if (!dv_drho) return;
if (dv_dv)
*dv_dv = 0.0;
if (dv_drho)
*dv_drho = 0.0;
if (!dv_drho)
return;
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
mfem::Vector shape_rho(dof_rho);
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
const mfem::IntegrationRule *ir =
&mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
for (int q = 0; q < ir->GetNPoints(); ++q) {
using Scalar = EOS_T::value_type;
xad::Tape<Scalar> tape;
const mfem::IntegrationPoint& ip = ir->IntPoint(q);
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetIntPoint(&ip);
auto [J_inv, detJ, weight] = m_map.GetQuadratureContext(Tr, ip);
@@ -140,29 +158,32 @@ export namespace mean_field::integrators {
for (int i = 0; i < dof_rho; ++i) {
x_rho += rho_dofs(i) * shape_rho(i);
}
if (x_rho < 1e-15) x_rho = EOS_T(1e-15);
if (x_rho < 1e-15)
x_rho = EOS_T(1e-15);
EOS_T x_P = m_eos(x_rho, EOS_T(0.0));
tape.registerOutput(x_P);
x_P.setAdjoint(1.0);
tape.computeAdjoints();
double dP_drho = x_rho.getAdjoint();
double dP_drho = x_rho.getAdjoint();
double debug_K = 1.5;
double debug_n = 3.0;
double analytic_dp = debug_K * (1.0 + 1.0 / debug_n) * std::pow(xad::value(x_rho), 1.0 / debug_n);
double debug_K = 1.5;
double debug_n = 3.0;
double analytic_dp = debug_K * (1.0 + 1.0 / debug_n) *
std::pow(xad::value(x_rho), 1.0 / debug_n);
double ad_err = std::abs(dP_drho - analytic_dp);
double ad_err = std::abs(dP_drho - analytic_dp);
for (int i = 0; i < dof_v; ++i) {
for (int c = 0; c < dim; ++c) {
int row = i + c * dof_v;
for (int j = 0; j < dof_rho; ++j) {
int col = j;
double term = dshape_v_phys(i, c) * dP_drho * shape_rho(j);
double term =
dshape_v_phys(i, c) * dP_drho * shape_rho(j);
(*dv_drho)(row, col) -= term * weight;
}
}
}
}
}
}
} // namespace mean_field::integrators

View File

@@ -4,9 +4,13 @@ export module mean_field:integrators.viscosity;
import :mapping.domain_mapper;
export namespace mean_field::integrators {
class ViscosityIntegrator : public mfem::BlockNonlinearFormIntegrator {
class ViscosityIntegrator : public mfem::BlockNonlinearFormIntegrator {
public:
ViscosityIntegrator(const mapping::DomainMapper& map, double mu, int quad_boost);
ViscosityIntegrator(
const mapping::DomainMapper &map,
double mu,
int quad_boost
);
void SetMu(const double mu);
@@ -23,10 +27,11 @@ export namespace mean_field::integrators {
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) override;
private:
const mapping::DomainMapper& m_map;
const mapping::DomainMapper &m_map;
double m_mu;
int m_quad_boost;
};
}
} // namespace mean_field::integrators