LCOV - code coverage report
Current view: top level - src/MaxwellSolvers - FDTDSolverBase.hpp (source / functions) Coverage Total Hit
Test: final_report.info Lines: 0.0 % 63 0
Test Date: 2025-07-18 17:15:09 Functions: 0.0 % 14 0

            Line data    Source code
       1              : //
       2              : // Class FDTDSolverBase
       3              : //  Base class for solvers for Maxwell's equations using the FDTD method
       4              : //
       5              : 
       6              : namespace ippl {
       7              : 
       8              :     /**
       9              :      * @brief Constructor for the FDTDSolverBase class.
      10              :      *
      11              :      * Initializes the solver by setting the source and electromagnetic fields.
      12              :      *
      13              :      * @param source Reference to the source field.
      14              :      * @param E Reference to the electric field.
      15              :      * @param B Reference to the magnetic field.
      16              :      */
      17              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      18            0 :     FDTDSolverBase<EMField, SourceField, boundary_conditions>::FDTDSolverBase(SourceField& source,
      19              :                                                                               EMField& E,
      20            0 :                                                                               EMField& B) {
      21            0 :         Maxwell<EMField, SourceField>::setSources(source);
      22            0 :         Maxwell<EMField, SourceField>::setEMFields(E, B);
      23            0 :     }
      24              : 
      25              :     /**
      26              :      * @brief Solves the FDTD equations.
      27              :      *
      28              :      * Advances the simulation by one time step, shifts the time for the fields, and evaluates the
      29              :      * electric and magnetic fields at the new time.
      30              :      */
      31              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      32            0 :     void FDTDSolverBase<EMField, SourceField, boundary_conditions>::solve() {
      33            0 :         step();
      34            0 :         timeShift();
      35            0 :         evaluate_EB();
      36            0 :     }
      37              : 
      38              :     /**
      39              :      * @brief Sets periodic boundary conditions.
      40              :      *
      41              :      * Configures the solver to use periodic boundary conditions by setting the appropriate boundary
      42              :      * conditions for the fields.
      43              :      */
      44              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      45              :     void
      46            0 :     FDTDSolverBase<EMField, SourceField, boundary_conditions>::setPeriodicBoundaryConditions() {
      47            0 :         typename SourceField::BConds_t vector_bcs;
      48            0 :         auto bcsetter_single = [&vector_bcs]<size_t Idx>(const std::index_sequence<Idx>&) {
      49            0 :             vector_bcs[Idx] = std::make_shared<ippl::PeriodicFace<SourceField>>(Idx);
      50            0 :             return 0;
      51              :         };
      52            0 :         auto bcsetter = [bcsetter_single]<size_t... Idx>(const std::index_sequence<Idx...>&) {
      53            0 :             int x = (bcsetter_single(std::index_sequence<Idx>{}) ^ ...);
      54              :             (void)x;
      55              :         };
      56            0 :         bcsetter(std::make_index_sequence<Dim * 2>{});
      57            0 :         A_n.setFieldBC(vector_bcs);
      58            0 :         A_np1.setFieldBC(vector_bcs);
      59            0 :         A_nm1.setFieldBC(vector_bcs);
      60            0 :     }
      61              : 
      62              :     /**
      63              :      * @brief Shifts the saved fields in time.
      64              :      *
      65              :      * Copies the current field values to the previous time step field and the next time step field
      66              :      * values to the current field.
      67              :      */
      68              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      69            0 :     void FDTDSolverBase<EMField, SourceField, boundary_conditions>::timeShift() {
      70              :         // Look into this, maybe cyclic swap is better
      71            0 :         Kokkos::deep_copy(this->A_nm1.getView(), this->A_n.getView());
      72            0 :         Kokkos::deep_copy(this->A_n.getView(), this->A_np1.getView());
      73            0 :     }
      74              : 
      75              :     /**
      76              :      * @brief Applies the boundary conditions.
      77              :      *
      78              :      * Applies the specified boundary conditions (periodic or absorbing) to the fields.
      79              :      */
      80              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
      81            0 :     void FDTDSolverBase<EMField, SourceField, boundary_conditions>::applyBCs() {
      82              :         if constexpr (boundary_conditions == periodic) {
      83            0 :             A_n.getFieldBC().apply(A_n);
      84            0 :             A_nm1.getFieldBC().apply(A_nm1);
      85            0 :             A_np1.getFieldBC().apply(A_np1);
      86              :         } else {
      87              :             Vector<uint32_t, Dim> true_nr = nr_m;
      88              :             true_nr += (A_n.getNghost() * 2);
      89              :             second_order_mur_boundary_conditions bcs{};
      90              :             bcs.apply(A_n, A_nm1, A_np1, this->dt, true_nr, layout_mp->getLocalNDIndex());
      91              :         }
      92            0 :     }
      93              : 
      94              :     /**
      95              :      * @brief Evaluates the electric and magnetic fields.
      96              :      *
      97              :      * Computes the electric and magnetic fields based on the current, previous, and next time step
      98              :      * field values, as well as the source field.
      99              :      */
     100              :     template <typename EMField, typename SourceField, fdtd_bc boundary_conditions>
     101            0 :     void FDTDSolverBase<EMField, SourceField, boundary_conditions>::evaluate_EB() {
     102            0 :         *(Maxwell<EMField, SourceField>::En_mp)   = typename EMField::value_type(0);
     103            0 :         *(Maxwell<EMField, SourceField>::Bn_mp)   = typename EMField::value_type(0);
     104            0 :         ippl::Vector<scalar, 3> inverse_2_spacing = ippl::Vector<scalar, 3>(0.5) / hr_m;
     105            0 :         const scalar idt                          = scalar(1.0) / dt;
     106            0 :         auto A_np1 = this->A_np1.getView(), A_n = this->A_n.getView(),
     107            0 :              A_nm1  = this->A_nm1.getView();
     108            0 :         auto source = Maxwell<EMField, SourceField>::JN_mp->getView();
     109            0 :         auto Eview  = Maxwell<EMField, SourceField>::En_mp->getView();
     110            0 :         auto Bview  = Maxwell<EMField, SourceField>::Bn_mp->getView();
     111              : 
     112              :         // Calculate the electric and magnetic fields
     113              :         // Curl and grad of ippl are not used here, because we have a 4-component vector and we need
     114              :         // it for the last three components
     115            0 :         Kokkos::parallel_for(
     116            0 :             this->A_n.getFieldRangePolicy(), KOKKOS_LAMBDA(size_t i, size_t j, size_t k) {
     117            0 :                 ippl::Vector<scalar, 3> dAdt;
     118            0 :                 dAdt[0] = (A_np1(i, j, k)[1] - A_n(i, j, k)[1]) * idt;
     119            0 :                 dAdt[1] = (A_np1(i, j, k)[2] - A_n(i, j, k)[2]) * idt;
     120            0 :                 dAdt[2] = (A_np1(i, j, k)[3] - A_n(i, j, k)[3]) * idt;
     121              : 
     122            0 :                 ippl::Vector<scalar, 4> dAdx =
     123            0 :                     (A_n(i + 1, j, k) - A_n(i - 1, j, k)) * inverse_2_spacing[0];
     124            0 :                 ippl::Vector<scalar, 4> dAdy =
     125            0 :                     (A_n(i, j + 1, k) - A_n(i, j - 1, k)) * inverse_2_spacing[1];
     126            0 :                 ippl::Vector<scalar, 4> dAdz =
     127            0 :                     (A_n(i, j, k + 1) - A_n(i, j, k - 1)) * inverse_2_spacing[2];
     128              : 
     129            0 :                 ippl::Vector<scalar, 3> grad_phi{dAdx[0], dAdy[0], dAdz[0]};
     130            0 :                 ippl::Vector<scalar, 3> curlA{
     131            0 :                     dAdy[3] - dAdz[2],
     132            0 :                     dAdz[1] - dAdx[3],
     133            0 :                     dAdx[2] - dAdy[1],
     134              :                 };
     135            0 :                 Eview(i, j, k) = -dAdt - grad_phi;
     136            0 :                 Bview(i, j, k) = curlA;
     137            0 :             });
     138            0 :         Kokkos::fence();
     139            0 :     }
     140              : 
     141              : }  // namespace ippl
        

Generated by: LCOV version 2.0-1