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