The OpenMP kernel distributes independent cell updates among CPU threads while preserving phase order. Here is its parallel region, with array pointers and dimensions prepared before entry:
#pragma omp parallel \ default(none) \ firstprivate(Hy, Ez, Ch1, Ch2, Ce1, Ce2, width, nsteps) \ shared(sim) { for (size_t n = 0; n < nsteps; n++) { // Update Hy #pragma omp for schedule(static) for (size_t k = 0; k < width - 1; k++) { Hy[k] = Ch1[k] * Hy[k] + Ch2[k] * (Ez[k + 1] - Ez[k]); } // Update Ez #pragma omp for schedule(static) for (size_t k = 1; k < width; k++) { Ez[k] = Ce1[k] * Ez[k] + Ce2[k] * (Hy[k] - Hy[k - 1]); } // Inject Ez source #pragma omp single { Fdtd_EzSourcesApply(sim->fsim_sources, sim); Fdtd_EzStateNextStep(sim->fsim_state); } } }
Each magnetic iteration writes a different Hy[k]. The electric loop reads the completed magnetic phase, including values updated by other threads. The implicit barriers make those reads safe.
The single block applies each source and increments the shared counter once. Select this path with --set-accel=openmp or Fdtd_EzSimSetAccel(). The library does not automatically switch to serial execution for small grids; benchmark the work per thread and synchronization costs.
Source: fdtd_ez_kernels.c.