예제 #1
0
def computeUpwindSaturation(NWorldCoarse, boundarys, sT, fluxTF):
    d = np.size(NWorldCoarse)
    
    sTF = np.tile(sT[...,None], [1, 2*d])
    basis = util.linearpIndexBasis(NWorldCoarse-1)
    for k in range(d):
        b = basis[k]

        N = np.array(NWorldCoarse-1)
        N[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(N, NWorldCoarse-1)
            
        N[k] = 0
        TIndBottom = util.lowerLeftpIndexMap(N, NWorldCoarse-1)

        for face in [0,1]:
            faceInd = 2*k+face
            stepToFace = b*(face*(NWorldCoarse[k]-1))
            TIndInterior = (1-face)*b + TIndBase
            TIndBoundary = stepToFace + TIndBottom

            # Interior
            TIndDst = TIndInterior[fluxTF[TIndInterior, faceInd] < 0]
            TIndSrc = TIndDst + (2*face - 1)*b
            sTF[TIndDst, faceInd] = sT[TIndSrc]

            # Boundary
            TIndDst = TIndBoundary[fluxTF[TIndBoundary, faceInd] < 0]
            sTF[TIndDst, faceInd] = boundarys[k, face]
            
    return sTF
예제 #2
0
def harmonicMeanOverFaces(NPatchCoarse, NCoarseElement, k, boundary, aPatch):
    NPatchFine = NPatchCoarse*NCoarseElement
    
    TPatchBasis = util.linearpIndexBasis(NPatchCoarse-1)

    NPatchBottom = np.array(NPatchCoarse)
    NPatchBottom[k] = 1
    NtBottom = np.prod(NPatchBottom)

    NPatchBase = np.array(NPatchCoarse)
    NPatchBase[k] -= 1
        
    TIndBase = util.lowerLeftpIndexMap(NPatchBase-1, NPatchCoarse-1)
    TIndBottom = util.lowerLeftpIndexMap(NPatchBottom-1, NPatchCoarse-1)

    t0Faces = faceElementIndices(NPatchCoarse, NCoarseElement, k, 0)
    t1Faces = faceElementIndices(NPatchCoarse, NCoarseElement, k, 1)

    aH0Faces = aPatch[t0Faces[TPatchBasis[k] + TIndBase]]
    aH1Faces = aPatch[t1Faces[TIndBase]]

    if boundary==0:
        abFaces = aPatch[t0Faces]
        abFaces[TPatchBasis[k] + TIndBase] = 2*aH0Faces*aH1Faces/(aH0Faces + aH1Faces)
    elif boundary==1:
        abFaces = aPatch[t1Faces]
        abFaces[TIndBase] = 2*aH0Faces*aH1Faces/(aH0Faces + aH1Faces)

    return abFaces
예제 #3
0
def computeJumps(NWorldCoarse, quantityT):
    d = np.size(NWorldCoarse)
    b = util.linearpIndexBasis(NWorldCoarse-1)

    jumpTF = np.tile(quantityT[...,None], [1, 2*d])
    for k in range(d):
        NWorldBase = np.array(NWorldCoarse)
        NWorldBase[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(NWorldBase-1, NWorldCoarse-1)
        jump = quantityT[TIndBase] - quantityT[TIndBase + b[k]]
        jumpTF[TIndBase, 2*k + 1] = jump
        jumpTF[TIndBase + b[k], 2*k] = -jump

    return jumpTF
예제 #4
0
def computeConservativeFlux(world, fluxTF, f=None):
    # From Odsaeter et al.
    # No source terms implemented yet here.
    assert(f is None)

    boundaryConditions = world.boundaryConditions
    FLoc = world.FLocCoarse

    fluxTF = np.array(fluxTF)
    
    NWorldCoarse = world.NWorldCoarse
    d = np.size(NWorldCoarse)
    
    tBasis = util.linearpIndexBasis(NWorldCoarse-1)

    def applyNeumannBoundaryConditions(fluxTF):
        def applyNeumannBoundaryConditionsOneSide(fluxTF, k, boundary):
            stepToFace = (boundary)*tBasis[k]*(NWorldCoarse[k]-1)
            NWorldBottom = np.array(NWorldCoarse)
            NWorldBottom[k] = 1
            TIndBoundary = stepToFace + util.lowerLeftpIndexMap(NWorldBottom-1, NWorldCoarse-1)
            fluxTF[TIndBoundary, 2*k+boundary] = 0

        for k in range(d):
            for boundary in [0, 1]:
                if boundaryConditions[k, boundary] == 1:
                    applyNeumannBoundaryConditionsOneSide(fluxTF, k, boundary)

    applyNeumannBoundaryConditions(fluxTF)
    
    boundaryMap = boundaryConditions==0
    FC = fem.assembleFaceConnectivityMatrix(NWorldCoarse, FLoc, boundaryMap)

    r = -np.sum(fluxTF, axis=1)
    y = linalg.linSolve(FC, r)

    yJumpsTF = computeJumps(NWorldCoarse, y)

    # fluxTF is already scaled with face area. Scale the jumps before adding
    scaledyJumpsTF = yJumpsTF*FLoc[np.newaxis, ...]
    
    conservativeFluxTF = fluxTF + scaledyJumpsTF
    
    applyNeumannBoundaryConditions(conservativeFluxTF)

    return conservativeFluxTF
예제 #5
0
def faceElementIndices(NPatchCoarse, NCoarseElement, k, boundary):
    '''Return indices of fine elements adjacent to face (k, boundary) for all coarse triangles

    Return type shape: (NtCoarse, Number of elements of face)
    '''
    NPatchFine = NPatchCoarse*NCoarseElement

    NFace = np.array(NCoarseElement)
    NFace[k] = 1
    
    tPatchBasis = util.linearpIndexBasis(NPatchFine-1)
    tStepToFace = boundary*tPatchBasis[k]*(NCoarseElement[k]-1)

    tIndexMap = tStepToFace + util.lowerLeftpIndexMap(NFace-1, NPatchFine-1)
    tStartIndices = util.pIndexMap(NPatchCoarse-1, NPatchFine-1, NCoarseElement)
    tIndices = np.add.outer(tStartIndices, tIndexMap)
    
    return tIndices
예제 #6
0
def computeAverageFaceFlux(NWorldCoarse, fluxTF):
    # Note  I: these velocities are not conservative and do not fulfill
    #          strongly with Neumann boundary conditions
    #
    # Note II: the velocities are integrated and hence already scaled with face
    #          area
    d = np.size(NWorldCoarse)
    b = util.linearpIndexBasis(NWorldCoarse-1)

    avgFluxTF = np.array(fluxTF)
    for k in range(d):
        NWorldBase = np.array(NWorldCoarse-1)
        NWorldBase[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(NWorldBase, NWorldCoarse-1)
        avg = 0.5*(fluxTF[TIndBase, 2*k + 1] - fluxTF[TIndBase + b[k], 2*k])
        avgFluxTF[TIndBase, 2*k + 1] = avg
        avgFluxTF[TIndBase + b[k], 2*k] = -avg

    return avgFluxTF
예제 #7
0
def computeElementFaceFluxFromSigma(NWorldCoarse, sigmaFluxT):
    d = np.size(NWorldCoarse)

    NtCoarse = np.prod(NWorldCoarse)
    fluxTF = np.zeros([NtCoarse, 2*d])

    pBasis = util.linearpIndexBasis(np.ones_like(NWorldCoarse))
    for k in range(d):
        N = np.ones_like(NWorldCoarse)
        N[k] = 0
        bottomp = util.lowerLeftpIndexMap(N, np.ones_like(N))
        topp = bottomp + pBasis[k]

        NFace = np.array(NWorldCoarse)
        NFace[k] = 1
        faceArea = np.prod(1./NFace)
        
        fluxTF[:,2*k] = faceArea*np.mean(-sigmaFluxT[:,bottomp], axis=1)
        fluxTF[:,2*k + 1] = faceArea*np.mean(-sigmaFluxT[:,topp], axis=1)

    return fluxTF
예제 #8
0
def assembleFaceConnectivityMatrix(NPatch, FLoc, boundaryMap=None):
    Nt = np.prod(NPatch)

    d = np.size(NPatch)

    if boundaryMap is None:
        boundaryMap = np.zeros([d, 2], dtype='bool')

    rowsList = []
    colsList = []
    valuesList = []

    tBasis = util.linearpIndexBasis(NPatch - 1)
    for k in range(d):
        for boundary in [0, 1]:
            NPatchBase = np.array(NPatch)
            NPatchBase[k] -= 1

            TIndInterior = (1 -
                            boundary) * tBasis[k] + util.lowerLeftpIndexMap(
                                NPatchBase - 1, NPatch - 1)
            nT = np.size(TIndInterior)

            FLocRepeated = np.repeat(FLoc[2 * k + boundary], nT)

            # Add diagonal elements
            rowsList.append(TIndInterior)
            colsList.append(TIndInterior)
            valuesList.append(FLocRepeated)

            # Add off-diagonal elements
            rowsList.append(TIndInterior + (2 * boundary - 1) * tBasis[k])
            colsList.append(TIndInterior)
            valuesList.append(-FLocRepeated / 2.)

            rowsList.append(TIndInterior)
            colsList.append(TIndInterior + (2 * boundary - 1) * tBasis[k])
            valuesList.append(-FLocRepeated / 2.)

            # Add boundary diagonal elements, if applies
            if boundaryMap[k, boundary]:
                NPatchBottom = np.array(NPatch)
                NPatchBottom[k] = 1

                TIndBoundary = (boundary)*tBasis[k]*(NPatch[k]-1) + \
                               util.lowerLeftpIndexMap(NPatchBottom-1, NPatch-1)
                nT = np.size(TIndBoundary)

                FLocRepeatedBoundary = np.repeat(FLoc[2 * k + boundary], nT)

                rowsList.append(TIndBoundary)
                colsList.append(TIndBoundary)
                valuesList.append(FLocRepeatedBoundary)

    # Concatenate lists
    rows = np.hstack(rowsList)
    cols = np.hstack(colsList)
    values = np.hstack(valuesList)

    # Create sparse matrix
    FC = sparse.csc_matrix((values, (rows, cols)), shape=(Nt, Nt))

    return FC
예제 #9
0
 def __init__(self, NMax):
     self.NMax = NMax
     self.indexBasis = util.linearpIndexBasis(NMax)
     self.factorCache = dict()