Efficient Polyhedral Gravity Modeling in Modern C++ and Python

Efficient Polyhedral Gravity Modeling in Modern C++ and Python - Published in JOSS (2024)

https://github.com/esa/polyhedral-gravity-model

Science Score: 100.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 11 DOI reference(s) in README and JOSS metadata
  • Academic publication links
    Links to: joss.theoj.org
  • Committers with academic emails
    1 of 5 committers (20.0%) from academic institutions
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Keywords

cpp17 gravity polyhedral-model python
Last synced: 4 months ago · JSON representation ·

Repository

Implementation of a polyhedral gravity model in C++17 with a Python Binding

Basic Info
Statistics
  • Stars: 31
  • Watchers: 3
  • Forks: 11
  • Open Issues: 1
  • Releases: 33
Topics
cpp17 gravity polyhedral-model python
Created over 3 years ago · Last pushed 8 months ago
Metadata Files
Readme Contributing License Citation

README.md

polyhedral-gravity-model

DOI GitHub GitHub Actions Workflow Status GitHub Actions Workflow Status

PyPI Static Badge PyPI - Downloads

Conda Conda Conda


Mesh of (433) Eros with 739 vertices and 1474 faces

Table of Contents

References

This code is a validated implementation in C++17 of the Polyhedral Gravity Model by Tsoulis et al.. Additionally, the model provides a Python binding. It was initially created in a collaborative project between TU Munich and ESA's Advanced Concepts Team.

If this implementation proves useful to you, please consider citing the accompanying paper published in the Journal of Open Source Software.

The implementation is based on the paper Tsoulis, D., 2012. Analytical computation of the full gravity tensor of a homogeneous arbitrarily shaped polyhedral source using line integrals. Geophysics, 77(2), pp.F1-F11. and its corresponding implementation in FORTRAN.

Supplementary details can be found in the more recent paper TSOULIS, Dimitrios; GAVRIILIDOU, Georgia. A computational review of the line integral analytical formulation of the polyhedral gravity signal. Geophysical Prospecting, 2021, 69. Jg., Nr. 8-9, S. 1745-1760. and its corresponding implementation in MATLAB, which is strongly based on the former implementation in FORTRAN.

Documentation & Examples

[!NOTE] The GitHub Pages of this project contain the full extensive documentation of the C++ Library and Python Interface as well as background on the gravity model and advanced settings not detailed here.

Input & Output (C++ and Python)

Input

The evaluation of the polyhedral gravity model requires the following parameters:

| Name | |----------------------------------------------------------------------------| | Polyhedral Mesh (either as vertices & faces or as polyhedral source files) | | Constant Density $\rho$ |

The mesh and the constant density's unit must match. Have a look at the documentation to view the supported mesh files.

Output

The calculation outputs the following parameters for every Computation Point P. The units of the respective output depend on the units of the input parameters (mesh and density)! Hence, if e.g., your mesh is in $km$, the density must match. Further, output units will be different accordingly.

| Name | Unit (if mesh in $[m]$ and $\rho$ in $[kg/m^3]$) | Comment | |:----------------------------------------------------------:|:------------------------------------------------:|:----------------------------------------------------------------:| | $V$ | $\frac{m^2}{s^2}$ or $\frac{J}{kg}$ | The potential or also called specific energy | | $Vx$, $Vy$, $Vz$ | $\frac{m}{s^2}$ | The gravitational acceleration in the three cartesian directions | | $V{xx}$, $V{yy}$, $V{zz}$, $V{xy}$, $V{xz}$, $V_{yz}$ | $\frac{1}{s^2}$ | The spatial rate of change of the gravitational acceleration |

[!NOTE] This gravity model's output obeys to the geodesy and geophysics sign conventions. Hence, the potential $V$ for a polyhedron with a mass $m > 0$ is defined as positive. Accordingly, the accelerations are defined as $\textbf{g} = + \nabla V$.

Minimal Python Example

The following example shows how to use the python interface to compute the gravity around a cube:

```python import numpy as np from polyhedral_gravity import Polyhedron, GravityEvaluable, evaluate, PolyhedronIntegrity, NormalOrientation, MetricUnit

We define the cube as a polyhedron with 8 vertices and 12 triangular faces

The polyhedron's normals point outwards (see below for checking this)

The density is set to 1.0

cubevertices = np.array( [[-1, -1, -1], [1, -1, -1], [1, 1, -1], [-1, 1, -1], [-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]] ) cubefaces = np.array( [[1, 3, 2], [0, 3, 1], [0, 1, 5], [0, 5, 4], [0, 7, 3], [0, 4, 7], [1, 2, 6], [1, 6, 5], [2, 3, 6], [3, 7, 6], [4, 5, 6], [4, 6, 7]] ) cubedensity = 1.0 computationpoint = np.array([0, 0, 0]) ```

We first define a constant density Polyhedron from vertices and faces

python cube_polyhedron = Polyhedron( polyhedral_source=(cube_vertices, cube_faces), density=cube_density, )

In case you want to hand over the polyhedron via a supported file format, just replace the polyhedral_source argument with a list of strings, where each string is the path to a supported file format, e.g. polyhedral_source=["eros.node","eros.face"] or polyhedral_source=["eros.mesh"].

Continuing, the simplest way to compute the gravity is to use the evaluate function:

python potential, acceleration, tensor = evaluate( polyhedron=cube_polyhedron, computation_points=computation_point, parallel=True, )

The more advanced way is to use the GravityEvaluable class. It caches the internal data structure and properties which can be reused for multiple evaluations. This is especially useful if you want to compute the gravity for multiple computation points but don't know the "future points" in advance.

```python evaluable = GravityEvaluable(polyhedron=cubepolyhedron) # stores intermediate computation steps potential, acceleration, tensor = evaluable( computationpoints=computation_point, parallel=True, )

Any future evaluable call after this one will be faster

```

Note that the computation_point could also be (N, 3)-shaped array to compute multiple points at once. In this case, the return value of evaluate(..) or an GravityEvaluable will be a list of triplets comprising potential, acceleration, and tensor.

The gravity model requires that all the polyhedron's plane unit normals consistently point outwards or inwards the polyhedron. You can specify this via the normal_orientation. This property is - by default - checked when constructing the Polyhedron! So, don't worry, it is impossible if not explicitly disabled to create an invalid Polyhedron. You can disable/ enable this setting via the optional integrity_check flag and can even automatically repair the ordering via HEAL. If you are confident that your mesh is defined correctly (e.g., checked once with the integrity check) you can disable this check (via DISABLE) to avoid the additional runtime overhead of the check. Also, you can set the metric unit of the mesh and the density. This also influences the output unit. E.g., Density in $kg/m^3$, Mesh in $m$, then the potential is given in $m^2/s^2$.

python cube_polyhedron = Polyhedron( polyhedral_source=(cube_vertices, cube_faces),# coordinates in m (default), km, or unitless density=cube_density, # kg/m^3 (default) or kg/km^3 or unitless normal_orientation=NormalOrientation.INWARDS, # OUTWARDS (default) or INWARDS integrity_check=PolyhedronIntegrity.VERIFY, # VERIFY (default), DISABLE or HEAL metric_unit=MetricUnit.METER, # METER (default), KILOMETER, UNITLESS )

[!TIP] More examples and plots are depicted in the jupyter notebook and the second jupyter notebook

Minimal C++ Example

The following example shows how to use the C++ library to compute the gravity. It works analogously to the Python example above.

cpp // Defining the input like above in the Python example std::vector<std::array<double, 3>> vertices = ... std::vector<std::array<size_t, 3>> faces = ... double density = 1.0; // The constant density polyhedron is defined by its vertices & faces // It also supports the hand-over of NormalOrientation and PolyhedronIntegrity as optional arguments // as above described for the Python Interface Polyhedron polyhedron{vertices, faces, density}; std::vector<std::array<double, 3>> points = ... std::array<double, 3> point = points[0]; bool parallel = true;

The C++ library provides also two ways to compute the gravity. Via the free function evaluate...

cpp const auto[pot, acc, tensor] = GravityModel::evaluate(polyhedron, point, parallel);

... or via the GravityEvaluable class.

```cpp // Instantiation of the GravityEvaluable object GravityEvaluable evaluable{polyhedron};

// From now, we can evaluate the gravity model for any point with const auto[potential, acceleration, tensor] = evaluable(point, parallel); // or for multiple points with const auto results = evaluable(points, parallel); ```

Similarly to Python, the C++ implementation also provides mesh checking capabilities.

[!TIP] For reference, have a look at the main method of the C++ executable.

Installation

With conda

The python interface can be easily installed with conda:

bash conda install -c conda-forge polyhedral-gravity-model

With pip

As a second option, you can also install the python interface with pip from PyPi.

bash pip install polyhedral-gravity

Binaries for the most common platforms are available on PyPI, including Windows, Linux, and macOS. For macOS and Linux, binaries for x86_64 and aarch64 are provided. In case pip uses the source distribution, please make sure that you have a C++17 capable compiler and CMake installed.

From source

The project uses the following dependencies, all of them are automatically set up via CMake:

  • GoogleTest (1.15.2 or compatible), only required for testing
  • spdlog (1.13.0 or compatible), required for logging
  • tetgen (1.6 or compatible), required for I/O
  • yaml-cpp (0.8.0 or compatible), required for I/O
  • thrust (2.1.0 or compatible), required for parallelization and utility
  • xsimd (11.1.0 or compatible), required for vectorization of the atan(..)
  • pybind11 (2.12.0 or compatible), required for the Python interface, but not the C++ standalone

The module will be built using a C++17 capable compiler, CMake. Just execute the following command in the repository root folder:

bash pip install .

To modify the build options (like parallelization) have a look at the next paragraph. The options are modified by setting the environment variables before executing the pip install . command, e.g.:

bash export POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB" pip install .

(Optional: For a faster build, you can install all dependencies available for your system in your local python environment. That way, they won't be fetched from GitHub.)

C++ Library & Executable

Building the C++ Library & Executable

The program is built by using CMake. So first make sure that you installed CMake and then follow these steps:

bash mkdir build cd build cmake .. <options> cmake --build .

The following options are available:

| Name (Default) | Options | |-------------------------------------------------------------:|:--------------------------------------------------------------------------------------------| | POLYHEDRALGRAVITYPARALLELIZATION (CPP) | CPP = Serial Execution / OMP or TBB = Parallel Execution with OpenMP or Intel\'s TBB | | POLYHEDRALGRAVITYLOGGINGLEVEL (INFO) | TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, OFF | | BUILDPOLYHEDRALGRAVITYDOCS (OFF) | Build this documentation | | BUILDPOLYHEDRALGRAVITYTESTS (ON) | Build the Tests | | BUILDPOLYHEDRALGRAVITYPYTHON_INTERFACE (ON) | Build the Python interface |

During testing POLYHEDRALGRAVITYPARALLELIZATION=TBB has been the most performant. It is further not recommended to change the POLYHEDRALGRAVITYLOGGING_LEVEL to something else than INFO=2.

The recommended CMake settings using the TBB backend would look like this:

bash cmake .. -POLYHEDRAL_GRAVITY_PARALLELIZATION="TBB"

Running the C++ Executable

After the build, the gravity model can be run by executing:

bash ./polyhedralGravity <YAML-Configuration-File>

where the YAML-Configuration-File contains the required parameters. Examples for Configuration Files and Polyhedral Source Files can be found in this repository in the folder /example-config/.

Input Configuration File

The configuration should look similar to the given example below. It is required to specify the source-files of the polyhedron's mesh (more info about the supported file in the documentation), the density of the polyhedron, and the wished computation points where the gravity tensor shall be computed. Further, one must specify the name of the .csv output file.

````yaml

gravityModel: input: polyhedron: # polyhedron source-file(s) - "../example-config/data/tsoulis.node" # .node contains the vertices - "../example-config/data/tsoulis.face" # .face contains the triangular faces density: 2670.0 # constant density, units must match with the mesh (see a section below) # Depends on metricunit: 'km' -> kg/km^3, 'm' -> kg/m^3, 'unitless' -> 'unitless' points: # Location of the computation point(s) P - [ 0, 0, 0 ] # Here it is situated at the origin checkmesh: true # Fully optional, enables mesh autodetect+repair of # the polyhedron's vertex ordering (not given: true) metricunit: m # Unit of mesh: One of 'm', 'km' or 'unitless' (not given: 'm') output: filename: "gravityresult.csv" # The name of the output file ````

Output

The executable produces a CSV file containing $V$, $Vx$, $Vy$, $Vz$, $V{xx}$, $V{yy}$, $V{zz}$, $V{xy}$, $V{xz}$, $V_{yz}$ for every computation point P.

Testing

The project uses GoogleTest for testing. In order to execute those tests, just execute the following command in the build directory:

bash ctest

For the Python test suite, please execute the following command in the repository root folder:

bash pytest

Contributing

We are happy to accept contributions to the project in the form of suggestions, bug reports, and pull requests. Please have a look at the contributing guidelines for more information.

Owner

  • Name: European Space Agency
  • Login: esa
  • Kind: organization
  • Location: Europe

The European Space Agency (ESA) is Europe’s gateway to space. Its mission is to shape the development of Europe’s space capability.

JOSS Publication

Efficient Polyhedral Gravity Modeling in Modern C++ and Python
Published
June 01, 2024
Volume 9, Issue 98, Page 6384
Authors
Jonas Schuhmacher ORCID
Chair for Scientific Computing, Technische Universität München, Arcisstraße 21, 80333 München, Germany
Emmanuel Blazquez ORCID
Advanced Concepts Team, European Space Agency, European Space Research and Technology Centre (ESTEC), Keplerlaan 1, 2201 AZ Noordwijk, The Netherlands
Fabio Gratl ORCID
Chair for Scientific Computing, Technische Universität München, Arcisstraße 21, 80333 München, Germany
Dario Izzo ORCID
Advanced Concepts Team, European Space Agency, European Space Research and Technology Centre (ESTEC), Keplerlaan 1, 2201 AZ Noordwijk, The Netherlands
Pablo Gómez ORCID
Advanced Concepts Team, European Space Agency, European Space Research and Technology Centre (ESTEC), Keplerlaan 1, 2201 AZ Noordwijk, The Netherlands
Editor
Dan Foreman-Mackey ORCID
Tags
astronomy dynamics asteroids gravity numerical methods polyhedral model

Citation (CITATION.cff)

cff-version: "1.2.0"
authors:
- family-names: Schuhmacher
  given-names: Jonas
  orcid: "https://orcid.org/0009-0005-9693-4530"
- family-names: Blazquez
  given-names: Emmanuel
  orcid: "https://orcid.org/0000-0001-9697-582X"
- family-names: Gratl
  given-names: Fabio
  orcid: "https://orcid.org/0000-0001-5195-7919"
- family-names: Izzo
  given-names: Dario
  orcid: "https://orcid.org/0000-0002-9846-8423"
- family-names: Gómez
  given-names: Pablo
  orcid: "https://orcid.org/0000-0002-5631-8240"
doi: 10.5281/zenodo.11221939
message: If you use this software, please cite our article in the
  Journal of Open Source Software.
preferred-citation:
  authors:
  - family-names: Schuhmacher
    given-names: Jonas
    orcid: "https://orcid.org/0009-0005-9693-4530"
  - family-names: Blazquez
    given-names: Emmanuel
    orcid: "https://orcid.org/0000-0001-9697-582X"
  - family-names: Gratl
    given-names: Fabio
    orcid: "https://orcid.org/0000-0001-5195-7919"
  - family-names: Izzo
    given-names: Dario
    orcid: "https://orcid.org/0000-0002-9846-8423"
  - family-names: Gómez
    given-names: Pablo
    orcid: "https://orcid.org/0000-0002-5631-8240"
  date-published: 2024-06-01
  doi: 10.21105/joss.06384
  issn: 2475-9066
  issue: 98
  journal: Journal of Open Source Software
  publisher:
    name: Open Journals
  start: 6384
  title: Efficient Polyhedral Gravity Modeling in Modern C++ and Python
  type: article
  url: "https://joss.theoj.org/papers/10.21105/joss.06384"
  volume: 9
title: Efficient Polyhedral Gravity Modeling in Modern C++ and Python

GitHub Events

Total
  • Create event: 4
  • Release event: 1
  • Issues event: 2
  • Watch event: 6
  • Delete event: 5
  • Issue comment event: 7
  • Push event: 37
  • Pull request event: 6
  • Pull request review event: 15
  • Pull request review comment event: 19
  • Fork event: 1
Last Year
  • Create event: 4
  • Release event: 1
  • Issues event: 2
  • Watch event: 6
  • Delete event: 5
  • Issue comment event: 7
  • Push event: 37
  • Pull request event: 6
  • Pull request review event: 15
  • Pull request review comment event: 19
  • Fork event: 1

Committers

Last synced: 5 months ago

All Time
  • Total Commits: 352
  • Total Committers: 5
  • Avg Commits per committer: 70.4
  • Development Distribution Score (DDS): 0.063
Past Year
  • Commits: 55
  • Committers: 1
  • Avg Commits per committer: 55.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Jonas Schuhmacher j****r@t****e 330
Pablo Gómez c****t@p****t 15
Santiago Soler s****r@f****m 5
Dan F-M f****y@g****m 1
Bojun 3****y 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 18
  • Total pull requests: 32
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 14 days
  • Total issue authors: 7
  • Total pull request authors: 5
  • Average comments per issue: 1.67
  • Average comments per pull request: 1.09
  • Merged pull requests: 32
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 2
  • Pull requests: 8
  • Average time to close issues: 2 months
  • Average time to close pull requests: 20 days
  • Issue authors: 2
  • Pull request authors: 1
  • Average comments per issue: 1.0
  • Average comments per pull request: 1.38
  • Merged pull requests: 8
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • santisoler (8)
  • gomezzz (2)
  • metric-space (1)
  • schuhmaj (1)
  • tobiKaboom (1)
  • JoachimSchwabe (1)
  • mikegrudic (1)
Pull Request Authors
  • schuhmaj (33)
  • santisoler (8)
  • dfm (2)
  • gomezzz (1)
  • BerginJay (1)
Top Labels
Issue Labels
enhancement (2) documentation (2) paper (1)
Pull Request Labels
enhancement (8) documentation (2) paper (1)

Packages

  • Total packages: 2
  • Total downloads:
    • pypi 869 last-month
  • Total dependent packages: 0
    (may contain duplicates)
  • Total dependent repositories: 0
    (may contain duplicates)
  • Total versions: 13
  • Total maintainers: 1
pypi.org: polyhedral-gravity

Package to compute full gravity tensor of a given constant density polyhedron for arbitrary points according to the geodetic convention

  • Versions: 12
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 869 Last month
Rankings
Dependent packages count: 7.5%
Downloads: 15.7%
Average: 31.0%
Dependent repos count: 69.8%
Maintainers (1)
Last synced: 4 months ago
conda-forge.org: polyhedral-gravity-model

The package polyhedral_gravity provides a simple-to-use interface for evaluating the full gravity tensor of a constant-density polyhedron at arbitrary given computation points according to the geodetic convention. The computation is based on the line integral approach by Tsoulis et al., which transforms the triple integral into a summation. The implementation relies on a fast, parallelized backbone in C++ capable of evaluating the gravity at thousands of computation points in a fraction of a second. The package includes the functionality to read a polyhedral mesh from files and transform it to fulfill the preconditions of Tsoulis' formulation.

  • Versions: 1
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent repos count: 34.0%
Average: 50.8%
Dependent packages count: 51.2%
Stargazers count: 57.0%
Forks count: 61.1%
Last synced: 4 months ago

Dependencies

.github/workflows/build-and-test.yml actions
  • actions/checkout v3 composite
  • ilammy/msvc-dev-cmd v1 composite
  • mamba-org/provision-with-micromamba main composite
.github/workflows/draft-pdf.yml actions
  • actions/checkout v3 composite
  • actions/upload-artifact v1 composite
  • openjournals/openjournals-draft-action master composite
.github/workflows/wheels.yml actions
  • actions/checkout v3 composite
  • actions/download-artifact v3 composite
  • actions/setup-python v4 composite
  • actions/upload-artifact v3 composite
  • ilammy/msvc-dev-cmd v1 composite
  • pypa/cibuildwheel v2.15.0 composite
  • pypa/gh-action-pypi-publish release/v1 composite