xref: /libCEED/examples/deal.II/bps.h (revision 571e8cf012cd9ba55521730d89ff29ce614d2bcd)
18c81f8b0SPeter Munch // ---------------------------------------------------------------------
28c81f8b0SPeter Munch //
38c81f8b0SPeter Munch // Copyright (C) 2023 by the deal.II authors
48c81f8b0SPeter Munch //
58c81f8b0SPeter Munch // This file is part of the deal.II library.
68c81f8b0SPeter Munch //
78c81f8b0SPeter Munch // The deal.II library is free software; you can use it, redistribute
88c81f8b0SPeter Munch // it, and/or modify it under the terms of the GNU Lesser General
98c81f8b0SPeter Munch // Public License as published by the Free Software Foundation; either
108c81f8b0SPeter Munch // version 2.1 of the License, or (at your option) any later version.
118c81f8b0SPeter Munch // The full text of the license can be found in the file LICENSE.md at
128c81f8b0SPeter Munch // the top level directory of deal.II.
138c81f8b0SPeter Munch //
148c81f8b0SPeter Munch //  Authors: Peter Munch, Martin Kronbichler
158c81f8b0SPeter Munch //
168c81f8b0SPeter Munch // ---------------------------------------------------------------------
178c81f8b0SPeter Munch 
188c81f8b0SPeter Munch // deal.II includes
198c81f8b0SPeter Munch #include <deal.II/dofs/dof_tools.h>
208c81f8b0SPeter Munch 
218c81f8b0SPeter Munch #include <deal.II/fe/mapping.h>
228c81f8b0SPeter Munch 
238c81f8b0SPeter Munch #include <deal.II/lac/la_parallel_vector.h>
248c81f8b0SPeter Munch 
258c81f8b0SPeter Munch #include <deal.II/matrix_free/fe_evaluation.h>
268c81f8b0SPeter Munch #include <deal.II/matrix_free/matrix_free.h>
27*571e8cf0SJeremy L Thompson #include <deal.II/matrix_free/shape_info.h>
288c81f8b0SPeter Munch #include <deal.II/matrix_free/tools.h>
298c81f8b0SPeter Munch 
308c81f8b0SPeter Munch // libCEED includes
312097acd5SJeremy L Thompson #include <ceed.h>
322097acd5SJeremy L Thompson #include <ceed/backend.h>
338c81f8b0SPeter Munch 
348c81f8b0SPeter Munch // QFunction source
358c81f8b0SPeter Munch #include "bps-qfunctions.h"
368c81f8b0SPeter Munch 
378c81f8b0SPeter Munch using namespace dealii;
388c81f8b0SPeter Munch 
398c81f8b0SPeter Munch /**
408c81f8b0SPeter Munch  * BP types. For more details, see https://ceed.exascaleproject.org/bps/.
418c81f8b0SPeter Munch  */
428c81f8b0SPeter Munch enum class BPType : unsigned int
438c81f8b0SPeter Munch {
448c81f8b0SPeter Munch   BP1,
458c81f8b0SPeter Munch   BP2,
468c81f8b0SPeter Munch   BP3,
478c81f8b0SPeter Munch   BP4,
488c81f8b0SPeter Munch   BP5,
498c81f8b0SPeter Munch   BP6
508c81f8b0SPeter Munch };
518c81f8b0SPeter Munch 
528c81f8b0SPeter Munch 
538c81f8b0SPeter Munch 
548c81f8b0SPeter Munch /**
558c81f8b0SPeter Munch  * Struct storing relevant information regarding each BP.
568c81f8b0SPeter Munch  */
578c81f8b0SPeter Munch struct BPInfo
588c81f8b0SPeter Munch {
598c81f8b0SPeter Munch   BPInfo(const BPType type, const int dim, const int fe_degree)
608c81f8b0SPeter Munch     : type(type)
618c81f8b0SPeter Munch     , dim(dim)
628c81f8b0SPeter Munch     , fe_degree(fe_degree)
638c81f8b0SPeter Munch   {
648c81f8b0SPeter Munch     if (type == BPType::BP1)
658c81f8b0SPeter Munch       type_string = "BP1";
668c81f8b0SPeter Munch     else if (type == BPType::BP2)
678c81f8b0SPeter Munch       type_string = "BP2";
688c81f8b0SPeter Munch     else if (type == BPType::BP3)
698c81f8b0SPeter Munch       type_string = "BP3";
708c81f8b0SPeter Munch     else if (type == BPType::BP4)
718c81f8b0SPeter Munch       type_string = "BP4";
728c81f8b0SPeter Munch     else if (type == BPType::BP5)
738c81f8b0SPeter Munch       type_string = "BP5";
748c81f8b0SPeter Munch     else if (type == BPType::BP6)
758c81f8b0SPeter Munch       type_string = "BP6";
768c81f8b0SPeter Munch 
778c81f8b0SPeter Munch     this->n_q_points_1d = (type <= BPType::BP4) ? (fe_degree + 2) : (fe_degree + 1);
788c81f8b0SPeter Munch 
798c81f8b0SPeter Munch     this->n_components =
808c81f8b0SPeter Munch       (type == BPType::BP1 || type == BPType::BP3 || type == BPType::BP5) ? 1 : dim;
818c81f8b0SPeter Munch   }
828c81f8b0SPeter Munch 
838c81f8b0SPeter Munch 
848c81f8b0SPeter Munch   BPType       type;
858c81f8b0SPeter Munch   std::string  type_string;
868c81f8b0SPeter Munch   unsigned int dim;
878c81f8b0SPeter Munch   unsigned int fe_degree;
888c81f8b0SPeter Munch   unsigned int n_q_points_1d;
898c81f8b0SPeter Munch   unsigned int n_components;
908c81f8b0SPeter Munch };
918c81f8b0SPeter Munch 
928c81f8b0SPeter Munch 
938c81f8b0SPeter Munch 
948c81f8b0SPeter Munch /**
958c81f8b0SPeter Munch  * Base class of operators.
968c81f8b0SPeter Munch  */
978c81f8b0SPeter Munch template <typename Number>
988c81f8b0SPeter Munch class OperatorBase
998c81f8b0SPeter Munch {
1008c81f8b0SPeter Munch public:
1018c81f8b0SPeter Munch   /**
1028c81f8b0SPeter Munch    * deal.II vector type
1038c81f8b0SPeter Munch    */
1048c81f8b0SPeter Munch   using VectorType = LinearAlgebra::distributed::Vector<Number>;
1058c81f8b0SPeter Munch 
1068c81f8b0SPeter Munch   /**
1078c81f8b0SPeter Munch    * Initialize vector.
1088c81f8b0SPeter Munch    */
1098c81f8b0SPeter Munch   virtual void
1108c81f8b0SPeter Munch   reinit() = 0;
1118c81f8b0SPeter Munch 
1128c81f8b0SPeter Munch   /**
1138c81f8b0SPeter Munch    * Perform matrix-vector product
1148c81f8b0SPeter Munch    */
1158c81f8b0SPeter Munch   virtual void
1168c81f8b0SPeter Munch   vmult(VectorType &dst, const VectorType &src) const = 0;
1178c81f8b0SPeter Munch 
1188c81f8b0SPeter Munch   /**
1198c81f8b0SPeter Munch    * Initialize vector.
1208c81f8b0SPeter Munch    */
1218c81f8b0SPeter Munch   virtual void
1228c81f8b0SPeter Munch   initialize_dof_vector(VectorType &vec) const = 0;
1238c81f8b0SPeter Munch 
1248c81f8b0SPeter Munch   /**
1258c81f8b0SPeter Munch    * Compute inverse of diagonal.
1268c81f8b0SPeter Munch    */
1278c81f8b0SPeter Munch   virtual void
1288c81f8b0SPeter Munch   compute_inverse_diagonal(VectorType &diagonal) const = 0;
1298c81f8b0SPeter Munch };
1308c81f8b0SPeter Munch 
1318c81f8b0SPeter Munch 
1328c81f8b0SPeter Munch /**
1338c81f8b0SPeter Munch  * Operator implementation using libCEED.
1348c81f8b0SPeter Munch  */
1358c81f8b0SPeter Munch template <int dim, typename Number>
1368c81f8b0SPeter Munch class OperatorCeed : public OperatorBase<Number>
1378c81f8b0SPeter Munch {
1388c81f8b0SPeter Munch public:
1398c81f8b0SPeter Munch   using VectorType = typename OperatorBase<Number>::VectorType;
1408c81f8b0SPeter Munch 
1418c81f8b0SPeter Munch   /**
1428c81f8b0SPeter Munch    * Constructor.
1438c81f8b0SPeter Munch    */
1448c81f8b0SPeter Munch   OperatorCeed(const Mapping<dim>              &mapping,
1458c81f8b0SPeter Munch                const DoFHandler<dim>           &dof_handler,
1468c81f8b0SPeter Munch                const AffineConstraints<Number> &constraints,
1478c81f8b0SPeter Munch                const Quadrature<dim>           &quadrature,
1488c81f8b0SPeter Munch                const BPType                    &bp,
1498c81f8b0SPeter Munch                const std::string               &resource)
1508c81f8b0SPeter Munch     : mapping(mapping)
1518c81f8b0SPeter Munch     , dof_handler(dof_handler)
1528c81f8b0SPeter Munch     , constraints(constraints)
1538c81f8b0SPeter Munch     , quadrature(quadrature)
1548c81f8b0SPeter Munch     , bp(bp)
1558c81f8b0SPeter Munch     , resource(resource)
1568c81f8b0SPeter Munch   {
1578c81f8b0SPeter Munch     reinit();
1588c81f8b0SPeter Munch   }
1598c81f8b0SPeter Munch 
1608c81f8b0SPeter Munch   /**
1618c81f8b0SPeter Munch    * Destructor.
1628c81f8b0SPeter Munch    */
1638c81f8b0SPeter Munch   ~OperatorCeed()
1648c81f8b0SPeter Munch   {
1652097acd5SJeremy L Thompson     CeedVectorDestroy(&src_ceed);
1662097acd5SJeremy L Thompson     CeedVectorDestroy(&dst_ceed);
16770dc8078SJeremy L Thompson     CeedOperatorDestroy(&op_apply);
1688c81f8b0SPeter Munch     CeedDestroy(&ceed);
1698c81f8b0SPeter Munch   }
1708c81f8b0SPeter Munch 
1718c81f8b0SPeter Munch   /**
1728c81f8b0SPeter Munch    * Initialized internal data structures, particularly, libCEED.
1738c81f8b0SPeter Munch    */
1748c81f8b0SPeter Munch   void
1758c81f8b0SPeter Munch   reinit() override
1768c81f8b0SPeter Munch   {
1778efac696SJeremy L Thompson     CeedVector           q_data;
1788efac696SJeremy L Thompson     CeedBasis            sol_basis;
1798efac696SJeremy L Thompson     CeedElemRestriction  sol_restriction;
1808efac696SJeremy L Thompson     CeedElemRestriction  q_data_restriction;
1818efac696SJeremy L Thompson     BuildContext         build_ctx_data;
1828efac696SJeremy L Thompson     CeedQFunctionContext build_ctx;
1838efac696SJeremy L Thompson     CeedQFunction        qf_apply;
1848efac696SJeremy L Thompson 
1858c81f8b0SPeter Munch     const auto &tria = dof_handler.get_triangulation();
1868c81f8b0SPeter Munch     const auto &fe   = dof_handler.get_fe();
1878c81f8b0SPeter Munch 
1888c81f8b0SPeter Munch     const auto n_components = fe.n_components();
1898c81f8b0SPeter Munch 
1908c81f8b0SPeter Munch     if (bp == BPType::BP1 || bp == BPType::BP3 || bp == BPType::BP5)
1918c81f8b0SPeter Munch       {
1928c81f8b0SPeter Munch         AssertThrow(n_components == 1, ExcInternalError());
1938c81f8b0SPeter Munch       }
1948c81f8b0SPeter Munch     else
1958c81f8b0SPeter Munch       {
1968c81f8b0SPeter Munch         AssertThrow(n_components == dim, ExcInternalError());
1978c81f8b0SPeter Munch       }
1988c81f8b0SPeter Munch 
1998c81f8b0SPeter Munch     // 1) create CEED instance -> "MatrixFree"
2008c81f8b0SPeter Munch     const char *ceed_spec = resource.c_str();
2018c81f8b0SPeter Munch     CeedInit(ceed_spec, &ceed);
2028c81f8b0SPeter Munch 
2038c81f8b0SPeter Munch     // 2) create shape functions -> "ShapeInfo"
2048c81f8b0SPeter Munch     const unsigned int fe_degree  = fe.tensor_degree();
2058c81f8b0SPeter Munch     const unsigned int n_q_points = quadrature.get_tensor_basis()[0].size();
2064566048fSJeremy L Thompson     {
207*571e8cf0SJeremy L Thompson       dealii::internal::MatrixFreeFunctions::ShapeInfo<double> shape_info;
208*571e8cf0SJeremy L Thompson       shape_info.reinit(quadrature, fe, 0);
209*571e8cf0SJeremy L Thompson       dealii::internal::MatrixFreeFunctions::UnivariateShapeData<double> shape_data =
210*571e8cf0SJeremy L Thompson         shape_info.get_shape_data();
211*571e8cf0SJeremy L Thompson 
212*571e8cf0SJeremy L Thompson       std::vector<CeedScalar> q_ref_1d(n_q_points);
213*571e8cf0SJeremy L Thompson       std::vector<CeedScalar> q_weight_1d(n_q_points);
2144566048fSJeremy L Thompson       const unsigned int      array_size = (fe_degree + 1) * (n_q_points);
215*571e8cf0SJeremy L Thompson       std::vector<CeedScalar> interp_1d(array_size);
216*571e8cf0SJeremy L Thompson       std::vector<CeedScalar> grad_1d(array_size);
2174566048fSJeremy L Thompson       for (unsigned int i = 0; i < n_q_points; i++)
2184566048fSJeremy L Thompson         {
2194566048fSJeremy L Thompson           // Retrieve quadrature info
220*571e8cf0SJeremy L Thompson           // Convert reference element from [0, 1] to [-1, 1]
221*571e8cf0SJeremy L Thompson           q_ref_1d[i]    = 2.0 * (quadrature.get_tensor_basis()[0].point(i)(0) - 0.5);
2224566048fSJeremy L Thompson           q_weight_1d[i] = 2.0 * quadrature.get_tensor_basis()[0].weight(i);
2234566048fSJeremy L Thompson 
2244566048fSJeremy L Thompson           // Retrieve 1D shape function values
2254566048fSJeremy L Thompson           for (unsigned int j = 0; j < fe_degree + 1; j++)
2264566048fSJeremy L Thompson             {
227*571e8cf0SJeremy L Thompson               interp_1d[j + i * (fe_degree + 1)] = shape_data.shape_values[j + i * (fe_degree + 1)];
228*571e8cf0SJeremy L Thompson               // Scale derivatives by 1/2 for new reference element length
229*571e8cf0SJeremy L Thompson               grad_1d[j + i * (fe_degree + 1)] =
230*571e8cf0SJeremy L Thompson                 0.5 * shape_data.shape_gradients[j + i * (fe_degree + 1)];
2314566048fSJeremy L Thompson             }
2324566048fSJeremy L Thompson         }
2334566048fSJeremy L Thompson 
2344566048fSJeremy L Thompson       CeedBasisCreateTensorH1(ceed,
2354566048fSJeremy L Thompson                               dim,
2364566048fSJeremy L Thompson                               n_components,
2374566048fSJeremy L Thompson                               fe_degree + 1,
2384566048fSJeremy L Thompson                               n_q_points,
239*571e8cf0SJeremy L Thompson                               interp_1d.data(),
240*571e8cf0SJeremy L Thompson                               grad_1d.data(),
241*571e8cf0SJeremy L Thompson                               q_ref_1d.data(),
242*571e8cf0SJeremy L Thompson                               q_weight_1d.data(),
2434566048fSJeremy L Thompson                               &sol_basis);
2444566048fSJeremy L Thompson     }
2458c81f8b0SPeter Munch 
2468c81f8b0SPeter Munch     // 3) create restriction matrix -> DoFInfo
2478c81f8b0SPeter Munch     unsigned int n_local_active_cells = 0;
2488c81f8b0SPeter Munch 
2498c81f8b0SPeter Munch     for (const auto &cell : dof_handler.active_cell_iterators())
2508c81f8b0SPeter Munch       if (cell->is_locally_owned())
2518c81f8b0SPeter Munch         n_local_active_cells++;
2528c81f8b0SPeter Munch 
2538c81f8b0SPeter Munch     partitioner =
2548c81f8b0SPeter Munch       std::make_shared<Utilities::MPI::Partitioner>(dof_handler.locally_owned_dofs(),
2558c81f8b0SPeter Munch                                                     DoFTools::extract_locally_active_dofs(
2568c81f8b0SPeter Munch                                                       dof_handler),
2578c81f8b0SPeter Munch                                                     dof_handler.get_communicator());
2588c81f8b0SPeter Munch 
2598c81f8b0SPeter Munch     std::vector<CeedInt> indices;
2608c81f8b0SPeter Munch     indices.reserve(n_local_active_cells * fe.n_dofs_per_cell() / n_components);
2618c81f8b0SPeter Munch 
2628c81f8b0SPeter Munch     const auto dof_mapping = FETools::lexicographic_to_hierarchic_numbering<dim>(fe_degree);
2638c81f8b0SPeter Munch 
2648c81f8b0SPeter Munch     std::vector<types::global_dof_index> local_indices(fe.n_dofs_per_cell());
2658c81f8b0SPeter Munch 
2668c81f8b0SPeter Munch     for (const auto &cell : dof_handler.active_cell_iterators())
2678c81f8b0SPeter Munch       if (cell->is_locally_owned())
2688c81f8b0SPeter Munch         {
2698c81f8b0SPeter Munch           cell->get_dof_indices(local_indices);
2708c81f8b0SPeter Munch 
2718c81f8b0SPeter Munch           for (const auto i : dof_mapping)
2728c81f8b0SPeter Munch             indices.emplace_back(
2738c81f8b0SPeter Munch               partitioner->global_to_local(local_indices[fe.component_to_system_index(0, i)]) /
2748c81f8b0SPeter Munch               n_components);
2758c81f8b0SPeter Munch         }
2768c81f8b0SPeter Munch 
2778c81f8b0SPeter Munch     CeedElemRestrictionCreate(ceed,
2788c81f8b0SPeter Munch                               n_local_active_cells,
2798c81f8b0SPeter Munch                               fe.n_dofs_per_cell() / n_components,
2808c81f8b0SPeter Munch                               n_components,
2818c81f8b0SPeter Munch                               std::max<unsigned int>(this->extended_local_size() / n_components, 1),
2828c81f8b0SPeter Munch                               this->extended_local_size(),
2838c81f8b0SPeter Munch                               CEED_MEM_HOST,
2848c81f8b0SPeter Munch                               CEED_COPY_VALUES,
2858c81f8b0SPeter Munch                               indices.data(),
2868c81f8b0SPeter Munch                               &sol_restriction);
2878c81f8b0SPeter Munch 
2888c81f8b0SPeter Munch     // 4) create mapping -> MappingInfo
2898c81f8b0SPeter Munch     const unsigned int n_components_metric = (bp <= BPType::BP2) ? 1 : (dim * (dim + 1) / 2);
2908c81f8b0SPeter Munch 
2918c81f8b0SPeter Munch     this->weights = compute_metric_data(ceed, mapping, tria, quadrature, bp);
2928c81f8b0SPeter Munch 
2938c81f8b0SPeter Munch     strides = {{1,
2948c81f8b0SPeter Munch                 static_cast<int>(quadrature.size()),
2958c81f8b0SPeter Munch                 static_cast<int>(quadrature.size() * n_components_metric)}};
2968c81f8b0SPeter Munch     CeedVectorCreate(ceed, weights.size(), &q_data);
2978c81f8b0SPeter Munch     CeedVectorSetArray(q_data, CEED_MEM_HOST, CEED_USE_POINTER, weights.data());
2988c81f8b0SPeter Munch     CeedElemRestrictionCreateStrided(ceed,
2998c81f8b0SPeter Munch                                      n_local_active_cells,
3008c81f8b0SPeter Munch                                      quadrature.size(),
3018c81f8b0SPeter Munch                                      n_components_metric,
3028c81f8b0SPeter Munch                                      weights.size(),
3038c81f8b0SPeter Munch                                      strides.data(),
3048c81f8b0SPeter Munch                                      &q_data_restriction);
3058c81f8b0SPeter Munch 
3068c81f8b0SPeter Munch     build_ctx_data.dim       = dim;
3078c81f8b0SPeter Munch     build_ctx_data.space_dim = dim;
3088c81f8b0SPeter Munch 
3098c81f8b0SPeter Munch     CeedQFunctionContextCreate(ceed, &build_ctx);
3108c81f8b0SPeter Munch     CeedQFunctionContextSetData(
3118efac696SJeremy L Thompson       build_ctx, CEED_MEM_HOST, CEED_COPY_VALUES, sizeof(build_ctx_data), &build_ctx_data);
3128c81f8b0SPeter Munch 
3138c81f8b0SPeter Munch     // 5) create q operation
3148c81f8b0SPeter Munch     if (bp == BPType::BP1)
3158c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_apply_mass, f_apply_mass_loc, &qf_apply);
3168c81f8b0SPeter Munch     else if (bp == BPType::BP2)
3178c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_apply_mass_vec, f_apply_mass_vec_loc, &qf_apply);
3188c81f8b0SPeter Munch     else if (bp == BPType::BP3 || bp == BPType::BP5)
3198c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_apply_poisson, f_apply_poisson_loc, &qf_apply);
3208c81f8b0SPeter Munch     else if (bp == BPType::BP4 || bp == BPType::BP6)
3218c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_apply_poisson_vec, f_apply_poisson_vec_loc, &qf_apply);
3228c81f8b0SPeter Munch     else
3238c81f8b0SPeter Munch       AssertThrow(false, ExcInternalError());
3248c81f8b0SPeter Munch 
3258c81f8b0SPeter Munch     if (bp <= BPType::BP2)
3268c81f8b0SPeter Munch       CeedQFunctionAddInput(qf_apply, "u", n_components, CEED_EVAL_INTERP);
3278c81f8b0SPeter Munch     else
3288c81f8b0SPeter Munch       CeedQFunctionAddInput(qf_apply, "u", dim * n_components, CEED_EVAL_GRAD);
3298c81f8b0SPeter Munch 
3308c81f8b0SPeter Munch     CeedQFunctionAddInput(qf_apply, "qdata", n_components_metric, CEED_EVAL_NONE);
3318c81f8b0SPeter Munch 
3328c81f8b0SPeter Munch     if (bp <= BPType::BP2)
3338c81f8b0SPeter Munch       CeedQFunctionAddOutput(qf_apply, "v", n_components, CEED_EVAL_INTERP);
3348c81f8b0SPeter Munch     else
3358c81f8b0SPeter Munch       CeedQFunctionAddOutput(qf_apply, "v", dim * n_components, CEED_EVAL_GRAD);
3368c81f8b0SPeter Munch 
3378c81f8b0SPeter Munch     CeedQFunctionSetContext(qf_apply, build_ctx);
3388c81f8b0SPeter Munch 
3398c81f8b0SPeter Munch     // 6) put everything together
3408c81f8b0SPeter Munch     CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_apply);
3418c81f8b0SPeter Munch 
3428c81f8b0SPeter Munch     CeedOperatorSetField(op_apply, "u", sol_restriction, sol_basis, CEED_VECTOR_ACTIVE);
343fab7d8a4SJeremy L Thompson     CeedOperatorSetField(op_apply, "qdata", q_data_restriction, CEED_BASIS_NONE, q_data);
3448c81f8b0SPeter Munch     CeedOperatorSetField(op_apply, "v", sol_restriction, sol_basis, CEED_VECTOR_ACTIVE);
3458efac696SJeremy L Thompson 
3462097acd5SJeremy L Thompson     // 7) libCEED vectors
3472097acd5SJeremy L Thompson     CeedElemRestrictionCreateVector(sol_restriction, &src_ceed, NULL);
3482097acd5SJeremy L Thompson     CeedElemRestrictionCreateVector(sol_restriction, &dst_ceed, NULL);
3492097acd5SJeremy L Thompson 
3502097acd5SJeremy L Thompson     // 8) cleanup
3518efac696SJeremy L Thompson     CeedVectorDestroy(&q_data);
3528efac696SJeremy L Thompson     CeedElemRestrictionDestroy(&q_data_restriction);
3538efac696SJeremy L Thompson     CeedElemRestrictionDestroy(&sol_restriction);
3548efac696SJeremy L Thompson     CeedBasisDestroy(&sol_basis);
3558efac696SJeremy L Thompson     CeedQFunctionContextDestroy(&build_ctx);
3568efac696SJeremy L Thompson     CeedQFunctionDestroy(&qf_apply);
3578c81f8b0SPeter Munch   }
3588c81f8b0SPeter Munch 
3598c81f8b0SPeter Munch   /**
3608c81f8b0SPeter Munch    * Perform matrix-vector product.
3618c81f8b0SPeter Munch    */
3628c81f8b0SPeter Munch   void
3638c81f8b0SPeter Munch   vmult(VectorType &dst, const VectorType &src) const override
3648c81f8b0SPeter Munch   {
3658c81f8b0SPeter Munch     // communicate: update ghost values
3668c81f8b0SPeter Munch     src.update_ghost_values();
3678c81f8b0SPeter Munch 
3688c81f8b0SPeter Munch     if (dof_handler.get_fe().n_components() == 1)
3698c81f8b0SPeter Munch       {
3702097acd5SJeremy L Thompson         // pass memory buffers to libCEED
3712097acd5SJeremy L Thompson         VectorTypeCeed x(src_ceed);
3722097acd5SJeremy L Thompson         VectorTypeCeed y(dst_ceed);
3730850f995SJeremy L Thompson         x.import_array(src, CEED_MEM_HOST);
3740850f995SJeremy L Thompson         y.import_array(dst, CEED_MEM_HOST);
3758c81f8b0SPeter Munch 
3768c81f8b0SPeter Munch         // apply operator
3772097acd5SJeremy L Thompson         CeedOperatorApply(op_apply, x(), y(), CEED_REQUEST_IMMEDIATE);
3782097acd5SJeremy L Thompson 
3792097acd5SJeremy L Thompson         // pull arrays back to deal.II
3800850f995SJeremy L Thompson         x.sync_array();
3810850f995SJeremy L Thompson         y.sync_array();
3828c81f8b0SPeter Munch       }
3838c81f8b0SPeter Munch     else // TODO: needed for multiple components
3848c81f8b0SPeter Munch       {
3858c81f8b0SPeter Munch         // allocate space for block vectors
3868c81f8b0SPeter Munch         src_tmp.reinit(this->extended_local_size(), true);
3878c81f8b0SPeter Munch         dst_tmp.reinit(this->extended_local_size(), true);
3888c81f8b0SPeter Munch 
3892097acd5SJeremy L Thompson         // copy to block vector
3902097acd5SJeremy L Thompson         copy_to_block_vector(src_tmp, src);
3918c81f8b0SPeter Munch 
3922097acd5SJeremy L Thompson         // pass memory buffers to libCEED
3932097acd5SJeremy L Thompson         VectorTypeCeed x(src_ceed);
3942097acd5SJeremy L Thompson         VectorTypeCeed y(dst_ceed);
3950850f995SJeremy L Thompson         x.import_array(src_tmp, CEED_MEM_HOST);
3960850f995SJeremy L Thompson         y.import_array(dst_tmp, CEED_MEM_HOST);
3978c81f8b0SPeter Munch 
3988c81f8b0SPeter Munch         // apply operator
3992097acd5SJeremy L Thompson         CeedOperatorApply(op_apply, x(), y(), CEED_REQUEST_IMMEDIATE);
4008c81f8b0SPeter Munch 
4012097acd5SJeremy L Thompson         // pull arrays back to deal.II
4020850f995SJeremy L Thompson         x.sync_array();
4030850f995SJeremy L Thompson         y.sync_array();
4042097acd5SJeremy L Thompson 
4052097acd5SJeremy L Thompson         // copy from block vector
4062097acd5SJeremy L Thompson         copy_from_block_vector(dst, dst_tmp);
4078c81f8b0SPeter Munch       }
4088c81f8b0SPeter Munch 
4098c81f8b0SPeter Munch     // communicate: compress
4108c81f8b0SPeter Munch     src.zero_out_ghost_values();
4118c81f8b0SPeter Munch     dst.compress(VectorOperation::add);
4128c81f8b0SPeter Munch 
4138c81f8b0SPeter Munch     // apply constraints: we assume homogeneous DBC
4148c81f8b0SPeter Munch     constraints.set_zero(dst);
4158c81f8b0SPeter Munch   }
4168c81f8b0SPeter Munch 
4178c81f8b0SPeter Munch   /**
4188c81f8b0SPeter Munch    * Initialized vector.
4198c81f8b0SPeter Munch    */
4208c81f8b0SPeter Munch   void
4218c81f8b0SPeter Munch   initialize_dof_vector(VectorType &vec) const override
4228c81f8b0SPeter Munch   {
4238c81f8b0SPeter Munch     vec.reinit(partitioner);
4248c81f8b0SPeter Munch   }
4258c81f8b0SPeter Munch 
4268c81f8b0SPeter Munch   /**
4278c81f8b0SPeter Munch    * Compute inverse of diagonal.
4288c81f8b0SPeter Munch    */
4298c81f8b0SPeter Munch   void
4308c81f8b0SPeter Munch   compute_inverse_diagonal(VectorType &diagonal) const override
4318c81f8b0SPeter Munch   {
4328c81f8b0SPeter Munch     this->initialize_dof_vector(diagonal);
4338c81f8b0SPeter Munch 
4342097acd5SJeremy L Thompson     // pass memory buffer to libCEED
4352097acd5SJeremy L Thompson     VectorTypeCeed y(dst_ceed);
4360850f995SJeremy L Thompson     y.import_array(diagonal, CEED_MEM_HOST);
4378c81f8b0SPeter Munch 
4382097acd5SJeremy L Thompson     CeedOperatorLinearAssembleDiagonal(op_apply, y(), CEED_REQUEST_IMMEDIATE);
4392097acd5SJeremy L Thompson 
4402097acd5SJeremy L Thompson     // pull array back to deal.II
4410850f995SJeremy L Thompson     y.sync_array();
4428c81f8b0SPeter Munch 
4438c81f8b0SPeter Munch     const unsigned int n_components = dof_handler.get_fe().n_components();
4448c81f8b0SPeter Munch 
4458c81f8b0SPeter Munch     if (n_components > 1) // TODO: needed for multiple components
4468c81f8b0SPeter Munch       {
4478c81f8b0SPeter Munch         VectorType tmp(diagonal);
4488c81f8b0SPeter Munch 
4498c81f8b0SPeter Munch         copy_from_block_vector(tmp, diagonal);
4508c81f8b0SPeter Munch 
4518c81f8b0SPeter Munch         std::swap(tmp, diagonal);
4528c81f8b0SPeter Munch       }
4538c81f8b0SPeter Munch 
4548c81f8b0SPeter Munch     diagonal.compress(VectorOperation::add);
4558c81f8b0SPeter Munch 
4568c81f8b0SPeter Munch     for (auto &i : diagonal)
4578c81f8b0SPeter Munch       i = (std::abs(i) > 1.0e-10) ? (1.0 / i) : 1.0;
4588c81f8b0SPeter Munch   }
4598c81f8b0SPeter Munch 
4608c81f8b0SPeter Munch private:
4618c81f8b0SPeter Munch   /**
4628c81f8b0SPeter Munch    * Wrapper around a deal.II vector to create a libCEED vector view.
4638c81f8b0SPeter Munch    */
4648c81f8b0SPeter Munch   class VectorTypeCeed
4658c81f8b0SPeter Munch   {
4668c81f8b0SPeter Munch   public:
4678c81f8b0SPeter Munch     /**
4688c81f8b0SPeter Munch      * Constructor.
4698c81f8b0SPeter Munch      */
4702097acd5SJeremy L Thompson     VectorTypeCeed(const CeedVector &vec_orig)
4718c81f8b0SPeter Munch     {
4722097acd5SJeremy L Thompson       vec_ceed = NULL;
4732097acd5SJeremy L Thompson       CeedVectorReferenceCopy(vec_orig, &vec_ceed);
4748c81f8b0SPeter Munch     }
4758c81f8b0SPeter Munch 
4768c81f8b0SPeter Munch     /**
4778c81f8b0SPeter Munch      * Return libCEED vector view.
4788c81f8b0SPeter Munch      */
4798c81f8b0SPeter Munch     CeedVector &
4808c81f8b0SPeter Munch     operator()()
4818c81f8b0SPeter Munch     {
4828c81f8b0SPeter Munch       return vec_ceed;
4838c81f8b0SPeter Munch     }
4848c81f8b0SPeter Munch 
4858c81f8b0SPeter Munch     /**
4862097acd5SJeremy L Thompson      * Set deal.II memory in libCEED vector.
4872097acd5SJeremy L Thompson      */
4882097acd5SJeremy L Thompson     void
4890850f995SJeremy L Thompson     import_array(const VectorType &vec, const CeedMemType space)
4902097acd5SJeremy L Thompson     {
4910850f995SJeremy L Thompson       mem_space = space;
4920850f995SJeremy L Thompson       CeedVectorSetArray(vec_ceed, mem_space, CEED_USE_POINTER, vec.get_values());
4932097acd5SJeremy L Thompson     }
4942097acd5SJeremy L Thompson 
4952097acd5SJeremy L Thompson     /**
4968c81f8b0SPeter Munch      * Sync memory from device to host.
4978c81f8b0SPeter Munch      */
4988c81f8b0SPeter Munch     void
4990850f995SJeremy L Thompson     sync_array()
5008c81f8b0SPeter Munch     {
5010850f995SJeremy L Thompson       CeedVectorSyncArray(vec_ceed, mem_space);
5028c81f8b0SPeter Munch     }
5038c81f8b0SPeter Munch 
5048c81f8b0SPeter Munch     /**
5058c81f8b0SPeter Munch      * Destructor: destroy vector view.
5068c81f8b0SPeter Munch      */
5078c81f8b0SPeter Munch     ~VectorTypeCeed()
5088c81f8b0SPeter Munch     {
5092097acd5SJeremy L Thompson       bool has_array;
5100850f995SJeremy L Thompson       CeedVectorHasBorrowedArrayOfType(vec_ceed, mem_space, &has_array);
5112097acd5SJeremy L Thompson       if (has_array)
5122097acd5SJeremy L Thompson         {
5138c81f8b0SPeter Munch           CeedScalar *ptr;
5140850f995SJeremy L Thompson           CeedVectorTakeArray(vec_ceed, mem_space, &ptr);
5152097acd5SJeremy L Thompson         }
5168c81f8b0SPeter Munch       CeedVectorDestroy(&vec_ceed);
5178c81f8b0SPeter Munch     }
5188c81f8b0SPeter Munch 
5198c81f8b0SPeter Munch   private:
5208c81f8b0SPeter Munch     /**
5218c81f8b0SPeter Munch      * libCEED vector view.
5228c81f8b0SPeter Munch      */
5230850f995SJeremy L Thompson     CeedMemType mem_space;
5248c81f8b0SPeter Munch     CeedVector  vec_ceed;
5258c81f8b0SPeter Munch   };
5268c81f8b0SPeter Munch 
5278c81f8b0SPeter Munch   /**
5288c81f8b0SPeter Munch    * Copy from block vector.
5298c81f8b0SPeter Munch    *
5308c81f8b0SPeter Munch    * @note Only needed for multiple components.
5318c81f8b0SPeter Munch    */
5328c81f8b0SPeter Munch   void
5338c81f8b0SPeter Munch   copy_from_block_vector(VectorType &dst, const VectorType &src) const
5348c81f8b0SPeter Munch   {
5358c81f8b0SPeter Munch     const unsigned int scalar_size = this->extended_local_size() / dim;
5368c81f8b0SPeter Munch 
5378c81f8b0SPeter Munch     for (unsigned int i = 0; i < scalar_size; ++i)
5388c81f8b0SPeter Munch       for (unsigned int j = 0; j < dim; ++j)
5398c81f8b0SPeter Munch         dst.get_values()[j + i * dim] = src.get_values()[j * scalar_size + i];
5408c81f8b0SPeter Munch   }
5418c81f8b0SPeter Munch 
5428c81f8b0SPeter Munch   /**
5438c81f8b0SPeter Munch    * Copy to block vector.
5448c81f8b0SPeter Munch    *
5458c81f8b0SPeter Munch    * @note Only needed for multiple components.
5468c81f8b0SPeter Munch    */
5478c81f8b0SPeter Munch   void
5488c81f8b0SPeter Munch   copy_to_block_vector(VectorType &dst, const VectorType &src) const
5498c81f8b0SPeter Munch   {
5508c81f8b0SPeter Munch     const unsigned int scalar_size = this->extended_local_size() / dim;
5518c81f8b0SPeter Munch 
5528c81f8b0SPeter Munch     for (unsigned int i = 0; i < scalar_size; ++i)
5538c81f8b0SPeter Munch       for (unsigned int j = 0; j < dim; ++j)
5548c81f8b0SPeter Munch         dst.get_values()[j * scalar_size + i] = src.get_values()[j + i * dim];
5558c81f8b0SPeter Munch   }
5568c81f8b0SPeter Munch 
5578c81f8b0SPeter Munch   /**
5588c81f8b0SPeter Munch    * Number of locally active DoFs.
5598c81f8b0SPeter Munch    */
5608c81f8b0SPeter Munch   unsigned int
5618c81f8b0SPeter Munch   extended_local_size() const
5628c81f8b0SPeter Munch   {
5638c81f8b0SPeter Munch     return partitioner->locally_owned_size() + partitioner->n_ghost_indices();
5648c81f8b0SPeter Munch   }
5658c81f8b0SPeter Munch 
5668c81f8b0SPeter Munch   /**
5678c81f8b0SPeter Munch    * Compute metric data: Jacobian, ...
5688c81f8b0SPeter Munch    */
5698c81f8b0SPeter Munch   static std::vector<double>
5708c81f8b0SPeter Munch   compute_metric_data(const Ceed               &ceed,
5718c81f8b0SPeter Munch                       const Mapping<dim>       &mapping,
5728c81f8b0SPeter Munch                       const Triangulation<dim> &tria,
5738c81f8b0SPeter Munch                       const Quadrature<dim>    &quadrature,
5748c81f8b0SPeter Munch                       const BPType              bp)
5758c81f8b0SPeter Munch   {
5768c81f8b0SPeter Munch     std::vector<double> weights;
5778c81f8b0SPeter Munch 
5788c81f8b0SPeter Munch     if (false)
5798c81f8b0SPeter Munch       {
5808c81f8b0SPeter Munch         FE_Nothing<dim> dummy_fe;
5818c81f8b0SPeter Munch         FEValues<dim>   fe_values(mapping, dummy_fe, quadrature, update_JxW_values);
5828c81f8b0SPeter Munch 
5838c81f8b0SPeter Munch         for (const auto &cell : tria.active_cell_iterators())
5848c81f8b0SPeter Munch           if (cell->is_locally_owned())
5858c81f8b0SPeter Munch             {
5868c81f8b0SPeter Munch               fe_values.reinit(cell);
5878c81f8b0SPeter Munch 
5888c81f8b0SPeter Munch               for (const auto q : fe_values.quadrature_point_indices())
5898c81f8b0SPeter Munch                 weights.emplace_back(fe_values.JxW(q));
5908c81f8b0SPeter Munch             }
5918c81f8b0SPeter Munch 
5928c81f8b0SPeter Munch         return weights;
5938c81f8b0SPeter Munch       }
5948c81f8b0SPeter Munch 
5958c81f8b0SPeter Munch     CeedBasis            geo_basis;
5968c81f8b0SPeter Munch     CeedVector           q_data;
5978c81f8b0SPeter Munch     CeedElemRestriction  q_data_restriction;
5988c81f8b0SPeter Munch     CeedVector           node_coords;
5998c81f8b0SPeter Munch     CeedElemRestriction  geo_restriction;
6008c81f8b0SPeter Munch     CeedQFunctionContext build_ctx;
6018c81f8b0SPeter Munch     CeedQFunction        qf_build;
6028c81f8b0SPeter Munch     CeedOperator         op_build;
6038c81f8b0SPeter Munch 
6048c81f8b0SPeter Munch     const unsigned int n_q_points = quadrature.get_tensor_basis()[0].size();
6058c81f8b0SPeter Munch 
6068c81f8b0SPeter Munch     const unsigned int n_components = (bp <= BPType::BP2) ? 1 : (dim * (dim + 1) / 2);
6078c81f8b0SPeter Munch 
6088c81f8b0SPeter Munch     const auto mapping_q = dynamic_cast<const MappingQ<dim> *>(&mapping);
6098c81f8b0SPeter Munch 
6108c81f8b0SPeter Munch     AssertThrow(mapping_q, ExcMessage("Wrong mapping!"));
6118c81f8b0SPeter Munch 
6128c81f8b0SPeter Munch     const unsigned int fe_degree = mapping_q->get_degree();
6138c81f8b0SPeter Munch 
6148c81f8b0SPeter Munch     CeedBasisCreateTensorH1Lagrange(
6158c81f8b0SPeter Munch       ceed, dim, dim, fe_degree + 1, n_q_points, CEED_GAUSS, &geo_basis);
6168c81f8b0SPeter Munch 
6178c81f8b0SPeter Munch     unsigned int n_local_active_cells = 0;
6188c81f8b0SPeter Munch 
6198c81f8b0SPeter Munch     for (const auto &cell : tria.active_cell_iterators())
6208c81f8b0SPeter Munch       if (cell->is_locally_owned())
6218c81f8b0SPeter Munch         n_local_active_cells++;
6228c81f8b0SPeter Munch 
6238c81f8b0SPeter Munch     std::vector<double>  geo_support_points;
6248c81f8b0SPeter Munch     std::vector<CeedInt> geo_indices;
6258c81f8b0SPeter Munch 
6268c81f8b0SPeter Munch     FE_Q<dim> geo_fe(fe_degree);
6278c81f8b0SPeter Munch 
6288c81f8b0SPeter Munch     DoFHandler<dim> geo_dof_handler(tria);
6298c81f8b0SPeter Munch     geo_dof_handler.distribute_dofs(geo_fe);
6308c81f8b0SPeter Munch 
6318c81f8b0SPeter Munch     const auto geo_partitioner =
6328c81f8b0SPeter Munch       std::make_shared<Utilities::MPI::Partitioner>(geo_dof_handler.locally_owned_dofs(),
6338c81f8b0SPeter Munch                                                     DoFTools::extract_locally_active_dofs(
6348c81f8b0SPeter Munch                                                       geo_dof_handler),
6358c81f8b0SPeter Munch                                                     geo_dof_handler.get_communicator());
6368c81f8b0SPeter Munch 
6378c81f8b0SPeter Munch     geo_indices.reserve(n_local_active_cells * geo_fe.n_dofs_per_cell());
6388c81f8b0SPeter Munch 
6398c81f8b0SPeter Munch     const auto dof_mapping = FETools::lexicographic_to_hierarchic_numbering<dim>(fe_degree);
6408c81f8b0SPeter Munch 
6418c81f8b0SPeter Munch     FEValues<dim> fe_values(mapping,
6428c81f8b0SPeter Munch                             geo_fe,
6438c81f8b0SPeter Munch                             geo_fe.get_unit_support_points(),
6448c81f8b0SPeter Munch                             update_quadrature_points);
6458c81f8b0SPeter Munch 
6468c81f8b0SPeter Munch     std::vector<types::global_dof_index> local_indices(geo_fe.n_dofs_per_cell());
6478c81f8b0SPeter Munch 
6488c81f8b0SPeter Munch     const unsigned int n_points =
6498c81f8b0SPeter Munch       geo_partitioner->locally_owned_size() + geo_partitioner->n_ghost_indices();
6508c81f8b0SPeter Munch 
6518c81f8b0SPeter Munch     geo_support_points.resize(dim * n_points);
6528c81f8b0SPeter Munch 
6538c81f8b0SPeter Munch     for (const auto &cell : geo_dof_handler.active_cell_iterators())
6548c81f8b0SPeter Munch       if (cell->is_locally_owned())
6558c81f8b0SPeter Munch         {
6568c81f8b0SPeter Munch           fe_values.reinit(cell);
6578c81f8b0SPeter Munch           cell->get_dof_indices(local_indices);
6588c81f8b0SPeter Munch 
6598c81f8b0SPeter Munch           for (const auto i : dof_mapping)
6608c81f8b0SPeter Munch             {
6618c81f8b0SPeter Munch               const auto index = geo_partitioner->global_to_local(local_indices[i]);
6628c81f8b0SPeter Munch               geo_indices.emplace_back(index);
6638c81f8b0SPeter Munch 
6648c81f8b0SPeter Munch               const auto point = fe_values.quadrature_point(i);
6658c81f8b0SPeter Munch 
6668c81f8b0SPeter Munch               for (unsigned int d = 0; d < dim; ++d)
6678c81f8b0SPeter Munch                 geo_support_points[index + d * n_points] = point[d];
6688c81f8b0SPeter Munch             }
6698c81f8b0SPeter Munch         }
6708c81f8b0SPeter Munch 
6718c81f8b0SPeter Munch     weights.resize(n_local_active_cells * quadrature.size() * n_components);
6728c81f8b0SPeter Munch 
6738c81f8b0SPeter Munch     CeedInt strides[3] = {1,
6748c81f8b0SPeter Munch                           static_cast<int>(quadrature.size()),
6758c81f8b0SPeter Munch                           static_cast<int>(quadrature.size() * n_components)};
6768c81f8b0SPeter Munch 
6778c81f8b0SPeter Munch     CeedVectorCreate(ceed, weights.size(), &q_data);
6788c81f8b0SPeter Munch     CeedVectorSetArray(q_data, CEED_MEM_HOST, CEED_USE_POINTER, weights.data());
6798c81f8b0SPeter Munch     CeedElemRestrictionCreateStrided(ceed,
6808c81f8b0SPeter Munch                                      n_local_active_cells,
6818c81f8b0SPeter Munch                                      quadrature.size(),
6828c81f8b0SPeter Munch                                      n_components,
6838c81f8b0SPeter Munch                                      weights.size(),
6848c81f8b0SPeter Munch                                      strides,
6858c81f8b0SPeter Munch                                      &q_data_restriction);
6868c81f8b0SPeter Munch 
6878c81f8b0SPeter Munch     CeedVectorCreate(ceed, geo_support_points.size(), &node_coords);
6888c81f8b0SPeter Munch     CeedVectorSetArray(node_coords, CEED_MEM_HOST, CEED_USE_POINTER, geo_support_points.data());
6898c81f8b0SPeter Munch 
6908c81f8b0SPeter Munch     CeedElemRestrictionCreate(ceed,
6918c81f8b0SPeter Munch                               n_local_active_cells,
6928c81f8b0SPeter Munch                               geo_fe.n_dofs_per_cell(),
6938c81f8b0SPeter Munch                               dim,
6948c81f8b0SPeter Munch                               std::max<unsigned int>(geo_support_points.size() / dim, 1),
6958c81f8b0SPeter Munch                               geo_support_points.size(),
6968c81f8b0SPeter Munch                               CEED_MEM_HOST,
6978c81f8b0SPeter Munch                               CEED_COPY_VALUES,
6988c81f8b0SPeter Munch                               geo_indices.data(),
6998c81f8b0SPeter Munch                               &geo_restriction);
7008c81f8b0SPeter Munch 
7018c81f8b0SPeter Munch     BuildContext build_ctx_data;
7028c81f8b0SPeter Munch     build_ctx_data.dim       = dim;
7038c81f8b0SPeter Munch     build_ctx_data.space_dim = dim;
7048c81f8b0SPeter Munch 
7058c81f8b0SPeter Munch     CeedQFunctionContextCreate(ceed, &build_ctx);
7068c81f8b0SPeter Munch     CeedQFunctionContextSetData(
7078c81f8b0SPeter Munch       build_ctx, CEED_MEM_HOST, CEED_USE_POINTER, sizeof(build_ctx_data), &build_ctx_data);
7088c81f8b0SPeter Munch 
7098c81f8b0SPeter Munch     // 5) create q operation
7108c81f8b0SPeter Munch     if (bp <= BPType::BP2)
7118c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_build_mass, f_build_mass_loc, &qf_build);
7128c81f8b0SPeter Munch     else
7138c81f8b0SPeter Munch       CeedQFunctionCreateInterior(ceed, 1, f_build_poisson, f_build_poisson_loc, &qf_build);
7148c81f8b0SPeter Munch 
7158c81f8b0SPeter Munch     CeedQFunctionAddInput(qf_build, "geo", dim * dim, CEED_EVAL_GRAD);
7168c81f8b0SPeter Munch     CeedQFunctionAddInput(qf_build, "weights", 1, CEED_EVAL_WEIGHT);
7178c81f8b0SPeter Munch     CeedQFunctionAddOutput(qf_build, "qdata", n_components, CEED_EVAL_NONE);
7188c81f8b0SPeter Munch     CeedQFunctionSetContext(qf_build, build_ctx);
7198c81f8b0SPeter Munch 
7208c81f8b0SPeter Munch     // 6) put everything together
7218c81f8b0SPeter Munch     CeedOperatorCreate(ceed, qf_build, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_build);
7228c81f8b0SPeter Munch     CeedOperatorSetField(op_build, "geo", geo_restriction, geo_basis, CEED_VECTOR_ACTIVE);
7238c81f8b0SPeter Munch     CeedOperatorSetField(
7248c81f8b0SPeter Munch       op_build, "weights", CEED_ELEMRESTRICTION_NONE, geo_basis, CEED_VECTOR_NONE);
7258c81f8b0SPeter Munch     CeedOperatorSetField(
726fab7d8a4SJeremy L Thompson       op_build, "qdata", q_data_restriction, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE);
7278c81f8b0SPeter Munch 
7288c81f8b0SPeter Munch     CeedOperatorApply(op_build, node_coords, q_data, CEED_REQUEST_IMMEDIATE);
7298c81f8b0SPeter Munch 
7308c81f8b0SPeter Munch     CeedVectorDestroy(&node_coords);
7318c81f8b0SPeter Munch     CeedVectorSyncArray(q_data, CEED_MEM_HOST);
7328c81f8b0SPeter Munch     CeedVectorDestroy(&q_data);
73370dc8078SJeremy L Thompson     CeedElemRestrictionDestroy(&geo_restriction);
73470dc8078SJeremy L Thompson     CeedElemRestrictionDestroy(&q_data_restriction);
7358c81f8b0SPeter Munch     CeedBasisDestroy(&geo_basis);
73670dc8078SJeremy L Thompson     CeedQFunctionContextDestroy(&build_ctx);
73770dc8078SJeremy L Thompson     CeedQFunctionDestroy(&qf_build);
73870dc8078SJeremy L Thompson     CeedOperatorDestroy(&op_build);
7398c81f8b0SPeter Munch 
7408c81f8b0SPeter Munch     return weights;
7418c81f8b0SPeter Munch   }
7428c81f8b0SPeter Munch 
7438c81f8b0SPeter Munch   /**
7448c81f8b0SPeter Munch    * Mapping object passed to the constructor.
7458c81f8b0SPeter Munch    */
7468c81f8b0SPeter Munch   const Mapping<dim> &mapping;
7478c81f8b0SPeter Munch 
7488c81f8b0SPeter Munch   /**
7498c81f8b0SPeter Munch    * DoFHandler object passed to the constructor.
7508c81f8b0SPeter Munch    */
7518c81f8b0SPeter Munch   const DoFHandler<dim> &dof_handler;
7528c81f8b0SPeter Munch 
7538c81f8b0SPeter Munch   /**
7548c81f8b0SPeter Munch    * Constraints object passed to the constructor.
7558c81f8b0SPeter Munch    */
7568c81f8b0SPeter Munch   const AffineConstraints<Number> &constraints;
7578c81f8b0SPeter Munch 
7588c81f8b0SPeter Munch   /**
7598c81f8b0SPeter Munch    * Quadrature rule object passed to the constructor.
7608c81f8b0SPeter Munch    */
7618c81f8b0SPeter Munch   const Quadrature<dim> &quadrature;
7628c81f8b0SPeter Munch 
7638c81f8b0SPeter Munch   /**
7648c81f8b0SPeter Munch    * Selected BP.
7658c81f8b0SPeter Munch    */
7668c81f8b0SPeter Munch   const BPType bp;
7678c81f8b0SPeter Munch 
7688c81f8b0SPeter Munch   /**
7698c81f8b0SPeter Munch    * Resource name.
7708c81f8b0SPeter Munch    */
7718c81f8b0SPeter Munch   const std::string resource;
7728c81f8b0SPeter Munch 
7738c81f8b0SPeter Munch   /**
7748c81f8b0SPeter Munch    * Partitioner for distributed vectors.
7758c81f8b0SPeter Munch    */
7768c81f8b0SPeter Munch   std::shared_ptr<Utilities::MPI::Partitioner> partitioner;
7778c81f8b0SPeter Munch 
7788c81f8b0SPeter Munch   /**
7798c81f8b0SPeter Munch    * libCEED data structures.
7808c81f8b0SPeter Munch    */
7818c81f8b0SPeter Munch   Ceed                   ceed;
7828c81f8b0SPeter Munch   std::vector<double>    weights;
7838c81f8b0SPeter Munch   std::array<CeedInt, 3> strides;
7842097acd5SJeremy L Thompson   CeedVector             src_ceed;
7852097acd5SJeremy L Thompson   CeedVector             dst_ceed;
7868c81f8b0SPeter Munch   CeedOperator           op_apply;
7878c81f8b0SPeter Munch 
7888c81f8b0SPeter Munch   /**
7898c81f8b0SPeter Munch    * Temporal (tempral) vectors.
7908c81f8b0SPeter Munch    *
7918c81f8b0SPeter Munch    * @note Only needed for multiple components.
7928c81f8b0SPeter Munch    */
7938c81f8b0SPeter Munch   mutable VectorType src_tmp;
7948c81f8b0SPeter Munch   mutable VectorType dst_tmp;
7958c81f8b0SPeter Munch };
7968c81f8b0SPeter Munch 
7978c81f8b0SPeter Munch 
7988c81f8b0SPeter Munch 
7998c81f8b0SPeter Munch template <int dim, typename Number>
8008c81f8b0SPeter Munch class OperatorDealii : public OperatorBase<Number>
8018c81f8b0SPeter Munch {
8028c81f8b0SPeter Munch public:
8038c81f8b0SPeter Munch   using VectorType = typename OperatorBase<Number>::VectorType;
8048c81f8b0SPeter Munch 
8058c81f8b0SPeter Munch   /**
8068c81f8b0SPeter Munch    * Constructor.
8078c81f8b0SPeter Munch    */
8088c81f8b0SPeter Munch   OperatorDealii(const Mapping<dim>              &mapping,
8098c81f8b0SPeter Munch                  const DoFHandler<dim>           &dof_handler,
8108c81f8b0SPeter Munch                  const AffineConstraints<Number> &constraints,
8118c81f8b0SPeter Munch                  const Quadrature<dim>           &quadrature,
8128c81f8b0SPeter Munch                  const BPType                    &bp)
8138c81f8b0SPeter Munch     : mapping(mapping)
8148c81f8b0SPeter Munch     , dof_handler(dof_handler)
8158c81f8b0SPeter Munch     , constraints(constraints)
8168c81f8b0SPeter Munch     , quadrature(quadrature)
8178c81f8b0SPeter Munch     , bp(bp)
8188c81f8b0SPeter Munch   {
8198c81f8b0SPeter Munch     reinit();
8208c81f8b0SPeter Munch   }
8218c81f8b0SPeter Munch 
8228c81f8b0SPeter Munch   /**
8238c81f8b0SPeter Munch    * Destructor.
8248c81f8b0SPeter Munch    */
8258c81f8b0SPeter Munch   ~OperatorDealii() = default;
8268c81f8b0SPeter Munch 
8278c81f8b0SPeter Munch   /**
8288c81f8b0SPeter Munch    * Initialized internal data structures, particularly, MatrixFree.
8298c81f8b0SPeter Munch    */
8308c81f8b0SPeter Munch   void
8318c81f8b0SPeter Munch   reinit() override
8328c81f8b0SPeter Munch   {
8338c81f8b0SPeter Munch     // configure MatrixFree
8348c81f8b0SPeter Munch     typename MatrixFree<dim, Number>::AdditionalData additional_data;
8358c81f8b0SPeter Munch     additional_data.tasks_parallel_scheme =
8368c81f8b0SPeter Munch       MatrixFree<dim, Number>::AdditionalData::TasksParallelScheme::none;
8378c81f8b0SPeter Munch 
8388c81f8b0SPeter Munch     // create MatrixFree
8398c81f8b0SPeter Munch     matrix_free.reinit(mapping, dof_handler, constraints, quadrature, additional_data);
8408c81f8b0SPeter Munch   }
8418c81f8b0SPeter Munch 
8428c81f8b0SPeter Munch   /**
8438c81f8b0SPeter Munch    * Matrix-vector product.
8448c81f8b0SPeter Munch    */
8458c81f8b0SPeter Munch   void
8468c81f8b0SPeter Munch   vmult(VectorType &dst, const VectorType &src) const override
8478c81f8b0SPeter Munch   {
8488c81f8b0SPeter Munch     if (dof_handler.get_fe().n_components() == 1)
8498c81f8b0SPeter Munch       {
8508c81f8b0SPeter Munch         matrix_free.cell_loop(&OperatorDealii::do_cell_integral_range<1>, this, dst, src, true);
8518c81f8b0SPeter Munch       }
8528c81f8b0SPeter Munch     else
8538c81f8b0SPeter Munch       {
8548c81f8b0SPeter Munch         AssertThrow(dof_handler.get_fe().n_components() == dim, ExcInternalError());
8558c81f8b0SPeter Munch 
8568c81f8b0SPeter Munch         matrix_free.cell_loop(&OperatorDealii::do_cell_integral_range<dim>, this, dst, src, true);
8578c81f8b0SPeter Munch       }
8588c81f8b0SPeter Munch   }
8598c81f8b0SPeter Munch 
8608c81f8b0SPeter Munch   /**
8618c81f8b0SPeter Munch    * Initialize vector.
8628c81f8b0SPeter Munch    */
8638c81f8b0SPeter Munch   void
8648c81f8b0SPeter Munch   initialize_dof_vector(VectorType &vec) const override
8658c81f8b0SPeter Munch   {
8668c81f8b0SPeter Munch     matrix_free.initialize_dof_vector(vec);
8678c81f8b0SPeter Munch   }
8688c81f8b0SPeter Munch 
8698c81f8b0SPeter Munch   /**
8708c81f8b0SPeter Munch    * Compute inverse of diagonal.
8718c81f8b0SPeter Munch    */
8728c81f8b0SPeter Munch   void
8738c81f8b0SPeter Munch   compute_inverse_diagonal(VectorType &diagonal) const override
8748c81f8b0SPeter Munch   {
8758c81f8b0SPeter Munch     this->initialize_dof_vector(diagonal);
8768c81f8b0SPeter Munch 
8778c81f8b0SPeter Munch     if (dof_handler.get_fe().n_components() == 1)
8788c81f8b0SPeter Munch       {
8798c81f8b0SPeter Munch         MatrixFreeTools::compute_diagonal(matrix_free,
8808c81f8b0SPeter Munch                                           diagonal,
8818c81f8b0SPeter Munch                                           &OperatorDealii::do_cell_integral_local<1>,
8828c81f8b0SPeter Munch                                           this);
8838c81f8b0SPeter Munch       }
8848c81f8b0SPeter Munch     else
8858c81f8b0SPeter Munch       {
8868c81f8b0SPeter Munch         AssertThrow(dof_handler.get_fe().n_components() == dim, ExcInternalError());
8878c81f8b0SPeter Munch 
8888c81f8b0SPeter Munch         MatrixFreeTools::compute_diagonal(matrix_free,
8898c81f8b0SPeter Munch                                           diagonal,
8908c81f8b0SPeter Munch                                           &OperatorDealii::do_cell_integral_local<dim>,
8918c81f8b0SPeter Munch                                           this);
8928c81f8b0SPeter Munch       }
8938c81f8b0SPeter Munch 
8948c81f8b0SPeter Munch     for (auto &i : diagonal)
8958c81f8b0SPeter Munch       i = (std::abs(i) > 1.0e-10) ? (1.0 / i) : 1.0;
8968c81f8b0SPeter Munch   }
8978c81f8b0SPeter Munch 
8988c81f8b0SPeter Munch private:
8998c81f8b0SPeter Munch   /**
9008c81f8b0SPeter Munch    * Cell integral without vector access.
9018c81f8b0SPeter Munch    */
9028c81f8b0SPeter Munch   template <int n_components>
9038c81f8b0SPeter Munch   void
9048c81f8b0SPeter Munch   do_cell_integral_local(FEEvaluation<dim, -1, 0, n_components, Number> &phi) const
9058c81f8b0SPeter Munch   {
9068c81f8b0SPeter Munch     if (bp <= BPType::BP2) // mass matrix
9078c81f8b0SPeter Munch       {
9088c81f8b0SPeter Munch         phi.evaluate(EvaluationFlags::values);
9098c81f8b0SPeter Munch         for (const auto q : phi.quadrature_point_indices())
9108c81f8b0SPeter Munch           phi.submit_value(phi.get_value(q), q);
9118c81f8b0SPeter Munch         phi.integrate(EvaluationFlags::values);
9128c81f8b0SPeter Munch       }
9138c81f8b0SPeter Munch     else // Poisson operator
9148c81f8b0SPeter Munch       {
9158c81f8b0SPeter Munch         phi.evaluate(EvaluationFlags::gradients);
9168c81f8b0SPeter Munch         for (const auto q : phi.quadrature_point_indices())
9178c81f8b0SPeter Munch           phi.submit_gradient(phi.get_gradient(q), q);
9188c81f8b0SPeter Munch         phi.integrate(EvaluationFlags::gradients);
9198c81f8b0SPeter Munch       }
9208c81f8b0SPeter Munch   }
9218c81f8b0SPeter Munch 
9228c81f8b0SPeter Munch   /**
9238c81f8b0SPeter Munch    * Cell integral on a range of cells.
9248c81f8b0SPeter Munch    */
9258c81f8b0SPeter Munch   template <int n_components>
9268c81f8b0SPeter Munch   void
9278c81f8b0SPeter Munch   do_cell_integral_range(const MatrixFree<dim, Number>               &matrix_free,
9288c81f8b0SPeter Munch                          VectorType                                  &dst,
9298c81f8b0SPeter Munch                          const VectorType                            &src,
9308c81f8b0SPeter Munch                          const std::pair<unsigned int, unsigned int> &range) const
9318c81f8b0SPeter Munch   {
9328c81f8b0SPeter Munch     FEEvaluation<dim, -1, 0, n_components, Number> phi(matrix_free, range);
9338c81f8b0SPeter Munch 
9348c81f8b0SPeter Munch     for (unsigned cell = range.first; cell < range.second; ++cell)
9358c81f8b0SPeter Munch       {
9368c81f8b0SPeter Munch         phi.reinit(cell);
9378c81f8b0SPeter Munch         phi.read_dof_values(src);            // read source vector
9388c81f8b0SPeter Munch         do_cell_integral_local(phi);         // cell integral
9398c81f8b0SPeter Munch         phi.distribute_local_to_global(dst); // write to destination vector
9408c81f8b0SPeter Munch       }
9418c81f8b0SPeter Munch   }
9428c81f8b0SPeter Munch 
9438c81f8b0SPeter Munch   /**
9448c81f8b0SPeter Munch    * Mapping object passed to the constructor.
9458c81f8b0SPeter Munch    */
9468c81f8b0SPeter Munch   const Mapping<dim> &mapping;
9478c81f8b0SPeter Munch 
9488c81f8b0SPeter Munch   /**
9498c81f8b0SPeter Munch    * DoFHandler object passed to the constructor.
9508c81f8b0SPeter Munch    */
9518c81f8b0SPeter Munch   const DoFHandler<dim> &dof_handler;
9528c81f8b0SPeter Munch 
9538c81f8b0SPeter Munch   /**
9548c81f8b0SPeter Munch    * Constraints object passed to the constructor.
9558c81f8b0SPeter Munch    */
9568c81f8b0SPeter Munch   const AffineConstraints<Number> &constraints;
9578c81f8b0SPeter Munch 
9588c81f8b0SPeter Munch   /**
9598c81f8b0SPeter Munch    * Quadrature rule object passed to the constructor.
9608c81f8b0SPeter Munch    */
9618c81f8b0SPeter Munch   const Quadrature<dim> &quadrature;
9628c81f8b0SPeter Munch 
9638c81f8b0SPeter Munch   /**
9648c81f8b0SPeter Munch    * Selected BP.
9658c81f8b0SPeter Munch    */
9668c81f8b0SPeter Munch   const BPType bp;
9678c81f8b0SPeter Munch 
9688c81f8b0SPeter Munch   /**
9698c81f8b0SPeter Munch    * MatrixFree object.
9708c81f8b0SPeter Munch    */
9718c81f8b0SPeter Munch   MatrixFree<dim, Number> matrix_free;
9728c81f8b0SPeter Munch };
973