LCOV - code coverage report
Current view: top level - src/MaxwellSolvers - FDTDSolverBase.hpp (source / functions) Coverage Total Hit
Test: report.info Lines: 0.0 % 63 0
Test Date: 2025-06-27 19:43:11 Functions: 0.0 % 14 0
Branches: 0.0 % 110 0

             Branch data     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