polyhedral-gravity 3.0rc3__tar.gz → 3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {polyhedral_gravity-3.0rc3/polyhedral_gravity.egg-info → polyhedral_gravity-3.2}/PKG-INFO +17 -17
  2. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/README.md +16 -16
  3. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/pybind11.cmake +3 -4
  4. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/spdlog.cmake +3 -4
  5. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/tbb.cmake +3 -3
  6. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/yaml.cmake +3 -3
  7. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2/polyhedral_gravity.egg-info}/PKG-INFO +17 -17
  8. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/polyhedral_gravity.egg-info/SOURCES.txt +2 -0
  9. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/setup.py +1 -1
  10. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityModelData.h +33 -16
  11. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityModelDetail.cpp +12 -12
  12. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityModelDetail.h +1 -0
  13. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/Polyhedron.cpp +6 -6
  14. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/Polyhedron.h +5 -4
  15. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/util/UtilityConstants.h +0 -9
  16. polyhedral_gravity-3.2/src/polyhedralGravity/util/UtilityFloatArithmetic.cpp +51 -0
  17. polyhedral_gravity-3.2/src/polyhedralGravity/util/UtilityFloatArithmetic.h +73 -0
  18. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravityPython/PolyhedralGravityPython.cpp +3 -3
  19. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/CMakeLists.txt +0 -0
  20. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/LICENSE +0 -0
  21. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/MANIFEST.in +0 -0
  22. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/FindSphinx.cmake +0 -0
  23. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/gtest.cmake +0 -0
  24. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/tetgen.cmake +0 -0
  25. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/thrust.cmake +0 -0
  26. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/cmake/xsimd.cmake +0 -0
  27. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/polyhedral_gravity.egg-info/dependency_links.txt +0 -0
  28. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/polyhedral_gravity.egg-info/not-zip-safe +0 -0
  29. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/polyhedral_gravity.egg-info/top_level.txt +0 -0
  30. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/setup.cfg +0 -0
  31. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/CMakeLists.txt +0 -0
  32. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/main.cpp +0 -0
  33. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/CMakeLists.txt +0 -0
  34. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/ConfigSource.h +0 -0
  35. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/DataSource.h +0 -0
  36. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/TetgenAdapter.cpp +0 -0
  37. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/TetgenAdapter.h +0 -0
  38. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/YAMLConfigReader.cpp +0 -0
  39. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/input/YAMLConfigReader.h +0 -0
  40. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityEvaluable.cpp +0 -0
  41. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityEvaluable.h +0 -0
  42. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityModel.cpp +0 -0
  43. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/model/GravityModel.h +0 -0
  44. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/output/CSVWriter.cpp +0 -0
  45. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/output/CSVWriter.h +0 -0
  46. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/output/Logging.cpp +0 -0
  47. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/output/Logging.h +0 -0
  48. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/util/UtilityContainer.h +0 -0
  49. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravity/util/UtilityThrust.h +0 -0
  50. {polyhedral_gravity-3.0rc3 → polyhedral_gravity-3.2}/src/polyhedralGravityPython/CMakeLists.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyhedral_gravity
3
- Version: 3.0rc3
3
+ Version: 3.2
4
4
  Summary: Package to compute full gravity tensor of a given constant density polyhedron for arbitrary points according to the geodetic convention
5
5
  Author: Jonas Schuhmacher
6
6
  Author-email: jonas.schuhmacher@tum.de
@@ -79,8 +79,8 @@ which is strongly based on the former implementation in FORTRAN.
79
79
 
80
80
  > [!NOTE]
81
81
  > The [GitHub Pages](https://esa.github.io/polyhedral-gravity-model) of this project
82
- contain the full extensive documentation of C++ Library and the Python Interface
83
- as well as background on the gravity model and advanced settings not detailed here!
82
+ contain the full extensive documentation of the C++ Library and Python Interface
83
+ as well as background on the gravity model and advanced settings not detailed here.
84
84
 
85
85
  ## Input & Output (C++ and Python)
86
86
 
@@ -139,7 +139,7 @@ cube_density = 1.0
139
139
  computation_point = np.array([0, 0, 0])
140
140
  ```
141
141
 
142
- We first, define a constant density Polyhedron from `vertices` and `faces`
142
+ We first define a constant density Polyhedron from `vertices` and `faces`
143
143
 
144
144
  ```python
145
145
  cube_polyhedron = Polyhedron(
@@ -148,9 +148,9 @@ cube_polyhedron = Polyhedron(
148
148
  )
149
149
  ```
150
150
 
151
- In case you want to hand over the polyhedron via a supported file format,
151
+ In case you want to hand over the polyhedron via a [supported file format](https://esa.github.io/polyhedral-gravity-model/quickstart/supported_input.html),
152
152
  just replace the `polyhedral_source` argument with *a list of strings*,
153
- where each string is the path to a supported file format.
153
+ where each string is the path to a supported file format, e.g. `polyhedral_source=["eros.node","eros.face"]` or `polyhedral_source=["eros.mesh"]`.
154
154
 
155
155
  Continuing, the simplest way to compute the gravity is to use the `evaluate` function:
156
156
 
@@ -168,14 +168,15 @@ evaluations. This is especially useful if you want to compute the gravity
168
168
  for multiple computation points, but don't know the "future points" in advance.
169
169
 
170
170
  ```python
171
- evaluable = GravityEvaluable(polyhedron=cube_polyhedron)
171
+ evaluable = GravityEvaluable(polyhedron=cube_polyhedron) # stores intermediate computation steps
172
172
  potential, acceleration, tensor = evaluable(
173
173
  computation_points=computation_point,
174
174
  parallel=True,
175
175
  )
176
+ # Any future evaluable call after this one will be faster
176
177
  ```
177
178
 
178
- Note that the `computation_point` could also be (N, 3)-shaped array.
179
+ Note that the `computation_point` could also be (N, 3)-shaped array to compute multiple points at once.
179
180
  In this case, the return value of `evaluate(..)` or an `GravityEvaluable` will
180
181
  be a list of triplets comprising potential, acceleration, and tensor.
181
182
 
@@ -185,15 +186,15 @@ This property is - by default - checked when constructing the `Polyhedron`! So,
185
186
  is impossible if not **explicitly** disabled to create an invalid `Polyhedron`.
186
187
  You can disable/ enable this setting via the optional `integrity_check` flag and can even
187
188
  automatically repair the ordering via `HEAL`.
188
- As advanced user/ when you "know the mesh",
189
- you want to disable this check (via `DISABLE`) due to the additional runtime overhead!
189
+ If you are confident that your mesh is defined correctly (e.g. checked once with the integrity check)
190
+ you can disable this check (via `DISABLE`) to avoid the additional runtime overhead of the check.
190
191
 
191
192
  ```python
192
193
  cube_polyhedron = Polyhedron(
193
194
  polyhedral_source=(cube_vertices, cube_faces),
194
195
  density=cube_density,
195
196
  normal_orientation=NormalOrientation.INWARDS, # OUTWARDS (default) or INWARDS
196
- integrity_check=PolyhedronIntegrity.VERIFY, # AUTOMATIC (default) == VERIFY, DISABLE or HEAL
197
+ integrity_check=PolyhedronIntegrity.VERIFY, # VERIFY (default), DISABLE or HEAL
197
198
  )
198
199
  ```
199
200
 
@@ -276,12 +277,12 @@ The project uses the following dependencies,
276
277
  all of them are **automatically** set-up via CMake:
277
278
 
278
279
  - GoogleTest (1.13.0 or compatible), only required for testing
279
- - spdlog (1.11.0 or compatible), required for logging
280
+ - spdlog (1.13.0 or compatible), required for logging
280
281
  - tetgen (1.6 or compatible), required for I/O
281
- - yaml-cpp (0.7.0 or compatible), required for I/O
282
+ - yaml-cpp (0.8.0 or compatible), required for I/O
282
283
  - thrust (2.1.0 or compatible), required for parallelization and utility
283
284
  - xsimd (11.1.0 or compatible), required for vectorization of the `atan(..)`
284
- - pybind11 (2.10.4 or compatible), required for the Python interface, but not the C++ standalone
285
+ - pybind11 (2.12.0 or compatible), required for the Python interface, but not the C++ standalone
285
286
 
286
287
  The module will be build using a C++17 capable compiler,
287
288
  CMake. Just execute the following command in
@@ -333,8 +334,7 @@ The following options are available:
333
334
  During testing POLYHEDRAL_GRAVITY_PARALLELIZATION=`TBB` has been the most performant.
334
335
  It is further not recommend to change the LOGGING_LEVEL to something else than `INFO=2`.
335
336
 
336
- The recommended CMake command would look like this (we only need to change `PARALLELIZATION_DEVICE`, since
337
- the defaults of the others are already correctly set):
337
+ The recommended CMake settings using the `TBB` backend would look like this:
338
338
 
339
339
  ```bash
340
340
  cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
@@ -345,7 +345,7 @@ cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
345
345
  After the build, the gravity model can be run by executing:
346
346
 
347
347
  ```bash
348
- ./polyhedralGravity <YAML-Configuration-File>
348
+ ./polyhedralGravity <YAML-Configuration-File>
349
349
  ```
350
350
 
351
351
  where the YAML-Configuration-File contains the required parameters.
@@ -60,8 +60,8 @@ which is strongly based on the former implementation in FORTRAN.
60
60
 
61
61
  > [!NOTE]
62
62
  > The [GitHub Pages](https://esa.github.io/polyhedral-gravity-model) of this project
63
- contain the full extensive documentation of C++ Library and the Python Interface
64
- as well as background on the gravity model and advanced settings not detailed here!
63
+ contain the full extensive documentation of the C++ Library and Python Interface
64
+ as well as background on the gravity model and advanced settings not detailed here.
65
65
 
66
66
  ## Input & Output (C++ and Python)
67
67
 
@@ -120,7 +120,7 @@ cube_density = 1.0
120
120
  computation_point = np.array([0, 0, 0])
121
121
  ```
122
122
 
123
- We first, define a constant density Polyhedron from `vertices` and `faces`
123
+ We first define a constant density Polyhedron from `vertices` and `faces`
124
124
 
125
125
  ```python
126
126
  cube_polyhedron = Polyhedron(
@@ -129,9 +129,9 @@ cube_polyhedron = Polyhedron(
129
129
  )
130
130
  ```
131
131
 
132
- In case you want to hand over the polyhedron via a supported file format,
132
+ In case you want to hand over the polyhedron via a [supported file format](https://esa.github.io/polyhedral-gravity-model/quickstart/supported_input.html),
133
133
  just replace the `polyhedral_source` argument with *a list of strings*,
134
- where each string is the path to a supported file format.
134
+ where each string is the path to a supported file format, e.g. `polyhedral_source=["eros.node","eros.face"]` or `polyhedral_source=["eros.mesh"]`.
135
135
 
136
136
  Continuing, the simplest way to compute the gravity is to use the `evaluate` function:
137
137
 
@@ -149,14 +149,15 @@ evaluations. This is especially useful if you want to compute the gravity
149
149
  for multiple computation points, but don't know the "future points" in advance.
150
150
 
151
151
  ```python
152
- evaluable = GravityEvaluable(polyhedron=cube_polyhedron)
152
+ evaluable = GravityEvaluable(polyhedron=cube_polyhedron) # stores intermediate computation steps
153
153
  potential, acceleration, tensor = evaluable(
154
154
  computation_points=computation_point,
155
155
  parallel=True,
156
156
  )
157
+ # Any future evaluable call after this one will be faster
157
158
  ```
158
159
 
159
- Note that the `computation_point` could also be (N, 3)-shaped array.
160
+ Note that the `computation_point` could also be (N, 3)-shaped array to compute multiple points at once.
160
161
  In this case, the return value of `evaluate(..)` or an `GravityEvaluable` will
161
162
  be a list of triplets comprising potential, acceleration, and tensor.
162
163
 
@@ -166,15 +167,15 @@ This property is - by default - checked when constructing the `Polyhedron`! So,
166
167
  is impossible if not **explicitly** disabled to create an invalid `Polyhedron`.
167
168
  You can disable/ enable this setting via the optional `integrity_check` flag and can even
168
169
  automatically repair the ordering via `HEAL`.
169
- As advanced user/ when you "know the mesh",
170
- you want to disable this check (via `DISABLE`) due to the additional runtime overhead!
170
+ If you are confident that your mesh is defined correctly (e.g. checked once with the integrity check)
171
+ you can disable this check (via `DISABLE`) to avoid the additional runtime overhead of the check.
171
172
 
172
173
  ```python
173
174
  cube_polyhedron = Polyhedron(
174
175
  polyhedral_source=(cube_vertices, cube_faces),
175
176
  density=cube_density,
176
177
  normal_orientation=NormalOrientation.INWARDS, # OUTWARDS (default) or INWARDS
177
- integrity_check=PolyhedronIntegrity.VERIFY, # AUTOMATIC (default) == VERIFY, DISABLE or HEAL
178
+ integrity_check=PolyhedronIntegrity.VERIFY, # VERIFY (default), DISABLE or HEAL
178
179
  )
179
180
  ```
180
181
 
@@ -257,12 +258,12 @@ The project uses the following dependencies,
257
258
  all of them are **automatically** set-up via CMake:
258
259
 
259
260
  - GoogleTest (1.13.0 or compatible), only required for testing
260
- - spdlog (1.11.0 or compatible), required for logging
261
+ - spdlog (1.13.0 or compatible), required for logging
261
262
  - tetgen (1.6 or compatible), required for I/O
262
- - yaml-cpp (0.7.0 or compatible), required for I/O
263
+ - yaml-cpp (0.8.0 or compatible), required for I/O
263
264
  - thrust (2.1.0 or compatible), required for parallelization and utility
264
265
  - xsimd (11.1.0 or compatible), required for vectorization of the `atan(..)`
265
- - pybind11 (2.10.4 or compatible), required for the Python interface, but not the C++ standalone
266
+ - pybind11 (2.12.0 or compatible), required for the Python interface, but not the C++ standalone
266
267
 
267
268
  The module will be build using a C++17 capable compiler,
268
269
  CMake. Just execute the following command in
@@ -314,8 +315,7 @@ The following options are available:
314
315
  During testing POLYHEDRAL_GRAVITY_PARALLELIZATION=`TBB` has been the most performant.
315
316
  It is further not recommend to change the LOGGING_LEVEL to something else than `INFO=2`.
316
317
 
317
- The recommended CMake command would look like this (we only need to change `PARALLELIZATION_DEVICE`, since
318
- the defaults of the others are already correctly set):
318
+ The recommended CMake settings using the `TBB` backend would look like this:
319
319
 
320
320
  ```bash
321
321
  cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
@@ -326,7 +326,7 @@ cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
326
326
  After the build, the gravity model can be run by executing:
327
327
 
328
328
  ```bash
329
- ./polyhedralGravity <YAML-Configuration-File>
329
+ ./polyhedralGravity <YAML-Configuration-File>
330
330
  ```
331
331
 
332
332
  where the YAML-Configuration-File contains the required parameters.
@@ -2,7 +2,7 @@ include(FetchContent)
2
2
 
3
3
  message(STATUS "Setting up pybind11")
4
4
 
5
- find_package(pybind11 2.10.4 QUIET)
5
+ find_package(pybind11 2.12.0 QUIET)
6
6
 
7
7
  if (${pybind11_FOUND})
8
8
 
@@ -12,11 +12,10 @@ else()
12
12
 
13
13
  message(STATUS "Using pybind11 from git repository")
14
14
 
15
- #Fetches the version 2.10.4 from the official github of pybind11
16
15
  FetchContent_Declare(pybind11
17
16
  GIT_REPOSITORY https://github.com/pybind/pybind11
18
- GIT_TAG v2.10.4
19
- )
17
+ GIT_TAG v2.12.0
18
+ )
20
19
 
21
20
  FetchContent_MakeAvailable(pybind11)
22
21
 
@@ -2,7 +2,7 @@ include(FetchContent)
2
2
 
3
3
  message(STATUS "Setting up spdlog")
4
4
 
5
- find_package(spdlog 1.11.0 QUIET)
5
+ find_package(spdlog 1.13.0 QUIET)
6
6
 
7
7
  if (${spdlog_FOUND})
8
8
 
@@ -12,11 +12,10 @@ else()
12
12
 
13
13
  message(STATUS "Using spdlog from git repository")
14
14
 
15
- #Fetches the version 1.11.0 for spdlog
16
15
  FetchContent_Declare(spdlog
17
16
  GIT_REPOSITORY https://github.com/gabime/spdlog.git
18
- GIT_TAG v1.11.0
19
- )
17
+ GIT_TAG v1.13.0
18
+ )
20
19
 
21
20
  # Disable stuff we don't need
22
21
  option(SPDLOG_BUILD_EXAMPLE "" OFF)
@@ -2,11 +2,11 @@ include(FetchContent)
2
2
 
3
3
  message(STATUS "Setting up tbb via CMake")
4
4
 
5
- #Fetches the version v2021.5.0 from the official github of tbb
5
+ #Fetches the version v2021.12.0 from the official github of tbb
6
6
  FetchContent_Declare(tbb
7
7
  GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git
8
- GIT_TAG v2021.5.0
9
- )
8
+ GIT_TAG v2021.12.0
9
+ )
10
10
 
11
11
  # Disable tests & and do not treat tbb-compile errors as warnings
12
12
  option(TBB_TEST "Enable testing" OFF)
@@ -2,7 +2,7 @@ include(FetchContent)
2
2
 
3
3
  message(STATUS "Setting up yaml-cpp")
4
4
 
5
- find_package(yaml-cpp 0.7.0 QUIET)
5
+ find_package(yaml-cpp 0.8.0 QUIET)
6
6
 
7
7
  if (${yaml-cpp_FOUND})
8
8
 
@@ -10,10 +10,10 @@ if (${yaml-cpp_FOUND})
10
10
 
11
11
  else()
12
12
 
13
- #Fetches the version 0.7.0 for yaml-cpp
13
+ #Fetches the version 0.8.0 for yaml-cpp
14
14
  FetchContent_Declare(yaml-cpp
15
15
  GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
16
- GIT_TAG yaml-cpp-0.7.0
16
+ GIT_TAG 0.8.0
17
17
  )
18
18
 
19
19
  # Disable everything we don't need
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyhedral_gravity
3
- Version: 3.0rc3
3
+ Version: 3.2
4
4
  Summary: Package to compute full gravity tensor of a given constant density polyhedron for arbitrary points according to the geodetic convention
5
5
  Author: Jonas Schuhmacher
6
6
  Author-email: jonas.schuhmacher@tum.de
@@ -79,8 +79,8 @@ which is strongly based on the former implementation in FORTRAN.
79
79
 
80
80
  > [!NOTE]
81
81
  > The [GitHub Pages](https://esa.github.io/polyhedral-gravity-model) of this project
82
- contain the full extensive documentation of C++ Library and the Python Interface
83
- as well as background on the gravity model and advanced settings not detailed here!
82
+ contain the full extensive documentation of the C++ Library and Python Interface
83
+ as well as background on the gravity model and advanced settings not detailed here.
84
84
 
85
85
  ## Input & Output (C++ and Python)
86
86
 
@@ -139,7 +139,7 @@ cube_density = 1.0
139
139
  computation_point = np.array([0, 0, 0])
140
140
  ```
141
141
 
142
- We first, define a constant density Polyhedron from `vertices` and `faces`
142
+ We first define a constant density Polyhedron from `vertices` and `faces`
143
143
 
144
144
  ```python
145
145
  cube_polyhedron = Polyhedron(
@@ -148,9 +148,9 @@ cube_polyhedron = Polyhedron(
148
148
  )
149
149
  ```
150
150
 
151
- In case you want to hand over the polyhedron via a supported file format,
151
+ In case you want to hand over the polyhedron via a [supported file format](https://esa.github.io/polyhedral-gravity-model/quickstart/supported_input.html),
152
152
  just replace the `polyhedral_source` argument with *a list of strings*,
153
- where each string is the path to a supported file format.
153
+ where each string is the path to a supported file format, e.g. `polyhedral_source=["eros.node","eros.face"]` or `polyhedral_source=["eros.mesh"]`.
154
154
 
155
155
  Continuing, the simplest way to compute the gravity is to use the `evaluate` function:
156
156
 
@@ -168,14 +168,15 @@ evaluations. This is especially useful if you want to compute the gravity
168
168
  for multiple computation points, but don't know the "future points" in advance.
169
169
 
170
170
  ```python
171
- evaluable = GravityEvaluable(polyhedron=cube_polyhedron)
171
+ evaluable = GravityEvaluable(polyhedron=cube_polyhedron) # stores intermediate computation steps
172
172
  potential, acceleration, tensor = evaluable(
173
173
  computation_points=computation_point,
174
174
  parallel=True,
175
175
  )
176
+ # Any future evaluable call after this one will be faster
176
177
  ```
177
178
 
178
- Note that the `computation_point` could also be (N, 3)-shaped array.
179
+ Note that the `computation_point` could also be (N, 3)-shaped array to compute multiple points at once.
179
180
  In this case, the return value of `evaluate(..)` or an `GravityEvaluable` will
180
181
  be a list of triplets comprising potential, acceleration, and tensor.
181
182
 
@@ -185,15 +186,15 @@ This property is - by default - checked when constructing the `Polyhedron`! So,
185
186
  is impossible if not **explicitly** disabled to create an invalid `Polyhedron`.
186
187
  You can disable/ enable this setting via the optional `integrity_check` flag and can even
187
188
  automatically repair the ordering via `HEAL`.
188
- As advanced user/ when you "know the mesh",
189
- you want to disable this check (via `DISABLE`) due to the additional runtime overhead!
189
+ If you are confident that your mesh is defined correctly (e.g. checked once with the integrity check)
190
+ you can disable this check (via `DISABLE`) to avoid the additional runtime overhead of the check.
190
191
 
191
192
  ```python
192
193
  cube_polyhedron = Polyhedron(
193
194
  polyhedral_source=(cube_vertices, cube_faces),
194
195
  density=cube_density,
195
196
  normal_orientation=NormalOrientation.INWARDS, # OUTWARDS (default) or INWARDS
196
- integrity_check=PolyhedronIntegrity.VERIFY, # AUTOMATIC (default) == VERIFY, DISABLE or HEAL
197
+ integrity_check=PolyhedronIntegrity.VERIFY, # VERIFY (default), DISABLE or HEAL
197
198
  )
198
199
  ```
199
200
 
@@ -276,12 +277,12 @@ The project uses the following dependencies,
276
277
  all of them are **automatically** set-up via CMake:
277
278
 
278
279
  - GoogleTest (1.13.0 or compatible), only required for testing
279
- - spdlog (1.11.0 or compatible), required for logging
280
+ - spdlog (1.13.0 or compatible), required for logging
280
281
  - tetgen (1.6 or compatible), required for I/O
281
- - yaml-cpp (0.7.0 or compatible), required for I/O
282
+ - yaml-cpp (0.8.0 or compatible), required for I/O
282
283
  - thrust (2.1.0 or compatible), required for parallelization and utility
283
284
  - xsimd (11.1.0 or compatible), required for vectorization of the `atan(..)`
284
- - pybind11 (2.10.4 or compatible), required for the Python interface, but not the C++ standalone
285
+ - pybind11 (2.12.0 or compatible), required for the Python interface, but not the C++ standalone
285
286
 
286
287
  The module will be build using a C++17 capable compiler,
287
288
  CMake. Just execute the following command in
@@ -333,8 +334,7 @@ The following options are available:
333
334
  During testing POLYHEDRAL_GRAVITY_PARALLELIZATION=`TBB` has been the most performant.
334
335
  It is further not recommend to change the LOGGING_LEVEL to something else than `INFO=2`.
335
336
 
336
- The recommended CMake command would look like this (we only need to change `PARALLELIZATION_DEVICE`, since
337
- the defaults of the others are already correctly set):
337
+ The recommended CMake settings using the `TBB` backend would look like this:
338
338
 
339
339
  ```bash
340
340
  cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
@@ -345,7 +345,7 @@ cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"
345
345
  After the build, the gravity model can be run by executing:
346
346
 
347
347
  ```bash
348
- ./polyhedralGravity <YAML-Configuration-File>
348
+ ./polyhedralGravity <YAML-Configuration-File>
349
349
  ```
350
350
 
351
351
  where the YAML-Configuration-File contains the required parameters.
@@ -41,6 +41,8 @@ src/polyhedralGravity/output/Logging.cpp
41
41
  src/polyhedralGravity/output/Logging.h
42
42
  src/polyhedralGravity/util/UtilityConstants.h
43
43
  src/polyhedralGravity/util/UtilityContainer.h
44
+ src/polyhedralGravity/util/UtilityFloatArithmetic.cpp
45
+ src/polyhedralGravity/util/UtilityFloatArithmetic.h
44
46
  src/polyhedralGravity/util/UtilityThrust.h
45
47
  src/polyhedralGravityPython/CMakeLists.txt
46
48
  src/polyhedralGravityPython/PolyhedralGravityPython.cpp
@@ -175,7 +175,7 @@ picture_in_readme = '''<p align="center">
175
175
  # --------------------------------------------------------------------------------
176
176
  setup(
177
177
  name="polyhedral_gravity",
178
- version="3.0rc3",
178
+ version="3.2",
179
179
  author="Jonas Schuhmacher",
180
180
  author_email="jonas.schuhmacher@tum.de",
181
181
  description="Package to compute full gravity tensor of a given constant density polyhedron for arbitrary points "
@@ -6,7 +6,7 @@
6
6
  #include <algorithm>
7
7
  #include <tuple>
8
8
  #include "polyhedralGravity/util/UtilityContainer.h"
9
- #include "polyhedralGravity/util/UtilityConstants.h"
9
+ #include "polyhedralGravity/util/UtilityFloatArithmetic.h"
10
10
 
11
11
  namespace polyhedralGravity {
12
12
 
@@ -76,20 +76,23 @@ namespace polyhedralGravity {
76
76
  double s2;
77
77
 
78
78
  /**
79
- * Checks two Distance structs for equality.
80
- * @warning This method compares doubles! So only exact copies will evaluate to true.
79
+ * Checks two Distance structs for equality with another one by ensuring that the members are
80
+ * almost equal.
81
81
  * @param rhs the other Distance struct
82
82
  * @return true if equal
83
83
  *
84
84
  * @note Just used for testing purpose
85
85
  */
86
86
  bool operator==(const Distance &rhs) const {
87
- return l1 == rhs.l1 && l2 == rhs.l2 && s1 == rhs.s1 && s2 == rhs.s2;
87
+ return util::almostEqualRelative(l1, rhs.l1) &&
88
+ util::almostEqualRelative(l2, rhs.l2) &&
89
+ util::almostEqualRelative(s1, rhs.s1) &&
90
+ util::almostEqualRelative(s2, rhs.s2);
88
91
  }
89
92
 
90
93
  /**
91
- * Checks two Distance structs for inequality.
92
- * @warning This method compares doubles! So only exact copies will evaluate to false.
94
+ * Checks two Distance structs for inequality with another one by ensuring that the members are
95
+ * not almost equal.
93
96
  * @param rhs the other Distance struct
94
97
  * @return false if unequal
95
98
  *
@@ -130,20 +133,20 @@ namespace polyhedralGravity {
130
133
  double an;
131
134
 
132
135
  /**
133
- * Checks two TranscendentalExpressions for equality.
134
- * @warning This method compares doubles! So only exact copies will evaluate to true.
136
+ * Checks two TranscendentalExpressions for equality with another one by ensuring that the members are
137
+ * almost equal.
135
138
  * @param rhs the other TranscendentalExpressions
136
139
  * @return true if equal
137
140
  *
138
141
  * @note Just used for testing purpose
139
142
  */
140
143
  bool operator==(const TranscendentalExpression &rhs) const {
141
- return ln == rhs.ln && an == rhs.an;
144
+ return util::almostEqualRelative(ln, rhs.ln) && util::almostEqualRelative(an, rhs.an);
142
145
  }
143
146
 
144
147
  /**
145
- * Checks two TranscendentalExpressions for inequality.
146
- * @warning This method compares doubles! So only exact copies will evaluate to false.
148
+ * Checks two TranscendentalExpressions for inequality with another one by ensuring that the members are
149
+ * not almost equal.
147
150
  * @param rhs the other TranscendentalExpressions
148
151
  * @return false if unequal
149
152
  *
@@ -191,20 +194,23 @@ namespace polyhedralGravity {
191
194
  double d;
192
195
 
193
196
  /**
194
- * Checking the equality of two this Hessian Plane with another one by comparing their members.
195
- * @warning This method compares doubles! So only exact copies will evaluate to true.
197
+ * Checking the equality of two this Hessian Plane with another one by ensuring that the members are
198
+ * almost equal.
196
199
  * @param rhs other HessianPlane
197
200
  * @return true if equal
198
201
  *
199
202
  * @note Just used for testing purpose
200
203
  */
201
204
  bool operator==(const HessianPlane &rhs) const {
202
- return a == rhs.a && b == rhs.b && c == rhs.c && d == rhs.d;
205
+ return util::almostEqualRelative(a, rhs.a) &&
206
+ util::almostEqualRelative(b, rhs.b) &&
207
+ util::almostEqualRelative(c, rhs.c) &&
208
+ util::almostEqualRelative(d, rhs.d);
203
209
  }
204
210
 
205
211
  /**
206
- * Checking the inequality of two this Hessian Plane with another one by comparing their members.
207
- * @warning This method compares doubles! So only exact copies will evaluate to false.
212
+ * Checking the inequality of two this Hessian Plane with another one by ensuring that the members are
213
+ * not almost equal.
208
214
  * @param rhs other HessianPlane
209
215
  * @return true if unequal
210
216
  *
@@ -213,6 +219,17 @@ namespace polyhedralGravity {
213
219
  bool operator!=(const HessianPlane &rhs) const {
214
220
  return !(rhs == *this);
215
221
  }
222
+
223
+ /**
224
+ * Pretty output of this struct on the given ostream.
225
+ * @param os the ostream
226
+ * @param hessianPlane a HessianPlane
227
+ * @return os
228
+ */
229
+ friend std::ostream &operator<<(std::ostream &os, const HessianPlane &hessianPlane) {
230
+ os << "a: " << hessianPlane.a << " b: " << hessianPlane.b << " c: " << hessianPlane.c << " d: " << hessianPlane.d;
231
+ return os;
232
+ }
216
233
  };
217
234
 
218
235
  }
@@ -28,7 +28,7 @@ namespace polyhedralGravity::GravityModel::detail {
28
28
  //Calculate N_i * -G_i1 where * is the dot product and then use the inverted sgn
29
29
  //We abstain on the double multiplication with -1 in the line above and beyond since two
30
30
  //times multiplying with -1 equals no change
31
- return sgn(dot(planeUnitNormal, vertex0), util::EPSILON);
31
+ return sgn(dot(planeUnitNormal, vertex0), util::EPSILON_ZERO_OFFSET);
32
32
  }
33
33
 
34
34
  HessianPlane computeHessianPlane(const Array3 &p, const Array3 &q, const Array3 &r) {
@@ -95,7 +95,7 @@ namespace polyhedralGravity::GravityModel::detail {
95
95
  segmentNormalOrientations.begin(),
96
96
  [&projectionPointOnPlane](const Array3 &segmentUnitNormal, const Array3 &vertex) {
97
97
  using namespace util;
98
- return sgn((dot(segmentUnitNormal, projectionPointOnPlane - vertex)), util::EPSILON) * -1.0;
98
+ return sgn((dot(segmentUnitNormal, projectionPointOnPlane - vertex)), util::EPSILON_ZERO_OFFSET) * -1.0;
99
99
  });
100
100
  return segmentNormalOrientations;
101
101
  }
@@ -190,8 +190,8 @@ namespace polyhedralGravity::GravityModel::detail {
190
190
 
191
191
  //4. Option: |s1 - l1| == 0 && |s2 - l2| == 0 Computation point P is located from the beginning on
192
192
  // the direction of a specific segment (P coincides with P' and P'')
193
- if (std::abs(distance.s1 - distance.l1) < EPSILON &&
194
- std::abs(distance.s2 - distance.l2) < EPSILON) {
193
+ if (std::abs(distance.s1 - distance.l1) < EPSILON_ZERO_OFFSET &&
194
+ std::abs(distance.s2 - distance.l2) < EPSILON_ZERO_OFFSET) {
195
195
  //4. Option - Case 2: P is located on the segment from its right side
196
196
  // s1 = -|s1|, s2 = -|s2|, l1 = -|l1|, l2 = -|l2|
197
197
  if (distance.s2 < distance.s1) {
@@ -200,7 +200,7 @@ namespace polyhedralGravity::GravityModel::detail {
200
200
  distance.l1 *= -1.0;
201
201
  distance.l2 *= -1.0;
202
202
  return distance;
203
- } else if (std::abs(distance.s2 - distance.s1) < EPSILON) {
203
+ } else if (std::abs(distance.s2 - distance.s1) < EPSILON_ZERO_OFFSET) {
204
204
  //4. Option - Case 1: P is located inside the segment (s2 == s1)
205
205
  // s1 = -|s1|, s2 = |s2|, l1 = -|l1|, l2 = |l2|
206
206
  distance.s1 *= -1.0;
@@ -264,9 +264,9 @@ namespace polyhedralGravity::GravityModel::detail {
264
264
  // If sigma_pq == 0 && either of the distances of P' to the two segment endpoints == 0 OR
265
265
  // the 1D and 3D distances are smaller than some EPSILON
266
266
  // then LN_pq can be set to zero
267
- if ((segmentNormalOrientation == 0.0 && (r1Norm < EPSILON || r2Norm < EPSILON)) ||
268
- (std::abs(distance.s1 + distance.s2) < EPSILON &&
269
- std::abs(distance.l1 + distance.l2) < EPSILON)) {
267
+ if ((segmentNormalOrientation == 0.0 && (r1Norm < EPSILON_ZERO_OFFSET || r2Norm < EPSILON_ZERO_OFFSET)) ||
268
+ (std::abs(distance.s1 + distance.s2) < EPSILON_ZERO_OFFSET &&
269
+ std::abs(distance.l1 + distance.l2) < EPSILON_ZERO_OFFSET)) {
270
270
  transcendentalExpressionPerSegment.ln = 0.0;
271
271
  } else {
272
272
  //Implementation of
@@ -277,7 +277,7 @@ namespace polyhedralGravity::GravityModel::detail {
277
277
 
278
278
  //Compute AN_pq according to (15)
279
279
  // If h_p == 0 or h_pq == 0 then AN_pq is zero, too (distances are always positive!)
280
- if (planeDistance < EPSILON || segmentDistance < EPSILON) {
280
+ if (planeDistance < EPSILON_ZERO_OFFSET || segmentDistance < EPSILON_ZERO_OFFSET) {
281
281
  transcendentalExpressionPerSegment.an = 0.0;
282
282
  } else {
283
283
  //Implementation of:
@@ -331,7 +331,7 @@ namespace polyhedralGravity::GravityModel::detail {
331
331
  const unsigned int j = thrust::get<2>(tuple);
332
332
 
333
333
  //segmentNormalOrientation != 0.0
334
- if (std::abs(segmentNormalOrientation) > EPSILON) {
334
+ if (std::abs(segmentNormalOrientation) > EPSILON_ZERO_OFFSET) {
335
335
  return false;
336
336
  }
337
337
 
@@ -358,14 +358,14 @@ namespace polyhedralGravity::GravityModel::detail {
358
358
  j = thrust::get<1>(tuple);
359
359
 
360
360
  //segmentNormalOrientation != 0.0
361
- if (std::abs(segmentNormalOrientation) > EPSILON) {
361
+ if (std::abs(segmentNormalOrientation) > EPSILON_ZERO_OFFSET) {
362
362
  return false;
363
363
  }
364
364
 
365
365
  r1Norm = projectionPointVertexNorms[(j + 1) % 3];
366
366
  r2Norm = projectionPointVertexNorms[j];
367
367
  //r1Norm == 0.0 || r2Norm == 0.0
368
- return r1Norm < EPSILON || r2Norm < EPSILON;
368
+ return r1Norm < EPSILON_ZERO_OFFSET || r2Norm < EPSILON_ZERO_OFFSET;
369
369
  })) {
370
370
  using namespace util;
371
371
  //Two segment vectors G_1 and G_2 of this plane
@@ -21,6 +21,7 @@
21
21
  #include "polyhedralGravity/util/UtilityConstants.h"
22
22
  #include "polyhedralGravity/util/UtilityContainer.h"
23
23
  #include "polyhedralGravity/util/UtilityThrust.h"
24
+ #include "polyhedralGravity/util/UtilityFloatArithmetic.h"
24
25
  #include "polyhedralGravity/output/Logging.h"
25
26
 
26
27
  namespace polyhedralGravity::GravityModel::detail {
@@ -137,7 +137,7 @@ namespace polyhedralGravity {
137
137
  "The mesh check is enabled and analyzes the polyhedron for degnerated faces & "
138
138
  "that all plane unit normals point in the specified direction. This checks requires "
139
139
  "a quadratic runtime cost which is most of the time not desirable. "
140
- "Please explcity set the inetgrity_check to either VERIFY, HEAL or DISABLE."
140
+ "Please explicitly set the integrity_check to either VERIFY, HEAL or DISABLE."
141
141
  "You can find further details in the documentation!");
142
142
  // NO BREAK! AUTOMATIC implies VERIFY, but with a info mesage to explcitly set the option
143
143
  case PolyhedronIntegrity::VERIFY:
@@ -153,13 +153,13 @@ namespace polyhedralGravity {
153
153
  if (violatingIndices.empty()) {
154
154
  sstream << "Instead all plane unit normals are pointing "
155
155
  << actualOrientation
156
- << ". You can either reconstruct the polyhedron with the ortientation set to " << actualOrientation
156
+ << ". You can either reconstruct the polyhedron with the orientation set to " << actualOrientation
157
157
  << ". Alternativly, you can reconstruct with the inetgrity_check set to HEAL";
158
158
  } else {
159
159
  sstream << "The actual majority orientation of the polyhedron's normals is " << actualOrientation
160
160
  << ". You can either:\n 1) Fix the ordering of the following faces:\n"
161
161
  << violatingIndices << '\n'
162
- << "2) Or you reconstruct the polyhedron using the inetgrity_check set to HEAL.";
162
+ << "2) Or you reconstruct the polyhedron using the integrity_check set to HEAL.";
163
163
  }
164
164
  // In case of HEAL, don't throw but repair
165
165
  if (integrity != PolyhedronIntegrity::HEAL) {
@@ -202,7 +202,7 @@ namespace polyhedralGravity {
202
202
  const Array3 rayVector = normal(segmentVector1, segmentVector2);
203
203
 
204
204
  // The origin of the array has a slight offset in direction of the normal
205
- const Array3 rayOrigin = centroid + (rayVector * EPSILON);
205
+ const Array3 rayOrigin = centroid + (rayVector * EPSILON_ZERO_OFFSET);
206
206
 
207
207
  // Count every triangular face which is intersected by the ray
208
208
  const auto &[begin, end] = this->transformIterator();
@@ -224,7 +224,7 @@ namespace polyhedralGravity {
224
224
  const Array3 edge2 = triangle[2] - triangle[0];
225
225
  const Array3 h = cross(rayVector, edge2);
226
226
  const double a = dot(edge1, h);
227
- if (a > -EPSILON && a < EPSILON) {
227
+ if (a > -EPSILON_ZERO_OFFSET && a < EPSILON_ZERO_OFFSET) {
228
228
  return nullptr;
229
229
  }
230
230
 
@@ -242,7 +242,7 @@ namespace polyhedralGravity {
242
242
  }
243
243
 
244
244
  const double t = f * dot(edge2, q);
245
- if (t > EPSILON) {
245
+ if (t > EPSILON_ZERO_OFFSET) {
246
246
  return std::make_unique<Array3>(rayOrigin + rayVector * t);
247
247
  } else {
248
248
  return nullptr;
@@ -22,6 +22,7 @@
22
22
  #include "thrust/iterator/transform_iterator.h"
23
23
  #include "polyhedralGravity/util/UtilityContainer.h"
24
24
  #include "polyhedralGravity/util/UtilityConstants.h"
25
+ #include "polyhedralGravity/util/UtilityFloatArithmetic.h"
25
26
 
26
27
  namespace polyhedralGravity {
27
28
 
@@ -150,7 +151,7 @@ namespace polyhedralGravity {
150
151
  *
151
152
  * @note ASSERTS PRE-CONDITION that the in the indexing in the faces vector starts with zero!
152
153
  * @throws std::invalid_argument if no face contains the node zero indicating mathematical index
153
- * @throws std::invalid_argument dpending on the {@param integrity} flag
154
+ * @throws std::invalid_argument dpending on the {@link integrity} flag
154
155
  */
155
156
  Polyhedron(
156
157
  const std::vector<Array3> &vertices,
@@ -169,7 +170,7 @@ namespace polyhedralGravity {
169
170
  *
170
171
  * @note ASSERTS PRE-CONDITION that the in the indexing in the faces vector starts with zero!
171
172
  * @throws std::invalid_argument if no face contains the node zero indicating mathematical index
172
- * @throws std::invalid_argument dpending on the {@param integrity} flag
173
+ * @throws std::invalid_argument dpending on the {@link integrity} flag
173
174
  */
174
175
  Polyhedron(
175
176
  const PolyhedralSource &polyhedralSource,
@@ -187,7 +188,7 @@ namespace polyhedralGravity {
187
188
  *
188
189
  * @note ASSERTS PRE-CONDITION that the in the indexing in the faces vector starts with zero!
189
190
  * @throws std::invalid_argument if no face contains the node zero indicating mathematical index
190
- * @throws std::invalid_argument dpending on the {@param integrity} flag
191
+ * @throws std::invalid_argument dpending on the {@link integrity} flag
191
192
  */
192
193
  Polyhedron(const PolyhedralFiles &polyhedralFiles, double density,
193
194
  const NormalOrientation &orientation = NormalOrientation::OUTWARDS,
@@ -203,7 +204,7 @@ namespace polyhedralGravity {
203
204
  *
204
205
  * @note ASSERTS PRE-CONDITION that the in the indexing in the faces vector starts with zero!
205
206
  * @throws std::invalid_argument if no face contains the node zero indicating mathematical index
206
- * @throws std::invalid_argument dpending on the {@param integrity} flag
207
+ * @throws std::invalid_argument dpending on the {@link integrity} flag
207
208
  */
208
209
  Polyhedron(const std::variant<PolyhedralSource, PolyhedralFiles> &polyhedralSource, double density,
209
210
  const NormalOrientation &orientation = NormalOrientation::OUTWARDS,
@@ -2,15 +2,6 @@
2
2
 
3
3
  namespace polyhedralGravity::util {
4
4
 
5
- /**
6
- * The EPSILON used in the polyhedral gravity model.
7
- * @related Used to determine if a floating point number is equal to zero as threshold for rounding errors
8
- * @related Used for the sgn() function to determine the sign of a double value. Different compilers
9
- * produce different results if no EPSILON is applied for the comparison!
10
- */
11
- constexpr double EPSILON = 1e-14;
12
-
13
-
14
5
  /**
15
6
  * PI with enough precision
16
7
  */
@@ -0,0 +1,51 @@
1
+ #include "UtilityFloatArithmetic.h"
2
+
3
+
4
+ namespace polyhedralGravity::util {
5
+
6
+ template<typename FloatType>
7
+ bool almostEqualUlps(FloatType lhs, FloatType rhs, int ulpDistance) {
8
+ static_assert(std::is_same_v<FloatType, float> || std::is_same_v<FloatType, double>,
9
+ "Template argument must be FloatType: Either float or double!");
10
+
11
+ // In case the floats are equal in their representation, return true
12
+ if (lhs == rhs) {
13
+ return true;
14
+ }
15
+
16
+ // In case the signs mismatch, return false
17
+ if (lhs < static_cast<FloatType>(0.0) && rhs > static_cast<FloatType>(0.0) ||
18
+ lhs > static_cast<FloatType>(0.0) && rhs < static_cast<FloatType>(0.0)) {
19
+ return false;
20
+ }
21
+
22
+ if constexpr (std::is_same_v<FloatType, float>) {
23
+ // In case of float, compute ULP distance by interpreting float as 32-bit integer
24
+ return reinterpret_cast<std::int32_t&>(rhs) - reinterpret_cast<std::int32_t&>(lhs) <= ulpDistance;
25
+ }
26
+ else if constexpr (std::is_same_v<FloatType, double>) {
27
+ // In case of double, compute ULP distance by interpreting double as 64-bit integer
28
+ return reinterpret_cast<std::int64_t&>(rhs) - reinterpret_cast<std::int64_t&>(lhs) <= ulpDistance;
29
+ }
30
+
31
+ // Due to the static_assert above, this should not happen
32
+ return false;
33
+ }
34
+
35
+ // Template Instantations for float and double (required since definition is in .cpp file,
36
+ // also makes the static assert not strictly necessary)
37
+ template bool almostEqualUlps<float>(float lhs, float rhs, int ulpDistance);
38
+ template bool almostEqualUlps<double>(double lhs, double rhs, int ulpDistance);
39
+
40
+
41
+ template<typename FloatType>
42
+ bool almostEqualRelative(FloatType lhs, FloatType rhs, double epsilon) {
43
+ const FloatType diff = std::abs(rhs - lhs);
44
+ const FloatType largerValue = std::max(std::abs(rhs), std::abs(lhs));
45
+ return diff <= largerValue * epsilon;
46
+ }
47
+
48
+ template bool almostEqualRelative<float>(float lhs, float rhs, double epsilon);
49
+ template bool almostEqualRelative<double>(double lhs, double rhs, double epsilon);
50
+
51
+ }
@@ -0,0 +1,73 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <cmath>
5
+ #include <cstdint>
6
+ #include <type_traits>
7
+
8
+ namespace polyhedralGravity::util {
9
+
10
+ /**
11
+ * The EPSILON used in the polyhedral gravity model to determine a radius around zero/ to use as slight offset.
12
+ * @related Used to determine if a floating point number is equal to zero as threshold for rounding errors
13
+ * @related Used for the sgn() function to determine the sign of a double value. Different compilers
14
+ * produce different results if no EPSILON is applied for the comparison!
15
+ */
16
+ constexpr double EPSILON_ZERO_OFFSET = 1e-14;
17
+
18
+ /**
19
+ * This relative EPSILON is utilized ONLY for testing purposes to compare intermediate values to
20
+ * Tsoulis' reference implementation Fortran.
21
+ * It is used in the {@link polyhedralGravity::util::almostEqualRelative} function.
22
+ *
23
+ * @note While in theory no difference at all is observed when compiling this program on Linux using GCC on x86_64,
24
+ * the intermediate values change when the program is compiled in different environments.
25
+ * Hence, this solves the flakiness of the tests when on different plattforms
26
+ */
27
+ constexpr double EPSILON_ALMOST_EQUAL = 1e-10;
28
+
29
+ /**
30
+ * The maximal allowed ULP distance utilized for FloatingPoint comparisons using the
31
+ * {@link polyhedralGravity::util::almostEqualUlps} function.
32
+ *
33
+ * @see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
34
+ */
35
+ constexpr int MAX_ULP_DISTANCE = 4;
36
+
37
+
38
+ /**
39
+ * Function for comparing closeness of two floating point numbers using ULP (Units in the Last Place) method.
40
+ *
41
+ * @tparam FloatType must be either double or float (ensured by static assertion)
42
+ * @param lhs The left hand side floating point number to compare.
43
+ * @param rhs The right hand side floating point number to compare.
44
+ * @param ulpDistance The maximum acceptable ULP distance between the two floating points
45
+ * for which they would be considered near each other. This is optional and by default, it will be {@link MAX_ULP_DISTANCE}.
46
+ *
47
+ * @return true if the ULP distance between lhs and rhs is less than or equal to the provided ulpDistance value, otherwise, false.
48
+ * Returns true if both numbers are exactly the same. Returns false if the signs do not match.
49
+ * @example The ULP distance between 3.0 and std::nextafter(3.0, INFINITY) would be 1,
50
+ * the ULP distance of 3.0 and std::nextafter(std::nextafter(3.0, INFINITY), INFINITY) would be 2, etc.
51
+ * @see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
52
+ */
53
+ template<typename FloatType>
54
+ bool almostEqualUlps(FloatType lhs, FloatType rhs, int ulpDistance = MAX_ULP_DISTANCE);
55
+
56
+ /**
57
+ * Function to check if two floating point numbers are relatively equal to each other within a given error range or tolerance.
58
+ *
59
+ * @tparam FloatType must be either double or float (ensured by static assertion)
60
+ * @param lhs The first floating-point number to be compared.
61
+ * @param rhs The second floating-point number to be compared.
62
+ * @param epsilon The tolerance for comparison. Two numbers that are less than epsilon apart are considered equal.
63
+ * The default value is {@link EPSILON_ALMOST_EQUAL}.
64
+ *
65
+ * @return boolean value - Returns `true` if the absolute difference between `lhs` and `rhs` is less than or equal to
66
+ * the relative error factored by the larger of the magnitude of `lhs` and `rhs`. Otherwise, `false`.
67
+ * @see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
68
+ */
69
+ template<typename FloatType>
70
+ bool almostEqualRelative(FloatType lhs, FloatType rhs, double epsilon = EPSILON_ALMOST_EQUAL);
71
+
72
+
73
+ }
@@ -152,8 +152,8 @@ PYBIND11_MODULE(polyhedral_gravity, m) {
152
152
 
153
153
  * :code:`AUTOMATIC` (Default): Prints to stdout and throws ValueError if normal_orientation is wrong/ inconsisten
154
154
  * :code:`VERIFY`: Like :code:`AUTOMATIC`, but does not print to stdout
155
- * :code:`DISABLE`: Recommened, when you know the mesh to avoid to pay :math:`O(n^2)` runtime. Disables ALL checks
156
- * :code`HEAL`: Automatically fixes the normal_orientation and vertex ordering to the correct values
155
+ * :code:`DISABLE`: Recommened, when you are familiar with the mesh to avoid :math:`O(n^2)` runtime cost. Disables ALL checks
156
+ * :code:`HEAL`: Automatically fixes the normal_orientation and vertex ordering to the correct values
157
157
 
158
158
  Raises:
159
159
  ValueError: If the faces array does not contain a reference to vertex 0 indicating an index start at 1
@@ -182,7 +182,7 @@ PYBIND11_MODULE(polyhedral_gravity, m) {
182
182
  This utility is mainly for diagnostics and debugging purposes. If the polyhedron is constrcuted with `integrity_check`
183
183
  set to :code:`AUTOMATIC` or :code:`VERIFY`, the construction fails anyways.
184
184
  If set to :code:`HEAL`, this method should return an empty set (but maybe a different ordering than initially specified)
185
- Only if set to code:`DISABLE`, then this method might actually return a set with faulty indices.
185
+ Only if set to :code:`DISABLE`, then this method might actually return a set with faulty indices.
186
186
  Hence, if you want to know your mesh error. Construct the polyhedron with :code:`integrity_check=DISABLE` and call this method.
187
187
  )mydelimiter")
188
188
  .def("__getitem__", &Polyhedron::getResolvedFace, R"mydelimiter(