@@ -133,26 +133,26 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
133133 " type LinearAlgebra::distributed::Vector." );
134134
135135 /* *
136- * The scalar type used by the vector-type template argument .
136+ * Partitioner needed by the intermediate vector .
137137 */
138- using Number = typename VectorType::value_type ;
138+ std::shared_ptr< const Utilities::MPI::Partitioner> partitioner_coarse ;
139139
140140 /* *
141- * Default constructor .
141+ * Partitioner needed by the intermediate vector .
142142 */
143- MGTwoLevelTransferBase () ;
143+ std::shared_ptr< const Utilities::MPI::Partitioner> partitioner_fine ;
144144
145145 /* *
146146 * Perform prolongation on a solution vector.
147147 */
148- void
149- prolongate_and_add (VectorType &dst, const VectorType &src) const ;
148+ virtual void
149+ prolongate_and_add (VectorType &dst, const VectorType &src) const = 0 ;
150150
151151 /* *
152152 * Perform restriction on a residual vector.
153153 */
154- void
155- restrict_and_add (VectorType &dst, const VectorType &src) const ;
154+ virtual void
155+ restrict_and_add (VectorType &dst, const VectorType &src) const = 0 ;
156156
157157 /* *
158158 * Perform interpolation of a solution vector from the fine level to the
@@ -181,6 +181,38 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
181181 */
182182 virtual std::size_t
183183 memory_consumption () const = 0 ;
184+ };
185+
186+
187+
188+ /* *
189+ * Base class for MGTwoLevelTransferNonNested and MGTwoLevelTransfer.
190+ */
191+ template <typename VectorType>
192+ class MGTwoLevelTransferCore : public MGTwoLevelTransferBase <VectorType>
193+ {
194+ public:
195+ /* *
196+ * The scalar type used by the vector-type template argument.
197+ */
198+ using Number = typename VectorType::value_type;
199+
200+ /* *
201+ * Default constructor.
202+ */
203+ MGTwoLevelTransferCore ();
204+
205+ /* *
206+ * @copydoc MGTwoLevelTransferBase::prolongate_and_add
207+ */
208+ void
209+ prolongate_and_add (VectorType &dst, const VectorType &src) const override ;
210+
211+ /* *
212+ * @copydoc MGTwoLevelTransferBase::restrict_and_add
213+ */
214+ void
215+ restrict_and_add (VectorType &dst, const VectorType &src) const override ;
184216
185217protected:
186218 /* *
@@ -242,17 +274,6 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
242274 */
243275 bool fine_element_is_continuous;
244276
245- public:
246- /* *
247- * Partitioner needed by the intermediate vector.
248- */
249- std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_coarse;
250-
251- /* *
252- * Partitioner needed by the intermediate vector.
253- */
254- std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
255-
256277protected:
257278 /* *
258279 * Internal vector on which the actual prolongation/restriction is performed.
@@ -327,7 +348,7 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
327348 * point, and we fall back to the first option in such a case.
328349 */
329350template <int dim, typename VectorType>
330- class MGTwoLevelTransfer : public MGTwoLevelTransferBase <VectorType>
351+ class MGTwoLevelTransfer : public MGTwoLevelTransferCore <VectorType>
331352{
332353public:
333354 static_assert (
@@ -627,6 +648,133 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
627648
628649 friend class internal ::MGTwoLevelTransferImplementation;
629650
651+ friend class MGTransferMatrixFree <dim, Number, MemorySpace::Host>;
652+
653+ friend class MGTransferMatrixFree <dim, Number, MemorySpace::Default>;
654+ };
655+
656+
657+ /* *
658+ * A transfer class supporting device vectors via copying them to the host and
659+ * using an internal transfer of type MGTwoLevelTransfer defined on the
660+ * host.
661+ */
662+ template <int dim, typename VectorType>
663+ class MGTwoLevelTransferCopyToHost : public MGTwoLevelTransferBase <VectorType>
664+ {
665+ public:
666+ static_assert (
667+ std::is_same_v<
668+ VectorType,
669+ LinearAlgebra::distributed::Vector<typename VectorType::value_type,
670+ MemorySpace::Default>>,
671+ " This class is currently only implemented for vectors of "
672+ " type LinearAlgebra::distributed::Vector, This class should not be initialized on the host as it will perform redundant transfers. Use MGTwoLevelTransfer instead." );
673+
674+
675+ /* *
676+ * The scalar type used by the vector-type template argument.
677+ */
678+ using Number = typename VectorType::value_type;
679+
680+ using VectorTypeHost =
681+ LinearAlgebra::distributed::Vector<Number, MemorySpace::Host>;
682+ /* *
683+ * Default constructor.
684+ */
685+ MGTwoLevelTransferCopyToHost () = default ;
686+
687+ /* *
688+ * @copydoc MGTwoLevelTransfer::reinit(const DoFHandler<dim>, const DoFHandler<dim>, const AffineConstraints<Number>, const AffineConstraints<Number>, const unsigned int, const unsigned int)
689+ */
690+ void
691+ reinit (const DoFHandler<dim> &dof_handler_fine,
692+ const DoFHandler<dim> &dof_handler_coarse,
693+ const AffineConstraints<Number> &constraint_fine =
694+ AffineConstraints<Number>(),
695+ const AffineConstraints<Number> &constraint_coarse =
696+ AffineConstraints<Number>(),
697+ const unsigned int mg_level_fine = numbers::invalid_unsigned_int,
698+ const unsigned int mg_level_coarse = numbers::invalid_unsigned_int);
699+
700+ /* *
701+ * @copydoc MGTwoLevelTransfer::reinit(const MatrixFree<dim, Number>, const unsigned int, const MatrixFree<dim, Number>, const unsigned int)
702+ */
703+ void
704+ reinit (const MatrixFree<dim, Number> &matrix_free_fine,
705+ const unsigned int dof_no_fine,
706+ const MatrixFree<dim, Number> &matrix_free_coarse,
707+ const unsigned int dof_no_coarse);
708+
709+ /* *
710+ * @copydoc MGTwoLevelTransfer::fast_polynomial_transfer_supported
711+ */
712+ bool
713+ fast_polynomial_transfer_supported (const unsigned int fe_degree_fine,
714+ const unsigned int fe_degree_coarse);
715+
716+ /* *
717+ * @copydoc MGTwoLevelTransfer::prolongate_and_add
718+ */
719+ void
720+ prolongate_and_add (VectorType &dst, const VectorType &src) const override ;
721+
722+ /* *
723+ * @copydoc MGTwoLevelTransfer::restrict_and_add
724+ */
725+ void
726+ restrict_and_add (VectorType &dst, const VectorType &src) const override ;
727+
728+ /* *
729+ * @copydoc MGTwoLevelTransfer::interpolate
730+ */
731+ void
732+ interpolate (VectorType &dst, const VectorType &src) const override ;
733+
734+ /* *
735+ * @copydoc MGTwoLevelTransfer::enable_inplace_operations_if_possible
736+ */
737+ std::pair<bool , bool >
738+ enable_inplace_operations_if_possible (
739+ const std::shared_ptr<const Utilities::MPI::Partitioner>
740+ &partitioner_coarse,
741+ const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner_fine)
742+ override ;
743+
744+ /* *
745+ * @copydoc MGTwoLevelTransfer::memory_consumption
746+ */
747+ std::size_t
748+ memory_consumption () const override ;
749+
750+ private:
751+ /* *
752+ * The internal transfer defined on the host which handles all operations.
753+ */
754+ MGTwoLevelTransfer<dim, VectorTypeHost> host_transfer;
755+
756+ /* *
757+ * Vectors used for the host transfer.
758+ */
759+
760+ mutable VectorTypeHost host_vector_coarse;
761+
762+ mutable VectorTypeHost host_vector_fine;
763+
764+ /* *
765+ * Copies a device vector to a host vector.
766+ */
767+ void
768+ copy_to_host (VectorTypeHost &dst, const VectorType &src) const ;
769+
770+ /* *
771+ * Copies a host vector to a device vector.
772+ */
773+ void
774+ copy_from_host (VectorType &dst, const VectorTypeHost &src) const ;
775+
776+ friend class internal ::MGTwoLevelTransferImplementation;
777+
630778 friend class MGTransferMatrixFree <dim,
631779 Number,
632780 typename VectorType::memory_space>;
@@ -638,7 +786,7 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
638786 * Class for transfer between two non-nested multigrid levels.
639787 */
640788template <int dim, typename VectorType>
641- class MGTwoLevelTransferNonNested : public MGTwoLevelTransferBase <VectorType>
789+ class MGTwoLevelTransferNonNested : public MGTwoLevelTransferCore <VectorType>
642790{
643791private:
644792 static_assert (
@@ -1451,6 +1599,150 @@ class MGTransferBlockMatrixFree
14511599
14521600/* ----------------------- Inline functions --------------------------------- */
14531601
1602+ template <int dim, typename VectorType>
1603+ void
1604+ MGTwoLevelTransferCopyToHost<dim, VectorType>::reinit(
1605+ const DoFHandler<dim> &dof_handler_fine,
1606+ const DoFHandler<dim> &dof_handler_coarse,
1607+ const AffineConstraints<Number> &constraint_fine,
1608+ const AffineConstraints<Number> &constraint_coarse,
1609+ const unsigned int mg_level_fine,
1610+ const unsigned int mg_level_coarse)
1611+ {
1612+ host_transfer.reinit (dof_handler_fine,
1613+ dof_handler_coarse,
1614+ constraint_fine,
1615+ constraint_coarse,
1616+ mg_level_fine,
1617+ mg_level_coarse);
1618+ }
1619+
1620+ template <int dim, typename VectorType>
1621+ void
1622+ MGTwoLevelTransferCopyToHost<dim, VectorType>::reinit(
1623+ const MatrixFree<dim, Number> &matrix_free_fine,
1624+ const unsigned int dof_no_fine,
1625+ const MatrixFree<dim, Number> &matrix_free_coarse,
1626+ const unsigned int dof_no_coarse)
1627+ {
1628+ host_transfer.reinit (matrix_free_fine,
1629+ dof_no_fine,
1630+ matrix_free_coarse,
1631+ dof_no_coarse);
1632+ }
1633+
1634+
1635+ template <int dim, typename VectorType>
1636+ bool
1637+ MGTwoLevelTransferCopyToHost<dim, VectorType>::
1638+ fast_polynomial_transfer_supported (const unsigned int fe_degree_fine,
1639+ const unsigned int fe_degree_coarse)
1640+ {
1641+ return host_transfer.fast_polynomial_transfer_supported (fe_degree_fine,
1642+ fe_degree_coarse);
1643+ }
1644+
1645+ template <int dim, typename VectorType>
1646+ void
1647+ MGTwoLevelTransferCopyToHost<dim, VectorType>::prolongate_and_add(
1648+ VectorType &dst,
1649+ const VectorType &src) const
1650+ {
1651+ if (host_vector_coarse.size () == 0 )
1652+ host_vector_coarse.reinit (src.get_partitioner ());
1653+ if (host_vector_fine.size () == 0 )
1654+ host_vector_fine.reinit (dst.get_partitioner ());
1655+
1656+ copy_to_host (host_vector_fine, dst);
1657+ copy_to_host (host_vector_coarse, src);
1658+
1659+ host_transfer.prolongate_and_add (host_vector_fine, host_vector_coarse);
1660+
1661+ copy_from_host (dst, host_vector_fine);
1662+ }
1663+
1664+ template <int dim, typename VectorType>
1665+ void
1666+ MGTwoLevelTransferCopyToHost<dim, VectorType>::restrict_and_add(
1667+ VectorType &dst,
1668+ const VectorType &src) const
1669+ {
1670+ if (host_vector_coarse.size () == 0 )
1671+ host_vector_coarse.reinit (dst.get_partitioner ());
1672+ if (host_vector_fine.size () == 0 )
1673+ host_vector_fine.reinit (src.get_partitioner ());
1674+
1675+ copy_to_host (host_vector_coarse, dst);
1676+ copy_to_host (host_vector_fine, src);
1677+
1678+ host_transfer.restrict_and_add (host_vector_coarse, host_vector_fine);
1679+
1680+ copy_from_host (dst, host_vector_coarse);
1681+ }
1682+
1683+ template <int dim, typename VectorType>
1684+ void
1685+ MGTwoLevelTransferCopyToHost<dim, VectorType>::interpolate(
1686+ VectorType &dst,
1687+ const VectorType &src) const
1688+ {
1689+ if (host_vector_coarse.size () == 0 )
1690+ host_vector_coarse.reinit (dst.get_partitioner ());
1691+ if (host_vector_fine.size () == 0 )
1692+ host_vector_fine.reinit (src.get_partitioner ());
1693+
1694+ copy_to_host (host_vector_fine, src);
1695+
1696+ host_transfer.interpolate (host_vector_coarse, host_vector_fine);
1697+
1698+ copy_from_host (dst, host_vector_coarse);
1699+ }
1700+
1701+ template <int dim, typename VectorType>
1702+ std::pair<bool , bool >
1703+ MGTwoLevelTransferCopyToHost<dim, VectorType>::
1704+ enable_inplace_operations_if_possible (
1705+ const std::shared_ptr<const Utilities::MPI::Partitioner>
1706+ &partitioner_coarse,
1707+ const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner_fine)
1708+ {
1709+ return host_transfer.enable_inplace_operations_if_possible (partitioner_coarse,
1710+ partitioner_fine);
1711+ }
1712+
1713+ template <int dim, typename VectorType>
1714+ std::size_t
1715+ MGTwoLevelTransferCopyToHost<dim, VectorType>::memory_consumption() const
1716+ {
1717+ return host_transfer.memory_consumption ();
1718+ }
1719+
1720+ template <int dim, typename VectorType>
1721+ void
1722+ MGTwoLevelTransferCopyToHost<dim, VectorType>::copy_to_host(
1723+ VectorTypeHost &dst,
1724+ const VectorType &src) const
1725+ {
1726+ LinearAlgebra::ReadWriteVector<Number> rw_vector (
1727+ src.get_partitioner ()->locally_owned_range ());
1728+ rw_vector.import_elements (src, VectorOperation::insert);
1729+
1730+ dst.import_elements (rw_vector, VectorOperation::insert);
1731+ }
1732+
1733+ template <int dim, typename VectorType>
1734+ void
1735+ MGTwoLevelTransferCopyToHost<dim, VectorType>::copy_from_host(
1736+ VectorType &dst,
1737+ const VectorTypeHost &src) const
1738+ {
1739+ LinearAlgebra::ReadWriteVector<Number> rw_vector (
1740+ src.get_partitioner ()->locally_owned_range ());
1741+ rw_vector.import_elements (src, VectorOperation::insert);
1742+
1743+ dst.import_elements (rw_vector, VectorOperation::insert);
1744+ }
1745+
14541746
14551747
14561748template <int dim, typename Number, typename MemorySpace>
0 commit comments