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-cpu.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 3 --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 68*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 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>; 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> 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