Ejemplo n.º 1
0
def testGenerateTriangulationFromPointSet(points):
    """
    input: point-set

    generate triangle representation of the points

    output: an array contaning the points, and element to Node connectivity
    """
    #mwf debug
    #import pdb
    #pdb.set_trace()
    #default representation for holding input points
    tri0 = triangleWrappers.new()

    triangleWrappers.setPoints(tri0, points[:, :2])

    flags = "qz"  #just use simple quality mesh generation, number from zero

    #default representation for holding output points
    tri1 = triangleWrappers.new()

    triangleWrappers.applyTriangulateNoVoronoi(flags, tri0, tri1)

    #if returning nodeArray and elementNodesArray outside of routine
    #use getPointsCopy, getTrianglesCopy
    #otherwise if doing all the necessary generation of quadrature points
    #and weights internally don't need deep copy
    nodeArray2d = triangleWrappers.getPointsCopy(tri1)
    elementNodesArray = triangleWrappers.getTrianglesCopy(tri1)

    #clean up
    del tri0
    del tri1

    return nodeArray2d, elementNodesArray
Ejemplo n.º 2
0
    def convertFromProteusMesh(self, meshin, verbose=0):
        """
        generate a Triangle mesh representation from an proteus mesh.
        This version will copy over the nodes and elements from the
        proteus mesh.

        Deletes the existing Triangle mesh and regenerates.
        """

        #first check that the input mesh has the correct dimensions and
        #minimal information necessary
        spaceDim = 2
        assert (meshin.nElementBoundaries_element == spaceDim + 1)
        assert (meshin.nodeArray is not None)
        assert (meshin.elementNodesArray is not None)

        #get a clean slate
        tri0 = triangleWrappers.new()
        #don't set any markers for now
        #input array should be nNodes by spacedim
        nodesIn = meshin.nodeArray[:, :spaceDim]
        triangleWrappers.setPoints(tri0, nodesIn)
        #triangle array should be nElements x 3
        triAin = meshin.elementNodesArray[:, :spaceDim + 1]
        triangleWrappers.setTriangles(tri0, triAin)

        flagsAdd = "r"  #use element and node connections
        flags = flagsAdd + self.baseFlags
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                logEvent('readNodeAndEle makeVoronoi= ', self.makeVoronoi,
                         ' flags= ', flags)
        #end if
        self.lastFlags = flags
        #reset data representations if necessary
        self.resetDefaultTrirep(index=0, verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0, verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags, tri0, self.trirep[0],
                                              self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False

        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags, tri0,
                                                       self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #clean up explicitly
        del tri0
Ejemplo n.º 3
0
    def convertFromProteusMesh(self,meshin,verbose=0):
        """
        generate a Triangle mesh representation from an proteus mesh.
        This version will copy over the nodes and elements from the
        proteus mesh.

        Deletes the existing Triangle mesh and regenerates.
        """

        #first check that the input mesh has the correct dimensions and
        #minimal information necessary
        spaceDim = 2
        assert(meshin.nElementBoundaries_element == spaceDim+1)
        assert(meshin.nodeArray is not None)
        assert(meshin.elementNodesArray is not None)

        #get a clean slate
        tri0 = triangleWrappers.new()
        #don't set any markers for now
        #input array should be nNodes by spacedim
        nodesIn = meshin.nodeArray[:,:spaceDim]
        triangleWrappers.setPoints(tri0,nodesIn)
        #triangle array should be nElements x 3
        triAin  = meshin.elementNodesArray[:,:spaceDim+1]
        triangleWrappers.setTriangles(tri0,triAin)

        flagsAdd = "r" #use element and node connections
        flags = flagsAdd+self.baseFlags
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                logEvent('readNodeAndEle makeVoronoi= ',self.makeVoronoi,' flags= ',flags)
        #end if
        self.lastFlags = flags
        #reset data representations if necessary
        self.resetDefaultTrirep(index=0,verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0,verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags,tri0,self.trirep[0],self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False

        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags,tri0,self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #clean up explicitly
        del tri0
Ejemplo n.º 4
0
def testGenerateTriangulationFromPointSet(points):
    """
    input: point-set

    generate triangle representation of the points

    output: an array contaning the points, and element to Node connectivity
    """
    #mwf debug
    #import pdb
    #pdb.set_trace()
    #default representation for holding input points
    tri0 = triangleWrappers.new()

    triangleWrappers.setPoints(tri0,points[:,:2])

    flags = "qz" #just use simple quality mesh generation, number from zero

    #default representation for holding output points
    tri1 = triangleWrappers.new()

    triangleWrappers.applyTriangulateNoVoronoi(flags,tri0,tri1)

    #if returning nodeArray and elementNodesArray outside of routine
    #use getPointsCopy, getTrianglesCopy
    #otherwise if doing all the necessary generation of quadrature points
    #and weights internally don't need deep copy
    nodeArray2d = triangleWrappers.getPointsCopy(tri1)
    elementNodesArray = triangleWrappers.getTrianglesCopy(tri1)



    #clean up
    del tri0
    del tri1

    return nodeArray2d,elementNodesArray
Ejemplo n.º 5
0
    def readFromPolyFile(self, filebase, flagsAdd="", verbose=0):
        """
        read triangle representation from filebase.poly file
        assumes the nbase data member is set appropriately
        """
        reader = TriangleUtils.TriangleInputFileReader()
        if verbose > 0:
            print 'readFromPolyFile filebase= ', filebase
        #end if

        polyDataInfo, polyData = reader.readPoly(filebase,
                                                 nbase=self.nbase,
                                                 verbose=verbose)

        if verbose > 3:
            for type in ['node', 'segment', 'hole', 'region']:
                print 'Poly: ', type, 'Info= \n', polyDataInfo[type], '\n'
            #end for
        #end if

        nodes, nodesA, nodesM = (polyData['node']['nodes'],
                                 polyData['node']['nodeAttributes'],
                                 polyData['node']['nodeMarkers'])
        segments, segmentsM = (polyData['segment']['segments'],
                               polyData['segment']['segmentMarkers'])
        holes = polyData['hole']['holes']
        regions = polyData['region']['regions']

        if verbose > 3:
            print """Poly file read:
            nodes   = \n%s\n nodeAttributes= \n%s\n nodeMarkers= \n%s\n
            segments= \n%s\n segmentMarkers= \n%s\n
            holes   = \n%s\n
            regions = \n%s\n
            """ % (nodes, nodesA, nodesM, segments, segmentsM, holes, regions)
        #end if
        tri0 = triangleWrappers.new()

        if nodesM == None:
            triangleWrappers.setPoints(tri0, nodes)
        else:
            nodesMtmp = numpy.zeros(nodesM.shape, 'i')
            nodesMtmp[:] = nodesM
            nodesM = nodesMtmp
            triangleWrappers.setPointsAndMarkers(tri0, nodes, nodesM)
        if not nodesA == None:
            triangleWrappers.setPointAttributes(tri0, nodesA)
        #end if
        if segmentsM == None:
            triangleWrappers.setSegments(tri0, segments)
        else:
            triangleWrappers.setSegmentsAndMarkers(tri0, segments, segmentsM)
        #end if
        if (not holes == None):
            triangleWrappers.setHoles(tri0, holes)
        #end if
        if (not regions == None):
            #print 'setting trin1 regions=\n',regions2
            triangleWrappers.setRegions(tri0, regions)
        #end if

        flags = flagsAdd + self.baseFlags
        if flags.find('p') == -1:
            print 'flags = ', flags, ' must have p, appending'
            flags += "p"
        #end
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                print 'readNodeAndEle makeVoronoi= ', self.makeVoronoi, ' flags= ', flags
        #end if
        self.lastFlags = flags
        #reset data representations if necessary
        self.resetDefaultTrirep(index=0, verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0, verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags, tri0, self.trirep[0],
                                              self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False
        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags, tri0,
                                                       self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #clean up?
        del tri0
Ejemplo n.º 6
0
    def readFromNodeAndEleFiles(self, filebase, flagsAdd="", verbose=0):
        """
        read triangle representation from filebase.node and filebase.ele
        files. assumes the nbase data member is set appropriately
        """
        reader = TriangleUtils.TriangleInputFileReader()
        if verbose > 0:
            print 'readFromNodeAndEleFiles filebase= ', filebase
        #end if
        nodeDataInfo, nodeData = reader.readNodes(filebase, nbase=self.nbase)
        nodes, nodesA, nodesM = (nodeData['nodes'], nodeData['nodeAttributes'],
                                 nodeData['nodeMarkers'])

        if verbose > 3:
            print 'Nodes: nodeInfo= ', nodeDataInfo
            print """Nodes: nodes= \n%s\n nodeAttributes= \n%s\n nodeMarkers= \n%s
            """ % (nodes, nodesA, nodesM)
        #end if

        triDataInfo, triData = reader.readTriangles(filebase, nbase=self.nbase)
        triangles, trianglesA = triData['triangles'], triData[
            'triangleAttributes']

        if verbose > 3:
            print 'Triangles: triInfo= ', triDataInfo
            print """Triangles: elems= \n%s\n triAttributes= \n%s
            """ % (triangles, trianglesA)
        #end if

        #now create an initial representation
        tri0 = triangleWrappers.new()

        if nodesM == None:
            triangleWrappers.setPoints(tri0, nodes)
        else:
            triangleWrappers.setPointsAndMarkers(tri0, nodes, nodesM)
        if not nodesA == None:
            triangleWrappers.setPointAttributes(tri0, nodesA)
        #end if

        triangleWrappers.setTriangles(tri0, triangles)
        if not trianglesA == None:
            triangleWrappers.setTriangleAttributes(tri0, trianglesA)

        #run triangulate on it using the base flags and whatever else was
        #added
        flags = flagsAdd + self.baseFlags
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                print 'readNodeAndEle makeVoronoi= ', self.makeVoronoi, ' flags= ', flags
        #end if
        self.lastFlags = flags

        #reset data representations if necessary
        self.resetDefaultTrirep(index=0, verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0, verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags, tri0, self.trirep[0],
                                              self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False
        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags, tri0,
                                                       self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #do I need to clean up explicitly?
        del tri0
Ejemplo n.º 7
0
def testGenerateSSIPtriangulation(points):
    """
    input: vertices and SSIP points belonging to a single element

    generate triangle representation of the points

    output: an array contaning the points, and element quadrature weights for the points

    test with input
import numpy
from proteus import TriangleTools
points = numpy.array([[0.0,0.0,0.0],[0.5,0.4,0.],[1.0,0.0,0.0],[0.2,0.3,0.0],[0.0,1.0,0.0]])
dV,x = TriangleTools.testGenerateSSIPtriangulation(points)

    """
    #mwf debug
    #import pdb
    #pdb.set_trace()
    #default representation for holding input points
    tri0 = triangleWrappers.new()

    triangleWrappers.setPoints(tri0, points[:, :2])

    flags = "z"  #"qz" #just use simple quality mesh generation, number from zero

    #default representation for holding output points
    tri1 = triangleWrappers.new()

    triangleWrappers.applyTriangulateNoVoronoi(flags, tri0, tri1)

    #doing all the necessary generation of quadrature points
    #and weights internally don't need deep copy
    nodeArray2d = triangleWrappers.getPoints(tri1)
    elementNodesArray = triangleWrappers.getTriangles(tri1)

    import Quadrature, cfemIntegrals
    #try Gauss quadrature different orders
    #subElementQuadrature = Quadrature.GaussTriangle()
    #subElementQuadrature.setOrder(2)  #order(1)
    #What about vertex quadrature
    subElementQuadrature = Quadrature.LobattoTriangle()
    subElementQuadrature.setOrder(3)

    nSubQuadraturePoints = len(subElementQuadrature.weights)
    nElements = elementNodesArray.shape[0]
    nQuadraturePoints = nElements * nSubQuadraturePoints
    nSpace = 2
    nDOF_element = 3
    weights_ref = numpy.array(subElementQuadrature.weights)
    points_ref = numpy.array(subElementQuadrature.points)
    #loop through elements, compute area, map reference points to physical space,
    #and compute physical space weights

    #to be consistent need to have nodes be 3d
    nodeArray = numpy.zeros((nodeArray2d.shape[0], 3), 'd')
    nodeArray[:, 0:2] = nodeArray2d
    #need to store psi and grad_psi to avoid recalculating across a lot of elements?
    #shape functions  are 1-x-y, x, y
    psi = numpy.zeros((nSubQuadraturePoints, nDOF_element), 'd')
    psi[:, 0] = 1.0 - points_ref[:, 0] - points_ref[:, 1]
    psi[:, 1] = points_ref[:, 0]
    psi[:, 2] = points_ref[:, 1]
    #for k in range(nSubQuadraturePoints):
    #    psi[k,0] = 1.0-subElementQuadrature.points[k][0]-subElementQuadrature.points[k][1]
    #    psi[k,1] = subElementQuadrature.points[k][0]
    #    psi[k,2] = subElementQuadrature.points[k][1]
    grad_psi = numpy.zeros((nSubQuadraturePoints, nDOF_element, nSpace), 'd')
    #shape functions  are 1-x-y, x, y
    grad_psi[:, 0, 0].fill(-1.)
    grad_psi[:, 0, 1].fill(-1.)
    grad_psi[:, 1, 0].fill(1.0)
    grad_psi[:, 2, 1].fill(1.0)
    #waste space to reuse code
    jacobianArray = numpy.zeros(
        (nElements, nSubQuadraturePoints, nSpace, nSpace), 'd')
    jacobianDetArray = numpy.zeros((nElements, nSubQuadraturePoints), 'd')
    jacobianInvArray = numpy.zeros(
        (nElements, nSubQuadraturePoints, nSpace, nSpace), 'd')

    cfemIntegrals.parametricMaps_getJacobianValues(grad_psi, elementNodesArray,
                                                   nodeArray, jacobianArray,
                                                   jacobianDetArray,
                                                   jacobianInvArray)

    jacobianDetArrayAbs = numpy.absolute(jacobianDetArray)
    #weights and points shaped like nSubElements x nQuadraturePointsSubElement
    q_sub_dV = numpy.zeros((nElements, nSubQuadraturePoints), 'd')
    q_sub_x = numpy.zeros((nElements, nSubQuadraturePoints, 3), 'd')

    cfemIntegrals.calculateIntegrationWeights(jacobianDetArrayAbs, weights_ref,
                                              q_sub_dV)

    cfemIntegrals.parametricMaps_getValues(psi, elementNodesArray, nodeArray,
                                           q_sub_x)

    #clean up
    del tri0
    del tri1

    #exit
    return q_sub_dV, q_sub_x
Ejemplo n.º 8
0
    def readFromPolyFile(self,filebase,flagsAdd="",verbose=0):
        """Reads in the triangle representation from filebase.poly file.

        Parameters
        ----------
        filebase : str
            The filename with the triangluation.
        flagsAdd : str
        verbose : int
            A flag indicating how much information to pipe to stdout.

        Notes
        -----
        Function assumes the nbase data member is set appropriately.
        """
        reader = TriangleUtils.TriangleInputFileReader()
        if verbose > 0:
            logEvent('readFromPolyFile filebase= ',filebase)
        #end if

        polyDataInfo,polyData = reader.readPoly(filebase,nbase=self.nbase,
                                                verbose=verbose)

        if verbose > 3:
            for type in ['node','segment','hole','region']:
                logEvent('Poly: ',type,'Info= \n',polyDataInfo[type],'\n')
            #end for
        #end if

        nodes,nodesA,nodesM = (polyData['node']['nodes'],
                               polyData['node']['nodeAttributes'],
                               polyData['node']['nodeMarkers'])
        segments,segmentsM   = (polyData['segment']['segments'],
                                polyData['segment']['segmentMarkers'])
        holes                 = polyData['hole']['holes']
        regions               = polyData['region']['regions']

        if verbose > 3:
            logEvent("""Poly file read:
            nodes   = \n%s\n nodeAttributes= \n%s\n nodeMarkers= \n%s\n
            segments= \n%s\n segmentMarkers= \n%s\n
            holes   = \n%s\n
            regions = \n%s\n
            """ % (nodes,nodesA,nodesM,segments,segmentsM,holes,regions))
        #end if
        tri0 = triangleWrappers.new()

        if nodesM is None:
            triangleWrappers.setPoints(tri0,nodes)
        else:
            nodesMtmp = numpy.zeros(nodesM.shape,'i')
            nodesMtmp[:] = nodesM
            nodesM = nodesMtmp
            triangleWrappers.setPointsAndMarkers(tri0,nodes,nodesM)
        if nodesA is not None:
            triangleWrappers.setPointAttributes(tri0,nodesA)
        #end if
        if segmentsM is None:
            triangleWrappers.setSegments(tri0,segments)
        else:
            triangleWrappers.setSegmentsAndMarkers(tri0,segments,segmentsM)
        #end if
        if (holes is not None):
            triangleWrappers.setHoles(tri0,holes)
        #end if
        if (regions is not None):
            #print 'setting trin1 regions=\n',regions2
            triangleWrappers.setRegions(tri0,regions)
        #end if

        flags = flagsAdd+self.baseFlags
        if flags.find('p') == -1:
            logEvent('flags = ',flags,' must have p, appending')
            flags += "p"
        #end
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                logEvent('readNodeAndEle makeVoronoi= ',self.makeVoronoi,' flags= ',flags)
        #end if
        self.lastFlags = flags
        #reset data representations if necessary
        self.resetDefaultTrirep(index=0,verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0,verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags,tri0,self.trirep[0],self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False
        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags,tri0,self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #clean up?
        del tri0
Ejemplo n.º 9
0
    def readFromNodeAndEleFiles(self,filebase,flagsAdd="",verbose=0):
        """
        read triangle representation from filebase.node and filebase.ele
        files. assumes the nbase data member is set appropriately
        """
        reader = TriangleUtils.TriangleInputFileReader()
        if verbose > 0:
            logEvent('readFromNodeAndEleFiles filebase= ',filebase)
        #end if
        nodeDataInfo,nodeData = reader.readNodes(filebase,nbase=self.nbase)
        nodes,nodesA,nodesM = (nodeData['nodes'],
                               nodeData['nodeAttributes'],
                               nodeData['nodeMarkers'])

        if verbose > 3:
            logEvent('Nodes: nodeInfo= ',nodeDataInfo)
            logEvent("""Nodes: nodes= \n%s\n nodeAttributes= \n%s\n nodeMarkers= \n%s
            """ % (nodes,nodesA,nodesM))
        #end if

        triDataInfo,triData = reader.readTriangles(filebase,nbase=self.nbase)
        triangles,trianglesA = triData['triangles'],triData['triangleAttributes']

        if verbose > 3:
            logEvent('Triangles: triInfo= ',triDataInfo)
            logEvent("""Triangles: elems= \n%s\n triAttributes= \n%s
            """ % (triangles,trianglesA))
        #end if

        #now create an initial representation
        tri0 = triangleWrappers.new()

        if nodesM is None:
            triangleWrappers.setPoints(tri0,nodes)
        else:
            triangleWrappers.setPointsAndMarkers(tri0,nodes,nodesM)
        if nodesA is not None:
            triangleWrappers.setPointAttributes(tri0,nodesA)
        #end if

        triangleWrappers.setTriangles(tri0,triangles)
        if trianglesA is not None:
            triangleWrappers.setTriangleAttributes(tri0,trianglesA)

        #run triangulate on it using the base flags and whatever else was
        #added
        flags = flagsAdd+self.baseFlags
        if flags.find('v') >= 0:
            self.makeVoronoi = True
            if verbose > 0:
                logEvent('readNodeAndEle makeVoronoi= ',self.makeVoronoi,' flags= ',flags)
        #end if
        self.lastFlags = flags

        #reset data representations if necessary
        self.resetDefaultTrirep(index=0,verbose=verbose)
        if self.makeVoronoi:
            self.resetDefaultVorrep(index=0,verbose=verbose)
        #end vorrep initialized

        if self.makeVoronoi:
            triangleWrappers.applyTriangulate(flags,tri0,self.trirep[0],self.vorrep[0])
            #handles no longer contain trivial representations
            self.trirepDefaultInit[0] = False
            self.vorrepDefaultInit[0] = False
        else:
            triangleWrappers.applyTriangulateNoVoronoi(flags,tri0,self.trirep[0])
            #handle no longer contains trivial representations
            self.trirepDefaultInit[0] = False
        #end if

        #do I need to clean up explicitly?
        del tri0
Ejemplo n.º 10
0
def testGenerateSSIPtriangulation(points):
    """
    input: vertices and SSIP points belonging to a single element

    generate triangle representation of the points

    output: an array contaning the points, and element quadrature weights for the points

    test with input
import numpy
from proteus import TriangleTools
points = numpy.array([[0.0,0.0,0.0],[0.5,0.4,0.],[1.0,0.0,0.0],[0.2,0.3,0.0],[0.0,1.0,0.0]])
dV,x = TriangleTools.testGenerateSSIPtriangulation(points)

    """
    #mwf debug
    #import pdb
    #pdb.set_trace()
    #default representation for holding input points
    tri0 = triangleWrappers.new()

    triangleWrappers.setPoints(tri0,points[:,:2])

    flags = "z"#"qz" #just use simple quality mesh generation, number from zero

    #default representation for holding output points
    tri1 = triangleWrappers.new()

    triangleWrappers.applyTriangulateNoVoronoi(flags,tri0,tri1)

    #doing all the necessary generation of quadrature points
    #and weights internally don't need deep copy
    nodeArray2d = triangleWrappers.getPoints(tri1)
    elementNodesArray = triangleWrappers.getTriangles(tri1)

    import Quadrature,cfemIntegrals
    #try Gauss quadrature different orders
    #subElementQuadrature = Quadrature.GaussTriangle()
    #subElementQuadrature.setOrder(2)  #order(1)
    #What about vertex quadrature
    subElementQuadrature = Quadrature.LobattoTriangle()
    subElementQuadrature.setOrder(3)

    nSubQuadraturePoints = len(subElementQuadrature.weights)
    nElements = elementNodesArray.shape[0]
    nQuadraturePoints = nElements*nSubQuadraturePoints
    nSpace = 2
    nDOF_element = 3
    weights_ref = numpy.array(subElementQuadrature.weights)
    points_ref  = numpy.array(subElementQuadrature.points)
    #loop through elements, compute area, map reference points to physical space,
    #and compute physical space weights

    #to be consistent need to have nodes be 3d
    nodeArray = numpy.zeros((nodeArray2d.shape[0],3),'d')
    nodeArray[:,0:2] = nodeArray2d
    #need to store psi and grad_psi to avoid recalculating across a lot of elements?
    #shape functions  are 1-x-y, x, y
    psi = numpy.zeros((nSubQuadraturePoints,nDOF_element),'d')
    psi[:,0] = 1.0-points_ref[:,0]-points_ref[:,1]
    psi[:,1] = points_ref[:,0]
    psi[:,2] = points_ref[:,1]
    #for k in range(nSubQuadraturePoints):
    #    psi[k,0] = 1.0-subElementQuadrature.points[k][0]-subElementQuadrature.points[k][1]
    #    psi[k,1] = subElementQuadrature.points[k][0]
    #    psi[k,2] = subElementQuadrature.points[k][1]
    grad_psi = numpy.zeros((nSubQuadraturePoints,nDOF_element,nSpace),'d')
    #shape functions  are 1-x-y, x, y
    grad_psi[:,0,0].fill(-1.); grad_psi[:,0,1].fill(-1.)
    grad_psi[:,1,0].fill(1.0);
    grad_psi[:,2,1].fill(1.0)
    #waste space to reuse code
    jacobianArray    = numpy.zeros((nElements,nSubQuadraturePoints,nSpace,nSpace),'d')
    jacobianDetArray = numpy.zeros((nElements,nSubQuadraturePoints),'d')
    jacobianInvArray = numpy.zeros((nElements,nSubQuadraturePoints,nSpace,nSpace),'d')

    cfemIntegrals.parametricMaps_getJacobianValues(grad_psi,
                                                   elementNodesArray,
                                                   nodeArray,
                                                   jacobianArray,
                                                   jacobianDetArray,
                                                   jacobianInvArray)


    jacobianDetArrayAbs = numpy.absolute(jacobianDetArray)
    #weights and points shaped like nSubElements x nQuadraturePointsSubElement
    q_sub_dV = numpy.zeros((nElements,nSubQuadraturePoints),'d')
    q_sub_x  = numpy.zeros((nElements,nSubQuadraturePoints,3),'d')

    cfemIntegrals.calculateIntegrationWeights(jacobianDetArrayAbs,
                                              weights_ref,
                                              q_sub_dV)

    cfemIntegrals.parametricMaps_getValues(psi,
                                           elementNodesArray,
                                           nodeArray,
                                           q_sub_x)


    #clean up
    del tri0
    del tri1

    #exit
    return q_sub_dV,q_sub_x