source: issm/trunk/src/m/classes/m1qn3inversion.py@ 27035

Last change on this file since 27035 was 27035, checked in by Mathieu Morlighem, 3 years ago

merged trunk-jpl and trunk for revision 27033

File size: 11.1 KB
RevLine 
[21341]1import numpy as np
[25836]2from checkfield import checkfield
3from fielddisplay import fielddisplay
4from marshallcostfunctions import marshallcostfunctions
[19105]5from project3d import project3d
6from supportedcontrols import supportedcontrols
7from supportedcostfunctions import supportedcostfunctions
[25836]8from WriteData import WriteData
[17906]9
[24313]10
[17906]11class m1qn3inversion(object):
[25836]12 """M1QN3 class definition
[17906]13
[25836]14 Usage:
15 m1qn3inversion = m1qn3inversion()
16 """
[17906]17
[24313]18 def __init__(self, *args): # {{{
19 if not len(args):
20 print('empty init')
21 self.iscontrol = 0
22 self.incomplete_adjoint = 0
[25836]23 self.control_parameters = np.nan
24 self.control_scaling_factors = np.nan
[24313]25 self.maxsteps = 0
26 self.maxiter = 0
27 self.dxmin = 0.
28 self.gttol = 0.
[25836]29 self.cost_functions = np.nan
30 self.cost_functions_coefficients = np.nan
31 self.min_parameters = np.nan
32 self.max_parameters = np.nan
33 self.vx_obs = np.nan
34 self.vy_obs = np.nan
35 self.vz_obs = np.nan
36 self.vel_obs = np.nan
37 self.thickness_obs = np.nan
[17906]38
[24313]39 self.setdefaultparameters()
40 elif len(args) == 1 and args[0].__module__ == 'inversion':
41 print('converting inversion to m1qn3inversion')
42 inv = args[0]
43 #first call setdefaultparameters:
44 self.setdefaultparameters()
[19105]45
[24313]46 #then go fish whatever is available in the inversion object provided to the constructor
47 self.iscontrol = inv.iscontrol
48 self.incomplete_adjoint = inv.incomplete_adjoint
49 self.control_parameters = inv.control_parameters
50 self.maxsteps = inv.nsteps
51 self.cost_functions = inv.cost_functions
52 self.cost_functions_coefficients = inv.cost_functions_coefficients
53 self.min_parameters = inv.min_parameters
54 self.max_parameters = inv.max_parameters
55 self.vx_obs = inv.vx_obs
56 self.vy_obs = inv.vy_obs
57 self.vz_obs = inv.vz_obs
58 self.vel_obs = inv.vel_obs
59 self.thickness_obs = inv.thickness_obs
60 else:
61 raise Exception('constructor not supported')
62 #}}}
[17906]63
[24313]64 def __repr__(self): # {{{
[25836]65 s = ' m1qn3inversion parameters:\n'
66 s += '{}\n'.format(fielddisplay(self, 'iscontrol', 'is inversion activated?'))
67 s += '{}\n'.format(fielddisplay(self, 'incomplete_adjoint', '1: linear viscosity, 0: non - linear viscosity'))
68 s += '{}\n'.format(fielddisplay(self, 'control_parameters', 'ex: [''FrictionCoefficient''], or [''MaterialsRheologyBbar'']'))
69 s += '{}\n'.format(fielddisplay(self, 'control_scaling_factors', 'order of magnitude of each control (useful for multi - parameter optimization)'))
70 s += '{}\n'.format(fielddisplay(self, 'maxsteps', 'maximum number of iterations (gradient computation)'))
71 s += '{}\n'.format(fielddisplay(self, 'maxiter', 'maximum number of Function evaluation (forward run)'))
72 s += '{}\n'.format(fielddisplay(self, 'dxmin', 'convergence criterion: two points less than dxmin from eachother (sup - norm) are considered identical'))
73 s += '{}\n'.format(fielddisplay(self, 'gttol', '||g(X)||/||g(X0)|| (g(X0): gradient at initial guess X0)'))
74 s += '{}\n'.format(fielddisplay(self, 'cost_functions', 'indicate the type of response for each optimization step'))
75 s += '{}\n'.format(fielddisplay(self, 'cost_functions_coefficients', 'cost_functions_coefficients applied to the misfit of each vertex and for each control_parameter'))
76 s += '{}\n'.format(fielddisplay(self, 'min_parameters', 'absolute minimum acceptable value of the inversed parameter on each vertex'))
77 s += '{}\n'.format(fielddisplay(self, 'max_parameters', 'absolute maximum acceptable value of the inversed parameter on each vertex'))
78 s += '{}\n'.format(fielddisplay(self, 'vx_obs', 'observed velocity x component [m / yr]'))
79 s += '{}\n'.format(fielddisplay(self, 'vy_obs', 'observed velocity y component [m / yr]'))
80 s += '{}\n'.format(fielddisplay(self, 'vel_obs', 'observed velocity magnitude [m / yr]'))
81 s += '{}\n'.format(fielddisplay(self, 'thickness_obs', 'observed thickness [m]'))
82 s += '{}\n'.format('Available cost functions:')
83 s += '{}\n'.format(' 101: SurfaceAbsVelMisfit')
84 s += '{}\n'.format(' 102: SurfaceRelVelMisfit')
85 s += '{}\n'.format(' 103: SurfaceLogVelMisfit')
86 s += '{}\n'.format(' 104: SurfaceLogVxVyMisfit')
87 s += '{}\n'.format(' 105: SurfaceAverageVelMisfit')
88 s += '{}\n'.format(' 201: ThicknessAbsMisfit')
89 s += '{}\n'.format(' 501: DragCoefficientAbsGradient')
90 s += '{}\n'.format(' 502: RheologyBbarAbsGradient')
91 s += '{}\n'.format(' 503: ThicknessAbsGradient')
92 return s
[24313]93 #}}}
[17906]94
[24313]95 def setdefaultparameters(self): # {{{
96 #default is incomplete adjoint for now
97 self.incomplete_adjoint = 1
98 #parameter to be inferred by control methods (only
99 #drag and B are supported yet)
100 self.control_parameters = 'FrictionCoefficient'
101 #Scaling factor for each control
102 self.control_scaling_factors = 1
103 #number of iterations
104 self.maxsteps = 20
105 self.maxiter = 40
106 #several responses can be used:
107 self.cost_functions = 101
108 #m1qn3 parameters
109 self.dxmin = 0.1
110 self.gttol = 1e-4
[17906]111
[24313]112 return self
113 #}}}
[17909]114
[25836]115 def extrude(self, md): # {{{
116 self.vx_obs = project3d(md, 'vector', self.vx_obs, 'type', 'node')
117 self.vy_obs = project3d(md, 'vector', self.vy_obs, 'type', 'node')
118 self.vel_obs = project3d(md, 'vector', self.vel_obs, 'type', 'node')
119 self.thickness_obs = project3d(md, 'vector', self.thickness_obs, 'type', 'node')
120 if not np.any(np.isnan(self.cost_functions_coefficients)):
121 self.cost_functions_coefficients = project3d(md, 'vector', self.cost_functions_coefficients, 'type', 'node')
122 if not np.any(np.isnan(self.min_parameters)):
123 self.min_parameters = project3d(md, 'vector', self.min_parameters, 'type', 'node')
124 if not np.any(np.isnan(self.max_parameters)):
125 self.max_parameters = project3d(md, 'vector', self.max_parameters, 'type', 'node')
126 return self
127 #}}}
128
[24313]129 def checkconsistency(self, md, solution, analyses): # {{{
[25836]130 # Early return
[24313]131 if not self.iscontrol:
132 return md
[17906]133
[24313]134 num_controls = np.size(md.inversion.control_parameters)
135 num_costfunc = np.size(md.inversion.cost_functions)
[17906]136
[24313]137 md = checkfield(md, 'fieldname', 'inversion.iscontrol', 'values', [0, 1])
138 md = checkfield(md, 'fieldname', 'inversion.incomplete_adjoint', 'values', [0, 1])
139 md = checkfield(md, 'fieldname', 'inversion.control_parameters', 'cell', 1, 'values', supportedcontrols())
140 md = checkfield(md, 'fieldname', 'inversion.control_scaling_factors', 'size', [num_controls], '>', 0, 'NaN', 1, 'Inf', 1)
141 md = checkfield(md, 'fieldname', 'inversion.maxsteps', 'numel', [1], '>=', 0)
142 md = checkfield(md, 'fieldname', 'inversion.maxiter', 'numel', [1], '>=', 0)
143 md = checkfield(md, 'fieldname', 'inversion.dxmin', 'numel', [1], '>', 0.)
144 md = checkfield(md, 'fieldname', 'inversion.gttol', 'numel', [1], '>', 0.)
145 md = checkfield(md, 'fieldname', 'inversion.cost_functions', 'size', [num_costfunc], 'values', supportedcostfunctions())
146 md = checkfield(md, 'fieldname', 'inversion.cost_functions_coefficients', 'size', [md.mesh.numberofvertices, num_costfunc], '>=', 0)
147 md = checkfield(md, 'fieldname', 'inversion.min_parameters', 'size', [md.mesh.numberofvertices, num_controls])
148 md = checkfield(md, 'fieldname', 'inversion.max_parameters', 'size', [md.mesh.numberofvertices, num_controls])
[17906]149
[24313]150 if solution == 'BalancethicknessSolution':
151 md = checkfield(md, 'fieldname', 'inversion.thickness_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
[25836]152 elif solution == 'BalancethicknessSoftSolution':
153 md = checkfield(md, 'fieldname', 'inversion.thickness_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
[24313]154 else:
155 md = checkfield(md, 'fieldname', 'inversion.vx_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
156 md = checkfield(md, 'fieldname', 'inversion.vy_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
157 return md
158 # }}}
[17906]159
[24313]160 def marshall(self, prefix, md, fid): # {{{
161 yts = md.constants.yts
162 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'iscontrol', 'format', 'Boolean')
163 WriteData(fid, prefix, 'name', 'md.inversion.type', 'data', 2, 'format', 'Integer')
164 if not self.iscontrol:
165 return
166 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'incomplete_adjoint', 'format', 'Boolean')
167 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'control_scaling_factors', 'format', 'DoubleMat', 'mattype', 3)
168 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'maxsteps', 'format', 'Integer')
169 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'maxiter', 'format', 'Integer')
170 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'dxmin', 'format', 'Double')
171 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'gttol', 'format', 'Double')
172 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'cost_functions_coefficients', 'format', 'DoubleMat', 'mattype', 1)
173 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'min_parameters', 'format', 'DoubleMat', 'mattype', 3)
174 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'max_parameters', 'format', 'DoubleMat', 'mattype', 3)
175 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'vx_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
176 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'vy_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
177 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'vz_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
178 WriteData(fid, prefix, 'object', self, 'class', 'inversion', 'fieldname', 'thickness_obs', 'format', 'DoubleMat', 'mattype', 1)
[17906]179
[25836]180 # Process control parameters
[24313]181 num_control_parameters = len(self.control_parameters)
182 WriteData(fid, prefix, 'object', self, 'fieldname', 'control_parameters', 'format', 'StringArray')
183 WriteData(fid, prefix, 'data', num_control_parameters, 'name', 'md.inversion.num_control_parameters', 'format', 'Integer')
[17906]184
[25836]185 # Process cost functions
[24313]186 num_cost_functions = np.size(self.cost_functions)
187 data = marshallcostfunctions(self.cost_functions)
188 WriteData(fid, prefix, 'data', data, 'name', 'md.inversion.cost_functions', 'format', 'StringArray')
189 WriteData(fid, prefix, 'data', num_cost_functions, 'name', 'md.inversion.num_cost_functions', 'format', 'Integer')
190 # }}}
Note: See TracBrowser for help on using the repository browser.