def soroptions(**kwargs): #SOROPTIONS - return Relaxation Solver petsc options # # Usage: # options=soroptions; #retrieve options provided in varargin arguments=pairoptions.pairoptions(**kwargs) options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','cg'],['pc_type','sor'],['pc_sor_omega',1.1],['pc_sor_its',2]]; #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1=arguments.list[i][0] arg2=arguments.list[i][1] found=0; for j in range(len(options)): joption=options[j][0] if joption==arg1: joption[1]=arg2; options[j]=joption; found=1; break if not found: #this option did not exist, add it: options.append([arg1,arg2]) return options
def jacobicgoptions(*args): #ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options # # Usage: # options=jacobicgoptions; #retrieve options provided in varargin arguments=pairoptions.pairoptions(**kwargs) options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','cg'],['ksp_max_it',100],['ksp_rtol',1e-15]]; #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1=arguments.list[i][0] arg2=arguments.list[i][1] found=0; for j in range(len(options)): joption=options[j][0] if joption==arg1: joption[1]=arg2; options[j]=joption; found=1; break if not found: #this option did not exist, add it: options.append([arg1,arg2]) return options
def issmgslsolver(*args): #ISSMSOLVE - return issm solver options # # Usage: # options=issmsolver; #retrieve options provided in varargin arguments = pairoptions.pairoptions(*args) options = OrderedDict() options['toolkit'] = 'issm' options['mat_type'] = 'dense' options['vec_type'] = 'seq' options['solver_type'] = 'gsl' #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1 = arguments.list[i][0] arg2 = arguments.list[i][1] found = 0 for j in range(len(options)): joption = options[j][0] if joption == arg1: joption[1] = arg2 options[j] = joption found = 1 break if not found: #this option did not exist, add it: options.append([arg1, arg2]) return options
def asmoptions(*args): #ASMOPTIONS - return ASM petsc options # # Usage: # options=asmoptions; #retrieve options provided in varargin arguments = pairoptions.pairoptions(**kwargs) options = [['toolkit', 'petsc'], ['mat_type', 'aij'], ['ksp_type', 'gmres'], ['pc_type', 'asm'], ['sub_pc_type', 'lu'], ['pc_asm_overlap', 3], ['ksp_max_it', 100], ['ksp_rtol', 1e-30]] #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1 = arguments.list[i][0] arg2 = arguments.list[i][1] found = 0 for j in range(len(options)): joption = options[j][0] if joption == arg1: joption[1] = arg2 options[j] = joption found = 1 break if not found: #this option did not exist, add it: options.append([arg1, arg2]) return options
def __init__(self,*args): # {{{ self.name='' self.login='' self.np=1 self.port=0 self.interactive=1 self.codepath=IssmConfig('ISSM_PREFIX')[0]+'/bin' self.executionpath=issmdir()+'/execution' self.valgrind=issmdir()+'/externalpackages/valgrind/install/bin/valgrind' self.valgrindlib=issmdir()+'/externalpackages/valgrind/install/lib/libmpidebug.so' self.valgrindsup=issmdir()+'/externalpackages/valgrind/issm.supp' #use provided options to change fields options=pairoptions(*args) #get name self.name=socket.gethostname() #initialize cluster using user settings if provided if os.path.exists(self.name+'_settings.py'): execfile(self.name+'_settings.py',globals()) #OK get other fields self=options.AssignObjectFields(self)
def __init__(self,*args): # {{{ self.name = 'pfe' self.login = '' self.numnodes = 20 self.cpuspernode = 8 self.port = 1025 self.queue = 'long' self.time = 12*60 self.processor = 'wes' self.codepath = '' self.executionpath = '' self.grouplist = 's1010' self.interactive = 0 self.bbftp = 0 self.numstreams = 8 self.hyperthreading = 0 #use provided options to change fields options=pairoptions(*args) #initialize cluster using user settings if provided self=pfe_settings(self) self.np=self.nprocs() #OK get other fields self=options.AssignObjectFields(self)
def matlaboptions(**kwargs): #MATLABOPTIONS - return Matlab petsc options # # Usage: # options=matlaboptions; #retrieve options provided in varargin arguments = pairoptions.pairoptions(**kwargs) options = [['toolkit', 'petsc'], ['ksp_type', 'matlab']] #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1 = arguments.list[i][0] arg2 = arguments.list[i][1] found = 0 for j in range(len(options)): joption = options[j][0] if joption == arg1: joption[1] = arg2 options[j] = joption found = 1 break if not found: #this option did not exist, add it: options.append([arg1, arg2]) return options
def __init__(self, *args): # {{{ self.name = '' self.type = '' self.fos_reverse_index = float('NaN') self.exp = '' self.segments = [] self.index = -1 self.nods = 0 #set defaults self.setdefaultparameters() #use provided options to change fields options = pairoptions(*args) self.name = options.getfieldvalue('name', '') self.type = options.getfieldvalue('type', '') self.exp = options.getfieldvalue('exp', '') self.segments = options.getfieldvalue('segments', []) self.index = options.getfieldvalue('index', -1) self.nods = options.getfieldvalue('nods', 0) #if name is mass flux: if strcmpi(self.name, 'MassFlux'): #make sure that we supplied a file and that it exists! if not os.path.exists(self.exp): raise IOError( "dependent checkconsistency: specified 'exp' file does not exist!" ) #process the file and retrieve segments mesh = options.getfieldvalue('mesh') self.segments = MeshProfileIntersection(mesh.elements, mesh.x, mesh.y, self.exp)[0]
def mumpsoptions(**kwargs): """ MUMPSOPTIONS - return MUMPS direct solver petsc options Usage: options=mumpsoptions; """ #retrieve options provided in varargin options=pairoptions.pairoptions(**kwargs) mumps=OrderedDict() #default mumps options PETSC_VERSION=IssmConfig('_PETSC_MAJOR_')[0] if PETSC_VERSION==2.: mumps['toolkit']='petsc' mumps['mat_type']=options.getfieldvalue('mat_type','aijmumps') mumps['ksp_type']=options.getfieldvalue('ksp_type','preonly') mumps['pc_type']=options.getfieldvalue('pc_type','lu') mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120) mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true') if PETSC_VERSION==3.: mumps['toolkit']='petsc' mumps['mat_type']=options.getfieldvalue('mat_type','mpiaij') mumps['ksp_type']=options.getfieldvalue('ksp_type','preonly') mumps['pc_type']=options.getfieldvalue('pc_type','lu') mumps['pc_factor_mat_solver_package']=options.getfieldvalue('pc_factor_mat_solver_package','mumps') mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120) mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true') return mumps
def __init__(self, *args): # {{{ self.name = '' self.definitionstring = '' self.profilename = '' self.segments = float('NaN') #set defaults self.setdefaultparameters() #use provided options to change fields options = pairoptions(*args) #OK get other fields self = options.AssignObjectFields(self)
def __init__(self,**kwargs): # {{{ self.name = '' self.type = '' self.fos_forward_index = float('NaN') self.fov_forward_indices = numpy.array([]) self.nods = 0 #set defaults self.setdefaultparameters() #use provided options to change fields options=pairoptions(**kwargs) #OK get other fields self=options.AssignObjectFields(self)
def __init__(self, *args): # {{{ #BEGINFIELDS self.mprocessor = False self.module = False self.solution = False self.solver = False self.convergence = False self.control = False self.qmu = False self.autodiff = False self.smb = False #ENDFIELDS if not len(args): #Don't do anything self.solution = True self.qmu = True self.control = True pass elif len(args) == 1: binary = args[0] if isinstance(binary, (str, unicode)): if binary.lower() == 'all': binary = 2**11 - 1 #all ones self.BinaryToVerbose(binary) self.solver = False #Do not use by default else: binary = int(binary, 2) self.BinaryToVerbose(binary) elif isinstance(binary, (int, long, float)): self.BinaryToVerbose(int(binary)) else: #Use options to initialize object self = pairoptions(*args).AssignObjectFields(self) #Cast to logicals listproperties = vars(self) for fieldname, fieldvalue in listproperties.iteritems(): if isinstance(fieldvalue, bool) or isinstance( fieldvalue, (int, long, float)): setattr(self, fieldname, bool(fieldvalue)) else: raise TypeError( "verbose supported field values are logicals only (True or False)" )
def __init__(self, *args): # {{{ self.name = 'cyclone' self.login = '' self.np = 2 self.time = 100 self.codepath = '' self.executionpath = '' self.port = '' self.interactive = 0 #use provided options to change fields options = pairoptions(*args) #initialize cluster using user settings if provided self = cyclone_settings(self) #OK get other fields self = options.AssignObjectFields(self)
def __init__(self, **kwargs): # {{{ self._currentstep = 0 self.repository = './' self.prefix = 'model.' self.trunkprefix = '' self.steps = [] self.requestedsteps = [0] #process options options = pairoptions.pairoptions(**kwargs) #Get prefix prefix = options.getfieldvalue('prefix', 'model.') if not isinstance(prefix, str): raise TypeError("prefix is not a string") if not m.strcmp(prefix, prefix.strip()) or len(prefix.split()) > 1: raise TypeError("prefix should not have any white space") self.prefix = prefix #Get repository repository = options.getfieldvalue('repository', './') if not isinstance(repository, str): raise TypeError("repository is not a string") if not os.path.isdir(repository): raise IOError("Directory '%s' not found" % repository) self.repository = repository #Get steps self.requestedsteps = options.getfieldvalue('steps', [0]) #Get trunk prefix (only if provided by user) if options.exist('trunkprefix'): trunkprefix = options.getfieldvalue('trunkprefix', '') if not isinstance(trunkprefix, str): raise TypeError("trunkprefix is not a string") if not m.strcmp(trunkprefix, trunkprefix.strip()) or len( trunkprefix.split()) > 1: raise TypeError("trunkprefix should not have any white space") self.trunkprefix = trunkprefix
def iluasmoptions(*args): """ ILUASMOPTIONS - Usage: options=iluasmoptions; """ #retrieve options provided in varargin options = pairoptions.pairoptions(**kwargs) iluasm = OrderedDict() #default iluasm options iluasm['toolkit'] = 'petsc' iluasm['mat_type'] = options.getfieldvalue('mat_type', 'aij') iluasm['ksp_type'] = options.getfieldvalue('ksp_type', 'gmres') iluasm['pc_type'] = options.getfieldvalue('pc_type', 'asm') iluasm['sub_pc_type'] = options.getfieldvalue('sub_pc_type', 'ilu') iluasm['pc_asm_overlap'] = options.getfieldvalue('pc_asm_overlap', 5) iluasm['ksp_max_it'] = options.getfieldvalue('ksp_max_it', 100) iluasm['ksp_rtol'] = options.getfieldvalue('ksp_rtol', 1e-15) return iluasm
def stokesoptions(**kwargs): #STOKESOPTIONS - return STOKES multi-physics solver petsc options # # Usage: # options=stokesoptions; #retrieve options provided in varargin arguments = pairoptions.pairoptions(**kwargs) #default stokes options PETSC_VERSION = IssmConfig('_PETSC_MAJOR_')[0] if PETSC_VERSION == 2.: raise RuntimeError( 'stokesoptions error message: multi-physics options not supported in Petsc 2' ) if PETSC_VERSION == 3.: options=[['toolkit','petsc'],['mat_type','mpiaij'],['ksp_max_it',1000],['ksp_type','gmres'],['pc_type','fieldsplit'],['pc_field_split_type','schur'],\ ['fieldsplit_0_pc_type','hypre'],['fieldsplit_0_ksp_type','gmres'],['fieldsplit_0_pc_hypre_type','boomerang'],\ ['fieldsplit_1_pc_type','jacobi'],['fieldsplit_1_ksp_type','preonly'],['issm_option_solver','stokes']] #now, go through our arguments, and write over default options. for i in range(len(arguments.list)): arg1 = arguments.list[i][0] arg2 = arguments.list[i][1] found = 0 for j in range(len(options)): joption = options[j][0] if joption == arg1: joption[1] = arg2 options[j] = joption found = 1 break if not found: #this option did not exist, add it: options.append([arg1, arg2]) return options
def __init__(self, *args): # {{{ self.name = 'vilje' self.login = '' self.numnodes = 2 self.cpuspernode = 32 self.procspernodes = 16 self.mem = 28 self.queue = 'workq' self.time = 2 * 60 self.codepath = '' self.executionpath = '' self.interactive = 0 self.port = [] self.accountname = '' #use provided options to change fields options = pairoptions(*args) #initialize cluster using user settings if provided self = vilje_settings(self) #OK get other fields self = options.AssignObjectFields(self) self.np = self.numnodes * self.procspernodes
def checkfield(md, *args): """ CHECKFIELD - check field consistency Used to check model consistency., Requires: 'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname)) If 'field' is provided, it will assume the argument following 'field' is a numeric array. Available options: - NaN: 1 if check that there is no NaN - size: [lines cols], NaN for non checked dimensions - >: greater than provided value - >=: greater or equal to provided value - <: smallerthan provided value - <=: smaller or equal to provided value - < vec: smallerthan provided values on each vertex - timeseries: 1 if check time series consistency (size and time) - values: cell of strings or vector of acceptable values - numel: list of acceptable number of elements - cell: 1 if check that is cell - empty: 1 if check that non empty - message: overloaded error message Usage: md = checkfield(md,fieldname,options); """ #get options options = pairoptions(*args) #get field from model if options.exist('field'): field = options.getfieldvalue('field') fieldname = options.getfieldvalue('fieldname', 'no fieldname') else: fieldname = options.getfieldvalue('fieldname') exec("field=md.{}".format(fieldname)) if isinstance(field, (bool, int, long, float)): field = np.array([field]) #check empty if options.exist('empty'): if not field: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' is empty" % fieldname)) #Check size if options.exist('size'): fieldsize = options.getfieldvalue('size') if len(fieldsize) == 1: if np.isnan(fieldsize[0]): pass elif np.ndim(field) == 1: if not np.size(field) == fieldsize[0]: md = md.checkmessage( options.getfieldvalue( 'message', "field {} size should be {}".format( fieldname, fieldsize[0]))) else: try: exec("md.{}=field[:,0]".format(fieldname)) print( '{} had a bad dimension, we fixed it but you should check it' .format(fieldname)) except IndexError: md = md.checkmessage( options.getfieldvalue( 'message', "field {} should have {} dimension".format( fieldname, len(fieldsize)))) elif len(fieldsize) == 2: if np.isnan(fieldsize[0]): if not np.size(field, 1) == fieldsize[1]: md = md.checkmessage( options.getfieldvalue( 'message', "field '%s' should have %d columns" % (fieldname, fieldsize[1]))) elif np.isnan(fieldsize[1]): if not np.size(field, 0) == fieldsize[0]: md = md.checkmessage( options.getfieldvalue( 'message', "field '%s' should have %d lines" % (fieldname, fieldsize[0]))) elif fieldsize[1] == 1: if (not np.size(field, 0) == fieldsize[0]): md = md.checkmessage( options.getfieldvalue( 'message', "field '%s' size should be %d x %d" % (fieldname, fieldsize[0], fieldsize[1]))) else: if (not np.size(field, 0) == fieldsize[0]) or (not np.size( field, 1) == fieldsize[1]): md = md.checkmessage( options.getfieldvalue( 'message', "field '%s' size should be %d x %d" % (fieldname, fieldsize[0], fieldsize[1]))) #Check numel if options.exist('numel'): fieldnumel = options.getfieldvalue('numel') if np.size(field) not in fieldnumel: if len(fieldnumel) == 1: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' size should be %d" % (fieldname,fieldnumel))) elif len(fieldnumel) == 2: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1]))) else: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' size should be %s" % (fieldname,fieldnumel))) #check NaN if options.getfieldvalue('NaN', 0): if np.any(np.isnan(field)): md = md.checkmessage(options.getfieldvalue('message',\ "NaN values found in field '%s'" % fieldname)) #check Inf if options.getfieldvalue('Inf', 0): if np.any(np.isinf(field)): md = md.checkmessage(options.getfieldvalue('message',\ "Inf values found in field '%s'" % fieldname)) #check cell if options.getfieldvalue('cell', 0): if not isinstance(field, (tuple, list, dict)): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should be a cell" % fieldname)) #check values if options.exist('values'): fieldvalues = options.getfieldvalue('values') if False in m.ismember(field, fieldvalues): if len(fieldvalues) == 1: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' value should be '%s'" % (fieldname,fieldvalues[0]))) elif len(fieldvalues) == 2: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' values should be '%s' or '%s'" % (fieldname,fieldvalues[0],fieldvalues[1]))) else: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have values in %s" % (fieldname,fieldvalues))) #check greater if options.exist('>='): lowerbound = options.getfieldvalue('>=') if np.any(field < lowerbound): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have values above %d" % (fieldname,lowerbound))) if options.exist('>'): lowerbound = options.getfieldvalue('>') if np.any(field <= lowerbound): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have values above %d" % (fieldname,lowerbound))) #check smaller if options.exist('<='): upperbound = options.getfieldvalue('<=') if np.any(field > upperbound): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have values below %d" % (fieldname,upperbound))) if options.exist('<'): upperbound = options.getfieldvalue('<') if np.any(field >= upperbound): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have values below %d" % (fieldname,upperbound))) #check file if options.getfieldvalue('file', 0): if not os.path.exists(field): md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname, field)) #Check row of strings if options.exist('stringrow'): if not isinstance(field, list): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should be a list" %fieldname)) #Check forcings (size and times) if options.getfieldvalue('timeseries', 0): if np.size(field, 0) == md.mesh.numberofvertices: if np.ndim(field) > 1 and not np.size(field, 1) == 1: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname)) elif np.size(field, 0) == md.mesh.numberofvertices + 1 or np.size( field, 0) == 2: if not all(field[-1, :] == np.sort(field[-1, :])): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' columns should be sorted chronologically" % fieldname)) if any(field[-1, 0:-1] == field[-1, 1:]): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' columns must not contain duplicate timesteps" % fieldname)) else: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname)) #Check single value forcings (size and times) if options.getfieldvalue('singletimeseries', 0): if np.size(field, 0) == 2: if not all(field[-1, :] == np.sort(field[-1, :])): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' columns should be sorted chronologically" % fieldname)) if any(field[-1, 0:-1] == field[-1, 1:]): md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' columns must not contain duplicate timesteps" % fieldname)) else: md = md.checkmessage(options.getfieldvalue('message',\ "field '%s' should have 2 lines" % fieldname)) return md
def buildlist(self, *arg): #{{{ #check length of input if len(arg) % 2: raise TypeError('Invalid parameter/value pair arguments') #go through args and build list (like pairoptions) rawoptions = pairoptions.pairoptions(*arg) numoptions = len(arg) / 2 rawlist = [ ] # cannot be a dict since they do not support duplicate keys for i in xrange(numoptions): if isinstance(arg[2 * i], (str, unicode)): rawlist.append([arg[2 * i], arg[2 * i + 1]]) else: #option is not a string, ignore it print "WARNING: option number %d is not a string and will be ignored." % ( i + 1) #get figure number self.figurenumber = rawoptions.getfieldvalue('figure', 1) rawoptions.removefield('figure', 0) #get number of subplots numberofplots = Counter(x for sublist in rawlist for x in sublist if isinstance(x, (str, unicode)))['data'] self.numberofplots = numberofplots #figure out whether alloptions flag is on if rawoptions.getfieldvalue('alloptions', 'off') is 'on': allflag = 1 else: allflag = 0 #initialize self.list (will need a list of dict's (or nested dict) for numberofplots>1) #self.list=defaultdict(dict) for i in xrange(numberofplots): self.list[i] = pairoptions.pairoptions() #process plot options for i in xrange(len(rawlist)): #if alloptions flag is on, apply to all plots if (allflag and 'data' not in rawlist[i][0] and '#' not in rawlist[i][0]): for j in xrange(numberofplots): self.list[j].addfield(rawlist[i][0], rawlist[i][1]) elif '#' in rawlist[i][0]: #get subplots associated string = rawlist[i][0].split('#') plotnums = string[-1].split(',') field = string[0] #loop over plotnums for k in xrange(len(plotnums)): plotnum = plotnums[k] #Empty if not plotnum: continue # '#all' elif 'all' in plotnum: for j in xrange(numberofplots): self.list[j].addfield(field, rawlist[i][1]) # '#i-j' elif '-' in plotnum: nums = plotnum.split('-') if len(nums) != 2: continue if False in [x.isdigit() for x in nums]: raise ValueError( 'error: in option i-j both i and j must be integers' ) for j in xrange(int(nums[0]) - 1, int(nums[1])): self.list[j].addfield(field, rawlist[i][1]) # Deal with #i else: #assign to subplot if int(plotnum) > numberofplots: raise ValueError( 'error: %s cannot be assigned %d which exceeds the number of subplots' % (field, plotnum)) self.list[int(plotnum) - 1].addfield( field, rawlist[i][1]) else: #go through all subplots and assign key-value pairs j = 0 while j <= numberofplots - 1: if not self.list[j].exist(rawlist[i][0]): self.list[j].addfield(rawlist[i][0], rawlist[i][1]) break else: j = j + 1 if j + 1 > numberofplots: print "WARNING: too many instances of '%s' in options" % rawlist[ i][0]
def project3d(md, *args): """ PROJECT3D - vertically project a vector from 2d mesh vertically project a vector from 2d mesh (split in noncoll and coll areas) into a 3d mesh. This vector can be a node vector of size (md.mesh.numberofvertices2d,N/A) or an element vector of size (md.mesh.numberofelements2d,N/A). arguments: 'vector': 2d vector 'type': 'element' or 'node'. options: 'layer' a layer number where vector should keep its values. If not specified, all layers adopt the value of the 2d vector. 'padding': default to 0 (value adopted by other 3d layers not being projected Examples: extruded_vector=project3d(md,'vector',vector2d,'type','node','layer',1,'padding',NaN) extruded_vector=project3d(md,'vector',vector2d,'type','element','padding',0) extruded_vector=project3d(md,'vector',vector2d,'type','node') """ #some regular checks if not md: raise TypeError("bad usage") if md.mesh.domaintype().lower() != '3d': raise TypeError("input model is not 3d") #retrieve parameters from options. options = pairoptions(*args) vector2d = options.getfieldvalue('vector') #mandatory vectype = options.getfieldvalue('type') #mandatory layer = options.getfieldvalue('layer', 0) #optional (do all layers otherwise) paddingvalue = options.getfieldvalue('padding', 0) #0 by default vector1d = False if isinstance(vector2d, np.ndarray) and np.ndim(vector2d) == 1: vector1d = True vector2d = vector2d.reshape(-1, ) if isinstance(vector2d, (bool, int, long, float)) or np.size(vector2d) == 1: projected_vector = vector2d elif vectype.lower() == 'node': #Initialize 3d vector if np.ndim(vector2d) == 1: if vector2d.shape[0] == md.mesh.numberofvertices2d: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofvertices))).astype(vector2d.dtype) elif vector2d.shape[0] == md.mesh.numberofvertices2d + 1: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofvertices + 1))).astype(vector2d.dtype) projected_vector[-1] = vector2d[-1] vector2d = vector2d[:-1] else: raise TypeError("vector length not supported") #Fill in if layer == 0: for i in xrange(md.mesh.numberoflayers): projected_vector[(i * md.mesh.numberofvertices2d):( (i + 1) * md.mesh.numberofvertices2d)] = vector2d else: projected_vector[((layer - 1) * md.mesh.numberofvertices2d):( layer * md.mesh.numberofvertices2d)] = vector2d else: if vector2d.shape[0] == md.mesh.numberofvertices2d: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofvertices, np.size( vector2d, axis=1)))).astype(vector2d.dtype) elif vector2d.shape[0] == md.mesh.numberofvertices2d + 1: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofvertices + 1, np.size( vector2d, axis=1)))).astype(vector2d.dtype) projected_vector[-1, :] = vector2d[-1, :] vector2d = vector2d[:-1, :] else: raise TypeError("vector length not supported") #Fill in if layer == 0: for i in xrange(md.mesh.numberoflayers): projected_vector[(i * md.mesh.numberofvertices2d):( (i + 1) * md.mesh.numberofvertices2d), :] = vector2d else: projected_vector[((layer - 1) * md.mesh.numberofvertices2d):( layer * md.mesh.numberofvertices2d), :] = vector2d elif vectype.lower() == 'element': #Initialize 3d vector if np.ndim(vector2d) == 1: if vector2d.shape[0] == md.mesh.numberofelements2d: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofelements))).astype(vector2d.dtype) elif vector2d.shape[0] == md.mesh.numberofelements2d + 1: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofelements + 1))).astype(vector2d.dtype) projected_vector[-1] = vector2d[-1] vector2d = vector2d[:-1] else: raise TypeError("vector length not supported") #Fill in if layer == 0: for i in xrange(md.mesh.numberoflayers - 1): projected_vector[(i * md.mesh.numberofelements2d):( (i + 1) * md.mesh.numberofelements2d)] = vector2d else: projected_vector[((layer - 1) * md.mesh.numberofelements2d):( layer * md.mesh.numberofelements2d)] = vector2d else: if vector2d.shape[0] == md.mesh.numberofelements2d: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofelements, np.size( vector2d, axis=1)))).astype(vector2d.dtype) elif vector2d.shape[0] == md.mesh.numberofelements2d + 1: projected_vector = (paddingvalue * np.ones( (md.mesh.numberofelements + 1, np.size( vector2d, axis=1)))).astype(vector2d.dtype) projected_vector[-1, :] = vector2d[-1, :] vector2d = vector2d[:-1, :] else: raise TypeError("vector length not supported") #Fill in if layer == 0: for i in xrange(md.mesh.numberoflayers - 1): projected_vector[(i * md.mesh.numberofelements2d):( (i + 1) * md.mesh.numberofelements2d), :] = vector2d else: projected_vector[((layer - 1) * md.mesh.numberofelements2d):( layer * md.mesh.numberofelements2d), :] = vector2d else: raise TypeError("project3d error message: unknown projection type") if vector1d: projected_vector = projected_vector.reshape(-1, ) return projected_vector
def setflowequation(md, **kwargs): """ SETFLOWEQUATION - associate a solution type to each element This routine works like plotmodel: it works with an even number of inputs 'SIA','SSA','HO','L1L2','FS' and 'fill' are the possible options that must be followed by the corresponding exp file or flags list It can either be a domain file (argus type, .exp extension), or an array of element flags. If user wants every element outside the domain to be setflowequationd, add '~' to the name of the domain file (ex: '~HO.exp'); an empty string '' will be considered as an empty domain a string 'all' will be considered as the entire domain You can specify the type of coupling, 'penalties' or 'tiling', to use with the input 'coupling' Usage: md=setflowequation(md,varargin) Example: md=setflowequation(md,'HO','HO.exp',fill','SIA','coupling','tiling'); """ #some checks on list of arguments if not isinstance(md, model) or not len(kwargs): raise TypeError("setflowequation error message") #process options options = pairoptions(**kwargs) print(options) # options=deleteduplicates(options,1); #Find_out what kind of coupling to use coupling_method = options.getfieldvalue('coupling', 'tiling') if coupling_method is not 'tiling' or not 'penalties': raise TypeError("coupling type can only be: tiling or penalties") #recover elements distribution SIAflag = FlagElements(md, options.getfieldvalue('SIA', '')) SSAflag = FlagElements(md, options.getfieldvalue('SSA', '')) HOflag = FlagElements(md, options.getfieldvalue('HO', '')) L1L2flag = FlagElements(md, options.getfieldvalue('L1L2', '')) FSflag = FlagElements(md, options.getfieldvalue('FS', '')) filltype = options.getfieldvalue('fill', 'none') #Flag the elements that have not been flagged as filltype if filltype is 'SIA': SIAflag[numpy.nonzero( numpy.logical_not(p.logical_or_n(SSAflag, HOflag)))] = True elif filltype is 'SSA': SSAflag[numpy.nonzero( numpy.logical_not(p.logical_or_n(SIAflag, HOflag, FSflag)))] = True elif filltype is 'HO': HOflag[numpy.nonzero( numpy.logical_not(p.logical_or_n(SIAflag, SSAflag, FSflag)))] = True #check that each element has at least one flag if not any(SIAflag + SSAflag + L1L2flag + HOflag + FSflag): raise TypeError( "elements type not assigned, supported models are 'SIA','SSA','HO' and 'FS'" ) #check that each element has only one flag if any(SIAflag + SSAflag + L1L2flag + HOflag + FSflag > 1): print( "setflowequation warning message: some elements have several types, higher order type is used for them" ) SIAflag[numpy.nonzero(numpy.logical_and(SIAflag, SSAflag))] = False SIAflag[numpy.nonzero(numpy.logical_and(SIAflag, HOflag))] = False SSAflag[numpy.nonzero(numpy.logical_and(SSAflag, HOflag))] = False #FS can only be used alone for now: if any(FSflag) and any(SIAflag): raise TypeError( "FS cannot be used with any other model for now, put FS everywhere" ) #Initialize node fields nodeonSIA = numpy.zeros(md.mesh.numberofvertices, bool) nodeonSIA[md.mesh.elements[numpy.nonzero(SIAflag), :] - 1] = True nodeonSSA = numpy.zeros(md.mesh.numberofvertices, bool) nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag), :] - 1] = True nodeonL1L2 = numpy.zeros(md.mesh.numberofvertices, bool) nodeonL1L2[md.mesh.elements[numpy.nonzero(L1L2flag), :] - 1] = True nodeonHO = numpy.zeros(md.mesh.numberofvertices, bool) nodeonHO[md.mesh.elements[numpy.nonzero(HOflag), :] - 1] = True nodeonFS = numpy.zeros(md.mesh.numberofvertices, bool) noneflag = numpy.zeros(md.mesh.numberofelements, bool) #First modify FSflag to get rid of elements contrained everywhere (spc + border with HO or SSA) if any(FSflag): # fullspcnodes=double((~isnan(md.stressbalance.spcvx)+~isnan(md.stressbalance.spcvy)+~isnan(md.stressbalance.spcvz))==3 | (nodeonHO & nodeonFS)); %find all the nodes on the boundary of the domain without icefront fullspcnodes=numpy.logical_or(numpy.logical_not(numpy.isnan(md.stressbalance.spcvx)).astype(int)+ \ numpy.logical_not(numpy.isnan(md.stressbalance.spcvy)).astype(int)+ \ numpy.logical_not(numpy.isnan(md.stressbalance.spcvz)).astype(int)==3, \ numpy.logical_and(nodeonHO,nodeonFS)).astype(int) #find all the nodes on the boundary of the domain without icefront # fullspcelems=double(sum(fullspcnodes(md.mesh.elements),2)==6); %find all the nodes on the boundary of the domain without icefront fullspcelems = ( numpy.sum(fullspcnodes[md.mesh.elements - 1], axis=1) == 6 ).astype( int ) #find all the nodes on the boundary of the domain without icefront FSflag[numpy.nonzero(fullspcelems.reshape(-1))] = False nodeonFS[md.mesh.elements[numpy.nonzero(FSflag), :] - 1] = True #Then complete with NoneApproximation or the other model used if there is no FS if any(FSflag): if any(HOflag): #fill with HO HOflag[numpy.logical_not(FSflag)] = True nodeonHO[md.mesh.elements[numpy.nonzero(HOflag), :] - 1] = True elif any(SSAflag): #fill with SSA SSAflag[numpy.logical_not(FSflag)] = True nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag), :] - 1] = True else: #fill with none noneflag[numpy.nonzero(numpy.logical_not(FSflag))] = True #Now take care of the coupling between SSA and HO md.stressbalance.vertex_pairing = numpy.array([]) nodeonSSAHO = numpy.zeros(md.mesh.numberofvertices, bool) nodeonHOFS = numpy.zeros(md.mesh.numberofvertices, bool) nodeonSSAFS = numpy.zeros(md.mesh.numberofvertices, bool) SSAHOflag = numpy.zeros(md.mesh.numberofelements, bool) SSAFSflag = numpy.zeros(md.mesh.numberofelements, bool) HOFSflag = numpy.zeros(md.mesh.numberofelements, bool) if coupling_method is 'penalties': #Create the border nodes between HO and SSA and extrude them numnodes2d = md.mesh.numberofvertices2d numlayers = md.mesh.numberoflayers bordernodes2d = numpy.nonzero( numpy.logical_and(nodeonHO[0:numnodes2d], nodeonSSA[0:numnodes2d]) )[0] + 1 #Nodes connected to two different types of elements #initialize and fill in penalties structure if numpy.all(numpy.logical_not(numpy.isnan(bordernodes2d))): penalties = numpy.zeros((0, 2)) for i in range(1, numlayers): penalties = numpy.vstack( (penalties, numpy.hstack((bordernodes2d.reshape(-1, 1), bordernodes2d.reshape(-1, 1) + md.mesh.numberofvertices2d * (i))))) md.stressbalance.vertex_pairing = penalties elif coupling_method is 'tiling': if any(SSAflag) and any(HOflag): #coupling SSA HO #Find node at the border nodeonSSAHO[numpy.nonzero(numpy.logical_and(nodeonSSA, nodeonHO))] = True #SSA elements in contact with this layer become SSAHO elements matrixelements = m.ismember(md.mesh.elements - 1, numpy.nonzero(nodeonSSAHO)[0]) commonelements = numpy.sum(matrixelements, axis=1) != 0 commonelements[numpy.nonzero( HOflag )] = False #only one layer: the elements previously in SSA SSAflag[numpy.nonzero( commonelements)] = False #these elements are now SSAHOelements SSAHOflag[numpy.nonzero(commonelements)] = True nodeonSSA[:] = False nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag), :] - 1] = True #rule out elements that don't touch the 2 boundaries pos = numpy.nonzero(SSAHOflag)[0] elist = numpy.zeros(numpy.size(pos), dtype=int) elist = elist + numpy.sum(nodeonSSA[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) elist = elist - numpy.sum(nodeonHO[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) pos1 = numpy.nonzero(elist == 1)[0] SSAflag[pos[pos1]] = True SSAHOflag[pos[pos1]] = False pos2 = numpy.nonzero(elist == -1)[0] HOflag[pos[pos2]] = True SSAHOflag[pos[pos2]] = False #Recompute nodes associated to these elements nodeonSSA[:] = False nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag), :] - 1] = True nodeonHO[:] = False nodeonHO[md.mesh.elements[numpy.nonzero(HOflag), :] - 1] = True nodeonSSAHO[:] = False nodeonSSAHO[md.mesh.elements[numpy.nonzero(SSAHOflag), :] - 1] = True elif any(HOflag) and any(FSflag): #coupling HO FS #Find node at the border nodeonHOFS[numpy.nonzero(numpy.logical_and(nodeonHO, nodeonFS))] = True #FS elements in contact with this layer become HOFS elements matrixelements = m.ismember(md.mesh.elements - 1, numpy.nonzero(nodeonHOFS)[0]) commonelements = numpy.sum(matrixelements, axis=1) != 0 commonelements[numpy.nonzero( HOflag )] = False #only one layer: the elements previously in SSA FSflag[numpy.nonzero( commonelements)] = False #these elements are now SSAHOelements HOFSflag[numpy.nonzero(commonelements)] = True nodeonFS = numpy.zeros(md.mesh.numberofvertices, bool) nodeonFS[md.mesh.elements[numpy.nonzero(FSflag), :] - 1] = True #rule out elements that don't touch the 2 boundaries pos = numpy.nonzero(HOFSflag)[0] elist = numpy.zeros(numpy.size(pos), dtype=int) elist = elist + numpy.sum(nodeonFS[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) elist = elist - numpy.sum(nodeonHO[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) pos1 = numpy.nonzero(elist == 1)[0] FSflag[pos[pos1]] = True HOFSflag[pos[pos1]] = False pos2 = numpy.nonzero(elist == -1)[0] HOflag[pos[pos2]] = True HOFSflag[pos[pos2]] = False #Recompute nodes associated to these elements nodeonFS[:] = False nodeonFS[md.mesh.elements[numpy.nonzero(FSflag), :] - 1] = True nodeonHO[:] = False nodeonHO[md.mesh.elements[numpy.nonzero(HOflag), :] - 1] = True nodeonHOFS[:] = False nodeonHOFS[md.mesh.elements[numpy.nonzero(HOFSflag), :] - 1] = True elif any(FSflag) and any(SSAflag): #Find node at the border nodeonSSAFS[numpy.nonzero(numpy.logical_and(nodeonSSA, nodeonFS))] = True #FS elements in contact with this layer become SSAFS elements matrixelements = m.ismember(md.mesh.elements - 1, numpy.nonzero(nodeonSSAFS)[0]) commonelements = numpy.sum(matrixelements, axis=1) != 0 commonelements[numpy.nonzero( SSAflag )] = False #only one layer: the elements previously in SSA FSflag[numpy.nonzero( commonelements )] = False #these elements are now SSASSAelements SSAFSflag[numpy.nonzero(commonelements)] = True nodeonFS = numpy.zeros(md.mesh.numberofvertices, bool) nodeonFS[md.mesh.elements[numpy.nonzero(FSflag), :] - 1] = True #rule out elements that don't touch the 2 boundaries pos = numpy.nonzero(SSAFSflag)[0] elist = numpy.zeros(numpy.size(pos), dtype=int) elist = elist + numpy.sum(nodeonSSA[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) elist = elist - numpy.sum(nodeonFS[md.mesh.elements[pos, :] - 1], axis=1).astype(bool) pos1 = numpy.nonzero(elist == 1)[0] SSAflag[pos[pos1]] = True SSAFSflag[pos[pos1]] = False pos2 = numpy.nonzero(elist == -1)[0] FSflag[pos[pos2]] = True SSAFSflag[pos[pos2]] = False #Recompute nodes associated to these elements nodeonSSA[:] = False nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag), :] - 1] = True nodeonFS[:] = False nodeonFS[md.mesh.elements[numpy.nonzero(FSflag), :] - 1] = True nodeonSSAFS[:] = False nodeonSSAFS[md.mesh.elements[numpy.nonzero(SSAFSflag), :] - 1] = True elif any(FSflag) and any(SIAflag): raise TypeError("type of coupling not supported yet") #Create SSAHOApproximation where needed md.flowequation.element_equation = numpy.zeros(md.mesh.numberofelements, int) md.flowequation.element_equation[numpy.nonzero(noneflag)] = 0 md.flowequation.element_equation[numpy.nonzero(SIAflag)] = 1 md.flowequation.element_equation[numpy.nonzero(SSAflag)] = 2 md.flowequation.element_equation[numpy.nonzero(L1L2flag)] = 3 md.flowequation.element_equation[numpy.nonzero(HOflag)] = 4 md.flowequation.element_equation[numpy.nonzero(FSflag)] = 5 md.flowequation.element_equation[numpy.nonzero(SSAHOflag)] = 6 md.flowequation.element_equation[numpy.nonzero(SSAFSflag)] = 7 md.flowequation.element_equation[numpy.nonzero(HOFSflag)] = 8 #border md.flowequation.borderHO = nodeonHO md.flowequation.borderSSA = nodeonSSA md.flowequation.borderFS = nodeonFS #Create vertices_type md.flowequation.vertex_equation = numpy.zeros(md.mesh.numberofvertices, int) pos = numpy.nonzero(nodeonSSA) md.flowequation.vertex_equation[pos] = 2 pos = numpy.nonzero(nodeonL1L2) md.flowequation.vertex_equation[pos] = 3 pos = numpy.nonzero(nodeonHO) md.flowequation.vertex_equation[pos] = 4 pos = numpy.nonzero(nodeonFS) md.flowequation.vertex_equation[pos] = 5 #DO SIA LAST! Otherwise spcs might not be set up correctly (SIA should have priority) pos = numpy.nonzero(nodeonSIA) md.flowequation.vertex_equation[pos] = 1 if any(FSflag): pos = numpy.nonzero(numpy.logical_not(nodeonFS)) if not (any(HOflag) or any(SSAflag)): md.flowequation.vertex_equation[pos] = 0 pos = numpy.nonzero(nodeonSSAHO) md.flowequation.vertex_equation[pos] = 6 pos = numpy.nonzero(nodeonHOFS) md.flowequation.vertex_equation[pos] = 7 pos = numpy.nonzero(nodeonSSAFS) md.flowequation.vertex_equation[pos] = 8 #figure out solution types md.flowequation.isSIA = any(md.flowequation.element_equation == 1) md.flowequation.isSSA = any(md.flowequation.element_equation == 2) md.flowequation.isL1L2 = any(md.flowequation.element_equation == 3) md.flowequation.isHO = any(md.flowequation.element_equation == 4) md.flowequation.isFS = any(md.flowequation.element_equation == 5) return md #Check that tiling can work: if any(md.flowequation.borderSSA) and any( md.flowequation.borderHO) and any( md.flowequation.borderHO + md.flowequation.borderSSA != 1): raise TypeError("error coupling domain too irregular") if any(md.flowequation.borderSSA) and any( md.flowequation.borderFS) and any( md.flowequation.borderFS + md.flowequation.borderSSA != 1): raise TypeError("error coupling domain too irregular") if any(md.flowequation.borderFS) and any(md.flowequation.borderHO) and any( md.flowequation.borderHO + md.flowequation.borderFS != 1): raise TypeError("error coupling domain too irregular") return md
def bamg(md, *kwargs): """ BAMG - mesh generation Available options (for more details see ISSM website http://issm.jpl.nasa.gov/): - domain : followed by an ARGUS file that prescribes the domain outline - hmin : minimum edge length (default is 10^-100) - hmax : maximum edge length (default is 10^100) - hVertices : imposed edge length for each vertex (geometry or mesh) - hminVertices : minimum edge length for each vertex (mesh) - hmaxVertices : maximum edge length for each vertex (mesh) - anisomax : maximum ratio between the smallest and largest edges (default is 10^30) - coeff : coefficient applied to the metric (2-> twice as many elements, default is 1) - cutoff : scalar used to compute the metric when metric type 2 or 3 are applied - err : error used to generate the metric from a field - errg : geometric error (default is 0.1) - field : field of the model that will be used to compute the metric to apply several fields, use one column per field - gradation : maximum ratio between two adjacent edges - Hessiantype : 0 -> use double P2 projection (default) 1 -> use Green formula - KeepVertices : try to keep initial vertices when adaptation is done on an existing mesh (default 1) - MaxCornerAngle : maximum angle of corners in degree (default is 10) - maxnbv : maximum number of vertices used to allocate memory (default is 10^6) - maxsubdiv : maximum subdivision of exisiting elements (default is 10) - metric : matrix (numberofnodes x 3) used as a metric - Metrictype : 1 -> absolute error c/(err coeff^2) * Abs(H) (default) 2 -> relative error c/(err coeff^2) * Abs(H)/max(s,cutoff*max(s)) 3 -> rescaled absolute error c/(err coeff^2) * Abs(H)/(smax-smin) - nbjacoby : correction used by Hessiantype=1 (default is 1) - nbsmooth : number of metric smoothing procedure (default is 3) - omega : relaxation parameter of the smoothing procedure (default is 1.8) - power : power applied to the metric (default is 1) - splitcorners : split triangles whuch have 3 vertices on the outline (default is 1) - geometricalmetric : take the geometry into account to generate the metric (default is 0) - verbose : level of verbosity (default is 1) - rifts : followed by an ARGUS file that prescribes the rifts - toltip : tolerance to move tip on an existing point of the domain outline - tracks : followed by an ARGUS file that prescribes the tracks that the mesh will stick to - RequiredVertices : mesh vertices that are required. [x,y,ref]; ref is optional - tol : if the distance between 2 points of the domain outline is less than tol, they will be merged Examples: md=bamg(md,'domain','DomainOutline.exp','hmax',3000); md=bamg(md,'field',[md.inversion.vel_obs md.geometry.thickness],'hmax',20000,'hmin',1000); md=bamg(md,'metric',A,'hmin',1000,'hmax',20000,'gradation',3,'anisomax',1); """ #process options options = pairoptions(**kwargs) # options=deleteduplicates(options,1); #initialize the structures required as input of Bamg bamg_options = OrderedDict() bamg_geometry = bamggeom() bamg_mesh = bamgmesh() # Bamg Geometry parameters {{{ if options.exist('domain'): #Check that file exists domainfile = options.getfieldvalue('domain') if not os.path.exists(domainfile): raise IOError("bamg error message: file '%s' not found" % domainfile) domain = expread(domainfile) #Build geometry count = 0 for i, domaini in enumerate(domain): #Check that the domain is closed if (domaini['x'][0] != domaini['x'][-1] or domaini['y'][0] != domaini['y'][-1]): raise RuntimeError( "bamg error message: all contours provided in ''domain'' should be closed" ) #Checks that all holes are INSIDE the principle domain outline if i: flags = ContourToNodes(domaini['x'], domaini['y'], domainfile, 0) if numpy.any(numpy.logical_not(flags)): raise RuntimeError( "bamg error message: All holes should be strictly inside the principal domain" ) #Add all points to bamg_geometry nods = domaini['nods'] - 1 #the domain are closed 0=end bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, numpy.hstack( (domaini['x'][0:nods].reshape(-1, 1), domaini['y'][0:nods].reshape(-1, 1), numpy.ones( (nods, 1)))))) bamg_geometry.Edges = numpy.vstack( (bamg_geometry.Edges, numpy.hstack( (numpy.arange(count + 1, count + nods + 1).reshape(-1, 1), numpy.hstack((numpy.arange(count + 2, count + nods + 1), count + 1)).reshape(-1, 1), 1. * numpy.ones( (nods, 1)))))) if i: bamg_geometry.SubDomains = numpy.vstack( (bamg_geometry.SubDomains, [2, count + 1, 1, 1])) #update counter count += nods #take care of rifts if options.exist('rifts'): #Check that file exists riftfile = options.getfieldvalue('rifts') if not os.path.exists(riftfile): raise IOError("bamg error message: file '%s' not found" % riftfile) rift = expread(riftfile) for i, rifti in enumerate(rift): #detect whether all points of the rift are inside the domain flags = ContourToNodes(rifti['x'], rifti['y'], domain[0], 0) if numpy.all(numpy.logical_not(flags)): raise RuntimeError( "one rift has all its points outside of the domain outline" ) elif numpy.any(numpy.logical_not(flags)): #We LOTS of work to do print( "Rift tip outside of or on the domain has been detected and is being processed..." ) #check that only one point is outside (for now) if numpy.sum(numpy.logical_not(flags).astype(int)) != 1: raise RuntimeError( "bamg error message: only one point outside of the domain is supported yet" ) #Move tip outside to the first position if not flags[0]: #OK, first point is outside (do nothing), pass elif not flags[-1]: rifti['x'] = numpy.flipud(rifti['x']) rifti['y'] = numpy.flipud(rifti['y']) else: raise RuntimeError( "bamg error message: only a rift tip can be outside of the domain" ) #Get cordinate of intersection point x1 = rifti['x'][0] y1 = rifti['y'][0] x2 = rifti['x'][1] y2 = rifti['y'][1] for j in range(0, numpy.size(domain[0]['x']) - 1): if SegIntersect( numpy.array([[x1, y1], [x2, y2]]), numpy.array( [[domain[0]['x'][j], domain[0]['y'][j]], [ domain[0]['x'][j + 1], domain[0]['y'][j + 1] ]])): #Get position of the two nodes of the edge in domain i1 = j i2 = j + 1 #rift is crossing edge [i1 i2] of the domain #Get coordinate of intersection point (http://mathworld.wolfram.com/Line-LineIntersection.html) x3 = domain[0]['x'][i1] y3 = domain[0]['y'][i1] x4 = domain[0]['x'][i2] y4 = domain[0]['y'][i2] # x=det([det([x1 y1; x2 y2]) x1-x2;det([x3 y3; x4 y4]) x3-x4])/det([x1-x2 y1-y2;x3-x4 y3-y4]); # y=det([det([x1 y1; x2 y2]) y1-y2;det([x3 y3; x4 y4]) y3-y4])/det([x1-x2 y1-y2;x3-x4 y3-y4]); x = numpy.linalg.det( numpy.array([[ numpy.linalg.det( numpy.array([[x1, y1], [x2, y2]])), x1 - x2 ], [ numpy.linalg.det( numpy.array([[x3, y3], [x4, y4]])), x3 - x4 ]])) / numpy.linalg.det( numpy.array([[ x1 - x2, y1 - y2 ], [x3 - x4, y3 - y4]])) y = numpy.linalg.det( numpy.array([[ numpy.linalg.det( numpy.array([[x1, y1], [x2, y2]])), y1 - y2 ], [ numpy.linalg.det( numpy.array([[x3, y3], [x4, y4]])), y3 - y4 ]])) / numpy.linalg.det( numpy.array([[ x1 - x2, y1 - y2 ], [x3 - x4, y3 - y4]])) segdis = sqrt((x4 - x3)**2 + (y4 - y3)**2) tipdis = numpy.array([ sqrt((x - x3)**2 + (y - y3)**2), sqrt((x - x4)**2 + (y - y4)**2) ]) if numpy.min( tipdis) / segdis < options.getfieldvalue( 'toltip', 0): print("moving tip-domain intersection point") #Get position of the closer point if tipdis[0] > tipdis[1]: pos = i2 else: pos = i1 #This point is only in Vertices (number pos). #OK, now we can add our own rift nods = rifti['nods'] - 1 bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, numpy.hstack( (rifti['x'][1:].reshape(-1, 1), rifti['y'][1:].reshape(-1, 1), numpy.ones((nods, 1)))))) bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges,\ numpy.array([[pos,count+1,(1+i)]]),\ numpy.hstack((numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),(1+i)*numpy.ones((nods-1,1)))))) count += nods break else: #Add intersection point to Vertices bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, numpy.array([[x, y, 1]]))) count += 1 #Decompose the crossing edge into 2 subedges pos = numpy.nonzero( numpy.logical_and( bamg_geometry.Edges[:, 0] == i1, bamg_geometry.Edges[:, 1] == i2))[0] if not pos: raise RuntimeError( "bamg error message: a problem occurred..." ) bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges[0:pos-1,:],\ numpy.array([[bamg_geometry.Edges[pos,0],count ,bamg_geometry.Edges[pos,2]]]),\ numpy.array([[count ,bamg_geometry.Edges[pos,1],bamg_geometry.Edges[pos,2]]]),\ bamg_geometry.Edges[pos+1:,:])) #OK, now we can add our own rift nods = rifti['nods'] - 1 bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, numpy.hstack( (rifti['x'][1:].reshape(-1, 1), rifti['y'][1:].reshape(-1, 1), numpy.ones((nods, 1)))))) bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges,\ numpy.array([[count,count+1,2]]),\ numpy.hstack((numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),(1+i)*numpy.ones((nods-1,1)))))) count += nods break else: nods = rifti['nods'] - 1 bamg_geometry.Vertices = numpy.vstack( bamg_geometry.Vertices, numpy.hstack(rifti['x'][:], rifti['y'][:], numpy.ones((nods + 1, 1)))) bamg_geometry.Edges = numpy.vstack( bamg_geometry.Edges, numpy.hstack( numpy.arange(count + 1, count + nods).reshape(-1, 1), numpy.arange(count + 2, count + nods + 1).reshape(-1, 1), i * numpy.ones((nods, 1)))) count = +nods + 1 #Deal with tracks if options.exist('tracks'): #read tracks track = options.getfieldvalue('tracks') if all(isinstance(track, str)): A = expread(track) track = numpy.hstack((A.x.reshape(-1, 1), A.y.reshape(-1, 1))) else: track = float(track) #for some reason, it is of class "single" if numpy.size(track, axis=1) == 2: track = numpy.hstack((track, 3. * numpy.ones( (size(track, axis=0), 1)))) #only keep those inside flags = ContourToNodes(track[:, 0], track[:, 1], domainfile, 0) track = track[numpy.nonzero(flags), :] #Add all points to bamg_geometry nods = numpy.size(track, axis=0) bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, track)) bamg_geometry.Edges = numpy.vstack( (bamg_geometry.Edges, numpy.hstack( (numpy.arange(count + 1, count + nods).reshape(-1, 1), numpy.arange(count + 2, count + nods + 1).reshape(-1, 1), 3. * numpy.ones((nods - 1, 1)))))) #update counter count += nods #Deal with vertices that need to be kept by mesher if options.exist('RequiredVertices'): #recover RequiredVertices requiredvertices = options.getfieldvalue( 'RequiredVertices') #for some reason, it is of class "single" if numpy.size(requiredvertices, axis=1) == 2: requiredvertices = numpy.hstack( (requiredvertices, 4. * numpy.ones( (numpy.size(requiredvertices, axis=0), 1)))) #only keep those inside flags = ContourToNodes(requiredvertices[:, 0], requiredvertices[:, 1], domainfile, 0)[0] requiredvertices = requiredvertices[numpy.nonzero(flags)[0], :] #Add all points to bamg_geometry nods = numpy.size(requiredvertices, axis=0) bamg_geometry.Vertices = numpy.vstack( (bamg_geometry.Vertices, requiredvertices)) #update counter count += nods #process geom #bamg_geometry=processgeometry(bamg_geometry,options.getfieldvalue('tol',float(nan)),domain[0]) elif isinstance(md.private.bamg, dict) and 'geometry' in md.private.bamg: bamg_geometry = bamggeom(md.private.bamg['geometry'].__dict__) else: #do nothing... pass #}}} # Bamg Mesh parameters {{{ if not options.exist('domain') and md.mesh.numberofvertices and m.strcmp( md.mesh.elementtype(), 'Tria'): if isinstance(md.private.bamg, dict) and 'mesh' in md.private.bamg: bamg_mesh = bamgmesh(md.private.bamg['mesh'].__dict__) else: bamg_mesh.Vertices = numpy.hstack( (md.mesh.x.reshape(-1, 1), md.mesh.y.reshape(-1, 1), numpy.ones((md.mesh.numberofvertices, 1)))) bamg_mesh.Triangles = numpy.hstack( (md.mesh.elements, numpy.ones((md.mesh.numberofelements, 1)))) if isinstance(md.rifts.riftstruct, dict): raise TypeError( "bamg error message: rifts not supported yet. Do meshprocessrift AFTER bamg" ) #}}} # Bamg Options {{{ bamg_options['Crack'] = options.getfieldvalue('Crack', 0) bamg_options['anisomax'] = options.getfieldvalue('anisomax', 10.**30) bamg_options['coeff'] = options.getfieldvalue('coeff', 1.) bamg_options['cutoff'] = options.getfieldvalue('cutoff', 10.**-5) bamg_options['err'] = options.getfieldvalue('err', numpy.array([[0.01]])) bamg_options['errg'] = options.getfieldvalue('errg', 0.1) bamg_options['field'] = options.getfieldvalue('field', numpy.empty((0, 1))) bamg_options['gradation'] = options.getfieldvalue('gradation', 1.5) bamg_options['Hessiantype'] = options.getfieldvalue('Hessiantype', 0) bamg_options['hmin'] = options.getfieldvalue('hmin', 10.**-100) bamg_options['hmax'] = options.getfieldvalue('hmax', 10.**100) bamg_options['hminVertices'] = options.getfieldvalue( 'hminVertices', numpy.empty((0, 1))) bamg_options['hmaxVertices'] = options.getfieldvalue( 'hmaxVertices', numpy.empty((0, 1))) bamg_options['hVertices'] = options.getfieldvalue('hVertices', numpy.empty((0, 1))) bamg_options['KeepVertices'] = options.getfieldvalue('KeepVertices', 1) bamg_options['MaxCornerAngle'] = options.getfieldvalue( 'MaxCornerAngle', 10.) bamg_options['maxnbv'] = options.getfieldvalue('maxnbv', 10**6) bamg_options['maxsubdiv'] = options.getfieldvalue('maxsubdiv', 10.) bamg_options['metric'] = options.getfieldvalue('metric', numpy.empty( (0, 1))) bamg_options['Metrictype'] = options.getfieldvalue('Metrictype', 0) bamg_options['nbjacobi'] = options.getfieldvalue('nbjacobi', 1) bamg_options['nbsmooth'] = options.getfieldvalue('nbsmooth', 3) bamg_options['omega'] = options.getfieldvalue('omega', 1.8) bamg_options['power'] = options.getfieldvalue('power', 1.) bamg_options['splitcorners'] = options.getfieldvalue('splitcorners', 1) bamg_options['geometricalmetric'] = options.getfieldvalue( 'geometricalmetric', 0) bamg_options['random'] = options.getfieldvalue('rand', True) bamg_options['verbose'] = options.getfieldvalue('verbose', 1) #}}} #call Bamg [bamgmesh_out, bamggeom_out] = BamgMesher(bamg_mesh.__dict__, bamg_geometry.__dict__, bamg_options) # plug results onto model md.private.bamg = OrderedDict() md.private.bamg['mesh'] = bamgmesh(bamgmesh_out) md.private.bamg['geometry'] = bamggeom(bamggeom_out) md.mesh = mesh2d() md.mesh.x = bamgmesh_out['Vertices'][:, 0].copy() md.mesh.y = bamgmesh_out['Vertices'][:, 1].copy() md.mesh.elements = bamgmesh_out['Triangles'][:, 0:3].astype(int) md.mesh.edges = bamgmesh_out['IssmEdges'].astype(int) md.mesh.segments = bamgmesh_out['IssmSegments'][:, 0:3].astype(int) md.mesh.segmentmarkers = bamgmesh_out['IssmSegments'][:, 3].astype(int) #Fill in rest of fields: md.mesh.numberofelements = numpy.size(md.mesh.elements, axis=0) md.mesh.numberofvertices = numpy.size(md.mesh.x) md.mesh.numberofedges = numpy.size(md.mesh.edges, axis=0) md.mesh.vertexonboundary = numpy.zeros(md.mesh.numberofvertices, bool) md.mesh.vertexonboundary[md.mesh.segments[:, 0:2] - 1] = True md.mesh.elementconnectivity = md.private.bamg['mesh'].ElementConnectivity md.mesh.elementconnectivity[numpy.nonzero( numpy.isnan(md.mesh.elementconnectivity))] = 0 md.mesh.elementconnectivity = md.mesh.elementconnectivity.astype(int) #Check for orphan if numpy.any( numpy.logical_not( numpy.in1d(numpy.arange(1, md.mesh.numberofvertices + 1), md.mesh.elements.flat))): raise RuntimeError( "Output mesh has orphans. Decrease MaxCornerAngle to prevent outside points (ex: 0.01)" ) return md
def WriteData(fid, **kwargs): """ WRITEDATA - write model field in binary file Usage: WriteData(fid,varargin) """ #process options options = pairoptions.pairoptions(**kwargs) #Get data properties if options.exist('object'): #This is an object field, construct enum and data obj = options.getfieldvalue('object') fieldname = options.getfieldvalue('fieldname') classname = options.getfieldvalue( 'class', str(type(obj)).rsplit('.')[-1].split("'")[0]) if options.exist('enum'): enum = options.getfieldvalue('enum') else: enum = BuildEnum(classname + '_' + fieldname) data = getattr(obj, fieldname) else: #No processing required data = options.getfieldvalue('data') enum = options.getfieldvalue('enum') format = options.getfieldvalue('format') mattype = options.getfieldvalue('mattype', 0) #only required for matrices timeserieslength = options.getfieldvalue('timeserieslength', -1) #Process sparse matrices # if issparse(data), # data=full(data); # end #Scale data if necesarry if options.exist('scale'): scale = options.getfieldvalue('scale') if numpy.size(data) > 1: if numpy.size(data, 0) == timeserieslength: data = numpy.array(data) data[0:-1, :] = scale * data[0:-1, :] else: data = scale * data else: data = scale * data if numpy.size(data) > 1: if numpy.size(data, 0) == timeserieslength: yts = 365.0 * 24.0 * 3600.0 data[-1, :] = yts * data[-1, :] #Step 1: write the enum to identify this record uniquely fid.write(struct.pack('i', enum)) #Step 2: write the data itself. if m.strcmpi(format, 'Boolean'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0]) #first write length of record fid.write(struct.pack('i', 4 + 4)) #1 bool (disguised as an int)+code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write integer fid.write(struct.pack( 'i', int(data))) #send an int, not easy to send a bool # }}} elif m.strcmpi(format, 'Integer'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0]) #first write length of record fid.write(struct.pack('i', 4 + 4)) #1 integer + code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write integer fid.write(struct.pack('i', data)) # }}} elif m.strcmpi(format, 'Double'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0]) #first write length of record fid.write(struct.pack('i', 8 + 4)) #1 double+code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write double fid.write(struct.pack('d', data)) # }}} elif m.strcmpi(format, 'String'): # {{{ #first write length of record fid.write(struct.pack('i', len(data) + 4 + 4)) #string + string size + code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write string fid.write(struct.pack('i', len(data))) fid.write(struct.pack('%ds' % len(data), data)) # }}} elif m.strcmpi(format, 'BooleanMat'): # {{{ if isinstance(data, bool): data = numpy.array([data]) elif isinstance(data, (list, tuple)): data = numpy.array(data).reshape(-1, 1) if numpy.ndim(data) == 1: if numpy.size(data): data = data.reshape(numpy.size(data), 1) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if s[0] == 1 and s[1] == 1 and math.isnan(data[0][0]): s = (0, 0) #first write length of record fid.write(struct.pack( 'i', 4 + 4 + 8 * s[0] * s[1] + 4 + 4)) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in range(s[0]): for j in range(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'IntMat'): # {{{ if isinstance(data, int): data = numpy.array([data]) elif isinstance(data, (list, tuple)): data = numpy.array(data).reshape(-1, 1) if numpy.ndim(data) == 1: if numpy.size(data): data = data.reshape(numpy.size(data), 1) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if s[0] == 1 and s[1] == 1 and math.isnan(data[0][0]): s = (0, 0) #first write length of record fid.write(struct.pack( 'i', 4 + 4 + 8 * s[0] * s[1] + 4 + 4)) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in range(s[0]): for j in range(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'DoubleMat'): # {{{ if isinstance(data, (bool, int, float)): data = numpy.array([data]) elif isinstance(data, (list, tuple)): data = numpy.array(data).reshape(-1, 1) if numpy.ndim(data) == 1: if numpy.size(data): data = data.reshape(numpy.size(data), 1) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if s[0] == 1 and s[1] == 1 and math.isnan(data[0][0]): s = (0, 0) #first write length of record recordlength = 4 + 4 + 8 * s[0] * s[1] + 4 + 4 #2 integers (32 bits) + the double matrix + code + matrix type if recordlength > 2**31: raise ValueError( 'field %s cannot be marshalled because it is larger than 4^31 bytes!' % EnumToString(enum)[0]) fid.write( struct.pack('i', recordlength) ) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in range(s[0]): for j in range(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'MatArray'): # {{{ #first get length of record recordlength = 4 + 4 #number of records + code for matrix in data: if isinstance(matrix, (bool, int, float)): matrix = numpy.array([matrix]) elif isinstance(matrix, (list, tuple)): matrix = numpy.array(matrix).reshape(-1, 1) if numpy.ndim(matrix) == 1: if numpy.size(matrix): matrix = matrix.reshape(numpy.size(matrix), 1) else: matrix = matrix.reshape(0, 0) s = matrix.shape recordlength += 4 * 2 + s[0] * s[ 1] * 8 #row and col of matrix + matrix of doubles #write length of record fid.write(struct.pack('i', recordlength)) #write data code: fid.write(struct.pack('i', FormatToCode(format))) #write data, first number of records fid.write(struct.pack('i', len(data))) #write each matrix: for matrix in data: if isinstance(matrix, (bool, int, float)): matrix = numpy.array([matrix]) elif isinstance(matrix, (list, tuple)): matrix = numpy.array(matrix).reshape(-1, 1) if numpy.ndim(matrix) == 1: matrix = matrix.reshape(numpy.size(matrix), 1) s = matrix.shape fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in range(s[0]): for j in range(s[1]): fid.write(struct.pack('d', float(matrix[i][j]))) # }}} elif m.strcmpi(format, 'StringArray'): # {{{ #first get length of record recordlength = 4 + 4 #for length of array + code for string in data: recordlength += 4 + len(string) #for each string #write length of record fid.write(struct.pack('i', recordlength)) #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write length of string array fid.write(struct.pack('i', len(data))) #now write the strings for string in data: fid.write(struct.pack('i', len(string))) fid.write(struct.pack('%ds' % len(string), string)) # }}} else: # {{{ raise TypeError( 'WriteData error message: data type: %d not supported yet! (%s)' % (format, EnumToString(enum)[0]))
def buildlist(self, **kwargs): #{{{ for name, value in kwargs.items(): self.rawlist[name] = value #get figure number self.figurenumber = rawoptions.getfieldvalue('figure', 1) rawoptions.removefield('figure', 0) #get number of subplots numberofplots = Counter(x for sublist in rawlist for x in sublist if isinstance(x, str))['data'] self.numberofplots = numberofplots #figure out whether alloptions flag is on if rawoptions.getfieldvalue('alloptions', 'off') is 'on': allflag = 1 else: allflag = 0 #initialize self.list (will need a list of dict's (or nested dict) for numberofplots>1) #self.list=defaultdict(dict) for i in range(numberofplots): self.list[i] = pairoptions.pairoptions() #process plot options for i in range(len(rawlist)): #if alloptions flag is on, apply to all plots if (allflag and 'data' not in rawlist[i][0] and '#' not in rawlist[i][0]): for j in range(numberofplots): self.list[j].addfield(rawlist[i][0], rawlist[i][1]) elif '#' in rawlist[i][0]: #get subplots associated string = rawlist[i][0].split('#') plotnums = string[-1].split(',') field = string[0] #loop over plotnums for k in range(len(plotnums)): plotnum = plotnums[k] #Empty if not plotnum: continue # '#all' elif 'all' in plotnum: for j in range(numberofplots): self.list[j].addfield(field, rawlist[i][1]) # '#i-j' elif '-' in plotnum: nums = plotnum.split('-') if len(nums) != 2: continue if False in [x.isdigit() for x in nums]: raise ValueError( 'error: in option i-j both i and j must be integers' ) for j in range(int(nums[0]) - 1, int(nums[1])): self.list[j].addfield(field, rawlist[i][1]) # Deal with #i else: #assign to subplot if int(plotnum) > numberofplots: raise ValueError( 'error: %s cannot be assigned %d which exceeds the number of subplots' % (field, plotnum)) self.list[int(plotnum) - 1].addfield( field, rawlist[i][1]) else: #go through all subplots and assign key-value pairs j = 0 while j <= numberofplots - 1: if not self.list[j].exist(rawlist[i][0]): self.list[j].addfield(rawlist[i][0], rawlist[i][1]) break else: j = j + 1 if j + 1 > numberofplots: print(("WARNING: too many instances of '%s' in options" % rawlist[i][0]))
def setmask(md, floatingicename, groundedicename, *args): """ SETMASK - establish boundaries between grounded and floating ice. By default, ice is considered grounded. The contour floatingicename defines nodes for which ice is floating. The contour groundedicename defines nodes inside an floatingice, that are grounded (ie: ice rises, islands, etc ...) All input files are in the Argus format (extension .exp). Usage: md=setmask(md,floatingicename,groundedicename) Examples: md=setmask(md,'all',''); md=setmask(md,'Iceshelves.exp','Islands.exp'); """ #some checks on list of arguments print type(md) if not isinstance(md,model): raise TypeError("setmask error message") if len(args)%2: raise TypeError("odd number of arguments provided in setmask") #process options options=pairoptions.pairoptions(*args) #Get assigned fields x = md.mesh.x y = md.mesh.y elements = md.mesh.elements #Assign elementonfloatingice, elementongroundedice, vertexongroundedice and vertexonfloatingice. Only change at your own peril! This is synchronized heavily with the GroundingLineMigration module. {{{ elementonfloatingice = FlagElements(md, floatingicename) elementongroundedice = FlagElements(md, groundedicename) #Because groundedice nodes and elements can be included into an floatingice, we need to update. Remember, all the previous #arrays come from domain outlines that can intersect one another: elementonfloatingice = np.logical_and(elementonfloatingice,np.logical_not(elementongroundedice)) elementongroundedice = np.logical_not(elementonfloatingice) #the order here is important. we choose vertexongroundedice as default on the grounding line. vertexonfloatingice = np.zeros(md.mesh.numberofvertices,'bool') vertexongroundedice = np.zeros(md.mesh.numberofvertices,'bool') vertexongroundedice[md.mesh.elements[np.nonzero(elementongroundedice),:]-1]=True vertexonfloatingice[np.nonzero(np.logical_not(vertexongroundedice))]=True #}}} #level sets md.mask.groundedice_levelset = -1.*np.ones(md.mesh.numberofvertices) md.mask.groundedice_levelset[md.mesh.elements[np.nonzero(elementongroundedice),:]-1]=1. if(len(args)): md.mask.ice_levelset = 1.*np.ones(md.mesh.numberofvertices) icedomainfile = options.getfieldvalue('icedomain','none') if not os.path.exists(icedomainfile): raise IOError("setmask error message: ice domain file '%s' not found." % icedomainfile) #use contourtomesh to set ice values inside ice domain vertexinsideicedomain,elementinsideicedomain=ContourToMesh(elements,x,y,icedomainfile,'node',1) md.mask.ice_levelset[np.nonzero(vertexinsideicedomain)[0]] = -1. else: md.mask.ice_levelset = -1.*np.ones(md.mesh.numberofvertices) return md
def solve(md, solutionstring, *args): """ SOLVE - apply solution sequence for this model Usage: md=solve(md,solutionstring,varargin) where varargin is a list of paired arguments of string OR enums solution types available comprise: - 'Stressbalance' or 'sb' - 'Masstransport' or 'mt' - 'Thermal' or 'th' - 'Steadystate' or 'ss' - 'Transient' or 'tr' - 'Balancethickness' or 'mc' - 'Balancevelocity' or 'bv' - 'BedSlope' or 'bsl' - 'SurfaceSlope' or 'ssl' - 'Hydrology' or 'hy' - 'DamageEvolution' or 'da' - 'Gia' or 'gia' - 'Sealevelrise' or 'slr' extra options: - loadonly : does not solve. only load results - checkconsistency : 'yes' or 'no' (default is 'yes'), ensures checks on consistency of model - restart: 'directory name (relative to the execution directory) where the restart file is located. Examples: md=solve(md,'Stressbalance'); md=solve(md,'sb'); """ #recover and process solve options if solutionstring.lower() == 'sb' or solutionstring.lower( ) == 'stressbalance': solutionstring = 'StressbalanceSolution' elif solutionstring.lower() == 'mt' or solutionstring.lower( ) == 'masstransport': solutionstring = 'MasstransportSolution' elif solutionstring.lower() == 'th' or solutionstring.lower() == 'thermal': solutionstring = 'ThermalSolution' elif solutionstring.lower() == 'st' or solutionstring.lower( ) == 'steadystate': solutionstring = 'SteadystateSolution' elif solutionstring.lower() == 'tr' or solutionstring.lower( ) == 'transient': solutionstring = 'TransientSolution' elif solutionstring.lower() == 'mc' or solutionstring.lower( ) == 'balancethickness': solutionstring = 'BalancethicknessSolution' elif solutionstring.lower() == 'bv' or solutionstring.lower( ) == 'balancevelocity': solutionstring = 'BalancevelocitySolution' elif solutionstring.lower() == 'bsl' or solutionstring.lower( ) == 'bedslope': solutionstring = 'BedSlopeSolution' elif solutionstring.lower() == 'ssl' or solutionstring.lower( ) == 'surfaceslope': solutionstring = 'SurfaceSlopeSolution' elif solutionstring.lower() == 'hy' or solutionstring.lower( ) == 'hydrology': solutionstring = 'HydrologySolution' elif solutionstring.lower() == 'da' or solutionstring.lower( ) == 'damageevolution': solutionstring = 'DamageEvolutionSolution' elif solutionstring.lower() == 'gia' or solutionstring.lower() == 'gia': solutionstring = 'GiaSolution' elif solutionstring.lower() == 'slr' or solutionstring.lower( ) == 'sealevelrise': solutionstring = 'SealevelriseSolution' else: raise ValueError("solutionstring '%s' not supported!" % solutionstring) options = pairoptions('solutionstring', solutionstring, *args) #recover some fields md.private.solution = solutionstring cluster = md.cluster if options.getfieldvalue('batch', 'no') == 'yes': batch = 1 else: batch = 0 #check model consistency if options.getfieldvalue('checkconsistency', 'yes') == 'yes': print "checking model consistency" ismodelselfconsistent(md) #First, build a runtime name that is unique restart = options.getfieldvalue('restart', '') if restart == 1: pass #do nothing else: if restart: md.private.runtimename = restart else: if options.getfieldvalue('runtimename', True): c = datetime.datetime.now() md.private.runtimename = "%s-%02i-%02i-%04i-%02i-%02i-%02i-%i" % ( md.miscellaneous.name, c.month, c.day, c.year, c.hour, c.minute, c.second, os.getpid()) else: md.private.runtimename = md.miscellaneous.name #if running qmu analysis, some preprocessing of dakota files using models #fields needs to be carried out. if md.qmu.isdakota: md = preqmu(md, options) #Do we load results only? if options.getfieldvalue('loadonly', False): md = loadresultsfromcluster(md) return md #Write all input files marshall(md) # bin file md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits') # toolkits file cluster.BuildQueueScript(md.private.runtimename, md.miscellaneous.name, md.private.solution, md.settings.io_gather, md.debug.valgrind, md.debug.gprof, md.qmu.isdakota, md.transient.isoceancoupling) # queue file #Stop here if batch mode if options.getfieldvalue('batch', 'no') == 'yes': print 'batch mode requested: not launching job interactively' print 'launch solution sequence on remote cluster by hand' return md #Upload all required files: modelname = md.miscellaneous.name filelist = [ modelname + '.bin ', modelname + '.toolkits ', modelname + '.queue ' ] if md.qmu.isdakota: filelist.append(modelname + '.qmu.in') if not restart: cluster.UploadQueueJob(md.miscellaneous.name, md.private.runtimename, filelist) #Launch job cluster.LaunchQueueJob(md.miscellaneous.name, md.private.runtimename, filelist, restart, batch) #wait on lock if md.settings.waitonlock > 0: #we wait for the done file islock = waitonlock(md) if islock == 0: #no results to be loaded print 'The results must be loaded manually with md=loadresultsfromcluster(md).' else: #load results print 'loading results from cluster' md = loadresultsfromcluster(md) #post processes qmu results if necessary if md.qmu.isdakota: if not strncmpi(options['keep'], 'y', 1): shutil.rmtree('qmu' + str(os.getpid())) return md
def WriteData(fid, prefix, *args): """ WRITEDATA - write model field in binary file Usage: WriteData(fid,varargin) """ #process options options = pairoptions.pairoptions(*args) #Get data properties if options.exist('object'): #This is an object field, construct enum and data obj = options.getfieldvalue('object') fieldname = options.getfieldvalue('fieldname') classname = options.getfieldvalue( 'class', str(type(obj)).rsplit('.')[-1].split("'")[0]) name = options.getfieldvalue('name', prefix + '.' + fieldname) if options.exist('data'): data = options.getfieldvalue('data') else: data = getattr(obj, fieldname) else: #No processing required data = options.getfieldvalue('data') name = options.getfieldvalue('name') format = options.getfieldvalue('format') mattype = options.getfieldvalue('mattype', 0) #only required for matrices timeserieslength = options.getfieldvalue('timeserieslength', -1) #Process sparse matrices # if issparse(data), # data=full(data); # end #Scale data if necesarry if options.exist('scale'): scale = options.getfieldvalue('scale') if np.size(data) > 1: if np.size(data, 0) == timeserieslength: data = np.array(data) data[0:-1, :] = scale * data[0:-1, :] else: data = scale * data else: data = scale * data if np.size(data) > 1: if np.size(data, 0) == timeserieslength: yts = options.getfieldvalue('yts') data[-1, :] = yts * data[-1, :] #Step 1: write the enum to identify this record uniquely fid.write(struct.pack('i', len(name))) fid.write(struct.pack('%ds' % len(name), name)) #Step 2: write the data itself. if m.strcmpi(format, 'Boolean'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0]) #first write length of record fid.write(struct.pack('i', 4 + 4)) #1 bool (disguised as an int)+code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write integer fid.write(struct.pack( 'i', int(data))) #send an int, not easy to send a bool # }}} elif m.strcmpi(format, 'Integer'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0]) #first write length of record fid.write(struct.pack('i', 4 + 4)) #1 integer + code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write integer fid.write(struct.pack('i', data)) # }}} elif m.strcmpi(format, 'Double'): # {{{ # if len(data) !=1: # raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0]) #first write length of record fid.write(struct.pack('i', 8 + 4)) #1 double+code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write double fid.write(struct.pack('d', data)) # }}} elif m.strcmpi(format, 'String'): # {{{ #first write length of record fid.write(struct.pack('i', len(data) + 4 + 4)) #string + string size + code #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write string fid.write(struct.pack('i', len(data))) fid.write(struct.pack('%ds' % len(data), data)) # }}} elif m.strcmpi(format, 'BooleanMat'): # {{{ if isinstance(data, bool): data = np.array([data]) elif isinstance(data, (list, tuple)): data = np.array(data).reshape(-1, ) if np.ndim(data) == 1: if np.size(data): data = data.reshape(np.size(data), ) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if np.ndim(data) == 2 and np.product(s) == 1 and np.all( np.isnan(data)): s = (0, 0) #first write length of record fid.write(struct.pack( 'i', 4 + 4 + 8 * np.product(s) + 4 + 4)) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix if np.ndim(data) == 1: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', 1)) for i in xrange(s[0]): fid.write(struct.pack('d', float( data[i]))) #get to the "c" convention, hence the transpose else: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in xrange(s[0]): for j in xrange(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'IntMat'): # {{{ if isinstance(data, (int, long)): data = np.array([data]) elif isinstance(data, (list, tuple)): data = np.array(data).reshape(-1, ) if np.ndim(data) == 1: if np.size(data): data = data.reshape(np.size(data), ) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if np.ndim(data) == 2 and np.product(s) == 1 and np.all( np.isnan(data)): s = (0, 0) #first write length of record fid.write(struct.pack( 'i', 4 + 4 + 8 * np.product(s) + 4 + 4)) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix if np.ndim(data) == 1: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', 1)) for i in xrange(s[0]): fid.write(struct.pack('d', float( data[i]))) #get to the "c" convention, hence the transpose else: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in xrange(s[0]): for j in xrange(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'DoubleMat'): # {{{ if isinstance(data, (bool, int, long, float)): data = np.array([data]) elif isinstance(data, (list, tuple)): data = np.array(data).reshape(-1, ) if np.ndim(data) == 1: if np.size(data): data = data.reshape(np.size(data), ) else: data = data.reshape(0, 0) #Get size s = data.shape #if matrix = NaN, then do not write anything if np.ndim(data) == 1 and np.product(s) == 1 and np.all( np.isnan(data)): s = (0, 0) #first write length of record recordlength = 4 + 4 + 8 * np.product(s) + 4 + 4 #2 integers (32 bits) + the double matrix + code + matrix type if recordlength > 4**31: raise ValueError( 'field %s cannot be marshalled because it is larger than 4^31 bytes!' % enum) fid.write( struct.pack('i', recordlength) ) #2 integers (32 bits) + the double matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #now write matrix if np.ndim(data) == 1: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', 1)) for i in xrange(s[0]): fid.write(struct.pack('d', float( data[i]))) #get to the "c" convention, hence the transpose else: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in xrange(s[0]): for j in xrange(s[1]): fid.write(struct.pack('d', float( data[i] [j]))) #get to the "c" convention, hence the transpose # }}} elif m.strcmpi(format, 'CompressedMat'): # {{{ if isinstance(data, (bool, int, long, float)): data = np.array([data]) elif isinstance(data, (list, tuple)): data = np.array(data).reshape(-1, ) if np.ndim(data) == 1: if np.size(data): data = data.reshape(np.size(data), ) else: data = data.reshape(0, 0) #Get size s = data.shape if np.ndim(data) == 1: n2 = 1 else: n2 = s[1] #if matrix = NaN, then do not write anything if np.ndim(data) == 1 and np.product(s) == 1 and np.all( np.isnan(data)): s = (0, 0) n2 = 0 #first write length of record recordlength = 4 + 4 + 8 + 8 + 1 * ( s[0] - 1 ) * n2 + 8 * n2 + 4 + 4 #2 integers (32 bits) + the matrix + code + matrix type if recordlength > 4**31: raise ValueError( 'field %s cannot be marshalled because it is larger than 4^31 bytes!' % enum) fid.write(struct.pack('i', recordlength) ) #2 integers (32 bits) + the matrix + code + matrix type #write data code and matrix type: fid.write(struct.pack('i', FormatToCode(format))) fid.write(struct.pack('i', mattype)) #Write offset and range A = data[0:s[0] - 1] offsetA = A.min() rangeA = A.max() - offsetA if rangeA == 0: A = A * 0 else: A = (A - offsetA) / rangeA * 255. #now write matrix if np.ndim(data) == 1: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', 1)) fid.write(struct.pack('d', float(offsetA))) fid.write(struct.pack('d', float(rangeA))) for i in xrange(s[0] - 1): fid.write(struct.pack('B', int(A[i]))) fid.write(struct.pack('d', float( data[s[0] - 1]))) #get to the "c" convention, hence the transpose elif np.product(s) > 0: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) fid.write(struct.pack('d', float(offsetA))) fid.write(struct.pack('d', float(rangeA))) for i in xrange(s[0] - 1): for j in xrange(s[1]): fid.write(struct.pack('B', int( A[i] [j]))) #get to the "c" convention, hence the transpose for j in xrange(s[1]): fid.write(struct.pack('d', float(data[s[0] - 1][j]))) # }}} elif m.strcmpi(format, 'MatArray'): # {{{ #first get length of record recordlength = 4 + 4 #number of records + code for matrix in data: if isinstance(matrix, (bool, int, long, float)): matrix = np.array([matrix]) elif isinstance(matrix, (list, tuple)): matrix = np.array(matrix).reshape(-1, ) if np.ndim(matrix) == 1: if np.size(matrix): matrix = matrix.reshape(np.size(matrix), ) else: matrix = matrix.reshape(0, 0) s = matrix.shape recordlength += 4 * 2 + np.product( s) * 8 #row and col of matrix + matrix of doubles #write length of record fid.write(struct.pack('i', recordlength)) #write data code: fid.write(struct.pack('i', FormatToCode(format))) #write data, first number of records fid.write(struct.pack('i', len(data))) #write each matrix: for matrix in data: if isinstance(matrix, (bool, int, long, float)): matrix = np.array([matrix]) elif isinstance(matrix, (list, tuple)): matrix = np.array(matrix).reshape(-1, ) if np.ndim(matrix) == 1: matrix = matrix.reshape(np.size(matrix), ) s = matrix.shape if np.ndim(data) == 1: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', 1)) for i in xrange(s[0]): fid.write( struct.pack('d', float(matrix[i])) ) #get to the "c" convention, hence the transpose else: fid.write(struct.pack('i', s[0])) fid.write(struct.pack('i', s[1])) for i in xrange(s[0]): for j in xrange(s[1]): fid.write(struct.pack('d', float(matrix[i][j]))) # }}} elif m.strcmpi(format, 'StringArray'): # {{{ #first get length of record recordlength = 4 + 4 #for length of array + code for string in data: recordlength += 4 + len(string) #for each string #write length of record fid.write(struct.pack('i', recordlength)) #write data code: fid.write(struct.pack('i', FormatToCode(format))) #now write length of string array fid.write(struct.pack('i', len(data))) #now write the strings for string in data: fid.write(struct.pack('i', len(string))) fid.write(struct.pack('%ds' % len(string), string)) # }}} else: # {{{ raise TypeError( 'WriteData error message: data type: %d not supported yet! (%s)' % (format, enum))
def solve(md, solutionenum, **kwargs): """ SOLVE - apply solution sequence for this model Usage: md=solve(md,solutionenum,varargin) where varargin is a list of paired arguments of string OR enums solution types available comprise: - StressbalanceSolutionEnum - MasstransportSolutionEnum - ThermalSolutionEnum - SteadystateSolutionEnum - TransientSolutionEnum - BalancethicknessSolutionEnum - BedSlopeSolutionEnum - SurfaceSlopeSolutionEnum - HydrologySolutionEnum - FlaimSolutionEnum extra options: - loadonly : does not solve. only load results - checkconsistency : 'yes' or 'no' (default is 'yes'), ensures checks on consistency of model - restart: 'directory name (relative to the execution directory) where the restart file is located. Examples: md=solve(md,StressbalanceSolutionEnum); """ #recover and process solve options if EnumToString(solutionenum)[0][-8:] != 'Solution': raise ValueError("solutionenum '%s' not supported!" % EnumToString(solutionenum)[0]) options = pairoptions(solutionenum=solutionenum, **kwargs) #recover some fields md.private.solution = solutionenum cluster = md.cluster #check model consistency if m.strcmpi(options.getfieldvalue('checkconsistency', 'yes'), 'yes'): print("checking model consistency") if solutionenum == FlaimSolutionEnum(): md.private.isconsistent = True md.mesh.checkconsistency(md, solutionenum) md.flaim.checkconsistency(md, solutionenum) if not md.private.isconsistent: raise RuntimeError("Model not consistent, see messages above.") else: ismodelselfconsistent(md) #First, build a runtime name that is unique restart = options.getfieldvalue('restart', '') if restart == 1: pass #do nothing else: if restart: md.private.runtimename = restart else: if options.getfieldvalue('runtimename', True): c = datetime.datetime.now() md.private.runtimename = "%s-%02i-%02i-%04i-%02i-%02i-%02i-%i" % ( md.miscellaneous.name, c.month, c.day, c.year, c.hour, c.minute, c.second, os.getpid()) else: md.private.runtimename = md.miscellaneous.name #if running qmu analysis, some preprocessing of dakota files using models #fields needs to be carried out. if md.qmu.isdakota: md = preqmu(md, options) #flaim analysis if solutionenum == FlaimSolutionEnum(): md = flaim_sol(md, options) [md.private.solution] = EnumToString(solutionenum) return md #Do we load results only? if options.getfieldvalue('loadonly', False): md = loadresultsfromcluster(md) return md #Write all input files marshall(md) # bin file md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits') # toolkits file cluster.BuildQueueScript(md.private.runtimename, md.miscellaneous.name, md.private.solution, md.settings.io_gather, md.debug.valgrind, md.debug.gprof, md.qmu.isdakota) # queue file #Stop here if batch mode if m.strcmpi(options.getfieldvalue('batch', 'no'), 'yes'): print('batch mode requested: not launching job interactively') print('launch solution sequence on remote cluster by hand') return md #Upload all required files: modelname = md.miscellaneous.name filelist = [ modelname + '.bin ', modelname + '.toolkits ', modelname + '.queue ' ] if md.qmu.isdakota: filelist.append(modelname + '.qmu.in') if not restart: cluster.UploadQueueJob(md.miscellaneous.name, md.private.runtimename, filelist) #Launch job cluster.LaunchQueueJob(md.miscellaneous.name, md.private.runtimename, filelist, restart) #wait on lock if md.settings.waitonlock > 0: #we wait for the done file islock = waitonlock(md) if islock == 0: #no results to be loaded print( 'The results must be loaded manually with md=loadresultsfromcluster(md).' ) else: #load results print('loading results from cluster') md = loadresultsfromcluster(md) #post processes qmu results if necessary if md.qmu.isdakota: if not strncmpi(options['keep'], 'y', 1): shutil.rmtree('qmu' + str(os.getpid())) return md