feat(libmeanfield): centrifugal + pressure
This commit is contained in:
@@ -4,7 +4,9 @@ module;
|
||||
module mean_field;
|
||||
|
||||
namespace mean_field::integrators {
|
||||
AdvectionIntegrator::AdvectionIntegrator(const mapping::DomainMapper &map) : m_map(map) {}
|
||||
AdvectionIntegrator::AdvectionIntegrator(const mapping::DomainMapper &map)
|
||||
: m_map(map) {
|
||||
}
|
||||
|
||||
void AdvectionIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
@@ -16,17 +18,17 @@ namespace mean_field::integrators {
|
||||
return;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement *fe_v = el[0];
|
||||
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 &v_dofs = *elfun[0];
|
||||
const mfem::Vector &rho_dofs = *elfun[1];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
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]) {
|
||||
@@ -37,7 +39,8 @@ namespace mean_field::integrators {
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
|
||||
|
||||
const mfem::IntegrationRule *ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder() + 1);
|
||||
const mfem::IntegrationRule *ir =
|
||||
&mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder() + 1);
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); q++) {
|
||||
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
|
||||
@@ -80,7 +83,8 @@ namespace mean_field::integrators {
|
||||
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
r_v(i + c * dof_v) += shape_v(i) * rho_val * adv_val(c) * weight;
|
||||
r_v(i + c * dof_v) +=
|
||||
shape_v(i) * rho_val * adv_val(c) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,27 +95,30 @@ namespace mean_field::integrators {
|
||||
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_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 &v_dofs = *elfun[0];
|
||||
const mfem::Vector &rho_dofs = *elfun[1];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
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_dv)
|
||||
*dv_dv = 0.0;
|
||||
if (dv_drho)
|
||||
*dv_drho = 0.0;
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
|
||||
|
||||
const mfem::IntegrationRule *ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder() + 1);
|
||||
const mfem::IntegrationRule *ir =
|
||||
&mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder() + 1);
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); q++) {
|
||||
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
|
||||
@@ -164,22 +171,27 @@ namespace mean_field::integrators {
|
||||
double v_dot_grad_phi_j = 0.0;
|
||||
|
||||
for (int k = 0; k < dim; ++k) {
|
||||
v_dot_grad_phi_j += v_val(k) * dshape_v_phys(j, k);
|
||||
v_dot_grad_phi_j +=
|
||||
v_val(k) * dshape_v_phys(j, k);
|
||||
}
|
||||
|
||||
for (int d = 0; d < dim; ++d) {
|
||||
// Trial function component
|
||||
int col = j + d * dof_v;
|
||||
int col = j + d * dof_v;
|
||||
|
||||
// \rho (\delta \vec{v} \cdot \nabla \vec{v})
|
||||
// \delta v is along direction 'd' for the cth component of advection
|
||||
// \delta v is along direction 'd' for the cth
|
||||
// component of advection
|
||||
double termA = shape_v(j) * grad_v(c, d);
|
||||
|
||||
// \rho(\vec{v} \cdot \nabla \delta \vec{v})
|
||||
// Only non-zero when the advected component matches the test component
|
||||
double termB = (c == d) ? v_dot_grad_phi_j : 0.0;
|
||||
// Only non-zero when the advected component
|
||||
// matches the test component
|
||||
double termB =
|
||||
(c == d) ? v_dot_grad_phi_j : 0.0;
|
||||
|
||||
(*dv_dv)(row, col) += shape_v(i) * rho_val * (termA + termB) * weight;
|
||||
(*dv_dv)(row, col) += shape_v(i) * rho_val *
|
||||
(termA + termB) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +204,7 @@ namespace mean_field::integrators {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
int row = i + c * dof_v;
|
||||
for (int j = 0; j < dof_rho; ++j) {
|
||||
int col = j;
|
||||
int col = j;
|
||||
|
||||
// \delta \rho * (\vec{v} \cdot \nabla \vec{v})
|
||||
double term = shape_rho(j) * adv_val(c);
|
||||
@@ -203,4 +215,4 @@ namespace mean_field::integrators {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
@@ -3,41 +3,49 @@ module;
|
||||
module mean_field;
|
||||
|
||||
namespace mean_field::integrators {
|
||||
CentrifugalForceIntegrator::CentrifugalForceIntegrator(
|
||||
const mapping::DomainMapper& map,
|
||||
const mfem::Vector& omega
|
||||
) : m_map(map), m_omega(3) {
|
||||
MFEM_ASSERT(omega.Size() == 3, "Omega vector must be 3D");
|
||||
m_omega = omega;
|
||||
}
|
||||
|
||||
void CentrifugalForceIntegrator::SetOmega(const mfem::Vector& omega) {
|
||||
CentrifugalForceIntegrator::CentrifugalForceIntegrator(
|
||||
const mapping::DomainMapper &map,
|
||||
const mfem::Vector &omega
|
||||
)
|
||||
: m_map(map),
|
||||
m_omega(3) {
|
||||
MFEM_ASSERT(omega.Size() == 3, "Omega vector must be 3D");
|
||||
m_omega = omega;
|
||||
}
|
||||
|
||||
void CentrifugalForceIntegrator::SetOmega(const mfem::Vector &omega) {
|
||||
MFEM_ASSERT(omega.Size() == 3, "Omega vector must be 3D");
|
||||
m_omega = omega;
|
||||
}
|
||||
|
||||
void CentrifugalForceIntegrator::SetIntegrationRule(
|
||||
const mfem::IntegrationRule &ir
|
||||
) {
|
||||
m_ir = &ir;
|
||||
}
|
||||
|
||||
void CentrifugalForceIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
mfem::ElementTransformation &Tr,
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array<mfem::Vector *> &elvec
|
||||
) {
|
||||
if (utils::is_vacuum(Tr, elvec)) {
|
||||
return;
|
||||
}
|
||||
if (utils::is_vacuum(Tr, elvec)) {
|
||||
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];
|
||||
r_v = 0.0;
|
||||
mfem::Vector &r_v = *elvec[0];
|
||||
r_v.SetSize(dof_v * dim);
|
||||
r_v = 0.0;
|
||||
if (elvec[1]) {
|
||||
elvec[1]->SetSize(dof_rho);
|
||||
*elvec[1] = 0.0;
|
||||
@@ -47,10 +55,15 @@ namespace mean_field::integrators {
|
||||
mfem::Vector x_phys(dim);
|
||||
mfem::Vector a(dim), b(dim);
|
||||
|
||||
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
|
||||
MFEM_VERIFY(
|
||||
m_ir, "CentrifugalForceIntegrator must be configured with an "
|
||||
"integration rule before assembly. Call "
|
||||
"SetIntegrationRule first."
|
||||
);
|
||||
const mfem::IntegrationRule *ir = m_ir;
|
||||
|
||||
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);
|
||||
@@ -61,14 +74,14 @@ namespace mean_field::integrators {
|
||||
m_map.GetPhysicalPoint(Tr, ip, x_phys);
|
||||
|
||||
// ω x r
|
||||
a(0) = m_omega(1) * x_phys(2) - m_omega(2) * x_phys(1);
|
||||
a(1) = m_omega(2) * x_phys(0) - m_omega(0) * x_phys(2);
|
||||
a(2) = m_omega(0) * x_phys(1) - m_omega(1) * x_phys(0);
|
||||
a(0) = m_omega(1) * x_phys(2) - m_omega(2) * x_phys(1);
|
||||
a(1) = m_omega(2) * x_phys(0) - m_omega(0) * x_phys(2);
|
||||
a(2) = m_omega(0) * x_phys(1) - m_omega(1) * x_phys(0);
|
||||
|
||||
// ω x (ω x r) [centrifugal acceleration]
|
||||
b(0) = m_omega(1) * a(2) - m_omega(2) * a(1);
|
||||
b(1) = m_omega(2) * a(0) - m_omega(0) * a(2);
|
||||
b(2) = m_omega(0) * a(1) - m_omega(1) * a(0);
|
||||
b(0) = m_omega(1) * a(2) - m_omega(2) * a(1);
|
||||
b(1) = m_omega(2) * a(0) - m_omega(0) * a(2);
|
||||
b(2) = m_omega(0) * a(1) - m_omega(1) * a(0);
|
||||
|
||||
double rho_val = 0.0;
|
||||
for (int i = 0; i < dof_rho; ++i) {
|
||||
@@ -89,30 +102,39 @@ namespace mean_field::integrators {
|
||||
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];
|
||||
if (utils::is_vacuum(Tr, elmats)) {
|
||||
return;
|
||||
}
|
||||
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();
|
||||
|
||||
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 (elmats(1, 0)) *elmats(1, 0) = 0.0;
|
||||
if (elmats(1, 1)) *elmats(1, 1) = 0.0;
|
||||
if (dv_drho) *dv_drho = 0.0;
|
||||
if (!dv_drho) return;
|
||||
if (dv_dv)
|
||||
*dv_dv = 0.0;
|
||||
if (elmats(1, 0))
|
||||
*elmats(1, 0) = 0.0;
|
||||
if (elmats(1, 1))
|
||||
*elmats(1, 1) = 0.0;
|
||||
if (dv_drho)
|
||||
*dv_drho = 0.0;
|
||||
if (!dv_drho)
|
||||
return;
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::Vector x_phys(dim);
|
||||
mfem::Vector a(dim), b(dim);
|
||||
|
||||
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);
|
||||
@@ -137,10 +159,11 @@ namespace mean_field::integrators {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const int row = i + c * dof_v;
|
||||
for (int j = 0; j < dof_rho; ++j) {
|
||||
(*dv_drho)(row, j) += shape_v(i) * shape_rho(j) * b(c) * weight;
|
||||
(*dv_drho)(row, j) +=
|
||||
shape_v(i) * shape_rho(j) * b(c) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
@@ -4,38 +4,43 @@ module;
|
||||
module mean_field;
|
||||
|
||||
namespace mean_field::integrators {
|
||||
CoriolisIntegrator::CoriolisIntegrator(const mapping::DomainMapper& map, const mfem::Vector& omega)
|
||||
: m_map(map), m_omega(omega) {
|
||||
CoriolisIntegrator::CoriolisIntegrator(
|
||||
const mapping::DomainMapper &map,
|
||||
const mfem::Vector &omega
|
||||
)
|
||||
: m_map(map),
|
||||
m_omega(omega) {
|
||||
m_omega_mat.SetSize(3, 3);
|
||||
m_omega_mat = 0.0;
|
||||
m_omega_mat = 0.0;
|
||||
m_omega_mat(0, 1) = -m_omega(2);
|
||||
m_omega_mat(0, 2) = m_omega(1);
|
||||
m_omega_mat(1, 0) = m_omega(2);
|
||||
m_omega_mat(0, 2) = m_omega(1);
|
||||
m_omega_mat(1, 0) = m_omega(2);
|
||||
m_omega_mat(1, 2) = -m_omega(0);
|
||||
m_omega_mat(2, 0) = -m_omega(1);
|
||||
m_omega_mat(2, 1) = m_omega(0);
|
||||
m_omega_mat(2, 1) = m_omega(0);
|
||||
}
|
||||
|
||||
void CoriolisIntegrator::AssembleElementVector(const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
mfem::ElementTransformation &Tr,
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array<mfem::Vector *> &elvec
|
||||
void CoriolisIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
mfem::ElementTransformation &Tr,
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array<mfem::Vector *> &elvec
|
||||
) {
|
||||
if (utils::is_vacuum(Tr, elvec)) {
|
||||
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& v_dofs = *elfun[0];
|
||||
const mfem::Vector& rho_dofs = *elfun[1];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
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]) {
|
||||
@@ -44,10 +49,11 @@ namespace mean_field::integrators {
|
||||
}
|
||||
|
||||
mfem::Vector shape_v(dof_v), 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);
|
||||
@@ -56,11 +62,14 @@ 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);
|
||||
|
||||
mfem::Vector v_val(dim); v_val = 0.0;
|
||||
mfem::Vector v_val(dim);
|
||||
v_val = 0.0;
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) v_val(c) += v_dofs(i + c * dof_v) * shape_v(i);
|
||||
for (int c = 0; c < dim; ++c)
|
||||
v_val(c) += v_dofs(i + c * dof_v) * shape_v(i);
|
||||
}
|
||||
|
||||
mfem::Vector F_coriolis(dim);
|
||||
@@ -69,39 +78,44 @@ namespace mean_field::integrators {
|
||||
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
r_v(i + c * dof_v) += shape_v(i) * rho_val * F_coriolis(c) * weight;
|
||||
r_v(i + c * dof_v) +=
|
||||
shape_v(i) * rho_val * F_coriolis(c) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoriolisIntegrator::AssembleElementGrad(const mfem::Array<const mfem::FiniteElement*> &el,
|
||||
mfem::ElementTransformation &Tr,
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array2D<mfem::DenseMatrix *> &elmats
|
||||
void CoriolisIntegrator::AssembleElementGrad(
|
||||
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& v_dofs = *elfun[0];
|
||||
const mfem::Vector& rho_dofs = *elfun[1];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
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_dv)
|
||||
*dv_dv = 0.0;
|
||||
if (dv_drho)
|
||||
*dv_drho = 0.0;
|
||||
|
||||
mfem::Vector shape_v(dof_v), 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);
|
||||
@@ -110,11 +124,14 @@ 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);
|
||||
|
||||
mfem::Vector v_val(dim); v_val = 0.0;
|
||||
mfem::Vector v_val(dim);
|
||||
v_val = 0.0;
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) v_val(c) += v_dofs(i + c * dof_v) * shape_v(i);
|
||||
for (int c = 0; c < dim; ++c)
|
||||
v_val(c) += v_dofs(i + c * dof_v) * shape_v(i);
|
||||
}
|
||||
|
||||
mfem::Vector F_coriolis(dim);
|
||||
@@ -124,12 +141,14 @@ namespace mean_field::integrators {
|
||||
if (dv_dv) {
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
int row = i + c * dof_v;
|
||||
const int row = i + c * dof_v;
|
||||
for (int j = 0; j < dof_v; ++j) {
|
||||
for (int d = 0; d < dim; ++d) {
|
||||
int col = j + d * dof_v;
|
||||
int col = j + d * dof_v;
|
||||
double coupling = m_omega_mat(c, d);
|
||||
(*dv_dv)(row, col) += shape_v(i) * shape_v(j) * 2.0 * rho_val * coupling * weight;
|
||||
(*dv_dv)(row, col) += shape_v(i) * shape_v(j) *
|
||||
2.0 * rho_val * coupling *
|
||||
weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,11 +161,12 @@ namespace mean_field::integrators {
|
||||
int row = i + c * dof_v;
|
||||
for (int j = 0; j < dof_rho; ++j) {
|
||||
int col = j;
|
||||
(*dv_drho)(row, col) += shape_v(i) * shape_rho(j) * F_coriolis(c) * weight;
|
||||
(*dv_drho)(row, col) += shape_v(i) * shape_rho(j) *
|
||||
F_coriolis(c) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
@@ -1,124 +1,341 @@
|
||||
module;
|
||||
#include <mfem.hpp>
|
||||
module mean_field;
|
||||
import :solver.fields;
|
||||
|
||||
namespace {
|
||||
using namespace mean_field;
|
||||
|
||||
constexpr int velocity_block =
|
||||
solver::block_index(solver::FieldBlock::velocity);
|
||||
constexpr int density_block =
|
||||
solver::block_index(solver::FieldBlock::density);
|
||||
constexpr int gravity_gradient_block =
|
||||
solver::block_index(solver::FieldBlock::gravity_gradient);
|
||||
constexpr int displacement_block =
|
||||
solver::block_index(solver::FieldBlock::displacement);
|
||||
} // namespace
|
||||
|
||||
namespace mean_field::integrators {
|
||||
GravityForceIntegrator::GravityForceIntegrator(
|
||||
const mapping::DomainMapper& map,
|
||||
const mfem::GridFunction& phi
|
||||
): m_map(map), m_phi(&phi) {}
|
||||
GravityMomentumIntegrator::GravityMomentumIntegrator(
|
||||
const mapping::DomainMapper &map,
|
||||
const GravityForceJacobianMode jacobian_mode
|
||||
)
|
||||
: m_map(map),
|
||||
m_jacobian_mode(jacobian_mode) {
|
||||
}
|
||||
|
||||
void GravityForceIntegrator::SetPotential(const mfem::GridFunction& phi) { m_phi = φ };
|
||||
void GravityMomentumIntegrator::SetJacobianMode(
|
||||
const GravityForceJacobianMode jacobian_mode
|
||||
) {
|
||||
m_jacobian_mode = jacobian_mode;
|
||||
}
|
||||
|
||||
void GravityForceIntegrator::AssembleElementVector(
|
||||
void GravityMomentumIntegrator::SetIntegrationRule(
|
||||
const mfem::IntegrationRule &integration_rule
|
||||
) {
|
||||
m_integration_rule = &integration_rule;
|
||||
}
|
||||
|
||||
GravityForceJacobianMode
|
||||
GravityMomentumIntegrator::GetJacobianMode() const {
|
||||
return m_jacobian_mode;
|
||||
}
|
||||
|
||||
void GravityMomentumIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
mfem::ElementTransformation &Tr,
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array<mfem::Vector *> &elvec
|
||||
) {
|
||||
|
||||
if (utils::is_vacuum(Tr, elvec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement* fe_v = el[0];
|
||||
const mfem::FiniteElement* fe_rho = el[1];
|
||||
MFEM_VERIFY(
|
||||
m_integration_rule,
|
||||
"GravityForceIntegrator must be configured with an "
|
||||
"integration rule before assembly."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
el.Size() > gravity_gradient_block,
|
||||
"GravityForceIntegrator requires velocity, density, and "
|
||||
"gravity-gradient finite elements."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
elfun.Size() > gravity_gradient_block,
|
||||
"GravityForceIntegrator requires velocity, density, and "
|
||||
"gravity-gradient element states."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
elvec.Size() > velocity_block && elvec[velocity_block],
|
||||
"GravityForceIntegrator requires a velocity residual block."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
el[velocity_block] && el[density_block] &&
|
||||
el[gravity_gradient_block],
|
||||
"GravityForceIntegrator received a null finite element."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
elfun[density_block] && elfun[gravity_gradient_block],
|
||||
"GravityForceIntegrator received a null element state."
|
||||
);
|
||||
|
||||
const int dof_v = fe_v->GetDof();
|
||||
const int dof_rho = fe_rho->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
const mfem::FiniteElement *velocity_element = el[velocity_block];
|
||||
const mfem::FiniteElement *density_element = el[density_block];
|
||||
const mfem::FiniteElement *gravity_gradient_element =
|
||||
el[gravity_gradient_block];
|
||||
|
||||
const mfem::Vector& rho_dofs = *elfun[1];
|
||||
const int velocity_dofs_count = velocity_element->GetDof();
|
||||
const int density_dofs_count = density_element->GetDof();
|
||||
const int gravity_gradient_dofs_count =
|
||||
gravity_gradient_element->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
|
||||
mfem::Vector& r_v = *elvec[0];
|
||||
r_v.SetSize(dof_v * dim);
|
||||
r_v = 0.0;
|
||||
if (elvec[1]) {
|
||||
elvec[1]->SetSize(dof_rho);
|
||||
*elvec[1] = 0.0;
|
||||
const mfem::Vector &density_dofs = *elfun[density_block];
|
||||
const mfem::Vector &gravity_gradient_dofs =
|
||||
*elfun[gravity_gradient_block];
|
||||
|
||||
MFEM_VERIFY(
|
||||
density_dofs.Size() == density_dofs_count,
|
||||
"GravityForceIntegrator received an incorrectly sized density "
|
||||
"state."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
gravity_gradient_dofs.Size() == gravity_gradient_dofs_count,
|
||||
"GravityForceIntegrator received an incorrectly sized "
|
||||
"gravity-gradient "
|
||||
"state."
|
||||
);
|
||||
|
||||
for (int block = 0; block < elvec.Size(); ++block) {
|
||||
if (elvec[block]) {
|
||||
*elvec[block] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::Vector grad_phi_ref(dim), grad_phi_phys(dim), grad_phi_elem(dim);
|
||||
mfem::Vector &velocity_residual = *elvec[velocity_block];
|
||||
velocity_residual.SetSize(dim * velocity_dofs_count);
|
||||
velocity_residual = 0.0;
|
||||
|
||||
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
|
||||
if (elvec.Size() > density_block && elvec[density_block]) {
|
||||
elvec[density_block]->SetSize(density_dofs_count);
|
||||
*elvec[density_block] = 0.0;
|
||||
}
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint& ip = ir->IntPoint(q);
|
||||
Tr.SetIntPoint(&ip);
|
||||
if (elvec.Size() > gravity_gradient_block &&
|
||||
elvec[gravity_gradient_block]) {
|
||||
elvec[gravity_gradient_block]->SetSize(gravity_gradient_dofs_count);
|
||||
*elvec[gravity_gradient_block] = 0.0;
|
||||
}
|
||||
|
||||
auto [J_inv, detJ, weight] = m_map.GetQuadratureContext(Tr, ip);
|
||||
m_phi->GetGradient(Tr, grad_phi_elem);
|
||||
mfem::DenseMatrix J_map(dim, dim), J_map_inv(dim, dim);
|
||||
m_map.ComputeJacobian(Tr, J_map);
|
||||
mfem::CalcInverse(J_map, J_map_inv);
|
||||
J_map_inv.MultTranspose(grad_phi_elem, grad_phi_phys);
|
||||
mfem::Vector velocity_shape(velocity_dofs_count);
|
||||
mfem::Vector density_shape(density_dofs_count);
|
||||
mfem::DenseMatrix gravity_gradient_shape(
|
||||
gravity_gradient_dofs_count, dim
|
||||
);
|
||||
mfem::Vector gravity_gradient_element_value(dim);
|
||||
mfem::Vector gravity_gradient_physical_value(dim);
|
||||
|
||||
fe_v->CalcShape(ip, shape_v);
|
||||
fe_rho->CalcShape(ip, shape_rho);
|
||||
const mfem::IntegrationRule &integration_rule = *m_integration_rule;
|
||||
|
||||
double rho_val = 0.0;
|
||||
for (int i = 0; i < dof_rho; ++i) {
|
||||
rho_val += rho_dofs(i) * shape_rho(i);
|
||||
for (int q = 0; q < integration_rule.GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint &integration_point =
|
||||
integration_rule.IntPoint(q);
|
||||
Tr.SetIntPoint(&integration_point);
|
||||
|
||||
const mapping::VolumeQuadratureContext context =
|
||||
m_map.GetQuadratureContext(Tr, integration_point);
|
||||
|
||||
velocity_element->CalcShape(integration_point, velocity_shape);
|
||||
density_element->CalcShape(integration_point, density_shape);
|
||||
gravity_gradient_element->CalcVShape(Tr, gravity_gradient_shape);
|
||||
|
||||
gravity_gradient_shape.MultTranspose(
|
||||
gravity_gradient_dofs, gravity_gradient_element_value
|
||||
);
|
||||
context.J_inv.MultTranspose(
|
||||
gravity_gradient_element_value, gravity_gradient_physical_value
|
||||
);
|
||||
|
||||
double density_value = 0.0;
|
||||
for (int i = 0; i < density_dofs_count; ++i) {
|
||||
density_value += density_dofs(i) * density_shape(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
r_v(i + c * dof_v) += shape_v(i) * rho_val * grad_phi_phys(c) * weight;
|
||||
for (int i = 0; i < velocity_dofs_count; ++i) {
|
||||
for (int component = 0; component < dim; ++component) {
|
||||
velocity_residual(i + component * velocity_dofs_count) +=
|
||||
velocity_shape(i) * density_value *
|
||||
gravity_gradient_physical_value(component) *
|
||||
context.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GravityForceIntegrator::AssembleElementGrad(
|
||||
void GravityMomentumIntegrator::AssembleElementGrad(
|
||||
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];
|
||||
if (utils::is_vacuum(Tr, elmats)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int dof_v = fe_v->GetDof();
|
||||
const int dof_rho = fe_rho->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
MFEM_VERIFY(
|
||||
m_integration_rule,
|
||||
"GravityForceIntegrator must be configured with an "
|
||||
"integration rule before assembly."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
el.Size() > gravity_gradient_block,
|
||||
"GravityForceIntegrator requires velocity, density, and "
|
||||
"gravity-gradient finite elements."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
elfun.Size() > gravity_gradient_block,
|
||||
"GravityForceIntegrator requires velocity, density, and "
|
||||
"gravity-gradient element states."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
el[velocity_block] && el[density_block] &&
|
||||
el[gravity_gradient_block],
|
||||
"GravityForceIntegrator received a null finite element."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
elfun[density_block] && elfun[gravity_gradient_block],
|
||||
"GravityForceIntegrator received a null element state."
|
||||
);
|
||||
|
||||
mfem::DenseMatrix* dv_dv = elmats(0, 0);
|
||||
mfem::DenseMatrix* dv_drho = elmats(0, 1);
|
||||
for (int row = 0; row < elmats.NumRows(); ++row) {
|
||||
for (int column = 0; column < elmats.NumCols(); ++column) {
|
||||
if (elmats(row, column)) {
|
||||
*elmats(row, column) = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dv_dv) *dv_dv = 0.0;
|
||||
if (dv_drho) *dv_drho = 0.0;
|
||||
if (m_jacobian_mode == GravityForceJacobianMode::exact) {
|
||||
MFEM_ABORT(
|
||||
"Exact GravityForceIntegrator geometry Jacobian is unavailable "
|
||||
"until "
|
||||
"DomainMapper linearization is "
|
||||
"implemented."
|
||||
);
|
||||
}
|
||||
|
||||
if (!dv_drho) return;
|
||||
const mfem::FiniteElement *velocity_element = el[velocity_block];
|
||||
const mfem::FiniteElement *density_element = el[density_block];
|
||||
const mfem::FiniteElement *gravity_gradient_element =
|
||||
el[gravity_gradient_block];
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::Vector grad_phi_ref(dim), grad_phi_phys(dim), grad_phi_elem(dim);
|
||||
const int velocity_dofs_count = velocity_element->GetDof();
|
||||
const int density_dofs_count = density_element->GetDof();
|
||||
const int gravity_gradient_dofs_count =
|
||||
gravity_gradient_element->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
|
||||
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder());
|
||||
const mfem::Vector &density_dofs = *elfun[density_block];
|
||||
const mfem::Vector &gravity_gradient_dofs =
|
||||
*elfun[gravity_gradient_block];
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint& ip = ir->IntPoint(q);
|
||||
Tr.SetIntPoint(&ip);
|
||||
MFEM_VERIFY(
|
||||
density_dofs.Size() == density_dofs_count,
|
||||
"GravityForceIntegrator received an incorrectly sized density "
|
||||
"state."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
gravity_gradient_dofs.Size() == gravity_gradient_dofs_count,
|
||||
"GravityForceIntegrator received an incorrectly sized "
|
||||
"gravity-gradient "
|
||||
"state."
|
||||
);
|
||||
|
||||
auto [J_inv, detJ, weight] = m_map.GetQuadratureContext(Tr, ip);
|
||||
m_phi->GetGradient(Tr, grad_phi_elem);
|
||||
mfem::DenseMatrix J_map(dim, dim), J_map_inv(dim, dim);
|
||||
m_map.ComputeJacobian(Tr, J_map);
|
||||
mfem::CalcInverse(J_map, J_map_inv);
|
||||
J_map_inv.MultTranspose(grad_phi_elem, grad_phi_phys);
|
||||
mfem::DenseMatrix *dv_drho = elmats(velocity_block, density_block);
|
||||
mfem::DenseMatrix *dv_dgrad_phi =
|
||||
m_jacobian_mode == GravityForceJacobianMode::field_coupled
|
||||
? elmats(velocity_block, gravity_gradient_block)
|
||||
: nullptr;
|
||||
|
||||
fe_v->CalcShape(ip, shape_v);
|
||||
fe_rho->CalcShape(ip, shape_rho);
|
||||
if (!dv_drho && !dv_dgrad_phi) {
|
||||
return;
|
||||
}
|
||||
|
||||
mfem::Vector velocity_shape(velocity_dofs_count);
|
||||
mfem::Vector density_shape(density_dofs_count);
|
||||
mfem::DenseMatrix gravity_gradient_shape(
|
||||
gravity_gradient_dofs_count, dim
|
||||
);
|
||||
mfem::Vector gravity_gradient_element_value(dim);
|
||||
mfem::Vector gravity_gradient_physical_value(dim);
|
||||
mfem::Vector gravity_basis_element(dim);
|
||||
mfem::Vector gravity_basis_physical(dim);
|
||||
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const int row = i + c * dof_v;
|
||||
for (int j = 0; j < dof_rho; ++j) {
|
||||
(*dv_drho)(row, j) += shape_v(i) * shape_rho(j) * grad_phi_phys(c) * weight;
|
||||
const mfem::IntegrationRule &integration_rule = *m_integration_rule;
|
||||
|
||||
for (int q = 0; q < integration_rule.GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint &integration_point =
|
||||
integration_rule.IntPoint(q);
|
||||
Tr.SetIntPoint(&integration_point);
|
||||
|
||||
const mapping::VolumeQuadratureContext context =
|
||||
m_map.GetQuadratureContext(Tr, integration_point);
|
||||
|
||||
velocity_element->CalcShape(integration_point, velocity_shape);
|
||||
density_element->CalcShape(integration_point, density_shape);
|
||||
gravity_gradient_element->CalcVShape(Tr, gravity_gradient_shape);
|
||||
|
||||
gravity_gradient_shape.MultTranspose(
|
||||
gravity_gradient_dofs, gravity_gradient_element_value
|
||||
);
|
||||
context.J_inv.MultTranspose(
|
||||
gravity_gradient_element_value, gravity_gradient_physical_value
|
||||
);
|
||||
|
||||
double density_value = 0.0;
|
||||
for (int i = 0; i < density_dofs_count; ++i) {
|
||||
density_value += density_dofs(i) * density_shape(i);
|
||||
}
|
||||
|
||||
if (dv_drho) {
|
||||
for (int i = 0; i < velocity_dofs_count; ++i) {
|
||||
for (int component = 0; component < dim; ++component) {
|
||||
const int row = i + component * velocity_dofs_count;
|
||||
|
||||
for (int j = 0; j < density_dofs_count; ++j) {
|
||||
(*dv_drho)(row, j) +=
|
||||
velocity_shape(i) * density_shape(j) *
|
||||
gravity_gradient_physical_value(component) *
|
||||
context.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dv_dgrad_phi) {
|
||||
for (int j = 0; j < gravity_gradient_dofs_count; ++j) {
|
||||
for (int component = 0; component < dim; ++component) {
|
||||
gravity_basis_element(component) =
|
||||
gravity_gradient_shape(j, component);
|
||||
}
|
||||
|
||||
context.J_inv.MultTranspose(
|
||||
gravity_basis_element, gravity_basis_physical
|
||||
);
|
||||
|
||||
for (int i = 0; i < velocity_dofs_count; ++i) {
|
||||
for (int component = 0; component < dim; ++component) {
|
||||
const int row = i + component * velocity_dofs_count;
|
||||
(*dv_dgrad_phi)(row, j) +=
|
||||
velocity_shape(i) * density_value *
|
||||
gravity_basis_physical(component) *
|
||||
context.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
@@ -4,7 +4,10 @@ module;
|
||||
module mean_field;
|
||||
|
||||
namespace mean_field::integrators {
|
||||
ContinuityVolumeIntegrator::ContinuityVolumeIntegrator(const mapping::DomainMapper& map) : m_map(map) {};
|
||||
ContinuityVolumeIntegrator::ContinuityVolumeIntegrator(
|
||||
const mapping::DomainMapper &map
|
||||
)
|
||||
: m_map(map) { };
|
||||
|
||||
void ContinuityVolumeIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
@@ -16,35 +19,37 @@ namespace mean_field::integrators {
|
||||
return;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement *fe_v = el[0];
|
||||
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 v_dofs = *elfun[0];
|
||||
const mfem::Vector rho_dofs = *elfun[1];
|
||||
const mfem::Vector v_dofs = *elfun[0];
|
||||
const mfem::Vector rho_dofs = *elfun[1];
|
||||
|
||||
void* data_rho_before = elvec[1] ? (void*)elvec[1]->GetData() : nullptr;
|
||||
void *data_rho_before =
|
||||
elvec[1] ? (void *)elvec[1]->GetData() : nullptr;
|
||||
int size_rho_before = elvec[1] ? elvec[1]->Size() : -1;
|
||||
|
||||
if (elvec[0]) {
|
||||
elvec[0]->SetSize(dof_v * dim);
|
||||
*elvec[0] = 0.0;
|
||||
}
|
||||
mfem::Vector& r_rho = *elvec[1];
|
||||
mfem::Vector &r_rho = *elvec[1];
|
||||
r_rho.SetSize(dof_rho);
|
||||
r_rho = 0.0;
|
||||
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::DenseMatrix dshape_rho_ref(dof_rho, dim), dshape_rho_phys(dof_rho, dim);
|
||||
mfem::DenseMatrix dshape_rho_ref(dof_rho, dim),
|
||||
dshape_rho_phys(dof_rho, dim);
|
||||
|
||||
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);
|
||||
@@ -54,7 +59,8 @@ namespace mean_field::integrators {
|
||||
fe_rho->CalcDShape(ip, dshape_rho_ref);
|
||||
mfem::Mult(dshape_rho_ref, J_inv, dshape_rho_phys);
|
||||
|
||||
mfem::Vector v_val(dim); v_val = 0.0;
|
||||
mfem::Vector v_val(dim);
|
||||
v_val = 0.0;
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const int row = i + c * dof_v;
|
||||
@@ -83,32 +89,38 @@ namespace mean_field::integrators {
|
||||
const mfem::Array2D<mfem::DenseMatrix *> &elmats
|
||||
) {
|
||||
|
||||
const mfem::FiniteElement *fe_v = el[0];
|
||||
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& v_dofs = *elfun[0];
|
||||
const mfem::Vector& rho_dofs = *elfun[1];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
const mfem::Vector &rho_dofs = *elfun[1];
|
||||
|
||||
mfem::DenseMatrix* drho_dv = elmats(1, 0);
|
||||
mfem::DenseMatrix* drho_drho = elmats(1, 1);
|
||||
mfem::DenseMatrix *drho_dv = elmats(1, 0);
|
||||
mfem::DenseMatrix *drho_drho = elmats(1, 1);
|
||||
|
||||
if (elmats(0, 0)) *elmats(0, 0) = 0.0;
|
||||
if (elmats(0, 1)) *elmats(0, 1) = 0.0;
|
||||
if (elmats(0, 0))
|
||||
*elmats(0, 0) = 0.0;
|
||||
if (elmats(0, 1))
|
||||
*elmats(0, 1) = 0.0;
|
||||
|
||||
if (drho_dv) *drho_dv = 0.0;
|
||||
if (drho_drho) *drho_drho = 0.0;
|
||||
if (drho_dv)
|
||||
*drho_dv = 0.0;
|
||||
if (drho_drho)
|
||||
*drho_drho = 0.0;
|
||||
|
||||
mfem::Vector shape_v(dof_v), shape_rho(dof_rho);
|
||||
mfem::DenseMatrix dshape_rho_ref(dof_rho, dim), dshape_rho_phys(dof_rho, dim);
|
||||
mfem::DenseMatrix dshape_rho_ref(dof_rho, dim),
|
||||
dshape_rho_phys(dof_rho, dim);
|
||||
|
||||
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);
|
||||
@@ -118,7 +130,8 @@ namespace mean_field::integrators {
|
||||
fe_rho->CalcDShape(ip, dshape_rho_ref);
|
||||
mfem::Mult(dshape_rho_ref, J_inv, dshape_rho_phys);
|
||||
|
||||
mfem::Vector v_val(dim); v_val = 0.0;
|
||||
mfem::Vector v_val(dim);
|
||||
v_val = 0.0;
|
||||
for (int i = 0; i < dof_v; ++i) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const int row = i + c * dof_v;
|
||||
@@ -136,7 +149,8 @@ namespace mean_field::integrators {
|
||||
for (int j = 0; j < dof_v; ++j) {
|
||||
for (int d = 0; d < dim; ++d) {
|
||||
const int col = j + d * dof_v;
|
||||
(*drho_dv)(i, col) -= dshape_rho_phys(i, d) * rho_val * shape_v(j) * weight;
|
||||
(*drho_dv)(i, col) -= dshape_rho_phys(i, d) *
|
||||
rho_val * shape_v(j) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,15 +163,19 @@ namespace mean_field::integrators {
|
||||
grad_psi_dot_v += dshape_rho_phys(i, c) * v_val(c);
|
||||
}
|
||||
for (int j = 0; j < dof_rho; ++j) {
|
||||
(*drho_drho)(i, j) -= grad_psi_dot_v * shape_rho(j) * weight;
|
||||
|
||||
(*drho_drho)(i, j) -=
|
||||
grad_psi_dot_v * shape_rho(j) * weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContinuityFaceIntegrator::ContinuityFaceIntegrator(const mapping::DomainMapper& map): m_map(map) {}
|
||||
ContinuityFaceIntegrator::ContinuityFaceIntegrator(
|
||||
const mapping::DomainMapper &map
|
||||
)
|
||||
: m_map(map) {
|
||||
}
|
||||
|
||||
void ContinuityFaceIntegrator::AssembleFaceVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el1,
|
||||
@@ -166,19 +184,19 @@ namespace mean_field::integrators {
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array<mfem::Vector *> &elvect
|
||||
) {
|
||||
const mfem::FiniteElement *fe_v_minus = el1[0];
|
||||
const mfem::FiniteElement *fe_v_plus = el2[0];
|
||||
const mfem::FiniteElement *fe_v_minus = el1[0];
|
||||
const mfem::FiniteElement *fe_v_plus = el2[0];
|
||||
|
||||
const mfem::FiniteElement *fe_rho_minus = el1[1];
|
||||
const mfem::FiniteElement *fe_rho_plus = el2[1];
|
||||
const mfem::FiniteElement *fe_rho_plus = el2[1];
|
||||
|
||||
const int dof_v_minus = fe_v_minus->GetDof();
|
||||
const int dof_v_plus = fe_v_plus->GetDof();
|
||||
const int dof_v_minus = fe_v_minus->GetDof();
|
||||
const int dof_v_plus = fe_v_plus->GetDof();
|
||||
|
||||
const int dof_rho_minus = fe_rho_minus->GetDof();
|
||||
const int dof_rho_plus = fe_rho_plus->GetDof();
|
||||
const int dof_rho_minus = fe_rho_minus->GetDof();
|
||||
const int dof_rho_plus = fe_rho_plus->GetDof();
|
||||
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
|
||||
if (elvect[0]) {
|
||||
elvect[0]->SetSize(dim * dof_v_minus + dim * dof_v_plus);
|
||||
@@ -186,10 +204,10 @@ namespace mean_field::integrators {
|
||||
}
|
||||
mfem::Vector &r_rho = *elvect[1];
|
||||
r_rho.SetSize(dof_rho_minus + dof_rho_plus);
|
||||
r_rho = 0.0;
|
||||
r_rho = 0.0;
|
||||
|
||||
const int attr_minus = Tr.Elem1->Attribute;
|
||||
const int attr_plus = (Tr.Elem2 != nullptr) ? Tr.Elem2->Attribute : -1;
|
||||
const int attr_plus = (Tr.Elem2 != nullptr) ? Tr.Elem2->Attribute : -1;
|
||||
constexpr int VACUUM_ATTR = 3;
|
||||
|
||||
if (attr_minus == VACUUM_ATTR || attr_plus == VACUUM_ATTR) {
|
||||
@@ -200,30 +218,39 @@ namespace mean_field::integrators {
|
||||
return; // Boundary face,
|
||||
}
|
||||
|
||||
const mfem::Vector &v_dofs = *elfun[0]; // Size: dim * dof_v_minus + dim*dof_v_plus
|
||||
const mfem::Vector &rho_dofs = *elfun[1]; // Size: dof_rho_minus + dof_rho_plus
|
||||
const mfem::Vector &v_dofs =
|
||||
*elfun[0]; // Size: dim * dof_v_minus + dim*dof_v_plus
|
||||
const mfem::Vector &rho_dofs =
|
||||
*elfun[1]; // Size: dof_rho_minus + dof_rho_plus
|
||||
|
||||
// Helpers to auto offset to the correct point in the dof array
|
||||
auto rho_minus_dof = [&](const int i) {return rho_dofs(i);};
|
||||
auto rho_plus_dof = [&](const int i) {return rho_dofs(i + dof_rho_minus);};
|
||||
auto v_minus_dof = [&](const int k, const int c) {return v_dofs(k + c * dof_v_minus);};
|
||||
auto rho_minus_dof = [&](const int i) { return rho_dofs(i); };
|
||||
auto rho_plus_dof = [&](const int i) {
|
||||
return rho_dofs(i + dof_rho_minus);
|
||||
};
|
||||
auto v_minus_dof = [&](const int k, const int c) {
|
||||
return v_dofs(k + c * dof_v_minus);
|
||||
};
|
||||
|
||||
const int p_v = fe_v_minus->GetOrder();
|
||||
const int p_rho = fe_rho_minus->GetOrder();
|
||||
const int p_v = fe_v_minus->GetOrder();
|
||||
const int p_rho = fe_rho_minus->GetOrder();
|
||||
const int int_order = 2 * std::max(p_v, p_rho) + 1;
|
||||
|
||||
const mfem::IntegrationRule *ir = &mfem::IntRules.Get(Tr.GetGeometryType(), int_order);
|
||||
const mfem::IntegrationRule *ir =
|
||||
&mfem::IntRules.Get(Tr.GetGeometryType(), int_order);
|
||||
|
||||
mfem::Vector shape_v_minus(dof_v_minus), shape_rho_minus(dof_rho_minus), shape_rho_plus(dof_rho_plus);
|
||||
mfem::Vector shape_v_minus(dof_v_minus), shape_rho_minus(dof_rho_minus),
|
||||
shape_rho_plus(dof_rho_plus);
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint& face_ip = ir->IntPoint(q);
|
||||
const mfem::IntegrationPoint &face_ip = ir->IntPoint(q);
|
||||
|
||||
Tr.SetAllIntPoints(&face_ip);
|
||||
const mfem::IntegrationPoint &ip_minus = Tr.GetElement1IntPoint();
|
||||
const mfem::IntegrationPoint &ip_plus = Tr.GetElement2IntPoint();
|
||||
const mfem::IntegrationPoint &ip_plus = Tr.GetElement2IntPoint();
|
||||
|
||||
auto [n_unit, ds, v_dot_n_scale] = m_map.GetFaceQuadratureContext(Tr, face_ip);
|
||||
auto [n_unit, ds, v_dot_n_scale] =
|
||||
m_map.GetFaceQuadratureContext(Tr, face_ip);
|
||||
|
||||
fe_v_minus->CalcShape(ip_minus, shape_v_minus);
|
||||
fe_rho_minus->CalcShape(ip_minus, shape_rho_minus);
|
||||
@@ -251,12 +278,14 @@ namespace mean_field::integrators {
|
||||
}
|
||||
|
||||
// Upwind density
|
||||
// I use the convention that the flow is positive when moving from minus to plus
|
||||
// I use the convention that the flow is positive when moving from
|
||||
// minus to plus
|
||||
const double rho_up = (u_n >= 0) ? rho_minus_val : rho_plus_val;
|
||||
|
||||
const double flux_weighted = u_n * rho_up * ds;
|
||||
|
||||
// Note the normals need to be in opposite directions for these two fluxes
|
||||
// Note the normals need to be in opposite directions for these two
|
||||
// fluxes
|
||||
for (int i = 0; i < dof_rho_minus; ++i) {
|
||||
r_rho(i) += shape_rho_minus(i) * flux_weighted;
|
||||
}
|
||||
@@ -274,25 +303,26 @@ namespace mean_field::integrators {
|
||||
const mfem::Array<const mfem::Vector *> &elfun,
|
||||
const mfem::Array2D<mfem::DenseMatrix *> &elmats
|
||||
) {
|
||||
const mfem::FiniteElement *fe_v_minus = el1[0];
|
||||
const mfem::FiniteElement *fe_v_plus = el2[0];
|
||||
const mfem::FiniteElement *fe_v_minus = el1[0];
|
||||
const mfem::FiniteElement *fe_v_plus = el2[0];
|
||||
const mfem::FiniteElement *fe_rho_minus = el1[1];
|
||||
const mfem::FiniteElement *fe_rho_plus = el2[1];
|
||||
const mfem::FiniteElement *fe_rho_plus = el2[1];
|
||||
|
||||
const int dof_v_minus = fe_v_minus->GetDof();
|
||||
const int dof_v_plus = fe_v_plus->GetDof();
|
||||
const int dof_rho_minus = fe_rho_minus->GetDof();
|
||||
const int dof_rho_plus = fe_rho_plus->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
const int dof_v_minus = fe_v_minus->GetDof();
|
||||
const int dof_v_plus = fe_v_plus->GetDof();
|
||||
const int dof_rho_minus = fe_rho_minus->GetDof();
|
||||
const int dof_rho_plus = fe_rho_plus->GetDof();
|
||||
const int dim = Tr.GetSpaceDim();
|
||||
|
||||
const int N_v_total = dim * (dof_v_minus + dof_v_plus);
|
||||
const int N_rho_total = dof_rho_minus + dof_rho_plus;
|
||||
const int N_v_total = dim * (dof_v_minus + dof_v_plus);
|
||||
const int N_rho_total = dof_rho_minus + dof_rho_plus;
|
||||
|
||||
auto size_and_zero_mat = [&](mfem::DenseMatrix* mat, const int r_size, const int c_size) {
|
||||
if (mat) {
|
||||
mat->SetSize(r_size, c_size);
|
||||
*mat = 0.0;
|
||||
}
|
||||
auto size_and_zero_mat = [&](mfem::DenseMatrix *mat, const int r_size,
|
||||
const int c_size) {
|
||||
if (mat) {
|
||||
mat->SetSize(r_size, c_size);
|
||||
*mat = 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
size_and_zero_mat(elmats(0, 0), N_v_total, N_v_total);
|
||||
@@ -300,34 +330,41 @@ namespace mean_field::integrators {
|
||||
size_and_zero_mat(elmats(1, 0), N_rho_total, N_v_total);
|
||||
size_and_zero_mat(elmats(1, 1), N_rho_total, N_rho_total);
|
||||
|
||||
if (skip_face(Tr)) return;
|
||||
if (skip_face(Tr))
|
||||
return;
|
||||
|
||||
mfem::DenseMatrix *drho_dv = elmats(1, 0);
|
||||
mfem::DenseMatrix *drho_dv = elmats(1, 0);
|
||||
mfem::DenseMatrix *drho_drho = elmats(1, 1);
|
||||
|
||||
if (!drho_dv && !drho_drho) return;
|
||||
if (!drho_dv && !drho_drho)
|
||||
return;
|
||||
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
const mfem::Vector &rho_dofs = *elfun[1];
|
||||
|
||||
const int int_order = 2 * std::max(fe_v_minus->GetOrder(), fe_rho_minus->GetOrder()) + 1;
|
||||
const mfem::IntegrationRule *ir = &mfem::IntRules.Get(Tr.GetGeometryType(), int_order);
|
||||
const int int_order =
|
||||
2 * std::max(fe_v_minus->GetOrder(), fe_rho_minus->GetOrder()) + 1;
|
||||
const mfem::IntegrationRule *ir =
|
||||
&mfem::IntRules.Get(Tr.GetGeometryType(), int_order);
|
||||
|
||||
mfem::Vector shape_v_minus(dof_v_minus), shape_rho_minus(dof_rho_minus), shape_rho_plus(dof_rho_plus);
|
||||
mfem::Vector shape_v_minus(dof_v_minus), shape_rho_minus(dof_rho_minus),
|
||||
shape_rho_plus(dof_rho_plus);
|
||||
|
||||
for (int q = 0; q < ir->GetNPoints(); ++q) {
|
||||
const mfem::IntegrationPoint& face_ip = ir->IntPoint(q);
|
||||
const mfem::IntegrationPoint &face_ip = ir->IntPoint(q);
|
||||
Tr.SetAllIntPoints(&face_ip);
|
||||
const mfem::IntegrationPoint &ip_minus = Tr.GetElement1IntPoint();
|
||||
const mfem::IntegrationPoint &ip_plus = Tr.GetElement2IntPoint();
|
||||
const mfem::IntegrationPoint &ip_plus = Tr.GetElement2IntPoint();
|
||||
|
||||
auto [n_unit, ds, v_dot_n_scale] = m_map.GetFaceQuadratureContext(Tr, face_ip);
|
||||
auto [n_unit, ds, v_dot_n_scale] =
|
||||
m_map.GetFaceQuadratureContext(Tr, face_ip);
|
||||
|
||||
fe_v_minus->CalcShape(ip_minus, shape_v_minus);
|
||||
fe_rho_minus->CalcShape(ip_minus, shape_rho_minus);
|
||||
fe_rho_plus->CalcShape(ip_plus, shape_rho_plus);
|
||||
|
||||
const double u_n = compute_u_n(v_dofs, shape_v_minus, n_unit, dof_v_minus, dim);
|
||||
const double u_n =
|
||||
compute_u_n(v_dofs, shape_v_minus, n_unit, dof_v_minus, dim);
|
||||
|
||||
double rho_minus_val = 0.0;
|
||||
for (int i = 0; i < dof_rho_minus; ++i) {
|
||||
@@ -353,18 +390,21 @@ namespace mean_field::integrators {
|
||||
(*drho_drho)(i, ip) += shape_rho_minus(i) * col_w;
|
||||
}
|
||||
for (int j = 0; j < dof_rho_plus; ++j) {
|
||||
(*drho_drho)(dof_rho_minus + j, ip) -= shape_rho_plus(j) * col_w;
|
||||
(*drho_drho)(dof_rho_minus + j, ip) -=
|
||||
shape_rho_plus(j) * col_w;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int jp = 0; jp < dof_rho_plus; ++jp) {
|
||||
const double col_w = u_w * shape_rho_plus(jp);
|
||||
const int col_idx = dof_rho_minus + jp;
|
||||
const int col_idx = dof_rho_minus + jp;
|
||||
for (int i = 0; i < dof_rho_minus; ++i) {
|
||||
(*drho_drho)(i, col_idx) += shape_rho_minus(i) * col_w;
|
||||
(*drho_drho)(i, col_idx) +=
|
||||
shape_rho_minus(i) * col_w;
|
||||
}
|
||||
for (int j = 0; j < dof_rho_plus; ++j) {
|
||||
(*drho_drho)(dof_rho_minus + j, col_idx) -= shape_rho_plus(j) * col_w;
|
||||
(*drho_drho)(dof_rho_minus + j, col_idx) -=
|
||||
shape_rho_plus(j) * col_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,13 +415,15 @@ namespace mean_field::integrators {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const double n_c_rho_w = n_unit(c) * rho_w;
|
||||
for (int k = 0; k < dof_v_minus; ++k) {
|
||||
const int col_idx = k + c * dof_v_minus;
|
||||
const int col_idx = k + c * dof_v_minus;
|
||||
const double col_w = n_c_rho_w * shape_v_minus(k);
|
||||
for (int i = 0; i < dof_rho_minus; ++i) {
|
||||
(*drho_dv)(i, col_idx) += shape_rho_minus(i) * col_w;
|
||||
(*drho_dv)(i, col_idx) +=
|
||||
shape_rho_minus(i) * col_w;
|
||||
}
|
||||
for (int j = 0; j < dof_rho_plus; ++j) {
|
||||
(*drho_dv)(dof_rho_minus + j, col_idx) -= shape_rho_plus(j) * col_w;
|
||||
(*drho_dv)(dof_rho_minus + j, col_idx) -=
|
||||
shape_rho_plus(j) * col_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,9 +431,11 @@ namespace mean_field::integrators {
|
||||
}
|
||||
}
|
||||
|
||||
bool ContinuityFaceIntegrator::skip_face(const mfem::FaceElementTransformations& Tr) {
|
||||
bool ContinuityFaceIntegrator::skip_face(
|
||||
const mfem::FaceElementTransformations &Tr
|
||||
) {
|
||||
constexpr int VACUUM_ATTR = 3;
|
||||
const int attr_minus = Tr.Elem1->Attribute;
|
||||
const int attr_minus = Tr.Elem1->Attribute;
|
||||
const int attr_plus = (Tr.Elem2 != nullptr) ? Tr.Elem2->Attribute : -1;
|
||||
if (attr_minus == VACUUM_ATTR || attr_plus == VACUUM_ATTR) {
|
||||
return true; // No flux contribution for vacuum faces
|
||||
@@ -402,7 +446,13 @@ namespace mean_field::integrators {
|
||||
return false;
|
||||
}
|
||||
|
||||
double ContinuityFaceIntegrator::compute_u_n(const mfem::Vector& v_dofs, const mfem::Vector& shape_v_minus, const mfem::Vector& n_unit, int dof_v_minus, int dim) {
|
||||
double ContinuityFaceIntegrator::compute_u_n(
|
||||
const mfem::Vector &v_dofs,
|
||||
const mfem::Vector &shape_v_minus,
|
||||
const mfem::Vector &n_unit,
|
||||
int dof_v_minus,
|
||||
int dim
|
||||
) {
|
||||
double u_n = 0.0;
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
double v_c = 0.0;
|
||||
@@ -413,5 +463,4 @@ namespace mean_field::integrators {
|
||||
}
|
||||
return u_n;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mean_field::integrators
|
||||
|
||||
@@ -4,12 +4,18 @@ module mean_field;
|
||||
|
||||
namespace mean_field::integrators {
|
||||
ViscosityIntegrator::ViscosityIntegrator(
|
||||
const mapping::DomainMapper& map,
|
||||
const mapping::DomainMapper &map,
|
||||
const double mu,
|
||||
const int quad_boost
|
||||
) : m_map(map), m_mu(mu), m_quad_boost(quad_boost) {}
|
||||
)
|
||||
: m_map(map),
|
||||
m_mu(mu),
|
||||
m_quad_boost(quad_boost) {
|
||||
}
|
||||
|
||||
void ViscosityIntegrator::SetMu(const double mu) { m_mu = mu; }
|
||||
void ViscosityIntegrator::SetMu(const double mu) {
|
||||
m_mu = mu;
|
||||
}
|
||||
|
||||
void ViscosityIntegrator::AssembleElementVector(
|
||||
const mfem::Array<const mfem::FiniteElement *> &el,
|
||||
@@ -21,19 +27,19 @@ namespace mean_field::integrators {
|
||||
return;
|
||||
}
|
||||
|
||||
void* data_before = (void*)elvec[0]->GetData();
|
||||
int size_before = elvec[0]->Size();
|
||||
void *data_before = (void *)elvec[0]->GetData();
|
||||
int size_before = elvec[0]->Size();
|
||||
|
||||
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& v_dofs = *elfun[0];
|
||||
const mfem::Vector &v_dofs = *elfun[0];
|
||||
|
||||
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]) {
|
||||
@@ -43,12 +49,13 @@ namespace mean_field::integrators {
|
||||
|
||||
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
|
||||
|
||||
const mfem::IntegrationRule* ir = &mfem::IntRules.Get(fe_v->GetGeomType(), 2 * fe_v->GetOrder() + m_quad_boost);
|
||||
const mfem::IntegrationRule *ir = &mfem::IntRules.Get(
|
||||
fe_v->GetGeomType(), 2 * fe_v->GetOrder() + m_quad_boost
|
||||
);
|
||||
|
||||
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);
|
||||
@@ -57,12 +64,13 @@ namespace mean_field::integrators {
|
||||
mfem::Mult(dshape_v_ref, J_inv, dshape_v_phys);
|
||||
|
||||
// ∇v(c,j) = δj v_c
|
||||
mfem::DenseMatrix grad_v(dim, dim); grad_v = 0.0;
|
||||
mfem::DenseMatrix grad_v(dim, dim);
|
||||
grad_v = 0.0;
|
||||
for (int n = 0; n < dof_v; ++n) {
|
||||
for (int c = 0; c < dim; ++c) {
|
||||
const double vn_c = v_dofs(n + c * dof_v);
|
||||
for (int j = 0; j < dim; ++j) {
|
||||
grad_v( c, j) += vn_c * dshape_v_phys(n, j);
|
||||
grad_v(c, j) += vn_c * dshape_v_phys(n, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +88,8 @@ namespace mean_field::integrators {
|
||||
double acc = 0.0;
|
||||
for (int j = 0; j < dim; ++j) {
|
||||
double D_cj = grad_v(c, j) + grad_v(j, c);
|
||||
if (c == j) D_cj -= (2.0 / 3.0) * div_v;
|
||||
if (c == j)
|
||||
D_cj -= (2.0 / 3.0) * div_v;
|
||||
acc += dshape_v_phys(i, j) * D_cj;
|
||||
}
|
||||
r_v(i + c * dof_v) += mu_w * acc;
|
||||
@@ -95,27 +104,33 @@ namespace mean_field::integrators {
|
||||
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();
|
||||
|
||||
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_drho) *dv_drho =0.0;
|
||||
if (dv_dv) *dv_dv = 0.0;
|
||||
if (elmats(1, 0)) *elmats(1, 0) = 0.0;
|
||||
if (elmats(1, 1)) *elmats(1, 1) = 0.0;
|
||||
if (!dv_dv) return;
|
||||
if (dv_drho)
|
||||
*dv_drho = 0.0;
|
||||
if (dv_dv)
|
||||
*dv_dv = 0.0;
|
||||
if (elmats(1, 0))
|
||||
*elmats(1, 0) = 0.0;
|
||||
if (elmats(1, 1))
|
||||
*elmats(1, 1) = 0.0;
|
||||
if (!dv_dv)
|
||||
return;
|
||||
|
||||
mfem::DenseMatrix dshape_v_ref(dof_v, dim), dshape_v_phys(dof_v, dim);
|
||||
|
||||
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);
|
||||
@@ -137,20 +152,20 @@ namespace mean_field::integrators {
|
||||
for (int d = 0; d < dim; ++d) {
|
||||
const int col = n + d * dof_v;
|
||||
|
||||
double val = 0.0;
|
||||
if (c == d) val += dot_grad;
|
||||
double val = 0.0;
|
||||
if (c == d)
|
||||
val += dot_grad;
|
||||
|
||||
val += dshape_v_phys(i, d) * dshape_v_phys(n, c);
|
||||
|
||||
val -= (2.0 / 3.0) * dshape_v_phys(i, c) * dshape_v_phys(n, d);
|
||||
val -= (2.0 / 3.0) * dshape_v_phys(i, c) *
|
||||
dshape_v_phys(n, d);
|
||||
(*dv_dv)(row, col) += mu_w * val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace mean_field::integrators
|
||||
Reference in New Issue
Block a user