feat(FieldDofMap): Completed FieldDofMap migration
also removed legacy BarotropicPolytrope implementation
This commit is contained in:
@@ -12,6 +12,10 @@ namespace mean_field::utils {
|
||||
) {
|
||||
const int dim = fem.mesh->Dimension();
|
||||
x_ref = x_phys_target;
|
||||
mapping::GridFunctionMappingEvaluator mapping_evaluator(
|
||||
*fem.domainMapperStateless, *fem.displacement,
|
||||
*fem.compactificationCoordinate
|
||||
);
|
||||
|
||||
mfem::Array<int> init_elem;
|
||||
mfem::Array<mfem::IntegrationPoint> init_ip;
|
||||
@@ -29,15 +33,18 @@ namespace mean_field::utils {
|
||||
mfem::Array<mfem::IntegrationPoint> origin_ip;
|
||||
fem.mesh->FindPoints(P_origin, origin_elem, origin_ip, false);
|
||||
|
||||
if (origin_elem.Size() > 0 && origin_elem[0] >= 0 && fem.mapping->HasDisplacementField()) {
|
||||
if (origin_elem.Size() > 0 && origin_elem[0] >= 0) {
|
||||
mfem::ElementTransformation *T0 = fem.mesh->GetElementTransformation(origin_elem[0]);
|
||||
T0->SetIntPoint(&origin_ip[0]);
|
||||
|
||||
mfem::DenseMatrix J0(dim, dim), J0_inv(dim, dim);
|
||||
fem.mapping->ComputeJacobian(*T0, J0);
|
||||
mfem::CalcInverse(J0, J0_inv);
|
||||
mapping::MappingPointContext context;
|
||||
MFEM_VERIFY(
|
||||
mapping_evaluator.EvaluatePoint(*T0, origin_ip[0], context) ==
|
||||
mapping::MappingStatus::valid,
|
||||
"Reference-point initialization encountered an invalid mapping."
|
||||
);
|
||||
|
||||
J0_inv.Mult(x_phys_target, x_ref);
|
||||
context.inverse_mapping_jacobian.Mult(x_phys_target, x_ref);
|
||||
}
|
||||
|
||||
init_P.SetCol(0, x_ref);
|
||||
@@ -70,9 +77,6 @@ namespace mean_field::utils {
|
||||
mfem::Vector residual(dim);
|
||||
mfem::Vector step(dim);
|
||||
|
||||
mfem::DenseMatrix J_map(dim, dim);
|
||||
mfem::DenseMatrix J_map_inv(dim, dim);
|
||||
|
||||
int find_failures = 0;
|
||||
|
||||
for (int iter = 0; iter < max_iter; ++iter) {
|
||||
@@ -99,8 +103,12 @@ namespace mean_field::utils {
|
||||
mfem::ElementTransformation *T = fem.mesh->GetElementTransformation(elemID);
|
||||
T->SetIntPoint(&ip);
|
||||
|
||||
mfem::Vector current_x_phys(dim);
|
||||
fem.mapping->GetPhysicalPoint(*T, ip, current_x_phys);
|
||||
mapping::MappingPointContext context;
|
||||
if (mapping_evaluator.EvaluatePoint(*T, ip, context) !=
|
||||
mapping::MappingStatus::valid) {
|
||||
return false;
|
||||
}
|
||||
const mfem::Vector ¤t_x_phys = context.physical_position;
|
||||
|
||||
for (int i = 0; i < dim; ++i) {
|
||||
residual(i) = current_x_phys(i) - x_phys_target(i);
|
||||
@@ -110,9 +118,7 @@ namespace mean_field::utils {
|
||||
return true;
|
||||
}
|
||||
|
||||
fem.mapping->ComputeJacobian(*T, J_map);
|
||||
mfem::CalcInverse(J_map, J_map_inv);
|
||||
J_map_inv.Mult(residual, step);
|
||||
context.inverse_mapping_jacobian.Mult(residual, step);
|
||||
|
||||
double alpha = 1.0;
|
||||
mfem::Vector x_ref_candidate(dim);
|
||||
|
||||
@@ -1,123 +1,24 @@
|
||||
module;
|
||||
#include <expected>
|
||||
#include <mfem.hpp>
|
||||
|
||||
module mean_field;
|
||||
import :boundary.contexts;
|
||||
|
||||
namespace mean_field::utils {
|
||||
DOMAINS operator|(
|
||||
DOMAINS lhs,
|
||||
DOMAINS rhs
|
||||
) {
|
||||
return static_cast<DOMAINS>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
}
|
||||
DOMAINS operator|(DOMAINS lhs, DOMAINS rhs) {
|
||||
return static_cast<DOMAINS>(static_cast<uint8_t>(lhs) |
|
||||
static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
DOMAINS operator&(
|
||||
DOMAINS lhs,
|
||||
DOMAINS rhs
|
||||
) {
|
||||
return static_cast<DOMAINS>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
|
||||
}
|
||||
DOMAINS operator&(DOMAINS lhs, DOMAINS rhs) {
|
||||
return static_cast<DOMAINS>(static_cast<uint8_t>(lhs) &
|
||||
static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
void populate_element_mask(
|
||||
const mfem::Mesh *mesh,
|
||||
const DOMAINS domain,
|
||||
mfem::Array<int> &mask
|
||||
) {
|
||||
const int max_attr = mesh->attributes.Max();
|
||||
mask.SetSize(max_attr);
|
||||
mask = 0;
|
||||
int get_mesh_order(const mfem::Mesh &mesh) {
|
||||
if (mesh.GetNodes() != nullptr) {
|
||||
return mesh.GetNodes()->FESpace()->GetMaxElementOrder();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((domain & DOMAINS::CORE) == DOMAINS::CORE && max_attr >= 1) {
|
||||
mask[0] = 1;
|
||||
}
|
||||
|
||||
if ((domain & DOMAINS::ENVELOPE) == DOMAINS::ENVELOPE && max_attr >= 2) {
|
||||
mask[1] = 1;
|
||||
}
|
||||
|
||||
if ((domain & DOMAINS::VACUUM) == DOMAINS::VACUUM && max_attr >= 3) {
|
||||
mask[2] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void populate_domain_tdofs(
|
||||
const mfem::ParFiniteElementSpace *fes,
|
||||
const mfem::Array<int> &element_mask,
|
||||
mfem::Array<int> &ess_tdof
|
||||
) {
|
||||
mfem::Array<int> vdof_marker(fes->GetVSize());
|
||||
vdof_marker = 0;
|
||||
|
||||
for (int i = 0; i < fes->GetMesh()->GetNE(); i++) {
|
||||
const int attr = fes->GetMesh()->GetAttribute(i);
|
||||
|
||||
if (element_mask[attr - 1]) {
|
||||
mfem::Array<int> dofs;
|
||||
fes->GetElementVDofs(i, dofs);
|
||||
|
||||
for (int j = 0; j < dofs.Size(); j++) {
|
||||
int index = dofs[j];
|
||||
if (index < 0)
|
||||
index = -1 - index;
|
||||
vdof_marker[index] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fes->MarkerToList(vdof_marker, ess_tdof);
|
||||
}
|
||||
|
||||
std::expected<
|
||||
boundary::Bounds,
|
||||
boundary::BoundsError>
|
||||
discover_bounds(
|
||||
const mfem::Mesh *mesh,
|
||||
const int vacuum_attr
|
||||
) {
|
||||
double local_min_r = std::numeric_limits<double>::max();
|
||||
double local_max_r = -std::numeric_limits<double>::max();
|
||||
bool found_vacuum = false;
|
||||
|
||||
for (int i = 0; i < mesh->GetNE(); ++i) {
|
||||
if (mesh->GetAttribute(i) == vacuum_attr) {
|
||||
found_vacuum = true;
|
||||
mfem::Array<int> vertices;
|
||||
mesh->GetElementVertices(i, vertices);
|
||||
for (const int v : vertices) {
|
||||
const double *coords = mesh->GetVertex(v);
|
||||
double r = std::sqrt(coords[0] * coords[0] + coords[1] * coords[1] + coords[2] * coords[2]);
|
||||
local_min_r = std::min(local_min_r, r);
|
||||
local_max_r = std::max(local_max_r, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double global_min_r, global_max_r;
|
||||
int global_found_vacuum;
|
||||
int l_found = found_vacuum ? 1 : 0;
|
||||
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
if (const auto *pmesh = dynamic_cast<const mfem::ParMesh *>(mesh)) {
|
||||
comm = pmesh->GetComm();
|
||||
}
|
||||
|
||||
MPI_Allreduce(&local_min_r, &global_min_r, 1, MPI_DOUBLE, MPI_MIN, comm);
|
||||
MPI_Allreduce(&local_max_r, &global_max_r, 1, MPI_DOUBLE, MPI_MAX, comm);
|
||||
MPI_Allreduce(&l_found, &global_found_vacuum, 1, MPI_INT, MPI_MAX, comm);
|
||||
|
||||
if (global_found_vacuum) {
|
||||
return boundary::Bounds(global_min_r, global_max_r);
|
||||
}
|
||||
return std::unexpected(boundary::BoundsError::CANNOT_FIND_VACUUM);
|
||||
}
|
||||
|
||||
int get_mesh_order(const mfem::Mesh &mesh) {
|
||||
if (mesh.GetNodes() != nullptr) {
|
||||
return mesh.GetNodes()->FESpace()->GetMaxElementOrder();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace mean_field::utils
|
||||
} // namespace mean_field::utils
|
||||
|
||||
Reference in New Issue
Block a user