Example #1
0
 def test_permTensor_dim2_perm3(self):
     self.rock2.perm = np.array([[5, 3, 1], [5, 3, 1], [5, 3, 7], [5, 3,
                                                                   7]])
     K_prst = permTensor(self.rock2, 2)
     K_mrst = np.array([[5, 3, 3, 1], [5, 3, 3, 1], [5, 3, 3, 7],
                        [5, 3, 3, 7]])
     assert np.array_equal(K_prst, K_mrst)
Example #2
0
 def test_permTensor_dim3_perm1(self):
     self.rock3.perm = np.array([[5], [5], [5], [5]])
     K_prst = permTensor(self.rock3, 3)
     K_mrst = np.array([[5, 0, 0, 0, 5, 0, 0, 0, 5],
                        [5, 0, 0, 0, 5, 0, 0, 0, 5],
                        [5, 0, 0, 0, 5, 0, 0, 0, 5],
                        [5, 0, 0, 0, 5, 0, 0, 0, 5]])
     assert np.array_equal(K_prst, K_mrst)
Example #3
0
 def test_permTensor_dim3_perm3(self):
     self.rock3.perm = np.array([[5, 3, 1], [5, 3, 1], [5, 3, 7], [5, 3,
                                                                   7]])
     K_prst = permTensor(self.rock3, 3)
     K_mrst = np.array([[5, 0, 0, 0, 3, 0, 0, 0, 1],
                        [5, 0, 0, 0, 3, 0, 0, 0, 1],
                        [5, 0, 0, 0, 3, 0, 0, 0, 7],
                        [5, 0, 0, 0, 3, 0, 0, 0, 7]])
     assert np.array_equal(K_prst, K_mrst)
Example #4
0
 def test_permTensor_dim3_perm6(self):
     self.rock3.perm = np.array([[5, 3, 1, 6, 6, 6], [5, 3, 1, 6, 6, 6],
                                 [5, 3, 7, 6, 6, 6], [5, 3, 7, 6, 6, 6]])
     K_prst = permTensor(self.rock3, 3)
     K_mrst = np.array([[5, 3, 1, 3, 6, 6, 1, 6, 6],
                        [5, 3, 1, 3, 6, 6, 1, 6, 6],
                        [5, 3, 7, 3, 6, 6, 7, 6, 6],
                        [5, 3, 7, 3, 6, 6, 7, 6, 6]])
     assert np.array_equal(K_prst, K_mrst)
Example #5
0
def computeTrans(G, rock, K_system="xyz", cellCenters=None, cellFaceCenters=None,
        verbose=False):
    """
    Compute transmissibilities for a grid.

    Synopsis:
        T = computeTrans(G, rock)
        T = computeTrans(G, rock, **kwargs)

    Arguments:
        G (Grid):
            prst.gridprocessing.Grid instance.

        rock (Rock):
            prst.params.rock.Rock instance with `perm` attribute. The
            permeability is assumed to be in units of metres squared (m^2).
            Use constant `darcy` from prst.utils.units to convert to m^2, e.g.,

                from prst.utils.units import *
                perm = convert(perm, from_=milli*darcy, to=meter**2)

            if the permeability is provided in units of millidarcies.

            The field rock.perm may have ONE column for a scalar permeability in each cell,
            TWO/THREE columns for a diagonal permeability in each cell (in 2/D
            D) and THREE/SIX columns for a symmetric full tensor permeability.
            In the latter case, each cell gets the permability tensor.

                K_i = [ k1  k2 ]      in two space dimensions
                      [ k2  k3 ]

                K_i = [ k1  k2  k3 ]  in three space dimensions
                      [ k2  k4  k5 ]
                      [ k3  k5  k6 ]

        K_system (Optional[str]):
            The system permeability. Valid values are "xyz" and "loc_xyz".

        cellCenters (Optional[ndarray]):
            Compute transmissibilities based on supplied cellCenters rather
            than default G.cells.centroids. Must have shape (n,2) for 2D and
            (n,3) for 3D.

        cellFaceCenters (Optional[ndarray]):
            Compute transmissibilities based on supplied cellFaceCenters rather
            than default `G.faces.centroids[G.cells.faces[:,0], :]`.

    Returns:
        T: Half-transmissibilities for each local face of each grid cell in the
        grid. The number of half-transmissibilities equals the number of rows
        in `G.cells.faces`. 2D column array.

    Comments:
        PLEASE NOTE: Face normals are assumed to have length equal to the
        corresponding face areas. This property is guaranteed by function
        `computeGeometry`.

    See also:
        computeGeometry, computeMimeticIP (MRST), darcy, permTensor, Rock
    """
    if K_system not in ["xyz", "loc_xyz"]:
        raise TypeError(
            "Specified permeability coordinate system must be a 'xyz' or 'loc_xyz'")

    if verbose:
        print("Computing one-sided transmissibilites.")

    # Vectors from cell centroids to face centroids
    assert G.cells.facePos.ndim == 2, "facePos has wrong dimensions"
    cellNo = rldecode(np.arange(G.cells.num), np.diff(G.cells.facePos, axis=0))
    if cellCenters is None:
        C = G.cells.centroids
    else:
        C = cellCenters
    if cellFaceCenters is None:
        C = G.faces.centroids[G.cells.faces[:,0],:] - C[cellNo,:]
    else:
        C = cellFaceCenters - C[cellNo,:]

    # Normal vectors
    sgn = 2*(cellNo == G.faces.neighbors[G.cells.faces[:,0], 0]) - 1
    N = sgn[:,np.newaxis] * G.faces.normals[G.cells.faces[:,0],:]

    if K_system == "xyz":
        K, i, j = permTensor(rock, G.gridDim, rowcols=True)
        assert K.shape[0] == G.cells.num, \
            "Permeability must be defined in active cells only.\n"+\
            "Got {} tensors, expected {} (== num cells)".format(K.shape[0], G.cells.num)

        # Compute T = C'*K*N / C'*C. Loop based to limit memory use.
        T = np.zeros(cellNo.size)
        for k in range(i.size):
            tmp = C[:,i[k]] * K[cellNo,k] * N[:,j[k]]
            # Handle both 1d and 2d array.
            if tmp.ndim == 1:
                T += tmp
            else:
                T += np.sum(tmp, axis=1)
        T = T / np.sum(C*C, axis=1)

    elif K_system == "loc_xyz":
        if rock.perm.shape[1] == 1:
            rock.perm = np.tile(rock.perm, (1, G.gridDim))
        if rock.perm.shape[1] != G.cartDims.size:
            raise ValueError(
                "Permeability coordinate system `loc_xyz` is only "+\
                "valid for diagonal tensor.")
        assert rock.perm.shape[0] == G.cells.num,\
            "Permeability must be defined in active cells only. "+\
            "Got {} tensors, expected {} == (num cells)".format(rock.perm.shape[0], G.cells.num)

        dim = np.ceil(G.cells.faces[:,1] / 2)
        raise NotImplementedError("Function not finished for K_system='loc_xyz'")
        # See MRST, solvers/computeTrans.m

    else:
        raise ValueError("Unknown permeability coordinate system {}.".format(K_system))

    is_neg = T < 0
    if np.any(is_neg):
        if verbose:
            prst.log.warn("Warning: {} negative transmissibilities. ".format(np.sum(is_neg))+
                          "Replaced by absolute values...")
            T[is_neg] = -T[is_neg]

    return np.atleast_2d(T).transpose()
Example #6
0
def computeTrans(G,
                 rock,
                 K_system="xyz",
                 cellCenters=None,
                 cellFaceCenters=None,
                 verbose=False):
    """
    Compute transmissibilities for a grid.

    Synopsis:
        T = computeTrans(G, rock)
        T = computeTrans(G, rock, **kwargs)

    Arguments:
        G (Grid):
            prst.gridprocessing.Grid instance.

        rock (Rock):
            prst.params.rock.Rock instance with `perm` attribute. The
            permeability is assumed to be in units of metres squared (m^2).
            Use constant `darcy` from prst.utils.units to convert to m^2, e.g.,

                from prst.utils.units import *
                perm = convert(perm, from_=milli*darcy, to=meter**2)

            if the permeability is provided in units of millidarcies.

            The field rock.perm may have ONE column for a scalar permeability in each cell,
            TWO/THREE columns for a diagonal permeability in each cell (in 2/D
            D) and THREE/SIX columns for a symmetric full tensor permeability.
            In the latter case, each cell gets the permability tensor.

                K_i = [ k1  k2 ]      in two space dimensions
                      [ k2  k3 ]

                K_i = [ k1  k2  k3 ]  in three space dimensions
                      [ k2  k4  k5 ]
                      [ k3  k5  k6 ]

        K_system (Optional[str]):
            The system permeability. Valid values are "xyz" and "loc_xyz".

        cellCenters (Optional[ndarray]):
            Compute transmissibilities based on supplied cellCenters rather
            than default G.cells.centroids. Must have shape (n,2) for 2D and
            (n,3) for 3D.

        cellFaceCenters (Optional[ndarray]):
            Compute transmissibilities based on supplied cellFaceCenters rather
            than default `G.faces.centroids[G.cells.faces[:,0], :]`.

    Returns:
        T: Half-transmissibilities for each local face of each grid cell in the
        grid. The number of half-transmissibilities equals the number of rows
        in `G.cells.faces`. 2D column array.

    Comments:
        PLEASE NOTE: Face normals are assumed to have length equal to the
        corresponding face areas. This property is guaranteed by function
        `computeGeometry`.

    See also:
        computeGeometry, computeMimeticIP (MRST), darcy, permTensor, Rock
    """
    if K_system not in ["xyz", "loc_xyz"]:
        raise TypeError(
            "Specified permeability coordinate system must be a 'xyz' or 'loc_xyz'"
        )

    if verbose:
        print("Computing one-sided transmissibilites.")

    # Vectors from cell centroids to face centroids
    assert G.cells.facePos.ndim == 2, "facePos has wrong dimensions"
    cellNo = rldecode(np.arange(G.cells.num), np.diff(G.cells.facePos, axis=0))
    if cellCenters is None:
        C = G.cells.centroids
    else:
        C = cellCenters
    if cellFaceCenters is None:
        C = G.faces.centroids[G.cells.faces[:, 0], :] - C[cellNo, :]
    else:
        C = cellFaceCenters - C[cellNo, :]

    # Normal vectors
    sgn = 2 * (cellNo == G.faces.neighbors[G.cells.faces[:, 0], 0]) - 1
    N = sgn[:, np.newaxis] * G.faces.normals[G.cells.faces[:, 0], :]

    if K_system == "xyz":
        K, i, j = permTensor(rock, G.gridDim, rowcols=True)
        assert K.shape[0] == G.cells.num, \
            "Permeability must be defined in active cells only.\n"+\
            "Got {} tensors, expected {} (== num cells)".format(K.shape[0], G.cells.num)

        # Compute T = C'*K*N / C'*C. Loop based to limit memory use.
        T = np.zeros(cellNo.size)
        for k in range(i.size):
            tmp = C[:, i[k]] * K[cellNo, k] * N[:, j[k]]
            # Handle both 1d and 2d array.
            if tmp.ndim == 1:
                T += tmp
            else:
                T += np.sum(tmp, axis=1)
        T = T / np.sum(C * C, axis=1)

    elif K_system == "loc_xyz":
        if rock.perm.shape[1] == 1:
            rock.perm = np.tile(rock.perm, (1, G.gridDim))
        if rock.perm.shape[1] != G.cartDims.size:
            raise ValueError(
                "Permeability coordinate system `loc_xyz` is only "+\
                "valid for diagonal tensor.")
        assert rock.perm.shape[0] == G.cells.num,\
            "Permeability must be defined in active cells only. "+\
            "Got {} tensors, expected {} == (num cells)".format(rock.perm.shape[0], G.cells.num)

        dim = np.ceil(G.cells.faces[:, 1] / 2)
        raise NotImplementedError(
            "Function not finished for K_system='loc_xyz'")
        # See MRST, solvers/computeTrans.m

    else:
        raise ValueError(
            "Unknown permeability coordinate system {}.".format(K_system))

    is_neg = T < 0
    if np.any(is_neg):
        if verbose:
            prst.log.warn("Warning: {} negative transmissibilities. ".format(
                np.sum(is_neg)) + "Replaced by absolute values...")
            T[is_neg] = -T[is_neg]

    return np.atleast_2d(T).transpose()