santisoler: @leouieda Could you take a quick look at this. Specially to the design of the extended `point_mass_gravity()` function. I'm not quite sure about the dictionaries I defined, so I wanted to have a second opinion.

I added some functions to compute distances in Cartesian coordinates inside `forward/point_mass.py`. I intend to move them as proposed in #69.

If you can't find time to review it, let me know. I think the main issues that can live here are related with design, so maybe I could merge it and we can discuss it afterwards when you have time.
leouieda: Looks good! It would be good to have a gallery example as well to visually verify that the results are correct. Maybe one with 2 masses at different depths with opposite densities?
santisoler: Thanks for the quick review @leouieda. I've added a simple example as you proposed. If you like it, feel free to merge this.
santisoler: @leouieda Would you mind taking a final look at this? If you agree with the new variable name and don't have any other suggestion, I think this is ready to be merged.
leouieda: @santisoler this is great! I love that docstring! Made a few corrections to the text but once these are done feel free to merge!
santisoler: Thanks for the review @leouieda! I like how it looks, so I'll merge it right away!
diff --git a/doc/references.rst b/doc/references.rst
index 15b82b5..ba43242 100644
--- a/doc/references.rst
+++ b/doc/references.rst
@@ -3,7 +3,9 @@ References
 
 .. [AmanteEakins2009] Amante, C. and B.W. Eakins, 2009. ETOPO1 1 Arc-Minute Global Relief Model: Procedures, Data Sources and Analysis. NOAA Technical Memorandum NESDIS NGDC-24. National Geophysical Data Center, NOAA. doi:`10.7289/V5C8276M <https://doi.org/10.7289/V5C8276M>`__
 .. [BarthelmesKohler2016] Barthelmes, F. and Kohler, W. (2016), International Centre for Global Earth Models (ICGEM), in: Drewes, H., Kuglitsch, F., Adam, J. et al., The Geodesists Handbook 2016, Journal of Geodesy (2016), 90(10), pp 907-1205, doi:`10.1007/s00190-016-0948-z <https://doi.org/10.1007/s00190-016-0948-z>`__
+.. [Blakely1995] Blakely, R. (1995). Potential Theory in Gravity and Magnetic Applications. Cambridge: Cambridge University Press. doi:`10.1017/CBO9780511549816 <https://doi.org/10.1017/CBO9780511549816>`__
 .. [Forste_etal2014] Förste, Christoph; Bruinsma, Sean.L.; Abrikosov, Oleg; Lemoine, Jean-Michel; Marty, Jean Charles; Flechtner, Frank; Balmino, G.; Barthelmes, F.; Biancale, R. (2014): EIGEN-6C4 The latest combined global gravity field model including GOCE data up to degree and order 2190 of GFZ Potsdam and GRGS Toulouse. GFZ Data Services. doi:`10.5880/icgem.2015.1 <http://doi.org/10.5880/icgem.2015.1>`__
+.. [Grombein2013] Grombein, T., Seitz, K., Heck, B. (2013), Optimized formulas for the gravitational field of a tesseroid, Journal of Geodesy. doi:`10.1007/s00190-013-0636-1 <https://doi.org/10.1007/s00190-013-0636-1>`__
 .. [Hofmann-WellenhofMoritz2006] Hofmann-Wellenhof, B., & Moritz, H. (2006). Physical Geodesy (2nd, corr. ed. 2006 edition ed.). Wien ; New York: Springer.
 .. [LiGotze2001] Li, X. and H. J. Gotze, 2001, Tutorial: Ellipsoid, geoid, gravity, geodesy, and geophysics, Geophysics, 66(6), p. 1660-1668, doi:`10.1190/1.1487109 <https://doi.org/10.1190/1.1487109>`__
 .. [TurcotteSchubert2014] Turcotte, D. L., & Schubert, G. (2014). Geodynamics (3 edition). Cambridge, United Kingdom: Cambridge University Press.
diff --git a/examples/forward/point_mass.py b/examples/forward/point_mass.py
new file mode 100644
index 0000000..4c8f91a
--- /dev/null
+++ b/examples/forward/point_mass.py
@@ -0,0 +1,54 @@
+"""
+Point Mass in Cartesian Coordinates
+===================================
+
+The simplest geometry used to compute gravitational fields are point masses.
+Although modelling geologic structures with point masses can be challenging, they are
+very usefull for other purposes: creating synthetic models, solving inverse problems
+very quickly, generating equivalent sources for interpolation or gridding, etc.
+The gravitational fields generated by point masses can be quickly computed
+either in Cartesian or in geocentric spherical coordinate systems.
+We will compute the downward component of the gravitational acceleration generated by
+a set of point masses on a computation grid given in Cartesian coordinates. We will do
+it throught the :func:`harmonica.point_mass_gravity` function.
+"""
+import harmonica as hm
+import verde as vd
+import matplotlib.pyplot as plt
+import matplotlib.ticker
+
+
+# Define two point masses with oposite mass values of 10000000 kg
+easting = [5e3, 15e3]
+northing = [5e3, 15e3]
+down = [7e3, 2.5e3]
+points = [easting, northing, down]
+# We're using "negative" masses to represent a "mass deficit"
+masses = [10e6, -10e6]
+
+# Define computation points on a grid at 500m above the ground
+coordinates = vd.grid_coordinates(
+    region=[0, 20e3, 0, 20e3], shape=(80, 80), extra_coords=-500
+)
+
+# Compute the downward component of the acceleration
+gravity = hm.point_mass_gravity(
+    coordinates, points, masses, field="g_z", coordinate_system="cartesian"
+)
+print(gravity)
+
+# Plot the gravitational field
+fig, ax = plt.subplots(figsize=(8, 9))
+ax.set_aspect("equal")
+img = plt.pcolormesh(*coordinates[:2], gravity)
+# Add colorbar
+fmt = matplotlib.ticker.ScalarFormatter(useMathText=True)
+fmt.set_powerlimits((0, 0))
+plt.colorbar(img, ax=ax, format=fmt, pad=0.04, shrink=0.73, label="mGal")
+ax.set_title("Downward component of gravitational acceleration")
+# Convert axes units to km
+ax.set_xticklabels(ax.get_xticks() * 1e-3)
+ax.set_yticklabels(ax.get_yticks() * 1e-3)
+ax.set_xlabel("km")
+ax.set_ylabel("km")
+plt.show()
diff --git a/harmonica/forward/point_mass.py b/harmonica/forward/point_mass.py
index f6a200e..5b12660 100644
--- a/harmonica/forward/point_mass.py
+++ b/harmonica/forward/point_mass.py
@@ -7,28 +7,117 @@ from numba import jit
 from ..constants import GRAVITATIONAL_CONST
 
 
-def point_mass_gravity(coordinates, points, masses, field, dtype="float64"):
-    """
-    Compute gravitational fields of a point mass on spherical coordinates.
+def point_mass_gravity(
+    coordinates, points, masses, field, coordinate_system="cartesian", dtype="float64"
+):
+    r"""
+    Compute gravitational fields of point masses.
+
+    It can compute the gravitational fields of point masses on a set of computation
+    points defined either in Cartesian or geocentric spherical coordinates.
+
+    The potential gravity field generated by a point mass with mass :math:`m` located at
+    a point :math:`Q` on a computation point :math:`P` can be computed as:
+
+    .. math::
+
+        V(P) = \frac{G m}{l},
+
+    where :math:`G` is the gravitational constant and :math:`l` is the Euclidean
+    distance between :math:`P` and :math:`Q` [Blakely1995]_.
+
+    In Cartesian coordinates, the points :math:`P` and :math:`Q` are given by :math:`x`,
+    :math:`y` and :math:`z` coordinates, which can be translated into ``northing``,
+    ``easting`` and ``down``, respectively.
+    If :math:`P` is located at :math:`(x, y, z)`, and :math:`Q` at :math:`(x_p, y_p,
+    z_p)`, the distance :math:`l` can be computed as:
+
+    .. math::
+
+        l = \sqrt{ (x - x_p)^2 + (y - y_p)^2 + (z - z_p)^2 }.
+
+    The gradient of the potential, also known as the gravity acceleration vector
+    :math:`\vec{g}`, is defined as:
+
+    .. math::
+
+        \vec{g} = \nabla V.
+
+    Therefore, the :math:`z` component of :math:`\vec{g}` at the point :math:`P` can be
+    computed as (remember that :math:`z` points downward):
+
+    .. math::
+
+        g_z(P) = \frac{G m}{l^3} (z_p - z).
+
+    On a geocentric spherical coordinate system, the points :math:`P` and :math:`Q` are
+    given by the ``longitude``, ``latitude`` and ``radius`` coordinates, i.e.
+    :math:`\lambda`, :math:`\varphi` and :math:`r`, respectively. On this coordinate
+    system, the Euclidean distance between :math:`P(r, \varphi, \lambda)` and
+    :math:`Q(r_p, \varphi_p, \lambda_p)` can be calculated  as follows [Grombein2013]_:
+
+    .. math::
+
+        l = \sqrt{ r^2 + r_p^2 - 2 r r_p \cos \Psi },
+
+    where
+
+    .. math::
+
+        \cos \Psi = \sin \varphi \sin \varphi_p +
+        \cos \varphi \cos \varphi_p \cos(\lambda - \lambda_p).
+
+    The radial component of the acceleration vector on a local North-oriented
+    system whose origin is located on the point :math:`P(r, \varphi, \lambda)`
+    is given by [Grombein2013]_:
+
+    .. math::
+
+        g_r(P) = \frac{G m}{l^3} (r_p \cos \Psi - r).
+
+    .. warning::
+
+        When working in Cartesian coordinates, the **z direction points downwards**,
+        i.e. positive and negative values represent points below and above the surface,
+        respectively.
+
 
     Parameters
     ----------
     coordinates : list or array
-        List or array containing `longitude`, `latitude` and `radius` of computation
-        points defined on a spherical geocentric coordinate system.
-        Both `longitude` and `latitude` should be in degrees and `radius` in meters.
+        List or array containing the coordinates of computation points in the following
+        order: ``easting``, ``northing`` and ``down`` (if coordinates given in
+        Cartesian coordiantes), or ``longitude``, ``latitude`` and ``radius`` (if given
+        on a spherical geocentric coordinate system).
+        All ``easting``, ``northing`` and ``down`` should be in meters.
+        Both ``longitude`` and ``latitude`` should be in degrees and ``radius`` in
+        meters.
     points : list or array
-        List or array containing the coordinates of the point masses `longitude_p`,
-        `latitude_p`, `radius_p` defined on a spherical geocentric coordinate system.
-        Both `longitude_p` and `latitude_p` should be in degrees and `radius` in meters.
+        List or array containing the coordinates of the point masses in the following
+        order: ``easting``, ``northing`` and ``down`` (if coordinates given in
+        Cartesian coordiantes), or ``longitude``, ``latitude`` and ``radius`` (if given
+        on a spherical geocentric coordinate system).
+        All ``easting``, ``northing`` and ``down`` should be in meters.
+        Both ``longitude`` and ``latitude`` should be in degrees and ``radius`` in
+        meters.
     masses : list or array
         List or array containing the mass of each point mass in kg.
     field : str
         Gravitational field that wants to be computed.
-        The available fields are:
+        The available fields in Cartesian coordinates are:
+
+        - Gravitational potential: ``potential``
+        - Downward acceleration: ``g_z``
+
+        The available fields in spherical geocentric coordinates are:
 
         - Gravitational potential: ``potential``
         - Radial acceleration: ``g_r``
+
+    coordinate_system : str (optional)
+        Coordinate system of the coordinates of the computation points and the point
+        masses. Available coordinates systems: ``cartesian``, ``spherical``.
+        Default ``cartesian``.
     dtype : data-type (optional)
         Data type assigned to resulting gravitational field, and coordinates of point
         masses and computation points. Default to ``np.float64``.
@@ -37,50 +126,122 @@ def point_mass_gravity(coordinates, points, masses, field, dtype="float64"):
     Returns
     -------
     result : array
-        Gravitational field generated by the `point_mass` on the computation points
-        defined in `coordinates`.
+        Gravitational field generated by the ``point_mass`` on the computation points
+        defined in ``coordinates``.
         The potential is given in SI units, the accelerations in mGal and the Marussi
         tensor components in Eotvos.
     """
-    kernels = {"potential": kernel_potential, "g_r": kernel_g_r}
-    if field not in kernels:
+    # Organize dispatchers and kernel functions inside dictionaries
+    dispatchers = {
+        "cartesian": jit_point_mass_cartesian,
+        "spherical": jit_point_mass_spherical,
+    }
+    kernels = {
+        "cartesian": {"potential": kernel_potential_cartesian, "g_z": kernel_g_z},
+        "spherical": {"potential": kernel_potential_spherical, "g_r": kernel_g_r},
+    }
+    # Sanity checks for coordinate_system and field
+    if coordinate_system not in ("cartesian", "spherical"):
+        raise ValueError(
+            "Coordinate system {} not recognized".format(coordinate_system)
+        )
+    if field not in kernels[coordinate_system]:
         raise ValueError("Gravity field {} not recognized".format(field))
     # Figure out the shape and size of the output array
     cast = np.broadcast(*coordinates[:3])
     result = np.zeros(cast.size, dtype=dtype)
     # Prepare arrays to be passed to the jitted functions
-    longitude, latitude, radius = (
-        np.atleast_1d(i).ravel().astype(dtype) for i in coordinates[:3]
-    )
-    longitude_p, latitude_p, radius_p = (
-        np.atleast_1d(i).ravel().astype(dtype) for i in points[:3]
-    )
+    coordinates = (np.atleast_1d(i).ravel().astype(dtype) for i in coordinates[:3])
+    points = (np.atleast_1d(i).ravel().astype(dtype) for i in points[:3])
     masses = np.atleast_1d(masses).astype(dtype).ravel()
     # Compute gravitational field
-    jit_point_mass_gravity(
-        longitude,
-        latitude,
-        radius,
-        longitude_p,
-        latitude_p,
-        radius_p,
-        masses,
-        result,
-        kernels[field],
+    dispatchers[coordinate_system](
+        *coordinates, *points, masses, result, kernels[coordinate_system][field]
     )
     result *= GRAVITATIONAL_CONST
     # Convert to more convenient units
-    if field == "g_r":
+    if field in ("g_r", "g_z"):
         result *= 1e5  # SI to mGal
     return result.reshape(cast.shape)
 
 
 @jit(nopython=True)
-def jit_point_mass_gravity(
+def jit_point_mass_cartesian(
+    easting, northing, down, easting_p, northing_p, down_p, masses, out, kernel
+):  # pylint: disable=invalid-name
+    """
+    Compute gravity field of point masses on computation points in Cartesian coordinates
+
+    Parameters
+    ----------
+    easting, northing, down : 1d-arrays
+        Coordinates of computation points in Cartesian coordinate system.
+    easting_p, northing_p, down_p : 1d-arrays
+        Coordinates of point masses in Cartesian coordinate system.
+    masses : 1d-array
+        Mass of each point mass in SI units.
+    out : 1d-array
+        Array where the gravitational field on each computation point will be appended.
+        It must have the same size of ``easting``, ``northing`` and ``down``.
+    kernel : func
+        Kernel function that will be used to compute the gravity field on the
+        computation points.
+    """
+    for l in range(easting.size):
+        for m in range(easting_p.size):
+            out[l] += masses[m] * kernel(
+                easting[l], northing[l], down[l], easting_p[m], northing_p[m], down_p[m]
+            )
+
+
+@jit(nopython=True)
+def kernel_potential_cartesian(easting, northing, down, easting_p, northing_p, down_p):
+    """
+    Kernel function for potential gravity field in Cartesian coordinates
+    """
+    return 1 / _distance_cartesian(
+        [easting, northing, down], [easting_p, northing_p, down_p]
+    )
+
+
+@jit(nopython=True)
+def kernel_g_z(easting, northing, down, easting_p, northing_p, down_p):
+    """
+    Kernel function for downward component of gravity gradient in Cartesian coordinates
+    """
+    distance_sq = _distance_cartesian_sq(
+        [easting, northing, down], [easting_p, northing_p, down_p]
+    )
+    return (down_p - down) / distance_sq ** (3 / 2)
+
+
+@jit(nopython=True)
+def _distance_cartesian_sq(point_a, point_b):
+    """
+    Calculate the square distance between two points given in Cartesian coordinates
+    """
+    easting, northing, down = point_a[:]
+    easting_p, northing_p, down_p = point_b[:]
+    distance_sq = (
+        (easting - easting_p) ** 2 + (northing - northing_p) ** 2 + (down - down_p) ** 2
+    )
+    return distance_sq
+
+
+@jit(nopython=True)
+def _distance_cartesian(point_a, point_b):
+    """
+    Calculate the distance between two points given in Cartesian coordinates
+    """
+    return np.sqrt(_distance_cartesian_sq(point_a, point_b))
+
+
+@jit(nopython=True)
+def jit_point_mass_spherical(
     longitude, latitude, radius, longitude_p, latitude_p, radius_p, masses, out, kernel
 ):  # pylint: disable=invalid-name
     """
-    Compute gravity field of point masses on computation points.
+    Compute gravity field of point masses on computation points in spherical coordiantes
 
     Parameters
     ----------
@@ -123,11 +284,11 @@ def jit_point_mass_gravity(
 
 
 @jit(nopython=True)
-def kernel_potential(
+def kernel_potential_spherical(
     longitude, cosphi, sinphi, radius, longitude_p, cosphi_p, sinphi_p, radius_p
 ):
     """
-    Kernel function for potential gravity field
+    Kernel function for potential gravity field in spherical coordinates
     """
     coslambda = np.cos(longitude_p - longitude)
     cospsi = sinphi_p * sinphi + cosphi_p * cosphi * coslambda
@@ -140,7 +301,7 @@ def kernel_g_r(
     longitude, cosphi, sinphi, radius, longitude_p, cosphi_p, sinphi_p, radius_p
 ):
     """
-    Kernel function for radial component of gravity gradient
+    Kernel function for radial component of gravity gradient in spherical coordinates
     """
     coslambda = np.cos(longitude_p - longitude)
     cospsi = sinphi_p * sinphi + cosphi_p * cosphi * coslambda
diff --git a/harmonica/forward/tesseroid.py b/harmonica/forward/tesseroid.py
index 021d51f..d3d679e 100644
--- a/harmonica/forward/tesseroid.py
+++ b/harmonica/forward/tesseroid.py
@@ -6,7 +6,7 @@ import numpy as np
 from numpy.polynomial.legendre import leggauss
 
 from ..constants import GRAVITATIONAL_CONST
-from .point_mass import jit_point_mass_gravity, kernel_potential, kernel_g_r
+from .point_mass import jit_point_mass_spherical, kernel_potential_spherical, kernel_g_r
 
 STACK_SIZE = 100
 MAX_DISCRETIZATIONS = 100000
@@ -110,7 +110,7 @@ def tesseroid_gravity(
     array(-112.54539933)
 
     """
-    kernels = {"potential": kernel_potential, "g_r": kernel_g_r}
+    kernels = {"potential": kernel_potential_spherical, "g_r": kernel_g_r}
     if field not in kernels:
         raise ValueError("Gravity field {} not recognized".format(field))
     # Figure out the shape and size of the output array
@@ -258,7 +258,7 @@ def jit_tesseroid_gravity(
                 weights,
             )
             # Compute gravity fields
-            jit_point_mass_gravity(
+            jit_point_mass_spherical(
                 computation_point[0:1],
                 computation_point[1:2],
                 computation_point[2:3],

Point masses gravity computation on Cartesian coordinates
**Description of the desired feature**

The most simple geometry that generates gravitational fields are point masses.
We should make a similar implementation that the one proposed on #47 but for Cartesian coordinates.

**Are you willing to help implement and maintain this feature?** Yes/No
diff --git a/harmonica/tests/test_point_mass.py b/harmonica/tests/test_point_mass.py
index 3aba539..dfa1dd8 100644
--- a/harmonica/tests/test_point_mass.py
+++ b/harmonica/tests/test_point_mass.py
@@ -9,19 +9,106 @@ from ..constants import GRAVITATIONAL_CONST
 from ..forward.point_mass import point_mass_gravity
 
 
-def test_invalid_field():
-    "Check if an invalid gravitational field is passed as argument"
+def test_invalid_coordinate_system():
+    "Check if invalid coordinate system is passed"
+    coordinates = [0.0, 0.0, 0.0]
     point_mass = [0.0, 0.0, 0.0]
     mass = 1.0
-    longitude = np.array(0.0)
-    latitude = np.array(0.0)
-    height = np.array(0.0)
     with pytest.raises(ValueError):
         point_mass_gravity(
-            [longitude, latitude, height], point_mass, mass, "this-field-does-not-exist"
+            coordinates,
+            point_mass,
+            mass,
+            "potential",
+            "this-is-not-a-valid-coordinate-system",
         )
 
 
+def test_invalid_field():
+    "Check if an invalid gravitational field is passed as argument"
+    coordinates = [0.0, 0.0, 0.0]
+    point_mass = [0.0, 0.0, 0.0]
+    mass = 1.0
+    for coordinate_system in ("spherical", "cartesian"):
+        with pytest.raises(ValueError):
+            point_mass_gravity(
+                coordinates,
+                point_mass,
+                mass,
+                "this-field-does-not-exist",
+                coordinate_system,
+            )
+
+
+def test_invalid_field_for_coordinate_system():
+    "Check if an invalid field is passed for that coordinate system"
+    coordinates = [0.0, 0.0, 0.0]
+    point_mass = [0.0, 0.0, 0.0]
+    mass = 1.0
+    cartesian_exclusive_fields = ["g_z"]
+    spherical_exclusive_fields = ["g_r"]
+    for field in spherical_exclusive_fields:
+        with pytest.raises(ValueError):
+            point_mass_gravity(coordinates, point_mass, mass, field, "cartesian")
+    for field in cartesian_exclusive_fields:
+        with pytest.raises(ValueError):
+            point_mass_gravity(coordinates, point_mass, mass, field, "spherical")
+
+
+# ---------------------------
+# Cartesian coordinates tests
+# ---------------------------
+@pytest.mark.use_numba
+def test_potential_cartesian_symmetry():
+    """
+    Test if potential field of a point mass has symmetry in Cartesian coordinates
+    """
+    # Define a single point mass
+    point_mass = [1.1, 1.2, 1.3]
+    masses = [2670]
+    # Define a set of computation points at a fixed distance from the point mass
+    distance = 3.3
+    easting = point_mass[0] * np.ones(6)
+    northing = point_mass[1] * np.ones(6)
+    down = point_mass[2] * np.ones(6)
+    easting[0] += distance
+    easting[1] -= distance
+    northing[2] += distance
+    northing[3] -= distance
+    down[4] += distance
+    down[5] -= distance
+    coordinates = [easting, northing, down]
+    # Compute potential gravity field on each computation point
+    results = point_mass_gravity(
+        coordinates, point_mass, masses, "potential", "cartesian"
+    )
+    npt.assert_allclose(*results)
+
+
+@pytest.mark.use_numba
+def test_g_z_symmetry():
+    """
+    Test if g_z field of a point mass has symmetry in Cartesian coordinates
+    """
+    # Define a single point mass
+    point_mass = [1.1, 1.2, 1.3]
+    masses = [2670]
+    # Define a pair of computation points above and bellow the point mass
+    distance = 3.3
+    easting = point_mass[0] * np.ones(2)
+    northing = point_mass[1] * np.ones(2)
+    down = point_mass[2] * np.ones(2)
+    down[0] += distance
+    down[1] -= distance
+    coordinates = [easting, northing, down]
+    # Compute g_z gravity field on each computation point
+    results = point_mass_gravity(coordinates, point_mass, masses, "g_z", "cartesian")
+    npt.assert_allclose(results[0], -results[1])
+
+
+# ---------------------------
+# Spherical coordinates tests
+# ---------------------------
 @pytest.mark.use_numba
 def test_point_mass_on_origin():
     "Check potential and g_r of point mass on origin"
@@ -39,7 +126,9 @@ def test_point_mass_on_origin():
     # Compare results with analytical solutions
     for field in analytical:
         npt.assert_allclose(
-            point_mass_gravity([longitude, latitude, radius], point_mass, mass, field),
+            point_mass_gravity(
+                [longitude, latitude, radius], point_mass, mass, field, "spherical"
+            ),
             analytical[field],
         )
 
@@ -67,7 +156,9 @@ def test_point_mass_same_radial_direction():
                 # Compare results with analytical solutions
                 for field in analytical:
                     npt.assert_allclose(
-                        point_mass_gravity(coordinates, point_mass, mass, field),
+                        point_mass_gravity(
+                            coordinates, point_mass, mass, field, "spherical"
+                        ),
                         analytical[field],
                     )
 
@@ -95,7 +186,9 @@ def test_point_mass_potential_on_equator():
                 analytical = {"potential": GRAVITATIONAL_CONST * mass / distance}
                 # Compare results with analytical solutions
                 npt.assert_allclose(
-                    point_mass_gravity(coordinates, point_mass, mass, "potential"),
+                    point_mass_gravity(
+                        coordinates, point_mass, mass, "potential", "spherical"
+                    ),
                     analytical["potential"],
                 )
 
@@ -123,6 +216,8 @@ def test_point_mass_potential_on_same_meridian():
                 analytical = {"potential": GRAVITATIONAL_CONST * mass / distance}
                 # Compare results with analytical solutions
                 npt.assert_allclose(
-                    point_mass_gravity(coordinates, point_mass, mass, "potential"),
+                    point_mass_gravity(
+                        coordinates, point_mass, mass, "potential", "spherical"
+                    ),
                     analytical["potential"],
                 )

environment.yml
pip install -e .
parse_log_pytest
environment.yml
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster @ file:///home/conda/feedstock_root/build_artifacts/alabaster_1673645646525/work
astroid @ file:///croot/astroid_1676904296642/work
attrs @ file:///home/conda/feedstock_root/build_artifacts/attrs_1722977137225/work
Babel @ file:///home/conda/feedstock_root/build_artifacts/babel_1702422572539/work
black @ file:///home/conda/feedstock_root/build_artifacts/black-recipe_1666773063432/work
bokeh @ file:///home/conda/feedstock_root/build_artifacts/bokeh_1660586590972/work
Bottleneck @ file:///home/conda/feedstock_root/build_artifacts/bottleneck_1649629660965/work
Brotli @ file:///home/conda/feedstock_root/build_artifacts/brotli-split_1648883617327/work
Cartopy @ file:///home/conda/feedstock_root/build_artifacts/cartopy_1631908358075/work
certifi @ file:///home/conda/feedstock_root/build_artifacts/certifi_1725278078093/work/certifi
charset-normalizer @ file:///home/conda/feedstock_root/build_artifacts/charset-normalizer_1728479282467/work
click @ file:///home/conda/feedstock_root/build_artifacts/click_1651215140632/work
cloudpickle @ file:///home/conda/feedstock_root/build_artifacts/cloudpickle_1674202310934/work
colorama @ file:///home/conda/feedstock_root/build_artifacts/colorama_1666700638685/work
coverage @ file:///home/conda/feedstock_root/build_artifacts/coverage_1652409068862/work
cycler @ file:///home/conda/feedstock_root/build_artifacts/cycler_1635519461629/work
cytoolz==0.11.2
dask==2021.10.0
dill @ file:///home/conda/feedstock_root/build_artifacts/dill_1706434688412/work
distributed @ file:///tmp/build/80754af9/distributed_1635968201545/work
docutils @ file:///home/conda/feedstock_root/build_artifacts/docutils_1648737573548/work
exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1720869315914/work
flake8 @ file:///home/conda/feedstock_root/build_artifacts/flake8_1659645013175/work
fonttools @ file:///home/conda/feedstock_root/build_artifacts/fonttools_1651017735934/work
fsspec @ file:///home/conda/feedstock_root/build_artifacts/fsspec_1674184942191/work
-e git+https://github.com/fatiando/harmonica.git@12a1d95a3caa169d4e7bb31f2e61ec9c9e5a8259#egg=harmonica
HeapDict @ file:///home/conda/feedstock_root/build_artifacts/heapdict_1722613793866/work
idna @ file:///home/conda/feedstock_root/build_artifacts/idna_1726459485162/work
imagesize @ file:///home/conda/feedstock_root/build_artifacts/imagesize_1656939531508/work
importlib-metadata @ file:///home/conda/feedstock_root/build_artifacts/importlib-metadata_1653252814274/work
iniconfig @ file:///home/conda/feedstock_root/build_artifacts/iniconfig_1673103042956/work
isort @ file:///home/conda/feedstock_root/build_artifacts/isort_1675293796116/work
Jinja2 @ file:///home/conda/feedstock_root/build_artifacts/jinja2_1715127149914/work
joblib @ file:///home/conda/feedstock_root/build_artifacts/joblib_1691577114857/work
kiwisolver @ file:///home/conda/feedstock_root/build_artifacts/kiwisolver_1648854392523/work
lazy-object-proxy @ file:///home/conda/feedstock_root/build_artifacts/lazy-object-proxy_1649033171084/work
llvmlite==0.38.0
locket @ file:///home/conda/feedstock_root/build_artifacts/locket_1650660393415/work
MarkupSafe @ file:///home/conda/feedstock_root/build_artifacts/markupsafe_1648737551960/work
matplotlib @ file:///croot/matplotlib-suite_1667356714455/work
mccabe @ file:///home/conda/feedstock_root/build_artifacts/mccabe_1643049622439/work
msgpack @ file:///home/conda/feedstock_root/build_artifacts/msgpack-python_1648745991116/work
munkres==1.1.4
mypy-extensions @ file:///home/conda/feedstock_root/build_artifacts/mypy_extensions_1675543315189/work
numba @ file:///home/conda/feedstock_root/build_artifacts/numba_1652226558760/work
numexpr @ file:///home/conda/feedstock_root/build_artifacts/numexpr_1649636747170/work
numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1649806299270/work
numpydoc @ file:///home/conda/feedstock_root/build_artifacts/numpydoc_1665273484262/work
olefile @ file:///home/conda/feedstock_root/build_artifacts/olefile_1701735466804/work
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1696202382185/work
pandas==1.3.5
partd @ file:///home/conda/feedstock_root/build_artifacts/partd_1695667515973/work
pathspec @ file:///home/conda/feedstock_root/build_artifacts/pathspec_1702249949303/work
Pillow @ file:///home/conda/feedstock_root/build_artifacts/pillow_1630696604087/work
platformdirs @ file:///home/conda/feedstock_root/build_artifacts/platformdirs_1699715570510/work
pluggy @ file:///home/conda/feedstock_root/build_artifacts/pluggy_1648772594554/work
pooch @ file:///home/conda/feedstock_root/build_artifacts/pooch_1717777836653/work
psutil @ file:///home/conda/feedstock_root/build_artifacts/psutil_1653089169272/work
pycodestyle @ file:///home/conda/feedstock_root/build_artifacts/pycodestyle_1659638152915/work
pyflakes @ file:///home/conda/feedstock_root/build_artifacts/pyflakes_1659210156976/work
Pygments @ file:///home/conda/feedstock_root/build_artifacts/pygments_1700607939962/work
pylint @ file:///home/conda/feedstock_root/build_artifacts/pylint_1678161361281/work
pyparsing @ file:///home/conda/feedstock_root/build_artifacts/pyparsing_1724616129934/work
pyproj @ file:///home/conda/feedstock_root/build_artifacts/pyproj_1650061576675/work
PyQt5==5.15.4
PyQt5-sip==12.9.0
pyshp @ file:///home/conda/feedstock_root/build_artifacts/pyshp_1659002966020/work
PySocks @ file:///home/conda/feedstock_root/build_artifacts/pysocks_1648857264451/work
pytest @ file:///home/conda/feedstock_root/build_artifacts/pytest_1704035161844/work
pytest-cov @ file:///home/conda/feedstock_root/build_artifacts/pytest-cov_1684964868191/work
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1709299778482/work
pytz @ file:///home/conda/feedstock_root/build_artifacts/pytz_1726055524169/work
PyYAML @ file:///home/conda/feedstock_root/build_artifacts/pyyaml_1648757092905/work
requests @ file:///home/conda/feedstock_root/build_artifacts/requests_1716354486713/work
scikit-learn @ file:///home/conda/feedstock_root/build_artifacts/scikit-learn_1640464152916/work
scipy @ file:///home/conda/feedstock_root/build_artifacts/scipy_1637806658031/work
Shapely @ file:///home/conda/feedstock_root/build_artifacts/shapely_1635194349843/work
sip @ file:///home/conda/feedstock_root/build_artifacts/sip_1646101199960/work
six @ file:///home/conda/feedstock_root/build_artifacts/six_1620240208055/work
snowballstemmer @ file:///home/conda/feedstock_root/build_artifacts/snowballstemmer_1637143057757/work
sortedcontainers @ file:///home/conda/feedstock_root/build_artifacts/sortedcontainers_1621217038088/work
Sphinx==1.8.5
sphinx-gallery @ file:///home/conda/feedstock_root/build_artifacts/sphinx-gallery_1700542355088/work
sphinx-rtd-theme @ file:///home/conda/feedstock_root/build_artifacts/sphinx_rtd_theme_1692694729860/work
sphinxcontrib-jquery @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-jquery_1678808969227/work
sphinxcontrib-serializinghtml @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-serializinghtml_1649380998999/work
sphinxcontrib-websupport @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-websupport_1636966052463/work
tblib @ file:///home/conda/feedstock_root/build_artifacts/tblib_1702066284995/work
threadpoolctl @ file:///home/conda/feedstock_root/build_artifacts/threadpoolctl_1643647933166/work
toml @ file:///home/conda/feedstock_root/build_artifacts/toml_1604308577558/work
tomli @ file:///home/conda/feedstock_root/build_artifacts/tomli_1727974628237/work
tomlkit @ file:///home/conda/feedstock_root/build_artifacts/tomlkit_1715185399719/work
toolz @ file:///home/conda/feedstock_root/build_artifacts/toolz_1706112571092/work
tornado @ file:///home/conda/feedstock_root/build_artifacts/tornado_1648827244717/work
typed-ast @ file:///home/conda/feedstock_root/build_artifacts/typed-ast_1650218777101/work
typing_extensions @ file:///home/conda/feedstock_root/build_artifacts/typing_extensions_1688315532570/work
unicodedata2 @ file:///home/conda/feedstock_root/build_artifacts/unicodedata2_1649111917568/work
urllib3 @ file:///home/conda/feedstock_root/build_artifacts/urllib3_1708239446578/work
verde @ file:///home/conda/feedstock_root/build_artifacts/verde_1683616029179/work
wrapt @ file:///home/conda/feedstock_root/build_artifacts/wrapt_1651495229974/work
xarray @ file:///home/conda/feedstock_root/build_artifacts/xarray_1639125986756/work
zict @ file:///home/conda/feedstock_root/build_artifacts/zict_1651156074437/work
zipp @ file:///home/conda/feedstock_root/build_artifacts/zipp_1677313463193/work

name: harmonica
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - alabaster=0.7.13=pyhd8ed1ab_0
  - astroid=2.14.2=py37h06a4308_0
  - attrs=24.2.0=pyh71513ae_0
  - babel=2.14.0=pyhd8ed1ab_0
  - black=22.10.0=py37h89c1867_1
  - bokeh=2.4.3=pyhd8ed1ab_3
  - bottleneck=1.3.4=py37hda87dfa_1
  - brotli=1.0.9=h166bdaf_7
  - brotli-bin=1.0.9=h166bdaf_7
  - brotli-python=1.0.9=py37hd23a5d3_7
  - bzip2=1.0.8=h7f98852_4
  - c-ares=1.18.1=h7f98852_0
  - ca-certificates=2025.2.25=h06a4308_0
  - cartopy=0.20.0=py37hbe109c4_0
  - certifi=2024.8.30=pyhd8ed1ab_0
  - charset-normalizer=3.4.0=pyhd8ed1ab_0
  - click=8.1.3=py37h89c1867_0
  - cloudpickle=2.2.1=pyhd8ed1ab_0
  - colorama=0.4.6=pyhd8ed1ab_0
  - coverage=6.3.3=py37h540881e_0
  - cycler=0.11.0=pyhd8ed1ab_0
  - cytoolz=0.11.2=py37h540881e_2
  - dask=2021.10.0=pyhd8ed1ab_0
  - dask-core=2021.10.0=pyhd3eb1b0_0
  - dbus=1.13.18=hb2f20db_0
  - dill=0.3.8=pyhd8ed1ab_0
  - distributed=2021.10.0=py37h06a4308_0
  - docutils=0.18.1=py37h89c1867_1
  - exceptiongroup=1.2.2=pyhd8ed1ab_0
  - expat=2.4.8=h27087fc_0
  - flake8=5.0.4=pyhd8ed1ab_0
  - fontconfig=2.14.0=h8e229c2_0
  - fonttools=4.33.3=py37h540881e_0
  - freetype=2.12.1=h4a9f257_0
  - fsspec=2023.1.0=pyhd8ed1ab_0
  - geos=3.9.1=h9c3ff4c_2
  - glib=2.78.4=h6a678d5_0
  - glib-tools=2.78.4=h6a678d5_0
  - gst-plugins-base=1.14.1=h6a678d5_1
  - gstreamer=1.14.1=h5eee18b_1
  - heapdict=1.0.1=pyhd8ed1ab_1
  - icu=58.2=hf484d3e_1000
  - idna=3.10=pyhd8ed1ab_0
  - imagesize=1.4.1=pyhd8ed1ab_0
  - importlib-metadata=4.11.4=py37h89c1867_0
  - importlib_metadata=4.11.4=hd8ed1ab_0
  - iniconfig=2.0.0=pyhd8ed1ab_0
  - isort=5.11.5=pyhd8ed1ab_0
  - jbig=2.1=h7f98852_2003
  - jinja2=3.1.4=pyhd8ed1ab_0
  - joblib=1.3.2=pyhd8ed1ab_0
  - jpeg=9e=h166bdaf_1
  - keyutils=1.6.1=h166bdaf_0
  - kiwisolver=1.4.2=py37h7cecad7_1
  - krb5=1.19.3=h3790be6_0
  - lazy-object-proxy=1.7.1=py37h540881e_1
  - lcms2=2.12=hddcbb42_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - lerc=2.2.1=h9c3ff4c_0
  - libblas=3.9.0=16_linux64_openblas
  - libbrotlicommon=1.0.9=h166bdaf_7
  - libbrotlidec=1.0.9=h166bdaf_7
  - libbrotlienc=1.0.9=h166bdaf_7
  - libcblas=3.9.0=16_linux64_openblas
  - libclang=10.0.1=default_hde54327_1
  - libcurl=7.79.1=h2574ce0_1
  - libdeflate=1.7=h7f98852_5
  - libedit=3.1.20191231=he28a2e2_2
  - libev=4.33=h516909a_1
  - libevent=2.1.12=h8f2d780_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgfortran-ng=13.2.0=h69a702a_0
  - libgfortran5=13.2.0=ha4646dd_0
  - libglib=2.78.4=hdc74915_0
  - libgomp=11.2.0=h1234567_1
  - libiconv=1.17=h166bdaf_0
  - liblapack=3.9.0=16_linux64_openblas
  - libllvm10=10.0.1=he513fc3_3
  - libllvm11=11.1.0=hf817b99_2
  - libnghttp2=1.43.0=h812cca2_1
  - libopenblas=0.3.21=h043d6bf_0
  - libpng=1.6.37=h21135ba_2
  - libpq=12.9=h16c4e8d_3
  - libssh2=1.10.0=ha56f1ee_2
  - libstdcxx-ng=11.2.0=h1234567_1
  - libtiff=4.3.0=hf544144_1
  - libuuid=2.32.1=h7f98852_1000
  - libwebp-base=1.2.2=h7f98852_1
  - libxcb=1.15=h7f8727e_0
  - libxkbcommon=1.0.3=he3ba5ed_0
  - libxml2=2.9.14=h74e7548_0
  - llvmlite=0.38.0=py37h4ff587b_0
  - locket=1.0.0=pyhd8ed1ab_0
  - lz4-c=1.9.4=h6a678d5_1
  - markupsafe=2.1.1=py37h540881e_1
  - matplotlib=3.5.3=py37h89c1867_2
  - matplotlib-base=3.5.3=py37hf590b9c_0
  - mccabe=0.7.0=pyhd8ed1ab_0
  - msgpack-python=1.0.3=py37h7cecad7_1
  - munkres=1.1.4=pyh9f0ad1d_0
  - mypy_extensions=1.0.0=pyha770c72_0
  - ncurses=6.4=h6a678d5_0
  - nomkl=1.0=h5ca1d4c_0
  - nspr=4.35=h6a678d5_0
  - nss=3.89.1=h6a678d5_0
  - numba=0.55.1=py37h43839f2_1
  - numexpr=2.8.0=py37h85a3170_102
  - numpy=1.21.6=py37h976b520_0
  - numpydoc=1.5.0=pyhd8ed1ab_0
  - olefile=0.47=pyhd8ed1ab_0
  - openjpeg=2.4.0=hb52868f_1
  - openssl=1.1.1w=h7f8727e_0
  - packaging=23.2=pyhd8ed1ab_0
  - pandas=1.3.5=py37h8c16a72_0
  - partd=1.4.1=pyhd8ed1ab_0
  - pathspec=0.12.1=pyhd8ed1ab_0
  - pcre2=10.42=hebb0a14_1
  - pillow=8.3.2=py37h0f21c89_0
  - pip=24.0=pyhd8ed1ab_0
  - platformdirs=4.0.0=pyhd8ed1ab_0
  - pluggy=1.0.0=py37h89c1867_3
  - pooch=1.8.2=pyhd8ed1ab_0
  - proj=8.0.1=h277dcde_0
  - psutil=5.9.1=py37h540881e_0
  - pycodestyle=2.9.1=pyhd8ed1ab_0
  - pyflakes=2.5.0=pyhd8ed1ab_0
  - pygments=2.17.2=pyhd8ed1ab_0
  - pylint=2.16.4=pyhd8ed1ab_0
  - pyparsing=3.1.4=pyhd8ed1ab_0
  - pyproj=3.2.1=py37hcc46e62_6
  - pyqt=5.15.4=py37hd23a5d3_0
  - pyqt5-sip=12.9.0=py37hd23a5d3_0
  - pyshp=2.3.1=pyhd8ed1ab_0
  - pysocks=1.7.1=py37h89c1867_5
  - pytest=7.4.4=pyhd8ed1ab_0
  - pytest-cov=4.1.0=pyhd8ed1ab_0
  - python=3.7.16=h7a1cb2a_0
  - python-dateutil=2.9.0=pyhd8ed1ab_0
  - python_abi=3.7=2_cp37m
  - pytz=2024.2=pyhd8ed1ab_0
  - pyyaml=6.0=py37h540881e_4
  - qt-main=5.15.2=h327a75a_7
  - readline=8.2=h5eee18b_0
  - requests=2.32.2=pyhd8ed1ab_0
  - scikit-learn=1.0.2=py37hf9e9bfc_0
  - scipy=1.7.3=py37hf2a6cf1_0
  - setuptools=65.6.3=py37h06a4308_0
  - shapely=1.8.0=py37h48c49eb_0
  - sip=6.5.1=py37hcd2ae1e_2
  - six=1.16.0=pyh6c4a22f_0
  - snowballstemmer=2.2.0=pyhd8ed1ab_0
  - sortedcontainers=2.4.0=pyhd8ed1ab_0
  - sphinx=1.8.5=py37_0
  - sphinx-gallery=0.15.0=pyhd8ed1ab_0
  - sphinx_rtd_theme=1.3.0=pyha770c72_0
  - sphinxcontrib-jquery=4.1=pyhd8ed1ab_0
  - sphinxcontrib-serializinghtml=1.1.5=pyhd8ed1ab_2
  - sphinxcontrib-websupport=1.2.4=pyhd8ed1ab_1
  - sqlite=3.45.3=h5eee18b_0
  - tblib=3.0.0=pyhd8ed1ab_0
  - threadpoolctl=3.1.0=pyh8a188c0_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd8ed1ab_0
  - tomli=2.0.2=pyhd8ed1ab_0
  - tomlkit=0.12.5=pyha770c72_0
  - toolz=0.12.1=pyhd8ed1ab_0
  - tornado=6.1=py37h540881e_3
  - typed-ast=1.5.3=py37h540881e_0
  - typing-extensions=4.7.1=hd8ed1ab_0
  - typing_extensions=4.7.1=pyha770c72_0
  - unicodedata2=14.0.0=py37h540881e_1
  - urllib3=2.2.1=pyhd8ed1ab_0
  - verde=1.8.0=pyhd8ed1ab_0
  - wheel=0.38.4=py37h06a4308_0
  - wrapt=1.14.1=py37h540881e_0
  - xarray=0.20.2=pyhd8ed1ab_0
  - xz=5.6.4=h5eee18b_1
  - yaml=0.2.5=h7f98852_2
  - zict=2.2.0=pyhd8ed1ab_0
  - zipp=3.15.0=pyhd8ed1ab_0
  - zlib=1.2.13=h5eee18b_1
  - zstd=1.5.6=hc292b87_0
prefix: /opt/conda/envs/harmonica

harmonica/tests/test_point_mass.py::test_invalid_coordinate_system harmonica/tests/test_point_mass.py::test_invalid_field_for_coordinate_system harmonica/tests/test_point_mass.py::test_potential_cartesian_symmetry harmonica/tests/test_point_mass.py::test_g_z_symmetry harmonica/tests/test_point_mass.py::test_point_mass_on_origin harmonica/tests/test_point_mass.py::test_point_mass_same_radial_direction harmonica/tests/test_point_mass.py::test_point_mass_potential_on_equator harmonica/tests/test_point_mass.py::test_point_mass_potential_on_same_meridian
harmonica/tests/test_point_mass.py::test_invalid_field
doc/references.rst harmonica/forward/tesseroid.py harmonica/forward/point_mass.py examples/forward/point_mass.py
doc/references.rst harmonica/forward/tesseroid.py harmonica/forward/point_mass.py examples/forward/point_mass.py