예제 #1
0
def covariantDerivative(T):
    """
    Returns a ``CurvilinearTensor`` that is the covariant derivative of
    the ``CurvilinearTensor`` argument ``T``.
    """
    n = rank(T.T)
    ii = indices(n + 2)
    g = T.g
    gamma = getChristoffel(g)
    retval = grad(T.T)
    for i in range(0, n):
        # use ii[n] as the new index of the covariant deriv
        # use ii[n+1] as dummy index
        if (T.lowered[i]):
            retval -= as_tensor(T.T[ii[0:i]+(ii[n+1],)+ii[i+1:n]]\
                                *gamma[(ii[n+1],ii[i],ii[n])],\
                                ii[0:n+1])
        else:
            retval += as_tensor(T.T[ii[0:i]+(ii[n+1],)+ii[i+1:n]]\
                                *gamma[(ii[i],ii[n+1],ii[n])],\
                                ii[0:n+1])
    newLowered = T.lowered + [
        True,
    ]
    return CurvilinearTensor(retval, g, newLowered)
예제 #2
0
def assemble(e, dx):
    """Assemble UFL form given by UFL expression e and UFL integration measure dx.
       The expression can be a tensor quantity of rank 0, 1 or 2.

    Parameters
    ----------
    e: UFL Expr
    dx: UFL Measure

    Returns
    -------
    Assembled form f = e * dx as scalar or numpy array (depends on rank of e).

    """

    import numpy as np
    from mpi4py import MPI

    rank = ufl.rank(e)
    shape = ufl.shape(e)

    if rank == 0:
        f_ = MPI.COMM_WORLD.allreduce(dolfinx.fem.assemble_scalar(e * dx), op=MPI.SUM)
    elif rank == 1:
        f_ = np.zeros(shape)
        for row in range(shape[0]):
            f_[row] = MPI.COMM_WORLD.allreduce(dolfinx.fem.assemble_scalar(e[row] * dx), op=MPI.SUM)
    elif rank == 2:
        f_ = np.zeros(shape)
        for row in range(shape[0]):
            for col in range(shape[1]):
                f_[row, col] = MPI.COMM_WORLD.allreduce(dolfinx.fem.assemble_scalar(e[row, col] * dx), op=MPI.SUM)
    return f_
예제 #3
0
def cartesianCurl(f, F):
    """
    The curl operator corresponding to ``cartesianGrad(f,F)``.  For ``f`` of 
    rank 1, it returns a vector in 3D or a scalar in 2D.  For ``f`` scalar
    in 2D, it returns a vector.
    """
    n = rank(f)
    gradf = cartesianGrad(f, F)
    if (n == 1):
        m = shape(f)[0]
        eps = PermutationSymbol(m)
        if (m == 3):
            (i, j, k) = indices(3)
            return as_tensor(eps[i, j, k] * gradf[k, j], (i, ))
        elif (m == 2):
            (j, k) = indices(2)
            return eps[j, k] * gradf[k, j]
        else:
            print("ERROR: Unsupported dimension of argument to curl.")
            exit()
    elif (n == 0):
        return as_vector((-gradf[1], gradf[0]))
    else:
        print("ERROR: Unsupported rank of argument to curl.")
        exit()
예제 #4
0
def cartesianDiv(f, F):
    """
    The divergence operator corresponding to ``cartesianGrad(f,F)`` that 
    sums on the last two indices.
    """
    n = rank(f)
    ii = indices(n)
    return as_tensor(cartesianGrad(f, F)[ii + (ii[n - 1], )], ii[0:n - 1])
예제 #5
0
 def flat(self):
     """
     Returns an associated tensor with all indices lowered.
     """
     retval = self
     for i in range(0, rank(self.T)):
         retval = retval.lowerIndex(i)
     return retval
예제 #6
0
 def sharp(self):
     """
     Returns an associated tensor with all indices raised.
     """
     retval = self
     for i in range(0, rank(self.T)):
         retval = retval.raiseIndex(i)
     return retval
예제 #7
0
def curvilinearInner(T, S):
    """
    Returns the inner product of ``CurvilinearTensor`` objects
    ``T`` and ``S``, inserting factors of the metric and inverse metric
    as needed, depending on the co/contra-variant status of corresponding
    indices.
    """
    Tsharp = T.sharp()
    Sflat = S.flat()
    ii = indices(rank(T.T))
    return as_tensor(Tsharp.T[ii] * Sflat.T[ii], ())
예제 #8
0
def curvilinearGrad(T):
    """
    Returns the gradient of ``CurvilinearTensor`` argument ``T``, i.e., the
    covariant derivative with the last index raised.
    """
    n = rank(T.T)
    ii = indices(n + 2)
    g = T.g
    deriv = covariantDerivative(T)
    invg = inv(g)
    # raise last index
    retval = as_tensor(deriv.T[ii[0:n+1]]*invg[ii[n:n+2]],\
                       ii[0:n]+(ii[n+1],))
    return CurvilinearTensor(retval, g, T.lowered + [
        False,
    ])
예제 #9
0
 def raiseLowerIndex(self, i):
     """
     Flips the raised/lowered status of the ``i``-th index.
     """
     n = rank(self.T)
     ii = indices(n + 1)
     mat = self.g
     if (self.lowered[i]):
         mat = inv(self.g)
     else:
         mat = self.g
     retval = as_tensor(self.T[ii[0:i]+(ii[i],)+ii[i+1:n]]\
                        *mat[ii[i],ii[n]],\
                        ii[0:i]+(ii[n],)+ii[i+1:n])
     return CurvilinearTensor(retval,self.g,\
                              self.lowered[0:i]\
                              +[not self.lowered[i],]+self.lowered[i+1:])
예제 #10
0
 def __init__(self, T, g, lowered=None):
     """
     Create a ``CurvilinearTensor`` with components given by the UFL tensor
     ``T``, on a manifold with metric ``g``.  The sequence of Booleans
     ``lowered`` indicates whether or not each index is lowered.  The 
     default is for all indices to be lowered.
     """
     self.T = T
     self.g = g
     if (lowered != None):
         self.lowered = lowered
     else:
         # default: all lowered indices
         self.lowered = []
         for i in range(0, rank(T)):
             self.lowered += [
                 True,
             ]
예제 #11
0
def curvilinearDiv(T):
    """
    Returns the divergence of the ``CurvilinearTensor`` argument ``T``, i.e.,
    the covariant derivative, but contracting over the new index and the 
    last raised index.  

    NOTE: This operation is invalid for tensors that do not 
    contain at least one raised index.
    """
    n = rank(T.T)
    ii = indices(n)
    g = T.g
    j = -1  # last raised index
    for i in range(0, n):
        if (not T.lowered[i]):
            j = i
    if (j == -1):
        print("ERROR: Divergence operator requires at least one raised index.")
        exit()
    deriv = covariantDerivative(T)
    retval = as_tensor(deriv.T[ii[0:n] + (ii[j], )], ii[0:j] + ii[j + 1:n])
    return CurvilinearTensor(retval, g, T.lowered[0:j] + T.lowered[j + 1:n])
예제 #12
0
 def rank(self):
     """
     Returns the rank of the tensor.
     """
     return rank(self.T)