8#include <kernel/lafem/null_matrix.hpp> 
    9#include <kernel/lafem/sparse_matrix_bcsr.hpp> 
   10#include <kernel/lafem/sparse_matrix_csr.hpp> 
   11#include <kernel/lafem/saddle_point_matrix.hpp> 
   12#include <kernel/lafem/tuple_matrix.hpp> 
   13#include <kernel/global/matrix.hpp> 
   14#include <kernel/solver/base.hpp> 
   15#include <kernel/solver/amavanka_base.hpp> 
   16#include <kernel/util/stop_watch.hpp> 
   62    template<
typename Matrix_, 
typename Filter_>
 
   79      typedef typename Intern::AmaVankaMatrixHelper<Matrix_>::VankaMatrix 
VankaMatrixType;
 
  128      explicit AmaVanka(
const Matrix_& matrix, 
const Filter_& filter,
 
  145        this->_macro_dofs.clear();
 
  160        if(
int(
_macro_dofs.size()) >= Intern::AmaVankaMatrixHelper<Matrix_>::num_blocks)
 
  161          XABORTM(
"all macro-dofs graphs have already been added");
 
  165          XABORTM(
"macro count mismatch");
 
  168        _macro_dofs.emplace_back(std::forward<Adjacency::Graph>(dofs));
 
  183        this->_num_steps = num_steps;
 
  195        this->_omega = omega;
 
  206        this->_skip_singular = skip_sing;
 
  214        std::size_t s = 
_vanka.bytes();
 
  216          s += 
sizeof(
Index) * std::size_t(g.get_num_nodes_domain() + g.get_num_indices());
 
  217        for(
const auto& g : _dof_macros)
 
  218          s += 
sizeof(
Index) * std::size_t(g.get_num_nodes_domain() + g.get_num_indices());
 
  232        return std::size_t(
_vanka.template used_elements<LAFEM::Perspective::pod>());
 
  240        watch_init_symbolic.
reset();
 
  241        watch_init_numeric.
reset();
 
  250        return watch_init_symbolic.
elapsed();
 
  258        return watch_init_numeric.
elapsed();
 
  278        watch_init_symbolic.
start();
 
  283        if(this->_num_steps > 
Index(1))
 
  285          this->_vec_c = this->_matrix.create_vector_l();
 
  286          this->_vec_d = this->_matrix.create_vector_l();
 
  290        if(this->_auto_macros)
 
  293          if(!Intern::AmaVankaCore::deduct_macro_dofs(this->_matrix, this->_macro_dofs))
 
  294            XABORTM(
"Cannot auto-deduct macros for this matrix type");
 
  299           "invalid number of macro-dof graphs; did you push all of them?");
 
  302        this->_dof_macros.resize(this->_macro_dofs.size());
 
  303        for(std::size_t i(0); i < this->_macro_dofs.size(); ++i)
 
  306          XASSERT(this->_macro_dofs.at(i).get_num_nodes_domain() == this->_macro_dofs.front().get_num_nodes_domain());
 
  313        if(this->_skip_singular)
 
  314          this->_macro_mask.resize(this->_macro_dofs.front().get_num_nodes_domain(), 0);
 
  316        Solver::Intern::AmaVankaCore::alloc(this->_vanka, this->_dof_macros, this->_macro_dofs, 
Index(0), 
Index(0));
 
  318        watch_init_symbolic.
stop();
 
  324        this->_vanka.clear();
 
  325        this->_macro_mask.clear();
 
  326        this->_dof_macros.clear();
 
  327        if(this->_auto_macros)
 
  328          this->_macro_dofs.clear();
 
  329        if(this->_num_steps > 
Index(1))
 
  331          this->_vec_d.clear();
 
  332          this->_vec_c.clear();
 
  340        const DataType eps = Math::eps<DataType>();
 
  342        watch_init_numeric.
start();
 
  345        this->_vanka.format();
 
  348        const Index num_macros = 
Index(this->_macro_dofs.front().get_num_nodes_domain());
 
  349        const Index stride = Intern::AmaVankaCore::calc_stride(this->_vanka, this->_macro_dofs);
 
  351        FEAT_PRAGMA_OMP(parallel)
 
  354          std::vector<DataType> vec_local(stride*stride, 
DataType(0)), vec_local_t(stride*stride, 
DataType(0));
 
  355          std::vector<Index> vec_pivot(stride);
 
  357          DataType* local_t = vec_local_t.data();
 
  358          Index* pivot = vec_pivot.data();
 
  362          for(
Index imacro = 0; imacro < num_macros; ++imacro)
 
  365            const std::pair<Index,Index> nrc = Intern::AmaVankaCore::gather(this->_matrix,
 
  369            XASSERTM(nrc.first == nrc.second, 
"local matrix is not square");
 
  372            bool singular = 
false;
 
  375            if(this->_skip_singular)
 
  385              for(
Index i(0); i < nrc.first; ++i)
 
  386                for(
Index j(0); j < nrc.second; ++j)
 
  387                  local_t[i*stride+j] = local[i*stride+j];
 
  394              for(
Index i(0); i < nrc.first; ++i)
 
  396                for(
Index j(0); j < nrc.first; ++j)
 
  399                  for(
Index k(0); k < nrc.first; ++k)
 
  400                    xij -= local_t[i*stride+k] * local[k*stride+j]; 
 
  409              singular = !(norm < eps);
 
  412              this->_macro_mask[imacro] = (singular ? 0 : 1);
 
  423              FEAT_PRAGMA_OMP(critical)
 
  425                Intern::AmaVankaCore::scatter_add(this->_vanka, local, stride, imacro, this->_macro_dofs,
 
  431            for(
Index i(0); i < nrc.first; ++i)
 
  432              for(
Index j(0); j < nrc.second; ++j)
 
  438        Solver::Intern::AmaVankaCore::scale_rows(this->_vanka, this->_omega, this->_dof_macros, this->_macro_mask, 
Index(0), 
Index(0));
 
  440        watch_init_numeric.
stop();
 
  449        this->_vanka.apply(vec_x, vec_b);
 
  450        this->_filter.filter_cor(vec_x);
 
  456          this->_matrix.apply(this->_vec_d, vec_x, vec_b, -
DataType(1));
 
  458          this->_filter.filter_def(this->_vec_d);
 
  460          this->_vanka.apply(this->_vec_c, this->_vec_d);
 
  462          this->_filter.filter_cor(this->_vec_c);
 
  464          vec_x.axpy(this->_vec_c);
 
  472      bool compare(
const AmaVanka* other)
 const 
  474        return Intern::AmaVankaMatrixHelper<VankaMatrixType>::compare(this->_vanka, other->_vanka);
 
  496    template<
typename Matrix_, 
typename Filter_>
 
  497    std::shared_ptr<AmaVanka<Matrix_, Filter_>> 
new_amavanka(
const Matrix_& matrix, 
const Filter_& filter,
 
  498      typename Matrix_::DataType omega = 
typename Matrix_::DataType(1), 
Index num_steps = 
Index(1))
 
  500      return std::make_shared<AmaVanka<Matrix_, Filter_>>(matrix, filter, omega, num_steps);
 
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Adjacency Graph implementation.
Additive Macro-wise Matrix-based Vanka preconditioner/smoother.
std::size_t bytes() const
Returns the total number of bytes currently allocated in this object.
virtual String name() const override
Returns the name of the solver.
const Matrix_ & _matrix
the system matrix
std::vector< int > _macro_mask
the macro mask
Matrix_::DataType DataType
our data type
virtual Status apply(VectorType &vec_x, const VectorType &vec_b) override
applies the preconditioner
double time_apply() const
Returns the total accumulated time for the solver application.
Index _num_steps
number of steps
void set_omega(DataType omega)
Sets the damping parameter omega.
VectorType _vec_c
temporary vectors
Matrix_::IndexType IndexType
our index type
bool _auto_macros
deduct macro dofs automatically?
DataType _omega
damping parameter
bool _skip_singular
skip singular macros?
int _num_threads
number of threads for numeric factorization
virtual void init_numeric() override
Performs numeric factorization.
void reset_timings()
Resets the internal stop watches for time measurement.
virtual void init_symbolic() override
Performs symbolic factorization.
double time_init_symbolic() const
Returns the total accumulated time for symbolic initialization.
std::size_t data_size() const
Returns the total data size used by the AmaVanka smoother.
void set_skip_singular(bool skip_sing)
Sets whether singular macros are to be skipped.
const Filter_ & _filter
the system filter
Matrix_::VectorTypeL VectorType
our vector type
AmaVanka(const Matrix_ &matrix, const Filter_ &filter, const DataType omega=DataType(1), const Index num_steps=Index(1))
Constructor.
double time_init_numeric() const
Returns the total accumulated time for numeric initialization.
VankaMatrixType _vanka
the Vanka preconditioner matrix
virtual void done_symbolic() override
Releases the symbolic factorization data.
void set_num_steps(Index num_steps)
Sets the number of smoothing steps.
Solver::SolverBase< typename Matrix_::VectorTypeL > BaseClass
our base-class
void push_macro_dofs(Adjacency::Graph &&dofs)
Pushes the dofs-at-macro graph of the next block.
void clear_macro_dofs()
Clears the macro dofs graphs.
Intern::AmaVankaMatrixHelper< Matrix_ >::VankaMatrix VankaMatrixType
the type of our Vanka matrix
std::vector< Adjacency::Graph > _macro_dofs
the DOF-macro graphs
Polymorphic solver interface.
virtual void init_symbolic()
Symbolic initialization method.
virtual void init_numeric()
Numeric initialization method.
virtual void done_symbolic()
Symbolic finalization method.
double elapsed() const
Returns the total elapsed time in seconds.
void start()
Starts the stop-watch.
void reset()
Resets the elapsed time.
void stop()
Stops the stop-watch and increments elapsed time.
String class implementation.
@ transpose
Render-Transpose mode.
DT_ invert_matrix(const IT_ n, const IT_ stride, DT_ a[], IT_ p[])
Inverts a matrix and returns its determinant.
std::shared_ptr< AmaVanka< Matrix_, Filter_ > > new_amavanka(const Matrix_ &matrix, const Filter_ &filter, typename Matrix_::DataType omega=typename Matrix_::DataType(1), Index num_steps=Index(1))
Creates a new AmaVanka smoother object.
Status
Solver status return codes enumeration.
@ success
solving successful (convergence criterion fulfilled)
std::uint64_t Index
Index data type.