Index: ../trunk-jpl/src/m/boundaryconditions/getlovenumbers.py =================================================================== --- ../trunk-jpl/src/m/boundaryconditions/getlovenumbers.py (revision 26300) +++ ../trunk-jpl/src/m/boundaryconditions/getlovenumbers.py (revision 26301) @@ -4,23 +4,27 @@ def getlovenumbers(*args): #{{{ - ''' - GETLOVENUMBERS - provide love numbers retrieved from: + """GETLOVENUMBERS - provide love numbers retrieved from: http://www.srosat.com/iag-jsg/loveNb.php in a chosen reference frame - Usage: - series = love_numbers('type', 'loadingverticaldisplacement', 'referenceframe', 'CM', 'maxdeg', 1001) + Usage: + series = love_numbers('type', 'loadingverticaldisplacement', 'referenceframe', 'CM', 'maxdeg', 1001) - - type = one of 'loadingverticaldisplacement', - 'loadinggravitationalpotential', 'loadinghorizontaldisplacement', - 'tidalverticaldisplacement', 'tidalgravitationalpotential', - 'tidalhorizontaldisplacement' - - reference_frame = one of 'CM' (default) and 'CF' - - maxdeg = default 1000 + - type = one of 'loadingverticaldisplacement', + 'loadinggravitationalpotential', 'loadinghorizontaldisplacement', + 'tidalverticaldisplacement', 'tidalgravitationalpotential', + 'tidalhorizontaldisplacement' + - reference_frame = one of 'CM' (default) and 'CF' + - maxdeg = default 1000 - Example: - h = love_number - ''' + Example: + h = getlovenumbers('type', 'loadingverticaldisplacement', 'referenceframe', 'CM', 'maxdeg', maxdeg) + k = getlovenumbers('type', 'loadinggravitationalpotential', 'referenceframe', 'CM', 'maxdeg', maxdeg) + l = getlovenumbers('type', 'loadinghorizontaldisplacement', 'referenceframe', 'CM', 'maxdeg', maxdeg) + th = getlovenumbers('type', 'tidalverticaldisplacement', 'referenceframe', 'CM', 'maxdeg', maxdeg) + tk = getlovenumbers('type', 'tidalgravitationalpotential', 'referenceframe', 'CM', 'maxdeg', maxdeg) + tl = getlovenumbers('type', 'tidalhorizontaldisplacement', 'referenceframe', 'CM', 'maxdeg', maxdeg) + """ TYPES = [ 'loadingverticaldisplacement', @@ -31,12 +35,15 @@ 'tidalhorizontaldisplacement' ] - #recover options + # Recover options options = pairoptions(*args) type = options.getfieldvalue('type') frame = options.getfieldvalue('referenceframe', 'CM') maxdeg = options.getfieldvalue('maxdeg', 1000) + if (maxdeg > 10000): + raise Exception('PREM love numbers computed only for deg < 10,000. Request lower maxdeg') + if type not in TYPES: raise Exception('type should be one of {}'.format(TYPES)) @@ -10044,10 +10051,10 @@ [-6.27342778, -0.00030945, 0.00018956, 0.00031100, -0.00000116, 0.00000000] ]) - #cut off series at maxdeg + # Cut off series at maxdeg love_numbers = np.delete(love_numbers, range(maxdeg + 1, len(love_numbers)), axis=0) - #retrieve right type + # Retrieve right type if type == 'loadingverticaldisplacement': series = love_numbers[:, 0] elif type == 'loadinggravitationalpotential': @@ -10061,7 +10068,7 @@ elif type == 'tidalhorizontaldisplacement': series = love_numbers[:, 5] else: - raise Exception("love_numbers error message: unknown type: {}".format(type)) + raise Exception('love_numbers error message: unknown type: {}'.format(type)) #choose degree 1 term for CF reference system if frame == 'CM': @@ -10074,7 +10081,7 @@ elif type == 'loadinghorizontaldisplacement': series[1] = 0.134 else: - raise Exception("love_numbers error message: unknown reference frame: {}".format(frame)) + raise Exception('love_numbers error message: unknown reference frame: {}'.format(frame)) return series #}}} Index: ../trunk-jpl/src/m/classes/amr.m =================================================================== --- ../trunk-jpl/src/m/classes/amr.m (revision 26300) +++ ../trunk-jpl/src/m/classes/amr.m (revision 26301) @@ -83,7 +83,7 @@ %control of element lengths self.gradation=1.5; - %other criterias + %other criteria self.groundingline_resolution=500.; self.groundingline_distance=0.; self.icefront_resolution=500.; Index: ../trunk-jpl/src/m/classes/amr.py =================================================================== --- ../trunk-jpl/src/m/classes/amr.py (revision 26300) +++ ../trunk-jpl/src/m/classes/amr.py (revision 26301) @@ -4,84 +4,93 @@ class amr(object): - """ - AMR Class definition + """AMR Class definition Usage: amr = amr() """ - def __init__(self): # {{{ - self.hmin = 0. - self.hmax = 0. + def __init__(self): #{{{ + self.hmin = 0 + self.hmax = 0 self.fieldname = '' - self.err = 0. - self.keepmetric = 0. - self.gradation = 0. - self.groundingline_resolution = 0. - self.groundingline_distance = 0. - self.icefront_resolution = 0. - self.icefront_distance = 0. - self.thicknesserror_resolution = 0. - self.thicknesserror_threshold = 0. - self.thicknesserror_groupthreshold = 0. - self.thicknesserror_maximum = 0. - self.deviatoricerror_resolution = 0. - self.deviatoricerror_threshold = 0. - self.deviatoricerror_groupthreshold = 0. - self.deviatoricerror_maximum = 0. - self.restart = 0. - #set defaults + self.err = 0 + self.keepmetric = 0 + self.gradation = 0 + self.groundingline_resolution = 0 + self.groundingline_distance = 0 + self.icefront_resolution = 0 + self.icefront_distance = 0 + self.thicknesserror_resolution = 0 + self.thicknesserror_threshold = 0 + self.thicknesserror_groupthreshold = 0 + self.thicknesserror_maximum = 0 + self.deviatoricerror_resolution = 0 + self.deviatoricerror_threshold = 0 + self.deviatoricerror_groupthreshold = 0 + self.deviatoricerror_maximum = 0 + self.restart = 0 + self.setdefaultparameters() #}}} - def __repr__(self): # {{{ - string = " amr parameters:" - string = "%s\n%s" % (string, fielddisplay(self, "hmin", "minimum element length")) - string = "%s\n%s" % (string, fielddisplay(self, "hmax", "maximum element length")) - string = "%s\n%s" % (string, fielddisplay(self, "fieldname", "name of input that will be used to compute the metric (should be an input of FemModel)")) - string = "%s\n%s" % (string, fielddisplay(self, "keepmetric", "indicates whether the metric should be kept every remeshing time")) - string = "%s\n%s" % (string, fielddisplay(self, "gradation", "maximum ratio between two adjacent edges")) - string = "%s\n%s" % (string, fielddisplay(self, "groundingline_resolution", "element length near the grounding line")) - string = "%s\n%s" % (string, fielddisplay(self, "groundingline_distance", "distance around the grounding line which elements will be refined")) - string = "%s\n%s" % (string, fielddisplay(self, "icefront_resolution", "element length near the ice front")) - string = "%s\n%s" % (string, fielddisplay(self, "icefront_distance", "distance around the ice front which elements will be refined")) - string = "%s\n%s" % (string, fielddisplay(self, "thicknesserror_resolution", "element length when thickness error estimator is used")) - string = "%s\n%s" % (string, fielddisplay(self, "thicknesserror_threshold", "maximum threshold thickness error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "thicknesserror_groupthreshold", "maximum group threshold thickness error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "thicknesserror_maximum", "maximum thickness error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "deviatoricerror_resolution", "element length when deviatoric stress error estimator is used")) - string = "%s\n%s" % (string, fielddisplay(self, "deviatoricerror_threshold", "maximum threshold deviatoricstress error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "deviatoricerror_groupthreshold", "maximum group threshold deviatoric stress error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "deviatoricerror_maximum", "maximum deviatoricstress error permitted")) - string = "%s\n%s" % (string, fielddisplay(self, "restart", "indicates if ReMesh() will call before first time step")) - return string + def __repr__(self): #{{{ + s = ' amr parameters:\n' + s += '{}\n'.format(fielddisplay(self, 'hmin', 'minimum element length')) + s += '{}\n'.format(fielddisplay(self, 'hmax', 'maximum element length')) + s += '{}\n'.format(fielddisplay(self, 'fieldname', 'name of input that will be used to compute the metric (should be an input of FemModel)')) + s += '{}\n'.format(fielddisplay(self, 'keepmetric', 'indicates whether the metric should be kept every remeshing time')) + s += '{}\n'.format(fielddisplay(self, 'gradation', 'maximum ratio between two adjacent edges')) + s += '{}\n'.format(fielddisplay(self, 'groundingline_resolution', 'element length near the grounding line')) + s += '{}\n'.format(fielddisplay(self, 'groundingline_distance', 'distance around the grounding line which elements will be refined')) + s += '{}\n'.format(fielddisplay(self, 'icefront_resolution', 'element length near the ice front')) + s += '{}\n'.format(fielddisplay(self, 'icefront_distance', 'distance around the ice front which elements will be refined')) + s += '{}\n'.format(fielddisplay(self, 'thicknesserror_resolution', 'element length when thickness error estimator is used')) + s += '{}\n'.format(fielddisplay(self, 'thicknesserror_threshold', 'maximum threshold thickness error permitted')) + s += '{}\n'.format(fielddisplay(self, 'thicknesserror_groupthreshold', 'maximum group threshold thickness error permitted')) + s += '{}\n'.format(fielddisplay(self, 'thicknesserror_maximum', 'maximum thickness error permitted')) + s += '{}\n'.format(fielddisplay(self, 'deviatoricerror_resolution', 'element length when deviatoric stress error estimator is used')) + s += '{}\n'.format(fielddisplay(self, 'deviatoricerror_threshold', 'maximum threshold deviatoricstress error permitted')) + s += '{}\n'.format(fielddisplay(self, 'deviatoricerror_groupthreshold', 'maximum group threshold deviatoric stress error permitted')) + s += '{}\n'.format(fielddisplay(self, 'deviatoricerror_maximum', 'maximum deviatoricstress error permitted')) + s += '{}\n'.format(fielddisplay(self, 'restart', 'indicates if ReMesh() will call before first time step')) + return s #}}} - def setdefaultparameters(self): # {{{ - self.hmin = 100. - self.hmax = 100.e3 + def setdefaultparameters(self): #{{{ + self.hmin = 100 + self.hmax = 100e3 + + # Fields self.fieldname = 'Vel' - self.err = 3. + self.err = 3 + + # Keep metric? self.keepmetric = 1 + + # Control of element lengths self.gradation = 1.5 - self.groundingline_resolution = 500. + + # Other criteria + self.groundingline_resolution = 500 self.groundingline_distance = 0 - self.icefront_resolution = 500. + self.icefront_resolution = 500 self.icefront_distance = 0 - self.thicknesserror_resolution = 500. + self.thicknesserror_resolution = 500 self.thicknesserror_threshold = 0 self.thicknesserror_groupthreshold = 0 self.thicknesserror_maximum = 0 - self.deviatoricerror_resolution = 500. + self.deviatoricerror_resolution = 500 self.deviatoricerror_threshold = 0 self.deviatoricerror_groupthreshold = 0 self.deviatoricerror_maximum = 0 - self.restart = 0. + + # Is restart? This calls femmodel->ReMesh() before first time step. + self.restart = 0 return self #}}} - def checkconsistency(self, md, solution, analyses): # {{{ + def checkconsistency(self, md, solution, analyses): #{{{ md = checkfield(md, 'fieldname', 'amr.hmax', 'numel', [1], '>', 0, 'NaN', 1) md = checkfield(md, 'fieldname', 'amr.hmin', 'numel', [1], '>', 0, '<', self.hmax, 'NaN', 1) md = checkfield(md, 'fieldname', 'amr.keepmetric', 'numel', [1], '>=', 0, '<=', 1, 'NaN', 1) @@ -100,9 +109,9 @@ md = checkfield(md, 'fieldname', 'amr.deviatoricerror_maximum', 'numel', [1], '>=', 0, 'NaN', 1, 'Inf', 1) md = checkfield(md, 'fieldname', 'amr.restart', 'numel', [1], '>=', 0, '<=', 1, 'NaN', 1) return md - # }}} + # }}} - def marshall(self, prefix, md, fid): # {{{ + def marshall(self, prefix, md, fid): #{{{ WriteData(fid, prefix, 'name', 'md.amr.type', 'data', 1, 'format', 'Integer') WriteData(fid, prefix, 'object', self, 'fieldname', 'hmin', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'fieldname', 'hmax', 'format', 'Double') @@ -123,4 +132,4 @@ WriteData(fid, prefix, 'object', self, 'fieldname', 'deviatoricerror_groupthreshold', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'fieldname', 'deviatoricerror_maximum', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'class', 'amr', 'fieldname', 'restart', 'format', 'Integer') - # }}} + #}}} Index: ../trunk-jpl/src/m/classes/dsl.m =================================================================== --- ../trunk-jpl/src/m/classes/dsl.m (revision 26300) +++ ../trunk-jpl/src/m/classes/dsl.m (revision 26301) @@ -12,10 +12,6 @@ end methods - function self = extrude(self,md) % {{{ - self.sea_surface_height_above_geoid=project3d(md,'vector',self.sea_surface_height_above_geoid,'type','node','layer',1); - self.sea_water_pressure_at_sea_floor=project3d(md,'vector',self.sea_water_pressure_at_sea_floor,'type','node','layer',1); - end % }}} function self = dsl(varargin) % {{{ switch nargin case 0 @@ -33,6 +29,14 @@ self.sea_water_pressure_at_sea_floor=NaN; end % }}} + function disp(self) % {{{ + + disp(sprintf(' dsl parameters:')); + fielddisplay(self,'global_average_thermosteric_sea_level','Corresponds to zostoga field in CMIP5 archives. Specified as a temporally variable quantity (in m).'); + fielddisplay(self,'sea_surface_height_above_geoid','Corresponds to zos field in CMIP5 archives. Spatial average is 0. Specified as a spatio-temporally variable quantity (in m).'); + fielddisplay(self,'sea_water_pressure_at_sea_floor','Corresponds to bpo field in CMIP5 archives. Specified as a spatio-temporally variable quantity (in m equivalent, not in Pa!).'); + + end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ %Early return @@ -48,28 +52,17 @@ end end % }}} - function disp(self) % {{{ - - disp(sprintf(' dsl parameters:')); - fielddisplay(self,'global_average_thermosteric_sea_level','Corresponds to zostoga field in CMIP5 archives. Specified as a temporally variable quantity (in m).'); - fielddisplay(self,'sea_surface_height_above_geoid','Corresponds to zos field in CMIP5 archives. Spatial average is 0. Specified as a spatio-temporally variable quantity (in m).'); - fielddisplay(self,'sea_water_pressure_at_sea_floor','Corresponds to bpo field in CMIP5 archives. Specified as a spatio-temporally variable quantity (in m equivalent, not in Pa!).'); - - end % }}} function marshall(self,prefix,md,fid) % {{{ - + yts=md.constants.yts; WriteData(fid,prefix,'name','md.dsl.model','data',1,'format','Integer'); - WriteData(fid,prefix,'object',self,'fieldname','global_average_thermosteric_sea_level','format','DoubleMat','mattype',2,'timeseries',1,'timeserieslength',2,'yts',md.constants.yts); %mattype 2, because we are sending a GMSL value identical everywhere on each element. - WriteData(fid,prefix,'object',self,'fieldname','sea_surface_height_above_geoid','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); %mattype 1 because we specify DSL at vertex locations. - WriteData(fid,prefix,'object',self,'fieldname','sea_water_pressure_at_sea_floor','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); %mattype 1 because we specify bottom pressure at vertex locations. + WriteData(fid,prefix,'object',self,'fieldname','global_average_thermosteric_sea_level','format','DoubleMat','mattype',2,'timeseries',1,'timeserieslength',2,'yts',yts); %mattype 2, because we are sending a GMSL value identical everywhere on each element. + WriteData(fid,prefix,'object',self,'fieldname','sea_surface_height_above_geoid','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); %mattype 1 because we specify DSL at vertex locations. + WriteData(fid,prefix,'object',self,'fieldname','sea_water_pressure_at_sea_floor','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); %mattype 1 because we specify bottom pressure at vertex locations. end % }}} - function savemodeljs(self,fid,modelname) % {{{ - - writejs1Darray(fid,[modelname '.dsl.global_average_thermosteric_sea_level'],self.global_average_thermosteric_sea_level); - writejs1Darray(fid,[modelname '.dsl.sea_surface_height_above_geoid'],self.sea_surface_height_above_geoid); - writejs1Darray(fid,[modelname '.dsl.sea_water_pressure_at_sea_floor'],self.sea_water_pressure_at_sea_floor); - + function self = extrude(self,md) % {{{ + self.sea_surface_height_above_geoid=project3d(md,'vector',self.sea_surface_height_above_geoid,'type','node','layer',1); + self.sea_water_pressure_at_sea_floor=project3d(md,'vector',self.sea_water_pressure_at_sea_floor,'type','node','layer',1); end % }}} function self = initialize(self,md) % {{{ @@ -86,6 +79,12 @@ disp(' no dsl.sea_water_pressure_at_sea_floor specified: transient values set at zero'); end end % }}} - + function savemodeljs(self,fid,modelname) % {{{ + + writejs1Darray(fid,[modelname '.dsl.global_average_thermosteric_sea_level'],self.global_average_thermosteric_sea_level); + writejs1Darray(fid,[modelname '.dsl.sea_surface_height_above_geoid'],self.sea_surface_height_above_geoid); + writejs1Darray(fid,[modelname '.dsl.sea_water_pressure_at_sea_floor'],self.sea_water_pressure_at_sea_floor); + + end % }}} end end Index: ../trunk-jpl/src/m/classes/fourierlove.m =================================================================== --- ../trunk-jpl/src/m/classes/fourierlove.m (revision 26300) +++ ../trunk-jpl/src/m/classes/fourierlove.m (revision 26301) @@ -5,25 +5,25 @@ classdef fourierlove properties (SetAccess=public) - nfreq = 0; - frequencies = 0; - sh_nmax = 0; - sh_nmin = 0; - g0 = 0; - r0 = 0; - mu0 = 0; - Gravitational_Constant = 0; - allow_layer_deletion = 0; - underflow_tol = 0; - integration_steps_per_layer= 0; - istemporal = 0; - n_temporal_iterations = 0; - time = 0; - love_kernels = 0; - forcing_type = 0; - inner_core_boundary = 0; - core_mantle_boundary = 0; - complex_computation = 0; + nfreq = 0; + frequencies = 0; + sh_nmax = 0; + sh_nmin = 0; + g0 = 0; + r0 = 0; + mu0 = 0; + Gravitational_Constant = 0; + allow_layer_deletion = 0; + underflow_tol = 0; + integration_steps_per_layer = 0; + istemporal = 0; + n_temporal_iterations = 0; + time = 0; + love_kernels = 0; + forcing_type = 0; + inner_core_boundary = 0; + core_mantle_boundary = 0; + complex_computation = 0; end methods (Static) @@ -33,8 +33,6 @@ end% }}} end methods - function self = extrude(self,md) % {{{ - end % }}} function self = fourierlove(varargin) % {{{ switch nargin case 0 @@ -52,7 +50,7 @@ % work on matlab script for computing g0 for given Earth's structure. self.g0=9.81; % m/s^2; self.r0=6371*1e3; %m; - self.mu0=10^11; % Pa + self.mu0=1e11; % Pa self.Gravitational_Constant=6.67259e-11; % m^3 kg^-1 s^-2 self.allow_layer_deletion=1; self.underflow_tol=1e-16; %threshold of deep to surface love number ratio to trigger the deletion of layer @@ -67,24 +65,24 @@ self.complex_computation=0; end % }}} function disp(self) % {{{ - fielddisplay(self,'nfreq','number of frequencies sampled (default 1, elastic) [Hz]'); + fielddisplay(self,'nfreq','number of frequencies sampled (default: 1, elastic) [Hz]'); fielddisplay(self,'frequencies','frequencies sampled (convention defaults to 0 for the elastic case) [Hz]'); - fielddisplay(self,'sh_nmax','maximum spherical harmonic degree (default 256, .35 deg, or 40 km at equator)'); - fielddisplay(self,'sh_nmin','minimum spherical harmonic degree (default 1)'); - fielddisplay(self,'g0','adimensioning constant for gravity (default 10) [m/s^2]'); - fielddisplay(self,'r0','adimensioning constant for radius (default 6371*10^3) [m]'); - fielddisplay(self,'mu0','adimensioning constant for stress (default 10^11) [Pa]'); - fielddisplay(self,'Gravitational_Constant','Newtonian constant of gravitation (default 6.67259e-11 [m^3 kg^-1 s^-2])'); - fielddisplay(self,'allow_layer_deletion','allow for migration of the integration boundary with increasing spherical harmonics degree (default 1)'); - fielddisplay(self,'underflow_tol','threshold of deep to surface love number ratio to trigger the deletion of layers (default 2.2204460492503131E-016)'); - 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)'); - 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'}); - 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)'); - fielddisplay(self,'time','time vector for deformation if istemporal (default 0) [s]'); - fielddisplay(self,'love_kernels','compute love numbers at depth? (default 0)'); - 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 '}); - fielddisplay(self,'inner_core_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default 1)'); - fielddisplay(self,'core_mantle_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default 2)'); + fielddisplay(self,'sh_nmax','maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)'); + fielddisplay(self,'sh_nmin','minimum spherical harmonic degree (default: 1)'); + fielddisplay(self,'g0','adimensioning constant for gravity (default: 10) [m/s^2]'); + fielddisplay(self,'r0','adimensioning constant for radius (default: 6371*10^3) [m]'); + fielddisplay(self,'mu0','adimensioning constant for stress (default: 10^11) [Pa]'); + fielddisplay(self,'Gravitational_Constant','Newtonian constant of gravitation (default: 6.67259e-11 [m^3 kg^-1 s^-2])'); + fielddisplay(self,'allow_layer_deletion','allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)'); + fielddisplay(self,'underflow_tol','threshold of deep to surface love number ratio to trigger the deletion of layers (default: 1e-16)'); + 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)'); + 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'}); + 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)'); + fielddisplay(self,'time','time vector for deformation if istemporal (default: 0) [s]'); + fielddisplay(self,'love_kernels','compute love numbers at depth? (default: 0)'); + 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 '}); + fielddisplay(self,'inner_core_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)'); + fielddisplay(self,'core_mantle_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)'); end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ @@ -111,8 +109,8 @@ md = checkfield(md,'fieldname','love.n_temporal_iterations','NaN',1,'Inf',1,'numel',1,'>',0); md = checkfield(md,'fieldname','love.time','NaN',1,'Inf',1,'numel',md.love.nfreq/2/md.love.n_temporal_iterations); end - if md.love.sh_nmin<=1 & (md.love.forcing_type==9 || md.love.forcing_type==5 || md.love.forcing_type==1) - error('Degree 1 not supported for Volumetric Potential forcing. Use sh_min>=2 for this kind of calculation.') + if md.love.sh_nmin<=1 & (md.love.forcing_type==1 || md.love.forcing_type==5 || md.love.forcing_type==9) + error(['Degree 1 not supported for forcing type ' num2str(md.love.forcing_type) '. Use sh_min>=2 for this kind of calculation.']) end %need 'litho' material: @@ -129,7 +127,7 @@ end % }}} function marshall(self,prefix,md,fid) % {{{ - + WriteData(fid,prefix,'object',self,'fieldname','nfreq','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','frequencies','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'fieldname','sh_nmax','format','Integer'); @@ -151,6 +149,8 @@ WriteData(fid,prefix,'object',self,'fieldname','core_mantle_boundary','format','Integer'); end % }}} + function self = extrude(self,md) % {{{ + end % }}} function savemodeljs(self,fid,modelname) % {{{ error('not implemented yet!'); end % }}} Index: ../trunk-jpl/src/m/classes/fourierlove.py =================================================================== --- ../trunk-jpl/src/m/classes/fourierlove.py (revision 26300) +++ ../trunk-jpl/src/m/classes/fourierlove.py (revision 26301) @@ -1,3 +1,5 @@ +import numpy as np + from fielddisplay import fielddisplay from checkfield import checkfield from WriteData import WriteData @@ -4,12 +6,13 @@ class fourierlove(object): - """FOURIERLOVE - Fourier Love Number class definition + """FOURIERLOVE - class definition Usage: - fourierlove = fourierlove() + md.love = fourierlove() """ - def __init__(self): # {{{ + + def __init__(self): #{{{ self.nfreq = 0 self.frequencies = 0 self.sh_nmax = 0 @@ -17,96 +20,155 @@ self.g0 = 0 self.r0 = 0 self.mu0 = 0 + self.Gravitational_Constant = 0 self.allow_layer_deletion = 0 + self.underflow_tol = 0 + self.integration_steps_per_layer = 0 + self.istemporal = 0 + self.n_temporal_iterations = 0 + self.time = 0 self.love_kernels = 0 self.forcing_type = 0 + self.inner_core_boundary = 0 + self.core_mantle_boundary = 0 + self.complex_computation = 0 self.setdefaultparameters() #}}} - def __repr__(self): # {{{ - # TODO: - # - Convert all formatting to calls to .format (see any - # already converted .__repr__ method for examples) - # - string = ' Fourier Love class:' - string = "%s\n%s" % (string, fielddisplay(self, 'nfreq', 'number of frequencies sampled (default 1, elastic) [Hz]')) - string = "%s\n%s" % (string, fielddisplay(self, 'frequencies', 'frequencies sampled (convention defaults to 0 for the elastic case) [Hz]')) - string = "%s\n%s" % (string, fielddisplay(self, 'sh_nmax', 'maximum spherical harmonic degree (default 256, .35 deg, or 40 km at equator)')) - string = "%s\n%s" % (string, fielddisplay(self, 'sh_nmin', 'minimum spherical harmonic degree (default 1)')) - string = "%s\n%s" % (string, fielddisplay(self, 'g0', 'adimensioning constant for gravity (default 10) [m / s^2]')) - string = "%s\n%s" % (string, fielddisplay(self, 'r0', 'adimensioning constant for radius (default 6378e3) [m]')) - string = "%s\n%s" % (string, fielddisplay(self, 'mu0', 'adimensioning constant for stress (default 1.0e11) [Pa]')) - string = "%s\n%s" % (string, fielddisplay(self, 'allow_layer_deletion', 'allow for migration of the integration boundary with increasing spherical harmonics degree (default 1)')) - string = "%s\n%s" % (string, fielddisplay(self, 'love_kernels', 'compute love numbers at depth? (default 0)')) - string = "%s\n%s" % (string, fielddisplay(self, 'forcing_type', 'integer indicating the nature and depth of the forcing for the Love number calculation (default 11) :')) - string = "%s\n%s" % (string, ' 1: Inner core boundary -- Volumic Potential') - string = "%s\n%s" % (string, ' 2: Inner core boundary -- Pressure') - string = "%s\n%s" % (string, ' 3: Inner core boundary -- Loading') - string = "%s\n%s" % (string, ' 4: Inner core boundary -- Tangential traction') - string = "%s\n%s" % (string, ' 5: Core mantle boundary -- Volumic Potential') - string = "%s\n%s" % (string, ' 6: Core mantle boundary -- Pressure') - string = "%s\n%s" % (string, ' 7: Core mantle boundary -- Loading') - string = "%s\n%s" % (string, ' 8: Core mantle boundary -- Tangential traction') - string = "%s\n%s" % (string, ' 9: Surface-- Volumic Potential') - string = "%s\n%s" % (string, ' 10: Surface-- Pressure') - string = "%s\n%s" % (string, ' 11: Surface-- Loading') - string = "%s\n%s" % (string, ' 12: Surface-- Tangential traction ') + def __repr__(self): #{{{ + s = ' Fourier Love class:\n' + s += '{}\n'.format(fielddisplay(self, 'nfreq', 'number of frequencies sampled (default: 1, elastic) [Hz]')) + s += '{}\n'.format(fielddisplay(self, 'frequencies', 'frequencies sampled (convention defaults to 0 for the elastic case) [Hz]')) + s += '{}\n'.format(fielddisplay(self, 'sh_nmax', 'maximum spherical harmonic degree (default: 256, .35 deg, or 40 km at equator)')) + s += '{}\n'.format(fielddisplay(self, 'sh_nmin', 'minimum spherical harmonic degree (default: 1)')) + s += '{}\n'.format(fielddisplay(self, 'g0', 'adimensioning constant for gravity (default: 10) [m / s^2]')) + s += '{}\n'.format(fielddisplay(self, 'r0', 'adimensioning constant for radius (default: 6378e3) [m]')) + s += '{}\n'.format(fielddisplay(self, 'mu0', 'adimensioning constant for stress (default: 1.0e11) [Pa]')) + s += '{}\n'.format(fielddisplay(self, 'allow_layer_deletion', 'allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)')) + s += '{}\n'.format(fielddisplay(self, 'Gravitational_Constant', 'Newtonian constant of gravitation (default: 6.67259e-11 [m^3 kg^-1 s^-2])')) + s += '{}\n'.format(fielddisplay(self, 'allow_layer_deletion', 'allow for migration of the integration boundary with increasing spherical harmonics degree (default: 1)')) + s += '{}\n'.format(fielddisplay(self, 'underflow_tol', 'threshold of deep to surface love number ratio to trigger the deletion of layers (default: 1e-16)')) + s += '{}\n'.format(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)')) + s += '{}\n'.format(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'})) + s += '{}\n'.format(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)')) + s += '{}\n'.format(fielddisplay(self, 'time', 'time vector for deformation if istemporal (default: 0) [s]')) + s += '{}\n'.format(fielddisplay(self, 'love_kernels', 'compute love numbers at depth? (default: 0)')) + s += '{}\n'.format(fielddisplay(self, 'forcing_type', 'integer indicating the nature and depth of the forcing for the Love number calculation (default: 11):')) + s += '{}\n'.format(' 1: Inner core boundary -- Volumic Potential') + s += '{}\n'.format(' 2: Inner core boundary -- Pressure') + s += '{}\n'.format(' 3: Inner core boundary -- Loading') + s += '{}\n'.format(' 4: Inner core boundary -- Tangential traction') + s += '{}\n'.format(' 5: Core mantle boundary -- Volumic Potential') + s += '{}\n'.format(' 6: Core mantle boundary -- Pressure') + s += '{}\n'.format(' 7: Core mantle boundary -- Loading') + s += '{}\n'.format(' 8: Core mantle boundary -- Tangential traction') + s += '{}\n'.format(' 9: Surface-- Volumic Potential') + s += '{}\n'.format(' 10: Surface-- Pressure') + s += '{}\n'.format(' 11: Surface-- Loading') + s += '{}\n'.format(' 12: Surface-- Tangential traction ') + s += '{}\n'.format(fielddisplay(self, 'inner_core_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default: 1)')) + s += '{}\n'.format(fielddisplay(self, 'core_mantle_boundary', 'interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default: 2)')) - return string + return s #}}} - def extrude(self, md): # {{{ - return self - #}}} - - def setdefaultparameters(self): # {{{ - #we setup an elastic love number computation by default. + def setdefaultparameters(self): #{{{ + # We setup an elastic love number computation by default self.nfreq = 1 - self.frequencies = [0] #Hz - self.sh_nmax = 256 # .35 degree, 40 km at the equator. + self.frequencies = [0] # Hz + self.sh_nmax = 256 # .35 degree, 40 km at the equator self.sh_nmin = 1 + # Work on matlab script for computing g0 for given Earth's structure self.g0 = 9.81 # m/s^2 - self.r0 = 6371e3 #m + self.r0 = 6371 * 1e3 # m self.mu0 = 1e11 # Pa + self.Gravitational_Constant = 6.67259e-11 # m^3 kg^-1 s^-2 self.allow_layer_deletion = 1 + self.underflow_tol = 1e-16 # Threshold of deep to surface love number ratio to trigger the deletion of layer + self.integration_steps_per_layer = 100 + self.istemporal = 0 + self.n_temporal_iterations = 8 + self.time = [0] # s self.love_kernels = 0 - self.forcing_type = 11 - - return self + self.forcing_type = 11 # Surface loading + self.inner_core_boundary = 1 + self.core_mantle_boundary = 2 + self.complex_computation = 0 #}}} - def checkconsistency(self, md, solution, analyses): # {{{ + def checkconsistency(self, md, solution, analyses): #{{{ if 'LoveAnalysis' not in analyses: return md - md = checkfield(md, 'fieldname', 'love.nfreq', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) - md = checkfield(md, 'fieldname', 'love.frequencies', 'NaN', 1, 'Inf', 1, 'numel', [md.love.nfreq]) - md = checkfield(md, 'fieldname', 'love.sh_nmax', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) - md = checkfield(md, 'fieldname', 'love.sh_nmin', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) - md = checkfield(md, 'fieldname', 'love.g0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) - md = checkfield(md, 'fieldname', 'love.r0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) - md = checkfield(md, 'fieldname', 'love.mu0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0) + + md = checkfield(md, 'fieldname', 'love.nfreq', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.frequencies', 'NaN', 1, 'Inf', 1, 'numel', md.love.nfreq) + md = checkfield(md, 'fieldname', 'love.sh_nmax', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.sh_nmin', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.g0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.r0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.mu0', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.Gravitational_Constant', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) md = checkfield(md, 'fieldname', 'love.allow_layer_deletion', 'values', [0, 1]) + md = checkfield(md, 'fieldname', 'love.underflow_tol', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.integration_steps_per_layer', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) md = checkfield(md, 'fieldname', 'love.love_kernels', 'values', [0, 1]) - md = checkfield(md, 'fieldname', 'love.forcing_type', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0, '<=', 12) - if md.love.sh_nmin <= 1 and md.love.forcing_type == 9: - raise RuntimeError("Degree 1 not supported for Volumetric Potential forcing. Use sh_min >= 2 for this kind of calculation.") + md = checkfield(md, 'fieldname', 'love.forcing_type', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', 12) + md = checkfield(md, 'fieldname', 'love.complex_computation', 'NaN', 1, 'Inf', 1, 'numel', 1, 'values', [0, 1]) - # need 'litho' material + md = checkfield(md, 'fieldname', 'love.istemporal', 'values', [0, 1]) + if md.love.istemporal: + md = checkfield(md, 'fieldname', 'love.n_temporal_iterations', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'love.time', 'NaN', 1, 'Inf', 1, 'numel', md.love.nfreq / 2 / md.love.n_temporal_iterations) + if md.love.sh_nmin <= 1 and (md.love.forcing_type == 1 or md.love.forcing_type == 5 or md.love.forcing_type == 9): + raise RuntimeError('Degree 1 not supported for forcing type {}. Use sh_min >= 2 for this kind of calculation.'.format(md.love.forcing_type)) + + # Need 'litho' material if not hasattr(md.materials, 'materials') or 'litho' not in md.materials.nature: raise RuntimeError('Need a \'litho\' material to run a Fourier Love number analysis') + + mat = np.where(np.array(nature) == 'litho')[0] + if md.love.forcing_type <= 4: + md = checkfield(md, 'fieldname', 'love.inner_core_boundary', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', md.materials[mat].numlayers) + elif md.love.forcing_type <= 8: + md = checkfield(md, 'fieldname', 'love.core_mantle_boundary', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0, '<=', md.materials[mat].numlayers) + return md - # }}} + #}}} - def marshall(self, prefix, md, fid): # {{{ + def marshall(self, prefix, md, fid): #{{{ WriteData(fid, prefix, 'object', self, 'fieldname', 'nfreq', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'frequencies', 'format', 'DoubleMat', 'mattype', 3) + WriteData(fid, prefix, 'object', self, 'fieldname', 'frequencies', 'format', 'DoubleMat', 'mattype',3) WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmax', 'format', 'Integer') WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmin', 'format', 'Integer') WriteData(fid, prefix, 'object', self, 'fieldname', 'g0', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'fieldname', 'r0', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'fieldname', 'mu0', 'format', 'Double') + WriteData(fid, prefix, 'object', self, 'fieldname', 'Gravitational_Constant', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'fieldname', 'allow_layer_deletion', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'fieldname', 'underflow_tol', 'format', 'Double') + WriteData(fid, prefix, 'object', self, 'fieldname', 'integration_steps_per_layer', 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'istemporal', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'fieldname', 'n_temporal_iterations', 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'complex_computation', 'format', 'Boolean') + # Note: no need to marshall the time vector, we have frequencies WriteData(fid, prefix, 'object', self, 'fieldname', 'love_kernels', 'format', 'Boolean') WriteData(fid, prefix, 'object', self, 'fieldname', 'forcing_type', 'format', 'Integer') - # }}} + WriteData(fid, prefix, 'object', self, 'fieldname', 'inner_core_boundary', 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'core_mantle_boundary', 'format', 'Integer') + #}}} + + def extrude(self, md): #{{{ + return self + #}}} + + def build_frequencies_from_time(self): #{{{ + if not self.istemporal: + raise RuntimeError('cannot build frequencies for temporal love numbers if love.istemporal==0') + print('Temporal love numbers: Overriding md.love.nfreq and md.love.frequencies') + self.nfreq = len(self.time) * 2 * self.n_temporal_iterations + self.frequencies = np.zeros((self.nfreq, 1)) + for i in range(len(self.time)): + for j in range(2 * self.n_temporal_iterations): + self.frequencies[(i - 1) * 2 * self.n_temporal_iterations + j] = j * np.log(2) / self.time[i] / 2 / np.pi + #}}} Index: ../trunk-jpl/src/m/classes/geometry.py =================================================================== --- ../trunk-jpl/src/m/classes/geometry.py (revision 26300) +++ ../trunk-jpl/src/m/classes/geometry.py (revision 26301) @@ -36,7 +36,7 @@ #}}} def setdefaultparameters(self): #{{{ - return self + return #}}} def checkconsistency(self, md, solution, analyses): #{{{ Index: ../trunk-jpl/src/m/classes/hydrologyshreve.py =================================================================== --- ../trunk-jpl/src/m/classes/hydrologyshreve.py (revision 26300) +++ ../trunk-jpl/src/m/classes/hydrologyshreve.py (revision 26301) @@ -1,3 +1,5 @@ +import numpy as np + from fielddisplay import fielddisplay from checkfield import checkfield from WriteData import WriteData @@ -10,43 +12,35 @@ hydrologyshreve = hydrologyshreve() """ - def __init__(self): # {{{ - self.spcwatercolumn = float('NaN') + def __init__(self, *args): #{{{ + self.spcwatercolumn = np.nan self.stabilization = 0 self.requested_outputs = [] - self.setdefaultparameters() + nargs = len(args) + if nargs == 0: + self.setdefaultparameters() + elif nargs == 1: + self.setdefaultparameters(args) + else: + raise RuntimeError('constructor not supported') #}}} - def __repr__(self): # {{{ - # TODO: - # - Convert all formatting to calls to .format (see any - # already converted .__repr__ method for examples) - # - string = ' hydrologyshreve solution parameters:' - string = "%s\n%s" % (string, fielddisplay(self, 'spcwatercolumn', 'water thickness constraints (NaN means no constraint) [m]')) - string = "%s\n%s" % (string, fielddisplay(self, 'stabilization', 'artificial diffusivity (default is 1). can be more than 1 to increase diffusivity.')) - string = "%s\n%s" % (string, fielddisplay(self, 'requested_outputs', 'additional outputs requested')) - return string + def __repr__(self): #{{{ + s = ' hydrologyshreve solution parameters:\n' + s += '{}\n'.format(fielddisplay(self, 'spcwatercolumn', 'water thickness constraints (NaN means no constraint) [m]')) + s += '{}\n'.format(fielddisplay(self, 'stabilization', 'artificial diffusivity (default: 1). can be more than 1 to increase diffusivity.')) + s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested')) + return s #}}} - def extrude(self, md): # {{{ - return self - #}}} - - def setdefaultparameters(self): # {{{ - #Type of stabilization to use 0:nothing 1:artificial_diffusivity + def setdefaultparameters(self): #{{{ + # Type of stabilization to use 0:nothing 1:artificial_diffusivity self.stabilization = 1 self.requested_outputs = ['default'] - return self #}}} - def defaultoutputs(self, md): # {{{ - list = ['Watercolumn', 'HydrologyWaterVx', 'HydrologyWaterVy'] - return list - #}}} - - def checkconsistency(self, md, solution, analyses): # {{{ + def checkconsistency(self, md, solution, analyses): #{{{ #Early return if 'HydrologyShreveAnalysis' not in analyses or (solution == 'TransientSolution' and not md.transient.ishydrology): return md @@ -53,20 +47,25 @@ md = checkfield(md, 'fieldname', 'hydrology.spcwatercolumn', 'Inf', 1, 'timeseries', 1) md = checkfield(md, 'fieldname', 'hydrology.stabilization', '>=', 0) - md = checkfield(md, 'fieldname', 'hydrology.requested_outputs', 'stringrow', 1) return md # }}} - def marshall(self, prefix, md, fid): # {{{ + def defaultoutputs(self, md): #{{{ + return ['Watercolumn', 'HydrologyWaterVx', 'HydrologyWaterVy'] + #}}} + + def marshall(self, prefix, md, fid): #{{{ WriteData(fid, prefix, 'name', 'md.hydrology.model', 'data', 2, 'format', 'Integer') WriteData(fid, prefix, 'object', self, 'fieldname', 'spcwatercolumn', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', md.constants.yts) WriteData(fid, prefix, 'object', self, 'fieldname', 'stabilization', 'format', 'Double') - #process requested outputs outputs = self.requested_outputs indices = [i for i, x in enumerate(outputs) if x == 'default'] - if len(indices) > 0: + if len(indices): outputscopy = outputs[0:max(0, indices[0] - 1)] + self.defaultoutputs(md) + outputs[indices[0] + 1:] outputs = outputscopy WriteData(fid, prefix, 'data', outputs, 'name', 'md.hydrology.requested_outputs', 'format', 'StringArray') + # }}} - # }}} + def extrude(self, md): #{{{ + return self + #}}} Index: ../trunk-jpl/src/m/classes/initialization.m =================================================================== --- ../trunk-jpl/src/m/classes/initialization.m (revision 26300) +++ ../trunk-jpl/src/m/classes/initialization.m (revision 26301) @@ -26,26 +26,6 @@ sample = NaN; end methods - function self = extrude(self,md) % {{{ - self.vx=project3d(md,'vector',self.vx,'type','node'); - self.vy=project3d(md,'vector',self.vy,'type','node'); - self.vz=project3d(md,'vector',self.vz,'type','node'); - self.vel=project3d(md,'vector',self.vel,'type','node'); - self.temperature=project3d(md,'vector',self.temperature,'type','node'); - self.enthalpy=project3d(md,'vector',self.enthalpy,'type','node'); - self.waterfraction=project3d(md,'vector',self.waterfraction,'type','node'); - self.watercolumn=project3d(md,'vector',self.watercolumn,'type','node','layer',1); - self.sediment_head=project3d(md,'vector',self.sediment_head,'type','node','layer',1); - self.epl_head=project3d(md,'vector',self.epl_head,'type','node','layer',1); - self.epl_thickness=project3d(md,'vector',self.epl_thickness,'type','node','layer',1); - self.sealevel=project3d(md,'vector',self.sealevel,'type','node','layer',1); - self.bottompressure=project3d(md,'vector',self.bottompressure,'type','node','layer',1); - self.dsl=project3d(md,'vector',self.dsl,'type','node','layer',1); - self.str=project3d(md,'vector',self.str,'type','node','layer',1); - - %Lithostatic pressure by default - self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z); - end % }}} function self = initialization(varargin) % {{{ switch nargin case 0 @@ -200,6 +180,26 @@ WriteData(fid,prefix,'data',enthalpy,'format','DoubleMat','mattype',1,'name','md.initialization.enthalpy'); end end % }}} + function self = extrude(self,md) % {{{ + self.vx=project3d(md,'vector',self.vx,'type','node'); + self.vy=project3d(md,'vector',self.vy,'type','node'); + self.vz=project3d(md,'vector',self.vz,'type','node'); + self.vel=project3d(md,'vector',self.vel,'type','node'); + self.temperature=project3d(md,'vector',self.temperature,'type','node'); + self.enthalpy=project3d(md,'vector',self.enthalpy,'type','node'); + self.waterfraction=project3d(md,'vector',self.waterfraction,'type','node'); + self.watercolumn=project3d(md,'vector',self.watercolumn,'type','node','layer',1); + self.sediment_head=project3d(md,'vector',self.sediment_head,'type','node','layer',1); + self.epl_head=project3d(md,'vector',self.epl_head,'type','node','layer',1); + self.epl_thickness=project3d(md,'vector',self.epl_thickness,'type','node','layer',1); + self.sealevel=project3d(md,'vector',self.sealevel,'type','node','layer',1); + self.bottompressure=project3d(md,'vector',self.bottompressure,'type','node','layer',1); + self.dsl=project3d(md,'vector',self.dsl,'type','node','layer',1); + self.str=project3d(md,'vector',self.str,'type','node','layer',1); + + %Lithostatic pressure by default + self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z); + end % }}} function savemodeljs(self,fid,modelname) % {{{ writejs1Darray(fid,[modelname '.initialization.vx'],self.vx); Index: ../trunk-jpl/src/m/classes/lovenumbers.m =================================================================== --- ../trunk-jpl/src/m/classes/lovenumbers.m (revision 26300) +++ ../trunk-jpl/src/m/classes/lovenumbers.m (revision 26301) @@ -15,14 +15,14 @@ l = []; %idem %tidal love numbers for computing rotational feedback: - th = []; - tk = []; - tl = []; - tk2secular = 0; %deg 2 secular number. + th = []; + tk = []; + tl = []; + tk2secular = 0; %deg 2 secular number. %time/frequency for visco-elastic love numbers timefreq = []; - istime = 1; + istime = 1; end methods @@ -32,8 +32,24 @@ referenceframe=getfieldvalue(options,'referenceframe','CM'); self=setdefaultparameters(self,maxdeg,referenceframe); end % }}} + function disp(self) % {{{ + disp(sprintf(' lovenumbers parameters:')); + + fielddisplay(self,'h','load Love number for radial displacement'); + fielddisplay(self,'k','load Love number for gravitational potential perturbation'); + fielddisplay(self,'l','load Love number for horizontal displacements'); + + fielddisplay(self,'th','tidal load Love number (deg 2)'); + fielddisplay(self,'tk','tidal load Love number (deg 2)'); + fielddisplay(self,'tl','tidal load Love number (deg 2)'); + fielddisplay(self,'tk2secular','secular fluid Love number'); + + fielddisplay(self,'istime','time (default: 1) or frequency love numbers (0)'); + fielddisplay(self,'timefreq','time/frequency vector (yr or 1/yr)'); + + end % }}} function self = setdefaultparameters(self,maxdeg,referenceframe) % {{{ - + %initialize love numbers: self.h=getlovenumbers('type','loadingverticaldisplacement','referenceframe',referenceframe,'maxdeg',maxdeg); self.k=getlovenumbers('type','loadinggravitationalpotential','referenceframe',referenceframe,'maxdeg',maxdeg); @@ -44,7 +60,7 @@ %secular fluid love number: self.tk2secular=0.942; - + %time: self.istime=1; %temporal love numbers by default self.timefreq=0; %elastic case by default. @@ -72,7 +88,7 @@ if (size(self.h,1)~=size(self.k,1) | size(self.h,1)~=size(self.l,1)), error('lovenumbers error message: love numbers should be provided at the same level of accuracy'); end - + ntf=length(self.timefreq); if( size(self.h,2) ~= ntf | size(self.k,2) ~= ntf | size(self.l,2) ~= ntf | size(self.th,2) ~= ntf | size(self.tk,2) ~= ntf | size(self.tl,2) ~= ntf ), error('lovenumbers error message: love numbers should have as many time/frequency steps as the time/frequency vector'); @@ -82,22 +98,6 @@ function list=defaultoutputs(self,md) % {{{ list = {}; end % }}} - function disp(self) % {{{ - disp(sprintf(' lovenumbers parameters:')); - - fielddisplay(self,'h','load Love number for radial displacement'); - fielddisplay(self,'k','load Love number for gravitational potential perturbation'); - fielddisplay(self,'l','load Love number for horizontal displacements'); - - fielddisplay(self,'th','tidal load Love number (deg 2)'); - fielddisplay(self,'tk','tidal load Love number (deg 2)'); - fielddisplay(self,'tl','tidal load Love number (deg 2)'); - fielddisplay(self,'tk2secular','secular fluid Love number'); - - fielddisplay(self,'istime','time (default=1) or frequency love numbers (0)'); - fielddisplay(self,'timefreq','time/frequency vector (yr or 1/yr)'); - - end % }}} function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','h','name','md.solidearth.lovenumbers.h','format','DoubleMat','mattype',1); Index: ../trunk-jpl/src/m/classes/materials.m =================================================================== --- ../trunk-jpl/src/m/classes/materials.m (revision 26300) +++ ../trunk-jpl/src/m/classes/materials.m (revision 26301) @@ -203,7 +203,7 @@ fielddisplay(self,'ebm_alpha','array describing each layer''s exponent parameter controlling the shape of shear modulus curve between taul and tauh, only for EBM rheology (numlayers)'); fielddisplay(self,'ebm_delta','array describing each layer''s amplitude of the transient relaxation (ratio between elastic rigity to pre-maxwell relaxation rigity), only for EBM rheology (numlayers)'); fielddisplay(self,'ebm_taul','array describing each layer''s starting period for transient relaxation, only for EBM rheology (numlayers) [s]'); - fielddisplay(self,'ebm_tauh','array describing each layer''s array describing each layer''s end period for transient relaxation, only for Burgers rheology (numlayers) [s]'); + fielddisplay(self,'ebm_tauh','array describing each layer''s array describing each layer''s end period for transient relaxation, only for Burgers rheology (numlayers) [s]'); fielddisplay(self,'rheologymodel','array describing whether we adopt a Maxwell (0), Burgers (1) or EBM (2) rheology (default: 0)'); @@ -255,7 +255,7 @@ if md.materials.rheologymodel(i)==1 & (isnan(md.materials.burgers_viscosity(i) | isnan(md.materials.burgers_mu(i)))), error('materials checkconsistency error message: Litho burgers_viscosity or burgers_mu has NaN values, inconsistent with rheologymodel choice'); end - if md.materials.rheologymodel(i)==2 & (isnan(md.materials.ebm_alpha(i)) | isnan(md.materials.ebm_delta(i)) | isnan(md.materials.ebm_taul(i)) | isnan(md.materials.ebm_tauh(i)) ), + if md.materials.rheologymodel(i)==2 & (isnan(md.materials.ebm_alpha(i)) | isnan(md.materials.ebm_delta(i)) | isnan(md.materials.ebm_taul(i)) | isnan(md.materials.ebm_tauh(i))), error('materials checkconsistency error message: Litho ebm_alpha, ebm_delta, ebm_taul or ebm_tauh has NaN values, inconsistent with rheologymodel choice'); end end @@ -283,7 +283,7 @@ %1: MatdamageiceEnum 2: MatestarEnum 3: MaticeEnum 4: MatenhancediceEnum 5: MaterialsEnum WriteData(fid,prefix,'name','md.materials.nature','data',naturetointeger(self.nature),'format','IntMat','mattype',3); - WriteData(fid,prefix,'name','md.materials.type','data',5,'format','Integer'); %DANGER, this can evolve if you have classes. + WriteData(fid,prefix,'name','md.materials.type','data',5,'format','Integer'); %DANGER: this can evolve if you have classes. for i=1:length(self.nature), nat=self.nature{i}; switch nat @@ -325,6 +325,7 @@ earth_density=earth_density + (self.radius(i+1)^3-self.radius(i)^3)*self.density(i); end earth_density=earth_density/self.radius(self.numlayers+1)^3; + disp(earth_density) self.earth_density=earth_density; case 'hydro' WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_ice','format','Double'); @@ -540,7 +541,7 @@ t4 = s(i,4)/((ra^3)*6.); vs = vs + t1*(r2^3) + t2*(r2^4) + t3*(r2^5) + t4*(r2^6) - ( t1*(r1^3) + t2*(r1^4) + t3*(r1^5) + t4*(r1^6) ); - end + end ro = ro*3 / (rad(j+1)^3-rad(j)^3); vp = vp*3 /(rad(j+1)^3-rad(j)^3); vs = vs*3 / (rad(j+1)^3-rad(j)^3); @@ -556,7 +557,6 @@ end end % }}} - end end @@ -583,5 +583,3 @@ end end end % }}} - - Index: ../trunk-jpl/src/m/classes/model.m =================================================================== --- ../trunk-jpl/src/m/classes/model.m (revision 26300) +++ ../trunk-jpl/src/m/classes/model.m (revision 26301) @@ -38,10 +38,10 @@ thermal = 0; steadystate = 0; transient = 0; - levelset = 0; + levelset = 0; calving = 0; frontalforcings = 0; - love = 0; + love = 0; esa = 0; sampling = 0; @@ -48,7 +48,7 @@ autodiff = 0; inversion = 0; qmu = 0; - amr = 0; + amr = 0; results = 0; outputdefinition = 0; radaroverlay = 0; @@ -206,6 +206,50 @@ end %}}} + function disp(self) % {{{ + disp(sprintf('%19s: %-22s -- %s','mesh' ,['[1x1 ' class(self.mesh) ']'],'mesh properties')); + disp(sprintf('%19s: %-22s -- %s','mask' ,['[1x1 ' class(self.mask) ']'],'defines grounded and floating elements')); + disp(sprintf('%19s: %-22s -- %s','geometry' ,['[1x1 ' class(self.geometry) ']'],'surface elevation, bedrock topography, ice thickness,...')); + disp(sprintf('%19s: %-22s -- %s','constants' ,['[1x1 ' class(self.constants) ']'],'physical constants')); + disp(sprintf('%19s: %-22s -- %s','smb' ,['[1x1 ' class(self.smb) ']'],'surface mass balance')); + disp(sprintf('%19s: %-22s -- %s','basalforcings' ,['[1x1 ' class(self.basalforcings) ']'],'bed forcings')); + disp(sprintf('%19s: %-22s -- %s','materials' ,['[1x1 ' class(self.materials) ']'],'material properties')); + disp(sprintf('%19s: %-22s -- %s','damage' ,['[1x1 ' class(self.damage) ']'],'parameters for damage evolution solution')); + disp(sprintf('%19s: %-22s -- %s','friction' ,['[1x1 ' class(self.friction) ']'],'basal friction/drag properties')); + disp(sprintf('%19s: %-22s -- %s','flowequation' ,['[1x1 ' class(self.flowequation) ']'],'flow equations')); + disp(sprintf('%19s: %-22s -- %s','timestepping' ,['[1x1 ' class(self.timestepping) ']'],'time stepping for transient models')); + disp(sprintf('%19s: %-22s -- %s','initialization' ,['[1x1 ' class(self.initialization) ']'],'initial guess/state')); + disp(sprintf('%19s: %-22s -- %s','rifts' ,['[1x1 ' class(self.rifts) ']'],'rifts properties')); + disp(sprintf('%19s: %-22s -- %s','solidearth' ,['[1x1 ' class(self.solidearth) ']'],'solidearth inputs and settings')); + disp(sprintf('%19s: %-22s -- %s','dsl' ,['[1x1 ' class(self.dsl) ']'],'dynamic sea-level ')); + disp(sprintf('%19s: %-22s -- %s','debug' ,['[1x1 ' class(self.debug) ']'],'debugging tools (valgrind, gprof)')); + disp(sprintf('%19s: %-22s -- %s','verbose' ,['[1x1 ' class(self.verbose) ']'],'verbosity level in solve')); + disp(sprintf('%19s: %-22s -- %s','settings' ,['[1x1 ' class(self.settings) ']'],'settings properties')); + disp(sprintf('%19s: %-22s -- %s','toolkits' ,['[1x1 ' class(self.toolkits) ']'],'PETSc options for each solution')); + disp(sprintf('%19s: %-22s -- %s','cluster' ,['[1x1 ' class(self.cluster) ']'],'cluster parameters (number of CPUs...)')); + disp(sprintf('%19s: %-22s -- %s','balancethickness',['[1x1 ' class(self.balancethickness) ']'],'parameters for balancethickness solution')); + disp(sprintf('%19s: %-22s -- %s','stressbalance' ,['[1x1 ' class(self.stressbalance) ']'],'parameters for stressbalance solution')); + disp(sprintf('%19s: %-22s -- %s','groundingline' ,['[1x1 ' class(self.groundingline) ']'],'parameters for groundingline solution')); + disp(sprintf('%19s: %-22s -- %s','hydrology' ,['[1x1 ' class(self.hydrology) ']'],'parameters for hydrology solution')); + disp(sprintf('%19s: %-22s -- %s','masstransport' ,['[1x1 ' class(self.masstransport) ']'],'parameters for masstransport solution')); + disp(sprintf('%19s: %-22s -- %s','thermal' ,['[1x1 ' class(self.thermal) ']'],'parameters for thermal solution')); + disp(sprintf('%19s: %-22s -- %s','steadystate' ,['[1x1 ' class(self.steadystate) ']'],'parameters for steadystate solution')); + disp(sprintf('%19s: %-22s -- %s','transient' ,['[1x1 ' class(self.transient) ']'],'parHwoameters for transient solution')); + disp(sprintf('%19s: %-22s -- %s','levelset' ,['[1x1 ' class(self.levelset) ']'],'parameters for moving boundaries (level-set method)')); + disp(sprintf('%19s: %-22s -- %s','calving' ,['[1x1 ' class(self.calving) ']'],'parameters for calving')); + disp(sprintf('%19s: %-22s -- %s','frontalforcings' ,['[1x1 ' class(self.frontalforcings) ']'],'parameters for frontalforcings')); + disp(sprintf('%19s: %-22s -- %s','esa' ,['[1x1 ' class(self.esa) ']'],'parameters for elastic adjustment solution')); + disp(sprintf('%19s: %-22s -- %s','love' ,['[1x1 ' class(self.love) ']'],'parameters for love solution')); + disp(sprintf('%19s: %-22s -- %s','sampling' ,['[1x1 ' class(self.sampling) ']'],'parameters for stochastic sampler')); + disp(sprintf('%19s: %-22s -- %s','autodiff' ,['[1x1 ' class(self.autodiff) ']'],'automatic differentiation parameters')); + disp(sprintf('%19s: %-22s -- %s','inversion' ,['[1x1 ' class(self.inversion) ']'],'parameters for inverse methods')); + disp(sprintf('%19s: %-22s -- %s','qmu' ,['[1x1 ' class(self.qmu) ']'],'Dakota properties')); + disp(sprintf('%19s: %-22s -- %s','amr' ,['[1x1 ' class(self.amr) ']'],'adaptive mesh refinement properties')); + disp(sprintf('%19s: %-22s -- %s','outputdefinition',['[1x1 ' class(self.outputdefinition) ']'],'output definition')); + disp(sprintf('%19s: %-22s -- %s','results' ,['[1x1 ' class(self.results) ']'],'model results')); + disp(sprintf('%19s: %-22s -- %s','radaroverlay' ,['[1x1 ' class(self.radaroverlay) ']'],'radar image for plot overlay')); + disp(sprintf('%19s: %-22s -- %s','miscellaneous' ,['[1x1 ' class(self.miscellaneous) ']'],'miscellaneous fields')); + end % }}} function md = setdefaultparameters(md,planet) % {{{ %initialize subclasses @@ -1132,7 +1176,7 @@ if md.mesh.average_vertex_connectivity<=25, md.mesh.average_vertex_connectivity=100; end - end % }}} + end % }}} function md = structtomodel(md,structmd) % {{{ if ~isstruct(structmd) error('input model is not a structure'); end @@ -1583,97 +1627,54 @@ md.mesh.average_vertex_connectivity=100; end end % }}} - function disp(self) % {{{ - disp(sprintf('%19s: %-22s -- %s','mesh' ,['[1x1 ' class(self.mesh) ']'],'mesh properties')); - disp(sprintf('%19s: %-22s -- %s','mask' ,['[1x1 ' class(self.mask) ']'],'defines grounded and floating elements')); - disp(sprintf('%19s: %-22s -- %s','geometry' ,['[1x1 ' class(self.geometry) ']'],'surface elevation, bedrock topography, ice thickness,...')); - disp(sprintf('%19s: %-22s -- %s','constants' ,['[1x1 ' class(self.constants) ']'],'physical constants')); - disp(sprintf('%19s: %-22s -- %s','smb' ,['[1x1 ' class(self.smb) ']'],'surface mass balance')); - disp(sprintf('%19s: %-22s -- %s','basalforcings' ,['[1x1 ' class(self.basalforcings) ']'],'bed forcings')); - disp(sprintf('%19s: %-22s -- %s','materials' ,['[1x1 ' class(self.materials) ']'],'material properties')); - disp(sprintf('%19s: %-22s -- %s','damage' ,['[1x1 ' class(self.damage) ']'],'parameters for damage evolution solution')); - disp(sprintf('%19s: %-22s -- %s','friction' ,['[1x1 ' class(self.friction) ']'],'basal friction/drag properties')); - disp(sprintf('%19s: %-22s -- %s','flowequation' ,['[1x1 ' class(self.flowequation) ']'],'flow equations')); - disp(sprintf('%19s: %-22s -- %s','timestepping' ,['[1x1 ' class(self.timestepping) ']'],'time stepping for transient models')); - disp(sprintf('%19s: %-22s -- %s','initialization' ,['[1x1 ' class(self.initialization) ']'],'initial guess/state')); - disp(sprintf('%19s: %-22s -- %s','rifts' ,['[1x1 ' class(self.rifts) ']'],'rifts properties')); - disp(sprintf('%19s: %-22s -- %s','solidearth' ,['[1x1 ' class(self.solidearth) ']'],'solidearth inputs and settings')); - disp(sprintf('%19s: %-22s -- %s','dsl' ,['[1x1 ' class(self.dsl) ']'],'dynamic sea-level ')); - disp(sprintf('%19s: %-22s -- %s','debug' ,['[1x1 ' class(self.debug) ']'],'debugging tools (valgrind, gprof)')); - disp(sprintf('%19s: %-22s -- %s','verbose' ,['[1x1 ' class(self.verbose) ']'],'verbosity level in solve')); - disp(sprintf('%19s: %-22s -- %s','settings' ,['[1x1 ' class(self.settings) ']'],'settings properties')); - disp(sprintf('%19s: %-22s -- %s','toolkits' ,['[1x1 ' class(self.toolkits) ']'],'PETSc options for each solution')); - disp(sprintf('%19s: %-22s -- %s','cluster' ,['[1x1 ' class(self.cluster) ']'],'cluster parameters (number of CPUs...)')); - disp(sprintf('%19s: %-22s -- %s','balancethickness',['[1x1 ' class(self.balancethickness) ']'],'parameters for balancethickness solution')); - disp(sprintf('%19s: %-22s -- %s','stressbalance' ,['[1x1 ' class(self.stressbalance) ']'],'parameters for stressbalance solution')); - disp(sprintf('%19s: %-22s -- %s','groundingline' ,['[1x1 ' class(self.groundingline) ']'],'parameters for groundingline solution')); - disp(sprintf('%19s: %-22s -- %s','hydrology' ,['[1x1 ' class(self.hydrology) ']'],'parameters for hydrology solution')); - disp(sprintf('%19s: %-22s -- %s','masstransport' ,['[1x1 ' class(self.masstransport) ']'],'parameters for masstransport solution')); - disp(sprintf('%19s: %-22s -- %s','thermal' ,['[1x1 ' class(self.thermal) ']'],'parameters for thermal solution')); - disp(sprintf('%19s: %-22s -- %s','steadystate' ,['[1x1 ' class(self.steadystate) ']'],'parameters for steadystate solution')); - disp(sprintf('%19s: %-22s -- %s','transient' ,['[1x1 ' class(self.transient) ']'],'parHwoameters for transient solution')); - disp(sprintf('%19s: %-22s -- %s','levelset' ,['[1x1 ' class(self.levelset) ']'],'parameters for moving boundaries (level-set method)')); - disp(sprintf('%19s: %-22s -- %s','calving' ,['[1x1 ' class(self.calving) ']'],'parameters for calving')); - disp(sprintf('%19s: %-22s -- %s','frontalforcings' ,['[1x1 ' class(self.frontalforcings) ']'],'parameters for frontalforcings')); - disp(sprintf('%19s: %-22s -- %s','esa' ,['[1x1 ' class(self.esa) ']'],'parameters for elastic adjustment solution')); - disp(sprintf('%19s: %-22s -- %s','love' ,['[1x1 ' class(self.love) ']'],'parameters for love solution')); - disp(sprintf('%19s: %-22s -- %s','sampling' ,['[1x1 ' class(self.sampling) ']'],'parameters for stochastic sampler')); - disp(sprintf('%19s: %-22s -- %s','autodiff' ,['[1x1 ' class(self.autodiff) ']'],'automatic differentiation parameters')); - disp(sprintf('%19s: %-22s -- %s','inversion' ,['[1x1 ' class(self.inversion) ']'],'parameters for inverse methods')); - disp(sprintf('%19s: %-22s -- %s','qmu' ,['[1x1 ' class(self.qmu) ']'],'Dakota properties')); - disp(sprintf('%19s: %-22s -- %s','amr' ,['[1x1 ' class(self.amr) ']'],'adaptive mesh refinement properties')); - disp(sprintf('%19s: %-22s -- %s','outputdefinition',['[1x1 ' class(self.outputdefinition) ']'],'output definition')); - disp(sprintf('%19s: %-22s -- %s','results' ,['[1x1 ' class(self.results) ']'],'model results')); - disp(sprintf('%19s: %-22s -- %s','radaroverlay' ,['[1x1 ' class(self.radaroverlay) ']'],'radar image for plot overlay')); - disp(sprintf('%19s: %-22s -- %s','miscellaneous' ,['[1x1 ' class(self.miscellaneous) ']'],'miscellaneous fields')); - end % }}} function memory(self) % {{{ - disp(sprintf('\nMemory imprint:\n')); + disp(sprintf('\nMemory imprint:\n')); - fields=properties('model'); - mem=0; + fields=properties('model'); + mem=0; - for i=1:length(fields), - field=self.(fields{i}); - s=whos('field'); - mem=mem+s.bytes/1e6; - disp(sprintf('%19s: %6.2f Mb',fields{i},s.bytes/1e6)); + for i=1:length(fields), + field=self.(fields{i}); + s=whos('field'); + mem=mem+s.bytes/1e6; + disp(sprintf('%19s: %6.2f Mb',fields{i},s.bytes/1e6)); + end + disp(sprintf('%19s--%10s','--------------','--------------')); + disp(sprintf('%19s: %g Mb','Total',mem)); end - disp(sprintf('%19s--%10s','--------------','--------------')); - disp(sprintf('%19s: %g Mb','Total',mem)); - end % }}} + % }}} function netcdf(self,filename) % {{{ - %NETCDF - save model as netcdf - % - % Usage: - % netcdf(md,filename) - % - % Example: - % netcdf(md,'model.nc'); + %NETCDF - save model as netcdf + % + % Usage: + % netcdf(md,filename) + % + % Example: + % netcdf(md,'model.nc'); - disp('Saving model as NetCDF'); - %1. Create NetCDF file - ncid=netcdf.create(filename,'CLOBBER'); - netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Conventions','CF-1.4'); - netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Title',['ISSM model (' self.miscellaneous.name ')']); - netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Author',getenv('USER')); - netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Date',datestr(now)); + disp('Saving model as NetCDF'); + %1. Create NetCDF file + ncid=netcdf.create(filename,'CLOBBER'); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Conventions','CF-1.4'); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Title',['ISSM model (' self.miscellaneous.name ')']); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Author',getenv('USER')); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Date',datestr(now)); - %Preallocate variable id, needed to write variables in netcdf file - var_id=zeros(1000,1);%preallocate + %Preallocate variable id, needed to write variables in netcdf file + var_id=zeros(1000,1);%preallocate - for step=1:2, - counter=0; - [var_id,counter]=structtonc(ncid,'md',self,0,var_id,counter,step); - if step==1, netcdf.endDef(ncid); end - end + for step=1:2, + counter=0; + [var_id,counter]=structtonc(ncid,'md',self,0,var_id,counter,step); + if step==1, netcdf.endDef(ncid); end + end - if counter>1000, - warning(['preallocation of var_id need to be updated from ' num2str(1000) ' to ' num2str(counter)]); - end + if counter>1000, + warning(['preallocation of var_id need to be updated from ' num2str(1000) ' to ' num2str(counter)]); + end - netcdf.close(ncid) + netcdf.close(ncid) end % }}} function xylim(self) % {{{ @@ -1681,40 +1682,40 @@ ylim([min(self.mesh.y) max(self.mesh.y)]) end % }}} function md=upload(md) % {{{ - %the goal of this routine is to upload the model onto a server, and to empty it. - %So first, save the model with a unique name and upload the file to the server: - random_part=fix(rand(1)*10000); - id=[md.miscellaneous.name '-' regexprep(datestr(now),'[^\w'']','') '-' num2str(random_part) '-' getenv('USER') '-' oshostname() '.upload']; - eval(['save ' id ' md']); + %the goal of this routine is to upload the model onto a server, and to empty it. + %So first, save the model with a unique name and upload the file to the server: + random_part=fix(rand(1)*10000); + id=[md.miscellaneous.name '-' regexprep(datestr(now),'[^\w'']','') '-' num2str(random_part) '-' getenv('USER') '-' oshostname() '.upload']; + eval(['save ' id ' md']); - %Now, upload the file: - issmscpout(md.settings.upload_server,md.settings.upload_path,md.settings.upload_login,md.settings.upload_port,{id},1); + %Now, upload the file: + issmscpout(md.settings.upload_server,md.settings.upload_path,md.settings.upload_login,md.settings.upload_port,{id},1); - %Now, empty this model of everything except settings, and record name of file we just uploaded! - settings_back=md.settings; - md=model(); - md.settings=settings_back; - md.settings.upload_filename=id; + %Now, empty this model of everything except settings, and record name of file we just uploaded! + settings_back=md.settings; + md=model(); + md.settings=settings_back; + md.settings.upload_filename=id; - %get locally rid of file that was uploaded - eval(['delete ' id]); + %get locally rid of file that was uploaded + eval(['delete ' id]); end % }}} function md=download(md) % {{{ - %the goal of this routine is to download the internals of the current model from a server, because - %this model is empty, except for the settings which tell us where to go and find this model! + %the goal of this routine is to download the internals of the current model from a server, because + %this model is empty, except for the settings which tell us where to go and find this model! - %Download the file: - issmscpin(md.settings.upload_server, md.settings.upload_login, md.settings.upload_port, md.settings.upload_path, {md.settings.upload_filename}); + %Download the file: + issmscpin(md.settings.upload_server, md.settings.upload_login, md.settings.upload_port, md.settings.upload_path, {md.settings.upload_filename}); - name=md.settings.upload_filename; + name=md.settings.upload_filename; - %Now, load this model: - md=loadmodel(md.settings.upload_filename); + %Now, load this model: + md=loadmodel(md.settings.upload_filename); - %get locally rid of file that was downloaded - eval(['delete ' name]); + %get locally rid of file that was downloaded + eval(['delete ' name]); end % }}} function savemodeljs(md,modelname,websiteroot,varargin) % {{{ Index: ../trunk-jpl/src/m/classes/model.py =================================================================== --- ../trunk-jpl/src/m/classes/model.py (revision 26300) +++ ../trunk-jpl/src/m/classes/model.py (revision 26301) @@ -75,31 +75,39 @@ class model(object): - #properties + """MODEL - class definition + + Usage: + md = model() + """ + def __init__(self, *args): #{{{ self.mesh = None self.mask = None + + self.geometry = None self.constants = None - self.geometry = None - self.initialization = None self.smb = None self.basalforcings = None + self.materials = None + self.damage = None self.friction = None + self.flowequation = None + self.timestepping = None + self.initialization = None self.rifts = None + self.dsl = None self.solidearth = None - self.dsl = None - self.timestepping = None - self.groundingline = None - self.materials = None - self.damage = None - self.flowequation = None + self.debug = None self.verbose = None self.settings = None self.toolkits = None self.cluster = None + self.balancethickness = None self.stressbalance = None + self.groundingline = None self.hydrology = None self.masstransport = None self.thermal = None @@ -111,81 +119,30 @@ self.love = None self.esa = None self.sampling = None + self.autodiff = None self.inversion = None self.qmu = None self.amr = None - self.radaroverlay = None self.results = None self.outputdefinition = None + self.radaroverlay = None self.miscellaneous = None self.private = None - nargs = len(args) - - if nargs == 0: + if len(args) == 0: self.setdefaultparameters('earth') else: - self.setdefaultparameters(args[0]) options = pairoptions(*args) planet = options.getfieldvalue('planet', 'earth') self.setdefaultparameters(planet) -#}}} + #}}} - def properties(self): # {{{ - # ordered list of properties since vars(self) is random - return ['mesh', - 'mask', - 'constants', - 'geometry', - 'initialization', - 'smb', - 'basalforcings', - 'friction', - 'rifts', - 'solidearth', - 'dsl', - 'timestepping', - 'groundingline', - 'materials', - 'damage', - 'flowequation', - 'debug', - 'verbose', - 'settings', - 'toolkits', - 'cluster', - 'balancethickness', - 'stressbalance', - 'hydrology', - 'masstransport', - 'thermal', - 'steadystate', - 'transient', - 'levelset', - 'calving', - 'frontalforcings', - 'love', - 'esa', - 'sampling', - 'autodiff', - 'inversion', - 'qmu', - 'amr', - 'radaroverlay', - 'results', - 'outputdefinition', - 'miscellaneous', - 'private'] - # }}} - def __repr__(obj): #{{{ # TODO: # - Convert all formatting to calls to .format (see any # already converted .__repr__ method for examples) # - - #print "Here %s the number: %d" % ("is", 37) s = "%19s: %-22s -- %s" % ("mesh", "[%s %s]" % ("1x1", obj.mesh.__class__.__name__), "mesh properties") s = "%s\n%s" % (s, "%19s: %-22s -- %s" % ("mask", "[%s %s]" % ("1x1", obj.mask.__class__.__name__), "defines grounded and floating elements")) s = "%s\n%s" % (s, "%19s: %-22s -- %s" % ("geometry", "[%s %s]" % ("1x1", obj.geometry.__class__.__name__), "surface elevation, bedrock topography, ice thickness, ...")) @@ -229,8 +186,55 @@ s = "%s\n%s" % (s, "%19s: %-22s -- %s" % ("radaroverlay", "[%s %s]" % ("1x1", obj.radaroverlay.__class__.__name__), "radar image for plot overlay")) s = "%s\n%s" % (s, "%19s: %-22s -- %s" % ("miscellaneous", "[%s %s]" % ("1x1", obj.miscellaneous.__class__.__name__), "miscellaneous fields")) return s - # }}} + #}}} + def properties(self): #{{{ + # ordered list of properties since vars(self) is random + return ['mesh', + 'mask', + 'geometry', + 'constants', + 'smb', + 'basalforcings', + 'materials', + 'damage', + 'friction', + 'flowequation', + 'timestepping', + 'initialization', + 'rifts', + 'dsl', + 'solidearth', + 'debug', + 'verbose', + 'settings', + 'toolkits', + 'cluster', + 'balancethickness', + 'stressbalance', + 'groundingline', + 'hydrology', + 'masstransport', + 'thermal', + 'steadystate', + 'transient', + 'levelset', + 'calving', + 'frontalforcings', + 'love', + 'esa', + 'sampling', + 'autodiff', + 'inversion', + 'qmu', + 'amr', + 'results', + 'outputdefinition', + 'radaroverlay', + 'miscellaneous', + 'private'] + #}}} + def setdefaultparameters(self, planet): #{{{ self.mesh = mesh2d() self.mask = mask() @@ -277,14 +281,14 @@ self.private = private() #}}} - def checkmessage(self, string): # {{{ + def checkmessage(self, string): #{{{ print("model not consistent: {}".format(string)) self.private.isconsistent = False return self - # }}} + #}}} #@staticmethod - def extract(self, area): # {{{ + def extract(self, area): #{{{ """EXTRACT - extract a model according to an Argus contour or flag list This routine extracts a submodel from a bigger model with respect to a given contour @@ -561,9 +565,9 @@ md2.mesh.extractedelements = pos_elem + 1 return md2 - # }}} + #}}} - def extrude(md, *args): # {{{ + def extrude(md, *args): #{{{ """EXTRUDE - vertically extrude a 2d mesh vertically extrude a 2d mesh and create corresponding 3d mesh. @@ -748,7 +752,7 @@ md.mesh.average_vertex_connectivity = 100 return md - # }}} + #}}} def collapse(md): #{{{ """COLLAPSE - collapses a 3d mesh into a 2d mesh Index: ../trunk-jpl/src/m/classes/sampling.m =================================================================== --- ../trunk-jpl/src/m/classes/sampling.m (revision 26300) +++ ../trunk-jpl/src/m/classes/sampling.m (revision 26301) @@ -5,107 +5,98 @@ classdef sampling properties (SetAccess=public) - kappa = NaN; - tau = 0; - beta = NaN; - phi = 0; - alpha = 0; - robin = 0; - seed = 0; - requested_outputs = {}; - end + kappa = NaN; + tau = 0; + beta = NaN; + phi = 0; + alpha = 0; + robin = 0; + seed = 0; + requested_outputs = {}; + end methods function self = sampling(varargin) % {{{ - switch nargin + switch nargin case 0 self=setdefaultparameters(self); otherwise error('constructor not supported'); - end + end end % }}} - function list = defaultoutputs(self,md) % {{{ + function disp(self) % {{{ - list = {}; + disp(sprintf(' Sampling parameters:')); - end % }}} + disp(sprintf('\n %s','Parameters of PDE operator (kappa^2 I-Laplacian)^(alpha/2)(tau):')); + fielddisplay(self,'kappa','coefficient of the identity operator'); + fielddisplay(self,'tau','scaling coefficient of the solution (default: 1.0)'); + fielddisplay(self,'alpha','exponent in PDE operator, (default: 2.0, BiLaplacian covariance operator)'); + + disp(sprintf('\n %s','Parameters of Robin boundary conditions nabla () \cdot normvec + beta ():')); + fielddisplay(self,'robin','Apply Robin boundary conditions (1 if applied and 0 for homogenous Neumann boundary conditions) (default: 0)'); + fielddisplay(self,'beta','Coefficient in Robin boundary conditions (to be defined for robin = 1)'); + + disp(sprintf('\n %s','Parameters for first-order autoregressive process (X_t = phi X_{t-1} + noise) (if transient):')); + fielddisplay(self,'phi','Temporal correlation factor (|phi|<1 for stationary process, phi = 1 for random walk process) (default 0)'); + + disp(sprintf('\n %s','Other parameters of stochastic sampler:')); + fielddisplay(self,'seed','Seed for pseudorandom number generator (given seed if >=0 and random seed if <0) (default: -1)'); + fielddisplay(self,'requested_outputs','additional outputs requested (not implemented yet)'); + + end % }}}',' function self = setdefaultparameters(self) % {{{ - - %Scaling coefficient - self.tau=1; - %Apply Robin boundary conditions - self.robin=0; - - %Temporal correlation factor - self.phi=0; - - %Exponent in fraction SPDE (default=2, biLaplacian covariance + %Scaling coefficient + self.tau=1; + + %Apply Robin boundary conditions + self.robin=0; + + %Temporal correlation factor + self.phi=0; + + %Exponent in fraction SPDE (default: 2, biLaplacian covariance %operator) self.alpha=2; % Default - - %Seed for pseudorandom number generator (default -1 for random seed) - self.seed=-1; - + + %Seed for pseudorandom number generator (default: -1, for random seed) + self.seed=-1; + %default output self.requested_outputs={'default'}; end % }}} - function md = setparameters(self,md,lc,sigma) % {{{ - - nu = self.alpha-1; - KAPPA = sqrt(8*nu)/lc; - TAU = sqrt(gamma(nu)/(gamma(self.alpha)*(4*pi)*KAPPA^(2*nu)*sigma^2)); - md.sampling.kappa = KAPPA*ones(md.mesh.numberofvertices,1); - md.sampling.tau = TAU; - + function list = defaultoutputs(self,md) % {{{ + + list = {}; + end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - - if ~ismember('SamplingAnalysis',analyses), return; end - - md = checkfield(md,'fieldname','sampling.kappa','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1],'>',0); - md = checkfield(md,'fieldname','sampling.tau','NaN',1,'Inf',1,'numel',1,'>',0); - md = checkfield(md,'fieldname','sampling.robin','numel',1,'values',[0 1]); - if(md.sampling.robin) - md = checkfield(md,'fieldname','sampling.beta','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1],'>',0); - end - md = checkfield(md,'fieldname','sampling.phi','NaN',1,'Inf',1,'numel',1,'>=',0); - md = checkfield(md,'fieldname','sampling.alpha','NaN',1,'Inf',1,'numel',1,'>',0); - md = checkfield(md,'fieldname','sampling.seed','NaN',1,'Inf',1,'numel',1); - md = checkfield(md,'fieldname','sampling.requested_outputs','stringrow',1); - end % }}} - function disp(self) % {{{ + if ~ismember('SamplingAnalysis',analyses), return; end - disp(sprintf(' Sampling parameters:')); + md = checkfield(md,'fieldname','sampling.kappa','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1],'>',0); + md = checkfield(md,'fieldname','sampling.tau','NaN',1,'Inf',1,'numel',1,'>',0); + md = checkfield(md,'fieldname','sampling.robin','numel',1,'values',[0 1]); + if(md.sampling.robin) + md = checkfield(md,'fieldname','sampling.beta','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1],'>',0); + end + md = checkfield(md,'fieldname','sampling.phi','NaN',1,'Inf',1,'numel',1,'>=',0); + md = checkfield(md,'fieldname','sampling.alpha','NaN',1,'Inf',1,'numel',1,'>',0); + md = checkfield(md,'fieldname','sampling.seed','NaN',1,'Inf',1,'numel',1); + md = checkfield(md,'fieldname','sampling.requested_outputs','stringrow',1); - disp(sprintf('\n %s','Parameters of PDE operator (kappa^2 I-Laplacian)^(alpha/2)(tau):')); - fielddisplay(self,'kappa','coefficient of the identity operator'); - fielddisplay(self,'tau','scaling coefficient of the solution (default 1.0)'); - fielddisplay(self,'alpha','exponent in PDE operator, (default 2.0, BiLaplacian covariance operator)'); - - disp(sprintf('\n %s','Parameters of Robin boundary conditions nabla () \cdot normvec + beta ():')); - fielddisplay(self,'robin','Apply Robin boundary conditions (1 if applied and 0 for homogenous Neumann boundary conditions) (default 0)'); - fielddisplay(self,'beta','Coefficient in Robin boundary conditions (to be defined for robin = 1)'); - - disp(sprintf('\n %s','Parameters for first-order autoregressive process (X_t = phi X_{t-1} + noise) (if transient):')); - fielddisplay(self,'phi','Temporal correlation factor (|phi|<1 for stationary process, phi = 1 for random walk process) (default 0)'); - - disp(sprintf('\n %s','Other parameters of stochastic sampler:')); - fielddisplay(self,'seed','Seed for pseudorandom number generator (given seed if >=0 and random seed if <0) (default -1)'); - fielddisplay(self,'requested_outputs','additional outputs requested (not implemented yet)'); - end % }}} function marshall(self,prefix,md,fid) % {{{ - WriteData(fid,prefix,'object',self,'fieldname','kappa','format','DoubleMat','mattype',1); - WriteData(fid,prefix,'object',self,'fieldname','tau','format','Double'); - WriteData(fid,prefix,'object',self,'fieldname','beta','format','DoubleMat','mattype',1); - WriteData(fid,prefix,'object',self,'fieldname','phi','format','Double'); - WriteData(fid,prefix,'object',self,'fieldname','alpha','format','Integer'); - WriteData(fid,prefix,'object',self,'fieldname','robin','format','Boolean'); - WriteData(fid,prefix,'object',self,'fieldname','seed','format','Integer'); - + WriteData(fid,prefix,'object',self,'fieldname','kappa','format','DoubleMat','mattype',1); + WriteData(fid,prefix,'object',self,'fieldname','tau','format','Double'); + WriteData(fid,prefix,'object',self,'fieldname','beta','format','DoubleMat','mattype',1); + WriteData(fid,prefix,'object',self,'fieldname','phi','format','Double'); + WriteData(fid,prefix,'object',self,'fieldname','alpha','format','Integer'); + WriteData(fid,prefix,'object',self,'fieldname','robin','format','Boolean'); + WriteData(fid,prefix,'object',self,'fieldname','seed','format','Integer'); + %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); @@ -115,17 +106,26 @@ end WriteData(fid,prefix,'data',outputs,'name','md.sampling.requested_outputs','format','StringArray'); end % }}} + function md = setparameters(self,md,lc,sigma) % {{{ + + nu = self.alpha-1; + KAPPA = sqrt(8*nu)/lc; + TAU = sqrt(gamma(nu)/(gamma(self.alpha)*(4*pi)*KAPPA^(2*nu)*sigma^2)); + md.sampling.kappa = KAPPA*ones(md.mesh.numberofvertices,1); + md.sampling.tau = TAU; + + end % }}} function savemodeljs(self,fid,modelname) % {{{ - - writejsdouble(fid,[modelname '.sampling.kappa'],self.kappa); - writejsdouble(fid,[modelname '.sampling.tau'],self.tau); - writejsdouble(fid,[modelname '.sampling.beta'],self.beta); - writejsdouble(fid,[modelname '.sampling.phi'],self.beta); - writejsdouble(fid,[modelname '.sampling.alpha'],self.alpha); - writejsdouble(fid,[modelname '.sampling.robin'],self.robin); - writejsdouble(fid,[modelname '.sampling.seed'],self.seed); + + writejsdouble(fid,[modelname '.sampling.kappa'],self.kappa); + writejsdouble(fid,[modelname '.sampling.tau'],self.tau); + writejsdouble(fid,[modelname '.sampling.beta'],self.beta); + writejsdouble(fid,[modelname '.sampling.phi'],self.beta); + writejsdouble(fid,[modelname '.sampling.alpha'],self.alpha); + writejsdouble(fid,[modelname '.sampling.robin'],self.robin); + writejsdouble(fid,[modelname '.sampling.seed'],self.seed); writejscellstring(fid,[modelname '.sampling.requested_outputs'],self.requested_outputs); end % }}} end -end \ No newline at end of file +end Index: ../trunk-jpl/src/m/classes/sampling.py =================================================================== --- ../trunk-jpl/src/m/classes/sampling.py (revision 26300) +++ ../trunk-jpl/src/m/classes/sampling.py (revision 26301) @@ -1,5 +1,7 @@ import numpy as np +from math import * + from checkfield import checkfield from fielddisplay import fielddisplay from project3d import project3d @@ -13,11 +15,10 @@ sampling = sampling() """ - def __init__(self): # {{{ - self.kappa = float('NaN') + def __init__(self, *args): #{{{ + self.kappa = np.nan self.tau = 0 - self.beta = float('NaN') - self.hydrostatic_adjustment = 0 + self.beta = np.nan self.phi = 0 self.alpha = 0 self.robin = 0 @@ -24,72 +25,87 @@ self.seed = 0 self.requested_outputs = [] - # Set defaults - self.setdefaultparameters() - + if len(args) == 0: + self.setdefaultparameters() + else: + raise RuntimeError('constructor not supported') #}}} - def __repr__(self): # {{{ + def __repr__(self): #{{{ s = ' Sampling parameters::\n' - s += '{}\n'.format(fielddisplay(self,'kappa','coefficient of the identity operator')) - s += '{}\n'.format(fielddisplay(self,'tau','scaling coefficient of the solution (default 1.0)')) - s += '{}\n'.format(fielddisplay(self,'alpha','exponent in PDE operator, (default 2.0, BiLaplacian covariance operator)')) - s += '{}\n'.format(disp(sprintf('\n %s','Parameters of Robin boundary conditions nabla () \cdot normvec + beta ():'))) - s += '{}\n'.format(fielddisplay(self,'beta','Coefficient in Robin boundary conditions (to be defined for robin = 1)')) - s += '{}\n'.format(fielddisplay(self,'phi','Temporal correlation factor (|phi|<1 for stationary process, phi = 1 for random walk process) (default 0)')) - s += '{}\n'.format(fielddisplay(self,'seed','Seed for pseudorandom number generator (given seed if >=0 and random seed if <0) (default -1)')) + s += ' Parameters of PDE operator (kappa^2 I-Laplacian)^(alpha/2)(tau):\n' + s += '{}\n'.format(fielddisplay(self, 'kappa', 'coefficient of the identity operator')) + s += '{}\n'.format(fielddisplay(self, 'tau', 'scaling coefficient of the solution (default: 1.0)')) + s += '{}\n'.format(fielddisplay(self, 'alpha', 'exponent in PDE operator, (default: 2.0, BiLaplacian covariance operator)')) + + s += ' Parameters of Robin boundary conditions nabla () \cdot normvec + beta ():\n' + s += '{}\n'.format(fielddisplay(self, 'robin', 'Apply Robin boundary conditions (1 if applied and 0 for homogenous Neumann boundary conditions) (default: 0)')) + s += '{}\n'.format(fielddisplay(self, 'beta', 'Coefficient in Robin boundary conditions (to be defined for robin = 1)')) + + s += ' Parameters for first-order autoregressive process (X_t = phi X_{t-1} + noise) (if transient):\n' + s += '{}\n'.format(fielddisplay(self, 'phi', 'Temporal correlation factor (|phi|<1 for stationary process, phi = 1 for random walk process) (default 0)')) + + s += ' Other parameters of stochastic sampler:\n' + s += '{}\n'.format(fielddisplay(self, 'seed', 'Seed for pseudorandom number generator (given seed if >=0 and random seed if <0) (default: -1)')) s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested (not implemented yet)')) + return s #}}} - def defaultoutputs(self, md): # {{{ - return [] - - #}}} - def setdefaultparameters(self): # {{{ + def setdefaultparameters(self): #{{{ # Scaling coefficient self.tau = 1 + # Apply Robin boundary conditions self.robin = 0 + # Temporal correlation factor self.phi = 0 - # Exponent in fraction SPDE (default=2, biLaplacian covariance operator) + + # Exponent in fraction SPDE (default: 2, biLaplacian covariance operator) self.alpha = 2 - # Seed for pseudorandom number generator (default -1 for random seed) - self.alpha = -1 + + # Seed for pseudorandom number generator (default: -1, for random seed) + self.seed = -1 + # Default output self.requested_outputs = ['default'] + return self #}}} - def checkconsistency(self, md, solution, analyses): # {{{ - # Early return + def defaultoutputs(self, md): #{{{ + return [] + #}}} + + def checkconsistency(self, md, solution, analyses): #{{{ if ('SamplingAnalysis' not in analyses): return md - md = checkfield(md,'fieldname','sampling.kappa','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices],'>',0) - md = checkfield(md,'fieldname','sampling.tau','NaN',1,'Inf',1,'numel',1,'>',0) - md = checkfield(md,'fieldname','sampling.robin','numel',1,'values',[0, 1]) + md = checkfield(md, 'fieldname', 'sampling.kappa', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices], '>', 0) + md = checkfield(md, 'fieldname', 'sampling.tau', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'sampling.robin', 'numel', 1, 'values', [0, 1]) if md.sampling.robin: - md = checkfield(md,'fieldname','sampling.beta','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices],'>',0) - md = checkfield(md,'fieldname','sampling.phi','NaN',1,'Inf',1,'numel',1,'>=',0) - md = checkfield(md,'fieldname','sampling.alpha','NaN',1,'Inf',1,'numel',1,'>',0) - md = checkfield(md,'fieldname','sampling.seed','NaN',1,'Inf',1,'numel',1) - md = checkfield(md,'fieldname','sampling.requested_outputs','stringrow',1) + md = checkfield(md, 'fieldname', 'sampling.beta', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices], '>', 0) + end + md = checkfield(md, 'fieldname', 'sampling.phi', 'NaN', 1, 'Inf', 1, 'numel', 1, '>=', 0) + md = checkfield(md, 'fieldname', 'sampling.alpha', 'NaN', 1, 'Inf', 1, 'numel', 1, '>', 0) + md = checkfield(md, 'fieldname', 'sampling.seed', 'NaN', 1, 'Inf', 1, 'numel', 1) + md = checkfield(md, 'fieldname', 'sampling.requested_outputs', 'stringrow', 1) return md - # }}} + #}}} - def marshall(self, prefix, md, fid): # {{{ - WriteData(fid,prefix,'object',self,'fieldname','kappa','format','DoubleMat','mattype',1) - WriteData(fid,prefix,'object',self,'fieldname','tau','format','Double') - WriteData(fid,prefix,'object',self,'fieldname','beta','format','DoubleMat','mattype',1) - WriteData(fid,prefix,'object',self,'fieldname','phi','format','Double') - WriteData(fid,prefix,'object',self,'fieldname','alpha','format','Integer') - WriteData(fid,prefix,'object',self,'fieldname','robin','format','Boolean') - WriteData(fid,prefix,'object',self,'fieldname','seed','format','Integer') + def marshall(self, prefix, md, fid): #{{{ + WriteData(fid, prefix, 'object', self, 'fieldname', 'kappa', 'format', 'DoubleMat', 'mattype', 1) + WriteData(fid, prefix, 'object', self, 'fieldname', 'tau', 'format', 'Double') + WriteData(fid, prefix, 'object', self, 'fieldname', 'beta', 'format', 'DoubleMat', 'mattype', 1) + WriteData(fid, prefix, 'object', self, 'fieldname', 'phi', 'format', 'Double') + WriteData(fid, prefix, 'object', self, 'fieldname', 'alpha', 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'robin', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'fieldname', 'seed', 'format', 'Integer') - #process requested outputs + # Process requested outputs outputs = self.requested_outputs indices = [i for i, x in enumerate(outputs) if x == 'default'] if len(indices) > 0: @@ -96,5 +112,14 @@ outputscopy = outputs[0:max(0, indices[0] - 1)] + self.defaultoutputs(md) + outputs[indices[0] + 1:] outputs = outputscopy WriteData(fid, prefix, 'data', outputs, 'name', 'md.sampling.requested_outputs', 'format', 'StringArray') + #}}} - # }}} + def setparameters(self, md, lc, sigma): #{{{ + nu = self.alpha - 1 + KAPPA = pow((8 * nu), 0.5) / lc + TAU = pow((math.gamma(nu) / math.gamma(self.alpha) * (4 * np.pi) * pow(KAPPA, 2 * nu) * pow(sigma, 2)), 0.5) + md.sampling.kappa = KAPPA * np.ones((md.mesh.numberofvertices, 1)) + md.sampling.tau = TAU + + return md + #}}} Index: ../trunk-jpl/src/m/classes/solidearthsettings.m =================================================================== --- ../trunk-jpl/src/m/classes/solidearthsettings.m (revision 26300) +++ ../trunk-jpl/src/m/classes/solidearthsettings.m (revision 26301) @@ -91,6 +91,27 @@ self.grdmodel=0; end % }}} + function disp(self) % {{{ + disp(sprintf(' solidearth settings:')); + + fielddisplay(self,'reltol','sea level change relative convergence criterion (default, NaN: not applied)'); + fielddisplay(self,'abstol','sea level change absolute convergence criterion(default, NaN: not applied)'); + fielddisplay(self,'maxiter','maximum number of nonlinear iterations'); + fielddisplay(self,'grdocean','does this planet have an ocean, if set to 1: global water mass is conserved in GRD module (default: 1)'); + fielddisplay(self,'ocean_area_scaling','correction for model representation of ocean area (default: No correction)'); + fielddisplay(self,'sealevelloading','enables surface loading from sea-level change (default: 1)'); + fielddisplay(self,'isgrd','compute GRD patterns (default: 1)'); + fielddisplay(self,'compute_bp_grd','compute GRD patterns for bottom pressure loads (default: 1)'); + fielddisplay(self,'runfrequency','how many time steps we skip before we run solidearthsettings solver during transient (default: 1)'); + fielddisplay(self,'selfattraction','enables surface mass load to perturb the gravity field'); + fielddisplay(self,'elastic','enables elastic deformation from surface loading'); + fielddisplay(self,'viscous','enables viscous deformation from surface loading'); + fielddisplay(self,'rotation','enables polar motion to feedback on the GRD fields'); + fielddisplay(self,'degacc','accuracy (default: .01 deg) for numerical discretization of the Green''s functions'); + fielddisplay(self,'timeacc','time accuracy (default: 1 yr) for numerical discretization of the Green''s functions'); + fielddisplay(self,'grdmodel','type of deformation model, 0 for no GRD, 1 for spherical GRD model (SESAW model), 2 for half-space planar GRD (visco-elastic model from Ivins)'); + fielddisplay(self,'cross_section_shape','1: square-edged (default). 2: elliptical. See iedge in GiaDeflectionCore'); + end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), @@ -134,27 +155,6 @@ end end % }}} - function disp(self) % {{{ - disp(sprintf(' solidearth settings:')); - - fielddisplay(self,'reltol','sea level change relative convergence criterion (default, NaN: not applied)'); - fielddisplay(self,'abstol','sea level change absolute convergence criterion(default, NaN: not applied)'); - fielddisplay(self,'maxiter','maximum number of nonlinear iterations'); - fielddisplay(self,'grdocean','does this planet have an ocean, if set to 1: global water mass is conserved in GRD module (default: 1)'); - fielddisplay(self,'ocean_area_scaling','correction for model representation of ocean area (default: No correction)'); - fielddisplay(self,'sealevelloading','enables surface loading from sea-level change (default: 1)'); - fielddisplay(self,'isgrd','compute GRD patterns (default: 1)'); - fielddisplay(self,'compute_bp_grd','compute GRD patterns for bottom pressure loads (default: 1)'); - fielddisplay(self,'runfrequency','how many time steps we skip before we run solidearthsettings solver during transient (default: 1)'); - fielddisplay(self,'selfattraction','enables surface mass load to perturb the gravity field'); - fielddisplay(self,'elastic','enables elastic deformation from surface loading'); - fielddisplay(self,'viscous','enables viscous deformation from surface loading'); - fielddisplay(self,'rotation','enables polar motion to feedback on the GRD fields'); - fielddisplay(self,'degacc','accuracy (default: .01 deg) for numerical discretization of the Green''s functions'); - fielddisplay(self,'timeacc','time accuracy (default: 1 yr) for numerical discretization of the Green''s functions'); - fielddisplay(self,'grdmodel','type of deformation model, 0 for no GRD, 1 for spherical GRD model (SESAW model), 2 for half-space planar GRD (visco-elastic model from Ivins)'); - fielddisplay(self,'cross_section_shape','1: square-edged (default). 2: elliptical. See iedge in GiaDeflectionCore'); - end % }}} function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','reltol','name','md.solidearth.settings.reltol','format','Double'); WriteData(fid,prefix,'object',self,'fieldname','abstol','name','md.solidearth.settings.abstol','format','Double'); Index: ../trunk-jpl/src/m/miscellaneous/MatlabFuncs.py =================================================================== --- ../trunk-jpl/src/m/miscellaneous/MatlabFuncs.py (revision 26300) +++ ../trunk-jpl/src/m/miscellaneous/MatlabFuncs.py (revision 26301) @@ -1,60 +1,79 @@ -def oshostname(): - import socket +def acosd(X): #{{{ + """ function acosd - Inverse cosine in degrees - return socket.gethostname() + Usage: + Y = acosd(X) + """ + import numpy as np + return np.degrees(np.arccos(X)) +#}}} -def ispc(): - import platform +def asind(X): #{{{ + """ function asind - Inverse sine in degrees - if 'Windows' in platform.system(): - return True - else: - return False + Usage: + Y = asind(X) + """ + import numpy as np + return np.degrees(np.arcsin(X)) +#}}} -def ismac(): - import platform +def atand(X): #{{{ + """ function atand - Inverse tangent in degrees - if 'Darwin' in platform.system(): - return True - else: - return False + Usage: + Y = atand(X) + """ + import numpy as np + return np.degrees(np.arctan(X)) +#}}} -def strcmp(s1, s2): - if s1 == s2: - return True - else: - return False +def atan2d(Y, X): #{{{ + """ function atan2d - Four-quadrant inverse tangent in degrees + Usage: + D = atan2d(Y, X) + """ + import numpy as np -def strncmp(s1, s2, n): + return np.degrees(np.arctan2(Y, X)) +#}}} - if s1[0:n] == s2[0:n]: - return True +def det(a): #{{{ + if a.shape == (1, ): + return a[0] + elif a.shape == (1, 1): + return a[0, 0] + elif a.shape == (2, 2): + return a[0, 0] * a[1, 1] - a[0, 1] * a[1, 0] else: - return False + raise TypeError("MatlabFunc.det only implemented for shape (2, 2), not for shape %s." % str(a.shape)) +#}}} +def heaviside(x): #{{{ + import numpy as np -def strcmpi(s1, s2): + y = np.zeros_like(x) + y[np.nonzero(x > 0.)] = 1. + y[np.nonzero(x == 0.)] = 0.5 - if s1.lower() == s2.lower(): - return True - else: - return False + return y +#}}} +def ismac(): #{{{ + import platform -def strncmpi(s1, s2, n): - - if s1.lower()[0:n] == s2.lower()[0:n]: + if 'Darwin' in platform.system(): return True else: return False +#}}} - -def ismember(a, s): +def ismember(a, s): #{{{ import numpy as np if not isinstance(s, (tuple, list, dict, np.ndarray)): @@ -65,32 +84,33 @@ if not isinstance(a, np.ndarray): b = [item in s for item in a] - else: if not isinstance(s, np.ndarray): b = np.empty_like(a) for i, item in enumerate(a.flat): b.flat[i] = item in s - else: b = np.in1d(a.flat, s.flat).reshape(a.shape) return b +#}}} +def ispc(): #{{{ + import platform -def det(a): - - if a.shape == (1, ): - return a[0] - elif a.shape == (1, 1): - return a[0, 0] - elif a.shape == (2, 2): - return a[0, 0] * a[1, 1] - a[0, 1] * a[1, 0] + if 'Windows' in platform.system(): + return True else: - raise TypeError("MatlabFunc.det only implemented for shape (2, 2), not for shape %s." % str(a.shape)) + return False +#}}} +def oshostname(): #{{{ + import socket -def sparse(ivec, jvec, svec, m=0, n=0, nzmax=0): + return socket.gethostname() +#}}} + +def sparse(ivec, jvec, svec, m=0, n=0, nzmax=0): #{{{ import numpy as np if not m: @@ -104,13 +124,32 @@ a[i - 1, j - 1] += s return a +#}}} +def strcmp(s1, s2): #{{{ + if s1 == s2: + return True + else: + return False +#}}} -def heaviside(x): - import numpy as np +def strcmpi(s1, s2): #{{{ + if s1.lower() == s2.lower(): + return True + else: + return False +#}}} - y = np.zeros_like(x) - y[np.nonzero(x > 0.)] = 1. - y[np.nonzero(x == 0.)] = 0.5 +def strncmp(s1, s2, n): #{{{ + if s1[0:n] == s2[0:n]: + return True + else: + return False +#}}} - return y +def strncmpi(s1, s2, n): #{{{ + if s1.lower()[0:n] == s2.lower()[0:n]: + return True + else: + return False +#}}} Index: ../trunk-jpl/src/m/miscellaneous/PythonFuncs.py =================================================================== --- ../trunk-jpl/src/m/miscellaneous/PythonFuncs.py (revision 26300) +++ ../trunk-jpl/src/m/miscellaneous/PythonFuncs.py (revision 26301) @@ -1,25 +1,22 @@ import numpy as np -def logical_and_n(*arg): - +def logical_and_n(*arg): #{{{ if len(arg): result = arg[0] for item in arg[1:]: result = np.logical_and(result, item) return result - else: return None +#}}} - -def logical_or_n(*arg): - +def logical_or_n(*arg): #{{{ if len(arg): result = arg[0] for item in arg[1:]: result = np.logical_or(result, item) return result - else: return None +#}}} Index: ../trunk-jpl/src/m/solve/marshall.m =================================================================== --- ../trunk-jpl/src/m/solve/marshall.m (revision 26300) +++ ../trunk-jpl/src/m/solve/marshall.m (revision 26301) @@ -44,7 +44,7 @@ st=fclose(fid); % Uncomment the following to make a copy of the binary input file for debugging -% purposes (can be fed into scripts/ReadBin.py). +% purposes (can be fed into scripts/BinRead.py). % copyfile([md.miscellaneous.name '.bin'], [md.miscellaneous.name '.m.bin']) if st==-1, Index: ../trunk-jpl/src/m/solve/marshall.py =================================================================== --- ../trunk-jpl/src/m/solve/marshall.py (revision 26300) +++ ../trunk-jpl/src/m/solve/marshall.py (revision 26301) @@ -45,7 +45,7 @@ fid.close() # Uncomment the following to make a copy of the binary input file for - # debugging purposes (can be fed into scripts/ReadBin.py). + # debugging purposes (can be fed into scripts/BinRead.py). # copy_cmd = "cp {}.bin {}.py.bin".format(md.miscellaneous.name, md.miscellaneous.name) # subprocess.call(copy_cmd, shell=True) Index: ../trunk-jpl/src/m/classes/dsl.py =================================================================== --- ../trunk-jpl/src/m/classes/dsl.py (revision 26300) +++ ../trunk-jpl/src/m/classes/dsl.py (revision 26301) @@ -7,16 +7,21 @@ class dsl(object): - """DSL - slass definition + """DSL - class definition Usage: - dsl = dsl() + dsl = dsl() # dynamic sea level class, based on CMIP5 outputs """ - def __init__(self): #{{{ + def __init__(self, *args): #{{{ self.global_average_thermosteric_sea_level = np.nan # Corresponds to zostoga field in CMIP5 archives. Specified as a temporally variable quantity (in m). self.sea_surface_height_above_geoid = np.nan # Corresponds to zos field in CMIP5 archives. Spatial average is 0. Specified as a spatio-temporally variable quantity (in m). self.sea_water_pressure_at_sea_floor = np.nan # Corresponds to bpo field in CMIP5 archives. Specified as a spatio-temporally variable quantity (in m equivalent, not in Pa!). + + if len(args) == 0: + self.setdefaultparameters() + else: + raise Exception('constructor not supported') #}}} def __repr__(self): #{{{ @@ -27,27 +32,15 @@ return s #}}} - def defaultoutputs(self, md): #{{{ - return [] + def setdefaultparameters(self): #{{{ + self.global_average_thermosteric_sea_level = np.nan + self.sea_surface_height_above_geoid = np.nan + self.sea_water_pressure_at_sea_floor = np.nan #}}} - def initialize(self, md): #{{{ - if np.isnan(self.global_average_thermosteric_sea_level): - self.global_average_thermosteric_sea_level = np.array([0, 0]).reshape(-1, 1) - print(' no dsl.global_average_thermosteric_sea_level specified: transient values set at zero') - - if np.isnan(self.sea_surface_height_above_geoid): - self.sea_surface_height_above_geoid = np.array(np.zeros(md.mesh.numberofvertices)).reshape(-1, 1) - print(' no dsl.sea_surface_height_above_geoid specified: transient values set at zero') - - if np.isnan(self.sea_water_pressure_at_sea_floor): - self.sea_water_pressure_at_sea_floor = np.array(np.zeros(md.mesh.numberofvertices)).reshape(-1, 1) - print(' no dsl.sea_water_pressure_at_sea_floor specified: transient values set at zero') - #}}} - def checkconsistency(self, md, solution, analyses): #{{{ # Early return - if ('SealevelriseAnalysis' not in analyses) or (solution == 'TransientSolution' and not md.transient.isslc): + if ('SealevelchangeAnalysis' not in analyses) or (solution == 'TransientSolution' and not md.transient.isslc): return md md = checkfield(md, 'fieldname', 'dsl.global_average_thermosteric_sea_level', 'NaN', 1, 'Inf', 1) @@ -60,16 +53,31 @@ return md # }}} + def marshall(self, prefix, md, fid): #{{{ + yts = md.constants.yts + WriteData(fid, prefix, 'name', 'md.dsl.model', 'data', 1, 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'global_average_thermosteric_sea_level', 'format', 'DoubleMat', 'mattype', 2, 'timeseries', 1, 'yts', yts) # mattype 2, because we are sending a GMSL value identical everywhere on each element. + WriteData(fid, prefix, 'object', self, 'fieldname', 'sea_surface_height_above_geoid', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts) # mattype 1 because we specify DSL at vertex locations. + WriteData(fid, prefix, 'object', self, 'fieldname', 'sea_water_pressure_at_sea_floor', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts) # mattype 1 because we specify bottom pressure at vertex locations. + # }}} + def extrude(self, md): #{{{ - self.sea_surface_height_above_geoid = project3d(md, 'vector', self.sea_surface_height_above_geoid, 'type', 'node') - self.sea_water_pressure_at_sea_floor = project3d(md, 'vector', self.sea_water_pressure_at_sea_floor, 'type', 'node') + self.sea_surface_height_above_geoid = project3d(md, 'vector', self.sea_surface_height_above_geoid, 'type', 'node', 'layer', 1) + self.sea_water_pressure_at_sea_floor = project3d(md, 'vector', self.sea_water_pressure_at_sea_floor, 'type', 'node', 'layer', 1) return self #}}} - def marshall(self, prefix, md, fid): #{{{ - yts = md.constants.yts - WriteData(fid, prefix, 'name', 'md.dsl.model', 'data', 1, 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'class', 'dsl', 'fieldname', 'global_average_thermosteric_sea_level', 'format', 'DoubleMat', 'mattype', 2, 'timeserieslength', 1+1, 'yts', md.constants.yts, 'scale', 1e-3/md.constants.yts) # mattype 2, because we are sending a GMSL value identical everywhere on each element. - WriteData(fid, prefix, 'object', self, 'class', 'dsl', 'fieldname', 'sea_water_pressure_at_sea_floor', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices+1, 'yts', md.constants.yts, 'scale', 1e-3/md.constants.yts) # mattype 1 because we specify DSL at vertex locations. - WriteData(fid, prefix, 'object', self, 'class', 'dsl', 'fieldname', 'sea_surface_height_above_geoid', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices+1, 'yts', md.constants.yts) # mattype 1 because we specify bottom pressure at vertex locations. - # }}} + + def initialize(self, md): #{{{ + if np.isnan(self.global_average_thermosteric_sea_level): + self.global_average_thermosteric_sea_level = np.array([0, 0]).reshape(-1, 1) + print(' no dsl.global_average_thermosteric_sea_level specified: transient values set at zero') + + if np.isnan(self.sea_surface_height_above_geoid): + self.sea_surface_height_above_geoid = np.append(np.zeros((md.mesh.numberofvertices, 1)), 0).reshape(-1, 1) + print(' no dsl.sea_surface_height_above_geoid specified: transient values set at zero') + + if np.isnan(self.sea_water_pressure_at_sea_floor): + self.sea_water_pressure_at_sea_floor = np.append(np.zeros((md.mesh.numberofvertices, 1)), 0).reshape(-1, 1) + print(' no dsl.sea_water_pressure_at_sea_floor specified: transient values set at zero') + #}}} Index: ../trunk-jpl/src/m/classes/hydrologyshreve.m =================================================================== --- ../trunk-jpl/src/m/classes/hydrologyshreve.m (revision 26300) +++ ../trunk-jpl/src/m/classes/hydrologyshreve.m (revision 26301) @@ -10,8 +10,6 @@ requested_outputs = {}; end methods - function self = extrude(self,md) % {{{ - end % }}} function self = hydrologyshreve(varargin) % {{{ switch nargin case 0 @@ -22,10 +20,13 @@ error('constructor not supported'); end end % }}} - function list = defaultoutputs(self,md) % {{{ - list = {'Watercolumn','HydrologyWaterVx','HydrologyWaterVy'}; - end % }}} + function disp(self) % {{{ + disp(sprintf(' hydrologyshreve solution parameters:')); + fielddisplay(self,'spcwatercolumn','water thickness constraints (NaN means no constraint) [m]'); + fielddisplay(self,'stabilization','artificial diffusivity (default: 1). can be more than 1 to increase diffusivity.'); + fielddisplay(self,'requested_outputs','additional outputs requested'); + end % }}} function self = setdefaultparameters(self) % {{{ %Type of stabilization to use 0:nothing 1:artificial_diffusivity @@ -33,7 +34,7 @@ self.requested_outputs = {'default'}; end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - + %Early return if ~ismember('HydrologyShreveAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.ishydrology==0), return; end @@ -40,25 +41,23 @@ md = checkfield(md,'fieldname','hydrology.spcwatercolumn','Inf',1,'timeseries',1); md = checkfield(md,'fieldname','hydrology.stabilization','>=',0); end % }}} - function disp(self) % {{{ - disp(sprintf(' hydrologyshreve solution parameters:')); - fielddisplay(self,'spcwatercolumn','water thickness constraints (NaN means no constraint) [m]'); - fielddisplay(self,'stabilization','artificial diffusivity (default is 1). can be more than 1 to increase diffusivity.'); - fielddisplay(self,'requested_outputs','additional outputs requested'); - + function list = defaultoutputs(self,md) % {{{ + list = {'Watercolumn','HydrologyWaterVx','HydrologyWaterVy'}; end % }}} function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'name','md.hydrology.model','data',2,'format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','spcwatercolumn','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Double'); - outputs = self.requested_outputs; - pos = find(ismember(outputs,'default')); - if ~isempty(pos), - outputs(pos) = []; %remove 'default' from outputs - outputs = [outputs defaultoutputs(self,md)]; %add defaults - end - WriteData(fid,prefix,'data',outputs,'name','md.hydrology.requested_outputs','format','StringArray'); + outputs = self.requested_outputs; + pos = find(ismember(outputs,'default')); + if ~isempty(pos), + outputs(pos) = []; %remove 'default' from outputs + outputs = [outputs defaultoutputs(self,md)]; %add defaults + end + WriteData(fid,prefix,'data',outputs,'name','md.hydrology.requested_outputs','format','StringArray'); end % }}} + function self = extrude(self,md) % {{{ + end % }}} function savemodeljs(self,fid,modelname) % {{{ writejs1Darray(fid,[modelname '.hydrology.spcwatercolumn'],self.spcwatercolumn); Index: ../trunk-jpl/src/m/classes/initialization.py =================================================================== --- ../trunk-jpl/src/m/classes/initialization.py (revision 26300) +++ ../trunk-jpl/src/m/classes/initialization.py (revision 26301) @@ -10,32 +10,33 @@ """INITIALIZATION class definition Usage: - initialization = initialization() + initialization = initialization() """ - def __init__(self): # {{{ + def __init__(self): #{{{ self.vx = np.nan self.vy = np.nan self.vz = np.nan self.vel = np.nan - self.enthalpy = np.nan self.pressure = np.nan self.temperature = np.nan + self.enthalpy = np.nan self.waterfraction = np.nan - self.watercolumn = np.nan self.sediment_head = np.nan self.epl_head = np.nan self.epl_thickness = np.nan + self.watercolumn = np.nan self.hydraulic_potential = np.nan self.channelarea = np.nan self.sealevel = np.nan self.bottompressure = np.nan + self.dsl = np.nan + self.str = np.nan self.sample = np.nan - #set defaults self.setdefaultparameters() #}}} - def __repr__(self): # {{{ + def __repr__(self): #{{{ s = ' initial field values:\n' s += '{}\n'.format(fielddisplay(self, 'vx', 'x component of velocity [m / yr]')) s += '{}\n'.format(fielddisplay(self, 'vy', 'y component of velocity [m / yr]')) @@ -51,37 +52,13 @@ s += '{}\n'.format(fielddisplay(self, 'epl_thickness', 'thickness of the epl [m]')) s += '{}\n'.format(fielddisplay(self, 'hydraulic_potential', 'Hydraulic potential (for GlaDS) [Pa]')) s += '{}\n'.format(fielddisplay(self, 'channelarea', 'subglaciale water channel area (for GlaDS) [m2]')) - s += '{}\n'.format(fielddisplay(self,'sample','Realization of a Gaussian random field')) + s += '{}\n'.format(fielddisplay(self,'sample', 'Realization of a Gaussian random field')) return s #}}} - def extrude(self, md): # {{{ - self.vx = project3d(md, 'vector', self.vx, 'type', 'node') - self.vy = project3d(md, 'vector', self.vy, 'type', 'node') - self.vz = project3d(md, 'vector', self.vz, 'type', 'node') - self.vel = project3d(md, 'vector', self.vel, 'type', 'node') - self.temperature = project3d(md, 'vector', self.temperature, 'type', 'node') - self.enthalpy = project3d(md, 'vector', self.enthalpy, 'type', 'node') - self.waterfraction = project3d(md, 'vector', self.waterfraction, 'type', 'node') - self.watercolumn = project3d(md, 'vector', self.watercolumn, 'type', 'node') - self.sediment_head = project3d(md, 'vector', self.sediment_head, 'type', 'node', 'layer', 1) - self.epl_head = project3d(md, 'vector', self.epl_head, 'type', 'node', 'layer', 1) - self.epl_thickness = project3d(md, 'vector', self.epl_thickness, 'type', 'node', 'layer', 1) - self.sealevel = project3d(md, 'vector', self.sealevel, 'type', 'node', 'layer', 1) - self.bottompressure = project3d(md, 'vector', self.bottompressure, 'type', 'node', 'layer', 1) - - #Lithostatic pressure by default - if np.ndim(md.geometry.surface) == 2: - print('Reshaping md.geometry.surface for your convenience but you should fix it in your model set up') - self.pressure = md.constants.g * md.materials.rho_ice * (md.geometry.surface.reshape(-1, ) - md.mesh.z) - else: - self.pressure = md.constants.g * md.materials.rho_ice * (md.geometry.surface - md.mesh.z) - - return self + def setdefaultparameters(self): #{{{ + return #}}} - def setdefaultparameters(self): # {{{ - return self - #}}} - def checkconsistency(self, md, solution, analyses): # {{{ + def checkconsistency(self, md, solution, analyses): #{{{ if 'StressbalanceAnalysis' in analyses and not solution == 'TransientSolution' and not md.transient.isstressbalance: if not np.any(np.logical_or(np.isnan(md.initialization.vx), np.isnan(md.initialization.vy))): md = checkfield(md, 'fieldname', 'initialization.vx', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) @@ -129,17 +106,20 @@ md = checkfield(md, 'fieldname', 'initialization.channelarea', 'NaN', 1, 'Inf', 1, '>=', 0, 'size', [md.mesh.numberofelements]) if 'SamplingAnalysis' in analyses and not solution == 'TransientSolution' and not md.transient.issampling: if np.any(np.isnan(md.initialization.sample)): - md = checkfield(md,'fieldname','initialization.sample','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices]) + md = checkfield(md, 'fieldname', 'initialization.sample', 'NaN', 1,'Inf', 1, 'size', [md.mesh.numberofvertices]) return md - # }}} - def marshall(self, prefix, md, fid): # {{{ + #}}} + def marshall(self, prefix, md, fid): #{{{ yts = md.constants.yts - WriteData(fid, prefix, 'object', self, 'fieldname', 'vx', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts) - WriteData(fid, prefix, 'object', self, 'fieldname', 'vy', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts) - WriteData(fid, prefix, 'object', self, 'fieldname', 'vz', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts) + + WriteData(fid, prefix, 'object', self, 'fieldname', 'vx', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1 / yts) + WriteData(fid, prefix, 'object', self, 'fieldname', 'vy', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1 / yts) + WriteData(fid, prefix, 'object', self, 'fieldname', 'vz', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1 / yts) WriteData(fid, prefix, 'object', self, 'fieldname', 'pressure', 'format', 'DoubleMat', 'mattype', 1) - WriteData(fid, prefix, 'object', self, 'fieldname', 'sealevel', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', md.constants.yts) + WriteData(fid, prefix, 'object', self, 'fieldname', 'sealevel', 'format', 'DoubleMat', 'mattype', 1,'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts) WriteData(fid, prefix, 'object', self, 'fieldname', 'bottompressure', 'format', 'DoubleMat', 'mattype', 1) + WriteData(fid, prefix, 'object', self, 'fieldname', 'str', 'format', 'DoubleMat', 'mattype', 1) + WriteData(fid, prefix, 'object', self, 'fieldname', 'dsl', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'temperature', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'waterfraction', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'sediment_head', 'format', 'DoubleMat', 'mattype', 1) @@ -148,13 +128,39 @@ WriteData(fid, prefix, 'object', self, 'fieldname', 'watercolumn', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'channelarea', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'hydraulic_potential', 'format', 'DoubleMat', 'mattype', 1) - WriteData(fid,prefix,'object',self,'fieldname','sample','format','DoubleMat','mattype',1) + WriteData(fid, prefix, 'object', self, 'fieldname', 'sample', 'format', 'DoubleMat', 'mattype', 1) + if md.thermal.isenthalpy: if (np.size(self.enthalpy) <= 1): + # Reconstruct enthalpy tpmp = md.materials.meltingpoint - md.materials.beta * md.initialization.pressure - pos = np.nonzero(md.initialization.waterfraction > 0.)[0] + pos = np.where(md.initialization.waterfraction > 0)[0] self.enthalpy = md.materials.heatcapacity * (md.initialization.temperature - md.constants.referencetemperature) - self.enthalpy[pos] = md.materials.heatcapacity * (tpmp[pos].reshape(-1, ) - md.constants.referencetemperature) + md.materials.latentheat * md.initialization.waterfraction[pos].reshape(-1, ) + self.enthalpy[pos] = md.materials.heatcapacity * (tpmp[pos].reshape(-1, 1) - md.constants.referencetemperature) + md.materials.latentheat * md.initialization.waterfraction[pos].reshape(-1, 1) WriteData(fid, prefix, 'data', self.enthalpy, 'format', 'DoubleMat', 'mattype', 1, 'name', 'md.initialization.enthalpy') - # }}} + #}}} + def extrude(self, md): #{{{ + self.vx = project3d(md, 'vector', self.vx, 'type', 'node') + self.vy = project3d(md, 'vector', self.vy, 'type', 'node') + self.vz = project3d(md, 'vector', self.vz, 'type', 'node') + self.vel = project3d(md, 'vector', self.vel, 'type', 'node') + self.temperature = project3d(md, 'vector', self.temperature, 'type', 'node') + self.enthalpy = project3d(md, 'vector', self.enthalpy, 'type', 'node') + self.waterfraction = project3d(md, 'vector', self.waterfraction, 'type', 'node') + self.watercolumn = project3d(md, 'vector', self.watercolumn, 'type', 'node') + self.sediment_head = project3d(md, 'vector', self.sediment_head, 'type', 'node', 'layer', 1) + self.epl_head = project3d(md, 'vector', self.epl_head, 'type', 'node', 'layer', 1) + self.epl_thickness = project3d(md, 'vector', self.epl_thickness, 'type', 'node', 'layer', 1) + self.sealevel = project3d(md, 'vector', self.sealevel, 'type', 'node', 'layer', 1) + self.bottompressure = project3d(md, 'vector', self.bottompressure, 'type', 'node', 'layer', 1) + + # Lithostatic pressure by default + if np.ndim(md.geometry.surface) == 2: + print('Reshaping md.geometry.surface for your convenience but you should fix it in your model set up') + self.pressure = md.constants.g * md.materials.rho_ice * (md.geometry.surface.reshape(-1, 1) - md.mesh.z) + else: + self.pressure = md.constants.g * md.materials.rho_ice * (md.geometry.surface - md.mesh.z) + + return self + #}}} Index: ../trunk-jpl/src/m/classes/lovenumbers.py =================================================================== --- ../trunk-jpl/src/m/classes/lovenumbers.py (revision 26300) +++ ../trunk-jpl/src/m/classes/lovenumbers.py (revision 26301) @@ -9,8 +9,11 @@ """LOVENUMBERS class definition Usage: - lovenumbers = lovenumbers() #will setup love numbers deg 1001 by default - lovenumbers = lovenumbers('maxdeg', 10001); #supply numbers of degrees required (here, 10001) + lovenumbers = lovenumbers() + lovenumbers = lovenumbers('maxdeg', 10000, 'referenceframe', 'CF'); + + Choose numbers of degrees required (1000 by default) and reference frame + (between CF and CM; CM by default) """ def __init__(self, *args): #{{{ @@ -25,6 +28,10 @@ self.tl = [] self.tk2secular = 0 # deg 2 secular number + # Time/frequency for visco-elastic love numbers + self.timefreq = [] + self.istime = 1 + options = pairoptions(*args) maxdeg = options.getfieldvalue('maxdeg', 1000) referenceframe = options.getfieldvalue('referenceframe', 'CM') @@ -31,6 +38,20 @@ self.setdefaultparameters(maxdeg, referenceframe) #}}} + def __repr__(self): #{{{ + s = ' lovenumbers parameters:\n' + s += '{}\n'.format(fielddisplay(self, 'h', 'load Love number for radial displacement')) + s += '{}\n'.format(fielddisplay(self, 'k', 'load Love number for gravitational potential perturbation')) + s += '{}\n'.format(fielddisplay(self, 'l', 'load Love number for horizontal displacements')) + s += '{}\n'.format(fielddisplay(self, 'th', 'tidal load Love number (deg 2)')) + s += '{}\n'.format(fielddisplay(self, 'tk', 'tidal load Love number (deg 2)')) + s += '{}\n'.format(fielddisplay(self, 'tl', 'tidal load Love number (deg 2)')) + s += '{}\n'.format(fielddisplay(self, 'tk2secular', 'secular fluid Love number')) + s += '{}\n'.format(fielddisplay(self, 'istime', 'time (default: 1) or frequency love numbers (0)')) + s += '{}\n'.format(fielddisplay(self, 'timefreq', 'time/frequency vector (yr or 1/yr)')) + return s + #}}} + def setdefaultparameters(self, maxdeg, referenceframe): #{{{ # Initialize love numbers self.h = getlovenumbers('type', 'loadingverticaldisplacement', 'referenceframe', referenceframe, 'maxdeg', maxdeg) @@ -42,11 +63,15 @@ # Secular fluid love number self.tk2secular = 0.942 + + # Time + self.istime = 1 # Temporal love numbers by default + self.timefreq = 0 # Elastic case by default return self #}}} def checkconsistency(self, md, solution, analyses): #{{{ - if ('SealevelriseAnalysis' not in analyses) or (solution == 'TransientSolution' and not md.transient.isslc): + if ('SealevelchangeAnalysis' not in analyses) or (solution == 'TransientSolution' and not md.transient.isslc): return md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.h', 'NaN', 1, 'Inf', 1) md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.k', 'NaN', 1, 'Inf', 1) @@ -55,9 +80,17 @@ md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.th', 'NaN', 1, 'Inf', 1) md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.tk', 'NaN', 1, 'Inf', 1) md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.tk2secular', 'NaN', 1, 'Inf', 1) + md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.timefreq', 'NaN', 1, 'Inf', 1) + md = checkfield(md, 'fieldname', 'solidearth.lovenumbers.istime', 'NaN', 1, 'Inf', 1, 'values', [0, 1]) + # Check that love numbers are provided at the same level of accuracy if (self.h.shape[0] != self.k.shape[0]) or (self.h.shape[0] != self.l.shape[0]): raise ValueError('lovenumbers error message: love numbers should be provided at the same level of accuracy') + + ntf = len(self.timefreq) + if (self.h.shape[1] != ntf or self.k.shape[1] != ntf or self.l.shape[1] != ntf or self.th.shape[1] != ntf or self.tk.shape[1] != ntf or self.tl.shape[1] != ntf): + raise ValueError('lovenumbers error message: love numbers should have as many time/frequency steps as the time/frequency vector') + return md #}}} @@ -65,17 +98,6 @@ return[] #}}} - def __repr__(self): #{{{ - s = ' lovenumbers parameters:\n' - s += '{}\n'.format(fielddisplay(self, 'h', 'load Love number for radial displacement')) - s += '{}\n'.format(fielddisplay(self, 'k', 'load Love number for gravitational potential perturbation')) - s += '{}\n'.format(fielddisplay(self, 'l', 'load Love number for horizontal displacements')) - s += '{}\n'.format(fielddisplay(self, 'th', 'tidal load Love number (deg 2)')) - s += '{}\n'.format(fielddisplay(self, 'tk', 'tidal load Love number (deg 2)')) - s += '{}\n'.format(fielddisplay(self, 'tk2secular', 'secular fluid Love number')) - return s - #}}} - def marshall(self, prefix, md, fid): #{{{ WriteData(fid, prefix, 'object', self, 'fieldname', 'h', 'name', 'md.solidearth.lovenumbers.h', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'k', 'name', 'md.solidearth.lovenumbers.k', 'format', 'DoubleMat', 'mattype', 1) @@ -85,6 +107,13 @@ WriteData(fid, prefix, 'object', self, 'fieldname', 'tk', 'name', 'md.solidearth.lovenumbers.tk', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'fieldname', 'tl', 'name', 'md.solidearth.lovenumbers.tl', 'format', 'DoubleMat', 'mattype', 1) WriteData(fid, prefix, 'object', self, 'data', self.tk2secular, 'fieldname', 'lovenumbers.tk2secular', 'format', 'Double') + + if (self.istime): + scale = md.constants.yts + else: + scale = 1.0 / md.constants.yts + WriteData(fid, prefix, 'object', self, 'fieldname', 'istime', 'name', 'md.solidearth.lovenumbers.istime', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'fieldname', 'timefreq', 'name', 'md.solidearth.lovenumbers.timefreq', 'format', 'DoubleMat', 'mattype', 1, 'scale', scale); #}}} def extrude(self, md): #{{{ Index: ../trunk-jpl/src/m/classes/materials.py =================================================================== --- ../trunk-jpl/src/m/classes/materials.py (revision 26300) +++ ../trunk-jpl/src/m/classes/materials.py (revision 26301) @@ -24,6 +24,7 @@ if not(self.nature[i] == 'litho' or self.nature[i] == 'ice' or self.nature[i] == 'hydro'): raise RuntimeError("materials constructor error message: nature of the material not supported yet! ('ice' or 'litho' or 'hydro')") + # Start filling in the dynamic fields (not truly dynamic under Python) for i in range(len(self.nature)): nat = self.nature[i] if nat == 'ice': @@ -66,7 +67,6 @@ raise RuntimeError("materials constructor error message: nature of the material not supported yet! ('ice' or 'litho' or 'hydro')") self.earth_density = 0 - # Set default parameters self.setdefaultparameters() #}}} @@ -104,11 +104,11 @@ s += '{}\n'.format(fielddisplay(self, 'ebm_alpha', 'array describing each layer\'s exponent parameter controlling the shape of shear modulus curve between taul and tauh, only for EBM rheology (numlayers)')) s += '{}\n'.format(fielddisplay(self, 'ebm_delta', 'array describing each layer\'s amplitude of the transient relaxation (ratio between elastic rigity to pre-maxwell relaxation rigity), only for EBM rheology (numlayers)')) s += '{}\n'.format(fielddisplay(self, 'ebm_taul', 'array describing each layer\'s starting period for transient relaxation, only for EBM rheology (numlayers) [s]')) - s += '{}\n'.format(fielddisplay(self, 'ebm_tauh', 'array describing each layer''s array describing each layer\'s end period for transient relaxation, only for Burgers rheology (numlayers) [s]')) + s += '{}\n'.format(fielddisplay(self, 'ebm_tauh', 'array describing each layer''s array describing each layer\'s end period for transient relaxation, only for Burgers rheology (numlayers) [s]')) s += '{}\n'.format(fielddisplay(self, 'rheologymodel', 'array describing whether we adopt a Maxwell (0), Burgers (1) or EBM (2) rheology (default: 0)')) s += '{}\n'.format(fielddisplay(self, 'density', 'array describing each layer\'s density (numlayers) [kg/m^3]')) - s += '{}\n'.format(fielddisplay(self, 'issolid', 'array describing whether the layer is solid or liquid (default 1) (numlayers)')) + s += '{}\n'.format(fielddisplay(self, 'issolid', 'array describing whether the layer is solid or liquid (default: 1) (numlayers)')) elif nat == 'hydro': s += 'Hydro:\n' s += '{}\n'.format(fielddisplay(self, 'rho_ice', 'ice density [kg/m^3]')) @@ -126,19 +126,19 @@ nat = self.nature[i] if nat == 'ice': # Ice density (kg/m^3) - self.rho_ice = 917. + self.rho_ice = 917 # Ocean water density (kg/m^3) - self.rho_water = 1023. + self.rho_water = 1023 # Fresh water density (kg/m^3) - self.rho_freshwater = 1000. + self.rho_freshwater = 1000 # Water viscosity (N.s/m^2) self.mu_water = 0.001787 # Ice heat capacity cp (J/kg/K) - self.heatcapacity = 2093. + self.heatcapacity = 2093 # Ice latent heat of fusion L (J/kg) self.latentheat = 3.34 * 1e5 @@ -159,7 +159,7 @@ self.beta = 9.8 * 1e-8 # Mixed layer (ice-water interface) heat capacity (J/kg/K) - self.mixed_layer_capacity = 3974. + self.mixed_layer_capacity = 3974 # Thermal exchange velocity (ice-water interface) (m/s) self.thermal_exchange_velocity = 1.00 * 1e-4 @@ -192,17 +192,17 @@ self.ebm_taul = [np.nan, np.nan] self.ebm_tauh = [np.nan, np.nan] self.rheologymodel = [0, 0] - self.density = [5.51e3, 5.50e3] # (Pa) # Mantle and lithosphere density [kg/m^3] - self.issolid = [1, 1] # Is layer solid or liquid? + self.density = [5.51e3, 5.50e3] # (Pa) # Mantle and lithosphere density [kg/m^3] + self.issolid = [1, 1] # Is layer solid or liquid? elif nat == 'hydro': # Ice density (kg/m^3) - self.rho_ice = 917. + self.rho_ice = 917 # Ocean water density (kg/m^3) - self.rho_water = 1023. + self.rho_water = 1023 # Fresh water density (kg/m^3) - self.rho_freshwater = 1000. + self.rho_freshwater = 1000 else: raise RuntimeError("materials setdefaultparameters error message: nature of the material not supported yet! ('ice' or 'litho' or 'hydro')") @@ -250,7 +250,7 @@ raise RuntimeError('First layer must be solid (issolid[0] > 0 AND lame_mu[0] > 0). Add a weak inner core if necessary.') ind = np.where(md.materials.issolid == 0)[0] if np.sum(np.in1d(np.diff(ind),1) >= 1): # If there are at least two consecutive indices that contain issolid = 0 - raise RuntimeError('Fluid layers detected at layers #{} but having 2 or more adjacent fluid layers is not supported yet. Consider merging them.'.format(i)) + raise RuntimeError('Fluid layers detected at layers #' + indices + ', but having 2 or more adjacent fluid layers is not supported yet. Consider merging them.') elif nat == 'hydro': md = checkfield(md, 'fieldname', 'materials.rho_ice', '>', 0) @@ -266,7 +266,7 @@ def marshall(self, prefix, md, fid): #{{{ #1: MatdamageiceEnum 2: MatestarEnum 3: MaticeEnum 4: MatenhancediceEnum 5: MaterialsEnum WriteData(fid, prefix, 'name', 'md.materials.nature', 'data', naturetointeger(self.nature), 'format', 'IntMat', 'mattype', 3) - WriteData(fid, prefix, 'name', 'md.materials.type', 'data', 5, 'format', 'Integer') #DANGER, this can evolve if you have classes + WriteData(fid, prefix, 'name', 'md.materials.type', 'data', 5, 'format', 'Integer') #DANGER: this can evolve if you have classes for i in range(len(self.nature)): nat = self.nature[i] if nat == 'ice': @@ -306,6 +306,7 @@ for i in range(self.numlayers): earth_density = earth_density + (pow(self.radius[i + 1], 3) - pow(self.radius[i], 3)) * self.density[i] earth_density = earth_density / pow(self.radius[self.numlayers], 3) + print(earth_density) self.earth_density = earth_density elif nat == 'hydro': WriteData(fid, prefix, 'object', self, 'class', 'materials', 'fieldname', 'rho_ice', 'format', 'Double') Index: ../trunk-jpl/src/m/classes/solidearth.m =================================================================== --- ../trunk-jpl/src/m/classes/solidearth.m (revision 26300) +++ ../trunk-jpl/src/m/classes/solidearth.m (revision 26301) @@ -44,6 +44,24 @@ error('solidearth constructor error message: zero or one argument only!'); end end % }}} + function disp(self) % {{{ + disp(sprintf(' solidearth inputs, forcings and settings:')); + + fielddisplay(self,'planetradius','planet radius [m]'); + fielddisplay(self,'transitions','indices into parts of the mesh that will be icecaps'); + fielddisplay(self,'requested_outputs','additional outputs requested'); + fielddisplay(self,'partitionice','ice partition vector for barystatic contribution'); + fielddisplay(self,'partitionhydro','hydro partition vector for barystatic contribution'); + fielddisplay(self,'partitionocean','ocean partition vector for barystatic contribution'); + if isempty(self.external), fielddisplay(self,'external','external solution, of the type solidearthsolution'); end + self.settings.disp(); + self.lovenumbers.disp(); + self.rotational.disp(); + if ~isempty(self.external), + self.external.disp(); + end + + end % }}} function self = setdefaultparameters(self,planet) % {{{ %output default: @@ -86,24 +104,6 @@ function list=defaultoutputs(self,md) % {{{ list = {'Sealevel'}; end % }}} - function disp(self) % {{{ - disp(sprintf(' solidearth inputs, forcings and settings:')); - - fielddisplay(self,'planetradius','planet radius [m]'); - fielddisplay(self,'transitions','indices into parts of the mesh that will be icecaps'); - fielddisplay(self,'requested_outputs','additional outputs requested'); - fielddisplay(self,'partitionice','ice partition vector for barystatic contribution'); - fielddisplay(self,'partitionhydro','hydro partition vector for barystatic contribution'); - fielddisplay(self,'partitionocean','ocean partition vector for barystatic contribution'); - if isempty(self.external), fielddisplay(self,'external','external solution, of the type solidearthsolution'); end - self.settings.disp(); - self.lovenumbers.disp(); - self.rotational.disp(); - if ~isempty(self.external), - self.external.disp(); - end - - end % }}} function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','planetradius','format','Double'); Index: ../trunk-jpl/src/m/classes/solidearthsettings.py =================================================================== --- ../trunk-jpl/src/m/classes/solidearthsettings.py (revision 26300) +++ ../trunk-jpl/src/m/classes/solidearthsettings.py (revision 26301) @@ -120,9 +120,9 @@ if md.mesh.__class__.__name__ is 'mesh3dsurface': if self.grdmodel == 2: raise RuntimeException('model requires a 2D mesh to run gia Ivins computations (change mesh from mesh3dsurface to mesh2d)') - else: - if self.grdmodel == 1: - raise RuntimeException('model requires a 3D surface mesh to run GRD computations (change mesh from mesh2d to mesh3dsurface)') + else: + if self.grdmodel == 1: + raise RuntimeException('model requires a 3D surface mesh to run GRD computations (change mesh from mesh2d to mesh3dsurface)') if self.sealevelloading and not self.grdocean: raise RuntimeException('solidearthsettings checkconsistency error message: need grdocean on if sealevelloading flag is set') @@ -133,24 +133,24 @@ #}}} def marshall(self, prefix, md, fid): #{{{ - WriteData(fid, prefix, 'object', self, 'fieldname', 'reltol', 'name', 'md.solidearth.settings.reltol', 'format', 'Double') - WriteData(fid, prefix, 'object', self, 'fieldname', 'abstol', 'name', 'md.solidearth.settings.abstol', 'format', 'Double') - WriteData(fid, prefix, 'object', self, 'fieldname', 'maxiter', 'name', 'md.solidearth.settings.maxiter', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'selfattraction', 'name', 'md.solidearth.settings.selfattraction', 'format', 'Boolean') - WriteData(fid, prefix, 'object', self, 'fieldname', 'elastic', 'name', 'md.solidearth.settings.elastic', 'format', 'Boolean') - WriteData(fid, prefix, 'object', self, 'fieldname', 'viscous', 'name', 'md.solidearth.settings.viscous', 'format', 'Boolean') - WriteData(fid, prefix, 'object', self, 'fieldname', 'rotation', 'name', 'md.solidearth.settings.rotation', 'format', 'Boolean') - WriteData(fid, prefix, 'object', self, 'fieldname', 'grdocean', 'name', 'md.solidearth.settings.grdocean', 'format', 'Boolean') - WriteData(fid, prefix, 'object', self, 'fieldname', 'ocean_area_scaling', 'name', 'md.solidearth.settings.ocean_area_scaling', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'runfrequency', 'name', 'md.solidearth.settings.runfrequency', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'degacc', 'name', 'md.solidearth.settings.degacc', 'format', 'Double') - WriteData(fid, prefix, 'object', self, 'fieldname', 'timeacc', 'name', 'md.solidearth.settings.timeacc', 'format', 'Double', 'scale', md.constants.yts) - WriteData(fid, prefix, 'object', self, 'fieldname', 'horiz', 'name', 'md.solidearth.settings.horiz', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'sealevelloading', 'name', 'md.solidearth.settings.sealevelloading', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname','isgrd', 'name', 'md.solidearth.settings.isgrd', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'compute_bp_grd', 'name', 'md.solidearth.settings.compute_bp_grd', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'grdmodel', 'name', 'md.solidearth.settings.grdmodel', 'format', 'Integer') - WriteData(fid, prefix, 'object', self, 'fieldname', 'cross_section_shape', 'name', 'md.solidearth.settings.cross_section_shape', 'format', 'Integer') + WriteData(fid, prefix, 'object', self, 'fieldname', 'reltol', 'name', 'md.solidearth.settings.reltol', 'format', 'Double'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'abstol', 'name', 'md.solidearth.settings.abstol', 'format', 'Double'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'maxiter', 'name', 'md.solidearth.settings.maxiter', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'selfattraction', 'name', 'md.solidearth.settings.selfattraction', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'elastic', 'name', 'md.solidearth.settings.elastic', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'viscous', 'name', 'md.solidearth.settings.viscous', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'rotation', 'name', 'md.solidearth.settings.rotation', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'grdocean', 'name', 'md.solidearth.settings.grdocean', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'ocean_area_scaling', 'name', 'md.solidearth.settings.ocean_area_scaling', 'format', 'Boolean'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'runfrequency', 'name', 'md.solidearth.settings.runfrequency', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'degacc', 'name', 'md.solidearth.settings.degacc', 'format', 'Double'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'timeacc', 'name', 'md.solidearth.settings.timeacc', 'format', 'Double', 'scale',md.constants.yts); + WriteData(fid, prefix, 'object', self, 'fieldname', 'horiz', 'name', 'md.solidearth.settings.horiz', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'sealevelloading', 'name', 'md.solidearth.settings.sealevelloading', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'isgrd', 'name', 'md.solidearth.settings.isgrd', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'compute_bp_grd', 'name', 'md.solidearth.settings.compute_bp_grd', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'grdmodel', 'name', 'md.solidearth.settings.grdmodel', 'format', 'Integer'); + WriteData(fid, prefix, 'object', self, 'fieldname', 'cross_section_shape', 'name', 'md.solidearth.settings.cross_section_shape', 'format', 'Integer'); #}}} def extrude(self, md): #{{{ Index: ../trunk-jpl/src/m/classes/solidearthsolution.py =================================================================== --- ../trunk-jpl/src/m/classes/solidearthsolution.py (nonexistent) +++ ../trunk-jpl/src/m/classes/solidearthsolution.py (revision 26301) @@ -0,0 +1,80 @@ +import numpy as np + +from checkfield import checkfield +from fielddisplay import fielddisplay +from WriteData import WriteData + + +class solidearthsolution(object): + """SOLIDEARTHSOLUTION class definition + + Usage: + solidearthsolution = solidearthsolution() + """ + + def __init__(self, *args): #{{{ + self.displacementeast = None + self.displacementnorth = None + self.displacementup = None + self.geoid = None + + if len(args) == 0: + self.setdefaultparameters() + else: + raise RuntimeError('constructor not supported') + #}}} + + def __repr__(self): #{{{ + s = ' units for time series is (yr)\n' + s += '{}\n'.format(fielddisplay(self, 'displacementeast', 'solid-Earth Eastwards bedrock displacement series (m)')) + s += '{}\n'.format(fielddisplay(self, 'displacementnorth', 'solid-Earth Northwards bedrock displacement time series (m)')) + s += '{}\n'.format(fielddisplay(self, 'displacementup', 'solid-Earth bedrock uplift time series (m)')) + s += '{}\n'.format(fielddisplay(self, 'geoid', 'solid-Earth geoid time series (m)')) + + return s + #}}} + + def setdefaultparameters(self): #{{{ + self.displacementeast = [] + self.displacementnorth = [] + self.displacementup = [] + self.geoid = [] + #}}} + + def checkconsistency(self, md, solution, analyses): #{{{ + md = checkfield(md, 'fieldname', 'solidearth.external.displacementeast', 'Inf', 1, 'timeseries', 1) + md = checkfield(md, 'fieldname', 'solidearth.external.displacementnorth', 'Inf', 1, 'timeseries', 1) + md = checkfield(md, 'fieldname', 'solidearth.external.displacementup', 'Inf', 1, 'timeseries', 1) + md = checkfield(md, 'fieldname', 'solidearth.external.geoid', 'Inf', 1, 'timeseries', 1) + #}}} + + def marshall(self, prefix, md, fid): #{{{ + yts = md.constants.yts + + # Transform our time series into time series rates + if np.shape(self.displacementeast, 1) == 1: + print('External solidearthsolution warning: only one time step provided, assuming the values are rates per year') + displacementeast_rate = np.append(np.array(self.displacementeast).reshape(-1, 1), 0) + displacementnorth_rate = np.append(np.array(self.displacementnorth).reshape(-1, 1), 0) + displacementup_rate = np.append(np.array(self.displacementup).reshape(-1, 1), 0) + geoid_rate = np.append(np.array(self.geoid).reshape(-1, 1), 0) + else: + time = self.displacementeast[-1, :] + dt = np.diff(time, 1, 1) + displacementeast_rate = np.diff(self.displacementeast[0:-2, :], 1, 1) / dt + displacementeast_rate.append(time[0:-2]) + displacementnorth_rate = np.diff(self.displacementnorth[0:-2, :], 1, 1) / dt + displacementnorth_rate.append(time[0:-2]) + displacementup_rate = np.diff(self.displacementup[0:-2, :], 1, 1) / dt + displacementup_rate.append(time[0:-2]) + geoid_rate = np.diff(self.geoid[0:-2, :], 1, 1) / dt + geoid_rate.append(time[0:-2]) + WriteData(fid, prefix, 'object', self, 'fieldname', 'displacementeast', 'data', displacementeast_rate, 'format', 'DoubleMat', 'name', 'md.solidearth.external.displacementeast', 'mattype', 1, 'scale', 1 / yts,'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts); + WriteData(fid, prefix, 'object', self, 'fieldname', 'displacementup', 'data', displacementup_rate,'format', 'DoubleMat', 'name', 'md.solidearth.external.displacementup', 'mattype', 1, 'scale', 1 / yts,'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts); + WriteData(fid, prefix, 'object', self, 'fieldname', 'displacementnorth', 'data', displacementnorth_rate,'format', 'DoubleMat', 'name', 'md.solidearth.external.displacementnorth', 'mattype', 1, 'scale', 1 / yts,'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts); + WriteData(fid, prefix, 'object', self, 'fieldname', 'geoid', 'data', geoid_rate,'format', 'DoubleMat', 'name', 'md.solidearth.external.geoid', 'mattype', 1, 'scale', 1 / yts,'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts); + #}}} + + def extrude(self, md): #{{{ + return self + #}}} Index: ../trunk-jpl/test/NightlyRun/test2002.m =================================================================== --- ../trunk-jpl/test/NightlyRun/test2002.m (revision 26300) +++ ../trunk-jpl/test/NightlyRun/test2002.m (revision 26301) @@ -14,6 +14,7 @@ %solidearth loading: {{{ md.masstransport.spcthickness=[md.geometry.thickness;0]; md.smb.mass_balance=zeros(md.mesh.numberofvertices,1); + %antarctica xe=md.mesh.x(md.mesh.elements)*[1;1;1]/3; ye=md.mesh.y(md.mesh.elements)*[1;1;1]/3; @@ -25,6 +26,7 @@ pos=find(late < -80); md.masstransport.spcthickness(md.mesh.elements(pos,:))= md.masstransport.spcthickness(md.mesh.elements(pos,:))-100; posant=pos; + %greenland pos=find(late>60 & late<90 & longe>-75 & longe<-15); md.masstransport.spcthickness(md.mesh.elements(pos,:))= md.masstransport.spcthickness(md.mesh.elements(pos,:))-100; @@ -95,6 +97,7 @@ md=solve(md,'Transient'); Seustatic=md.results.TransientSolution.Sealevel; Beustatic=md.results.TransientSolution.Bed; +pause %eustatic + selfattraction run: md.solidearth.settings.selfattraction=1; Index: ../trunk-jpl/test/NightlyRun/test2002.py =================================================================== --- ../trunk-jpl/test/NightlyRun/test2002.py (revision 26300) +++ ../trunk-jpl/test/NightlyRun/test2002.py (revision 26301) @@ -1,6 +1,8 @@ #Test Name: EarthSlc import numpy as np +from MatlabFuncs import * + from gmshplanet import * from gmtmask import * from lovenumbers import * @@ -11,98 +13,137 @@ from solve import * -#mesh earth: +# Mesh earth +# +# NOTE: In MATLAB, we currently use cached mesh to account for differences in +# mesh generated under Linux versus under macOS +# md = model() -md.mesh = gmshplanet('radius', 6.371012 * 1e3, 'resolution', 700.) #700 km resolution mesh +md.mesh = gmshplanet('radius', 6.371012 * 1e3, 'resolution', 700.) # 700 km resolution mesh -#parameterize solidearth solution: -#solidearth loading: -md.solidearth.surfaceload.icethicknesschange = np.zeros((md.mesh.numberofelements, 1)) -md.solidearth.initialsealevel = np.zeros((md.mesh.numberofvertices, 1)) -md.dsl.global_average_thermosteric_sea_level_change = np.zeros((2, 1)) -md.dsl.sea_surface_height_change_above_geoid = np.zeros((md.mesh.numberofvertices + 1, 1)) -md.dsl.sea_water_pressure_change_at_sea_floor = np.zeros((md.mesh.numberofvertices + 1, 1)) +# Geometry for the bed, arbitrary thickness of 100 +md.geometry.bed = np.zeros((md.mesh.numberofvertices, 1)) +md.geometry.base = md.geometry.bed +md.geometry.thickness = 100 * np.ones((md.mesh.numberofvertices, 1)) +md.geometry.surface = md.geometry.bed + md.geometry.thickness -#antarctica -late = md.mesh.lat[md.mesh.elements - 1].sum(axis=1) / 3 -longe = md.mesh.long[md.mesh.elements - 1].sum(axis=1) / 3 +# Solidearth loading #{{{ +md.masstransport.spcthickness = np.append(md.geometry.thickness, 0) +md.smb.mass_balance = np.zeros((md.mesh.numberofvertices, 1)) + +# Antarctica +xe = md.mesh.x[md.mesh.elements - 1].sum(axis=1) / 3 +ye = md.mesh.y[md.mesh.elements - 1].sum(axis=1) / 3 +ze = md.mesh.z[md.mesh.elements - 1].sum(axis=1) / 3 +re = pow((pow(xe, 2) + pow(ye, 2) + pow(ze, 2)), 0.5) + +late = asind(ze / re) +longe = atan2d(ye, xe) pos = np.where(late < -80)[0] -md.solidearth.surfaceload.icethicknesschange[pos] = -100 -#greenland -pos = np.where(np.logical_and.reduce((late > 70, late < 80, longe > -60, longe < -30)))[0] -md.solidearth.surfaceload.icethicknesschange[pos] = -100 +md.masstransport.spcthickness[md.mesh.elements[pos]] = md.masstransport.spcthickness[md.mesh.elements[pos]] - 100 +posant = pos -#elastic loading from love numbers: -md.solidearth.lovenumbers = lovenumbers('maxdeg', 100) +# Greenland +pos = np.where(np.logical_and.reduce((late > 60, late < 90, longe > -75, longe < -15)))[0] +md.masstransport.spcthickness[md.mesh.elements[pos]] = md.masstransport.spcthickness[md.mesh.elements[pos]] - 100 +posgre = pos + +# Elastic loading from love numbers: +md.solidearth.lovenumbers = lovenumbers('maxdeg', 1000) #}}} -#mask: {{{ +# Mask: {{{ mask = gmtmask(md.mesh.lat, md.mesh.long) -icemask = np.ones((md.mesh.numberofvertices, 1)) +oceanmask = -1 * np.ones((md.mesh.numberofvertices, 1)) pos = np.where(mask == 0)[0] -icemask[pos] = -1 -pos = np.where(mask[md.mesh.elements - 1].sum(axis=1) < 3)[0] -icemask[md.mesh.elements[pos, :] - 1] = -1 -md.mask.ice_levelset = icemask -md.mask.ocean_levelset = -icemask +oceanmask[pos] = 1 -#make sure that the elements that have loads are fully grounded -pos = np.nonzero(md.solidearth.surfaceload.icethicknesschange)[0] -md.mask.ocean_levelset[md.mesh.elements[pos, :] - 1] = 1 +icemask = np.ones((md.mesh.numberofvertices, 1)) +icemask[md.mesh.elements[posant]] = -1 +icemask[md.mesh.elements[posgre]] = -1 -#make sure wherever there is an ice load, that the mask is set to ice: -#pos = np.nonzero(md.solidearth.surfaceload.icethicknesschange)[0] # TODO: Do we need to do this twice? -md.mask.ice_levelset[md.mesh.elements[pos, :] - 1] = -1 -# }}} +md.mask.ice_levelset = icemask +md.mask.ocean_levelset = oceanmask +#}}} -md.solidearth.settings.ocean_area_scaling = 0 +# Time stepping {{{ +md.timestepping.start_time = 0 +md.timestepping.time_step = 1 +md.timestepping.final_time = 1 +#}}} -#geometry for the bed, arbitrary -md.geometry.bed = -np.ones((md.mesh.numberofvertices, 1)) +# Masstransport +md.basalforcings.groundedice_melting_rate = np.zeros((md.mesh.numberofvertices, 1)) +md.basalforcings.floatingice_melting_rate = np.zeros((md.mesh.numberofvertices, 1)) +md.initialization.vx = np.zeros((md.mesh.numberofvertices, 1)) +md.initialization.vy = np.zeros((md.mesh.numberofvertices, 1)) +md.initialization.sealevel = np.zeros((md.mesh.numberofvertices, 1)) +md.initialization.str = 0 -#materials -md.materials=materials('hydro') +# Materials +md.materials = materials('hydro') -#Miscellaneous +# Miscellaneous md.miscellaneous.name = 'test2002' -#Solution parameters +# Solution parameters +md.cluster.np = 3 md.solidearth.settings.reltol = np.nan md.solidearth.settings.abstol = 1e-3 -md.solidearth.settings.computesealevelchange = 1 +md.solidearth.settings.sealevelloading = 1 +md.solidearth.settings.isgrd = 1 +md.solidearth.settings.ocean_area_scaling = 0 +md.solidearth.settings.grdmodel = 1 -#max number of iterations reverted back to 10 (i.e., the original default value) +# Physics +md.transient.issmb = 0 +md.transient.isstressbalance = 0 +md.transient.isthermal = 0 +md.transient.ismasstransport = 1 +md.transient.isslc = 1 +md.solidearth.requested_outputs = ['Sealevel', 'Bed'] + +# Max number of iterations reverted back to 10 (i.e., the original default value) md.solidearth.settings.maxiter = 10 -#eustatic run: -md.solidearth.settings.rigid = 0 +# Eustatic run +md.solidearth.settings.selfattraction = 0 md.solidearth.settings.elastic = 0 md.solidearth.settings.rotation = 0 -md = solve(md, 'Sealevelrise') -Seustatic = md.results.SealevelriseSolution.Sealevel +md.solidearth.settings.viscous = 0 -#eustatic + rigid run: -md.solidearth.settings.rigid = 1 +md = solve(md, 'Transient') +Seustatic = md.results.TransientSolution.Sealevel +Beustatic = md.results.TransientSolution.Bed + +# Eustatic + selfattraction run +md.solidearth.settings.selfattraction = 1 md.solidearth.settings.elastic = 0 md.solidearth.settings.rotation = 0 -md = solve(md, 'Sealevelrise') -Srigid = md.results.SealevelriseSolution.Sealevel +md.solidearth.settings.viscous = 0 +md = solve(md, 'tr') +Sselfattraction = md.results.TransientSolution.Sealevel +Bselfattraction = md.results.TransientSolution.Bed -#eustatic + rigid + elastic run: -md.solidearth.settings.rigid = 1 +# Eustatic + selfattraction + elastic run +md.solidearth.settings.selfattraction = 1 md.solidearth.settings.elastic = 1 md.solidearth.settings.rotation = 0 -md = solve(md, 'Sealevelrise') -Selastic = md.results.SealevelriseSolution.Sealevel +md.solidearth.settings.viscous = 0 +md = solve(md, 'tr') +Selastic = md.results.TransientSolution.Sealevel +Belastic = md.results.TransientSolution.Bed -#eustatic + rigid + elastic + rotation run: -md.solidearth.settings.rigid = 1 +# Eustatic + selfattraction + elastic + rotation run +md.solidearth.settings.selfattraction = 1 md.solidearth.settings.elastic = 1 md.solidearth.settings.rotation = 1 -md = solve(md, 'Sealevelrise') -Srotation = md.results.SealevelriseSolution.Sealevel +md.solidearth.settings.viscous = 0 +md = solve(md, 'tr') +Srotation = md.results.TransientSolution.Sealevel +Brotation = md.results.TransientSolution.Bed -#Fields and tolerances to track changes -field_names = ['Eustatic', 'Rigid', 'Elastic', 'Rotation'] -field_tolerances = [1e-13, 1e-13, 1e-13, 1e-13] -field_values = [Seustatic, Srigid, Selastic, Srotation] +# Fields and tolerances to track changes +field_names = ['Seustatic', 'Sselfattraction', 'Selastic', 'Srotation', 'Beustatic', 'Bselfattraction', 'Belastic', 'Brotation'] +field_tolerances = [1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13, 1e-13] +field_values = [Seustatic, Sselfattraction, Selastic, Srotation, Beustatic, Bselfattraction, Belastic, Brotation]