source: issm/trunk-jpl/src/m/classes/inversion.py@ 24261

Last change on this file since 24261 was 24261, checked in by bdef, 5 years ago

BUG: still some space fix

File size: 11.4 KB
Line 
1import numpy as np
2from project3d import project3d
3from fielddisplay import fielddisplay
4from checkfield import checkfield
5from WriteData import WriteData
6from supportedcontrols import supportedcontrols
7from supportedcostfunctions import supportedcostfunctions
8from marshallcostfunctions import marshallcostfunctions
9
10
11class inversion(object):
12 """
13 INVERSION class definition
14
15 Usage:
16 inversion = inversion()
17 """
18
19 def __init__(self): # {{{
20 self.iscontrol = 0
21 self.incomplete_adjoint = 0
22 self.control_parameters = float('NaN')
23 self.nsteps = 0
24 self.maxiter_per_step = float('NaN')
25 self.cost_functions = ''
26 self.cost_functions_coefficients = float('NaN')
27 self.gradient_scaling = float('NaN')
28 self.cost_function_threshold = 0
29 self.min_parameters = float('NaN')
30 self.max_parameters = float('NaN')
31 self.step_threshold = float('NaN')
32 self.vx_obs = float('NaN')
33 self.vy_obs = float('NaN')
34 self.vz_obs = float('NaN')
35 self.vel_obs = float('NaN')
36 self.thickness_obs = float('NaN')
37 self.surface_obs = float('NaN')
38
39 #set defaults
40 self.setdefaultparameters()
41
42 #}}}
43
44 def __repr__(self): # {{{
45 string = ' inversion parameters:'
46 string = "%s\n%s" % (string, fielddisplay(self, 'iscontrol', 'is inversion activated?'))
47 string = "%s\n%s" % (string, fielddisplay(self, 'incomplete_adjoint', '1: linear viscosity, 0: non - linear viscosity'))
48 string = "%s\n%s" % (string, fielddisplay(self, 'control_parameters', 'ex: {''FrictionCoefficient''}, or {''MaterialsRheologyBbar''}'))
49 string = "%s\n%s" % (string, fielddisplay(self, 'nsteps', 'number of optimization searches'))
50 string = "%s\n%s" % (string, fielddisplay(self, 'cost_functions', 'indicate the type of response for each optimization step'))
51 string = "%s\n%s" % (string, fielddisplay(self, 'cost_functions_coefficients', 'cost_functions_coefficients applied to the misfit of each vertex and for each control_parameter'))
52 string = "%s\n%s" % (string, fielddisplay(self, 'cost_function_threshold', 'misfit convergence criterion. Default is 1%, NaN if not applied'))
53 string = "%s\n%s" % (string, fielddisplay(self, 'maxiter_per_step', 'maximum iterations during each optimization step'))
54 string = "%s\n%s" % (string, fielddisplay(self, 'gradient_scaling', 'scaling factor on gradient direction during optimization, for each optimization step'))
55 string = "%s\n%s" % (string, fielddisplay(self, 'step_threshold', 'decrease threshold for misfit, default is 30%'))
56 string = "%s\n%s" % (string, fielddisplay(self, 'min_parameters', 'absolute minimum acceptable value of the inversed parameter on each vertex'))
57 string = "%s\n%s" % (string, fielddisplay(self, 'max_parameters', 'absolute maximum acceptable value of the inversed parameter on each vertex'))
58 string = "%s\n%s" % (string, fielddisplay(self, 'vx_obs', 'observed velocity x component [m / yr]'))
59 string = "%s\n%s" % (string, fielddisplay(self, 'vy_obs', 'observed velocity y component [m / yr]'))
60 string = "%s\n%s" % (string, fielddisplay(self, 'vel_obs', 'observed velocity magnitude [m / yr]'))
61 string = "%s\n%s" % (string, fielddisplay(self, 'thickness_obs', 'observed thickness [m]'))
62 string = "%s\n%s" % (string, fielddisplay(self, 'surface_obs', 'observed surface elevation [m]'))
63 string = "%s\n%s" % (string, 'Available cost functions:')
64 string = "%s\n%s" % (string, ' 101: SurfaceAbsVelMisfit')
65 string = "%s\n%s" % (string, ' 102: SurfaceRelVelMisfit')
66 string = "%s\n%s" % (string, ' 103: SurfaceLogVelMisfit')
67 string = "%s\n%s" % (string, ' 104: SurfaceLogVxVyMisfit')
68 string = "%s\n%s" % (string, ' 105: SurfaceAverageVelMisfit')
69 string = "%s\n%s" % (string, ' 201: ThicknessAbsMisfit')
70 string = "%s\n%s" % (string, ' 501: DragCoefficientAbsGradient')
71 string = "%s\n%s" % (string, ' 502: RheologyBbarAbsGradient')
72 string = "%s\n%s" % (string, ' 503: ThicknessAbsGradient')
73 return string
74 #}}}
75
76 def extrude(self, md): # {{{
77 self.vx_obs = project3d(md, 'vector', self.vx_obs, 'type', 'node')
78 self.vy_obs = project3d(md, 'vector', self.vy_obs, 'type', 'node')
79 self.vel_obs = project3d(md, 'vector', self.vel_obs, 'type', 'node')
80 self.thickness_obs = project3d(md, 'vector', self.thickness_obs, 'type', 'node')
81 if not np.any(np.isnan(self.cost_functions_coefficients)):
82 self.cost_functions_coefficients = project3d(md, 'vector', self.cost_functions_coefficients, 'type', 'node')
83 if not np.any(np.isnan(self.min_parameters)):
84 self.min_parameters = project3d(md, 'vector', self.min_parameters, 'type', 'node')
85 if not np.any(np.isnan(self.max_parameters)):
86 self.max_parameters = project3d(md, 'vector', self.max_parameters, 'type', 'node')
87 return self
88 #}}}
89
90 def setdefaultparameters(self): # {{{
91
92 #default is incomplete adjoint for now
93 self.incomplete_adjoint = 1
94 #parameter to be inferred by control methods (only
95 #drag and B are supported yet)
96 self.control_parameters = 'FrictionCoefficient'
97 #number of steps in the control methods
98 self.nsteps = 20
99 #maximum number of iteration in the optimization algorithm for
100 #each step
101 self.maxiter_per_step = 20 * np.ones(self.nsteps)
102 #the inversed parameter is updated as follows:
103 #new_par = old_par + gradient_scaling(n) * C * gradient with C in [0 1]
104 #usually the gradient_scaling must be of the order of magnitude of the
105 #inversed parameter (1.0e8 for B, 50 for drag) and can be decreased
106 #after the first iterations
107 self.gradient_scaling = 50 * np.ones((self.nsteps, 1))
108 #several responses can be used:
109 self.cost_functions = [101, ]
110 #step_threshold is used to speed up control method. When
111 #misfit(1) / misfit(0) < self.step_threshold, we go directly to
112 #the next step
113 self.step_threshold = 0.7 * np.ones(self.nsteps) #30 per cent decrement
114 #cost_function_threshold is a criteria to stop the control methods.
115 #if J[n] - J[n - 1] / J[n] < criteria, the control run stops
116 #NaN if not applied
117 self.cost_function_threshold = float('NaN') #not activated
118
119 return self
120 #}}}
121
122 def checkconsistency(self, md, solution, analyses): # {{{
123 #Early return
124 if not self.iscontrol:
125 return md
126
127 num_controls = np.size(md.inversion.control_parameters)
128 num_costfunc = np.size(md.inversion.cost_functions)
129
130 md = checkfield(md, 'fieldname', 'inversion.iscontrol', 'values', [0, 1])
131 md = checkfield(md, 'fieldname', 'inversion.incomplete_adjoint', 'values', [0, 1])
132 md = checkfield(md, 'fieldname', 'inversion.control_parameters', 'cell', 1, 'values', supportedcontrols())
133 md = checkfield(md, 'fieldname', 'inversion.nsteps', 'numel', [1], '>=', 0)
134 md = checkfield(md, 'fieldname', 'inversion.maxiter_per_step', 'size', [md.inversion.nsteps], '>=', 0)
135 md = checkfield(md, 'fieldname', 'inversion.step_threshold', 'size', [md.inversion.nsteps])
136 md = checkfield(md, 'fieldname', 'inversion.cost_functions', 'size', [num_costfunc], 'values', supportedcostfunctions())
137 md = checkfield(md, 'fieldname', 'inversion.cost_functions_coefficients', 'size', [md.mesh.numberofvertices, num_costfunc], '>=', 0)
138 md = checkfield(md, 'fieldname', 'inversion.gradient_scaling', 'size', [md.inversion.nsteps, num_controls])
139 md = checkfield(md, 'fieldname', 'inversion.min_parameters', 'size', [md.mesh.numberofvertices, num_controls])
140 md = checkfield(md, 'fieldname', 'inversion.max_parameters', 'size', [md.mesh.numberofvertices, num_controls])
141
142 #Only SSA, HO and FS are supported right now
143 if solution == 'StressbalanceSolution':
144 if not (md.flowequation.isSSA or md.flowequation.isHO or md.flowequation.isFS or md.flowequation.isL1L2):
145 md.checkmessage("'inversion can only be performed for SSA, HO or FS ice flow models")
146
147 if solution == 'BalancethicknessSolution':
148 md = checkfield(md, 'fieldname', 'inversion.thickness_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
149 else:
150 md = checkfield(md, 'fieldname', 'inversion.vx_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
151 md = checkfield(md, 'fieldname', 'inversion.vy_obs', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
152
153 return md
154 # }}}
155
156 def marshall(self, prefix, md, fid): # {{{
157 yts = md.constants.yts
158
159 WriteData(fid, prefix, 'name', 'md.inversion.type', 'data', 0, 'format', 'Integer')
160 WriteData(fid, prefix, 'object', self, 'fieldname', 'iscontrol', 'format', 'Boolean')
161 WriteData(fid, prefix, 'object', self, 'fieldname', 'incomplete_adjoint', 'format', 'Boolean')
162 WriteData(fid, prefix, 'object', self, 'fieldname', 'vel_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
163 if not self.iscontrol:
164 return
165 WriteData(fid, prefix, 'object', self, 'fieldname', 'nsteps', 'format', 'Integer')
166 WriteData(fid, prefix, 'object', self, 'fieldname', 'maxiter_per_step', 'format', 'DoubleMat', 'mattype', 3)
167 WriteData(fid, prefix, 'object', self, 'fieldname', 'cost_functions_coefficients', 'format', 'DoubleMat', 'mattype', 1)
168 WriteData(fid, prefix, 'object', self, 'fieldname', 'gradient_scaling', 'format', 'DoubleMat', 'mattype', 3)
169 WriteData(fid, prefix, 'object', self, 'fieldname', 'cost_function_threshold', 'format', 'Double')
170 WriteData(fid, prefix, 'object', self, 'fieldname', 'min_parameters', 'format', 'DoubleMat', 'mattype', 3)
171 WriteData(fid, prefix, 'object', self, 'fieldname', 'max_parameters', 'format', 'DoubleMat', 'mattype', 3)
172 WriteData(fid, prefix, 'object', self, 'fieldname', 'step_threshold', 'format', 'DoubleMat', 'mattype', 3)
173 WriteData(fid, prefix, 'object', self, 'fieldname', 'vx_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
174 WriteData(fid, prefix, 'object', self, 'fieldname', 'vy_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
175 WriteData(fid, prefix, 'object', self, 'fieldname', 'vz_obs', 'format', 'DoubleMat', 'mattype', 1, 'scale', 1. / yts)
176 WriteData(fid, prefix, 'object', self, 'fieldname', 'thickness_obs', 'format', 'DoubleMat', 'mattype', 1)
177 WriteData(fid, prefix, 'object', self, 'fieldname', 'surface_obs', 'format', 'DoubleMat', 'mattype', 1)
178
179 #process control parameters
180 num_control_parameters = len(self.control_parameters)
181 WriteData(fid, prefix, 'object', self, 'fieldname', 'control_parameters', 'format', 'StringArray')
182 WriteData(fid, prefix, 'data', num_control_parameters, 'name', 'md.inversion.num_control_parameters', 'format', 'Integer')
183
184 #process cost functions
185 num_cost_functions = np.size(self.cost_functions)
186 data = marshallcostfunctions(self.cost_functions)
187 WriteData(fid, prefix, 'data', data, 'name', 'md.inversion.cost_functions', 'format', 'StringArray')
188 WriteData(fid, prefix, 'data', num_cost_functions, 'name', 'md.inversion.num_cost_functions', 'format', 'Integer')
189 # }}}
Note: See TracBrowser for help on using the repository browser.