dirac_solver 0.0.1
A Dirac ecuation Solver
Cargando...
Buscando...
Nada coincide
Referencia de la clase FDTDLeapfrogIntegrator

Implementación concreta de TimeIntegrator mediante el esquema FDTD de salto de rana (Leapfrog). Más...

#include <TimeIntegrator.h>

+ Diagrama de herencia de FDTDLeapfrogIntegrator
+ Diagrama de colaboración de FDTDLeapfrogIntegrator:

Métodos públicos

 FDTDLeapfrogIntegrator (py::array_t< std::complex< double >, py::array::c_style|py::array::forcecast > initial_psi, const Grid &grid, std::shared_ptr< Potential > potential, std::shared_ptr< BoundaryCondition > boundary_condition, double dt, double mass)
 Constructor principal del integrador Leapfrog.
 
void step () override
 Avanza un paso de tiempo completo según el esquema FDTD Leapfrog.
 
std::string get_name () const override
 Devuelve el nombre del integrador.
 
py::array_t< std::complex< double > > get_psi () const
 Devuelve la función de onda actual en formato NumPy.
 
- Métodos públicos heredados de TimeIntegrator
virtual ~TimeIntegrator ()=default
 

Descripción detallada

Implementación concreta de TimeIntegrator mediante el esquema FDTD de salto de rana (Leapfrog).

Este integrador emplea el método Finite-Difference Time-Domain (FDTD) con un esquema temporal tipo "leapfrog", ampliamente usado para ecuaciones de onda relativistas como la ecuación de Dirac.

El algoritmo alterna entre los estados ψ(t - Δt), ψ(t) y ψ(t + Δt) para avanzar la solución sin necesidad de almacenar todas las configuraciones temporales.

Características principales

  • Soporta dominios 1D, 2D y 3D.
  • Compatible con potenciales arbitrarios Potential.
  • Integra condiciones de frontera mediante la clase BoundaryCondition.
  • Expone la función de onda al entorno Python vía pybind11.

Referencias

  • Taflove, A., & Hagness, S. C. (2005). Computational Electrodynamics: The Finite-Difference Time-Domain Method.
  • Thaller, B. (1992). The Dirac Equation.

Documentación de constructores y destructores

◆ FDTDLeapfrogIntegrator()

FDTDLeapfrogIntegrator::FDTDLeapfrogIntegrator ( py::array_t< std::complex< double >, py::array::c_style|py::array::forcecast >  initial_psi,
const Grid grid,
std::shared_ptr< Potential potential,
std::shared_ptr< BoundaryCondition boundary_condition,
double  dt,
double  mass 
)
inline

Constructor principal del integrador Leapfrog.

Inicializa la función de onda y los buffers de tiempo (ψ_prev, ψ_curr, ψ_next), validando dimensiones y preparando los parámetros del algoritmo.

Parámetros
initial_psiEstado inicial del campo espinorial, como array NumPy de forma (N, 4).
gridObjeto de tipo Grid que define la geometría de la simulación.
potentialPotencial escalar aplicado a la partícula.
boundary_conditionCondición de frontera a aplicar (e.g. periódica, absorbente).
dtPaso temporal.
massMasa de la partícula.
Excepciones
std::runtime_errorSi la forma del array de entrada no es (N, 4) o si el número de puntos no coincide con la malla.
94 : grid_(grid), potential_(potential), boundary_condition_(boundary_condition), dt_(dt), mass_(mass)
95 {
96 // Validación de dimensiones de entrada
97 py::buffer_info psi_info = initial_psi.request();
98 if (psi_info.ndim != 2 || psi_info.shape[1] != 4) {
99 throw std::runtime_error("El psi inicial debe ser un array de NumPy de forma (N, 4)");
100 }
101 if (static_cast<size_t>(psi_info.shape[0]) != grid_.get_total_points()) {
102 throw std::runtime_error("El número de puntos en psi debe coincidir con el total de puntos de la malla.");
103 }
104
105 // Asignación de memoria
106 size_t n_points = grid_.get_total_points();
107 psi_curr_.resize(n_points);
108 psi_prev_.resize(n_points);
109 psi_next_.resize(n_points);
110
111 // Copiar datos desde el array de NumPy a psi_curr_
112 auto ptr = static_cast<Dirac::complex*>(psi_info.ptr);
113 for (size_t i = 0; i < n_points; ++i)
114 for (size_t j = 0; j < 4; ++j)
115 psi_curr_[i].components[j] = ptr[i * 4 + j];
116
117 // Inicialización básica del buffer previo
118 psi_prev_ = psi_curr_;
119 }
size_t get_total_points() const
Calcula el número total de puntos en la malla.
Definition Grid.h:47
std::complex< double > complex
Definition DiracMatrices.h:9

Documentación de funciones miembro

◆ get_name()

std::string FDTDLeapfrogIntegrator::get_name ( ) const
inlineoverridevirtual

Devuelve el nombre del integrador.

Devuelve
La cadena "FDTDLeapfrogIntegrator".

Implementa TimeIntegrator.

209 {
210 return "FDTDLeapfrogIntegrator";
211 }

◆ get_psi()

py::array_t< std::complex< double > > FDTDLeapfrogIntegrator::get_psi ( ) const
inline

Devuelve la función de onda actual en formato NumPy.

Convierte internamente el vector de spinors psi_curr_ a un array bidimensional compatible con Python, de forma (N, 4).

Devuelve
Un objeto py::array_t<std::complex<double>> con la función de onda actual.
221 {
222 py::array_t<std::complex<double>> result({grid_.get_total_points(), 4ul});
223 auto buf = result.request();
224 auto* ptr = static_cast<std::complex<double>*>(buf.ptr);
225
226 for (size_t i = 0; i < grid_.get_total_points(); ++i)
227 for (size_t j = 0; j < 4; ++j)
228 ptr[i * 4 + j] = psi_curr_[i].components[j];
229
230 return result;
231 }

◆ step()

void FDTDLeapfrogIntegrator::step ( )
inlineoverridevirtual

Avanza un paso de tiempo completo según el esquema FDTD Leapfrog.

Calcula el operador espacial y el término local del Hamiltoniano para cada punto de la malla, aplicando las matrices de Dirac correspondientes a cada dimensión. Luego, actualiza ψ(t+Δt) a partir de ψ(t) y ψ(t-Δt).

También aplica la condición de frontera definida por boundary_condition_.

Nota
Actualmente implementa derivadas centrales de segundo orden y admite condiciones periódicas o absorbentes.

Implementa TimeIntegrator.

133 {
134 size_t n_points = grid_.get_total_points();
135 const auto& shape = grid_.get_shape();
136 const auto& spacing = grid_.get_spacing();
137 bool is_periodic = (boundary_condition_->get_name() == "PeriodicBoundary");
138
139 for (size_t i = 0; i < n_points; ++i) {
140 Dirac::Spinor h_spatial_psi;
141
142 // --- Operador diferencial espacial según la dimensionalidad ---
143 if (grid_.get_dim() == 1) {
144 size_t i_prev = (is_periodic && i == 0) ? n_points - 1 : i - 1;
145 size_t i_next = (is_periodic && i == n_points - 1) ? 0 : i + 1;
146 h_spatial_psi = Dirac::multiply(Dirac::alpha_z, psi_curr_[i_next] - psi_curr_[i_prev]);
147 h_spatial_psi = (Dirac::complex(0, -1.0) / (2.0 * spacing[0])) * h_spatial_psi;
148 }
149 else if (grid_.get_dim() == 2) {
150 size_t nx = shape[0];
151 size_t ny = shape[1];
152 size_t ix = i % nx;
153 size_t iy = i / nx;
154 size_t ix_prev = (is_periodic && ix == 0) ? nx - 1 : ix - 1;
155 size_t ix_next = (is_periodic && ix == nx - 1) ? 0 : ix + 1;
156 size_t iy_prev = (is_periodic && iy == 0) ? ny - 1 : iy - 1;
157 size_t iy_next = (is_periodic && iy == ny - 1) ? 0 : iy + 1;
158
159 Dirac::Spinor dx_psi = Dirac::multiply(Dirac::alpha_x, psi_curr_[iy * nx + ix_next] - psi_curr_[iy * nx + ix_prev]);
160 Dirac::Spinor dy_psi = Dirac::multiply(Dirac::alpha_y, psi_curr_[iy_next * nx + ix] - psi_curr_[iy_prev * nx + ix]);
161 h_spatial_psi = (Dirac::complex(0, -1.0) / (2.0 * spacing[0])) * dx_psi +
162 (Dirac::complex(0, -1.0) / (2.0 * spacing[1])) * dy_psi;
163 }
164 else if (grid_.get_dim() == 3) {
165 size_t nx = shape[0];
166 size_t ny = shape[1];
167 size_t nz = shape[2];
168 size_t ix = i % nx;
169 size_t iy = (i / nx) % ny;
170 size_t iz = i / (nx * ny);
171
172 size_t ix_prev = (is_periodic && ix == 0) ? nx - 1 : ix - 1;
173 size_t ix_next = (is_periodic && ix == nx - 1) ? 0 : ix + 1;
174 size_t iy_prev = (is_periodic && iy == 0) ? ny - 1 : iy - 1;
175 size_t iy_next = (is_periodic && iy == ny - 1) ? 0 : iy + 1;
176 size_t iz_prev = (is_periodic && iz == 0) ? nz - 1 : iz - 1;
177 size_t iz_next = (is_periodic && iz == nz - 1) ? 0 : iz + 1;
178
179 Dirac::Spinor dx_psi = Dirac::multiply(Dirac::alpha_x, psi_curr_[iz * nx * ny + iy * nx + ix_next] - psi_curr_[iz * nx * ny + iy * nx + ix_prev]);
180 Dirac::Spinor dy_psi = Dirac::multiply(Dirac::alpha_y, psi_curr_[iz * nx * ny + iy_next * nx + ix] - psi_curr_[iz * nx * ny + iy_prev * nx + ix]);
181 Dirac::Spinor dz_psi = Dirac::multiply(Dirac::alpha_z, psi_curr_[(iz_next * nx * ny) + iy * nx + ix] - psi_curr_[(iz_prev * nx * ny) + iy * nx + ix]);
182 h_spatial_psi = (Dirac::complex(0, -1.0) / (2.0 * spacing[0])) * dx_psi +
183 (Dirac::complex(0, -1.0) / (2.0 * spacing[1])) * dy_psi +
184 (Dirac::complex(0, -1.0) / (2.0 * spacing[2])) * dz_psi;
185 }
186
187 // --- Término local del Hamiltoniano ---
188 std::vector<double> coords = grid_.get_coords(i);
189 double v_at_i = potential_->evaluate(coords);
190 Dirac::Spinor h_local_psi = mass_ * Dirac::multiply(Dirac::beta, psi_curr_[i]) + v_at_i * psi_curr_[i];
191
192 // --- Actualización temporal ---
193 Dirac::Spinor h_psi = h_spatial_psi + h_local_psi;
194 psi_next_[i] = psi_prev_[i] - (Dirac::complex(0, 2.0) * dt_) * h_psi;
195 }
196
197 // Aplicar condición de frontera
198 boundary_condition_->apply(psi_next_, grid_);
199
200 // Rotar buffers de tiempo
201 psi_prev_ = psi_curr_;
202 psi_curr_ = psi_next_;
203 }
size_t get_dim() const
Definition Grid.h:39
std::vector< double > get_coords(size_t index) const
Obtiene las coordenadas espaciales para un índice de malla plano dado.
Definition Grid.h:60
const std::vector< double > & get_spacing() const
Definition Grid.h:41
const std::vector< size_t > & get_shape() const
Definition Grid.h:40
Spinor multiply(const Matrix4x4 &M, const Spinor &s)
Definition DiracMatrices.h:63
const Matrix4x4 alpha_y
Definition DiracMatrices.h:48
const Matrix4x4 alpha_z
Definition DiracMatrices.h:55
const Matrix4x4 alpha_x
Definition DiracMatrices.h:41
const Matrix4x4 beta
Definition DiracMatrices.h:33
Definition DiracMatrices.h:12

La documentación de esta clase está generada del siguiente archivo: