1*d416dc2bSJeremy L Thompson // ---------------------------------------------------------------------
2*d416dc2bSJeremy L Thompson //
3*d416dc2bSJeremy L Thompson // Copyright (C) 2023 by the deal.II authors
4*d416dc2bSJeremy L Thompson //
5*d416dc2bSJeremy L Thompson // This file is part of the deal.II library.
6*d416dc2bSJeremy L Thompson //
7*d416dc2bSJeremy L Thompson // The deal.II library is free software; you can use it, redistribute
8*d416dc2bSJeremy L Thompson // it, and/or modify it under the terms of the GNU Lesser General
9*d416dc2bSJeremy L Thompson // Public License as published by the Free Software Foundation; either
10*d416dc2bSJeremy L Thompson // version 2.1 of the License, or (at your option) any later version.
11*d416dc2bSJeremy L Thompson // The full text of the license can be found in the file LICENSE.md at
12*d416dc2bSJeremy L Thompson // the top level directory of deal.II.
13*d416dc2bSJeremy L Thompson //
14*d416dc2bSJeremy L Thompson // Authors: Peter Munch, Martin Kronbichler
15*d416dc2bSJeremy L Thompson //
16*d416dc2bSJeremy L Thompson // ---------------------------------------------------------------------
17*d416dc2bSJeremy L Thompson
18*d416dc2bSJeremy L Thompson // deal.II includes
19*d416dc2bSJeremy L Thompson #include <deal.II/base/conditional_ostream.h>
20*d416dc2bSJeremy L Thompson #include <deal.II/base/mpi.h>
21*d416dc2bSJeremy L Thompson #include <deal.II/base/parameter_handler.h>
22*d416dc2bSJeremy L Thompson #include <deal.II/base/quadrature_lib.h>
23*d416dc2bSJeremy L Thompson
24*d416dc2bSJeremy L Thompson #include <deal.II/distributed/shared_tria.h>
25*d416dc2bSJeremy L Thompson #include <deal.II/distributed/tria.h>
26*d416dc2bSJeremy L Thompson
27*d416dc2bSJeremy L Thompson #include <deal.II/dofs/dof_handler.h>
28*d416dc2bSJeremy L Thompson #include <deal.II/dofs/dof_renumbering.h>
29*d416dc2bSJeremy L Thompson
30*d416dc2bSJeremy L Thompson #include <deal.II/fe/fe_nothing.h>
31*d416dc2bSJeremy L Thompson #include <deal.II/fe/fe_q.h>
32*d416dc2bSJeremy L Thompson #include <deal.II/fe/fe_system.h>
33*d416dc2bSJeremy L Thompson #include <deal.II/fe/fe_tools.h>
34*d416dc2bSJeremy L Thompson #include <deal.II/fe/fe_values.h>
35*d416dc2bSJeremy L Thompson #include <deal.II/fe/mapping_q1.h>
36*d416dc2bSJeremy L Thompson
37*d416dc2bSJeremy L Thompson #include <deal.II/grid/grid_generator.h>
38*d416dc2bSJeremy L Thompson
39*d416dc2bSJeremy L Thompson #include <deal.II/lac/affine_constraints.h>
40*d416dc2bSJeremy L Thompson #include <deal.II/lac/precondition.h>
41*d416dc2bSJeremy L Thompson #include <deal.II/lac/solver_cg.h>
42*d416dc2bSJeremy L Thompson
43*d416dc2bSJeremy L Thompson // boost
44*d416dc2bSJeremy L Thompson #include <boost/algorithm/string.hpp>
45*d416dc2bSJeremy L Thompson
46*d416dc2bSJeremy L Thompson #include <sstream>
47*d416dc2bSJeremy L Thompson
48*d416dc2bSJeremy L Thompson // include operators
49*d416dc2bSJeremy L Thompson #include "bps-ceed.h"
50*d416dc2bSJeremy L Thompson #include "bps-kokkos.h"
51*d416dc2bSJeremy L Thompson
52*d416dc2bSJeremy L Thompson // Test cases
53*d416dc2bSJeremy L Thompson //TESTARGS(name="BP1") --resource {ceed_resource} --bp BP1 --fe_degree 2 --print_timings 0
54*d416dc2bSJeremy L Thompson //TESTARGS(name="BP4") --resource {ceed_resource} --bp BP4 --fe_degree 1 --print_timings 0
55*d416dc2bSJeremy L Thompson
56*d416dc2bSJeremy L Thompson /**
57*d416dc2bSJeremy L Thompson * Relevant parameters.
58*d416dc2bSJeremy L Thompson */
59*d416dc2bSJeremy L Thompson struct Parameters
60*d416dc2bSJeremy L Thompson {
61*d416dc2bSJeremy L Thompson BPType bp = BPType::BP5;
62*d416dc2bSJeremy L Thompson unsigned int n_global_refinements = 1;
63*d416dc2bSJeremy L Thompson unsigned int fe_degree = 2;
64*d416dc2bSJeremy L Thompson bool print_timings = true;
65*d416dc2bSJeremy L Thompson std::string libCEED_resource = "/cpu/self";
66*d416dc2bSJeremy L Thompson
67*d416dc2bSJeremy L Thompson bool
parseParameters68*d416dc2bSJeremy L Thompson parse(int argc, char *argv[])
69*d416dc2bSJeremy L Thompson {
70*d416dc2bSJeremy L Thompson if (argc == 1 && (std::string(argv[0]) == "--help"))
71*d416dc2bSJeremy L Thompson {
72*d416dc2bSJeremy L Thompson std::cout << "Usage: ./bp [OPTION]..." << std::endl;
73*d416dc2bSJeremy L Thompson std::cout << std::endl;
74*d416dc2bSJeremy L Thompson std::cout << "--bp name of benchmark (BP1-BP6)" << std::endl;
75*d416dc2bSJeremy L Thompson std::cout << "--n_refinements number of refinements (0-)" << std::endl;
76*d416dc2bSJeremy L Thompson std::cout << "--fe_degree polynomial degree (1-)" << std::endl;
77*d416dc2bSJeremy L Thompson std::cout << "--print_timings name of benchmark (0, 1)" << std::endl;
78*d416dc2bSJeremy L Thompson std::cout << "--resource name of resource (e.g., /cpu/self/avx/blocked)" << std::endl;
79*d416dc2bSJeremy L Thompson
80*d416dc2bSJeremy L Thompson return true;
81*d416dc2bSJeremy L Thompson }
82*d416dc2bSJeremy L Thompson
83*d416dc2bSJeremy L Thompson AssertThrow(argc % 2 == 0, ExcInternalError());
84*d416dc2bSJeremy L Thompson
85*d416dc2bSJeremy L Thompson while (argc > 0)
86*d416dc2bSJeremy L Thompson {
87*d416dc2bSJeremy L Thompson std::string label(argv[0]);
88*d416dc2bSJeremy L Thompson
89*d416dc2bSJeremy L Thompson if ("--bp" == label)
90*d416dc2bSJeremy L Thompson {
91*d416dc2bSJeremy L Thompson std::string bp_string(argv[1]);
92*d416dc2bSJeremy L Thompson
93*d416dc2bSJeremy L Thompson if (bp_string == "BP1")
94*d416dc2bSJeremy L Thompson bp = BPType::BP1;
95*d416dc2bSJeremy L Thompson else if (bp_string == "BP2")
96*d416dc2bSJeremy L Thompson bp = BPType::BP2;
97*d416dc2bSJeremy L Thompson else if (bp_string == "BP3")
98*d416dc2bSJeremy L Thompson bp = BPType::BP3;
99*d416dc2bSJeremy L Thompson else if (bp_string == "BP4")
100*d416dc2bSJeremy L Thompson bp = BPType::BP4;
101*d416dc2bSJeremy L Thompson else if (bp_string == "BP5")
102*d416dc2bSJeremy L Thompson bp = BPType::BP5;
103*d416dc2bSJeremy L Thompson else if (bp_string == "BP6")
104*d416dc2bSJeremy L Thompson bp = BPType::BP6;
105*d416dc2bSJeremy L Thompson else
106*d416dc2bSJeremy L Thompson AssertThrow(false, ExcInternalError());
107*d416dc2bSJeremy L Thompson }
108*d416dc2bSJeremy L Thompson else if ("--n_refinements" == label)
109*d416dc2bSJeremy L Thompson {
110*d416dc2bSJeremy L Thompson n_global_refinements = std::atoi(argv[1]);
111*d416dc2bSJeremy L Thompson }
112*d416dc2bSJeremy L Thompson else if ("--fe_degree" == label)
113*d416dc2bSJeremy L Thompson {
114*d416dc2bSJeremy L Thompson fe_degree = std::atoi(argv[1]);
115*d416dc2bSJeremy L Thompson }
116*d416dc2bSJeremy L Thompson else if ("--print_timings" == label)
117*d416dc2bSJeremy L Thompson {
118*d416dc2bSJeremy L Thompson print_timings = std::atoi(argv[1]);
119*d416dc2bSJeremy L Thompson }
120*d416dc2bSJeremy L Thompson else if ("--resource" == label)
121*d416dc2bSJeremy L Thompson {
122*d416dc2bSJeremy L Thompson libCEED_resource = std::string(argv[1]);
123*d416dc2bSJeremy L Thompson }
124*d416dc2bSJeremy L Thompson else
125*d416dc2bSJeremy L Thompson {
126*d416dc2bSJeremy L Thompson AssertThrow(false, ExcNotImplemented());
127*d416dc2bSJeremy L Thompson }
128*d416dc2bSJeremy L Thompson
129*d416dc2bSJeremy L Thompson
130*d416dc2bSJeremy L Thompson argc -= 2;
131*d416dc2bSJeremy L Thompson argv += 2;
132*d416dc2bSJeremy L Thompson }
133*d416dc2bSJeremy L Thompson
134*d416dc2bSJeremy L Thompson return false;
135*d416dc2bSJeremy L Thompson }
136*d416dc2bSJeremy L Thompson };
137*d416dc2bSJeremy L Thompson
138*d416dc2bSJeremy L Thompson
139*d416dc2bSJeremy L Thompson
140*d416dc2bSJeremy L Thompson int
main(int argc,char * argv[])141*d416dc2bSJeremy L Thompson main(int argc, char *argv[])
142*d416dc2bSJeremy L Thompson {
143*d416dc2bSJeremy L Thompson Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
144*d416dc2bSJeremy L Thompson
145*d416dc2bSJeremy L Thompson Parameters params;
146*d416dc2bSJeremy L Thompson if (params.parse(argc - 1, argv + 1))
147*d416dc2bSJeremy L Thompson return 0;
148*d416dc2bSJeremy L Thompson
149*d416dc2bSJeremy L Thompson ConditionalOStream pout(std::cout, Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0);
150*d416dc2bSJeremy L Thompson
151*d416dc2bSJeremy L Thompson // configuration
152*d416dc2bSJeremy L Thompson const BPType bp = params.bp;
153*d416dc2bSJeremy L Thompson
154*d416dc2bSJeremy L Thompson using Number = double;
155*d416dc2bSJeremy L Thompson using VectorType = LinearAlgebra::distributed::Vector<Number, MemorySpace::Default>;
156*d416dc2bSJeremy L Thompson const unsigned int dim = 2;
157*d416dc2bSJeremy L Thompson const unsigned int fe_degree = params.fe_degree;
158*d416dc2bSJeremy L Thompson const unsigned int n_q_points = (bp <= BPType::BP4) ? (fe_degree + 2) : (fe_degree + 1);
159*d416dc2bSJeremy L Thompson const unsigned int n_refinements = params.n_global_refinements;
160*d416dc2bSJeremy L Thompson const unsigned int n_components =
161*d416dc2bSJeremy L Thompson (bp == BPType::BP1 || bp == BPType::BP3 || bp == BPType::BP5) ? 1 : dim;
162*d416dc2bSJeremy L Thompson
163*d416dc2bSJeremy L Thompson // create mapping, quadrature, fe, mesh, ...
164*d416dc2bSJeremy L Thompson MappingQ1<dim> mapping;
165*d416dc2bSJeremy L Thompson QGauss<dim> quadrature(n_q_points);
166*d416dc2bSJeremy L Thompson FESystem<dim> fe(FE_Q<dim>(fe_degree), n_components);
167*d416dc2bSJeremy L Thompson
168*d416dc2bSJeremy L Thompson #ifdef DEAL_II_WITH_P4EST
169*d416dc2bSJeremy L Thompson parallel::distributed::Triangulation<dim> tria(MPI_COMM_WORLD);
170*d416dc2bSJeremy L Thompson #else
171*d416dc2bSJeremy L Thompson Triangulation<dim> tria;
172*d416dc2bSJeremy L Thompson #endif
173*d416dc2bSJeremy L Thompson
174*d416dc2bSJeremy L Thompson GridGenerator::hyper_cube(tria);
175*d416dc2bSJeremy L Thompson tria.refine_global(n_refinements);
176*d416dc2bSJeremy L Thompson
177*d416dc2bSJeremy L Thompson DoFHandler<dim> dof_handler(tria);
178*d416dc2bSJeremy L Thompson dof_handler.distribute_dofs(fe);
179*d416dc2bSJeremy L Thompson
180*d416dc2bSJeremy L Thompson DoFRenumbering::support_point_wise(dof_handler);
181*d416dc2bSJeremy L Thompson
182*d416dc2bSJeremy L Thompson AffineConstraints<Number> constraints;
183*d416dc2bSJeremy L Thompson
184*d416dc2bSJeremy L Thompson if (!(bp == BPType::BP1 || bp == BPType::BP2))
185*d416dc2bSJeremy L Thompson {
186*d416dc2bSJeremy L Thompson // for stiffness matrix
187*d416dc2bSJeremy L Thompson DoFTools::make_zero_boundary_constraints(dof_handler, constraints);
188*d416dc2bSJeremy L Thompson constraints.close();
189*d416dc2bSJeremy L Thompson }
190*d416dc2bSJeremy L Thompson
191*d416dc2bSJeremy L Thompson const auto test = [&](const std::string &label, const auto &op) {
192*d416dc2bSJeremy L Thompson (void)label;
193*d416dc2bSJeremy L Thompson
194*d416dc2bSJeremy L Thompson // initialize vector
195*d416dc2bSJeremy L Thompson VectorType u, v;
196*d416dc2bSJeremy L Thompson op.initialize_dof_vector(u);
197*d416dc2bSJeremy L Thompson op.initialize_dof_vector(v);
198*d416dc2bSJeremy L Thompson u = 1.0;
199*d416dc2bSJeremy L Thompson
200*d416dc2bSJeremy L Thompson constraints.set_zero(u);
201*d416dc2bSJeremy L Thompson
202*d416dc2bSJeremy L Thompson // perform matrix-vector product
203*d416dc2bSJeremy L Thompson op.vmult(v, u);
204*d416dc2bSJeremy L Thompson
205*d416dc2bSJeremy L Thompson // create solver
206*d416dc2bSJeremy L Thompson ReductionControl reduction_control(100, 1e-20, 1e-6);
207*d416dc2bSJeremy L Thompson
208*d416dc2bSJeremy L Thompson // create preconditioner
209*d416dc2bSJeremy L Thompson DiagonalMatrix<VectorType> diagonal_matrix;
210*d416dc2bSJeremy L Thompson op.compute_inverse_diagonal(diagonal_matrix.get_vector());
211*d416dc2bSJeremy L Thompson
212*d416dc2bSJeremy L Thompson std::chrono::time_point<std::chrono::system_clock> now;
213*d416dc2bSJeremy L Thompson
214*d416dc2bSJeremy L Thompson bool not_converged = false;
215*d416dc2bSJeremy L Thompson
216*d416dc2bSJeremy L Thompson try
217*d416dc2bSJeremy L Thompson {
218*d416dc2bSJeremy L Thompson // solve problem
219*d416dc2bSJeremy L Thompson SolverCG<VectorType> solver(reduction_control);
220*d416dc2bSJeremy L Thompson now = std::chrono::system_clock::now();
221*d416dc2bSJeremy L Thompson solver.solve(op, v, u, diagonal_matrix);
222*d416dc2bSJeremy L Thompson }
223*d416dc2bSJeremy L Thompson catch (const SolverControl::NoConvergence &)
224*d416dc2bSJeremy L Thompson {
225*d416dc2bSJeremy L Thompson pout << "Error: solver failed to converge with" << std::endl;
226*d416dc2bSJeremy L Thompson not_converged = true;
227*d416dc2bSJeremy L Thompson }
228*d416dc2bSJeremy L Thompson
229*d416dc2bSJeremy L Thompson
230*d416dc2bSJeremy L Thompson const auto time =
231*d416dc2bSJeremy L Thompson std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now() - now)
232*d416dc2bSJeremy L Thompson .count() /
233*d416dc2bSJeremy L Thompson 1e9;
234*d416dc2bSJeremy L Thompson
235*d416dc2bSJeremy L Thompson
236*d416dc2bSJeremy L Thompson if (params.print_timings || not_converged)
237*d416dc2bSJeremy L Thompson {
238*d416dc2bSJeremy L Thompson pout << label << ": " << reduction_control.last_step() << " " << v.l2_norm() << " "
239*d416dc2bSJeremy L Thompson << (params.print_timings ? time : 0.0) << std::endl;
240*d416dc2bSJeremy L Thompson }
241*d416dc2bSJeremy L Thompson };
242*d416dc2bSJeremy L Thompson
243*d416dc2bSJeremy L Thompson // create and test the libCEED operator
244*d416dc2bSJeremy L Thompson OperatorCeed<dim, Number, MemorySpace::Default> op_ceed(
245*d416dc2bSJeremy L Thompson mapping, dof_handler, constraints, quadrature, bp, params.libCEED_resource);
246*d416dc2bSJeremy L Thompson test("ceed", op_ceed);
247*d416dc2bSJeremy L Thompson
248*d416dc2bSJeremy L Thompson // create and test a native deal.II operator
249*d416dc2bSJeremy L Thompson OperatorDealii<dim, Number> op_dealii(mapping, dof_handler, constraints, quadrature, bp);
250*d416dc2bSJeremy L Thompson test("dealii", op_dealii);
251*d416dc2bSJeremy L Thompson }
252