module; #include module mean_field; namespace mean_field::integrators { GravityForceIntegrator::GravityForceIntegrator( const mapping::DomainMapper& map, const mfem::GridFunction& phi ): m_map(map), m_phi(&phi) {} void GravityForceIntegrator::SetPotential(const mfem::GridFunction& phi) { m_phi = φ }; void GravityForceIntegrator::AssembleElementVector( const mfem::Array &el, mfem::ElementTransformation &Tr, const mfem::Array &elfun, const mfem::Array &elvec ) { if (utils::is_vacuum(Tr, elvec)) { 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 mfem::Vector& rho_dofs = *elfun[1]; 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::Vector shape_v(dof_v), shape_rho(dof_rho); mfem::Vector grad_phi_ref(dim), grad_phi_phys(dim), grad_phi_elem(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_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); fe_v->CalcShape(ip, shape_v); 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_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; } } } } void GravityForceIntegrator::AssembleElementGrad( const mfem::Array &el, mfem::ElementTransformation &Tr, const mfem::Array &elfun, const mfem::Array2D &elmats ) { 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_dv) *dv_dv = 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 grad_phi_ref(dim), grad_phi_phys(dim), grad_phi_elem(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_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); fe_v->CalcShape(ip, shape_v); fe_rho->CalcShape(ip, shape_rho); 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; } } } } } }