LCOV - code coverage report
Current view: top level - src/MaxwellSolvers - StandardFDTDSolver.hpp (source / functions) Coverage Total Hit
Test: final_report.info Lines: 0.0 % 65 0
Test Date: 2025-07-09 17:06:48 Functions: 0.0 % 4 0

            Line data    Source code
       1              : /**
       2              :  * @file StandardFDTDSolver.hpp
       3              :  * @brief Impelmentation of the StandardFDTDSolver class functions.
       4              :  */
       5              : 
       6              : namespace ippl {
       7              : 
       8              :     /**
       9              :      * @brief Constructor for the StandardFDTDSolver class.
      10              :      *
      11              :      * This constructor initializes the StandardFDTDSolver with the given source field and
      12              :      * electromagnetic fields and initializes the solver.
      13              :      *
      14              :      * @param source The source field.
      15              :      * @param E The electric field.
      16              :      * @param B The magnetic field.
      17              :      */
      18              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      19            0 :     StandardFDTDSolver<EMField, SourceField, boundary_conditions>::StandardFDTDSolver(
      20              :         SourceField& source, EMField& E, EMField& B)
      21            0 :         : FDTDSolverBase<EMField, SourceField, boundary_conditions>(source, E, B) {
      22            0 :         initialize();
      23            0 :     }
      24              : 
      25              :     /**
      26              :      * @brief Advances the simulation by one time step.
      27              :      *
      28              :      * This function updates the fields by one time step using the FDTD method.
      29              :      * It calculates the new field values based on the current and previous field values,
      30              :      * as well as the source field. The boundary conditions are applied after the update.
      31              :      */
      32              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      33            0 :     void StandardFDTDSolver<EMField, SourceField, boundary_conditions>::step() {
      34            0 :         const auto& ldom       = this->layout_mp->getLocalNDIndex();
      35            0 :         const int nghost       = this->A_n.getNghost();
      36            0 :         const auto aview       = this->A_n.getView();
      37            0 :         const auto anp1view    = this->A_np1.getView();
      38            0 :         const auto anm1view    = this->A_nm1.getView();
      39            0 :         const auto source_view = Maxwell<EMField, SourceField>::JN_mp->getView();
      40              : 
      41              :         // Calculate the coefficients for the nondispersive update
      42            0 :         const scalar a1 = scalar(2)
      43            0 :                           * (scalar(1) - Kokkos::pow(this->dt / this->hr_m[0], 2)
      44            0 :                              - Kokkos::pow(this->dt / this->hr_m[1], 2)
      45            0 :                              - Kokkos::pow(this->dt / this->hr_m[2], 2));
      46            0 :         const scalar a2               = Kokkos::pow(this->dt / this->hr_m[0], 2);
      47            0 :         const scalar a4               = Kokkos::pow(this->dt / this->hr_m[1], 2);
      48            0 :         const scalar a6               = Kokkos::pow(this->dt / this->hr_m[2], 2);
      49            0 :         const scalar a8               = Kokkos::pow(this->dt, 2);
      50            0 :         Vector<uint32_t, Dim> true_nr = this->nr_m;
      51            0 :         true_nr += (nghost * 2);
      52            0 :         constexpr uint32_t one_if_absorbing_otherwise_0 =
      53              :             boundary_conditions == absorbing
      54              :                 ? 1
      55              :                 : 0;  // 1 if absorbing, 0 otherwise, indicates the start index of the field
      56              : 
      57              :         // Update the field values
      58            0 :         Kokkos::parallel_for(
      59            0 :             "Source field update", ippl::getRangePolicy(aview, nghost),
      60            0 :             KOKKOS_LAMBDA(const size_t i, const size_t j, const size_t k) {
      61              :                 // global indices
      62            0 :                 const uint32_t ig = i + ldom.first()[0];
      63            0 :                 const uint32_t jg = j + ldom.first()[1];
      64            0 :                 const uint32_t kg = k + ldom.first()[2];
      65              :                 // check if at a boundary of the field
      66            0 :                 uint32_t val =
      67            0 :                     uint32_t(ig == one_if_absorbing_otherwise_0)
      68            0 :                     + (uint32_t(jg == one_if_absorbing_otherwise_0) << 1)
      69            0 :                     + (uint32_t(kg == one_if_absorbing_otherwise_0) << 2)
      70            0 :                     + (uint32_t(ig == true_nr[0] - one_if_absorbing_otherwise_0 - 1) << 3)
      71            0 :                     + (uint32_t(jg == true_nr[1] - one_if_absorbing_otherwise_0 - 1) << 4)
      72            0 :                     + (uint32_t(kg == true_nr[2] - one_if_absorbing_otherwise_0 - 1) << 5);
      73              :                 // update the interior field values
      74            0 :                 if (val == 0) {
      75            0 :                     SourceVector_t interior = -anm1view(i, j, k) + a1 * aview(i, j, k)
      76            0 :                                               + a2 * (aview(i + 1, j, k) + aview(i - 1, j, k))
      77            0 :                                               + a4 * (aview(i, j + 1, k) + aview(i, j - 1, k))
      78            0 :                                               + a6 * (aview(i, j, k + 1) + aview(i, j, k - 1))
      79            0 :                                               + a8 * source_view(i, j, k);
      80            0 :                     anp1view(i, j, k) = interior;
      81            0 :                 }
      82              :             });
      83            0 :         Kokkos::fence();
      84            0 :         this->A_np1.fillHalo();
      85            0 :         this->applyBCs();
      86            0 :     }
      87              : 
      88              :     /**
      89              :      * @brief Initializes the solver.
      90              :      *
      91              :      * This function initializes the solver by setting up the layout, mesh, and fields.
      92              :      * It retrieves the mesh spacing, domain, and mesh size, and initializes the fields to zero.
      93              :      */
      94              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      95            0 :     void StandardFDTDSolver<EMField, SourceField, boundary_conditions>::initialize() {
      96              :         // get layout and mesh
      97            0 :         this->layout_mp = &(this->JN_mp->getLayout());
      98            0 :         this->mesh_mp   = &(this->JN_mp->get_mesh());
      99              : 
     100              :         // get mesh spacing, timestep, domain, and mesh size
     101            0 :         this->hr_m = this->mesh_mp->getMeshSpacing();
     102            0 :         this->dt   = this->hr_m[0] / 2;
     103            0 :         for (unsigned int i = 0; i < Dim; ++i) {
     104            0 :             this->dt = std::min(this->dt, this->hr_m[i] / 2);
     105              :         }
     106            0 :         this->domain_m = this->layout_mp->getDomain();
     107            0 :         for (unsigned int i = 0; i < Dim; ++i)
     108            0 :             this->nr_m[i] = this->domain_m[i].length();
     109              : 
     110              :         // initialize fields
     111            0 :         this->A_nm1.initialize(*(this->mesh_mp), *(this->layout_mp));
     112            0 :         this->A_n.initialize(*(this->mesh_mp), *(this->layout_mp));
     113            0 :         this->A_np1.initialize(*(this->mesh_mp), *(this->layout_mp));
     114              : 
     115              :         // Initialize fields to zero
     116            0 :         this->A_nm1 = 0.0;
     117            0 :         this->A_n   = 0.0;
     118            0 :         this->A_np1 = 0.0;
     119              : 
     120              :         // set the mesh domain
     121              :         if constexpr (boundary_conditions == periodic) {
     122            0 :             this->setPeriodicBoundaryConditions();
     123              :         }
     124            0 :     }
     125              : }  // namespace ippl
        

Generated by: LCOV version 2.0-1