feat(libmeanfield): centrifugal + pressure
This commit is contained in:
@@ -25,4 +25,4 @@ export namespace mean_field::integrators {
|
||||
private:
|
||||
const mapping::DomainMapper &m_map;
|
||||
};
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user