Source code for avni.mapping.geodesy

#!/usr/bin/env python

#####################  IMPORT STANDARD MODULES   #########################

# python 3 compatibility
from __future__ import absolute_import, division, print_function
import sys
if (sys.version_info[:2] < (3, 0)):
    from builtins import float,int,list,tuple

import os
import numpy as np
from math import atan
from configobj import ConfigObj
import typing as tp

####################### IMPORT AVNI LIBRARIES  ###########################

from .. import constants
from ..tools import convert2units,get_configdir,get_fullpath

##########################################################################

[docs]def getplanetconstants(planet: tp.Union[None,str] = None, configfile: tp.Union[None,str] = None, option = None): """Load the astronomic-geodetic constraints for a planet from a configuration file. Parameters ---------- planet : tp.Union[None,str], optional _description_, by default None so :py:func:`constants.planetpreferred` configfile : tp.Union[None,str], optional all the planet configurations are in this file., by default None so read from so :py:func:`get_configdir/constants.planetpreferred` option GRS option for constants, by default None so use the default one :Authors: Raj Moulik (moulik@caa.columbia.edu) :Last Modified: 2023.02.16 5.00 """ # defaults if planet is None: planet = constants.planetpreferred if configfile is None: configfile = get_fullpath(get_configdir()+'/'+constants.planetconstants) if not os.path.isfile(configfile): raise IOError('No configuration file found: '+configfile) else: parser = ConfigObj(configfile) if option == None: try: option = parser[planet]['default'] except: raise KeyError('Default GRS needs to be specified for '+planet+' in file '+configfile+'. Or an option passed as an argument to getplanetconstants') try: parser_select = parser[planet][option] except: raise IOError('No planet '+planet+' with GRS '+option+' found in file '+configfile) constants.a_e = convert2units(parser_select['a_e']) # Equatorial radius constants.GM = convert2units(parser_select['GM']) # Geocentric gravitational constant m^3s^-2 constants.G = convert2units(parser_select['G']) # Gravitational constant m^3kg^-1s^-2 constants.R = convert2units(parser_select['R']) # Radius of the Earth in m try: constants.f = convert2units(parser_select['f']) #flattening constants.rf = 1./constants.f #inverse flattening except KeyError: try: constants.rf = convert2units(parser_select['1/f']) #inverse flattening constants.f = 1./constants.rf #flattening except: raise KeyError('need either flattening (f) or inverse flattening (1/f) for '+planet+' in '+configfile) constants.omega = convert2units(parser_select['omega']) #Angular velocity in rad/s constants.M_true = convert2units(parser_select['M_true']) # Solid Earth mass in kg constants.I_true = convert2units(parser_select['I_true'])# Moment of inertia in m^2 kg constants.rhobar = convert2units(parser_select['rhobar']) # Average density in kg/m^3 #length of 1 degree in km try: constants.deg2km = convert2units(parser_select['deg2km']) except KeyError: constants.deg2km = 2*np.pi*constants.a_e/360/1000 constants.deg2m = constants.deg2km * 1000. #length of 1 degree in m #DeltaJ2 Permanent tide correction try: constants.DeltaJ2 = convert2units(parser_select['DeltaJ2']) except KeyError: constants.DeltaJ2 = None try: constants.k2 = convert2units(parser_select['k2']) except KeyError: constants.k2 = None try: constants.barC2hydro = convert2units(parser_select['barC2hydro']) except KeyError: constants.barC2hydro = None try: constants.barC4hydro = convert2units(parser_select['barC4hydro']) except KeyError: constants.barC4hydro = None # correction for geographic-geocentric conversion: 0.993277 for 1/f=297 try: print('... Re - Initialized avni module with constants for '+planet+' from '+parser_select['cite']+' from geocentric correction '+str(constants.geoco)) constants.geoco = (1.0 - constants.f)**2. except AttributeError: constants.geoco = (1.0 - constants.f)**2. constants.planet = planet constants.grs = option
[docs]def evaluate_grs(GM: tp.Union[None,float] = None, f: tp.Union[None,float] = None, a_e: tp.Union[None,float] = None, omega: tp.Union[None,float] = None, R: tp.Union[None,float] = None, nzo: int = 10, store: bool = False): """Calculate geopotential constants in a reference earth model. All the following page numbers and equation numbers refer to the book Physical Geodesy by Hofmann-wellenhof and Moritz :cite:p:`hofmann2006physical` Parameters ---------- GM : tp.Union[None,float], optional Gravitational constant times mass reference, by default None f : tp.Union[None,float], optional Flattening, by default None a_e : tp.Union[None,float], optional Semi-major axis, by default None omega : tp.Union[None,float], optional Angular velocity, by default None R : tp.Union[None,float], optional _description_, by default None nzo : int, optional Number of zonal harmonics (2,4,... 2*nzo), by default 10 store : bool, optional Store in constants or return as output if False, by default False Returns ------- barC2n Normalized even zonal harmonics of the corresponding Somigliana-Pizzetti normal field. barC2n(:,1): normalized zonal harmonics barC2n(:,2): degree of the zonal harmonic [2 4 ... 2*nzo] geqt Normal gravity at the equator gpol Normal gravity at the pole U0 Normal potential at the ellipsoid m omega^2*a^2*b/(GM) ecc First eccentricity eccp Second eccentricity a_p Semi-minor axis E Linear eccentricity c Polar radius of curvature :Authors: Raj Moulik (moulik@caa.columbia.edu) :Last Modified: 2023.02.16 5.00 """ # defaults are from constants if GM == None: GM = constants.GM if f == None: f = constants.f if a_e == None: a_e = constants.a_e if R == None: R = constants.R if omega == None: omega = constants.omega # First eccentricity; ecc=np.sqrt(2*f-f**2) if store: constants.ecc = ecc # First eccentricity squared ecc2=ecc**2 if store: constants.ecc2 = ecc2 # Second eccentricity # p. 71, Eqn.(2-138); eccp=ecc/(1-f) if store: constants.eccp = eccp # Second eccentricity squared eccp2=eccp**2 if store: constants.eccp2 = eccp2 # Semi-minor axis a_p=a_e*(1-f) if store: constants.a_p = a_p # m # p. 70, Eqn.(2-137); m=(omega**2)*(a_e**2)*a_p/GM; if store: constants.m = m # q_0 and q_0p # p. 67, Eqn.(2-113) # In the book, q_0 is q q_0=1/2*((1+3/eccp2)*atan(eccp)-3/eccp) if store: constants.q_0 = q_0 # and q_0p is q_0 q_0p=3*(1+1/eccp2)*(1-1/eccp*atan(eccp))-1 if store: constants.q_0p = q_0p # J_2 # p. 75-76, Eqn.(2-165), Eqn.(2-166) and Eqn.(2-172) j_2=ecc2/3*(1-2/15*m*eccp/q_0) if store: constants.j_2 = j_2 # j_2n # p. 76, Eqn.(2-170) and Eqn.(2-172) j_2n = {} for N in np.arange(1,nzo+1): j_2n[2*N]=((-1)**(N+1))*3*(ecc2**N)/(2*N+1)/(2*N+3)*(1-N+5*N*j_2/ecc2) if store: constants.j_2n = j_2n # Normalized C2n0 terms. # p. 60, Eqn.(2-80) barC2n={} for N in np.arange(1,nzo+1): barC2n[2*N] = -j_2n[2*N]/np.sqrt(2*2*N+1) if store: constants.barC2n = barC2n # Normal gravity at the equator. # p. 71, Eqn.(2-141); geqt=GM/a_e/a_p*(1-m-m/6*eccp*q_0p/q_0) if store: constants.geqt = geqt # Normal gravity at the pole. # p. 71, Eqn.(2-142) gpol=GM/(a_e**2)*(1+m/3*eccp*q_0p/q_0) if store: constants.gpol = gpol # Mean Normal gravity Somiglinana's closed formula at phi=45. k = (a_p*gpol/a_e/geqt)-1 g0= geqt*(1+k/2)/np.sqrt(1-ecc2/2) if store: constants.g0 = g0 # Mean gravitational acceleration on the sphere g=GM/(R**2) if store: constants.g = g # Linear eccentricity # p. 66, Eqn.(2-101) E=np.sqrt(a_e**2-a_p**2); if store: constants.E = E # Normal potential at the ellipsoid # p. 68, Eqn.(2-123) U0=GM/E*atan(eccp)+1/3*(omega**2)*(a_e**2) if store: constants.U0 = U0 # Polar radius of curvature # p. 73, eqn.(2-150) c=(a_e**2)/a_p if store: constants.c = c if not store: return barC2n,j_2n,geqt,gpol,g0,g,U0,m,ecc,eccp,a_p,E,c