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> 278c81f8b0SPeter Munch #include <deal.II/matrix_free/tools.h> 288c81f8b0SPeter Munch 298c81f8b0SPeter Munch // libCEED includes 308c81f8b0SPeter Munch #include <ceed/ceed.h> 318c81f8b0SPeter Munch 328c81f8b0SPeter Munch // QFunction source 338c81f8b0SPeter Munch #include "bps-qfunctions.h" 348c81f8b0SPeter Munch 358c81f8b0SPeter Munch using namespace dealii; 368c81f8b0SPeter Munch 378c81f8b0SPeter Munch /** 388c81f8b0SPeter Munch * BP types. For more details, see https://ceed.exascaleproject.org/bps/. 398c81f8b0SPeter Munch */ 408c81f8b0SPeter Munch enum class BPType : unsigned int 418c81f8b0SPeter Munch { 428c81f8b0SPeter Munch BP1, 438c81f8b0SPeter Munch BP2, 448c81f8b0SPeter Munch BP3, 458c81f8b0SPeter Munch BP4, 468c81f8b0SPeter Munch BP5, 478c81f8b0SPeter Munch BP6 488c81f8b0SPeter Munch }; 498c81f8b0SPeter Munch 508c81f8b0SPeter Munch 518c81f8b0SPeter Munch 528c81f8b0SPeter Munch /** 538c81f8b0SPeter Munch * Struct storing relevant information regarding each BP. 548c81f8b0SPeter Munch */ 558c81f8b0SPeter Munch struct BPInfo 568c81f8b0SPeter Munch { 578c81f8b0SPeter Munch BPInfo(const BPType type, const int dim, const int fe_degree) 588c81f8b0SPeter Munch : type(type) 598c81f8b0SPeter Munch , dim(dim) 608c81f8b0SPeter Munch , fe_degree(fe_degree) 618c81f8b0SPeter Munch { 628c81f8b0SPeter Munch if (type == BPType::BP1) 638c81f8b0SPeter Munch type_string = "BP1"; 648c81f8b0SPeter Munch else if (type == BPType::BP2) 658c81f8b0SPeter Munch type_string = "BP2"; 668c81f8b0SPeter Munch else if (type == BPType::BP3) 678c81f8b0SPeter Munch type_string = "BP3"; 688c81f8b0SPeter Munch else if (type == BPType::BP4) 698c81f8b0SPeter Munch type_string = "BP4"; 708c81f8b0SPeter Munch else if (type == BPType::BP5) 718c81f8b0SPeter Munch type_string = "BP5"; 728c81f8b0SPeter Munch else if (type == BPType::BP6) 738c81f8b0SPeter Munch type_string = "BP6"; 748c81f8b0SPeter Munch 758c81f8b0SPeter Munch this->n_q_points_1d = (type <= BPType::BP4) ? (fe_degree + 2) : (fe_degree + 1); 768c81f8b0SPeter Munch 778c81f8b0SPeter Munch this->n_components = 788c81f8b0SPeter Munch (type == BPType::BP1 || type == BPType::BP3 || type == BPType::BP5) ? 1 : dim; 798c81f8b0SPeter Munch } 808c81f8b0SPeter Munch 818c81f8b0SPeter Munch 828c81f8b0SPeter Munch BPType type; 838c81f8b0SPeter Munch std::string type_string; 848c81f8b0SPeter Munch unsigned int dim; 858c81f8b0SPeter Munch unsigned int fe_degree; 868c81f8b0SPeter Munch unsigned int n_q_points_1d; 878c81f8b0SPeter Munch unsigned int n_components; 888c81f8b0SPeter Munch }; 898c81f8b0SPeter Munch 908c81f8b0SPeter Munch 918c81f8b0SPeter Munch 928c81f8b0SPeter Munch /** 938c81f8b0SPeter Munch * Base class of operators. 948c81f8b0SPeter Munch */ 958c81f8b0SPeter Munch template <typename Number> 968c81f8b0SPeter Munch class OperatorBase 978c81f8b0SPeter Munch { 988c81f8b0SPeter Munch public: 998c81f8b0SPeter Munch /** 1008c81f8b0SPeter Munch * deal.II vector type 1018c81f8b0SPeter Munch */ 1028c81f8b0SPeter Munch using VectorType = LinearAlgebra::distributed::Vector<Number>; 1038c81f8b0SPeter Munch 1048c81f8b0SPeter Munch /** 1058c81f8b0SPeter Munch * Initialize vector. 1068c81f8b0SPeter Munch */ 1078c81f8b0SPeter Munch virtual void 1088c81f8b0SPeter Munch reinit() = 0; 1098c81f8b0SPeter Munch 1108c81f8b0SPeter Munch /** 1118c81f8b0SPeter Munch * Perform matrix-vector product 1128c81f8b0SPeter Munch */ 1138c81f8b0SPeter Munch virtual void 1148c81f8b0SPeter Munch vmult(VectorType &dst, const VectorType &src) const = 0; 1158c81f8b0SPeter Munch 1168c81f8b0SPeter Munch /** 1178c81f8b0SPeter Munch * Initialize vector. 1188c81f8b0SPeter Munch */ 1198c81f8b0SPeter Munch virtual void 1208c81f8b0SPeter Munch initialize_dof_vector(VectorType &vec) const = 0; 1218c81f8b0SPeter Munch 1228c81f8b0SPeter Munch /** 1238c81f8b0SPeter Munch * Compute inverse of diagonal. 1248c81f8b0SPeter Munch */ 1258c81f8b0SPeter Munch virtual void 1268c81f8b0SPeter Munch compute_inverse_diagonal(VectorType &diagonal) const = 0; 1278c81f8b0SPeter Munch }; 1288c81f8b0SPeter Munch 1298c81f8b0SPeter Munch 1308c81f8b0SPeter Munch /** 1318c81f8b0SPeter Munch * Operator implementation using libCEED. 1328c81f8b0SPeter Munch */ 1338c81f8b0SPeter Munch template <int dim, typename Number> 1348c81f8b0SPeter Munch class OperatorCeed : public OperatorBase<Number> 1358c81f8b0SPeter Munch { 1368c81f8b0SPeter Munch public: 1378c81f8b0SPeter Munch using VectorType = typename OperatorBase<Number>::VectorType; 1388c81f8b0SPeter Munch 1398c81f8b0SPeter Munch /** 1408c81f8b0SPeter Munch * Constructor. 1418c81f8b0SPeter Munch */ 1428c81f8b0SPeter Munch OperatorCeed(const Mapping<dim> &mapping, 1438c81f8b0SPeter Munch const DoFHandler<dim> &dof_handler, 1448c81f8b0SPeter Munch const AffineConstraints<Number> &constraints, 1458c81f8b0SPeter Munch const Quadrature<dim> &quadrature, 1468c81f8b0SPeter Munch const BPType &bp, 1478c81f8b0SPeter Munch const std::string &resource) 1488c81f8b0SPeter Munch : mapping(mapping) 1498c81f8b0SPeter Munch , dof_handler(dof_handler) 1508c81f8b0SPeter Munch , constraints(constraints) 1518c81f8b0SPeter Munch , quadrature(quadrature) 1528c81f8b0SPeter Munch , bp(bp) 1538c81f8b0SPeter Munch , resource(resource) 1548c81f8b0SPeter Munch { 1558c81f8b0SPeter Munch reinit(); 1568c81f8b0SPeter Munch } 1578c81f8b0SPeter Munch 1588c81f8b0SPeter Munch /** 1598c81f8b0SPeter Munch * Destructor. 1608c81f8b0SPeter Munch */ 1618c81f8b0SPeter Munch ~OperatorCeed() 1628c81f8b0SPeter Munch { 16370dc8078SJeremy L Thompson CeedOperatorDestroy(&op_apply); 1648c81f8b0SPeter Munch CeedDestroy(&ceed); 1658c81f8b0SPeter Munch } 1668c81f8b0SPeter Munch 1678c81f8b0SPeter Munch /** 1688c81f8b0SPeter Munch * Initialized internal data structures, particularly, libCEED. 1698c81f8b0SPeter Munch */ 1708c81f8b0SPeter Munch void 1718c81f8b0SPeter Munch reinit() override 1728c81f8b0SPeter Munch { 173*8efac696SJeremy L Thompson CeedVector q_data; 174*8efac696SJeremy L Thompson CeedBasis sol_basis; 175*8efac696SJeremy L Thompson CeedElemRestriction sol_restriction; 176*8efac696SJeremy L Thompson CeedElemRestriction q_data_restriction; 177*8efac696SJeremy L Thompson BuildContext build_ctx_data; 178*8efac696SJeremy L Thompson CeedQFunctionContext build_ctx; 179*8efac696SJeremy L Thompson CeedQFunction qf_apply; 180*8efac696SJeremy L Thompson 1818c81f8b0SPeter Munch const auto &tria = dof_handler.get_triangulation(); 1828c81f8b0SPeter Munch const auto &fe = dof_handler.get_fe(); 1838c81f8b0SPeter Munch 1848c81f8b0SPeter Munch const auto n_components = fe.n_components(); 1858c81f8b0SPeter Munch 1868c81f8b0SPeter Munch if (bp == BPType::BP1 || bp == BPType::BP3 || bp == BPType::BP5) 1878c81f8b0SPeter Munch { 1888c81f8b0SPeter Munch AssertThrow(n_components == 1, ExcInternalError()); 1898c81f8b0SPeter Munch } 1908c81f8b0SPeter Munch else 1918c81f8b0SPeter Munch { 1928c81f8b0SPeter Munch AssertThrow(n_components == dim, ExcInternalError()); 1938c81f8b0SPeter Munch } 1948c81f8b0SPeter Munch 1958c81f8b0SPeter Munch // 1) create CEED instance -> "MatrixFree" 1968c81f8b0SPeter Munch const char *ceed_spec = resource.c_str(); 1978c81f8b0SPeter Munch CeedInit(ceed_spec, &ceed); 1988c81f8b0SPeter Munch 1998c81f8b0SPeter Munch // 2) create shape functions -> "ShapeInfo" 2008c81f8b0SPeter Munch const unsigned int fe_degree = fe.tensor_degree(); 2018c81f8b0SPeter Munch const unsigned int n_q_points = quadrature.get_tensor_basis()[0].size(); 2028c81f8b0SPeter Munch CeedBasisCreateTensorH1Lagrange( 2038c81f8b0SPeter Munch ceed, dim, n_components, fe_degree + 1, n_q_points, CEED_GAUSS, &sol_basis); 2048c81f8b0SPeter Munch 2058c81f8b0SPeter Munch // 3) create restriction matrix -> DoFInfo 2068c81f8b0SPeter Munch unsigned int n_local_active_cells = 0; 2078c81f8b0SPeter Munch 2088c81f8b0SPeter Munch for (const auto &cell : dof_handler.active_cell_iterators()) 2098c81f8b0SPeter Munch if (cell->is_locally_owned()) 2108c81f8b0SPeter Munch n_local_active_cells++; 2118c81f8b0SPeter Munch 2128c81f8b0SPeter Munch partitioner = 2138c81f8b0SPeter Munch std::make_shared<Utilities::MPI::Partitioner>(dof_handler.locally_owned_dofs(), 2148c81f8b0SPeter Munch DoFTools::extract_locally_active_dofs( 2158c81f8b0SPeter Munch dof_handler), 2168c81f8b0SPeter Munch dof_handler.get_communicator()); 2178c81f8b0SPeter Munch 2188c81f8b0SPeter Munch std::vector<CeedInt> indices; 2198c81f8b0SPeter Munch indices.reserve(n_local_active_cells * fe.n_dofs_per_cell() / n_components); 2208c81f8b0SPeter Munch 2218c81f8b0SPeter Munch const auto dof_mapping = FETools::lexicographic_to_hierarchic_numbering<dim>(fe_degree); 2228c81f8b0SPeter Munch 2238c81f8b0SPeter Munch std::vector<types::global_dof_index> local_indices(fe.n_dofs_per_cell()); 2248c81f8b0SPeter Munch 2258c81f8b0SPeter Munch for (const auto &cell : dof_handler.active_cell_iterators()) 2268c81f8b0SPeter Munch if (cell->is_locally_owned()) 2278c81f8b0SPeter Munch { 2288c81f8b0SPeter Munch cell->get_dof_indices(local_indices); 2298c81f8b0SPeter Munch 2308c81f8b0SPeter Munch for (const auto i : dof_mapping) 2318c81f8b0SPeter Munch indices.emplace_back( 2328c81f8b0SPeter Munch partitioner->global_to_local(local_indices[fe.component_to_system_index(0, i)]) / 2338c81f8b0SPeter Munch n_components); 2348c81f8b0SPeter Munch } 2358c81f8b0SPeter Munch 2368c81f8b0SPeter Munch CeedElemRestrictionCreate(ceed, 2378c81f8b0SPeter Munch n_local_active_cells, 2388c81f8b0SPeter Munch fe.n_dofs_per_cell() / n_components, 2398c81f8b0SPeter Munch n_components, 2408c81f8b0SPeter Munch std::max<unsigned int>(this->extended_local_size() / n_components, 1), 2418c81f8b0SPeter Munch this->extended_local_size(), 2428c81f8b0SPeter Munch CEED_MEM_HOST, 2438c81f8b0SPeter Munch CEED_COPY_VALUES, 2448c81f8b0SPeter Munch indices.data(), 2458c81f8b0SPeter Munch &sol_restriction); 2468c81f8b0SPeter Munch 2478c81f8b0SPeter Munch // 4) create mapping -> MappingInfo 2488c81f8b0SPeter Munch const unsigned int n_components_metric = (bp <= BPType::BP2) ? 1 : (dim * (dim + 1) / 2); 2498c81f8b0SPeter Munch 2508c81f8b0SPeter Munch this->weights = compute_metric_data(ceed, mapping, tria, quadrature, bp); 2518c81f8b0SPeter Munch 2528c81f8b0SPeter Munch strides = {{1, 2538c81f8b0SPeter Munch static_cast<int>(quadrature.size()), 2548c81f8b0SPeter Munch static_cast<int>(quadrature.size() * n_components_metric)}}; 2558c81f8b0SPeter Munch CeedVectorCreate(ceed, weights.size(), &q_data); 2568c81f8b0SPeter Munch CeedVectorSetArray(q_data, CEED_MEM_HOST, CEED_USE_POINTER, weights.data()); 2578c81f8b0SPeter Munch CeedElemRestrictionCreateStrided(ceed, 2588c81f8b0SPeter Munch n_local_active_cells, 2598c81f8b0SPeter Munch quadrature.size(), 2608c81f8b0SPeter Munch n_components_metric, 2618c81f8b0SPeter Munch weights.size(), 2628c81f8b0SPeter Munch strides.data(), 2638c81f8b0SPeter Munch &q_data_restriction); 2648c81f8b0SPeter Munch 2658c81f8b0SPeter Munch build_ctx_data.dim = dim; 2668c81f8b0SPeter Munch build_ctx_data.space_dim = dim; 2678c81f8b0SPeter Munch 2688c81f8b0SPeter Munch CeedQFunctionContextCreate(ceed, &build_ctx); 2698c81f8b0SPeter Munch CeedQFunctionContextSetData( 270*8efac696SJeremy L Thompson build_ctx, CEED_MEM_HOST, CEED_COPY_VALUES, sizeof(build_ctx_data), &build_ctx_data); 2718c81f8b0SPeter Munch 2728c81f8b0SPeter Munch // 5) create q operation 2738c81f8b0SPeter Munch if (bp == BPType::BP1) 2748c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_apply_mass, f_apply_mass_loc, &qf_apply); 2758c81f8b0SPeter Munch else if (bp == BPType::BP2) 2768c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_apply_mass_vec, f_apply_mass_vec_loc, &qf_apply); 2778c81f8b0SPeter Munch else if (bp == BPType::BP3 || bp == BPType::BP5) 2788c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_apply_poisson, f_apply_poisson_loc, &qf_apply); 2798c81f8b0SPeter Munch else if (bp == BPType::BP4 || bp == BPType::BP6) 2808c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_apply_poisson_vec, f_apply_poisson_vec_loc, &qf_apply); 2818c81f8b0SPeter Munch else 2828c81f8b0SPeter Munch AssertThrow(false, ExcInternalError()); 2838c81f8b0SPeter Munch 2848c81f8b0SPeter Munch if (bp <= BPType::BP2) 2858c81f8b0SPeter Munch CeedQFunctionAddInput(qf_apply, "u", n_components, CEED_EVAL_INTERP); 2868c81f8b0SPeter Munch else 2878c81f8b0SPeter Munch CeedQFunctionAddInput(qf_apply, "u", dim * n_components, CEED_EVAL_GRAD); 2888c81f8b0SPeter Munch 2898c81f8b0SPeter Munch CeedQFunctionAddInput(qf_apply, "qdata", n_components_metric, CEED_EVAL_NONE); 2908c81f8b0SPeter Munch 2918c81f8b0SPeter Munch if (bp <= BPType::BP2) 2928c81f8b0SPeter Munch CeedQFunctionAddOutput(qf_apply, "v", n_components, CEED_EVAL_INTERP); 2938c81f8b0SPeter Munch else 2948c81f8b0SPeter Munch CeedQFunctionAddOutput(qf_apply, "v", dim * n_components, CEED_EVAL_GRAD); 2958c81f8b0SPeter Munch 2968c81f8b0SPeter Munch CeedQFunctionSetContext(qf_apply, build_ctx); 2978c81f8b0SPeter Munch 2988c81f8b0SPeter Munch // 6) put everything together 2998c81f8b0SPeter Munch CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_apply); 3008c81f8b0SPeter Munch 3018c81f8b0SPeter Munch CeedOperatorSetField(op_apply, "u", sol_restriction, sol_basis, CEED_VECTOR_ACTIVE); 302fab7d8a4SJeremy L Thompson CeedOperatorSetField(op_apply, "qdata", q_data_restriction, CEED_BASIS_NONE, q_data); 3038c81f8b0SPeter Munch CeedOperatorSetField(op_apply, "v", sol_restriction, sol_basis, CEED_VECTOR_ACTIVE); 304*8efac696SJeremy L Thompson 305*8efac696SJeremy L Thompson // 7) cleanup 306*8efac696SJeremy L Thompson CeedVectorDestroy(&q_data); 307*8efac696SJeremy L Thompson CeedElemRestrictionDestroy(&q_data_restriction); 308*8efac696SJeremy L Thompson CeedElemRestrictionDestroy(&sol_restriction); 309*8efac696SJeremy L Thompson CeedBasisDestroy(&sol_basis); 310*8efac696SJeremy L Thompson CeedQFunctionContextDestroy(&build_ctx); 311*8efac696SJeremy L Thompson CeedQFunctionDestroy(&qf_apply); 3128c81f8b0SPeter Munch } 3138c81f8b0SPeter Munch 3148c81f8b0SPeter Munch /** 3158c81f8b0SPeter Munch * Perform matrix-vector product. 3168c81f8b0SPeter Munch */ 3178c81f8b0SPeter Munch void 3188c81f8b0SPeter Munch vmult(VectorType &dst, const VectorType &src) const override 3198c81f8b0SPeter Munch { 3208c81f8b0SPeter Munch // communicate: update ghost values 3218c81f8b0SPeter Munch src.update_ghost_values(); 3228c81f8b0SPeter Munch 3238c81f8b0SPeter Munch if (dof_handler.get_fe().n_components() == 1) 3248c81f8b0SPeter Munch { 3258c81f8b0SPeter Munch // create libCEED view on deal.II vectors 3268c81f8b0SPeter Munch VectorTypeCeed src_ceed(ceed, src); 3278c81f8b0SPeter Munch VectorTypeCeed dst_ceed(ceed, dst); 3288c81f8b0SPeter Munch 3298c81f8b0SPeter Munch // apply operator 3308c81f8b0SPeter Munch CeedOperatorApply(op_apply, src_ceed(), dst_ceed(), CEED_REQUEST_IMMEDIATE); 3318c81f8b0SPeter Munch } 3328c81f8b0SPeter Munch else // TODO: needed for multiple components 3338c81f8b0SPeter Munch { 3348c81f8b0SPeter Munch // allocate space for block vectors 3358c81f8b0SPeter Munch src_tmp.reinit(this->extended_local_size(), true); 3368c81f8b0SPeter Munch dst_tmp.reinit(this->extended_local_size(), true); 3378c81f8b0SPeter Munch 3388c81f8b0SPeter Munch copy_to_block_vector(src_tmp, src); // copy to block vector 3398c81f8b0SPeter Munch 3408c81f8b0SPeter Munch // create libCEED view on deal.II vectors 3418c81f8b0SPeter Munch VectorTypeCeed src_ceed(ceed, src_tmp); 3428c81f8b0SPeter Munch VectorTypeCeed dst_ceed(ceed, dst_tmp); 3438c81f8b0SPeter Munch 3448c81f8b0SPeter Munch // apply operator 3458c81f8b0SPeter Munch CeedOperatorApply(op_apply, src_ceed(), dst_ceed(), CEED_REQUEST_IMMEDIATE); 3468c81f8b0SPeter Munch 3478c81f8b0SPeter Munch dst_ceed.sync_to_host(); // pull libCEED data back to host 3488c81f8b0SPeter Munch copy_from_block_vector(dst, dst_tmp); // copy from block vector 3498c81f8b0SPeter Munch } 3508c81f8b0SPeter Munch 3518c81f8b0SPeter Munch // communicate: compress 3528c81f8b0SPeter Munch src.zero_out_ghost_values(); 3538c81f8b0SPeter Munch dst.compress(VectorOperation::add); 3548c81f8b0SPeter Munch 3558c81f8b0SPeter Munch // apply constraints: we assume homogeneous DBC 3568c81f8b0SPeter Munch constraints.set_zero(dst); 3578c81f8b0SPeter Munch } 3588c81f8b0SPeter Munch 3598c81f8b0SPeter Munch /** 3608c81f8b0SPeter Munch * Initialized vector. 3618c81f8b0SPeter Munch */ 3628c81f8b0SPeter Munch void 3638c81f8b0SPeter Munch initialize_dof_vector(VectorType &vec) const override 3648c81f8b0SPeter Munch { 3658c81f8b0SPeter Munch vec.reinit(partitioner); 3668c81f8b0SPeter Munch } 3678c81f8b0SPeter Munch 3688c81f8b0SPeter Munch /** 3698c81f8b0SPeter Munch * Compute inverse of diagonal. 3708c81f8b0SPeter Munch */ 3718c81f8b0SPeter Munch void 3728c81f8b0SPeter Munch compute_inverse_diagonal(VectorType &diagonal) const override 3738c81f8b0SPeter Munch { 3748c81f8b0SPeter Munch this->initialize_dof_vector(diagonal); 3758c81f8b0SPeter Munch 3768c81f8b0SPeter Munch VectorTypeCeed diagonal_ceed(ceed, diagonal); 3778c81f8b0SPeter Munch 3788c81f8b0SPeter Munch CeedOperatorLinearAssembleDiagonal(op_apply, diagonal_ceed(), CEED_REQUEST_IMMEDIATE); 3798c81f8b0SPeter Munch 3808c81f8b0SPeter Munch const unsigned int n_components = dof_handler.get_fe().n_components(); 3818c81f8b0SPeter Munch 3828c81f8b0SPeter Munch if (n_components > 1) // TODO: needed for multiple components 3838c81f8b0SPeter Munch { 3848c81f8b0SPeter Munch VectorType tmp(diagonal); 3858c81f8b0SPeter Munch 3868c81f8b0SPeter Munch copy_from_block_vector(tmp, diagonal); 3878c81f8b0SPeter Munch 3888c81f8b0SPeter Munch std::swap(tmp, diagonal); 3898c81f8b0SPeter Munch } 3908c81f8b0SPeter Munch 3918c81f8b0SPeter Munch diagonal.compress(VectorOperation::add); 3928c81f8b0SPeter Munch 3938c81f8b0SPeter Munch for (auto &i : diagonal) 3948c81f8b0SPeter Munch i = (std::abs(i) > 1.0e-10) ? (1.0 / i) : 1.0; 3958c81f8b0SPeter Munch } 3968c81f8b0SPeter Munch 3978c81f8b0SPeter Munch private: 3988c81f8b0SPeter Munch /** 3998c81f8b0SPeter Munch * Wrapper around a deal.II vector to create a libCEED vector view. 4008c81f8b0SPeter Munch */ 4018c81f8b0SPeter Munch class VectorTypeCeed 4028c81f8b0SPeter Munch { 4038c81f8b0SPeter Munch public: 4048c81f8b0SPeter Munch /** 4058c81f8b0SPeter Munch * Constructor. 4068c81f8b0SPeter Munch */ 4078c81f8b0SPeter Munch VectorTypeCeed(const Ceed &ceed, const VectorType &vec) 4088c81f8b0SPeter Munch { 4098c81f8b0SPeter Munch const unsigned int n_dofs = 4108c81f8b0SPeter Munch vec.get_partitioner()->locally_owned_size() + vec.get_partitioner()->n_ghost_indices(); 4118c81f8b0SPeter Munch 4128c81f8b0SPeter Munch CeedVectorCreate(ceed, n_dofs, &vec_ceed); 4138c81f8b0SPeter Munch CeedVectorSetArray(vec_ceed, CEED_MEM_HOST, CEED_USE_POINTER, vec.get_values()); 4148c81f8b0SPeter Munch } 4158c81f8b0SPeter Munch 4168c81f8b0SPeter Munch /** 4178c81f8b0SPeter Munch * Return libCEED vector view. 4188c81f8b0SPeter Munch */ 4198c81f8b0SPeter Munch CeedVector & 4208c81f8b0SPeter Munch operator()() 4218c81f8b0SPeter Munch { 4228c81f8b0SPeter Munch return vec_ceed; 4238c81f8b0SPeter Munch } 4248c81f8b0SPeter Munch 4258c81f8b0SPeter Munch /** 4268c81f8b0SPeter Munch * Sync memory from device to host. 4278c81f8b0SPeter Munch */ 4288c81f8b0SPeter Munch void 4298c81f8b0SPeter Munch sync_to_host() 4308c81f8b0SPeter Munch { 4318c81f8b0SPeter Munch CeedVectorSyncArray(vec_ceed, CEED_MEM_HOST); 4328c81f8b0SPeter Munch } 4338c81f8b0SPeter Munch 4348c81f8b0SPeter Munch /** 4358c81f8b0SPeter Munch * Destructor: destroy vector view. 4368c81f8b0SPeter Munch */ 4378c81f8b0SPeter Munch ~VectorTypeCeed() 4388c81f8b0SPeter Munch { 4398c81f8b0SPeter Munch CeedScalar *ptr; 4408c81f8b0SPeter Munch CeedVectorTakeArray(vec_ceed, CEED_MEM_HOST, &ptr); 4418c81f8b0SPeter Munch CeedVectorDestroy(&vec_ceed); 4428c81f8b0SPeter Munch } 4438c81f8b0SPeter Munch 4448c81f8b0SPeter Munch private: 4458c81f8b0SPeter Munch /** 4468c81f8b0SPeter Munch * libCEED vector view. 4478c81f8b0SPeter Munch */ 4488c81f8b0SPeter Munch CeedVector vec_ceed; 4498c81f8b0SPeter Munch }; 4508c81f8b0SPeter Munch 4518c81f8b0SPeter Munch /** 4528c81f8b0SPeter Munch * Copy from block vector. 4538c81f8b0SPeter Munch * 4548c81f8b0SPeter Munch * @note Only needed for multiple components. 4558c81f8b0SPeter Munch */ 4568c81f8b0SPeter Munch void 4578c81f8b0SPeter Munch copy_from_block_vector(VectorType &dst, const VectorType &src) const 4588c81f8b0SPeter Munch { 4598c81f8b0SPeter Munch const unsigned int scalar_size = this->extended_local_size() / dim; 4608c81f8b0SPeter Munch 4618c81f8b0SPeter Munch for (unsigned int i = 0; i < scalar_size; ++i) 4628c81f8b0SPeter Munch for (unsigned int j = 0; j < dim; ++j) 4638c81f8b0SPeter Munch dst.get_values()[j + i * dim] = src.get_values()[j * scalar_size + i]; 4648c81f8b0SPeter Munch } 4658c81f8b0SPeter Munch 4668c81f8b0SPeter Munch /** 4678c81f8b0SPeter Munch * Copy to block vector. 4688c81f8b0SPeter Munch * 4698c81f8b0SPeter Munch * @note Only needed for multiple components. 4708c81f8b0SPeter Munch */ 4718c81f8b0SPeter Munch void 4728c81f8b0SPeter Munch copy_to_block_vector(VectorType &dst, const VectorType &src) const 4738c81f8b0SPeter Munch { 4748c81f8b0SPeter Munch const unsigned int scalar_size = this->extended_local_size() / dim; 4758c81f8b0SPeter Munch 4768c81f8b0SPeter Munch for (unsigned int i = 0; i < scalar_size; ++i) 4778c81f8b0SPeter Munch for (unsigned int j = 0; j < dim; ++j) 4788c81f8b0SPeter Munch dst.get_values()[j * scalar_size + i] = src.get_values()[j + i * dim]; 4798c81f8b0SPeter Munch } 4808c81f8b0SPeter Munch 4818c81f8b0SPeter Munch /** 4828c81f8b0SPeter Munch * Number of locally active DoFs. 4838c81f8b0SPeter Munch */ 4848c81f8b0SPeter Munch unsigned int 4858c81f8b0SPeter Munch extended_local_size() const 4868c81f8b0SPeter Munch { 4878c81f8b0SPeter Munch return partitioner->locally_owned_size() + partitioner->n_ghost_indices(); 4888c81f8b0SPeter Munch } 4898c81f8b0SPeter Munch 4908c81f8b0SPeter Munch /** 4918c81f8b0SPeter Munch * Compute metric data: Jacobian, ... 4928c81f8b0SPeter Munch */ 4938c81f8b0SPeter Munch static std::vector<double> 4948c81f8b0SPeter Munch compute_metric_data(const Ceed &ceed, 4958c81f8b0SPeter Munch const Mapping<dim> &mapping, 4968c81f8b0SPeter Munch const Triangulation<dim> &tria, 4978c81f8b0SPeter Munch const Quadrature<dim> &quadrature, 4988c81f8b0SPeter Munch const BPType bp) 4998c81f8b0SPeter Munch { 5008c81f8b0SPeter Munch std::vector<double> weights; 5018c81f8b0SPeter Munch 5028c81f8b0SPeter Munch if (false) 5038c81f8b0SPeter Munch { 5048c81f8b0SPeter Munch FE_Nothing<dim> dummy_fe; 5058c81f8b0SPeter Munch FEValues<dim> fe_values(mapping, dummy_fe, quadrature, update_JxW_values); 5068c81f8b0SPeter Munch 5078c81f8b0SPeter Munch for (const auto &cell : tria.active_cell_iterators()) 5088c81f8b0SPeter Munch if (cell->is_locally_owned()) 5098c81f8b0SPeter Munch { 5108c81f8b0SPeter Munch fe_values.reinit(cell); 5118c81f8b0SPeter Munch 5128c81f8b0SPeter Munch for (const auto q : fe_values.quadrature_point_indices()) 5138c81f8b0SPeter Munch weights.emplace_back(fe_values.JxW(q)); 5148c81f8b0SPeter Munch } 5158c81f8b0SPeter Munch 5168c81f8b0SPeter Munch return weights; 5178c81f8b0SPeter Munch } 5188c81f8b0SPeter Munch 5198c81f8b0SPeter Munch CeedBasis geo_basis; 5208c81f8b0SPeter Munch CeedVector q_data; 5218c81f8b0SPeter Munch CeedElemRestriction q_data_restriction; 5228c81f8b0SPeter Munch CeedVector node_coords; 5238c81f8b0SPeter Munch CeedElemRestriction geo_restriction; 5248c81f8b0SPeter Munch CeedQFunctionContext build_ctx; 5258c81f8b0SPeter Munch CeedQFunction qf_build; 5268c81f8b0SPeter Munch CeedOperator op_build; 5278c81f8b0SPeter Munch 5288c81f8b0SPeter Munch const unsigned int n_q_points = quadrature.get_tensor_basis()[0].size(); 5298c81f8b0SPeter Munch 5308c81f8b0SPeter Munch const unsigned int n_components = (bp <= BPType::BP2) ? 1 : (dim * (dim + 1) / 2); 5318c81f8b0SPeter Munch 5328c81f8b0SPeter Munch const auto mapping_q = dynamic_cast<const MappingQ<dim> *>(&mapping); 5338c81f8b0SPeter Munch 5348c81f8b0SPeter Munch AssertThrow(mapping_q, ExcMessage("Wrong mapping!")); 5358c81f8b0SPeter Munch 5368c81f8b0SPeter Munch const unsigned int fe_degree = mapping_q->get_degree(); 5378c81f8b0SPeter Munch 5388c81f8b0SPeter Munch CeedBasisCreateTensorH1Lagrange( 5398c81f8b0SPeter Munch ceed, dim, dim, fe_degree + 1, n_q_points, CEED_GAUSS, &geo_basis); 5408c81f8b0SPeter Munch 5418c81f8b0SPeter Munch unsigned int n_local_active_cells = 0; 5428c81f8b0SPeter Munch 5438c81f8b0SPeter Munch for (const auto &cell : tria.active_cell_iterators()) 5448c81f8b0SPeter Munch if (cell->is_locally_owned()) 5458c81f8b0SPeter Munch n_local_active_cells++; 5468c81f8b0SPeter Munch 5478c81f8b0SPeter Munch std::vector<double> geo_support_points; 5488c81f8b0SPeter Munch std::vector<CeedInt> geo_indices; 5498c81f8b0SPeter Munch 5508c81f8b0SPeter Munch FE_Q<dim> geo_fe(fe_degree); 5518c81f8b0SPeter Munch 5528c81f8b0SPeter Munch DoFHandler<dim> geo_dof_handler(tria); 5538c81f8b0SPeter Munch geo_dof_handler.distribute_dofs(geo_fe); 5548c81f8b0SPeter Munch 5558c81f8b0SPeter Munch const auto geo_partitioner = 5568c81f8b0SPeter Munch std::make_shared<Utilities::MPI::Partitioner>(geo_dof_handler.locally_owned_dofs(), 5578c81f8b0SPeter Munch DoFTools::extract_locally_active_dofs( 5588c81f8b0SPeter Munch geo_dof_handler), 5598c81f8b0SPeter Munch geo_dof_handler.get_communicator()); 5608c81f8b0SPeter Munch 5618c81f8b0SPeter Munch geo_indices.reserve(n_local_active_cells * geo_fe.n_dofs_per_cell()); 5628c81f8b0SPeter Munch 5638c81f8b0SPeter Munch const auto dof_mapping = FETools::lexicographic_to_hierarchic_numbering<dim>(fe_degree); 5648c81f8b0SPeter Munch 5658c81f8b0SPeter Munch FEValues<dim> fe_values(mapping, 5668c81f8b0SPeter Munch geo_fe, 5678c81f8b0SPeter Munch geo_fe.get_unit_support_points(), 5688c81f8b0SPeter Munch update_quadrature_points); 5698c81f8b0SPeter Munch 5708c81f8b0SPeter Munch std::vector<types::global_dof_index> local_indices(geo_fe.n_dofs_per_cell()); 5718c81f8b0SPeter Munch 5728c81f8b0SPeter Munch const unsigned int n_points = 5738c81f8b0SPeter Munch geo_partitioner->locally_owned_size() + geo_partitioner->n_ghost_indices(); 5748c81f8b0SPeter Munch 5758c81f8b0SPeter Munch geo_support_points.resize(dim * n_points); 5768c81f8b0SPeter Munch 5778c81f8b0SPeter Munch for (const auto &cell : geo_dof_handler.active_cell_iterators()) 5788c81f8b0SPeter Munch if (cell->is_locally_owned()) 5798c81f8b0SPeter Munch { 5808c81f8b0SPeter Munch fe_values.reinit(cell); 5818c81f8b0SPeter Munch cell->get_dof_indices(local_indices); 5828c81f8b0SPeter Munch 5838c81f8b0SPeter Munch for (const auto i : dof_mapping) 5848c81f8b0SPeter Munch { 5858c81f8b0SPeter Munch const auto index = geo_partitioner->global_to_local(local_indices[i]); 5868c81f8b0SPeter Munch geo_indices.emplace_back(index); 5878c81f8b0SPeter Munch 5888c81f8b0SPeter Munch const auto point = fe_values.quadrature_point(i); 5898c81f8b0SPeter Munch 5908c81f8b0SPeter Munch for (unsigned int d = 0; d < dim; ++d) 5918c81f8b0SPeter Munch geo_support_points[index + d * n_points] = point[d]; 5928c81f8b0SPeter Munch } 5938c81f8b0SPeter Munch } 5948c81f8b0SPeter Munch 5958c81f8b0SPeter Munch weights.resize(n_local_active_cells * quadrature.size() * n_components); 5968c81f8b0SPeter Munch 5978c81f8b0SPeter Munch CeedInt strides[3] = {1, 5988c81f8b0SPeter Munch static_cast<int>(quadrature.size()), 5998c81f8b0SPeter Munch static_cast<int>(quadrature.size() * n_components)}; 6008c81f8b0SPeter Munch 6018c81f8b0SPeter Munch CeedVectorCreate(ceed, weights.size(), &q_data); 6028c81f8b0SPeter Munch CeedVectorSetArray(q_data, CEED_MEM_HOST, CEED_USE_POINTER, weights.data()); 6038c81f8b0SPeter Munch CeedElemRestrictionCreateStrided(ceed, 6048c81f8b0SPeter Munch n_local_active_cells, 6058c81f8b0SPeter Munch quadrature.size(), 6068c81f8b0SPeter Munch n_components, 6078c81f8b0SPeter Munch weights.size(), 6088c81f8b0SPeter Munch strides, 6098c81f8b0SPeter Munch &q_data_restriction); 6108c81f8b0SPeter Munch 6118c81f8b0SPeter Munch CeedVectorCreate(ceed, geo_support_points.size(), &node_coords); 6128c81f8b0SPeter Munch CeedVectorSetArray(node_coords, CEED_MEM_HOST, CEED_USE_POINTER, geo_support_points.data()); 6138c81f8b0SPeter Munch 6148c81f8b0SPeter Munch CeedElemRestrictionCreate(ceed, 6158c81f8b0SPeter Munch n_local_active_cells, 6168c81f8b0SPeter Munch geo_fe.n_dofs_per_cell(), 6178c81f8b0SPeter Munch dim, 6188c81f8b0SPeter Munch std::max<unsigned int>(geo_support_points.size() / dim, 1), 6198c81f8b0SPeter Munch geo_support_points.size(), 6208c81f8b0SPeter Munch CEED_MEM_HOST, 6218c81f8b0SPeter Munch CEED_COPY_VALUES, 6228c81f8b0SPeter Munch geo_indices.data(), 6238c81f8b0SPeter Munch &geo_restriction); 6248c81f8b0SPeter Munch 6258c81f8b0SPeter Munch BuildContext build_ctx_data; 6268c81f8b0SPeter Munch build_ctx_data.dim = dim; 6278c81f8b0SPeter Munch build_ctx_data.space_dim = dim; 6288c81f8b0SPeter Munch 6298c81f8b0SPeter Munch CeedQFunctionContextCreate(ceed, &build_ctx); 6308c81f8b0SPeter Munch CeedQFunctionContextSetData( 6318c81f8b0SPeter Munch build_ctx, CEED_MEM_HOST, CEED_USE_POINTER, sizeof(build_ctx_data), &build_ctx_data); 6328c81f8b0SPeter Munch 6338c81f8b0SPeter Munch // 5) create q operation 6348c81f8b0SPeter Munch if (bp <= BPType::BP2) 6358c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_build_mass, f_build_mass_loc, &qf_build); 6368c81f8b0SPeter Munch else 6378c81f8b0SPeter Munch CeedQFunctionCreateInterior(ceed, 1, f_build_poisson, f_build_poisson_loc, &qf_build); 6388c81f8b0SPeter Munch 6398c81f8b0SPeter Munch CeedQFunctionAddInput(qf_build, "geo", dim * dim, CEED_EVAL_GRAD); 6408c81f8b0SPeter Munch CeedQFunctionAddInput(qf_build, "weights", 1, CEED_EVAL_WEIGHT); 6418c81f8b0SPeter Munch CeedQFunctionAddOutput(qf_build, "qdata", n_components, CEED_EVAL_NONE); 6428c81f8b0SPeter Munch CeedQFunctionSetContext(qf_build, build_ctx); 6438c81f8b0SPeter Munch 6448c81f8b0SPeter Munch // 6) put everything together 6458c81f8b0SPeter Munch CeedOperatorCreate(ceed, qf_build, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_build); 6468c81f8b0SPeter Munch CeedOperatorSetField(op_build, "geo", geo_restriction, geo_basis, CEED_VECTOR_ACTIVE); 6478c81f8b0SPeter Munch CeedOperatorSetField( 6488c81f8b0SPeter Munch op_build, "weights", CEED_ELEMRESTRICTION_NONE, geo_basis, CEED_VECTOR_NONE); 6498c81f8b0SPeter Munch CeedOperatorSetField( 650fab7d8a4SJeremy L Thompson op_build, "qdata", q_data_restriction, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE); 6518c81f8b0SPeter Munch 6528c81f8b0SPeter Munch CeedOperatorApply(op_build, node_coords, q_data, CEED_REQUEST_IMMEDIATE); 6538c81f8b0SPeter Munch 6548c81f8b0SPeter Munch CeedVectorDestroy(&node_coords); 6558c81f8b0SPeter Munch CeedVectorSyncArray(q_data, CEED_MEM_HOST); 6568c81f8b0SPeter Munch CeedVectorDestroy(&q_data); 65770dc8078SJeremy L Thompson CeedElemRestrictionDestroy(&geo_restriction); 65870dc8078SJeremy L Thompson CeedElemRestrictionDestroy(&q_data_restriction); 6598c81f8b0SPeter Munch CeedBasisDestroy(&geo_basis); 66070dc8078SJeremy L Thompson CeedQFunctionContextDestroy(&build_ctx); 66170dc8078SJeremy L Thompson CeedQFunctionDestroy(&qf_build); 66270dc8078SJeremy L Thompson CeedOperatorDestroy(&op_build); 6638c81f8b0SPeter Munch 6648c81f8b0SPeter Munch return weights; 6658c81f8b0SPeter Munch } 6668c81f8b0SPeter Munch 6678c81f8b0SPeter Munch /** 6688c81f8b0SPeter Munch * Mapping object passed to the constructor. 6698c81f8b0SPeter Munch */ 6708c81f8b0SPeter Munch const Mapping<dim> &mapping; 6718c81f8b0SPeter Munch 6728c81f8b0SPeter Munch /** 6738c81f8b0SPeter Munch * DoFHandler object passed to the constructor. 6748c81f8b0SPeter Munch */ 6758c81f8b0SPeter Munch const DoFHandler<dim> &dof_handler; 6768c81f8b0SPeter Munch 6778c81f8b0SPeter Munch /** 6788c81f8b0SPeter Munch * Constraints object passed to the constructor. 6798c81f8b0SPeter Munch */ 6808c81f8b0SPeter Munch const AffineConstraints<Number> &constraints; 6818c81f8b0SPeter Munch 6828c81f8b0SPeter Munch /** 6838c81f8b0SPeter Munch * Quadrature rule object passed to the constructor. 6848c81f8b0SPeter Munch */ 6858c81f8b0SPeter Munch const Quadrature<dim> &quadrature; 6868c81f8b0SPeter Munch 6878c81f8b0SPeter Munch /** 6888c81f8b0SPeter Munch * Selected BP. 6898c81f8b0SPeter Munch */ 6908c81f8b0SPeter Munch const BPType bp; 6918c81f8b0SPeter Munch 6928c81f8b0SPeter Munch /** 6938c81f8b0SPeter Munch * Resource name. 6948c81f8b0SPeter Munch */ 6958c81f8b0SPeter Munch const std::string resource; 6968c81f8b0SPeter Munch 6978c81f8b0SPeter Munch /** 6988c81f8b0SPeter Munch * Partitioner for distributed vectors. 6998c81f8b0SPeter Munch */ 7008c81f8b0SPeter Munch std::shared_ptr<Utilities::MPI::Partitioner> partitioner; 7018c81f8b0SPeter Munch 7028c81f8b0SPeter Munch /** 7038c81f8b0SPeter Munch * libCEED data structures. 7048c81f8b0SPeter Munch */ 7058c81f8b0SPeter Munch Ceed ceed; 7068c81f8b0SPeter Munch std::vector<double> weights; 7078c81f8b0SPeter Munch std::array<CeedInt, 3> strides; 7088c81f8b0SPeter Munch CeedOperator op_apply; 7098c81f8b0SPeter Munch 7108c81f8b0SPeter Munch /** 7118c81f8b0SPeter Munch * Temporal (tempral) vectors. 7128c81f8b0SPeter Munch * 7138c81f8b0SPeter Munch * @note Only needed for multiple components. 7148c81f8b0SPeter Munch */ 7158c81f8b0SPeter Munch mutable VectorType src_tmp; 7168c81f8b0SPeter Munch mutable VectorType dst_tmp; 7178c81f8b0SPeter Munch }; 7188c81f8b0SPeter Munch 7198c81f8b0SPeter Munch 7208c81f8b0SPeter Munch 7218c81f8b0SPeter Munch template <int dim, typename Number> 7228c81f8b0SPeter Munch class OperatorDealii : public OperatorBase<Number> 7238c81f8b0SPeter Munch { 7248c81f8b0SPeter Munch public: 7258c81f8b0SPeter Munch using VectorType = typename OperatorBase<Number>::VectorType; 7268c81f8b0SPeter Munch 7278c81f8b0SPeter Munch /** 7288c81f8b0SPeter Munch * Constructor. 7298c81f8b0SPeter Munch */ 7308c81f8b0SPeter Munch OperatorDealii(const Mapping<dim> &mapping, 7318c81f8b0SPeter Munch const DoFHandler<dim> &dof_handler, 7328c81f8b0SPeter Munch const AffineConstraints<Number> &constraints, 7338c81f8b0SPeter Munch const Quadrature<dim> &quadrature, 7348c81f8b0SPeter Munch const BPType &bp) 7358c81f8b0SPeter Munch : mapping(mapping) 7368c81f8b0SPeter Munch , dof_handler(dof_handler) 7378c81f8b0SPeter Munch , constraints(constraints) 7388c81f8b0SPeter Munch , quadrature(quadrature) 7398c81f8b0SPeter Munch , bp(bp) 7408c81f8b0SPeter Munch { 7418c81f8b0SPeter Munch reinit(); 7428c81f8b0SPeter Munch } 7438c81f8b0SPeter Munch 7448c81f8b0SPeter Munch /** 7458c81f8b0SPeter Munch * Destructor. 7468c81f8b0SPeter Munch */ 7478c81f8b0SPeter Munch ~OperatorDealii() = default; 7488c81f8b0SPeter Munch 7498c81f8b0SPeter Munch /** 7508c81f8b0SPeter Munch * Initialized internal data structures, particularly, MatrixFree. 7518c81f8b0SPeter Munch */ 7528c81f8b0SPeter Munch void 7538c81f8b0SPeter Munch reinit() override 7548c81f8b0SPeter Munch { 7558c81f8b0SPeter Munch // configure MatrixFree 7568c81f8b0SPeter Munch typename MatrixFree<dim, Number>::AdditionalData additional_data; 7578c81f8b0SPeter Munch additional_data.tasks_parallel_scheme = 7588c81f8b0SPeter Munch MatrixFree<dim, Number>::AdditionalData::TasksParallelScheme::none; 7598c81f8b0SPeter Munch 7608c81f8b0SPeter Munch // create MatrixFree 7618c81f8b0SPeter Munch matrix_free.reinit(mapping, dof_handler, constraints, quadrature, additional_data); 7628c81f8b0SPeter Munch } 7638c81f8b0SPeter Munch 7648c81f8b0SPeter Munch /** 7658c81f8b0SPeter Munch * Matrix-vector product. 7668c81f8b0SPeter Munch */ 7678c81f8b0SPeter Munch void 7688c81f8b0SPeter Munch vmult(VectorType &dst, const VectorType &src) const override 7698c81f8b0SPeter Munch { 7708c81f8b0SPeter Munch if (dof_handler.get_fe().n_components() == 1) 7718c81f8b0SPeter Munch { 7728c81f8b0SPeter Munch matrix_free.cell_loop(&OperatorDealii::do_cell_integral_range<1>, this, dst, src, true); 7738c81f8b0SPeter Munch } 7748c81f8b0SPeter Munch else 7758c81f8b0SPeter Munch { 7768c81f8b0SPeter Munch AssertThrow(dof_handler.get_fe().n_components() == dim, ExcInternalError()); 7778c81f8b0SPeter Munch 7788c81f8b0SPeter Munch matrix_free.cell_loop(&OperatorDealii::do_cell_integral_range<dim>, this, dst, src, true); 7798c81f8b0SPeter Munch } 7808c81f8b0SPeter Munch } 7818c81f8b0SPeter Munch 7828c81f8b0SPeter Munch /** 7838c81f8b0SPeter Munch * Initialize vector. 7848c81f8b0SPeter Munch */ 7858c81f8b0SPeter Munch void 7868c81f8b0SPeter Munch initialize_dof_vector(VectorType &vec) const override 7878c81f8b0SPeter Munch { 7888c81f8b0SPeter Munch matrix_free.initialize_dof_vector(vec); 7898c81f8b0SPeter Munch } 7908c81f8b0SPeter Munch 7918c81f8b0SPeter Munch /** 7928c81f8b0SPeter Munch * Compute inverse of diagonal. 7938c81f8b0SPeter Munch */ 7948c81f8b0SPeter Munch void 7958c81f8b0SPeter Munch compute_inverse_diagonal(VectorType &diagonal) const override 7968c81f8b0SPeter Munch { 7978c81f8b0SPeter Munch this->initialize_dof_vector(diagonal); 7988c81f8b0SPeter Munch 7998c81f8b0SPeter Munch if (dof_handler.get_fe().n_components() == 1) 8008c81f8b0SPeter Munch { 8018c81f8b0SPeter Munch MatrixFreeTools::compute_diagonal(matrix_free, 8028c81f8b0SPeter Munch diagonal, 8038c81f8b0SPeter Munch &OperatorDealii::do_cell_integral_local<1>, 8048c81f8b0SPeter Munch this); 8058c81f8b0SPeter Munch } 8068c81f8b0SPeter Munch else 8078c81f8b0SPeter Munch { 8088c81f8b0SPeter Munch AssertThrow(dof_handler.get_fe().n_components() == dim, ExcInternalError()); 8098c81f8b0SPeter Munch 8108c81f8b0SPeter Munch MatrixFreeTools::compute_diagonal(matrix_free, 8118c81f8b0SPeter Munch diagonal, 8128c81f8b0SPeter Munch &OperatorDealii::do_cell_integral_local<dim>, 8138c81f8b0SPeter Munch this); 8148c81f8b0SPeter Munch } 8158c81f8b0SPeter Munch 8168c81f8b0SPeter Munch for (auto &i : diagonal) 8178c81f8b0SPeter Munch i = (std::abs(i) > 1.0e-10) ? (1.0 / i) : 1.0; 8188c81f8b0SPeter Munch } 8198c81f8b0SPeter Munch 8208c81f8b0SPeter Munch private: 8218c81f8b0SPeter Munch /** 8228c81f8b0SPeter Munch * Cell integral without vector access. 8238c81f8b0SPeter Munch */ 8248c81f8b0SPeter Munch template <int n_components> 8258c81f8b0SPeter Munch void 8268c81f8b0SPeter Munch do_cell_integral_local(FEEvaluation<dim, -1, 0, n_components, Number> &phi) const 8278c81f8b0SPeter Munch { 8288c81f8b0SPeter Munch if (bp <= BPType::BP2) // mass matrix 8298c81f8b0SPeter Munch { 8308c81f8b0SPeter Munch phi.evaluate(EvaluationFlags::values); 8318c81f8b0SPeter Munch for (const auto q : phi.quadrature_point_indices()) 8328c81f8b0SPeter Munch phi.submit_value(phi.get_value(q), q); 8338c81f8b0SPeter Munch phi.integrate(EvaluationFlags::values); 8348c81f8b0SPeter Munch } 8358c81f8b0SPeter Munch else // Poisson operator 8368c81f8b0SPeter Munch { 8378c81f8b0SPeter Munch phi.evaluate(EvaluationFlags::gradients); 8388c81f8b0SPeter Munch for (const auto q : phi.quadrature_point_indices()) 8398c81f8b0SPeter Munch phi.submit_gradient(phi.get_gradient(q), q); 8408c81f8b0SPeter Munch phi.integrate(EvaluationFlags::gradients); 8418c81f8b0SPeter Munch } 8428c81f8b0SPeter Munch } 8438c81f8b0SPeter Munch 8448c81f8b0SPeter Munch /** 8458c81f8b0SPeter Munch * Cell integral on a range of cells. 8468c81f8b0SPeter Munch */ 8478c81f8b0SPeter Munch template <int n_components> 8488c81f8b0SPeter Munch void 8498c81f8b0SPeter Munch do_cell_integral_range(const MatrixFree<dim, Number> &matrix_free, 8508c81f8b0SPeter Munch VectorType &dst, 8518c81f8b0SPeter Munch const VectorType &src, 8528c81f8b0SPeter Munch const std::pair<unsigned int, unsigned int> &range) const 8538c81f8b0SPeter Munch { 8548c81f8b0SPeter Munch FEEvaluation<dim, -1, 0, n_components, Number> phi(matrix_free, range); 8558c81f8b0SPeter Munch 8568c81f8b0SPeter Munch for (unsigned cell = range.first; cell < range.second; ++cell) 8578c81f8b0SPeter Munch { 8588c81f8b0SPeter Munch phi.reinit(cell); 8598c81f8b0SPeter Munch phi.read_dof_values(src); // read source vector 8608c81f8b0SPeter Munch do_cell_integral_local(phi); // cell integral 8618c81f8b0SPeter Munch phi.distribute_local_to_global(dst); // write to destination vector 8628c81f8b0SPeter Munch } 8638c81f8b0SPeter Munch } 8648c81f8b0SPeter Munch 8658c81f8b0SPeter Munch /** 8668c81f8b0SPeter Munch * Mapping object passed to the constructor. 8678c81f8b0SPeter Munch */ 8688c81f8b0SPeter Munch const Mapping<dim> &mapping; 8698c81f8b0SPeter Munch 8708c81f8b0SPeter Munch /** 8718c81f8b0SPeter Munch * DoFHandler object passed to the constructor. 8728c81f8b0SPeter Munch */ 8738c81f8b0SPeter Munch const DoFHandler<dim> &dof_handler; 8748c81f8b0SPeter Munch 8758c81f8b0SPeter Munch /** 8768c81f8b0SPeter Munch * Constraints object passed to the constructor. 8778c81f8b0SPeter Munch */ 8788c81f8b0SPeter Munch const AffineConstraints<Number> &constraints; 8798c81f8b0SPeter Munch 8808c81f8b0SPeter Munch /** 8818c81f8b0SPeter Munch * Quadrature rule object passed to the constructor. 8828c81f8b0SPeter Munch */ 8838c81f8b0SPeter Munch const Quadrature<dim> &quadrature; 8848c81f8b0SPeter Munch 8858c81f8b0SPeter Munch /** 8868c81f8b0SPeter Munch * Selected BP. 8878c81f8b0SPeter Munch */ 8888c81f8b0SPeter Munch const BPType bp; 8898c81f8b0SPeter Munch 8908c81f8b0SPeter Munch /** 8918c81f8b0SPeter Munch * MatrixFree object. 8928c81f8b0SPeter Munch */ 8938c81f8b0SPeter Munch MatrixFree<dim, Number> matrix_free; 8948c81f8b0SPeter Munch }; 895