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