feat(field-support): added field support system, mid migration
currently the barotope and the pressure force operator are migrated to the new support system
This commit is contained in:
@@ -168,10 +168,7 @@ namespace mean_field::mapping {
|
||||
|
||||
const double map_determinant = map_jacobian.Det();
|
||||
|
||||
MFEM_VERIFY(
|
||||
map_determinant > 0.0,
|
||||
"Domain mapping has a non-positive Jacobian 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);
|
||||
|
||||
@@ -27,26 +27,17 @@ namespace {
|
||||
} // namespace
|
||||
|
||||
namespace mean_field::mapping::compactification {
|
||||
KelvinCompactification::KelvinCompactification(
|
||||
options::KelvinCompactificationOptions options
|
||||
)
|
||||
KelvinCompactification::KelvinCompactification(options::KelvinCompactificationOptions options)
|
||||
: m_options(options) {
|
||||
if (!std::isfinite(m_options.r_star_ref) ||
|
||||
!std::isfinite(m_options.r_inf_ref)) {
|
||||
throw std::invalid_argument(
|
||||
"Kelvin compactification radii must be finite."
|
||||
);
|
||||
if (!std::isfinite(m_options.r_star_ref) || !std::isfinite(m_options.r_inf_ref)) {
|
||||
throw std::invalid_argument("Kelvin compactification radii must be finite.");
|
||||
}
|
||||
|
||||
if (m_options.r_star_ref <= 0.0 ||
|
||||
m_options.r_inf_ref <= m_options.r_star_ref) {
|
||||
throw std::invalid_argument(
|
||||
"Kelvin compactification requires 0 < r_star_ref < r_inf_ref."
|
||||
);
|
||||
if (m_options.r_star_ref <= 0.0 || m_options.r_inf_ref <= m_options.r_star_ref) {
|
||||
throw std::invalid_argument("Kelvin compactification requires 0 < r_star_ref < r_inf_ref.");
|
||||
}
|
||||
|
||||
if (!std::isfinite(m_options.coordinate_tolerance) ||
|
||||
m_options.coordinate_tolerance < 0.0 ||
|
||||
if (!std::isfinite(m_options.coordinate_tolerance) || m_options.coordinate_tolerance < 0.0 ||
|
||||
m_options.coordinate_tolerance >= 1.0) {
|
||||
throw std::invalid_argument(
|
||||
"Kelvin compactification coordinate tolerance must be finite "
|
||||
@@ -65,8 +56,7 @@ namespace mean_field::mapping::compactification {
|
||||
|
||||
const double tolerance = m_options.coordinate_tolerance;
|
||||
|
||||
if (compactification_coordinate < -tolerance ||
|
||||
compactification_coordinate > 1.0 + tolerance) {
|
||||
if (compactification_coordinate < -tolerance || compactification_coordinate > 1.0 + tolerance) {
|
||||
return MappingStatus::outside_reference_domain;
|
||||
}
|
||||
|
||||
@@ -78,26 +68,22 @@ namespace mean_field::mapping::compactification {
|
||||
return MappingStatus::at_compactified_infinity;
|
||||
}
|
||||
|
||||
const double radial_extent = m_options.r_inf_ref - m_options.r_star_ref;
|
||||
const double computational_radius =
|
||||
m_options.r_star_ref + coordinate * radial_extent;
|
||||
const double radial_extent = m_options.r_inf_ref - m_options.r_star_ref;
|
||||
const double computational_radius = m_options.r_star_ref + coordinate * radial_extent;
|
||||
|
||||
if (!std::isfinite(computational_radius) ||
|
||||
computational_radius <= 0.0) {
|
||||
if (!std::isfinite(computational_radius) || computational_radius <= 0.0) {
|
||||
return MappingStatus::invalid_reference_radius;
|
||||
}
|
||||
|
||||
const double one_minus_coordinate = 1.0 - coordinate;
|
||||
const double denominator = computational_radius * one_minus_coordinate;
|
||||
const double denominator = computational_radius * one_minus_coordinate;
|
||||
|
||||
if (!std::isfinite(denominator) || denominator <= 0.0) {
|
||||
return MappingStatus::non_finite_result;
|
||||
}
|
||||
|
||||
const double scale = m_options.r_star_ref / denominator;
|
||||
const double scale_derivative =
|
||||
scale *
|
||||
(1.0 / one_minus_coordinate - radial_extent / computational_radius);
|
||||
const double scale = m_options.r_star_ref / denominator;
|
||||
const double scale_derivative = scale * (1.0 / one_minus_coordinate - radial_extent / computational_radius);
|
||||
|
||||
if (!std::isfinite(scale) || !std::isfinite(scale_derivative)) {
|
||||
return MappingStatus::non_finite_result;
|
||||
@@ -122,21 +108,18 @@ namespace mean_field::mapping::compactification {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
|
||||
if (input.displacement_jacobian.Height() != dimension ||
|
||||
input.displacement_jacobian.Width() != dimension) {
|
||||
if (input.displacement_jacobian.Height() != dimension || input.displacement_jacobian.Width() != dimension) {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
|
||||
if (!vector_is_finite(input.reference_position) ||
|
||||
!vector_is_finite(input.displaced_position) ||
|
||||
if (!vector_is_finite(input.reference_position) || !vector_is_finite(input.displaced_position) ||
|
||||
!vector_is_finite(input.compactification_coordinate_gradient) ||
|
||||
!matrix_is_finite(input.displacement_jacobian)) {
|
||||
return MappingStatus::non_finite_input;
|
||||
}
|
||||
|
||||
RadialFactors factors;
|
||||
const MappingStatus factor_status =
|
||||
ComputeRadialFactors(input.compactification_coordinate, factors);
|
||||
const MappingStatus factor_status = ComputeRadialFactors(input.compactification_coordinate, factors);
|
||||
if (factor_status != MappingStatus::valid)
|
||||
return factor_status;
|
||||
|
||||
@@ -144,21 +127,16 @@ namespace mean_field::mapping::compactification {
|
||||
result.mapping_jacobian.SetSize(dimension, dimension);
|
||||
|
||||
for (int i = 0; i < dimension; ++i) {
|
||||
result.physical_position(i) =
|
||||
factors.scale * input.displaced_position(i);
|
||||
result.physical_position(i) = factors.scale * input.displaced_position(i);
|
||||
|
||||
for (int j = 0; j < dimension; ++j) {
|
||||
const double scale_gradient =
|
||||
factors.scale_derivative *
|
||||
input.compactification_coordinate_gradient(j);
|
||||
const double scale_gradient = factors.scale_derivative * input.compactification_coordinate_gradient(j);
|
||||
result.mapping_jacobian(i, j) =
|
||||
factors.scale * input.displacement_jacobian(i, j) +
|
||||
input.displaced_position(i) * scale_gradient;
|
||||
factors.scale * input.displacement_jacobian(i, j) + input.displaced_position(i) * scale_gradient;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vector_is_finite(result.physical_position) ||
|
||||
!matrix_is_finite(result.mapping_jacobian)) {
|
||||
if (!vector_is_finite(result.physical_position) || !matrix_is_finite(result.mapping_jacobian)) {
|
||||
return MappingStatus::non_finite_result;
|
||||
}
|
||||
|
||||
@@ -185,13 +163,11 @@ namespace mean_field::mapping::compactification {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
|
||||
if (input.displacement_jacobian.Height() != dimension ||
|
||||
input.displacement_jacobian.Width() != dimension) {
|
||||
if (input.displacement_jacobian.Height() != dimension || input.displacement_jacobian.Width() != dimension) {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
|
||||
if (result.physical_position.Size() != dimension ||
|
||||
result.mapping_jacobian.Height() != dimension ||
|
||||
if (result.physical_position.Size() != dimension || result.mapping_jacobian.Height() != dimension ||
|
||||
result.mapping_jacobian.Width() != dimension) {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
@@ -202,23 +178,20 @@ namespace mean_field::mapping::compactification {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
|
||||
if (!vector_is_finite(input.reference_position) ||
|
||||
!vector_is_finite(input.displaced_position) ||
|
||||
if (!vector_is_finite(input.reference_position) || !vector_is_finite(input.displaced_position) ||
|
||||
!vector_is_finite(input.compactification_coordinate_gradient) ||
|
||||
!matrix_is_finite(input.displacement_jacobian)) {
|
||||
return MappingStatus::non_finite_input;
|
||||
}
|
||||
|
||||
if (!vector_is_finite(result.physical_position) ||
|
||||
!matrix_is_finite(result.mapping_jacobian) ||
|
||||
if (!vector_is_finite(result.physical_position) || !matrix_is_finite(result.mapping_jacobian) ||
|
||||
!vector_is_finite(direction.displaced_position_variation) ||
|
||||
!matrix_is_finite(direction.displacement_jacobian_variation)) {
|
||||
return MappingStatus::non_finite_input;
|
||||
}
|
||||
|
||||
RadialFactors factors;
|
||||
const MappingStatus factor_status =
|
||||
ComputeRadialFactors(input.compactification_coordinate, factors);
|
||||
const MappingStatus factor_status = ComputeRadialFactors(input.compactification_coordinate, factors);
|
||||
if (factor_status != MappingStatus::valid)
|
||||
return factor_status;
|
||||
|
||||
@@ -226,16 +199,12 @@ namespace mean_field::mapping::compactification {
|
||||
variation.mapping_jacobian_variation.SetSize(dimension, dimension);
|
||||
|
||||
for (int i = 0; i < dimension; ++i) {
|
||||
variation.physical_position_variation(i) =
|
||||
factors.scale * direction.displaced_position_variation(i);
|
||||
variation.physical_position_variation(i) = factors.scale * direction.displaced_position_variation(i);
|
||||
|
||||
for (int j = 0; j < dimension; ++j) {
|
||||
const double scale_gradient =
|
||||
factors.scale_derivative *
|
||||
input.compactification_coordinate_gradient(j);
|
||||
const double scale_gradient = factors.scale_derivative * input.compactification_coordinate_gradient(j);
|
||||
variation.mapping_jacobian_variation(i, j) =
|
||||
factors.scale *
|
||||
direction.displacement_jacobian_variation(i, j) +
|
||||
factors.scale * direction.displacement_jacobian_variation(i, j) +
|
||||
direction.displaced_position_variation(i) * scale_gradient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,7 @@ namespace {
|
||||
domain_mapper.ComputeJacobian(transformation, map_jacobian);
|
||||
|
||||
const double map_determinant = map_jacobian.Det();
|
||||
MFEM_VERIFY(
|
||||
map_determinant > 0.0,
|
||||
"Domain mapping has a non-positive Jacobian determinant."
|
||||
);
|
||||
MFEM_VERIFY(map_determinant > 0.0, "Domain mapping has a non-positive Jacobian determinant.");
|
||||
return map_determinant;
|
||||
}
|
||||
} // namespace
|
||||
@@ -32,8 +29,7 @@ namespace mean_field::mapping {
|
||||
m_r_star_ref(r_star_ref),
|
||||
m_r_inf_ref(r_inf_ref) {
|
||||
InitAllScratchSpaces();
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true
|
||||
: m_displacement_is_identity = false;
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true : m_displacement_is_identity = false;
|
||||
}
|
||||
|
||||
DomainMapper::DomainMapper(
|
||||
@@ -46,8 +42,7 @@ namespace mean_field::mapping {
|
||||
m_r_star_ref(r_star_ref),
|
||||
m_r_inf_ref(r_inf_ref) {
|
||||
InitAllScratchSpaces();
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true
|
||||
: m_displacement_is_identity = false;
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true : m_displacement_is_identity = false;
|
||||
}
|
||||
|
||||
bool DomainMapper::is_vacuum(const mfem::ElementTransformation &T) const {
|
||||
@@ -76,14 +71,12 @@ namespace mean_field::mapping {
|
||||
m_d = &d;
|
||||
InvalidateCache();
|
||||
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true
|
||||
: m_displacement_is_identity = false;
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true : m_displacement_is_identity = false;
|
||||
}
|
||||
|
||||
bool DomainMapper::HasCompactification() const noexcept {
|
||||
return std::isfinite(m_r_star_ref) && std::isfinite(m_r_inf_ref) &&
|
||||
m_r_star_ref > 0.0 && m_r_inf_ref > m_r_star_ref &&
|
||||
m_xi_clamp > 0.0 && m_xi_clamp < 1.0;
|
||||
return std::isfinite(m_r_star_ref) && std::isfinite(m_r_inf_ref) && m_r_star_ref > 0.0 &&
|
||||
m_r_inf_ref > m_r_star_ref && m_xi_clamp > 0.0 && m_xi_clamp < 1.0;
|
||||
}
|
||||
|
||||
bool DomainMapper::HasDisplacementField() const noexcept {
|
||||
@@ -95,10 +88,9 @@ namespace mean_field::mapping {
|
||||
return true;
|
||||
}
|
||||
|
||||
const int local_identity = m_d->Normlinf() == 0.0 ? 1 : 0;
|
||||
const int local_identity = m_d->Normlinf() == 0.0 ? 1 : 0;
|
||||
|
||||
const auto *parallel_displacement =
|
||||
dynamic_cast<const mfem::ParGridFunction *>(m_d);
|
||||
const auto *parallel_displacement = dynamic_cast<const mfem::ParGridFunction *>(m_d);
|
||||
|
||||
if (parallel_displacement == nullptr) {
|
||||
return local_identity == 1;
|
||||
@@ -106,8 +98,7 @@ namespace mean_field::mapping {
|
||||
|
||||
int global_identity = 0;
|
||||
MPI_Allreduce(
|
||||
&local_identity, &global_identity, 1, MPI_INT, MPI_MIN,
|
||||
parallel_displacement->ParFESpace()->GetComm()
|
||||
&local_identity, &global_identity, 1, MPI_INT, MPI_MIN, parallel_displacement->ParFESpace()->GetComm()
|
||||
);
|
||||
|
||||
return global_identity == 1;
|
||||
@@ -116,8 +107,7 @@ namespace mean_field::mapping {
|
||||
void DomainMapper::ResetDisplacement() {
|
||||
m_d = nullptr;
|
||||
InvalidateCache();
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true
|
||||
: m_displacement_is_identity = false;
|
||||
CalcIsIdentity() ? m_displacement_is_identity = true : m_displacement_is_identity = false;
|
||||
}
|
||||
|
||||
void DomainMapper::ComputeJacobian(
|
||||
@@ -223,11 +213,7 @@ namespace mean_field::mapping {
|
||||
mfem::Vector n_unit(dim);
|
||||
n_unit = n_raw;
|
||||
n_unit /= n_raw_mag;
|
||||
return FaceQuadratureContext{
|
||||
.normal = n_unit,
|
||||
.ds = ip.weight * n_raw_mag,
|
||||
.v_dot_n_scale = 1.0
|
||||
};
|
||||
return FaceQuadratureContext{.normal = n_unit, .ds = ip.weight * n_raw_mag, .v_dot_n_scale = 1.0};
|
||||
}
|
||||
|
||||
// Nanson's Formula
|
||||
@@ -253,9 +239,7 @@ namespace mean_field::mapping {
|
||||
const double n_raw_mag = n_raw.Norml2();
|
||||
|
||||
return FaceQuadratureContext{
|
||||
.normal = n_unit,
|
||||
.ds = ip.weight * n_raw_mag,
|
||||
.v_dot_n_scale = n_phys_mag / n_raw_mag
|
||||
.normal = n_unit, .ds = ip.weight * n_raw_mag, .v_dot_n_scale = n_phys_mag / n_raw_mag
|
||||
};
|
||||
}
|
||||
|
||||
@@ -297,15 +281,11 @@ namespace mean_field::mapping {
|
||||
const mfem::Vector &reference_flux,
|
||||
mfem::Vector &physical_flux
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
reference_flux.Size() == m_dim,
|
||||
"The reference H(div) flux has the wrong dimension."
|
||||
);
|
||||
MFEM_VERIFY(reference_flux.Size() == m_dim, "The reference H(div) flux has the wrong dimension.");
|
||||
|
||||
mfem::DenseMatrix map_jacobian(m_dim, m_dim);
|
||||
const double map_determinant = get_positive_map_jacobian(
|
||||
*this, transformation, integration_point, map_jacobian
|
||||
);
|
||||
const double map_determinant =
|
||||
get_positive_map_jacobian(*this, transformation, integration_point, map_jacobian);
|
||||
|
||||
mfem::Vector mapped_flux(m_dim);
|
||||
map_jacobian.Mult(reference_flux, mapped_flux);
|
||||
@@ -320,15 +300,11 @@ namespace mean_field::mapping {
|
||||
const mfem::Vector &physical_flux,
|
||||
mfem::Vector &reference_flux
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
physical_flux.Size() == m_dim,
|
||||
"The physical flux has the wrong dimension."
|
||||
);
|
||||
MFEM_VERIFY(physical_flux.Size() == m_dim, "The physical flux has the wrong dimension.");
|
||||
|
||||
mfem::DenseMatrix map_jacobian(m_dim, m_dim);
|
||||
const double map_determinant = get_positive_map_jacobian(
|
||||
*this, transformation, integration_point, map_jacobian
|
||||
);
|
||||
const double map_determinant =
|
||||
get_positive_map_jacobian(*this, transformation, integration_point, map_jacobian);
|
||||
|
||||
mfem::DenseMatrix inverse_map_jacobian(m_dim, m_dim);
|
||||
mfem::CalcInverse(map_jacobian, inverse_map_jacobian);
|
||||
@@ -346,15 +322,10 @@ namespace mean_field::mapping {
|
||||
const mfem::Vector &reference_gradient,
|
||||
mfem::Vector &physical_gradient
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
reference_gradient.Size() == m_dim,
|
||||
"The reference gradient has the wrong dimension."
|
||||
);
|
||||
MFEM_VERIFY(reference_gradient.Size() == m_dim, "The reference gradient has the wrong dimension.");
|
||||
|
||||
mfem::DenseMatrix map_jacobian(m_dim, m_dim);
|
||||
get_positive_map_jacobian(
|
||||
*this, transformation, integration_point, map_jacobian
|
||||
);
|
||||
get_positive_map_jacobian(*this, transformation, integration_point, map_jacobian);
|
||||
|
||||
mfem::DenseMatrix inverse_map_jacobian(m_dim, m_dim);
|
||||
mfem::CalcInverse(map_jacobian, inverse_map_jacobian);
|
||||
@@ -382,8 +353,7 @@ namespace mean_field::mapping {
|
||||
}
|
||||
|
||||
double DomainMapper::GetCacheHitRate() const {
|
||||
return (static_cast<double>(m_cache_hits)) /
|
||||
static_cast<double>(m_cache_misses + m_cache_hits);
|
||||
return (static_cast<double>(m_cache_hits)) / static_cast<double>(m_cache_misses + m_cache_hits);
|
||||
}
|
||||
|
||||
void DomainMapper::ResetCacheStats() const {
|
||||
@@ -404,9 +374,9 @@ namespace mean_field::mapping {
|
||||
const mfem::Vector &x_ref,
|
||||
mfem::Vector &x_phys
|
||||
) const {
|
||||
const double r_ref = x_ref.Norml2();
|
||||
double xi = (r_ref - m_r_star_ref) / (m_r_inf_ref - m_r_star_ref);
|
||||
xi = std::clamp(xi, 0.0, m_xi_clamp);
|
||||
const double r_ref = x_ref.Norml2();
|
||||
double xi = (r_ref - m_r_star_ref) / (m_r_inf_ref - m_r_star_ref);
|
||||
xi = std::clamp(xi, 0.0, m_xi_clamp);
|
||||
const double factor = m_r_star_ref / (r_ref * (1 - xi));
|
||||
x_phys *= factor;
|
||||
}
|
||||
@@ -428,8 +398,7 @@ namespace mean_field::mapping {
|
||||
const double k = m_r_star_ref / (r_ref * denom);
|
||||
|
||||
const double dk_dr =
|
||||
m_r_star_ref * ((1.0 / (delta_R * r_ref * denom * denom)) -
|
||||
(1.0 / (r_ref * r_ref * denom)));
|
||||
m_r_star_ref * ((1.0 / (delta_R * r_ref * denom * denom)) - (1.0 / (r_ref * r_ref * denom)));
|
||||
|
||||
J.SetSize(m_dim, m_dim);
|
||||
const double outer_factor = dk_dr / r_ref;
|
||||
@@ -445,14 +414,11 @@ namespace mean_field::mapping {
|
||||
m_cached_elem_id = -1;
|
||||
}
|
||||
|
||||
void DomainMapper::UpdateElementCache(
|
||||
const mfem::ElementTransformation &T
|
||||
) const {
|
||||
void DomainMapper::UpdateElementCache(const mfem::ElementTransformation &T) const {
|
||||
if (!HasDisplacementField())
|
||||
return;
|
||||
|
||||
if (T.ElementNo != m_cached_elem_id ||
|
||||
T.ElementType != m_cached_elem_type) {
|
||||
if (T.ElementNo != m_cached_elem_id || T.ElementType != m_cached_elem_type) {
|
||||
m_cache_misses++;
|
||||
m_cached_elem_id = T.ElementNo;
|
||||
m_cached_elem_type = T.ElementType;
|
||||
|
||||
@@ -39,9 +39,7 @@ namespace mean_field::mapping {
|
||||
: m_element(&element),
|
||||
m_dofs(dofs) {
|
||||
if (element.GetRangeType() != mfem::FiniteElement::SCALAR) {
|
||||
throw std::invalid_argument(
|
||||
"Compactification coordinate requires a scalar finite element."
|
||||
);
|
||||
throw std::invalid_argument("Compactification coordinate requires a scalar finite element.");
|
||||
}
|
||||
|
||||
if (element.GetMapType() != mfem::FiniteElement::VALUE) {
|
||||
@@ -75,8 +73,7 @@ namespace mean_field::mapping {
|
||||
}
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &
|
||||
ElementCompactificationData::GetElement() const noexcept {
|
||||
const mfem::FiniteElement &ElementCompactificationData::GetElement() const noexcept {
|
||||
return *m_element;
|
||||
}
|
||||
|
||||
@@ -102,8 +99,7 @@ namespace mean_field::mapping {
|
||||
"The displacement element must have at least one degree of "
|
||||
"freedom."
|
||||
);
|
||||
if (displacement_dofs.Size() <= 0 ||
|
||||
displacement_dofs.Size() % dof_count != 0) {
|
||||
if (displacement_dofs.Size() <= 0 || displacement_dofs.Size() % dof_count != 0) {
|
||||
throw std::invalid_argument(
|
||||
"The displacement vector size must be a positive multiple of "
|
||||
"the "
|
||||
@@ -117,31 +113,25 @@ namespace mean_field::mapping {
|
||||
if (ordering == mfem::Ordering::byNODES) {
|
||||
for (int component = 0; component < m_dimension; ++component) {
|
||||
for (int i = 0; i < dof_count; ++i) {
|
||||
m_dof_matrix(i, component) =
|
||||
displacement_dofs(i + component * dof_count);
|
||||
m_dof_matrix(i, component) = displacement_dofs(i + component * dof_count);
|
||||
}
|
||||
}
|
||||
} else if (ordering == mfem::Ordering::byVDIM) {
|
||||
for (int i = 0; i < dof_count; ++i) {
|
||||
for (int component = 0; component < m_dimension; ++component) {
|
||||
m_dof_matrix(i, component) =
|
||||
displacement_dofs(component + i * m_dimension);
|
||||
m_dof_matrix(i, component) = displacement_dofs(component + i * m_dimension);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw std::invalid_argument(
|
||||
"Unsupported MFEM displacement ordering."
|
||||
);
|
||||
throw std::invalid_argument("Unsupported MFEM displacement ordering.");
|
||||
}
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &
|
||||
ElementDisplacementData::GetElement() const noexcept {
|
||||
const mfem::FiniteElement &ElementDisplacementData::GetElement() const noexcept {
|
||||
return *m_element;
|
||||
}
|
||||
|
||||
const mfem::DenseMatrix &
|
||||
ElementDisplacementData::GetDofMatrix() const noexcept {
|
||||
const mfem::DenseMatrix &ElementDisplacementData::GetDofMatrix() const noexcept {
|
||||
return m_dof_matrix;
|
||||
}
|
||||
|
||||
@@ -161,9 +151,7 @@ namespace mean_field::mapping {
|
||||
const mfem::FiniteElement &element,
|
||||
const mfem::Vector &displacement_dofs
|
||||
) {
|
||||
return ElementDisplacementData(
|
||||
element, displacement_dofs, mfem::Ordering::byNODES
|
||||
);
|
||||
return ElementDisplacementData(element, displacement_dofs, mfem::Ordering::byNODES);
|
||||
}
|
||||
|
||||
DomainMapperStateless::Workspace::Workspace(const int dimension) {
|
||||
@@ -172,9 +160,7 @@ namespace mean_field::mapping {
|
||||
|
||||
void DomainMapperStateless::Workspace::SetDimension(const int dimension) {
|
||||
if (dimension <= 0) {
|
||||
throw std::invalid_argument(
|
||||
"Domain mapping workspace dimension must be positive."
|
||||
);
|
||||
throw std::invalid_argument("Domain mapping workspace dimension must be positive.");
|
||||
}
|
||||
|
||||
m_dimension = dimension;
|
||||
@@ -197,9 +183,7 @@ namespace mean_field::mapping {
|
||||
m_exterior_result.mapping_jacobian.SetSize(dimension, dimension);
|
||||
|
||||
m_exterior_variation.physical_position_variation.SetSize(dimension);
|
||||
m_exterior_variation.mapping_jacobian_variation.SetSize(
|
||||
dimension, dimension
|
||||
);
|
||||
m_exterior_variation.mapping_jacobian_variation.SetSize(dimension, dimension);
|
||||
}
|
||||
|
||||
int DomainMapperStateless::Workspace::GetDimension() const noexcept {
|
||||
@@ -213,22 +197,15 @@ namespace mean_field::mapping {
|
||||
: m_options(options),
|
||||
m_exterior_map(std::move(exterior_map)) {
|
||||
if (m_options.dimension <= 0)
|
||||
throw std::invalid_argument(
|
||||
"The domain-mapping dimension must be positive."
|
||||
);
|
||||
throw std::invalid_argument("The domain-mapping dimension must be positive.");
|
||||
if (m_options.vacuum_element_attribute <= 0)
|
||||
throw std::invalid_argument(
|
||||
"The vacuum element attribute must be positive."
|
||||
);
|
||||
throw std::invalid_argument("The vacuum element attribute must be positive.");
|
||||
if (!m_exterior_map)
|
||||
throw std::invalid_argument(
|
||||
"DomainMapperStateless requires an exterior-domain mapping."
|
||||
);
|
||||
throw std::invalid_argument("DomainMapperStateless requires an exterior-domain mapping.");
|
||||
}
|
||||
|
||||
bool DomainMapperStateless::IsCompactifiedElement(
|
||||
const mfem::ElementTransformation &transformation
|
||||
) const noexcept {
|
||||
bool
|
||||
DomainMapperStateless::IsCompactifiedElement(const mfem::ElementTransformation &transformation) const noexcept {
|
||||
return transformation.Attribute == m_options.vacuum_element_attribute;
|
||||
}
|
||||
|
||||
@@ -240,17 +217,13 @@ namespace mean_field::mapping {
|
||||
return m_options.vacuum_element_attribute;
|
||||
}
|
||||
|
||||
const compactification::ExteriorDomainMap &
|
||||
DomainMapperStateless::GetExteriorMap() const noexcept {
|
||||
const compactification::ExteriorDomainMap &DomainMapperStateless::GetExteriorMap() const noexcept {
|
||||
return *m_exterior_map;
|
||||
}
|
||||
|
||||
void DomainMapperStateless::ValidateElementData(
|
||||
const ElementMappingData &element_data
|
||||
) const {
|
||||
const ElementDisplacementData &displacement = element_data.displacement;
|
||||
const ElementCompactificationData &compactification =
|
||||
element_data.compactification;
|
||||
void DomainMapperStateless::ValidateElementData(const ElementMappingData &element_data) const {
|
||||
const ElementDisplacementData &displacement = element_data.displacement;
|
||||
const ElementCompactificationData &compactification = element_data.compactification;
|
||||
|
||||
if (displacement.GetDimension() != m_options.dimension) {
|
||||
throw std::invalid_argument(
|
||||
@@ -275,8 +248,7 @@ namespace mean_field::mapping {
|
||||
);
|
||||
}
|
||||
|
||||
if (displacement.GetElement().GetGeomType() !=
|
||||
compactification.GetElement().GetGeomType()) {
|
||||
if (displacement.GetElement().GetGeomType() != compactification.GetElement().GetGeomType()) {
|
||||
throw std::invalid_argument(
|
||||
"Displacement and compactification finite elements have "
|
||||
"different "
|
||||
@@ -284,31 +256,25 @@ namespace mean_field::mapping {
|
||||
);
|
||||
}
|
||||
|
||||
if (compactification.GetElement().GetRangeType() !=
|
||||
mfem::FiniteElement::SCALAR) {
|
||||
throw std::invalid_argument(
|
||||
"Compactification coordinate requires a scalar finite element."
|
||||
);
|
||||
if (compactification.GetElement().GetRangeType() != mfem::FiniteElement::SCALAR) {
|
||||
throw std::invalid_argument("Compactification coordinate requires a scalar finite element.");
|
||||
}
|
||||
|
||||
if (compactification.GetElement().GetMapType() !=
|
||||
mfem::FiniteElement::VALUE) {
|
||||
if (compactification.GetElement().GetMapType() != mfem::FiniteElement::VALUE) {
|
||||
throw std::invalid_argument(
|
||||
"Compactification coordinate requires a value-mapped finite "
|
||||
"element."
|
||||
);
|
||||
}
|
||||
|
||||
if (compactification.GetElement().GetDerivType() !=
|
||||
mfem::FiniteElement::GRAD) {
|
||||
if (compactification.GetElement().GetDerivType() != mfem::FiniteElement::GRAD) {
|
||||
throw std::invalid_argument(
|
||||
"Compactification coordinate finite element does not provide a "
|
||||
"gradient."
|
||||
);
|
||||
}
|
||||
|
||||
if (compactification.GetDofCount() !=
|
||||
compactification.GetElement().GetDof()) {
|
||||
if (compactification.GetDofCount() != compactification.GetElement().GetDof()) {
|
||||
throw std::invalid_argument(
|
||||
"Compactification coordinate DOF count does not match its "
|
||||
"finite "
|
||||
@@ -328,8 +294,7 @@ namespace mean_field::mapping {
|
||||
const mfem::Vector &dofs = compactification.GetDofs();
|
||||
const int dof_count = element.GetDof();
|
||||
|
||||
if (workspace.GetDimension() != m_options.dimension ||
|
||||
transformation.GetSpaceDim() != m_options.dimension ||
|
||||
if (workspace.GetDimension() != m_options.dimension || transformation.GetSpaceDim() != m_options.dimension ||
|
||||
element.GetDim() != m_options.dimension) {
|
||||
return MappingStatus::invalid_dimension;
|
||||
}
|
||||
@@ -346,22 +311,14 @@ namespace mean_field::mapping {
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
workspace.m_compactification_shape.SetSize(dof_count);
|
||||
workspace.m_compactification_dshape.SetSize(
|
||||
dof_count, m_options.dimension
|
||||
);
|
||||
workspace.m_compactification_dshape.SetSize(dof_count, m_options.dimension);
|
||||
|
||||
element.CalcShape(
|
||||
integration_point, workspace.m_compactification_shape
|
||||
);
|
||||
element.CalcPhysDShape(
|
||||
transformation, workspace.m_compactification_dshape
|
||||
);
|
||||
element.CalcShape(integration_point, workspace.m_compactification_shape);
|
||||
element.CalcPhysDShape(transformation, workspace.m_compactification_dshape);
|
||||
|
||||
point_data.coordinate = dofs * workspace.m_compactification_shape;
|
||||
point_data.coordinate_gradient.SetSize(m_options.dimension);
|
||||
workspace.m_compactification_dshape.MultTranspose(
|
||||
dofs, point_data.coordinate_gradient
|
||||
);
|
||||
workspace.m_compactification_dshape.MultTranspose(dofs, point_data.coordinate_gradient);
|
||||
|
||||
if (!std::isfinite(point_data.coordinate)) {
|
||||
return MappingStatus::non_finite_result;
|
||||
@@ -411,15 +368,10 @@ namespace mean_field::mapping {
|
||||
ValidateElementData(element_data);
|
||||
|
||||
if (workspace.GetDimension() != m_options.dimension)
|
||||
throw std::invalid_argument(
|
||||
"The mapping workspace has the wrong dimension."
|
||||
);
|
||||
throw std::invalid_argument("The mapping workspace has the wrong dimension.");
|
||||
if (transformation.GetSpaceDim() != m_options.dimension)
|
||||
throw std::invalid_argument(
|
||||
"The element transformation has the wrong spatial dimension."
|
||||
);
|
||||
if (transformation.GetGeometryType() !=
|
||||
element_data.displacement.GetElement().GetGeomType())
|
||||
throw std::invalid_argument("The element transformation has the wrong spatial dimension.");
|
||||
if (transformation.GetGeometryType() != element_data.displacement.GetElement().GetGeomType())
|
||||
throw std::invalid_argument(
|
||||
"The element transformation geometry does not match the "
|
||||
"supplied "
|
||||
@@ -432,12 +384,11 @@ namespace mean_field::mapping {
|
||||
transformation.Transform(integration_point, context.reference_position);
|
||||
|
||||
EvaluateField(
|
||||
element_data.displacement, transformation, integration_point,
|
||||
workspace, workspace.m_field_value, workspace.m_field_jacobian
|
||||
element_data.displacement, transformation, integration_point, workspace, workspace.m_field_value,
|
||||
workspace.m_field_jacobian
|
||||
);
|
||||
|
||||
if (!vector_is_finite(context.reference_position) ||
|
||||
!vector_is_finite(workspace.m_field_value) ||
|
||||
if (!vector_is_finite(context.reference_position) || !vector_is_finite(workspace.m_field_value) ||
|
||||
!matrix_is_finite(workspace.m_field_jacobian)) {
|
||||
return MappingStatus::non_finite_input;
|
||||
}
|
||||
@@ -446,9 +397,7 @@ namespace mean_field::mapping {
|
||||
context.displaced_position = context.reference_position;
|
||||
context.displaced_position += workspace.m_field_value;
|
||||
|
||||
context.displacement_jacobian.SetSize(
|
||||
m_options.dimension, m_options.dimension
|
||||
);
|
||||
context.displacement_jacobian.SetSize(m_options.dimension, m_options.dimension);
|
||||
context.displacement_jacobian = workspace.m_field_jacobian;
|
||||
for (int i = 0; i < m_options.dimension; ++i)
|
||||
context.displacement_jacobian(i, i) += 1.0;
|
||||
@@ -456,43 +405,34 @@ namespace mean_field::mapping {
|
||||
context.compactified = IsCompactifiedElement(transformation);
|
||||
|
||||
if (context.compactified) {
|
||||
const MappingStatus coordinate_status =
|
||||
EvaluateCompactificationCoordinate(
|
||||
element_data.compactification, transformation,
|
||||
integration_point, workspace,
|
||||
workspace.m_compactification_point
|
||||
);
|
||||
const MappingStatus coordinate_status = EvaluateCompactificationCoordinate(
|
||||
element_data.compactification, transformation, integration_point, workspace,
|
||||
workspace.m_compactification_point
|
||||
);
|
||||
|
||||
if (coordinate_status != MappingStatus::valid)
|
||||
return coordinate_status;
|
||||
|
||||
const compactification::ExteriorMapInput exterior_input{
|
||||
.reference_position = context.reference_position,
|
||||
.displaced_position = context.displaced_position,
|
||||
.displacement_jacobian = context.displacement_jacobian,
|
||||
.compactification_coordinate =
|
||||
workspace.m_compactification_point.coordinate,
|
||||
.compactification_coordinate_gradient =
|
||||
workspace.m_compactification_point.coordinate_gradient
|
||||
.reference_position = context.reference_position,
|
||||
.displaced_position = context.displaced_position,
|
||||
.displacement_jacobian = context.displacement_jacobian,
|
||||
.compactification_coordinate = workspace.m_compactification_point.coordinate,
|
||||
.compactification_coordinate_gradient = workspace.m_compactification_point.coordinate_gradient
|
||||
};
|
||||
|
||||
const MappingStatus exterior_status = m_exterior_map->Evaluate(
|
||||
exterior_input, workspace.m_exterior_result
|
||||
);
|
||||
const MappingStatus exterior_status = m_exterior_map->Evaluate(exterior_input, workspace.m_exterior_result);
|
||||
if (exterior_status != MappingStatus::valid)
|
||||
return exterior_status;
|
||||
|
||||
context.physical_position =
|
||||
workspace.m_exterior_result.physical_position;
|
||||
context.mapping_jacobian =
|
||||
workspace.m_exterior_result.mapping_jacobian;
|
||||
context.physical_position = workspace.m_exterior_result.physical_position;
|
||||
context.mapping_jacobian = workspace.m_exterior_result.mapping_jacobian;
|
||||
} else {
|
||||
context.physical_position = context.displaced_position;
|
||||
context.mapping_jacobian = context.displacement_jacobian;
|
||||
}
|
||||
|
||||
if (!vector_is_finite(context.physical_position) ||
|
||||
!matrix_is_finite(context.mapping_jacobian))
|
||||
if (!vector_is_finite(context.physical_position) || !matrix_is_finite(context.mapping_jacobian))
|
||||
return MappingStatus::non_finite_result;
|
||||
|
||||
context.mapping_determinant = context.mapping_jacobian.Det();
|
||||
@@ -501,12 +441,8 @@ namespace mean_field::mapping {
|
||||
if (context.mapping_determinant <= 0.0)
|
||||
return MappingStatus::non_positive_determinant;
|
||||
|
||||
context.inverse_mapping_jacobian.SetSize(
|
||||
m_options.dimension, m_options.dimension
|
||||
);
|
||||
mfem::CalcInverse(
|
||||
context.mapping_jacobian, context.inverse_mapping_jacobian
|
||||
);
|
||||
context.inverse_mapping_jacobian.SetSize(m_options.dimension, m_options.dimension);
|
||||
mfem::CalcInverse(context.mapping_jacobian, context.inverse_mapping_jacobian);
|
||||
|
||||
if (!matrix_is_finite(context.inverse_mapping_jacobian))
|
||||
return MappingStatus::non_finite_result;
|
||||
@@ -521,33 +457,22 @@ namespace mean_field::mapping {
|
||||
Workspace &workspace,
|
||||
VolumeMappingContext &context
|
||||
) const {
|
||||
const MappingStatus point_status = EvaluatePoint(
|
||||
element_data, transformation, integration_point, workspace,
|
||||
context.mapping
|
||||
);
|
||||
const MappingStatus point_status =
|
||||
EvaluatePoint(element_data, transformation, integration_point, workspace, context.mapping);
|
||||
if (point_status != MappingStatus::valid)
|
||||
return point_status;
|
||||
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
mfem::Mult(
|
||||
context.mapping.mapping_jacobian, transformation.Jacobian(),
|
||||
workspace.m_full_element_jacobian
|
||||
);
|
||||
mfem::Mult(context.mapping.mapping_jacobian, transformation.Jacobian(), workspace.m_full_element_jacobian);
|
||||
|
||||
context.quadrature.J_inv.SetSize(
|
||||
m_options.dimension, m_options.dimension
|
||||
);
|
||||
mfem::CalcInverse(
|
||||
workspace.m_full_element_jacobian, context.quadrature.J_inv
|
||||
);
|
||||
context.quadrature.J_inv.SetSize(m_options.dimension, m_options.dimension);
|
||||
mfem::CalcInverse(workspace.m_full_element_jacobian, context.quadrature.J_inv);
|
||||
|
||||
context.quadrature.detJ = context.mapping.mapping_determinant;
|
||||
context.quadrature.weight = integration_point.weight *
|
||||
transformation.Weight() *
|
||||
context.mapping.mapping_determinant;
|
||||
context.quadrature.detJ = context.mapping.mapping_determinant;
|
||||
context.quadrature.weight =
|
||||
integration_point.weight * transformation.Weight() * context.mapping.mapping_determinant;
|
||||
|
||||
if (!matrix_is_finite(context.quadrature.J_inv) ||
|
||||
!std::isfinite(context.quadrature.weight))
|
||||
if (!matrix_is_finite(context.quadrature.J_inv) || !std::isfinite(context.quadrature.weight))
|
||||
return MappingStatus::non_finite_result;
|
||||
if (context.quadrature.weight <= 0.0)
|
||||
return MappingStatus::non_positive_determinant;
|
||||
@@ -555,33 +480,24 @@ namespace mean_field::mapping {
|
||||
return MappingStatus::valid;
|
||||
}
|
||||
|
||||
mfem::ElementTransformation &
|
||||
DomainMapperStateless::SelectFaceElementTransformation(
|
||||
mfem::ElementTransformation &DomainMapperStateless::SelectFaceElementTransformation(
|
||||
mfem::FaceElementTransformations &transformation,
|
||||
const FaceElementSide side
|
||||
) {
|
||||
if (side == FaceElementSide::element_1) {
|
||||
MFEM_VERIFY(
|
||||
transformation.Elem1 != nullptr,
|
||||
"The face does not have an element-1 transformation."
|
||||
);
|
||||
MFEM_VERIFY(transformation.Elem1 != nullptr, "The face does not have an element-1 transformation.");
|
||||
return *transformation.Elem1;
|
||||
}
|
||||
|
||||
MFEM_VERIFY(
|
||||
transformation.Elem2 != nullptr,
|
||||
"The face does not have an element-2 transformation."
|
||||
);
|
||||
MFEM_VERIFY(transformation.Elem2 != nullptr, "The face does not have an element-2 transformation.");
|
||||
return *transformation.Elem2;
|
||||
}
|
||||
|
||||
const mfem::IntegrationPoint &
|
||||
DomainMapperStateless::SelectFaceElementIntegrationPoint(
|
||||
const mfem::IntegrationPoint &DomainMapperStateless::SelectFaceElementIntegrationPoint(
|
||||
mfem::FaceElementTransformations &transformation,
|
||||
const FaceElementSide side
|
||||
) {
|
||||
mfem::ElementTransformation &element_transformation =
|
||||
SelectFaceElementTransformation(transformation, side);
|
||||
mfem::ElementTransformation &element_transformation = SelectFaceElementTransformation(transformation, side);
|
||||
return element_transformation.GetIntPoint();
|
||||
}
|
||||
|
||||
@@ -594,63 +510,47 @@ namespace mean_field::mapping {
|
||||
FaceMappingContext &context
|
||||
) const {
|
||||
transformation.SetAllIntPoints(&integration_point);
|
||||
mfem::ElementTransformation &element_transformation =
|
||||
SelectFaceElementTransformation(transformation, side);
|
||||
mfem::ElementTransformation &element_transformation = SelectFaceElementTransformation(transformation, side);
|
||||
const mfem::IntegrationPoint &element_integration_point =
|
||||
SelectFaceElementIntegrationPoint(transformation, side);
|
||||
|
||||
const MappingStatus point_status = EvaluatePoint(
|
||||
element_data, element_transformation, element_integration_point,
|
||||
workspace, context.mapping
|
||||
);
|
||||
const MappingStatus point_status =
|
||||
EvaluatePoint(element_data, element_transformation, element_integration_point, workspace, context.mapping);
|
||||
if (point_status != MappingStatus::valid)
|
||||
return point_status;
|
||||
|
||||
workspace.m_reference_normal.SetSize(m_options.dimension);
|
||||
mfem::CalcOrtho(
|
||||
transformation.Jacobian(), workspace.m_reference_normal
|
||||
);
|
||||
mfem::CalcOrtho(transformation.Jacobian(), workspace.m_reference_normal);
|
||||
if (side == FaceElementSide::element_2)
|
||||
workspace.m_reference_normal *= -1.0;
|
||||
|
||||
const double reference_normal_magnitude =
|
||||
workspace.m_reference_normal.Norml2();
|
||||
if (!std::isfinite(reference_normal_magnitude) ||
|
||||
reference_normal_magnitude <= 0.0)
|
||||
const double reference_normal_magnitude = workspace.m_reference_normal.Norml2();
|
||||
if (!std::isfinite(reference_normal_magnitude) || reference_normal_magnitude <= 0.0)
|
||||
return MappingStatus::non_finite_result;
|
||||
|
||||
context.reference_normal.SetSize(m_options.dimension);
|
||||
context.reference_normal = workspace.m_reference_normal;
|
||||
context.reference_normal /= reference_normal_magnitude;
|
||||
|
||||
context.mapping.inverse_mapping_jacobian.MultTranspose(
|
||||
workspace.m_reference_normal, workspace.m_mapped_normal
|
||||
);
|
||||
context.mapping.inverse_mapping_jacobian.MultTranspose(workspace.m_reference_normal, workspace.m_mapped_normal);
|
||||
workspace.m_mapped_normal *= context.mapping.mapping_determinant;
|
||||
|
||||
const double mapped_normal_magnitude =
|
||||
workspace.m_mapped_normal.Norml2();
|
||||
if (!std::isfinite(mapped_normal_magnitude) ||
|
||||
mapped_normal_magnitude <= 0.0)
|
||||
const double mapped_normal_magnitude = workspace.m_mapped_normal.Norml2();
|
||||
if (!std::isfinite(mapped_normal_magnitude) || mapped_normal_magnitude <= 0.0)
|
||||
return MappingStatus::non_finite_result;
|
||||
|
||||
context.quadrature.normal.SetSize(m_options.dimension);
|
||||
context.quadrature.normal = workspace.m_mapped_normal;
|
||||
context.quadrature.normal /= mapped_normal_magnitude;
|
||||
|
||||
context.reference_surface_weight =
|
||||
integration_point.weight * reference_normal_magnitude;
|
||||
context.physical_surface_weight =
|
||||
integration_point.weight * mapped_normal_magnitude;
|
||||
context.reference_surface_weight = integration_point.weight * reference_normal_magnitude;
|
||||
context.physical_surface_weight = integration_point.weight * mapped_normal_magnitude;
|
||||
|
||||
context.quadrature.ds = context.reference_surface_weight;
|
||||
context.quadrature.v_dot_n_scale =
|
||||
mapped_normal_magnitude / reference_normal_magnitude;
|
||||
context.quadrature.ds = context.reference_surface_weight;
|
||||
context.quadrature.v_dot_n_scale = mapped_normal_magnitude / reference_normal_magnitude;
|
||||
|
||||
if (!vector_is_finite(context.quadrature.normal) ||
|
||||
!std::isfinite(context.reference_surface_weight) ||
|
||||
!std::isfinite(context.physical_surface_weight) ||
|
||||
!std::isfinite(context.quadrature.v_dot_n_scale)) {
|
||||
if (!vector_is_finite(context.quadrature.normal) || !std::isfinite(context.reference_surface_weight) ||
|
||||
!std::isfinite(context.physical_surface_weight) || !std::isfinite(context.quadrature.v_dot_n_scale)) {
|
||||
return MappingStatus::non_finite_result;
|
||||
}
|
||||
|
||||
@@ -668,8 +568,7 @@ namespace mean_field::mapping {
|
||||
) const {
|
||||
ValidateElementData(element_data);
|
||||
const ElementMappingData direction_data{
|
||||
.displacement = direction,
|
||||
.compactification = element_data.compactification
|
||||
.displacement = direction, .compactification = element_data.compactification
|
||||
};
|
||||
ValidateElementData(direction_data);
|
||||
|
||||
@@ -679,9 +578,7 @@ namespace mean_field::mapping {
|
||||
"degree-of-freedom counts."
|
||||
);
|
||||
if (workspace.GetDimension() != m_options.dimension)
|
||||
throw std::invalid_argument(
|
||||
"The mapping workspace has the wrong dimension."
|
||||
);
|
||||
throw std::invalid_argument("The mapping workspace has the wrong dimension.");
|
||||
if (base_context.compactified != IsCompactifiedElement(transformation))
|
||||
throw std::invalid_argument(
|
||||
"The base mapping context does not match the current element "
|
||||
@@ -689,86 +586,66 @@ namespace mean_field::mapping {
|
||||
);
|
||||
|
||||
EvaluateField(
|
||||
direction, transformation, integration_point, workspace,
|
||||
workspace.m_field_value, workspace.m_field_jacobian
|
||||
direction, transformation, integration_point, workspace, workspace.m_field_value, workspace.m_field_jacobian
|
||||
);
|
||||
|
||||
if (!vector_is_finite(workspace.m_field_value) ||
|
||||
!matrix_is_finite(workspace.m_field_jacobian))
|
||||
if (!vector_is_finite(workspace.m_field_value) || !matrix_is_finite(workspace.m_field_jacobian))
|
||||
return MappingStatus::non_finite_input;
|
||||
|
||||
variation.displacement_variation = workspace.m_field_value;
|
||||
variation.displacement_jacobian_variation = workspace.m_field_jacobian;
|
||||
|
||||
if (base_context.compactified) {
|
||||
const MappingStatus coordinate_status =
|
||||
EvaluateCompactificationCoordinate(
|
||||
element_data.compactification, transformation,
|
||||
integration_point, workspace,
|
||||
workspace.m_compactification_point
|
||||
);
|
||||
const MappingStatus coordinate_status = EvaluateCompactificationCoordinate(
|
||||
element_data.compactification, transformation, integration_point, workspace,
|
||||
workspace.m_compactification_point
|
||||
);
|
||||
|
||||
if (coordinate_status != MappingStatus::valid)
|
||||
return coordinate_status;
|
||||
|
||||
const compactification::ExteriorMapInput exterior_input{
|
||||
.reference_position = base_context.reference_position,
|
||||
.displaced_position = base_context.displaced_position,
|
||||
.displacement_jacobian = base_context.displacement_jacobian,
|
||||
.compactification_coordinate =
|
||||
workspace.m_compactification_point.coordinate,
|
||||
.compactification_coordinate_gradient =
|
||||
workspace.m_compactification_point.coordinate_gradient
|
||||
.reference_position = base_context.reference_position,
|
||||
.displaced_position = base_context.displaced_position,
|
||||
.displacement_jacobian = base_context.displacement_jacobian,
|
||||
.compactification_coordinate = workspace.m_compactification_point.coordinate,
|
||||
.compactification_coordinate_gradient = workspace.m_compactification_point.coordinate_gradient
|
||||
};
|
||||
|
||||
workspace.m_exterior_result.physical_position =
|
||||
base_context.physical_position;
|
||||
workspace.m_exterior_result.mapping_jacobian =
|
||||
base_context.mapping_jacobian;
|
||||
workspace.m_exterior_result.physical_position = base_context.physical_position;
|
||||
workspace.m_exterior_result.mapping_jacobian = base_context.mapping_jacobian;
|
||||
|
||||
const compactification::ExteriorMapDirection exterior_direction{
|
||||
.displaced_position_variation =
|
||||
variation.displacement_variation,
|
||||
.displacement_jacobian_variation =
|
||||
variation.displacement_jacobian_variation
|
||||
.displaced_position_variation = variation.displacement_variation,
|
||||
.displacement_jacobian_variation = variation.displacement_jacobian_variation
|
||||
};
|
||||
|
||||
// ReSharper disable once CppTooWideScopeInitStatement
|
||||
const MappingStatus exterior_status =
|
||||
m_exterior_map->EvaluateVariation(
|
||||
exterior_input, workspace.m_exterior_result,
|
||||
exterior_direction, workspace.m_exterior_variation
|
||||
);
|
||||
const MappingStatus exterior_status = m_exterior_map->EvaluateVariation(
|
||||
exterior_input, workspace.m_exterior_result, exterior_direction, workspace.m_exterior_variation
|
||||
);
|
||||
|
||||
if (exterior_status != MappingStatus::valid) {
|
||||
return exterior_status;
|
||||
}
|
||||
|
||||
variation.physical_position_variation =
|
||||
workspace.m_exterior_variation.physical_position_variation;
|
||||
variation.mapping_jacobian_variation =
|
||||
workspace.m_exterior_variation.mapping_jacobian_variation;
|
||||
variation.physical_position_variation = workspace.m_exterior_variation.physical_position_variation;
|
||||
variation.mapping_jacobian_variation = workspace.m_exterior_variation.mapping_jacobian_variation;
|
||||
} else {
|
||||
variation.physical_position_variation =
|
||||
variation.displacement_variation;
|
||||
variation.mapping_jacobian_variation =
|
||||
variation.displacement_jacobian_variation;
|
||||
variation.physical_position_variation = variation.displacement_variation;
|
||||
variation.mapping_jacobian_variation = variation.displacement_jacobian_variation;
|
||||
}
|
||||
|
||||
mfem::Mult(
|
||||
base_context.inverse_mapping_jacobian,
|
||||
variation.mapping_jacobian_variation, workspace.m_matrix_temp_1
|
||||
base_context.inverse_mapping_jacobian, variation.mapping_jacobian_variation, workspace.m_matrix_temp_1
|
||||
);
|
||||
|
||||
double trace = 0.0;
|
||||
for (int i = 0; i < m_options.dimension; ++i)
|
||||
trace += workspace.m_matrix_temp_1(i, i);
|
||||
variation.mapping_determinant_variation =
|
||||
base_context.mapping_determinant * trace;
|
||||
variation.mapping_determinant_variation = base_context.mapping_determinant * trace;
|
||||
|
||||
variation.inverse_mapping_jacobian_variation.SetSize(
|
||||
m_options.dimension, m_options.dimension
|
||||
);
|
||||
variation.inverse_mapping_jacobian_variation.SetSize(m_options.dimension, m_options.dimension);
|
||||
mfem::Mult(
|
||||
workspace.m_matrix_temp_1, base_context.inverse_mapping_jacobian,
|
||||
variation.inverse_mapping_jacobian_variation
|
||||
@@ -795,34 +672,26 @@ namespace mean_field::mapping {
|
||||
VolumeMappingVariation &variation
|
||||
) const {
|
||||
const MappingStatus point_status = EvaluatePointVariation(
|
||||
element_data, direction, transformation, integration_point,
|
||||
base_context.mapping, workspace, variation.mapping
|
||||
element_data, direction, transformation, integration_point, base_context.mapping, workspace,
|
||||
variation.mapping
|
||||
);
|
||||
if (point_status != MappingStatus::valid)
|
||||
return point_status;
|
||||
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
mfem::Mult(
|
||||
variation.mapping.mapping_jacobian_variation,
|
||||
transformation.Jacobian(), workspace.m_full_element_jacobian
|
||||
);
|
||||
mfem::Mult(
|
||||
base_context.quadrature.J_inv, workspace.m_full_element_jacobian,
|
||||
workspace.m_matrix_temp_1
|
||||
variation.mapping.mapping_jacobian_variation, transformation.Jacobian(), workspace.m_full_element_jacobian
|
||||
);
|
||||
mfem::Mult(base_context.quadrature.J_inv, workspace.m_full_element_jacobian, workspace.m_matrix_temp_1);
|
||||
|
||||
variation.inverse_element_jacobian_variation.SetSize(
|
||||
m_options.dimension, m_options.dimension
|
||||
);
|
||||
variation.inverse_element_jacobian_variation.SetSize(m_options.dimension, m_options.dimension);
|
||||
mfem::Mult(
|
||||
workspace.m_matrix_temp_1, base_context.quadrature.J_inv,
|
||||
variation.inverse_element_jacobian_variation
|
||||
workspace.m_matrix_temp_1, base_context.quadrature.J_inv, variation.inverse_element_jacobian_variation
|
||||
);
|
||||
variation.inverse_element_jacobian_variation *= -1.0;
|
||||
|
||||
variation.weight_variation =
|
||||
integration_point.weight * transformation.Weight() *
|
||||
variation.mapping.mapping_determinant_variation;
|
||||
integration_point.weight * transformation.Weight() * variation.mapping.mapping_determinant_variation;
|
||||
|
||||
if (!matrix_is_finite(variation.inverse_element_jacobian_variation) ||
|
||||
!std::isfinite(variation.weight_variation))
|
||||
@@ -842,30 +711,24 @@ namespace mean_field::mapping {
|
||||
FaceMappingVariation &variation
|
||||
) const {
|
||||
transformation.SetAllIntPoints(&integration_point);
|
||||
mfem::ElementTransformation &element_transformation =
|
||||
SelectFaceElementTransformation(transformation, side);
|
||||
mfem::ElementTransformation &element_transformation = SelectFaceElementTransformation(transformation, side);
|
||||
const mfem::IntegrationPoint &element_integration_point =
|
||||
SelectFaceElementIntegrationPoint(transformation, side);
|
||||
|
||||
const MappingStatus point_status = EvaluatePointVariation(
|
||||
element_data, direction, element_transformation,
|
||||
element_integration_point, base_context.mapping, workspace,
|
||||
element_data, direction, element_transformation, element_integration_point, base_context.mapping, workspace,
|
||||
variation.mapping
|
||||
);
|
||||
if (point_status != MappingStatus::valid)
|
||||
return point_status;
|
||||
|
||||
workspace.m_reference_normal.SetSize(m_options.dimension);
|
||||
mfem::CalcOrtho(
|
||||
transformation.Jacobian(), workspace.m_reference_normal
|
||||
);
|
||||
mfem::CalcOrtho(transformation.Jacobian(), workspace.m_reference_normal);
|
||||
if (side == FaceElementSide::element_2)
|
||||
workspace.m_reference_normal *= -1.0;
|
||||
|
||||
const double reference_normal_magnitude =
|
||||
workspace.m_reference_normal.Norml2();
|
||||
if (!std::isfinite(reference_normal_magnitude) ||
|
||||
reference_normal_magnitude <= 0.0)
|
||||
const double reference_normal_magnitude = workspace.m_reference_normal.Norml2();
|
||||
if (!std::isfinite(reference_normal_magnitude) || reference_normal_magnitude <= 0.0)
|
||||
return MappingStatus::non_finite_result;
|
||||
|
||||
base_context.mapping.inverse_mapping_jacobian.MultTranspose(
|
||||
@@ -878,32 +741,23 @@ namespace mean_field::mapping {
|
||||
variation.mapping.inverse_mapping_jacobian_variation.MultTranspose(
|
||||
workspace.m_reference_normal, variation.physical_normal_variation
|
||||
);
|
||||
variation.physical_normal_variation *=
|
||||
base_context.mapping.mapping_determinant;
|
||||
variation.physical_normal_variation *= base_context.mapping.mapping_determinant;
|
||||
variation.physical_normal_variation.Add(
|
||||
variation.mapping.mapping_determinant_variation,
|
||||
workspace.m_vector_temp
|
||||
variation.mapping.mapping_determinant_variation, workspace.m_vector_temp
|
||||
);
|
||||
|
||||
const double mapped_normal_magnitude =
|
||||
workspace.m_mapped_normal.Norml2();
|
||||
if (!std::isfinite(mapped_normal_magnitude) ||
|
||||
mapped_normal_magnitude <= 0.0)
|
||||
const double mapped_normal_magnitude = workspace.m_mapped_normal.Norml2();
|
||||
if (!std::isfinite(mapped_normal_magnitude) || mapped_normal_magnitude <= 0.0)
|
||||
return MappingStatus::non_finite_result;
|
||||
|
||||
const double mapped_normal_magnitude_variation =
|
||||
base_context.quadrature.normal *
|
||||
variation.physical_normal_variation;
|
||||
base_context.quadrature.normal * variation.physical_normal_variation;
|
||||
|
||||
variation.physical_normal_variation.Add(
|
||||
-mapped_normal_magnitude_variation, base_context.quadrature.normal
|
||||
);
|
||||
variation.physical_normal_variation.Add(-mapped_normal_magnitude_variation, base_context.quadrature.normal);
|
||||
variation.physical_normal_variation /= mapped_normal_magnitude;
|
||||
|
||||
variation.physical_surface_weight_variation =
|
||||
integration_point.weight * mapped_normal_magnitude_variation;
|
||||
variation.normal_flux_scale_variation =
|
||||
mapped_normal_magnitude_variation / reference_normal_magnitude;
|
||||
variation.physical_surface_weight_variation = integration_point.weight * mapped_normal_magnitude_variation;
|
||||
variation.normal_flux_scale_variation = mapped_normal_magnitude_variation / reference_normal_magnitude;
|
||||
|
||||
if (!vector_is_finite(variation.physical_normal_variation) ||
|
||||
!std::isfinite(variation.physical_surface_weight_variation) ||
|
||||
|
||||
@@ -41,15 +41,12 @@ namespace mean_field::mapping {
|
||||
mfem::Vector &physical_gradient
|
||||
) {
|
||||
MFEM_VERIFY(
|
||||
reference_gradient.Size() ==
|
||||
context.inverse_mapping_jacobian.Height(),
|
||||
reference_gradient.Size() == context.inverse_mapping_jacobian.Height(),
|
||||
"The reference scalar gradient has the wrong dimension."
|
||||
);
|
||||
|
||||
physical_gradient.SetSize(reference_gradient.Size());
|
||||
context.inverse_mapping_jacobian.MultTranspose(
|
||||
reference_gradient, physical_gradient
|
||||
);
|
||||
context.inverse_mapping_jacobian.MultTranspose(reference_gradient, physical_gradient);
|
||||
}
|
||||
|
||||
void MapPhysicalGradientToReference(
|
||||
@@ -63,9 +60,7 @@ namespace mean_field::mapping {
|
||||
);
|
||||
|
||||
reference_gradient.SetSize(physical_gradient.Size());
|
||||
context.mapping_jacobian.MultTranspose(
|
||||
physical_gradient, reference_gradient
|
||||
);
|
||||
context.mapping_jacobian.MultTranspose(physical_gradient, reference_gradient);
|
||||
}
|
||||
|
||||
void MapReferenceVectorGradientToPhysical(
|
||||
@@ -74,19 +69,12 @@ namespace mean_field::mapping {
|
||||
mfem::DenseMatrix &physical_gradient
|
||||
) {
|
||||
MFEM_VERIFY(
|
||||
reference_gradient.Width() ==
|
||||
context.inverse_mapping_jacobian.Height(),
|
||||
reference_gradient.Width() == context.inverse_mapping_jacobian.Height(),
|
||||
"The reference vector gradient has the wrong dimension."
|
||||
);
|
||||
|
||||
physical_gradient.SetSize(
|
||||
reference_gradient.Height(),
|
||||
context.inverse_mapping_jacobian.Width()
|
||||
);
|
||||
mfem::Mult(
|
||||
reference_gradient, context.inverse_mapping_jacobian,
|
||||
physical_gradient
|
||||
);
|
||||
physical_gradient.SetSize(reference_gradient.Height(), context.inverse_mapping_jacobian.Width());
|
||||
mfem::Mult(reference_gradient, context.inverse_mapping_jacobian, physical_gradient);
|
||||
}
|
||||
|
||||
void MapPhysicalVectorGradientToReference(
|
||||
@@ -99,12 +87,8 @@ namespace mean_field::mapping {
|
||||
"The physical vector gradient has the wrong dimension."
|
||||
);
|
||||
|
||||
reference_gradient.SetSize(
|
||||
physical_gradient.Height(), context.mapping_jacobian.Width()
|
||||
);
|
||||
mfem::Mult(
|
||||
physical_gradient, context.mapping_jacobian, reference_gradient
|
||||
);
|
||||
reference_gradient.SetSize(physical_gradient.Height(), context.mapping_jacobian.Width());
|
||||
mfem::Mult(physical_gradient, context.mapping_jacobian, reference_gradient);
|
||||
}
|
||||
|
||||
double MapHDivDivergenceToPhysical(
|
||||
@@ -120,19 +104,11 @@ namespace mean_field::mapping {
|
||||
) {
|
||||
const int dimension = context.mapping_jacobian.Height();
|
||||
|
||||
MFEM_VERIFY(
|
||||
context.mapping_jacobian.Width() == dimension,
|
||||
"The mapping Jacobian must be square."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
context.mapping_determinant > 0.0,
|
||||
"The mapping determinant must be positive."
|
||||
);
|
||||
MFEM_VERIFY(context.mapping_jacobian.Width() == dimension, "The mapping Jacobian must be square.");
|
||||
MFEM_VERIFY(context.mapping_determinant > 0.0, "The mapping determinant must be positive.");
|
||||
|
||||
mass_tensor.SetSize(dimension, dimension);
|
||||
mfem::MultAtB(
|
||||
context.mapping_jacobian, context.mapping_jacobian, mass_tensor
|
||||
);
|
||||
mfem::MultAtB(context.mapping_jacobian, context.mapping_jacobian, mass_tensor);
|
||||
mass_tensor *= 1 / context.mapping_determinant;
|
||||
}
|
||||
|
||||
@@ -143,19 +119,12 @@ namespace mean_field::mapping {
|
||||
const int dimension = context.inverse_mapping_jacobian.Height();
|
||||
|
||||
MFEM_VERIFY(
|
||||
context.inverse_mapping_jacobian.Width() == dimension,
|
||||
"The inverse mapping Jacobian must be square."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
context.mapping_determinant > 0.0,
|
||||
"The mapping determinant must be positive."
|
||||
context.inverse_mapping_jacobian.Width() == dimension, "The inverse mapping Jacobian must be square."
|
||||
);
|
||||
MFEM_VERIFY(context.mapping_determinant > 0.0, "The mapping determinant must be positive.");
|
||||
|
||||
diffusion_tensor.SetSize(dimension, dimension);
|
||||
mfem::MultABt(
|
||||
context.inverse_mapping_jacobian, context.inverse_mapping_jacobian,
|
||||
diffusion_tensor
|
||||
);
|
||||
mfem::MultABt(context.inverse_mapping_jacobian, context.inverse_mapping_jacobian, diffusion_tensor);
|
||||
diffusion_tensor *= context.mapping_determinant;
|
||||
}
|
||||
|
||||
@@ -170,9 +139,7 @@ namespace mean_field::mapping {
|
||||
);
|
||||
|
||||
physical_field.SetSize(reference_field.Size());
|
||||
context.inverse_mapping_jacobian.MultTranspose(
|
||||
reference_field, physical_field
|
||||
);
|
||||
context.inverse_mapping_jacobian.MultTranspose(reference_field, physical_field);
|
||||
}
|
||||
|
||||
void MapPhysicalFieldToHCurlReference(
|
||||
@@ -239,35 +206,24 @@ namespace mean_field::mapping {
|
||||
const MappingPointVariation &variation,
|
||||
mfem::DenseMatrix &mass_tensor_variation
|
||||
) {
|
||||
const double determinant = context.mapping_determinant;
|
||||
const double determinant_variation =
|
||||
variation.mapping_determinant_variation;
|
||||
const int dimension = context.inverse_mapping_jacobian.Width();
|
||||
const double determinant = context.mapping_determinant;
|
||||
const double determinant_variation = variation.mapping_determinant_variation;
|
||||
const int dimension = context.inverse_mapping_jacobian.Width();
|
||||
|
||||
mass_tensor_variation.SetSize(dimension, dimension);
|
||||
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(determinant) && determinant > 0.0,
|
||||
"The mapping determinant must be positive and finite."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(determinant_variation),
|
||||
"The mapping determinant variation must be finite."
|
||||
std::isfinite(determinant) && determinant > 0.0, "The mapping determinant must be positive and finite."
|
||||
);
|
||||
MFEM_VERIFY(std::isfinite(determinant_variation), "The mapping determinant variation must be finite.");
|
||||
|
||||
mfem::DenseMatrix determinant_correction(dimension, dimension);
|
||||
ComputeHDivMassTensor(context, determinant_correction);
|
||||
determinant_correction *= determinant_variation / determinant;
|
||||
|
||||
mfem::DenseMatrix right_jacobian_variation(dimension, dimension);
|
||||
mfem::MultAtB(
|
||||
context.mapping_jacobian, variation.mapping_jacobian_variation,
|
||||
right_jacobian_variation
|
||||
);
|
||||
mfem::MultAtB(
|
||||
variation.mapping_jacobian_variation, context.mapping_jacobian,
|
||||
mass_tensor_variation
|
||||
);
|
||||
mfem::MultAtB(context.mapping_jacobian, variation.mapping_jacobian_variation, right_jacobian_variation);
|
||||
mfem::MultAtB(variation.mapping_jacobian_variation, context.mapping_jacobian, mass_tensor_variation);
|
||||
|
||||
mass_tensor_variation += right_jacobian_variation;
|
||||
mass_tensor_variation *= 1 / determinant;
|
||||
|
||||
Reference in New Issue
Block a user