Esempio n. 1
0
    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
Esempio n. 2
0
File: mesh2d.py Progetto: pf4d/issm
    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
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
File: model.py Progetto: pf4d/issm
    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
Esempio n. 6
0
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
Esempio n. 7
0
File: bamg.py Progetto: pf4d/issm
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
Esempio n. 8
0
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