From: Daniel Arndt Date: Sun, 1 Oct 2017 20:53:01 +0000 (+0200) Subject: Allow to use PreconditionMG with a separate DoFHandler for each block X-Git-Tag: v9.0.0-rc1~995^2~3 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4cd9001f0e02b5624dc292479c5d1bfd7053efa;p=dealii.git Allow to use PreconditionMG with a separate DoFHandler for each block --- diff --git a/include/deal.II/multigrid/multigrid.h b/include/deal.II/multigrid/multigrid.h index 1df6250a45..d9cf50b303 100644 --- a/include/deal.II/multigrid/multigrid.h +++ b/include/deal.II/multigrid/multigrid.h @@ -352,7 +352,11 @@ private: * void copy_from_mg(VectorType&) to store the result of the v-cycle * in @p dst. * - * @author Guido Kanschat, 1999, 2000, 2001, 2002 + * If VectorType is in fact a block vector and the TRANSFER object supports + * use of a separate DoFHandler for each block, this class also allows + * to be initialized with a separate DoFHandler for each block. + * + * @author Guido Kanschat, Daniel Arndt, 1999, 2000, 2001, 2002, 2017 */ template class PreconditionMG : public Subscriptor @@ -366,6 +370,14 @@ public: Multigrid &mg, const TRANSFER &transfer); + /** + * Same as above in case every component of a block vector + * uses its own DoFHandler. + */ + PreconditionMG(const std::vector*> &dof_handler, + Multigrid &mg, + const TRANSFER &transfer); + /** * Dummy function needed by other classes. */ @@ -408,14 +420,20 @@ public: const OtherVectorType &src) const; /** - * Return the partitioning of the range space of this preconditioner, i.e., the partitioning of the vectors that are result from matrix-vector products. + * Return the partitioning of the range space of this preconditioner, i.e., + * the partitioning of the vectors that are result from matrix-vector products. + * By default, the respective information for the first DoFHandler object + * are returned. */ - IndexSet locally_owned_range_indices() const; + IndexSet locally_owned_range_indices(const unsigned int block=0) const; /** - * Return the partitioning of the domain space of this preconditioner, i.e., the partitioning of the vectors this matrix has to be multiplied with. + * Return the partitioning of the domain space of this preconditioner, i.e., + * the partitioning of the vectors this matrix has to be multiplied with. + * By default, the respective information for the first DoFHandler object + * are returned. */ - IndexSet locally_owned_domain_indices() const; + IndexSet locally_owned_domain_indices(const unsigned int block=0) const; /** * Return the MPI communicator object in use with this preconditioner. @@ -426,7 +444,13 @@ private: /** * Associated @p DoFHandler. */ - SmartPointer,PreconditionMG > dof_handler; + std::vector,PreconditionMG > > dof_handler_vector; + + /** + * Storage for the pointers to the DoFHandler objects + * without SmartPointer wrapper. + */ + std::vector*> dof_handler_vector_raw; /** * The multigrid object. @@ -437,6 +461,12 @@ private: * Object for grid tranfer. */ SmartPointer > transfer; + + /** + * Flag to indicate if the object is initialized with a single DoFHandler + * or with one for each block. + */ + const bool uses_dof_handler_vector; }; /*@}*/ @@ -533,17 +563,142 @@ Multigrid::get_minlevel () const /* --------------------------- inline functions --------------------- */ +namespace internal +{ + namespace PreconditionMG + { + template + typename std::enable_if::type + vmult(const std::vector*> &dof_handler_vector, + dealii::Multigrid &multigrid, + const TRANSFER &transfer, + OtherVectorType &dst, + const OtherVectorType &src, + const bool uses_dof_handler_vector, int) + { + if (uses_dof_handler_vector) + transfer.copy_to_mg(dof_handler_vector, + multigrid.defect, + src); + else + transfer.copy_to_mg(*dof_handler_vector[0], + multigrid.defect, + src); + + multigrid.cycle(); + if (uses_dof_handler_vector) + transfer.copy_from_mg(dof_handler_vector, + dst, + multigrid.solution); + else + transfer.copy_from_mg(*dof_handler_vector[0], + dst, + multigrid.solution); + } + + template + void + vmult(const std::vector*> &dof_handler_vector, + dealii::Multigrid &multigrid, + const TRANSFER &transfer, + OtherVectorType &dst, + const OtherVectorType &src, + const bool uses_dof_handler_vector,...) + { + (void) uses_dof_handler_vector; + Assert (!uses_dof_handler_vector, ExcInternalError()); + transfer.copy_to_mg(*dof_handler_vector[0], + multigrid.defect, + src); + multigrid.cycle(); + transfer.copy_from_mg(*dof_handler_vector[0], + dst, + multigrid.solution); + } + + template + typename std::enable_if::type + vmult_add(const std::vector*> &dof_handler_vector, + dealii::Multigrid &multigrid, + const TRANSFER &transfer, + OtherVectorType &dst, + const OtherVectorType &src, + const bool uses_dof_handler_vector, int) + { + if (uses_dof_handler_vector) + transfer.copy_to_mg(dof_handler_vector, + multigrid.defect, + src); + else + transfer.copy_to_mg(*dof_handler_vector[0], + multigrid.defect, + src); + + multigrid.cycle(); + if (uses_dof_handler_vector) + transfer.copy_from_mg_add(dof_handler_vector, + dst, + multigrid.solution); + else + transfer.copy_from_mg_add(*dof_handler_vector[0], + dst, + multigrid.solution); + } + + template + void + vmult_add(const std::vector*> &dof_handler_vector, + dealii::Multigrid &multigrid, + const TRANSFER &transfer, + OtherVectorType &dst, + const OtherVectorType &src, + const bool uses_dof_handler_vector,...) + { + (void) uses_dof_handler_vector; + Assert (!uses_dof_handler_vector, ExcInternalError()); + transfer.copy_to_mg(*dof_handler_vector[0], + multigrid.defect, + src); + multigrid.cycle(); + transfer.copy_from_mg_add(*dof_handler_vector[0], + dst, + multigrid.solution); + } + } +} + template PreconditionMG ::PreconditionMG(const DoFHandler &dof_handler, Multigrid &mg, const TRANSFER &transfer) : - dof_handler(&dof_handler), + dof_handler_vector(1,&dof_handler), + dof_handler_vector_raw(1,&dof_handler), multigrid(&mg), - transfer(&transfer) + transfer(&transfer), + uses_dof_handler_vector(false) {} +template +PreconditionMG +::PreconditionMG(const std::vector*> &dof_handler, + Multigrid &mg, + const TRANSFER &transfer) + : + dof_handler_vector(dof_handler.size()), + dof_handler_vector_raw(dof_handler.size()), + multigrid(&mg), + transfer(&transfer), + uses_dof_handler_vector(true) +{ + for (unsigned int i = 0; i< dof_handler.size() ; ++i) + { + dof_handler_vector[i] = dof_handler[i]; + dof_handler_vector_raw[i] = dof_handler[i]; + } +} + template inline bool PreconditionMG::empty () const @@ -558,30 +713,26 @@ PreconditionMG::vmult (OtherVectorType &dst, const OtherVectorType &src) const { - transfer->copy_to_mg(*dof_handler, - multigrid->defect, - src); - multigrid->cycle(); - - transfer->copy_from_mg(*dof_handler, - dst, - multigrid->solution); + internal::PreconditionMG::vmult(dof_handler_vector_raw,*multigrid,*transfer, + dst,src,uses_dof_handler_vector,0); } template IndexSet -PreconditionMG::locally_owned_range_indices() const +PreconditionMG::locally_owned_range_indices(const unsigned int block) const { - return dof_handler->locally_owned_dofs(); + AssertIndexRange(block,dof_handler_vector.size()); + return dof_handler_vector[block]->locally_owned_dofs(); } template IndexSet -PreconditionMG::locally_owned_domain_indices() const +PreconditionMG::locally_owned_domain_indices(const unsigned int block) const { - return dof_handler->locally_owned_dofs(); + AssertIndexRange(block,dof_handler_vector.size()); + return dof_handler_vector[block]->locally_owned_dofs(); } @@ -591,7 +742,7 @@ PreconditionMG::get_mpi_communicator() const { // currently parallel GMG works with distributed Triangulation only, // so it should be a safe bet to use it to query MPI communicator: - const Triangulation &tria = dof_handler->get_triangulation(); + const Triangulation &tria = dof_handler_vector[0]->get_triangulation(); const parallel::distributed::Triangulation *ptria = dynamic_cast *>(&tria); Assert (ptria != nullptr, ExcInternalError()); return ptria->get_communicator (); @@ -605,13 +756,8 @@ PreconditionMG::vmult_add (OtherVectorType &dst, const OtherVectorType &src) const { - transfer->copy_to_mg(*dof_handler, - multigrid->defect, - src); - multigrid->cycle(); - transfer->copy_from_mg_add(*dof_handler, - dst, - multigrid->solution); + internal::PreconditionMG::vmult_add(dof_handler_vector_raw,*multigrid,*transfer, + dst,src,uses_dof_handler_vector,0); }