source: issm/trunk-jpl/src/m/classes/lovenumbers.py@ 27453

Last change on this file since 27453 was 27453, checked in by jdquinn, 2 years ago

CHG: MATLAB > Python translations; cleanup

File size: 8.4 KB
RevLine 
[26317]1import numpy as np
[25154]2from checkfield import checkfield
3from fielddisplay import fielddisplay
[25158]4from getlovenumbers import getlovenumbers
5from pairoptions import pairoptions
[25156]6from WriteData import WriteData
[25154]7
[26840]8
9class lovenumbers(object): #{{{
[27453]10 """lovenumbers class definition
[25154]11
[25688]12 Usage:
[26301]13 lovenumbers = lovenumbers()
14 lovenumbers = lovenumbers('maxdeg', 10000, 'referenceframe', 'CF');
15
16 Choose numbers of degrees required (1000 by default) and reference frame
17 (between CF and CM; CM by default)
[25688]18 """
[25154]19
[26178]20 def __init__(self, *args): #{{{
[26840]21 # Loading love numbers
22 self.h = [] # Provided by PREM model
23 self.k = [] # idem
24 self.l = [] # idem
[25154]25
[25688]26 # Tidal love numbers for computing rotational feedback
[25154]27 self.th = []
28 self.tk = []
29 self.tl = []
[26840]30 self.tk2secular = 0 # deg 2 secular number
31 self.pmtf_colinear = []
32 self.pmtf_ortho = []
[25158]33
[26301]34 # Time/frequency for visco-elastic love numbers
35 self.timefreq = []
36 self.istime = 1
37
[25158]38 options = pairoptions(*args)
39 maxdeg = options.getfieldvalue('maxdeg', 1000)
40 referenceframe = options.getfieldvalue('referenceframe', 'CM')
41 self.setdefaultparameters(maxdeg, referenceframe)
[25157]42 #}}}
[26840]43
[26301]44 def __repr__(self): #{{{
45 s = ' lovenumbers parameters:\n'
46 s += '{}\n'.format(fielddisplay(self, 'h', 'load Love number for radial displacement'))
47 s += '{}\n'.format(fielddisplay(self, 'k', 'load Love number for gravitational potential perturbation'))
48 s += '{}\n'.format(fielddisplay(self, 'l', 'load Love number for horizontal displacements'))
49 s += '{}\n'.format(fielddisplay(self, 'th', 'tidal load Love number (deg 2)'))
50 s += '{}\n'.format(fielddisplay(self, 'tk', 'tidal load Love number (deg 2)'))
51 s += '{}\n'.format(fielddisplay(self, 'tl', 'tidal load Love number (deg 2)'))
52 s += '{}\n'.format(fielddisplay(self, 'tk2secular', 'secular fluid Love number'))
[26828]53 s += '{}\n'.format(fielddisplay(self, 'pmtf_colinear', 'Colinear component of the Polar Motion Transfer Function (e.g. x-motion due to x-component perturbation of the inertia tensor)'))
54 s += '{}\n'.format(fielddisplay(self, 'pmtf_ortho', 'Orthogonal component of the Polar Motion Transfer Function (couples x and y components, only used for Chandler Wobble)'))
[26301]55 s += '{}\n'.format(fielddisplay(self, 'istime', 'time (default: 1) or frequency love numbers (0)'))
56 s += '{}\n'.format(fielddisplay(self, 'timefreq', 'time/frequency vector (yr or 1/yr)'))
[26840]57 s += '{}\n'.format(fielddisplay(self, 'pmtf_colinear', 'Colinear component of the Polar Motion Transfer Function (e.g. x-motion due to x-component perturbation of the inertia tensor)'))
58 s += '{}\n'.format(fielddisplay(self, 'pmtf_ortho', 'Orthogonal component of the Polar Motion Transfer Function (couples x and y components, only used for Chandler Wobble)'))
[26301]59 return s
60 #}}}
[26840]61
[26178]62 def setdefaultparameters(self, maxdeg, referenceframe): #{{{
[25688]63 # Initialize love numbers
[26317]64 self.h = getlovenumbers('type', 'loadingverticaldisplacement', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
65 self.k = getlovenumbers('type', 'loadinggravitationalpotential', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
66 self.l = getlovenumbers('type', 'loadinghorizontaldisplacement', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
67 self.th = getlovenumbers('type', 'tidalverticaldisplacement', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
68 self.tk = getlovenumbers('type', 'tidalgravitationalpotential', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
69 self.tl = getlovenumbers('type', 'tidalhorizontaldisplacement', 'referenceframe', referenceframe, 'maxdeg', maxdeg).reshape(-1,1)
[25154]70
[25688]71 # Secular fluid love number
[25154]72 self.tk2secular = 0.942
[26301]73
[26840]74 self.pmtf_colinear = np.array([0.0]).reshape(-1, 1)
75 self.pmtf_ortho = np.array([0.0]).reshape(-1, 1)
76 if maxdeg >= 2:
77 self.pmtf_colinear = ((1.0 + self.k[2, :]) / (1.0 - self.tk[2, :] / self.tk2secular)).reshape(-1, 1) # Valid only for elastic regime, not viscous. Also neglects chandler wobble.
78 self.pmtf_ortho = np.array([0.0]).reshape(-1, 1)
[26301]79 # Time
80 self.istime = 1 # Temporal love numbers by default
[26317]81 self.timefreq = np.zeros(1) # Elastic case by default
[25688]82 return self
[25157]83 #}}}
[26840]84
[26178]85 def checkconsistency(self, md, solution, analyses): #{{{
[26301]86 if ('SealevelchangeAnalysis' not in analyses) or (solution == 'TransientSolution' and not md.transient.isslc):
[25154]87 return
88 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.h', 'NaN', 1, 'Inf', 1)
89 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.k', 'NaN', 1, 'Inf', 1)
90 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.l', 'NaN', 1, 'Inf', 1)
91
92 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.th', 'NaN', 1, 'Inf', 1)
93 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.tk', 'NaN', 1, 'Inf', 1)
[26358]94 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.tl', 'NaN', 1, 'Inf', 1)
[25154]95 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.tk2secular', 'NaN', 1, 'Inf', 1)
[26828]96 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.pmtf_colinear', 'NaN', 1, 'Inf', 1)
97 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.pmtf_ortho', 'NaN', 1, 'Inf', 1)
[26301]98 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.timefreq', 'NaN', 1, 'Inf', 1)
99 md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.istime', 'NaN', 1, 'Inf', 1, 'values', [0, 1])
100
[25688]101 # Check that love numbers are provided at the same level of accuracy
[25166]102 if (self.h.shape[0] != self.k.shape[0]) or (self.h.shape[0] != self.l.shape[0]):
[25154]103 raise ValueError('lovenumbers error message: love numbers should be provided at the same level of accuracy')
[26301]104
105 ntf = len(self.timefreq)
[26840]106 if (np.shape(self.h)[1] != ntf or np.shape(self.k)[1] != ntf or np.shape(self.l)[1] != ntf or np.shape(self.th)[1] != ntf or np.shape(self.tk)[1] != ntf or np.shape(self.tl)[1] != ntf or np.shape(self.pmtf_colinear)[1] != ntf or np.shape(self.pmtf_ortho)[1] != ntf):
[26301]107 raise ValueError('lovenumbers error message: love numbers should have as many time/frequency steps as the time/frequency vector')
108
[26840]109 if self.istime and self.timefreq[0] != 0:
110 raise ValueError('temporal love numbers must start with elastic response, i.e. timefreq[0] = 0')
[25688]111 return md
[25157]112 #}}}
[26840]113
[26178]114 def defaultoutputs(self, md): #{{{
[25154]115 return[]
[25157]116 #}}}
[26840]117
[26178]118 def marshall(self, prefix, md, fid): #{{{
[25154]119 WriteData(fid, prefix, 'object', self, 'fieldname', 'h', 'name', 'md.solidearth.lovenumbers.h', 'format', 'DoubleMat', 'mattype', 1)
120 WriteData(fid, prefix, 'object', self, 'fieldname', 'k', 'name', 'md.solidearth.lovenumbers.k', 'format', 'DoubleMat', 'mattype', 1)
121 WriteData(fid, prefix, 'object', self, 'fieldname', 'l', 'name', 'md.solidearth.lovenumbers.l', 'format', 'DoubleMat', 'mattype', 1)
122
123 WriteData(fid, prefix, 'object', self, 'fieldname', 'th', 'name', 'md.solidearth.lovenumbers.th', 'format', 'DoubleMat', 'mattype', 1)
124 WriteData(fid, prefix, 'object', self, 'fieldname', 'tk', 'name', 'md.solidearth.lovenumbers.tk', 'format', 'DoubleMat', 'mattype', 1)
125 WriteData(fid, prefix, 'object', self, 'fieldname', 'tl', 'name', 'md.solidearth.lovenumbers.tl', 'format', 'DoubleMat', 'mattype', 1)
[27417]126 WriteData(fid, prefix, 'object', self, 'fieldname', 'pmtf_colinear','name','md.solidearth.lovenumbers.pmtf_colinear','format','DoubleMat','mattype',1)
127 WriteData(fid, prefix, 'object', self, 'fieldname', 'pmtf_ortho','name','md.solidearth.lovenumbers.pmtf_ortho','format','DoubleMat','mattype',1)
[25154]128 WriteData(fid, prefix, 'object', self, 'data', self.tk2secular, 'fieldname', 'lovenumbers.tk2secular', 'format', 'Double')
[26301]129
130 if (self.istime):
131 scale = md.constants.yts
132 else:
133 scale = 1.0 / md.constants.yts
134 WriteData(fid, prefix, 'object', self, 'fieldname', 'istime', 'name', 'md.solidearth.lovenumbers.istime', 'format', 'Boolean')
135 WriteData(fid, prefix, 'object', self, 'fieldname', 'timefreq', 'name', 'md.solidearth.lovenumbers.timefreq', 'format', 'DoubleMat', 'mattype', 1, 'scale', scale);
[25157]136 #}}}
[27417]137
[26178]138 def extrude(self, md): #{{{
[25154]139 return
[27417]140 #}}}
Note: See TracBrowser for help on using the repository browser.