Skip to content
Snippets Groups Projects
Forked from agnumpde / dune-solvers
88 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
genericvectortools.hh 10.17 KiB
// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=8 sw=4 sts=4:
#ifndef GENERIC_VECTOR_TOOL_HH
#define GENERIC_VECTOR_TOOL_HH

/** \file
    \brief Various tools for working with istl vectors of arbitrary nesting depth
*/

#include<iostream>
#include<bitset>

#include <dune/common/diagonalmatrix.hh>
#include <dune/common/fvector.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/diagonalmatrix.hh>
#include <dune/common/indices.hh>
#include <dune/common/hybridutilities.hh>

#include <dune/istl/scaledidmatrix.hh>
#include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh>

#include <dune/matrix-vector/genericvectortools.hh>
#include <dune/matrix-vector/resize.hh>

#include <dune/solvers/operators/sumoperator.hh>

/** \brief Various tools for working with istl vectors of arbitrary nesting depth
*/
struct GenericVector
{


    //! Write vector to given stream
    template <class VectorType>
    DUNE_DEPRECATED_MSG("Please use Dune::MatrixVector::Generic::writeBinary instead.")
    static void writeBinary(std::ostream& s, const VectorType& v)
    {
      Dune::MatrixVector::Generic::writeBinary(s, v);
    }

    //! Read vector from a given stream
    template <class VectorType>
    DUNE_DEPRECATED_MSG("Please use Dune::MatrixVector::Generic::readBinary instead.")
    static void readBinary(std::istream& s, VectorType& v)
    {
        Dune::MatrixVector::Generic::readBinary(s, v);
    }

    //! Resize vector recursivly to size of given vector/matrix
    template <class VectorTypeA, class VectorTypeB>
    DUNE_DEPRECATED_MSG("Please use Dune::MatrixVector::resize instead.")
    static void resize(VectorTypeA& a, const VectorTypeB& b)
    {
        Dune::MatrixVector::resize(a, b);
    }

    //! Set vector to zero at indices that are true in bitvector recursivly
    template <class VectorType, class BitVectorType>
    DUNE_DEPRECATED_MSG("Please use Dune::MatrixVector::Generic::truncate instead.")
    static void truncate(VectorType& v, const BitVectorType& tr)
    {
        Dune::MatrixVector::Generic::truncate(v, tr);
    }

    //! weave two vector blocks into each other e.g. [[u1...un][w1...wn]] --> [[u1 w1]...[un wn]]
    template <class LVectorType, class RVectorType>
    static void interlace(const LVectorType& lvec DUNE_UNUSED, RVectorType& rvec DUNE_UNUSED)
    {
        DUNE_THROW(Dune::NotImplemented,"GenericVector::interlace not implemented for given VectorTypes");
    }

    /** \brief weave two vector blocks into each other e.g. [[u1...un][w1...wn]] --> [[u1 w1]...[un wn]]
     *
     * interlace: \f$\left((\mathbb R^k)^m\right)^n\longrightarrow(\mathbb R^k\cdot n)^m\f$, i.e. for example
     *
     * \f[
     *   \begin{pmatrix}
     *    \begin{pmatrix}
     *     \begin{pmatrix} a_{11}\\ a_{12} \end{pmatrix}\\
     *     \begin{pmatrix} a_{21}\\ a_{22} \end{pmatrix}\\
     *     \begin{pmatrix} a_{31}\\ a_{32} \end{pmatrix}
     *    \end{pmatrix}\\
     *    \begin{pmatrix}
     *     \begin{pmatrix} b_{11}\\ b_{12} \end{pmatrix}\\
     *     \begin{pmatrix} b_{21}\\ b_{22} \end{pmatrix}\\
     *     \begin{pmatrix} b_{31}\\ b_{32} \end{pmatrix}
     *    \end{pmatrix}\\
     *    \begin{pmatrix}
     *     \begin{pmatrix} c_{11}\\ c_{12} \end{pmatrix}\\
     *     \begin{pmatrix} c_{21}\\ c_{22} \end{pmatrix}\\
     *     \begin{pmatrix} c_{31}\\ c_{32} \end{pmatrix}
     *    \end{pmatrix}\\
     *    \begin{pmatrix}
     *     \begin{pmatrix} d_{11}\\ d_{12} \end{pmatrix}\\
     *     \begin{pmatrix} d_{21}\\ d_{22} \end{pmatrix}\\
     *     \begin{pmatrix} d_{31}\\ d_{32} \end{pmatrix}
     *    \end{pmatrix}
     *   \end{pmatrix}
     *
     *   \xrightarrow{interlace}
     *
     *   \begin{pmatrix}
     *    \begin{pmatrix}
     *     a_{11}\\ a_{12}\\ b_{11}\\ b_{12}\\ c_{11}\\ c_{12}\\ d_{11}\\ d_{12}
     *    \end{pmatrix}\\
     *    \begin{pmatrix}
     *     a_{21}\\ a_{22}\\ b_{21}\\ b_{22}\\ c_{21}\\ c_{22}\\ d_{21}\\ d_{22}
     *    \end{pmatrix}\\
     *    \begin{pmatrix}
     *     a_{31}\\ a_{32}\\ b_{31}\\ b_{32}\\ c_{31}\\ c_{32}\\ d_{31}\\ d_{32}
     *    \end{pmatrix}
     *   \end{pmatrix}
     * \f]
     */
    template <class LVectorBlock, class RVectorBlock>
    static void interlace(const Dune::BlockVector<Dune::BlockVector<LVectorBlock> >& lvec, Dune::BlockVector<RVectorBlock>& rvec)
    {
        static_assert(RVectorBlock::dimension % LVectorBlock::dimension == 0, "Block sizes don't match.");

        rvec.resize(lvec[0].size());
        rvec = 0.0;

        size_t offset = LVectorBlock::dimension;

        for (size_t i=0; i<lvec[0].size(); ++i)
            for (size_t k=0; k<lvec.size(); ++k)
                for (size_t j=0; j<offset; ++j)
                    rvec[i][j+k*offset] = lvec[k][i][j];
    }

    //! unweave two vectors previously interlaced e.g. [[u1 w1]...[un wn]] --> [[u1...un][w1...wn]]
    template <class LVectorType, class RVectorType>
    static void deinterlace(const LVectorType& lvec DUNE_UNUSED, RVectorType& rvec DUNE_UNUSED)
    {
        DUNE_THROW(Dune::NotImplemented,"GenericVector::deinterlace not implemented for given VectorTypes");
    }

    template <class LVectorBlock, class RVectorBlock>
    static void deinterlace(const Dune::BlockVector<LVectorBlock>& lvec, Dune::BlockVector<Dune::BlockVector<RVectorBlock> >& rvec)
    {
        static_assert(LVectorBlock::dimension % RVectorBlock::dimension == 0, "Block sizes don't match.");

        rvec.resize(LVectorBlock::dimension / RVectorBlock::dimension);
        for (size_t k=0; k<rvec.size(); ++k)
            rvec[k].resize(lvec.size());
        rvec = 0.0;

        size_t offset = RVectorBlock::dimension;

        for (size_t i=0; i<lvec.size(); ++i)
            for (size_t k=0; k<rvec.size(); ++k)
                for (size_t j=0; j<offset; ++j)
                    rvec[k][i][j] = lvec[i][j+k*offset];
    }

    template <class VectorType>
    static std::size_t isnan(const VectorType& x)
    {
        std::size_t r = 0;

        typename VectorType::ConstIterator x_it=x.begin();
        typename VectorType::ConstIterator x_end=x.end();
        for (;x_it!=x_end; ++x_it)
            r += isnan(*x_it);

        return r;
    }

    template <class field_type, int n>
    static std::size_t isnan(const Dune::FieldVector<field_type,n>& x)
    {
        std::size_t r=0;

        for (std::size_t i=0; i<n; ++i)
            r += (size_t)(std::fpclassify(x[i])==FP_NAN);

        return r;
    }
};

struct GenericMatrix
{

    //! Set matrix to zero at indices that are true in bitvector recursivly
    template <class MatrixType, class BitVectorTypeR, class BitVectorTypeC>
    static void truncate(MatrixType& mat, const BitVectorTypeR& trows, const BitVectorTypeC& tcols, bool setTruncatedDiagonalOne)
    {
        assert(trows.size()==mat.N());
        assert(tcols.size()==mat.M());
        typename MatrixType::RowIterator row_it = mat.begin();
        typename MatrixType::RowIterator row_end = mat.end();
        for(; row_it!=row_end; ++row_it)
        {
            size_t row = row_it.index();

            typename MatrixType::row_type::iterator col_it = row_it->begin();
            typename MatrixType::row_type::iterator col_end = row_it->end();
            for (; col_it!=col_end; ++col_it)
            {
                size_t col = col_it.index();
                GenericMatrix::truncate(*col_it, trows[row], tcols[col], setTruncatedDiagonalOne and (col==row));
            }
        }
    }

    template <class field_type, int n, int m, class BitVectorTypeR, class BitVectorTypeC>
    static void truncate(Dune::FieldMatrix<field_type,n,m>& mat, const BitVectorTypeR& trows, const BitVectorTypeC& tcols, bool setTruncatedDiagonalOne)
    {
//        static_assert(BitVectorTypeR.size()==n and BitVectorTypeC.size()==m,"BitVector length doesn't match matrix size.");
        assert(trows.size()==n and tcols.size()==m);

        for(size_t row=0; row<n; ++row)
        {
            if (trows[row])
            {
                mat[row] = 0.0;
                if (setTruncatedDiagonalOne)
                    mat[row][row] = 1.0;
                continue;
            }

            for (size_t col=0; col<m; ++col)
            {
                if (tcols[col])
                    mat[row][col] = (setTruncatedDiagonalOne and col==row)?1.0:0.0;
            }
        }
    }

    template <class field_type, int n, class BitVectorType>
    static void truncate(Dune::DiagonalMatrix<field_type,n>& mat, const BitVectorType& trows, const BitVectorType& tcols, bool setTruncatedDiagonalOne)
    {
        for(size_t row=0; row<n; ++row)
        {
            if (trows[row])
            {
                mat.diagonal(row) = setTruncatedDiagonalOne?1.0:0.0;
                continue;
            }

            if (tcols[row])
                mat.diagonal(row) = setTruncatedDiagonalOne?1.0:0.0;
        }
    }

    template <class MatrixType>
    static std::size_t isnan(const MatrixType& A)
    {
        std::size_t r=0;

        typename MatrixType::ConstRowIterator row_it=A.begin();
        typename MatrixType::ConstRowIterator row_end=A.end();
        for (;row_it!=row_end; ++row_it)
        {
            typename MatrixType::ConstColIterator col_it=row_it->begin();
            typename MatrixType::ConstColIterator col_end=row_it->end();
            for (;col_it!=col_end; ++col_it)
                r += isnan(*col_it);
        }

        return r;
    }

    template <class field_type, int n, int m>
    static std::size_t isnan(const Dune::FieldMatrix<field_type,n,m>& x)
    {
        std::size_t r=0;

        for (std::size_t i=0; i<n; ++i)
            for (std::size_t j=0; j<m; ++j)
                r += (size_t)(std::fpclassify(x[i][j])==FP_NAN);

        if (r!=0)
            std::cout << x << std::endl;

        return r;
    }
    template <class field_type, int n>
    static std::size_t isnan(const Dune::DiagonalMatrix<field_type,n>& x)
    {
        std::size_t r=0;

        for (std::size_t i=0; i<n; ++i)
            r += (size_t)(std::fpclassify(x.diagonal(i))==FP_NAN);

        if (r!=0)
            std::cout << x << std::endl;

        return r;
    }

    template <class field_type, int n>
    static std::size_t isnan(const Dune::ScaledIdentityMatrix<field_type,n>& x)
    {
        return n*(size_t)(std::fpclassify(x.scalar())==FP_NAN);
    }

};

#endif