def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'mesh.x', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) md = checkfield(md, 'fieldname', 'mesh.y', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) md = checkfield(md, 'fieldname', 'mesh.z', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) md = checkfield(md, 'fieldname', 'mesh.elements', 'NaN', 1, 'Inf', 1, '>', 0, 'values', numpy.arange(1, md.mesh.numberofvertices + 1)) md = checkfield(md, 'fieldname', 'mesh.elements', 'size', [md.mesh.numberofelements, 6]) if numpy.any( numpy.logical_not( m.ismember(numpy.arange(1, md.mesh.numberofvertices + 1), md.mesh.elements))): md.checkmessage( "orphan nodes have been found. Check the mesh3dprisms outline") md = checkfield(md, 'fieldname', 'mesh.numberoflayers', '>=', 0) md = checkfield(md, 'fieldname', 'mesh.numberofelements', '>', 0) md = checkfield(md, 'fieldname', 'mesh.numberofvertices', '>', 0) md = checkfield(md, 'fieldname', 'mesh.vertexonbase', 'size', [md.mesh.numberofvertices], 'values', [0, 1]) md = checkfield(md, 'fieldname', 'mesh.vertexonsurface', 'size', [md.mesh.numberofvertices], 'values', [0, 1]) md = checkfield( md, 'fieldname', 'mesh.average_vertex_connectivity', '>=', 24, 'message', "'mesh.average_vertex_connectivity' should be at least 24 in 3d") return md
def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'mesh.x', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) md = checkfield(md, 'fieldname', 'mesh.y', 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices]) md = checkfield(md, 'fieldname', 'mesh.elements', 'NaN', 1, 'Inf', 1, '>', 0, 'values', np.arange(1, md.mesh.numberofvertices + 1)) md = checkfield(md, 'fieldname', 'mesh.elements', 'size', [md.mesh.numberofelements, 3]) if np.any( np.logical_not( m.ismember(np.arange(1, md.mesh.numberofvertices + 1), md.mesh.elements))): md.checkmessage( "orphan nodes have been found. Check the mesh outline") md = checkfield(md, 'fieldname', 'mesh.numberofelements', '>', 0) md = checkfield(md, 'fieldname', 'mesh.numberofvertices', '>', 0) md = checkfield( md, 'fieldname', 'mesh.average_vertex_connectivity', '>=', 9, 'message', "'mesh.average_vertex_connectivity' should be at least 9 in 2d") md = checkfield(md, 'fieldname', 'mesh.segments', 'NaN', 1, 'Inf', 1, '>', 0, 'size', [np.nan, 3]) if solution == 'ThermalSolution': md.checkmessage("thermal not supported for 2d mesh") return md
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 meshprocessoutsiderifts(md, domainoutline): """ MESHPROCESSOUTSIDERIFTS - process rifts when they touch the domain outline Usage: md=meshprocessoutsiderifts(md,domain) """ #go through rifts, and figure out which ones touch the domain outline for rift in md.rifts.riftstruct: #first, flag nodes that belong to the domain outline flags = ContourToMesh(md.mesh.elements, md.mesh.x, md.mesh.y, domainoutline, 'node', 0) tips = rift.tips outsidetips = tips[np.nonzero(flags[rift.tips - 1])[0]] #we have found outsidetips, tips that touch the domain outline. go through them for tip in outsidetips: #find tip in the segments, take first segment (there should be 2) that holds tip, #and node_connected_to_tip is the other node on this segment: tipindex = np.nonzero(rift.segments[:, 0] == tip)[0] if tipindex: tipindex = tipindex[0] node_connected_to_tip = rift.segments[tipindex, 1] else: tipindex = np.nonzero(rift.segments[:, 1] == tip)[0] tipindex = tipindex[0] node_connected_to_tip = rift.segments[tipindex, 1] #ok, we have the tip node, and the first node connected to it, on the rift. Now, #identify all the elements that are connected to the tip, and that are on the same #side of the rift. A = tip B = node_connected_to_tip elements = np.empty(0, int) while flags( B ): #as long as B does not belong to the domain outline, keep looking. #detect elements on edge A,B: edgeelements = ElementsFromEdge(md.mesh.elements, A, B) #rule out those we already detected already_detected = m.ismember(edgeelements, elements) nextelement = edgeelements( np.nonzero(np.logical_not(already_detected))[0]) #add new detected element to the list of elements we are looking for. elements = np.concatenate((elements, nextelement)) #new B: B = md.mesh.elements[ nextelement - 1, np.nonzero( np.logical_not( m.ismember(md.mesh.elements[ nextelement - 1, :], np.array([A, B]))))] #take the list of elements on one side of the rift that connect to the tip, #and duplicate the tip on them, so as to open the rift to the outside. num = np.size(md.mesh.x) + 1 md.mesh.x = np.concatenate((md.mesh.x, md.mesh.x[tip])) md.mesh.y = np.concatenate((md.mesh.y, md.mesh.y[tip])) md.mesh.numberofvertices = num #replace tip in elements newelements = md.mesh.elements[elements - 1, :] pos = np.nonzero(newelements == tip) newelements[pos] = num md.mesh.elements[elements - 1, :] = newelements rift.tips = np.concatenate((rift.tips, num)) #deal with segments tipsegments = np.nonzero( np.logical_or(md.mesh.segments[:, 0] == tip, md.mesh.segments[:, 1] == tip))[0] for segment_index in tipsegments: pos = np.nonzero( md.mesh.segments[segment_index, 0:2] != tip)[0] other_node = md.mesh.segments[segment_index, pos] if not isconnected(md.mesh.elements, other_node, tip): pos = np.nonzero(md.mesh.segments[segment_index, 0:2] == tip)[0] md.mesh.segments[segment_index, pos] = num #Fill in rest of fields: md.mesh.numberofelements = np.size(md.mesh.elements, axis=0) md.mesh.numberofvertices = np.size(md.mesh.x) md.mesh.vertexonboundary = np.zeros(np.size(md.mesh.x), bool) md.mesh.vertexonboundary[md.mesh.segments[:, 0:2] - 1] = True md.rifts.numrifts = length(md.rifts.riftstruct) return md
def extract(md, area): # {{{ """ extract - extract a model according to an Argus contour or flag list This routine extracts a submodel from a bigger model with respect to a given contour md 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 extract2d, 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 Usage: md2=extract(md,area) Examples: md2=extract(md,'Domain.exp') See also: EXTRUDE, COLLAPSE """ #copy model md1 = copy.deepcopy(md) #get elements that are inside area flag_elem = FlagElements(md1, area) if not np.any(flag_elem): raise RuntimeError("extracted model is empty") #kick out all elements with 3 dirichlets spc_elem = np.nonzero(np.logical_not(flag_elem))[0] spc_node = np.unique(md1.mesh.elements[spc_elem, :]) - 1 flag = np.ones(md1.mesh.numberofvertices) flag[spc_node] = 0 pos = np.nonzero( np.logical_not(np.sum(flag[md1.mesh.elements - 1], axis=1)))[0] flag_elem[pos] = 0 #extracted elements and nodes lists pos_elem = np.nonzero(flag_elem)[0] pos_node = np.unique(md1.mesh.elements[pos_elem, :]) - 1 #keep track of some fields numberofvertices1 = md1.mesh.numberofvertices numberofelements1 = md1.mesh.numberofelements numberofvertices2 = np.size(pos_node) numberofelements2 = np.size(pos_elem) flag_node = np.zeros(numberofvertices1) flag_node[pos_node] = 1 #Create Pelem and Pnode (transform old nodes in new nodes and same thing for the elements) Pelem = np.zeros(numberofelements1, int) Pelem[pos_elem] = np.arange(1, numberofelements2 + 1) Pnode = np.zeros(numberofvertices1, int) Pnode[pos_node] = np.arange(1, numberofvertices2 + 1) #renumber the elements (some node won't exist anymore) elements_1 = copy.deepcopy(md1.mesh.elements) elements_2 = elements_1[pos_elem, :] elements_2[:, 0] = Pnode[elements_2[:, 0] - 1] elements_2[:, 1] = Pnode[elements_2[:, 1] - 1] elements_2[:, 2] = Pnode[elements_2[:, 2] - 1] if md1.mesh.__class__.__name__ == 'mesh3dprisms': elements_2[:, 3] = Pnode[elements_2[:, 3] - 1] elements_2[:, 4] = Pnode[elements_2[:, 4] - 1] elements_2[:, 5] = Pnode[elements_2[:, 5] - 1] #OK, now create the new model! #take every field from model md2 = copy.deepcopy(md1) #automatically modify fields #loop over model fields model_fields = vars(md1) for fieldi in model_fields: #get field field = getattr(md1, fieldi) fieldsize = np.shape(field) if hasattr(field, '__dict__') and not m.ismember( fieldi, ['results'])[0]: #recursive call object_fields = vars(field) for fieldj in object_fields: #get field field = getattr(getattr(md1, fieldi), fieldj) fieldsize = np.shape(field) if len(fieldsize): #size = number of nodes * n if fieldsize[0] == numberofvertices1: setattr(getattr(md2, fieldi), fieldj, field[pos_node]) elif fieldsize[0] == numberofvertices1 + 1: setattr(getattr(md2, fieldi), fieldj, np.vstack((field[pos_node], field[-1, :]))) #size = number of elements * n elif fieldsize[0] == numberofelements1: setattr(getattr(md2, fieldi), fieldj, field[pos_elem]) else: if len(fieldsize): #size = number of nodes * n if fieldsize[0] == numberofvertices1: setattr(md2, fieldi, field[pos_node]) elif fieldsize[0] == numberofvertices1 + 1: setattr(md2, fieldi, np.hstack((field[pos_node], field[-1, :]))) #size = number of elements * n elif fieldsize[0] == numberofelements1: setattr(md2, fieldi, field[pos_elem]) #modify some specific fields #Mesh md2.mesh.numberofelements = numberofelements2 md2.mesh.numberofvertices = numberofvertices2 md2.mesh.elements = elements_2 #mesh.uppervertex mesh.lowervertex if md1.mesh.__class__.__name__ == 'mesh3dprisms': md2.mesh.uppervertex = md1.mesh.uppervertex[pos_node] pos = np.where(~np.isnan(md2.mesh.uppervertex))[0] md2.mesh.uppervertex[pos] = Pnode[ md2.mesh.uppervertex[pos].astype(int) - 1] md2.mesh.lowervertex = md1.mesh.lowervertex[pos_node] pos = np.where(~np.isnan(md2.mesh.lowervertex))[0] md2.mesh.lowervertex[pos] = Pnode[ md2.mesh.lowervertex[pos].astype(int) - 1] md2.mesh.upperelements = md1.mesh.upperelements[pos_elem] pos = np.where(~np.isnan(md2.mesh.upperelements))[0] md2.mesh.upperelements[pos] = Pelem[ md2.mesh.upperelements[pos].astype(int) - 1] md2.mesh.lowerelements = md1.mesh.lowerelements[pos_elem] pos = np.where(~np.isnan(md2.mesh.lowerelements))[0] md2.mesh.lowerelements[pos] = Pelem[ md2.mesh.lowerelements[pos].astype(int) - 1] #Initial 2d mesh if md1.mesh.__class__.__name__ == 'mesh3dprisms': flag_elem_2d = flag_elem[np.arange(0, md1.mesh.numberofelements2d)] pos_elem_2d = np.nonzero(flag_elem_2d)[0] flag_node_2d = flag_node[np.arange(0, md1.mesh.numberofvertices2d)] pos_node_2d = np.nonzero(flag_node_2d)[0] md2.mesh.numberofelements2d = np.size(pos_elem_2d) md2.mesh.numberofvertices2d = np.size(pos_node_2d) md2.mesh.elements2d = md1.mesh.elements2d[pos_elem_2d, :] md2.mesh.elements2d[:, 0] = Pnode[md2.mesh.elements2d[:, 0] - 1] md2.mesh.elements2d[:, 1] = Pnode[md2.mesh.elements2d[:, 1] - 1] md2.mesh.elements2d[:, 2] = Pnode[md2.mesh.elements2d[:, 2] - 1] md2.mesh.x2d = md1.mesh.x[pos_node_2d] md2.mesh.y2d = md1.mesh.y[pos_node_2d] #Edges if m.strcmp(md.mesh.domaintype(), '2Dhorizontal'): if np.ndim(md2.mesh.edges) > 1 and np.size( md2.mesh.edges, axis=1 ) > 1: #do not use ~isnan because there are some np.nans... #renumber first two columns pos = np.nonzero(md2.mesh.edges[:, 3] != -1)[0] md2.mesh.edges[:, 0] = Pnode[md2.mesh.edges[:, 0] - 1] md2.mesh.edges[:, 1] = Pnode[md2.mesh.edges[:, 1] - 1] md2.mesh.edges[:, 2] = Pelem[md2.mesh.edges[:, 2] - 1] md2.mesh.edges[pos, 3] = Pelem[md2.mesh.edges[pos, 3] - 1] #remove edges when the 2 vertices are not in the domain. md2.mesh.edges = md2.mesh.edges[np.nonzero( np.logical_and(md2.mesh.edges[:, 0], md2.mesh.edges[:, 1]) )[0], :] #Replace all zeros by -1 in the last two columns pos = np.nonzero(md2.mesh.edges[:, 2] == 0)[0] md2.mesh.edges[pos, 2] = -1 pos = np.nonzero(md2.mesh.edges[:, 3] == 0)[0] md2.mesh.edges[pos, 3] = -1 #Invert -1 on the third column with last column (Also invert first two columns!!) pos = np.nonzero(md2.mesh.edges[:, 2] == -1)[0] md2.mesh.edges[pos, 2] = md2.mesh.edges[pos, 3] md2.mesh.edges[pos, 3] = -1 values = md2.mesh.edges[pos, 1] md2.mesh.edges[pos, 1] = md2.mesh.edges[pos, 0] md2.mesh.edges[pos, 0] = values #Finally remove edges that do not belong to any element pos = np.nonzero( np.logical_and(md2.mesh.edges[:, 1] == -1, md2.mesh.edges[:, 2] == -1))[0] md2.mesh.edges = np.delete(md2.mesh.edges, pos, axis=0) #Penalties if np.any(np.logical_not(np.isnan(md2.stressbalance.vertex_pairing))): for i in xrange(np.size(md1.stressbalance.vertex_pairing, axis=0)): md2.stressbalance.vertex_pairing[i, :] = Pnode[ md1.stressbalance.vertex_pairing[i, :]] md2.stressbalance.vertex_pairing = md2.stressbalance.vertex_pairing[ np.nonzero(md2.stressbalance.vertex_pairing[:, 0])[0], :] if np.any(np.logical_not(np.isnan(md2.masstransport.vertex_pairing))): for i in xrange(np.size(md1.masstransport.vertex_pairing, axis=0)): md2.masstransport.vertex_pairing[i, :] = Pnode[ md1.masstransport.vertex_pairing[i, :]] md2.masstransport.vertex_pairing = md2.masstransport.vertex_pairing[ np.nonzero(md2.masstransport.vertex_pairing[:, 0])[0], :] #recreate segments if md1.mesh.__class__.__name__ == 'mesh2d': md2.mesh.vertexconnectivity = NodeConnectivity( md2.mesh.elements, md2.mesh.numberofvertices)[0] md2.mesh.elementconnectivity = ElementConnectivity( md2.mesh.elements, md2.mesh.vertexconnectivity)[0] md2.mesh.segments = contourenvelope(md2) md2.mesh.vertexonboundary = np.zeros(numberofvertices2, bool) md2.mesh.vertexonboundary[md2.mesh.segments[:, 0:2] - 1] = True else: #First do the connectivity for the contourenvelope in 2d md2.mesh.vertexconnectivity = NodeConnectivity( md2.mesh.elements2d, md2.mesh.numberofvertices2d)[0] md2.mesh.elementconnectivity = ElementConnectivity( md2.mesh.elements2d, md2.mesh.vertexconnectivity)[0] segments = contourenvelope(md2) md2.mesh.vertexonboundary = np.zeros( numberofvertices2 / md2.mesh.numberoflayers, bool) md2.mesh.vertexonboundary[segments[:, 0:2] - 1] = True md2.mesh.vertexonboundary = np.tile(md2.mesh.vertexonboundary, md2.mesh.numberoflayers) #Then do it for 3d as usual md2.mesh.vertexconnectivity = NodeConnectivity( md2.mesh.elements, md2.mesh.numberofvertices)[0] md2.mesh.elementconnectivity = ElementConnectivity( md2.mesh.elements, md2.mesh.vertexconnectivity)[0] #Boundary conditions: Dirichlets on new boundary #Catch the elements that have not been extracted orphans_elem = np.nonzero(np.logical_not(flag_elem))[0] orphans_node = np.unique(md1.mesh.elements[orphans_elem, :]) - 1 #Figure out which node are on the boundary between md2 and md1 nodestoflag1 = np.intersect1d(orphans_node, pos_node) nodestoflag2 = Pnode[nodestoflag1].astype(int) - 1 if np.size(md1.stressbalance.spcvx) > 1 and np.size( md1.stressbalance.spcvy) > 2 and np.size( md1.stressbalance.spcvz) > 2: if np.size(md1.inversion.vx_obs) > 1 and np.size( md1.inversion.vy_obs) > 1: md2.stressbalance.spcvx[nodestoflag2] = md2.inversion.vx_obs[ nodestoflag2] md2.stressbalance.spcvy[nodestoflag2] = md2.inversion.vy_obs[ nodestoflag2] else: md2.stressbalance.spcvx[nodestoflag2] = np.nan md2.stressbalance.spcvy[nodestoflag2] = np.nan print "\n!! extract warning: spc values should be checked !!\n\n" #put 0 for vz md2.stressbalance.spcvz[nodestoflag2] = 0 if np.any(np.logical_not(np.isnan(md1.thermal.spctemperature))): md2.thermal.spctemperature[nodestoflag2] = 1 #Results fields if md1.results: md2.results = results() for solutionfield, field in md1.results.__dict__.iteritems(): if isinstance(field, list): setattr(md2.results, solutionfield, []) #get time step for i, fieldi in enumerate(field): if isinstance(fieldi, results) and fieldi: getattr(md2.results, solutionfield).append(results()) fieldr = getattr(md2.results, solutionfield)[i] #get subfields for solutionsubfield, subfield in fieldi.__dict__.iteritems( ): if np.size(subfield) == numberofvertices1: setattr(fieldr, solutionsubfield, subfield[pos_node]) elif np.size(subfield) == numberofelements1: setattr(fieldr, solutionsubfield, subfield[pos_elem]) else: setattr(fieldr, solutionsubfield, subfield) else: getattr(md2.results, solutionfield).append(None) elif isinstance(field, results): setattr(md2.results, solutionfield, results()) if isinstance(field, results) and field: fieldr = getattr(md2.results, solutionfield) #get subfields for solutionsubfield, subfield in field.__dict__.iteritems( ): if np.size(subfield) == numberofvertices1: setattr(fieldr, solutionsubfield, subfield[pos_node]) elif np.size(subfield) == numberofelements1: setattr(fieldr, solutionsubfield, subfield[pos_elem]) else: setattr(fieldr, solutionsubfield, subfield) #Keep track of pos_node and pos_elem md2.mesh.extractedvertices = pos_node + 1 md2.mesh.extractedelements = pos_elem + 1 return md2
def contourenvelope(md,*args): """ CONTOURENVELOPE - build a set of segments enveloping a contour .exp Usage: segments=contourenvelope(md,varargin) Example: segments=contourenvelope(md,'Stream.exp'); segments=contourenvelope(md); """ #some checks if len(args)>1: raise RuntimeError("contourenvelope error message: bad usage") if len(args)==1: flags=args[0] if isinstance(flags,str): file=flags if not os.path.exists(file): raise IOError("contourenvelope error message: file '%s' not found" % file) isfile=1 elif isinstance(flags,(bool,int,float)): #do nothing for now isfile=0 else: raise TypeError("contourenvelope error message: second argument should be a file or an elements flag") #Now, build the connectivity tables for this mesh. #Computing connectivity if numpy.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices and numpy.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices2d: [md.mesh.vertexconnectivity]=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices) if numpy.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements and numpy.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements2d: [md.mesh.elementconnectivity]=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity) #get nodes inside profile elementconnectivity=copy.deepcopy(md.mesh.elementconnectivity) if md.mesh.dimension()==2: elements=copy.deepcopy(md.mesh.elements) x=copy.deepcopy(md.mesh.x) y=copy.deepcopy(md.mesh.y) numberofvertices=copy.deepcopy(md.mesh.numberofvertices) numberofelements=copy.deepcopy(md.mesh.numberofelements) else: elements=copy.deepcopy(md.mesh.elements2d) x=copy.deepcopy(md.mesh.x2d) y=copy.deepcopy(md.mesh.y2d) numberofvertices=copy.deepcopy(md.mesh.numberofvertices2d) numberofelements=copy.deepcopy(md.mesh.numberofelements2d) if len(args)==1: if isfile: #get flag list of elements and nodes inside the contour nodein=ContourToMesh(elements,x,y,file,'node',1) elemin=(numpy.sum(nodein(elements),axis=1)==numpy.size(elements,axis=1)) #modify element connectivity elemout=numpy.nonzero(numpy.logical_not(elemin))[0] elementconnectivity[elemout,:]=0 elementconnectivity[numpy.nonzero(m.ismember(elementconnectivity,elemout+1))]=0 else: #get flag list of elements and nodes inside the contour nodein=numpy.zeros(numberofvertices) elemin=numpy.zeros(numberofelements) pos=numpy.nonzero(flags) elemin[pos]=1 nodein[elements[pos,:]-1]=1 #modify element connectivity elemout=numpy.nonzero(numpy.logical_not(elemin))[0] elementconnectivity[elemout,:]=0 elementconnectivity[numpy.nonzero(m.ismember(elementconnectivity,elemout+1))]=0 #Find element on boundary #First: find elements on the boundary of the domain flag=copy.deepcopy(elementconnectivity) if len(args)==1: flag[numpy.nonzero(flag)]=elemin[flag[numpy.nonzero(flag)]] elementonboundary=numpy.logical_and(numpy.prod(flag,axis=1)==0,numpy.sum(flag,axis=1)>0) #Find segments on boundary pos=numpy.nonzero(elementonboundary)[0] num_segments=numpy.size(pos) segments=numpy.zeros((num_segments*3,3),int) count=0 for el1 in pos: els2=elementconnectivity[el1,numpy.nonzero(elementconnectivity[el1,:])[0]]-1 if numpy.size(els2)>1: flag=numpy.intersect1d(numpy.intersect1d(elements[els2[0],:],elements[els2[1],:]),elements[el1,:]) nods1=elements[el1,:] nods1=numpy.delete(nods1,numpy.nonzero(nods1==flag)) segments[count,:]=[nods1[0],nods1[1],el1+1] ord1=numpy.nonzero(nods1[0]==elements[el1,:])[0][0] ord2=numpy.nonzero(nods1[1]==elements[el1,:])[0][0] #swap segment nodes if necessary if ( (ord1==0 and ord2==1) or (ord1==1 and ord2==2) or (ord1==2 and ord2==0) ): temp=segments[count,0] segments[count,0]=segments[count,1] segments[count,1]=temp segments[count,0:2]=numpy.flipud(segments[count,0:2]) count+=1 else: nods1=elements[el1,:] flag=numpy.setdiff1d(nods1,elements[els2,:]) for j in range(0,3): nods=numpy.delete(nods1,j) if numpy.any(m.ismember(flag,nods)): segments[count,:]=[nods[0],nods[1],el1+1] ord1=numpy.nonzero(nods[0]==elements[el1,:])[0][0] ord2=numpy.nonzero(nods[1]==elements[el1,:])[0][0] if ( (ord1==0 and ord2==1) or (ord1==1 and ord2==2) or (ord1==2 and ord2==0) ): temp=segments[count,0] segments[count,0]=segments[count,1] segments[count,1]=temp segments[count,0:2]=numpy.flipud(segments[count,0:2]) count+=1 segments=segments[0:count,:] return segments
def processgeometry(geom, tol, outline): # {{{ raise RuntimeError("bamg.py/processgeometry is not complete.") #Deal with edges print("Checking Edge crossing...") i = 0 while (i < numpy.size(geom.Edges, axis=0)): #edge counter i += 1 #Get coordinates x1 = geom.Vertices[geom.Edges[i, 0], 0] y1 = geom.Vertices[geom.Edges[i, 0], 1] x2 = geom.Vertices[geom.Edges[i, 1], 0] y2 = geom.Vertices[geom.Edges[i, 1], 1] color1 = geom.Edges[i, 2] j = i #test edges located AFTER i only while (j < numpy.size(geom.Edges, axis=0)): #edge counter j += 1 #Skip if the two edges already have a vertex in common if any(m.ismember(geom.Edges[i, 0:2], geom.Edges[j, 0:2])): continue #Get coordinates x3 = geom.Vertices[geom.Edges[j, 0], 0] y3 = geom.Vertices[geom.Edges[j, 0], 1] x4 = geom.Vertices[geom.Edges[j, 1], 0] y4 = geom.Vertices[geom.Edges[j, 1], 1] color2 = geom.Edges[j, 2] #Check if the two edges are crossing one another if SegIntersect(numpy.array([[x1, y1], [x2, y2]]), numpy.array([[x3, y3], [x4, y4]])): #Get coordinate of intersection point (http://mathworld.wolfram.com/Line-LineIntersection.html) 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]]))) #Add vertex to the list of vertices geom.Vertices = numpy.vstack( (geom.Vertices, [x, y, min(color1, color2)])) id = numpy.size(geom.Vertices, axis=0) #Update edges i and j edgei = geom.Edges[i, :].copy() edgej = geom.Edges[j, :].copy() geom.Edges[i, :] = [edgei(0), id, edgei(2)] geom.Edges = numpy.vstack( (geom.Edges, [id, edgei(1), edgei(2)])) geom.Edges[j, :] = [edgej(0), id, edgej(2)] geom.Edges = numpy.vstack( (geom.Edges, [id, edgej(1), edgej(2)])) #update current edge second tip x2 = x y2 = y #Check point outside print("Checking for points outside the domain...") i = 0 num = 0 while (i < numpy.size(geom.Vertices, axis=0)): #vertex counter i += 1 #Get coordinates x = geom.Vertices[i, 0] y = geom.Vertices[i, 1] color = geom.Vertices[i, 2] #Check that the point is inside the domain if color != 1 and not ContourToNodes(x, y, outline[0], 1): #Remove points from list of Vertices num += 1 geom.Vertices[i, :] = [] #update edges posedges = numpy.nonzero(geom.Edges == i) geom.Edges[posedges[0], :] = [] posedges = numpy.nonzero(geom.Edges > i) geom.Edges[posedges] = geom.Edges[posedges] - 1 #update counter i -= 1 if num: print( "WARNING: %d points outside the domain outline have been removed" % num) """ %Check point spacing if ~isnan(tol), disp('Checking point spacing...'); i=0; while (i<size(geom.Vertices,1)), %vertex counter i=i+1; %Get coordinates x1=geom.Vertices(i,1); y1=geom.Vertices(i,2); j=i; %test edges located AFTER i only while (j<size(geom.Vertices,1)), %vertex counter j=j+1; %Get coordinates x2=geom.Vertices(j,1); y2=geom.Vertices(j,2); %Check whether the two vertices are too close if ((x2-x1)**2+(y2-y1)**2<tol**2) %Remove points from list of Vertices geom.Vertices(j,:)=[]; %update edges posedges=find(m.ismember(geom.Edges,j)); geom.Edges(posedges)=i; posedges=find(geom.Edges>j); geom.Edges(posedges)=geom.Edges(posedges)-1; %update counter j=j-1; end end end end %remove empty edges geom.Edges(find(geom.Edges(:,1)==geom.Edges(:,2)),:)=[]; """ return geom
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