From 4e451d6be01ce3a0c54df01432969f049910da65 Mon Sep 17 00:00:00 2001 From: Simon Schlepphorst Date: Tue, 31 Mar 2026 10:41:58 +0200 Subject: [PATCH 1/2] clang-format saveguards for ASCII art --- src/FEM/NedelecSpace.hpp | 6 ++++++ unit_tests/FEM/FEMVector.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/FEM/NedelecSpace.hpp b/src/FEM/NedelecSpace.hpp index 861bf3250..8debd5e13 100644 --- a/src/FEM/NedelecSpace.hpp +++ b/src/FEM/NedelecSpace.hpp @@ -711,10 +711,12 @@ namespace ippl { T y = localPoint(1); switch (localDOF){ + // clang-format off case 0: result(0) = 1 - y; break; case 1: result(1) = 1 - x; break; case 2: result(0) = y; break; case 3: result(1) = x; break; + // clang-format on } } else if constexpr (Dim == 3) { T x = localPoint(0); @@ -722,6 +724,7 @@ namespace ippl { T z = localPoint(2); switch (localDOF){ + // clang-format off case 0: result(0) = y*z - y - z + 1; break; case 1: result(1) = x*z - x - z + 1; break; case 2: result(0) = y*(1 - z); break; @@ -734,6 +737,7 @@ namespace ippl { case 9: result(1) = z*(1 - x); break; case 10: result(0) = y*z; break; case 11: result(1) = x*z; break; + // clang-format on } } @@ -763,10 +767,12 @@ namespace ippl { // run into any problems switch (localDOF) { + // clang-format off case 0: result(0) = 1; break; case 1: result(0) = -1; break; case 2: result(0) = -1; break; case 3: result(0) = 1; break; + // clang-format on } } else { T x = localPoint(0); diff --git a/unit_tests/FEM/FEMVector.cpp b/unit_tests/FEM/FEMVector.cpp index 76042a9e5..e70ca1051 100644 --- a/unit_tests/FEM/FEMVector.cpp +++ b/unit_tests/FEM/FEMVector.cpp @@ -493,6 +493,7 @@ TEST(FEMVector, CG) { std::vector aRef = {5, 4, 5, 1, 5, 1, 2, 2, 5, 1}; std::vector matRef = { + // clang-format off 10, -1, 3, 0, 0, 0, 0, 0, 0, 0, -1, 10, -1, 3, 0, 0, 0, 0, 0, 0, 3, -1, 10, -1, 3, 0, 0, 0, 0, 0, @@ -503,6 +504,7 @@ TEST(FEMVector, CG) { 0, 0, 0, 0, 0, 3, -1, 10, -1, 3, 0, 0, 0, 0, 0, 0, 3, -1, 10, -1, 0, 0, 0, 0, 0, 0, 0, 3, -1, 10 + // clang-format on }; From 0a9381aee9efd71b24bcb271f5fd9865620caa2e Mon Sep 17 00:00:00 2001 From: Simon Schlepphorst Date: Tue, 31 Mar 2026 10:44:17 +0200 Subject: [PATCH 2/2] clang-format everything! Tool version: clang-format version 21.1.8 Command line for reproducibility: `find . -iname "*.h" -o -iname "*.hpp" -o -iname "*.cpp" | xargs clang-format -style=file -i` --- alpine/AlpineManager.h | 32 +- alpine/BumponTailInstabilityManager.h | 13 +- alpine/FieldContainer.hpp | 3 +- alpine/FieldSolver.hpp | 31 +- alpine/LandauDamping.cpp | 4 +- alpine/LandauDampingManager.h | 29 +- alpine/LoadBalancer.hpp | 54 +- alpine/ParticleContainer.hpp | 2 +- alpine/PenningTrapManager.h | 2 +- cosmology/GravityManager.h | 2 +- doc/examples/BasicsSolver.hpp | 4 +- doc/examples/CustomPreconditioner.hpp | 44 +- doc/examples/CustomSolver.hpp | 26 +- examples/collisions/FieldContainer.hpp | 11 +- examples/collisions/P3MHeating.hpp | 304 ++- examples/collisions/P3MParticleContainer.hpp | 34 +- examples/collisions/datatypes.h | 12 +- src/Communicate/Archive.hpp | 3 +- src/Communicate/Status.h | 2 +- src/Communicate/Tags.h | 2 +- src/Communicate/Window.h | 2 +- src/Communicate/Window.hpp | 2 +- src/FEM/Elements/Element.h | 6 +- src/FEM/FEMInterpolate.hpp | 238 ++- src/FEM/FEMVector.h | 221 +- src/FEM/FEMVector.hpp | 197 +- src/FEM/FiniteElementSpace.h | 3 +- src/FEM/FiniteElementSpace.hpp | 3 +- src/FEM/LagrangeSpace.h | 15 +- src/FEM/LagrangeSpace.hpp | 139 +- src/FEM/NedelecSpace.h | 153 +- src/FEM/NedelecSpace.hpp | 1196 +++++------ src/FEM/Quadrature/GaussJacobiQuadrature.h | 4 +- src/FEM/Quadrature/Quadrature.hpp | 4 +- src/Field/BareFieldOperations.hpp | 14 +- src/Field/BcTypes.h | 6 +- src/Field/BcTypes.hpp | 17 +- src/Field/HaloCells.h | 3 +- src/Field/HaloCells.hpp | 23 +- src/FieldLayout/FieldLayout.h | 10 +- src/FieldLayout/FieldLayout.hpp | 7 +- src/FieldLayout/SubFieldLayout.h | 57 +- src/FieldLayout/SubFieldLayout.hpp | 63 +- src/Ippl.cpp | 2 +- src/LinearSolvers/PCG.h | 61 +- src/LinearSolvers/Preconditioner.h | 31 +- src/Manager/BaseManager.h | 9 +- src/Manager/FieldSolverBase.h | 3 +- src/Manager/PicManager.h | 3 +- src/Manager/datatypes.h | 13 +- src/MaxwellSolvers/AbsorbingBC.h | 3 +- src/MaxwellSolvers/FDTDSolverBase.h | 2 +- .../FEMMaxwellDiffusionSolver.h | 101 +- src/MaxwellSolvers/Maxwell.h | 4 +- src/Meshes/Mesh.h | 2 +- src/Meshes/UniformCartesian.h | 4 +- src/Particle/ParticleAttrib.h | 8 +- src/Particle/ParticleAttrib.hpp | 94 +- src/Particle/ParticleAttribBase.h | 2 +- src/Particle/ParticleBase.h | 4 +- src/Particle/ParticleSpatialLayout.h | 20 +- src/Particle/ParticleSpatialLayout.hpp | 3 +- src/Particle/ParticleSpatialOverlapLayout.hpp | 3 +- src/PoissonSolvers/EvalFunctor.h | 2 +- src/PoissonSolvers/FEMPoissonSolver.h | 41 +- src/PoissonSolvers/FFTOpenPoissonSolver.hpp | 2 +- .../FFTTruncatedGreenPeriodicPoissonSolver.h | 8 +- ...FFTTruncatedGreenPeriodicPoissonSolver.hpp | 19 +- src/PoissonSolvers/LaplaceHelpers.h | 6 +- .../PreconditionedFEMPoissonSolver.h | 66 +- src/Random/NormalDistribution.h | 2 +- src/Random/Utility.h | 2 +- src/Region/RegionLayout.hpp | 5 +- src/Types/Variant.h | 10 +- src/Types/Vector.h | 2 +- src/Types/Vector.hpp | 3 +- src/Utility/ParallelDispatch.h | 4 +- test/solver/TestCGSolver_convergence.cpp | 21 +- .../fem/TestMaxwellDiffusionPolyZeroBC.cpp | 260 ++- .../TestMaxwellDiffusionPolyZeroBCTimed.cpp | 249 ++- .../solver/fem/TestMaxwellDiffusionZeroBC.cpp | 257 ++- test/solver/fem/TestNonhomDirichlet_1d.cpp | 12 +- .../TestNonhomDirichlet_1d_preconditioned.cpp | 22 +- test/solver/fem/TestNonhomDirichlet_1dcos.cpp | 8 +- test/solver/fem/TestNonhomDirichlet_2d.cpp | 17 +- .../TestNonhomDirichlet_2d_preconditioned.cpp | 27 +- test/solver/fem/TestNonhomDirichlet_3d.cpp | 33 +- .../TestNonhomDirichlet_3d_preconditioned.cpp | 43 +- test/solver/fem/TestPeriodicBC_sin.cpp | 10 +- .../fem/TestPeriodicBC_sin_preconditioned.cpp | 20 +- test/solver/fem/TestPeriodicBC_sinsin.cpp | 46 +- .../fem/TestScaling_PeriodicBC_sinsin.cpp | 40 +- .../TestScaling_PeriodicBC_sinsin_precon.cpp | 48 +- .../fem/TestScaling_ZeroBC_sin_precon.cpp | 10 +- test/solver/fem/TestZeroBC_constant1d.cpp | 7 +- .../TestZeroBC_constant1d_preconditioned.cpp | 17 +- test/solver/fem/TestZeroBC_polynomial2d.cpp | 17 +- ...TestZeroBC_polynomial2d_preconditioned.cpp | 27 +- test/solver/fem/TestZeroBC_sin.cpp | 4 +- .../fem/TestZeroBC_sin_preconditioned.cpp | 14 +- test/types/TestTuple.cpp | 2 +- test/types/TestVector3.cpp | 2 +- unit_tests/BareField/BareField.cpp | 20 +- unit_tests/Communicate/BufferHandler.cpp | 3 +- unit_tests/Communicate/LogEntry.cpp | 2 +- unit_tests/FEM/AssembleRHS.cpp | 355 ++-- unit_tests/FEM/EdgeElement.cpp | 10 +- unit_tests/FEM/FEMVector.cpp | 414 ++-- unit_tests/FEM/FiniteElementSpace.cpp | 37 +- unit_tests/FEM/HexahedralElement.cpp | 15 +- unit_tests/FEM/InterpolateDiracs.cpp | 537 ++--- unit_tests/FEM/LagrangeSpace.cpp | 135 +- unit_tests/FEM/LocateElement.cpp | 70 +- unit_tests/FEM/NedelecSpace.cpp | 1770 ++++++++--------- unit_tests/FEM/QuadrilateralElement.cpp | 12 +- unit_tests/Field/Field.cpp | 7 +- unit_tests/Field/FieldSubLayout.cpp | 21 +- unit_tests/Field/FieldSubLayoutBC.cpp | 11 +- unit_tests/Field/HaloSubLayout.cpp | 11 +- unit_tests/PIC/ORB.cpp | 3 +- unit_tests/PIC/PIC.cpp | 2 +- unit_tests/Particle/GatherScatterTest.cpp | 132 +- unit_tests/Particle/ParticleSendRecv.cpp | 6 +- unit_tests/TestUtils.h | 2 +- 124 files changed, 4014 insertions(+), 4315 deletions(-) diff --git a/alpine/AlpineManager.h b/alpine/AlpineManager.h index ff5ff85c5..f696084c6 100644 --- a/alpine/AlpineManager.h +++ b/alpine/AlpineManager.h @@ -3,6 +3,7 @@ #include +#include "FEM/FEMInterpolate.hpp" #include "FieldContainer.hpp" #include "FieldSolver.hpp" #include "LoadBalancer.hpp" @@ -13,7 +14,6 @@ #include "Random/InverseTransformSampling.h" #include "Random/NormalDistribution.h" #include "Random/Randn.h" -#include "FEM/FEMInterpolate.hpp" using view_type = typename ippl::detail::ViewType, 1>::view_type; @@ -35,6 +35,7 @@ class AlpineManager : public ippl::PicManager, std::string solver_m; std::string stepMethod_m; std::vector preconditioner_params_m; + public: AlpineManager(size_type totalP_, int nt_, Vector_t& nr_, double lbt_, std::string& solver_, std::string& stepMethod_, @@ -98,7 +99,7 @@ class AlpineManager : public ippl::PicManager, std::vector getPreconditionerParams() const { return preconditioner_params_m; }; - virtual void dump(){/* default does nothing */}; + virtual void dump() { /* default does nothing */ }; void pre_step() override { Inform m("Pre-step"); @@ -116,7 +117,7 @@ class AlpineManager : public ippl::PicManager, m << "Finished time step: " << this->it_m << " time: " << this->time_m << endl; } - void grid2par() override { + void grid2par() override { if ((getSolver() == "FEM") || (getSolver() == "FEM_PRECON")) { gatherFEM(); } else { @@ -129,15 +130,15 @@ class AlpineManager : public ippl::PicManager, } void gatherFEM() { - using exec_space = typename Kokkos::View::execution_space; - using policy_type = Kokkos::RangePolicy; + using exec_space = typename Kokkos::View::execution_space; + using policy_type = Kokkos::RangePolicy; size_type localParticles = this->pcontainer_m->getLocalNum(); policy_type iteration_policy(0, localParticles); - // get the Finite Element space from the solver, + // get the Finite Element space from the solver, // since the interpolation depends on the space auto* solver = dynamic_cast(this->fsolver_m.get()); - auto& space = solver->getSpace(); + auto& space = solver->getSpace(); interpolate_grad_to_diracs(this->pcontainer_m->E, this->fcontainer_m->getPhi(), this->pcontainer_m->R, space, iteration_policy); @@ -182,14 +183,14 @@ class AlpineManager : public ippl::PicManager, double Q = Q_m; size_type localParticles = this->pcontainer_m->getLocalNum(); - using exec_space = typename Kokkos::View::execution_space; + using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; policy_type iteration_policy(0, localParticles); - // get the Finite Element space from the solver, + // get the Finite Element space from the solver, // since the interpolation depends on the space auto* solver = dynamic_cast(this->fsolver_m.get()); - auto& space = solver->getSpace(); + auto& space = solver->getSpace(); assemble_rhs_from_particles(*q, *rho, *R, space, iteration_policy); @@ -220,12 +221,13 @@ class AlpineManager : public ippl::PicManager, } void getDensity(Field_t* rho) { - Vector_t rmin = rmin_m; - Vector_t rmax = rmax_m; - Vector_t hr = this->hr_m; - double Q = Q_m; + Vector_t rmin = rmin_m; + Vector_t rmax = rmax_m; + Vector_t hr = this->hr_m; + double Q = Q_m; - if ((this->fsolver_m->getStype() != "FEM") && (this->fsolver_m->getStype() != "FEM_PRECON")) { + if ((this->fsolver_m->getStype() != "FEM") + && (this->fsolver_m->getStype() != "FEM_PRECON")) { double cellVolume = std::reduce(hr.begin(), hr.end(), 1., std::multiplies()); (*rho) = (*rho) / cellVolume; } diff --git a/alpine/BumponTailInstabilityManager.h b/alpine/BumponTailInstabilityManager.h index 7525f9af1..b6ea585d8 100644 --- a/alpine/BumponTailInstabilityManager.h +++ b/alpine/BumponTailInstabilityManager.h @@ -1,8 +1,8 @@ #ifndef IPPL_BUMPON_TAIL_INSTABILITY_MANAGER_H #define IPPL_BUMPON_TAIL_INSTABILITY_MANAGER_H -#include #include +#include #include "AlpineManager.h" #include "FieldContainer.hpp" @@ -83,9 +83,9 @@ class BumponTailInstabilityManager : public AlpineManager { public: void pre_run() override { Inform m("Pre Run"); - - const double pi = Kokkos::numbers::pi_v; - + + const double pi = Kokkos::numbers::pi_v; + if (this->solver_m == "OPEN") { throw IpplException("BumpOnTailInstability", "Open boundaries solver incompatible with this simulation!"); @@ -393,9 +393,8 @@ class BumponTailInstabilityManager : public AlpineManager { auto& Pi = pc->P; for (unsigned d = allDims ? 0 : Dim - 1; d < Dim; d++) { Kokkos::parallel_for( - "Copy phase space", pcount, KOKKOS_CLASS_LAMBDA(const size_t i) { - phase(i) = {Ri(i)[d], Pi(i)[d]}; - }); + "Copy phase space", pcount, + KOKKOS_CLASS_LAMBDA(const size_t i) { phase(i) = {Ri(i)[d], Pi(i)[d]}; }); phaseSpace = 0; Kokkos::fence(); scatter(pc->q, phaseSpace, phase); diff --git a/alpine/FieldContainer.hpp b/alpine/FieldContainer.hpp index 76d27459d..a0c355327 100644 --- a/alpine/FieldContainer.hpp +++ b/alpine/FieldContainer.hpp @@ -63,7 +63,8 @@ class FieldContainer { void initializeFields(std::string stype_m = "") { E_m.initialize(mesh_m, fl_m); rho_m.initialize(mesh_m, fl_m); - if ((stype_m == "CG") || (stype_m == "PCG") || (stype_m == "FEM") || (stype_m == "FEM_PRECON")) { + if ((stype_m == "CG") || (stype_m == "PCG") || (stype_m == "FEM") + || (stype_m == "FEM_PRECON")) { phi_m.initialize(mesh_m, fl_m); } } diff --git a/alpine/FieldSolver.hpp b/alpine/FieldSolver.hpp index 7fccbf749..e1a2cbb81 100644 --- a/alpine/FieldSolver.hpp +++ b/alpine/FieldSolver.hpp @@ -1,8 +1,8 @@ #ifndef IPPL_FIELD_SOLVER_H #define IPPL_FIELD_SOLVER_H -#include #include +#include #include "Manager/BaseManager.h" #include "Manager/FieldSolverBase.h" @@ -63,11 +63,11 @@ class FieldSolver : public ippl::FieldSolverBase { // CG requires explicit periodic boundary conditions while the periodic Poisson solver // simply assumes them typedef ippl::BConds, Dim> bc_type; - if ((this->getStype() == "CG") || (this->getStype() == "PCG") || (this->getStype() == "FEM") || - (this->getStype() == "FEM_PRECON")) { + if ((this->getStype() == "CG") || (this->getStype() == "PCG") || (this->getStype() == "FEM") + || (this->getStype() == "FEM_PRECON")) { bc_type allPeriodic; for (unsigned int i = 0; i < 2 * Dim; ++i) { - allPeriodic[i] = std::make_shared>>(i); + allPeriodic[i] = std::make_shared>>(i); } phi_m->setFieldBC(allPeriodic); if ((this->getStype() == "FEM") || (this->getStype() == "FEM_PRECON")) { @@ -77,10 +77,10 @@ class FieldSolver : public ippl::FieldSolverBase { } void runSolver() override { - if ((this->getStype() == "CG") || (this->getStype() == "PCG") || (this->getStype() == "FEM") || - (this->getStype() == "FEM_PRECON")) { + if ((this->getStype() == "CG") || (this->getStype() == "PCG") || (this->getStype() == "FEM") + || (this->getStype() == "FEM_PRECON")) { int iterations = 0; - int residue = 0; + int residue = 0; if (this->getStype() == "FEM") { FEMSolver_t& solver = std::get>(this->getSolver()); @@ -89,7 +89,8 @@ class FieldSolver : public ippl::FieldSolverBase { iterations = solver.getIterationCount(); residue = solver.getResidue(); } else if (this->getStype() == "FEM_PRECON") { - FEMPreconSolver_t& solver = std::get>(this->getSolver()); + FEMPreconSolver_t& solver = + std::get>(this->getSolver()); solver.solve(); iterations = solver.getIterationCount(); @@ -105,8 +106,8 @@ class FieldSolver : public ippl::FieldSolverBase { if (ippl::Comm->rank() == 0) { std::filesystem::create_directory("data_CG"); std::stringstream fname; - if ((this->getStype() == "CG") || (this->getStype() == "FEM") || - (this->getStype() == "FEM_PRECON")) { + if ((this->getStype() == "CG") || (this->getStype() == "FEM") + || (this->getStype() == "FEM_PRECON")) { fname << "data_CG/CG_"; } else { fname << "data_CG/"; @@ -153,10 +154,10 @@ class FieldSolver : public ippl::FieldSolverBase { solver.setRhs(*rho_m); - if constexpr ((std::is_same_v>) || - (std::is_same_v>) || - (std::is_same_v>)) { - // The CG solver and FEMPoissonSolver compute the potential + if constexpr ((std::is_same_v>) + || (std::is_same_v>) + || (std::is_same_v>)) { + // The CG solver and FEMPoissonSolver compute the potential // directly and use this to get the electric field solver.setLhs(*phi_m); solver.setGradient(*E_m); @@ -292,7 +293,7 @@ class FieldSolver : public ippl::FieldSolverBase { sp.add("richardson_iterations", richardson_iterations); sp.add("communication", communication); sp.add("ssor_omega", ssor_omega); - + initSolverWithParams>(sp); } diff --git a/alpine/LandauDamping.cpp b/alpine/LandauDamping.cpp index 718672513..76fcb0099 100644 --- a/alpine/LandauDamping.cpp +++ b/alpine/LandauDamping.cpp @@ -47,7 +47,7 @@ int main(int argc, char* argv[]) { Inform msg(TestName); Inform msg2all(TestName, INFORM_ALL_NODES); - static IpplTimings::TimerRef mainTimer = IpplTimings::getTimer("total"); + static IpplTimings::TimerRef mainTimer = IpplTimings::getTimer("total"); static IpplTimings::TimerRef initializeTimer = IpplTimings::getTimer("initialize"); IpplTimings::startTimer(mainTimer); IpplTimings::startTimer(initializeTimer); @@ -82,7 +82,7 @@ int main(int argc, char* argv[]) { manager.pre_run(); IpplTimings::stopTimer(initializeTimer); - + manager.setTime(0.0); msg << "Starting iterations ..." << endl; diff --git a/alpine/LandauDampingManager.h b/alpine/LandauDampingManager.h index b8491c7a5..5d96397db 100644 --- a/alpine/LandauDampingManager.h +++ b/alpine/LandauDampingManager.h @@ -1,8 +1,8 @@ #ifndef IPPL_LANDAU_DAMPING_MANAGER_H #define IPPL_LANDAU_DAMPING_MANAGER_H -#include #include +#include #include "AlpineManager.h" #include "FieldContainer.hpp" @@ -67,7 +67,7 @@ class LandauDampingManager : public AlpineManager { Inform m("Pre Run"); const double pi = Kokkos::numbers::pi_v; - + if (this->solver_m == "OPEN") { throw IpplException("LandauDamping", "Open boundaries solver incompatible with this simulation!"); @@ -84,7 +84,7 @@ class LandauDampingManager : public AlpineManager { this->rmax_m = 2 * pi / this->kw_m; bool isFEM = ((this->getSolver() == "FEM") || (this->getSolver() == "FEM_PRECON")); - + Vector nElements = this->nr_m - 1; if (isFEM) { this->hr_m = this->rmax_m / nElements; @@ -110,8 +110,7 @@ class LandauDampingManager : public AlpineManager { this->isAllPeriodic_m)); this->setParticleContainer(std::make_shared( - this->fcontainer_m->getMesh(), this->fcontainer_m->getFL(), - isFEM)); + this->fcontainer_m->getMesh(), this->fcontainer_m->getFL(), isFEM)); this->fcontainer_m->initializeFields(this->solver_m); @@ -191,7 +190,8 @@ class LandauDampingManager : public AlpineManager { this->fcontainer_m->getRho().getFieldRangePolicy(), KOKKOS_LAMBDA(const index_array_type& args) { // local to global index conversion - Vector_t xvec = (args + lDom.first() - nghost + 0.5*(!isFEM)) * hr + origin; + Vector_t xvec = + (args + lDom.first() - nghost + 0.5 * (!isFEM)) * hr + origin; // ippl::apply accesses the view at the given indices and obtains a // reference; see src/Expression/IpplOperations.h @@ -246,7 +246,7 @@ class LandauDampingManager : public AlpineManager { this->pcontainer_m->q = this->Q_m / totalP; // For FEM need an update due to node-centering, as periodic BCs mean - // that a particle at R=0 is equivalent to R=1 so it could be on the + // that a particle at R=0 is equivalent to R=1 so it could be on the // wrong rank and needs to be sent over. if (isFEM) { this->pcontainer_m->update(); @@ -325,7 +325,7 @@ class LandauDampingManager : public AlpineManager { if ((this->getSolver() == "FEM") || (this->getSolver() == "FEM_PRECON")) { // When using FEM, we only have E on particles - // so we use the dump function which computes the + // so we use the dump function which computes the // energy using the particles instead of the field. dumpLandau(); } else { @@ -385,15 +385,15 @@ class LandauDampingManager : public AlpineManager { ippl::Comm->barrier(); } - // Overloaded dumpLandau which computes the E-field energy using the particles - // instead of using the E-field on the grid (as above). Since we have E for + // Overloaded dumpLandau which computes the E-field energy using the particles + // instead of using the E-field on the grid (as above). Since we have E for // each particle, we treat the particles as Monte-Carlo samples to compute // the energy integral. void dumpLandau() { - auto Eview = this->pcontainer_m->E.getView(); + auto Eview = this->pcontainer_m->E.getView(); size_type localParticles = this->pcontainer_m->getLocalNum(); - using exec_space = typename Kokkos::View::execution_space; + using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; policy_type iteration_policy(0, localParticles); @@ -412,9 +412,8 @@ class LandauDampingManager : public AlpineManager { // MC integration: divide by no. of particles N and multiply by volume ippl::Vector domain_size = this->rmax_m - this->rmin_m; - double fieldEnergy = - std::reduce(domain_size.begin(), domain_size.end(), - globaltemp, std::multiplies()); + double fieldEnergy = std::reduce(domain_size.begin(), domain_size.end(), globaltemp, + std::multiplies()); fieldEnergy = fieldEnergy / this->totalP_m; diff --git a/alpine/LoadBalancer.hpp b/alpine/LoadBalancer.hpp index e9d0cc1d1..136026584 100644 --- a/alpine/LoadBalancer.hpp +++ b/alpine/LoadBalancer.hpp @@ -59,8 +59,8 @@ class LoadBalancer { (*E_m).updateLayout(*fl); (*rho_m).updateLayout(*fl); - if (fs_m->getStype() == "CG" || fs_m->getStype() == "PCG" || fs_m->getStype() == "FEM" || - fs_m->getStype() == "FEM_PRECON") { + if (fs_m->getStype() == "CG" || fs_m->getStype() == "PCG" || fs_m->getStype() == "FEM" + || fs_m->getStype() == "FEM_PRECON") { phi_m->updateLayout(*fl); phi_m->setFieldBC(phi_m->getFieldBC()); } @@ -85,35 +85,35 @@ class LoadBalancer { bool& isFirstRepartition) { // Repartition the domains - using Base = ippl::ParticleBase>; - typename Base::particle_position_type *R; - R = &pc_m->R; - bool res = orb.binaryRepartition(*R, *fl, isFirstRepartition); - if (res != true) { - std::cout << "Could not repartition!" << std::endl; - return; - } - // Update - this->updateLayout(fl, mesh, isFirstRepartition); - if (fs_m->getStype() == "FEM") { - std::get>(fs_m->getSolver()).setRhs(*rho_m); - } - if (fs_m->getStype() == "FEM_PRECON") { - std::get>(fs_m->getSolver()).setRhs(*rho_m); + using Base = ippl::ParticleBase>; + typename Base::particle_position_type* R; + R = &pc_m->R; + bool res = orb.binaryRepartition(*R, *fl, isFirstRepartition); + if (res != true) { + std::cout << "Could not repartition!" << std::endl; + return; + } + // Update + this->updateLayout(fl, mesh, isFirstRepartition); + if (fs_m->getStype() == "FEM") { + std::get>(fs_m->getSolver()).setRhs(*rho_m); + } + if (fs_m->getStype() == "FEM_PRECON") { + std::get>(fs_m->getSolver()).setRhs(*rho_m); + } + if constexpr (Dim == 2 || Dim == 3) { + if (fs_m->getStype() == "FFT") { + std::get>(fs_m->getSolver()).setRhs(*rho_m); } - if constexpr (Dim == 2 || Dim == 3) { - if (fs_m->getStype() == "FFT") { - std::get>(fs_m->getSolver()).setRhs(*rho_m); - } - if constexpr (Dim == 3) { - if (fs_m->getStype() == "TG") { - std::get>(fs_m->getSolver()).setRhs(*rho_m); - } else if (fs_m->getStype() == "OPEN") { - std::get>(fs_m->getSolver()).setRhs(*rho_m); - } + if constexpr (Dim == 3) { + if (fs_m->getStype() == "TG") { + std::get>(fs_m->getSolver()).setRhs(*rho_m); + } else if (fs_m->getStype() == "OPEN") { + std::get>(fs_m->getSolver()).setRhs(*rho_m); } } } + } bool balance(size_type totalP, const unsigned int nstep) { if (ippl::Comm->size() < 2 && loadbalancethreshold_m != 1.0) { diff --git a/alpine/ParticleContainer.hpp b/alpine/ParticleContainer.hpp index 6a1b55708..40473311a 100644 --- a/alpine/ParticleContainer.hpp +++ b/alpine/ParticleContainer.hpp @@ -31,7 +31,7 @@ class ParticleContainer : public ippl::ParticleBase>& pl) { pl_m = pl; } void registerAttributes() { - //only needed for vis + // only needed for vis P.set_name("velocity"); q.set_name("charge"); E.set_name("electric_field"); diff --git a/alpine/PenningTrapManager.h b/alpine/PenningTrapManager.h index b721f3ec8..8d886f5a4 100644 --- a/alpine/PenningTrapManager.h +++ b/alpine/PenningTrapManager.h @@ -1,8 +1,8 @@ #ifndef IPPL_PENNING_TRAP_MANAGER_H #define IPPL_PENNING_TRAP_MANAGER_H -#include #include +#include #include "AlpineManager.h" #include "FieldContainer.hpp" diff --git a/cosmology/GravityManager.h b/cosmology/GravityManager.h index 80ca4fd87..6a6ab70a6 100644 --- a/cosmology/GravityManager.h +++ b/cosmology/GravityManager.h @@ -232,7 +232,7 @@ class GravityManager : public ippl::PicManager /** * @brief Virtual method to dump data (default does nothing). */ - virtual void dump(){/* default does nothing */}; + virtual void dump() { /* default does nothing */ }; // Step methods diff --git a/doc/examples/BasicsSolver.hpp b/doc/examples/BasicsSolver.hpp index b88784fae..c8ba63ec2 100644 --- a/doc/examples/BasicsSolver.hpp +++ b/doc/examples/BasicsSolver.hpp @@ -1,5 +1,5 @@ /** -@page basic_solver Basics: Solver {#Solver} +@page basic_solver Basics: Solver {#Solver} @section solvers Solvers @@ -96,7 +96,7 @@ FFTsolver.solve(); The potential is stored in the rho Field. The E-Field is stored in the fieldE Field. -## [Optional] Using a Preconditioner +## [Optional] Using a Preconditioner If you want to precondition the solver you can add following parameters to the parameter list: @code diff --git a/doc/examples/CustomPreconditioner.hpp b/doc/examples/CustomPreconditioner.hpp index ac4e9f261..a8ff19bbd 100644 --- a/doc/examples/CustomPreconditioner.hpp +++ b/doc/examples/CustomPreconditioner.hpp @@ -2,17 +2,24 @@ # Introduction to the Preconditioner Base Class -The preconditioner class in the IPPL framework serves as an abstract base class for different preconditioning strategies applied in iterative solvers. It encapsulates common functionalities and interfaces that are essential for all types of preconditioners. -Structure of the Preconditioner Base Class - -- Template Parameter: The class template Field determines the type of the numerical field the preconditioner will operate on. -- Constructor: Constructors initialize the preconditioner, optionally setting a type name to identify the preconditioner strategy. -- Virtual Function ('operator()'): This is a pure virtual function in the base class that must be implemented by derived classes to define the specific preconditioning behavior. +The preconditioner class in the IPPL framework serves as an abstract base class for different +preconditioning strategies applied in iterative solvers. It encapsulates common functionalities and +interfaces that are essential for all types of preconditioners. Structure of the Preconditioner Base +Class + +- Template Parameter: The class template Field determines the type of the numerical field the +preconditioner will operate on. +- Constructor: Constructors initialize the preconditioner, optionally setting a type name to +identify the preconditioner strategy. +- Virtual Function ('operator()'): This is a pure virtual function in the base class that must be +implemented by derived classes to define the specific preconditioning behavior. Steps to Create a Custom Preconditioner ## Step 1: Define the Preconditioner Class -Begin by defining a new class that inherits from the 'preconditioner' provided by the IPPL framework. This new class should implement all abstract methods from the base class and can add additional members as needed for its specific strategy. +Begin by defining a new class that inherits from the 'preconditioner' provided by the IPPL +framework. This new class should implement all abstract methods from the base class and can add +additional members as needed for its specific strategy. @code template @@ -32,15 +39,19 @@ struct custom_preconditioner : public preconditioner { ## Step 2: Implement the Constructor -Use the constructor of your custom preconditioner to initialize any data members and forward any necessary parameters to the base class constructor, which sets the type name of the preconditioner. +Use the constructor of your custom preconditioner to initialize any data members and forward any +necessary parameters to the base class constructor, which sets the type name of the preconditioner. ## Step 3: Override the Operator Function -Implement the 'operator()' function to apply your preconditioning logic to the input field. This method is crucial as it defines how the preconditioner modifies the input data, aligning with the specific algorithmic needs of your solver. -# Example Implementations +Implement the 'operator()' function to apply your preconditioning logic to the input field. This +method is crucial as it defines how the preconditioner modifies the input data, aligning with the +specific algorithmic needs of your solver. # Example Implementations ## Jacobi Preconditioner -The 'jacobi_preconditioner' provided by IPPL is a derived class of preconditioner. It implements a specific preconditioning strategy using an inverse diagonal matrix and a damping factor. Here is how it extends the base class: +The 'jacobi_preconditioner' provided by IPPL is a derived class of preconditioner. It implements a +specific preconditioning strategy using an inverse diagonal matrix and a damping factor. Here is how +it extends the base class: @code @@ -50,7 +61,8 @@ struct jacobi_preconditioner : public preconditioner { double w_m; // Damping factor jacobi_preconditioner(InvDiagF&& inverse_diagonal, double w = 1.0) - : preconditioner("Jacobi"), inverse_diagonal_m(std::move(inverse_diagonal)), w_m(w) {} + : preconditioner("Jacobi"), inverse_diagonal_m(std::move(inverse_diagonal)), w_m(w) +{} Field operator()(Field& u) override { typename Field::mesh_type& mesh = u.get_mesh(); @@ -65,7 +77,8 @@ struct jacobi_preconditioner : public preconditioner { @endcode ## Scaling Preconditioner -A simple example of a custom preconditioner that scales the input field can be structured as follows: +A simple example of a custom preconditioner that scales the input field can be structured as +follows: @code @@ -84,6 +97,7 @@ struct scaling_preconditioner : public preconditioner { # Integration with Solvers -To utilize your custom preconditioner in a solver, instantiate it and configure the solver to use it. +To utilize your custom preconditioner in a solver, instantiate it and configure the solver to use +it. -*/ \ No newline at end of file +*/ \ No newline at end of file diff --git a/doc/examples/CustomSolver.hpp b/doc/examples/CustomSolver.hpp index 2d6644329..03b159f3f 100644 --- a/doc/examples/CustomSolver.hpp +++ b/doc/examples/CustomSolver.hpp @@ -1,19 +1,22 @@ /** @page custom_solver Creating Custom Solver -Here, we'll provide detailed guidelines on how to extend this base class of the 'SolverAlgorithm' to develop your own solver algorithm, -using the PCG (Preconditioned Conjugate Gradient) solver as an example. +Here, we'll provide detailed guidelines on how to extend this base class of the 'SolverAlgorithm' to +develop your own solver algorithm, using the PCG (Preconditioned Conjugate Gradient) solver as an +example. ## Introduction to SolverAlgorithm Base Class The SolverAlgorithm class is a template abstract class designed to serve as a -foundation for various numerical solver algorithms. -It provides a common interface for solving problems of the form +foundation for various numerical solver algorithms. +It provides a common interface for solving problems of the form Op(lhs) = rhs, where Op is a differential operator and lhs and rhs are fields. ** Key Components of SolverAlgorithm ** -- Template Parameters: The class template parameters FieldLHS and FieldRHS define the types for the left-hand side (LHS) and right-hand side (RHS) of the equation respectively. -- Virtual Function: The operator() function is a pure virtual function that must be implemented by derived classes. It is where the main logic of the solver is implemented. +- Template Parameters: The class template parameters FieldLHS and FieldRHS define the types for the +left-hand side (LHS) and right-hand side (RHS) of the equation respectively. +- Virtual Function: The operator() function is a pure virtual function that must be implemented by +derived classes. It is where the main logic of the solver is implemented. @code @@ -42,13 +45,14 @@ namespace ippl { } // namespace ippl -@endcode +@endcode ## Steps to Create a Custom Solver ### 1. Define the Solver Class -Start by defining your solver class that inherits from SolverAlgorithm. Specify any additional data members or methods needed for your solver. +Start by defining your solver class that inherits from SolverAlgorithm. Specify any additional data +members or methods needed for your solver. @code #include "SolverAlgorithm.h" @@ -63,10 +67,12 @@ class MySolver : public ippl::SolverAlgorithm { @endcode ## 2. Implement the Solver Logic -Implement the operator() function, which contains the core logic for the solver. This function should use the provided lhs, rhs, and params to compute the solution to the problem. +Implement the operator() function, which contains the core logic for the solver. This function +should use the provided lhs, rhs, and params to compute the solution to the problem. @code -void operator()(typename Base::lhs_type& lhs, typename Base::rhs_type& rhs, const ParameterList& params) override { +void operator()(typename Base::lhs_type& lhs, typename Base::rhs_type& rhs, const ParameterList& +params) override { // Initialization and setup // Iterative solution process // Post-processing and cleanup diff --git a/examples/collisions/FieldContainer.hpp b/examples/collisions/FieldContainer.hpp index f136e821f..ce68c75e4 100644 --- a/examples/collisions/FieldContainer.hpp +++ b/examples/collisions/FieldContainer.hpp @@ -7,11 +7,10 @@ // Define the FieldsContainer class template -class FieldContainer{ +class FieldContainer { public: - FieldContainer(Vector_t& hr, Vector_t& rmin, - Vector_t& rmax, std::array decomp, - ippl::NDIndex domain, Vector_t origin, + FieldContainer(Vector_t& hr, Vector_t& rmin, Vector_t& rmax, + std::array decomp, ippl::NDIndex domain, Vector_t origin, bool isAllPeriodic) : hr_m(hr) , rmin_m(rmin) @@ -20,7 +19,7 @@ class FieldContainer{ , mesh_m(domain, hr, origin) , fl_m(MPI_COMM_WORLD, domain, decomp, isAllPeriodic) {} - ~FieldContainer(){} + ~FieldContainer() {} private: Vector_t hr_m; @@ -56,7 +55,7 @@ class FieldContainer{ void setDecomp(std::array decomp) { decomp_m = decomp; } Mesh_t& getMesh() { return mesh_m; } - void setMesh(Mesh_t & mesh) { mesh_m = mesh; } + void setMesh(Mesh_t& mesh) { mesh_m = mesh; } FieldLayout_t& getFL() { return fl_m; } void setFL(std::shared_ptr>& fl) { fl_m = fl; } diff --git a/examples/collisions/P3MHeating.hpp b/examples/collisions/P3MHeating.hpp index 868435a18..8b052d4af 100644 --- a/examples/collisions/P3MHeating.hpp +++ b/examples/collisions/P3MHeating.hpp @@ -2,11 +2,11 @@ #define IPPL_P3M_BENCH_MANAGER_HPP // includes -#include -#include -#include #include #include +#include +#include +#include // Alpine Headers // #include "../alpine/LoadBalancer.hpp" @@ -14,68 +14,73 @@ // P3M Headers #include "P3M3DManager.h" -#include "PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h" #include "P3MParticleContainer.hpp" +#include "PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h" // Distribution functions +#include "datatypes.h" + #include "Random/Distribution.h" #include "Random/NormalDistribution.h" #include "Random/UniformDistribution.h" -#include "datatypes.h" - /** * @class P3MHeatingManager * @brief A class that benchmarks the P3M Method * * @tparam T the data dype for simulation variables * @tparam Dim the dimensionality of the simulation -*/ -template -class P3MHeatingManager - : public P3M3DManager > { + */ +template +class P3MHeatingManager : public P3M3DManager > { public: using ParticleContainer_t = P3MParticleContainer; - using Base = P3M3DManager >; - using FieldContainer_t = FieldContainer; + using Base = P3M3DManager >; + using FieldContainer_t = FieldContainer; protected: - size_type totalP_m; // Total number of particles - int nt_m; // Total number of time steps - T dt_m; // Time step size - Vector_t nr_m; // Domain granularity - T rcut_m; // Interaction cutoff radius - std::string solver_m; // solver is P3MSolver - T beamRad_m; // beam radius - T focusingF_m; // constant focusing force - T boxlen_m; // box length + size_type totalP_m; // Total number of particles + int nt_m; // Total number of time steps + T dt_m; // Time step size + Vector_t nr_m; // Domain granularity + T rcut_m; // Interaction cutoff radius + std::string solver_m; // solver is P3MSolver + T beamRad_m; // beam radius + T focusingF_m; // constant focusing force + T boxlen_m; // box length public: - P3MHeatingManager(size_type totalP_, int nt_, T dt_, Vector_t &nr_, T rcut_, T alpha_, + P3MHeatingManager(size_type totalP_, int nt_, T dt_, Vector_t& nr_, T rcut_, T alpha_, T beamRad_, T focusingF_, T boxlen_) : P3M3DManager >() - , totalP_m(totalP_), nt_m(nt_), dt_m(dt_), nr_m(nr_), rcut_m(rcut_), solver_m("P3M"), beamRad_m(beamRad_), - focusingF_m(focusingF_), boxlen_m(boxlen_), alpha_m(alpha_) { - } - - ~P3MHeatingManager() { - } + , totalP_m(totalP_) + , nt_m(nt_) + , dt_m(dt_) + , nr_m(nr_) + , rcut_m(rcut_) + , solver_m("P3M") + , beamRad_m(beamRad_) + , focusingF_m(focusingF_) + , boxlen_m(boxlen_) + , alpha_m(alpha_) {} + + ~P3MHeatingManager() {} protected: - T time_m; // Simulation time - T it_m; // Iteration counter - T alpha_m; // Green's function splitting parameter - T epsilon_m; // Regularization for PP interaction - Vector_t rmin_m; // minimum domain extend - Vector_t rmax_m; // maximum domain extend - Vector_t hr_m; // PM Meshwidth - Vector_t nCells_m; // Number of cells in each dimension - T Q_m; // Particle Charge + T time_m; // Simulation time + T it_m; // Iteration counter + T alpha_m; // Green's function splitting parameter + T epsilon_m; // Regularization for PP interaction + Vector_t rmin_m; // minimum domain extend + Vector_t rmax_m; // maximum domain extend + Vector_t hr_m; // PM Meshwidth + Vector_t nCells_m; // Number of cells in each dimension + T Q_m; // Particle Charge Vector_t origin_m; bool isAllPeriodic_m; - ippl::NDIndex domain_m; // Domain as index range - std::array decomp_m; // Domain Decomposition - T rhoNorm_m; // Rho norm, required for scatterCIC + ippl::NDIndex domain_m; // Domain as index range + std::array decomp_m; // Domain Decomposition + T rhoNorm_m; // Rho norm, required for scatterCIC public: size_type getTotalP() const { return totalP_m; } @@ -86,9 +91,9 @@ class P3MHeatingManager void setNt(int nt_) { nt_m = nt_; } - const Vector_t &getNr() const { return nr_m; } + const Vector_t& getNr() const { return nr_m; } - void setNr(const Vector_t &nr_) { nr_m = nr_; } + void setNr(const Vector_t& nr_) { nr_m = nr_; } T getTime() const { return time_m; } @@ -103,10 +108,10 @@ class P3MHeatingManager this->decomp_m.fill(true); // this->alpha_m = 2./this->rcut_m; - T box_length = this->boxlen_m; - this->rmin_m = Vector_t(-box_length / 2.); - this->rmax_m = Vector_t(box_length / 2.); - this->origin_m = rmin_m; + T box_length = this->boxlen_m; + this->rmin_m = Vector_t(-box_length / 2.); + this->rmax_m = Vector_t(box_length / 2.); + this->origin_m = rmin_m; this->isAllPeriodic_m = true; for (unsigned d = 0; d < Dim; ++d) { @@ -116,28 +121,21 @@ class P3MHeatingManager m << "hr: " << this->hr_m << endl; // initialize time stuff - this->it_m = 0; + this->it_m = 0; this->time_m = 0.; // initialize field container - this->setFieldContainer( - std::make_shared( - this->hr_m, this->rmin_m, this->rmax_m, this->decomp_m, - this->domain_m, this->origin_m, this->isAllPeriodic_m - ) - ); + this->setFieldContainer(std::make_shared( + this->hr_m, this->rmin_m, this->rmax_m, this->decomp_m, this->domain_m, this->origin_m, + this->isAllPeriodic_m)); // Set Particle Container (to P3MParticleContainer) - this->setParticleContainer( - std::make_shared( - this->fcontainer_m->getMesh(), this->fcontainer_m->getFL(), this->rcut_m - ) - ); + this->setParticleContainer(std::make_shared( + this->fcontainer_m->getMesh(), this->fcontainer_m->getFL(), this->rcut_m)); // m << "Device Space: " << Device::name() << endl; // m << "Host Space: " << Host::name() << endl; - this->fcontainer_m->initializeFields("P3M"); // initialize solver @@ -150,27 +148,19 @@ class P3MHeatingManager sp.add("comm", ippl::p2p_pl); sp.add("r2c_direction", 0); sp.add("alpha", this->alpha_m); - sp.add("force_constant", static_cast(2.532638e8)); // ke + sp.add("force_constant", static_cast(2.532638e8)); // ke - - this->setFieldSolver( - std::make_shared >( - this->fcontainer_m->getE(), this->fcontainer_m->getRho(), sp - ) - ); + this->setFieldSolver(std::make_shared >( + this->fcontainer_m->getE(), this->fcontainer_m->getRho(), sp)); ippl::ParameterList ppInteractionParams; ppInteractionParams.add("rcut", this->rcut_m); ppInteractionParams.add("alpha", this->alpha_m); - ppInteractionParams.add("force_constant", static_cast(2.532638e8)); // ke - - this->setInteractionSolver( - std::make_shared( - *this->pcontainer_m, this->pcontainer_m->E, this->pcontainer_m->R, this->pcontainer_m->Q, - ppInteractionParams - ) - ); + ppInteractionParams.add("force_constant", static_cast(2.532638e8)); // ke + this->setInteractionSolver(std::make_shared( + *this->pcontainer_m, this->pcontainer_m->E, this->pcontainer_m->R, + this->pcontainer_m->Q, ppInteractionParams)); static IpplTimings::TimerRef particleInitTimer = IpplTimings::getTimer("particle_init"); IpplTimings::startTimer(particleInitTimer); @@ -195,29 +185,30 @@ class P3MHeatingManager void computeBeamStatistics() { Inform m("ComputeBeamStatistics"); - const auto R = this->pcontainer_m->R.getView(); + const auto R = this->pcontainer_m->R.getView(); const auto nLoc = this->pcontainer_m->getLocalNum(); - const auto P = this->pcontainer_m->P.getView(); + const auto P = this->pcontainer_m->P.getView(); // const T beamRad = this->beamRad_m; Vector_t stats(0.0); - Kokkos::parallel_reduce("compute sigma x", nLoc, - KOKKOS_LAMBDA(const size_type i, Vector_t &sum) { - sum[0] += R(i)[0] * R(i)[0]; - sum[1] += P(i)[0] * P(i)[0]; - sum[2] += R(i)[0] * P(i)[0]; - sum[3] += R(i)[1] * R(i)[1]; - sum[4] += P(i)[1] * P(i)[1]; - sum[5] += R(i)[1] * P(i)[1]; - sum[6] += R(i)[2] * R(i)[2]; - sum[7] += P(i)[2] * P(i)[2]; - sum[8] += R(i)[2] * P(i)[2]; - sum[9] += R(i)[0]; - sum[10] += R(i)[1]; - sum[11] += R(i)[2]; - }, stats - ); + Kokkos::parallel_reduce( + "compute sigma x", nLoc, + KOKKOS_LAMBDA(const size_type i, Vector_t& sum) { + sum[0] += R(i)[0] * R(i)[0]; + sum[1] += P(i)[0] * P(i)[0]; + sum[2] += R(i)[0] * P(i)[0]; + sum[3] += R(i)[1] * R(i)[1]; + sum[4] += P(i)[1] * P(i)[1]; + sum[5] += R(i)[1] * P(i)[1]; + sum[6] += R(i)[2] * R(i)[2]; + sum[7] += P(i)[2] * P(i)[2]; + sum[8] += R(i)[2] * P(i)[2]; + sum[9] += R(i)[0]; + sum[10] += R(i)[1]; + sum[11] += R(i)[2]; + }, + stats); Kokkos::fence(); Vector_t global_stats(0.0); @@ -229,9 +220,12 @@ class P3MHeatingManager const T sigma_x = Kokkos::sqrt(global_stats[0] - global_stats[9] * global_stats[9]); const T sigma_y = Kokkos::sqrt(global_stats[3] - global_stats[10] * global_stats[10]); const T sigma_z = Kokkos::sqrt(global_stats[6] - global_stats[11] * global_stats[11]); - const T emit_x = Kokkos::sqrt(global_stats[0] * global_stats[1] - global_stats[2] * global_stats[2]); - const T emit_y = Kokkos::sqrt(global_stats[3] * global_stats[4] - global_stats[5] * global_stats[5]); - const T emit_z = Kokkos::sqrt(global_stats[6] * global_stats[7] - global_stats[8] * global_stats[8]); + const T emit_x = + Kokkos::sqrt(global_stats[0] * global_stats[1] - global_stats[2] * global_stats[2]); + const T emit_y = + Kokkos::sqrt(global_stats[3] * global_stats[4] - global_stats[5] * global_stats[5]); + const T emit_z = + Kokkos::sqrt(global_stats[6] * global_stats[7] - global_stats[8] * global_stats[8]); // T beta = avg_xsq / emit_x; // T sigma_x = Kokkos::sqrt(avg_xsq); @@ -244,13 +238,11 @@ class P3MHeatingManager Inform m("computeTemperature"); Vector_t avgVel(0.0); const auto nLoc = this->pcontainer_m->getLocalNum(); - const auto P = this->pcontainer_m->P.getView(); + const auto P = this->pcontainer_m->P.getView(); - Kokkos::parallel_reduce("compute average velocity", nLoc, - KOKKOS_LAMBDA(const size_type i, Vector_t &sum) { - sum += P(i); - }, avgVel - ); + Kokkos::parallel_reduce( + "compute average velocity", nLoc, + KOKKOS_LAMBDA(const size_type i, Vector_t& sum) { sum += P(i); }, avgVel); Kokkos::fence(); ippl::Comm->allreduce(avgVel[0], 3, std::plus()); @@ -265,11 +257,12 @@ class P3MHeatingManager Vector_t localTemperature(0.0); Vector_t globalTemperature(0.0); - Kokkos::parallel_reduce("compute temperature", nLoc, - KOKKOS_LAMBDA(const size_type i, Vector_t &sum) { - sum += (P(i) - avgVel) * (P(i) - avgVel); // remove mean transportation - }, localTemperature - ); + Kokkos::parallel_reduce( + "compute temperature", nLoc, + KOKKOS_LAMBDA(const size_type i, Vector_t& sum) { + sum += (P(i) - avgVel) * (P(i) - avgVel); // remove mean transportation + }, + localTemperature); Kokkos::fence(); ippl::Comm->reduce(&localTemperature[0], &globalTemperature[0], 3, std::plus(), 0); @@ -291,7 +284,7 @@ class P3MHeatingManager Inform m("Initialize Particles"); int commSize = ippl::Comm->size(); - int rank = ippl::Comm->rank(); + int rank = ippl::Comm->rank(); static IpplTimings::TimerRef ITimer = IpplTimings::getTimer("initializeParticles"); static IpplTimings::TimerRef CTimer = IpplTimings::getTimer("particleCreation"); @@ -300,13 +293,13 @@ class P3MHeatingManager IpplTimings::startTimer(ITimer); - unsigned np = this->totalP_m; + unsigned np = this->totalP_m; unsigned nloc = np / commSize; this->Q_m = np; // make sure all particles are accounted for - //if(rank == commSize-1){ + // if(rank == commSize-1){ // nloc = np - (commSize-1)*nloc; //} @@ -334,8 +327,7 @@ class P3MHeatingManager IpplTimings::startTimer(GTimer); Kokkos::parallel_for( - "initialize particles", nloc, - KOKKOS_LAMBDA(const size_t index) { + "initialize particles", nloc, KOKKOS_LAMBDA(const size_t index) { Vector_t x(0.0); auto generator = rand_pool.get_state(); @@ -350,10 +342,11 @@ class P3MHeatingManager // calculate position T normsq = x[0] * x[0] + x[1] * x[1] + x[2] * x[2]; - Vector_t pos = beamRad * (Kokkos::pow(u, 1. / 3.) / Kokkos::sqrt(normsq)) * x; + Vector_t pos = + beamRad * (Kokkos::pow(u, 1. / 3.) / Kokkos::sqrt(normsq)) * x; for (unsigned d = 0; d < Dim; ++d) { - P(index)[d] = 0; // initialize with zero momentum + P(index)[d] = 0; // initialize with zero momentum R(index)[d] = pos[d]; } Q(index) = 1; @@ -374,9 +367,7 @@ class P3MHeatingManager IpplTimings::stopTimer(ITimer); } - void pre_step() override { - Inform m("pre step"); - } + void pre_step() override { Inform m("pre step"); } void post_step() override { Inform m("post step"); @@ -387,28 +378,22 @@ class P3MHeatingManager this->it_m++; } - void grid2par() override { - gatherCIC(); - } + void grid2par() override { gatherCIC(); } - void par2grid() override { - scatterCIC(); - } + void par2grid() override { scatterCIC(); } - void advance() override { - LeapFrogStep(); - } + void advance() override { LeapFrogStep(); } void LeapFrogStep() { Inform m("LeapFrogStep"); - T dt = this->dt_m; + T dt = this->dt_m; auto pc = this->pcontainer_m; auto fc = this->fcontainer_m; - static IpplTimings::TimerRef PTimer = IpplTimings::getTimer("pushVelocity"); - static IpplTimings::TimerRef RTimer = IpplTimings::getTimer("pushPosition"); - static IpplTimings::TimerRef updateTimer = IpplTimings::getTimer("update"); - static IpplTimings::TimerRef PPSolveTimer = IpplTimings::getTimer("PPInteraction"); + static IpplTimings::TimerRef PTimer = IpplTimings::getTimer("pushVelocity"); + static IpplTimings::TimerRef RTimer = IpplTimings::getTimer("pushPosition"); + static IpplTimings::TimerRef updateTimer = IpplTimings::getTimer("update"); + static IpplTimings::TimerRef PPSolveTimer = IpplTimings::getTimer("PPInteraction"); static IpplTimings::TimerRef FieldSolveTimer = IpplTimings::getTimer("FieldSolve"); IpplTimings::startTimer(RTimer); @@ -444,17 +429,18 @@ class P3MHeatingManager Inform m("computeAvgSpaceChargeForces"); const auto totalP = this->totalP_m; - const auto nLoc = this->pcontainer_m->getLocalNum(); - const auto E = this->pcontainer_m->E.getView(); + const auto nLoc = this->pcontainer_m->getLocalNum(); + const auto E = this->pcontainer_m->E.getView(); Vector_t avgE(0.0); - Kokkos::parallel_reduce("compute average space charge forces", nLoc, - KOKKOS_LAMBDA(const size_type i, Vector_t &sum) { - sum[0] += Kokkos::abs(E(i)[0]); - sum[1] += Kokkos::abs(E(i)[1]); - sum[2] += Kokkos::abs(E(i)[2]); - }, avgE - ); + Kokkos::parallel_reduce( + "compute average space charge forces", nLoc, + KOKKOS_LAMBDA(const size_type i, Vector_t& sum) { + sum[0] += Kokkos::abs(E(i)[0]); + sum[1] += Kokkos::abs(E(i)[1]); + sum[2] += Kokkos::abs(E(i)[2]); + }, + avgE); Kokkos::fence(); ippl::Comm->allreduce(avgE[0], 3, std::plus()); @@ -471,40 +457,36 @@ class P3MHeatingManager const auto E = this->pcontainer_m->E.getView(); const auto R = this->pcontainer_m->R.getView(); - const T beamRad = this->beamRad_m; + const T beamRad = this->beamRad_m; const T focusStrength = this->focusingF_m; - const auto nLoc = this->pcontainer_m->getLocalNum(); + const auto nLoc = this->pcontainer_m->getLocalNum(); m << "Focusing Force " << focusStrength << endl; - Kokkos::parallel_for("apply constant focusing", nLoc, - KOKKOS_LAMBDA(const size_type &i) { - Vector_t F = focusStrength * (R(i) / beamRad); - // TODO if Q would not be all ones, this should involve Q somehow? - E(i) += F; - } - ); + Kokkos::parallel_for( + "apply constant focusing", nLoc, KOKKOS_LAMBDA(const size_type& i) { + Vector_t F = focusStrength * (R(i) / beamRad); + // TODO if Q would not be all ones, this should involve Q somehow? + E(i) += F; + }); Kokkos::fence(); } void gatherCIC() { - gather(this->pcontainer_m->E, - this->fcontainer_m->getE(), - this->pcontainer_m->R - ); + gather(this->pcontainer_m->E, this->fcontainer_m->getE(), this->pcontainer_m->R); } void scatterCIC() { Inform m("scatter "); this->fcontainer_m->getRho() = 0.0; - ippl::ParticleAttrib *q = &this->pcontainer_m->Q; - typename ParticleContainer_t::particle_position_type *R = &this->pcontainer_m->R; - auto rho = &this->fcontainer_m->getRho(); - T Q = this->Q_m; - Vector_t rmin = this->rmin_m; - Vector_t rmax = this->rmax_m; - Vector_t hr = this->hr_m; + ippl::ParticleAttrib* q = &this->pcontainer_m->Q; + typename ParticleContainer_t::particle_position_type* R = &this->pcontainer_m->R; + auto rho = &this->fcontainer_m->getRho(); + T Q = this->Q_m; + Vector_t rmin = this->rmin_m; + Vector_t rmax = this->rmax_m; + Vector_t hr = this->hr_m; scatter(*q, *rho, *R); T relError = std::fabs((Q - (*rho).sum()) / Q); @@ -520,14 +502,14 @@ class P3MHeatingManager if (TotalParticles != totalP_m || relError > 1e-10) { m << "Time step: " << it_m << endl; m << "Total particles in the sim. " << totalP_m << " " - << "after update: " << TotalParticles << endl; + << "after update: " << TotalParticles << endl; m << "Rel. error in charge conservation: " << relError << endl; ippl::Comm->abort(); } } T cellVolume = std::reduce(hr.begin(), hr.end(), 1., std::multiplies()); - (*rho) = (*rho) / cellVolume; + (*rho) = (*rho) / cellVolume; rhoNorm_m = norm(*rho); diff --git a/examples/collisions/P3MParticleContainer.hpp b/examples/collisions/P3MParticleContainer.hpp index 9d964e3e9..196892e77 100644 --- a/examples/collisions/P3MParticleContainer.hpp +++ b/examples/collisions/P3MParticleContainer.hpp @@ -1,44 +1,48 @@ #ifndef IPPL_P3M_PARTICLE_CONTAINER #define IPPL_P3M_PARTICLE_CONTAINER +#include +#include #include -#include "Manager/BaseManager.h" + #include "datatypes.h" -#include -#include + +#include "Manager/BaseManager.h" #include "Particle/ParticleSpatialOverlapLayout.h" /** * @class P3MParticleContainer * @brief Particle Container Class for running P3M Simulations (in 3D). - * + * * @tparam T The data type for simulation variables * @tparam Dim The dimensionality of the simulation -*/ + */ -template -class P3MParticleContainer : public ippl::ParticleBase > { +template +class P3MParticleContainer : public ippl::ParticleBase> { public: - template - using PLayout_t = ippl::ParticleSpatialOverlapLayout >; + template + using PLayout_t = ippl::ParticleSpatialOverlapLayout>; - using Base = ippl::ParticleBase>; + using Base = ippl::ParticleBase>; using Vector = ippl::Vector; using particle_neighbor_list_type = typename PLayout_t::particle_neighbor_list_type; using particle_vector_type = typename Base::particle_position_type; using particle_scalar_type = ippl::ParticleAttrib; + public: - particle_scalar_type Q; // charge - particle_vector_type P; // particle velocity - particle_vector_type E; // electric field at particle position + particle_scalar_type Q; // charge + particle_vector_type P; // particle velocity + particle_vector_type E; // electric field at particle position private: - PLayout_t pl_m; // Particle layout + PLayout_t pl_m; // Particle layout public: - P3MParticleContainer(Mesh_t &mesh, FieldLayout_t &FL, const T &rcutoff) : pl_m(FL, mesh, rcutoff) { + P3MParticleContainer(Mesh_t& mesh, FieldLayout_t& FL, const T& rcutoff) + : pl_m(FL, mesh, rcutoff) { this->initialize(pl_m); registerAttributes(); diff --git a/examples/collisions/datatypes.h b/examples/collisions/datatypes.h index f12f25162..68b0c0272 100644 --- a/examples/collisions/datatypes.h +++ b/examples/collisions/datatypes.h @@ -24,10 +24,10 @@ using size_type = ippl::detail::size_type; template using Vector = ippl::Vector; -template +template using Field = ippl::Field, Centering_t, ViewArgs...>; -template +template using ORB = ippl::OrthogonalRecursiveBisection, T>; template @@ -39,7 +39,7 @@ using Vector_t = ippl::Vector; template using Field_t = Field; -template +template using VField_t = Field, Dim, ViewArgs...>; template @@ -52,7 +52,9 @@ using FFTSolver_t = ConditionalType, Field_t>>; template -using P3MSolver_t = ConditionalType, Field_t>>; +using P3MSolver_t = + ConditionalType, Field_t>>; template using OpenSolver_t = @@ -67,4 +69,4 @@ const double pi = Kokkos::numbers::pi_v; extern const char* TestName; -#endif // IPPL_DATATYPES_H +#endif // IPPL_DATATYPES_H diff --git a/src/Communicate/Archive.hpp b/src/Communicate/Archive.hpp index 77758f55f..a8ebfea65 100644 --- a/src/Communicate/Archive.hpp +++ b/src/Communicate/Archive.hpp @@ -86,8 +86,7 @@ namespace ippl { template template void Archive::deserialize(Kokkos::View*, ViewArgs...>& view, - size_type nrecvs) - { + size_type nrecvs) { // if we have to enlarge the destination view if (nrecvs > view.extent(0)) { Kokkos::realloc(view, nrecvs); diff --git a/src/Communicate/Status.h b/src/Communicate/Status.h index bfc206ca7..cfd7dc70f 100644 --- a/src/Communicate/Status.h +++ b/src/Communicate/Status.h @@ -15,7 +15,7 @@ namespace ippl { public: Status() : status_m() - , count_m(-1){}; + , count_m(-1) {}; Status(const Status&) = default; diff --git a/src/Communicate/Tags.h b/src/Communicate/Tags.h index f744839e0..38b8a4369 100644 --- a/src/Communicate/Tags.h +++ b/src/Communicate/Tags.h @@ -44,7 +44,7 @@ namespace ippl { FEMVECTOR = 40000 }; } // namespace tag - } // namespace mpi + } // namespace mpi } // namespace ippl #endif diff --git a/src/Communicate/Window.h b/src/Communicate/Window.h index e6f2a3669..b9da32762 100644 --- a/src/Communicate/Window.h +++ b/src/Communicate/Window.h @@ -96,7 +96,7 @@ namespace ippl { bool allocated_m; }; } // namespace rma - } // namespace mpi + } // namespace mpi } // namespace ippl #include "Communicate/Window.hpp" diff --git a/src/Communicate/Window.hpp b/src/Communicate/Window.hpp index 6e0a6a634..a83f1c626 100644 --- a/src/Communicate/Window.hpp +++ b/src/Communicate/Window.hpp @@ -179,5 +179,5 @@ namespace ippl { } } // namespace rma - } // namespace mpi + } // namespace mpi } // namespace ippl diff --git a/src/FEM/Elements/Element.h b/src/FEM/Elements/Element.h index 32a062149..2159f3045 100644 --- a/src/FEM/Elements/Element.h +++ b/src/FEM/Elements/Element.h @@ -27,14 +27,14 @@ namespace ippl { // Cannot define common functions to all Element child classes // due to problem with accessing the Element functions through - // the Finite Element Space class from device code + // the Finite Element Space class from device code // (defaults to base class virtual function which causes errors) - // + // // The common functions would be globalToLocal, localToGlobal, // getDeterminantOfTransformationJacobian, getInverseTransposeTransformationJacobian, // and isPointInRefElement. // - // Virtual functions would be getLocalVertices, getTransformationJacobian, + // Virtual functions would be getLocalVertices, getTransformationJacobian, // and getInverseTransformationJacobian. }; diff --git a/src/FEM/FEMInterpolate.hpp b/src/FEM/FEMInterpolate.hpp index ded9729e8..7f60685ac 100644 --- a/src/FEM/FEMInterpolate.hpp +++ b/src/FEM/FEMInterpolate.hpp @@ -1,45 +1,39 @@ #ifndef IPPL_FEMINTERPOLATE_H #define IPPL_FEMINTERPOLATE_H - namespace ippl { - /** - * @brief Mapping from global position to element ND index and - * reference coordinates (xi ∈ [0,1)^Dim) on a UniformCartesian mesh. - * - * Assumes the input x is strictly inside the computational domain so that - * for each dimension d: 0 ≤ (x[d]-origin[d])/h[d] < nr[d]-1. - */ + /** + * @brief Mapping from global position to element ND index and + * reference coordinates (xi ∈ [0,1)^Dim) on a UniformCartesian mesh. + * + * Assumes the input x is strictly inside the computational domain so that + * for each dimension d: 0 ≤ (x[d]-origin[d])/h[d] < nr[d]-1. + */ template - KOKKOS_INLINE_FUNCTION void - locate_element_nd_and_xi(const Vector& hr, - const Vector& origin, - const Vector& x, - Vector& e_nd, - Vector& xi) { - + KOKKOS_INLINE_FUNCTION void locate_element_nd_and_xi(const Vector& hr, + const Vector& origin, + const Vector& x, + Vector& e_nd, + Vector& xi) { for (unsigned d = 0; d < Dim; ++d) { - const T s = (x[d] - origin[d]) / hr[d]; // To cell units + const T s = (x[d] - origin[d]) / hr[d]; // To cell units const size_t e = static_cast(Kokkos::floor(s)); - e_nd[d] = e; - xi[d] = s - static_cast(e); + e_nd[d] = e; + xi[d] = s - static_cast(e); } } - - template - KOKKOS_INLINE_FUNCTION - auto view_ptr_impl(View& v, const IVec& I, std::index_sequence) - -> decltype(&v(I[Is]...)) { - return &v(I[Is]...); + template + KOKKOS_INLINE_FUNCTION auto view_ptr_impl(View& v, const IVec& I, std::index_sequence) + -> decltype(&v(I[Is]...)) { + return &v(I[Is]...); } - template - KOKKOS_INLINE_FUNCTION - auto view_ptr(View& v, const IVec& I) - -> decltype(view_ptr_impl(v, I, std::make_index_sequence{})) { - return view_ptr_impl(v, I, std::make_index_sequence{}); + template + KOKKOS_INLINE_FUNCTION auto view_ptr(View& v, const IVec& I) + -> decltype(view_ptr_impl(v, I, std::make_index_sequence{})) { + return view_ptr_impl(v, I, std::make_index_sequence{}); } /** @@ -56,31 +50,29 @@ namespace ippl { * @tparam policy_type Kokkos execution policy (defaults to Field::execution_space) */ template > - inline void assemble_rhs_from_particles(const AttribIn& attrib, Field& f, - const PosAttrib& pp, const Space& space, - policy_type iteration_policy) - { + typename policy_type = Kokkos::RangePolicy> + inline void assemble_rhs_from_particles(const AttribIn& attrib, Field& f, const PosAttrib& pp, + const Space& space, policy_type iteration_policy) { constexpr unsigned Dim = Field::dim; - using T = typename Field::value_type; - using view_type = typename Field::view_type; - using mesh_type = typename Field::Mesh_t; + using T = typename Field::value_type; + using view_type = typename Field::view_type; + using mesh_type = typename Field::Mesh_t; static IpplTimings::TimerRef t = IpplTimings::getTimer("assemble_rhs_from_particles(P1)"); IpplTimings::startTimer(t); view_type view = f.getView(); - + // Mesh / layout (for locating + indexing into the field view) mesh_type& mesh = f.get_mesh(); - const auto hr = mesh.getMeshSpacing(); + const auto hr = mesh.getMeshSpacing(); const auto origin = mesh.getOrigin(); FieldLayout& layout = f.getLayout(); const NDIndex& lDom = layout.getLocalNDIndex(); - const int nghost = f.getNghost(); + const int nghost = f.getNghost(); Field lumpedMass(mesh, layout); space.evaluateLumpedMass(lumpedMass); @@ -94,10 +86,10 @@ namespace ippl { // make device copy of space auto device_space = space.getDeviceMirror(); - Kokkos::parallel_for("assemble_rhs_from_particles_P1", iteration_policy, - KOKKOS_LAMBDA(const size_t p) { + Kokkos::parallel_for( + "assemble_rhs_from_particles_P1", iteration_policy, KOKKOS_LAMBDA(const size_t p) { const Vector x = d_pos(p); - const T val = d_attr(p); + const T val = d_attr(p); Vector e_nd; Vector xi; @@ -109,12 +101,12 @@ namespace ippl { // Deposit into each vertex/DOF for (size_t a = 0; a < dofs.dim; ++a) { - const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); - const T w = device_space.evaluateRefElementShapeFunction(local, xi); + const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); + const T w = device_space.evaluateRefElementShapeFunction(local, xi); // ND coords (global, vertex-centered) const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]); - Vector I; // indices into view + Vector I; // indices into view for (unsigned d = 0; d < Dim; ++d) { I[d] = static_cast(v_nd[d] - lDom[d].first() + nghost); @@ -123,25 +115,22 @@ namespace ippl { Kokkos::atomic_add(view_ptr(view, I), val * w / m); } - } - ); + }); static IpplTimings::TimerRef accumulateHaloTimer = IpplTimings::getTimer("accumulateHalo"); IpplTimings::startTimer(accumulateHaloTimer); f.accumulateHalo(); IpplTimings::stopTimer(accumulateHaloTimer); - } - template - KOKKOS_INLINE_FUNCTION - decltype(auto) view_ref_impl(View& v, const IVec& I, std::index_sequence) { + template + KOKKOS_INLINE_FUNCTION decltype(auto) view_ref_impl(View& v, const IVec& I, + std::index_sequence) { return v(I[Is]...); } - template - KOKKOS_INLINE_FUNCTION - decltype(auto) view_ref(View& v, const IVec& I) { + template + KOKKOS_INLINE_FUNCTION decltype(auto) view_ref(View& v, const IVec& I) { return view_ref_impl(v, I, std::make_index_sequence{}); } @@ -160,31 +149,28 @@ namespace ippl { */ template > - inline void interpolate_to_diracs(AttribOut& attrib_out, - const Field& coeffs, - const PosAttrib& pp, - const Space& space, - policy_type iteration_policy) - { + inline void interpolate_to_diracs(AttribOut& attrib_out, const Field& coeffs, + const PosAttrib& pp, const Space& space, + policy_type iteration_policy) { constexpr unsigned Dim = Field::dim; - using T = typename AttribOut::value_type; - using field_value_type = typename Field::value_type; - using view_type = typename Field::view_type; - using mesh_type = typename Field::Mesh_t; + using T = typename AttribOut::value_type; + using field_value_type = typename Field::value_type; + using view_type = typename Field::view_type; + using mesh_type = typename Field::Mesh_t; static IpplTimings::TimerRef timer = IpplTimings::getTimer("interpolate_field_to_particles(P1)"); IpplTimings::startTimer(timer); - view_type view = coeffs.getView(); + view_type view = coeffs.getView(); const mesh_type& mesh = coeffs.get_mesh(); - const auto hr = mesh.getMeshSpacing(); + const auto hr = mesh.getMeshSpacing(); const auto origin = mesh.getOrigin(); const FieldLayout& layout = coeffs.getLayout(); - const NDIndex& lDom = layout.getLocalNDIndex(); - const int nghost = coeffs.getNghost(); + const NDIndex& lDom = layout.getLocalNDIndex(); + const int nghost = coeffs.getNghost(); // Particle device views auto d_pos = pp.getView(); @@ -193,33 +179,33 @@ namespace ippl { // make device copy of space auto device_space = space.getDeviceMirror(); - Kokkos::parallel_for("interpolate_to_diracs_P1", iteration_policy, - KOKKOS_LAMBDA(const size_t p) { + Kokkos::parallel_for( + "interpolate_to_diracs_P1", iteration_policy, KOKKOS_LAMBDA(const size_t p) { + const Vector x = d_pos(p); - const Vector x = d_pos(p); + Vector e_nd; + Vector xi; + locate_element_nd_and_xi(hr, origin, x, e_nd, xi); - Vector e_nd; - Vector xi; - locate_element_nd_and_xi(hr, origin, x, e_nd, xi); + const auto dofs = device_space.getGlobalDOFIndices(e_nd); - const auto dofs = device_space.getGlobalDOFIndices(e_nd); + field_value_type up = field_value_type(0); - field_value_type up = field_value_type(0); + for (size_t a = 0; a < dofs.dim; ++a) { + const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); + const field_value_type w = + device_space.evaluateRefElementShapeFunction(local, xi); - for (size_t a = 0; a < dofs.dim; ++a) { - const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); - const field_value_type w = device_space.evaluateRefElementShapeFunction(local, xi); + const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]); + Vector I; + for (unsigned d = 0; d < Dim; ++d) { + I[d] = static_cast(v_nd[d] - lDom.first()[d] + nghost); + } - const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]); - Vector I; - for (unsigned d = 0; d < Dim; ++d) { - I[d] = static_cast(v_nd[d] - lDom.first()[d] + nghost); + up += view_ref(view, I) * w; } - - up += view_ref(view, I) * w; - } - d_out(p) = static_cast(up); - }); + d_out(p) = static_cast(up); + }); } /** @@ -237,35 +223,33 @@ namespace ippl { */ template > - inline void interpolate_grad_to_diracs(AttribOut& attrib_out, - const Field& coeffs, - const PosAttrib& pp, - const Space& space, - policy_type iteration_policy) - { + inline void interpolate_grad_to_diracs(AttribOut& attrib_out, const Field& coeffs, + const PosAttrib& pp, const Space& space, + policy_type iteration_policy) { constexpr unsigned Dim = Field::dim; - using T = typename Field::value_type; - using view_type = typename Field::view_type; - using mesh_type = typename Field::Mesh_t; + using T = typename Field::value_type; + using view_type = typename Field::view_type; + using mesh_type = typename Field::Mesh_t; static IpplTimings::TimerRef timer = IpplTimings::getTimer("interpolate_field_to_particles(P1)"); IpplTimings::startTimer(timer); // Compute Inverse Transpose Transformation Jacobian () - const auto firstElementVertexPoints = space.getElementMeshVertexPoints(Vector(0)); + const auto firstElementVertexPoints = + space.getElementMeshVertexPoints(Vector(0)); const Vector DPhiInvT = space.getInverseTransposeTransformationJacobian(firstElementVertexPoints); - view_type view = coeffs.getView(); + view_type view = coeffs.getView(); const mesh_type& mesh = coeffs.get_mesh(); - const auto hr = mesh.getMeshSpacing(); + const auto hr = mesh.getMeshSpacing(); const auto origin = mesh.getOrigin(); const FieldLayout& layout = coeffs.getLayout(); - const NDIndex& lDom = layout.getLocalNDIndex(); - const int nghost = coeffs.getNghost(); + const NDIndex& lDom = layout.getLocalNDIndex(); + const int nghost = coeffs.getNghost(); // Particle device views auto d_pos = pp.getView(); @@ -274,37 +258,37 @@ namespace ippl { // make device copy of space auto device_space = space.getDeviceMirror(); - Kokkos::parallel_for("interpolate_to_diracs_P1", iteration_policy, - KOKKOS_LAMBDA(const size_t p) { + Kokkos::parallel_for( + "interpolate_to_diracs_P1", iteration_policy, KOKKOS_LAMBDA(const size_t p) { + const Vector x = d_pos(p); - const Vector x = d_pos(p); + Vector e_nd; + Vector xi; + locate_element_nd_and_xi(hr, origin, x, e_nd, xi); - Vector e_nd; - Vector xi; - locate_element_nd_and_xi(hr, origin, x, e_nd, xi); + const auto dofs = device_space.getGlobalDOFIndices(e_nd); - const auto dofs = device_space.getGlobalDOFIndices(e_nd); + Vector up(0.0); - Vector up(0.0); + for (size_t a = 0; a < dofs.dim; ++a) { + const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); + Vector w = + device_space.evaluateRefElementShapeFunctionGradient(local, xi); + w = DPhiInvT * w; - for (size_t a = 0; a < dofs.dim; ++a) { - const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]); - Vector w = device_space.evaluateRefElementShapeFunctionGradient(local, xi); - w = DPhiInvT * w; + const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]); + Vector I; + for (unsigned d = 0; d < Dim; ++d) { + I[d] = static_cast(v_nd[d] - lDom.first()[d] + nghost); + } - const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]); - Vector I; - for (unsigned d = 0; d < Dim; ++d) { - I[d] = static_cast(v_nd[d] - lDom.first()[d] + nghost); + // negative as E = -grad(phi), but in the future this should be + // more general (maybe bool to say whether we want negative or positive?) + up += -(view_ref(view, I) * w); } - - // negative as E = -grad(phi), but in the future this should be - // more general (maybe bool to say whether we want negative or positive?) - up += -(view_ref(view, I) * w); - } - d_out(p) = up; - }); + d_out(p) = up; + }); } -} // namespace ippl +} // namespace ippl #endif diff --git a/src/FEM/FEMVector.h b/src/FEM/FEMVector.h index df09b86c6..b770b5229 100644 --- a/src/FEM/FEMVector.h +++ b/src/FEM/FEMVector.h @@ -1,51 +1,51 @@ // Class FEMVector -// This class represents a one dimensional vector which can be used in the +// This class represents a one dimensional vector which can be used in the // context of FEM to represent a field defined on the DOFs of a mesh. - #ifndef IPPL_FEMVECTOR_H #define IPPL_FEMVECTOR_H #include "Types/ViewTypes.h" + #include "Field/HaloCells.h" namespace ippl { /** * @brief 1D vector used in the context of FEM. - * + * * This class represents a 1D vector which stores elements of type \p T and * provides functionalities to handle halo cells and their exchanges. * It can conceptually be though of being a mathemtical vector, and to this * extend is used during fem to represent the vectors \f$x\f$, \f$b\f$ when * solving the linear system \f$Ax = b\f$. - * + * * We use this instead of an \c ippl::Field, because for basis * functions which have DoFs at non-vertex positions a representation as a * field is not easily possible. - * + * * @tparam T The datatype which the vector is storing. */ template - class FEMVector : public detail::Expression< - FEMVector, - sizeof(typename detail::ViewType::view_type)>{ + class FEMVector + : public detail::Expression, + sizeof(typename detail::ViewType::view_type)> { public: /** * @brief Dummy parameter in order for the \p detail::Expression defined * operators to work. - * + * * In the file IpplOperations.h a bunch of operations are defined, we * want to be able to use them with a \c FEMVector, the problem is that * they require the class to have a \p dim parameter, therefore we have * one here. */ static constexpr unsigned dim = 1; - + /** * @brief Dummy type definition in order for the \p detail::Expression * defined operators to work. - * + * * In the file IpplOperations.h a bunch of operations are defined, we * want to be able to use them with a \c FEMVector, the problem is that * they require the class to define a \p value_type type. So therefore @@ -55,10 +55,10 @@ namespace ippl { /** * @brief Constructor taking size, neighbors, and halo exchange indices. - * + * * Constructor of a FEMVector taking in the size and information about - * the neighboring MPI ranks. - * + * the neighboring MPI ranks. + * * @param n The size of the vector. * @param neighbors The ranks of the neighboring MPI tasks. * @param sendIdxs The indices for which the data should be sent to the @@ -66,25 +66,23 @@ namespace ippl { * @param recvIdxs The halo cell indices. */ FEMVector(size_t n, std::vector neighbors, - std::vector< Kokkos::View > sendIdxs, - std::vector< Kokkos::View > recvIdxs); - - + std::vector > sendIdxs, + std::vector > recvIdxs); + /** * @brief Copy constructor (shallow). - * + * * Creates a shallow copy of the other vector, by copying the underlying * \c Kokkos::View and boundary infromation. - * + * * @param other The other vector we are copying from. */ KOKKOS_FUNCTION FEMVector(const FEMVector& other); - /** * @brief Constructor only taking size, does not create any MPI/boundary * information. - * + * * This constructor only takes the size of the vector and allocates the * appropriate number of elements, it does not sotre any MPI * communication or boundary infromation. This constructor is useful @@ -92,11 +90,10 @@ namespace ippl { * for any communication. */ FEMVector(size_t n); - /** * @brief Copy values from neighboring ranks into local halo. - * + * * This function takes the local values which are part of other ranks * halos and copies them to the corresponding halo cells of those * neighbors. @@ -105,7 +102,7 @@ namespace ippl { /** * @brief Accumulate halo values in neighbor. - * + * * This function takes the local halo values (which are part of another * ranks values) and sums them to these corresponding values of the * neighbor ranks. @@ -114,176 +111,157 @@ namespace ippl { /** * @brief Set the halo cells to \p setValue. - * + * * @param setValue The value to which the halo cells should be set. */ void setHalo(T setValue); - /** * @brief Set all the values of the vector to \p value. - * + * * Sets all the values in the vector to \p value this also includes the * halo cells. - * + * * @param value The value to which the entries should be set. */ - FEMVector& operator= (T value); - + FEMVector& operator=(T value); /** * @brief Set all the values of this vector to the values of the * expression. - * + * * Set the values of this vector to the values of \p expr - * + * * @param expr The expression from which to copy the values - * + * * @note Here we have to check how efficient this is, because in theory * we are copying a FEMVector onto the device when we are calling the * operator[] function inside of the Kokkos::parallel_for. */ template - FEMVector& operator= (const detail::Expression& expr); + FEMVector& operator=(const detail::Expression& expr); - /** * @brief Copy the values from another \c FEMVector to this one. - * + * * Sets the element values of this vector to the ones of \p v, only the * values are set everything else (MPI config, boundaries) are ignored. - * + * * @param v The other vector to copy values from. - */ - FEMVector& operator= (const FEMVector& v); - - + */ + FEMVector& operator=(const FEMVector& v); /** * @brief Subscript operator to get value at position \p i. - * + * * This function returns the value of the vector at index \p i, it is * equivalent to \p FEMVector::operator(). - * + * * @param i The index off the value to retrieve. */ - KOKKOS_INLINE_FUNCTION T operator[] (size_t i) const; - + KOKKOS_INLINE_FUNCTION T operator[](size_t i) const; /** * @brief Subscript operator to get value at position \p i. - * + * * This function returns the value of the vector at index \p i, it is * equivalent to \p FEMVector::operator(). - * + * * @param i The index off the value to retrieve. */ - KOKKOS_INLINE_FUNCTION T operator() (size_t i) const; - + KOKKOS_INLINE_FUNCTION T operator()(size_t i) const; /** * @brief Get underlying data view. - * + * * Returns a constant reference to the underlying data the FEMVector is * storing, this corresponds to a \c Kokkos::View living on the default * device. */ const Kokkos::View& getView() const; - /** * @brief Get the size (number of elements) of the vector. */ size_t size() const; - /** * @brief Create a deep copy, where all the information of this vector * is copied to a new one. - * + * * Returns a \c FEMVector which is an exact copy of this one. All the * information (elements, MPI information, etc.) are explicitly copied * (i.e. deep copy). - * + * * @returns An exact copy of this vector - */ + */ FEMVector deepCopy() const; - /** * @brief Create a new \c FEMVector with different data type, but same * size and boundary infromation. - * + * * This function is used to create a new \c FEMVector with same size and - * boundary infromation, but of different data type. The boundary + * boundary infromation, but of different data type. The boundary * information is copied over via a deep copy fashion. - * + * * @tparam K The data type of the new vector. - * + * * @returns A vector of same structure but new data type. */ template FEMVector skeletonCopy() const; - /** * @brief Pack data into \p BoundaryInfo::commBuffer_m for * MPI communication. - * + * * This function takes data from the vector accoding to \p idxStore and * stores it inside of \p BoundaryInfo::commBuffer_m. - * + * * @param idxStore A 1D Kokkos view which stores the the indices for * \p FEMVector::data_m which we want to send. */ void pack(const Kokkos::View& idxStore); - - + /** * @brief Unpack data from \p BoundaryInfo::commBuffer_m into * \p FEMVector::data_m after communication. - * + * * This function takes data from \p BoundaryInfo::commBuffer_m and stores * it accoding to \p idxStore in * \p FEMVector::data_m. - * + * * @param idxStore A 1D Kokkos view which stores the the indices for * \p FEMVector::data_m to which we want to store. - * + * * @tparam Op The operator to use in order to update the values in * \p FEMVector::data_m. */ template void unpack(const Kokkos::View& idxStore); - /** * @brief Struct for assigment operator to be used with * \p FEMVector::unpack(). */ - struct Assign{ - KOKKOS_INLINE_FUNCTION void operator()(T& lhs, const T& rhs) const { - lhs = rhs; - } + struct Assign { + KOKKOS_INLINE_FUNCTION void operator()(T& lhs, const T& rhs) const { lhs = rhs; } }; - /** * @brief Struct for addition+assignment operator to be used with * \p FEMVector::unpack(). */ - struct AssignAdd{ - KOKKOS_INLINE_FUNCTION void operator()(T& lhs, const T& rhs) const { - lhs += rhs; - } + struct AssignAdd { + KOKKOS_INLINE_FUNCTION void operator()(T& lhs, const T& rhs) const { lhs += rhs; } }; - private: /** * @brief Structure holding MPI neighbor and boundary information. - * - * This struct holds all the information regarding MPI (neighbor list, + * + * This struct holds all the information regarding MPI (neighbor list, * indecies which need to be exchanged...) and additionaly boundary * information, like what type of boundary we have. The \c FEMVector * class then has a pointer to an object of this, the reason behind is @@ -291,26 +269,24 @@ namespace ippl { * without having to worry about copying much additional information. */ struct BoundaryInfo { - /** * @brief constructor for a \c BoundaryInfo object. - * + * * Constructor to be used to create an object of type * \c BoundaryInfo. - * + * * @param neighbors The ranks of the neighboring MPI tasks. * @param sendIdxs The indices for which the data should be sent to * the MPI neighbors. - * @param recvIdxs The halo cell indices. + * @param recvIdxs The halo cell indices. */ - BoundaryInfo (std::vector neighbors, - std::vector< Kokkos::View > sendIdxs, - std::vector< Kokkos::View > recvIdxs_m); + BoundaryInfo(std::vector neighbors, + std::vector > sendIdxs, + std::vector > recvIdxs_m); - /** * @brief Stores the ranks of the neighboring MPI tasks. - * + * * A vector storing the ranks of the neighboring MPI tasks. This is * used during halo operators in combination with * \p BoundaryInfo::sendIdxs_m and @@ -322,39 +298,38 @@ namespace ippl { /** * @brief Stores indices of \p FEMVector::data_m which need to be * send to the MPI neighbors. - * + * * This is a 2D list which stores the indices of the * \p FEMVector::data_m variable which need to be sent to the MPI * neighbors. The first dimension goes over all the neighbors and * should be used in combination with \p BoundaryInfo::neighbors_m * while the second dimension goes over the actual indices. - * + * * This corresponds to the indices which belong to this rank but are * shared by the halos of the other ranks. */ - std::vector< Kokkos::View > sendIdxs_m; + std::vector > sendIdxs_m; /** * @brief Stores indices of \p FEMVector::data_m which are part of * the halo. - * + * * This is a 2D list which stores the indices of the * \p FEMVector::data_m variable which are part of the halo. The * first dimension goes over all the * neighbors and should be used in combination with * \p BoundaryInfo::neighbors_m while the second dimension goes * over the actual indices. - * + * * It is called recvIdxs to be in line with * \c ippl::detail::HaloCells and because it stores the indices for * which we recive data from the neighbors. */ - std::vector< Kokkos::View > recvIdxs_m; - + std::vector > recvIdxs_m; /** * @brief Buffer for MPI communication. - * + * * This buffer is used during MPI communication in order to store * the values which should be send to the neighbors. We are using a * \c ippl::detail::FieldBufferData even though we do not have a @@ -363,42 +338,39 @@ namespace ippl { */ detail::FieldBufferData commBuffer_m; }; - + /** * @brief Data this object is storing. - * + * * The data which the \c FEMVector is storing, it is represented by a * one dimensional \c Kokkos::View and lives on the default device. */ Kokkos::View data_m; - /** * @brief Struct holding all the MPI and boundary information. - * + * * Pointer to a struct holding all the information required for MPI * communication and general boundary information. The reason for it * beeing a pointer, is such that when this \c FEMVector object is - * copied to device only a pointer and not all the data needs to be + * copied to device only a pointer and not all the data needs to be * copied to device. */ std::shared_ptr boundaryInfo_m; - }; - /** * @brief Calculate the inner product between two \c ippl::FEMVector(s). - * + * * Calculates the inner product \f$ a^T b\f$ between the * \c ippl::FEMVector(s) \p a and \p b. Note that during the * inner product computations the halo cells are included, if this should * not be the case the hallo cells should be set to 0 using the * \p ippl::FEMVector::setHalo() function. - * + * * @param a First field. * @param b Second field. - * + * * @return The value \f$a^Tb\f$. */ template @@ -407,14 +379,11 @@ namespace ippl { auto aView = a.getView(); auto bView = b.getView(); - size_t n = aView.extent(0); - Kokkos::parallel_reduce("FEMVector innerProduct", n, - KOKKOS_LAMBDA(const size_t i, T& val){ - val += aView(i)*bView(i); - }, - Kokkos::Sum(localSum) - ); + Kokkos::parallel_reduce( + "FEMVector innerProduct", n, + KOKKOS_LAMBDA(const size_t i, T& val) { val += aView(i) * bView(i); }, + Kokkos::Sum(localSum)); T globalSum = 0; ippl::Comm->allreduce(localSum, globalSum, 1, std::plus()); @@ -423,37 +392,35 @@ namespace ippl { template T norm(const FEMVector& v, int p = 2) { - - T local = 0; + T local = 0; auto view = v.getView(); - size_t n = view.extent(0); + size_t n = view.extent(0); switch (p) { case 0: { - Kokkos::parallel_reduce("FEMVector l0 norm", n, + Kokkos::parallel_reduce( + "FEMVector l0 norm", n, KOKKOS_LAMBDA(const size_t i, T& val) { val = Kokkos::max(val, Kokkos::abs(view(i))); }, - Kokkos::Max(local) - ); + Kokkos::Max(local)); T globalMax = 0; ippl::Comm->allreduce(local, globalMax, 1, std::greater()); return globalMax; } default: { - Kokkos::parallel_reduce("FEMVector lp norm", n, + Kokkos::parallel_reduce( + "FEMVector lp norm", n, KOKKOS_LAMBDA(const size_t i, T& val) { val += std::pow(Kokkos::abs(view(i)), p); }, - Kokkos::Sum(local) - ); + Kokkos::Sum(local)); T globalSum = 0; ippl::Comm->allreduce(local, globalSum, 1, std::plus()); return std::pow(globalSum, 1.0 / p); } } } -} // namespace ippl - +} // namespace ippl #include "FEMVector.hpp" diff --git a/src/FEM/FEMVector.hpp b/src/FEM/FEMVector.hpp index 7e94d2bee..0dbfab6ba 100644 --- a/src/FEM/FEMVector.hpp +++ b/src/FEM/FEMVector.hpp @@ -1,38 +1,30 @@ -namespace ippl{ +namespace ippl { template FEMVector::FEMVector(size_t n, std::vector neighbors, - std::vector< Kokkos::View > sendIdxs, - std::vector< Kokkos::View > recvIdxs) : - data_m("FEMVector::data", n), boundaryInfo_m(new BoundaryInfo(std::move(neighbors), - std::move(sendIdxs), std::move(recvIdxs))) { - - } - + std::vector > sendIdxs, + std::vector > recvIdxs) + : data_m("FEMVector::data", n) + , boundaryInfo_m( + new BoundaryInfo(std::move(neighbors), std::move(sendIdxs), std::move(recvIdxs))) {} template - FEMVector::FEMVector(size_t n) : data_m("FEMVector::data", n), boundaryInfo_m(nullptr){ - - } - + FEMVector::FEMVector(size_t n) + : data_m("FEMVector::data", n) + , boundaryInfo_m(nullptr) {} - template - KOKKOS_FUNCTION - FEMVector::FEMVector(const FEMVector& other) : data_m(other.data_m), - boundaryInfo_m(other.boundaryInfo_m) { - - } - + KOKKOS_FUNCTION FEMVector::FEMVector(const FEMVector& other) + : data_m(other.data_m) + , boundaryInfo_m(other.boundaryInfo_m) {} template FEMVector::BoundaryInfo::BoundaryInfo(std::vector neighbors, - std::vector< Kokkos::View > sendIdxs, - std::vector< Kokkos::View > recvIdxs) : - neighbors_m(neighbors), sendIdxs_m(sendIdxs), recvIdxs_m(recvIdxs) { - - } - + std::vector > sendIdxs, + std::vector > recvIdxs) + : neighbors_m(neighbors) + , sendIdxs_m(sendIdxs) + , recvIdxs_m(recvIdxs) {} template void FEMVector::fillHalo() { @@ -51,33 +43,32 @@ namespace ippl{ // Send loop. for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { size_t neighborRank = boundaryInfo_m->neighbors_m[i]; - size_t nsends = boundaryInfo_m->sendIdxs_m[i].extent(0); - size_t tag = mpi::tag::FEMVECTOR + ippl::Comm->rank(); - + size_t nsends = boundaryInfo_m->sendIdxs_m[i].extent(0); + size_t tag = mpi::tag::FEMVECTOR + ippl::Comm->rank(); + // pack data, i.e., copy values from data_m to commBuffer_m pack(boundaryInfo_m->sendIdxs_m[i]); - // ippl MPI communication which sends data to neighbors mpi::Communicator::buffer_type archive = ippl::Comm->getBuffer(nsends); ippl::Comm->isend(neighborRank, tag, boundaryInfo_m->commBuffer_m, *archive, - requests[i], nsends); + requests[i], nsends); archive->resetWritePos(); } // Recieve loop for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { size_t neighborRank = boundaryInfo_m->neighbors_m[i]; - size_t nrecvs = boundaryInfo_m->recvIdxs_m[i].extent(0); - size_t tag = mpi::tag::FEMVECTOR + boundaryInfo_m->neighbors_m[i]; + size_t nrecvs = boundaryInfo_m->recvIdxs_m[i].extent(0); + size_t tag = mpi::tag::FEMVECTOR + boundaryInfo_m->neighbors_m[i]; // ippl MPI communication which will recive data from neighbors, // will put data into commBuffer_m mpi::Communicator::buffer_type archive = ippl::Comm->getBuffer(nrecvs); ippl::Comm->recv(neighborRank, tag, boundaryInfo_m->commBuffer_m, *archive, - nrecvs * sizeof(T), nrecvs); + nrecvs * sizeof(T), nrecvs); archive->resetReadPos(); // unpack recieved data, i.e., copy from commBuffer_m to data_m @@ -90,7 +81,6 @@ namespace ippl{ ippl::Comm->freeAllBuffers(); } - template void FEMVector::accumulateHalo() { // check that we have halo information @@ -108,33 +98,32 @@ namespace ippl{ // Send loop. for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { size_t neighborRank = boundaryInfo_m->neighbors_m[i]; - size_t nsends = boundaryInfo_m->recvIdxs_m[i].extent(0); - size_t tag = mpi::tag::FEMVECTOR + ippl::Comm->rank(); - + size_t nsends = boundaryInfo_m->recvIdxs_m[i].extent(0); + size_t tag = mpi::tag::FEMVECTOR + ippl::Comm->rank(); + // pack data, i.e., copy values from data_m to commBuffer_m pack(boundaryInfo_m->recvIdxs_m[i]); - // ippl MPI communication which sends data to neighbors mpi::Communicator::buffer_type archive = ippl::Comm->getBuffer(nsends); ippl::Comm->isend(neighborRank, tag, boundaryInfo_m->commBuffer_m, *archive, - requests[i], nsends); + requests[i], nsends); archive->resetWritePos(); } // Receive loop for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { size_t neighborRank = boundaryInfo_m->neighbors_m[i]; - size_t nrecvs = boundaryInfo_m->sendIdxs_m[i].extent(0); - size_t tag = mpi::tag::FEMVECTOR + boundaryInfo_m->neighbors_m[i]; + size_t nrecvs = boundaryInfo_m->sendIdxs_m[i].extent(0); + size_t tag = mpi::tag::FEMVECTOR + boundaryInfo_m->neighbors_m[i]; // ippl MPI communication which will receive data from neighbors, // will put data into commBuffer_m mpi::Communicator::buffer_type archive = ippl::Comm->getBuffer(nrecvs); ippl::Comm->recv(neighborRank, tag, boundaryInfo_m->commBuffer_m, *archive, - nrecvs * sizeof(T), nrecvs); + nrecvs * sizeof(T), nrecvs); archive->resetReadPos(); // unpack recieved data, i.e., copy from commBuffer_m to data_m @@ -147,7 +136,6 @@ namespace ippl{ ippl::Comm->freeAllBuffers(); } - template void FEMVector::setHalo(T setValue) { // check that we have halo information @@ -161,70 +149,55 @@ namespace ippl{ for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { auto& view = boundaryInfo_m->recvIdxs_m[i]; - Kokkos::parallel_for("FEMVector::setHalo()",view.extent(0), - KOKKOS_CLASS_LAMBDA(const size_t& j){ - data_m[view(j)] = setValue; - } - ); + Kokkos::parallel_for( + "FEMVector::setHalo()", view.extent(0), + KOKKOS_CLASS_LAMBDA(const size_t& j) { data_m[view(j)] = setValue; }); } } - template - FEMVector& FEMVector::operator= (T value) { - Kokkos::parallel_for("FEMVector::operator=(T value)", data_m.extent(0), - KOKKOS_CLASS_LAMBDA(const size_t& i){ - data_m[i] = value; - } - ); + FEMVector& FEMVector::operator=(T value) { + Kokkos::parallel_for( + "FEMVector::operator=(T value)", data_m.extent(0), + KOKKOS_CLASS_LAMBDA(const size_t& i) { data_m[i] = value; }); return *this; } - template template - FEMVector& FEMVector::operator= (const detail::Expression& expr) { + FEMVector& FEMVector::operator=(const detail::Expression& expr) { using capture_type = detail::CapturedExpression; capture_type expr_ = reinterpret_cast(expr); - Kokkos::parallel_for("FEMVector::operator=(Expression)", data_m.extent(0), - KOKKOS_CLASS_LAMBDA(const size_t& i){ - data_m[i] = expr_(i); - } - ); + Kokkos::parallel_for( + "FEMVector::operator=(Expression)", data_m.extent(0), + KOKKOS_CLASS_LAMBDA(const size_t& i) { data_m[i] = expr_(i); }); return *this; } - template - FEMVector& FEMVector::operator= (const FEMVector& v) { + FEMVector& FEMVector::operator=(const FEMVector& v) { auto view = v.getView(); - Kokkos::parallel_for("FEMVector::operator=(FEMVector)", data_m.extent(0), - KOKKOS_CLASS_LAMBDA(const size_t& i){ - data_m[i] = view(i); - } - ); + Kokkos::parallel_for( + "FEMVector::operator=(FEMVector)", data_m.extent(0), + KOKKOS_CLASS_LAMBDA(const size_t& i) { data_m[i] = view(i); }); return *this; } - template - KOKKOS_INLINE_FUNCTION T FEMVector::operator[] (size_t i) const { + KOKKOS_INLINE_FUNCTION T FEMVector::operator[](size_t i) const { return data_m(i); } - template - KOKKOS_INLINE_FUNCTION T FEMVector::operator() (size_t i) const { + KOKKOS_INLINE_FUNCTION T FEMVector::operator()(size_t i) const { return this->operator[](i); } - template const Kokkos::View& FEMVector::getView() const { return data_m; } - template size_t FEMVector::size() const { return data_m.extent(0); @@ -236,29 +209,31 @@ namespace ippl{ if (boundaryInfo_m) { // The neighbor_m can be simply passed to the new vector, the sendIdxs_m // and recvIdxs_m need to be explicitly copied. - std::vector< Kokkos::View > newSendIdxs; - std::vector< Kokkos::View > newRecvIdxs; - + std::vector > newSendIdxs; + std::vector > newRecvIdxs; + for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { - newSendIdxs.emplace_back(Kokkos::View(boundaryInfo_m->sendIdxs_m[i].label(), - boundaryInfo_m->sendIdxs_m[i].extent(0))); + newSendIdxs.emplace_back( + Kokkos::View(boundaryInfo_m->sendIdxs_m[i].label(), + boundaryInfo_m->sendIdxs_m[i].extent(0))); Kokkos::deep_copy(newSendIdxs[i], boundaryInfo_m->sendIdxs_m[i]); - - newRecvIdxs.emplace_back(Kokkos::View(boundaryInfo_m->recvIdxs_m[i].label(), - boundaryInfo_m->recvIdxs_m[i].extent(0))); - + + newRecvIdxs.emplace_back( + Kokkos::View(boundaryInfo_m->recvIdxs_m[i].label(), + boundaryInfo_m->recvIdxs_m[i].extent(0))); + Kokkos::deep_copy(newRecvIdxs[i], boundaryInfo_m->recvIdxs_m[i]); } // create the new FEMVector FEMVector newVector(size(), boundaryInfo_m->neighbors_m, newSendIdxs, newRecvIdxs); - // copy over the values + // copy over the values newVector = *this; return newVector; } else { FEMVector newVector(size()); - // copy over the values + // copy over the values newVector = *this; return newVector; @@ -272,17 +247,19 @@ namespace ippl{ if (boundaryInfo_m) { // The neighbor_m can be simply passed to the new vector, the sendIdxs_m // and recvIdxs_m need to be explicitly copied. - std::vector< Kokkos::View > newSendIdxs; - std::vector< Kokkos::View > newRecvIdxs; - + std::vector > newSendIdxs; + std::vector > newRecvIdxs; + for (size_t i = 0; i < boundaryInfo_m->neighbors_m.size(); ++i) { - newSendIdxs.emplace_back(Kokkos::View(boundaryInfo_m->sendIdxs_m[i].label(), - boundaryInfo_m->sendIdxs_m[i].extent(0))); + newSendIdxs.emplace_back( + Kokkos::View(boundaryInfo_m->sendIdxs_m[i].label(), + boundaryInfo_m->sendIdxs_m[i].extent(0))); Kokkos::deep_copy(newSendIdxs[i], boundaryInfo_m->sendIdxs_m[i]); - - newRecvIdxs.emplace_back(Kokkos::View(boundaryInfo_m->recvIdxs_m[i].label(), - boundaryInfo_m->recvIdxs_m[i].extent(0))); - + + newRecvIdxs.emplace_back( + Kokkos::View(boundaryInfo_m->recvIdxs_m[i].label(), + boundaryInfo_m->recvIdxs_m[i].extent(0))); + Kokkos::deep_copy(newRecvIdxs[i], boundaryInfo_m->recvIdxs_m[i]); } @@ -292,12 +269,11 @@ namespace ippl{ return newVector; } else { FEMVector newVector(size()); - + return newVector; } } - template void FEMVector::pack(const Kokkos::View& idxStore) { // check that we have halo information @@ -308,7 +284,7 @@ namespace ippl{ "Did you use the correct constructor to construct the FEMVector?"); } - size_t nIdxs = idxStore.extent(0); + size_t nIdxs = idxStore.extent(0); auto& bufferData = boundaryInfo_m->commBuffer_m.buffer; if (bufferData.size() < nIdxs) { @@ -316,15 +292,12 @@ namespace ippl{ Kokkos::realloc(bufferData, nIdxs * overalloc); } - Kokkos::parallel_for("FEMVector::pack()", nIdxs, - KOKKOS_CLASS_LAMBDA(const size_t& i) { - bufferData(i) = data_m(idxStore(i)); - } - ); + Kokkos::parallel_for( + "FEMVector::pack()", nIdxs, + KOKKOS_CLASS_LAMBDA(const size_t& i) { bufferData(i) = data_m(idxStore(i)); }); Kokkos::fence(); } - template template void FEMVector::unpack(const Kokkos::View& idxStore) { @@ -336,22 +309,18 @@ namespace ippl{ "Did you use the correct constructor to construct the FEMVector?"); } - size_t nIdxs = idxStore.extent(0); - auto& bufferData = boundaryInfo_m->commBuffer_m.buffer; + size_t nIdxs = idxStore.extent(0); + auto& bufferData = boundaryInfo_m->commBuffer_m.buffer; if (bufferData.size() < nIdxs) { int overalloc = Comm->getDefaultOverallocation(); Kokkos::realloc(bufferData, nIdxs * overalloc); } Op op; - Kokkos::parallel_for("FEMVector::unpack()", nIdxs, - KOKKOS_CLASS_LAMBDA(const size_t& i) { - op(data_m(idxStore(i)), bufferData(i)); - } - ); + Kokkos::parallel_for( + "FEMVector::unpack()", nIdxs, + KOKKOS_CLASS_LAMBDA(const size_t& i) { op(data_m(idxStore(i)), bufferData(i)); }); Kokkos::fence(); } - - -} // namespace ippl +} // namespace ippl diff --git a/src/FEM/FiniteElementSpace.h b/src/FEM/FiniteElementSpace.h index b0ea61539..944239fcd 100644 --- a/src/FEM/FiniteElementSpace.h +++ b/src/FEM/FiniteElementSpace.h @@ -187,7 +187,7 @@ namespace ippl { * @return size_t - The local DOF index */ KOKKOS_FUNCTION virtual size_t getLocalDOFIndex(const size_t& elementIndex, - const size_t& globalDOFIndex) const = 0; + const size_t& globalDOFIndex) const = 0; /** * @brief Get the global DOF index from the element index and local DOF @@ -219,7 +219,6 @@ namespace ippl { KOKKOS_FUNCTION virtual Vector getGlobalDOFIndices( const size_t& elementIndex) const = 0; - /////////////////////////////////////////////////////////////////////// /// Member variables ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// diff --git a/src/FEM/FiniteElementSpace.hpp b/src/FEM/FiniteElementSpace.hpp index 86b2eeba8..1f3892650 100644 --- a/src/FEM/FiniteElementSpace.hpp +++ b/src/FEM/FiniteElementSpace.hpp @@ -23,8 +23,7 @@ namespace ippl { template void FiniteElementSpace::setMesh(UniformCartesian& mesh) - { + FieldRHS>::setMesh(UniformCartesian& mesh) { assert(mesh.Dimension == Dim && "Mesh dimension does not match the dimension of the space"); mesh_m = mesh; diff --git a/src/FEM/LagrangeSpace.h b/src/FEM/LagrangeSpace.h index fbc6f2355..ff3c03c34 100644 --- a/src/FEM/LagrangeSpace.h +++ b/src/FEM/LagrangeSpace.h @@ -130,7 +130,7 @@ namespace ippl { * @return size_t - The local DOF index */ KOKKOS_FUNCTION size_t getLocalDOFIndex(const size_t& elementIndex, - const size_t& globalDOFIndex) const override; + const size_t& globalDOFIndex) const override; /** * @brief Get the global DOF index from the element index and local DOF @@ -195,7 +195,8 @@ namespace ippl { /// Functions to access element info from outside ///////////////////// /////////////////////////////////////////////////////////////////////// - KOKKOS_FUNCTION point_t getInverseTransposeTransformationJacobian(vertex_points_t pt) const { + KOKKOS_FUNCTION point_t + getInverseTransposeTransformationJacobian(vertex_points_t pt) const { return this->ref_element_m.getInverseTransposeTransformationJacobian(pt); } @@ -230,8 +231,8 @@ namespace ippl { FieldLHS evaluateAx_diag(FieldLHS& field, F& evalFunction); /** - * @brief Assemble the left stiffness matrix A of the system - * but only for the boundary values, so that they can be + * @brief Assemble the left stiffness matrix A of the system + * but only for the boundary values, so that they can be * subtracted from the RHS for treatment of Dirichlet BCs * * @param field The field to assemble the matrix for @@ -290,17 +291,17 @@ namespace ippl { KOKKOS_FUNCTION indices_t getMeshVertexNDIndex(const size_t& vertex_index) const; KOKKOS_FUNCTION size_t getLocalDOFIndex(const indices_t& elementNDIndex, - const size_t& globalDOFIndex) const; + const size_t& globalDOFIndex) const; KOKKOS_FUNCTION Vector getGlobalDOFIndices( const indices_t& elementNDIndex) const; KOKKOS_FUNCTION T evaluateRefElementShapeFunction(const size_t& localDOF, - const point_t& localPoint) const; + const point_t& localPoint) const; KOKKOS_FUNCTION point_t evaluateRefElementShapeFunctionGradient( const size_t& localDOF, const point_t& localPoint) const; }; - DeviceStruct getDeviceMirror() const; + DeviceStruct getDeviceMirror() const; private: /** diff --git a/src/FEM/LagrangeSpace.hpp b/src/FEM/LagrangeSpace.hpp index 26a7c1072..1a08ac80c 100644 --- a/src/FEM/LagrangeSpace.hpp +++ b/src/FEM/LagrangeSpace.hpp @@ -33,14 +33,13 @@ namespace ippl { "Finite Element space only supports 1D, 2D and 3D meshes"); } - // LagrangeSpace initializer, to be made available to the FEMPoissonSolver + // LagrangeSpace initializer, to be made available to the FEMPoissonSolver // such that we can call it from setRhs. // Sets the correct mesh ad decomposes the elements among ranks according to layout. template void LagrangeSpace::initialize( - UniformCartesian& mesh, Layout_t& layout) - { + UniformCartesian& mesh, Layout_t& layout) { FiniteElementSpace::setMesh(mesh); @@ -68,7 +67,7 @@ namespace ippl { int upperBoundaryPoints = -1; - // We iterate over the local domain points, getting the corresponding elements, + // We iterate over the local domain points, getting the corresponding elements, // while tagging upper boundary points such that they can be removed after. Kokkos::View points("npoints", npoints); Kokkos::parallel_reduce( @@ -124,9 +123,9 @@ namespace ippl { template - KOKKOS_FUNCTION - size_t LagrangeSpace::getLocalDOFIndex - (const size_t& elementIndex, const size_t& globalDOFIndex) const { + KOKKOS_FUNCTION size_t + LagrangeSpace::getLocalDOFIndex( + const size_t& elementIndex, const size_t& globalDOFIndex) const { static_assert(Dim == 1 || Dim == 2 || Dim == 3, "Dim must be 1, 2 or 3"); // TODO fix not order independent, only works for order 1 static_assert(Order == 1, "Only order 1 is supported at the moment"); @@ -136,16 +135,16 @@ namespace ippl { this->LagrangeSpace::getGlobalDOFIndices(elementIndex); // Find the global DOF in the vector and return the local DOF index - // Note: It is important that this only works because the global_dofs + // Note: It is important that this only works because the global_dofs // are already arranged in the correct order from getGlobalDOFIndices for (size_t i = 0; i < global_dofs.dim; ++i) { if (global_dofs[i] == globalDOFIndex) { return i; } } - // commented this due to this being on device + // commented this due to this being on device // however, it would be good to throw an error in this case - //throw IpplException("LagrangeSpace::getLocalDOFIndex()", + // throw IpplException("LagrangeSpace::getLocalDOFIndex()", // "FEM Lagrange Space: Global DOF not found in specified element"); return 0; } @@ -357,11 +356,11 @@ namespace ippl { Inform m(""); // declare timers - static IpplTimings::TimerRef evalAx = IpplTimings::getTimer("evaluateAx"); + static IpplTimings::TimerRef evalAx = IpplTimings::getTimer("evaluateAx"); static IpplTimings::TimerRef evalAx_outer = IpplTimings::getTimer("evaluateAx: outer loop"); - static IpplTimings::TimerRef evalAx_bc = IpplTimings::getTimer("evaluateAx: BCs"); + static IpplTimings::TimerRef evalAx_bc = IpplTimings::getTimer("evaluateAx: BCs"); static IpplTimings::TimerRef evalAx_setup = IpplTimings::getTimer("evaluateAx: setup"); - static IpplTimings::TimerRef accumHalo = IpplTimings::getTimer("evaluateAx: accumHalo"); + static IpplTimings::TimerRef accumHalo = IpplTimings::getTimer("evaluateAx: accumHalo"); // start a timer IpplTimings::startTimer(evalAx); @@ -408,7 +407,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain and ghost cell information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -427,7 +426,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -454,7 +453,7 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { I_nd[d] = I_nd[d] - ldom[d].first() + nghost; } - apply(resultView, I_nd) = apply(view, I_nd); + apply(resultView, I_nd) = apply(view, I_nd); continue; } else if ((bcType == ZERO_FACE) && (this->isDOFOnBoundary(I_nd))) { continue; @@ -469,7 +468,7 @@ namespace ippl { J_nd = global_dof_ndindices[j]; // Skip boundary DOFs (Zero & Constant Dirichlet BCs) - if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) + if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) && this->isDOFOnBoundary(J_nd)) { continue; } @@ -558,7 +557,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -572,7 +571,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -599,7 +598,7 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { I_nd[d] = I_nd[d] - ldom[d].first() + nghost; } - apply(resultView, I_nd) = apply(view, I_nd); + apply(resultView, I_nd) = apply(view, I_nd); continue; } else if ((bcType == ZERO_FACE) && (this->isDOFOnBoundary(I_nd))) { continue; @@ -618,7 +617,7 @@ namespace ippl { } // Skip boundary DOFs (Zero & Constant Dirichlet BCs) - if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) + if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) && this->isDOFOnBoundary(J_nd)) { continue; } @@ -700,7 +699,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -714,7 +713,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -741,7 +740,7 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { I_nd[d] = I_nd[d] - ldom[d].first() + nghost; } - apply(resultView, I_nd) = apply(view, I_nd); + apply(resultView, I_nd) = apply(view, I_nd); continue; } else if ((bcType == ZERO_FACE) && (this->isDOFOnBoundary(I_nd))) { continue; @@ -760,7 +759,7 @@ namespace ippl { } // Skip boundary DOFs (Zero & Constant Dirichlet BCs) - if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) + if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) && this->isDOFOnBoundary(J_nd)) { continue; } @@ -796,7 +795,8 @@ namespace ippl { Inform m(""); // declare timer - static IpplTimings::TimerRef evalAx_upperlower = IpplTimings::getTimer("evaluateAxUpperLower"); + static IpplTimings::TimerRef evalAx_upperlower = + IpplTimings::getTimer("evaluateAxUpperLower"); // start a timer IpplTimings::startTimer(evalAx_upperlower); @@ -842,7 +842,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -856,7 +856,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -883,7 +883,7 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { I_nd[d] = I_nd[d] - ldom[d].first() + nghost; } - apply(resultView, I_nd) = apply(view, I_nd); + apply(resultView, I_nd) = apply(view, I_nd); continue; } else if ((bcType == ZERO_FACE) && (this->isDOFOnBoundary(I_nd))) { continue; @@ -898,7 +898,7 @@ namespace ippl { J_nd = global_dof_ndindices[j]; // Skip boundary DOFs (Zero & Constant Dirichlet BCs) - if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) + if (((bcType == ZERO_FACE) || (bcType == CONSTANT_FACE)) && this->isDOFOnBoundary(J_nd)) { continue; } @@ -979,7 +979,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -993,7 +993,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -1045,7 +1045,8 @@ namespace ippl { // apply the inverse diagonal after already summed all contributions from element matrices using index_array_type = typename RangePolicy::index_array_type; - ippl::parallel_for("Loop over result view to apply inverse", field.getFieldRangePolicy(), + ippl::parallel_for( + "Loop over result view to apply inverse", field.getFieldRangePolicy(), KOKKOS_LAMBDA(const index_array_type& args) { if (apply(resultView, args) != 0.0) { apply(resultView, args) = (1.0 / apply(resultView, args)) * apply(view, args); @@ -1062,7 +1063,7 @@ namespace ippl { FieldLHS LagrangeSpace::evaluateAx_diag(FieldLHS& field, F& evalFunction) { Inform m(""); - + // declare timer static IpplTimings::TimerRef evalAx_diag = IpplTimings::getTimer("evaluateAxDiag"); @@ -1108,7 +1109,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); // Get domain information auto ldom = (field.getLayout()).getLocalNDIndex(); @@ -1122,7 +1123,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -1149,7 +1150,7 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { I_nd[d] = I_nd[d] - ldom[d].first() + nghost; } - apply(resultView, I_nd) = apply(view, I_nd); + apply(resultView, I_nd) = apply(view, I_nd); continue; } else if ((bcType == ZERO_FACE) && (this->isDOFOnBoundary(I_nd))) { continue; @@ -1240,7 +1241,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); Vector global_dof_ndindices; @@ -1282,7 +1283,6 @@ namespace ippl { apply(resultView, I_nd) += A_K[i][j] * apply(view, J_nd); continue; } - } } }); @@ -1333,7 +1333,7 @@ namespace ippl { // Get boundary conditions from field BConds& bcField = field.getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); FieldRHS temp_field(field.get_mesh(), field.getLayout(), nghost); temp_field.setFieldBC(bcField); @@ -1351,7 +1351,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); @@ -1396,7 +1396,6 @@ namespace ippl { // add the contribution of the element to the field apply(atomic_view, dof_ndindex_I) += contrib; - } }); temp_field.accumulateHalo(); @@ -1456,7 +1455,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->LagrangeSpace::getGlobalDOFIndices(elementIndex); @@ -1660,28 +1659,27 @@ namespace ippl { // Function to return the device struct of this Lagrange Space template - typename LagrangeSpace:: - DeviceStruct - LagrangeSpace:: - getDeviceMirror() const { + typename LagrangeSpace::DeviceStruct + LagrangeSpace::getDeviceMirror() + const { DeviceStruct space_mirror; - space_mirror.nr_m = this->nr_m; + space_mirror.nr_m = this->nr_m; space_mirror.ref_element_m = this->ref_element_m; return space_mirror; } // I don't know how to avoid code duplication here... - // Make sure that any changes in getLocalDOFIndex, getGlobalDOFIndices, + // Make sure that any changes in getLocalDOFIndex, getGlobalDOFIndices, // evaluateRefElementShapeFunction, and getMeshVertexNDIndex from the // parent class FiniteElementSpace get propagated here. template KOKKOS_FUNCTION size_t - LagrangeSpace:: - DeviceStruct::getLocalDOFIndex(const indices_t& elementNDIndex, - const size_t& globalDOFIndex) const { - + LagrangeSpace::DeviceStruct::getLocalDOFIndex(const indices_t& elementNDIndex, + const size_t& globalDOFIndex) const { static_assert(Dim == 1 || Dim == 2 || Dim == 3, "Dim must be 1, 2 or 3"); // TODO fix not order independent, only works for order 1 static_assert(Order == 1, "Only order 1 is supported at the moment"); @@ -1691,16 +1689,16 @@ namespace ippl { this->getGlobalDOFIndices(elementNDIndex); // Find the global DOF in the vector and return the local DOF index - // Note: It is important that this only works because the global_dofs + // Note: It is important that this only works because the global_dofs // are already arranged in the correct order from getGlobalDOFIndices for (size_t i = 0; i < global_dofs.dim; ++i) { if (global_dofs[i] == globalDOFIndex) { return i; } } - // commented this due to this being on device + // commented this due to this being on device // however, it would be good to throw an error in this case - //throw IpplException("LagrangeSpace::getLocalDOFIndex()", + // throw IpplException("LagrangeSpace::getLocalDOFIndex()", // "FEM Lagrange Space: Global DOF not found in specified element"); return 0; } @@ -1708,10 +1706,10 @@ namespace ippl { template KOKKOS_FUNCTION Vector::DeviceStruct::numElementDOFs> - LagrangeSpace:: - DeviceStruct::getGlobalDOFIndices(const indices_t& elementNDIndex) const { - + FieldLHS, FieldRHS>::DeviceStruct::numElementDOFs> + LagrangeSpace::DeviceStruct::getGlobalDOFIndices(const indices_t& elementNDIndex) + const { Vector globalDOFs(0); // Compute the vector to multiply the ndindex with @@ -1782,11 +1780,11 @@ namespace ippl { template KOKKOS_FUNCTION T - LagrangeSpace:: - DeviceStruct::evaluateRefElementShapeFunction(const size_t& localDOF, - const LagrangeSpace::DeviceStruct:: + evaluateRefElementShapeFunction( + const size_t& localDOF, + const LagrangeSpace::point_t& localPoint) const { - static_assert(Order == 1, "Only order 1 is supported at the moment"); // Assert that the local vertex index is valid. assert(localDOF < DeviceStruct::numElementDOFs @@ -1817,8 +1815,9 @@ namespace ippl { typename QuadratureType, typename FieldLHS, typename FieldRHS> KOKKOS_FUNCTION typename LagrangeSpace::point_t - LagrangeSpace:: - DeviceStruct::evaluateRefElementShapeFunctionGradient(const size_t& localDOF, + LagrangeSpace::DeviceStruct:: + evaluateRefElementShapeFunctionGradient( + const size_t& localDOF, const LagrangeSpace::point_t& localPoint) const { // TODO fix not order independent, only works for order 1 @@ -1869,10 +1868,10 @@ namespace ippl { template - KOKKOS_FUNCTION typename LagrangeSpace::indices_t - LagrangeSpace:: - DeviceStruct::getMeshVertexNDIndex(const size_t& vertex_index) const { + KOKKOS_FUNCTION typename LagrangeSpace::indices_t + LagrangeSpace::DeviceStruct::getMeshVertexNDIndex(const size_t& vertex_index) const { // Copy the vertex index to the index variable we can alter during the computation. size_t index = vertex_index; diff --git a/src/FEM/NedelecSpace.h b/src/FEM/NedelecSpace.h index 63d746506..7b41822ed 100644 --- a/src/FEM/NedelecSpace.h +++ b/src/FEM/NedelecSpace.h @@ -7,13 +7,13 @@ #include -#include "FEM/FiniteElementSpace.h" #include "FEM/FEMVector.h" +#include "FEM/FiniteElementSpace.h" constexpr unsigned getNedelecNumElementDOFs(unsigned Dim, [[maybe_unused]] unsigned Order) { // needs to be constexpr pow function to work at compile time. Kokkos::pow // doesn't work. - return static_cast(static_cast(Dim)*power(2, static_cast(Dim-1))); + return static_cast(static_cast(Dim) * power(2, static_cast(Dim - 1))); } namespace ippl { @@ -31,22 +31,25 @@ namespace ippl { template // requires IsQuadrature - class NedelecSpace : public FiniteElementSpace, FEMVector> { + class NedelecSpace + : public FiniteElementSpace, FEMVector> { public: // The number of degrees of freedom per element static constexpr unsigned numElementDOFs = getNedelecNumElementDOFs(Dim, Order); // The dimension of the mesh - static constexpr unsigned dim = FiniteElementSpace, FEMVector>::dim; + static constexpr unsigned dim = + FiniteElementSpace, + FEMVector>::dim; // The order of the Nedelec space static constexpr unsigned order = Order; // The number of mesh vertices per element - static constexpr unsigned numElementVertices = FiniteElementSpace, FEMVector>::numElementVertices; + static constexpr unsigned numElementVertices = + FiniteElementSpace, + FEMVector>::numElementVertices; // A vector with the position of the element in the mesh in each dimension typedef typename FiniteElementSpace, FEMVector>::point_t point_t; typedef typename FiniteElementSpace, FEMVector>::vertex_points_t vertex_points_t; + FEMVector, FEMVector>::vertex_points_t + vertex_points_t; // Field layout type for domain decomposition info typedef FieldLayout Layout_t; // View types typedef typename detail::ViewType::view_type ViewType; - typedef typename detail::ViewType>::view_type AtomicViewType; - - + typedef typename detail::ViewType>::view_type + AtomicViewType; /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////// @@ -82,7 +84,7 @@ namespace ippl { * @param layout Reference to the field layout */ NedelecSpace(UniformCartesian& mesh, ElementType& ref_element, - const QuadratureType& quadrature, const Layout_t& layout); + const QuadratureType& quadrature, const Layout_t& layout); /** * @brief Construct a new NedelecSpace object (without layout) @@ -94,7 +96,7 @@ namespace ippl { * @param quadrature Reference to the quadrature rule */ NedelecSpace(UniformCartesian& mesh, ElementType& ref_element, - const QuadratureType& quadrature); + const QuadratureType& quadrature); /** * @brief Initialize a NedelecSpace object created with the default @@ -131,7 +133,7 @@ namespace ippl { * @return size_t - The local DOF index */ KOKKOS_FUNCTION size_t getLocalDOFIndex(const size_t& elementIndex, - const size_t& globalDOFIndex) const override; + const size_t& globalDOFIndex) const override; /** * @brief Get the global DOF index from the element index and local DOF. @@ -142,7 +144,7 @@ namespace ippl { * @return size_t - The global DOF index */ KOKKOS_FUNCTION size_t getGlobalDOFIndex(const size_t& elementIndex, - const size_t& localDOFIndex) const override; + const size_t& localDOFIndex) const override; /** * @brief Get the local DOF indices (vector of local DOF indices) @@ -162,8 +164,8 @@ namespace ippl { * @return Vector - The global DOF indices */ KOKKOS_FUNCTION Vector getGlobalDOFIndices( - const size_t& elementIndex) const override; - + const size_t& elementIndex) const override; + /** * @brief Get the global DOF indices (vector of global DOF indices) of * an element. @@ -173,8 +175,8 @@ namespace ippl { * @return Vector - The global DOF indices */ KOKKOS_FUNCTION Vector getGlobalDOFIndices( - const indices_t& elementIndex) const; - + const indices_t& elementIndex) const; + /** * @brief Get the DOF indices (vector of indices) corresponding to the * position inside the FEMVector of an element @@ -184,7 +186,7 @@ namespace ippl { * @return Vector - The DOF indices */ KOKKOS_FUNCTION Vector getFEMVectorDOFIndices( - const size_t& elementIndex, NDIndex ldom) const; + const size_t& elementIndex, NDIndex ldom) const; /** * @brief Get the DOF indices (vector of indices) corresponding to the @@ -195,16 +197,15 @@ namespace ippl { * @return Vector - The DOF indices */ KOKKOS_FUNCTION Vector getFEMVectorDOFIndices( - indices_t elementIndex, NDIndex ldom) const; + indices_t elementIndex, NDIndex ldom) const; - /** * @brief Get the cartesion position of a local DOF in the reference * element. - * + * * Given the local DOF index this function will return the cartesian * position of this DOF with respect to the reference element. - * + * */ KOKKOS_FUNCTION point_t getLocalDOFPosition(size_t localDOFIndex) const; @@ -212,7 +213,6 @@ namespace ippl { /// Basis functions and gradients ///////////////////////////////////// /////////////////////////////////////////////////////////////////////// - /** * @brief Evaluate the shape function of a local degree of freedom at a * given point in the reference element @@ -224,8 +224,7 @@ namespace ippl { * @return T - The value of the shape function at the given point */ KOKKOS_FUNCTION point_t evaluateRefElementShapeFunction(const size_t& localDOF, - const point_t& localPoint) const; - + const point_t& localPoint) const; /** * @brief Evaluate the curl of the shape function of a local degree of @@ -238,9 +237,9 @@ namespace ippl { * @return point_t (Vector) - The curl of the shape function * at the given point */ - KOKKOS_FUNCTION point_t evaluateRefElementShapeFunctionCurl(const size_t& localDOF, - const point_t& localPoint) const; - + KOKKOS_FUNCTION point_t evaluateRefElementShapeFunctionCurl( + const size_t& localDOF, const point_t& localPoint) const; + /////////////////////////////////////////////////////////////////////// /// Assembly operations /////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// @@ -258,7 +257,7 @@ namespace ippl { /** * @brief Assemble the load vector b of the system Ax = b, given a field * of the right hand side defined at the Nédélec DOF positions. If a - * functor instead of a field should be used, use the function + * functor instead of a field should be used, use the function * \c NedelecSpace::evaluateLoadVectorFunctor. * * @param f The source field defined at the Nédélec degrees fo freedom. @@ -266,7 +265,6 @@ namespace ippl { * @return The resulting rhs b of the Galerkin discretization. */ FEMVector evaluateLoadVector(const FEMVector& f) const; - /** * @brief Assemble the load vector b of the system Ax = b, given a @@ -275,41 +273,38 @@ namespace ippl { * * @param f The source function, which can be evaluated at arbitrary * points. - * + * * @tparam F The functor type. - * + * * @return The resulting rhs b of the Galerkin discretization. */ template FEMVector evaluateLoadVectorFunctor(const F& f) const; - - /////////////////////////////////////////////////////////////////////// /// FEMVector conversion and creation////////////////////////////////// /////////////////////////////////////////////////////////////////////// - + /** * @brief Creates and empty FEMVector. - * + * * Creates and empty FEMVector which corresponds to the domain this MPI * rank owns (according to the ippl layout created for this mesh). To * this extend it will also setup all the information needed to exchange * halo cells. - * + * * @returns An empty FEMVector for this domain. */ FEMVector createFEMVector() const; - /** * @brief Reconstructs function values at arbitrary points in the mesh * given the Nedelec DOF coefficients. - * + * * This function can be used to retrieve the values of a solution * function at arbitrary points inside of the mesh given the Nedelec * DOF coefficients which solved the problem using FEM. - * + * * @note Currently the function is able to handle both cases, where we * have that \p positions only contains positions which are inside of * local domain of this MPI rank (i.e. each rank gets its own unique @@ -318,23 +313,22 @@ namespace ippl { * it can be guaranteed, that each rank will get its own \p positions * then certain parts of the function implementation can be removed. * Instructions for this are given in the implementation itself. - * + * * @param positions The points at which the function should be - * evaluated. A \c Kokkos::View which stores in each element a 2D/3D + * evaluated. A \c Kokkos::View which stores in each element a 2D/3D * point. * @param coef The basis function coefficients obtained via FEM. - * + * * @return The function evaluated at the given points, stored inside of * \c Kokkos::View where each element corresponts to the function value * at the point described by the same element inside of \p positions. */ Kokkos::View reconstructToPoints(const Kokkos::View& positions, - const FEMVector& coef) const; + const FEMVector& coef) const; /////////////////////////////////////////////////////////////////////// /// Error norm computations /////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// - /** * @brief Given the Nedelec space DoF coefficients and an analytical @@ -345,8 +339,8 @@ namespace ippl { * * @return error - The error ||u_h - u_sol||_L2 */ - template T computeError(const FEMVector& u_h, const F& u_sol) const; - + template + T computeError(const FEMVector& u_h, const F& u_sol) const; /** * @brief Check if a DOF is on the boundary of the mesh @@ -354,7 +348,7 @@ namespace ippl { * This function takes as input the global index of a DoF and returns * if this DoF is on. If one would like to know which boundary this is * the function \c NedelecSpace::getBoundarySide can be used. - * + * * @param dofIdx The global DoF index for which should be checked if it * is on the boundary. * @@ -363,30 +357,28 @@ namespace ippl { */ KOKKOS_FUNCTION bool isDOFOnBoundary(const size_t& dofIdx) const; - /** - * @brief Returns which side the boundary is on. - * - * This function takes as input the global index of a DoF and then - * returns on which side of the domain boundary it is on, in 2d that - * would be either south, north, west, east and in 3d space and ground is - * added. The mapping is as follows: - * 0 = south - * 1 = west - * 2 = north - * 3 = east - * 4 = ground - * 5 = space - * -1 = not on a boundary. - * - * @param dofIdx the global DoF index for which the boundary side should - * be retrieved. - * - * @returns Which boundary side the DoF is on or -1 if on no boundary. - */ + /** + * @brief Returns which side the boundary is on. + * + * This function takes as input the global index of a DoF and then + * returns on which side of the domain boundary it is on, in 2d that + * would be either south, north, west, east and in 3d space and ground is + * added. The mapping is as follows: + * 0 = south + * 1 = west + * 2 = north + * 3 = east + * 4 = ground + * 5 = space + * -1 = not on a boundary. + * + * @param dofIdx the global DoF index for which the boundary side should + * be retrieved. + * + * @returns Which boundary side the DoF is on or -1 if on no boundary. + */ KOKKOS_FUNCTION int getBoundarySide(const size_t& dofIdx) const; - - private: /** * @brief Implementation of the \c NedelecSpace::createFEMVector @@ -399,7 +391,7 @@ namespace ippl { * function for 3d. */ FEMVector createFEMVector3d() const; - + /** * @brief Stores which elements (squares or cubes) belong to the current * MPI rank. @@ -407,23 +399,22 @@ namespace ippl { Kokkos::View elementIndices; /** - * @brief Stores the positions of the local Degrees of Freedoms on the + * @brief Stores the positions of the local Degrees of Freedoms on the * reference elements. - * + * * We are saying that the local degree of freedom positions are simply - * the centers of the edges. + * the centers of the edges. */ Vector localDofPositions_m; - + /** * @brief The layout of the MPI ranks over the mesh. - * + * * Standart ippl layout which dictates how the MPI ranks are layed out * over the mesh. It is used in order to be able to create FEMVectors, * retreive correct DOF indices and intitalize the elementIndices. */ Layout_t layout_m; - }; } // namespace ippl diff --git a/src/FEM/NedelecSpace.hpp b/src/FEM/NedelecSpace.hpp index 8debd5e13..b32e0a4d1 100644 --- a/src/FEM/NedelecSpace.hpp +++ b/src/FEM/NedelecSpace.hpp @@ -5,15 +5,15 @@ namespace ippl { // and decomposes the elements among ranks according to layout. template - NedelecSpace - ::NedelecSpace(UniformCartesian& mesh, ElementType& ref_element, - const QuadratureType& quadrature, const Layout_t& layout) - : FiniteElementSpace, FEMVector> - (mesh, ref_element, quadrature) { + NedelecSpace::NedelecSpace( + UniformCartesian& mesh, ElementType& ref_element, const QuadratureType& quadrature, + const Layout_t& layout) + : FiniteElementSpace, FEMVector>(mesh, ref_element, + quadrature) { // Assert that the dimension is either 2 or 3. static_assert(Dim >= 2 && Dim <= 3, - "The Nedelec Finite Element space only supports 2D and3D meshes"); + "The Nedelec Finite Element space only supports 2D and3D meshes"); // Initialize the elementIndices view initializeElementIndices(layout); @@ -22,57 +22,62 @@ namespace ippl { // NedelecSpace constructor, which calls the FiniteElementSpace constructor. template - NedelecSpace - ::NedelecSpace(UniformCartesian& mesh, ElementType& ref_element, - const QuadratureType& quadrature) - : FiniteElementSpace, FEMVector> - (mesh, ref_element, quadrature) { - + NedelecSpace::NedelecSpace( + UniformCartesian& mesh, ElementType& ref_element, const QuadratureType& quadrature) + : FiniteElementSpace, FEMVector>(mesh, ref_element, + quadrature) { // Assert that the dimension is either 2 or 3. static_assert(Dim >= 2 && Dim <= 3, - "The Nedelec Finite Element space only supports 2D and 3D meshes"); + "The Nedelec Finite Element space only supports 2D and 3D meshes"); } - // NedelecSpace initializer, to be made available to the FEMPoissonSolver + // NedelecSpace initializer, to be made available to the FEMPoissonSolver // such that we can call it from setRhs. // Sets the correct mesh and decomposes the elements among ranks according to layout. template - void NedelecSpace - ::initialize(UniformCartesian& mesh, const Layout_t& layout) { - - FiniteElementSpace, FEMVector>::setMesh(mesh); + void NedelecSpace::initialize( + UniformCartesian& mesh, const Layout_t& layout) { + FiniteElementSpace, FEMVector>::setMesh(mesh); // Initialize the elementIndices view initializeElementIndices(layout); // set the local DOF position vector - localDofPositions_m(0)(0) = 0.5; - localDofPositions_m(1)(1) = 0.5; - localDofPositions_m(2)(0) = 0.5; localDofPositions_m(2)(1) = 1; - localDofPositions_m(3)(0) = 1; localDofPositions_m(3)(1) = 0.5; - localDofPositions_m(4)(2) = 0.5; - localDofPositions_m(5)(0) = 1; localDofPositions_m(5)(2) = 0.5; - localDofPositions_m(6)(0) = 1; localDofPositions_m(6)(1) = 1; - localDofPositions_m(6)(2) = 0.5; - localDofPositions_m(7)(1) = 1; localDofPositions_m(7)(2) = 0.5; - localDofPositions_m(8)(0) = 0.5; localDofPositions_m(8)(2) = 1; - localDofPositions_m(9)(1) = 0.5; localDofPositions_m(9)(2) = 1; - localDofPositions_m(10)(0) = 0.5; localDofPositions_m(10)(1) = 1; - localDofPositions_m(10)(2) = 1; - localDofPositions_m(11)(0) = 1; localDofPositions_m(11)(1) = 0.5; - localDofPositions_m(11)(2) = 1; + localDofPositions_m(0)(0) = 0.5; + localDofPositions_m(1)(1) = 0.5; + localDofPositions_m(2)(0) = 0.5; + localDofPositions_m(2)(1) = 1; + localDofPositions_m(3)(0) = 1; + localDofPositions_m(3)(1) = 0.5; + localDofPositions_m(4)(2) = 0.5; + localDofPositions_m(5)(0) = 1; + localDofPositions_m(5)(2) = 0.5; + localDofPositions_m(6)(0) = 1; + localDofPositions_m(6)(1) = 1; + localDofPositions_m(6)(2) = 0.5; + localDofPositions_m(7)(1) = 1; + localDofPositions_m(7)(2) = 0.5; + localDofPositions_m(8)(0) = 0.5; + localDofPositions_m(8)(2) = 1; + localDofPositions_m(9)(1) = 0.5; + localDofPositions_m(9)(2) = 1; + localDofPositions_m(10)(0) = 0.5; + localDofPositions_m(10)(1) = 1; + localDofPositions_m(10)(2) = 1; + localDofPositions_m(11)(0) = 1; + localDofPositions_m(11)(1) = 0.5; + localDofPositions_m(11)(2) = 1; } // Initialize element indices Kokkos View template - void NedelecSpace - ::initializeElementIndices(const Layout_t& layout) { - - layout_m = layout; + void NedelecSpace::initializeElementIndices(const Layout_t& layout) { + layout_m = layout; const auto& ldom = layout.getLocalNDIndex(); int npoints = ldom.size(); auto first = ldom.first(); @@ -116,8 +121,7 @@ namespace ippl { const size_t idx = Kokkos::atomic_fetch_add(&index(), 1); elementIndices(idx) = points(i); } - } - ); + }); } /////////////////////////////////////////////////////////////////////// @@ -126,15 +130,15 @@ namespace ippl { template - KOKKOS_FUNCTION size_t NedelecSpace - ::numGlobalDOFs() const { - + KOKKOS_FUNCTION size_t + NedelecSpace::numGlobalDOFs() const { size_t num_global_dofs = 0; - + for (size_t d = 0; d < Dim; ++d) { - size_t accu = this->nr_m[d]-1; + size_t accu = this->nr_m[d] - 1; for (size_t d2 = 0; d2 < Dim; ++d2) { - if (d == d2) continue; + if (d == d2) + continue; accu *= this->nr_m[d2]; } num_global_dofs += accu; @@ -145,10 +149,9 @@ namespace ippl { template - KOKKOS_FUNCTION size_t NedelecSpace - ::getLocalDOFIndex(const size_t& elementIndex, - const size_t& globalDOFIndex) const { - + KOKKOS_FUNCTION size_t + NedelecSpace::getLocalDOFIndex( + const size_t& elementIndex, const size_t& globalDOFIndex) const { static_assert(Dim == 2 || Dim == 3, "Dim must be 2 or 3"); // Get all the global DOFs for the element @@ -176,10 +179,9 @@ namespace ippl { template - KOKKOS_FUNCTION size_t NedelecSpace - ::getGlobalDOFIndex(const size_t& elementIndex, - const size_t& localDOFIndex) const { - + KOKKOS_FUNCTION size_t + NedelecSpace::getGlobalDOFIndex( + const size_t& elementIndex, const size_t& localDOFIndex) const { const auto global_dofs = this->NedelecSpace::getGlobalDOFIndices(elementIndex); return global_dofs[localDOFIndex]; @@ -187,11 +189,10 @@ namespace ippl { template - KOKKOS_FUNCTION Vector::numElementDOFs> - NedelecSpace - ::getLocalDOFIndices() const { - + KOKKOS_FUNCTION Vector< + size_t, NedelecSpace::numElementDOFs> + NedelecSpace::getLocalDOFIndices() + const { Vector localDOFs; for (size_t dof = 0; dof < numElementDOFs; ++dof) { @@ -203,31 +204,29 @@ namespace ippl { template - KOKKOS_FUNCTION Vector::numElementDOFs> - NedelecSpace - ::getGlobalDOFIndices(const NedelecSpace::indices_t& elementIndex) const { - - + KOKKOS_FUNCTION Vector< + size_t, NedelecSpace::numElementDOFs> + NedelecSpace::getGlobalDOFIndices( + const NedelecSpace::indices_t& + elementIndex) const { // These are simply some manual caclualtions that need to be done. - + Vector globalDOFs(0); // Initialize a helper vector v Vector v(1); if constexpr (Dim == 2) { size_t nx = this->nr_m[0]; - v(1) = 2*nx-1; + v(1) = 2 * nx - 1; } else if constexpr (Dim == 3) { size_t nx = this->nr_m[0]; size_t ny = this->nr_m[1]; - v(1) = 2*nx -1; - v(2) = 3*nx*ny - nx - ny; + v(1) = 2 * nx - 1; + v(2) = 3 * nx * ny - nx - ny; } // For both 2D and 3D the first few DOF indices are the same - size_t nx = this->nr_m[0]; + size_t nx = this->nr_m[0]; globalDOFs(0) = v.dot(elementIndex); globalDOFs(1) = globalDOFs(0) + nx - 1; globalDOFs(2) = globalDOFs(1) + nx; @@ -236,74 +235,67 @@ namespace ippl { if constexpr (Dim == 3) { size_t ny = this->nr_m[1]; - globalDOFs(4) = v(2)*elementIndex(2) + 2*nx*ny - nx - ny - + elementIndex(1)*nx + elementIndex(0); - globalDOFs(5) = globalDOFs(4) + 1; - globalDOFs(6) = globalDOFs(4) + nx + 1; - globalDOFs(7) = globalDOFs(4) + nx; - globalDOFs(8) = globalDOFs(0) + 3*nx*ny - nx - ny; - globalDOFs(9) = globalDOFs(8) + nx - 1; + globalDOFs(4) = v(2) * elementIndex(2) + 2 * nx * ny - nx - ny + elementIndex(1) * nx + + elementIndex(0); + globalDOFs(5) = globalDOFs(4) + 1; + globalDOFs(6) = globalDOFs(4) + nx + 1; + globalDOFs(7) = globalDOFs(4) + nx; + globalDOFs(8) = globalDOFs(0) + 3 * nx * ny - nx - ny; + globalDOFs(9) = globalDOFs(8) + nx - 1; globalDOFs(10) = globalDOFs(9) + nx; globalDOFs(11) = globalDOFs(9) + 1; } - return globalDOFs; } template - KOKKOS_FUNCTION Vector::numElementDOFs> - NedelecSpace - ::getGlobalDOFIndices(const size_t& elementIndex) const { - + KOKKOS_FUNCTION Vector< + size_t, NedelecSpace::numElementDOFs> + NedelecSpace::getGlobalDOFIndices( + const size_t& elementIndex) const { indices_t elementPos = this->getElementNDIndex(elementIndex); return getGlobalDOFIndices(elementPos); } - - template - KOKKOS_FUNCTION Vector::numElementDOFs> - NedelecSpace - ::getFEMVectorDOFIndices(NedelecSpace::indices_t elementIndex, - NDIndex ldom) const { - - + KOKKOS_FUNCTION Vector< + size_t, NedelecSpace::numElementDOFs> + NedelecSpace::getFEMVectorDOFIndices( + NedelecSpace::indices_t elementIndex, + NDIndex ldom) const { // This function here is pretty much the same as getGlobalDOFIndices() // the only difference is the domain size and that we have an offset // of the subdomain of the rank to the global one, else it is the same Vector FEMVectorDOFs(0); - + // This corresponds to translating a global element position to one in // the subdomain of the rank. For this we subtract the starting position // the rank subdomain and add the "ghost" hyperplane. elementIndex -= ldom.first(); elementIndex += 1; - + indices_t dif(0); dif = ldom.last() - ldom.first(); - dif += 1 + 2; // plus 1 for last still being in +2 for ghosts. - + dif += 1 + 2; // plus 1 for last still being in +2 for ghosts. + // From here on out it is pretty much the same as the // getGlobalDOFIndices() function. Vector v(1); if constexpr (Dim == 2) { size_t nx = dif[0]; - v(1) = 2*nx-1; + v(1) = 2 * nx - 1; } else if constexpr (Dim == 3) { size_t nx = dif[0]; size_t ny = dif[1]; - v(1) = 2*nx -1; - v(2) = 3*nx*ny - nx - ny; + v(1) = 2 * nx - 1; + v(2) = 3 * nx * ny - nx - ny; } - size_t nx = dif[0]; + size_t nx = dif[0]; FEMVectorDOFs(0) = v.dot(elementIndex); FEMVectorDOFs(1) = FEMVectorDOFs(0) + nx - 1; FEMVectorDOFs(2) = FEMVectorDOFs(1) + nx; @@ -312,58 +304,52 @@ namespace ippl { if constexpr (Dim == 3) { size_t ny = dif[1]; - FEMVectorDOFs(4) = v(2)*elementIndex(2) + 2*nx*ny - nx - ny - + elementIndex(1)*nx + elementIndex(0); - FEMVectorDOFs(5) = FEMVectorDOFs(4) + 1; - FEMVectorDOFs(6) = FEMVectorDOFs(4) + nx + 1; - FEMVectorDOFs(7) = FEMVectorDOFs(4) + nx; - FEMVectorDOFs(8) = FEMVectorDOFs(0) + 3*nx*ny - nx - ny; - FEMVectorDOFs(9) = FEMVectorDOFs(8) + nx - 1; + FEMVectorDOFs(4) = v(2) * elementIndex(2) + 2 * nx * ny - nx - ny + elementIndex(1) * nx + + elementIndex(0); + FEMVectorDOFs(5) = FEMVectorDOFs(4) + 1; + FEMVectorDOFs(6) = FEMVectorDOFs(4) + nx + 1; + FEMVectorDOFs(7) = FEMVectorDOFs(4) + nx; + FEMVectorDOFs(8) = FEMVectorDOFs(0) + 3 * nx * ny - nx - ny; + FEMVectorDOFs(9) = FEMVectorDOFs(8) + nx - 1; FEMVectorDOFs(10) = FEMVectorDOFs(9) + nx; FEMVectorDOFs(11) = FEMVectorDOFs(9) + 1; } - - + return FEMVectorDOFs; } template - KOKKOS_FUNCTION Vector::numElementDOFs> - NedelecSpace - ::getFEMVectorDOFIndices(const size_t& elementIndex, NDIndex ldom) const { - + KOKKOS_FUNCTION Vector< + size_t, NedelecSpace::numElementDOFs> + NedelecSpace::getFEMVectorDOFIndices( + const size_t& elementIndex, NDIndex ldom) const { // First get the global element position indices_t elementPos = this->getElementNDIndex(elementIndex); return getFEMVectorDOFIndices(elementPos, ldom); } - template - KOKKOS_FUNCTION typename NedelecSpace::point_t - NedelecSpace - ::getLocalDOFPosition(size_t localDOFIndex) const { - + KOKKOS_FUNCTION + typename NedelecSpace::point_t + NedelecSpace::getLocalDOFPosition( + size_t localDOFIndex) const { // Hardcoded center of edges which are stored in the localDofPositions_m // vector. If the DOF position of an edge element actually is the center // of the edge is a different question... return localDofPositions_m(localDOFIndex); } - - /////////////////////////////////////////////////////////////////////// /// Assembly operations /////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// template + typename QuadratureType, typename FieldType> template - FEMVector NedelecSpace - ::evaluateAx(FEMVector& x, F& evalFunction) const { + FEMVector NedelecSpace::evaluateAx( + FEMVector& x, F& evalFunction) const { Inform m(""); - IpplTimings::TimerRef timerAxInit = IpplTimings::getTimer("Ax init"); IpplTimings::startTimer(timerAxInit); @@ -379,7 +365,7 @@ namespace ippl { // List of quadrature nodes const Vector q = this->quadrature_m.getIntegrationNodesForRefElement(); - + // Get the values of the basis functions and their curl at the // quadrature points. Vector, QuadratureType::numElementNodes> curl_b_q; @@ -387,7 +373,7 @@ namespace ippl { for (size_t k = 0; k < QuadratureType::numElementNodes; ++k) { for (size_t i = 0; i < numElementDOFs; ++i) { curl_b_q[k][i] = this->evaluateRefElementShapeFunctionCurl(i, q[k]); - val_b_q[k][i] = this->evaluateRefElementShapeFunction(i, q[k]); + val_b_q[k][i] = this->evaluateRefElementShapeFunction(i, q[k]); } } @@ -396,14 +382,12 @@ namespace ippl { ViewType view = x.getView(); AtomicViewType resultView = resultVector.getView(); - // Get domain information auto ldom = layout_m.getLocalNDIndex(); using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; - IpplTimings::stopTimer(timerAxInit); // Here we assemble the local matrix of an element. In theory this would @@ -423,7 +407,6 @@ namespace ippl { } IpplTimings::stopTimer(timerAxLocalMatrix); - IpplTimings::TimerRef timerAxLoop = IpplTimings::getTimer("Ax Loop"); IpplTimings::startTimer(timerAxLoop); @@ -432,15 +415,14 @@ namespace ippl { "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(const size_t index) { const size_t elementIndex = elementIndices(index); - + // Here we now retrieve the global DOF indices and their // position inside of the FEMVector const Vector global_dofs = this->NedelecSpace::getGlobalDOFIndices(elementIndex); - + const Vector vectorIndices = this->getFEMVectorDOFIndices(elementIndex, ldom); - // local DOF indices size_t i, j; @@ -448,7 +430,7 @@ namespace ippl { // global DOF n-dimensional indices (Vector of N indices // representing indices in each dimension) size_t I, J; - + for (i = 0; i < numElementDOFs; ++i) { I = global_dofs[i]; @@ -460,7 +442,7 @@ namespace ippl { for (j = 0; j < numElementDOFs; ++j) { J = global_dofs[j]; - // Skip boundary DOFs (Zero Dirichlet BCs) + // Skip boundary DOFs (Zero Dirichlet BCs) if (this->isDOFOnBoundary(J)) { continue; } @@ -468,21 +450,18 @@ namespace ippl { resultView(vectorIndices[i]) += A[i][j] * view(vectorIndices[j]); } } - } - ); + }); IpplTimings::stopTimer(timerAxLoop); - + return resultVector; - } - template - FEMVector NedelecSpace - ::evaluateLoadVector(const FEMVector::point_t>& f) const { - + typename QuadratureType, typename FieldType> + FEMVector + NedelecSpace::evaluateLoadVector( + const FEMVector::point_t>& f) const { // List of quadrature weights const Vector w = this->quadrature_m.getWeightsForRefElement(); @@ -493,8 +472,6 @@ namespace ippl { const indices_t zeroNdIndex = Vector(0); - - // Evaluate the basis functions for the DOF at the quadrature nodes Vector, QuadratureType::numElementNodes> basis_q; for (size_t k = 0; k < QuadratureType::numElementNodes; ++k) { @@ -503,16 +480,14 @@ namespace ippl { } } - - // Get the distance between the quadrature nodes and the DOFs + // Get the distance between the quadrature nodes and the DOFs // we assume that the dofs are at the center of an edge, this is then // going to be used to implement a very crude interpolation scheme. - Vector, QuadratureType::numElementNodes> - quadratureDOFDistances; + Vector, QuadratureType::numElementNodes> quadratureDOFDistances; for (size_t k = 0; k < QuadratureType::numElementNodes; ++k) { for (size_t i = 0; i < numElementDOFs; ++i) { - point_t dofPos = getLocalDOFPosition(i); - point_t d = dofPos - q[k]; + point_t dofPos = getLocalDOFPosition(i); + point_t d = dofPos - q[k]; quadratureDOFDistances[k][i] = Kokkos::sqrt(d.dot(d)); } } @@ -524,14 +499,13 @@ namespace ippl { // Get domain information and ghost cells auto ldom = layout_m.getLocalNDIndex(); - // Get boundary conditions from field FEMVector resultVector = createFEMVector(); // Get field data and make it atomic, // since it will be added to during the kokkos loop - AtomicViewType atomic_view = resultVector.getView(); - typename detail::ViewType::view_type view = f.getView(); + AtomicViewType atomic_view = resultVector.getView(); + typename detail::ViewType::view_type view = f.getView(); using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; @@ -540,7 +514,7 @@ namespace ippl { Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->NedelecSpace::getGlobalDOFIndices(elementIndex); @@ -554,7 +528,6 @@ namespace ippl { if (this->isDOFOnBoundary(I)) { continue; } - // calculate the contribution of this element T contrib = 0; @@ -568,12 +541,12 @@ namespace ippl { // the distance T dist = quadratureDOFDistances[k][j]; - + // running variable used for normalization - distSum += 1/dist; - + distSum += 1 / dist; + // get field value at DOF and interpolate to q_k - interpolatedVal += 1./dist * view(vectorIndices<:j:>); + interpolatedVal += 1. / dist * view(vectorIndices<:j:>); } // here we have to divide it by distSum in order to // normalize it @@ -585,19 +558,17 @@ namespace ippl { // add the contribution of the element to the field atomic_view(vectorIndices<:i:>) += contrib; - } }); - + return resultVector; } template + typename QuadratureType, typename FieldType> template - FEMVector NedelecSpace - ::evaluateLoadVectorFunctor(const F& f) const { - + FEMVector NedelecSpace::evaluateLoadVectorFunctor(const F& f) const { // List of quadrature weights const Vector w = this->quadrature_m.getWeightsForRefElement(); @@ -616,7 +587,6 @@ namespace ippl { } } - // Absolute value of det Phi_K const T absDetDPhi = Kokkos::abs(this->ref_element_m.getDeterminantOfTransformationJacobian( this->getElementMeshVertexPoints(zeroNdIndex))); @@ -624,7 +594,6 @@ namespace ippl { // Get domain information and ghost cells auto ldom = layout_m.getLocalNDIndex(); - // Get boundary conditions from field FEMVector resultVector = createFEMVector(); @@ -634,75 +603,68 @@ namespace ippl { using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; - // Loop over elements to compute contributions Kokkos::parallel_for( "Loop over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(size_t index) { - const size_t elementIndex = elementIndices(index); + const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->NedelecSpace::getGlobalDOFIndices(elementIndex); - + const Vector vectorIndices = this->getFEMVectorDOFIndices(elementIndex, ldom); - size_t i, I; for (i = 0; i < numElementDOFs; ++i) { I = global_dofs[i]; - if (this->isDOFOnBoundary(I)) { continue; } - + // calculate the contribution of this element T contrib = 0; for (size_t k = 0; k < QuadratureType::numElementNodes; ++k) { - // Get the global position of the quadrature point + // Get the global position of the quadrature point point_t pos = this->ref_element_m.localToGlobal( this->getElementMeshVertexPoints(this->getElementNDIndex(elementIndex)), - q[k]); - + q[k]); + // evaluate the rhs function at this global position point_t interpolatedVal = f(pos); - + // update contribution contrib += w[k] * basis_q[k][i].dot(interpolatedVal) * absDetDPhi; } // add the contribution of the element to the vector atomic_view(vectorIndices[i]) += contrib; - - } + } }); - + return resultVector; } - - /////////////////////////////////////////////////////////////////////// /// Basis functions and gradients ///////////////////////////////////// /////////////////////////////////////////////////////////////////////// template - KOKKOS_FUNCTION typename NedelecSpace::point_t - NedelecSpace - ::evaluateRefElementShapeFunction(const size_t& localDOF, - const NedelecSpace::point_t& localPoint) const { - + typename QuadratureType, typename FieldType> + KOKKOS_FUNCTION + typename NedelecSpace::point_t + NedelecSpace:: + evaluateRefElementShapeFunction( + const size_t& localDOF, + const NedelecSpace::point_t& + localPoint) const { // Assert that the local vertex index is valid. - assert(localDOF < numElementDOFs && "The local vertex index is invalid"); + assert(localDOF < numElementDOFs && "The local vertex index is invalid"); assert(this->ref_element_m.isPointInRefElement(localPoint) - && "Point is not in reference element"); - - + && "Point is not in reference element"); // Simply hardcoded point_t result(0); @@ -710,21 +672,21 @@ namespace ippl { T x = localPoint(0); T y = localPoint(1); - switch (localDOF){ - // clang-format off + switch (localDOF) { + // clang-format off case 0: result(0) = 1 - y; break; case 1: result(1) = 1 - x; break; case 2: result(0) = y; break; case 3: result(1) = x; break; - // clang-format on + // clang-format on } } else if constexpr (Dim == 3) { T x = localPoint(0); T y = localPoint(1); T z = localPoint(2); - switch (localDOF){ - // clang-format off + switch (localDOF) { + // clang-format off case 0: result(0) = y*z - y - z + 1; break; case 1: result(1) = x*z - x - z + 1; break; case 2: result(0) = y*(1 - z); break; @@ -737,24 +699,22 @@ namespace ippl { case 9: result(1) = z*(1 - x); break; case 10: result(0) = y*z; break; case 11: result(1) = x*z; break; - // clang-format on + // clang-format on } } - return result; } - template - KOKKOS_FUNCTION typename NedelecSpace::point_t - NedelecSpace - ::evaluateRefElementShapeFunctionCurl(const size_t& localDOF, - const NedelecSpace::point_t& localPoint) const { - + KOKKOS_FUNCTION + typename NedelecSpace::point_t + NedelecSpace:: + evaluateRefElementShapeFunctionCurl( + const size_t& localDOF, + const NedelecSpace::point_t& + localPoint) const { // Hard coded. point_t result(0); @@ -765,14 +725,14 @@ namespace ippl { // of it. This should lead to no problems, as we later on only will // take the dot product between two of them and therefore should not // run into any problems - + switch (localDOF) { - // clang-format off + // clang-format off case 0: result(0) = 1; break; case 1: result(0) = -1; break; case 2: result(0) = -1; break; case 3: result(0) = 1; break; - // clang-format on + // clang-format on } } else { T x = localPoint(0); @@ -780,34 +740,80 @@ namespace ippl { T z = localPoint(2); switch (localDOF) { - case 0: result(0) = 0; result(1) = -1+y; result(2) = 1-z; break; - case 1: result(0) = 1-x; result(1) = 0; result(2) = -1+z; break; - case 2: result(0) = 0; result(1) = -y; result(2) = -1+z; break; - case 3: result(0) = x; result(1) = 0; result(2) = 1-z; break; - case 4: result(0) = -1+x; result(1) = 1-y; result(2) = 0; break; - case 5: result(0) = -x; result(1) = -1+y; result(2) = 0; break; - case 6: result(0) = x; result(1) = -y; result(2) = 0; break; - case 7: result(0) = 1-x; result(1) = y; result(2) = 0; break; - case 8: result(0) = 0; result(1) = 1-y; result(2) = z; break; - case 9: result(0) = -1+x; result(1) = 0; result(2) = -z; break; - case 10: result(0) = 0; result(1) = y; result(2) = -z; break; - case 11: result(0) = -x; result(1) = 0; result(2) = z; break; + case 0: + result(0) = 0; + result(1) = -1 + y; + result(2) = 1 - z; + break; + case 1: + result(0) = 1 - x; + result(1) = 0; + result(2) = -1 + z; + break; + case 2: + result(0) = 0; + result(1) = -y; + result(2) = -1 + z; + break; + case 3: + result(0) = x; + result(1) = 0; + result(2) = 1 - z; + break; + case 4: + result(0) = -1 + x; + result(1) = 1 - y; + result(2) = 0; + break; + case 5: + result(0) = -x; + result(1) = -1 + y; + result(2) = 0; + break; + case 6: + result(0) = x; + result(1) = -y; + result(2) = 0; + break; + case 7: + result(0) = 1 - x; + result(1) = y; + result(2) = 0; + break; + case 8: + result(0) = 0; + result(1) = 1 - y; + result(2) = z; + break; + case 9: + result(0) = -1 + x; + result(1) = 0; + result(2) = -z; + break; + case 10: + result(0) = 0; + result(1) = y; + result(2) = -z; + break; + case 11: + result(0) = -x; + result(1) = 0; + result(2) = z; + break; } } return result; - } - /////////////////////////////////////////////////////////////////////// /// FEMVector conversion ////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// template - FEMVector NedelecSpace - ::createFEMVector() const { + FEMVector + NedelecSpace::createFEMVector() const { // This function will simply call one of the other two depending on the // dimension of the space if constexpr (Dim == 2) { @@ -817,38 +823,35 @@ namespace ippl { } } - template - Kokkos::View::point_t*> + Kokkos::View< + typename NedelecSpace::point_t*> NedelecSpace::reconstructToPoints( const Kokkos::View::point_t*>& positions, const FEMVector& coef) const { - + FieldType>::point_t*>& positions, + const FEMVector& coef) const { // The domain information of the subdomain of the MPI rank - auto ldom = layout_m.getLocalNDIndex(); - + auto ldom = layout_m.getLocalNDIndex(); + // The domain information of the global domain - auto gdom = layout_m.getDomain(); + auto gdom = layout_m.getDomain(); indices_t gextent = gdom.last() - gdom.first(); - - // The size of the global domain. - point_t domainSize = (this->nr_m-1) * this->hr_m; + // The size of the global domain. + point_t domainSize = (this->nr_m - 1) * this->hr_m; auto coefView = coef.getView(); Kokkos::View outView("reconstructed Func values at points", positions.extent(0)); - Kokkos::parallel_for("reconstructToPoints", positions.extent(0), - KOKKOS_CLASS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "reconstructToPoints", positions.extent(0), KOKKOS_CLASS_LAMBDA(size_t i) { // get the current position and for it figure out to which // element it belongs - point_t pos = positions<:i:>; + point_t pos = positions<:i:>; indices_t elemIdx = ((pos - this->origin_m) / domainSize) * gextent; - // next up we have to handle the case of when a position that // was provided to us lies on an edge at the upper bound of the // local domain, because in this case we have that the above @@ -860,18 +863,16 @@ namespace ippl { } } - // get correct indices const Vector vectorIndices = this->getFEMVectorDOFIndices(elemIdx, ldom); - // figure out position inside of the reference element point_t locPos = pos - (elemIdx * this->hr_m + this->origin_m); locPos /= this->hr_m; // because of numerical instabilities it might happen then when - // a point is on an edge this becomes marginally larger that 1 + // a point is on an edge this becomes marginally larger that 1 // or slightly negative which triggers an assertion. So this // simply is to prevent this. for (size_t d = 0; d < Dim; ++d) { @@ -879,24 +880,19 @@ namespace ippl { locPos<:d:> = Kokkos::max(T(0), locPos<:d:>); } - // interpolate the function value to the position, using the // basis functions. point_t val(0); for (size_t j = 0; j < numElementDOFs; ++j) { point_t funcVal = this->evaluateRefElementShapeFunction(j, locPos); - val += funcVal*coefView(vectorIndices<:j:>); + val += funcVal * coefView(vectorIndices<:j:>); } outView(i) = val; - - } - ); - + }); return outView; } - /////////////////////////////////////////////////////////////////////// /// Error norm computations /////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// @@ -908,7 +904,8 @@ namespace ippl { const FEMVector& u_h, const F& u_sol) const { if (this->quadrature_m.getOrder() < (2 * Order + 1)) { // throw exception - throw IpplException( "NedelecSpace::computeError()", + throw IpplException( + "NedelecSpace::computeError()", "Order of quadrature rule for error computation should be > 2*p + 1"); } @@ -931,33 +928,31 @@ namespace ippl { const indices_t zeroNdIndex = Vector(0); // Absolute value of det Phi_K - const T absDetDPhi = Kokkos::abs(this->ref_element_m - .getDeterminantOfTransformationJacobian(this->getElementMeshVertexPoints(zeroNdIndex))); + const T absDetDPhi = Kokkos::abs(this->ref_element_m.getDeterminantOfTransformationJacobian( + this->getElementMeshVertexPoints(zeroNdIndex))); // Variable to sum the error to T error = 0; // Get domain information and ghost cells - auto ldom = layout_m.getLocalNDIndex(); + auto ldom = layout_m.getLocalNDIndex(); using exec_space = typename Kokkos::View::execution_space; using policy_type = Kokkos::RangePolicy; auto view = u_h.getView(); - // Loop over elements to compute contributions - Kokkos::parallel_reduce("Compute error over elements", - policy_type(0, elementIndices.extent(0)), + Kokkos::parallel_reduce( + "Compute error over elements", policy_type(0, elementIndices.extent(0)), KOKKOS_CLASS_LAMBDA(size_t index, double& local) { const size_t elementIndex = elementIndices(index); const Vector global_dofs = this->NedelecSpace::getGlobalDOFIndices(elementIndex); - + const Vector vectorIndices = this->getFEMVectorDOFIndices(elementIndex, ldom); - // contribution of this element to the error T contrib = 0; for (size_t k = 0; k < QuadratureType::numElementNodes; ++k) { @@ -965,8 +960,8 @@ namespace ippl { // of the quadrature point point_t val_u_sol = u_sol(this->ref_element_m.localToGlobal( this->getElementMeshVertexPoints(this->getElementNDIndex(elementIndex)), - q[k])); - + q[k])); + // Here we now reconstruct the solution given the basis // functions. point_t val_u_h = 0; @@ -976,14 +971,13 @@ namespace ippl { } // calculate error and add to sum. - point_t dif = (val_u_sol - val_u_h); - T x = dif.dot(dif); + point_t dif = (val_u_sol - val_u_h); + T x = dif.dot(dif); contrib += w[k] * x * absDetDPhi; } local += contrib; }, - Kokkos::Sum(error) - ); + Kokkos::Sum(error)); // MPI reduce T global_error = 0.0; @@ -994,22 +988,23 @@ namespace ippl { template - KOKKOS_FUNCTION bool NedelecSpace - ::isDOFOnBoundary(const size_t& dofIdx) const { - + KOKKOS_FUNCTION bool NedelecSpace::isDOFOnBoundary(const size_t& dofIdx) const { bool onBoundary = false; if constexpr (Dim == 2) { size_t nx = this->nr_m[0]; size_t ny = this->nr_m[1]; // South - bool sVal = (dofIdx < nx -1); + bool sVal = (dofIdx < nx - 1); onBoundary = onBoundary || sVal; // North - onBoundary = onBoundary || (dofIdx > nx*(ny-1) + ny*(nx-1) - nx); + onBoundary = onBoundary || (dofIdx > nx * (ny - 1) + ny * (nx - 1) - nx); // West - onBoundary = onBoundary || ((dofIdx >= nx-1) && (dofIdx - (nx-1)) % (2*nx - 1) == 0); + onBoundary = + onBoundary || ((dofIdx >= nx - 1) && (dofIdx - (nx - 1)) % (2 * nx - 1) == 0); // East - onBoundary = onBoundary || ((dofIdx >= 2*nx-2) && ((dofIdx - 2*nx + 2) % (2*nx - 1) == 0)); + onBoundary = onBoundary + || ((dofIdx >= 2 * nx - 2) && ((dofIdx - 2 * nx + 2) % (2 * nx - 1) == 0)); } if constexpr (Dim == 3) { @@ -1017,86 +1012,87 @@ namespace ippl { size_t ny = this->nr_m[1]; size_t nz = this->nr_m[2]; - size_t zOffset = dofIdx / (nx*(ny-1) + ny*(nx-1) + nx*ny); + size_t zOffset = dofIdx / (nx * (ny - 1) + ny * (nx - 1) + nx * ny); - - if (dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset >= (nx*(ny-1) + ny*(nx-1))) { + if (dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + >= (nx * (ny - 1) + ny * (nx - 1))) { // we are parallel to z axis // therefore we have halve a cell offset and can never be on the ground or in // space - size_t f = dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset - - (nx*(ny-1) + ny*(nx-1)); - + size_t f = dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + - (nx * (ny - 1) + ny * (nx - 1)); + size_t yOffset = f / nx; // South onBoundary = onBoundary || yOffset == 0; // North - onBoundary = onBoundary || yOffset == ny-1; + onBoundary = onBoundary || yOffset == ny - 1; size_t xOffset = f % nx; // West onBoundary = onBoundary || xOffset == 0; // East - onBoundary = onBoundary || xOffset == nx-1; + onBoundary = onBoundary || xOffset == nx - 1; } else { // are parallel to one of the other axes // Ground onBoundary = onBoundary || zOffset == 0; // Space - onBoundary = onBoundary || zOffset == nz-1; - - size_t f = dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset; - size_t yOffset = f / (2*nx - 1); - size_t xOffset = f - (2*nx - 1)*yOffset; + onBoundary = onBoundary || zOffset == nz - 1; + + size_t f = dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset; + size_t yOffset = f / (2 * nx - 1); + size_t xOffset = f - (2 * nx - 1) * yOffset; - if (xOffset < (nx-1)) { + if (xOffset < (nx - 1)) { // we are parallel to the x axis, therefore we cannot // be on an west or east boundary, but we still can // be on a north or south boundary - + // South onBoundary = onBoundary || yOffset == 0; // North - onBoundary = onBoundary || yOffset == ny-1; - + onBoundary = onBoundary || yOffset == ny - 1; + } else { // we are parallel to the y axis, therefore we cannot be // on a south or north boundary, but we still can be on // a west or east boundary - if (xOffset >= nx-1) { - xOffset -= (nx-1); + if (xOffset >= nx - 1) { + xOffset -= (nx - 1); } // West onBoundary = onBoundary || xOffset == 0; // East - onBoundary = onBoundary || xOffset == nx-1; + onBoundary = onBoundary || xOffset == nx - 1; } } } return onBoundary; } - - template - KOKKOS_FUNCTION int NedelecSpace - ::getBoundarySide(const size_t& dofIdx) const { - + KOKKOS_FUNCTION int NedelecSpace::getBoundarySide(const size_t& dofIdx) const { if constexpr (Dim == 2) { size_t nx = this->nr_m[0]; size_t ny = this->nr_m[1]; // South - if (dofIdx < nx -1) return 0; + if (dofIdx < nx - 1) + return 0; // West - if ((dofIdx - (nx-1)) % (2*nx - 1) == 0) return 1; + if ((dofIdx - (nx - 1)) % (2 * nx - 1) == 0) + return 1; // North - if (dofIdx > nx*(ny-1) + ny*(nx-1) - nx) return 2; + if (dofIdx > nx * (ny - 1) + ny * (nx - 1) - nx) + return 2; // East - if ((dofIdx >= 2*nx-2) && (dofIdx - 2*nx + 2) % (2*nx - 1) == 0) return 3; + if ((dofIdx >= 2 * nx - 2) && (dofIdx - 2 * nx + 2) % (2 * nx - 1) == 0) + return 3; return -1; } @@ -1106,74 +1102,81 @@ namespace ippl { size_t ny = this->nr_m[1]; size_t nz = this->nr_m[2]; - size_t zOffset = dofIdx / (nx*(ny-1) + ny*(nx-1) + nx*ny); - + size_t zOffset = dofIdx / (nx * (ny - 1) + ny * (nx - 1) + nx * ny); - if (dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset >= (nx*(ny-1) + ny*(nx-1))) { + if (dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + >= (nx * (ny - 1) + ny * (nx - 1))) { // we are parallel to z axis // therefore we have halve a cell offset and can never be on the ground or in // space - size_t f = dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset - - (nx*(ny-1) + ny*(nx-1)); - + size_t f = dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + - (nx * (ny - 1) + ny * (nx - 1)); + size_t yOffset = f / nx; // South - if (yOffset == 0) return 0; + if (yOffset == 0) + return 0; // North - if (yOffset == ny-1) return 2; + if (yOffset == ny - 1) + return 2; size_t xOffset = f % nx; // West - if (xOffset == 0) return 1; + if (xOffset == 0) + return 1; // East - if (xOffset == nx-1) return 3; + if (xOffset == nx - 1) + return 3; } else { // are parallel to one of the other axes // Ground - if (zOffset == 0) return 4; + if (zOffset == 0) + return 4; // Space - if (zOffset == nz-1) return 5; - - size_t f = dofIdx - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset; - size_t yOffset = f / (2*nx - 1); - size_t xOffset = f - (2*nx - 1)*yOffset; + if (zOffset == nz - 1) + return 5; + + size_t f = dofIdx - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset; + size_t yOffset = f / (2 * nx - 1); + size_t xOffset = f - (2 * nx - 1) * yOffset; - if (xOffset < (nx-1)) { + if (xOffset < (nx - 1)) { // we are parallel to the x axis, therefore we cannot // be on an west or east boundary, but we still can // be on a north or south boundary - + // South - if (yOffset == 0) return 0; + if (yOffset == 0) + return 0; // North - if (yOffset == ny-1) return 2; - + if (yOffset == ny - 1) + return 2; + } else { // we are parallel to the y axis, therefore we cannot be // on a south or north boundary, but we still can be on // a west or east boundary - if (xOffset >= nx-1) { - xOffset -= (nx-1); + if (xOffset >= nx - 1) { + xOffset -= (nx - 1); } // West - if (xOffset == 0) return 1; + if (xOffset == 0) + return 1; // East - if (xOffset == nx-1) return 3; + if (xOffset == nx - 1) + return 3; } } return -1; } - } - template - FEMVector NedelecSpace - ::createFEMVector2d() const{ - + FEMVector + NedelecSpace::createFEMVector2d() const { // Here we will create an empty FEMVector for the case of the domain // being 2D. // The largest part of this is going to be the handling of the halo @@ -1191,8 +1194,8 @@ namespace ippl { // the correct DOFs might lead to an "out of the blue" feeling on why // exactly we selected those DOFs, but it should be easily verifyable // that those are the correct DOFs. - // Also note that we are not exchanging any boundary information over - // corners, test showed that this does not have any impact on the + // Also note that we are not exchanging any boundary information over + // corners, test showed that this does not have any impact on the // correctness. // For more information regarding the domain decomposition refer to the // report available at: TODO add reference to report on AMAS website @@ -1203,10 +1206,10 @@ namespace ippl { // Create the temporaries and so on which will store the MPI // information. std::vector neighbors; - std::vector< Kokkos::View > sendIdxs; - std::vector< Kokkos::View > recvIdxs; - std::vector< std::vector > sendIdxsTemp; - std::vector< std::vector > recvIdxsTemp; + std::vector> sendIdxs; + std::vector> recvIdxs; + std::vector> sendIdxsTemp; + std::vector> recvIdxsTemp; // Here we loop thought all the domains to figure out how we are related // to them and if we have to do any kind of exchange. @@ -1219,19 +1222,19 @@ namespace ippl { auto odom = doms(i); // East boundary - if (ldom.last()[0] == odom.first()[0]-1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + if (ldom.last()[0] == odom.first()[0] - 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { // Extract the range of the boundary. int begin = std::max(odom.first()[1], ldom.first()[1]); - int end = std::min(odom.last()[1], ldom.last()[1]); - int pos = ldom.last()[0]; - + int end = std::min(odom.last()[1], ldom.last()[1]); + int pos = ldom.last()[0]; + // Add this to the neighbour list. neighbors.push_back(i); sendIdxsTemp.push_back(std::vector()); recvIdxsTemp.push_back(std::vector()); size_t idx = neighbors.size() - 1; - + // Add all the halo indices_t elementPosHalo(0); elementPosHalo(0) = pos; @@ -1240,7 +1243,7 @@ namespace ippl { for (int k = begin; k <= end; ++k) { elementPosHalo(1) = k; elementPosSend(1) = k; - + auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); recvIdxsTemp[idx].push_back(dofIndicesHalo[3]); @@ -1250,7 +1253,7 @@ namespace ippl { } // Check if on very north if (end == layout_m.getDomain().last()[1] || ldom.last()[1] > odom.last()[1]) { - elementPosSend(1) = end; + elementPosSend(1) = end; auto dofIndicesSend = getFEMVectorDOFIndices(elementPosSend, ldom); // also have to add dof 2 sendIdxsTemp[idx].push_back(dofIndicesSend[2]); @@ -1258,28 +1261,28 @@ namespace ippl { } // West boundary - if (ldom.first()[0] == odom.last()[0]+1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + if (ldom.first()[0] == odom.last()[0] + 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { // Extract the range of the boundary. int begin = std::max(odom.first()[1], ldom.first()[1]); - int end = std::min(odom.last()[1], ldom.last()[1]); - int pos = ldom.first()[0]; - + int end = std::min(odom.last()[1], ldom.last()[1]); + int pos = ldom.first()[0]; + // Add this to the neighbour list. neighbors.push_back(i); sendIdxsTemp.push_back(std::vector()); recvIdxsTemp.push_back(std::vector()); size_t idx = neighbors.size() - 1; - + // Add all the halo indices_t elementPosHalo(0); - elementPosHalo(0) = pos-1; + elementPosHalo(0) = pos - 1; indices_t elementPosSend(0); elementPosSend(0) = pos; for (int k = begin; k <= end; ++k) { elementPosHalo(1) = k; elementPosSend(1) = k; - + auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); recvIdxsTemp[idx].push_back(dofIndicesHalo[0]); recvIdxsTemp[idx].push_back(dofIndicesHalo[1]); @@ -1289,7 +1292,7 @@ namespace ippl { } // Check if on very north if (end == layout_m.getDomain().last()[1] || odom.last()[1] > ldom.last()[1]) { - elementPosHalo(1) = end; + elementPosHalo(1) = end; auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); // also have to add dof 2 recvIdxsTemp[idx].push_back(dofIndicesHalo[2]); @@ -1297,19 +1300,19 @@ namespace ippl { } // North boundary - if (ldom.last()[1] == odom.first()[1]-1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + if (ldom.last()[1] == odom.first()[1] - 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { // Extract the range of the boundary. int begin = std::max(odom.first()[0], ldom.first()[0]); - int end = std::min(odom.last()[0], ldom.last()[0]); - int pos = ldom.last()[1]; - + int end = std::min(odom.last()[0], ldom.last()[0]); + int pos = ldom.last()[1]; + // Add this to the neighbour list. neighbors.push_back(i); sendIdxsTemp.push_back(std::vector()); recvIdxsTemp.push_back(std::vector()); size_t idx = neighbors.size() - 1; - + // Add all the halo indices_t elementPosHalo(0); elementPosHalo(1) = pos; @@ -1318,7 +1321,7 @@ namespace ippl { for (int k = begin; k <= end; ++k) { elementPosHalo(0) = k; elementPosSend(0) = k; - + auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); recvIdxsTemp[idx].push_back(dofIndicesHalo[2]); @@ -1328,7 +1331,7 @@ namespace ippl { } // Check if on very east if (end == layout_m.getDomain().last()[0] || ldom.last()[0] > odom.last()[0]) { - elementPosSend(0) = end; + elementPosSend(0) = end; auto dofIndicesSend = getFEMVectorDOFIndices(elementPosSend, ldom); // also have to add dof 3 sendIdxsTemp[idx].push_back(dofIndicesSend[3]); @@ -1336,28 +1339,28 @@ namespace ippl { } // South boundary - if (ldom.first()[1] == odom.last()[1]+1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + if (ldom.first()[1] == odom.last()[1] + 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { // Extract the range of the boundary. int begin = std::max(odom.first()[0], ldom.first()[0]); - int end = std::min(odom.last()[0], ldom.last()[0]); - int pos = ldom.first()[1]; - + int end = std::min(odom.last()[0], ldom.last()[0]); + int pos = ldom.first()[1]; + // Add this to the neighbour list. neighbors.push_back(i); sendIdxsTemp.push_back(std::vector()); recvIdxsTemp.push_back(std::vector()); size_t idx = neighbors.size() - 1; - + // Add all the halo indices_t elementPosHalo(0); - elementPosHalo(1) = pos-1; + elementPosHalo(1) = pos - 1; indices_t elementPosSend(0); elementPosSend(1) = pos; for (int k = begin; k <= end; ++k) { elementPosHalo(0) = k; elementPosSend(0) = k; - + auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); recvIdxsTemp[idx].push_back(dofIndicesHalo[0]); recvIdxsTemp[idx].push_back(dofIndicesHalo[1]); @@ -1367,7 +1370,7 @@ namespace ippl { } // Check if on very east if (end == layout_m.getDomain().last()[0] || odom.last()[0] > ldom.last()[0]) { - elementPosHalo(0) = end; + elementPosHalo(0) = end; auto dofIndicesHalo = getFEMVectorDOFIndices(elementPosHalo, ldom); // also have to add dof 3 recvIdxsTemp[idx].push_back(dofIndicesHalo[3]); @@ -1375,18 +1378,16 @@ namespace ippl { } } - - // Here we now have to translate the sendIdxsTemp and recvIdxsTemp which // are std::vectors into the correct list type which // is std::vector for (size_t i = 0; i < neighbors.size(); ++i) { - sendIdxs.push_back(Kokkos::View("FEMvector::sendIdxs[" + std::to_string(i) + - "]", sendIdxsTemp[i].size())); - recvIdxs.push_back(Kokkos::View("FEMvector::recvIdxs[" + std::to_string(i) + - "]", recvIdxsTemp[i].size())); - auto sendView = sendIdxs[i]; - auto recvView = recvIdxs[i]; + sendIdxs.push_back(Kokkos::View( + "FEMvector::sendIdxs[" + std::to_string(i) + "]", sendIdxsTemp[i].size())); + recvIdxs.push_back(Kokkos::View( + "FEMvector::recvIdxs[" + std::to_string(i) + "]", recvIdxsTemp[i].size())); + auto sendView = sendIdxs[i]; + auto recvView = recvIdxs[i]; auto hSendView = Kokkos::create_mirror_view(sendView); auto hRecvView = Kokkos::create_mirror_view(recvView); @@ -1401,30 +1402,22 @@ namespace ippl { Kokkos::deep_copy(sendView, hSendView); Kokkos::deep_copy(recvView, hRecvView); } - - // Now finaly create the FEMVector indices_t extents(0); - extents = (ldom.last() - ldom.first()) + 3; + extents = (ldom.last() - ldom.first()) + 3; size_t nx = extents(0); size_t ny = extents(1); - size_t n = nx*(ny-1) + ny*(nx-1); + size_t n = nx * (ny - 1) + ny * (nx - 1); FEMVector vec(n, neighbors, sendIdxs, recvIdxs); - + return vec; } - - template - FEMVector NedelecSpace - ::createFEMVector3d() const{ - - - - + FEMVector + NedelecSpace::createFEMVector3d() const { // Here we will create an empty FEMVector for the case of the domain // being 3D. // It follows the same principle as the 2D case (check comment there). @@ -1436,16 +1429,16 @@ namespace ippl { // axes (your standard west-east, south-north, and ground-space // exchanges), then we have two different types of diagonal exchanges, // which we will call "positive" and "negative", we have two types as - // a diagonal exchange always happens over an edge and this edges is - // shared by 4 different ranks, so we have two different diagonal - // exchanges per edge, which we differentiate with "positive" and + // a diagonal exchange always happens over an edge and this edges is + // shared by 4 different ranks, so we have two different diagonal + // exchanges per edge, which we differentiate with "positive" and // "negative". // If we now look at these types independently we have that the code // needed to perform one such exchange is large going to be independent // of the direction of the exchange (i.e. is the "flat" exchange // happening over a west-est or a ground-space boundary) the major // difference is the DOF indices we have to chose for the elements on - // the boundary (check the 2D case for more info). + // the boundary (check the 2D case for more info). // We therefore create 3 lambdas for these different types of boundaries // which we then call with appropriate arguments for the direction of the // exchange. @@ -1462,10 +1455,10 @@ namespace ippl { // Create the temporaries and so on which will store the MPI // information. std::vector neighbors; - std::vector< Kokkos::View > sendIdxs; - std::vector< Kokkos::View > recvIdxs; - std::vector< std::vector > sendIdxsTemp; - std::vector< std::vector > recvIdxsTemp; + std::vector> sendIdxs; + std::vector> recvIdxs; + std::vector> sendIdxsTemp; + std::vector> recvIdxsTemp; // The parameters are: // i: The index of the other dom we are looking at (according to doms). @@ -1478,7 +1471,7 @@ namespace ippl { // order in which we go though these axes). // va,vb: These are the placeholders for the sendIdxs and recvIdxs // arrays, note that depending on if an exchange happens from, - // e.g. west to east or from east to west the role of which of + // e.g. west to east or from east to west the role of which of // these placeholders stores the sendIdxs and which one stores // the recvIdxs changes. // posA, posB: The "a"-axis coordinate of the elements which are part of @@ -1493,23 +1486,22 @@ namespace ippl { // adom, bdom: The domain extents of the two domains which are part of // this exchange. auto flatBoundaryExchange = [this, &neighbors, &ldom]( - size_t i, size_t a, size_t f, size_t s, - std::vector >& va, std::vector >& vb, - int posA, int posB, - const std::vector& idxsA, const std::vector& idxsB, - NDIndex<3>& adom, NDIndex<3>& bdom) { - + size_t i, size_t a, size_t f, size_t s, + std::vector>& va, + std::vector>& vb, int posA, int posB, + const std::vector& idxsA, + const std::vector& idxsB, NDIndex<3>& adom, + NDIndex<3>& bdom) { int beginF = std::max(bdom.first()[f], adom.first()[f]); - int endF = std::min(bdom.last()[f], adom.last()[f]); + int endF = std::min(bdom.last()[f], adom.last()[f]); int beginS = std::max(bdom.first()[s], adom.first()[s]); - int endS = std::min(bdom.last()[s], adom.last()[s]); - + int endS = std::min(bdom.last()[s], adom.last()[s]); + neighbors.push_back(i); va.push_back(std::vector()); vb.push_back(std::vector()); size_t idx = neighbors.size() - 1; - indices_t elementPosA(0); elementPosA(a) = posA; indices_t elementPosB(0); @@ -1533,38 +1525,37 @@ namespace ippl { vb[idx].push_back(dofIndicesB[idxsB[1]]); vb[idx].push_back(dofIndicesB[idxsB[2]]); - // We now have reached the end of the first axis and have to - // figure out if we need to add any additional DOFs. If we + // figure out if we need to add any additional DOFs. If we // need to add DOFs depends on if we are at the mesh // boundary and if one of the two domains does not end here // and "overlaps" the other one. if (k == endF) { - if (endF == layout_m.getDomain().last()[f] || - bdom.last()[f] > adom.last()[f]) { + if (endF == layout_m.getDomain().last()[f] + || bdom.last()[f] > adom.last()[f]) { va[idx].push_back(dofIndicesA[idxsA[2]]); } - - if (endF == layout_m.getDomain().last()[f] || - adom.last()[f] > bdom.last()[f]) { + + if (endF == layout_m.getDomain().last()[f] + || adom.last()[f] > bdom.last()[f]) { vb[idx].push_back(dofIndicesB[idxsB[3]]); vb[idx].push_back(dofIndicesB[idxsB[4]]); } - + // This is a modification to the beginning of the f axis // we still put it on here as we are guaranteed that // like this it only gets called once - // call this last, as modifies elementPosA(s) + // call this last, as modifies elementPosA(s) if (bdom.first()[f] < adom.first()[f]) { - indices_t tmpPos = elementPosA; - tmpPos(f) = beginF-1; + indices_t tmpPos = elementPosA; + tmpPos(f) = beginF - 1; auto dofIndicestmp = this->getFEMVectorDOFIndices(tmpPos, ldom); va[idx].push_back(dofIndicestmp[idxsA[0]]); va[idx].push_back(dofIndicestmp[idxsA[1]]); } } } - + // We now have reached the end of the second axis and have to // figure out if we need to add any additional DOFs. If we need // to add DOFs depends on if we are at the mesh boundary and if @@ -1572,36 +1563,36 @@ namespace ippl { // other one. if (endS == layout_m.getDomain().last()[s] || bdom.last()[s] > adom.last()[s]) { - elementPosA(s) = endS; + elementPosA(s) = endS; auto dofIndicesA = this->getFEMVectorDOFIndices(elementPosA, ldom); va[idx].push_back(dofIndicesA[idxsA[3]]); } - + if (endS == layout_m.getDomain().last()[s] || adom.last()[s] > bdom.last()[s]) { - elementPosB(s) = endS; + elementPosB(s) = endS; auto dofIndicesB = this->getFEMVectorDOFIndices(elementPosB, ldom); vb[idx].push_back(dofIndicesB[idxsB[5]]); vb[idx].push_back(dofIndicesB[idxsB[6]]); } - + // This is a modification to the beginning of the s axis // we still put it on here as we are guaranteed that // like this it only gets called once // call this last, as modifies elementPosA(f); if (bdom.first()[f] < adom.first()[f]) { - indices_t tmpPos = elementPosA; - tmpPos(s) = beginS-1; + indices_t tmpPos = elementPosA; + tmpPos(s) = beginS - 1; auto dofIndicestmp = this->getFEMVectorDOFIndices(tmpPos, ldom); va[idx].push_back(dofIndicestmp[idxsA[0]]); va[idx].push_back(dofIndicestmp[idxsA[1]]); } } - // At this point we have reached the end of both axes f and s and + // At this point we have reached the end of both axes f and s and // therefore now have to make one final check. - if ((endF == layout_m.getDomain().last()[f] || adom.last()[f] > bdom.last()[f]) && - (endS == layout_m.getDomain().last()[s] || adom.last()[s] > bdom.last()[s])) { - elementPosB(f) = endF; - elementPosB(s) = endS; + if ((endF == layout_m.getDomain().last()[f] || adom.last()[f] > bdom.last()[f]) + && (endS == layout_m.getDomain().last()[s] || adom.last()[s] > bdom.last()[s])) { + elementPosB(f) = endF; + elementPosB(s) = endS; auto dofIndicesB = this->getFEMVectorDOFIndices(elementPosB, ldom); vb[idx].push_back(dofIndicesB[idxsB[7]]); } @@ -1617,7 +1608,7 @@ namespace ippl { // offsets to certain values. // va,vb: These are the placeholders for the sendIdxs and recvIdxs // arrays, note that depending on if an exchange happens from, - // e.g. west to east or from east to west the role of which of + // e.g. west to east or from east to west the role of which of // these placeholders stores the sendIdxs and which one stores // the recvIdxs changes. // idxsA, idxsB: These are going to be the local DOF indices of the @@ -1627,11 +1618,11 @@ namespace ippl { // the sendIdxs or the recvIdxs // odom: The other domain we are exchanging to. auto negativeDiagonalExchange = [this, &neighbors, &ldom]( - size_t i, size_t a, size_t f, size_t s, int ao, int bo, - std::vector >& va, std::vector >& vb, - const std::vector& idxsA, const std::vector& idxsB, - NDIndex<3>& odom) { - + size_t i, size_t a, size_t f, size_t s, int ao, int bo, + std::vector>& va, + std::vector>& vb, + const std::vector& idxsA, + const std::vector& idxsB, NDIndex<3>& odom) { neighbors.push_back(i); va.push_back(std::vector()); vb.push_back(std::vector()); @@ -1646,7 +1637,7 @@ namespace ippl { elementPosB(s) = ldom.first()[s] + bo; int begin = std::max(odom.first()[a], ldom.first()[a]); - int end = std::min(odom.last()[a], ldom.last()[a]); + int end = std::min(odom.last()[a], ldom.last()[a]); // Loop through all the elements along the edge. for (int k = begin; k <= end; ++k) { elementPosA(a) = k; @@ -1662,7 +1653,6 @@ namespace ippl { } }; - // The parameters are: // i: The index of the other dom we are looking at (according to doms). // a: Along which axis the edge is over which the exchange happens, @@ -1671,7 +1661,7 @@ namespace ippl { // have store in those two the other two axes. // va,vb: These are the placeholders for the sendIdxs and recvIdxs // arrays, note that depending on if an exchange happens from, - // e.g. west to east or from east to west the role of which of + // e.g. west to east or from east to west the role of which of // these placeholders stores the sendIdxs and which one stores // the recvIdxs changes. // idxsA, idxsB: These are going to be the local DOF indices of the @@ -1681,12 +1671,11 @@ namespace ippl { // the sendIdxs or the recvIdxs // odom: The other domain we are exchanging to. auto positiveDiagonalExchange = [this, &neighbors, &ldom]( - size_t i, size_t a, size_t f, size_t s, - indices_t posA, indices_t posB, - std::vector >& va, std::vector >& vb, - const std::vector& idxsA, const std::vector& idxsB, - NDIndex<3>& odom) { - + size_t i, size_t a, size_t f, size_t s, indices_t posA, + indices_t posB, std::vector>& va, + std::vector>& vb, + const std::vector& idxsA, + const std::vector& idxsB, NDIndex<3>& odom) { neighbors.push_back(i); va.push_back(std::vector()); vb.push_back(std::vector()); @@ -1701,7 +1690,7 @@ namespace ippl { elementPosB(s) = posB(s); int begin = std::max(odom.first()[a], ldom.first()[a]); - int end = std::min(odom.last()[a], ldom.last()[a]); + int end = std::min(odom.last()[a], ldom.last()[a]); for (int k = begin; k <= end; ++k) { elementPosA(a) = k; @@ -1721,7 +1710,6 @@ namespace ippl { // we can look at all the exchanges we need to make and call the lambdas // with the appropriate parameters. - // Here we loop through all the domains to figure out how we are related // to them and if we have to do any kind of exchange. size_t myRank = Comm->rank(); @@ -1733,269 +1721,164 @@ namespace ippl { auto odom = doms(i); // East boundary - if (ldom.last()[0] == odom.first()[0]-1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1]) && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - + if (ldom.last()[0] == odom.first()[0] - 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1]) + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { int pos = ldom.last()[0]; - flatBoundaryExchange( - i, 0, 1, 2, - recvIdxsTemp, sendIdxsTemp, - pos, pos, - {3,5,6,11}, {0,1,4,2,7,8,9,10}, - ldom, odom - ); + flatBoundaryExchange(i, 0, 1, 2, recvIdxsTemp, sendIdxsTemp, pos, pos, + {3, 5, 6, 11}, {0, 1, 4, 2, 7, 8, 9, 10}, ldom, odom); } // West boundary - if (ldom.first()[0] == odom.last()[0]+1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1]) && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - + if (ldom.first()[0] == odom.last()[0] + 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1]) + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { int pos = ldom.first()[0]; - flatBoundaryExchange( - i, 0, 1, 2, - sendIdxsTemp, recvIdxsTemp, - pos, pos-1, - {1,4,7,9}, {0,1,4,2,7,8,9,10}, - odom, ldom - ); + flatBoundaryExchange(i, 0, 1, 2, sendIdxsTemp, recvIdxsTemp, pos, pos - 1, + {1, 4, 7, 9}, {0, 1, 4, 2, 7, 8, 9, 10}, odom, ldom); } // North boundary - if (ldom.last()[1] == odom.first()[1]-1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - + if (ldom.last()[1] == odom.first()[1] - 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { int pos = ldom.last()[1]; - flatBoundaryExchange( - i, 1, 0, 2, - recvIdxsTemp, sendIdxsTemp, - pos, pos, - {2,7,6,10}, {0,1,4,3,5,8,9,11}, - ldom, odom - ); + flatBoundaryExchange(i, 1, 0, 2, recvIdxsTemp, sendIdxsTemp, pos, pos, + {2, 7, 6, 10}, {0, 1, 4, 3, 5, 8, 9, 11}, ldom, odom); } // South boundary - if (ldom.first()[1] == odom.last()[1]+1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - + if (ldom.first()[1] == odom.last()[1] + 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { int pos = ldom.first()[1]; - flatBoundaryExchange( - i, 1, 0, 2, - sendIdxsTemp, recvIdxsTemp, - pos, pos-1, - {0,4,5,8}, {0,1,4,3,5,8,9,11}, - odom, ldom - ); - + flatBoundaryExchange(i, 1, 0, 2, sendIdxsTemp, recvIdxsTemp, pos, pos - 1, + {0, 4, 5, 8}, {0, 1, 4, 3, 5, 8, 9, 11}, odom, ldom); } // Space boundary - if (ldom.last()[2] == odom.first()[2]-1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - + if (ldom.last()[2] == odom.first()[2] - 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { int pos = ldom.last()[2]; - flatBoundaryExchange( - i, 2, 0, 1, - recvIdxsTemp, sendIdxsTemp, - pos, pos, - {8,9,11,10}, {0,1,4,3,5,2,7,6}, - ldom, odom - ); + flatBoundaryExchange(i, 2, 0, 1, recvIdxsTemp, sendIdxsTemp, pos, pos, + {8, 9, 11, 10}, {0, 1, 4, 3, 5, 2, 7, 6}, ldom, odom); } // Ground boundary - if (ldom.first()[2] == odom.last()[2]+1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - + if (ldom.first()[2] == odom.last()[2] + 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0]) + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { int pos = ldom.first()[2]; - flatBoundaryExchange( - i, 2, 0, 1, - sendIdxsTemp, recvIdxsTemp, - pos, pos-1, - {0,1,3,2}, {0,1,4,3,5,2,7,6}, - odom, ldom - ); + flatBoundaryExchange(i, 2, 0, 1, sendIdxsTemp, recvIdxsTemp, pos, pos - 1, + {0, 1, 3, 2}, {0, 1, 4, 3, 5, 2, 7, 6}, odom, ldom); } - - // Next up we handle all the annoying diagonals. // The negative ones: // Parallel to y from space to ground, west to east - if (ldom.last()[0] == odom.first()[0]-1 && ldom.first()[2] == odom.last()[2]+1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - - negativeDiagonalExchange( - i, 1, 0, 2, 0, -1, - sendIdxsTemp, recvIdxsTemp, - {0,1}, {3,5}, - odom - ); + if (ldom.last()[0] == odom.first()[0] - 1 && ldom.first()[2] == odom.last()[2] + 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + negativeDiagonalExchange(i, 1, 0, 2, 0, -1, sendIdxsTemp, recvIdxsTemp, {0, 1}, + {3, 5}, odom); } // Parallel to y from ground to space, east to west - if (ldom.first()[0] == odom.last()[0]+1 && ldom.last()[2] == odom.first()[2]-1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - - negativeDiagonalExchange( - i, 1, 2, 0, -1, 0, - recvIdxsTemp, sendIdxsTemp, - {8,9}, {1,4}, - odom - ); + if (ldom.first()[0] == odom.last()[0] + 1 && ldom.last()[2] == odom.first()[2] - 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + negativeDiagonalExchange(i, 1, 2, 0, -1, 0, recvIdxsTemp, sendIdxsTemp, {8, 9}, + {1, 4}, odom); } - // Parallel to x from space to ground, south to north - if (ldom.last()[1] == odom.first()[1]-1 && ldom.first()[2] == odom.last()[2]+1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { - negativeDiagonalExchange( - i, 0, 1, 2, 0, -1, - sendIdxsTemp, recvIdxsTemp, - {0,1}, {2,7}, - odom - ); + if (ldom.last()[1] == odom.first()[1] - 1 && ldom.first()[2] == odom.last()[2] + 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + negativeDiagonalExchange(i, 0, 1, 2, 0, -1, sendIdxsTemp, recvIdxsTemp, {0, 1}, + {2, 7}, odom); } // Parallel to x from ground to space, north to south - if (ldom.first()[1] == odom.last()[1]+1 && ldom.last()[2] == odom.first()[2]-1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { - negativeDiagonalExchange( - i, 0, 2, 1, -1, 0, - recvIdxsTemp, sendIdxsTemp, - {8,9}, {0,4}, - odom - ); + if (ldom.first()[1] == odom.last()[1] + 1 && ldom.last()[2] == odom.first()[2] - 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + negativeDiagonalExchange(i, 0, 2, 1, -1, 0, recvIdxsTemp, sendIdxsTemp, {8, 9}, + {0, 4}, odom); } - // Parallel to z from west to east, north to south - if (ldom.last()[0] == odom.first()[0]-1 && ldom.first()[1] == odom.last()[1]+1 && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - negativeDiagonalExchange( - i, 2, 0, 1, 0, -1, - sendIdxsTemp, recvIdxsTemp, - {0,4}, {3,5}, - odom - ); + if (ldom.last()[0] == odom.first()[0] - 1 && ldom.first()[1] == odom.last()[1] + 1 + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { + negativeDiagonalExchange(i, 2, 0, 1, 0, -1, sendIdxsTemp, recvIdxsTemp, {0, 4}, + {3, 5}, odom); } // Parallel to z from east to west, south to north - if (ldom.first()[0] == odom.last()[0]+1 && ldom.last()[1] == odom.first()[1]-1 && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - negativeDiagonalExchange( - i, 2, 1, 0, -1, 0, - recvIdxsTemp, sendIdxsTemp, - {2,7}, {1,4}, - odom - ); + if (ldom.first()[0] == odom.last()[0] + 1 && ldom.last()[1] == odom.first()[1] - 1 + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { + negativeDiagonalExchange(i, 2, 1, 0, -1, 0, recvIdxsTemp, sendIdxsTemp, {2, 7}, + {1, 4}, odom); } - - // The positive ones // Parallel to y from ground to space, west to east - if (ldom.last()[0] == odom.first()[0]-1 && ldom.last()[2] == odom.first()[2]-1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - positiveDiagonalExchange( - i, 1, 0, 2, - ldom.last(), ldom.last(), - sendIdxsTemp, recvIdxsTemp, - {0,1,4}, {11}, - odom - ); + if (ldom.last()[0] == odom.first()[0] - 1 && ldom.last()[2] == odom.first()[2] - 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + positiveDiagonalExchange(i, 1, 0, 2, ldom.last(), ldom.last(), sendIdxsTemp, + recvIdxsTemp, {0, 1, 4}, {11}, odom); } // Parallel to y from space to ground, east to west - if (ldom.first()[0] == odom.last()[0]+1 && ldom.first()[2] == odom.last()[2]+1 && - !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { - positiveDiagonalExchange( - i, 1, 0, 2, - ldom.first()-1, ldom.first(), - recvIdxsTemp, sendIdxsTemp, - {0,1,4}, {1}, - odom - ); + if (ldom.first()[0] == odom.last()[0] + 1 && ldom.first()[2] == odom.last()[2] + 1 + && !(odom.last()[1] < ldom.first()[1] || odom.first()[1] > ldom.last()[1])) { + positiveDiagonalExchange(i, 1, 0, 2, ldom.first() - 1, ldom.first(), recvIdxsTemp, + sendIdxsTemp, {0, 1, 4}, {1}, odom); } - // Parallel to x from ground to space, south to north - if (ldom.last()[1] == odom.first()[1]-1 && ldom.last()[2] == odom.first()[2]-1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { - positiveDiagonalExchange( - i, 0, 1, 2, - ldom.last(), ldom.last(), - sendIdxsTemp, recvIdxsTemp, - {0,1,4}, {10}, - odom - ); + if (ldom.last()[1] == odom.first()[1] - 1 && ldom.last()[2] == odom.first()[2] - 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + positiveDiagonalExchange(i, 0, 1, 2, ldom.last(), ldom.last(), sendIdxsTemp, + recvIdxsTemp, {0, 1, 4}, {10}, odom); } // Parallel to x from space to ground, north to south - if (ldom.first()[1] == odom.last()[1]+1 && ldom.first()[2] == odom.last()[2]+1 && - !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { - positiveDiagonalExchange( - i, 0, 1, 2, - ldom.first()-1, ldom.first(), - recvIdxsTemp, sendIdxsTemp, - {0,1,4}, {0}, - odom - ); + if (ldom.first()[1] == odom.last()[1] + 1 && ldom.first()[2] == odom.last()[2] + 1 + && !(odom.last()[0] < ldom.first()[0] || odom.first()[0] > ldom.last()[0])) { + positiveDiagonalExchange(i, 0, 1, 2, ldom.first() - 1, ldom.first(), recvIdxsTemp, + sendIdxsTemp, {0, 1, 4}, {0}, odom); } - // Parallel to z from west to east, south to north - if (ldom.last()[0] == odom.first()[0]-1 && ldom.last()[1] == odom.first()[1]-1 && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - positiveDiagonalExchange( - i, 2, 0, 1, - ldom.last(), ldom.last(), - sendIdxsTemp, recvIdxsTemp, - {0,1,4}, {6}, - odom - ); + if (ldom.last()[0] == odom.first()[0] - 1 && ldom.last()[1] == odom.first()[1] - 1 + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { + positiveDiagonalExchange(i, 2, 0, 1, ldom.last(), ldom.last(), sendIdxsTemp, + recvIdxsTemp, {0, 1, 4}, {6}, odom); } // Parallel to z from east to west, north to south - if (ldom.first()[0] == odom.last()[0]+1 && ldom.first()[1] == odom.last()[1]+1 && - !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { - positiveDiagonalExchange( - i, 2, 0, 1, - ldom.first()-1, ldom.first(), - recvIdxsTemp, sendIdxsTemp, - {0,1,4}, {4}, - odom - ); + if (ldom.first()[0] == odom.last()[0] + 1 && ldom.first()[1] == odom.last()[1] + 1 + && !(odom.last()[2] < ldom.first()[2] || odom.first()[2] > ldom.last()[2])) { + positiveDiagonalExchange(i, 2, 0, 1, ldom.first() - 1, ldom.first(), recvIdxsTemp, + sendIdxsTemp, {0, 1, 4}, {4}, odom); } - } - - - // Here we now have to translate the sendIdxsTemp and recvIdxsTemp which // are std::vectors into the correct list type which // is std::vector for (size_t i = 0; i < neighbors.size(); ++i) { - sendIdxs.push_back(Kokkos::View("FEMvector::sendIdxs[" + std::to_string(i) + - "]", sendIdxsTemp[i].size())); - recvIdxs.push_back(Kokkos::View("FEMvector::recvIdxs[" + std::to_string(i) + - "]", recvIdxsTemp[i].size())); - auto sendView = sendIdxs[i]; - auto recvView = recvIdxs[i]; + sendIdxs.push_back(Kokkos::View( + "FEMvector::sendIdxs[" + std::to_string(i) + "]", sendIdxsTemp[i].size())); + recvIdxs.push_back(Kokkos::View( + "FEMvector::recvIdxs[" + std::to_string(i) + "]", recvIdxsTemp[i].size())); + auto sendView = sendIdxs[i]; + auto recvView = recvIdxs[i]; auto hSendView = Kokkos::create_mirror_view(sendView); auto hRecvView = Kokkos::create_mirror_view(recvView); - + for (size_t j = 0; j < sendIdxsTemp[i].size(); ++j) { hSendView(j) = sendIdxsTemp[i][j]; } - + for (size_t j = 0; j < recvIdxsTemp[i].size(); ++j) { hRecvView(j) = recvIdxsTemp[i][j]; } @@ -2003,21 +1886,18 @@ namespace ippl { Kokkos::deep_copy(sendView, hSendView); Kokkos::deep_copy(recvView, hRecvView); } - - // Now finaly create the FEMVector indices_t extents(0); - extents = (ldom.last() - ldom.first()) + 3; + extents = (ldom.last() - ldom.first()) + 3; size_t nx = extents(0); size_t ny = extents(1); size_t nz = extents(2); - size_t n = (nz-1)*(nx*(ny-1) + ny*(nx-1) + nx*ny) + nx*(ny-1) + ny*(nx-1); + size_t n = + (nz - 1) * (nx * (ny - 1) + ny * (nx - 1) + nx * ny) + nx * (ny - 1) + ny * (nx - 1); FEMVector vec(n, neighbors, sendIdxs, recvIdxs); - + return vec; } - - } // namespace ippl diff --git a/src/FEM/Quadrature/GaussJacobiQuadrature.h b/src/FEM/Quadrature/GaussJacobiQuadrature.h index d357d4909..4322b54a3 100644 --- a/src/FEM/Quadrature/GaussJacobiQuadrature.h +++ b/src/FEM/Quadrature/GaussJacobiQuadrature.h @@ -100,7 +100,7 @@ namespace ippl { const size_t& max_newton_itersations = 10, const size_t& min_newton_iterations = 1) : GaussJacobiQuadrature( - ref_element, 0.0, 0.0, max_newton_itersations, min_newton_iterations) {} + ref_element, 0.0, 0.0, max_newton_itersations, min_newton_iterations) {} }; /** @@ -125,7 +125,7 @@ namespace ippl { const size_t& max_newton_itersations = 10, const size_t& min_newton_iterations = 1) : GaussJacobiQuadrature( - ref_element, -0.5, -0.5, max_newton_itersations, min_newton_iterations) {} + ref_element, -0.5, -0.5, max_newton_itersations, min_newton_iterations) {} }; } // namespace ippl diff --git a/src/FEM/Quadrature/Quadrature.hpp b/src/FEM/Quadrature/Quadrature.hpp index 2468e0ec1..4e22f8c07 100644 --- a/src/FEM/Quadrature/Quadrature.hpp +++ b/src/FEM/Quadrature/Quadrature.hpp @@ -47,7 +47,9 @@ namespace ippl { Quadrature::getIntegrationNodesForRefElement() const { Vector q = this->getIntegrationNodes1D(0.0, 1.0); - Vector, std::remove_reference_t::numElementNodes> tensor_prod_q; + Vector, + std::remove_reference_t::numElementNodes> + tensor_prod_q; Vector nd_index(0); for (unsigned i = 0; i < std::remove_reference_t::numElementNodes; ++i) { diff --git a/src/Field/BareFieldOperations.hpp b/src/Field/BareFieldOperations.hpp index c4c0ab005..4a6b3cadd 100644 --- a/src/Field/BareFieldOperations.hpp +++ b/src/Field/BareFieldOperations.hpp @@ -15,16 +15,16 @@ namespace ippl { using T = typename BareField::value_type; constexpr unsigned Dim = BareField::dim; - static IpplTimings::TimerRef setup = IpplTimings::getTimer("inner_setup"); + static IpplTimings::TimerRef setup = IpplTimings::getTimer("inner_setup"); static IpplTimings::TimerRef ippl_red = IpplTimings::getTimer("ippl_reduce"); - static IpplTimings::TimerRef mpi_red = IpplTimings::getTimer("mpi_reduce"); + static IpplTimings::TimerRef mpi_red = IpplTimings::getTimer("mpi_reduce"); IpplTimings::startTimer(setup); T sum = 0; - auto& layout = f1.getLayout(); - auto& view1 = f1.getView(); - auto& view2 = f2.getView(); + auto& layout = f1.getLayout(); + auto& view1 = f1.getView(); + auto& view2 = f2.getView(); using exec_space = typename BareField::execution_space; using index_array_type = typename RangePolicy::index_array_type; @@ -61,8 +61,8 @@ namespace ippl { constexpr unsigned Dim = BareField::dim; T local = 0; - auto& layout = field.getLayout(); - auto& view = field.getView(); + auto& layout = field.getLayout(); + auto& view = field.getView(); using exec_space = typename BareField::execution_space; using index_array_type = typename RangePolicy::index_array_type; switch (p) { diff --git a/src/Field/BcTypes.h b/src/Field/BcTypes.h index 27d1ec0f6..f69694b65 100644 --- a/src/Field/BcTypes.h +++ b/src/Field/BcTypes.h @@ -57,10 +57,10 @@ namespace ippl { virtual FieldBC getBCType() const { return NO_FACE; } - virtual void findBCNeighbors(Field& field) = 0; - virtual void apply(Field& field) = 0; + virtual void findBCNeighbors(Field& field) = 0; + virtual void apply(Field& field) = 0; virtual void assignGhostToPhysical(Field& field) = 0; - virtual void write(std::ostream&) const = 0; + virtual void write(std::ostream&) const = 0; // Return face on which BC applies unsigned int getFace() const { return face_m; } diff --git a/src/Field/BcTypes.hpp b/src/Field/BcTypes.hpp index 8d92f8dd6..9fd922703 100644 --- a/src/Field/BcTypes.hpp +++ b/src/Field/BcTypes.hpp @@ -357,12 +357,11 @@ namespace ippl { throw IpplException("PeriodicFace::apply", "face number wrong"); } - bool upperFace = (face & 1); + bool upperFace = (face & 1); bool isBoundary = ((ldom[d].max() == domain[d].max()) && upperFace) - || ((ldom[d].min() == domain[d].min()) && !(upperFace)); + || ((ldom[d].min() == domain[d].min()) && !(upperFace)); if (isBoundary) { - auto N = view.extent(d) - 1; using exec_space = typename Field::execution_space; @@ -376,8 +375,8 @@ namespace ippl { for (size_t i = 0; i < Dim; ++i) { bool upperFace_i = (ldom[i].max() == domain[i].max()); bool lowerFace_i = (ldom[i].min() == domain[i].min()); - end[i] = view.extent(i) - nghost - (upperFace_i)*(isCorner); - begin[i] = nghost + (lowerFace_i)*(isCorner); + end[i] = view.extent(i) - nghost - (upperFace_i) * (isCorner); + begin[i] = nghost + (lowerFace_i) * (isCorner); } begin[d] = ((0 + nghost - 1) * (1 - upperFace)) + (N * upperFace); end[d] = begin[d] + 1; @@ -400,7 +399,7 @@ namespace ippl { coords[d] += shift; apply(view, coords) += right; - }); + }); } } @@ -418,9 +417,9 @@ namespace ippl { throw IpplException("ExtrapolateFace::apply", "face number wrong"); } - bool upperFace = (face & 1); + bool upperFace = (face & 1); bool isBoundary = ((ldom[d].max() == domain[d].max()) && upperFace) - || ((ldom[d].min() == domain[d].min()) && !(upperFace)); + || ((ldom[d].min() == domain[d].min()) && !(upperFace)); if (isBoundary) { auto N = view.extent(d) - 1; @@ -458,7 +457,7 @@ namespace ippl { coords[d] += shift; apply(view, coords) = right; - }); + }); } } } // namespace ippl diff --git a/src/Field/HaloCells.h b/src/Field/HaloCells.h index c4d87b9bd..8b8924fd3 100644 --- a/src/Field/HaloCells.h +++ b/src/Field/HaloCells.h @@ -139,7 +139,8 @@ namespace ippl { * unpack function call */ template - void exchangeBoundaries(view_type& view, Layout_t* layout, SendOrder order, int nghost = 1); + void exchangeBoundaries(view_type& view, Layout_t* layout, SendOrder order, + int nghost = 1); /*! * Extract the subview of the original data. This does not copy. diff --git a/src/Field/HaloCells.hpp b/src/Field/HaloCells.hpp index eb56642ce..8aca44527 100644 --- a/src/Field/HaloCells.hpp +++ b/src/Field/HaloCells.hpp @@ -21,7 +21,8 @@ namespace ippl { } template - void HaloCells::accumulateHalo_noghost(view_type& view, Layout_t* layout, int nghost) { + void HaloCells::accumulateHalo_noghost(view_type& view, + Layout_t* layout, int nghost) { exchangeBoundaries(view, layout, HALO_TO_INTERNAL_NOGHOST, nghost); } template @@ -54,7 +55,7 @@ namespace ippl { // needed for the NOGHOST approach - we want to remove the ghost // cells on the boundaries of the global domain from the halo // exchange when we set HALO_TO_INTERNAL_NOGHOST - const auto domain = layout->getDomain(); + const auto domain = layout->getDomain(); const auto& ldomains = layout->getHostLocalDomains(); size_t totalRequests = 0; @@ -62,7 +63,7 @@ namespace ippl { totalRequests += componentNeighbors.size(); } - int me=Comm->rank(); + int me = Comm->rank(); using memory_space = typename view_type::memory_space; using buffer_type = mpi::Communicator::buffer_type; @@ -88,10 +89,9 @@ namespace ippl { range = recvRanges[index][i]; for (size_t j = 0; j < Dim; ++j) { - bool isLower = ((range.lo[j] + ldomains[me][j].first() - - nghost) == domain[j].min()); - bool isUpper = ((range.hi[j] - 1 + - ldomains[me][j].first() - nghost) + bool isLower = ((range.lo[j] + ldomains[me][j].first() - nghost) + == domain[j].min()); + bool isUpper = ((range.hi[j] - 1 + ldomains[me][j].first() - nghost) == domain[j].max()); range.lo[j] += isLower * (nghost); range.hi[j] -= isUpper * (nghost); @@ -124,10 +124,9 @@ namespace ippl { range = sendRanges[index][i]; for (size_t j = 0; j < Dim; ++j) { - bool isLower = ((range.lo[j] + ldomains[me][j].first() - - nghost) == domain[j].min()); - bool isUpper = ((range.hi[j] - 1 + - ldomains[me][j].first() - nghost) + bool isLower = ((range.lo[j] + ldomains[me][j].first() - nghost) + == domain[j].min()); + bool isUpper = ((range.hi[j] - 1 + ldomains[me][j].first() - nghost) == domain[j].max()); range.lo[j] += isLower * (nghost); range.hi[j] -= isUpper * (nghost); @@ -150,7 +149,7 @@ namespace ippl { if (totalRequests > 0) { MPI_Waitall(totalRequests, requests.data(), MPI_STATUSES_IGNORE); } - + comm.freeAllBuffers(); } diff --git a/src/FieldLayout/FieldLayout.h b/src/FieldLayout/FieldLayout.h index 780040e8b..598284176 100644 --- a/src/FieldLayout/FieldLayout.h +++ b/src/FieldLayout/FieldLayout.h @@ -223,20 +223,22 @@ namespace ippl { // false: template bool operator==(const FieldLayout& x) const { - // Throw exception if the domains are not the same if (gDomain_m != x.getDomain()) { - throw std::runtime_error("FieldLayout: only FieldLayouts with the same global domain should be compared"); + throw std::runtime_error( + "FieldLayout: only FieldLayouts with the same global domain should be " + "compared"); } return gDomain_m == x.getDomain(); } bool operator==(const FieldLayout& x) const { - // Throw exception if the domains are not the same if (gDomain_m != x.getDomain()) { - throw std::runtime_error("FieldLayout: only FieldLayouts with the same global domain should be compared"); + throw std::runtime_error( + "FieldLayout: only FieldLayouts with the same global domain should be " + "compared"); } for (unsigned int i = 0; i < Dim; ++i) { diff --git a/src/FieldLayout/FieldLayout.hpp b/src/FieldLayout/FieldLayout.hpp index 2bcb1bcd1..e5a0d2b56 100644 --- a/src/FieldLayout/FieldLayout.hpp +++ b/src/FieldLayout/FieldLayout.hpp @@ -95,8 +95,11 @@ namespace ippl { } if (totparelems < nRanks) { - throw std::runtime_error("FieldLayout:initialize: domain can only be partitioned in to " - + std::to_string(totparelems) + " local domains, but there are " + std::to_string(nRanks) + " ranks, decrease the number of ranks or increase the domain."); + throw std::runtime_error( + "FieldLayout:initialize: domain can only be partitioned in to " + + std::to_string(totparelems) + " local domains, but there are " + + std::to_string(nRanks) + + " ranks, decrease the number of ranks or increase the domain."); } Kokkos::resize(dLocalDomains_m, nRanks); diff --git a/src/FieldLayout/SubFieldLayout.h b/src/FieldLayout/SubFieldLayout.h index 85fdd0151..b26a140ce 100644 --- a/src/FieldLayout/SubFieldLayout.h +++ b/src/FieldLayout/SubFieldLayout.h @@ -22,17 +22,18 @@ namespace ippl { /** * @class SubFieldLayout * @brief SubFieldLayout provides a layout for a sub-region of a larger field - * + * * SubFieldLayout extends FieldLayout to handle sub-regions of a larger computational domain. * It ensures that the sub-region is partitioned in the same way as the original FieldLayout, - * maintaining consistent parallel decomposition and neighbor relationships within the sub-region. - * + * maintaining consistent parallel decomposition and neighbor relationships within the + * sub-region. + * * @par Important Constraint: * SubFieldLayout only allows for sub-layouts that do NOT leave local domains empty. * All MPI ranks must have at least some portion of the sub-domain assigned to them. * If a sub-domain would result in empty local domains for some ranks, an exception * will be thrown during initialization. - * + * * @tparam Dim Number of spatial dimensions */ template @@ -45,71 +46,74 @@ namespace ippl { /** * @brief Default constructor, which should only be used if you are going to * call 'initialize' soon after (before using in any context) - * + * * @param communicator MPI communicator to use (defaults to MPI_COMM_WORLD) */ SubFieldLayout(const mpi::Communicator& = MPI_COMM_WORLD); /** * @brief Constructor that creates a SubFieldLayout for a sub-region of a larger domain - * + * * @param communicator MPI communicator to use * @param domain The full domain that defines the partitioning - * @param subDomain The sub-region within the full domain, which is partitioned in the same way as the fullomain + * @param subDomain The sub-region within the full domain, which is partitioned in the same + * way as the fullomain * @param decomp Array specifying which dimensions should be parallel * @param isAllPeriodic Whether all dimensions have periodic boundary conditions */ - SubFieldLayout(mpi::Communicator, const NDIndex& domain, const NDIndex& subDomain, std::array decomp, - bool isAllPeriodic = false); + SubFieldLayout(mpi::Communicator, const NDIndex& domain, const NDIndex& subDomain, + std::array decomp, bool isAllPeriodic = false); /** * @brief Constructor for full-domain layout. - * + * * @param communicator MPI communicator to use - * @param domain The full domain that defines the partitioning and is used as the sub-domain simultaneously + * @param domain The full domain that defines the partitioning and is used as the sub-domain + * simultaneously * @param decomp Array specifying which dimensions should be parallel * @param isAllPeriodic Whether all dimensions have periodic boundary conditions */ SubFieldLayout(mpi::Communicator, const NDIndex& domain, std::array decomp, - bool isAllPeriodic = false); + bool isAllPeriodic = false); /** * @brief Destructor: Everything deletes itself automatically */ virtual ~SubFieldLayout() = default; - + /** * @brief Initializes a SubFieldLayout with the sub-domain partitioned in the same way * as the original FieldLayout partitiones the full domain - * + * * @param domain The full domain to be partitioned * @param subDomain The sub-region within the full domain * @param decomp Array specifying which dimensions should be parallel * @param isAllPeriodic Whether all dimensions have periodic boundary conditions */ - void initialize(const NDIndex& domain, const NDIndex& subDomain, std::array decomp, - bool isAllPeriodic = false); - + void initialize(const NDIndex& domain, const NDIndex& subDomain, + std::array decomp, bool isAllPeriodic = false); + /** - * @brief Initializes a SubFieldLayout using the domain as both the full domain and sub-domain - * + * @brief Initializes a SubFieldLayout using the domain as both the full domain and + * sub-domain + * * @param domain The domain to be partitioned * @param decomp Array specifying which dimensions should be parallel * @param isAllPeriodic Whether all dimensions have periodic boundary conditions */ void initialize(const NDIndex& domain, std::array decomp, - bool isAllPeriodic = false); + bool isAllPeriodic = false); /** * @brief Return the original domain before sub-region extraction - * + * * @return Reference to the original full domain */ const NDIndex& getOriginDomain() const { return originDomain_m; } - + /** * @brief Compare SubFieldLayouts to see if they represent the same domain - * + * * @tparam Dim2 Dimension of the other SubFieldLayout * @param x The other SubFieldLayout to compare with * @return true if both the current domain, origin domain and local domains match @@ -139,10 +143,11 @@ namespace ippl { /** * @brief Compare SubFieldLayout to a FieldLayout to see if they represent the same domain - * + * * @tparam Dim2 Dimension of the FieldLayout * @param x The FieldLayout to compare with - * @return true if the SubFieldLayout's domain equals its original domain and matches the FieldLayout's domain and local domains + * @return true if the SubFieldLayout's domain equals its original domain and matches the + * FieldLayout's domain and local domains */ template bool operator==(const FieldLayout& x) const { @@ -170,7 +175,7 @@ namespace ippl { private: /** * @brief Original global domain in which the sub-field is defined - * + * * This stores the full domain before any sub-region extraction, * allowing comparison with regular FieldLayouts. */ diff --git a/src/FieldLayout/SubFieldLayout.hpp b/src/FieldLayout/SubFieldLayout.hpp index 53ee24c11..cd5b65586 100644 --- a/src/FieldLayout/SubFieldLayout.hpp +++ b/src/FieldLayout/SubFieldLayout.hpp @@ -19,7 +19,7 @@ namespace ippl { /** * @copydoc SubFieldLayout::SubFieldLayout(const mpi::Communicator&) - * + * * Creates a SubFieldLayout without specifying domains. The layout must be initialized * later using the initialize() methods. This constructor is useful when you need to * defer the layout configuration until more information is available. @@ -29,57 +29,61 @@ namespace ippl { : FieldLayout(communicator) {} /** - * @copydoc SubFieldLayout::SubFieldLayout(mpi::Communicator, const NDIndex&, const NDIndex&, std::array, bool) - * + * @copydoc SubFieldLayout::SubFieldLayout(mpi::Communicator, const NDIndex&, const + * NDIndex&, std::array, bool) + * * Implementation details: * Initializes both the full domain decomposition and the sub-domain layout. The sub-domain * must be contained within the full domain. All MPI ranks must have non-empty local domains * after intersection with the sub-domain, otherwise an exception will be thrown. - * + * * This constructor sets up the parallel decomposition based on the full domain, then * restricts the full domain to the specified sub-region while maintaining the same * partitioning structure. */ template SubFieldLayout::SubFieldLayout(mpi::Communicator communicator, const NDIndex& domain, - const NDIndex& subDomain, std::array isParallel, bool isAllPeriodic) + const NDIndex& subDomain, + std::array isParallel, bool isAllPeriodic) : FieldLayout(communicator) { initialize(domain, subDomain, isParallel, isAllPeriodic); } /** - * @copydoc SubFieldLayout::SubFieldLayout(mpi::Communicator, const NDIndex&, std::array, bool) - * + * @copydoc SubFieldLayout::SubFieldLayout(mpi::Communicator, const NDIndex&, + * std::array, bool) + * * Implementation details: * Creates a SubFieldLayout where the sub-domain is the same as the full domain, making it * functionally equivalent to a regular FieldLayout. */ template - SubFieldLayout::SubFieldLayout(mpi::Communicator communicator, const NDIndex& domain, - std::array isParallel, bool isAllPeriodic) + SubFieldLayout::SubFieldLayout(mpi::Communicator communicator, const NDIndex& domain, + std::array isParallel, bool isAllPeriodic) : FieldLayout(communicator) { initialize(domain, isParallel, isAllPeriodic); } /** - * @copydoc SubFieldLayout::initialize(const NDIndex&, const NDIndex&, std::array, bool) - * + * @copydoc SubFieldLayout::initialize(const NDIndex&, const NDIndex&, + * std::array, bool) + * * Implementation details: * This method first partitions the full domain for parallel processing, * then restricts each rank's local domain to the specified sub-domain. - * - * The sub-domain must be contained within the full domain, and all MPI ranks must have + * + * The sub-domain must be contained within the full domain, and all MPI ranks must have * non-empty local domains after intersection with the sub-domain, otherwise an exception * will be thrown. */ template - void SubFieldLayout::initialize(const NDIndex& domain, const NDIndex& subDomain, std::array isParallel, - bool isAllPeriodic) { - + void SubFieldLayout::initialize(const NDIndex& domain, const NDIndex& subDomain, + std::array isParallel, bool isAllPeriodic) { // Ensure the sub-domain is contained within the main domain PAssert(domain.contains(subDomain)); - // Call the base class initialize method to set up the main domain and parallel decomposition + // Call the base class initialize method to set up the main domain and parallel + // decomposition FieldLayout::initialize(domain, isParallel, isAllPeriodic); unsigned int nRanks = this->comm.size(); @@ -87,18 +91,22 @@ namespace ippl { originDomain_m = domain; this->gDomain_m = subDomain; - + // Check if all ranks have a valid local domain that intersects with the sub-domain if (this->hLocalDomains_m(this->comm.rank()).intersect(subDomain).empty()) { - throw std::runtime_error("SubFieldLayout:initialize: given subdomain is not valid, rank" - + std::to_string(this->comm.rank()) + " has an empty local domain, choose a sub-domain that has content on all ranks"); + throw std::runtime_error( + "SubFieldLayout:initialize: given subdomain is not valid, rank" + + std::to_string(this->comm.rank()) + + " has an empty local domain, choose a sub-domain that has content on all ranks"); } - // If the local domain is not contained in the sub-domain, change it to the intersection of the local domain and the sub-domain - // This ensures that the sub-field layout is consistent with the original layout + // If the local domain is not contained in the sub-domain, change it to the intersection of + // the local domain and the sub-domain This ensures that the sub-field layout is consistent + // with the original layout for (unsigned int rank = 0; rank < nRanks; ++rank) { if (!this->gDomain_m.contains(this->hLocalDomains_m(rank))) { - this->hLocalDomains_m(rank) = this->hLocalDomains_m(rank).intersect(this->gDomain_m); + this->hLocalDomains_m(rank) = + this->hLocalDomains_m(rank).intersect(this->gDomain_m); } } @@ -111,15 +119,16 @@ namespace ippl { /** * @copydoc SubFieldLayout::initialize(const NDIndex&, std::array, bool) - * + * * Implementation details: * This method initializes the layout to use the entire domain as both the full domain * and the sub-domain, making it equivalent to a regular FieldLayout. */ template - void SubFieldLayout::initialize(const NDIndex& domain, std::array isParallel, - bool isAllPeriodic) { - // Call the base class initialize method to set up the main domain and parallel decomposition + void SubFieldLayout::initialize(const NDIndex& domain, + std::array isParallel, bool isAllPeriodic) { + // Call the base class initialize method to set up the main domain and parallel + // decomposition FieldLayout::initialize(domain, isParallel, isAllPeriodic); originDomain_m = domain; diff --git a/src/Ippl.cpp b/src/Ippl.cpp index fc9563535..011a5ead9 100644 --- a/src/Ippl.cpp +++ b/src/Ippl.cpp @@ -88,7 +88,7 @@ namespace ippl { Info->setOutputLevel(infoLevel); Error->setOutputLevel(infoLevel); Warn->setOutputLevel(infoLevel); - + } catch (const std::exception& e) { if (Comm->rank() == 0) { std::cerr << e.what() << std::endl; diff --git a/src/LinearSolvers/PCG.h b/src/LinearSolvers/PCG.h index bdb65778d..cce173d61 100644 --- a/src/LinearSolvers/PCG.h +++ b/src/LinearSolvers/PCG.h @@ -6,9 +6,9 @@ #ifndef IPPL_PCG_H #define IPPL_PCG_H +#include "FEM/FEMVector.h" #include "Preconditioner.h" #include "SolverAlgorithm.h" -#include "FEM/FEMVector.h" namespace ippl { template ("tolerance") * norm(rhs); while (iterations_m < maxIterations && residueNorm > tolerance) { - IpplTimings::startTimer(apply); q = op_m(d); IpplTimings::stopTimer(apply); @@ -153,7 +151,7 @@ namespace ippl { IpplTimings::startTimer(inner); T alpha = delta1 / innerProduct(d, q); IpplTimings::stopTimer(inner); - lhs = lhs + alpha * d; + lhs = lhs + alpha * d; // The exact residue is given by // r = rhs - op_m(lhs); @@ -194,11 +192,10 @@ namespace ippl { lhs_type q; }; - template - class CG, FEMVector > - : public SolverAlgorithm, FEMVector> { + class CG, + FEMVector> : public SolverAlgorithm, FEMVector> { using Base = SolverAlgorithm, FEMVector>; public: @@ -249,13 +246,12 @@ namespace ippl { * @return Iteration count of last solve */ virtual int getIterationCount() { return iterations_m; } - + virtual void operator()(lhs_type& lhs, rhs_type& rhs, const ParameterList& params) override { - - //constexpr unsigned Dim = lhs_type::dim; - //typename lhs_type::Mesh_t& mesh = lhs.get_mesh(); - //typename lhs_type::Layout_t& layout = lhs.getLayout(); + // constexpr unsigned Dim = lhs_type::dim; + // typename lhs_type::Mesh_t& mesh = lhs.get_mesh(); + // typename lhs_type::Layout_t& layout = lhs.getLayout(); iterations_m = 0; const int maxIterations = params.get("max_iterations"); @@ -263,23 +259,21 @@ namespace ippl { // Variable names mostly based on description in // https://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf lhs_type r = lhs.deepCopy(); - r = 0; + r = 0; lhs_type d = lhs.deepCopy(); - d = 0; - - + d = 0; + r = rhs - op_m(lhs); r.setHalo(0); - d = r; //.deepCopy(); - //d.setFieldBC(bc); + d = r; //.deepCopy(); + // d.setFieldBC(bc); T delta1 = innerProduct(r, d); T delta0 = delta1; residueNorm = Kokkos::sqrt(delta1); const T tolerance = params.get("tolerance") * norm(rhs); lhs_type q = lhs.deepCopy(); - q = 0; - + q = 0; while (iterations_m < maxIterations && residueNorm > tolerance) { q = op_m(d); @@ -303,8 +297,6 @@ namespace ippl { residueNorm = Kokkos::sqrt(delta1); d = r + beta * d; ++iterations_m; - - } } @@ -316,7 +308,6 @@ namespace ippl { int iterations_m = 0; }; - template @@ -337,7 +328,7 @@ namespace ippl { PCG() : CG() - , preconditioner_m(nullptr){}; + , preconditioner_m(nullptr) {}; /*! * Sets the differential operator for the conjugate gradient algorithm @@ -365,8 +356,9 @@ namespace ippl { // set in main double omega = 1.57079632679 // This is a dummy default parameter, actual default // parameter should be set in main - // default = pi/2 as this was found optimal during hyperparameter scan for test case - // (see https://amas.web.psi.ch/people/aadelmann/ETH-Accel-Lecture-1/projectscompleted/cse/BSc-mbolliger.pdf) + // default = pi/2 as this was found optimal during hyperparameter scan for test case + // (see + // https://amas.web.psi.ch/people/aadelmann/ETH-Accel-Lecture-1/projectscompleted/cse/BSc-mbolliger.pdf) ) override { if (preconditioner_type == "jacobi") { // Turn on damping parameter @@ -396,8 +388,7 @@ namespace ippl { preconditioner_m = std::move(std::make_unique< richardson_preconditioner_alt>( - std::move(op), std::move(inverse_diagonal), - richardson_iterations)); + std::move(op), std::move(inverse_diagonal), richardson_iterations)); } else if (preconditioner_type == "gauss-seidel") { preconditioner_m = std::move( std::make_unique>( @@ -468,7 +459,7 @@ namespace ippl { this->residueNorm = Kokkos::sqrt(Kokkos::abs(delta1)); const T tolerance = params.get("tolerance") * this->residueNorm; - while (this->iterations_m < maxIterations && this->residueNorm > tolerance) { + while (this->iterations_mresidueNorm> tolerance) { q = this->op_m(d); q = q.deepCopy(); T alpha = delta1 / innerProduct(d, q); diff --git a/src/LinearSolvers/Preconditioner.h b/src/LinearSolvers/Preconditioner.h index 09eb876aa..e26f34076 100644 --- a/src/LinearSolvers/Preconditioner.h +++ b/src/LinearSolvers/Preconditioner.h @@ -296,12 +296,11 @@ namespace ippl { } Field operator()(Field& r) override { - - // In the FEM solver, which uses the preconditioner, + // In the FEM solver, which uses the preconditioner, // we re-use a resultField to avoid allocating new // memory at every iteration. // In order for the operator calls to not rewrite - // on this same field over and over when calling + // on this same field over and over when calling // the operators (upper, diag, inverse, lower, etc) // we need deep copies to the preconditioner fields. @@ -310,7 +309,7 @@ namespace ippl { ULg_m = upper_and_lower_m(g_m); ULg_m = ULg_m.deepCopy(); g_m = r - ULg_m; - + // The inverse diagonal is applied to the // vector itself to return the result usually. // However, the operator for FEM already @@ -332,7 +331,7 @@ namespace ippl { mesh_type& mesh = b.get_mesh(); ULg_m = Field(mesh, layout); - g_m = Field(mesh, layout); + g_m = Field(mesh, layout); } protected: @@ -357,23 +356,23 @@ namespace ippl { using layout_type = typename Field::Layout_t; richardson_preconditioner_alt(OperatorF&& op, InvDiagF&& inverse_diagonal, - unsigned innerloops = 5) + unsigned innerloops = 5) : preconditioner("Richardson_alt") , innerloops_m(innerloops) { - op_m = std::move(op); + op_m = std::move(op); inverse_diagonal_m = std::move(inverse_diagonal); } Field operator()(Field& r) override { - // In the FEM solver, which uses the preconditioner, + // In the FEM solver, which uses the preconditioner, // we re-use a resultField to avoid allocating new // memory at every iteration. // In order for the operator calls to not rewrite - // on this same field over and over when calling + // on this same field over and over when calling // the operators (upper, diag, inverse, lower, etc) // we need deep copies to the preconditioner fields. - g_m = 0; + g_m = 0; g_old_m = 0; for (unsigned int j = 0; j < innerloops_m; ++j) { @@ -402,8 +401,8 @@ namespace ippl { layout_type& layout = b.getLayout(); mesh_type& mesh = b.get_mesh(); - Ag_m = Field(mesh, layout); - g_m = Field(mesh, layout); + Ag_m = Field(mesh, layout); + g_m = Field(mesh, layout); g_old_m = Field(mesh, layout); } @@ -443,11 +442,11 @@ namespace ippl { x = 0; // Initial guess - // In the FEM solver, which uses the preconditioner, + // In the FEM solver, which uses the preconditioner, // we re-use a resultField to avoid allocating new // memory at every iteration. // In order for the operator calls to not rewrite - // on this same field over and over when calling + // on this same field over and over when calling // the operators (upper, diag, inverse, lower, etc) // we need deep copies to the preconditioner fields. @@ -554,11 +553,11 @@ namespace ippl { static IpplTimings::TimerRef loopTimer = IpplTimings::getTimer("SSOR loop"); IpplTimings::startTimer(loopTimer); - // In the FEM solver, which uses the preconditioner, + // In the FEM solver, which uses the preconditioner, // we re-use a resultField to avoid allocating new // memory at every iteration. // In order for the operator calls to not rewrite - // on this same field over and over when calling + // on this same field over and over when calling // the operators (upper, diag, inverse, lower, etc) // we need deep copies to the preconditioner fields. diff --git a/src/Manager/BaseManager.h b/src/Manager/BaseManager.h index 525dbd4bd..58a9e3072 100644 --- a/src/Manager/BaseManager.h +++ b/src/Manager/BaseManager.h @@ -22,8 +22,7 @@ namespace ippl { * Derived classes can override this method to allocate memory, initialize variables, etc. * The default implementation does nothing. */ - virtual void pre_run() { /* default does nothing */ - } + virtual void pre_run() { /* default does nothing */ } /** * @brief A method that should be used for preparation before perfoming a step of @@ -32,8 +31,7 @@ namespace ippl { * The default implementation does nothing. */ - virtual void pre_step() { /* default does nothing */ - } + virtual void pre_step() { /* default does nothing */ } /** * @brief A method that should be used after perfoming a step of simulation. @@ -41,8 +39,7 @@ namespace ippl { * Derived classes can override this method to dump data, increment time, etc. * The default implementation does nothing. */ - virtual void post_step() { /* default does nothing */ - } + virtual void post_step() { /* default does nothing */ } /** * @brief A method that should be used to execute/advance a step of simulation. diff --git a/src/Manager/FieldSolverBase.h b/src/Manager/FieldSolverBase.h index 2aa4d20d8..24954c9fa 100644 --- a/src/Manager/FieldSolverBase.h +++ b/src/Manager/FieldSolverBase.h @@ -3,9 +3,10 @@ #include -#include "Manager/BaseManager.h" #include "datatypes.h" +#include "Manager/BaseManager.h" + // Define the FieldSolverBase class namespace ippl { template diff --git a/src/Manager/PicManager.h b/src/Manager/PicManager.h index 9eae389b0..8bc903dbb 100644 --- a/src/Manager/PicManager.h +++ b/src/Manager/PicManager.h @@ -62,7 +62,6 @@ namespace ippl { */ std::shared_ptr getParticleContainer() { return pcontainer_m; } - /** * @brief Get a particle container by index. * @param i The index of the particle container (0-based). @@ -137,7 +136,7 @@ namespace ippl { std::shared_ptr fcontainer_m; /** - * @brief Default (first) particle container, kept for backward + * @brief Default (first) particle container, kept for backward * compatibility. */ std::shared_ptr pcontainer_m; diff --git a/src/Manager/datatypes.h b/src/Manager/datatypes.h index cabcc7da3..276eda7ca 100644 --- a/src/Manager/datatypes.h +++ b/src/Manager/datatypes.h @@ -1,12 +1,12 @@ #ifndef IPPL_DATATYPES_H #define IPPL_DATATYPES_H +#include "PoissonSolvers/FEMPoissonSolver.h" #include "PoissonSolvers/FFTOpenPoissonSolver.h" #include "PoissonSolvers/FFTPeriodicPoissonSolver.h" #include "PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h" #include "PoissonSolvers/NullSolver.h" #include "PoissonSolvers/PoissonCG.h" -#include "PoissonSolvers/FEMPoissonSolver.h" #include "PoissonSolvers/PreconditionedFEMPoissonSolver.h" // some typedefs @@ -67,16 +67,15 @@ using OpenSolver_t = ConditionalType, Field_t>>; template -using FEMSolver_t = ippl::FEMPoissonSolver, Field>; +using FEMSolver_t = ippl::FEMPoissonSolver, Field>; template -using FEMPreconSolver_t = ippl::PreconditionedFEMPoissonSolver, Field>; +using FEMPreconSolver_t = ippl::PreconditionedFEMPoissonSolver, Field>; template -using Solver_t = VariantFromConditionalTypes, FFTSolver_t, - FFTTruncatedGreenSolver_t, - OpenSolver_t, NullSolver_t, - FEMSolver_t, FEMPreconSolver_t>; +using Solver_t = VariantFromConditionalTypes< + CGSolver_t, FFTSolver_t, FFTTruncatedGreenSolver_t, + OpenSolver_t, NullSolver_t, FEMSolver_t, FEMPreconSolver_t>; extern const char* TestName; diff --git a/src/MaxwellSolvers/AbsorbingBC.h b/src/MaxwellSolvers/AbsorbingBC.h index 81474241d..c8bf4f2e3 100644 --- a/src/MaxwellSolvers/AbsorbingBC.h +++ b/src/MaxwellSolvers/AbsorbingBC.h @@ -219,7 +219,8 @@ struct second_order_abc_edge { using ippl::apply; // Get the opposite direction of the normal vectors for the two normal axes (direction to - // the interior of the domain), 1 or -1 in the direction of the normal axis and 0 in the others + // the interior of the domain), 1 or -1 in the direction of the normal axis and 0 in the + // others ippl::Vector normal_axis1_onehot = ippl::Vector{normal_axis1 == 0, normal_axis1 == 1, normal_axis1 == 2} * int32_t(na1_zero ? 1 : -1); diff --git a/src/MaxwellSolvers/FDTDSolverBase.h b/src/MaxwellSolvers/FDTDSolverBase.h index 62028eda1..1d8e4c1ae 100644 --- a/src/MaxwellSolvers/FDTDSolverBase.h +++ b/src/MaxwellSolvers/FDTDSolverBase.h @@ -75,7 +75,7 @@ namespace ippl { * @brief Evaluates the electric and magnetic fields. */ void evaluate_EB(); - + /** * @brief Initializes the solver. This is a pure virtual function. */ diff --git a/src/MaxwellSolvers/FEMMaxwellDiffusionSolver.h b/src/MaxwellSolvers/FEMMaxwellDiffusionSolver.h index 6c627a3ff..8caacdcf2 100644 --- a/src/MaxwellSolvers/FEMMaxwellDiffusionSolver.h +++ b/src/MaxwellSolvers/FEMMaxwellDiffusionSolver.h @@ -1,24 +1,25 @@ // Class FEMMaxwellDifussionSolver -// Solves the electric diffusion probelm given by curl(curl(E)) + E = f in +// Solves the electric diffusion probelm given by curl(curl(E)) + E = f in // the domain and n x E = 0 on the boundary. #ifndef IPPL_FEM_MAXWELL_DIFFUSION_SOLVER_H #define IPPL_FEM_MAXWELL_DIFFUSION_SOLVER_H -#include "LinearSolvers/PCG.h" -#include "Maxwell.h" +#include #include #include -#include + +#include "LinearSolvers/PCG.h" +#include "Maxwell.h" namespace ippl { /** * @brief Representation of the lhs of the problem we are trying to solve. - * - * In our case this corresponds to the variational formulation of the + * + * In our case this corresponds to the variational formulation of the * curl(curl(E)) + E and is curl(b_i)*curl(b_j) + b_i*b_j. - * + * * @tparam T The type we are working with. * @tparam Dim the dimension of the space. * @tparam numElementDOFs the number of DOFs per element that we have. @@ -27,7 +28,7 @@ namespace ippl { struct EvalFunctor { /** * @brief The inverse transpose Jacobian. - * + * * As we have a unirectangular grid it is the same for all the differnt * Elements and we therefore have to store it only once. */ @@ -35,7 +36,7 @@ namespace ippl { /** * @brief The determinant of the Jacobian. - * + * * As we have a unirectangular grid it is the same for all the differnt * Elements and we therefore have to store it only once. */ @@ -51,28 +52,28 @@ namespace ippl { /** * @brief Returns the evaluation of * (curl(b_i)*curl(b_j) + b_i*b_j)*absDetDPhi. - * + * * This function takes as input the basis function values and their curl * for the different DOFs and returns the evaluation of the inner part * of the integral of the variational formuation, which corresponds to * (curl(b_i)*curl(b_j) + b_i*b_j), but note that we additionally also * multiply this with absDetDPhi, which is required by the quadrature * rule. In theroy this could also be done outside of this. - * + * * @param i The first DOF index. * @param j The second DOF index. * @param curl_b_q_k The curl of the DOFs. * @param val_b_q_k The values of the DOFs. - * + * * @returns (curl(b_i)*curl(b_j) + b_i*b_j)*absDetDPhi */ - KOKKOS_FUNCTION auto operator()(size_t i, size_t j, + KOKKOS_FUNCTION auto operator()( + size_t i, size_t j, const ippl::Vector, numElementDOFs>& curl_b_q_k, const ippl::Vector, numElementDOFs>& val_b_q_k) const { - - T curlTerm = dot(DPhiInvT*curl_b_q_k[j], DPhiInvT*curl_b_q_k[i]).apply(); + T curlTerm = dot(DPhiInvT * curl_b_q_k[j], DPhiInvT * curl_b_q_k[i]).apply(); T massTerm = dot(val_b_q_k[j], val_b_q_k[i]).apply(); - return (curlTerm + massTerm)*absDetDPhi; + return (curlTerm + massTerm) * absDetDPhi; } }; @@ -92,41 +93,41 @@ namespace ippl { // vector data represented by an ippl::Vector using T = typename FieldType::value_type::value_type; - typedef Vector point_t; + typedef Vector point_t; public: - using Base = Maxwell; + using Base = Maxwell; using MeshType = typename FieldType::Mesh_t; // PCG (Preconditioned Conjugate Gradient) is the solver algorithm used using PCGSolverAlgorithm_t = CG, FEMVector, FEMVector, FEMVector, - FEMVector, FEMVector, FEMVector>; + FEMVector, FEMVector, FEMVector>; // FEM Space types - using ElementType = std::conditional_t, - ippl::HexahedralElement>; + using ElementType = + std::conditional_t, ippl::HexahedralElement>; using QuadratureType = GaussJacobiQuadrature; using NedelecType = NedelecSpace; // default constructor (compatibility with Alpine) - FEMMaxwellDiffusionSolver() + FEMMaxwellDiffusionSolver() : Base() , rhsVector_m(nullptr) , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) - , nedelecSpace_m(*(new MeshType(NDIndex(Vector(0)), Vector(0), - Vector(0))), refElement_m, quadrature_m) - {} + , nedelecSpace_m(*(new MeshType(NDIndex(Vector(0)), + Vector(0), Vector(0))), + refElement_m, quadrature_m) {} - FEMMaxwellDiffusionSolver(FieldType& lhs, FieldType& rhs, const FEMVector& rhsVector) + FEMMaxwellDiffusionSolver(FieldType& lhs, FieldType& rhs, + const FEMVector& rhsVector) : Base(lhs, lhs, rhs) , rhsVector_m(nullptr) , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) , nedelecSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) { - static_assert(std::is_floating_point::value, "Not a floating point type"); setDefaultParameters(); @@ -136,11 +137,9 @@ namespace ippl { rhsVector_m->accumulateHalo(); rhsVector_m->fillHalo(); - } void setRhs(FieldType& rhs, const FEMVector& rhsVector) { - Base::setRhs(rhs); // Calcualte the rhs, using the Nedelec space @@ -155,7 +154,6 @@ namespace ippl { * @brief Solve the equation using finite element methods. */ void solve() override { - const Vector zeroNdIndex = Vector(0); // We can pass the zeroNdIndex here, since the transformation @@ -174,16 +172,16 @@ namespace ippl { // Create the functor object which stores the function we have to // solve for the lhs - EvalFunctor maxwellDiffusionEval( - DPhiInvT, absDetDPhi); - - // The Ax operator - const auto algoOperator = [maxwellDiffusionEval, this](FEMVector vector) - -> FEMVector { + EvalFunctor maxwellDiffusionEval(DPhiInvT, + absDetDPhi); + // The Ax operator + const auto algoOperator = [maxwellDiffusionEval, + this](FEMVector vector) -> FEMVector { vector.fillHalo(); - FEMVector return_vector = nedelecSpace_m.evaluateAx(vector,maxwellDiffusionEval); + FEMVector return_vector = + nedelecSpace_m.evaluateAx(vector, maxwellDiffusionEval); return_vector.accumulateHalo(); @@ -192,10 +190,10 @@ namespace ippl { // setup the CG solver pcg_algo_m.setOperator(algoOperator); - + // Create the coefficient vector for the solution FEMVector lhsVector = rhsVector_m->deepCopy(); - + // Solve the system using CG try { pcg_algo_m(lhsVector, *rhsVector_m, this->params_m); @@ -203,13 +201,12 @@ namespace ippl { std::string msg = e.where() + ": " + e.what() + "\n"; Kokkos::abort(msg.c_str()); } - + // store solution. lhsVector_m = std::make_unique>(lhsVector); // set the boundary values to the correct values. lhsVector.fillHalo(); - } /** @@ -227,10 +224,10 @@ namespace ippl { /** * @brief Reconstructs function values at arbitrary points in the mesh. - * + * * This function can be used to retrieve the values of a solution * function at arbitrary points inside of the mesh. - * + * * @note Currently the function is able to handle both cases, where we * have that \p positions only contains positions which are inside of * local domain of this MPI rank (i.e. each rank gets its own unique @@ -239,11 +236,11 @@ namespace ippl { * it can be guaranteed, that each rank will get its own \p positions * then certain parts of the function implementation can be removed. * Instructions for this are given in the implementation itself. - * + * * @param positions The points at which the function should be - * evaluated. A \c Kokkos::View which stores in each element a 2D/3D + * evaluated. A \c Kokkos::View which stores in each element a 2D/3D * point. - * + * * @return The function evaluated at the given points, stored inside of * \c Kokkos::View where each element corresponts to the function value * at the point described by the same element inside of \p positions. @@ -252,8 +249,6 @@ namespace ippl { return this->nedelecSpace_m.reconstructToPoints(positions, *lhsVector_m); } - - /** * @brief Given an analytical solution computes the L2 norm error. * @@ -267,14 +262,12 @@ namespace ippl { return error_norm; } - protected: - /** * @brief The CG Solver we use */ PCGSolverAlgorithm_t pcg_algo_m; - + /** * @brief Sets the default values for the CG solver. * Defaults are: max Iterations = 10, tolerance = 1e-13 @@ -310,7 +303,7 @@ namespace ippl { /** * @brief The Nedelec Space object. - * + * * This is the representation of the Nedelec space that we have and * which we use to interact with all the Nedelec stuff. */ @@ -319,6 +312,4 @@ namespace ippl { } // namespace ippl - - -#endif // IPPL_FEM_MAXWELL_DIFFUSION_SOLVER_H +#endif // IPPL_FEM_MAXWELL_DIFFUSION_SOLVER_H diff --git a/src/MaxwellSolvers/Maxwell.h b/src/MaxwellSolvers/Maxwell.h index 78b3e7e21..a56a75ac3 100644 --- a/src/MaxwellSolvers/Maxwell.h +++ b/src/MaxwellSolvers/Maxwell.h @@ -8,9 +8,10 @@ #include "Types/Vector.h" +#include "Utility/ParameterList.h" + #include "Field/Field.h" -#include "Utility/ParameterList.h" #include "FieldLayout/FieldLayout.h" #include "Meshes/UniformCartesian.h" @@ -54,7 +55,6 @@ namespace ippl { Bn_mp = &B; } - /*! * Merges another parameter set into the solver's parameters, overwriting * existing parameters in case of conflict diff --git a/src/Meshes/Mesh.h b/src/Meshes/Mesh.h index 96ce4406c..ac5259ed0 100644 --- a/src/Meshes/Mesh.h +++ b/src/Meshes/Mesh.h @@ -22,7 +22,7 @@ namespace ippl { typedef Vector vector_type; typedef Vector matrix_type; - KOKKOS_INLINE_FUNCTION Mesh(){}; + KOKKOS_INLINE_FUNCTION Mesh() {}; KOKKOS_INLINE_FUNCTION virtual ~Mesh(){}; diff --git a/src/Meshes/UniformCartesian.h b/src/Meshes/UniformCartesian.h index 54db34bd5..56e6ad186 100644 --- a/src/Meshes/UniformCartesian.h +++ b/src/Meshes/UniformCartesian.h @@ -43,11 +43,11 @@ namespace ippl { // (x,y,z) coordinates of indexed vertex: KOKKOS_INLINE_FUNCTION vector_type getVertexPosition(const NDIndex& ndi) const override { - //printf("inside getVertexPosition"); + // printf("inside getVertexPosition"); vector_type vertexPosition; for (unsigned int d = 0; d < Dim; d++) { vertexPosition(d) = ndi[d].first() * meshSpacing_m[d] + this->origin_m(d); - //printf("vertexPos = %lf", vertexPosition(d)); + // printf("vertexPos = %lf", vertexPosition(d)); } return vertexPosition; } diff --git a/src/Particle/ParticleAttrib.h b/src/Particle/ParticleAttrib.h index b9732fdf0..5be0e78a2 100644 --- a/src/Particle/ParticleAttrib.h +++ b/src/Particle/ParticleAttrib.h @@ -75,15 +75,15 @@ namespace ippl { } virtual ~ParticleAttrib() = default; - + size_type size() const override { return dview_m.extent(0); } - + size_type packedSize(const size_type count) const override { return count * sizeof(value_type); } - + void resize(size_type n) { Kokkos::resize(dview_m, n); } - + void realloc(size_type n) { Kokkos::realloc(dview_m, n); } void print() { diff --git a/src/Particle/ParticleAttrib.hpp b/src/Particle/ParticleAttrib.hpp index bacea8d52..bf5c86599 100644 --- a/src/Particle/ParticleAttrib.hpp +++ b/src/Particle/ParticleAttrib.hpp @@ -36,13 +36,11 @@ namespace ippl { size_type invalidCount) { // Replace all invalid particles in the valid region with valid // particles in the invalid region - auto dview = dview_m; + auto dview = dview_m; using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::destroy()", policy_type(0, invalidCount), - KOKKOS_LAMBDA(const size_t i) { - dview(deleteIndex(i)) = dview(keepIndex(i)); - }); + KOKKOS_LAMBDA(const size_t i) { dview(deleteIndex(i)) = dview(keepIndex(i)); }); } template @@ -53,8 +51,8 @@ namespace ippl { Kokkos::realloc(buf_m, size * overalloc); } - auto buf = buf_m; - auto dview = dview_m; + auto buf = buf_m; + auto dview = dview_m; using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::pack()", policy_type(0, size), @@ -72,8 +70,8 @@ namespace ippl { } size_type count = *(this->localNum_mp); - auto buf = buf_m; - auto dview = dview_m; + auto buf = buf_m; + auto dview = dview_m; using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::unpack()", policy_type(0, nrecvs), @@ -84,7 +82,7 @@ namespace ippl { template // KOKKOS_INLINE_FUNCTION ParticleAttrib& ParticleAttrib::operator=(T x) { - auto dview = dview_m; + auto dview = dview_m; using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::operator=()", policy_type(0, *(this->localNum_mp)), @@ -100,7 +98,7 @@ namespace ippl { using capture_type = detail::CapturedExpression; capture_type expr_ = reinterpret_cast(expr); - auto dview = dview_m; + auto dview = dview_m; using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::operator=()", policy_type(0, *(this->localNum_mp)), @@ -135,18 +133,18 @@ namespace ippl { const NDIndex& lDom = layout.getLocalNDIndex(); const int nghost = f.getNghost(); - //using policy_type = Kokkos::RangePolicy; + // using policy_type = Kokkos::RangePolicy; const bool useHashView = hash_array.extent(0) > 0; if (useHashView && (iteration_policy.end() > hash_array.extent(0))) { Inform m("scatter"); - m << "Hash array was passed to scatter, but size does not match iteration policy." << endl; + m << "Hash array was passed to scatter, but size does not match iteration policy." + << endl; ippl::Comm->abort(); } - auto dview = dview_m; + auto dview = dview_m; auto ppview = pp.getView(); Kokkos::parallel_for( - "ParticleAttrib::scatter", iteration_policy, - KOKKOS_LAMBDA(const size_t idx) { + "ParticleAttrib::scatter", iteration_policy, KOKKOS_LAMBDA(const size_t idx) { // map index to possible hash_map size_t mapped_idx = useHashView ? hash_array(idx) : idx; @@ -201,8 +199,8 @@ namespace ippl { const NDIndex& lDom = layout.getLocalNDIndex(); const int nghost = f.getNghost(); - auto dview = dview_m; - auto ppview = pp.getView(); + auto dview = dview_m; + auto ppview = pp.getView(); using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "ParticleAttrib::gather", policy_type(0, *(this->localNum_mp)), @@ -216,21 +214,19 @@ namespace ippl { Vector args = index - lDom.first() + nghost; // gather - value_type gathered = detail::gatherFromField(std::make_index_sequence<1 << Field::dim>{}, - view, wlo, whi, args); + value_type gathered = detail::gatherFromField( + std::make_index_sequence<1 << Field::dim>{}, view, wlo, whi, args); if (addToAttribute) { dview(idx) += gathered; } else { - dview(idx) = gathered; + dview(idx) = gathered; } }); IpplTimings::stopTimer(gatherTimer); } template - void ParticleAttrib::applyPermutation( - const hash_type& permutation) { - + void ParticleAttrib::applyPermutation(const hash_type& permutation) { const auto view = this->getView(); const auto size = this->getParticleCount(); @@ -243,24 +239,22 @@ namespace ippl { Kokkos::fence(); - Kokkos::deep_copy(Kokkos::subview(view, Kokkos::make_pair(0, size)), temp); + Kokkos::deep_copy(Kokkos::subview(view, Kokkos::make_pair(0, size)), + temp); } - template - void ParticleAttrib::internalCopy( - const hash_type &indices) { + template + void ParticleAttrib::internalCopy(const hash_type& indices) { auto copySize = indices.size(); create(copySize); - auto view = this->getView(); + auto view = this->getView(); const auto size = this->getParticleCount(); using policy_type = Kokkos::RangePolicy; Kokkos::parallel_for( "Copy to temp", policy_type(0, copySize), - KOKKOS_LAMBDA(const size_type &i) { - view(size + i) = view(i); - }); + KOKKOS_LAMBDA(const size_type& i) { view(size + i) = view(i); }); Kokkos::fence(); } @@ -275,7 +269,7 @@ namespace ippl { * * This overload preserves legacy functionality by providing a default iteration policy. * It calls the member scatter() with a default Kokkos::RangePolicy. - * + * * @note The default behaviour is to scatter all particles without any custom index mapping. * * @tparam Attrib1 The type of the particle attribute. @@ -286,19 +280,21 @@ namespace ippl { * @param f The field onto which the data is scattered. * @param pp The ParticleAttrib representing particle positions. */ - template > + template > inline void scatter(const Attrib1& attrib, Field& f, const Attrib2& pp) { - attrib.scatter(f, pp, policy_type(0, attrib.getParticleCount())); + attrib.scatter(f, pp, policy_type(0, attrib.getParticleCount())); } /** - * @brief Non-class interface for scattering with a custom iteration policy and optional index array. + * @brief Non-class interface for scattering with a custom iteration policy and optional index + * array. * * This overload allows the caller to specify a custom `Kokkos::range_policy` and an optional * `ippl::hash_type` array. It forwards the parameters to the member scatter() function. - * - * @note See ParticleAttrib::scatter() for more information on the custom iteration functionality. + * + * @note See ParticleAttrib::scatter() for more information on the custom iteration + * functionality. * * @tparam Attrib1 The type of the particle attribute. * @tparam Field The type of the field. @@ -310,33 +306,33 @@ namespace ippl { * @param iteration_policy A custom `Kokkos::range_policy` defining the iteration range. * @param hash_array An optional `ippl::hash_type` array for index mapping. */ - template > - inline void scatter(const Attrib1& attrib, Field& f, const Attrib2& pp, + template > + inline void scatter(const Attrib1& attrib, Field& f, const Attrib2& pp, policy_type iteration_policy, typename Attrib1::hash_type hash_array = {}) { attrib.scatter(f, pp, iteration_policy, hash_array); } /** * @brief Non-class interface for gathering field data into a particle attribute. - * + * * This interface calls the member ParticleAttrib::gather() function with the provided * parameters and preserving legacy behavior by assigning `addToAttribute` a default value. - * + * * @note See ParticleAttrib::gather() for more information on the behavior of `addToAttribute`. - * + * * @tparam Attrib1 The type of the particle attribute. * @tparam Field The type of the field. * @tparam Attrib2 The type of the particle position attribute. * @param attrib The particle attribute to gather data into. * @param f The field from which data is gathered. * @param pp The ParticleAttrib representing particle positions. - * @param addToAttribute If true, the gathered field value is added to the current attribute value; - * otherwise, the attribute value is overwritten. + * @param addToAttribute If true, the gathered field value is added to the current attribute + * value; otherwise, the attribute value is overwritten. */ template - inline void gather(Attrib1& attrib, Field& f, const Attrib2& pp, - const bool addToAttribute = false) { + inline void gather(Attrib1& attrib, Field& f, const Attrib2& pp, + const bool addToAttribute = false) { attrib.gather(f, pp, addToAttribute); } @@ -344,7 +340,7 @@ namespace ippl { template \ T ParticleAttrib::name() { \ T temp = 0.0; \ - auto dview = dview_m; \ + auto dview = dview_m; \ using policy_type = Kokkos::RangePolicy; \ Kokkos::parallel_reduce( \ "fun", policy_type(0, *(this->localNum_mp)), \ diff --git a/src/Particle/ParticleAttribBase.h b/src/Particle/ParticleAttribBase.h index b0e973e79..de68ead67 100644 --- a/src/Particle/ParticleAttribBase.h +++ b/src/Particle/ParticleAttribBase.h @@ -78,7 +78,7 @@ namespace ippl { size_type getParticleCount() const { return *localNum_mp; } virtual void applyPermutation(const hash_type&) = 0; - virtual void internalCopy(const hash_type&) = 0; + virtual void internalCopy(const hash_type&) = 0; protected: const size_type* localNum_mp; diff --git a/src/Particle/ParticleBase.h b/src/Particle/ParticleBase.h index 577339cc7..35821ce97 100644 --- a/src/Particle/ParticleBase.h +++ b/src/Particle/ParticleBase.h @@ -68,7 +68,7 @@ namespace ippl { * * Minimal empty base class for all ParticleBase specializations. * Needed for e.g: c++20 constraints and concepts using std::derived_from - * + * */ class ParticleBaseBase { public: @@ -84,7 +84,7 @@ namespace ippl { * IDs will be disabled for the bunch) */ template - class ParticleBase: public ParticleBaseBase { + class ParticleBase : public ParticleBaseBase { constexpr static bool EnableIDs = sizeof...(IDProperties) > 0; public: diff --git a/src/Particle/ParticleSpatialLayout.h b/src/Particle/ParticleSpatialLayout.h index 9f82c870b..06feda13d 100644 --- a/src/Particle/ParticleSpatialLayout.h +++ b/src/Particle/ParticleSpatialLayout.h @@ -23,16 +23,16 @@ #ifndef IPPL_PARTICLE_SPATIAL_LAYOUT_H #define IPPL_PARTICLE_SPATIAL_LAYOUT_H +#include + #include "Types/IpplTypes.h" +#include "Communicate/Window.h" #include "FieldLayout/FieldLayout.h" #include "Particle/ParticleBase.h" #include "Particle/ParticleLayout.h" #include "Region/RegionLayout.h" -#include "Communicate/Window.h" -#include - namespace ippl { /*! @@ -81,14 +81,13 @@ namespace ippl { //! The FieldLayout containing information on nearest neighbors FieldLayout_t& flayout_m; - - + // Vector keeping track of the recieves from all ranks std::vector nRecvs_m; - + // MPI RMA window for one-sided communication mpi::rma::Window window_m; - + //! Type of the Kokkos view containing the local regions. using region_view_type = typename RegionLayout_t::view_type; //! Type of a single Region object. @@ -120,8 +119,10 @@ namespace ippl { * @return The total number of invalidated particles */ template - std::pair locateParticles(const ParticleContainer& pc, locate_type& ranks, - bool_type& invalid, locate_type& nSends_dview, locate_type& sends_dview) const; + std::pair locateParticles(const ParticleContainer& pc, + locate_type& ranks, bool_type& invalid, + locate_type& nSends_dview, + locate_type& sends_dview) const; /*! * @param rank we sent to @@ -141,4 +142,3 @@ namespace ippl { #include "Particle/ParticleSpatialLayout.hpp" #endif - diff --git a/src/Particle/ParticleSpatialLayout.hpp b/src/Particle/ParticleSpatialLayout.hpp index 44ae03fa7..a3628deaf 100644 --- a/src/Particle/ParticleSpatialLayout.hpp +++ b/src/Particle/ParticleSpatialLayout.hpp @@ -60,8 +60,7 @@ namespace ippl { ParticleSpatialLayout::ParticleSpatialLayout(FieldLayout& fl, Mesh& mesh, bool fem) : rlayout_m(fl, mesh, fem) - , flayout_m(fl) - { + , flayout_m(fl) { nRecvs_m.resize(Comm->size()); if (Comm->size() > 1) { window_m.create(*Comm, nRecvs_m.begin(), nRecvs_m.end()); diff --git a/src/Particle/ParticleSpatialOverlapLayout.hpp b/src/Particle/ParticleSpatialOverlapLayout.hpp index 4e06c3c75..1bd94ff3d 100644 --- a/src/Particle/ParticleSpatialOverlapLayout.hpp +++ b/src/Particle/ParticleSpatialOverlapLayout.hpp @@ -187,7 +187,8 @@ namespace ippl { for (unsigned d = 0; d < Dim; ++d) { anyPeriodic = anyPeriodic || periodic[d]; } - if (!anyPeriodic) return; + if (!anyPeriodic) + return; const auto& globalRegion = this->rlayout_m.getDomain(); const auto overlap = rcutoff_m; diff --git a/src/PoissonSolvers/EvalFunctor.h b/src/PoissonSolvers/EvalFunctor.h index f757f1cc6..2348a800e 100644 --- a/src/PoissonSolvers/EvalFunctor.h +++ b/src/PoissonSolvers/EvalFunctor.h @@ -25,6 +25,6 @@ namespace ippl { return dot((DPhiInvT * grad_b_q_k[j]), (DPhiInvT * grad_b_q_k[i])).apply() * absDetDPhi; } }; -} +} // namespace ippl #endif diff --git a/src/PoissonSolvers/FEMPoissonSolver.h b/src/PoissonSolvers/FEMPoissonSolver.h index 2a1bdf862..118a10d9b 100644 --- a/src/PoissonSolvers/FEMPoissonSolver.h +++ b/src/PoissonSolvers/FEMPoissonSolver.h @@ -5,9 +5,9 @@ #ifndef IPPL_FEMPOISSONSOLVER_H #define IPPL_FEMPOISSONSOLVER_H +#include "EvalFunctor.h" #include "LinearSolvers/PCG.h" #include "Poisson.h" -#include "EvalFunctor.h" namespace ippl { @@ -18,7 +18,8 @@ namespace ippl { * @tparam FieldLHS field type for the left hand side * @tparam FieldRHS field type for the right hand side */ - template + template class FEMPoissonSolver : public Poisson { constexpr static unsigned Dim = FieldLHS::dim; using Tlhs = typename FieldLHS::value_type; @@ -40,16 +41,17 @@ namespace ippl { using QuadratureType = GaussJacobiQuadrature; - using LagrangeType = LagrangeSpace; + using LagrangeType = + LagrangeSpace; // default constructor (compatibility with Alpine) - FEMPoissonSolver() + FEMPoissonSolver() : Base() , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) - , lagrangeSpace_m(*(new MeshType(NDIndex(Vector(0)), Vector(0), - Vector(0))), refElement_m, quadrature_m) - { + , lagrangeSpace_m(*(new MeshType(NDIndex(Vector(0)), + Vector(0), Vector(0))), + refElement_m, quadrature_m) { setDefaultParameters(); } @@ -57,8 +59,7 @@ namespace ippl { : Base(lhs, rhs) , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) - , lagrangeSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) - { + , lagrangeSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) { static_assert(std::is_floating_point::value, "Not a floating point type"); setDefaultParameters(); pcg_algo_m.initializeFields(rhs.get_mesh(), rhs.getLayout()); @@ -74,9 +75,7 @@ namespace ippl { /** * @brief Return the LagrangeSpace object. */ - LagrangeType& getSpace() { - return lagrangeSpace_m; - } + LagrangeType& getSpace() { return lagrangeSpace_m; } /** * @brief Solve the poisson equation using finite element methods. @@ -103,14 +102,15 @@ namespace ippl { const Tlhs absDetDPhi = Kokkos::abs( refElement_m.getDeterminantOfTransformationJacobian(firstElementVertexPoints)); - EvalFunctor poissonEquationEval( - DPhiInvT, absDetDPhi); + EvalFunctor poissonEquationEval(DPhiInvT, + absDetDPhi); // get BC type of our RHS BConds& bcField = (this->rhs_mp)->getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); - const auto algoOperator = [poissonEquationEval, &bcField, this](rhs_type field) -> lhs_type { + const auto algoOperator = [poissonEquationEval, &bcField, + this](rhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); @@ -125,8 +125,9 @@ namespace ippl { // send boundary values to RHS (load vector) i.e. lifting (Dirichlet BCs) if (bcType == CONSTANT_FACE) { - *(this->rhs_mp) = *(this->rhs_mp) - - lagrangeSpace_m.evaluateAx_lift(*(this->rhs_mp), poissonEquationEval); + *(this->rhs_mp) = + *(this->rhs_mp) + - lagrangeSpace_m.evaluateAx_lift(*(this->rhs_mp), poissonEquationEval); } // start a timer @@ -174,9 +175,9 @@ namespace ippl { Tlhs avg = this->lagrangeSpace_m.computeAvg(*(this->lhs_mp)); if (Vol) { lhs_type unit((this->lhs_mp)->get_mesh(), (this->lhs_mp)->getLayout()); - unit = 1.0; + unit = 1.0; Tlhs vol = this->lagrangeSpace_m.computeAvg(unit); - return avg/vol; + return avg / vol; } else { return avg; } diff --git a/src/PoissonSolvers/FFTOpenPoissonSolver.hpp b/src/PoissonSolvers/FFTOpenPoissonSolver.hpp index bd8ceec80..b538ae7bb 100644 --- a/src/PoissonSolvers/FFTOpenPoissonSolver.hpp +++ b/src/PoissonSolvers/FFTOpenPoissonSolver.hpp @@ -476,7 +476,7 @@ namespace ippl { rho2_mr = 0.0; rho2tr_m = 0.0; if (alg == Algorithm::VICO || alg == Algorithm::BIHARMONIC) { - grnL_m = 0.0; + grnL_m = 0.0; } if (alg == Algorithm::DCT_VICO) { grn2n1_m = 0.0; diff --git a/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h b/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h index c6144994b..9115328a3 100644 --- a/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h +++ b/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.h @@ -69,7 +69,6 @@ namespace ippl { // compute standard Green's function void greensFunction(); - private: Field_t grn_m; // the Green's function @@ -124,12 +123,13 @@ namespace ippl { this->params_m.add("comm", p2p_pl); break; default: - throw IpplException("FFTTruncatedGreenPeriodicPoissonSolver::setDefaultParameters", - "Unrecognized heffte communication type"); + throw IpplException( + "FFTTruncatedGreenPeriodicPoissonSolver::setDefaultParameters", + "Unrecognized heffte communication type"); } } }; } // namespace ippl #include "PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.hpp" -#endif // IPPL_FFT_TRUNCATED_GREEN_PERIODIC_POISSON_SOLVER_H_SOLVER_H_ +#endif // IPPL_FFT_TRUNCATED_GREEN_PERIODIC_POISSON_SOLVER_H_SOLVER_H_ diff --git a/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.hpp b/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.hpp index 65cce6669..6bead4cd2 100644 --- a/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.hpp +++ b/src/PoissonSolvers/FFTTruncatedGreenPeriodicPoissonSolver.hpp @@ -15,7 +15,8 @@ namespace ippl { // constructor and destructor template - FFTTruncatedGreenPeriodicPoissonSolver::FFTTruncatedGreenPeriodicPoissonSolver() + FFTTruncatedGreenPeriodicPoissonSolver::FFTTruncatedGreenPeriodicPoissonSolver() : Base() , mesh_mp(nullptr) , layout_mp(nullptr) @@ -25,7 +26,9 @@ namespace ippl { } template - FFTTruncatedGreenPeriodicPoissonSolver::FFTTruncatedGreenPeriodicPoissonSolver(rhs_type& rhs, ParameterList& params) + FFTTruncatedGreenPeriodicPoissonSolver< + FieldLHS, FieldRHS>::FFTTruncatedGreenPeriodicPoissonSolver(rhs_type& rhs, + ParameterList& params) : mesh_mp(nullptr) , layout_mp(nullptr) , meshComplex_m(nullptr) @@ -39,7 +42,9 @@ namespace ippl { } template - FFTTruncatedGreenPeriodicPoissonSolver::FFTTruncatedGreenPeriodicPoissonSolver(lhs_type& lhs, rhs_type& rhs, ParameterList& params) + FFTTruncatedGreenPeriodicPoissonSolver< + FieldLHS, FieldRHS>::FFTTruncatedGreenPeriodicPoissonSolver(lhs_type& lhs, rhs_type& rhs, + ParameterList& params) : mesh_mp(nullptr) , layout_mp(nullptr) , meshComplex_m(nullptr) @@ -63,7 +68,9 @@ namespace ippl { template void FFTTruncatedGreenPeriodicPoissonSolver::initializeFields() { - static_assert(Dim == 3, "Dimension other than 3 not supported in FFTTruncatedGreenPeriodicPoissonSolver!"); + static_assert( + Dim == 3, + "Dimension other than 3 not supported in FFTTruncatedGreenPeriodicPoissonSolver!"); // get layout and mesh layout_mp = &(this->rhs_mp->getLayout()); @@ -312,8 +319,8 @@ namespace ippl { // for the collision modelling method, it indicates // the splitting between Particle-Particle interactions // and the Particle-Mesh computations). - const Trhs alpha = this->params_m. template get("alpha"); - const Trhs forceConstant = this->params_m. template get("force_constant"); + const Trhs alpha = this->params_m.template get("alpha"); + const Trhs forceConstant = this->params_m.template get("force_constant"); // calculate square of the mesh spacing for each dimension Vector_t hrsq(hr_m * hr_m); diff --git a/src/PoissonSolvers/LaplaceHelpers.h b/src/PoissonSolvers/LaplaceHelpers.h index 65c8a83f2..f723f86be 100644 --- a/src/PoissonSolvers/LaplaceHelpers.h +++ b/src/PoissonSolvers/LaplaceHelpers.h @@ -329,9 +329,9 @@ namespace ippl { double negative_inverse_diagonal_laplace(Field& u) { constexpr unsigned Dim = Field::dim; using mesh_type = typename Field::Mesh_t; - mesh_type& mesh = u.get_mesh(); - double sum = 0.0; - double factor = 1.0; + mesh_type& mesh = u.get_mesh(); + double sum = 0.0; + double factor = 1.0; typename mesh_type::vector_type hvector(0); for (unsigned d = 0; d < Dim; ++d) { hvector[d] = Kokkos::pow(mesh.getMeshSpacing(d), 2); diff --git a/src/PoissonSolvers/PreconditionedFEMPoissonSolver.h b/src/PoissonSolvers/PreconditionedFEMPoissonSolver.h index c085478b1..95b6ec2b7 100644 --- a/src/PoissonSolvers/PreconditionedFEMPoissonSolver.h +++ b/src/PoissonSolvers/PreconditionedFEMPoissonSolver.h @@ -6,10 +6,10 @@ #define IPPL_PRECONFEMPOISSONSOLVER_H // #include "FEM/FiniteElementSpace.h" +#include "EvalFunctor.h" #include "LaplaceHelpers.h" #include "LinearSolvers/PCG.h" #include "Poisson.h" -#include "EvalFunctor.h" namespace ippl { /** @@ -41,16 +41,17 @@ namespace ippl { using QuadratureType = GaussJacobiQuadrature; - using LagrangeType = LagrangeSpace; + using LagrangeType = + LagrangeSpace; // default constructor (compatibility with Alpine) - PreconditionedFEMPoissonSolver() + PreconditionedFEMPoissonSolver() : Base() , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) - , lagrangeSpace_m(*(new MeshType(NDIndex(Vector(0)), Vector(0), - Vector(0))), refElement_m, quadrature_m) - { + , lagrangeSpace_m(*(new MeshType(NDIndex(Vector(0)), + Vector(0), Vector(0))), + refElement_m, quadrature_m) { setDefaultParameters(); } @@ -58,8 +59,7 @@ namespace ippl { : Base(lhs, rhs) , refElement_m() , quadrature_m(refElement_m, 0.0, 0.0) - , lagrangeSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) - { + , lagrangeSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) { static_assert(std::is_floating_point::value, "Not a floating point type"); setDefaultParameters(); } @@ -73,9 +73,7 @@ namespace ippl { /** * @brief Return the LagrangeSpace object. */ - LagrangeType& getSpace() { - return lagrangeSpace_m; - } + LagrangeType& getSpace() { return lagrangeSpace_m; } /** * @brief Solve the poisson equation using finite element methods. @@ -102,14 +100,15 @@ namespace ippl { const Tlhs absDetDPhi = Kokkos::abs( refElement_m.getDeterminantOfTransformationJacobian(firstElementVertexPoints)); - EvalFunctor poissonEquationEval( - DPhiInvT, absDetDPhi); + EvalFunctor poissonEquationEval(DPhiInvT, + absDetDPhi); // get BC type of our RHS BConds& bcField = (this->rhs_mp)->getFieldBC(); - FieldBC bcType = bcField[0]->getBCType(); + FieldBC bcType = bcField[0]->getBCType(); - const auto algoOperator = [poissonEquationEval, &bcField, this](rhs_type field) -> lhs_type { + const auto algoOperator = [poissonEquationEval, &bcField, + this](rhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); @@ -120,7 +119,8 @@ namespace ippl { return return_field; }; - const auto algoOperatorL = [poissonEquationEval, &bcField, this](lhs_type field) -> lhs_type { + const auto algoOperatorL = [poissonEquationEval, &bcField, + this](lhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); @@ -131,7 +131,8 @@ namespace ippl { return return_field; }; - const auto algoOperatorU = [poissonEquationEval, &bcField, this](lhs_type field) -> lhs_type { + const auto algoOperatorU = [poissonEquationEval, &bcField, + this](lhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); @@ -142,29 +143,34 @@ namespace ippl { return return_field; }; - const auto algoOperatorUL = [poissonEquationEval, &bcField, this](lhs_type field) -> lhs_type { + const auto algoOperatorUL = [poissonEquationEval, &bcField, + this](lhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); field.fillHalo(); - auto return_field = lagrangeSpace_m.evaluateAx_upperlower(field, poissonEquationEval); + auto return_field = + lagrangeSpace_m.evaluateAx_upperlower(field, poissonEquationEval); return return_field; }; - const auto algoOperatorInvD = [poissonEquationEval, &bcField, this](lhs_type field) -> lhs_type { + const auto algoOperatorInvD = [poissonEquationEval, &bcField, + this](lhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); field.fillHalo(); - auto return_field = lagrangeSpace_m.evaluateAx_inversediag(field, poissonEquationEval); + auto return_field = + lagrangeSpace_m.evaluateAx_inversediag(field, poissonEquationEval); return return_field; }; - const auto algoOperatorD = [poissonEquationEval, &bcField, this](lhs_type field) -> lhs_type { + const auto algoOperatorD = [poissonEquationEval, &bcField, + this](lhs_type field) -> lhs_type { // set appropriate BCs for the field as the info gets lost in the CG iteration field.setFieldBC(bcField); @@ -183,19 +189,19 @@ namespace ippl { int inner = this->params_m.template get("gauss_seidel_inner_iterations"); int outer = this->params_m.template get("gauss_seidel_outer_iterations"); double omega = this->params_m.template get("ssor_omega"); - int richardson_iterations = - this->params_m.template get("richardson_iterations"); + int richardson_iterations = this->params_m.template get("richardson_iterations"); pcg_algo_m.setPreconditioner(algoOperator, algoOperatorL, algoOperatorU, algoOperatorUL, - algoOperatorInvD, algoOperatorD, 0, 0, preconditioner_type, - level, degree, richardson_iterations, inner, outer, omega); + algoOperatorInvD, algoOperatorD, 0, 0, preconditioner_type, + level, degree, richardson_iterations, inner, outer, omega); pcg_algo_m.setOperator(algoOperator); // send boundary values to RHS (load vector) i.e. lifting (Dirichlet BCs) if (bcType == CONSTANT_FACE) { - *(this->rhs_mp) = *(this->rhs_mp) - - lagrangeSpace_m.evaluateAx_lift(*(this->rhs_mp), poissonEquationEval); + *(this->rhs_mp) = + *(this->rhs_mp) + - lagrangeSpace_m.evaluateAx_lift(*(this->rhs_mp), poissonEquationEval); } // start a timer @@ -247,9 +253,9 @@ namespace ippl { Tlhs avg = this->lagrangeSpace_m.computeAvg(*(this->lhs_mp)); if (Vol) { lhs_type unit((this->lhs_mp)->get_mesh(), (this->lhs_mp)->getLayout()); - unit = 1.0; + unit = 1.0; Tlhs vol = this->lagrangeSpace_m.computeAvg(unit); - return avg/vol; + return avg / vol; } else { return avg; } diff --git a/src/Random/NormalDistribution.h b/src/Random/NormalDistribution.h index 763afbe54..4086a5fa9 100644 --- a/src/Random/NormalDistribution.h +++ b/src/Random/NormalDistribution.h @@ -156,7 +156,7 @@ namespace ippl { */ KOKKOS_INLINE_FUNCTION NormalDistribution(const T* par_p) : ippl::random::Distribution>( - par_p) {} + par_p) {} }; } // namespace random diff --git a/src/Random/Utility.h b/src/Random/Utility.h index f0262e96f..f5b369779 100644 --- a/src/Random/Utility.h +++ b/src/Random/Utility.h @@ -59,7 +59,7 @@ namespace ippl { } }; } // namespace detail - } // namespace random + } // namespace random } // namespace ippl #endif diff --git a/src/Region/RegionLayout.hpp b/src/Region/RegionLayout.hpp index d074f6825..eea7004c5 100644 --- a/src/Region/RegionLayout.hpp +++ b/src/Region/RegionLayout.hpp @@ -53,11 +53,10 @@ namespace ippl { if (node_m) { for (unsigned int d = 0; d < Dim; d++) { T firstCoord = region_m[d].min(); - T lastCoord = region_m[d].max() - mesh.getMeshSpacing()[d]; - region_m[d] = PRegion(firstCoord, lastCoord); + T lastCoord = region_m[d].max() - mesh.getMeshSpacing()[d]; + region_m[d] = PRegion(firstCoord, lastCoord); } } - } // convert a given NDIndex into an NDRegion ... if this object was diff --git a/src/Types/Variant.h b/src/Types/Variant.h index 6332574c0..c0779eab4 100644 --- a/src/Types/Variant.h +++ b/src/Types/Variant.h @@ -354,7 +354,7 @@ namespace std _GLIBCXX_VISIBILITY(default) { _Variadic_union& operator=(const _Variadic_union&) = default; _Variadic_union& operator=(_Variadic_union&&) = default; - ~_Variadic_union(){}; + ~_Variadic_union() {}; constexpr ~_Variadic_union() requires(!__has_trivial_destructor(_First)) @@ -974,7 +974,7 @@ namespace std _GLIBCXX_VISIBILITY(default) { } } // namespace __variant - } // namespace __detail + } // namespace __detail template constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept { @@ -1284,8 +1284,8 @@ namespace std _GLIBCXX_VISIBILITY(default) { && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>, variant&> operator=(_Tp&& __rhs) noexcept( - is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>&& - is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) { + is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp> + && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) { constexpr auto __index = __accepted_index<_Tp>; if (index() == __index) std::get<__index>(*this) = std::forward<_Tp>(__rhs); @@ -1524,7 +1524,7 @@ namespace std _GLIBCXX_VISIBILITY(default) { using __detail::__variant::__gen_vtable_impl; using __detail::__variant::_Multi_array; - using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0 &&)>; + using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0&&)>; #ifdef _GLIBCXX_DEBUG #define _GLIBCXX_VISIT_UNREACHABLE __builtin_trap diff --git a/src/Types/Vector.h b/src/Types/Vector.h index 89a96bcad..e98de2499 100644 --- a/src/Types/Vector.h +++ b/src/Types/Vector.h @@ -96,7 +96,7 @@ namespace ippl { KOKKOS_INLINE_FUNCTION constexpr const_iterator end() const; KOKKOS_INLINE_FUNCTION T dot(const Vector& rhs) const; - + KOKKOS_INLINE_FUNCTION T Pnorm(const int p = 2) const; // Needs to be public to be a standard-layout type diff --git a/src/Types/Vector.hpp b/src/Types/Vector.hpp index 5f5ffa268..27ebc5bf5 100644 --- a/src/Types/Vector.hpp +++ b/src/Types/Vector.hpp @@ -189,9 +189,8 @@ namespace ippl { template KOKKOS_INLINE_FUNCTION T Vector::Pnorm(const int p) const { - T val = 0.0; - for(unsigned i = 0; i < Dim; ++i) { + for (unsigned i = 0; i < Dim; ++i) { val += Kokkos::pow(Kokkos::abs(data_m[i]), p); } diff --git a/src/Utility/ParallelDispatch.h b/src/Utility/ParallelDispatch.h index 437c56c22..a96139fa2 100644 --- a/src/Utility/ParallelDispatch.h +++ b/src/Utility/ParallelDispatch.h @@ -180,8 +180,8 @@ namespace ippl { }; template concept HasMemberValueType = requires() { - { typename T::value_type() }; - }; + { typename T::value_type() }; + }; template struct ExtractReducerReturnType { using type = T; diff --git a/test/solver/TestCGSolver_convergence.cpp b/test/solver/TestCGSolver_convergence.cpp index 0caa24a62..9898f5cf3 100644 --- a/test/solver/TestCGSolver_convergence.cpp +++ b/test/solver/TestCGSolver_convergence.cpp @@ -31,7 +31,7 @@ int main(int argc, char* argv[]) { m << "size, relError, residue, itCount" << endl; for (unsigned pt = 1 << 2; pt <= 1 << 10; pt = pt << 1) { - ippl::Vector I(pt); + ippl::Vector I(pt); ippl::NDIndex domain(I); std::array isParallel; // Specifies SERIAL, PARALLEL dims @@ -81,10 +81,10 @@ int main(int argc, char* argv[]) { double y = (jg + 0.5) * hx[1]; double z = (kg + 0.5) * hx[2]; - //viewSol(i) = sin(sin(pi*x)); - //viewSol(i, j) = sin(sin(pi*x)) * sin(sin(pi*y)); - viewSol(i, j, k) = sin(sin(pi*x)) * sin(sin(pi*y)) * sin(sin(pi*z)); - }); + // viewSol(i) = sin(sin(pi*x)); + // viewSol(i, j) = sin(sin(pi*x)) * sin(sin(pi*y)); + viewSol(i, j, k) = sin(sin(pi * x)) * sin(sin(pi * y)) * sin(sin(pi * z)); + }); const int shift2 = rhs.getNghost(); auto policyRHS = rhs.getFieldRangePolicy(); @@ -97,7 +97,7 @@ int main(int argc, char* argv[]) { double x = (ig + 0.5) * hx[0]; double y = (jg + 0.5) * hx[1]; double z = (kg + 0.5) * hx[2]; - + viewRHS(i, j, k) = pow(pi, 2) * (cos(sin(pi * z)) * sin(pi * z) * sin(sin(pi * x)) * sin(sin(pi * y)) @@ -129,7 +129,7 @@ int main(int argc, char* argv[]) { double x = (ig + 0.5) * hx[0]; viewRHS(i) = - pow(pi, 2) * ((cos(sin(pi * x)) * sin(pi * x)) + pow(pi, 2) * ((cos(sin(pi * x)) * sin(pi * x)) + (pow(cos(pi * x), 2) * sin(sin(pi * x)))); }); */ @@ -156,14 +156,13 @@ int main(int argc, char* argv[]) { // Laplace(solver solution) - rhs error = -laplace(lhs) - rhs; double residue = norm(error) / norm(rhs); - + residue = lapsolver.getResidue(); int size = pt; int itCount = lapsolver.getIterationCount(); - m << size << "," << std::setprecision(16) << relError << "," << residue << "," << itCount - << endl; - + m << size << "," << std::setprecision(16) << relError << "," << residue << "," + << itCount << endl; } IpplTimings::print("timings.dat"); } diff --git a/test/solver/fem/TestMaxwellDiffusionPolyZeroBC.cpp b/test/solver/fem/TestMaxwellDiffusionPolyZeroBC.cpp index 697d809d5..a1b1cd49d 100644 --- a/test/solver/fem/TestMaxwellDiffusionPolyZeroBC.cpp +++ b/test/solver/fem/TestMaxwellDiffusionPolyZeroBC.cpp @@ -1,7 +1,7 @@ // Tests the FEM Maxwell Diffusion solver by solving the problem: // // curl(curl(E)) + E = f in [-1,1]^dim -// n x E = 0 on boundary +// n x E = 0 on boundary // with dim = 2 or 3, // and f = {2 - (y^2 - 1), 2 - (x^2 - 1)} for 2d // = {-2*(z^2 - 1) - 2*(y^2 - 1) + (y^2 - 1)*(z^2 - 1), @@ -17,67 +17,64 @@ // #include "Ippl.h" + #include #include -#include "Meshes/Centering.h" #include "MaxwellSolvers/FEMMaxwellDiffusionSolver.h" - - +#include "Meshes/Centering.h" template -struct Analytical{ - using point_t = ippl::Vector; +struct Analytical { + using point_t = ippl::Vector; Analytical() {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const{ + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - T x = pos[0]; - T y = pos[1]; - sol[0] = -(y*y - 1); - sol[1] = -(x*x - 1); + T x = pos[0]; + T y = pos[1]; + sol[0] = -(y * y - 1); + sol[1] = -(x * x - 1); } else { - T x = pos[0]; - T y = pos[1]; - T z = pos[2]; - sol[0] = (y*y - 1)*(z*z - 1); - sol[1] = (x*x - 1)*(z*z - 1); - sol[2] = (x*x - 1)*(y*y - 1); + T x = pos[0]; + T y = pos[1]; + T z = pos[2]; + sol[0] = (y * y - 1) * (z * z - 1); + sol[1] = (x * x - 1) * (z * z - 1); + sol[2] = (x * x - 1) * (y * y - 1); } return sol; } }; - template struct Rhs { using point_t = ippl::Vector; Rhs() {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const { + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - T x = pos[0]; - T y = pos[1]; - sol[0] = 2 - (y*y - 1); - sol[1] = 2 - (x*x - 1); + T x = pos[0]; + T y = pos[1]; + sol[0] = 2 - (y * y - 1); + sol[1] = 2 - (x * x - 1); } if constexpr (Dim == 3) { - T x = pos[0]; - T y = pos[1]; - T z = pos[2]; - sol[0] = -2*(z*z - 1) - 2*(y*y - 1) + (y*y - 1)*(z*z - 1); - sol[1] = -2*(x*x - 1) - 2*(z*z - 1) + (x*x - 1)*(z*z - 1); - sol[2] = -2*(y*y - 1) - 2*(x*x - 1) + (x*x - 1)*(y*y - 1); + T x = pos[0]; + T y = pos[1]; + T z = pos[2]; + sol[0] = -2 * (z * z - 1) - 2 * (y * y - 1) + (y * y - 1) * (z * z - 1); + sol[1] = -2 * (x * x - 1) - 2 * (z * z - 1) + (x * x - 1) * (z * z - 1); + sol[2] = -2 * (y * y - 1) - 2 * (x * x - 1) + (x * x - 1) * (y * y - 1); } return sol; - } + } }; - template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { @@ -85,11 +82,11 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); - using Mesh_t = ippl::UniformCartesian; - using Field_t = ippl::Field, Dim, Mesh_t, Cell>; - using BConds_t = ippl::BConds; - using point_t = ippl::Vector; - using indices_t = ippl::Vector; + using Mesh_t = ippl::UniformCartesian; + using Field_t = ippl::Field, Dim, Mesh_t, Cell>; + using BConds_t = ippl::BConds; + using point_t = ippl::Vector; + using indices_t = ippl::Vector; const unsigned numCellsPerDim = numNodesPerDim - 1; const unsigned numGhosts = 1; @@ -117,107 +114,103 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, lhs.setFieldBC(bcField); rhs.setFieldBC(bcField); - // Get our rhs and solution functors Rhs rhsFunc; Analytical analytical; // create the FEMVector for the rhs - size_t n = 1; - auto ldom = layout.getLocalNDIndex(); + size_t n = 1; + auto ldom = layout.getLocalNDIndex(); indices_t extents = (ldom.last() - ldom.first()) + 3; - + if constexpr (Dim == 2) { size_t nx = extents(0); size_t ny = extents(1); - n = nx*(ny-1) + ny*(nx-1); + n = nx * (ny - 1) + ny * (nx - 1); } else { size_t nx = extents(0); size_t ny = extents(1); size_t nz = extents(2); - n = (nz-1)*(nx*(ny-1) + ny*(nx-1) + nx*ny) + nx*(ny-1) + ny*(nx-1); + n = (nz - 1) * (nx * (ny - 1) + ny * (nx - 1) + nx * ny) + nx * (ny - 1) + ny * (nx - 1); } ippl::FEMVector rhsVector(n); auto viewRhs = rhsVector.getView(); if constexpr (Dim == 2) { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); - size_t yOffset = i / (2*nx - 1); - size_t xOffset = i - (2*nx -1)*yOffset; - T x = xOffset*cellSpacing[0]; - T y = yOffset*cellSpacing[1]; - if (xOffset < (nx-1)) { + size_t yOffset = i / (2 * nx - 1); + size_t xOffset = i - (2 * nx - 1) * yOffset; + T x = xOffset * cellSpacing[0]; + T y = yOffset * cellSpacing[1]; + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - - viewRhs(i) = rhsFunc(point_t(x,y)); - } - ); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + + viewRhs(i) = rhsFunc(point_t(x, y)); + }); } else { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); size_t ny = extents(1); - - size_t zOffset = i / (nx*(ny-1) + ny*(nx-1) + nx*ny); - T z = zOffset*cellSpacing[2]; - T x = 0; - T y = 0; - if (i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset >= (nx*(ny-1) + ny*(nx-1))) { + size_t zOffset = i / (nx * (ny - 1) + ny * (nx - 1) + nx * ny); + T z = zOffset * cellSpacing[2]; + T x = 0; + T y = 0; + + if (i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + >= (nx * (ny - 1) + ny * (nx - 1))) { // we are parallel to z axis - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset - - (nx*(ny-1) + ny*(nx-1)); - z += cellSpacing[2]/2; - + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + - (nx * (ny - 1) + ny * (nx - 1)); + z += cellSpacing[2] / 2; + size_t yOffset = f / nx; - y = yOffset*cellSpacing[1]; + y = yOffset * cellSpacing[1]; size_t xOffset = f % nx; - x = xOffset*cellSpacing[0]; + x = xOffset * cellSpacing[0]; } else { // are parallel to one of the other axes - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset; - size_t yOffset = f / (2*nx - 1); - size_t xOffset = f - (2*nx - 1)*yOffset; + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset; + size_t yOffset = f / (2 * nx - 1); + size_t xOffset = f - (2 * nx - 1) * yOffset; - x = xOffset*cellSpacing[0]; - y = yOffset*cellSpacing[1]; + x = xOffset * cellSpacing[0]; + y = yOffset * cellSpacing[1]; - if (xOffset < (nx-1)) { + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - z += origin[2] + ldom.first()[2]*cellSpacing[2] - cellSpacing[2]; - - viewRhs(i) = rhsFunc(point_t(x,y,z)); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + z += origin[2] + ldom.first()[2] * cellSpacing[2] - cellSpacing[2]; - } - ); + viewRhs(i) = rhsFunc(point_t(x, y, z)); + }); } - IpplTimings::stopTimer(initTimer); // initialize the solver @@ -228,7 +221,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, params.add("tolerance", 10e-13); params.add("max_iterations", 10000); solver.mergeParameters(params); - + // solve the problem solver.solve(); @@ -240,64 +233,59 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, Kokkos::Random_XorShift64_Pool<> randomPool(42); Kokkos::View positions("positions", 100); - Kokkos::parallel_for("assign positions", 97, - KOKKOS_LAMBDA(size_t i) { - (void) positions; // add (void) to make clang happy i.e. no unused variable warning - (void) ldom; - (void) domain_start; - auto gen = randomPool.get_state(); + Kokkos::parallel_for( + "assign positions", 97, KOKKOS_LAMBDA(size_t i) { + (void)positions; // add (void) to make clang happy i.e. no unused variable warning + (void)ldom; + (void)domain_start; + auto gen = randomPool.get_state(); T cellWidth = (domain_end - domain_start) / numCellsPerDim; if constexpr (Dim == 2) { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start))); } else { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:2:>*cellWidth+domain_start, - ldom.last()<:2:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:2:> * cellWidth + domain_start, + ldom.last()<:2:> * cellWidth + domain_start))); } - if (i == 96) { - positions(97) = ldom.first()*cellWidth+domain_start; - positions(98) = ldom.last()*cellWidth+domain_start; + positions(97) = ldom.first() * cellWidth + domain_start; + positions(98) = ldom.last() * cellWidth + domain_start; // This point belongs to an edge if constexpr (Dim == 2) { - positions(99) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth); + positions(99) = + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth); } else { positions(99) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth, - ldom.first()<:2:>*cellWidth+domain_start + 0.5*cellWidth); + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth, + ldom.first()<:2:> * cellWidth + domain_start + 0.5 * cellWidth); } } randomPool.free_state(gen); - } - ); + }); - Kokkos::View funcVals = solver.reconstructToPoints(positions); // calculate the error T linfError = 0; - Kokkos::parallel_reduce( "calc l infinity", 100, - KOKKOS_LAMBDA (size_t i, T& lmax) { + Kokkos::parallel_reduce( + "calc l infinity", 100, + KOKKOS_LAMBDA(size_t i, T& lmax) { point_t dif = funcVals(i) - analytical(positions(i)); - T val = Kokkos::sqrt(dif.dot(dif)); - if( val > lmax ) lmax = val; + T val = Kokkos::sqrt(dif.dot(dif)); + if (val > lmax) + lmax = val; }, - Kokkos::Max(linfError) - ); + Kokkos::Max(linfError)); - // print information and error T coefError = solver.getL2Error(analytical); Inform m(0, 0); @@ -308,7 +296,6 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, m << std::setw(25) << std::setprecision(16) << solver.getResidue(); m << std::setw(15) << std::setprecision(16) << solver.getIterationCount(); m << endl; - } int main(int argc, char* argv[]) { @@ -328,15 +315,10 @@ int main(int argc, char* argv[]) { static IpplTimings::TimerRef allTimer = IpplTimings::getTimer("allTimer"); IpplTimings::startTimer(allTimer); - msg << std::setw(10) << "num_nodes" - << std::setw(25) << "cell_spacing" - << std::setw(25) << "interp_error_coef" - << std::setw(25) << "recon_error" - << std::setw(25) << "solver_residue" - << std::setw(15) << "num_it" - << endl; - - + msg << std::setw(10) << "num_nodes" << std::setw(25) << "cell_spacing" << std::setw(25) + << "interp_error_coef" << std::setw(25) << "recon_error" << std::setw(25) + << "solver_residue" << std::setw(15) << "num_it" << endl; + if (argc > 2 && std::atoi(argv[2]) != 0) { size_t n = std::atoi(argv<:2:>); if (dim == 2) { @@ -349,12 +331,12 @@ int main(int argc, char* argv[]) { } else { if (dim == 2) { // 2D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, -1.0, 1.0); } } else { // 3D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, -1.0, 1.0); } } diff --git a/test/solver/fem/TestMaxwellDiffusionPolyZeroBCTimed.cpp b/test/solver/fem/TestMaxwellDiffusionPolyZeroBCTimed.cpp index 0342bddd7..eca7f8b5d 100644 --- a/test/solver/fem/TestMaxwellDiffusionPolyZeroBCTimed.cpp +++ b/test/solver/fem/TestMaxwellDiffusionPolyZeroBCTimed.cpp @@ -1,7 +1,7 @@ // Tests the FEM Maxwell Diffusion solver by solving the problem: // // curl(curl(E)) + E = f in [-1,1]^dim -// n x E = 0 on boundary +// n x E = 0 on boundary // with dim = 2 or 3, // and f = {2 - (y^2 - 1), 2 - (x^2 - 1)} for 2d // = {-2*(z^2 - 1) - 2*(y^2 - 1) + (y^2 - 1)*(z^2 - 1), @@ -17,67 +17,64 @@ // #include "Ippl.h" + #include #include -#include "Meshes/Centering.h" #include "MaxwellSolvers/FEMMaxwellDiffusionSolver.h" - - +#include "Meshes/Centering.h" template -struct Analytical{ - using point_t = ippl::Vector; +struct Analytical { + using point_t = ippl::Vector; Analytical() {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const{ + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - T x = pos[0]; - T y = pos[1]; - sol[0] = -(y*y - 1); - sol[1] = -(x*x - 1); + T x = pos[0]; + T y = pos[1]; + sol[0] = -(y * y - 1); + sol[1] = -(x * x - 1); } else { - T x = pos[0]; - T y = pos[1]; - T z = pos[2]; - sol[0] = (y*y - 1)*(z*z - 1); - sol[1] = (x*x - 1)*(z*z - 1); - sol[2] = (x*x - 1)*(y*y - 1); + T x = pos[0]; + T y = pos[1]; + T z = pos[2]; + sol[0] = (y * y - 1) * (z * z - 1); + sol[1] = (x * x - 1) * (z * z - 1); + sol[2] = (x * x - 1) * (y * y - 1); } return sol; } }; - template struct Rhs { using point_t = ippl::Vector; Rhs() {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const { + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - T x = pos[0]; - T y = pos[1]; - sol[0] = 2 - (y*y - 1); - sol[1] = 2 - (x*x - 1); + T x = pos[0]; + T y = pos[1]; + sol[0] = 2 - (y * y - 1); + sol[1] = 2 - (x * x - 1); } if constexpr (Dim == 3) { - T x = pos[0]; - T y = pos[1]; - T z = pos[2]; - sol[0] = -2*(z*z - 1) - 2*(y*y - 1) + (y*y - 1)*(z*z - 1); - sol[1] = -2*(x*x - 1) - 2*(z*z - 1) + (x*x - 1)*(z*z - 1); - sol[2] = -2*(y*y - 1) - 2*(x*x - 1) + (x*x - 1)*(y*y - 1); + T x = pos[0]; + T y = pos[1]; + T z = pos[2]; + sol[0] = -2 * (z * z - 1) - 2 * (y * y - 1) + (y * y - 1) * (z * z - 1); + sol[1] = -2 * (x * x - 1) - 2 * (z * z - 1) + (x * x - 1) * (z * z - 1); + sol[2] = -2 * (y * y - 1) - 2 * (x * x - 1) + (x * x - 1) * (y * y - 1); } return sol; - } + } }; - template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { @@ -85,11 +82,11 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); - using Mesh_t = ippl::UniformCartesian; - using Field_t = ippl::Field, Dim, Mesh_t, Cell>; - using BConds_t = ippl::BConds; - using point_t = ippl::Vector; - using indices_t = ippl::Vector; + using Mesh_t = ippl::UniformCartesian; + using Field_t = ippl::Field, Dim, Mesh_t, Cell>; + using BConds_t = ippl::BConds; + using point_t = ippl::Vector; + using indices_t = ippl::Vector; const unsigned numCellsPerDim = numNodesPerDim - 1; const unsigned numGhosts = 1; @@ -117,107 +114,103 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, lhs.setFieldBC(bcField); rhs.setFieldBC(bcField); - // Get our rhs and solution functors Rhs rhsFunc; Analytical analytical; // create the FEMVector for the rhs - size_t n = 1; - auto ldom = layout.getLocalNDIndex(); + size_t n = 1; + auto ldom = layout.getLocalNDIndex(); indices_t extents = (ldom.last() - ldom.first()) + 3; - + if constexpr (Dim == 2) { size_t nx = extents(0); size_t ny = extents(1); - n = nx*(ny-1) + ny*(nx-1); + n = nx * (ny - 1) + ny * (nx - 1); } else { size_t nx = extents(0); size_t ny = extents(1); size_t nz = extents(2); - n = (nz-1)*(nx*(ny-1) + ny*(nx-1) + nx*ny) + nx*(ny-1) + ny*(nx-1); + n = (nz - 1) * (nx * (ny - 1) + ny * (nx - 1) + nx * ny) + nx * (ny - 1) + ny * (nx - 1); } ippl::FEMVector rhsVector(n); auto viewRhs = rhsVector.getView(); if constexpr (Dim == 2) { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); - size_t yOffset = i / (2*nx - 1); - size_t xOffset = i - (2*nx -1)*yOffset; - T x = xOffset*cellSpacing[0]; - T y = yOffset*cellSpacing[1]; - if (xOffset < (nx-1)) { + size_t yOffset = i / (2 * nx - 1); + size_t xOffset = i - (2 * nx - 1) * yOffset; + T x = xOffset * cellSpacing[0]; + T y = yOffset * cellSpacing[1]; + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - - viewRhs(i) = rhsFunc(point_t(x,y)); - } - ); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + + viewRhs(i) = rhsFunc(point_t(x, y)); + }); } else { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); size_t ny = extents(1); - - size_t zOffset = i / (nx*(ny-1) + ny*(nx-1) + nx*ny); - T z = zOffset*cellSpacing[2]; - T x = 0; - T y = 0; - if (i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset >= (nx*(ny-1) + ny*(nx-1))) { + size_t zOffset = i / (nx * (ny - 1) + ny * (nx - 1) + nx * ny); + T z = zOffset * cellSpacing[2]; + T x = 0; + T y = 0; + + if (i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + >= (nx * (ny - 1) + ny * (nx - 1))) { // we are parallel to z axis - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset - - (nx*(ny-1) + ny*(nx-1)); - z += cellSpacing[2]/2; - + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + - (nx * (ny - 1) + ny * (nx - 1)); + z += cellSpacing[2] / 2; + size_t yOffset = f / nx; - y = yOffset*cellSpacing[1]; + y = yOffset * cellSpacing[1]; size_t xOffset = f % nx; - x = xOffset*cellSpacing[0]; + x = xOffset * cellSpacing[0]; } else { // are parallel to one of the other axes - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset; - size_t yOffset = f / (2*nx - 1); - size_t xOffset = f - (2*nx - 1)*yOffset; + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset; + size_t yOffset = f / (2 * nx - 1); + size_t xOffset = f - (2 * nx - 1) * yOffset; - x = xOffset*cellSpacing[0]; - y = yOffset*cellSpacing[1]; + x = xOffset * cellSpacing[0]; + y = yOffset * cellSpacing[1]; - if (xOffset < (nx-1)) { + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - z += origin[2] + ldom.first()[2]*cellSpacing[2] - cellSpacing[2]; - - viewRhs(i) = rhsFunc(point_t(x,y,z)); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + z += origin[2] + ldom.first()[2] * cellSpacing[2] - cellSpacing[2]; - } - ); + viewRhs(i) = rhsFunc(point_t(x, y, z)); + }); } - IpplTimings::stopTimer(initTimer); // initialize the solver @@ -229,7 +222,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, params.add("tolerance", -1.); params.add("max_iterations", 100); solver.mergeParameters(params); - + // solve the problem solver.solve(); auto end = std::chrono::high_resolution_clock::now(); @@ -242,64 +235,59 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, Kokkos::Random_XorShift64_Pool<> randomPool(42); Kokkos::View positions("positions", 100); - Kokkos::parallel_for("assign positions", 97, - KOKKOS_LAMBDA(size_t i) { - (void) positions; - (void) ldom; - (void) domain_start; - auto gen = randomPool.get_state(); + Kokkos::parallel_for( + "assign positions", 97, KOKKOS_LAMBDA(size_t i) { + (void)positions; + (void)ldom; + (void)domain_start; + auto gen = randomPool.get_state(); T cellWidth = (domain_end - domain_start) / numCellsPerDim; if constexpr (Dim == 2) { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start))); } else { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:2:>*cellWidth+domain_start, - ldom.last()<:2:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:2:> * cellWidth + domain_start, + ldom.last()<:2:> * cellWidth + domain_start))); } - if (i == 96) { - positions(97) = ldom.first()*cellWidth+domain_start; - positions(98) = ldom.last()*cellWidth+domain_start; + positions(97) = ldom.first() * cellWidth + domain_start; + positions(98) = ldom.last() * cellWidth + domain_start; // This point belongs to an edge if constexpr (Dim == 2) { - positions(99) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth); + positions(99) = + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth); } else { positions(99) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth, - ldom.first()<:2:>*cellWidth+domain_start + 0.5*cellWidth); + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth, + ldom.first()<:2:> * cellWidth + domain_start + 0.5 * cellWidth); } } randomPool.free_state(gen); - } - ); + }); - Kokkos::View funcVals = solver.reconstructToPoints(positions); // calculate the error T linfError = 0; - Kokkos::parallel_reduce( "calc l infinity", 100, - KOKKOS_LAMBDA (size_t i, T& lmax) { + Kokkos::parallel_reduce( + "calc l infinity", 100, + KOKKOS_LAMBDA(size_t i, T& lmax) { point_t dif = funcVals(i) - analytical(positions(i)); - T val = Kokkos::sqrt(dif.dot(dif)); - if( val > lmax ) lmax = val; + T val = Kokkos::sqrt(dif.dot(dif)); + if (val > lmax) + lmax = val; }, - Kokkos::Max(linfError) - ); + Kokkos::Max(linfError)); - // print information and error T coefError = solver.getL2Error(analytical); Inform m(0, 0); @@ -317,7 +305,6 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, int main(int argc, char* argv[]) { ippl::initialize(argc, argv); { - using T = double; unsigned dim = 3; @@ -326,7 +313,6 @@ int main(int argc, char* argv[]) { dim = 2; } - if (argc > 2 && std::atoi(argv[2]) != 0) { size_t n = std::atoi(argv<:2:>); if (dim == 2) { @@ -339,17 +325,16 @@ int main(int argc, char* argv[]) { } else { if (dim == 2) { // 2D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, -1.0, 1.0); } } else { // 3D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, -1.0, 1.0); } } } - } ippl::finalize(); diff --git a/test/solver/fem/TestMaxwellDiffusionZeroBC.cpp b/test/solver/fem/TestMaxwellDiffusionZeroBC.cpp index a82360974..665dc8a06 100644 --- a/test/solver/fem/TestMaxwellDiffusionZeroBC.cpp +++ b/test/solver/fem/TestMaxwellDiffusionZeroBC.cpp @@ -1,7 +1,7 @@ // Tests the FEM MaxwellDiffuson solver by solving the problem: // // curl(curl(E)) + E = f in [1.0,3.0]^dim -// n x E = 0 on boundary +// n x E = 0 on boundary // with dim = 2,3 // and k = pi // and f = {(1+k^2)sin(k*y), (1+k^2)sin(k*x)} in 2d @@ -18,68 +18,69 @@ // #include "Ippl.h" -#include - -#include "Meshes/Centering.h" -#include "MaxwellSolvers/FEMMaxwellDiffusionSolver.h" +#include #include #include +#include "MaxwellSolvers/FEMMaxwellDiffusionSolver.h" +#include "Meshes/Centering.h" + template -struct Analytical{ - using point_t = ippl::Vector; +struct Analytical { + using point_t = ippl::Vector; T k; - Analytical(T k) : k(k) {} + Analytical(T k) + : k(k) {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const{ + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - sol[0] = Kokkos::sin(k*pos[1]); - sol[1] = Kokkos::sin(k*pos[0]); + sol[0] = Kokkos::sin(k * pos[1]); + sol[1] = Kokkos::sin(k * pos[0]); } else { - sol[0] = Kokkos::sin(k*pos[1])*Kokkos::sin(k*pos[2]); - sol[1] = Kokkos::sin(k*pos[2])*Kokkos::sin(k*pos[0]); - sol[2] = Kokkos::sin(k*pos[0])*Kokkos::sin(k*pos[1]); + sol[0] = Kokkos::sin(k * pos[1]) * Kokkos::sin(k * pos[2]); + sol[1] = Kokkos::sin(k * pos[2]) * Kokkos::sin(k * pos[0]); + sol[2] = Kokkos::sin(k * pos[0]) * Kokkos::sin(k * pos[1]); } return sol; } }; template -struct Rhs{ - using point_t = ippl::Vector; +struct Rhs { + using point_t = ippl::Vector; T k; - Rhs(T k) : k(k) {} + Rhs(T k) + : k(k) {} - KOKKOS_FUNCTION const point_t operator() (const point_t& pos) const{ + KOKKOS_FUNCTION const point_t operator()(const point_t& pos) const { point_t sol(0); if constexpr (Dim == 2) { - sol[0] = (1. + k*k)*Kokkos::sin(k*pos[1]); - sol[1] = (1. + k*k)*Kokkos::sin(k*pos[0]); + sol[0] = (1. + k * k) * Kokkos::sin(k * pos[1]); + sol[1] = (1. + k * k) * Kokkos::sin(k * pos[0]); } if constexpr (Dim == 3) { - sol[0] = (1. + 2*k*k)*Kokkos::sin(k*pos[1])*Kokkos::sin(k*pos[2]); - sol[1] = (1. + 2*k*k)*Kokkos::sin(k*pos[2])*Kokkos::sin(k*pos[0]); - sol[2] = (1. + 2*k*k)*Kokkos::sin(k*pos[0])*Kokkos::sin(k*pos[1]); + sol[0] = (1. + 2 * k * k) * Kokkos::sin(k * pos[1]) * Kokkos::sin(k * pos[2]); + sol[1] = (1. + 2 * k * k) * Kokkos::sin(k * pos[2]) * Kokkos::sin(k * pos[0]); + sol[2] = (1. + 2 * k * k) * Kokkos::sin(k * pos[0]) * Kokkos::sin(k * pos[1]); } return sol; } }; - template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { // start the timer - using Mesh_t = ippl::UniformCartesian; - using Field_t = ippl::Field, Dim, Mesh_t, Cell>; - using BConds_t = ippl::BConds; - using point_t = ippl::Vector; - using indices_t = ippl::Vector; + using Mesh_t = ippl::UniformCartesian; + using Field_t = ippl::Field, Dim, Mesh_t, Cell>; + using BConds_t = ippl::BConds; + using point_t = ippl::Vector; + using indices_t = ippl::Vector; const unsigned numCellsPerDim = numNodesPerDim - 1; const unsigned numGhosts = 1; @@ -109,105 +110,102 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // set k and retrieve the functors for the rhs and the solution. T k = 3.14159265359; - Analytical analytical(k); - Rhs rhsFunc(k); + Analytical analytical(k); + Rhs rhsFunc(k); // create the FEMVector for the rhs - size_t n = 1; - auto ldom = layout.getLocalNDIndex(); + size_t n = 1; + auto ldom = layout.getLocalNDIndex(); indices_t extents = (ldom.last() - ldom.first()) + 3; - + if constexpr (Dim == 2) { size_t nx = extents(0); size_t ny = extents(1); - n = nx*(ny-1) + ny*(nx-1); + n = nx * (ny - 1) + ny * (nx - 1); } else { size_t nx = extents(0); size_t ny = extents(1); size_t nz = extents(2); - n = (nz-1)*(nx*(ny-1) + ny*(nx-1) + nx*ny) + nx*(ny-1) + ny*(nx-1); + n = (nz - 1) * (nx * (ny - 1) + ny * (nx - 1) + nx * ny) + nx * (ny - 1) + ny * (nx - 1); } ippl::FEMVector rhsVector(n); auto viewRhs = rhsVector.getView(); if constexpr (Dim == 2) { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); - size_t yOffset = i / (2*nx - 1); - size_t xOffset = i - (2*nx -1)*yOffset; - T x = xOffset*cellSpacing[0]; - T y = yOffset*cellSpacing[1]; - if (xOffset < (nx-1)) { + size_t yOffset = i / (2 * nx - 1); + size_t xOffset = i - (2 * nx - 1) * yOffset; + T x = xOffset * cellSpacing[0]; + T y = yOffset * cellSpacing[1]; + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - - viewRhs(i) = rhsFunc(point_t(x,y)); - } - ); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + + viewRhs(i) = rhsFunc(point_t(x, y)); + }); } else { - Kokkos::parallel_for("Assign RHS", rhsVector.size(), - KOKKOS_LAMBDA(size_t i) { + Kokkos::parallel_for( + "Assign RHS", rhsVector.size(), KOKKOS_LAMBDA(size_t i) { size_t nx = extents(0); size_t ny = extents(1); - - size_t zOffset = i / (nx*(ny-1) + ny*(nx-1) + nx*ny); - T z = zOffset*cellSpacing[2]; - T x = 0; - T y = 0; - if (i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset >= (nx*(ny-1) + ny*(nx-1))) { + size_t zOffset = i / (nx * (ny - 1) + ny * (nx - 1) + nx * ny); + T z = zOffset * cellSpacing[2]; + T x = 0; + T y = 0; + + if (i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + >= (nx * (ny - 1) + ny * (nx - 1))) { // we are parallel to z axis - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset - - (nx*(ny-1) + ny*(nx-1)); - z += cellSpacing[2]/2; - + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset + - (nx * (ny - 1) + ny * (nx - 1)); + z += cellSpacing[2] / 2; + size_t yOffset = f / nx; - y = yOffset*cellSpacing[1]; + y = yOffset * cellSpacing[1]; size_t xOffset = f % nx; - x = xOffset*cellSpacing[0]; + x = xOffset * cellSpacing[0]; } else { // are parallel to one of the other axes - size_t f = i - (nx*(ny-1) + ny*(nx-1) + nx*ny)*zOffset; - size_t yOffset = f / (2*nx - 1); - size_t xOffset = f - (2*nx - 1)*yOffset; + size_t f = i - (nx * (ny - 1) + ny * (nx - 1) + nx * ny) * zOffset; + size_t yOffset = f / (2 * nx - 1); + size_t xOffset = f - (2 * nx - 1) * yOffset; - x = xOffset*cellSpacing[0]; - y = yOffset*cellSpacing[1]; + x = xOffset * cellSpacing[0]; + y = yOffset * cellSpacing[1]; - if (xOffset < (nx-1)) { + if (xOffset < (nx - 1)) { // we are parallel to the x axis - x += cellSpacing[0]/2.; + x += cellSpacing[0] / 2.; } else { // we are parallel to the y axis - y += cellSpacing[1]/2.; - x -= (nx-1)*cellSpacing[0]; + y += cellSpacing[1] / 2.; + x -= (nx - 1) * cellSpacing[0]; } } // have to subtract one cellspacing for the ghost cells - x += origin[0] + ldom.first()[0]*cellSpacing[0] - cellSpacing[0]; - y += origin[1] + ldom.first()[1]*cellSpacing[1] - cellSpacing[1]; - z += origin[2] + ldom.first()[2]*cellSpacing[2] - cellSpacing[2]; - - viewRhs(i) = rhsFunc(point_t(x,y,z)); + x += origin[0] + ldom.first()[0] * cellSpacing[0] - cellSpacing[0]; + y += origin[1] + ldom.first()[1] * cellSpacing[1] - cellSpacing[1]; + z += origin[2] + ldom.first()[2] * cellSpacing[2] - cellSpacing[2]; - } - ); + viewRhs(i) = rhsFunc(point_t(x, y, z)); + }); } - // initialize the solver IpplTimings::TimerRef timerSolverInit = IpplTimings::getTimer("solver init"); IpplTimings::startTimer(timerSolverInit); @@ -215,17 +213,16 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::FEMMaxwellDiffusionSolver solver(lhs, rhs, rhsVector); IpplTimings::stopTimer(timerSolverInit); - + // set the parameters ippl::ParameterList params; params.add("tolerance", 1e-13); params.add("max_iterations", 10000); solver.mergeParameters(params); - IpplTimings::TimerRef timerSolverSolve = IpplTimings::getTimer("solver solve"); IpplTimings::startTimer(timerSolverSolve); - + // solve the problem solver.solve(); @@ -241,62 +238,58 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, size_t numPoints = 100; Kokkos::View positions("positions", numPoints); - Kokkos::parallel_for("assign positions", numPoints-3, - KOKKOS_LAMBDA(size_t i) { - (void) positions; - (void) ldom; - (void) domain_start; - auto gen = randomPool.get_state(); + Kokkos::parallel_for( + "assign positions", numPoints - 3, KOKKOS_LAMBDA(size_t i) { + (void)positions; + (void)ldom; + (void)domain_start; + auto gen = randomPool.get_state(); T cellWidth = (domain_end - domain_start) / numCellsPerDim; if constexpr (Dim == 2) { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start))); } else { - positions(i) = - point_t(T(gen.drand(ldom.first()<:0:>*cellWidth+domain_start, - ldom.last()<:0:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:1:>*cellWidth+domain_start, - ldom.last()<:1:>*cellWidth+domain_start)), - T(gen.drand(ldom.first()<:2:>*cellWidth+domain_start, - ldom.last()<:2:>*cellWidth+domain_start))); + positions(i) = point_t(T(gen.drand(ldom.first()<:0:> * cellWidth + domain_start, + ldom.last()<:0:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:1:> * cellWidth + domain_start, + ldom.last()<:1:> * cellWidth + domain_start)), + T(gen.drand(ldom.first()<:2:> * cellWidth + domain_start, + ldom.last()<:2:> * cellWidth + domain_start))); } - - if (i == numPoints-4) { - positions(numPoints-3) = ldom.first()*cellWidth+domain_start; - positions(numPoints-2) = ldom.last()*cellWidth+domain_start; + if (i == numPoints - 4) { + positions(numPoints - 3) = ldom.first() * cellWidth + domain_start; + positions(numPoints - 2) = ldom.last() * cellWidth + domain_start; // This point belongs to an edge if constexpr (Dim == 2) { - positions(numPoints-1) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth); + positions(numPoints - 1) = + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth); } else { - positions(numPoints-1) = - point_t(ldom.first()<:0:>*cellWidth+domain_start + cellWidth, - ldom.first()<:1:>*cellWidth+domain_start + 0.5*cellWidth, - ldom.first()<:2:>*cellWidth+domain_start + 0.5*cellWidth); + positions(numPoints - 1) = + point_t(ldom.first()<:0:> * cellWidth + domain_start + cellWidth, + ldom.first()<:1:> * cellWidth + domain_start + 0.5 * cellWidth, + ldom.first()<:2:> * cellWidth + domain_start + 0.5 * cellWidth); } } randomPool.free_state(gen); - } - ); + }); - Kokkos::View funcVals = solver.reconstructToPoints(positions); // calculate the error T linfError = 0; - Kokkos::parallel_reduce( "calc l infinity", numPoints, - KOKKOS_LAMBDA (size_t i, T& lmax) { + Kokkos::parallel_reduce( + "calc l infinity", numPoints, + KOKKOS_LAMBDA(size_t i, T& lmax) { point_t dif = funcVals(i) - analytical(positions(i)); - T val = Kokkos::sqrt(dif.dot(dif)); - if( val > lmax ) lmax = val; + T val = Kokkos::sqrt(dif.dot(dif)); + if (val > lmax) + lmax = val; }, - Kokkos::Max(linfError) - ); + Kokkos::Max(linfError)); Inform m(0, 0); m << std::setw(10) << numNodesPerDim; @@ -321,14 +314,10 @@ int main(int argc, char* argv[]) { dim = 2; } - msg << std::setw(10) << "num_nodes" - << std::setw(25) << "cell_spacing" - << std::setw(25) << "interp_error_coef" - << std::setw(25) << "recon_error" - << std::setw(25) << "solver_residue" - << std::setw(15) << "num_it" - << endl; - + msg << std::setw(10) << "num_nodes" << std::setw(25) << "cell_spacing" << std::setw(25) + << "interp_error_coef" << std::setw(25) << "recon_error" << std::setw(25) + << "solver_residue" << std::setw(15) << "num_it" << endl; + if (argc > 2 && std::atoi(argv[2]) != 0) { size_t n = std::atoi(argv<:2:>); if (dim == 2) { @@ -341,12 +330,12 @@ int main(int argc, char* argv[]) { } else { if (dim == 2) { // 2D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, 1.0, 3.0); } } else { // 3D Sinusoidal - for (unsigned n = 16; n <= 1024; n = std::sqrt(2)*n) { + for (unsigned n = 16; n <= 1024; n = std::sqrt(2) * n) { testFEMSolver(n, 1.0, 3.0); } } diff --git a/test/solver/fem/TestNonhomDirichlet_1d.cpp b/test/solver/fem/TestNonhomDirichlet_1d.cpp index 68a6053fe..47bebcaa5 100644 --- a/test/solver/fem/TestNonhomDirichlet_1d.cpp +++ b/test/solver/fem/TestNonhomDirichlet_1d.cpp @@ -1,17 +1,17 @@ // Tests the FEM Poisson solver by solving the problem: // // -Laplacian(u) = 1.0, -// where x in [0,1] and u(0) = u(1) = 1.0. +// where x in [0,1] and u(0) = u(1) = 1.0. // -// The exact solution is +// The exact solution is // u(x) = 1 + x/2 - (x^2)/2. // // BCs: Dirichlet BCs (Constant Face = 1). // This is only 1D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_1d --info 5 @@ -24,7 +24,7 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - return (1.0 + 0.5*x_vec[0] - 0.5*(x_vec[0]*x_vec[0])); + return (1.0 + 0.5 * x_vec[0] - 0.5 * (x_vec[0] * x_vec[0])); } }; @@ -114,7 +114,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_1d_preconditioned.cpp b/test/solver/fem/TestNonhomDirichlet_1d_preconditioned.cpp index 3d9ef30ab..de04cf1bd 100644 --- a/test/solver/fem/TestNonhomDirichlet_1d_preconditioned.cpp +++ b/test/solver/fem/TestNonhomDirichlet_1d_preconditioned.cpp @@ -2,17 +2,17 @@ // by solving the problem: // // -Laplacian(u) = 1.0, -// where x in [0,1] and u(0) = u(1) = 1.0. +// where x in [0,1] and u(0) = u(1) = 1.0. // -// The exact solution is +// The exact solution is // u(x) = 1 + x/2 - (x^2)/2. // // BCs: Dirichlet BCs (Constant Face = 1). // This is only 1D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_1d_preconditioned --info 5 @@ -25,7 +25,7 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - return (1.0 + 0.5*x_vec[0] - 0.5*(x_vec[0]*x_vec[0])); + return (1.0 + 0.5 * x_vec[0] - 0.5 * (x_vec[0] * x_vec[0])); } }; @@ -99,13 +99,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; @@ -131,7 +131,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_1dcos.cpp b/test/solver/fem/TestNonhomDirichlet_1dcos.cpp index 31574c3b9..96717ab9a 100644 --- a/test/solver/fem/TestNonhomDirichlet_1dcos.cpp +++ b/test/solver/fem/TestNonhomDirichlet_1dcos.cpp @@ -1,7 +1,7 @@ // Tests the FEM Poisson solver by solving the problem: // // -Laplacian(u) = pi^2 * cos(pi * x), -// where x in [-1,1] and u(-1) = u(1) = -1. +// where x in [-1,1] and u(-1) = u(1) = -1. // // The exact solution is u(x) = cos(pi * x). // @@ -9,8 +9,8 @@ // This is only 1D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_1dcos --info 5 @@ -124,7 +124,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_2d.cpp b/test/solver/fem/TestNonhomDirichlet_2d.cpp index 3f1e3e0c5..52b65b57b 100644 --- a/test/solver/fem/TestNonhomDirichlet_2d.cpp +++ b/test/solver/fem/TestNonhomDirichlet_2d.cpp @@ -1,16 +1,16 @@ // Tests the FEM Poisson solver by solving the problem: // // -Laplacian(u) = f(x, y), -// where x,y in [0,1]^2 and u(boundaries) = 1.56, -// and f(x,y) is such that the exact solution is +// where x,y in [0,1]^2 and u(boundaries) = 1.56, +// and f(x,y) is such that the exact solution is // u(x,y) = x^2(1 - x^2) + y^2(1 - y^2) + 1.56. // // BCs: Dirichlet BCs (Constant Face = 1.56). // This is only 2D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_2d --info 5 @@ -23,8 +23,9 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - return (x_vec[0] * x_vec[0]) * (1.0 - x_vec[0] * x_vec[0]) - * (x_vec[1] * x_vec[1]) * (1.0 - x_vec[1]*x_vec[1]) + 1.56; + return (x_vec[0] * x_vec[0]) * (1.0 - x_vec[0] * x_vec[0]) * (x_vec[1] * x_vec[1]) + * (1.0 - x_vec[1] * x_vec[1]) + + 1.56; } }; @@ -35,7 +36,7 @@ KOKKOS_INLINE_FUNCTION T rhs_function(ippl::Vector x_vec) { double x4 = Kokkos::pow(x_vec[0], 4); double y4 = Kokkos::pow(x_vec[1], 4); - return -2.0*(y2 - y4 + (x4*(-1.0 + 6*y2)) + x2*(1.0-12*y2+6*y4)); + return -2.0 * (y2 - y4 + (x4 * (-1.0 + 6 * y2)) + x2 * (1.0 - 12 * y2 + 6 * y4)); } template @@ -126,7 +127,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_2d_preconditioned.cpp b/test/solver/fem/TestNonhomDirichlet_2d_preconditioned.cpp index 548ce34a2..e886a3d24 100644 --- a/test/solver/fem/TestNonhomDirichlet_2d_preconditioned.cpp +++ b/test/solver/fem/TestNonhomDirichlet_2d_preconditioned.cpp @@ -2,16 +2,16 @@ // by solving the problem: // // -Laplacian(u) = f(x, y), -// where x,y in [0,1]^2 and u(boundaries) = 1.56, -// and f(x,y) is such that the exact solution is +// where x,y in [0,1]^2 and u(boundaries) = 1.56, +// and f(x,y) is such that the exact solution is // u(x,y) = x^2(1 - x^2) + y^2(1 - y^2) + 1.56. // // BCs: Dirichlet BCs (Constant Face = 1.56). // This is only 2D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_2d_preconditioned --info 5 @@ -24,8 +24,9 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - return (x_vec[0] * x_vec[0]) * (1.0 - x_vec[0] * x_vec[0]) - * (x_vec[1] * x_vec[1]) * (1.0 - x_vec[1]*x_vec[1]) + 1.56; + return (x_vec[0] * x_vec[0]) * (1.0 - x_vec[0] * x_vec[0]) * (x_vec[1] * x_vec[1]) + * (1.0 - x_vec[1] * x_vec[1]) + + 1.56; } }; @@ -36,7 +37,7 @@ KOKKOS_INLINE_FUNCTION T rhs_function(ippl::Vector x_vec) { double x4 = Kokkos::pow(x_vec[0], 4); double y4 = Kokkos::pow(x_vec[1], 4); - return -2.0*(y2 - y4 + (x4*(-1.0 + 6*y2)) + x2*(1.0-12*y2+6*y4)); + return -2.0 * (y2 - y4 + (x4 * (-1.0 + 6 * y2)) + x2 * (1.0 - 12 * y2 + 6 * y4)); } template @@ -108,13 +109,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; @@ -140,7 +141,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_3d.cpp b/test/solver/fem/TestNonhomDirichlet_3d.cpp index 6462fbebc..644c650ec 100644 --- a/test/solver/fem/TestNonhomDirichlet_3d.cpp +++ b/test/solver/fem/TestNonhomDirichlet_3d.cpp @@ -1,16 +1,16 @@ // Tests the FEM Poisson solver by solving the problem: // // -Laplacian(u) = f(x, y, z), -// where x,y,z in [0,2]^3 and u(boundaries) = 8, -// and f(x,y,z) is such that the exact solution is +// where x,y,z in [0,2]^3 and u(boundaries) = 8, +// and f(x,y,z) is such that the exact solution is // u(x,y,z) = -x^2(4 - x^2)*y^2(4 - y^2)*z^2(4 - z^2) + 8. // // BCs: Dirichlet BCs (Constant Face = 8.0). // This is only 3D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_3d --info 5 @@ -27,21 +27,24 @@ struct AnalyticSol { T y = x_vec[1]; T z = x_vec[2]; - return -(x*x)*(4 - x*x)*(y*y)*(4 - y*y)*(z*z)*(4 - z*z) + 8.0; + return -(x * x) * (4 - x * x) * (y * y) * (4 - y * y) * (z * z) * (4 - z * z) + 8.0; } }; template KOKKOS_INLINE_FUNCTION T rhs_function(ippl::Vector x_vec) { - T x2 = x_vec[0]*x_vec[0]; - T y2 = x_vec[1]*x_vec[1]; - T z2 = x_vec[2]*x_vec[2]; - T x4 = x2*x2; - T y4 = y2*y2; - T z4 = z2*z2; - - return 8*y2*(-4+y2)*z2*(-4+z2)-4*x4*(-2*z2*(-4+z2)+y4*(-2+3*z2)+y2*(8-24*z2+3*z4)) - -4*x2*(8*z2*(-4+z2) + y4*(8-24*z2+3*z4)-8*y2*(4-18*z2+3*z4)); + T x2 = x_vec[0] * x_vec[0]; + T y2 = x_vec[1] * x_vec[1]; + T z2 = x_vec[2] * x_vec[2]; + T x4 = x2 * x2; + T y4 = y2 * y2; + T z4 = z2 * z2; + + return 8 * y2 * (-4 + y2) * z2 * (-4 + z2) + - 4 * x4 * (-2 * z2 * (-4 + z2) + y4 * (-2 + 3 * z2) + y2 * (8 - 24 * z2 + 3 * z4)) + - 4 * x2 + * (8 * z2 * (-4 + z2) + y4 * (8 - 24 * z2 + 3 * z4) + - 8 * y2 * (4 - 18 * z2 + 3 * z4)); } template @@ -130,7 +133,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestNonhomDirichlet_3d_preconditioned.cpp b/test/solver/fem/TestNonhomDirichlet_3d_preconditioned.cpp index 58f011f23..4e0bfb1cd 100644 --- a/test/solver/fem/TestNonhomDirichlet_3d_preconditioned.cpp +++ b/test/solver/fem/TestNonhomDirichlet_3d_preconditioned.cpp @@ -2,16 +2,16 @@ // by solving the problem: // // -Laplacian(u) = f(x, y, z), -// where x,y,z in [0,2]^3 and u(boundaries) = 8, -// and f(x,y,z) is such that the exact solution is +// where x,y,z in [0,2]^3 and u(boundaries) = 8, +// and f(x,y,z) is such that the exact solution is // u(x,y,z) = -x^2(4 - x^2)*y^2(4 - y^2)*z^2(4 - z^2) + 8. // // BCs: Dirichlet BCs (Constant Face = 8.0). // This is only 3D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestNonHomDirichlet_3d_preconditioned --info 5 @@ -28,21 +28,24 @@ struct AnalyticSol { T y = x_vec[1]; T z = x_vec[2]; - return -(x*x)*(4 - x*x)*(y*y)*(4 - y*y)*(z*z)*(4 - z*z) + 8.0; + return -(x * x) * (4 - x * x) * (y * y) * (4 - y * y) * (z * z) * (4 - z * z) + 8.0; } }; template KOKKOS_INLINE_FUNCTION T rhs_function(ippl::Vector x_vec) { - T x2 = x_vec[0]*x_vec[0]; - T y2 = x_vec[1]*x_vec[1]; - T z2 = x_vec[2]*x_vec[2]; - T x4 = x2*x2; - T y4 = y2*y2; - T z4 = z2*z2; - - return 8*y2*(-4+y2)*z2*(-4+z2)-4*x4*(-2*z2*(-4+z2)+y4*(-2+3*z2)+y2*(8-24*z2+3*z4)) - -4*x2*(8*z2*(-4+z2) + y4*(8-24*z2+3*z4)-8*y2*(4-18*z2+3*z4)); + T x2 = x_vec[0] * x_vec[0]; + T y2 = x_vec[1] * x_vec[1]; + T z2 = x_vec[2] * x_vec[2]; + T x4 = x2 * x2; + T y4 = y2 * y2; + T z4 = z2 * z2; + + return 8 * y2 * (-4 + y2) * z2 * (-4 + z2) + - 4 * x4 * (-2 * z2 * (-4 + z2) + y4 * (-2 + 3 * z2) + y2 * (8 - 24 * z2 + 3 * z4)) + - 4 * x2 + * (8 * z2 * (-4 + z2) + y4 * (8 - 24 * z2 + 3 * z4) + - 8 * y2 * (4 - 18 * z2 + 3 * z4)); } template @@ -115,13 +118,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; @@ -147,7 +150,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - sol; + lhs = lhs - sol; const T normError = norm(lhs) / norm(sol); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestPeriodicBC_sin.cpp b/test/solver/fem/TestPeriodicBC_sin.cpp index 6faaa3981..fad9ef741 100644 --- a/test/solver/fem/TestPeriodicBC_sin.cpp +++ b/test/solver/fem/TestPeriodicBC_sin.cpp @@ -6,14 +6,14 @@ // Exact solution is u(x) = sin(pi * x). // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // The test is available in 1D (problem above), // as well as 2D and 3D with analogous test cases. // // Here we use periodic BCs, so this should work -// for other domains too as long as the domain +// for other domains too as long as the domain // length is the size of the period i.e. 2. // // Usage: @@ -108,7 +108,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const ippl::Vector x = (iVec)*cellSpacing + origin; - apply(view_rhs, args) = sinusoidalRHSFunction(x); + apply(view_rhs, args) = sinusoidalRHSFunction(x); apply(view_analytical, args) = analytic(x); }); @@ -136,7 +136,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - analytical; + lhs = lhs - analytical; T normError = norm(lhs) / norm(analytical); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestPeriodicBC_sin_preconditioned.cpp b/test/solver/fem/TestPeriodicBC_sin_preconditioned.cpp index f7f777dac..5db894210 100644 --- a/test/solver/fem/TestPeriodicBC_sin_preconditioned.cpp +++ b/test/solver/fem/TestPeriodicBC_sin_preconditioned.cpp @@ -6,14 +6,14 @@ // Exact solution is u(x) = sin(pi * x). // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // The test is available in 1D (problem above), // as well as 2D and 3D with analogous test cases. // // Here we use periodic BCs, so this should work -// for other domains too as long as the domain +// for other domains too as long as the domain // length is the size of the period i.e. 2. // // Usage: @@ -108,7 +108,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const ippl::Vector x = (iVec)*cellSpacing + origin; - apply(view_rhs, args) = sinusoidalRHSFunction(x); + apply(view_rhs, args) = sinusoidalRHSFunction(x); apply(view_analytical, args) = analytic(x); }); @@ -118,13 +118,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; @@ -153,7 +153,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - analytical; + lhs = lhs - analytical; T normError = norm(lhs) / norm(analytical); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestPeriodicBC_sinsin.cpp b/test/solver/fem/TestPeriodicBC_sinsin.cpp index 7b018b164..e82187c21 100644 --- a/test/solver/fem/TestPeriodicBC_sinsin.cpp +++ b/test/solver/fem/TestPeriodicBC_sinsin.cpp @@ -3,18 +3,18 @@ // -Laplacian(u) = f(x), x in [-1,1] // u(-1) = u(1) = 0 // -// where f(x) is such that the exact solution is +// where f(x) is such that the exact solution is // u(x) = sin(sin(pi * x)). // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // The test is available in 1D (problem above), // as well as 2D and 3D with analogous test cases. // // Here we use periodic BCs, so this should work -// for other domains too as long as the domain +// for other domains too as long as the domain // length is the size of the period i.e. 2. // // Usage: @@ -42,32 +42,38 @@ KOKKOS_INLINE_FUNCTION T sinusoidalRHSFunction(ippl::Vector x_vec) { if (Dim == 1) { T x = x_vec[0]; - val = Kokkos::pow(pi, 2) * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); + val = Kokkos::pow(pi, 2) + * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); } else if (Dim == 2) { T x = x_vec[0]; T y = x_vec[1]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))); - + * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))); + } else if (Dim == 3) { T x = x_vec[0]; T y = x_vec[1]; T z = x_vec[2]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) - + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + Kokkos::pow(Kokkos::cos(pi * z), 2)) - * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))) - * Kokkos::sin(Kokkos::sin(pi * z))); + * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) + * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) + + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + + Kokkos::pow(Kokkos::cos(pi * z), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))) + * Kokkos::sin(Kokkos::sin(pi * z))); } return val; @@ -145,7 +151,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const ippl::Vector x = (iVec)*cellSpacing + origin; - apply(view_rhs, args) = sinusoidalRHSFunction(x); + apply(view_rhs, args) = sinusoidalRHSFunction(x); apply(view_analytical, args) = analytic(x); }); @@ -170,7 +176,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - analytical; + lhs = lhs - analytical; T normError = norm(lhs) / norm(analytical); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestScaling_PeriodicBC_sinsin.cpp b/test/solver/fem/TestScaling_PeriodicBC_sinsin.cpp index cd8237e9c..3a180999a 100644 --- a/test/solver/fem/TestScaling_PeriodicBC_sinsin.cpp +++ b/test/solver/fem/TestScaling_PeriodicBC_sinsin.cpp @@ -22,8 +22,8 @@ #include "Utility/Inform.h" #include "Utility/IpplTimings.h" -#include "PoissonSolvers/PoissonCG.h" #include "PoissonSolvers/FEMPoissonSolver.h" +#include "PoissonSolvers/PoissonCG.h" template KOKKOS_INLINE_FUNCTION T sinusoidalRHSFunction(ippl::Vector x_vec) { @@ -33,32 +33,38 @@ KOKKOS_INLINE_FUNCTION T sinusoidalRHSFunction(ippl::Vector x_vec) { if (Dim == 1) { T x = x_vec[0]; - val = Kokkos::pow(pi, 2) * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); + val = Kokkos::pow(pi, 2) + * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); } else if (Dim == 2) { T x = x_vec[0]; T y = x_vec[1]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))); - + * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))); + } else if (Dim == 3) { T x = x_vec[0]; T y = x_vec[1]; T z = x_vec[2]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) - + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + Kokkos::pow(Kokkos::cos(pi * z), 2)) - * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))) - * Kokkos::sin(Kokkos::sin(pi * z))); + * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) + * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) + + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + + Kokkos::pow(Kokkos::cos(pi * z), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))) + * Kokkos::sin(Kokkos::sin(pi * z))); } return val; @@ -108,7 +114,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::FieldLayout layout(MPI_COMM_WORLD, domain, isParallel); Field_t lhs(mesh, layout, numGhosts); // left hand side (updated in the algorithm) Field_t rhs(mesh, layout, numGhosts); // right hand side (updated - load vector) - Field_t rhs_store(mesh, layout, numGhosts); + Field_t rhs_store(mesh, layout, numGhosts); // Define boundary conditions BConds_t bcField; @@ -153,7 +159,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // start the timer static IpplTimings::TimerRef solveTimer = IpplTimings::getTimer("solve"); for (int i = 0; i < 5; ++i) { - lhs = 0; + lhs = 0; IpplTimings::startTimer(solveTimer); solver.solve(); diff --git a/test/solver/fem/TestScaling_PeriodicBC_sinsin_precon.cpp b/test/solver/fem/TestScaling_PeriodicBC_sinsin_precon.cpp index 0cbf4c05b..9fe4916ee 100644 --- a/test/solver/fem/TestScaling_PeriodicBC_sinsin_precon.cpp +++ b/test/solver/fem/TestScaling_PeriodicBC_sinsin_precon.cpp @@ -34,32 +34,38 @@ KOKKOS_INLINE_FUNCTION T sinusoidalRHSFunction(ippl::Vector x_vec) { if (Dim == 1) { T x = x_vec[0]; - val = Kokkos::pow(pi, 2) * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); + val = Kokkos::pow(pi, 2) + * ((Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x)) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) * Kokkos::sin(Kokkos::sin(pi * x)))); } else if (Dim == 2) { T x = x_vec[0]; T y = x_vec[1]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))); - + * (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))); + } else if (Dim == 3) { T x = x_vec[0]; T y = x_vec[1]; T z = x_vec[2]; val = Kokkos::pow(pi, 2) - * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) - + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) * Kokkos::sin(Kokkos::sin(pi * x)) - + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) - + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + Kokkos::pow(Kokkos::cos(pi * z), 2)) - * Kokkos::sin(Kokkos::sin(pi * x))) - * Kokkos::sin(Kokkos::sin(pi * y))) - * Kokkos::sin(Kokkos::sin(pi * z))); + * (Kokkos::cos(Kokkos::sin(pi * z)) * Kokkos::sin(pi * z) + * Kokkos::sin(Kokkos::sin(pi * x)) * Kokkos::sin(Kokkos::sin(pi * y)) + + (Kokkos::cos(Kokkos::sin(pi * y)) * Kokkos::sin(pi * y) + * Kokkos::sin(Kokkos::sin(pi * x)) + + (Kokkos::cos(Kokkos::sin(pi * x)) * Kokkos::sin(pi * x) + + (Kokkos::pow(Kokkos::cos(pi * x), 2) + Kokkos::pow(Kokkos::cos(pi * y), 2) + + Kokkos::pow(Kokkos::cos(pi * z), 2)) + * Kokkos::sin(Kokkos::sin(pi * x))) + * Kokkos::sin(Kokkos::sin(pi * y))) + * Kokkos::sin(Kokkos::sin(pi * z))); } return val; @@ -137,7 +143,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const ippl::Vector x = (iVec)*cellSpacing + origin; - apply(view_rhs, args) = sinusoidalRHSFunction(x); + apply(view_rhs, args) = sinusoidalRHSFunction(x); apply(view_analytical, args) = analytic(x); }); @@ -147,13 +153,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; @@ -179,7 +185,7 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, // Compute the error const T relError = solver.getL2Error(analytic); - lhs = lhs - analytical; + lhs = lhs - analytical; T normError = norm(lhs) / norm(analytical); m << std::setw(10) << numNodesPerDim; diff --git a/test/solver/fem/TestScaling_ZeroBC_sin_precon.cpp b/test/solver/fem/TestScaling_ZeroBC_sin_precon.cpp index 6462c9417..4d576b857 100644 --- a/test/solver/fem/TestScaling_ZeroBC_sin_precon.cpp +++ b/test/solver/fem/TestScaling_ZeroBC_sin_precon.cpp @@ -105,13 +105,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; diff --git a/test/solver/fem/TestZeroBC_constant1d.cpp b/test/solver/fem/TestZeroBC_constant1d.cpp index b530013b4..417680ce3 100644 --- a/test/solver/fem/TestZeroBC_constant1d.cpp +++ b/test/solver/fem/TestZeroBC_constant1d.cpp @@ -9,8 +9,8 @@ // This is only 1D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestZeroBC_constant1d --info 5 @@ -23,7 +23,7 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - T val = 1.0 - (x_vec[0]*x_vec[0]); + T val = 1.0 - (x_vec[0] * x_vec[0]); return val; } }; @@ -31,7 +31,6 @@ struct AnalyticSol { template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { - // start the timer static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); diff --git a/test/solver/fem/TestZeroBC_constant1d_preconditioned.cpp b/test/solver/fem/TestZeroBC_constant1d_preconditioned.cpp index df5b3d951..1c382fd0b 100644 --- a/test/solver/fem/TestZeroBC_constant1d_preconditioned.cpp +++ b/test/solver/fem/TestZeroBC_constant1d_preconditioned.cpp @@ -10,8 +10,8 @@ // This is only 1D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestZeroBC_constant1d_preconditioned --info 5 @@ -24,7 +24,7 @@ template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - T val = 1.0 - (x_vec[0]*x_vec[0]); + T val = 1.0 - (x_vec[0] * x_vec[0]); return val; } }; @@ -32,7 +32,6 @@ struct AnalyticSol { template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { - // start the timer static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); @@ -79,13 +78,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; diff --git a/test/solver/fem/TestZeroBC_polynomial2d.cpp b/test/solver/fem/TestZeroBC_polynomial2d.cpp index 33a3f1021..c8c72506f 100644 --- a/test/solver/fem/TestZeroBC_polynomial2d.cpp +++ b/test/solver/fem/TestZeroBC_polynomial2d.cpp @@ -9,8 +9,8 @@ // This is only 2D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestZeroBC_polynomial2d --info 5 @@ -22,9 +22,11 @@ template KOKKOS_INLINE_FUNCTION T RHSFunction(ippl::Vector x_vec) { - T val = -2.0 * (x_vec[1]*x_vec[1] - Kokkos::pow(x_vec[1],4) + (Kokkos::pow(x_vec[0],4) - * (-1.0 + 6*x_vec[1]*x_vec[1])) + x_vec[0]*x_vec[0]*(1 - 12*x_vec[1]*x_vec[1] - + 6*Kokkos::pow(x_vec[1],4))); + T val = + -2.0 + * (x_vec[1] * x_vec[1] - Kokkos::pow(x_vec[1], 4) + + (Kokkos::pow(x_vec[0], 4) * (-1.0 + 6 * x_vec[1] * x_vec[1])) + + x_vec[0] * x_vec[0] * (1 - 12 * x_vec[1] * x_vec[1] + 6 * Kokkos::pow(x_vec[1], 4))); return val; } @@ -32,8 +34,8 @@ KOKKOS_INLINE_FUNCTION T RHSFunction(ippl::Vector x_vec) { template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - T val = (x_vec[0] * x_vec[0]) * (1 - (x_vec[0]*x_vec[0])) - * (x_vec[1] * x_vec[1]) * (1 - (x_vec[1]*x_vec[1])); + T val = (x_vec[0] * x_vec[0]) * (1 - (x_vec[0] * x_vec[0])) * (x_vec[1] * x_vec[1]) + * (1 - (x_vec[1] * x_vec[1])); return val; } }; @@ -41,7 +43,6 @@ struct AnalyticSol { template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { - // start the timer static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); diff --git a/test/solver/fem/TestZeroBC_polynomial2d_preconditioned.cpp b/test/solver/fem/TestZeroBC_polynomial2d_preconditioned.cpp index 9f83fa3fc..1eeb0cc10 100644 --- a/test/solver/fem/TestZeroBC_polynomial2d_preconditioned.cpp +++ b/test/solver/fem/TestZeroBC_polynomial2d_preconditioned.cpp @@ -10,8 +10,8 @@ // This is only 2D! // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // Usage: // ./TestZeroBC_polynomial2d_preconditioned --info 5 @@ -23,9 +23,11 @@ template KOKKOS_INLINE_FUNCTION T RHSFunction(ippl::Vector x_vec) { - T val = -2.0 * (x_vec[1]*x_vec[1] - Kokkos::pow(x_vec[1],4) + (Kokkos::pow(x_vec[0],4) - * (-1.0 + 6*x_vec[1]*x_vec[1])) + x_vec[0]*x_vec[0]*(1 - 12*x_vec[1]*x_vec[1] - + 6*Kokkos::pow(x_vec[1],4))); + T val = + -2.0 + * (x_vec[1] * x_vec[1] - Kokkos::pow(x_vec[1], 4) + + (Kokkos::pow(x_vec[0], 4) * (-1.0 + 6 * x_vec[1] * x_vec[1])) + + x_vec[0] * x_vec[0] * (1 - 12 * x_vec[1] * x_vec[1] + 6 * Kokkos::pow(x_vec[1], 4))); return val; } @@ -33,8 +35,8 @@ KOKKOS_INLINE_FUNCTION T RHSFunction(ippl::Vector x_vec) { template struct AnalyticSol { KOKKOS_FUNCTION const T operator()(ippl::Vector x_vec) const { - T val = (x_vec[0] * x_vec[0]) * (1 - (x_vec[0]*x_vec[0])) - * (x_vec[1] * x_vec[1]) * (1 - (x_vec[1]*x_vec[1])); + T val = (x_vec[0] * x_vec[0]) * (1 - (x_vec[0] * x_vec[0])) * (x_vec[1] * x_vec[1]) + * (1 - (x_vec[1] * x_vec[1])); return val; } }; @@ -42,7 +44,6 @@ struct AnalyticSol { template void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, const T& domain_end = 1.0) { - // start the timer static IpplTimings::TimerRef initTimer = IpplTimings::getTimer("initTest"); IpplTimings::startTimer(initTimer); @@ -103,13 +104,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; diff --git a/test/solver/fem/TestZeroBC_sin.cpp b/test/solver/fem/TestZeroBC_sin.cpp index 06c9d32f1..7a035f485 100644 --- a/test/solver/fem/TestZeroBC_sin.cpp +++ b/test/solver/fem/TestZeroBC_sin.cpp @@ -8,8 +8,8 @@ // BCs: Homogeneous Dirichlet BCs (Zero). // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // The test is available in 1D (problem above), // as well as 2D and 3D with analogous test cases. diff --git a/test/solver/fem/TestZeroBC_sin_preconditioned.cpp b/test/solver/fem/TestZeroBC_sin_preconditioned.cpp index 4b5b508a8..936caac46 100644 --- a/test/solver/fem/TestZeroBC_sin_preconditioned.cpp +++ b/test/solver/fem/TestZeroBC_sin_preconditioned.cpp @@ -8,8 +8,8 @@ // BCs: Homogeneous Dirichlet BCs (Zero). // // The test prints out the relative error as we refine -// the mesh spacing i.e. it is a convergence study. -// The order of convergence should be 2. +// the mesh spacing i.e. it is a convergence study. +// The order of convergence should be 2. // // The test is available in 1D (problem above), // as well as 2D and 3D with analogous test cases. @@ -110,13 +110,13 @@ void testFEMSolver(const unsigned& numNodesPerDim, const T& domain_start = 0.0, ippl::PreconditionedFEMPoissonSolver solver(lhs, rhs); // parameters for the preconditioner - std::string preconditioner_type = "richardson"; + std::string preconditioner_type = "richardson"; int gauss_seidel_inner_iterations = 4; int gauss_seidel_outer_iterations = 2; - int newton_level = 1; // unused - int chebyshev_degree = 1; // unused - int richardson_iterations = 4; - double ssor_omega = 1.57079632679; + int newton_level = 1; // unused + int chebyshev_degree = 1; // unused + int richardson_iterations = 4; + double ssor_omega = 1.57079632679; // set the parameters ippl::ParameterList params; diff --git a/test/types/TestTuple.cpp b/test/types/TestTuple.cpp index c6a461c9c..c459dbae6 100644 --- a/test/types/TestTuple.cpp +++ b/test/types/TestTuple.cpp @@ -38,7 +38,7 @@ int main(int argc, char* argv[]) { ippl::Tuple red; Kokkos::parallel_reduce( 100, - KOKKOS_LAMBDA(size_t idx, ippl::Tuple & ref)->void { + KOKKOS_LAMBDA(size_t idx, ippl::Tuple& ref)->void { ref += view(idx); }, red); diff --git a/test/types/TestVector3.cpp b/test/types/TestVector3.cpp index 1841088d2..b81dba896 100644 --- a/test/types/TestVector3.cpp +++ b/test/types/TestVector3.cpp @@ -72,7 +72,7 @@ class VecSum : public Expression> { template KOKKOS_FUNCTION VecSum operator+(Expression const& u, Expression const& v) { - return VecSum(*static_cast(&u), *static_cast(&v)); + return VecSum(*static_cast(&u), *static_cast(&v)); } int main() { diff --git a/unit_tests/BareField/BareField.cpp b/unit_tests/BareField/BareField.cpp index fe439dc6f..a421849d1 100644 --- a/unit_tests/BareField/BareField.cpp +++ b/unit_tests/BareField/BareField.cpp @@ -117,10 +117,10 @@ TYPED_TEST(BareFieldTest, Sum) { *field = val; T sum = field->sum(); assertEqual(expected, sum); - auto& vfield = this->vfield; - *vfield = ippl::Vector(val); - ippl::Vector vsum = vfield->sum(); - for(unsigned d = 0;d < TestFixture::dim;d++){ + auto& vfield = this->vfield; + *vfield = ippl::Vector(val); + ippl::Vector vsum = vfield->sum(); + for (unsigned d = 0; d < TestFixture::dim; d++) { assertEqual(expected, vsum[d]); } } @@ -136,7 +136,7 @@ TYPED_TEST(BareFieldTest, Min) { Kokkos::parallel_for("Set field", field->getFieldRangePolicy(), FieldVal{view, lDom}); auto& vfield = this->vfield; - auto vview = vfield->getView(); + auto vview = vfield->getView(); Kokkos::parallel_for("Set field", field->getFieldRangePolicy(), VFieldVal{vview, lDom}); Kokkos::fence(); @@ -145,8 +145,8 @@ TYPED_TEST(BareFieldTest, Min) { // minimum value in 3D: -1 + nghost + nghost + nghost assertEqual(min, field->getNghost() * TestFixture::dim - 1); - ippl::Vector vsum = vfield->min(); - for(unsigned d = 0;d < TestFixture::dim;d++){ + ippl::Vector vsum = vfield->min(); + for (unsigned d = 0; d < TestFixture::dim; d++) { assertEqual(field->getNghost() * TestFixture::dim - 1, vsum[d]); } } @@ -164,7 +164,7 @@ TYPED_TEST(BareFieldTest, Max) { Kokkos::parallel_for("Set field", field->getFieldRangePolicy(), FieldVal{view, lDom}); auto& vfield = this->vfield; - auto vview = vfield->getView(); + auto vview = vfield->getView(); Kokkos::parallel_for("Set field", field->getFieldRangePolicy(), VFieldVal{vview, lDom}); Kokkos::fence(); @@ -172,8 +172,8 @@ TYPED_TEST(BareFieldTest, Max) { T max = field->max(); assertEqual(max, expected); - ippl::Vector vsum = vfield->max(); - for(unsigned d = 0;d < TestFixture::dim;d++){ + ippl::Vector vsum = vfield->max(); + for (unsigned d = 0; d < TestFixture::dim; d++) { assertEqual(expected, vsum[d]); } } diff --git a/unit_tests/Communicate/BufferHandler.cpp b/unit_tests/Communicate/BufferHandler.cpp index eef387da9..e0b04da6e 100644 --- a/unit_tests/Communicate/BufferHandler.cpp +++ b/unit_tests/Communicate/BufferHandler.cpp @@ -182,7 +182,8 @@ TYPED_TEST(TypedBufferHandlerTest, GetAllocatedAndFreeSize_AfterDeleteAllBuffers EXPECT_EQ(this->handler->getFreeSize(), 0); } -// Test: Buffer size is correctly accounted for if a free buffer is available but we request a larger one, thus reallocating this one +// Test: Buffer size is correctly accounted for if a free buffer is available but we request a +// larger one, thus reallocating this one TYPED_TEST(TypedBufferHandlerTest, GetAllocatedAndFreeSize_ResizeBufferLargerThanAvailable) { auto smallBuffer = this->handler->getBuffer(50, 1.0); this->handler->freeBuffer(smallBuffer); diff --git a/unit_tests/Communicate/LogEntry.cpp b/unit_tests/Communicate/LogEntry.cpp index f351cf04d..a5108ab7f 100644 --- a/unit_tests/Communicate/LogEntry.cpp +++ b/unit_tests/Communicate/LogEntry.cpp @@ -30,7 +30,7 @@ TEST(LogEntryTest, Serialize) { EXPECT_GT(buffer.size(), 0); } -// Test to ensure LogEntry can be deserialized correctly +// Test to ensure LogEntry can be deserialized correctly TEST(LogEntryTest, Deserialize) { ippl::LogEntry logEntry = createSampleLogEntry(); diff --git a/unit_tests/FEM/AssembleRHS.cpp b/unit_tests/FEM/AssembleRHS.cpp index 318a81da7..1afe096ac 100644 --- a/unit_tests/FEM/AssembleRHS.cpp +++ b/unit_tests/FEM/AssembleRHS.cpp @@ -1,9 +1,10 @@ #include "Ippl.h" -#include "TestUtils.h" -#include "gtest/gtest.h" #include +#include "TestUtils.h" +#include "gtest/gtest.h" + template struct Bunch : public ippl::ParticleBase { Bunch(PLayout& playout) @@ -17,234 +18,224 @@ struct Bunch : public ippl::ParticleBase { charge_container_type Q; }; - -template struct ElemSelector; +template +struct ElemSelector; template struct ElemSelector<1, T> { - using Elem = ippl::EdgeElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; + using Elem = ippl::EdgeElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; template struct ElemSelector<2, T> { - using Elem = ippl::QuadrilateralElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; + using Elem = ippl::QuadrilateralElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; template struct ElemSelector<3, T> { - using Elem = ippl::HexahedralElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; + using Elem = ippl::HexahedralElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; - -template +template class AssembleRHSTest; template class AssembleRHSTest>> : public ::testing::Test { public: - using value_type = T; - static constexpr unsigned dim = Dim; - - using Mesh_t = ippl::UniformCartesian; - using Centering_t = typename Mesh_t::DefaultCentering; - using field_t = ippl::Field; - - using ElemSel = ElemSelector; - using Elem = typename ElemSel::Elem; - using Quad = typename ElemSel::Quad; - using Space = typename ElemSel::template Space; - - using playout_t = ippl::ParticleSpatialLayout; - using bunch_t = Bunch; - - static ippl::NDIndex make_owned_nd(int nx) { - ippl::Index I0(nx); - if constexpr (dim == 1) { - return ippl::NDIndex<1>(I0); - } else if constexpr (dim == 2) { - ippl::Index I1(nx); - return ippl::NDIndex<2>(I0, I1); - } else { - ippl::Index I1(nx), I2(nx); - return ippl::NDIndex<3>(I0, I1, I2); + using value_type = T; + static constexpr unsigned dim = Dim; + + using Mesh_t = ippl::UniformCartesian; + using Centering_t = typename Mesh_t::DefaultCentering; + using field_t = ippl::Field; + + using ElemSel = ElemSelector; + using Elem = typename ElemSel::Elem; + using Quad = typename ElemSel::Quad; + using Space = typename ElemSel::template Space; + + using playout_t = ippl::ParticleSpatialLayout; + using bunch_t = Bunch; + + static ippl::NDIndex make_owned_nd(int nx) { + ippl::Index I0(nx); + if constexpr (dim == 1) { + return ippl::NDIndex<1>(I0); + } else if constexpr (dim == 2) { + ippl::Index I1(nx); + return ippl::NDIndex<2>(I0, I1); + } else { + ippl::Index I1(nx), I2(nx); + return ippl::NDIndex<3>(I0, I1, I2); + } } - } - - - static ippl::FieldLayout make_layout(const ippl::NDIndex& owned) { - std::array par{}; par.fill(true); - return ippl::FieldLayout(MPI_COMM_WORLD, owned, par); - } - - static Mesh_t make_mesh(const ippl::NDIndex& owned, - const ippl::Vector& h, - const ippl::Vector& origin) { - return Mesh_t(owned, h, origin); - } - - static field_t make_zero_field(Mesh_t& mesh, - ippl::FieldLayout& layout) { - field_t f; - f.initialize(mesh, layout); - Kokkos::deep_copy(f.getView(), T(0)); - return f; - } - - static Space make_space(Mesh_t& mesh) { - Elem e = ElemSel::make_elem(); - Quad q = ElemSel::make_quad(e); - return Space(mesh, e, q); - } - - // Axis-aligned domain bounds from mesh & nx - static void domain_bounds(const Mesh_t& mesh, int nx, - ippl::Vector& xmin, - ippl::Vector& xmax) { - const auto org = mesh.getOrigin(); - const auto h = mesh.getMeshSpacing(); - for (unsigned d=0; d make_layout(const ippl::NDIndex& owned) { + std::array par{}; + par.fill(true); + return ippl::FieldLayout(MPI_COMM_WORLD, owned, par); + } + + static Mesh_t make_mesh(const ippl::NDIndex& owned, const ippl::Vector& h, + const ippl::Vector& origin) { + return Mesh_t(owned, h, origin); } - } - - static double fill_uniform_particles(bunch_t& bunch, int n_local, - const ippl::Vector& xmin, - const ippl::Vector& xmax, - uint64_t seed = 1337) { - bunch.create(n_local); - - std::mt19937_64 eng(seed + ippl::Comm->rank()); - - std::uniform_real_distribution wdist(0, 1); - - auto R_host = bunch.R.getHostMirror(); - auto Q_host = bunch.Q.getHostMirror(); - - double local_sum = 0.0; - for (int i=0; i < n_local; ++i) { - ippl::Vector r{}; - for (unsigned d=0; d pd(xmin[d], xmax[d]); - r[d] = pd(eng); - } - const T q = wdist(eng); - R_host(i) = r; Q_host(i) = q; - local_sum += static_cast(q); + + static field_t make_zero_field(Mesh_t& mesh, ippl::FieldLayout& layout) { + field_t f; + f.initialize(mesh, layout); + Kokkos::deep_copy(f.getView(), T(0)); + return f; + } + + static Space make_space(Mesh_t& mesh) { + Elem e = ElemSel::make_elem(); + Quad q = ElemSel::make_quad(e); + return Space(mesh, e, q); } - Kokkos::deep_copy(bunch.R.getView(), R_host); - Kokkos::deep_copy(bunch.Q.getView(), Q_host); - bunch.update(); - return local_sum; - } - - static double mpi_sum(double x) { - double g = 0.0; - MPI_Allreduce(&x, &g, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - return g; - } - - static constexpr T tol() { - return std::numeric_limits::epsilon() * 10.0; - } + // Axis-aligned domain bounds from mesh & nx + static void domain_bounds(const Mesh_t& mesh, int nx, ippl::Vector& xmin, + ippl::Vector& xmax) { + const auto org = mesh.getOrigin(); + const auto h = mesh.getMeshSpacing(); + for (unsigned d = 0; d < dim; ++d) { + xmin[d] = org[d]; + xmax[d] = org[d] + h[d] * T(nx - 1); + } + } + + static double fill_uniform_particles(bunch_t& bunch, int n_local, + const ippl::Vector& xmin, + const ippl::Vector& xmax, uint64_t seed = 1337) { + bunch.create(n_local); + + std::mt19937_64 eng(seed + ippl::Comm->rank()); + + std::uniform_real_distribution wdist(0, 1); + + auto R_host = bunch.R.getHostMirror(); + auto Q_host = bunch.Q.getHostMirror(); + + double local_sum = 0.0; + for (int i = 0; i < n_local; ++i) { + ippl::Vector r{}; + for (unsigned d = 0; d < dim; ++d) { + std::uniform_real_distribution pd(xmin[d], xmax[d]); + r[d] = pd(eng); + } + const T q = wdist(eng); + R_host(i) = r; + Q_host(i) = q; + local_sum += static_cast(q); + } + + Kokkos::deep_copy(bunch.R.getView(), R_host); + Kokkos::deep_copy(bunch.Q.getView(), Q_host); + bunch.update(); + return local_sum; + } + + static double mpi_sum(double x) { + double g = 0.0; + MPI_Allreduce(&x, &g, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + return g; + } + + static constexpr T tol() { return std::numeric_limits::epsilon() * 10.0; } }; using Precisions = TestParams::Precisions; -using Ranks = TestParams::Ranks<1, 2, 3>; +using Ranks = TestParams::Ranks<1, 2, 3>; using Tests = TestForTypes::type>::type; TYPED_TEST_SUITE(AssembleRHSTest, Tests); - TYPED_TEST(AssembleRHSTest, ConservationOfTotalWeight) { - using T = typename TestFixture::value_type; - constexpr unsigned Dim = TestFixture::dim; - - using bunch_t = typename TestFixture::bunch_t; - using playout_t = typename TestFixture::playout_t; - using field_t = typename TestFixture::field_t; - using exec_space = typename field_t::view_type::execution_space; + using T = typename TestFixture::value_type; + constexpr unsigned Dim = TestFixture::dim; + using bunch_t = typename TestFixture::bunch_t; + using playout_t = typename TestFixture::playout_t; + using field_t = typename TestFixture::field_t; + using exec_space = typename field_t::view_type::execution_space; - int nx = 32; + int nx = 32; - // Fixed, arbitrary choice of origin and spacing - ippl::Vector origin; - for (unsigned d=0; d origin; + for (unsigned d = 0; d < Dim; ++d) { + origin[d] = T(-0.7 + 0.11 * d); + } - ippl::Vector h; - for (unsigned d=0; d h; + for (unsigned d = 0; d < Dim; ++d) { + h[d] = T(0.31 + 0.07 * d); + } - auto owned = TestFixture::make_owned_nd(nx); - auto layout = TestFixture::make_layout(owned); - auto mesh = TestFixture::make_mesh(owned, h, origin); + auto owned = TestFixture::make_owned_nd(nx); + auto layout = TestFixture::make_layout(owned); + auto mesh = TestFixture::make_mesh(owned, h, origin); - auto rhs = TestFixture::make_zero_field(mesh, layout); - auto space = TestFixture::make_space(mesh); + auto rhs = TestFixture::make_zero_field(mesh, layout); + auto space = TestFixture::make_space(mesh); - playout_t playout(layout, mesh); - bunch_t bunch(playout); + playout_t playout(layout, mesh); + bunch_t bunch(playout); - ippl::Vector xmin, xmax; - TestFixture::domain_bounds(mesh, nx, xmin, xmax); + ippl::Vector xmin, xmax; + TestFixture::domain_bounds(mesh, nx, xmin, xmax); - const int n_local = 1000; - const double local_w = TestFixture::fill_uniform_particles(bunch, n_local, xmin, xmax); + const int n_local = 1000; + const double local_w = TestFixture::fill_uniform_particles(bunch, n_local, xmin, xmax); - auto policy = Kokkos::RangePolicy(0, bunch.getLocalNum()); - ippl::assemble_rhs_from_particles(bunch.Q, rhs, bunch.R, space, policy); + auto policy = Kokkos::RangePolicy(0, bunch.getLocalNum()); + ippl::assemble_rhs_from_particles(bunch.Q, rhs, bunch.R, space, policy); - const double global_w = TestFixture::mpi_sum(local_w); - const double rhs_sum = static_cast(rhs.sum()); + const double global_w = TestFixture::mpi_sum(local_w); + const double rhs_sum = static_cast(rhs.sum()); - const double abs_tol = static_cast(TestFixture::tol()); - const double rel_tol = static_cast(TestFixture::tol()); + const double abs_tol = static_cast(TestFixture::tol()); + const double rel_tol = static_cast(TestFixture::tol()); - const double diff = std::abs(global_w - rhs_sum); - const double scale = std::max(std::abs(global_w), std::abs(rhs_sum)); - const double allow = abs_tol + rel_tol * scale; + const double diff = std::abs(global_w - rhs_sum); + const double scale = std::max(std::abs(global_w), std::abs(rhs_sum)); + const double allow = abs_tol + rel_tol * scale; - EXPECT_LE(diff, allow) - << "Conservation check failed:\n" - << " rhs_sum = " << rhs_sum << "\n" - << " sum(weights) = " << global_w << "\n" - << " |diff| = " << diff << "\n" - << " abs_tol = " << abs_tol << "\n" - << " rel_tol * max(|.|) = " << (rel_tol * scale) << "\n" - << " allowed (abs+rel * scale) = " << allow << "\n"; + EXPECT_LE(diff, allow) << "Conservation check failed:\n" + << " rhs_sum = " << rhs_sum << "\n" + << " sum(weights) = " << global_w << "\n" + << " |diff| = " << diff << "\n" + << " abs_tol = " << abs_tol << "\n" + << " rel_tol * max(|.|) = " << (rel_tol * scale) << "\n" + << " allowed (abs+rel * scale) = " << allow << "\n"; } - int main(int argc, char* argv[]) { - ippl::initialize(argc, argv); - int result = 0; - { - ::testing::InitGoogleTest(&argc, argv); - result = RUN_ALL_TESTS(); - } - ippl::finalize(); - return result; + ippl::initialize(argc, argv); + int result = 0; + { + ::testing::InitGoogleTest(&argc, argv); + result = RUN_ALL_TESTS(); + } + ippl::finalize(); + return result; } diff --git a/unit_tests/FEM/EdgeElement.cpp b/unit_tests/FEM/EdgeElement.cpp index d1defc516..e2881b7cf 100644 --- a/unit_tests/FEM/EdgeElement.cpp +++ b/unit_tests/FEM/EdgeElement.cpp @@ -40,7 +40,7 @@ class EdgeElementTest>> : public ::testing:: ippl::EdgeElement edge_element; const vertex_points_t local_points = {{0.0}, {1.0}}; - const point_t local_mid_point = {0.5}; + const point_t local_mid_point = {0.5}; ippl::Vector edges; }; @@ -58,8 +58,8 @@ TYPED_TEST(EdgeElementTest, LocalVertices) { } TYPED_TEST(EdgeElementTest, LocalToGlobal) { - using T = typename TestFixture::value_t; - using point_t = typename TestFixture::point_t; + using T = typename TestFixture::value_t; + using point_t = typename TestFixture::point_t; using vertex_points_t = typename TestFixture::vertex_points_t; auto& edge_element = this->edge_element; @@ -84,8 +84,8 @@ TYPED_TEST(EdgeElementTest, LocalToGlobal) { } TYPED_TEST(EdgeElementTest, GlobalToLocal) { - using T = typename TestFixture::value_t; - using point_t = typename TestFixture::point_t; + using T = typename TestFixture::value_t; + using point_t = typename TestFixture::point_t; using vertex_points_t = typename TestFixture::vertex_points_t; auto& edge_element = this->edge_element; diff --git a/unit_tests/FEM/FEMVector.cpp b/unit_tests/FEM/FEMVector.cpp index e70ca1051..fc545a4a2 100644 --- a/unit_tests/FEM/FEMVector.cpp +++ b/unit_tests/FEM/FEMVector.cpp @@ -1,98 +1,94 @@ -#include - #include "Ippl.h" -#include "LinearSolvers/PCG.h" -#include "gtest/gtest.h" +#include #include "Utility/ParameterList.h" - +#include "LinearSolvers/PCG.h" +#include "gtest/gtest.h" TEST(FEMVector, ValueAssign) { using T = double; - size_t n = 10; // size of the FEMVector + size_t n = 10; // size of the FEMVector // setup fake neighbors and halo related indices std::vector neighbors(1); - std::vector< Kokkos::View > sendIdxs(1,Kokkos::View("sendIdxs", 2)); - std::vector< Kokkos::View > recvIdxs(1,Kokkos::View("recvIdxs", 2)); - + std::vector > sendIdxs(1, Kokkos::View("sendIdxs", 2)); + std::vector > recvIdxs(1, Kokkos::View("recvIdxs", 2)); + // create the FEMVector - ippl::FEMVector v(10,neighbors, sendIdxs, recvIdxs); + ippl::FEMVector v(10, neighbors, sendIdxs, recvIdxs); // set all the values to 42 v = 42.; // check that every entry now is 42 - auto view = v.getView(); + auto view = v.getView(); auto hView = Kokkos::create_mirror_view(view); - Kokkos::deep_copy (hView, view); + Kokkos::deep_copy(hView, view); for (size_t i = 0; i < n; ++i) { EXPECT_EQ(hView(i), 42.); } } - TEST(FEMVector, FEMVectorAssign) { using T = double; - size_t n = 10; // size of the FEMVector + size_t n = 10; // size of the FEMVector // setup fake neighbors and halo related indices std::vector neighbors(1); - std::vector< Kokkos::View > sendIdxs(1,Kokkos::View("sendIdxs", 2)); - std::vector< Kokkos::View > recvIdxs(1,Kokkos::View("recvIdxs", 2)); - + std::vector > sendIdxs(1, Kokkos::View("sendIdxs", 2)); + std::vector > recvIdxs(1, Kokkos::View("recvIdxs", 2)); + // create the FEMVectors - ippl::FEMVector a(10,neighbors, sendIdxs, recvIdxs); - ippl::FEMVector b(10,neighbors, sendIdxs, recvIdxs); + ippl::FEMVector a(10, neighbors, sendIdxs, recvIdxs); + ippl::FEMVector b(10, neighbors, sendIdxs, recvIdxs); a = 42.; b = a; // check that every entry now is 42 - auto view = b.getView(); + auto view = b.getView(); auto hView = Kokkos::create_mirror_view(view); - Kokkos::deep_copy (hView, view); + Kokkos::deep_copy(hView, view); for (size_t i = 0; i < n; ++i) { EXPECT_EQ(hView(i), 42.); } } - TEST(FEMVector, ClearValue) { using T = double; // setup fake neighbors and halo related indices std::vector neighbors = {0, 0}; - std::vector< Kokkos::View > sendIdxs(2); - std::vector< Kokkos::View > recvIdxs(2); - Kokkos::resize(sendIdxs[0],2); - Kokkos::resize(sendIdxs[1],2); - Kokkos::resize(recvIdxs[0],2); - Kokkos::resize(recvIdxs[1],2); + std::vector > sendIdxs(2); + std::vector > recvIdxs(2); + Kokkos::resize(sendIdxs[0], 2); + Kokkos::resize(sendIdxs[1], 2); + Kokkos::resize(recvIdxs[0], 2); + Kokkos::resize(recvIdxs[1], 2); // set up all the neighbor indices stuff for (size_t i = 0; i < 2; ++i) { auto hSendView = Kokkos::create_mirror_view(sendIdxs[i]); auto hRecvView = Kokkos::create_mirror_view(recvIdxs[i]); for (size_t j = 0; j < 2; ++j) { - hSendView(j) = i*2 + 2 + j; - hRecvView(j) = i*2 + 6 + j; + hSendView(j) = i * 2 + 2 + j; + hRecvView(j) = i * 2 + 6 + j; } Kokkos::deep_copy(sendIdxs[i], hSendView); Kokkos::deep_copy(recvIdxs[i], hRecvView); } - + // create the FEMVector - ippl::FEMVector v(10,neighbors, sendIdxs, recvIdxs); + ippl::FEMVector v(10, neighbors, sendIdxs, recvIdxs); // clear the values of the halo to 42 v.setHalo(42.); // check that every entry now is 42 - auto view = v.getView(); + auto view = v.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); @@ -100,31 +96,30 @@ TEST(FEMVector, ClearValue) { auto hRecvIdxs = Kokkos::create_mirror_view(recvIdxs[n]); Kokkos::deep_copy(hRecvIdxs, recvIdxs[n]); for (size_t i = 0; i < recvIdxs[n].extent(0); ++i) { - EXPECT_EQ(hView(hRecvIdxs(i)),42.); + EXPECT_EQ(hView(hRecvIdxs(i)), 42.); } } } - TEST(FEMVector, deepCopyShallowCopy) { - using T = double; + using T = double; size_t n = 10; // setup fake neighbors and halo related indices std::vector neighbors = {0, 0}; - std::vector< Kokkos::View > sendIdxs(2); - std::vector< Kokkos::View > recvIdxs(2); - Kokkos::resize(sendIdxs[0],2); - Kokkos::resize(sendIdxs[1],2); - Kokkos::resize(recvIdxs[0],2); - Kokkos::resize(recvIdxs[1],2); + std::vector > sendIdxs(2); + std::vector > recvIdxs(2); + Kokkos::resize(sendIdxs[0], 2); + Kokkos::resize(sendIdxs[1], 2); + Kokkos::resize(recvIdxs[0], 2); + Kokkos::resize(recvIdxs[1], 2); // set up all the neighbor indices stuff for (size_t i = 0; i < 2; ++i) { auto hSendView = Kokkos::create_mirror_view(sendIdxs[i]); auto hRecvView = Kokkos::create_mirror_view(recvIdxs[i]); for (size_t j = 0; j < 2; ++j) { - hSendView(j) = i*2 + 2 + j; - hRecvView(j) = i*2 + 6 + j; + hSendView(j) = i * 2 + 2 + j; + hRecvView(j) = i * 2 + 6 + j; } Kokkos::deep_copy(sendIdxs[i], hSendView); Kokkos::deep_copy(recvIdxs[i], hRecvView); @@ -141,14 +136,14 @@ TEST(FEMVector, deepCopyShallowCopy) { v = 2.; v.setHalo(5.); - auto vView = v.getView(); + auto vView = v.getView(); auto shallowView = shallow.getView(); - auto deepView = deep.getView(); - - auto hvView = Kokkos::create_mirror_view(vView); + auto deepView = deep.getView(); + + auto hvView = Kokkos::create_mirror_view(vView); auto hShallowView = Kokkos::create_mirror_view(shallowView); - auto hDeepView = Kokkos::create_mirror_view(deepView); - + auto hDeepView = Kokkos::create_mirror_view(deepView); + Kokkos::deep_copy(hvView, vView); Kokkos::deep_copy(hShallowView, shallowView); Kokkos::deep_copy(hDeepView, deepView); @@ -162,49 +157,47 @@ TEST(FEMVector, deepCopyShallowCopy) { } } - - TEST(FEMVector, fillHalo) { - using T = double; + using T = double; size_t n = 10; // size of FEMVector // setup fake neighbors and halo related indices size_t rank = ippl::Comm->rank(); size_t size = ippl::Comm->size(); - size_t nr = (rank + 1) % size; - size_t nl = rank == 0 ? size - 1 : rank -1; - + size_t nr = (rank + 1) % size; + size_t nl = rank == 0 ? size - 1 : rank - 1; + std::vector neighbors = {nr, nl}; - std::vector< Kokkos::View > sendIdxs(2); - std::vector< Kokkos::View > recvIdxs(2); - Kokkos::resize(sendIdxs[0],2); - Kokkos::resize(sendIdxs[1],2); - Kokkos::resize(recvIdxs[0],2); - Kokkos::resize(recvIdxs[1],2); + std::vector > sendIdxs(2); + std::vector > recvIdxs(2); + Kokkos::resize(sendIdxs[0], 2); + Kokkos::resize(sendIdxs[1], 2); + Kokkos::resize(recvIdxs[0], 2); + Kokkos::resize(recvIdxs[1], 2); // set up all the neighbor indices stuff for (size_t i = 0; i < 2; ++i) { auto hSendView = Kokkos::create_mirror_view(sendIdxs[i]); auto hRecvView = Kokkos::create_mirror_view(recvIdxs[i]); for (size_t j = 0; j < 2; ++j) { - hSendView(j) = i*2 + 2 + j; - hRecvView(j) = i*2 + 6 + j; + hSendView(j) = i * 2 + 2 + j; + hRecvView(j) = i * 2 + 6 + j; } Kokkos::deep_copy(sendIdxs[i], hSendView); Kokkos::deep_copy(recvIdxs[i], hRecvView); } // create the FEMVector - ippl::FEMVector v(n,neighbors, sendIdxs, recvIdxs); + ippl::FEMVector v(n, neighbors, sendIdxs, recvIdxs); // set all the values to 42 v = (double)rank; v.fillHalo(); - auto view = v.getView(); + auto view = v.getView(); auto hView = Kokkos::create_mirror_view(view); - Kokkos::deep_copy (hView, view); + Kokkos::deep_copy(hView, view); EXPECT_EQ(hView(0), (double)rank); EXPECT_EQ(hView(1), (double)rank); @@ -218,119 +211,116 @@ TEST(FEMVector, fillHalo) { EXPECT_EQ(hView(9), (double)nl); } - TEST(FEMVector, accumulateHalo) { - using T = double; + using T = double; size_t n = 10; // size of FEMVector // setup fake neighbors and halo related indices - size_t rank = ippl::Comm->rank(); - size_t size = ippl::Comm->size(); - size_t nr = (rank + 1) % size; - size_t nl = rank == 0 ? size - 1 : rank -1; + size_t rank = ippl::Comm->rank(); + size_t size = ippl::Comm->size(); + size_t nr = (rank + 1) % size; + size_t nl = rank == 0 ? size - 1 : rank - 1; std::vector neighbors = {nr, nl}; - std::vector< Kokkos::View > sendIdxs(2); - std::vector< Kokkos::View > recvIdxs(2); - Kokkos::resize(sendIdxs[0],2); - Kokkos::resize(sendIdxs[1],2); - Kokkos::resize(recvIdxs[0],2); - Kokkos::resize(recvIdxs[1],2); + std::vector > sendIdxs(2); + std::vector > recvIdxs(2); + Kokkos::resize(sendIdxs[0], 2); + Kokkos::resize(sendIdxs[1], 2); + Kokkos::resize(recvIdxs[0], 2); + Kokkos::resize(recvIdxs[1], 2); // set up all the neighbor indices stuff for (size_t i = 0; i < 2; ++i) { auto hSendView = Kokkos::create_mirror_view(sendIdxs[i]); auto hRecvView = Kokkos::create_mirror_view(recvIdxs[i]); for (size_t j = 0; j < 2; ++j) { - hSendView(j) = i*2 + 2 + j; - hRecvView(j) = i*2 + 6 + j; + hSendView(j) = i * 2 + 2 + j; + hRecvView(j) = i * 2 + 6 + j; } Kokkos::deep_copy(sendIdxs[i], hSendView); Kokkos::deep_copy(recvIdxs[i], hRecvView); } // create the FEMVector - ippl::FEMVector v(n,neighbors, sendIdxs, recvIdxs); + ippl::FEMVector v(n, neighbors, sendIdxs, recvIdxs); // set all the values to 42 v = (double)rank; v.accumulateHalo(); - auto view = v.getView(); + auto view = v.getView(); auto hView = Kokkos::create_mirror_view(view); - Kokkos::deep_copy (hView, view); + Kokkos::deep_copy(hView, view); EXPECT_EQ(hView(0), (double)rank); EXPECT_EQ(hView(1), (double)rank); - EXPECT_EQ(hView(2), (double)rank+nr); - EXPECT_EQ(hView(3), (double)rank+nr); - EXPECT_EQ(hView(4), (double)rank+nl); - EXPECT_EQ(hView(5), (double)rank+nl); + EXPECT_EQ(hView(2), (double)rank + nr); + EXPECT_EQ(hView(3), (double)rank + nr); + EXPECT_EQ(hView(4), (double)rank + nl); + EXPECT_EQ(hView(5), (double)rank + nl); EXPECT_EQ(hView(6), (double)rank); EXPECT_EQ(hView(7), (double)rank); EXPECT_EQ(hView(8), (double)rank); EXPECT_EQ(hView(9), (double)rank); } - TEST(FEMVector, Arithmetic) { using T = double; - size_t n = 10; // size of the FEMVector + size_t n = 10; // size of the FEMVector // setup fake neighbors and halo related indices std::vector neighbors(1); - std::vector< Kokkos::View > sendIdxs(1,Kokkos::View("sendIdxs", 2)); - std::vector< Kokkos::View > recvIdxs(1,Kokkos::View("recvIdxs", 2)); - + std::vector > sendIdxs(1, Kokkos::View("sendIdxs", 2)); + std::vector > recvIdxs(1, Kokkos::View("recvIdxs", 2)); + // create the FEMVectors - ippl::FEMVector a(n,neighbors, sendIdxs, recvIdxs); - ippl::FEMVector b(n,neighbors, sendIdxs, recvIdxs); - ippl::FEMVector c(n,neighbors, sendIdxs, recvIdxs); - - auto aView = a.getView(); + ippl::FEMVector a(n, neighbors, sendIdxs, recvIdxs); + ippl::FEMVector b(n, neighbors, sendIdxs, recvIdxs); + ippl::FEMVector c(n, neighbors, sendIdxs, recvIdxs); + + auto aView = a.getView(); auto haView = Kokkos::create_mirror_view(aView); - auto bView = b.getView(); + auto bView = b.getView(); auto hbView = Kokkos::create_mirror_view(bView); - auto cView = c.getView(); + auto cView = c.getView(); auto hcView = Kokkos::create_mirror_view(cView); for (size_t i = 0; i < n; ++i) { haView(i) = i; - hbView(i) = i+1; + hbView(i) = i + 1; } Kokkos::deep_copy(bView, hbView); Kokkos::deep_copy(aView, haView); - + // check addition c = a + b; Kokkos::deep_copy(hcView, cView); for (size_t i = 0; i < n; ++i) { - EXPECT_EQ(hcView(i), i+i+1.); + EXPECT_EQ(hcView(i), i + i + 1.); } - + // check subtraction c = a - b; Kokkos::deep_copy(hcView, cView); for (size_t i = 0; i < n; ++i) { - EXPECT_EQ(hcView(i), i - (i+1.)); + EXPECT_EQ(hcView(i), i - (i + 1.)); } // check multiplication c = a * b; Kokkos::deep_copy(hcView, cView); for (size_t i = 0; i < n; ++i) { - EXPECT_EQ(hcView(i), i * (i+1.)); + EXPECT_EQ(hcView(i), i * (i + 1.)); } // check division c = a / b; Kokkos::deep_copy(hcView, cView); for (size_t i = 0; i < n; ++i) { - EXPECT_EQ(hcView(i), i / (i+1.)); + EXPECT_EQ(hcView(i), i / (i + 1.)); } - // check scalar addition c = a + 10.; Kokkos::deep_copy(hcView, cView); @@ -361,82 +351,81 @@ TEST(FEMVector, Arithmetic) { // check combination c = 1.; - c = c - 10*a - b; + c = c - 10 * a - b; Kokkos::deep_copy(hcView, cView); for (size_t i = 0; i < n; ++i) { - EXPECT_EQ(hcView(i), 1. - 10.*i - (i+1)); + EXPECT_EQ(hcView(i), 1. - 10. * i - (i + 1)); } - } TEST(FEMVector, innerProduct) { using T = double; - size_t n = 10; // size of the FEMVector + size_t n = 10; // size of the FEMVector // setup fake neighbors and halo related indices - size_t rank = ippl::Comm->rank(); - size_t size = ippl::Comm->size(); - size_t nr = (rank + 1) % size; - size_t nl = rank == 0 ? size - 1 : rank -1; + size_t rank = ippl::Comm->rank(); + size_t size = ippl::Comm->size(); + size_t nr = (rank + 1) % size; + size_t nl = rank == 0 ? size - 1 : rank - 1; std::vector neighbors = {nr, nl}; - std::vector< Kokkos::View > sendIdxs(2); - std::vector< Kokkos::View > recvIdxs(2); - Kokkos::resize(sendIdxs[0],2); - Kokkos::resize(sendIdxs[1],2); - Kokkos::resize(recvIdxs[0],2); - Kokkos::resize(recvIdxs[1],2); + std::vector > sendIdxs(2); + std::vector > recvIdxs(2); + Kokkos::resize(sendIdxs[0], 2); + Kokkos::resize(sendIdxs[1], 2); + Kokkos::resize(recvIdxs[0], 2); + Kokkos::resize(recvIdxs[1], 2); // set up all the neighbor indices stuff for (size_t i = 0; i < 2; ++i) { auto hSendView = Kokkos::create_mirror_view(sendIdxs[i]); auto hRecvView = Kokkos::create_mirror_view(recvIdxs[i]); for (size_t j = 0; j < 2; ++j) { - hSendView(j) = i*2 + 6 + j; - hRecvView(j) = i*2 + j; + hSendView(j) = i * 2 + 6 + j; + hRecvView(j) = i * 2 + j; } Kokkos::deep_copy(sendIdxs[i], hSendView); Kokkos::deep_copy(recvIdxs[i], hRecvView); } // create the FEMVectors - ippl::FEMVector a(n,neighbors, sendIdxs, recvIdxs); - ippl::FEMVector b(n,neighbors, sendIdxs, recvIdxs); - - auto aView = a.getView(); + ippl::FEMVector a(n, neighbors, sendIdxs, recvIdxs); + ippl::FEMVector b(n, neighbors, sendIdxs, recvIdxs); + + auto aView = a.getView(); auto haView = Kokkos::create_mirror_view(aView); - auto bView = b.getView(); + auto bView = b.getView(); auto hbView = Kokkos::create_mirror_view(bView); for (size_t i = 0; i < n; ++i) { haView(i) = i; - hbView(i) = i+1; + hbView(i) = i + 1; } Kokkos::deep_copy(bView, hbView); Kokkos::deep_copy(aView, haView); - T val = innerProduct(a,b); + T val = innerProduct(a, b); - EXPECT_EQ(val, 1./3*(n*n*n - n)*ippl::Comm->size()); + EXPECT_EQ(val, 1. / 3 * (n * n * n - n) * ippl::Comm->size()); - val = innerProduct(a,a); - EXPECT_EQ(val, 1./6*(n-1)*n*(2*n-1)*ippl::Comm->size()); + val = innerProduct(a, a); + EXPECT_EQ(val, 1. / 6 * (n - 1) * n * (2 * n - 1) * ippl::Comm->size()); } TEST(FEMVector, norm) { using T = double; - size_t n = 10; // size of the FEMVector + size_t n = 10; // size of the FEMVector // setup fake neighbors and halo related indices std::vector neighbors(1); - std::vector< Kokkos::View > sendIdxs(1,Kokkos::View("sendIdxs", 2)); - std::vector< Kokkos::View > recvIdxs(1,Kokkos::View("recvIdxs", 2)); - + std::vector > sendIdxs(1, Kokkos::View("sendIdxs", 2)); + std::vector > recvIdxs(1, Kokkos::View("recvIdxs", 2)); + // create the FEMVectors - ippl::FEMVector a(n,neighbors, sendIdxs, recvIdxs); - - auto aView = a.getView(); + ippl::FEMVector a(n, neighbors, sendIdxs, recvIdxs); + + auto aView = a.getView(); auto haView = Kokkos::create_mirror_view(aView); for (size_t i = 0; i < n; ++i) { @@ -446,15 +435,14 @@ TEST(FEMVector, norm) { T val = norm(a); - EXPECT_EQ(val, Kokkos::sqrt(ippl::Comm->size()*1/6.*(n-1)*n*(2*n-1))); + EXPECT_EQ(val, Kokkos::sqrt(ippl::Comm->size() * 1 / 6. * (n - 1) * n * (2 * n - 1))); } - TEST(FEMVector, CG) { using T = double; - using CG_t = ippl::CG, ippl::FEMVector, ippl::FEMVector, - ippl::FEMVector, ippl::FEMVector, ippl::FEMVector, - ippl::FEMVector >; + using CG_t = + ippl::CG, ippl::FEMVector, ippl::FEMVector, ippl::FEMVector, + ippl::FEMVector, ippl::FEMVector, ippl::FEMVector >; ippl::ParameterList params; params.add("output_type", 0b01); @@ -462,27 +450,27 @@ TEST(FEMVector, CG) { params.add("tolerance", (T)1e-13); CG_t cg; - + // create the FEMVectors size_t n = 10; ippl::FEMVector a(n); ippl::FEMVector b(n); - auto aView = a.getView(); + auto aView = a.getView(); auto haView = Kokkos::create_mirror_view(aView); - auto bView = b.getView(); + auto bView = b.getView(); auto hbView = Kokkos::create_mirror_view(bView); // Identity operator - a = 0.; - b = 3.; + a = 0.; + b = 3.; const auto operatorId = [](ippl::FEMVector v) -> ippl::FEMVector { return v; }; cg.setOperator(operatorId); - cg(a,b,params); + cg(a, b, params); // check that every entry now is 3 - Kokkos::deep_copy (haView, aView); + Kokkos::deep_copy(haView, aView); for (size_t i = 0; i < n; ++i) { EXPECT_EQ(haView(i), 3.); } @@ -491,9 +479,9 @@ TEST(FEMVector, CG) { { std::vector bRef = {61, 33, 75, 15, 69, 12, 47, 19, 53, 11}; std::vector aRef = {5, 4, 5, 1, 5, 1, 2, 2, 5, 1}; - + std::vector matRef = { - // clang-format off + // clang-format off 10, -1, 3, 0, 0, 0, 0, 0, 0, 0, -1, 10, -1, 3, 0, 0, 0, 0, 0, 0, 3, -1, 10, -1, 3, 0, 0, 0, 0, 0, @@ -504,30 +492,28 @@ TEST(FEMVector, CG) { 0, 0, 0, 0, 0, 3, -1, 10, -1, 3, 0, 0, 0, 0, 0, 0, 3, -1, 10, -1, 0, 0, 0, 0, 0, 0, 0, 3, -1, 10 - // clang-format on + // clang-format on }; - - + for (size_t i = 0; i < n; ++i) { hbView(i) = bRef[i]; } Kokkos::deep_copy(bView, hbView); - const auto operatorTriDiagMat = [=](ippl::FEMVector v) -> ippl::FEMVector { ippl::FEMVector out(v.size(), std::vector(), - std::vector< Kokkos::View >(), - std::vector< Kokkos::View >()); - auto outView = out.getView(); + std::vector >(), + std::vector >()); + auto outView = out.getView(); auto hOutView = Kokkos::create_mirror_view(outView); - auto vView = v.getView(); + auto vView = v.getView(); auto hvView = Kokkos::create_mirror_view(vView); Kokkos::deep_copy(hvView, vView); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { - hOutView(i) += hvView(j) * matRef[i*n + j]; + hOutView(i) += hvView(j) * matRef[i * n + j]; } } @@ -537,85 +523,68 @@ TEST(FEMVector, CG) { }; a = 1.; cg.setOperator(operatorTriDiagMat); - cg(a,b,params); - + cg(a, b, params); - Kokkos::deep_copy (haView, aView); + Kokkos::deep_copy(haView, aView); for (size_t i = 0; i < n; ++i) { EXPECT_NEAR(haView(i), aRef[i], 1e-6); } } - // some random matrix { - std::vector bRef = {23.91243720168186, 28.76946440071826, 11.39405321895077, - 14.58146738148548, 54.46293935692246, 50.55020649187946, - -6.966599074336089, 25.08955228913931, 97.98346398457775, - 61.88726870993443}; + std::vector bRef = {23.91243720168186, 28.76946440071826, 11.39405321895077, + 14.58146738148548, 54.46293935692246, 50.55020649187946, + -6.966599074336089, 25.08955228913931, 97.98346398457775, + 61.88726870993443}; std::vector aRef = {2, 2, 2, 5, 3, 1, 3, 3, 4, 3}; - + std::vector matRef = { - 10.15274438556837, -1.575357090699566, - 0.1033530371385715, -0.8261284642500747, -0.8834242907511218, - 5.652017827163076, -0.1701548630577168, 0.4131148230083384, - 2.671939012710765, -1.245594008895713, -1.575357090699566, - 6.382713346688194, 3.241831081261847, -2.937913800842192, - 2.297035155593666, 1.98989341982756, -1.977299789149673, - 2.764215315196782, 2.095562987718326, - 2.578887104935028, 0.1033530371385715, 3.241831081261847, - 7.995771133671092, -6.356959260093841, 4.662112232835592, - 2.01755777428059, -1.221016215206041, 0.8489913292249818, - 0.8146275942084533, - 0.7835362745329846, -0.8261284642500747, -2.937913800842192, - -6.356959260093841, - 8.700380945624307, -3.062426877405789, -2.120980515110928, - 1.607962852195594, -2.671019775396403, - 2.175940086736792, -0.9615875754267607, -0.8834242907511218, - 2.297035155593666, 4.662112232835592, -3.062426877405789, - 8.533392427711236, 3.401747061032478, 0.1010267492617375, - 2.490997357340004, 0.1648513849035274, - 6.728741781669867, 5.652017827163076, 1.98989341982756, - 2.01755777428059, -2.120980515110928, 3.401747061032478, - 10.80609077728808, -3.017414496852657, 2.325793498580139, - 6.569789197749419, -1.126484910557991, -0.1701548630577168, - -1.977299789149673, -1.221016215206041, 1.607962852195594, - 0.1010267492617375, -3.017414496852657, - 6.654116621919533, -4.497004122281946, -3.137962038753028, - 0.1751244348932011, 0.4131148230083384, 2.764215315196782, - 0.8489913292249818, -2.671019775396403, 2.490997357340004, - 2.325793498580139, -4.497004122281946, 6.11956623484971, - 0.1886720675300253, 4.990282684279192, 2.671939012710765, - 2.095562987718326, 0.8146275942084525, 2.175940086736793, - 0.1648513849035272, 6.569789197749419, -3.137962038753028, - 0.1886720675300255, - 22.24697534370522, -3.754956817331048, -1.245594008895714, - 2.578887104935028, 0.7835362745329846, -0.9615875754267607, - 6.728741781669866, -1.126484910557992, 0.1751244348932012, - 4.990282684279193, -3.754956817331048, 14.30847110775968 - }; - - + 10.15274438556837, -1.575357090699566, 0.1033530371385715, -0.8261284642500747, + -0.8834242907511218, 5.652017827163076, -0.1701548630577168, 0.4131148230083384, + 2.671939012710765, -1.245594008895713, -1.575357090699566, 6.382713346688194, + 3.241831081261847, -2.937913800842192, 2.297035155593666, 1.98989341982756, + -1.977299789149673, 2.764215315196782, 2.095562987718326, 2.578887104935028, + 0.1033530371385715, 3.241831081261847, 7.995771133671092, -6.356959260093841, + 4.662112232835592, 2.01755777428059, -1.221016215206041, 0.8489913292249818, + 0.8146275942084533, 0.7835362745329846, -0.8261284642500747, -2.937913800842192, + -6.356959260093841, 8.700380945624307, -3.062426877405789, -2.120980515110928, + 1.607962852195594, -2.671019775396403, 2.175940086736792, -0.9615875754267607, + -0.8834242907511218, 2.297035155593666, 4.662112232835592, -3.062426877405789, + 8.533392427711236, 3.401747061032478, 0.1010267492617375, 2.490997357340004, + 0.1648513849035274, 6.728741781669867, 5.652017827163076, 1.98989341982756, + 2.01755777428059, -2.120980515110928, 3.401747061032478, 10.80609077728808, + -3.017414496852657, 2.325793498580139, 6.569789197749419, -1.126484910557991, + -0.1701548630577168, -1.977299789149673, -1.221016215206041, 1.607962852195594, + 0.1010267492617375, -3.017414496852657, 6.654116621919533, -4.497004122281946, + -3.137962038753028, 0.1751244348932011, 0.4131148230083384, 2.764215315196782, + 0.8489913292249818, -2.671019775396403, 2.490997357340004, 2.325793498580139, + -4.497004122281946, 6.11956623484971, 0.1886720675300253, 4.990282684279192, + 2.671939012710765, 2.095562987718326, 0.8146275942084525, 2.175940086736793, + 0.1648513849035272, 6.569789197749419, -3.137962038753028, 0.1886720675300255, + 22.24697534370522, -3.754956817331048, -1.245594008895714, 2.578887104935028, + 0.7835362745329846, -0.9615875754267607, 6.728741781669866, -1.126484910557992, + 0.1751244348932012, 4.990282684279193, -3.754956817331048, 14.30847110775968}; + for (size_t i = 0; i < n; ++i) { hbView(i) = bRef[i]; } Kokkos::deep_copy(bView, hbView); - const auto operatorRandMat = [=](ippl::FEMVector v) -> ippl::FEMVector { ippl::FEMVector out(v.size(), std::vector(), - std::vector< Kokkos::View >(), - std::vector< Kokkos::View >()); - auto outView = out.getView(); + std::vector >(), + std::vector >()); + auto outView = out.getView(); auto hOutView = Kokkos::create_mirror_view(outView); - auto vView = v.getView(); + auto vView = v.getView(); auto hvView = Kokkos::create_mirror_view(vView); Kokkos::deep_copy(hvView, vView); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { - hOutView(i) += hvView(j) * matRef[i*n + j]; + hOutView(i) += hvView(j) * matRef[i * n + j]; } } @@ -625,18 +594,15 @@ TEST(FEMVector, CG) { }; a = 1.; cg.setOperator(operatorRandMat); - cg(a,b,params); + cg(a, b, params); - - Kokkos::deep_copy (haView, aView); + Kokkos::deep_copy(haView, aView); for (size_t i = 0; i < n; ++i) { EXPECT_NEAR(haView(i), aRef[i], 1e-6); } } - } - int main(int argc, char* argv[]) { int success = 1; ippl::initialize(argc, argv); diff --git a/unit_tests/FEM/FiniteElementSpace.cpp b/unit_tests/FEM/FiniteElementSpace.cpp index 933f72ec1..05ee7dac1 100644 --- a/unit_tests/FEM/FiniteElementSpace.cpp +++ b/unit_tests/FEM/FiniteElementSpace.cpp @@ -16,7 +16,7 @@ class FiniteElementSpaceTest>> : public ::tes void SetUp() override {} public: - using value_t = T; + using value_t = T; static constexpr unsigned dim = Dim; static_assert(Dim == 1 || Dim == 2 || Dim == 3, "Dim must be 1, 2 or 3"); @@ -26,23 +26,22 @@ class FiniteElementSpaceTest>> : public ::tes Dim == 1, ippl::EdgeElement, std::conditional_t, ippl::HexahedralElement>>; - using QuadratureType = ippl::MidpointQuadrature; - using FieldType = ippl::Field; - using FieldLayoutType= ippl::FieldLayout; + using QuadratureType = ippl::MidpointQuadrature; + using FieldType = ippl::Field; + using FieldLayoutType = ippl::FieldLayout; // Initialize a 4x4 mesh with 1.0 spacing and 0.0 offset. // 4 nodes in each dimension, or 3 elements in each dimension - + FiniteElementSpaceTest() : rng(42) , meshSizes(4) , ref_element() , mesh(ippl::NDIndex(meshSizes), ippl::Vector(1.0), ippl::Vector(-1.0)) , quadrature(ref_element) - , layout(MPI_COMM_WORLD, ippl::NDIndex(ippl::Vector(4)), + , layout(MPI_COMM_WORLD, ippl::NDIndex(ippl::Vector(4)), std::array{true}) - , fem_space(mesh, ref_element, quadrature, layout) - {} + , fem_space(mesh, ref_element, quadrature, layout) {} std::mt19937 rng; @@ -81,8 +80,8 @@ TYPED_TEST(FiniteElementSpaceTest, numElementsInDim) { } TYPED_TEST(FiniteElementSpaceTest, getMeshVertexNDIndex) { - const auto& fem_space = this->fem_space; - const auto& meshSizes = this->meshSizes; + const auto& fem_space = this->fem_space; + const auto& meshSizes = this->meshSizes; static constexpr std::size_t dim = TestFixture::dim; // compute the number of vertices @@ -112,8 +111,8 @@ TYPED_TEST(FiniteElementSpaceTest, getMeshVertexNDIndex) { } TYPED_TEST(FiniteElementSpaceTest, getMeshVertexIndex) { - const auto& fem_space = this->fem_space; - const auto& meshSizes = this->meshSizes; + const auto& fem_space = this->fem_space; + const auto& meshSizes = this->meshSizes; static constexpr std::size_t dim = TestFixture::dim; // compute the number of vertices @@ -141,7 +140,7 @@ TYPED_TEST(FiniteElementSpaceTest, getMeshVertexIndex) { } TYPED_TEST(FiniteElementSpaceTest, getElementMeshVertexNDIndices) { - const auto& fem_space = this->fem_space; + const auto& fem_space = this->fem_space; static constexpr std::size_t dim = TestFixture::dim; if (dim == 1) { @@ -171,9 +170,9 @@ TYPED_TEST(FiniteElementSpaceTest, getElementMeshVertexNDIndices) { } TYPED_TEST(FiniteElementSpaceTest, getElementNDIndex) { - const auto& fem_space = this->fem_space; + const auto& fem_space = this->fem_space; static constexpr std::size_t dim = TestFixture::dim; - const std::size_t& numElements = fem_space.numElements(); + const std::size_t& numElements = fem_space.numElements(); std::vector> element_nd_indices(dim); @@ -207,9 +206,9 @@ TYPED_TEST(FiniteElementSpaceTest, getElementNDIndex) { } TYPED_TEST(FiniteElementSpaceTest, getElementIndex) { - const auto& fem_space = this->fem_space; + const auto& fem_space = this->fem_space; static constexpr std::size_t dim = TestFixture::dim; - const std::size_t& numElements = fem_space.numElements(); + const std::size_t& numElements = fem_space.numElements(); std::vector> element_nd_indices(numElements); @@ -235,7 +234,7 @@ TYPED_TEST(FiniteElementSpaceTest, getElementIndex) { } TYPED_TEST(FiniteElementSpaceTest, getElementMeshVertexIndices) { - const auto& fem_space = this->fem_space; + const auto& fem_space = this->fem_space; static constexpr std::size_t dim = TestFixture::dim; ippl::Vector elementNDIndex; @@ -433,7 +432,7 @@ TYPED_TEST(FiniteElementSpaceTest, getElementMeshVertexIndices) { } TYPED_TEST(FiniteElementSpaceTest, getElementMeshVertexPoints) { - const auto& fem_space = this->fem_space; + const auto& fem_space = this->fem_space; static constexpr std::size_t dim = TestFixture::dim; const auto element_ndindex = ippl::Vector(2); diff --git a/unit_tests/FEM/HexahedralElement.cpp b/unit_tests/FEM/HexahedralElement.cpp index 0af33fd0a..c1b847a8c 100644 --- a/unit_tests/FEM/HexahedralElement.cpp +++ b/unit_tests/FEM/HexahedralElement.cpp @@ -16,10 +16,9 @@ class HexahedralElementTest>> : public ::tes void SetUp() override {} public: - using value_t = T; - using point_t = typename ippl::HexahedralElement::point_t; - using vertex_points_t = - typename ippl::HexahedralElement::vertex_points_t; + using value_t = T; + using point_t = typename ippl::HexahedralElement::point_t; + using vertex_points_t = typename ippl::HexahedralElement::vertex_points_t; static constexpr unsigned NumHexs = 3; @@ -79,10 +78,10 @@ class HexahedralElementTest>> : public ::tes ippl::HexahedralElement hex_element; - const vertex_points_t local_points = { - {0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}, {1.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 1.0}}; - const point_t local_mid_point = {0.5, 0.5, 0.5}; + const vertex_points_t local_points = {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, + {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 1.0}, + {1.0, 1.0, 1.0}, {0.0, 1.0, 1.0}}; + const point_t local_mid_point = {0.5, 0.5, 0.5}; ippl::Vector hexs; }; diff --git a/unit_tests/FEM/InterpolateDiracs.cpp b/unit_tests/FEM/InterpolateDiracs.cpp index 6669a7aa0..eb2f4444d 100644 --- a/unit_tests/FEM/InterpolateDiracs.cpp +++ b/unit_tests/FEM/InterpolateDiracs.cpp @@ -1,10 +1,11 @@ #include "Ippl.h" -#include "TestUtils.h" -#include "gtest/gtest.h" +#include #include #include -#include + +#include "TestUtils.h" +#include "gtest/gtest.h" template struct Bunch : public ippl::ParticleBase { @@ -19,312 +20,316 @@ struct Bunch : public ippl::ParticleBase { charge_container_type Q; }; - -template struct ElemSelector; +template +struct ElemSelector; template struct ElemSelector<1, T> { - using Elem = ippl::EdgeElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + using Elem = ippl::EdgeElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; template struct ElemSelector<2, T> { - using Elem = ippl::QuadrilateralElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + using Elem = ippl::QuadrilateralElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; template struct ElemSelector<3, T> { - using Elem = ippl::HexahedralElement; - using Quad = ippl::MidpointQuadrature; - template - using Space = ippl::LagrangeSpace; - static Elem make_elem() { return Elem{}; } - static Quad make_quad(const Elem& e) { return Quad(e); } + using Elem = ippl::HexahedralElement; + using Quad = ippl::MidpointQuadrature; + template + using Space = ippl::LagrangeSpace; + static Elem make_elem() { return Elem{}; } + static Quad make_quad(const Elem& e) { return Quad(e); } }; -template class InterpTest; +template +class InterpTest; template class InterpTest>> : public ::testing::Test { public: - using value_type = T; - static constexpr unsigned dim = Dim; - - using Mesh_t = ippl::UniformCartesian; - using Centering_t = typename Mesh_t::DefaultCentering; - using field_t = ippl::Field; - using ElemSel = ElemSelector; - using Space = typename ElemSel::template Space; - - using playout_t = ippl::ParticleSpatialLayout; - using bunch_t = Bunch; - - static constexpr T tol() { - return std::numeric_limits::epsilon() * 10.0; - } - - static ippl::NDIndex make_owned_nd(int nx) { - ippl::Index I0(nx); - if constexpr (dim == 1) { - return ippl::NDIndex<1>(I0); - } else if constexpr (dim == 2) { - ippl::Index I1(nx); - return ippl::NDIndex<2>(I0, I1); - } else { - ippl::Index I1(nx), I2(nx); - return ippl::NDIndex<3>(I0, I1, I2); - } - } - - static ippl::FieldLayout make_layout(const ippl::NDIndex& owned) { - std::array par{}; par.fill(true); - return ippl::FieldLayout(MPI_COMM_WORLD, owned, par); - } - - static Mesh_t make_mesh(const ippl::NDIndex& owned, - const ippl::Vector& h, - const ippl::Vector& origin) { - return Mesh_t(owned, h, origin); - } - - static field_t make_zero_field(Mesh_t& mesh, - ippl::FieldLayout& layout) { - field_t f; - f.initialize(mesh, layout); - Kokkos::deep_copy(f.getView(), T(0)); - return f; - } - - static Space make_space(Mesh_t& mesh, ippl::FieldLayout& layout) { - auto elem = ElemSel::make_elem(); - auto quad = ElemSel::make_quad(elem); - return Space(mesh, elem, quad, layout); - } - - - template - static void set_field_from_function(field_t& coeffs, const Func& u) { - constexpr unsigned D = dim; - using exec_space = typename field_t::view_type::execution_space; - - auto view = coeffs.getView(); - auto M = coeffs.get_mesh(); - auto lDom = coeffs.getLayout().getLocalNDIndex(); - const int nghost = coeffs.getNghost(); - - ippl::Vector first = lDom.first(); - ippl::Vector last = lDom.last(); - ippl::Vector ext; - for (unsigned d=0; d size; // ext + 2*nghost per axis - for (unsigned d=0; d(0, size[0]), - KOKKOS_LAMBDA(const int i0) { - const int v0 = first[0] + (i0 - nghost); - ippl::Vector x; - x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); - view(size_t(i0)) = u(x); - }); - } else if constexpr (D == 2) { - Kokkos::parallel_for("fill_field_fun_2d", - Kokkos::MDRangePolicy, exec_space>({0,0}, {size[0], size[1]}), - KOKKOS_LAMBDA(const int i0, const int i1) { - const int v0 = first[0] + (i0 - nghost); - const int v1 = first[1] + (i1 - nghost); - ippl::Vector x; - x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); - x[1] = M.getOrigin()[1] + M.getMeshSpacing()[1] * T(v1); - view(size_t(i0), size_t(i1)) = u(x); - }); - } else { // D == 3 - Kokkos::parallel_for("fill_field_fun_3d", - Kokkos::MDRangePolicy, exec_space>({0,0,0}, {size[0], size[1], size[2]}), - KOKKOS_LAMBDA(const int i0, const int i1, const int i2) { - const int v0 = first[0] + (i0 - nghost); - const int v1 = first[1] + (i1 - nghost); - const int v2 = first[2] + (i2 - nghost); - ippl::Vector x; - x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); - x[1] = M.getOrigin()[1] + M.getMeshSpacing()[1] * T(v1); - x[2] = M.getOrigin()[2] + M.getMeshSpacing()[2] * T(v2); - view(size_t(i0), size_t(i1), size_t(i2)) = u(x); - }); + using value_type = T; + static constexpr unsigned dim = Dim; + + using Mesh_t = ippl::UniformCartesian; + using Centering_t = typename Mesh_t::DefaultCentering; + using field_t = ippl::Field; + using ElemSel = ElemSelector; + using Space = typename ElemSel::template Space; + + using playout_t = ippl::ParticleSpatialLayout; + using bunch_t = Bunch; + + static constexpr T tol() { return std::numeric_limits::epsilon() * 10.0; } + + static ippl::NDIndex make_owned_nd(int nx) { + ippl::Index I0(nx); + if constexpr (dim == 1) { + return ippl::NDIndex<1>(I0); + } else if constexpr (dim == 2) { + ippl::Index I1(nx); + return ippl::NDIndex<2>(I0, I1); + } else { + ippl::Index I1(nx), I2(nx); + return ippl::NDIndex<3>(I0, I1, I2); + } } - Kokkos::fence(); - } - - static void fill_field_constant(field_t& coeffs, T c) { - Kokkos::deep_copy(coeffs.getView(), c); - } + static ippl::FieldLayout make_layout(const ippl::NDIndex& owned) { + std::array par{}; + par.fill(true); + return ippl::FieldLayout(MPI_COMM_WORLD, owned, par); + } + static Mesh_t make_mesh(const ippl::NDIndex& owned, const ippl::Vector& h, + const ippl::Vector& origin) { + return Mesh_t(owned, h, origin); + } - // Create particles uniformly in the GLOBAL domain - static void fill_uniform_positions(bunch_t& bunch, int n_local, - const Mesh_t& M, - uint64_t seed = 4242) { - bunch.create(n_local); - std::mt19937_64 eng(seed + ippl::Comm->rank()); - auto R_host = bunch.R.getHostMirror(); + static field_t make_zero_field(Mesh_t& mesh, ippl::FieldLayout& layout) { + field_t f; + f.initialize(mesh, layout); + Kokkos::deep_copy(f.getView(), T(0)); + return f; + } - ippl::Vector xmin, xmax; - domain_bounds(M, xmin, xmax); + static Space make_space(Mesh_t& mesh, ippl::FieldLayout& layout) { + auto elem = ElemSel::make_elem(); + auto quad = ElemSel::make_quad(elem); + return Space(mesh, elem, quad, layout); + } - // small interior margin vs locator’s open upper bound - ippl::Vector h = M.getMeshSpacing(); + template + static void set_field_from_function(field_t& coeffs, const Func& u) { + constexpr unsigned D = dim; + using exec_space = typename field_t::view_type::execution_space; + + auto view = coeffs.getView(); + auto M = coeffs.get_mesh(); + auto lDom = coeffs.getLayout().getLocalNDIndex(); + const int nghost = coeffs.getNghost(); + + ippl::Vector first = lDom.first(); + ippl::Vector last = lDom.last(); + ippl::Vector ext; + for (unsigned d = 0; d < D; ++d) + ext[d] = last[d] - first[d] + 1; + + ippl::Vector size; // ext + 2*nghost per axis + for (unsigned d = 0; d < D; ++d) + size[d] = ext[d] + 2 * nghost; + + if constexpr (D == 1) { + Kokkos::parallel_for( + "fill_field_fun_1d", Kokkos::RangePolicy(0, size[0]), + KOKKOS_LAMBDA(const int i0) { + const int v0 = first[0] + (i0 - nghost); + ippl::Vector x; + x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); + view(size_t(i0)) = u(x); + }); + } else if constexpr (D == 2) { + Kokkos::parallel_for( + "fill_field_fun_2d", + Kokkos::MDRangePolicy, exec_space>({0, 0}, {size[0], size[1]}), + KOKKOS_LAMBDA(const int i0, const int i1) { + const int v0 = first[0] + (i0 - nghost); + const int v1 = first[1] + (i1 - nghost); + ippl::Vector x; + x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); + x[1] = M.getOrigin()[1] + M.getMeshSpacing()[1] * T(v1); + view(size_t(i0), size_t(i1)) = u(x); + }); + } else { // D == 3 + Kokkos::parallel_for( + "fill_field_fun_3d", + Kokkos::MDRangePolicy, exec_space>({0, 0, 0}, + {size[0], size[1], size[2]}), + KOKKOS_LAMBDA(const int i0, const int i1, const int i2) { + const int v0 = first[0] + (i0 - nghost); + const int v1 = first[1] + (i1 - nghost); + const int v2 = first[2] + (i2 - nghost); + ippl::Vector x; + x[0] = M.getOrigin()[0] + M.getMeshSpacing()[0] * T(v0); + x[1] = M.getOrigin()[1] + M.getMeshSpacing()[1] * T(v1); + x[2] = M.getOrigin()[2] + M.getMeshSpacing()[2] * T(v2); + view(size_t(i0), size_t(i1), size_t(i2)) = u(x); + }); + } + + Kokkos::fence(); + } - for (int i=0; i r{}; - for (unsigned d=0; d pd(xmin[d] + 3 * h[d], xmax[d] - 3 * h[d]); - r[d] = pd(eng); - } - R_host(i) = r; + static void fill_field_constant(field_t& coeffs, T c) { + Kokkos::deep_copy(coeffs.getView(), c); } - Kokkos::deep_copy(bunch.R.getView(), R_host); - bunch.update(); // migrate to owning ranks - } - - static void domain_bounds(const Mesh_t& M, - ippl::Vector& xmin, - ippl::Vector& xmax) { - const auto org = M.getOrigin(); - const auto h = M.getMeshSpacing(); - const auto nr = M.getGridsize(); - for (unsigned d=0; drank()); + auto R_host = bunch.R.getHostMirror(); + + ippl::Vector xmin, xmax; + domain_bounds(M, xmin, xmax); + + // small interior margin vs locator’s open upper bound + ippl::Vector h = M.getMeshSpacing(); + + for (int i = 0; i < n_local; ++i) { + ippl::Vector r{}; + for (unsigned d = 0; d < dim; ++d) { + std::uniform_real_distribution pd(xmin[d] + 3 * h[d], xmax[d] - 3 * h[d]); + r[d] = pd(eng); + } + R_host(i) = r; + } + Kokkos::deep_copy(bunch.R.getView(), R_host); + bunch.update(); // migrate to owning ranks } - } - static double mpi_max(double x) { - double g = 0.0; - MPI_Allreduce(&x, &g, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); - return g; - } + static void domain_bounds(const Mesh_t& M, ippl::Vector& xmin, + ippl::Vector& xmax) { + const auto org = M.getOrigin(); + const auto h = M.getMeshSpacing(); + const auto nr = M.getGridsize(); + for (unsigned d = 0; d < dim; ++d) { + xmin[d] = org[d]; + xmax[d] = org[d] + h[d] * T(nr[d] - 1); + } + } + static double mpi_max(double x) { + double g = 0.0; + MPI_Allreduce(&x, &g, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + return g; + } }; using Precisions = TestParams::Precisions; -using Ranks = TestParams::Ranks<1,2,3>; +using Ranks = TestParams::Ranks<1, 2, 3>; using Tests = TestForTypes::type>::type; TYPED_TEST_SUITE(InterpTest, Tests); template void InterpolatesAffineExactly() { - using T = typename TestFixture::value_type; - constexpr unsigned Dim = TestFixture::dim; - using field_t = typename TestFixture::field_t; - using exec_space = typename field_t::view_type::execution_space; - using playout_t = typename TestFixture::playout_t; - using bunch_t = typename TestFixture::bunch_t; - - // Fixed, arbitrary choice of origin and spacing - const int nx = 10; - ippl::Vector origin, h; - for (unsigned d=0; d a; - for (unsigned d=0; d& x) -> T { - T s = c; - for (unsigned d=0; d(0, bunch.getLocalNum()); - Kokkos::deep_copy(bunch.Q.getView(), T(0)); - ippl::interpolate_to_diracs(bunch.Q, coeffs, bunch.R, space, policy); - - auto d_pos = bunch.R.getView(); - auto d_out = bunch.Q.getView(); - - double max_err = 0.0, max_ref = 0.0; - Kokkos::parallel_reduce("interp_affine_err", policy, - KOKKOS_LAMBDA(const int p, double& lmax) { - const T exact = u(d_pos(p)); - const T err = Kokkos::fabs(d_out(p) - exact); - if (double(err) > lmax) lmax = double(err); - }, Kokkos::Max(max_err)); - - Kokkos::parallel_reduce("interp_affine_ref", policy, - KOKKOS_LAMBDA(const int p, double& lmax) { - const T exact = u(d_pos(p)); - const double ref = std::abs(double(exact)); - if (ref > lmax) lmax = ref; - }, Kokkos::Max(max_ref)); + using T = typename TestFixture::value_type; + constexpr unsigned Dim = TestFixture::dim; + using field_t = typename TestFixture::field_t; + using exec_space = typename field_t::view_type::execution_space; + using playout_t = typename TestFixture::playout_t; + using bunch_t = typename TestFixture::bunch_t; + + // Fixed, arbitrary choice of origin and spacing + const int nx = 10; + ippl::Vector origin, h; + for (unsigned d = 0; d < Dim; ++d) { + origin[d] = T(-0.7 + 0.11 * d); + h[d] = T(0.31 + 0.07 * d); + } + + auto owned = TestFixture::make_owned_nd(nx); + auto layout = TestFixture::make_layout(owned); + auto mesh = TestFixture::make_mesh(owned, h, origin); + + // analytic affine function u(x) = c + sum a_d * x[d] + const T c = T(10.0); + ippl::Vector a; + for (unsigned d = 0; d < Dim; ++d) { + a[d] = T(0.21 + 0.1 * d); + } + + auto u = KOKKOS_LAMBDA(const ippl::Vector& x)->T { + T s = c; + for (unsigned d = 0; d < Dim; ++d) + s += a[d] * x[d]; + return s; + }; + + auto coeffs = TestFixture::make_zero_field(mesh, layout); + TestFixture::set_field_from_function(coeffs, u); + + auto view = coeffs.getView(); + + auto space = TestFixture::make_space(mesh, layout); + + playout_t playout(layout, mesh); + bunch_t bunch(playout); + + const int n_local = 1000; + TestFixture::fill_uniform_positions(bunch, n_local, mesh, /*seed=*/42); + + auto policy = Kokkos::RangePolicy(0, bunch.getLocalNum()); + Kokkos::deep_copy(bunch.Q.getView(), T(0)); + ippl::interpolate_to_diracs(bunch.Q, coeffs, bunch.R, space, policy); + + auto d_pos = bunch.R.getView(); + auto d_out = bunch.Q.getView(); + + double max_err = 0.0, max_ref = 0.0; + Kokkos::parallel_reduce( + "interp_affine_err", policy, + KOKKOS_LAMBDA(const int p, double& lmax) { + const T exact = u(d_pos(p)); + const T err = Kokkos::fabs(d_out(p) - exact); + if (double(err) > lmax) + lmax = double(err); + }, + Kokkos::Max(max_err)); + + Kokkos::parallel_reduce( + "interp_affine_ref", policy, + KOKKOS_LAMBDA(const int p, double& lmax) { + const T exact = u(d_pos(p)); + const double ref = std::abs(double(exact)); + if (ref > lmax) + lmax = ref; + }, + Kokkos::Max(max_ref)); // global (MPI) max across ranks - const double g_err = TestFixture::mpi_max(max_err); - const double g_ref = TestFixture::mpi_max(max_ref); - - // combined abs+rel tolerance based on fixture tol() - const double abs_tol = static_cast(TestFixture::tol()); - const double rel_tol = static_cast(TestFixture::tol()); - const double allow = abs_tol + rel_tol * g_ref; - - EXPECT_LE(g_err, allow) - << "Interpolation error too large for affine function over global domain:\n" - << " max |u_h(x_p) - u(x_p)| = " << g_err << "\n" - << " ref scale max|u(x_p)| = " << g_ref << "\n" - << " allowed (abs+rel) = " << allow - << " (abs_tol=" << abs_tol << ", rel_tol*ref=" << rel_tol * g_ref << ")"; - - std::cout << max_err << std::endl; + const double g_err = TestFixture::mpi_max(max_err); + const double g_ref = TestFixture::mpi_max(max_ref); + + // combined abs+rel tolerance based on fixture tol() + const double abs_tol = static_cast(TestFixture::tol()); + const double rel_tol = static_cast(TestFixture::tol()); + const double allow = abs_tol + rel_tol * g_ref; + + EXPECT_LE(g_err, allow) + << "Interpolation error too large for affine function over global domain:\n" + << " max |u_h(x_p) - u(x_p)| = " << g_err << "\n" + << " ref scale max|u(x_p)| = " << g_ref << "\n" + << " allowed (abs+rel) = " << allow << " (abs_tol=" << abs_tol + << ", rel_tol*ref=" << rel_tol * g_ref << ")"; + + std::cout << max_err << std::endl; } TYPED_TEST(InterpTest, InterpolatesAffineExactly) { - InterpolatesAffineExactly(); + InterpolatesAffineExactly(); } int main(int argc, char* argv[]) { - ippl::initialize(argc, argv); - int result = 0; - { - ::testing::InitGoogleTest(&argc, argv); - result = RUN_ALL_TESTS(); - } - ippl::finalize(); - return result; + ippl::initialize(argc, argv); + int result = 0; + { + ::testing::InitGoogleTest(&argc, argv); + result = RUN_ALL_TESTS(); + } + ippl::finalize(); + return result; } diff --git a/unit_tests/FEM/LagrangeSpace.cpp b/unit_tests/FEM/LagrangeSpace.cpp index c9dd65c64..51d14e24b 100644 --- a/unit_tests/FEM/LagrangeSpace.cpp +++ b/unit_tests/FEM/LagrangeSpace.cpp @@ -19,8 +19,9 @@ struct EvalFunctor { : DPhiInvT(DPhiInvT) , absDetDPhi(absDetDPhi) {} - KOKKOS_FUNCTION auto operator()(const size_t& i, const size_t& j, - const ippl::Vector, numElemDOFs>& grad_b_q_k) const { + KOKKOS_FUNCTION auto operator()( + const size_t& i, const size_t& j, + const ippl::Vector, numElemDOFs>& grad_b_q_k) const { return dot((DPhiInvT * grad_b_q_k[j]), (DPhiInvT * grad_b_q_k[i])).apply() * absDetDPhi; } }; @@ -31,7 +32,7 @@ class LagrangeSpaceTest, Rank>> : publ void SetUp() override {} public: - using value_t = T; + using value_t = T; static constexpr unsigned dim = Dim; static_assert(Dim == 1 || Dim == 2 || Dim == 3, "Dim must be 1, 2 or 3"); @@ -45,11 +46,13 @@ class LagrangeSpaceTest, Rank>> : publ using BetterQuadratureType = ippl::GaussLegendreQuadrature; using FieldType = ippl::Field; using BCType = ippl::BConds; - - using FieldLayoutType = ippl::FieldLayout; - using LagrangeType = ippl::LagrangeSpace; - using LagrangeTypeBetter = ippl::LagrangeSpace; + using FieldLayoutType = ippl::FieldLayout; + + using LagrangeType = + ippl::LagrangeSpace; + using LagrangeTypeBetter = + ippl::LagrangeSpace; LagrangeSpaceTest() : ref_element() @@ -66,12 +69,9 @@ class LagrangeSpaceTest, Rank>> : publ , layout_bigger(MPI_COMM_WORLD, ippl::NDIndex(ippl::Vector(5)), std::array{true}) , lagrangeSpace(mesh, ref_element, quadrature, layout) - , lagrangeSpaceBigger( - biggerMesh, ref_element, quadrature, layout_bigger) - , symmetricLagrangeSpace( - symmetricMesh, ref_element, betterQuadrature, layout_bigger) - {} - // fill the global reference DOFs + , lagrangeSpaceBigger(biggerMesh, ref_element, quadrature, layout_bigger) + , symmetricLagrangeSpace(symmetricMesh, ref_element, betterQuadrature, layout_bigger) {} + // fill the global reference DOFs ElementType ref_element; MeshType mesh; @@ -382,10 +382,10 @@ TYPED_TEST(LagrangeSpaceTest, getGlobalDOFIndices) { } TYPED_TEST(LagrangeSpaceTest, evaluateRefElementShapeFunction) { - auto& lagrangeSpace = this->lagrangeSpace; + auto& lagrangeSpace = this->lagrangeSpace; static constexpr std::size_t dim = TestFixture::dim; - const std::size_t& order = lagrangeSpace.order; - using T = typename TestFixture::value_t; + const std::size_t& order = lagrangeSpace.order; + using T = typename TestFixture::value_t; T tolerance = std::numeric_limits::epsilon() * 10.0; @@ -448,10 +448,10 @@ TYPED_TEST(LagrangeSpaceTest, evaluateRefElementShapeFunction) { } TYPED_TEST(LagrangeSpaceTest, evaluateRefElementShapeFunctionGradient) { - auto& lagrangeSpace = this->lagrangeSpace; + auto& lagrangeSpace = this->lagrangeSpace; static constexpr std::size_t dim = TestFixture::dim; - const std::size_t& order = lagrangeSpace.order; - using T = typename TestFixture::value_t; + const std::size_t& order = lagrangeSpace.order; + using T = typename TestFixture::value_t; T tolerance = 1e-7; @@ -562,21 +562,20 @@ TYPED_TEST(LagrangeSpaceTest, evaluateRefElementShapeFunctionGradient) { } TYPED_TEST(LagrangeSpaceTest, evaluateAx) { - using T = typename TestFixture::value_t; - using FieldType = typename TestFixture::FieldType; - using BCType = typename TestFixture::BCType; + using T = typename TestFixture::value_t; + using FieldType = typename TestFixture::FieldType; + using BCType = typename TestFixture::BCType; using LagrangeType = typename TestFixture::LagrangeType; const auto& refElement = this->ref_element; - auto& lagrangeSpace = this->lagrangeSpaceBigger; + auto& lagrangeSpace = this->lagrangeSpaceBigger; auto mesh = this->biggerMesh; static constexpr std::size_t dim = TestFixture::dim; const std::size_t& order = lagrangeSpace.order; if (order == 1) { // create layout - ippl::NDIndex domain( - ippl::Vector(mesh.getGridsize(0))); + ippl::NDIndex domain(ippl::Vector(mesh.getGridsize(0))); // specifies decomposition; here all dimensions are parallel std::array isParallel; @@ -597,13 +596,11 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { // 1. Define the eval function for the evaluateAx function - const ippl::Vector zeroNdIndex = - ippl::Vector(0); + const ippl::Vector zeroNdIndex = ippl::Vector(0); // Inverse Transpose Transformation Jacobian - const ippl::Vector DPhiInvT = - refElement.getInverseTransposeTransformationJacobian( - lagrangeSpace.getElementMeshVertexPoints(zeroNdIndex)); + const ippl::Vector DPhiInvT = refElement.getInverseTransposeTransformationJacobian( + lagrangeSpace.getElementMeshVertexPoints(zeroNdIndex)); // Absolute value of det Phi_K const T absDetDPhi = std::abs(refElement.getDeterminantOfTransformationJacobian( @@ -627,7 +624,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -637,7 +634,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { // We don't take into account nghost as this causes // coords to be negative, which causes an overflow due // to the index type. - // All below indices for setting the ref_field are + // All below indices for setting the ref_field are // shifted by 1 to include the ghost (applies to all tests). for (unsigned int d = 0; d < lagrangeSpace.dim; ++d) { coords[d] += ldom[d].first(); @@ -655,7 +652,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { Kokkos::deep_copy(view_ref, mirror); // compare values with reference - z = z - ref_field; + z = z - ref_field; double err = ippl::norm(z); ASSERT_NEAR(err, 0.0, 1e-6); @@ -675,7 +672,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -685,17 +682,17 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { for (unsigned int d = 0; d < lagrangeSpace.dim; ++d) { coords[d] += ldom[d].first(); } - + // reference field - if (((coords[0] == 2) && (coords[1] == 2)) || - ((coords[0] == 2) && (coords[1] == 4)) || - ((coords[0] == 4) && (coords[1] == 2)) || - ((coords[0] == 4) && (coords[1] == 4))) { + if (((coords[0] == 2) && (coords[1] == 2)) + || ((coords[0] == 2) && (coords[1] == 4)) + || ((coords[0] == 4) && (coords[1] == 2)) + || ((coords[0] == 4) && (coords[1] == 4))) { mirror(args...) = 1.5; - } else if (((coords[0] == 2) && (coords[1] == 3)) || - ((coords[0] == 3) && (coords[1] == 2)) || - ((coords[0] == 3) && (coords[1] == 4)) || - ((coords[0] == 4) && (coords[1] == 3))) { + } else if (((coords[0] == 2) && (coords[1] == 3)) + || ((coords[0] == 3) && (coords[1] == 2)) + || ((coords[0] == 3) && (coords[1] == 4)) + || ((coords[0] == 4) && (coords[1] == 3))) { mirror(args...) = 1.0; } else { mirror(args...) = 0.0; @@ -706,7 +703,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { Kokkos::deep_copy(view_ref, mirror); // compare values with reference - z = z - ref_field; + z = z - ref_field; double err = ippl::norm(z); ASSERT_NEAR(err, 0.0, 1e-6); @@ -726,7 +723,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -738,25 +735,23 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { } // reference field - if (((coords[0] > 1) && (coords[0] < 5)) && - ((coords[1] > 1) && (coords[1] < 5)) && - ((coords[2] > 1) && (coords[2] < 5))) { - + if (((coords[0] > 1) && (coords[0] < 5)) && ((coords[1] > 1) && (coords[1] < 5)) + && ((coords[2] > 1) && (coords[2] < 5))) { mirror(args...) = 2.53125; - + if ((coords[0] == 3) || (coords[1] == 3) || (coords[2] == 3)) { mirror(args...) = 2.25; } - if (((coords[0] == 3) && (coords[1] == 3) && (coords[2] == 2)) || - ((coords[0] == 3) && (coords[1] == 2) && (coords[2] == 3)) || - ((coords[0] == 2) && (coords[1] == 3) && (coords[2] == 3)) || - ((coords[0] == 4) && (coords[1] == 3) && (coords[2] == 3)) || - ((coords[0] == 3) && (coords[1] == 4) && (coords[2] == 3)) || - ((coords[0] == 3) && (coords[1] == 3) && (coords[2] == 4))) { + if (((coords[0] == 3) && (coords[1] == 3) && (coords[2] == 2)) + || ((coords[0] == 3) && (coords[1] == 2) && (coords[2] == 3)) + || ((coords[0] == 2) && (coords[1] == 3) && (coords[2] == 3)) + || ((coords[0] == 4) && (coords[1] == 3) && (coords[2] == 3)) + || ((coords[0] == 3) && (coords[1] == 4) && (coords[2] == 3)) + || ((coords[0] == 3) && (coords[1] == 3) && (coords[2] == 4))) { mirror(args...) = 1.5; } - + if ((coords[0] == 3) && (coords[1] == 3) && (coords[2] == 3)) { mirror(args...) = 0.0; } @@ -769,7 +764,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateAx) { Kokkos::deep_copy(view_ref, mirror); // compare values with reference - z = z - ref_field; + z = z - ref_field; double err = ippl::norm(z); ASSERT_NEAR(err, 0.0, 1e-6); @@ -787,16 +782,14 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { using FieldType = typename TestFixture::FieldType; using BCType = typename TestFixture::BCType; - const auto& lagrangeSpace = this->symmetricLagrangeSpace; - auto mesh = this->symmetricMesh; + const auto& lagrangeSpace = this->symmetricLagrangeSpace; + auto mesh = this->symmetricMesh; static constexpr std::size_t dim = TestFixture::dim; - const std::size_t& order = lagrangeSpace.order; + const std::size_t& order = lagrangeSpace.order; if (order == 1) { - // initialize the RHS field - ippl::NDIndex domain( - ippl::Vector(mesh.getGridsize(0))); + ippl::NDIndex domain(ippl::Vector(mesh.getGridsize(0))); // specifies decomposition; here all dimensions are parallel std::array isParallel; @@ -826,7 +819,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -879,7 +872,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -891,8 +884,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { } // reference field - if ((coords[0] < 2) || (coords[1] < 2) || - (coords[0] > 4) || (coords[1] > 4)) { + if ((coords[0] < 2) || (coords[1] < 2) || (coords[0] > 4) || (coords[1] > 4)) { mirror(args...) = 0.0; } else { mirror(args...) = 0.875; @@ -909,7 +901,6 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { ASSERT_NEAR(err, 0.0, 1e-6); } else if constexpr (dim == 3) { - rhs_field = 1.25; // call evaluateLoadVector @@ -921,7 +912,7 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { auto view_ref = ref_field.getView(); auto mirror = Kokkos::create_mirror_view(view_ref); - auto ldom = layout.getLocalNDIndex(); + auto ldom = layout.getLocalNDIndex(); nestedViewLoop(mirror, 0, [&](const Idx... args) { using index_type = std::tuple_element_t<0, std::tuple>; @@ -933,8 +924,8 @@ TYPED_TEST(LagrangeSpaceTest, evaluateLoadVector) { } // reference field - if ((coords[0] == 1) || (coords[1] == 1) || (coords[2] == 1) || - (coords[0] == 5) || (coords[1] == 5) || (coords[2] == 5)) { + if ((coords[0] == 1) || (coords[1] == 1) || (coords[2] == 1) || (coords[0] == 5) + || (coords[1] == 5) || (coords[2] == 5)) { mirror(args...) = 0.0; } else { mirror(args...) = 0.15625; diff --git a/unit_tests/FEM/LocateElement.cpp b/unit_tests/FEM/LocateElement.cpp index 0709bc6fd..f14753e95 100644 --- a/unit_tests/FEM/LocateElement.cpp +++ b/unit_tests/FEM/LocateElement.cpp @@ -1,32 +1,29 @@ #include "Ippl.h" -#include "TestUtils.h" +#include "TestUtils.h" #include "gtest/gtest.h" - template struct MeshStub { - ippl::Vector nr; // vertices per axis - ippl::Vector h; // spacing - ippl::Vector org; // origin + ippl::Vector nr; // vertices per axis + ippl::Vector h; // spacing + ippl::Vector org; // origin - KOKKOS_INLINE_FUNCTION ippl::Vector getGridsize() const { return nr; } - KOKKOS_INLINE_FUNCTION ippl::Vector getMeshSpacing() const { return h; } - KOKKOS_INLINE_FUNCTION ippl::Vector getOrigin() const { return org; } + KOKKOS_INLINE_FUNCTION ippl::Vector getGridsize() const { return nr; } + KOKKOS_INLINE_FUNCTION ippl::Vector getMeshSpacing() const { return h; } + KOKKOS_INLINE_FUNCTION ippl::Vector getOrigin() const { return org; } }; -template +template class LocateElementTest; template class LocateElementTest>> : public ::testing::Test { public: - using value_type = T; + using value_type = T; static constexpr unsigned dim = Dim; - static constexpr T tol() { - return std::numeric_limits::epsilon() * 10.0; - } + static constexpr T tol() { return std::numeric_limits::epsilon() * 10.0; } }; using Precisions = TestParams::Precisions; @@ -36,51 +33,48 @@ using Tests = TestForTypes::type>::ty TYPED_TEST_SUITE(LocateElementTest, Tests); TYPED_TEST(LocateElementTest, DeterministicPoints) { - using T = typename TestFixture::value_type; + using T = typename TestFixture::value_type; constexpr unsigned Dim = TestFixture::dim; - - MeshStub M{}; + MeshStub M{}; // Fixed, arbitrary choice of origin, spacing and number of vertices - for (unsigned d=0; d s1, s2, x1, x2; - for (unsigned d=0; d s1, s2, x1, x2; + for (unsigned d = 0; d < Dim; ++d) { s1[d] = T(1) + T(0.25); - s2[d] = T(2) + T(0.75); + s2[d] = T(2) + T(0.75); } - for (unsigned d=0; d e_nd{}; - ippl::Vector xi{}; + ippl::Vector e_nd{}; + ippl::Vector xi{}; - ippl::locate_element_nd_and_xi(M.h, M.org, x1, e_nd, xi); + ippl::locate_element_nd_and_xi(M.h, M.org, x1, e_nd, xi); - for (unsigned d=0; d(M.h, M.org, x2, e_nd, xi); - for (unsigned d=0; d(M.h, M.org, x2, e_nd, xi); + for (unsigned d = 0; d < Dim; ++d) { + EXPECT_EQ(e_nd[d], size_t(2)); + EXPECT_NEAR(xi[d], T(0.75), TestFixture::tol()); } } - int main(int argc, char* argv[]) { int success = 1; ippl::initialize(argc, argv); diff --git a/unit_tests/FEM/NedelecSpace.cpp b/unit_tests/FEM/NedelecSpace.cpp index b89253954..dc8a51707 100644 --- a/unit_tests/FEM/NedelecSpace.cpp +++ b/unit_tests/FEM/NedelecSpace.cpp @@ -5,16 +5,17 @@ #include "TestUtils.h" #include "gtest/gtest.h" - template class NedelecSpaceTest; template struct DummyFunctor { - KOKKOS_FUNCTION const T operator()(size_t i, size_t j, + KOKKOS_FUNCTION const T operator()( + size_t i, size_t j, [[maybe_unused]] const ippl::Vector, numElementDOFs>& curl_b_q_k, - [[maybe_unused]] const ippl::Vector, numElementDOFs>& val_b_q_k) const { - return i==j; //val_b_q_k<:i:>.dot(val_b_q_k<:j:>); + [[maybe_unused]] const ippl::Vector, numElementDOFs>& val_b_q_k) + const { + return i == j; // val_b_q_k<:i:>.dot(val_b_q_k<:j:>); } }; @@ -24,36 +25,36 @@ class NedelecSpaceTest, Rank>> : public ::testing void SetUp() override {} public: - using value_t = T; + using value_t = T; static constexpr unsigned dim = Dim; static_assert(Dim == 2 || Dim == 3, "Dim must be 2 or 3"); static_assert(Order == 1, "Currently only order 1 is supported"); using MeshType = ippl::UniformCartesian; - using ElementType = std::conditional_t, - std::conditional_t, - ippl::HexahedralElement>>; + using ElementType = std::conditional_t< + Dim == 1, ippl::EdgeElement, + std::conditional_t, ippl::HexahedralElement>>; using QuadratureType = ippl::GaussJacobiQuadrature; - using FieldType = ippl::Field; - using BCType = ippl::BConds; - using Layout = ippl::FieldLayout; + using FieldType = ippl::Field; + using BCType = ippl::BConds; + using Layout = ippl::FieldLayout; using NedelecType = ippl::NedelecSpace; NedelecSpaceTest() : ref_element() - , mesh(ippl::NDIndex(ippl::Vector(5)), - ippl::Vector(1.0), ippl::Vector(0.0)) - , meshSmall(ippl::NDIndex(ippl::Vector(3)), - ippl::Vector(1.0), ippl::Vector(0.0)) + , mesh(ippl::NDIndex(ippl::Vector(5)), ippl::Vector(1.0), + ippl::Vector(0.0)) + , meshSmall(ippl::NDIndex(ippl::Vector(3)), ippl::Vector(1.0), + ippl::Vector(0.0)) , quadrature(ref_element, 0.0, 0.0) , layout(MPI_COMM_WORLD, ippl::NDIndex(ippl::Vector(5)), - std::array{true}) + std::array{true}) , layoutSmall(MPI_COMM_WORLD, ippl::NDIndex(ippl::Vector(3)), - std::array{true}) - , nedelecSpace(mesh, ref_element, quadrature,layout) + std::array{true}) + , nedelecSpace(mesh, ref_element, quadrature, layout) , nedelecSpaceSmall(meshSmall, ref_element, quadrature, layoutSmall) { // fill the global reference DOFs } @@ -68,8 +69,6 @@ class NedelecSpaceTest, Rank>> : public ::testing const NedelecType nedelecSpaceSmall; }; - - using Precisions = TestParams::Precisions; using Orders = TestParams::Ranks<1>; using Dimensions = TestParams::Ranks<2, 3>; @@ -77,62 +76,59 @@ using Combos = CreateCombinations::type; using Tests = TestForTypes::type; TYPED_TEST_CASE(NedelecSpaceTest, Tests); - TYPED_TEST(NedelecSpaceTest, numLocalDOFS) { - const auto& nedelecSpace = this->nedelecSpace; - int numElementDOFs = nedelecSpace.numElementDOFs; - static constexpr std::size_t dim = TestFixture::dim; - - if (dim == 2) { - EXPECT_EQ(numElementDOFs, 4); - } else{ - EXPECT_EQ(numElementDOFs, 12); - } + const auto& nedelecSpace = this->nedelecSpace; + int numElementDOFs = nedelecSpace.numElementDOFs; + static constexpr std::size_t dim = TestFixture::dim; + + if (dim == 2) { + EXPECT_EQ(numElementDOFs, 4); + } else { + EXPECT_EQ(numElementDOFs, 12); + } } TYPED_TEST(NedelecSpaceTest, numGlobalDOFs) { static constexpr std::size_t dim = TestFixture::dim; if (dim == 2) { - EXPECT_EQ(this->nedelecSpace.numGlobalDOFs(), 40); - } else{ - EXPECT_EQ(this->nedelecSpace.numGlobalDOFs(), 300); + EXPECT_EQ(this->nedelecSpace.numGlobalDOFs(), 40); + } else { + EXPECT_EQ(this->nedelecSpace.numGlobalDOFs(), 300); } - } - +} TYPED_TEST(NedelecSpaceTest, getGlobalDOFIndices) { - // Here we just check some random element and see if it is equivalent to a handcrafted one, - // probably the simplest way of doing this. - static constexpr std::size_t dim = TestFixture::dim; - - if (dim == 2) { - auto idxSet = this->nedelecSpace.getGlobalDOFIndices(3); - EXPECT_EQ(idxSet[0],3); - EXPECT_EQ(idxSet[1],7); - EXPECT_EQ(idxSet[2],12); - EXPECT_EQ(idxSet[3],8); - - idxSet = this->nedelecSpace.getGlobalDOFIndices(15); - EXPECT_EQ(idxSet[0],30); - EXPECT_EQ(idxSet[1],34); - EXPECT_EQ(idxSet[2],39); - EXPECT_EQ(idxSet[3],35); - } else if (dim == 3) { - auto idxSet = this->nedelecSpaceSmall.getGlobalDOFIndices(7); - EXPECT_EQ(idxSet[0], 27); - EXPECT_EQ(idxSet[1], 29); - EXPECT_EQ(idxSet[2], 32); - EXPECT_EQ(idxSet[3], 30); - EXPECT_EQ(idxSet[4], 37); - EXPECT_EQ(idxSet[5], 38); - EXPECT_EQ(idxSet[6], 41); - EXPECT_EQ(idxSet[7], 40); - EXPECT_EQ(idxSet[8], 48); - EXPECT_EQ(idxSet[9], 50); - EXPECT_EQ(idxSet[10],53); - EXPECT_EQ(idxSet[11],51); - } + // Here we just check some random element and see if it is equivalent to a handcrafted one, + // probably the simplest way of doing this. + static constexpr std::size_t dim = TestFixture::dim; + if (dim == 2) { + auto idxSet = this->nedelecSpace.getGlobalDOFIndices(3); + EXPECT_EQ(idxSet[0], 3); + EXPECT_EQ(idxSet[1], 7); + EXPECT_EQ(idxSet[2], 12); + EXPECT_EQ(idxSet[3], 8); + + idxSet = this->nedelecSpace.getGlobalDOFIndices(15); + EXPECT_EQ(idxSet[0], 30); + EXPECT_EQ(idxSet[1], 34); + EXPECT_EQ(idxSet[2], 39); + EXPECT_EQ(idxSet[3], 35); + } else if (dim == 3) { + auto idxSet = this->nedelecSpaceSmall.getGlobalDOFIndices(7); + EXPECT_EQ(idxSet[0], 27); + EXPECT_EQ(idxSet[1], 29); + EXPECT_EQ(idxSet[2], 32); + EXPECT_EQ(idxSet[3], 30); + EXPECT_EQ(idxSet[4], 37); + EXPECT_EQ(idxSet[5], 38); + EXPECT_EQ(idxSet[6], 41); + EXPECT_EQ(idxSet[7], 40); + EXPECT_EQ(idxSet[8], 48); + EXPECT_EQ(idxSet[9], 50); + EXPECT_EQ(idxSet[10], 53); + EXPECT_EQ(idxSet[11], 51); + } } TYPED_TEST(NedelecSpaceTest, isDOFOnBoundary) { @@ -160,7 +156,6 @@ TYPED_TEST(NedelecSpaceTest, isDOFOnBoundary) { EXPECT_TRUE(this->nedelecSpace.isDOFOnBoundary(26)); EXPECT_TRUE(this->nedelecSpace.isDOFOnBoundary(35)); - // check the ones which are false EXPECT_FALSE(this->nedelecSpace.isDOFOnBoundary(5)); EXPECT_FALSE(this->nedelecSpace.isDOFOnBoundary(6)); @@ -231,7 +226,6 @@ TYPED_TEST(NedelecSpaceTest, isDOFOnBoundary) { EXPECT_TRUE(this->nedelecSpaceSmall.isDOFOnBoundary(51)); EXPECT_TRUE(this->nedelecSpaceSmall.isDOFOnBoundary(52)); - // check some of the ones which are false EXPECT_FALSE(this->nedelecSpaceSmall.isDOFOnBoundary(16)); EXPECT_FALSE(this->nedelecSpaceSmall.isDOFOnBoundary(24)); @@ -242,100 +236,98 @@ TYPED_TEST(NedelecSpaceTest, isDOFOnBoundary) { } } - TYPED_TEST(NedelecSpaceTest, getBoundarySide) { - static constexpr std::size_t dim = TestFixture::dim; - if (dim == 2) { - // check all the ones which are true - // south boundary - EXPECT_EQ(this->nedelecSpace.getBoundarySide(0),0); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(1),0); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(2),0); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(3),0); - // north boundary - EXPECT_EQ(this->nedelecSpace.getBoundarySide(36),2); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(37),2); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(38),2); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(39),2); - // west boundary - EXPECT_EQ(this->nedelecSpace.getBoundarySide(4),1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(13),1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(22),1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(31),1); - // east boundary - EXPECT_EQ(this->nedelecSpace.getBoundarySide(8),3); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(17),3); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(26),3); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(35),3); - - - // check the ones which are false - EXPECT_EQ(this->nedelecSpace.getBoundarySide(5),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(6),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(7),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(9),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(10),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(11),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(12),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(14),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(15),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(16),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(18),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(19),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(20),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(21),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(23),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(24),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(25),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(27),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(28),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(29),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(30),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(32),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(33),-1); - EXPECT_EQ(this->nedelecSpace.getBoundarySide(34),-1); - - } else { - // check all the ones which are true - // south boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(13),0); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(21),0); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(22),0); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(34),0); - // north boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(19),2); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(31),2); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(32),2); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(40),2); - // west boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(15),1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(23),1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(28),1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(36),1); - // east boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(17),3); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(25),3); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(30),3); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(38),3); - // ground boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(3),4); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(5),4); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(6),4); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(8),4); - // space boundary - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(45),5); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(47),5); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(48),5); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(50),5); - - // check some of the ones which are false - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(16),-1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(24),-1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(26),-1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(27),-1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(29),-1); - EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(37),-1); - } + static constexpr std::size_t dim = TestFixture::dim; + if (dim == 2) { + // check all the ones which are true + // south boundary + EXPECT_EQ(this->nedelecSpace.getBoundarySide(0), 0); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(1), 0); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(2), 0); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(3), 0); + // north boundary + EXPECT_EQ(this->nedelecSpace.getBoundarySide(36), 2); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(37), 2); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(38), 2); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(39), 2); + // west boundary + EXPECT_EQ(this->nedelecSpace.getBoundarySide(4), 1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(13), 1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(22), 1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(31), 1); + // east boundary + EXPECT_EQ(this->nedelecSpace.getBoundarySide(8), 3); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(17), 3); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(26), 3); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(35), 3); + + // check the ones which are false + EXPECT_EQ(this->nedelecSpace.getBoundarySide(5), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(6), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(7), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(9), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(10), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(11), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(12), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(14), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(15), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(16), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(18), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(19), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(20), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(21), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(23), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(24), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(25), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(27), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(28), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(29), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(30), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(32), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(33), -1); + EXPECT_EQ(this->nedelecSpace.getBoundarySide(34), -1); + + } else { + // check all the ones which are true + // south boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(13), 0); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(21), 0); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(22), 0); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(34), 0); + // north boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(19), 2); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(31), 2); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(32), 2); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(40), 2); + // west boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(15), 1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(23), 1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(28), 1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(36), 1); + // east boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(17), 3); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(25), 3); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(30), 3); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(38), 3); + // ground boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(3), 4); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(5), 4); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(6), 4); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(8), 4); + // space boundary + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(45), 5); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(47), 5); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(48), 5); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(50), 5); + + // check some of the ones which are false + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(16), -1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(24), -1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(26), -1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(27), -1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(29), -1); + EXPECT_EQ(this->nedelecSpaceSmall.getBoundarySide(37), -1); + } } TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunction) { @@ -345,10 +337,10 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunction) { // the implementation in the NedelecSpace class and for this case we still // have this test here. So while it right now might not be the most useful // thing, it could become useful in the future. - + static constexpr std::size_t dim = TestFixture::dim; - using T = typename TestFixture::value_t; - using point_t = ippl::Vector; + using T = typename TestFixture::value_t; + using point_t = ippl::Vector; point_t point; point_t dif; @@ -359,18 +351,19 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunction) { point[0] = x; for (T y = 0; y <= 1; y += 0.05) { point[1] = y; - dif = this->nedelecSpace.evaluateRefElementShapeFunction(0, point) - point_t(1-y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(0, point) + - point_t(1 - y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(1, point) - point_t(0.,1-x); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(1, point) + - point_t(0., 1 - x); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(2, point) - point_t(y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); - - dif = this->nedelecSpace.evaluateRefElementShapeFunction(3, point) - point_t(0.,x); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(2, point) - point_t(y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(3, point) - point_t(0., x); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); } } } else if constexpr (dim == 3) { @@ -380,63 +373,59 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunction) { point[1] = y; for (T z = 0; z <= 1; z += 0.05) { point[2] = z; - dif = this->nedelecSpace.evaluateRefElementShapeFunction(0, point) - - point_t(y*z-y-z+1,0.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); - - dif = this->nedelecSpace.evaluateRefElementShapeFunction(1, point) - - point_t(0.,x*z-x-z+1,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(0, point) + - point_t(y * z - y - z + 1, 0., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(2, point) - - point_t(y*(1-z),0.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(1, point) + - point_t(0., x * z - x - z + 1, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(3, point) - - point_t(0.,x*(1-z),0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(2, point) + - point_t(y * (1 - z), 0., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(4, point) - - point_t(0.,0.,x*y-x-y+1); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(3, point) + - point_t(0., x * (1 - z), 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(5, point) - - point_t(0.,0.,x*(1-y)); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(4, point) + - point_t(0., 0., x * y - x - y + 1); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(6, point) - - point_t(0.,0.,x*y); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(5, point) + - point_t(0., 0., x * (1 - y)); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(7, point) - - point_t(0.,0.,y*(1-x)); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(6, point) + - point_t(0., 0., x * y); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(8, point) - - point_t(z*(1-y),0.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(7, point) + - point_t(0., 0., y * (1 - x)); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(9, point) - - point_t(0.,z*(1-x),0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(8, point) + - point_t(z * (1 - y), 0., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(10, point) - - point_t(y*z,0.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(9, point) + - point_t(0., z * (1 - x), 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); - dif = this->nedelecSpace.evaluateRefElementShapeFunction(11, point) - - point_t(0.,x*z,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(10, point) + - point_t(y * z, 0., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunction(11, point) + - point_t(0., x * z, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); } } } - } - } - TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunctionCurl) { // This might seem useless to test the reference element shape function curl // values using the same formulae as we are using in the NedelecSpace class @@ -444,10 +433,10 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunctionCurl) { // the implementation in the NedelecSpace class and for this case we still // have this test here. So while it right now might not be the most useful // thing, it could become useful in the future. - - using T = typename TestFixture::value_t; + + using T = typename TestFixture::value_t; static constexpr std::size_t dim = TestFixture::dim; - using point_t = ippl::Vector; + using point_t = ippl::Vector; point_t point; point_t dif; @@ -458,22 +447,21 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunctionCurl) { point[0] = x; for (T y = 0; y <= 1; y += 0.05) { point[1] = y; - dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(0, point) - - point_t(1.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(0, point) + - point_t(1., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(1, point) - - point_t(-1.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(-1., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(2, point) - - point_t(-1.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(-1., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(3, point) - - point_t(1.,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); - + - point_t(1., 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); } } } else if constexpr (dim == 3) { @@ -483,68 +471,62 @@ TYPED_TEST(NedelecSpaceTest, evaluateRefElementShapeFunctionCurl) { point[1] = y; for (T z = 0; z <= 1; z += 0.05) { point[2] = z; - dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(0, point) - - point_t(0.,-1+y,1-z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(0, point) + - point_t(0., -1 + y, 1 - z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(1, point) - - point_t(1-x,0.,-1+z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(1 - x, 0., -1 + z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(2, point) - - point_t(0.,-y,-1+z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(0., -y, -1 + z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(3, point) - - point_t(x,0.,1-z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(x, 0., 1 - z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(4, point) - - point_t(-1+x,1-y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(-1 + x, 1 - y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(5, point) - - point_t(-x,-1+y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(-x, -1 + y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(6, point) - - point_t(x,-y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(x, -y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(7, point) - - point_t(1-x,y,0.); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(1 - x, y, 0.); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(8, point) - - point_t(0.,1-y,z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(0., 1 - y, z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(9, point) - - point_t(-1+x,0.,-z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(-1 + x, 0., -z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(10, point) - - point_t(0.,y,-z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); + - point_t(0., y, -z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); dif = this->nedelecSpace.evaluateRefElementShapeFunctionCurl(11, point) - - point_t(-x,0.,z); - ASSERT_NEAR(dif.dot(dif), 0.,tolerance); - + - point_t(-x, 0., z); + ASSERT_NEAR(dif.dot(dif), 0., tolerance); } } } } - } - - - - TYPED_TEST(NedelecSpaceTest, createFEMVector) { // Note that this test will start to fail in case the implementation how the - // domain decomposition is done or how the FEMVector entires are ordered is + // domain decomposition is done or how the FEMVector entires are ordered is // changed. Also be aware of the domain boundaries, as there the // halo cells are not necessarily uniquely defined. All in all this test is // custom tailored to the current way we have implemented it and if in the @@ -553,274 +535,269 @@ TYPED_TEST(NedelecSpaceTest, createFEMVector) { // ranks, if more ranks are used the test is skipped. static constexpr std::size_t dim = TestFixture::dim; - + if constexpr (dim == 2) { auto vec = this->nedelecSpace.createFEMVector(); - vec = ippl::Comm->rank(); + vec = ippl::Comm->rank(); vec.fillHalo(); vec.accumulateHalo(); - auto view = vec.getView(); + auto view = vec.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); - if (ippl::Comm->size() == 1) { ASSERT_EQ(vec.size(), 84); for (size_t i = 0; i < hView.extent(0); ++i) { - ASSERT_EQ(hView(i),0); + ASSERT_EQ(hView(i), 0); } } if (ippl::Comm->size() == 2) { if (ippl::Comm->rank() == 0) { ASSERT_EQ(vec.size(), 45); - ASSERT_EQ(hView(0),0); - ASSERT_EQ(hView(1),0); - ASSERT_EQ(hView(2),0); - ASSERT_EQ(hView(3),0); - ASSERT_EQ(hView(4),0); - ASSERT_EQ(hView(5),0); - ASSERT_EQ(hView(6),0); - ASSERT_EQ(hView(7),0); - ASSERT_EQ(hView(8),0); - ASSERT_EQ(hView(9),0); - ASSERT_EQ(hView(10),0); - ASSERT_EQ(hView(11),0); - ASSERT_EQ(hView(12),0); - ASSERT_EQ(hView(13),1); - ASSERT_EQ(hView(14),0); - ASSERT_EQ(hView(15),0); - ASSERT_EQ(hView(16),0); - ASSERT_EQ(hView(17),0); - ASSERT_EQ(hView(18),0); - ASSERT_EQ(hView(19),0); - ASSERT_EQ(hView(20),1); - ASSERT_EQ(hView(21),0); - ASSERT_EQ(hView(22),0); - ASSERT_EQ(hView(23),0); - ASSERT_EQ(hView(24),0); - ASSERT_EQ(hView(25),0); - ASSERT_EQ(hView(26),0); - ASSERT_EQ(hView(27),1); - ASSERT_EQ(hView(28),0); - ASSERT_EQ(hView(29),0); - ASSERT_EQ(hView(30),0); - ASSERT_EQ(hView(31),0); - ASSERT_EQ(hView(32),0); - ASSERT_EQ(hView(33),0); - ASSERT_EQ(hView(34),1); - ASSERT_EQ(hView(35),0); - ASSERT_EQ(hView(36),0); - ASSERT_EQ(hView(37),0); - ASSERT_EQ(hView(38),0); - ASSERT_EQ(hView(39),0); - ASSERT_EQ(hView(40),0); - ASSERT_EQ(hView(41),1); - ASSERT_EQ(hView(42),0); - ASSERT_EQ(hView(43),0); - ASSERT_EQ(hView(44),0); - + ASSERT_EQ(hView(0), 0); + ASSERT_EQ(hView(1), 0); + ASSERT_EQ(hView(2), 0); + ASSERT_EQ(hView(3), 0); + ASSERT_EQ(hView(4), 0); + ASSERT_EQ(hView(5), 0); + ASSERT_EQ(hView(6), 0); + ASSERT_EQ(hView(7), 0); + ASSERT_EQ(hView(8), 0); + ASSERT_EQ(hView(9), 0); + ASSERT_EQ(hView(10), 0); + ASSERT_EQ(hView(11), 0); + ASSERT_EQ(hView(12), 0); + ASSERT_EQ(hView(13), 1); + ASSERT_EQ(hView(14), 0); + ASSERT_EQ(hView(15), 0); + ASSERT_EQ(hView(16), 0); + ASSERT_EQ(hView(17), 0); + ASSERT_EQ(hView(18), 0); + ASSERT_EQ(hView(19), 0); + ASSERT_EQ(hView(20), 1); + ASSERT_EQ(hView(21), 0); + ASSERT_EQ(hView(22), 0); + ASSERT_EQ(hView(23), 0); + ASSERT_EQ(hView(24), 0); + ASSERT_EQ(hView(25), 0); + ASSERT_EQ(hView(26), 0); + ASSERT_EQ(hView(27), 1); + ASSERT_EQ(hView(28), 0); + ASSERT_EQ(hView(29), 0); + ASSERT_EQ(hView(30), 0); + ASSERT_EQ(hView(31), 0); + ASSERT_EQ(hView(32), 0); + ASSERT_EQ(hView(33), 0); + ASSERT_EQ(hView(34), 1); + ASSERT_EQ(hView(35), 0); + ASSERT_EQ(hView(36), 0); + ASSERT_EQ(hView(37), 0); + ASSERT_EQ(hView(38), 0); + ASSERT_EQ(hView(39), 0); + ASSERT_EQ(hView(40), 0); + ASSERT_EQ(hView(41), 1); + ASSERT_EQ(hView(42), 0); + ASSERT_EQ(hView(43), 0); + ASSERT_EQ(hView(44), 0); } if (ippl::Comm->rank() == 1) { ASSERT_EQ(vec.size(), 58); - ASSERT_EQ(hView(0),1); - ASSERT_EQ(hView(1),1); - ASSERT_EQ(hView(2),1); - ASSERT_EQ(hView(3),1); - ASSERT_EQ(hView(4),1); - ASSERT_EQ(hView(5),1); - ASSERT_EQ(hView(6),1); - ASSERT_EQ(hView(7),1); - ASSERT_EQ(hView(8),1); - ASSERT_EQ(hView(9),0); - ASSERT_EQ(hView(10),1); - ASSERT_EQ(hView(11),1); - ASSERT_EQ(hView(12),1); - ASSERT_EQ(hView(13),0); - ASSERT_EQ(hView(14),2); - ASSERT_EQ(hView(15),1); - ASSERT_EQ(hView(16),1); - ASSERT_EQ(hView(17),1); - ASSERT_EQ(hView(18),0); - ASSERT_EQ(hView(19),1); - ASSERT_EQ(hView(20),1); - ASSERT_EQ(hView(21),1); - ASSERT_EQ(hView(22),0); - ASSERT_EQ(hView(23),2); - ASSERT_EQ(hView(24),1); - ASSERT_EQ(hView(25),1); - ASSERT_EQ(hView(26),1); - ASSERT_EQ(hView(27),0); - ASSERT_EQ(hView(28),1); - ASSERT_EQ(hView(29),1); - ASSERT_EQ(hView(30),1); - ASSERT_EQ(hView(31),0); - ASSERT_EQ(hView(32),2); - ASSERT_EQ(hView(33),1); - ASSERT_EQ(hView(34),1); - ASSERT_EQ(hView(35),1); - ASSERT_EQ(hView(36),0); - ASSERT_EQ(hView(37),1); - ASSERT_EQ(hView(38),1); - ASSERT_EQ(hView(39),1); - ASSERT_EQ(hView(40),0); - ASSERT_EQ(hView(41),2); - ASSERT_EQ(hView(42),1); - ASSERT_EQ(hView(43),1); - ASSERT_EQ(hView(44),1); - ASSERT_EQ(hView(45),0); - ASSERT_EQ(hView(46),1); - ASSERT_EQ(hView(47),1); - ASSERT_EQ(hView(48),1); - ASSERT_EQ(hView(49),0); - ASSERT_EQ(hView(50),2); - ASSERT_EQ(hView(51),1); - ASSERT_EQ(hView(52),1); - ASSERT_EQ(hView(53),1); - ASSERT_EQ(hView(54),0); - ASSERT_EQ(hView(55),1); - ASSERT_EQ(hView(56),1); - ASSERT_EQ(hView(57),1); - + ASSERT_EQ(hView(0), 1); + ASSERT_EQ(hView(1), 1); + ASSERT_EQ(hView(2), 1); + ASSERT_EQ(hView(3), 1); + ASSERT_EQ(hView(4), 1); + ASSERT_EQ(hView(5), 1); + ASSERT_EQ(hView(6), 1); + ASSERT_EQ(hView(7), 1); + ASSERT_EQ(hView(8), 1); + ASSERT_EQ(hView(9), 0); + ASSERT_EQ(hView(10), 1); + ASSERT_EQ(hView(11), 1); + ASSERT_EQ(hView(12), 1); + ASSERT_EQ(hView(13), 0); + ASSERT_EQ(hView(14), 2); + ASSERT_EQ(hView(15), 1); + ASSERT_EQ(hView(16), 1); + ASSERT_EQ(hView(17), 1); + ASSERT_EQ(hView(18), 0); + ASSERT_EQ(hView(19), 1); + ASSERT_EQ(hView(20), 1); + ASSERT_EQ(hView(21), 1); + ASSERT_EQ(hView(22), 0); + ASSERT_EQ(hView(23), 2); + ASSERT_EQ(hView(24), 1); + ASSERT_EQ(hView(25), 1); + ASSERT_EQ(hView(26), 1); + ASSERT_EQ(hView(27), 0); + ASSERT_EQ(hView(28), 1); + ASSERT_EQ(hView(29), 1); + ASSERT_EQ(hView(30), 1); + ASSERT_EQ(hView(31), 0); + ASSERT_EQ(hView(32), 2); + ASSERT_EQ(hView(33), 1); + ASSERT_EQ(hView(34), 1); + ASSERT_EQ(hView(35), 1); + ASSERT_EQ(hView(36), 0); + ASSERT_EQ(hView(37), 1); + ASSERT_EQ(hView(38), 1); + ASSERT_EQ(hView(39), 1); + ASSERT_EQ(hView(40), 0); + ASSERT_EQ(hView(41), 2); + ASSERT_EQ(hView(42), 1); + ASSERT_EQ(hView(43), 1); + ASSERT_EQ(hView(44), 1); + ASSERT_EQ(hView(45), 0); + ASSERT_EQ(hView(46), 1); + ASSERT_EQ(hView(47), 1); + ASSERT_EQ(hView(48), 1); + ASSERT_EQ(hView(49), 0); + ASSERT_EQ(hView(50), 2); + ASSERT_EQ(hView(51), 1); + ASSERT_EQ(hView(52), 1); + ASSERT_EQ(hView(53), 1); + ASSERT_EQ(hView(54), 0); + ASSERT_EQ(hView(55), 1); + ASSERT_EQ(hView(56), 1); + ASSERT_EQ(hView(57), 1); } } if (ippl::Comm->size() == 3) { if (ippl::Comm->rank() == 0) { ASSERT_EQ(vec.size(), 45); - ASSERT_EQ(hView(0),0); - ASSERT_EQ(hView(1),0); - ASSERT_EQ(hView(2),0); - ASSERT_EQ(hView(3),0); - ASSERT_EQ(hView(4),0); - ASSERT_EQ(hView(5),0); - ASSERT_EQ(hView(6),0); - ASSERT_EQ(hView(7),0); - ASSERT_EQ(hView(8),0); - ASSERT_EQ(hView(9),0); - ASSERT_EQ(hView(10),0); - ASSERT_EQ(hView(11),0); - ASSERT_EQ(hView(12),0); - ASSERT_EQ(hView(13),1); - ASSERT_EQ(hView(14),0); - ASSERT_EQ(hView(15),0); - ASSERT_EQ(hView(16),0); - ASSERT_EQ(hView(17),0); - ASSERT_EQ(hView(18),0); - ASSERT_EQ(hView(19),0); - ASSERT_EQ(hView(20),1); - ASSERT_EQ(hView(21),0); - ASSERT_EQ(hView(22),0); - ASSERT_EQ(hView(23),0); - ASSERT_EQ(hView(24),0); - ASSERT_EQ(hView(25),0); - ASSERT_EQ(hView(26),0); - ASSERT_EQ(hView(27),1); - ASSERT_EQ(hView(28),0); - ASSERT_EQ(hView(29),0); - ASSERT_EQ(hView(30),0); - ASSERT_EQ(hView(31),0); - ASSERT_EQ(hView(32),0); - ASSERT_EQ(hView(33),0); - ASSERT_EQ(hView(34),1); - ASSERT_EQ(hView(35),0); - ASSERT_EQ(hView(36),0); - ASSERT_EQ(hView(37),0); - ASSERT_EQ(hView(38),0); - ASSERT_EQ(hView(39),0); - ASSERT_EQ(hView(40),0); - ASSERT_EQ(hView(41),1); - ASSERT_EQ(hView(42),0); - ASSERT_EQ(hView(43),0); - ASSERT_EQ(hView(44),0); + ASSERT_EQ(hView(0), 0); + ASSERT_EQ(hView(1), 0); + ASSERT_EQ(hView(2), 0); + ASSERT_EQ(hView(3), 0); + ASSERT_EQ(hView(4), 0); + ASSERT_EQ(hView(5), 0); + ASSERT_EQ(hView(6), 0); + ASSERT_EQ(hView(7), 0); + ASSERT_EQ(hView(8), 0); + ASSERT_EQ(hView(9), 0); + ASSERT_EQ(hView(10), 0); + ASSERT_EQ(hView(11), 0); + ASSERT_EQ(hView(12), 0); + ASSERT_EQ(hView(13), 1); + ASSERT_EQ(hView(14), 0); + ASSERT_EQ(hView(15), 0); + ASSERT_EQ(hView(16), 0); + ASSERT_EQ(hView(17), 0); + ASSERT_EQ(hView(18), 0); + ASSERT_EQ(hView(19), 0); + ASSERT_EQ(hView(20), 1); + ASSERT_EQ(hView(21), 0); + ASSERT_EQ(hView(22), 0); + ASSERT_EQ(hView(23), 0); + ASSERT_EQ(hView(24), 0); + ASSERT_EQ(hView(25), 0); + ASSERT_EQ(hView(26), 0); + ASSERT_EQ(hView(27), 1); + ASSERT_EQ(hView(28), 0); + ASSERT_EQ(hView(29), 0); + ASSERT_EQ(hView(30), 0); + ASSERT_EQ(hView(31), 0); + ASSERT_EQ(hView(32), 0); + ASSERT_EQ(hView(33), 0); + ASSERT_EQ(hView(34), 1); + ASSERT_EQ(hView(35), 0); + ASSERT_EQ(hView(36), 0); + ASSERT_EQ(hView(37), 0); + ASSERT_EQ(hView(38), 0); + ASSERT_EQ(hView(39), 0); + ASSERT_EQ(hView(40), 0); + ASSERT_EQ(hView(41), 1); + ASSERT_EQ(hView(42), 0); + ASSERT_EQ(hView(43), 0); + ASSERT_EQ(hView(44), 0); } if (ippl::Comm->rank() == 1) { ASSERT_EQ(vec.size(), 45); - ASSERT_EQ(hView(0),1); - ASSERT_EQ(hView(1),1); - ASSERT_EQ(hView(2),1); - ASSERT_EQ(hView(3),1); - ASSERT_EQ(hView(4),1); - ASSERT_EQ(hView(5),1); - ASSERT_EQ(hView(6),1); - ASSERT_EQ(hView(7),0); - ASSERT_EQ(hView(8),1); - ASSERT_EQ(hView(9),2); - ASSERT_EQ(hView(10),0); - ASSERT_EQ(hView(11),2); - ASSERT_EQ(hView(12),2); - ASSERT_EQ(hView(13),2); - ASSERT_EQ(hView(14),0); - ASSERT_EQ(hView(15),1); - ASSERT_EQ(hView(16),2); - ASSERT_EQ(hView(17),0); - ASSERT_EQ(hView(18),2); - ASSERT_EQ(hView(19),2); - ASSERT_EQ(hView(20),2); - ASSERT_EQ(hView(21),0); - ASSERT_EQ(hView(22),1); - ASSERT_EQ(hView(23),2); - ASSERT_EQ(hView(24),0); - ASSERT_EQ(hView(25),2); - ASSERT_EQ(hView(26),2); - ASSERT_EQ(hView(27),2); - ASSERT_EQ(hView(28),0); - ASSERT_EQ(hView(29),1); - ASSERT_EQ(hView(30),2); - ASSERT_EQ(hView(31),0); - ASSERT_EQ(hView(32),2); - ASSERT_EQ(hView(33),2); - ASSERT_EQ(hView(34),2); - ASSERT_EQ(hView(35),0); - ASSERT_EQ(hView(36),1); - ASSERT_EQ(hView(37),2); - ASSERT_EQ(hView(38),0); - ASSERT_EQ(hView(39),2); - ASSERT_EQ(hView(40),2); - ASSERT_EQ(hView(41),2); - ASSERT_EQ(hView(42),0); - ASSERT_EQ(hView(43),1); - ASSERT_EQ(hView(44),2); - - + ASSERT_EQ(hView(0), 1); + ASSERT_EQ(hView(1), 1); + ASSERT_EQ(hView(2), 1); + ASSERT_EQ(hView(3), 1); + ASSERT_EQ(hView(4), 1); + ASSERT_EQ(hView(5), 1); + ASSERT_EQ(hView(6), 1); + ASSERT_EQ(hView(7), 0); + ASSERT_EQ(hView(8), 1); + ASSERT_EQ(hView(9), 2); + ASSERT_EQ(hView(10), 0); + ASSERT_EQ(hView(11), 2); + ASSERT_EQ(hView(12), 2); + ASSERT_EQ(hView(13), 2); + ASSERT_EQ(hView(14), 0); + ASSERT_EQ(hView(15), 1); + ASSERT_EQ(hView(16), 2); + ASSERT_EQ(hView(17), 0); + ASSERT_EQ(hView(18), 2); + ASSERT_EQ(hView(19), 2); + ASSERT_EQ(hView(20), 2); + ASSERT_EQ(hView(21), 0); + ASSERT_EQ(hView(22), 1); + ASSERT_EQ(hView(23), 2); + ASSERT_EQ(hView(24), 0); + ASSERT_EQ(hView(25), 2); + ASSERT_EQ(hView(26), 2); + ASSERT_EQ(hView(27), 2); + ASSERT_EQ(hView(28), 0); + ASSERT_EQ(hView(29), 1); + ASSERT_EQ(hView(30), 2); + ASSERT_EQ(hView(31), 0); + ASSERT_EQ(hView(32), 2); + ASSERT_EQ(hView(33), 2); + ASSERT_EQ(hView(34), 2); + ASSERT_EQ(hView(35), 0); + ASSERT_EQ(hView(36), 1); + ASSERT_EQ(hView(37), 2); + ASSERT_EQ(hView(38), 0); + ASSERT_EQ(hView(39), 2); + ASSERT_EQ(hView(40), 2); + ASSERT_EQ(hView(41), 2); + ASSERT_EQ(hView(42), 0); + ASSERT_EQ(hView(43), 1); + ASSERT_EQ(hView(44), 2); } if (ippl::Comm->rank() == 2) { ASSERT_EQ(vec.size(), 32); - ASSERT_EQ(hView(0),2); - ASSERT_EQ(hView(1),2); - ASSERT_EQ(hView(2),2); - ASSERT_EQ(hView(3),2); - ASSERT_EQ(hView(4),2); - ASSERT_EQ(hView(5),1); - ASSERT_EQ(hView(6),2); - ASSERT_EQ(hView(7),1); - ASSERT_EQ(hView(8),4); - ASSERT_EQ(hView(9),2); - ASSERT_EQ(hView(10),1); - ASSERT_EQ(hView(11),2); - ASSERT_EQ(hView(12),1); - ASSERT_EQ(hView(13),4); - ASSERT_EQ(hView(14),2); - ASSERT_EQ(hView(15),1); - ASSERT_EQ(hView(16),2); - ASSERT_EQ(hView(17),1); - ASSERT_EQ(hView(18),4); - ASSERT_EQ(hView(19),2); - ASSERT_EQ(hView(20),1); - ASSERT_EQ(hView(21),2); - ASSERT_EQ(hView(22),1); - ASSERT_EQ(hView(23),4); - ASSERT_EQ(hView(24),2); - ASSERT_EQ(hView(25),1); - ASSERT_EQ(hView(26),2); - ASSERT_EQ(hView(27),1); - ASSERT_EQ(hView(28),4); - ASSERT_EQ(hView(29),2); - ASSERT_EQ(hView(30),1); - ASSERT_EQ(hView(31),2); + ASSERT_EQ(hView(0), 2); + ASSERT_EQ(hView(1), 2); + ASSERT_EQ(hView(2), 2); + ASSERT_EQ(hView(3), 2); + ASSERT_EQ(hView(4), 2); + ASSERT_EQ(hView(5), 1); + ASSERT_EQ(hView(6), 2); + ASSERT_EQ(hView(7), 1); + ASSERT_EQ(hView(8), 4); + ASSERT_EQ(hView(9), 2); + ASSERT_EQ(hView(10), 1); + ASSERT_EQ(hView(11), 2); + ASSERT_EQ(hView(12), 1); + ASSERT_EQ(hView(13), 4); + ASSERT_EQ(hView(14), 2); + ASSERT_EQ(hView(15), 1); + ASSERT_EQ(hView(16), 2); + ASSERT_EQ(hView(17), 1); + ASSERT_EQ(hView(18), 4); + ASSERT_EQ(hView(19), 2); + ASSERT_EQ(hView(20), 1); + ASSERT_EQ(hView(21), 2); + ASSERT_EQ(hView(22), 1); + ASSERT_EQ(hView(23), 4); + ASSERT_EQ(hView(24), 2); + ASSERT_EQ(hView(25), 1); + ASSERT_EQ(hView(26), 2); + ASSERT_EQ(hView(27), 1); + ASSERT_EQ(hView(28), 4); + ASSERT_EQ(hView(29), 2); + ASSERT_EQ(hView(30), 1); + ASSERT_EQ(hView(31), 2); } } } @@ -830,438 +807,433 @@ TYPED_TEST(NedelecSpaceTest, createFEMVector) { // do not check all the values in the FEMVector, but only the ones which // are involved in the halo exchange operations. auto vec = this->nedelecSpaceSmall.createFEMVector(); - vec = ippl::Comm->rank(); + vec = ippl::Comm->rank(); vec.fillHalo(); vec.accumulateHalo(); - auto view = vec.getView(); + auto view = vec.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); if (ippl::Comm->size() == 1) { ASSERT_EQ(vec.size(), 300); for (size_t i = 0; i < hView.extent(0); ++i) { - ASSERT_EQ(hView(i),0); + ASSERT_EQ(hView(i), 0); } } if (ippl::Comm->size() == 2) { if (ippl::Comm->rank() == 0) { ASSERT_EQ(vec.size(), 170); - ASSERT_EQ(hView(43),0); - ASSERT_EQ(hView(45),0); - ASSERT_EQ(hView(46),1); - ASSERT_EQ(hView(48),0); - ASSERT_EQ(hView(50),0); - ASSERT_EQ(hView(51),1); - ASSERT_EQ(hView(53),0); - ASSERT_EQ(hView(55),0); - ASSERT_EQ(hView(56),1); - ASSERT_EQ(hView(58),0); - ASSERT_EQ(hView(63),0); - ASSERT_EQ(hView(64),1); - ASSERT_EQ(hView(66),0); - ASSERT_EQ(hView(67),1); - ASSERT_EQ(hView(69),0); - ASSERT_EQ(hView(70),1); - ASSERT_EQ(hView(72),0); - ASSERT_EQ(hView(73),1); - ASSERT_EQ(hView(80),0); - ASSERT_EQ(hView(82),0); - ASSERT_EQ(hView(83),1); - ASSERT_EQ(hView(85),0); - ASSERT_EQ(hView(87),0); - ASSERT_EQ(hView(88),1); - ASSERT_EQ(hView(90),0); - ASSERT_EQ(hView(92),0); - ASSERT_EQ(hView(93),1); - ASSERT_EQ(hView(95),0); - ASSERT_EQ(hView(100),0); - ASSERT_EQ(hView(101),1); - ASSERT_EQ(hView(103),0); - ASSERT_EQ(hView(104),1); - ASSERT_EQ(hView(106),0); - ASSERT_EQ(hView(107),1); - ASSERT_EQ(hView(109),0); - ASSERT_EQ(hView(110),1); - ASSERT_EQ(hView(117),0); - ASSERT_EQ(hView(119),0); - ASSERT_EQ(hView(120),1); - ASSERT_EQ(hView(122),0); - ASSERT_EQ(hView(124),0); - ASSERT_EQ(hView(125),1); - ASSERT_EQ(hView(127),0); - ASSERT_EQ(hView(129),0); - ASSERT_EQ(hView(130),1); - ASSERT_EQ(hView(132),0); - ASSERT_EQ(hView(137),0); - ASSERT_EQ(hView(138),1); - ASSERT_EQ(hView(140),0); - ASSERT_EQ(hView(141),1); - ASSERT_EQ(hView(143),0); - ASSERT_EQ(hView(144),1); - ASSERT_EQ(hView(146),0); - ASSERT_EQ(hView(147),1); - ASSERT_EQ(hView(154),0); - ASSERT_EQ(hView(156),0); - ASSERT_EQ(hView(157),1); - ASSERT_EQ(hView(159),0); - ASSERT_EQ(hView(161),0); - ASSERT_EQ(hView(162),1); - ASSERT_EQ(hView(164),0); - ASSERT_EQ(hView(166),0); - ASSERT_EQ(hView(167),1); - ASSERT_EQ(hView(169),0); - + ASSERT_EQ(hView(43), 0); + ASSERT_EQ(hView(45), 0); + ASSERT_EQ(hView(46), 1); + ASSERT_EQ(hView(48), 0); + ASSERT_EQ(hView(50), 0); + ASSERT_EQ(hView(51), 1); + ASSERT_EQ(hView(53), 0); + ASSERT_EQ(hView(55), 0); + ASSERT_EQ(hView(56), 1); + ASSERT_EQ(hView(58), 0); + ASSERT_EQ(hView(63), 0); + ASSERT_EQ(hView(64), 1); + ASSERT_EQ(hView(66), 0); + ASSERT_EQ(hView(67), 1); + ASSERT_EQ(hView(69), 0); + ASSERT_EQ(hView(70), 1); + ASSERT_EQ(hView(72), 0); + ASSERT_EQ(hView(73), 1); + ASSERT_EQ(hView(80), 0); + ASSERT_EQ(hView(82), 0); + ASSERT_EQ(hView(83), 1); + ASSERT_EQ(hView(85), 0); + ASSERT_EQ(hView(87), 0); + ASSERT_EQ(hView(88), 1); + ASSERT_EQ(hView(90), 0); + ASSERT_EQ(hView(92), 0); + ASSERT_EQ(hView(93), 1); + ASSERT_EQ(hView(95), 0); + ASSERT_EQ(hView(100), 0); + ASSERT_EQ(hView(101), 1); + ASSERT_EQ(hView(103), 0); + ASSERT_EQ(hView(104), 1); + ASSERT_EQ(hView(106), 0); + ASSERT_EQ(hView(107), 1); + ASSERT_EQ(hView(109), 0); + ASSERT_EQ(hView(110), 1); + ASSERT_EQ(hView(117), 0); + ASSERT_EQ(hView(119), 0); + ASSERT_EQ(hView(120), 1); + ASSERT_EQ(hView(122), 0); + ASSERT_EQ(hView(124), 0); + ASSERT_EQ(hView(125), 1); + ASSERT_EQ(hView(127), 0); + ASSERT_EQ(hView(129), 0); + ASSERT_EQ(hView(130), 1); + ASSERT_EQ(hView(132), 0); + ASSERT_EQ(hView(137), 0); + ASSERT_EQ(hView(138), 1); + ASSERT_EQ(hView(140), 0); + ASSERT_EQ(hView(141), 1); + ASSERT_EQ(hView(143), 0); + ASSERT_EQ(hView(144), 1); + ASSERT_EQ(hView(146), 0); + ASSERT_EQ(hView(147), 1); + ASSERT_EQ(hView(154), 0); + ASSERT_EQ(hView(156), 0); + ASSERT_EQ(hView(157), 1); + ASSERT_EQ(hView(159), 0); + ASSERT_EQ(hView(161), 0); + ASSERT_EQ(hView(162), 1); + ASSERT_EQ(hView(164), 0); + ASSERT_EQ(hView(166), 0); + ASSERT_EQ(hView(167), 1); + ASSERT_EQ(hView(169), 0); } if (ippl::Comm->rank() == 1) { ASSERT_EQ(vec.size(), 235); - ASSERT_EQ(hView(58),0); - ASSERT_EQ(hView(61),0); - ASSERT_EQ(hView(62),2); - ASSERT_EQ(hView(65),0); - ASSERT_EQ(hView(68),0); - ASSERT_EQ(hView(69),2); - ASSERT_EQ(hView(72),0); - ASSERT_EQ(hView(75),0); - ASSERT_EQ(hView(76),2); - ASSERT_EQ(hView(79),0); - ASSERT_EQ(hView(86),0); - ASSERT_EQ(hView(87),2); - ASSERT_EQ(hView(90),0); - ASSERT_EQ(hView(91),2); - ASSERT_EQ(hView(94),0); - ASSERT_EQ(hView(95),2); - ASSERT_EQ(hView(98),0); - ASSERT_EQ(hView(99),2); - ASSERT_EQ(hView(109),0); - ASSERT_EQ(hView(112),0); - ASSERT_EQ(hView(113),2); - ASSERT_EQ(hView(116),0); - ASSERT_EQ(hView(119),0); - ASSERT_EQ(hView(120),2); - ASSERT_EQ(hView(123),0); - ASSERT_EQ(hView(126),0); - ASSERT_EQ(hView(127),2); - ASSERT_EQ(hView(130),0); - ASSERT_EQ(hView(137),0); - ASSERT_EQ(hView(138),2); - ASSERT_EQ(hView(141),0); - ASSERT_EQ(hView(142),2); - ASSERT_EQ(hView(145),0); - ASSERT_EQ(hView(146),2); - ASSERT_EQ(hView(149),0); - ASSERT_EQ(hView(150),2); - ASSERT_EQ(hView(160),0); - ASSERT_EQ(hView(163),0); - ASSERT_EQ(hView(164),2); - ASSERT_EQ(hView(167),0); - ASSERT_EQ(hView(170),0); - ASSERT_EQ(hView(171),2); - ASSERT_EQ(hView(174),0); - ASSERT_EQ(hView(177),0); - ASSERT_EQ(hView(178),2); - ASSERT_EQ(hView(181),0); - ASSERT_EQ(hView(188),0); - ASSERT_EQ(hView(189),2); - ASSERT_EQ(hView(192),0); - ASSERT_EQ(hView(193),2); - ASSERT_EQ(hView(196),0); - ASSERT_EQ(hView(197),2); - ASSERT_EQ(hView(200),0); - ASSERT_EQ(hView(201),2); - ASSERT_EQ(hView(211),0); - ASSERT_EQ(hView(214),0); - ASSERT_EQ(hView(215),2); - ASSERT_EQ(hView(218),0); - ASSERT_EQ(hView(221),0); - ASSERT_EQ(hView(222),2); - ASSERT_EQ(hView(225),0); - ASSERT_EQ(hView(228),0); - ASSERT_EQ(hView(229),2); - ASSERT_EQ(hView(232),0); + ASSERT_EQ(hView(58), 0); + ASSERT_EQ(hView(61), 0); + ASSERT_EQ(hView(62), 2); + ASSERT_EQ(hView(65), 0); + ASSERT_EQ(hView(68), 0); + ASSERT_EQ(hView(69), 2); + ASSERT_EQ(hView(72), 0); + ASSERT_EQ(hView(75), 0); + ASSERT_EQ(hView(76), 2); + ASSERT_EQ(hView(79), 0); + ASSERT_EQ(hView(86), 0); + ASSERT_EQ(hView(87), 2); + ASSERT_EQ(hView(90), 0); + ASSERT_EQ(hView(91), 2); + ASSERT_EQ(hView(94), 0); + ASSERT_EQ(hView(95), 2); + ASSERT_EQ(hView(98), 0); + ASSERT_EQ(hView(99), 2); + ASSERT_EQ(hView(109), 0); + ASSERT_EQ(hView(112), 0); + ASSERT_EQ(hView(113), 2); + ASSERT_EQ(hView(116), 0); + ASSERT_EQ(hView(119), 0); + ASSERT_EQ(hView(120), 2); + ASSERT_EQ(hView(123), 0); + ASSERT_EQ(hView(126), 0); + ASSERT_EQ(hView(127), 2); + ASSERT_EQ(hView(130), 0); + ASSERT_EQ(hView(137), 0); + ASSERT_EQ(hView(138), 2); + ASSERT_EQ(hView(141), 0); + ASSERT_EQ(hView(142), 2); + ASSERT_EQ(hView(145), 0); + ASSERT_EQ(hView(146), 2); + ASSERT_EQ(hView(149), 0); + ASSERT_EQ(hView(150), 2); + ASSERT_EQ(hView(160), 0); + ASSERT_EQ(hView(163), 0); + ASSERT_EQ(hView(164), 2); + ASSERT_EQ(hView(167), 0); + ASSERT_EQ(hView(170), 0); + ASSERT_EQ(hView(171), 2); + ASSERT_EQ(hView(174), 0); + ASSERT_EQ(hView(177), 0); + ASSERT_EQ(hView(178), 2); + ASSERT_EQ(hView(181), 0); + ASSERT_EQ(hView(188), 0); + ASSERT_EQ(hView(189), 2); + ASSERT_EQ(hView(192), 0); + ASSERT_EQ(hView(193), 2); + ASSERT_EQ(hView(196), 0); + ASSERT_EQ(hView(197), 2); + ASSERT_EQ(hView(200), 0); + ASSERT_EQ(hView(201), 2); + ASSERT_EQ(hView(211), 0); + ASSERT_EQ(hView(214), 0); + ASSERT_EQ(hView(215), 2); + ASSERT_EQ(hView(218), 0); + ASSERT_EQ(hView(221), 0); + ASSERT_EQ(hView(222), 2); + ASSERT_EQ(hView(225), 0); + ASSERT_EQ(hView(228), 0); + ASSERT_EQ(hView(229), 2); + ASSERT_EQ(hView(232), 0); } } if (ippl::Comm->size() == 3) { if (ippl::Comm->rank() == 0) { ASSERT_EQ(vec.size(), 170); - ASSERT_EQ(hView(43),0); - ASSERT_EQ(hView(45),0); - ASSERT_EQ(hView(46),1); - ASSERT_EQ(hView(48),0); - ASSERT_EQ(hView(50),0); - ASSERT_EQ(hView(51),1); - ASSERT_EQ(hView(53),0); - ASSERT_EQ(hView(55),0); - ASSERT_EQ(hView(56),1); - ASSERT_EQ(hView(58),0); - ASSERT_EQ(hView(63),0); - ASSERT_EQ(hView(64),1); - ASSERT_EQ(hView(66),0); - ASSERT_EQ(hView(67),1); - ASSERT_EQ(hView(69),0); - ASSERT_EQ(hView(70),1); - ASSERT_EQ(hView(72),0); - ASSERT_EQ(hView(73),1); - ASSERT_EQ(hView(80),0); - ASSERT_EQ(hView(82),0); - ASSERT_EQ(hView(83),1); - ASSERT_EQ(hView(85),0); - ASSERT_EQ(hView(87),0); - ASSERT_EQ(hView(88),1); - ASSERT_EQ(hView(90),0); - ASSERT_EQ(hView(92),0); - ASSERT_EQ(hView(93),1); - ASSERT_EQ(hView(95),0); - ASSERT_EQ(hView(100),0); - ASSERT_EQ(hView(101),1); - ASSERT_EQ(hView(103),0); - ASSERT_EQ(hView(104),1); - ASSERT_EQ(hView(106),0); - ASSERT_EQ(hView(107),1); - ASSERT_EQ(hView(109),0); - ASSERT_EQ(hView(110),1); - ASSERT_EQ(hView(117),0); - ASSERT_EQ(hView(119),0); - ASSERT_EQ(hView(120),1); - ASSERT_EQ(hView(122),0); - ASSERT_EQ(hView(124),0); - ASSERT_EQ(hView(125),1); - ASSERT_EQ(hView(127),0); - ASSERT_EQ(hView(129),0); - ASSERT_EQ(hView(130),1); - ASSERT_EQ(hView(132),0); - ASSERT_EQ(hView(137),0); - ASSERT_EQ(hView(138),1); - ASSERT_EQ(hView(140),0); - ASSERT_EQ(hView(141),1); - ASSERT_EQ(hView(143),0); - ASSERT_EQ(hView(144),1); - ASSERT_EQ(hView(146),0); - ASSERT_EQ(hView(147),1); - ASSERT_EQ(hView(154),0); - ASSERT_EQ(hView(156),0); - ASSERT_EQ(hView(157),1); - ASSERT_EQ(hView(159),0); - ASSERT_EQ(hView(161),0); - ASSERT_EQ(hView(162),1); - ASSERT_EQ(hView(164),0); - ASSERT_EQ(hView(166),0); - ASSERT_EQ(hView(167),1); - ASSERT_EQ(hView(169),0); + ASSERT_EQ(hView(43), 0); + ASSERT_EQ(hView(45), 0); + ASSERT_EQ(hView(46), 1); + ASSERT_EQ(hView(48), 0); + ASSERT_EQ(hView(50), 0); + ASSERT_EQ(hView(51), 1); + ASSERT_EQ(hView(53), 0); + ASSERT_EQ(hView(55), 0); + ASSERT_EQ(hView(56), 1); + ASSERT_EQ(hView(58), 0); + ASSERT_EQ(hView(63), 0); + ASSERT_EQ(hView(64), 1); + ASSERT_EQ(hView(66), 0); + ASSERT_EQ(hView(67), 1); + ASSERT_EQ(hView(69), 0); + ASSERT_EQ(hView(70), 1); + ASSERT_EQ(hView(72), 0); + ASSERT_EQ(hView(73), 1); + ASSERT_EQ(hView(80), 0); + ASSERT_EQ(hView(82), 0); + ASSERT_EQ(hView(83), 1); + ASSERT_EQ(hView(85), 0); + ASSERT_EQ(hView(87), 0); + ASSERT_EQ(hView(88), 1); + ASSERT_EQ(hView(90), 0); + ASSERT_EQ(hView(92), 0); + ASSERT_EQ(hView(93), 1); + ASSERT_EQ(hView(95), 0); + ASSERT_EQ(hView(100), 0); + ASSERT_EQ(hView(101), 1); + ASSERT_EQ(hView(103), 0); + ASSERT_EQ(hView(104), 1); + ASSERT_EQ(hView(106), 0); + ASSERT_EQ(hView(107), 1); + ASSERT_EQ(hView(109), 0); + ASSERT_EQ(hView(110), 1); + ASSERT_EQ(hView(117), 0); + ASSERT_EQ(hView(119), 0); + ASSERT_EQ(hView(120), 1); + ASSERT_EQ(hView(122), 0); + ASSERT_EQ(hView(124), 0); + ASSERT_EQ(hView(125), 1); + ASSERT_EQ(hView(127), 0); + ASSERT_EQ(hView(129), 0); + ASSERT_EQ(hView(130), 1); + ASSERT_EQ(hView(132), 0); + ASSERT_EQ(hView(137), 0); + ASSERT_EQ(hView(138), 1); + ASSERT_EQ(hView(140), 0); + ASSERT_EQ(hView(141), 1); + ASSERT_EQ(hView(143), 0); + ASSERT_EQ(hView(144), 1); + ASSERT_EQ(hView(146), 0); + ASSERT_EQ(hView(147), 1); + ASSERT_EQ(hView(154), 0); + ASSERT_EQ(hView(156), 0); + ASSERT_EQ(hView(157), 1); + ASSERT_EQ(hView(159), 0); + ASSERT_EQ(hView(161), 0); + ASSERT_EQ(hView(162), 1); + ASSERT_EQ(hView(164), 0); + ASSERT_EQ(hView(166), 0); + ASSERT_EQ(hView(167), 1); + ASSERT_EQ(hView(169), 0); } if (ippl::Comm->rank() == 1) { ASSERT_EQ(vec.size(), 170); - ASSERT_EQ(hView(42),0); - ASSERT_EQ(hView(43),2); - ASSERT_EQ(hView(44),0); - ASSERT_EQ(hView(45),3); - ASSERT_EQ(hView(46),2); - ASSERT_EQ(hView(47),0); - ASSERT_EQ(hView(48),2); - ASSERT_EQ(hView(49),0); - ASSERT_EQ(hView(50),3); - ASSERT_EQ(hView(51),2); - ASSERT_EQ(hView(52),0); - ASSERT_EQ(hView(53),2); - ASSERT_EQ(hView(54),0); - ASSERT_EQ(hView(55),3); - ASSERT_EQ(hView(56),2); - ASSERT_EQ(hView(57),0); - ASSERT_EQ(hView(58),2); - ASSERT_EQ(hView(62),0); - ASSERT_EQ(hView(63),3); - ASSERT_EQ(hView(64),2); - ASSERT_EQ(hView(65),0); - ASSERT_EQ(hView(66),3); - ASSERT_EQ(hView(67),2); - ASSERT_EQ(hView(68),0); - ASSERT_EQ(hView(69),3); - ASSERT_EQ(hView(70),2); - ASSERT_EQ(hView(71),0); - ASSERT_EQ(hView(72),3); - ASSERT_EQ(hView(73),2); - ASSERT_EQ(hView(79),0); - ASSERT_EQ(hView(80),2); - ASSERT_EQ(hView(81),0); - ASSERT_EQ(hView(82),3); - ASSERT_EQ(hView(83),2); - ASSERT_EQ(hView(84),0); - ASSERT_EQ(hView(85),2); - ASSERT_EQ(hView(86),0); - ASSERT_EQ(hView(87),3); - ASSERT_EQ(hView(88),2); - ASSERT_EQ(hView(89),0); - ASSERT_EQ(hView(90),2); - ASSERT_EQ(hView(91),0); - ASSERT_EQ(hView(92),3); - ASSERT_EQ(hView(93),2); - ASSERT_EQ(hView(94),0); - ASSERT_EQ(hView(95),2); - ASSERT_EQ(hView(99),0); - ASSERT_EQ(hView(100),3); - ASSERT_EQ(hView(101),2); - ASSERT_EQ(hView(102),0); - ASSERT_EQ(hView(103),3); - ASSERT_EQ(hView(104),2); - ASSERT_EQ(hView(105),0); - ASSERT_EQ(hView(106),3); - ASSERT_EQ(hView(107),2); - ASSERT_EQ(hView(108),0); - ASSERT_EQ(hView(109),3); - ASSERT_EQ(hView(110),2); - ASSERT_EQ(hView(116),0); - ASSERT_EQ(hView(117),2); - ASSERT_EQ(hView(118),0); - ASSERT_EQ(hView(119),3); - ASSERT_EQ(hView(120),2); - ASSERT_EQ(hView(121),0); - ASSERT_EQ(hView(122),2); - ASSERT_EQ(hView(123),0); - ASSERT_EQ(hView(124),3); - ASSERT_EQ(hView(125),2); - ASSERT_EQ(hView(126),0); - ASSERT_EQ(hView(127),2); - ASSERT_EQ(hView(128),0); - ASSERT_EQ(hView(129),3); - ASSERT_EQ(hView(130),2); - ASSERT_EQ(hView(131),0); - ASSERT_EQ(hView(132),2); - ASSERT_EQ(hView(136),0); - ASSERT_EQ(hView(137),3); - ASSERT_EQ(hView(138),2); - ASSERT_EQ(hView(139),0); - ASSERT_EQ(hView(140),3); - ASSERT_EQ(hView(141),2); - ASSERT_EQ(hView(142),0); - ASSERT_EQ(hView(143),3); - ASSERT_EQ(hView(144),2); - ASSERT_EQ(hView(145),0); - ASSERT_EQ(hView(146),3); - ASSERT_EQ(hView(147),2); - ASSERT_EQ(hView(153),0); - ASSERT_EQ(hView(154),2); - ASSERT_EQ(hView(155),0); - ASSERT_EQ(hView(156),3); - ASSERT_EQ(hView(157),2); - ASSERT_EQ(hView(158),0); - ASSERT_EQ(hView(159),2); - ASSERT_EQ(hView(160),0); - ASSERT_EQ(hView(161),3); - ASSERT_EQ(hView(162),2); - ASSERT_EQ(hView(163),0); - ASSERT_EQ(hView(164),2); - ASSERT_EQ(hView(165),0); - ASSERT_EQ(hView(166),3); - ASSERT_EQ(hView(167),2); - ASSERT_EQ(hView(168),0); - ASSERT_EQ(hView(169),2); + ASSERT_EQ(hView(42), 0); + ASSERT_EQ(hView(43), 2); + ASSERT_EQ(hView(44), 0); + ASSERT_EQ(hView(45), 3); + ASSERT_EQ(hView(46), 2); + ASSERT_EQ(hView(47), 0); + ASSERT_EQ(hView(48), 2); + ASSERT_EQ(hView(49), 0); + ASSERT_EQ(hView(50), 3); + ASSERT_EQ(hView(51), 2); + ASSERT_EQ(hView(52), 0); + ASSERT_EQ(hView(53), 2); + ASSERT_EQ(hView(54), 0); + ASSERT_EQ(hView(55), 3); + ASSERT_EQ(hView(56), 2); + ASSERT_EQ(hView(57), 0); + ASSERT_EQ(hView(58), 2); + ASSERT_EQ(hView(62), 0); + ASSERT_EQ(hView(63), 3); + ASSERT_EQ(hView(64), 2); + ASSERT_EQ(hView(65), 0); + ASSERT_EQ(hView(66), 3); + ASSERT_EQ(hView(67), 2); + ASSERT_EQ(hView(68), 0); + ASSERT_EQ(hView(69), 3); + ASSERT_EQ(hView(70), 2); + ASSERT_EQ(hView(71), 0); + ASSERT_EQ(hView(72), 3); + ASSERT_EQ(hView(73), 2); + ASSERT_EQ(hView(79), 0); + ASSERT_EQ(hView(80), 2); + ASSERT_EQ(hView(81), 0); + ASSERT_EQ(hView(82), 3); + ASSERT_EQ(hView(83), 2); + ASSERT_EQ(hView(84), 0); + ASSERT_EQ(hView(85), 2); + ASSERT_EQ(hView(86), 0); + ASSERT_EQ(hView(87), 3); + ASSERT_EQ(hView(88), 2); + ASSERT_EQ(hView(89), 0); + ASSERT_EQ(hView(90), 2); + ASSERT_EQ(hView(91), 0); + ASSERT_EQ(hView(92), 3); + ASSERT_EQ(hView(93), 2); + ASSERT_EQ(hView(94), 0); + ASSERT_EQ(hView(95), 2); + ASSERT_EQ(hView(99), 0); + ASSERT_EQ(hView(100), 3); + ASSERT_EQ(hView(101), 2); + ASSERT_EQ(hView(102), 0); + ASSERT_EQ(hView(103), 3); + ASSERT_EQ(hView(104), 2); + ASSERT_EQ(hView(105), 0); + ASSERT_EQ(hView(106), 3); + ASSERT_EQ(hView(107), 2); + ASSERT_EQ(hView(108), 0); + ASSERT_EQ(hView(109), 3); + ASSERT_EQ(hView(110), 2); + ASSERT_EQ(hView(116), 0); + ASSERT_EQ(hView(117), 2); + ASSERT_EQ(hView(118), 0); + ASSERT_EQ(hView(119), 3); + ASSERT_EQ(hView(120), 2); + ASSERT_EQ(hView(121), 0); + ASSERT_EQ(hView(122), 2); + ASSERT_EQ(hView(123), 0); + ASSERT_EQ(hView(124), 3); + ASSERT_EQ(hView(125), 2); + ASSERT_EQ(hView(126), 0); + ASSERT_EQ(hView(127), 2); + ASSERT_EQ(hView(128), 0); + ASSERT_EQ(hView(129), 3); + ASSERT_EQ(hView(130), 2); + ASSERT_EQ(hView(131), 0); + ASSERT_EQ(hView(132), 2); + ASSERT_EQ(hView(136), 0); + ASSERT_EQ(hView(137), 3); + ASSERT_EQ(hView(138), 2); + ASSERT_EQ(hView(139), 0); + ASSERT_EQ(hView(140), 3); + ASSERT_EQ(hView(141), 2); + ASSERT_EQ(hView(142), 0); + ASSERT_EQ(hView(143), 3); + ASSERT_EQ(hView(144), 2); + ASSERT_EQ(hView(145), 0); + ASSERT_EQ(hView(146), 3); + ASSERT_EQ(hView(147), 2); + ASSERT_EQ(hView(153), 0); + ASSERT_EQ(hView(154), 2); + ASSERT_EQ(hView(155), 0); + ASSERT_EQ(hView(156), 3); + ASSERT_EQ(hView(157), 2); + ASSERT_EQ(hView(158), 0); + ASSERT_EQ(hView(159), 2); + ASSERT_EQ(hView(160), 0); + ASSERT_EQ(hView(161), 3); + ASSERT_EQ(hView(162), 2); + ASSERT_EQ(hView(163), 0); + ASSERT_EQ(hView(164), 2); + ASSERT_EQ(hView(165), 0); + ASSERT_EQ(hView(166), 3); + ASSERT_EQ(hView(167), 2); + ASSERT_EQ(hView(168), 0); + ASSERT_EQ(hView(169), 2); } if (ippl::Comm->rank() == 2) { ASSERT_EQ(vec.size(), 170); - ASSERT_EQ(hView(42),1); - ASSERT_EQ(hView(44),1); - ASSERT_EQ(hView(45),4); - ASSERT_EQ(hView(47),1); - ASSERT_EQ(hView(49),1); - ASSERT_EQ(hView(50),4); - ASSERT_EQ(hView(52),1); - ASSERT_EQ(hView(54),1); - ASSERT_EQ(hView(55),4); - ASSERT_EQ(hView(57),1); - ASSERT_EQ(hView(62),1); - ASSERT_EQ(hView(63),4); - ASSERT_EQ(hView(65),1); - ASSERT_EQ(hView(66),4); - ASSERT_EQ(hView(68),1); - ASSERT_EQ(hView(69),4); - ASSERT_EQ(hView(71),1); - ASSERT_EQ(hView(72),4); - ASSERT_EQ(hView(79),1); - ASSERT_EQ(hView(81),1); - ASSERT_EQ(hView(82),4); - ASSERT_EQ(hView(84),1); - ASSERT_EQ(hView(86),1); - ASSERT_EQ(hView(87),4); - ASSERT_EQ(hView(89),1); - ASSERT_EQ(hView(91),1); - ASSERT_EQ(hView(92),4); - ASSERT_EQ(hView(94),1); - ASSERT_EQ(hView(99),1); - ASSERT_EQ(hView(100),4); - ASSERT_EQ(hView(102),1); - ASSERT_EQ(hView(103),4); - ASSERT_EQ(hView(105),1); - ASSERT_EQ(hView(106),4); - ASSERT_EQ(hView(108),1); - ASSERT_EQ(hView(109),4); - ASSERT_EQ(hView(116),1); - ASSERT_EQ(hView(118),1); - ASSERT_EQ(hView(119),4); - ASSERT_EQ(hView(121),1); - ASSERT_EQ(hView(123),1); - ASSERT_EQ(hView(124),4); - ASSERT_EQ(hView(126),1); - ASSERT_EQ(hView(128),1); - ASSERT_EQ(hView(129),4); - ASSERT_EQ(hView(131),1); - ASSERT_EQ(hView(136),1); - ASSERT_EQ(hView(137),4); - ASSERT_EQ(hView(139),1); - ASSERT_EQ(hView(140),4); - ASSERT_EQ(hView(142),1); - ASSERT_EQ(hView(143),4); - ASSERT_EQ(hView(145),1); - ASSERT_EQ(hView(146),4); - ASSERT_EQ(hView(153),1); - ASSERT_EQ(hView(155),1); - ASSERT_EQ(hView(156),4); - ASSERT_EQ(hView(158),1); - ASSERT_EQ(hView(160),1); - ASSERT_EQ(hView(161),4); - ASSERT_EQ(hView(163),1); - ASSERT_EQ(hView(165),1); - ASSERT_EQ(hView(166),4); - ASSERT_EQ(hView(168),1); - + ASSERT_EQ(hView(42), 1); + ASSERT_EQ(hView(44), 1); + ASSERT_EQ(hView(45), 4); + ASSERT_EQ(hView(47), 1); + ASSERT_EQ(hView(49), 1); + ASSERT_EQ(hView(50), 4); + ASSERT_EQ(hView(52), 1); + ASSERT_EQ(hView(54), 1); + ASSERT_EQ(hView(55), 4); + ASSERT_EQ(hView(57), 1); + ASSERT_EQ(hView(62), 1); + ASSERT_EQ(hView(63), 4); + ASSERT_EQ(hView(65), 1); + ASSERT_EQ(hView(66), 4); + ASSERT_EQ(hView(68), 1); + ASSERT_EQ(hView(69), 4); + ASSERT_EQ(hView(71), 1); + ASSERT_EQ(hView(72), 4); + ASSERT_EQ(hView(79), 1); + ASSERT_EQ(hView(81), 1); + ASSERT_EQ(hView(82), 4); + ASSERT_EQ(hView(84), 1); + ASSERT_EQ(hView(86), 1); + ASSERT_EQ(hView(87), 4); + ASSERT_EQ(hView(89), 1); + ASSERT_EQ(hView(91), 1); + ASSERT_EQ(hView(92), 4); + ASSERT_EQ(hView(94), 1); + ASSERT_EQ(hView(99), 1); + ASSERT_EQ(hView(100), 4); + ASSERT_EQ(hView(102), 1); + ASSERT_EQ(hView(103), 4); + ASSERT_EQ(hView(105), 1); + ASSERT_EQ(hView(106), 4); + ASSERT_EQ(hView(108), 1); + ASSERT_EQ(hView(109), 4); + ASSERT_EQ(hView(116), 1); + ASSERT_EQ(hView(118), 1); + ASSERT_EQ(hView(119), 4); + ASSERT_EQ(hView(121), 1); + ASSERT_EQ(hView(123), 1); + ASSERT_EQ(hView(124), 4); + ASSERT_EQ(hView(126), 1); + ASSERT_EQ(hView(128), 1); + ASSERT_EQ(hView(129), 4); + ASSERT_EQ(hView(131), 1); + ASSERT_EQ(hView(136), 1); + ASSERT_EQ(hView(137), 4); + ASSERT_EQ(hView(139), 1); + ASSERT_EQ(hView(140), 4); + ASSERT_EQ(hView(142), 1); + ASSERT_EQ(hView(143), 4); + ASSERT_EQ(hView(145), 1); + ASSERT_EQ(hView(146), 4); + ASSERT_EQ(hView(153), 1); + ASSERT_EQ(hView(155), 1); + ASSERT_EQ(hView(156), 4); + ASSERT_EQ(hView(158), 1); + ASSERT_EQ(hView(160), 1); + ASSERT_EQ(hView(161), 4); + ASSERT_EQ(hView(163), 1); + ASSERT_EQ(hView(165), 1); + ASSERT_EQ(hView(166), 4); + ASSERT_EQ(hView(168), 1); } } - } } - TYPED_TEST(NedelecSpaceTest, evaluateLoadVector) { - using T = typename TestFixture::value_t; - T tolerance = std::numeric_limits::epsilon() * 10.0; - using NedelecType = typename TestFixture::NedelecType; + using T = typename TestFixture::value_t; + T tolerance = std::numeric_limits::epsilon() * 10.0; + using NedelecType = typename TestFixture::NedelecType; static constexpr std::size_t dim = TestFixture::dim; - - if (ippl::Comm->size() ==1) { - if (dim == 2){ + + if (ippl::Comm->size() == 1) { + if (dim == 2) { auto fModel = this->nedelecSpace.createFEMVector(); - - auto f = fModel.template skeletonCopy>(); - f = ippl::Vector(1.); - + + auto f = fModel.template skeletonCopy>(); + f = ippl::Vector(1.); + ippl::FEMVector out = this->nedelecSpace.evaluateLoadVector(f); - auto view = out.getView(); + auto view = out.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); auto ldom = this->layout.getLocalNDIndex(); - for (size_t elementIndex = 0; elementIndex < 20; ++ elementIndex) { + for (size_t elementIndex = 0; elementIndex < 20; ++elementIndex) { const ippl::Vector global_dofs = this->nedelecSpace.getGlobalDOFIndices(elementIndex); const ippl::Vector vectorIndices = this->nedelecSpace.getFEMVectorDOFIndices(elementIndex, ldom); - for (size_t i = 0; i < NedelecType::numElementDOFs; ++i) { size_t I = global_dofs[i]; if (this->nedelecSpace.isDOFOnBoundary(I)) { @@ -1269,32 +1241,30 @@ TYPED_TEST(NedelecSpaceTest, evaluateLoadVector) { } else { ASSERT_NEAR(hView(vectorIndices<:i:>), 1., tolerance); } - } } } - if (dim == 3){ + if (dim == 3) { auto fModel = this->nedelecSpaceSmall.createFEMVector(); - - auto f = fModel.template skeletonCopy>(); - f = ippl::Vector(1.); - + + auto f = fModel.template skeletonCopy>(); + f = ippl::Vector(1.); + ippl::FEMVector out = this->nedelecSpaceSmall.evaluateLoadVector(f); - auto view = out.getView(); + auto view = out.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); auto ldom = this->layoutSmall.getLocalNDIndex(); - for (size_t elementIndex = 0; elementIndex < 8; ++ elementIndex) { + for (size_t elementIndex = 0; elementIndex < 8; ++elementIndex) { const ippl::Vector global_dofs = this->nedelecSpaceSmall.getGlobalDOFIndices(elementIndex); const ippl::Vector vectorIndices = this->nedelecSpaceSmall.getFEMVectorDOFIndices(elementIndex, ldom); - for (size_t i = 0; i < NedelecType::numElementDOFs; ++i) { size_t I = global_dofs[i]; if (this->nedelecSpaceSmall.isDOFOnBoundary(I)) { @@ -1302,7 +1272,6 @@ TYPED_TEST(NedelecSpaceTest, evaluateLoadVector) { } else { ASSERT_NEAR(hView(vectorIndices<:i:>), 1., tolerance); } - } } } @@ -1311,34 +1280,32 @@ TYPED_TEST(NedelecSpaceTest, evaluateLoadVector) { } } - TYPED_TEST(NedelecSpaceTest, evaluateAx) { - using T = typename TestFixture::value_t; - T tolerance = std::numeric_limits::epsilon() * 100.0; - using NedelecType = typename TestFixture::NedelecType; + using T = typename TestFixture::value_t; + T tolerance = std::numeric_limits::epsilon() * 100.0; + using NedelecType = typename TestFixture::NedelecType; static constexpr std::size_t dim = TestFixture::dim; - if (ippl::Comm->size() ==1) { + if (ippl::Comm->size() == 1) { if (dim == 2) { auto f = DummyFunctor(); - auto x = this->nedelecSpace.createFEMVector(); - x = 1; - ippl::FEMVector out = this->nedelecSpace.evaluateAx(x,f); + auto x = this->nedelecSpace.createFEMVector(); + x = 1; + ippl::FEMVector out = this->nedelecSpace.evaluateAx(x, f); - auto view = out.getView(); + auto view = out.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); auto ldom = this->layout.getLocalNDIndex(); - for (size_t elementIndex = 0; elementIndex < 20; ++ elementIndex) { + for (size_t elementIndex = 0; elementIndex < 20; ++elementIndex) { const ippl::Vector global_dofs = this->nedelecSpace.getGlobalDOFIndices(elementIndex); const ippl::Vector vectorIndices = this->nedelecSpace.getFEMVectorDOFIndices(elementIndex, ldom); - for (size_t i = 0; i < NedelecType::numElementDOFs; ++i) { size_t I = global_dofs[i]; if (this->nedelecSpace.isDOFOnBoundary(I)) { @@ -1352,23 +1319,22 @@ TYPED_TEST(NedelecSpaceTest, evaluateAx) { if (dim == 3) { auto f = DummyFunctor(); - auto x = this->nedelecSpaceSmall.createFEMVector(); - x = 1; - ippl::FEMVector out = this->nedelecSpaceSmall.evaluateAx(x,f); + auto x = this->nedelecSpaceSmall.createFEMVector(); + x = 1; + ippl::FEMVector out = this->nedelecSpaceSmall.evaluateAx(x, f); - auto view = out.getView(); + auto view = out.getView(); auto hView = Kokkos::create_mirror_view(view); Kokkos::deep_copy(hView, view); auto ldom = this->layoutSmall.getLocalNDIndex(); - for (size_t elementIndex = 0; elementIndex < 8; ++ elementIndex) { + for (size_t elementIndex = 0; elementIndex < 8; ++elementIndex) { const ippl::Vector global_dofs = this->nedelecSpaceSmall.getGlobalDOFIndices(elementIndex); const ippl::Vector vectorIndices = this->nedelecSpaceSmall.getFEMVectorDOFIndices(elementIndex, ldom); - for (size_t i = 0; i < NedelecType::numElementDOFs; ++i) { size_t I = global_dofs[i]; if (this->nedelecSpaceSmall.isDOFOnBoundary(I)) { @@ -1378,15 +1344,11 @@ TYPED_TEST(NedelecSpaceTest, evaluateAx) { } } } - } } else { GTEST_SKIP(); } -} - - - +} int main(int argc, char* argv[]) { int success = 1; diff --git a/unit_tests/FEM/QuadrilateralElement.cpp b/unit_tests/FEM/QuadrilateralElement.cpp index e2d814aa3..515f73561 100644 --- a/unit_tests/FEM/QuadrilateralElement.cpp +++ b/unit_tests/FEM/QuadrilateralElement.cpp @@ -17,10 +17,9 @@ class QuadrilateralElementTest>> : public :: void SetUp() override {} public: - using value_t = T; - using point_t = typename ippl::QuadrilateralElement::point_t; - using vertex_points_t = - typename ippl::QuadrilateralElement::vertex_points_t; + using value_t = T; + using point_t = typename ippl::QuadrilateralElement::point_t; + using vertex_points_t = typename ippl::QuadrilateralElement::vertex_points_t; static constexpr unsigned NumQuads = 3; @@ -56,9 +55,8 @@ class QuadrilateralElementTest>> : public :: ippl::QuadrilateralElement quad_element; - const vertex_points_t local_points = { - {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}}; - const point_t local_mid_point = {0.5, 0.5}; + const vertex_points_t local_points = {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}}; + const point_t local_mid_point = {0.5, 0.5}; ippl::Vector quads; }; diff --git a/unit_tests/Field/Field.cpp b/unit_tests/Field/Field.cpp index 505832b5d..b3a1ee6f9 100644 --- a/unit_tests/Field/Field.cpp +++ b/unit_tests/Field/Field.cpp @@ -61,7 +61,7 @@ class FieldTest>> : public ::testing::Test { std::shared_ptr layout; std::array nPoints; std::array domain; - }; +}; template struct VFieldVal { @@ -244,9 +244,10 @@ TYPED_TEST(FieldTest, VolumeIntegral) { auto& field = this->field; /// to avoid error accumulation we increase the tolerance by the number of summands - std::size_t totalNumberOfPoints = std::accumulate(this->nPoints.begin(), this->nPoints.end(), std::size_t{1}, std::multiplies<>{}); + std::size_t totalNumberOfPoints = std::accumulate(this->nPoints.begin(), this->nPoints.end(), + std::size_t{1}, std::multiplies<>{}); - T tol = totalNumberOfPoints * tolerance; + T tol = totalNumberOfPoints * tolerance; const ippl::NDIndex lDom = field->getLayout().getLocalNDIndex(); const int shift = field->getNghost(); diff --git a/unit_tests/Field/FieldSubLayout.cpp b/unit_tests/Field/FieldSubLayout.cpp index 8f16cff98..986456212 100644 --- a/unit_tests/Field/FieldSubLayout.cpp +++ b/unit_tests/Field/FieldSubLayout.cpp @@ -25,13 +25,12 @@ class FieldSubLayoutTest>> : public ::testing using centering_type = typename mesh_type::DefaultCentering; using field_type = ippl::Field; using vfield_type = - ippl::Field, Dim, mesh_type, centering_type, ExecSpace>; - using layout_type = ippl::SubFieldLayout; + ippl::Field, Dim, mesh_type, centering_type, ExecSpace>; + using layout_type = ippl::SubFieldLayout; using testlayout_type = ippl::FieldLayout; FieldSubLayoutTest() : nPoints(getGridSizes()) { - // Calculate the domain size of the original layout // In this test we use a domain of +1 Point in each direction, // which is the domain of the origin layout, @@ -40,17 +39,17 @@ class FieldSubLayoutTest>> : public ::testing unsigned int subDomainReduction = 1; for (unsigned d = 0; d < Dim; d++) { - domain[d] = (nPoints[d]+subDomainReduction) / 32.; + domain[d] = (nPoints[d] + subDomainReduction) / 32.; } std::array originIndices; std::array indices; for (unsigned d = 0; d < Dim; d++) { - originIndices[d] = ippl::Index(nPoints[d]+subDomainReduction); - indices[d] = ippl::Index(nPoints[d]); + originIndices[d] = ippl::Index(nPoints[d] + subDomainReduction); + indices[d] = ippl::Index(nPoints[d]); } auto originOwned = std::make_from_tuple>(originIndices); - auto owned = std::make_from_tuple>(indices); + auto owned = std::make_from_tuple>(indices); ippl::Vector hx; ippl::Vector origin; @@ -59,14 +58,13 @@ class FieldSubLayoutTest>> : public ::testing isParallel.fill(true); for (unsigned d = 0; d < Dim; d++) { - hx[d] = domain[d] / (nPoints[d]+subDomainReduction); + hx[d] = domain[d] / (nPoints[d] + subDomainReduction); origin[d] = 0; } layout = std::make_shared(MPI_COMM_WORLD, originOwned, owned, isParallel); mesh = std::make_shared(owned, hx, origin); field = std::make_shared(*mesh, *layout); - } std::shared_ptr field; @@ -257,9 +255,10 @@ TYPED_TEST(FieldSubLayoutTest, VolumeIntegral) { auto& field = this->field; /// to avoid error accumulation we increase the tolerance by the number of summands - std::size_t totalNumberOfPoints = std::accumulate(this->nPoints.begin(), this->nPoints.end(), std::size_t{1}, std::multiplies<>{}); + std::size_t totalNumberOfPoints = std::accumulate(this->nPoints.begin(), this->nPoints.end(), + std::size_t{1}, std::multiplies<>{}); - T tol = totalNumberOfPoints * tolerance; + T tol = totalNumberOfPoints * tolerance; const ippl::NDIndex lDom = field->getLayout().getLocalNDIndex(); const int shift = field->getNghost(); diff --git a/unit_tests/Field/FieldSubLayoutBC.cpp b/unit_tests/Field/FieldSubLayoutBC.cpp index 66af2c5ec..97cdb3e7d 100644 --- a/unit_tests/Field/FieldSubLayoutBC.cpp +++ b/unit_tests/Field/FieldSubLayoutBC.cpp @@ -27,7 +27,6 @@ class FieldBCTest>> : public ::testing::Test FieldBCTest() : nPoints(getGridSizes()) { - // Calculate the domain size of the original layout // In this test we use a domain of +1 Point in each direction, // which is the domain of the origin layout, @@ -36,17 +35,17 @@ class FieldBCTest>> : public ::testing::Test unsigned int subDomainReduction = 1; for (unsigned d = 0; d < Dim; d++) { - domain[d] = (nPoints[d]+subDomainReduction) / 10; + domain[d] = (nPoints[d] + subDomainReduction) / 10; } std::array originIndices; std::array indices; for (unsigned d = 0; d < Dim; d++) { - originIndices[d] = ippl::Index(nPoints[d]+subDomainReduction); - indices[d] = ippl::Index(nPoints[d]); + originIndices[d] = ippl::Index(nPoints[d] + subDomainReduction); + indices[d] = ippl::Index(nPoints[d]); } auto originOwned = std::make_from_tuple>(originIndices); - auto owned = std::make_from_tuple>(indices); + auto owned = std::make_from_tuple>(indices); ippl::Vector hx; ippl::Vector origin; @@ -55,7 +54,7 @@ class FieldBCTest>> : public ::testing::Test isParallel.fill(true); // Specifies SERIAL, PARALLEL dims for (unsigned int d = 0; d < Dim; d++) { - hx[d] = domain[d] / (nPoints[d]+subDomainReduction); + hx[d] = domain[d] / (nPoints[d] + subDomainReduction); origin[d] = 0; } diff --git a/unit_tests/Field/HaloSubLayout.cpp b/unit_tests/Field/HaloSubLayout.cpp index 1977c7c0c..6de850787 100644 --- a/unit_tests/Field/HaloSubLayout.cpp +++ b/unit_tests/Field/HaloSubLayout.cpp @@ -24,21 +24,20 @@ class HaloTest>> : public ::testing::Test { HaloTest() : nPoints(getGridSizes()) { - unsigned int subDomainReduction = 1; for (unsigned d = 0; d < Dim; d++) { - domain[d] = (nPoints[d]+subDomainReduction) / 10; + domain[d] = (nPoints[d] + subDomainReduction) / 10; } std::array originIndices; std::array indices; for (unsigned d = 0; d < Dim; d++) { - originIndices[d] = ippl::Index(nPoints[d]+subDomainReduction); - indices[d] = ippl::Index(nPoints[d]); + originIndices[d] = ippl::Index(nPoints[d] + subDomainReduction); + indices[d] = ippl::Index(nPoints[d]); } auto originOwned = std::make_from_tuple>(originIndices); - auto owned = std::make_from_tuple>(indices); + auto owned = std::make_from_tuple>(indices); ippl::Vector hx; ippl::Vector origin; @@ -46,7 +45,7 @@ class HaloTest>> : public ::testing::Test { std::array isParallel; isParallel.fill(true); // Specifies SERIAL, PARALLEL dims for (unsigned d = 0; d < Dim; d++) { - hx[d] = domain[d] / (nPoints[d]+subDomainReduction); + hx[d] = domain[d] / (nPoints[d] + subDomainReduction); origin[d] = 0; } diff --git a/unit_tests/PIC/ORB.cpp b/unit_tests/PIC/ORB.cpp index 7debb8cd2..d6a5d184b 100644 --- a/unit_tests/PIC/ORB.cpp +++ b/unit_tests/PIC/ORB.cpp @@ -151,7 +151,7 @@ TYPED_TEST(ORBTest, Charge) { typename TestFixture::value_type tol = tolerance; double charge = 0.5; - bunch->Q = charge/this->nParticles; + bunch->Q = charge / this->nParticles; bunch->update(); @@ -164,7 +164,6 @@ TYPED_TEST(ORBTest, Charge) { double totalCharge = field->sum(); ASSERT_NEAR((charge - totalCharge), 0., tol); - } int main(int argc, char* argv[]) { diff --git a/unit_tests/PIC/PIC.cpp b/unit_tests/PIC/PIC.cpp index a49c4c5a9..f5fe369bf 100644 --- a/unit_tests/PIC/PIC.cpp +++ b/unit_tests/PIC/PIC.cpp @@ -66,7 +66,7 @@ class PICTest>> : public ::testing::Test { field = std::make_unique(mesh, layout); - playout_ptr = std::make_shared(layout,mesh); + playout_ptr = std::make_shared(layout, mesh); bunch = std::make_shared(*playout_ptr); diff --git a/unit_tests/Particle/GatherScatterTest.cpp b/unit_tests/Particle/GatherScatterTest.cpp index faf3c3222..0db7306ae 100644 --- a/unit_tests/Particle/GatherScatterTest.cpp +++ b/unit_tests/Particle/GatherScatterTest.cpp @@ -9,14 +9,15 @@ // #include "Ippl.h" -#include "TestUtils.h" -#include "gtest/gtest.h" -#include -#include -#include #include #include +#include +#include +#include + +#include "TestUtils.h" +#include "gtest/gtest.h" // A helper needed to reduce over a hash_type. // This is needed, since Kokkos kernels apparently @@ -25,15 +26,16 @@ struct ComputeTotalChargeLambda { Kokkos::View viewQ; Kokkos::View hash; - ComputeTotalChargeLambda(Kokkos::View viewQ_, Kokkos::View hash_) - : viewQ(viewQ_), hash(hash_) {} + ComputeTotalChargeLambda(Kokkos::View viewQ_, Kokkos::View hash_) + : viewQ(viewQ_) + , hash(hash_) {} KOKKOS_INLINE_FUNCTION void operator()(const size_t i, double& val) const { val += viewQ(hash(i)); } }; -// A simple bunch_type holding a charge attribute +// A simple bunch_type holding a charge attribute template struct Bunch : public ippl::ParticleBase { Bunch(PLayout& playout) @@ -42,7 +44,8 @@ struct Bunch : public ippl::ParticleBase { } ~Bunch() = default; - typedef ippl::ParticleAttrib charge_container_type; + typedef ippl::ParticleAttrib + charge_container_type; charge_container_type Q; }; @@ -52,30 +55,30 @@ class GatherScatterTest; template class GatherScatterTest>> : public ::testing::Test { public: - using scalar_type = T; - using exec_space = ExecSpace; + using scalar_type = T; + using exec_space = ExecSpace; static const unsigned dim = Dim; - using flayout_type = ippl::FieldLayout; - using mesh_type = ippl::UniformCartesian; - using playout_type = ippl::ParticleSpatialLayout; - using bunch_type = Bunch; + using flayout_type = ippl::FieldLayout; + using mesh_type = ippl::UniformCartesian; + using playout_type = ippl::ParticleSpatialLayout; + using bunch_type = Bunch; // Domain parameters: use a high resolution grid so that cells are small. std::array nPoints; std::array domain; flayout_type layout; mesh_type mesh; - std::shared_ptr playout; + std::shared_ptr playout; std::shared_ptr bunch; // Particle counts for the tests. - size_t nGather = 10; // for gather test: local particles per rank + size_t nGather = 10; // for gather test: local particles per rank size_t nScatter = static_cast(std::pow(64, Dim)); // for scatter tests // Store cell sizes (hx) for use in generating positions. T hx[Dim]; - GatherScatterTest() { } + GatherScatterTest() {} void SetUp() override { // Use a high-resolution grid (e.g. 512 cells per dimension) @@ -91,13 +94,13 @@ class GatherScatterTest>> : public ::testing: std::array isParallel; isParallel.fill(true); auto owned_tu = std::make_from_tuple>(owned); - layout = flayout_type(MPI_COMM_WORLD, owned_tu, isParallel); + layout = flayout_type(MPI_COMM_WORLD, owned_tu, isParallel); ippl::Vector hx_vec; ippl::Vector origin; for (size_t d = 0; d < Dim; d++) { hx_vec[d] = domain[d] / nPoints[d]; - hx[d] = hx_vec[d]; // store cell size for distribution + hx[d] = hx_vec[d]; // store cell size for distribution origin[d] = 0; } mesh = mesh_type(owned_tu, hx_vec, origin); @@ -138,30 +141,31 @@ class GatherScatterTest>> : public ::testing: } }; -using TestTypes = ::testing::Types< - Parameters>, - Parameters>, - Parameters>//, - //Parameters>, - //Parameters>, - //Parameters> ->; +using TestTypes = ::testing::Types>, + Parameters>, + Parameters> //, + // Parameters>, + // Parameters>, + // Parameters> + >; TYPED_TEST_SUITE(GatherScatterTest, TestTypes); // -// GatherTest: +// GatherTest: // First, set each local Q to 10.0. -// Then, call gather with addToAttribute = false so that Q becomes 1.0 (should replace value with 1.0). -// If Q != 0, then the values were 1. not replaced and 2. not correctly gathered from the field. -// Note: for a constant field, there should not be an error during linear interpolation. +// Then, call gather with addToAttribute = false so that Q becomes 1.0 (should replace value +// with 1.0). If Q != 0, then the values were 1. not replaced and 2. not correctly gathered from the +// field. Note: for a constant field, there should not be an error during linear interpolation. // TYPED_TEST(GatherScatterTest, GatherTestReplace) { const size_t n = this->nGather; this->fillRandomPositions(n); this->fillAttributeQ(10.0); - using Mesh_t = typename TestFixture::mesh_type; - using FieldType = ippl::Field; + using Mesh_t = typename TestFixture::mesh_type; + using FieldType = + ippl::Field; FieldType field; field.initialize(this->mesh, this->layout); field = 1.0; @@ -178,7 +182,7 @@ TYPED_TEST(GatherScatterTest, GatherTestReplace) { } // -// GatherTest: +// GatherTest: // First, set each local Q to 1.0. // Then, call gather with addToAttribute = true so that Q becomes 2.0 (should add 1.0 per particle). // @@ -187,8 +191,10 @@ TYPED_TEST(GatherScatterTest, GatherTestIncrement) { this->fillRandomPositions(n); this->fillAttributeQ(1.0); - using Mesh_t = typename TestFixture::mesh_type; - using FieldType = ippl::Field; + using Mesh_t = typename TestFixture::mesh_type; + using FieldType = + ippl::Field; FieldType field; field.initialize(this->mesh, this->layout); field = 1.0; @@ -216,46 +222,49 @@ TYPED_TEST(GatherScatterTest, ScatterSimpleTest) { this->fillAttributeQ(1.0); // Create and initialize a field/mesh. - using Mesh_t = typename TestFixture::mesh_type; - using FieldType = ippl::Field; + using Mesh_t = typename TestFixture::mesh_type; + using FieldType = + ippl::Field; FieldType field; field.initialize(this->mesh, this->layout); - + field = 0.0; // Perform the simple scatter operation (extended functionality is tested below). scatter(this->bunch->Q, field, this->bunch->R); // Compute the total charge in the field and from the particles. - double total_field = field.sum(); + double total_field = field.sum(); double total_particles = this->bunch->Q.sum(); // Check that the scattered field conserves charge. ASSERT_NEAR(total_field, total_particles, 1e-6); } - // -// ScatterCustomRangeTest: +// ScatterCustomRangeTest: // Set Q = 1.0 for all particles and scatter only a subset defined by a custom range policy. // Then compare the total charge in the field to the expected value. // TYPED_TEST(GatherScatterTest, ScatterCustomRangeTest) { const size_t n = this->nScatter; - if(n % ippl::Comm->size() != 0) { + if (n % ippl::Comm->size() != 0) { GTEST_SKIP() << "nScatter not divisible by number of ranks."; } this->fillRandomPositions(n); this->fillAttributeQ(1.0); - using Mesh_t = typename TestFixture::mesh_type; - using FieldType = ippl::Field; + using Mesh_t = typename TestFixture::mesh_type; + using FieldType = + ippl::Field; FieldType field; field.initialize(this->mesh, this->layout); field = 0.0; - size_t rank = ippl::Comm->rank(); - size_t nLoc = this->bunch->getLocalNum(); + size_t rank = ippl::Comm->rank(); + size_t nLoc = this->bunch->getLocalNum(); size_t NScattered = nLoc / 2 + rank; double Q_total = 1.0 * NScattered; @@ -269,7 +278,7 @@ TYPED_TEST(GatherScatterTest, ScatterCustomRangeTest) { } // -// ScatterCustomHashTest: +// ScatterCustomHashTest: // Assign random charges (in [0.5, 1.5]), create and shuffle an index array, // use it as a custom hash, scatter the first NScattered particles accordingly, // and compare the field’s total charge to the expected total. @@ -280,10 +289,10 @@ TYPED_TEST(GatherScatterTest, ScatterCustomHashTest) { GTEST_SKIP() << "nScatter not divisible by number of ranks."; } this->fillRandomPositions(n); - + size_t rank = ippl::Comm->rank(); - size_t nLoc = this->bunch->getLocalNum(); // since update() might change number of particles - size_t NScattered = nLoc / 2 + rank; // can be anything + size_t nLoc = this->bunch->getLocalNum(); // since update() might change number of particles + size_t NScattered = nLoc / 2 + rank; // can be anything // Assign random charges to particles std::mt19937_64 eng(42); @@ -295,8 +304,10 @@ TYPED_TEST(GatherScatterTest, ScatterCustomHashTest) { Kokkos::deep_copy(this->bunch->Q.getView(), Q_host); // Create and initialize a field/mesh. - using Mesh_t = typename TestFixture::mesh_type; - using FieldType = ippl::Field; + using Mesh_t = typename TestFixture::mesh_type; + using FieldType = + ippl::Field; FieldType field; field.initialize(this->mesh, this->layout); field = 0.0; @@ -315,15 +326,16 @@ TYPED_TEST(GatherScatterTest, ScatterCustomHashTest) { } Kokkos::deep_copy(hash, hash_host); - // First compute the total charge of the first NScattered particles as determined by the hash map + // First compute the total charge of the first NScattered particles as determined by the hash + // map double Q_total = 0.0; - auto viewQ = this->bunch->Q.getView(); + auto viewQ = this->bunch->Q.getView(); ComputeTotalChargeLambda lambda(viewQ, hash); - Kokkos::parallel_reduce("computeTotalCharge", - Kokkos::RangePolicy(0, NScattered), - lambda, Q_total); - /*Kokkos::parallel_reduce("computeTotalCharge", + Kokkos::parallel_reduce("computeTotalCharge", + Kokkos::RangePolicy(0, NScattered), + lambda, Q_total); + /*Kokkos::parallel_reduce("computeTotalCharge", Kokkos::RangePolicy(0, NScattered), KOKKOS_LAMBDA(const size_t i, double& val) { val += viewQ(hash(i)); diff --git a/unit_tests/Particle/ParticleSendRecv.cpp b/unit_tests/Particle/ParticleSendRecv.cpp index 912b4a58e..d3bc134d1 100644 --- a/unit_tests/Particle/ParticleSendRecv.cpp +++ b/unit_tests/Particle/ParticleSendRecv.cpp @@ -64,10 +64,10 @@ class ParticleSendRecv>> : public ::testing:: origin[d] = 0; } - layout = flayout_type(MPI_COMM_WORLD, owned, isParallel); - mesh = mesh_type(owned, hx, origin); + layout = flayout_type(MPI_COMM_WORLD, owned, isParallel); + mesh = mesh_type(owned, hx, origin); playout_ptr = std::make_shared(layout, mesh); - bunch = std::make_shared(*playout_ptr); + bunch = std::make_shared(*playout_ptr); using BC = ippl::BC; diff --git a/unit_tests/TestUtils.h b/unit_tests/TestUtils.h index e2a42628a..75da0f635 100644 --- a/unit_tests/TestUtils.h +++ b/unit_tests/TestUtils.h @@ -86,7 +86,7 @@ struct TestForTypes> { * @tparam T precision */ template -constexpr T tolerance = 10.*Kokkos::Experimental::epsilon_v; +constexpr T tolerance = 10. * Kokkos::Experimental::epsilon_v; /*! * Verifies that two values are equal to the correct level of precision