Beispiel #1
0
    def lon_derivative(self, lat: u.deg, lon: u.deg, r: u.m, lmax: int = None):
        """Return longitudinal derivative of the potential.

        Parameters
        ----------
        lat : ~astropy.units.Quantity
            Spherical latitude.
        lon : ~astropy.units.Quantity
            Spherical longitude.
        r : ~astropy.units.Quantity
            Radial distance.
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).

        Returns
        -------
        ~astropy.units.Quantity
            Longitudinal derivative.
        """

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)
        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)
        m_coeff = _np.tile(degrees, (lmax_comp + 1, 1))

        args = (_expand.in_coeff_lon_derivative, _expand.sum_lon_derivative,
                lmax_comp, degrees, m_coeff, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        out = -self.gm * ri * values

        return out.squeeze()
Beispiel #2
0
    def gradient(self, lat, lon, r, lmax=None, degrees=True):
        """Return gradient vector.

        The magnitude and the components of the gradient of the potential
        calculated on or above the ellipsoid without the centrifugal potential
        (eqs. 7 and 122 of STR09/02).

        Parameters
        ----------
        lat : float
            Latitude, in degrees.
        lon : float
            Longitude, in degrees.
        r   : float
            Radial distance, im meters.
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).
        degrees : bool, optional
            If True, the input `lat` and `lon` are given in degrees,
            otherwise radians.
        """

        if degrees:
            lat = _np.radians(lat)
            lon = _np.radians(lon)

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)
        lat, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)

        m_coeff = _np.tile(degrees, (lmax_comp + 1, 1))
        args = (_expand.in_coeff_gradient, _expand.sum_gradient, lmax_comp,
                degrees, m_coeff, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        gmri = self.gm * ri
        clat = _np.cos(lat)

        lat_d = gmri * clat * values[:, :, 0]
        lon_d = -gmri * values[:, :, 1]
        rad_d = -self.gm * ri**2 * values[:, :, 2]

        if self.omega is not None:
            lat_d += self.centrifugal.lat_derivative(lat, r, degrees=False)
            rad_d += self.centrifugal.r_derivative(lat, r, degrees=False)

        # total
        clati = _np.atleast_2d(1 / _np.ma.masked_values(clat, 0.0))
        clati = clati.filled(0.0)

        total = _np.sqrt((ri * lat_d)**2 + (clati * ri * lon_d)**2 + rad_d**2)

        return _np.squeeze([rad_d, lon_d, lat_d, total])
Beispiel #3
0
    def gradient(self, lat: u.deg, lon: u.deg, r: u.m, lmax: int = None):
        """Return gradient vector.

        The magnitude and the components of the gradient of the potential
        calculated on or above the ellipsoid without the centrifugal potential
        (eqs. 7 and 122 of STR09/02).

        Parameters
        ----------
        lat : ~astropy.units.Quantity
            Spherical latitude.
        lon : ~astropy.units.Quantity
            Spherical longitude.
        r : ~astropy.units.Quantity
            Radial distance.
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).
        """

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)
        lat, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)

        m_coeff = _np.tile(degrees, (lmax_comp + 1, 1))
        args = (_expand.in_coeff_gradient, _expand.sum_gradient, lmax_comp,
                degrees, m_coeff, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        gmri = self.gm * ri
        clat = _np.cos(lat)

        lat_d = gmri * clat * values[:, :, 0]
        lon_d = -gmri * values[:, :, 1]
        rad_d = -self.gm * ri**2 * values[:, :, 2]

        if self.omega is not None:
            lat_d += self.centrifugal.lat_derivative(lat, r)
            rad_d += self.centrifugal.r_derivative(lat, r)

        # total
        clati = _np.atleast_2d(1 / _np.ma.masked_values(clat, 0.0))
        clati = clati.filled(0.0)

        total = _np.sqrt((ri * lat_d)**2 + (clati * ri * lon_d)**2 + rad_d**2)

        return (rad_d.squeeze(), lon_d.squeeze(), lat_d.squeeze(),
                total.squeeze())
Beispiel #4
0
    def gravity_anomaly_sa(self, lat, lon, r, lmax=None, degrees=True):
        """Return (Molodensky) gravity anomaly in spherical approximation.

        The gravity anomaly calculated by spherical approximation (eqs. 100 or
        104 and 126 of STR09/02). Unlike the classical gravity anomaly, the
        Molodensky gravity anomaly and the spherical approximation can be
        generalised to 3-d space, hence here it can be calculated on (h=0) or
        above (h>0) the ellipsoid.

        Parameters
        ----------
        lat : float
            Latitude, in degrees
        lon : float
            Longitude, in degrees
        r   : float
            Radial distance, im meters
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).
        degrees : bool, optional
            If True, the input `lat` and `lon` are given in degrees,
            otherwise radians.

        Returns
        -------
        float
            Gravity anomaly, in m/s**2
        """

        if degrees:
            lat = _np.radians(lat)
            lon = _np.radians(lon)

        coeffs = self._anomalous._coeffs.coeffs
        cilm, lmax_comp = _get_lmax(coeffs, lmax=lmax)
        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self._coeffs.r0, lmax_comp)

        args = (_expand.in_coeff_gravity_anomaly, _expand.sum_potential,
                lmax_comp, degrees, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        out = self._coeffs.gm * ri**2 * values

        return _np.squeeze(out)
Beispiel #5
0
    def potential(self, lat, lon, r, lmax=None, degrees=True):
        """Return potential value.

        Parameters
        ----------
        lat : float or array
            Latitude, in degrees
        lon : float or array
            Longitude, in degrees
        r   : float or array
            Radial distance, im meters
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).
        degrees : bool, optional
            If True, the input `lat` and `lon` are given in degrees,
            otherwise radians.

        Returns
        -------
        float or array
            Potential, in m**2/s**2
        """

        if degrees:
            lat = _np.radians(lat)
            lon = _np.radians(lon)

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)

        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)
        args = (_expand.in_coeff_potential, _expand.sum_potential, lmax_comp,
                degrees, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r

        out = _np.squeeze(self.gm * ri * values)

        if self.omega is not None:
            out += self.centrifugal.potential(lat, r, degrees=False)

        return out
Beispiel #6
0
    def gravity_anomaly_sa(self,
                           lat: u.deg,
                           lon: u.deg,
                           r: u.m,
                           lmax: int = None) -> u.mGal:
        """Return (Molodensky) gravity anomaly in spherical approximation.

        The gravity anomaly calculated by spherical approximation (eqs. 100 or
        104 and 126 of STR09/02). Unlike the classical gravity anomaly, the
        Molodensky gravity anomaly and the spherical approximation can be
        generalised to 3-d space, hence here it can be calculated on (h=0) or
        above (h>0) the ellipsoid.

        Parameters
        ----------
        lat : ~astropy.units.Quantity
            Spherical latitude.
        lon : ~astropy.units.Quantity
            Spherical longitude.
        r : ~astropy.units.Quantity
            Radial distance.
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).

        Returns
        -------
        ~astropy.units.Quantity
            Gravity anomaly.
        """

        coeffs = self._anomalous._coeffs.coeffs
        cilm, lmax_comp = _get_lmax(coeffs, lmax=lmax)
        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self._coeffs.r0, lmax_comp)

        args = (_expand.in_coeff_gravity_anomaly, _expand.sum_potential,
                lmax_comp, degrees, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        out = self._coeffs.gm * ri**2 * values

        return _np.squeeze(out)
Beispiel #7
0
    def lon_derivative(self, lat, lon, r, lmax=None, degrees=True):
        """Return longitudinal derivative of the potential, in m/s**2.

        Parameters
        ----------
        lat : float or array
            Latitude, in degrees
        lon : float or array
            Longitude, in degrees
        r   : float or array
            Radial distance, im meters
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).
        degrees : bool, optional
            If True, the input `lat` and `lon` are given in degrees,
            otherwise radians.

        Returns
        -------
        float or array
            Longitudinal derivative, in m/s**2
        """

        if degrees:
            lat = _np.radians(lat)
            lon = _np.radians(lon)

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)
        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)
        m_coeff = _np.tile(degrees, (lmax_comp + 1, 1))

        args = (_expand.in_coeff_lon_derivative, _expand.sum_lon_derivative,
                lmax_comp, degrees, m_coeff, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r
        out = -self.gm * ri * values

        return _np.squeeze(out)
Beispiel #8
0
    def potential(self,
                  lat: u.deg,
                  lon: u.deg,
                  r: u.m,
                  lmax=None) -> u.m**2 / u.s**2:
        """Return potential value.

        Parameters
        ----------
        lat : ~astropy.units.Quantity
            Spherical latitude.
        lon : ~astropy.units.Quantity
            Spherical longitude.
        r : ~astropy.units.Quantity
            Radial distance.
        lmax : int, optional
            Maximum degree of the coefficients. Default is `None` (use all
            the coefficients).

        Returns
        -------
        ~astropy.units.Quantity
            Potential.
        """

        cilm, lmax_comp = _get_lmax(self._coeffs.coeffs, lmax=lmax)

        _, _, degrees, cosin, x, q = _expand.common_precompute(
            lat, lon, r, self.r0, lmax_comp)
        args = (_expand.in_coeff_potential, _expand.sum_potential, lmax_comp,
                degrees, cosin, cilm)

        values = _expand.expand_parallel(x, q, *args)

        ri = 1 / r

        out = _np.squeeze(self.gm * ri * values)

        if self.omega is not None:
            out += self.centrifugal.potential(lat, r)

        return out