Octopus
propagator_mxll.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 R. Jestaedt, F. Bonafe, H. Appel
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17
18#include "global.h"
19
21 use accel_oct_m
23 use batch_oct_m
25 use cube_oct_m
33 use fft_oct_m
35 use grid_oct_m
36 use global_oct_m
40 use index_oct_m
41 use io_oct_m
46 use math_oct_m
49 use mesh_oct_m
54 use mpi_oct_m
56 use output_oct_m
57 use parser_oct_m
62 use space_oct_m
67
68 implicit none
69
70 private
71 public :: &
90
91 ! The following routines are currently unused, but will be used in the near future.
92 ! In order not to generate warnings about them, we declared them as public
93 public :: &
97
99 logical :: bc_add_ab_region = .false.
100 logical :: bc_zero = .false.
101 logical :: bc_constant = .false.
102 logical :: bc_mirror_pec = .false.
103 logical :: bc_mirror_pmc = .false.
104 logical :: bc_plane_waves = .false.
105 logical :: bc_medium = .false.
106 type(exponential_t) :: te
107 logical :: plane_waves_in_box
108 integer :: tr_etrs_approx
109 end type propagator_mxll_t
110
111 integer, public, parameter :: &
112 RS_TRANS_FORWARD = 1, &
114
115 integer, parameter :: &
116 MXWLL_ETRS_FULL = 0, &
118
119contains
120
121 ! ---------------------------------------------------------
122 subroutine propagator_mxll_init(gr, namespace, st, hm, tr)
123 type(grid_t), intent(in) :: gr
124 type(namespace_t), intent(in) :: namespace
125 type(states_mxll_t), intent(inout) :: st
126 type(hamiltonian_mxll_t), intent(inout) :: hm
127 type(propagator_mxll_t), intent(inout) :: tr
128
129 integer :: idim
130
131 push_sub(propagator_mxll_init)
132
133 call profiling_in("PROPAGATOR_MXLL_INIT")
134
135 do idim = 1, 3
136 select case (hm%bc%bc_type(idim))
137 case (mxll_bc_zero)
138 hm%bc_zero = .true.
139 tr%bc_zero = .true.
140 case (mxll_bc_constant)
141 tr%bc_constant = .true.
142 tr%bc_add_ab_region = .true.
143 hm%bc_constant = .true.
144 hm%bc_add_ab_region = .true.
145 case (mxll_bc_mirror_pec)
146 tr%bc_mirror_pec = .true.
147 hm%bc_mirror_pec = .true.
148 case (mxll_bc_mirror_pmc)
149 tr%bc_mirror_pmc = .true.
150 hm%bc_mirror_pmc = .true.
152 tr%bc_plane_waves = .true.
153 tr%bc_add_ab_region = .true.
154 hm%plane_waves = .true.
155 hm%bc_plane_waves = .true.
156 hm%bc_add_ab_region = .true.
157 end select
158 end do
159
160 if (any(hm%bc%bc_type(1:3) == mxll_bc_constant)) then
161 call td_function_mxll_init(st, namespace, hm)
162 safe_allocate(st%rs_state_const(1:st%dim))
163 st%rs_state_const = m_z0
164 end if
165
166 !%Variable MaxwellTDETRSApprox
167 !%Type integer
168 !%Default no
169 !%Section Maxwell::TD Propagation
170 !%Description
171 !% Whether to perform approximations to the ETRS propagator.
172 !%Option no 0
173 !% No approximations.
174 !%Option const_steps 1
175 !% Use constant current density.
176 !%End
177 call parse_variable(namespace, 'MaxwellTDETRSApprox', mxwll_etrs_full, tr%tr_etrs_approx)
178
179 !%Variable MaxwellPlaneWavesInBox
180 !%Type logical
181 !%Default no
182 !%Section Maxwell
183 !%Description
184 !% Analytic evaluation of the incoming waves inside the box,
185 !% not doing any numerical propagation of Maxwells equations.
186 !%End
187 call parse_variable(namespace, 'MaxwellPlaneWavesInBox', .false., tr%plane_waves_in_box)
188 if (tr%plane_waves_in_box .and. .not. hm%bc%do_plane_waves) then
189 call external_waves_init(hm%bc%plane_wave, namespace)
190 end if
191
192 call messages_print_with_emphasis(namespace=namespace)
194 !tr%te%exp = .true.
195 call exponential_init(tr%te, namespace, full_batch=.true.) ! initialize Maxwell propagator
197 call profiling_out("PROPAGATOR_MXLL_INIT")
200 end subroutine propagator_mxll_init
202 ! ---------------------------------------------------------
203 subroutine mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
204 type(hamiltonian_mxll_t), intent(inout) :: hm
205 type(namespace_t), intent(in) :: namespace
206 type(grid_t), intent(inout) :: gr
207 class(space_t), intent(in) :: space
208 type(states_mxll_t), intent(inout) :: st
209 type(propagator_mxll_t), intent(inout) :: tr
210 type(batch_t), intent(inout) :: rs_stateb
211 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t1(:,:)
212 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t2(:,:)
213 real(real64), intent(in) :: time
214 real(real64), intent(in) :: dt
215
216 integer :: ii, ff_dim, idim, istate, inter_steps
217 real(real64) :: inter_dt, inter_time
218
219
220 logical :: pml_check
221 type(batch_t) :: ff_rs_stateb, ff_rs_state_pmlb
222 type(batch_t) :: ff_rs_inhom_1b, ff_rs_inhom_2b, ff_rs_inhom_meanb
223 complex(real64), allocatable :: rs_state(:, :)
224
225 push_sub(mxll_propagation_step)
226
227 call profiling_in('MXLL_PROPAGATOR_STEP')
228 pml_check = .false.
229
230 if (hm%ma_mx_coupling_apply) then
231 message(1) = "Maxwell-matter coupling not implemented yet"
232 call messages_fatal(1, namespace=namespace)
233 end if
234 safe_allocate(rs_state(gr%np, st%dim))
235
236 if (tr%plane_waves_in_box) then
237 rs_state = m_z0
238 call plane_waves_in_box_calculation(hm%bc, time+dt, gr, gr%der, st, rs_state)
239 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
240 safe_deallocate_a(rs_state)
241 pop_sub(mxll_propagation_step)
242 return
243 end if
244
245 do idim = 1, 3
246 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__cpml) then
247 pml_check = .true.
248 end if
249 end do
250
251 ! this must be called only once, but can not be placed in init routines because PML parameters need to know about dt
252 if (pml_check .and. .not. hm%bc%pml%parameters_initialized) &
253 call bc_mxll_generate_pml_parameters(hm%bc, space, gr, hm%c_factor, dt)
254
255 ff_dim = hm%dim
256
257 ! intermediate step variables
258 inter_steps = 1
259 inter_dt = m_one / inter_steps * dt
260
261 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
262 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
263
264 if (pml_check) then
265 call ff_rs_stateb%copy_to(ff_rs_state_pmlb)
266 end if
267
268 ! first step of Maxwell inhomogeneity propagation with constant current density
269 if ((hm%ma_mx_coupling_apply .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) .and. &
270 tr%tr_etrs_approx == mxwll_etrs_const) then
271 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
272 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
273 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
274
275 do istate = 1, hm%dim
276 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t1(:, istate))
277 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
278 end do
279 call batch_axpby(gr%np, m_half, ff_rs_inhom_2b, m_half, ff_rs_inhom_meanb)
280
281 ! inhomogeneity propagation
282 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_1b)
283 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
284
285 call hamiltonian_mxll_update(hm, time=time)
286 hm%cpml_hamiltonian = .false.
287 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt)
288
289 ! add term U(time+dt,time)J(time)
290 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
291 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
292 call hamiltonian_mxll_update(hm, time=time)
293 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt*m_half, &
294 psib2=ff_rs_inhom_meanb, deltat2=-inter_dt*m_half)
295 ! ff_rs_inhom_2b = U(time+dt/2,time) J(time)
296 ! ff_rs_inhom_meanb = U(time,time+dt/2) J(time)
297 ! add terms U(time+dt/2,time)J(time) and U(time,time+dt/2)J(time)
298 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
299 call batch_axpy(gr%np, m_one, ff_rs_inhom_meanb, ff_rs_inhom_1b)
300 call ff_rs_inhom_2b%end()
301 call ff_rs_inhom_meanb%end()
302 end if
303
304 do ii = 1, inter_steps
305
306 ! intermediate time
307 inter_time = time + inter_dt * (ii-1)
308
309 ! transformation of RS state into 3x3 or 4x4 representation
310 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_forward)
311
312 ! RS state propagation
313 call hamiltonian_mxll_update(hm, time=inter_time)
314 if (pml_check) then
315 call pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
316 end if
317
318 hm%cpml_hamiltonian = pml_check
319 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
320 hm%cpml_hamiltonian = .false.
321
322 if (pml_check) then
323 call pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, inter_time, inter_dt, m_zero, ff_rs_state_pmlb, ff_rs_stateb)
324 end if
325
326 !Below we add the contribution from the inhomogeneous terms
327 if ((hm%ma_mx_coupling_apply) .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) then
328 if (tr%tr_etrs_approx == mxwll_etrs_full) then
329 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
330 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
331 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
332
333 ! Interpolation of the external current
334 do istate = 1, hm%dim
335 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t2(:, istate))
336 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
337 end do
338 ! store t1 - t2 for the interpolation in mean
339 call batch_axpy(gr%np, -m_one, ff_rs_inhom_1b, ff_rs_inhom_meanb)
340 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
341 call batch_axpy(gr%np, ii / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_2b)
342 call batch_axpy(gr%np, (ii-1) / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_1b)
343
344 hm%cpml_hamiltonian = .false.
345 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt)
346 ! add terms U(time+dt,time)J(time) and J(time+dt)
347 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
348 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
349
350 do istate = 1, hm%dim
351 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
352 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
353 end do
354 call batch_axpby(gr%np, m_half, ff_rs_inhom_2b, m_half, ff_rs_inhom_1b)
355
356 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt/m_two, &
357 psib2=ff_rs_inhom_2b, deltat2=-inter_dt/m_two)
358
359 ! add terms U(time+dt/2,time)J(time) and U(time,time+dt/2)J(time+dt)
360 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
361 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
362
363 call ff_rs_inhom_1b%end()
364 call ff_rs_inhom_2b%end()
365 call ff_rs_inhom_meanb%end()
366 else if (tr%tr_etrs_approx == mxwll_etrs_const) then
367 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
368 end if
369 end if
370
371 ! PML convolution function update
372 if (pml_check) then
373 call cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
374 end if
375
376 ! back transformation of RS state representation
377 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_backward)
378
379 if (tr%bc_constant) then
380 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
381 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
382 if (st%rs_state_const_external) then
383 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, inter_time, inter_dt, m_zero, rs_state)
384 end if
385 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
386 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
387 end if
388
389 ! Propagation dt with H(inter_time+inter_dt) for PEC mirror boundaries
390 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
391 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
392 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
393 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
394 end if
395
396 ! Propagation dt with H(inter_time+inter_dt) for PMC mirror boundaries
397 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
398 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
399 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
400 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
401 end if
402
403 ! Apply mask absorbing boundaries
404 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
405 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
406 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, inter_time, inter_dt, m_zero, rs_state)
407 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
408 end if
409
410 if (tr%bc_plane_waves) then
411 ! Propagation dt with H(inter_time+inter_dt) for plane waves boundaries
412 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
413 call plane_waves_boundaries_calculation(hm, st, gr, inter_time+inter_dt, m_zero, rs_state)
414 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
415 end if
416
417 end do
418
419 if (tr%tr_etrs_approx == option__maxwelltdetrsapprox__const_steps) then
420 call ff_rs_inhom_1b%end()
421 end if
422
423 call ff_rs_stateb%end()
424
425 if (pml_check) then
426 call ff_rs_state_pmlb%end()
427 end if
428
429 safe_deallocate_a(rs_state)
430
431 call profiling_out('MXLL_PROPAGATOR_STEP')
432
433 pop_sub(mxll_propagation_step)
434 end subroutine mxll_propagation_step
435
436 ! ---------------------------------------------------------
437 subroutine mxll_propagate_leapfrog(hm, namespace, gr, st, tr, time, dt, counter)
438 type(hamiltonian_mxll_t), intent(inout) :: hm
439 type(namespace_t), intent(in) :: namespace
440 type(grid_t), intent(inout) :: gr
441 type(states_mxll_t), intent(inout) :: st
442 type(propagator_mxll_t), intent(inout) :: tr
443 real(real64), intent(in) :: time
444 real(real64), intent(in) :: dt
445 integer, intent(in) :: counter
446
447 type(batch_t) :: rs_state_tmpb
448
449 push_sub_with_profile(mxll_propagate_leapfrog)
450
451 call st%rs_stateb%copy_to(rs_state_tmpb)
452
453 call hamiltonian_mxll_update(hm, time)
454
455 ! do boundaries at the beginning
456 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, st%rs_stateb)
457
458 ! update PML convolution values
459 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
460 call mxll_update_pml_simple(hm, st%rs_stateb)
461 end if
462
463 ! apply hamiltonian
464 call hamiltonian_mxll_apply_simple(hm, namespace, gr, st%rs_stateb, rs_state_tmpb)
465 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
466
467 ! add inhomogeneous terms
468 call batch_xpay(gr%np, st%inhomogeneousb, m_one, rs_state_tmpb)
469
470 if (counter == 0) then
471 ! for the first step, we do one forward Euler step
472 call batch_xpay(gr%np, st%rs_stateb, dt, rs_state_tmpb)
473 else
474 ! the leapfrog step depends on the previous state
475 call batch_xpay(gr%np, st%rs_state_prevb, m_two*dt, rs_state_tmpb)
476 end if
477
478 ! save the current rs state
479 call st%rs_stateb%copy_data_to(gr%np, st%rs_state_prevb)
480 ! update to new timestep
481 call rs_state_tmpb%copy_data_to(gr%np, st%rs_stateb)
482
483 ! update PML convolution values
484 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
485 call mxll_copy_pml_simple(hm, st%rs_stateb)
486 end if
487
488 call rs_state_tmpb%end()
489
490 pop_sub_with_profile(mxll_propagate_leapfrog)
491 end subroutine mxll_propagate_leapfrog
492
493 ! ---------------------------------------------------------
507 subroutine mxll_propagate_expgauss1(hm, namespace, gr, st, tr, time, dt)
508 type(hamiltonian_mxll_t), intent(inout) :: hm
509 type(namespace_t), intent(in) :: namespace
510 type(grid_t), intent(inout) :: gr
511 type(states_mxll_t), intent(inout) :: st
512 type(propagator_mxll_t), intent(inout) :: tr
513 real(real64), intent(in) :: time
514 real(real64), intent(in) :: dt
515
516 type(batch_t) :: rs_state_tmpb
517
518 push_sub_with_profile(mxll_propagate_expgauss1)
519
520 call st%rs_stateb%copy_to(rs_state_tmpb)
521
522 call hamiltonian_mxll_update(hm, time)
523
524 ! do boundaries at the beginning (should be included in Hamiltonian?)
525 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
526 dt, st%rs_stateb)
527
528 ! update PML convolution values
529 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
530 call mxll_update_pml_simple(hm, st%rs_stateb)
531 end if
533 ! accumulate -i H F_n - J_1 in rs_state_tmpb
534 ! compute H F_n
535 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
536 ! compute -i H F_n
537 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
538 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
539 ! set J_1
540 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
541 ! accumulate -J_1 to rs_state_tmpb
542 call batch_axpy(gr%np, -m_one, st%inhomogeneousb, rs_state_tmpb)
543 end if
544 ! compute phi_1
545 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
546 ! F_{n+1} = F_n + dt * phi_1 (...)
547 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
548
549 call rs_state_tmpb%end()
550
551 ! update PML convolution values
552 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
553 call mxll_copy_pml_simple(hm, st%rs_stateb)
554 end if
555
556 pop_sub_with_profile(mxll_propagate_expgauss1)
557 end subroutine mxll_propagate_expgauss1
558
559 ! ---------------------------------------------------------
579 subroutine mxll_propagate_expgauss2(hm, namespace, gr, st, tr, time, dt)
580 type(hamiltonian_mxll_t), intent(inout) :: hm
581 type(namespace_t), intent(in) :: namespace
582 type(grid_t), intent(inout) :: gr
583 type(states_mxll_t), intent(inout) :: st
584 type(propagator_mxll_t), intent(inout) :: tr
585 real(real64), intent(in) :: time
586 real(real64), intent(in) :: dt
587
588 type(batch_t) :: rs_state_tmpb
589
590 push_sub_with_profile(mxll_propagate_expgauss2)
591
592 call st%rs_stateb%copy_to(rs_state_tmpb)
593
594 call hamiltonian_mxll_update(hm, time)
595
596 ! do boundaries at the beginning (should be included in Hamiltonian?)
597 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
598 dt, st%rs_stateb)
599
600 ! update PML convolution values
601 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
602 call mxll_update_pml_simple(hm, st%rs_stateb)
603 end if
604
605 ! accumulate -i H F_n - a_1 J_1 - a_2 J_2 in rs_state_tmpb
606 ! compute H F_n
607 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
608 ! compute -i H F_n
609 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
610 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
611 ! set J_1
612 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
613 ! accumulate -a_1 J_1 to rs_state_tmpb
614 call batch_axpy(gr%np, -m_half*(m_one+sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
615 ! set J_2
616 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
617 ! accumulate -a_2 J_2 to rs_state_tmpb
618 call batch_axpy(gr%np, -m_half*(m_one-sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
619 end if
620 ! compute phi_1
621 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
622 ! accumulate phi_1 term: F_{n+1} = F_n + dt * phi_1 (...)
623 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
624 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
625 call batch_set_zero(rs_state_tmpb)
626 ! set J_1
627 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
628 ! accumulate -b_1 J_1 to rs_state_tmpb
629 call batch_axpy(gr%np, sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
630 ! set J_2
631 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
632 ! accumulate -b_2 J_2 to rs_state_tmpb
633 call batch_axpy(gr%np, -sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
634
635 ! compute phi_2
636 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 2)
637 ! accumulate phi_2 term: F_{n+1} = F_n + dt * phi_2 (...)
638 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
639 end if
640
641 ! update PML convolution values
642 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
643 call mxll_copy_pml_simple(hm, st%rs_stateb)
644 end if
645
646 call rs_state_tmpb%end()
647
648 pop_sub_with_profile(mxll_propagate_expgauss2)
649 end subroutine mxll_propagate_expgauss2
650
651 ! ---------------------------------------------------------
652 subroutine set_medium_rs_state(st, gr, hm)
653 type(states_mxll_t), intent(inout) :: st
654 type(grid_t), intent(in) :: gr
655 type(hamiltonian_mxll_t), intent(in) :: hm
656
657 integer :: ip, ip_in, il, idim
658
659 push_sub(set_medium_rs_state)
660
661 assert(allocated(st%ep) .and. allocated(st%mu))
662
663 call profiling_in('SET_MEDIUM_RS_STATE')
664
665 if (hm%calc_medium_box) then
666 do il = 1, size(hm%medium_boxes)
667 assert(.not. hm%medium_boxes(il)%has_mapping)
668 do ip = 1, hm%medium_boxes(il)%points_number
669 if (abs(hm%medium_boxes(il)%c(ip)) <= m_epsilon) cycle
670 st%ep(ip) = hm%medium_boxes(il)%ep(ip)
671 st%mu(ip) = hm%medium_boxes(il)%mu(ip)
672 end do
673 end do
674 end if
675
676 do idim = 1, st%dim
677 if (hm%bc%bc_type(idim) == mxll_bc_medium) then
678 do ip_in = 1, hm%bc%medium(idim)%points_number
679 ip = hm%bc%medium(idim)%points_map(ip_in)
680 st%ep(ip) = hm%bc%medium(idim)%ep(ip_in)
681 st%mu(ip) = hm%bc%medium(idim)%mu(ip_in)
682 end do
683 end if
684 end do
685
686 call profiling_out('SET_MEDIUM_RS_STATE')
687
688 pop_sub(set_medium_rs_state)
689 end subroutine set_medium_rs_state
690
691 ! ---------------------------------------------------------
692 subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
693 type(hamiltonian_mxll_t), intent(in) :: hm
694 type(grid_t), intent(in) :: gr
695 type(states_mxll_t), intent(in) :: st
696 type(batch_t), intent(inout) :: rs_stateb
697 type(batch_t), intent(inout) :: ff_rs_stateb
698 integer, intent(in) :: sign
699
700 complex(real64), allocatable :: rs_state(:,:)
701 complex(real64), allocatable :: rs_state_tmp(:,:)
702 integer :: ii, np, ip
703
705
706 call profiling_in('TRANSFORM_RS_STATE')
707
708 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
709
710 np = gr%np
711 safe_allocate(rs_state(1:gr%np, 1:st%dim))
712
713 if (hm%operator == faraday_ampere_medium) then
714 if (sign == rs_trans_forward) then
715 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
716 ! 3 to 6
717 do ii = 1, 3
718 call batch_set_state(ff_rs_stateb, ii, np, rs_state(:, ii))
719 call batch_set_state(ff_rs_stateb, ii+3, np, conjg(rs_state(:, ii)))
720 end do
721 else
722 ! 6 to 3
723 safe_allocate(rs_state_tmp(1:gr%np, 1:st%dim))
724 do ii = 1, 3
725 call batch_get_state(ff_rs_stateb, ii, np, rs_state(:, ii))
726 call batch_get_state(ff_rs_stateb, ii+3, np, rs_state_tmp(:, ii))
727 !$omp parallel do
728 do ip = 1, np
729 rs_state(ip, ii) = m_half * (rs_state(ip, ii) + conjg(rs_state_tmp(ip, ii)))
730 end do
731 !$omp end parallel do
732 end do
733 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
734 safe_deallocate_a(rs_state_tmp)
735 end if
736 else
737 if (sign == rs_trans_forward) then
738 call rs_stateb%copy_data_to(gr%np, ff_rs_stateb)
739 else
740 call ff_rs_stateb%copy_data_to(gr%np, rs_stateb)
741 end if
742 end if
743 safe_deallocate_a(rs_state)
744
745 call profiling_out('TRANSFORM_RS_STATE')
746
748
749 end subroutine transform_rs_state_batch
750
751 ! ---------------------------------------------------------
752 subroutine transform_rs_densities(hm, mesh, rs_current_density, ff_density, sign)
753 type(hamiltonian_mxll_t), intent(in) :: hm
754 class(mesh_t), intent(in) :: mesh
755 complex(real64), intent(inout) :: rs_current_density(:,:)
756 complex(real64), intent(inout) :: ff_density(:,:)
757 integer, intent(in) :: sign
758
759
760 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
761 assert(size(rs_current_density, dim=2) == 3)
762
763 push_sub(transform_rs_densities)
764
765 call profiling_in('TRANSFORM_RS_DENSITIES')
766
767 if (hm%operator == faraday_ampere_medium) then
768 if (sign == rs_trans_forward) then
769 call transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_current_density, ff_density)
770 else
771 call transform_rs_densities_to_6x6_rs_densities_backward(mesh, ff_density, rs_current_density)
772 end if
773 else
774 if (sign == rs_trans_forward) then
775 ff_density(1:mesh%np, 1:3) = rs_current_density(1:mesh%np, 1:3)
776 else
777 rs_current_density(1:mesh%np, 1:3) = ff_density(1:mesh%np, 1:3)
778 end if
779 end if
780
781 call profiling_out('TRANSFORM_RS_DENSITIES')
782
784
785 end subroutine transform_rs_densities
786
787 !----------------------------------------------------------
788 subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_current_density, rs_density_6x6)
789 class(mesh_t), intent(in) :: mesh
790 complex(real64), intent(in) :: rs_current_density(:,:)
791 complex(real64), intent(inout) :: rs_density_6x6(:,:)
792
793 integer :: ii
794
795 assert(size(rs_current_density, dim=2) == 3)
796 assert(size(rs_density_6x6, dim=2) == 6)
797
798 ! no push_sub, called to frequently
799 do ii = 1, 3
800 rs_density_6x6(1:mesh%np, ii) = rs_current_density(1:mesh%np, ii)
801 rs_density_6x6(1:mesh%np, ii+3) = rs_current_density(1:mesh%np, ii)
802 end do
803
805
806 !----------------------------------------------------------
807 subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_current_density)
808 class(mesh_t), intent(in) :: mesh
809 complex(real64), intent(in) :: rs_density_6x6(:,:)
810 complex(real64), intent(inout) :: rs_current_density(:,:)
811
812 integer :: ii, ip
813
814 assert(size(rs_current_density, dim=2) == 3)
815 assert(size(rs_density_6x6, dim=2) == 6)
816
817 ! no push_sub, called to frequently
818 !$omp parallel private(ii, ip)
819 do ii = 1, 3
820 !$omp do
821 do ip = 1, mesh%np
822 rs_current_density(ip, ii) = m_half * &
823 real(rs_density_6x6(ip, ii) + rs_density_6x6(ip, ii+3), real64)
824 end do
825 end do
826 !$omp end parallel
827
829
830 !----------------------------------------------------------
831 subroutine calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, hm_elec, rs_state_matter)
832 type(grid_t), intent(in) :: gr_mxll
833 type(states_mxll_t), intent(in) :: st_mxll
834 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
835 type(grid_t), intent(in) :: gr_elec
836 type(hamiltonian_elec_t), intent(in) :: hm_elec
837 complex(real64), intent(inout) :: rs_state_matter(:,:)
838
839 complex(real64), allocatable :: tmp_pot_mx_gr(:,:), tmp_grad_mx_gr(:,:)
840
841 safe_allocate(tmp_pot_mx_gr(1:gr_mxll%np_part,1))
842 safe_allocate(tmp_grad_mx_gr(1:gr_mxll%np,1:gr_mxll%box%dim))
843 ! this subroutine needs the matter part
844
846
847 tmp_pot_mx_gr(:,:) = m_zero
848 tmp_grad_mx_gr(:,:) = m_zero
849 call zderivatives_grad(gr_mxll%der, tmp_pot_mx_gr(:,1), tmp_grad_mx_gr(:,:), set_bc = .false.)
850 tmp_grad_mx_gr = - tmp_grad_mx_gr
851
852 rs_state_matter = m_z0
853 call build_rs_state(real(tmp_grad_mx_gr(1:gr_mxll%np,:)), aimag(tmp_grad_mx_gr(1:gr_mxll%np,:)), st_mxll%rs_sign, &
854 rs_state_matter(1:gr_mxll%np,:), gr_mxll, st_mxll%ep(1:gr_mxll%np), st_mxll%mu(1:gr_mxll%np), &
855 gr_mxll%np)
856
857 safe_deallocate_a(tmp_pot_mx_gr)
858 safe_deallocate_a(tmp_grad_mx_gr)
859
862
863 !----------------------------------------------------------
864 subroutine get_vector_pot_and_transverse_field(namespace, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, &
865 poisson_solver, helmholtz, field, transverse_field, vector_potential)
866 type(namespace_t), intent(in) :: namespace
867 type(grid_t), intent(in) :: gr_mxll
868 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
869 type(states_mxll_t), intent(in) :: st_mxll
870 type(propagator_mxll_t), intent(in) :: tr_mxll
871 type(hamiltonian_elec_t), intent(in) :: hm
872 type(poisson_t), intent(in) :: poisson_solver
873 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
874 complex(real64), intent(inout) :: field(:,:)
875 complex(real64), intent(inout) :: transverse_field(:,:)
876 real(real64), intent(inout) :: vector_potential(:,:)
877
878 integer :: np, ip, idir
879 complex(real64), allocatable :: rs_state_plane_waves(:, :)
880
882
883 transverse_field = m_z0
884 vector_potential = m_zero
885
886 np = gr_mxll%np
887
888 if (hm_mxll%ma_mx_coupling) then
889
890 ! check what other transverse field methods are needed
891
892 ! trans_calc_method == OPTION__MAXWELLTRANSFIELDCALCULATIONMETHOD__TRANS_FIELD_POISSON
893 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
894 safe_allocate(rs_state_plane_waves(1:gr_mxll%np, 1:st_mxll%dim))
895 call mxll_get_batch(st_mxll%rs_state_plane_wavesb, rs_state_plane_waves, gr_mxll%np, st_mxll%dim)
896 end if
897
898 ! plane waves subtraction
899 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
900 !$omp parallel do collapse(2)
901 do idir = 1, size(transverse_field, dim=2)
902 do ip = 1, np
903 transverse_field(ip,idir) = field(ip,idir) - rs_state_plane_waves(ip,idir)
904 end do
905 end do
906 !$omp end parallel do
907 else
908 transverse_field(1:np,:) = field(1:np,:)
909 end if
910 ! apply helmholtz decomposition for transverse field
911 call helmholtz%get_trans_field(namespace, transverse_field, total_field=field)
912 ! plane waves addition
913 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
914 do idir = 1, size(transverse_field, dim=2)
915 call lalg_axpy(np, m_one, rs_state_plane_waves(:, idir), transverse_field(:, idir))
916 end do
917 safe_deallocate_a(rs_state_plane_waves)
918 end if
919
920 else
921
922 transverse_field(1:np,:) = field
923
924 end if
925
928
930
931 ! ---------------------------------------------------------
932 subroutine calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
933 type(namespace_t), intent(in) :: namespace
934 type(poisson_t), intent(in) :: poisson_solver
935 type(grid_t), intent(in) :: gr
936 type(states_mxll_t), intent(in) :: st
937 complex(real64), intent(in) :: field(:,:)
938 real(real64), contiguous, intent(inout) :: vector_potential(:,:)
939
940 integer :: idim
941 real(real64), allocatable :: dtmp(:,:)
942
943 safe_allocate(dtmp(1:gr%np_part,1:3))
944
945 dtmp = m_zero
946
947 call get_magnetic_field_state(field, gr, st%rs_sign, vector_potential, st%mu, gr%np_part)
948 dtmp = vector_potential
949 call dderivatives_curl(gr%der, dtmp, vector_potential, set_bc = .false.)
950 do idim=1, st%dim
951 call dpoisson_solve(poisson_solver, namespace, dtmp(:,idim), vector_potential(:,idim), .true.)
952 end do
953 vector_potential = m_one / (m_four * m_pi) * vector_potential
954
955 safe_deallocate_a(dtmp)
956
957 end subroutine calculate_vector_potential
958
959 !----------------------------------------------------------
960 subroutine energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
961 type(grid_t), intent(in) :: gr
962 type(states_mxll_t), intent(in) :: st
963 type(hamiltonian_mxll_t), intent(in) :: hm
964 type(energy_mxll_t), intent(inout) :: energy_mxll
965 complex(real64), intent(in) :: rs_field(:,:)
966 complex(real64), optional, intent(in) :: rs_field_plane_waves(:,:)
967
968 real(real64), allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:), energy_density_plane_waves(:)
969
970 push_sub(energy_mxll_calc)
971
972 call profiling_in('ENERGY_MXLL_CALC')
973
974 safe_allocate(energy_density(1:gr%np))
975 safe_allocate(e_energy_density(1:gr%np))
976 safe_allocate(b_energy_density(1:gr%np))
977 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
978 safe_allocate(energy_density_plane_waves(1:gr%np))
979 end if
980
981 call energy_density_calc(gr, st, rs_field, energy_density, e_energy_density, &
982 b_energy_density, hm%plane_waves, rs_field_plane_waves, energy_density_plane_waves)
983 energy_mxll%energy = dmf_integrate(gr, energy_density, mask=st%inner_points_mask)
984 energy_mxll%e_energy = dmf_integrate(gr, e_energy_density, mask=st%inner_points_mask)
985 energy_mxll%b_energy = dmf_integrate(gr, b_energy_density, mask=st%inner_points_mask)
986 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
987 energy_mxll%energy_plane_waves = dmf_integrate(gr, energy_density_plane_waves, mask=st%inner_points_mask)
988 else
989 energy_mxll%energy_plane_waves = m_zero
990 end if
991
992 energy_mxll%boundaries = dmf_integrate(gr, energy_density, mask=st%boundary_points_mask)
993
994 safe_deallocate_a(energy_density)
995 safe_deallocate_a(e_energy_density)
996 safe_deallocate_a(b_energy_density)
997 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
998 safe_deallocate_a(energy_density_plane_waves)
999 end if
1000
1001 call profiling_out('ENERGY_MXLL_CALC')
1002
1003 pop_sub(energy_mxll_calc)
1004 end subroutine energy_mxll_calc
1005
1006 !----------------------------------------------------------
1007 subroutine energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
1008 type(grid_t), intent(in) :: gr
1009 type(states_mxll_t), intent(in) :: st
1010 type(hamiltonian_mxll_t), intent(in) :: hm
1011 type(energy_mxll_t), intent(inout) :: energy_mxll
1012 type(batch_t), intent(in) :: rs_fieldb
1013 type(batch_t), intent(in) :: rs_field_plane_wavesb
1014
1015 type(batch_t) :: e_fieldb, b_fieldb, e_field_innerb, b_field_innerb, rs_field_plane_waves_innerb
1016 real(real64) :: tmp(1:st%dim)
1017 complex(real64) :: ztmp(1:st%dim)
1018
1019 push_sub(energy_mxll_calc_batch)
1020
1021 call profiling_in('ENERGY_MXLL_CALC_BATCH')
1022
1023 call dbatch_init(e_fieldb, 1, 1, st%dim, gr%np)
1024 if (st%pack_states) then
1025 call e_fieldb%do_pack(copy=.false.)
1026 end if
1027 call e_fieldb%copy_to(b_fieldb)
1028 call e_fieldb%copy_to(e_field_innerb)
1029 call e_fieldb%copy_to(b_field_innerb)
1030
1031 call batch_split_complex(gr%np, rs_fieldb, e_fieldb, b_fieldb)
1032
1033 ! subtract energy of inner points
1034 call batch_set_zero(e_field_innerb)
1035 call batch_set_zero(b_field_innerb)
1036 if (accel_is_enabled()) then
1037 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, e_fieldb, e_field_innerb)
1038 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, b_fieldb, b_field_innerb)
1039 else
1040 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, e_fieldb, e_field_innerb)
1041 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, b_fieldb, b_field_innerb)
1042 end if
1043 call dmesh_batch_dotp_vector(gr, e_field_innerb, e_field_innerb, tmp)
1044 energy_mxll%e_energy = sum(tmp)
1045 call dmesh_batch_dotp_vector(gr, b_field_innerb, b_field_innerb, tmp)
1046 energy_mxll%b_energy = sum(tmp)
1047 energy_mxll%energy = energy_mxll%e_energy + energy_mxll%b_energy
1048
1049 call dmesh_batch_dotp_vector(gr, e_fieldb, e_fieldb, tmp)
1050 energy_mxll%boundaries = sum(tmp)
1051 call dmesh_batch_dotp_vector(gr, b_fieldb, b_fieldb, tmp)
1052 energy_mxll%boundaries = energy_mxll%boundaries + sum(tmp)
1053 energy_mxll%boundaries = energy_mxll%boundaries - energy_mxll%energy
1054
1055 if (hm%plane_waves) then
1056 call rs_field_plane_wavesb%copy_to(rs_field_plane_waves_innerb)
1057 call batch_set_zero(rs_field_plane_waves_innerb)
1058 if (accel_is_enabled()) then
1059 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, &
1060 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1061 else
1062 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, &
1063 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1064 end if
1065 call zmesh_batch_dotp_vector(gr, rs_field_plane_waves_innerb, rs_field_plane_waves_innerb, ztmp)
1066 energy_mxll%energy_plane_waves = sum(real(ztmp, real64) )
1067 call rs_field_plane_waves_innerb%end()
1068 else
1069 energy_mxll%energy_plane_waves = m_zero
1070 end if
1071
1072 call e_fieldb%end()
1073 call b_fieldb%end()
1074 call e_field_innerb%end()
1075 call b_field_innerb%end()
1076
1077 call profiling_out('ENERGY_MXLL_CALC_BATCH')
1078
1079 pop_sub(energy_mxll_calc_batch)
1080 end subroutine energy_mxll_calc_batch
1081
1082 ! ---------------------------------------------------------
1083 subroutine mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
1084 type(namespace_t), intent(in) :: namespace
1085 type(grid_t), intent(in) :: gr
1086 type(hamiltonian_mxll_t), intent(inout) :: hm
1087 type(states_mxll_t), intent(inout) :: st
1088 type(propagator_mxll_t), intent(inout) :: tr
1089 real(real64), intent(in) :: time
1090 real(real64), intent(in) :: dt
1091 real(real64), intent(in) :: time_delay
1092 complex(real64), intent(inout) :: rs_state(:,:)
1093
1094 integer :: ip, ip_in, idim
1095 logical :: mask_check
1096
1098
1099 call profiling_in('MASK_ABSORBING_BOUNDARIES')
1100 mask_check = .false.
1101
1102 do idim = 1, 3
1103 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1104 mask_check = .true.
1105 end if
1106 end do
1107
1108 if (mask_check) then
1109 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1110 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1111 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1112 rs_state = rs_state - st%rs_state_plane_waves
1113 call maxwell_mask(hm, rs_state)
1114 rs_state = rs_state + st%rs_state_plane_waves
1115 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1116 !call constant_at_absorbing_boundaries_calculation(st, hm%bc)
1117 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1118 do ip_in=1, hm%bc%constant_points_number
1119 ip = hm%bc%constant_points_map(ip_in)
1120 rs_state(ip,:) = rs_state(ip,:) - st%rs_state_const(:)
1121 end do
1122 call maxwell_mask(hm, rs_state)
1123 do ip_in=1, hm%bc%constant_points_number
1124 ip = hm%bc%constant_points_map(ip_in)
1125 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const(:)
1126 end do
1127 else
1128 call maxwell_mask(hm, rs_state)
1129 end if
1130 end if
1131
1132 call profiling_out('MASK_ABSORBING_BOUNDARIES')
1133
1135 end subroutine mask_absorbing_boundaries
1136
1137 ! ---------------------------------------------------------
1138 subroutine maxwell_mask(hm, rs_state)
1139 type(hamiltonian_mxll_t), intent(in) :: hm
1140 complex(real64), intent(inout) :: rs_state(:,:)
1141
1142 integer :: ip, ip_in, idim
1143
1144 push_sub(maxwell_mask)
1145
1146 call profiling_in('MAXWELL_MASK')
1147
1148 do idim = 1, 3
1149 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1150 do ip_in = 1, hm%bc%mask_points_number(idim)
1151 ip = hm%bc%mask_points_map(ip_in,idim)
1152 rs_state(ip,:) = rs_state(ip,:) * hm%bc%mask(ip_in,idim)
1153 end do
1154 end if
1155 end do
1156
1157 call profiling_out('MAXWELL_MASK')
1158
1159 pop_sub(maxwell_mask)
1160 end subroutine maxwell_mask
1161
1162 ! ---------------------------------------------------------
1163 subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
1164 type(hamiltonian_mxll_t), intent(inout) :: hm
1165 type(grid_t), intent(in) :: gr
1166 type(states_mxll_t), intent(inout) :: st
1167 type(propagator_mxll_t), intent(inout) :: tr
1168 type(batch_t), intent(in) :: ff_rs_stateb
1169 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1170
1171 integer :: ii
1172 complex(real64), allocatable :: rs_state_constant(:,:)
1173 type(batch_t) :: rs_state_constantb
1174
1176
1177 call profiling_in('PML_PROP_STAGE_1_BATCH')
1179 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1180 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, &
1181 ff_rs_state_pmlb, rs_trans_forward)
1182 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1183 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1184 ! this could be optimized: right now we broadcast the constant value
1185 ! to the full mesh to be able to use the batch functions easily.
1186 ! in principle, we would need to do the transform only for one point
1187 ! and then subtract that value from all points of the state
1188 safe_allocate(rs_state_constant(1:gr%np,1:3))
1189 do ii = 1, 3
1190 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1191 end do
1192 call ff_rs_stateb%copy_to(rs_state_constantb)
1193 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, 3)
1194
1195 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, &
1196 ff_rs_state_pmlb, rs_trans_forward)
1197 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1198
1199 call rs_state_constantb%end()
1200
1201 safe_deallocate_a(rs_state_constant)
1202 else
1203 ! this copy should not be needed
1204 call ff_rs_stateb%copy_data_to(gr%np, ff_rs_state_pmlb)
1205 end if
1206
1207 call profiling_out('PML_PROP_STAGE_1_BATCH')
1208
1210 end subroutine pml_propagation_stage_1_batch
1211
1212 ! ---------------------------------------------------------
1213 subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
1214 type(hamiltonian_mxll_t), intent(inout) :: hm
1215 type(namespace_t), intent(in) :: namespace
1216 type(grid_t), intent(in) :: gr
1217 type(states_mxll_t), intent(inout) :: st
1218 type(propagator_mxll_t), intent(inout) :: tr
1219 real(real64), intent(in) :: time
1220 real(real64), intent(in) :: dt
1221 real(real64), intent(in) :: time_delay
1222 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1223 type(batch_t), intent(inout) :: ff_rs_stateb
1224
1225 integer :: ii, ff_dim
1226 complex(real64), allocatable :: rs_state_constant(:,:), ff_rs_state_constant(:,:)
1227 type(batch_t) :: ff_rs_state_plane_wavesb, ff_rs_constantb, rs_state_constantb
1228
1230
1231 call profiling_in('PML_PROP_STAGE_2_BATCH')
1232
1233 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1234 hm%cpml_hamiltonian = .true.
1235 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1236 hm%cpml_hamiltonian = .false.
1237 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1238
1239 call ff_rs_stateb%copy_to(ff_rs_state_plane_wavesb)
1240 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_state_plane_wavesb, rs_trans_forward)
1241
1242 if (ff_rs_stateb%status() == batch_device_packed) then
1243 ! use the map of points stored on the GPU in this case
1244 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%buff_map, &
1245 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1246 else
1247 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%points_map, &
1248 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1249 end if
1250
1251 call ff_rs_state_plane_wavesb%end()
1252
1253 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1254 hm%cpml_hamiltonian = .true.
1255 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1256 hm%cpml_hamiltonian = .false.
1257
1258 call ff_rs_stateb%copy_to(ff_rs_constantb)
1259 ff_dim = ff_rs_stateb%nst_linear
1260 safe_allocate(rs_state_constant(1:gr%np, 1:st%dim))
1261 ! copy the value to the full mesh to be able to use batches
1262 ! this is in principle unneeded, but otherwise we could not use batches...
1263 do ii = 1, st%dim
1264 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1265 end do
1266 call ff_rs_stateb%copy_to(rs_state_constantb)
1267 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, st%dim)
1268
1269 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, ff_rs_constantb, rs_trans_forward)
1270 if (ff_rs_stateb%status() == batch_device_packed) then
1271 ! use the map of points stored on the GPU in this case
1272 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%buff_constant_points_map, &
1273 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1274 else
1275 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%constant_points_map, &
1276 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1277 end if
1278
1279 call ff_rs_constantb%end()
1280 call rs_state_constantb%end()
1281
1282 safe_deallocate_a(rs_state_constant)
1283 safe_deallocate_a(ff_rs_state_constant)
1284 end if
1285
1286 call profiling_out('PML_PROP_STAGE_2_BATCH')
1287
1289 end subroutine pml_propagation_stage_2_batch
1290
1291 ! ---------------------------------------------------------
1292 subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
1293 type(hamiltonian_mxll_t), intent(inout) :: hm
1294 type(grid_t), intent(in) :: gr
1295 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1296
1297
1299
1300 call profiling_in('CPML_CONV_FUNCTION_UPDATE')
1301
1302 call cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1303
1304 call profiling_out('CPML_CONV_FUNCTION_UPDATE')
1305
1307 end subroutine cpml_conv_function_update
1309 ! ---------------------------------------------------------
1310 subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1311 type(hamiltonian_mxll_t), intent(inout) :: hm
1312 type(grid_t), intent(in) :: gr
1313 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1314
1315 integer :: ip, ip_in, np_part, rs_sign
1316 complex(real64) :: pml_a, pml_b, pml_g, grad
1317 integer :: pml_dir, field_dir, ifield, idir
1318 integer, parameter :: field_dirs(3, 2) = reshape([2, 3, 1, 3, 1, 2], [3, 2])
1319 logical :: with_medium
1320 type(batch_t) :: gradb(gr%der%dim)
1321 type(accel_kernel_t), save :: ker_pml
1322 integer :: bsize, gsize
1323
1325
1326 call profiling_in('CPML_CONV_UPDATE_VIA_RS')
1327
1328 assert(hm%dim == 3 .or. hm%dim == 6)
1329
1330 np_part = gr%np_part
1331 rs_sign = hm%rs_sign
1332
1333 call zderivatives_batch_grad(gr%der, ff_rs_state_pmlb, gradb)
1334
1335 with_medium = hm%dim == 6
1336
1337 do pml_dir = 1, hm%st%dim
1338 select case (gradb(pml_dir)%status())
1339 case (batch_not_packed)
1340 do ip_in=1, hm%bc%pml%points_number
1341 ip = hm%bc%pml%points_map(ip_in)
1342 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1343 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1344 do ifield = 1, 2
1345 field_dir = field_dirs(pml_dir, ifield)
1346 grad = gradb(pml_dir)%zff_linear(ip, field_dir)
1347 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1348 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1349 if (with_medium) then
1350 grad = gradb(pml_dir)%zff_linear(ip, field_dir+3)
1351 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1352 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1353 end if
1354 end do
1355 end do
1356 case (batch_packed)
1357 do ip_in=1, hm%bc%pml%points_number
1358 ip = hm%bc%pml%points_map(ip_in)
1359 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1360 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1361 do ifield = 1, 2
1362 field_dir = field_dirs(pml_dir, ifield)
1363 grad = gradb(pml_dir)%zff_pack(field_dir, ip)
1364 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1365 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1366 if (with_medium) then
1367 grad = gradb(pml_dir)%zff_pack(field_dir+3, ip)
1368 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1369 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1370 end if
1371 end do
1372 end do
1373 case (batch_device_packed)
1374 call accel_kernel_start_call(ker_pml, 'pml.cu', 'pml_update_conv')
1375
1376 if (with_medium) then
1377 call accel_set_kernel_arg(ker_pml, 0, 1_int32)
1378 else
1379 call accel_set_kernel_arg(ker_pml, 0, 0_int32)
1380 end if
1381 call accel_set_kernel_arg(ker_pml, 1, hm%bc%pml%points_number)
1382 call accel_set_kernel_arg(ker_pml, 2, pml_dir-1)
1383 call accel_set_kernel_arg(ker_pml, 3, hm%bc%pml%buff_map)
1384 call accel_set_kernel_arg(ker_pml, 4, gradb(pml_dir)%ff_device)
1385 call accel_set_kernel_arg(ker_pml, 5, log2(int(gradb(pml_dir)%pack_size(1), int32)))
1386 call accel_set_kernel_arg(ker_pml, 6, hm%bc%pml%buff_a)
1387 call accel_set_kernel_arg(ker_pml, 7, hm%bc%pml%buff_b)
1388 call accel_set_kernel_arg(ker_pml, 8, hm%bc%pml%buff_conv_plus)
1389 call accel_set_kernel_arg(ker_pml, 9, hm%bc%pml%buff_conv_minus)
1390
1391 ! Compute the grid size
1392 bsize = accel_max_block_size()
1393 call accel_grid_size(hm%bc%pml%points_number, bsize, gsize)
1394
1395 call accel_kernel_run(ker_pml, (/ gsize /), (/ bsize /))
1396 end select
1397 end do
1398
1399 do idir = 1, gr%der%dim
1400 call gradb(idir)%end()
1401 end do
1402
1403 if (accel_is_enabled()) then
1404 call accel_finish()
1405 end if
1406
1407 call profiling_out('CPML_CONV_UPDATE_VIA_RS')
1408
1411
1412 ! ---------------------------------------------------------
1413 subroutine td_function_mxll_init(st, namespace, hm)
1414 type(states_mxll_t), intent(inout) :: st
1415 type(namespace_t), intent(in) :: namespace
1416 type(hamiltonian_mxll_t), intent(inout) :: hm
1417
1418 type(block_t) :: blk
1419 integer :: il, nlines, idim, ncols, ierr
1420 real(real64) :: e_field(st%dim), b_field(st%dim)
1421 character(len=1024) :: mxf_expression
1422
1423 push_sub(td_function_mxll_init)
1424
1425 call profiling_in('TD_FUNCTION_MXLL_INIT')
1426
1427 !%Variable UserDefinedConstantSpatialMaxwellField
1428 !%Type block
1429 !%Section Maxwell
1430 !%Description
1431 !% Define parameters of spatially constant field.
1432 !%
1433 !% Example:
1434 !%
1435 !% <tt>%UserDefinedConstantSpatialMaxwellFields
1436 !% <br>&nbsp;&nbsp; plane_wave_parser | E_x | E_y | E_z | B_x | B_y | B_z | "tdf_function"
1437 !% <br>%</tt>
1438 !%
1439 !% This block defines three components of E field, three components of B field, and reference to
1440 !% the TD function.
1441 !%
1442 !%End
1443
1444 if (parse_block(namespace, 'UserDefinedConstantSpatialMaxwellField', blk) == 0) then
1445 st%rs_state_const_external = .true.
1446 nlines = parse_block_n(blk)
1447 safe_allocate(st%rs_state_const_td_function(1:nlines))
1448 safe_allocate(st%rs_state_const_amp(1:st%dim, 1:nlines))
1449 ! read all lines
1450 do il = 1, nlines
1451 e_field = m_zero
1452 b_field = m_zero
1453 ! Check that number of columns is five or six.
1454 ncols = parse_block_cols(blk, il - 1)
1455 if (ncols /= 7) then
1456 message(1) = 'Each line in the UserDefinedConstantSpatialMaxwellField block must have'
1457 message(2) = 'seven columns.'
1458 call messages_fatal(2, namespace=namespace)
1459 end if
1460 do idim = 1, st%dim
1461 call parse_block_float( blk, il - 1, idim-1, e_field(idim))
1462 end do
1463 do idim = 1, st%dim
1464 call parse_block_float( blk, il - 1, idim+2, b_field(idim))
1465 end do
1466 call parse_block_string( blk, il - 1, 6, mxf_expression)
1467 call build_rs_vector(e_field, b_field, st%rs_sign, st%rs_state_const_amp(:,il))
1468 call tdf_read(st%rs_state_const_td_function(il), namespace, trim(mxf_expression), ierr)
1469 end do
1470 end if
1471 call parse_block_end(blk)
1472
1473 !%Variable PropagateSpatialMaxwellField
1474 !%Type logical
1475 !%Default yes
1476 !%Section Maxwell::TD Propagation
1477 !%Description
1478 !% Allow for numerical propagation of Maxwells equations of spatially constant field.
1479 !% If set to no, do only analytic evaluation of the field inside the box.
1480 !%End
1481
1482 call parse_variable(namespace, 'PropagateSpatialMaxwellField', .true., hm%spatial_constant_propagate)
1483
1484 call profiling_out('TD_FUNCTION_MXLL_INIT')
1485
1486 pop_sub(td_function_mxll_init)
1487 end subroutine td_function_mxll_init
1488
1489 ! ---------------------------------------------------------
1490 subroutine spatial_constant_calculation(constant_calc, st, gr, hm, time, dt, delay, rs_state, set_initial_state)
1491 logical, intent(in) :: constant_calc
1492 type(states_mxll_t), intent(inout) :: st
1493 type(grid_t), intent(in) :: gr
1494 type(hamiltonian_mxll_t), intent(in) :: hm
1495 real(real64), intent(in) :: time
1496 real(real64), intent(in) :: dt
1497 real(real64), intent(in) :: delay
1498 complex(real64), intent(inout) :: rs_state(:,:)
1499 logical, optional, intent(in) :: set_initial_state
1500
1501 integer :: ip, ic, icn
1502 real(real64) :: tf_old, tf_new
1503 logical :: set_initial_state_
1504
1506
1507 call profiling_in('SPATIAL_CONSTANT_CALCULATION')
1509 set_initial_state_ = .false.
1510 if (present(set_initial_state)) set_initial_state_ = set_initial_state
1511
1512 if (hm%spatial_constant_apply) then
1513 if (constant_calc) then
1514 icn = size(st%rs_state_const_td_function(:))
1515 st%rs_state_const(:) = m_z0
1516 do ic = 1, icn
1517 tf_old = tdf(st%rs_state_const_td_function(ic), time-delay-dt)
1518 tf_new = tdf(st%rs_state_const_td_function(ic), time-delay)
1519 do ip = 1, gr%np
1520 if (set_initial_state_ .or. (.not. hm%spatial_constant_propagate)) then
1521 rs_state(ip,:) = st%rs_state_const_amp(:,ic) * tf_new
1522 else
1523 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const_amp(:,ic) * (tf_new - tf_old)
1524 end if
1525 end do
1526 st%rs_state_const(:) = st%rs_state_const(:) + st%rs_state_const_amp(:, ic) * tf_new
1527 end do
1528 end if
1529 end if
1530
1531 call profiling_out('SPATIAL_CONSTANT_CALCULATION')
1532
1534 end subroutine spatial_constant_calculation
1535
1536 ! ---------------------------------------------------------
1537 subroutine constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
1538 logical, intent(in) :: constant_calc
1539 type(bc_mxll_t), intent(inout) :: bc
1540 type(states_mxll_t), intent(in) :: st
1541 type(hamiltonian_mxll_t), intent(in) :: hm
1542 complex(real64), intent(inout) :: rs_state(:,:)
1543
1544 integer :: ip_in, ip
1545
1547 call profiling_in('CONSTANT_BOUNDARIES_CALC')
1548
1549 if (hm%spatial_constant_apply) then
1550 if (constant_calc) then
1551 do ip_in = 1, bc%constant_points_number
1552 ip = bc%constant_points_map(ip_in)
1553 rs_state(ip,:) = st%rs_state_const(:)
1554 bc%constant_rs_state(ip_in,:) = st%rs_state_const(:)
1555 end do
1556 end if
1557 end if
1558
1559 call profiling_out('CONSTANT_BOUNDARIES_CALC')
1560
1562 end subroutine constant_boundaries_calculation
1563
1564 ! ---------------------------------------------------------
1565 subroutine mirror_pec_boundaries_calculation(bc, st, rs_state)
1566 type(bc_mxll_t), intent(in) :: bc
1567 type(states_mxll_t), intent(in) :: st
1568 complex(real64), intent(inout) :: rs_state(:,:)
1569
1570 integer :: ip, ip_in, idim
1571 real(real64) :: e_field(st%dim), b_field(st%dim)
1572
1574
1575 do idim = 1, 3
1576 if (bc%bc_type(idim) == mxll_bc_mirror_pec) then
1577 do ip_in = 1, bc%mirror_points_number(idim)
1578 ip = bc%mirror_points_map(ip_in, idim)
1579 e_field(:) = m_zero
1580 call get_magnetic_field_vector(rs_state(ip,:), st%rs_sign, b_field(:), st%mu(ip))
1581 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1582 end do
1583 end if
1584 end do
1588
1589 ! ---------------------------------------------------------
1590 subroutine mirror_pmc_boundaries_calculation(bc, st, rs_state)
1591 type(bc_mxll_t), intent(in) :: bc
1592 type(states_mxll_t), intent(in) :: st
1593 complex(real64), intent(inout) :: rs_state(:,:)
1594
1595 integer :: ip, ip_in, idim
1596 real(real64) :: e_field(st%dim), b_field(st%dim)
1597
1599
1600 do idim = 1, 3
1601 if (bc%bc_type(idim) == mxll_bc_mirror_pmc) then
1602 do ip_in = 1, bc%mirror_points_number(idim)
1603 ip = bc%mirror_points_map(ip_in,idim)
1604 b_field(:) = m_zero
1605 call get_electric_field_vector(rs_state(ip,:), e_field(:), st%ep(ip))
1606 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1607 end do
1608 end if
1609 end do
1610
1613
1614 ! ---------------------------------------------------------
1615 subroutine plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
1616 type(hamiltonian_mxll_t), intent(in) :: hm
1617 type(states_mxll_t), intent(in) :: st
1618 class(mesh_t), intent(in) :: mesh
1619 real(real64), intent(in) :: time
1620 real(real64), intent(in) :: time_delay
1621 complex(real64), intent(inout) :: rs_state(:,:)
1622
1623 integer :: ip, ip_in, wn
1624 real(real64) :: x_prop(mesh%box%dim), rr, vv(mesh%box%dim), k_vector(mesh%box%dim)
1625 real(real64) :: k_vector_abs, nn
1626 complex(real64) :: e0(mesh%box%dim)
1627 real(real64) :: e_field(mesh%box%dim), b_field(mesh%box%dim)
1628 complex(real64) :: rs_state_add(mesh%box%dim)
1629 complex(real64) :: mx_func
1630
1633 call profiling_in('PLANE_WAVES_BOUNDARIES_C')
1634
1635 if (hm%plane_waves_apply) then
1636 do wn = 1, hm%bc%plane_wave%number
1637 k_vector(:) = hm%bc%plane_wave%k_vector(1:mesh%box%dim, wn)
1638 k_vector_abs = norm2(k_vector(1:mesh%box%dim))
1639 vv(:) = hm%bc%plane_wave%v_vector(1:mesh%box%dim, wn)
1640 e0(:) = hm%bc%plane_wave%e_field(1:mesh%box%dim, wn)
1641 do ip_in = 1, hm%bc%plane_wave%points_number
1642 ip = hm%bc%plane_wave%points_map(ip_in)
1643 e_field(:) = m_zero
1644 if (wn == 1) rs_state(ip,:) = m_z0
1645 nn = sqrt(st%ep(ip)/p_ep*st%mu(ip)/p_mu)
1646 x_prop(1:mesh%box%dim) = mesh%x(1:mesh%box%dim, ip) - vv(1:mesh%box%dim) * (time - time_delay)
1647 rr = norm2(x_prop(1:mesh%box%dim))
1648 if (hm%bc%plane_wave%modus(wn) == option__maxwellincidentwaves__plane_wave_mx_function) then
1649 ! Temporary variable assigned due to macro line length
1650 mx_func = mxf(hm%bc%plane_wave%mx_function(wn), x_prop(1:mesh%box%dim))
1651 e_field(1:mesh%box%dim) = real(e0(1:mesh%box%dim) * mx_func, real64)
1652 end if
1653 b_field(1:3) = dcross_product(k_vector, e_field) / p_c / k_vector_abs
1654 call build_rs_vector(e_field, b_field, st%rs_sign, rs_state_add, st%ep(ip), st%mu(ip))
1655 rs_state(ip, :) = rs_state(ip, :) + rs_state_add(:)
1656 end do
1657 end do
1658 else
1659 do ip_in = 1, hm%bc%plane_wave%points_number
1660 ip = hm%bc%plane_wave%points_map(ip_in)
1661 rs_state(ip,:) = m_z0
1662 end do
1663 end if
1664
1665 call profiling_out('PLANE_WAVES_BOUNDARIES_C')
1666
1669
1670 ! ---------------------------------------------------------
1671 subroutine plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1672 type(hamiltonian_mxll_t), intent(inout) :: hm
1673 type(propagator_mxll_t), intent(inout) :: tr
1674 type(namespace_t), intent(in) :: namespace
1675 type(states_mxll_t), intent(inout) :: st
1676 type(grid_t), intent(in) :: gr
1677 real(real64), intent(in) :: time
1678 real(real64), intent(in) :: dt
1679 real(real64), intent(in) :: time_delay
1680
1681 type(batch_t) :: ff_rs_stateb
1682 integer :: ff_dim
1683
1684 push_sub(plane_waves_propagation)
1686 call profiling_in('PLANE_WAVES_PROPAGATION')
1687
1688 ff_dim = hm%dim
1689 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
1690 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
1691
1692 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_forward)
1693
1694 ! Time evolution of RS plane waves state without any coupling with H(inter_time)
1695 call hamiltonian_mxll_update(hm, time=time)
1696 hm%cpml_hamiltonian = .false.
1697 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
1698
1699 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_backward)
1700 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1701 call plane_waves_boundaries_calculation(hm, st, gr, time+dt, time_delay, st%rs_state_plane_waves)
1702 call mxll_set_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1703 call ff_rs_stateb%end()
1704
1705 call profiling_out('PLANE_WAVES_PROPAGATION')
1707 end subroutine plane_waves_propagation
1708
1709 ! ---------------------------------------------------------
1710 subroutine plane_waves_in_box_calculation(bc, time, mesh, der, st, rs_state)
1711 type(bc_mxll_t), intent(inout) :: bc
1712 real(real64), intent(in) :: time
1713 class(mesh_t), intent(in) :: mesh
1714 type(derivatives_t), intent(in) :: der
1715 type(states_mxll_t), intent(in) :: st
1716 complex(real64), intent(inout) :: rs_state(:,:)
1717
1718 real(real64) :: e_field_total(mesh%np,st%dim), b_field_total(mesh%np,st%dim)
1719 complex(real64) :: rs_state_add(mesh%np,st%dim)
1720 integer :: idir
1721
1723
1724 call profiling_in('PLANE_WAVES_IN_BOX_CALCULATION')
1725
1726 call external_waves_eval(bc%plane_wave, time, mesh, "E field", e_field_total)
1727 call external_waves_eval(bc%plane_wave, time, mesh, "B field", b_field_total, der=der)
1728
1729 call build_rs_state(e_field_total, b_field_total, st%rs_sign, &
1730 rs_state_add(1:mesh%np,:), mesh, st%ep, st%mu)
1731 do idir = 1, st%dim
1732 call lalg_axpy(mesh%np, m_one, rs_state_add(:, idir), rs_state(:, idir))
1733 end do
1734
1735 call profiling_out('PLANE_WAVES_IN_BOX_CALCULATION')
1736
1738 end subroutine plane_waves_in_box_calculation
1739
1740 ! ---------------------------------------------------------
1741 subroutine mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
1742 type(propagator_mxll_t), intent(inout) :: tr
1743 type(states_mxll_t), intent(inout) :: st
1744 type(hamiltonian_mxll_t),intent(inout) :: hm
1745 type(grid_t), intent(in) :: gr
1746 type(namespace_t), intent(in) :: namespace
1747 real(real64), intent(in) :: time
1748 real(real64), intent(in) :: dt
1749 type(batch_t), intent(inout) :: rs_stateb
1750
1751 complex(real64), allocatable :: rs_state(:, :)
1752
1753 push_sub(mxll_apply_boundaries)
1754
1755 safe_allocate(rs_state(gr%np, st%dim))
1756
1757 if (tr%bc_constant) then
1758 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1759 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
1760 if (st%rs_state_const_external) then
1761 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, time, dt, m_zero, rs_state)
1762 end if
1763 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1764 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1765 end if
1767 ! PEC mirror boundaries
1768 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
1769 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1770 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
1771 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1772 end if
1773
1774 ! PMC mirror boundaries
1775 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
1776 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1777 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
1778 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1779 end if
1780
1781 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
1782 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1783 ! Apply mask absorbing boundaries
1784 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, m_zero, rs_state)
1785 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1786 end if
1787
1788 if (tr%bc_plane_waves) then
1789 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1790 ! calculate plane waves boundaries at t
1791 call plane_waves_boundaries_calculation(hm, st, gr, time, m_zero, rs_state)
1792 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1793 end if
1794
1795 safe_deallocate_a(rs_state)
1796
1797 pop_sub(mxll_apply_boundaries)
1798 end subroutine mxll_apply_boundaries
1799
1800end module propagator_mxll_oct_m
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:159
scale a batch by a constant or vector
Definition: batch_ops.F90:167
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:218
batchified version of
Definition: batch_ops.F90:187
constant times a vector plus a vector
Definition: lalg_basic.F90:173
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1439
subroutine, public accel_finish()
Definition: accel.F90:1124
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
integer pure function, public accel_max_block_size()
Definition: accel.F90:1208
This module implements batches of mesh functions.
Definition: batch.F90:135
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:286
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:286
subroutine, public zbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_CMPLX valued batch to given size without providing external memory
Definition: batch.F90:1924
subroutine, public dbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_FLOAT valued batch to given size without providing external memory
Definition: batch.F90:1614
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:286
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
subroutine, public batch_split_complex(np, xx, yy, zz)
extract the real and imaginary parts of a complex batch
Definition: batch_ops.F90:736
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
Definition: batch_ops.F90:265
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_curl(der, ff, op_ff, ghost_update, set_bc)
apply the curl operator to a vector of mesh functions
subroutine, public zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, factor)
apply the gradient to a batch of mesh functions
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public energy_density_calc(mesh, st, rs_field, energy_dens, e_energy_dens, b_energy_dens, plane_waves_check, rs_field_plane_waves, energy_dens_plane_waves)
subroutine, public exponential_init(te, namespace, full_batch)
subroutine, public external_waves_eval(external_waves, time, mesh, type_of_field, out_field_total, der)
Calculation of external waves from parsed formula.
subroutine, public external_waves_init(external_waves, namespace)
Here, plane wave is evaluated from analytical formulae on grid.
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_four
Definition: global.F90:204
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
real(real64), parameter, public m_fourth
Definition: global.F90:209
real(real64), parameter, public p_mu
Definition: global.F90:247
real(real64), parameter, public p_ep
Definition: global.F90:246
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:242
real(real64), parameter, public m_one
Definition: global.F90:201
real(real64), parameter, public m_three
Definition: global.F90:203
This module implements the underlying real-space grid.
Definition: grid.F90:119
subroutine, public hamiltonian_mxll_apply_simple(hm, namespace, mesh, psib, hpsib, terms, set_bc)
subroutine, public mxll_update_pml_simple(hm, rs_stateb)
integer, parameter, public faraday_ampere_medium
subroutine, public hamiltonian_mxll_update(this, time)
Maxwell Hamiltonian update (here only the time is updated, can maybe be added to another routine)
subroutine, public mxll_copy_pml_simple(hm, rs_stateb)
The Helmholtz decomposition is intended to contain "only mathematical" functions and procedures to co...
This module implements the index, used for the mesh points.
Definition: index.F90:124
Definition: io.F90:116
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1909
integer, parameter, public mxll_bc_mirror_pmc
integer, parameter, public mxll_bc_mirror_pec
integer, parameter, public mxll_bc_plane_waves
integer, parameter, public mxll_bc_medium
subroutine, public bc_mxll_generate_pml_parameters(bc, space, gr, c_factor, dt)
integer, parameter, public mxll_bc_constant
integer, parameter, public mxll_bc_zero
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:118
subroutine, public zmesh_batch_dotp_vector(mesh, aa, bb, dot, reduce, cproduct)
A simple switch between specialized kernels and generic kernels.
subroutine, public dmesh_batch_dotp_vector(mesh, aa, bb, dot, reduce, cproduct)
A simple switch between specialized kernels and generic kernels.
Definition: mesh_batch.F90:655
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
this module contains the output system
Definition: output.F90:117
Some general things and nomenclature:
Definition: par_vec.F90:173
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:818
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:1010
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
subroutine, public transform_rs_densities(hm, mesh, rs_current_density, ff_density, sign)
subroutine, public mirror_pec_boundaries_calculation(bc, st, rs_state)
subroutine td_function_mxll_init(st, namespace, hm)
subroutine, public get_vector_pot_and_transverse_field(namespace, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, poisson_solver, helmholtz, field, transverse_field, vector_potential)
subroutine, public plane_waves_in_box_calculation(bc, time, mesh, der, st, rs_state)
subroutine, public energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
subroutine plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
subroutine, public mxll_propagate_leapfrog(hm, namespace, gr, st, tr, time, dt, counter)
subroutine, public constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
subroutine, public mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
subroutine, public calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
subroutine, public mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
subroutine, public plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
subroutine, public spatial_constant_calculation(constant_calc, st, gr, hm, time, dt, delay, rs_state, set_initial_state)
subroutine, public set_medium_rs_state(st, gr, hm)
subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
subroutine maxwell_mask(hm, rs_state)
integer, parameter mxwll_etrs_const
subroutine, public calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, hm_elec, rs_state_matter)
subroutine, public mxll_propagate_expgauss1(hm, namespace, gr, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=1.
subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_current_density, rs_density_6x6)
subroutine, public energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
subroutine, public mxll_propagate_expgauss2(hm, namespace, gr, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=2.
integer, parameter, public rs_trans_backward
subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_current_density)
subroutine, public mirror_pmc_boundaries_calculation(bc, st, rs_state)
subroutine, public mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
subroutine, public propagator_mxll_init(gr, namespace, st, hm, tr)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
subroutine, public mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
subroutine, public get_electric_field_vector(rs_state_vector, electric_field_vector, ep_element)
subroutine, public build_rs_vector(e_vector, b_vector, rs_sign, rs_vector, ep_element, mu_element)
subroutine, public mxll_get_batch(rs_stateb, rs_state, np, dim, offset)
subroutine, public build_rs_state(e_field, b_field, rs_sign, rs_state, mesh, ep_field, mu_field, np)
subroutine, public get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
subroutine, public get_magnetic_field_vector(rs_state_vector, rs_sign, magnetic_field_vector, mu_element)
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
Definition: tdfunction.F90:220
Class defining batches of mesh functions.
Definition: batch.F90:161
class representing derivatives
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)