[22004] | 1 | %FOURIERLOVE class definition
|
---|
| 2 | %
|
---|
| 3 | % Usage:
|
---|
| 4 | % md.love=fourierlove();
|
---|
| 5 |
|
---|
| 6 | classdef fourierlove
|
---|
| 7 | properties (SetAccess=public)
|
---|
[26744] | 8 | nfreq = 0;
|
---|
| 9 | frequencies = 0;
|
---|
| 10 | sh_nmax = 0;
|
---|
| 11 | sh_nmin = 0;
|
---|
| 12 | g0 = 0;
|
---|
| 13 | r0 = 0;
|
---|
| 14 | mu0 = 0;
|
---|
| 15 | Gravitational_Constant = 0;
|
---|
| 16 | allow_layer_deletion = 0;
|
---|
| 17 | underflow_tol = 0;
|
---|
| 18 | integration_steps_per_layer = 0;
|
---|
| 19 | istemporal = 0;
|
---|
| 20 | n_temporal_iterations = 0;
|
---|
| 21 | time = 0;
|
---|
| 22 | love_kernels = 0;
|
---|
| 23 | forcing_type = 0;
|
---|
| 24 | inner_core_boundary = 0;
|
---|
| 25 | core_mantle_boundary = 0;
|
---|
| 26 | complex_computation = 0;
|
---|
| 27 |
|
---|
[22004] | 28 | end
|
---|
| 29 | methods (Static)
|
---|
| 30 | function self = loadobj(self) % {{{
|
---|
| 31 | % This function is directly called by matlab when a model object is
|
---|
| 32 | % loaded. Update old properties here
|
---|
| 33 | end% }}}
|
---|
| 34 | end
|
---|
| 35 | methods
|
---|
| 36 | function self = fourierlove(varargin) % {{{
|
---|
| 37 | switch nargin
|
---|
| 38 | case 0
|
---|
| 39 | self=setdefaultparameters(self);
|
---|
| 40 | otherwise
|
---|
| 41 | error('constructor not supported');
|
---|
| 42 | end
|
---|
| 43 | end % }}}
|
---|
| 44 | function self = setdefaultparameters(self) % {{{
|
---|
| 45 | %we setup an elastic love number computation by default.
|
---|
| 46 | self.nfreq=1;
|
---|
| 47 | self.frequencies=[0]; %Hz
|
---|
| 48 | self.sh_nmax=256; % .35 degree, 40 km at the equator.
|
---|
[25836] | 49 | self.sh_nmin=1;
|
---|
| 50 | % work on matlab script for computing g0 for given Earth's structure.
|
---|
| 51 | self.g0=9.81; % m/s^2;
|
---|
| 52 | self.r0=6371*1e3; %m;
|
---|
[26744] | 53 | self.mu0=1e11; % Pa
|
---|
| 54 | self.Gravitational_Constant=6.67259e-11; % m^3 kg^-1 s^-2
|
---|
| 55 | self.allow_layer_deletion=1;
|
---|
| 56 | self.underflow_tol=1e-16; %threshold of deep to surface love number ratio to trigger the deletion of layer
|
---|
| 57 | self.integration_steps_per_layer=100;
|
---|
| 58 | self.istemporal=0;
|
---|
| 59 | self.n_temporal_iterations=8;
|
---|
| 60 | self.time=[0]; %s
|
---|
[22383] | 61 | self.love_kernels=0;
|
---|
[26744] | 62 | self.forcing_type = 11; % surface loading
|
---|
| 63 | self.inner_core_boundary=1;
|
---|
| 64 | self.core_mantle_boundary=2;
|
---|
| 65 | self.complex_computation=0;
|
---|
[22004] | 66 | end % }}}
|
---|
| 67 | function disp(self) % {{{
|
---|
[26744] | 68 | fielddisplay(self,'nfreq','number of frequencies sampled (default: 1, elastic) [Hz]');
|
---|
[22004] | 69 | fielddisplay(self,'frequencies','frequencies sampled (convention defaults to 0 for the elastic case) [Hz]');
|
---|
[26744] | 70 | fielddisplay(self,'sh_nmax','maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)');
|
---|
| 71 | fielddisplay(self,'sh_nmin','minimum spherical harmonic degree (default: 1)');
|
---|
| 72 | fielddisplay(self,'g0','adimensioning constant for gravity (default: 10) [m/s^2]');
|
---|
| 73 | fielddisplay(self,'r0','adimensioning constant for radius (default: 6371*10^3) [m]');
|
---|
| 74 | fielddisplay(self,'mu0','adimensioning constant for stress (default: 10^11) [Pa]');
|
---|
| 75 | fielddisplay(self,'Gravitational_Constant','Newtonian constant of gravitation (default: 6.67259e-11 [m^3 kg^-1 s^-2])');
|
---|
| 76 | fielddisplay(self,'allow_layer_deletion','allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)');
|
---|
| 77 | fielddisplay(self,'underflow_tol','threshold of deep to surface love number ratio to trigger the deletion of layers (default: 1e-16)');
|
---|
| 78 | fielddisplay(self,'integration_steps_per_layer','number of radial steps to propagate the yi system from the bottom to the top of each layer (default: 100)');
|
---|
| 79 | fielddisplay(self,'istemporal',{'1 for time-dependent love numbers, 0 for frequency-dependent or elastic love numbers (default: 0)', 'If 1: use fourierlove function build_frequencies_from_time to meet consistency'});
|
---|
| 80 | fielddisplay(self,'n_temporal_iterations','max number of iterations in the inverse Laplace transform. Also the number of spectral samples per time step requested (default: 8)');
|
---|
| 81 | fielddisplay(self,'time','time vector for deformation if istemporal (default: 0) [s]');
|
---|
| 82 | fielddisplay(self,'love_kernels','compute love numbers at depth? (default: 0)');
|
---|
| 83 | fielddisplay(self,'forcing_type',{'integer indicating the nature and depth of the forcing for the Love number calculation (default: 11):','1: Inner core boundary -- Volumic Potential','2: Inner core boundary -- Pressure','3: Inner core boundary -- Loading','4: Inner core boundary -- Tangential traction','5: Core mantle boundary -- Volumic Potential','6: Core mantle boundary -- Pressure','7: Core mantle boundary -- Loading','8: Core mantle boundary -- Tangential traction','9: Surface -- Volumic Potential','10: Surface -- Pressure','11: Surface -- Loading','12: Surface -- Tangential traction '});
|
---|
| 84 | fielddisplay(self,'inner_core_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)');
|
---|
| 85 | fielddisplay(self,'core_mantle_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)');
|
---|
[22004] | 86 |
|
---|
| 87 | end % }}}
|
---|
| 88 | function md = checkconsistency(self,md,solution,analyses) % {{{
|
---|
| 89 |
|
---|
[26744] | 90 | if ~ismember('LoveAnalysis',analyses), return; end
|
---|
| 91 |
|
---|
[22004] | 92 | md = checkfield(md,'fieldname','love.nfreq','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 93 | md = checkfield(md,'fieldname','love.frequencies','NaN',1,'Inf',1,'numel',md.love.nfreq);
|
---|
| 94 | md = checkfield(md,'fieldname','love.sh_nmax','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 95 | md = checkfield(md,'fieldname','love.sh_nmin','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 96 | md = checkfield(md,'fieldname','love.g0','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 97 | md = checkfield(md,'fieldname','love.r0','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 98 | md = checkfield(md,'fieldname','love.mu0','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
[26744] | 99 | md = checkfield(md,'fieldname','love.Gravitational_Constant','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
[22004] | 100 | md = checkfield(md,'fieldname','love.allow_layer_deletion','values',[0 1]);
|
---|
[26744] | 101 | md = checkfield(md,'fieldname','love.underflow_tol','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 102 | md = checkfield(md,'fieldname','love.integration_steps_per_layer','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
[22383] | 103 | md = checkfield(md,'fieldname','love.love_kernels','values',[0 1]);
|
---|
[22004] | 104 | md = checkfield(md,'fieldname','love.forcing_type','NaN',1,'Inf',1,'numel',1,'>',0, '<=', 12);
|
---|
[26744] | 105 | md = checkfield(md,'fieldname','love.complex_computation','NaN',1,'Inf',1,'numel',1,'values',[0 1]);
|
---|
| 106 |
|
---|
| 107 | md = checkfield(md,'fieldname','love.istemporal','values',[0 1]);
|
---|
| 108 | if md.love.istemporal==1
|
---|
| 109 | md = checkfield(md,'fieldname','love.n_temporal_iterations','NaN',1,'Inf',1,'numel',1,'>',0);
|
---|
| 110 | md = checkfield(md,'fieldname','love.time','NaN',1,'Inf',1,'numel',md.love.nfreq/2/md.love.n_temporal_iterations);
|
---|
[22004] | 111 | end
|
---|
[26744] | 112 | if md.love.sh_nmin<=1 & (md.love.forcing_type==1 || md.love.forcing_type==5 || md.love.forcing_type==9)
|
---|
| 113 | error(['Degree 1 not supported for forcing type ' num2str(md.love.forcing_type) '. Use sh_min>=2 for this kind of calculation.'])
|
---|
| 114 | end
|
---|
| 115 |
|
---|
| 116 | %need 'litho' material:
|
---|
| 117 | if ~isa(md.materials,'materials') | ~sum(strcmpi(md.materials.nature,'litho'))
|
---|
| 118 | error('Need a ''litho'' material to run a Fourier Love number analysis');
|
---|
| 119 | end
|
---|
| 120 |
|
---|
| 121 | mat=find(strcmpi(md.materials.nature,'litho'));
|
---|
| 122 | if md.love.forcing_type<=4
|
---|
| 123 | md = checkfield(md,'fieldname','love.inner_core_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
|
---|
| 124 | elseif md.love.forcing_type<=8
|
---|
| 125 | md = checkfield(md,'fieldname','love.core_mantle_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
|
---|
| 126 | end
|
---|
| 127 |
|
---|
[22004] | 128 | end % }}}
|
---|
| 129 | function marshall(self,prefix,md,fid) % {{{
|
---|
[26744] | 130 |
|
---|
[22004] | 131 | WriteData(fid,prefix,'object',self,'fieldname','nfreq','format','Integer');
|
---|
| 132 | WriteData(fid,prefix,'object',self,'fieldname','frequencies','format','DoubleMat','mattype',3);
|
---|
| 133 | WriteData(fid,prefix,'object',self,'fieldname','sh_nmax','format','Integer');
|
---|
| 134 | WriteData(fid,prefix,'object',self,'fieldname','sh_nmin','format','Integer');
|
---|
| 135 | WriteData(fid,prefix,'object',self,'fieldname','g0','format','Double');
|
---|
| 136 | WriteData(fid,prefix,'object',self,'fieldname','r0','format','Double');
|
---|
| 137 | WriteData(fid,prefix,'object',self,'fieldname','mu0','format','Double');
|
---|
[26744] | 138 | WriteData(fid,prefix,'object',self,'fieldname','Gravitational_Constant','format','Double');
|
---|
[22004] | 139 | WriteData(fid,prefix,'object',self,'fieldname','allow_layer_deletion','format','Boolean');
|
---|
[26744] | 140 | WriteData(fid,prefix,'object',self,'fieldname','underflow_tol','format','Double');
|
---|
| 141 | WriteData(fid,prefix,'object',self,'fieldname','integration_steps_per_layer','format','Integer');
|
---|
| 142 | WriteData(fid,prefix,'object',self,'fieldname','istemporal','format','Boolean');
|
---|
| 143 | WriteData(fid,prefix,'object',self,'fieldname','n_temporal_iterations','format','Integer');
|
---|
| 144 | WriteData(fid,prefix,'object',self,'fieldname','complex_computation','format','Boolean');
|
---|
| 145 | %note: no need to marshall the time vector, we have frequencies
|
---|
[22383] | 146 | WriteData(fid,prefix,'object',self,'fieldname','love_kernels','format','Boolean');
|
---|
[22004] | 147 | WriteData(fid,prefix,'object',self,'fieldname','forcing_type','format','Integer');
|
---|
[26744] | 148 | WriteData(fid,prefix,'object',self,'fieldname','inner_core_boundary','format','Integer');
|
---|
| 149 | WriteData(fid,prefix,'object',self,'fieldname','core_mantle_boundary','format','Integer');
|
---|
[22004] | 150 |
|
---|
| 151 | end % }}}
|
---|
[26744] | 152 | function self = extrude(self,md) % {{{
|
---|
| 153 | end % }}}
|
---|
[22004] | 154 | function savemodeljs(self,fid,modelname) % {{{
|
---|
| 155 | error('not implemented yet!');
|
---|
| 156 | end % }}}
|
---|
[26744] | 157 | function self=build_frequencies_from_time(self) % {{{
|
---|
| 158 | if ~self.istemporal
|
---|
| 159 | error('cannot build frequencies for temporal love numbers if love.istemporal==0')
|
---|
| 160 | end
|
---|
| 161 | disp('Temporal love numbers: Overriding md.love.nfreq and md.love.frequencies');
|
---|
| 162 | self.nfreq=length(self.time)*2*self.n_temporal_iterations;
|
---|
| 163 | self.frequencies=zeros(self.nfreq,1);
|
---|
| 164 | for i=1:length(self.time)
|
---|
| 165 | for j=1:2*self.n_temporal_iterations
|
---|
| 166 | self.frequencies((i-1)*2*self.n_temporal_iterations +j) = j*log(2)/self.time(i)/2/pi;
|
---|
| 167 | end
|
---|
| 168 | end
|
---|
| 169 | end % }}}
|
---|
[22004] | 170 | end
|
---|
| 171 | end
|
---|