Files
MeanField/libmeanfield/impl/mapping/coefficients.cpp

230 lines
7.3 KiB
C++

module;
#include <mfem.hpp>
module mean_field;
import :mapping.types;
namespace mean_field::mapping {
///////////////////////////////
/// MappedScalarCoefficient ///
//////////////////////////////
MappedScalarCoefficient::MappedScalarCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
Coefficient &coeff,
const COORDINATE_SPACE coord_space
)
: m_mapping(
mapper,
displacement,
compactification_coordinate
),
m_coeff(coeff),
m_coord_space(coord_space) { };
double MappedScalarCoefficient::Eval(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) {
T.SetIntPoint(&ip);
double f_val = 0.0;
switch (m_coord_space) {
case COORDINATE_SPACE::PHYSICAL: {
f_val = eval_at_point(m_coeff, T, ip);
VolumeMappingContext context;
MFEM_VERIFY(
m_mapping.EvaluateVolume(T, ip, context) == MappingStatus::valid,
"Mapped scalar coefficient encountered an invalid mapping."
);
return f_val * std::abs(context.mapping.mapping_determinant);
}
case COORDINATE_SPACE::REFERENCE: {
f_val = m_coeff.Eval(T, ip);
return f_val;
}
}
}
double MappedScalarCoefficient::eval_at_point(
Coefficient &c,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) {
return c.Eval(T, ip);
}
//////////////////////////////////
/// MappedDiffusionCoefficient ///
//////////////////////////////////
MappedDiffusionCoefficient::MappedDiffusionCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
mfem::Coefficient &sigma,
const int dim
)
: MatrixCoefficient(dim),
m_mapping(
mapper,
displacement,
compactification_coordinate
),
m_scalar(&sigma),
m_tensor(nullptr) { };
MappedDiffusionCoefficient::MappedDiffusionCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
MatrixCoefficient &sigma
)
: MatrixCoefficient(sigma.GetHeight()),
m_mapping(
mapper,
displacement,
compactification_coordinate
),
m_scalar(nullptr),
m_tensor(&sigma) { };
void MappedDiffusionCoefficient::Eval(
mfem::DenseMatrix &K,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) {
const int dim = height;
T.SetIntPoint(&ip);
VolumeMappingContext context;
MFEM_VERIFY(
m_mapping.EvaluateVolume(T, ip, context) == MappingStatus::valid,
"Mapped diffusion coefficient encountered an invalid mapping."
);
const mfem::DenseMatrix &JInv = context.mapping.inverse_mapping_jacobian;
const double detJ = context.mapping.mapping_determinant;
if (m_scalar) {
const double sig_val = m_scalar->Eval(T, ip);
mfem::MultABt(JInv, JInv, K);
K *= sig_val * fabs(detJ);
} else {
mfem::DenseMatrix sig_mat(dim, dim);
m_tensor->Eval(sig_mat, T, ip);
mfem::DenseMatrix temp(dim, dim);
Mult(JInv, sig_mat, temp);
MultABt(temp, JInv, K);
K *= fabs(detJ);
}
}
///////////////////////////////
/// MappedVectorCoefficient ///
///////////////////////////////
MappedVectorCoefficient::MappedVectorCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
VectorCoefficient &coeff
)
: VectorCoefficient(coeff.GetVDim()),
m_mapping(
mapper,
displacement,
compactification_coordinate
),
m_coeff(coeff) { };
void MappedVectorCoefficient::Eval(
mfem::Vector &V,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) {
const int dim = vdim;
T.SetIntPoint(&ip);
VolumeMappingContext context;
MFEM_VERIFY(
m_mapping.EvaluateVolume(T, ip, context) == MappingStatus::valid,
"Mapped vector coefficient encountered an invalid mapping."
);
const mfem::DenseMatrix &JInv = context.mapping.inverse_mapping_jacobian;
const double detJ = context.mapping.mapping_determinant;
mfem::Vector C_phys(dim);
m_coeff.Eval(C_phys, T, ip);
V.SetSize(dim);
JInv.MultTranspose(C_phys, V);
V *= fabs(detJ);
}
///////////////////////////////////////////
/// PhysicalPositionFunctionCoefficient ///
///////////////////////////////////////////
PhysicalPositionFunctionCoefficient::PhysicalPositionFunctionCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
Func f // std::function<double(const mfem::Vector&)>
)
: m_f(std::move(f)),
m_mapping(
mapper,
displacement,
compactification_coordinate
) { };
double PhysicalPositionFunctionCoefficient::Eval(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) {
T.SetIntPoint(&ip);
MappingPointContext context;
MFEM_VERIFY(
m_mapping.EvaluatePoint(T, ip, context) == MappingStatus::valid,
"Physical-position coefficient encountered an invalid mapping."
);
return m_f(context.physical_position);
}
MappedHDivMassCoefficient::MappedHDivMassCoefficient(
const DomainMapper &mapper,
const mfem::GridFunction &displacement,
const mfem::GridFunction &compactification_coordinate,
const int dim
)
: MatrixCoefficient(dim),
m_mapping(
mapper,
displacement,
compactification_coordinate
) {
}
void MappedHDivMassCoefficient::Eval(
mfem::DenseMatrix &matrix,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point
) {
transformation.SetIntPoint(&integration_point);
VolumeMappingContext context;
MFEM_VERIFY(
m_mapping.EvaluateVolume(transformation, integration_point, context) == MappingStatus::valid,
"Mapped H(div) coefficient encountered an invalid mapping."
);
const mfem::DenseMatrix &map_jacobian = context.mapping.mapping_jacobian;
const double map_determinant = context.mapping.mapping_determinant;
MFEM_VERIFY(map_determinant > 0.0, "Domain mapping has a non-positive Jacobian determinant.");
mfem::MultAtB(map_jacobian, map_jacobian, matrix);
matrix *= 1.0 / std::abs(map_determinant);
}
} // namespace mean_field::mapping