From 21ee76a1f3e5fd66e98eb1c80e01aed2761381c0 Mon Sep 17 00:00:00 2001 From: Cameron Smith Date: Mon, 3 Aug 2026 13:38:49 -0400 Subject: [PATCH 1/3] loosen check on parametric coordinate values these checks are meant to protect the user and the devs from passing parametric coord inputs that are far from valid --- src/MeshField_Defines.hpp | 1 + src/MeshField_Shape.hpp | 76 +++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/MeshField_Defines.hpp b/src/MeshField_Defines.hpp index d3a216f..8467a0b 100644 --- a/src/MeshField_Defines.hpp +++ b/src/MeshField_Defines.hpp @@ -18,5 +18,6 @@ enum Mesh_Topology { static bool Debug = false; const Real MachinePrecision = 1e-15; const Real Epsilon = 1e-12; +const Real ParametricCoordTol = 1e-6; } // namespace MeshField #endif diff --git a/src/MeshField_Shape.hpp b/src/MeshField_Shape.hpp index 56eb241..5359220 100644 --- a/src/MeshField_Shape.hpp +++ b/src/MeshField_Shape.hpp @@ -23,9 +23,9 @@ namespace { * @param val Reference value * @return true if xi >= val within machine precision */ -KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshField::Real val) { +KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshField::Real val, const double tol) { if ( xi > val ) return true; - return (Kokkos::fabs(xi - val) <= MeshField::MachinePrecision); + return (Kokkos::fabs(xi - val) <= tol); } /** @@ -36,10 +36,10 @@ KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshFie * @return true if all xi[i] >= val within machine precision */ template -KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::Real val) { +KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::Real val, const double tol) { auto gt = true; for (size_t i = 0; i < xi.size(); i++) { - gt = gt && greaterThanOrEqual(xi[i],val); + gt = gt && greaterThanOrEqual(xi[i],val,tol); } return gt; } @@ -50,9 +50,9 @@ KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::R * @param val Reference value * @return true if xi <= val within machine precision */ -KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField::Real val) { +KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField::Real val, const double tol) { if ( xi < val ) return true; - return (Kokkos::fabs(xi - val) <= MeshField::MachinePrecision); + return (Kokkos::fabs(xi - val) <= tol); } /** @@ -63,10 +63,10 @@ KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField: * @return true if all xi[i] <= val within machine precision */ template -KOKKOS_INLINE_FUNCTION bool eachLessThanOrEqual(Array &xi, const MeshField::Real val) { +KOKKOS_INLINE_FUNCTION bool eachLessThanOrEqual(Array &xi, const MeshField::Real val, const double tol) { auto lt = true; for (size_t i = 0; i < xi.size(); i++) { - lt = lt && lessThanOrEqual(xi[i],val); + lt = lt && lessThanOrEqual(xi[i],val,tol); } return lt; } @@ -117,8 +117,8 @@ struct LinearEdgeShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector1 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,-1.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,-1.0,ParametricCoordTol)); // clang-format off return {(1.0 - xi[0]) / 2.0, (1.0 + xi[0]) / 2.0}; @@ -180,11 +180,11 @@ struct LinearTriangleShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector2 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); // clang-format off return {L0, xi[0], //L1 @@ -241,11 +241,11 @@ struct LinearTriangleCoordinateShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector2 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); // clang-format off return {L0, xi[0], @@ -307,11 +307,11 @@ struct QuadraticTriangleShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector2 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); const Real L1 = xi[0]; const Real L2 = xi[1]; // clang-format off @@ -332,11 +332,11 @@ struct QuadraticTriangleShape { KOKKOS_INLINE_FUNCTION Kokkos::Array getLocalGradients(Vector2 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); const Real L1 = xi[0]; const Real L2 = xi[1]; // clang-format off @@ -395,11 +395,11 @@ struct LinearTetrahedronShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector3 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1] - xi[2]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); // clang-format off return {L0, xi[0], //L1 @@ -482,11 +482,11 @@ struct QuadraticTetrahedronShape { */ KOKKOS_INLINE_FUNCTION Kokkos::Array getValues(Vector3 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1] - xi[2]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); const Real L1 = xi[0]; const Real L2 = xi[1]; const Real L3 = xi[2]; @@ -512,11 +512,11 @@ struct QuadraticTetrahedronShape { KOKKOS_INLINE_FUNCTION Kokkos::Array getLocalGradients(Vector3 const &xi) const { - assert(eachLessThanOrEqual(xi,1.0)); - assert(eachGreaterThanOrEqual(xi,0.0)); + assert(eachLessThanOrEqual(xi,1.0,ParametricCoordTol)); + assert(eachGreaterThanOrEqual(xi,0.0,ParametricCoordTol)); const Real L0 = 1 - xi[0] - xi[1] - xi[2]; - assert(greaterThanOrEqual(L0,0.0)); - assert(lessThanOrEqual(L0,1.0)); + assert(greaterThanOrEqual(L0,0.0,ParametricCoordTol)); + assert(lessThanOrEqual(L0,1.0,ParametricCoordTol)); const Real L1 = xi[0]; const Real L2 = xi[1]; const Real L3 = xi[2]; From 388ff729f0497e88b69a9183f1660e2436741ba9 Mon Sep 17 00:00:00 2001 From: Cameron Smith Date: Mon, 3 Aug 2026 13:42:54 -0400 Subject: [PATCH 2/3] use meshfield real type --- src/MeshField_Shape.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/MeshField_Shape.hpp b/src/MeshField_Shape.hpp index 5359220..8d5e9de 100644 --- a/src/MeshField_Shape.hpp +++ b/src/MeshField_Shape.hpp @@ -23,7 +23,7 @@ namespace { * @param val Reference value * @return true if xi >= val within machine precision */ -KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshField::Real val, const double tol) { +KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshField::Real val, const MeshField::Real tol) { if ( xi > val ) return true; return (Kokkos::fabs(xi - val) <= tol); } @@ -36,7 +36,7 @@ KOKKOS_INLINE_FUNCTION bool greaterThanOrEqual(MeshField::Real xi, const MeshFie * @return true if all xi[i] >= val within machine precision */ template -KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::Real val, const double tol) { +KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::Real val, const MeshField::Real tol) { auto gt = true; for (size_t i = 0; i < xi.size(); i++) { gt = gt && greaterThanOrEqual(xi[i],val,tol); @@ -50,7 +50,7 @@ KOKKOS_INLINE_FUNCTION bool eachGreaterThanOrEqual(Array &xi, const MeshField::R * @param val Reference value * @return true if xi <= val within machine precision */ -KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField::Real val, const double tol) { +KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField::Real val, const MeshField::Real tol) { if ( xi < val ) return true; return (Kokkos::fabs(xi - val) <= tol); } @@ -63,7 +63,7 @@ KOKKOS_INLINE_FUNCTION bool lessThanOrEqual(MeshField::Real xi, const MeshField: * @return true if all xi[i] <= val within machine precision */ template -KOKKOS_INLINE_FUNCTION bool eachLessThanOrEqual(Array &xi, const MeshField::Real val, const double tol) { +KOKKOS_INLINE_FUNCTION bool eachLessThanOrEqual(Array &xi, const MeshField::Real val, const MeshField::Real tol) { auto lt = true; for (size_t i = 0; i < xi.size(); i++) { lt = lt && lessThanOrEqual(xi[i],val,tol); From 8d830752ce0cc933bae71130b5b775b2191acf0c Mon Sep 17 00:00:00 2001 From: Cameron Smith Date: Mon, 3 Aug 2026 14:16:01 -0400 Subject: [PATCH 3/3] bump patch version not exactly a bug fix... but not a feature to merit a minor version increase --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aae165a..77573e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.13.0) -project(meshfields VERSION 1.0.0 LANGUAGES CXX) +project(meshfields VERSION 1.0.1 LANGUAGES CXX) include(GNUInstallDirs) include(CMakePackageConfigHelpers)