Skip to content
Snippets Groups Projects
LinAlg.cpp 6.89 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * \copyright
    
     * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
    
     *            Distributed under a Modified BSD License.
     *              See accompanying file LICENSE.txt or
     *              http://www.opengeosys.org/project/license
     *
     */
    
    
    #include "LinAlg.h"
    
    // TODO reorder LinAlg function signatures?
    
    
    // Global PETScMatrix/PETScVector //////////////////////////////////////////
    #ifdef USE_PETSC
    
    #include "MathLib/LinAlg/PETSc/PETScMatrix.h"
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    #include "MathLib/LinAlg/PETSc/PETScVector.h"
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    namespace MathLib
    {
    namespace LinAlg
    
    void setLocalAccessibleVector(PETScVector const& x)
    
    {
        x.setLocalAccessibleVector();
    }
    
    
    void set(PETScVector& x, PetscScalar const a)
    
    Norihiro Watanabe's avatar
    Norihiro Watanabe committed
    {
        VecSet(x.getRawVector(), a);
    }
    
    
    void copy(PETScVector const& x, PETScVector& y)
    {
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        if (!y.getRawVector())
            y.shallowCopy(x);
    
        VecCopy(x.getRawVector(), y.getRawVector());
    
    void scale(PETScVector& x, PetscScalar const a)
    
        VecScale(x.getRawVector(), a);
    
    void aypx(PETScVector& y, PetscScalar const a, PETScVector const& x)
    
    {
        // TODO check sizes
    
        VecAYPX(y.getRawVector(), a, x.getRawVector());
    
    void axpy(PETScVector& y, PetscScalar const a, PETScVector const& x)
    
    {
        // TODO check sizes
    
        VecAXPY(y.getRawVector(), a, x.getRawVector());
    
    // y = a*x + b*y
    
    void axpby(PETScVector& y, PetscScalar const a, PetscScalar const b,
               PETScVector const& x)
    
    {
        // TODO check sizes
    
        VecAXPBY(y.getRawVector(), a, b, x.getRawVector());
    
    // Explicit specialization
    // Computes w = x/y componentwise.
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    void componentwiseDivide(PETScVector& w, PETScVector const& x,
                             PETScVector const& y)
    
        VecPointwiseDivide(w.getRawVector(), x.getRawVector(), y.getRawVector());
    
    // Explicit specialization
    // Computes the Manhattan norm of x
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double norm1(PETScVector const& x)
    {
    
        PetscScalar norm = 0.;
        VecNorm(x.getRawVector(), NORM_1, &norm);
        return norm;
    
    // Explicit specialization
    // Computes the Euclidean norm of x
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double norm2(PETScVector const& x)
    {
    
        PetscScalar norm = 0.;
        VecNorm(x.getRawVector(), NORM_2, &norm);
        return norm;
    
    // Explicit specialization
    // Computes the Maximum norm of x
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double normMax(PETScVector const& x)
    {
    
        PetscScalar norm = 0.;
        VecNorm(x.getRawVector(), NORM_INFINITY, &norm);
        return norm;
    
    // Matrix
    
    void copy(PETScMatrix const& A, PETScMatrix& B)
    {
        B = A;
    }
    
    // A = a*A
    
    void scale(PETScMatrix& A, PetscScalar const a)
    
    {
        MatScale(A.getRawMatrix(), a);
    }
    
    // Y = a*Y + X
    
    void aypx(PETScMatrix& Y, PetscScalar const a, PETScMatrix const& X)
    
    {
        // TODO check sizes
        // TODO sparsity pattern, currently they are assumed to be different (slow)
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        MatAYPX(Y.getRawMatrix(), a, X.getRawMatrix(), DIFFERENT_NONZERO_PATTERN);
    
    void axpy(PETScMatrix& Y, PetscScalar const a, PETScMatrix const& X)
    
    {
        // TODO check sizes
        // TODO sparsity pattern, currently they are assumed to be different (slow)
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        MatAXPY(Y.getRawMatrix(), a, X.getRawMatrix(), DIFFERENT_NONZERO_PATTERN);
    
    }
    
    // Matrix and Vector
    
    // v3 = A*v1 + v2
    void matMult(PETScMatrix const& A, PETScVector const& x, PETScVector& y)
    {
        // TODO check sizes
        assert(&x != &y);
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        if (!y.getRawVector())
            y.shallowCopy(x);
    
        MatMult(A.getRawMatrix(), x.getRawVector(), y.getRawVector());
    
    }
    
    // v3 = A*v1 + v2
    void matMultAdd(PETScMatrix const& A, PETScVector const& v1,
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
                    PETScVector const& v2, PETScVector& v3)
    
    {
        // TODO check sizes
        assert(&v1 != &v3);
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        if (!v3.getRawVector())
            v3.shallowCopy(v1);
        MatMultAdd(A.getRawMatrix(), v1.getRawVector(), v2.getRawVector(),
                   v3.getRawVector());
    
    }
    
    void finalizeAssembly(PETScMatrix& A)
    {
        A.finalizeAssembly(MAT_FINAL_ASSEMBLY);
    }
    
    void finalizeAssembly(PETScVector& x)
    {
        x.finalizeAssembly();
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    }  // namespace LinAlg
    }  // namespace MathLib
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    // Sparse global EigenMatrix/EigenVector
    // //////////////////////////////////////////
    
    
    #include "MathLib/LinAlg/Eigen/EigenMatrix.h"
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    #include "MathLib/LinAlg/Eigen/EigenVector.h"
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    namespace MathLib
    {
    namespace LinAlg
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    void setLocalAccessibleVector(EigenVector const& /*x*/) {}
    
    void set(EigenVector& x, double const a)
    
        x.getRawVector().setConstant(a);
    
    void copy(EigenVector const& x, EigenVector& y)
    {
        y = x;
    }
    
    void scale(EigenVector& x, double const a)
    {
    
        x.getRawVector() *= a;
    
    }
    
    // y = a*y + X
    void aypx(EigenVector& y, double const a, EigenVector const& x)
    {
        // TODO: does that break anything?
    
        y.getRawVector() = a * y.getRawVector() + x.getRawVector();
    
    }
    
    // y = a*x + y
    void axpy(EigenVector& y, double const a, EigenVector const& x)
    {
        // TODO: does that break anything?
    
        y.getRawVector() += a * x.getRawVector();
    
    }
    
    // y = a*x + y
    void axpby(EigenVector& y, double const a, double const b, EigenVector const& x)
    {
        // TODO: does that break anything?
    
        y.getRawVector() = a * x.getRawVector() + b * y.getRawVector();
    
    // Explicit specialization
    // Computes w = x/y componentwise.
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    void componentwiseDivide(EigenVector& w, EigenVector const& x,
                             EigenVector const& y)
    
    {
        w.getRawVector().noalias() =
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
            x.getRawVector().cwiseQuotient(y.getRawVector());
    
    // Explicit specialization
    // Computes the Manhattan norm of x
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double norm1(EigenVector const& x)
    {
        return x.getRawVector().lpNorm<1>();
    }
    
    
    // Explicit specialization
    // Euclidean norm
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double norm2(EigenVector const& x)
    {
        return x.getRawVector().norm();
    }
    
    
    // Explicit specialization
    // Computes the Maximum norm of x
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    template <>
    
    double normMax(EigenVector const& x)
    {
        return x.getRawVector().lpNorm<Eigen::Infinity>();
    }
    
    
    // Matrix
    
    void copy(EigenMatrix const& A, EigenMatrix& B)
    {
        B = A;
    }
    
    // A = a*A
    void scale(EigenMatrix& A, double const a)
    {
        // TODO: does that break anything?
        A.getRawMatrix() *= a;
    }
    
    // Y = a*Y + X
    void aypx(EigenMatrix& Y, double const a, EigenMatrix const& X)
    {
        // TODO: does that break anything?
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        Y.getRawMatrix() = a * Y.getRawMatrix() + X.getRawMatrix();
    
    }
    
    // Y = a*X + Y
    void axpy(EigenMatrix& Y, double const a, EigenMatrix const& X)
    {
        // TODO: does that break anything?
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        Y.getRawMatrix() = a * X.getRawMatrix() + Y.getRawMatrix();
    
    }
    
    // Matrix and Vector
    
    // v3 = A*v1 + v2
    void matMult(EigenMatrix const& A, EigenVector const& x, EigenVector& y)
    {
        assert(&x != &y);
    
        y.getRawVector() = A.getRawMatrix() * x.getRawVector();
    
    }
    
    // v3 = A*v1 + v2
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    void matMultAdd(EigenMatrix const& A, EigenVector const& v1,
                    EigenVector const& v2, EigenVector& v3)
    
    {
        assert(&v1 != &v3);
        // TODO: does that break anything?
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
        v3.getRawVector() =
            v2.getRawVector() + A.getRawMatrix() * v1.getRawVector();
    
    void finalizeAssembly(EigenMatrix& x)
    {
        x.getRawMatrix().makeCompressed();
    }
    
    
    void finalizeAssembly(EigenVector& /*x*/) {}
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    }  // namespace LinAlg
    
    Dmitri Naumov's avatar
    Dmitri Naumov committed
    }  // namespace MathLib