Files

178 lines
5.9 KiB
C++

module;
#include <mfem.hpp>
module mean_field;
namespace mean_field::integrators {
ViscosityIntegrator::ViscosityIntegrator(
const mapping::DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
const double mu,
const int quad_boost
)
: m_mapping(
mapper,
displacement,
compactification_coordinate
),
m_mu(mu),
m_quad_boost(quad_boost) {
}
void ViscosityIntegrator::SetMu(const double mu) {
m_mu = mu;
}
void ViscosityIntegrator::AssembleElementVector(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array<mfem::Vector *> &elvec
) {
m_mapping.InvalidateCache();
if (utils::is_vacuum(Tr, elvec)) {
return;
}
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 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];
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;
}
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);
for (int q = 0; q < ir->GetNPoints(); ++q) {
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetIntPoint(&ip);
auto [J_inv, detJ, weight] = m_mapping.GetQuadratureContext(Tr, ip);
fe_v->CalcDShape(ip, dshape_v_ref);
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;
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);
}
}
}
double div_v = 0.0;
for (int c = 0; c < dim; ++c) {
div_v += grad_v(c, c);
}
// D_cj = dj v_c + dc v_j - (2/3) δcj ∇v
// R_v_i^c += μ * weight * ∑_j (δj φi) D_cj
const double mu_w = m_mu * weight;
for (int i = 0; i < dof_v; ++i) {
for (int c = 0; c < dim; ++c) {
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;
acc += dshape_v_phys(i, j) * D_cj;
}
r_v(i + c * dof_v) += mu_w * acc;
}
}
}
}
void ViscosityIntegrator::AssembleElementGrad(
const mfem::Array<const mfem::FiniteElement *> &el,
mfem::ElementTransformation &Tr,
const mfem::Array<const mfem::Vector *> &elfun,
const mfem::Array2D<mfem::DenseMatrix *> &elmats
) {
m_mapping.InvalidateCache();
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();
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;
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());
for (int q = 0; q < ir->GetNPoints(); ++q) {
const mfem::IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetIntPoint(&ip);
auto [J_inv, detJ, weight] = m_mapping.GetQuadratureContext(Tr, ip);
fe_v->CalcDShape(ip, dshape_v_ref);
mfem::Mult(dshape_v_ref, J_inv, dshape_v_phys);
const double mu_w = m_mu * weight;
for (int i = 0; i < dof_v; ++i) {
for (int n = 0; n < dof_v; ++n) {
double dot_grad = 0.0;
for (int j = 0; j < dim; ++j) {
dot_grad += dshape_v_phys(i, j) * dshape_v_phys(n, j);
}
for (int c = 0; c < dim; ++c) {
const int row = i + c * dof_v;
for (int d = 0; d < dim; ++d) {
const int col = n + d * dof_v;
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);
(*dv_dv)(row, col) += mu_w * val;
}
}
}
}
}
}
} // namespace mean_field::integrators