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
24 use comm_oct_m
26 use cube_oct_m
34 use fft_oct_m
36 use grid_oct_m
37 use global_oct_m
41 use index_oct_m
42 use io_oct_m
47 use math_oct_m
50 use mesh_oct_m
55 use mpi_oct_m
57 use output_oct_m
58 use parser_oct_m
63 use space_oct_m
66 use string_oct_m
69
70 implicit none
71
72 private
73 public :: &
92
93 ! The following routines are currently unused, but will be used in the near future.
94 ! In order not to generate warnings about them, we declared them as public
95 public :: &
99
101 logical :: bc_add_ab_region = .false.
102 logical :: bc_zero = .false.
103 logical :: bc_constant = .false.
104 logical :: bc_mirror_pec = .false.
105 logical :: bc_mirror_pmc = .false.
106 logical :: bc_plane_waves = .false.
107 logical :: bc_medium = .false.
108 type(exponential_t) :: te
109 logical :: plane_waves_in_box
110 integer :: tr_etrs_approx
111 end type propagator_mxll_t
112
113 integer, public, parameter :: &
114 RS_TRANS_FORWARD = 1, &
116
117 integer, parameter :: &
118 MXWLL_ETRS_FULL = 0, &
120
121contains
122
123 ! ---------------------------------------------------------
124 subroutine propagator_mxll_init(gr, namespace, st, hm, tr)
125 type(grid_t), intent(in) :: gr
126 type(namespace_t), intent(in) :: namespace
127 type(states_mxll_t), intent(inout) :: st
128 type(hamiltonian_mxll_t), intent(inout) :: hm
129 type(propagator_mxll_t), intent(inout) :: tr
130
131 integer :: idim
132
133 push_sub(propagator_mxll_init)
134
135 call profiling_in("PROPAGATOR_MXLL_INIT")
136
137 do idim = 1, 3
138 select case (hm%bc%bc_type(idim))
139 case (mxll_bc_zero)
140 hm%bc_zero = .true.
141 tr%bc_zero = .true.
142 case (mxll_bc_constant)
143 tr%bc_constant = .true.
144 tr%bc_add_ab_region = .true.
145 hm%bc_constant = .true.
146 hm%bc_add_ab_region = .true.
147 case (mxll_bc_mirror_pec)
148 tr%bc_mirror_pec = .true.
149 hm%bc_mirror_pec = .true.
150 case (mxll_bc_mirror_pmc)
151 tr%bc_mirror_pmc = .true.
152 hm%bc_mirror_pmc = .true.
154 tr%bc_plane_waves = .true.
155 tr%bc_add_ab_region = .true.
156 hm%plane_waves = .true.
157 hm%bc_plane_waves = .true.
158 hm%bc_add_ab_region = .true.
159 end select
160 end do
161
162 if (any(hm%bc%bc_type(1:3) == mxll_bc_constant)) then
163 call td_function_mxll_init(st, namespace, hm)
164 safe_allocate(st%rs_state_const(1:st%dim))
165 st%rs_state_const = m_z0
166 end if
167
168 !%Variable MaxwellTDETRSApprox
169 !%Type integer
170 !%Default no
171 !%Section Maxwell::TD Propagation
172 !%Description
173 !% Whether to perform approximations to the ETRS propagator.
174 !%Option no 0
175 !% No approximations.
176 !%Option const_steps 1
177 !% Use constant current density.
178 !%End
179 call parse_variable(namespace, 'MaxwellTDETRSApprox', mxwll_etrs_full, tr%tr_etrs_approx)
180
181 !%Variable MaxwellPlaneWavesInBox
182 !%Type logical
183 !%Default no
184 !%Section Maxwell
185 !%Description
186 !% Analytic evaluation of the incoming waves inside the box,
187 !% not doing any numerical propagation of Maxwells equations.
188 !%End
189 call parse_variable(namespace, 'MaxwellPlaneWavesInBox', .false., tr%plane_waves_in_box)
190 if (tr%plane_waves_in_box .and. .not. hm%bc%do_plane_waves) then
191 call external_waves_init(hm%bc%plane_wave, namespace)
192 end if
193
194 call messages_print_with_emphasis(namespace=namespace)
196 !tr%te%exp = .true.
197 call exponential_init(tr%te, namespace, full_batch=.true.) ! initialize Maxwell propagator
199 call profiling_out("PROPAGATOR_MXLL_INIT")
202 end subroutine propagator_mxll_init
204 ! ---------------------------------------------------------
205 subroutine mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
206 type(hamiltonian_mxll_t), intent(inout) :: hm
207 type(namespace_t), intent(in) :: namespace
208 type(grid_t), intent(inout) :: gr
209 class(space_t), intent(in) :: space
210 type(states_mxll_t), intent(inout) :: st
211 type(propagator_mxll_t), intent(inout) :: tr
212 type(batch_t), intent(inout) :: rs_stateb
213 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t1(:,:)
214 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t2(:,:)
215 real(real64), intent(in) :: time
216 real(real64), intent(in) :: dt
217
218 integer :: ii, ff_dim, idim, istate, inter_steps
219 real(real64) :: inter_dt, inter_time
220
221
222 logical :: pml_check
223 type(batch_t) :: ff_rs_stateb, ff_rs_state_pmlb
224 type(batch_t) :: ff_rs_inhom_1b, ff_rs_inhom_2b, ff_rs_inhom_meanb
225 complex(real64), allocatable :: rs_state(:, :)
226
227 push_sub(mxll_propagation_step)
228
229 call profiling_in('MXLL_PROPAGATOR_STEP')
230 pml_check = .false.
231
232 if (hm%ma_mx_coupling_apply) then
233 message(1) = "Maxwell-matter coupling not implemented yet"
234 call messages_fatal(1, namespace=namespace)
235 end if
236 safe_allocate(rs_state(gr%np, st%dim))
237
238 if (tr%plane_waves_in_box) then
239 rs_state = m_z0
240 call plane_waves_in_box_calculation(hm%bc, time+dt, space, gr, gr%der, st, rs_state)
241 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
242 safe_deallocate_a(rs_state)
243 pop_sub(mxll_propagation_step)
244 return
245 end if
246
247 do idim = 1, 3
248 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__cpml) then
249 pml_check = .true.
250 end if
251 end do
252
253 ! this must be called only once, but can not be placed in init routines because PML parameters need to know about dt
254 if (pml_check .and. .not. hm%bc%pml%parameters_initialized) &
255 call bc_mxll_generate_pml_parameters(hm%bc, space, gr, hm%c_factor, dt)
256
257 ff_dim = hm%dim
258
259 ! intermediate step variables
260 inter_steps = 1
261 inter_dt = m_one / inter_steps * dt
262
263 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
264 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
265
266 if (pml_check) then
267 call ff_rs_stateb%copy_to(ff_rs_state_pmlb)
268 end if
269
270 ! first step of Maxwell inhomogeneity propagation with constant current density
271 if ((hm%ma_mx_coupling_apply .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) .and. &
272 tr%tr_etrs_approx == mxwll_etrs_const) then
273 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
274 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
275 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
276
277 do istate = 1, hm%dim
278 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t1(:, istate))
279 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
280 end do
281 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_meanb)
282 call batch_scal(gr%np, m_half, ff_rs_inhom_meanb)
283
284 ! inhomogeneity propagation
285 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_1b)
286 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
287
288 call hamiltonian_mxll_update(hm, time=time)
289 hm%cpml_hamiltonian = .false.
290 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt)
291
292 ! add term U(time+dt,time)J(time)
293 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
294 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
295 call hamiltonian_mxll_update(hm, time=time)
296 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt*m_half)
297 ! add term U(time+dt/2,time)J(time)
298 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
299 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
300 call hamiltonian_mxll_update(hm, time=time)
301 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt*m_half)
302 ! add term U(time,time+dt/2)J(time)
303 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
304 call ff_rs_inhom_2b%end()
305 call ff_rs_inhom_meanb%end()
306 end if
307
308 do ii = 1, inter_steps
309
310 ! intermediate time
311 inter_time = time + inter_dt * (ii-1)
312
313 ! transformation of RS state into 3x3 or 4x4 representation
314 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_forward)
315
316 ! RS state propagation
317 call hamiltonian_mxll_update(hm, time=inter_time)
318 if (pml_check) then
319 call pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
320 end if
321
322 hm%cpml_hamiltonian = pml_check
323 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
324 hm%cpml_hamiltonian = .false.
325
326 if (pml_check) then
327 call pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, inter_time, inter_dt, m_zero, ff_rs_state_pmlb, ff_rs_stateb)
328 end if
329
330 !Below we add the contribution from the inhomogeneous terms
331 if ((hm%ma_mx_coupling_apply) .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) then
332 if (tr%tr_etrs_approx == mxwll_etrs_full) then
333 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
334 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
335 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
336
337 ! Interpolation of the external current
338 do istate = 1, hm%dim
339 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t2(:, istate))
340 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
341 end do
342 ! store t1 - t2 for the interpolation in mean
343 call batch_axpy(gr%np, -m_one, ff_rs_inhom_1b, ff_rs_inhom_meanb)
344 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
345 call batch_axpy(gr%np, ii / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_2b)
346 call batch_axpy(gr%np, (ii-1) / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_1b)
347
348 hm%cpml_hamiltonian = .false.
349 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt)
350 ! add terms U(time+dt,time)J(time) and J(time+dt)
351 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
352 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
353
354 do istate = 1, hm%dim
355 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
356 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
357 end do
358 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
359 call batch_scal(gr%np, m_half, ff_rs_inhom_1b)
360 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
361
362 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt/m_two)
363 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt/m_two)
364
365 ! add terms U(time+dt/2,time)J(time) and U(time,time+dt/2)J(time+dt)
366 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
367 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
368
369 call ff_rs_inhom_1b%end()
370 call ff_rs_inhom_2b%end()
371 call ff_rs_inhom_meanb%end()
372 else if (tr%tr_etrs_approx == mxwll_etrs_const) then
373 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
374 end if
375 end if
376
377 ! PML convolution function update
378 if (pml_check) then
379 call cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
380 end if
381
382 ! back transformation of RS state representation
383 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_backward)
384
385 if (tr%bc_constant) then
386 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
387 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
388 if (st%rs_state_const_external) then
389 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, inter_time, inter_dt, m_zero, rs_state)
390 end if
391 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
392 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
393 end if
394
395 ! Propagation dt with H(inter_time+inter_dt) for PEC mirror boundaries
396 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
397 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
398 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
399 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
400 end if
401
402 ! Propagation dt with H(inter_time+inter_dt) for PMC mirror boundaries
403 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
404 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
405 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
406 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
407 end if
408
409 ! Apply mask absorbing boundaries
410 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
411 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
412 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, inter_time, inter_dt, m_zero, rs_state)
413 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
414 end if
415
416 if (tr%bc_plane_waves) then
417 ! Propagation dt with H(inter_time+inter_dt) for plane waves boundaries
418 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
419 call plane_waves_boundaries_calculation(hm, st, gr, inter_time+inter_dt, m_zero, rs_state)
420 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
421 end if
422
423 end do
424
425 if (tr%tr_etrs_approx == option__maxwelltdetrsapprox__const_steps) then
426 call ff_rs_inhom_1b%end()
427 end if
428
429 call ff_rs_stateb%end()
430
431 if (pml_check) then
432 call ff_rs_state_pmlb%end()
433 end if
434
435 safe_deallocate_a(rs_state)
436
437 call profiling_out('MXLL_PROPAGATOR_STEP')
438
439 pop_sub(mxll_propagation_step)
440 end subroutine mxll_propagation_step
441
442 ! ---------------------------------------------------------
443 subroutine mxll_propagate_leapfrog(hm, namespace, gr, space, st, tr, time, dt, counter)
444 type(hamiltonian_mxll_t), intent(inout) :: hm
445 type(namespace_t), intent(in) :: namespace
446 type(grid_t), intent(inout) :: gr
447 class(space_t), intent(in) :: space
448 type(states_mxll_t), intent(inout) :: st
449 type(propagator_mxll_t), intent(inout) :: tr
450 real(real64), intent(in) :: time
451 real(real64), intent(in) :: dt
452 integer, intent(in) :: counter
453
454 type(batch_t) :: rs_state_tmpb
455
456 push_sub_with_profile(mxll_propagate_leapfrog)
457
458 call st%rs_stateb%copy_to(rs_state_tmpb)
459
460 call hamiltonian_mxll_update(hm, time)
461
462 ! do boundaries at the beginning
463 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, st%rs_stateb)
464
465 ! update PML convolution values
466 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
467 call mxll_update_pml_simple(hm, st%rs_stateb)
468 end if
469
470 ! apply hamiltonian
471 call hamiltonian_mxll_apply_simple(hm, namespace, gr, st%rs_stateb, rs_state_tmpb)
472 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
473
474 ! add inhomogeneous terms
475 call batch_xpay(gr%np, st%inhomogeneousb, m_one, rs_state_tmpb)
476
477 if (counter == 0) then
478 ! for the first step, we do one forward Euler step
479 call batch_xpay(gr%np, st%rs_stateb, dt, rs_state_tmpb)
480 else
481 ! the leapfrog step depends on the previous state
482 call batch_xpay(gr%np, st%rs_state_prevb, m_two*dt, rs_state_tmpb)
483 end if
484
485 ! save the current rs state
486 call st%rs_stateb%copy_data_to(gr%np, st%rs_state_prevb)
487 ! update to new timestep
488 call rs_state_tmpb%copy_data_to(gr%np, st%rs_stateb)
489
490 ! update PML convolution values
491 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
492 call mxll_copy_pml_simple(hm, st%rs_stateb)
493 end if
494
495 call rs_state_tmpb%end()
496
497 pop_sub_with_profile(mxll_propagate_leapfrog)
498 end subroutine mxll_propagate_leapfrog
499
500 ! ---------------------------------------------------------
514 subroutine mxll_propagate_expgauss1(hm, namespace, gr, space, st, tr, time, dt)
515 type(hamiltonian_mxll_t), intent(inout) :: hm
516 type(namespace_t), intent(in) :: namespace
517 type(grid_t), intent(inout) :: gr
518 class(space_t), intent(in) :: space
519 type(states_mxll_t), intent(inout) :: st
520 type(propagator_mxll_t), intent(inout) :: tr
521 real(real64), intent(in) :: time
522 real(real64), intent(in) :: dt
523
524 type(batch_t) :: rs_state_tmpb
525
526 push_sub_with_profile(mxll_propagate_expgauss1)
527
528 call st%rs_stateb%copy_to(rs_state_tmpb)
529
530 call hamiltonian_mxll_update(hm, time)
531
532 ! do boundaries at the beginning (should be included in Hamiltonian?)
533 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
534 dt, st%rs_stateb)
535
536 ! update PML convolution values
537 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
538 call mxll_update_pml_simple(hm, st%rs_stateb)
539 end if
540
541 ! accumulate -i H F_n - J_1 in rs_state_tmpb
542 ! compute H F_n
543 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
544 ! compute -i H F_n
545 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
546 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
547 ! set J_1
548 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
549 ! accumulate -J_1 to rs_state_tmpb
550 call batch_axpy(gr%np, -m_one, st%inhomogeneousb, rs_state_tmpb)
551 end if
552 ! compute phi_1
553 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
554 ! F_{n+1} = F_n + dt * phi_1 (...)
555 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
556
557 call rs_state_tmpb%end()
558
559 ! update PML convolution values
560 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
561 call mxll_copy_pml_simple(hm, st%rs_stateb)
562 end if
563
564 pop_sub_with_profile(mxll_propagate_expgauss1)
565 end subroutine mxll_propagate_expgauss1
566
567 ! ---------------------------------------------------------
587 subroutine mxll_propagate_expgauss2(hm, namespace, gr, space, st, tr, time, dt)
588 type(hamiltonian_mxll_t), intent(inout) :: hm
589 type(namespace_t), intent(in) :: namespace
590 type(grid_t), intent(inout) :: gr
591 class(space_t), intent(in) :: space
592 type(states_mxll_t), intent(inout) :: st
593 type(propagator_mxll_t), intent(inout) :: tr
594 real(real64), intent(in) :: time
595 real(real64), intent(in) :: dt
596
597 type(batch_t) :: rs_state_tmpb
598
599 push_sub_with_profile(mxll_propagate_expgauss2)
600
601 call st%rs_stateb%copy_to(rs_state_tmpb)
602
603 call hamiltonian_mxll_update(hm, time)
604
605 ! do boundaries at the beginning (should be included in Hamiltonian?)
606 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
607 dt, st%rs_stateb)
608
609 ! update PML convolution values
610 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
611 call mxll_update_pml_simple(hm, st%rs_stateb)
612 end if
613
614 ! accumulate -i H F_n - a_1 J_1 - a_2 J_2 in rs_state_tmpb
615 ! compute H F_n
616 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
617 ! compute -i H F_n
618 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
619 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
620 ! set J_1
621 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
622 ! accumulate -a_1 J_1 to rs_state_tmpb
623 call batch_axpy(gr%np, -m_half*(m_one+sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
624 ! set J_2
625 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
626 ! accumulate -a_2 J_2 to rs_state_tmpb
627 call batch_axpy(gr%np, -m_half*(m_one-sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
628 end if
629 ! compute phi_1
630 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
631 ! accumulate phi_1 term: F_{n+1} = F_n + dt * phi_1 (...)
632 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
633 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
634 call batch_set_zero(rs_state_tmpb)
635 ! set J_1
636 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
637 ! accumulate -b_1 J_1 to rs_state_tmpb
638 call batch_axpy(gr%np, sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
639 ! set J_2
640 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
641 ! accumulate -b_2 J_2 to rs_state_tmpb
642 call batch_axpy(gr%np, -sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
643
644 ! compute phi_2
645 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 2)
646 ! accumulate phi_2 term: F_{n+1} = F_n + dt * phi_2 (...)
647 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
648 end if
649
650 ! update PML convolution values
651 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
652 call mxll_copy_pml_simple(hm, st%rs_stateb)
653 end if
654
655 call rs_state_tmpb%end()
656
657 pop_sub_with_profile(mxll_propagate_expgauss2)
658 end subroutine mxll_propagate_expgauss2
659
660 ! ---------------------------------------------------------
661 subroutine set_medium_rs_state(st, gr, hm)
662 type(states_mxll_t), intent(inout) :: st
663 type(grid_t), intent(in) :: gr
664 type(hamiltonian_mxll_t), intent(in) :: hm
665
666 integer :: ip, ip_in, il, idim
667
668 push_sub(set_medium_rs_state)
669
670 assert(allocated(st%ep) .and. allocated(st%mu))
671
672 call profiling_in('SET_MEDIUM_RS_STATE')
673
674 if (hm%calc_medium_box) then
675 do il = 1, size(hm%medium_boxes)
676 assert(.not. hm%medium_boxes(il)%has_mapping)
677 do ip = 1, hm%medium_boxes(il)%points_number
678 if (abs(hm%medium_boxes(il)%c(ip)) <= m_epsilon) cycle
679 st%ep(ip) = hm%medium_boxes(il)%ep(ip)
680 st%mu(ip) = hm%medium_boxes(il)%mu(ip)
681 end do
682 end do
683 end if
684
685 do idim = 1, st%dim
686 if (hm%bc%bc_type(idim) == mxll_bc_medium) then
687 do ip_in = 1, hm%bc%medium(idim)%points_number
688 ip = hm%bc%medium(idim)%points_map(ip_in)
689 st%ep(ip) = hm%bc%medium(idim)%ep(ip_in)
690 st%mu(ip) = hm%bc%medium(idim)%mu(ip_in)
691 end do
692 end if
693 end do
694
695 call profiling_out('SET_MEDIUM_RS_STATE')
696
697 pop_sub(set_medium_rs_state)
698 end subroutine set_medium_rs_state
699
700 ! ---------------------------------------------------------
701 subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
702 type(hamiltonian_mxll_t), intent(in) :: hm
703 type(grid_t), intent(in) :: gr
704 type(states_mxll_t), intent(in) :: st
705 type(batch_t), intent(inout) :: rs_stateb
706 type(batch_t), intent(inout) :: ff_rs_stateb
707 integer, intent(in) :: sign
708
709 complex(real64), allocatable :: rs_state(:,:)
710 complex(real64), allocatable :: rs_state_tmp(:,:)
711 integer :: ii, np
712
714
715 call profiling_in('TRANSFORM_RS_STATE')
716
717 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
718
719 np = gr%np
720 safe_allocate(rs_state(1:gr%np, 1:st%dim))
721
722 if (hm%operator == faraday_ampere_medium) then
723 if (sign == rs_trans_forward) then
724 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
725 ! 3 to 6
726 do ii = 1, 3
727 call batch_set_state(ff_rs_stateb, ii, np, rs_state(:, ii))
728 call batch_set_state(ff_rs_stateb, ii+3, np, conjg(rs_state(:, ii)))
729 end do
730 else
731 ! 6 to 3
732 safe_allocate(rs_state_tmp(1:gr%np, 1:st%dim))
733 do ii = 1, 3
734 call batch_get_state(ff_rs_stateb, ii, np, rs_state(:, ii))
735 call batch_get_state(ff_rs_stateb, ii+3, np, rs_state_tmp(:, ii))
736 rs_state(1:np, ii) = m_half * (rs_state(1:np, ii) + conjg(rs_state_tmp(1:np, ii)))
737 end do
738 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
739 safe_deallocate_a(rs_state_tmp)
740 end if
741 else
742 if (sign == rs_trans_forward) then
743 call rs_stateb%copy_data_to(gr%np, ff_rs_stateb)
744 else
745 call ff_rs_stateb%copy_data_to(gr%np, rs_stateb)
746 end if
747 end if
748 safe_deallocate_a(rs_state)
749
750 call profiling_out('TRANSFORM_RS_STATE')
751
753
754 end subroutine transform_rs_state_batch
755
756 ! ---------------------------------------------------------
757 subroutine transform_rs_densities(hm, mesh, rs_charge_density, rs_current_density, ff_density, sign)
758 type(hamiltonian_mxll_t), intent(in) :: hm
759 class(mesh_t), intent(in) :: mesh
760 complex(real64), intent(inout) :: rs_charge_density(:)
761 complex(real64), intent(inout) :: rs_current_density(:,:)
762 complex(real64), intent(inout) :: ff_density(:,:)
763 integer, intent(in) :: sign
764
765
766 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
767 assert(size(rs_charge_density) == mesh%np .or. size(rs_charge_density) == mesh%np_part)
768 assert(size(rs_current_density, dim=1) == size(rs_charge_density))
769 assert(size(rs_current_density, dim=2) == 3)
770
771 push_sub(transform_rs_densities)
772
773 call profiling_in('TRANSFORM_RS_DENSITIES')
774
775 if (hm%operator == faraday_ampere_medium) then
776 if (sign == rs_trans_forward) then
777 call transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, &
778 rs_current_density, ff_density)
779 else
781 rs_charge_density, rs_current_density)
782 end if
783 else
784 if (sign == rs_trans_forward) then
785 ff_density(1:mesh%np, 1:3) = rs_current_density(1:mesh%np, 1:3)
786 else
787 rs_current_density(1:mesh%np, 1:3) = ff_density(1:mesh%np, 1:3)
788 end if
789 end if
790
791 call profiling_out('TRANSFORM_RS_DENSITIES')
792
794
795 end subroutine transform_rs_densities
797 !----------------------------------------------------------
798 subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, rs_current_density, rs_density_6x6)
799 class(mesh_t), intent(in) :: mesh
800 complex(real64), intent(in) :: rs_charge_density(:)
801 complex(real64), intent(in) :: rs_current_density(:,:)
802 complex(real64), intent(inout) :: rs_density_6x6(:,:)
803
804 integer :: ii
805
806 assert(size(rs_current_density, dim=2) == 3)
807 assert(size(rs_density_6x6, dim=2) == 6)
808
809 ! no push_sub, called to frequently
810 do ii = 1, 3
811 rs_density_6x6(1:mesh%np, ii) = rs_current_density(1:mesh%np, ii)
812 rs_density_6x6(1:mesh%np, ii+3) = rs_current_density(1:mesh%np, ii)
813 end do
814
816
817 !----------------------------------------------------------
818 subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_charge_density, rs_current_density)
819 class(mesh_t), intent(in) :: mesh
820 complex(real64), intent(in) :: rs_density_6x6(:,:)
821 complex(real64), intent(inout) :: rs_charge_density(:)
822 complex(real64), intent(inout) :: rs_current_density(:,:)
823
824 integer :: ii
825
826 assert(size(rs_current_density, dim=2) == 3)
827 assert(size(rs_density_6x6, dim=2) == 6)
828
829 ! no push_sub, called to frequently
830 do ii = 1, 3
831 rs_current_density(1:mesh%np, ii) = m_half * &
832 real(rs_density_6x6(1:mesh%np, ii) + rs_density_6x6(1:mesh%np, ii+3), real64)
833 end do
834
836
837 !----------------------------------------------------------
838 subroutine calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, st_elec, hm_elec, rs_state_matter)
839 type(grid_t), intent(in) :: gr_mxll
840 type(states_mxll_t), intent(in) :: st_mxll
841 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
842 type(grid_t), intent(in) :: gr_elec
843 type(states_elec_t), intent(in) :: st_elec
844 type(hamiltonian_elec_t), intent(in) :: hm_elec
845 complex(real64), intent(inout) :: rs_state_matter(:,:)
846
847 complex(real64), allocatable :: tmp_pot_mx_gr(:,:), tmp_grad_mx_gr(:,:)
848
849 safe_allocate(tmp_pot_mx_gr(1:gr_mxll%np_part,1))
850 safe_allocate(tmp_grad_mx_gr(1:gr_mxll%np,1:gr_mxll%box%dim))
851 ! this subroutine needs the matter part
854
855 tmp_pot_mx_gr(:,:) = m_zero
856 tmp_grad_mx_gr(:,:) = m_zero
857 call zderivatives_grad(gr_mxll%der, tmp_pot_mx_gr(:,1), tmp_grad_mx_gr(:,:), set_bc = .false.)
858 tmp_grad_mx_gr = - tmp_grad_mx_gr
859
860 rs_state_matter = m_z0
861 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, &
862 rs_state_matter(1:gr_mxll%np,:), gr_mxll, st_mxll%ep(1:gr_mxll%np), st_mxll%mu(1:gr_mxll%np), &
863 gr_mxll%np)
864
865 safe_deallocate_a(tmp_pot_mx_gr)
866 safe_deallocate_a(tmp_grad_mx_gr)
867
870
871 !----------------------------------------------------------
872 subroutine get_vector_pot_and_transverse_field(namespace, trans_calc_method, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, st, &
873 poisson_solver, helmholtz, time, field, transverse_field, vector_potential)
874 type(namespace_t), intent(in) :: namespace
875 integer, intent(in) :: trans_calc_method
876 type(grid_t), intent(in) :: gr_mxll
877 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
878 type(states_mxll_t), intent(in) :: st_mxll
879 type(propagator_mxll_t), intent(in) :: tr_mxll
880 type(hamiltonian_elec_t), intent(in) :: hm
881 type(states_elec_t), intent(in) :: st
882 type(poisson_t), intent(in) :: poisson_solver
883 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
884 real(real64), intent(in) :: time
885 complex(real64), intent(inout) :: field(:,:)
886 complex(real64), intent(inout) :: transverse_field(:,:)
887 real(real64), intent(inout) :: vector_potential(:,:)
888
889 integer :: np
890 complex(real64), allocatable :: rs_state_plane_waves(:, :)
891
894 transverse_field = m_z0
895 vector_potential = m_zero
896
897 np = gr_mxll%np
898
899 if (hm_mxll%ma_mx_coupling) then
900
901 ! check what other transverse field methods are needed
902
903 ! trans_calc_method == OPTION__MAXWELLTRANSFIELDCALCULATIONMETHOD__TRANS_FIELD_POISSON
904 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
905 safe_allocate(rs_state_plane_waves(1:gr_mxll%np, 1:st_mxll%dim))
906 call mxll_get_batch(st_mxll%rs_state_plane_wavesb, rs_state_plane_waves, gr_mxll%np, st_mxll%dim)
907 end if
908
909 ! plane waves subtraction
910 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
911 transverse_field(1:np,:) = field(1:np,:) - rs_state_plane_waves(1:np,:)
912 else
913 transverse_field(1:np,:) = field(1:np,:)
914 end if
915 ! apply helmholtz decomposition for transverse field
916 call helmholtz%get_trans_field(namespace, transverse_field, total_field=field)
917 ! plane waves addition
918 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
919 transverse_field(1:np,:) = transverse_field(1:np,:) + rs_state_plane_waves(1:np,:)
920 safe_deallocate_a(rs_state_plane_waves)
921 end if
922
923 else
924
925 transverse_field(1:np,:) = field
926
927 end if
928
929
931
934 ! ---------------------------------------------------------
935 subroutine calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
936 type(namespace_t), intent(in) :: namespace
937 type(poisson_t), intent(in) :: poisson_solver
938 type(grid_t), intent(in) :: gr
939 type(states_mxll_t), intent(in) :: st
940 complex(real64), intent(in) :: field(:,:)
941 real(real64), contiguous, intent(inout) :: vector_potential(:,:)
942
943 integer :: idim
944 real(real64), allocatable :: dtmp(:,:)
945
946 safe_allocate(dtmp(1:gr%np_part,1:3))
947
948 dtmp = m_zero
949
950 call get_magnetic_field_state(field, gr, st%rs_sign, vector_potential, st%mu, gr%np_part)
951 dtmp = vector_potential
952 call dderivatives_curl(gr%der, dtmp, vector_potential, set_bc = .false.)
953 do idim=1, st%dim
954 call dpoisson_solve(poisson_solver, namespace, dtmp(:,idim), vector_potential(:,idim), .true.)
955 end do
956 vector_potential = m_one / (m_four * m_pi) * vector_potential
957
958 safe_deallocate_a(dtmp)
959
960 end subroutine calculate_vector_potential
961
962 !----------------------------------------------------------
963 subroutine energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
964 type(grid_t), intent(in) :: gr
965 type(states_mxll_t), intent(in) :: st
966 type(hamiltonian_mxll_t), intent(in) :: hm
967 type(energy_mxll_t), intent(inout) :: energy_mxll
968 complex(real64), intent(in) :: rs_field(:,:)
969 complex(real64), optional, intent(in) :: rs_field_plane_waves(:,:)
970
971 real(real64), allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:), energy_density_plane_waves(:)
972
973 push_sub(energy_mxll_calc)
974
975 call profiling_in('ENERGY_MXLL_CALC')
976
977 safe_allocate(energy_density(1:gr%np))
978 safe_allocate(e_energy_density(1:gr%np))
979 safe_allocate(b_energy_density(1:gr%np))
980 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
981 safe_allocate(energy_density_plane_waves(1:gr%np))
982 end if
983
984 call energy_density_calc(gr, st, rs_field, energy_density, e_energy_density, &
985 b_energy_density, hm%plane_waves, rs_field_plane_waves, energy_density_plane_waves)
986 energy_mxll%energy = dmf_integrate(gr, energy_density, mask=st%inner_points_mask)
987 energy_mxll%e_energy = dmf_integrate(gr, e_energy_density, mask=st%inner_points_mask)
988 energy_mxll%b_energy = dmf_integrate(gr, b_energy_density, mask=st%inner_points_mask)
989 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
990 energy_mxll%energy_plane_waves = dmf_integrate(gr, energy_density_plane_waves, mask=st%inner_points_mask)
991 else
992 energy_mxll%energy_plane_waves = m_zero
993 end if
994
995 energy_mxll%boundaries = dmf_integrate(gr, energy_density, mask=st%boundary_points_mask)
996
997 safe_deallocate_a(energy_density)
998 safe_deallocate_a(e_energy_density)
999 safe_deallocate_a(b_energy_density)
1000 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
1001 safe_deallocate_a(energy_density_plane_waves)
1002 end if
1003
1004 call profiling_out('ENERGY_MXLL_CALC')
1005
1006 pop_sub(energy_mxll_calc)
1007 end subroutine energy_mxll_calc
1008
1009 !----------------------------------------------------------
1010 subroutine energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
1011 type(grid_t), intent(in) :: gr
1012 type(states_mxll_t), intent(in) :: st
1013 type(hamiltonian_mxll_t), intent(in) :: hm
1014 type(energy_mxll_t), intent(inout) :: energy_mxll
1015 type(batch_t), intent(in) :: rs_fieldb
1016 type(batch_t), intent(in) :: rs_field_plane_wavesb
1017
1018 type(batch_t) :: e_fieldb, b_fieldb, e_field_innerb, b_field_innerb, rs_field_plane_waves_innerb
1019 real(real64) :: tmp(1:st%dim)
1020 complex(real64) :: ztmp(1:st%dim)
1021
1022 push_sub(energy_mxll_calc_batch)
1023
1024 call profiling_in('ENERGY_MXLL_CALC_BATCH')
1025
1026 call dbatch_init(e_fieldb, 1, 1, st%dim, gr%np)
1027 if (st%pack_states) then
1028 call e_fieldb%do_pack(copy=.false.)
1029 end if
1030 call e_fieldb%copy_to(b_fieldb)
1031 call e_fieldb%copy_to(e_field_innerb)
1032 call e_fieldb%copy_to(b_field_innerb)
1033
1034 call batch_split_complex(gr%np, rs_fieldb, e_fieldb, b_fieldb)
1035
1036 ! subtract energy of inner points
1037 call batch_set_zero(e_field_innerb)
1038 call batch_set_zero(b_field_innerb)
1039 if (accel_is_enabled()) then
1040 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, e_fieldb, e_field_innerb)
1041 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, b_fieldb, b_field_innerb)
1042 else
1043 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, e_fieldb, e_field_innerb)
1044 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, b_fieldb, b_field_innerb)
1045 end if
1046 call dmesh_batch_dotp_vector(gr, e_field_innerb, e_field_innerb, tmp)
1047 energy_mxll%e_energy = sum(tmp)
1048 call dmesh_batch_dotp_vector(gr, b_field_innerb, b_field_innerb, tmp)
1049 energy_mxll%b_energy = sum(tmp)
1050 energy_mxll%energy = energy_mxll%e_energy + energy_mxll%b_energy
1051
1052 call dmesh_batch_dotp_vector(gr, e_fieldb, e_fieldb, tmp)
1053 energy_mxll%boundaries = sum(tmp)
1054 call dmesh_batch_dotp_vector(gr, b_fieldb, b_fieldb, tmp)
1055 energy_mxll%boundaries = energy_mxll%boundaries + sum(tmp)
1056 energy_mxll%boundaries = energy_mxll%boundaries - energy_mxll%energy
1057
1058 if (hm%plane_waves) then
1059 call rs_field_plane_wavesb%copy_to(rs_field_plane_waves_innerb)
1060 call batch_set_zero(rs_field_plane_waves_innerb)
1061 if (accel_is_enabled()) then
1062 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, &
1063 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1064 else
1065 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, &
1066 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1067 end if
1068 call zmesh_batch_dotp_vector(gr, rs_field_plane_waves_innerb, rs_field_plane_waves_innerb, ztmp)
1069 energy_mxll%energy_plane_waves = sum(real(tmp, real64) )
1070 call rs_field_plane_waves_innerb%end()
1071 else
1072 energy_mxll%energy_plane_waves = m_zero
1073 end if
1074
1075 call e_fieldb%end()
1076 call b_fieldb%end()
1077 call e_field_innerb%end()
1078 call b_field_innerb%end()
1079
1080 call profiling_out('ENERGY_MXLL_CALC_BATCH')
1081
1082 pop_sub(energy_mxll_calc_batch)
1083 end subroutine energy_mxll_calc_batch
1084
1085 ! ---------------------------------------------------------
1086 subroutine mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
1087 type(namespace_t), intent(in) :: namespace
1088 type(grid_t), intent(in) :: gr
1089 type(hamiltonian_mxll_t), intent(inout) :: hm
1090 type(states_mxll_t), intent(inout) :: st
1091 type(propagator_mxll_t), intent(inout) :: tr
1092 real(real64), intent(in) :: time
1093 real(real64), intent(in) :: dt
1094 real(real64), intent(in) :: time_delay
1095 complex(real64), intent(inout) :: rs_state(:,:)
1096
1097 integer :: ip, ip_in, idim
1098 logical :: mask_check
1099
1101
1102 call profiling_in('MASK_ABSORBING_BOUNDARIES')
1103 mask_check = .false.
1104
1105 do idim = 1, 3
1106 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1107 mask_check = .true.
1108 end if
1109 end do
1110
1111 if (mask_check) then
1112 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1113 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1114 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1115 rs_state = rs_state - st%rs_state_plane_waves
1116 call maxwell_mask(hm, rs_state)
1117 rs_state = rs_state + st%rs_state_plane_waves
1118 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1119 !call constant_at_absorbing_boundaries_calculation(st, hm%bc)
1120 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1121 do ip_in=1, hm%bc%constant_points_number
1122 ip = hm%bc%constant_points_map(ip_in)
1123 rs_state(ip,:) = rs_state(ip,:) - st%rs_state_const(:)
1124 end do
1125 call maxwell_mask(hm, rs_state)
1126 do ip_in=1, hm%bc%constant_points_number
1127 ip = hm%bc%constant_points_map(ip_in)
1128 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const(:)
1129 end do
1130 else
1131 call maxwell_mask(hm, rs_state)
1132 end if
1133 end if
1134
1135 call profiling_out('MASK_ABSORBING_BOUNDARIES')
1136
1138 end subroutine mask_absorbing_boundaries
1139
1140 ! ---------------------------------------------------------
1141 subroutine maxwell_mask(hm, rs_state)
1142 type(hamiltonian_mxll_t), intent(in) :: hm
1143 complex(real64), intent(inout) :: rs_state(:,:)
1144
1145 integer :: ip, ip_in, idim
1146
1147 push_sub(maxwell_mask)
1148
1149 call profiling_in('MAXWELL_MASK')
1150
1151 do idim = 1, 3
1152 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1153 do ip_in = 1, hm%bc%mask_points_number(idim)
1154 ip = hm%bc%mask_points_map(ip_in,idim)
1155 rs_state(ip,:) = rs_state(ip,:) * hm%bc%mask(ip_in,idim)
1156 end do
1157 end if
1158 end do
1159
1160 call profiling_out('MAXWELL_MASK')
1161
1162 pop_sub(maxwell_mask)
1163 end subroutine maxwell_mask
1164
1165 ! ---------------------------------------------------------
1166 subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
1167 type(hamiltonian_mxll_t), intent(inout) :: hm
1168 type(grid_t), intent(in) :: gr
1169 type(states_mxll_t), intent(inout) :: st
1170 type(propagator_mxll_t), intent(inout) :: tr
1171 type(batch_t), intent(in) :: ff_rs_stateb
1172 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1173
1174 integer :: ii
1175 complex(real64), allocatable :: rs_state_constant(:,:)
1176 type(batch_t) :: rs_state_constantb
1177
1179
1180 call profiling_in('PML_PROP_STAGE_1_BATCH')
1182 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1183 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, &
1184 ff_rs_state_pmlb, rs_trans_forward)
1185 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1186 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1187 ! this could be optimized: right now we broadcast the constant value
1188 ! to the full mesh to be able to use the batch functions easily.
1189 ! in principle, we would need to do the transform only for one point
1190 ! and then subtract that value from all points of the state
1191 safe_allocate(rs_state_constant(1:gr%np,1:3))
1192 do ii = 1, 3
1193 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1194 end do
1195 call ff_rs_stateb%copy_to(rs_state_constantb)
1196 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, 3)
1197
1198 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, &
1199 ff_rs_state_pmlb, rs_trans_forward)
1200 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1201
1202 call rs_state_constantb%end()
1203
1204 safe_deallocate_a(rs_state_constant)
1205 else
1206 ! this copy should not be needed
1207 call ff_rs_stateb%copy_data_to(gr%np, ff_rs_state_pmlb)
1208 end if
1209
1210 call profiling_out('PML_PROP_STAGE_1_BATCH')
1211
1213 end subroutine pml_propagation_stage_1_batch
1214
1215 ! ---------------------------------------------------------
1216 subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
1217 type(hamiltonian_mxll_t), intent(inout) :: hm
1218 type(namespace_t), intent(in) :: namespace
1219 type(grid_t), intent(in) :: gr
1220 type(states_mxll_t), intent(inout) :: st
1221 type(propagator_mxll_t), intent(inout) :: tr
1222 real(real64), intent(in) :: time
1223 real(real64), intent(in) :: dt
1224 real(real64), intent(in) :: time_delay
1225 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1226 type(batch_t), intent(inout) :: ff_rs_stateb
1227
1228 integer :: ii, ff_dim
1229 complex(real64), allocatable :: rs_state_constant(:,:), ff_rs_state_constant(:,:)
1230 type(batch_t) :: ff_rs_state_plane_wavesb, ff_rs_constantb, rs_state_constantb
1231
1233
1234 call profiling_in('PML_PROP_STAGE_2_BATCH')
1235
1236 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1237 hm%cpml_hamiltonian = .true.
1238 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1239 hm%cpml_hamiltonian = .false.
1240 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1241
1242 call ff_rs_stateb%copy_to(ff_rs_state_plane_wavesb)
1243 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_state_plane_wavesb, rs_trans_forward)
1244
1245 if (ff_rs_stateb%status() == batch_device_packed) then
1246 ! use the map of points stored on the GPU in this case
1247 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%buff_map, &
1248 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1249 else
1250 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%points_map, &
1251 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1252 end if
1253
1254 call ff_rs_state_plane_wavesb%end()
1255
1256 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1257 hm%cpml_hamiltonian = .true.
1258 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1259 hm%cpml_hamiltonian = .false.
1260
1261 call ff_rs_stateb%copy_to(ff_rs_constantb)
1262 ff_dim = ff_rs_stateb%nst_linear
1263 safe_allocate(rs_state_constant(1:gr%np, 1:st%dim))
1264 ! copy the value to the full mesh to be able to use batches
1265 ! this is in principle unneeded, but otherwise we could not use batches...
1266 do ii = 1, st%dim
1267 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1268 end do
1269 call ff_rs_stateb%copy_to(rs_state_constantb)
1270 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, st%dim)
1271
1272 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, ff_rs_constantb, rs_trans_forward)
1273 if (ff_rs_stateb%status() == batch_device_packed) then
1274 ! use the map of points stored on the GPU in this case
1275 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%buff_constant_points_map, &
1276 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1277 else
1278 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%constant_points_map, &
1279 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1280 end if
1281
1282 call ff_rs_constantb%end()
1283 call rs_state_constantb%end()
1284
1285 safe_deallocate_a(rs_state_constant)
1286 safe_deallocate_a(ff_rs_state_constant)
1287 end if
1288
1289 call profiling_out('PML_PROP_STAGE_2_BATCH')
1290
1292 end subroutine pml_propagation_stage_2_batch
1293
1294 ! ---------------------------------------------------------
1295 subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
1296 type(hamiltonian_mxll_t), intent(inout) :: hm
1297 type(grid_t), intent(in) :: gr
1298 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1299
1300
1302
1303 call profiling_in('CPML_CONV_FUNCTION_UPDATE')
1304
1305 call cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1306
1307 call profiling_out('CPML_CONV_FUNCTION_UPDATE')
1308
1310 end subroutine cpml_conv_function_update
1312 ! ---------------------------------------------------------
1313 subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1314 type(hamiltonian_mxll_t), intent(inout) :: hm
1315 type(grid_t), intent(in) :: gr
1316 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1317
1318 integer :: ip, ip_in, np_part, rs_sign
1319 complex(real64) :: pml_a, pml_b, pml_g, grad
1320 integer :: pml_dir, field_dir, ifield, idir
1321 integer, parameter :: field_dirs(3, 2) = reshape([2, 3, 1, 3, 1, 2], [3, 2])
1322 logical :: with_medium
1323 type(batch_t) :: gradb(gr%der%dim)
1324 type(accel_kernel_t), save :: ker_pml
1325 integer :: wgsize
1326
1328
1329 call profiling_in('CPML_CONV_UPDATE_VIA_RS')
1330
1331 assert(hm%dim == 3 .or. hm%dim == 6)
1332
1333 np_part = gr%np_part
1334 rs_sign = hm%rs_sign
1335
1336 call zderivatives_batch_grad(gr%der, ff_rs_state_pmlb, gradb)
1337
1338 with_medium = hm%dim == 6
1339
1340 do pml_dir = 1, hm%st%dim
1341 select case (gradb(pml_dir)%status())
1342 case (batch_not_packed)
1343 do ip_in=1, hm%bc%pml%points_number
1344 ip = hm%bc%pml%points_map(ip_in)
1345 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1346 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1347 do ifield = 1, 2
1348 field_dir = field_dirs(pml_dir, ifield)
1349 grad = gradb(pml_dir)%zff_linear(ip, field_dir)
1350 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1351 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1352 if (with_medium) then
1353 grad = gradb(pml_dir)%zff_linear(ip, field_dir+3)
1354 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1355 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1356 end if
1357 end do
1358 end do
1359 case (batch_packed)
1360 do ip_in=1, hm%bc%pml%points_number
1361 ip = hm%bc%pml%points_map(ip_in)
1362 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1363 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1364 do ifield = 1, 2
1365 field_dir = field_dirs(pml_dir, ifield)
1366 grad = gradb(pml_dir)%zff_pack(field_dir, ip)
1367 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1368 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1369 if (with_medium) then
1370 grad = gradb(pml_dir)%zff_pack(field_dir+3, ip)
1371 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1372 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1373 end if
1374 end do
1375 end do
1376 case (batch_device_packed)
1377 call accel_kernel_start_call(ker_pml, 'pml.cl', 'pml_update_conv')
1378
1379 if (with_medium) then
1380 call accel_set_kernel_arg(ker_pml, 0, 1_int32)
1381 else
1382 call accel_set_kernel_arg(ker_pml, 0, 0_int32)
1383 end if
1384 call accel_set_kernel_arg(ker_pml, 1, hm%bc%pml%points_number)
1385 call accel_set_kernel_arg(ker_pml, 2, pml_dir-1)
1386 call accel_set_kernel_arg(ker_pml, 3, hm%bc%pml%buff_map)
1387 call accel_set_kernel_arg(ker_pml, 4, gradb(pml_dir)%ff_device)
1388 call accel_set_kernel_arg(ker_pml, 5, log2(int(gradb(pml_dir)%pack_size(1), int32)))
1389 call accel_set_kernel_arg(ker_pml, 6, hm%bc%pml%buff_a)
1390 call accel_set_kernel_arg(ker_pml, 7, hm%bc%pml%buff_b)
1391 call accel_set_kernel_arg(ker_pml, 8, hm%bc%pml%buff_conv_plus)
1392 call accel_set_kernel_arg(ker_pml, 9, hm%bc%pml%buff_conv_minus)
1393
1394 wgsize = accel_max_workgroup_size()
1395 call accel_kernel_run(ker_pml, (/ accel_padded_size(hm%bc%pml%points_number) /), (/ wgsize /))
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')
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)
1527 end do
1528 st%rs_state_const(:) = st%rs_state_const(:) * tf_new
1529 end if
1530 end if
1531
1532 call profiling_out('SPATIAL_CONSTANT_CALCULATION')
1533
1535 end subroutine spatial_constant_calculation
1536
1537 ! ---------------------------------------------------------
1538 subroutine constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
1539 logical, intent(in) :: constant_calc
1540 type(bc_mxll_t), intent(inout) :: bc
1541 type(states_mxll_t), intent(in) :: st
1542 type(hamiltonian_mxll_t), intent(in) :: hm
1543 complex(real64), intent(inout) :: rs_state(:,:)
1544
1545 integer :: ip_in, ip
1546
1548 call profiling_in('CONSTANT_BOUNDARIES_CALC')
1549
1550 if (hm%spatial_constant_apply) then
1551 if (constant_calc) then
1552 do ip_in = 1, bc%constant_points_number
1553 ip = bc%constant_points_map(ip_in)
1554 rs_state(ip,:) = st%rs_state_const(:)
1555 bc%constant_rs_state(ip_in,:) = st%rs_state_const(:)
1556 end do
1557 end if
1558 end if
1559
1560 call profiling_out('CONSTANT_BOUNDARIES_CALC')
1561
1563 end subroutine constant_boundaries_calculation
1564
1565 ! ---------------------------------------------------------
1566 subroutine mirror_pec_boundaries_calculation(bc, st, rs_state)
1567 type(bc_mxll_t), intent(in) :: bc
1568 type(states_mxll_t), intent(in) :: st
1569 complex(real64), intent(inout) :: rs_state(:,:)
1570
1571 integer :: ip, ip_in, idim
1572 real(real64) :: e_field(st%dim), b_field(st%dim)
1573
1575
1576 do idim = 1, 3
1577 if (bc%bc_type(idim) == mxll_bc_mirror_pec) then
1578 do ip_in = 1, bc%mirror_points_number(idim)
1579 ip = bc%mirror_points_map(ip_in, idim)
1580 e_field(:) = m_zero
1581 call get_magnetic_field_vector(rs_state(ip,:), st%rs_sign, b_field(:), st%mu(ip))
1582 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1583 end do
1584 end if
1585 end do
1586
1589
1590 ! ---------------------------------------------------------
1591 subroutine mirror_pmc_boundaries_calculation(bc, st, rs_state)
1592 type(bc_mxll_t), intent(in) :: bc
1593 type(states_mxll_t), intent(in) :: st
1594 complex(real64), intent(inout) :: rs_state(:,:)
1595
1596 integer :: ip, ip_in, idim
1597 real(real64) :: e_field(st%dim), b_field(st%dim)
1598
1600
1601 do idim = 1, 3
1602 if (bc%bc_type(idim) == mxll_bc_mirror_pmc) then
1603 do ip_in = 1, bc%mirror_points_number(idim)
1604 ip = bc%mirror_points_map(ip_in,idim)
1605 b_field(:) = m_zero
1606 call get_electric_field_vector(rs_state(ip,:), e_field(:), st%ep(ip))
1607 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1608 end do
1609 end if
1610 end do
1611
1614
1615 ! ---------------------------------------------------------
1616 subroutine plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
1617 type(hamiltonian_mxll_t), intent(in) :: hm
1618 type(states_mxll_t), intent(in) :: st
1619 class(mesh_t), intent(in) :: mesh
1620 real(real64), intent(in) :: time
1621 real(real64), intent(in) :: time_delay
1622 complex(real64), intent(inout) :: rs_state(:,:)
1623
1624 integer :: ip, ip_in, wn
1625 real(real64) :: x_prop(mesh%box%dim), rr, vv(mesh%box%dim), k_vector(mesh%box%dim)
1626 real(real64) :: k_vector_abs, nn
1627 complex(real64) :: e0(mesh%box%dim)
1628 real(real64) :: e_field(mesh%box%dim), b_field(mesh%box%dim)
1629 complex(real64) :: rs_state_add(mesh%box%dim)
1630 complex(real64) :: mx_func
1631
1634 call profiling_in('PLANE_WAVES_BOUNDARIES_C')
1635
1636 if (hm%plane_waves_apply) then
1637 do wn = 1, hm%bc%plane_wave%number
1638 k_vector(:) = hm%bc%plane_wave%k_vector(1:mesh%box%dim, wn)
1639 k_vector_abs = norm2(k_vector(1:mesh%box%dim))
1640 vv(:) = hm%bc%plane_wave%v_vector(1:mesh%box%dim, wn)
1641 e0(:) = hm%bc%plane_wave%e_field(1:mesh%box%dim, wn)
1642 do ip_in = 1, hm%bc%plane_wave%points_number
1643 ip = hm%bc%plane_wave%points_map(ip_in)
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(ip,1:mesh%box%dim) - 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)
1685
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, space, mesh, der, st, rs_state)
1711 type(bc_mxll_t), intent(inout) :: bc
1712 real(real64), intent(in) :: time
1713 class(space_t), intent(in) :: space
1714 class(mesh_t), intent(in) :: mesh
1715 type(derivatives_t), intent(in) :: der
1716 type(states_mxll_t), intent(in) :: st
1717 complex(real64), intent(inout) :: rs_state(:,:)
1718
1719 real(real64) :: e_field_total(mesh%np,st%dim), b_field_total(mesh%np,st%dim)
1720 complex(real64) :: rs_state_add(mesh%np,st%dim)
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 rs_state(1:mesh%np,:) = rs_state(1:mesh%np,:) + rs_state_add(1:mesh%np,:)
1732
1733 call profiling_out('PLANE_WAVES_IN_BOX_CALCULATION')
1734
1736 end subroutine plane_waves_in_box_calculation
1737
1738 ! ---------------------------------------------------------
1739 subroutine mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
1740 type(propagator_mxll_t), intent(inout) :: tr
1741 type(states_mxll_t), intent(inout) :: st
1742 type(hamiltonian_mxll_t),intent(inout) :: hm
1743 type(grid_t), intent(in) :: gr
1744 type(namespace_t), intent(in) :: namespace
1745 real(real64), intent(in) :: time
1746 real(real64), intent(in) :: dt
1747 type(batch_t), intent(inout) :: rs_stateb
1748
1749 complex(real64), allocatable :: rs_state(:, :)
1750
1751 push_sub(mxll_apply_boundaries)
1752
1753 safe_allocate(rs_state(gr%np, st%dim))
1754
1755 if (tr%bc_constant) then
1756 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1757 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
1758 if (st%rs_state_const_external) then
1759 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, time, dt, m_zero, rs_state)
1760 end if
1761 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1762 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1763 end if
1764
1765 ! PEC mirror boundaries
1766 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
1767 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1768 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
1769 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1770 end if
1771
1772 ! PMC mirror boundaries
1773 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
1774 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1775 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
1776 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1777 end if
1778
1779 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
1780 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1781 ! Apply mask absorbing boundaries
1782 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, m_zero, rs_state)
1783 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1784 end if
1785
1786 if (tr%bc_plane_waves) then
1787 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1788 ! calculate plane waves boundaries at t
1789 call plane_waves_boundaries_calculation(hm, st, gr, time, m_zero, rs_state)
1790 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1791 end if
1792
1793 safe_deallocate_a(rs_state)
1794
1795 pop_sub(mxll_apply_boundaries)
1796 end subroutine mxll_apply_boundaries
1797
1798end module propagator_mxll_oct_m
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:156
scale a batch by a constant or vector
Definition: batch_ops.F90:164
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:203
batchified version of
Definition: batch_ops.F90:172
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1375
subroutine, public accel_finish()
Definition: accel.F90:984
pure logical function, public accel_is_enabled()
Definition: accel.F90:418
integer pure function, public accel_max_workgroup_size()
Definition: accel.F90:1098
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:1915
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:1610
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:590
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
Definition: batch_ops.F90:244
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:192
real(real64), parameter, public m_zero
Definition: global.F90:190
real(real64), parameter, public m_four
Definition: global.F90:194
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:188
real(real64), parameter, public m_fourth
Definition: global.F90:199
real(real64), parameter, public p_mu
Definition: global.F90:233
real(real64), parameter, public p_ep
Definition: global.F90:232
complex(real64), parameter, public m_z0
Definition: global.F90:200
complex(real64), parameter, public m_zi
Definition: global.F90:204
real(real64), parameter, public m_epsilon
Definition: global.F90:206
real(real64), parameter, public m_half
Definition: global.F90:196
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:228
real(real64), parameter, public m_one
Definition: global.F90:191
real(real64), parameter, public m_three
Definition: global.F90:193
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:1942
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)
calculate the vector of dot-products of mesh functions between two batches
subroutine, public dmesh_batch_dotp_vector(mesh, aa, bb, dot, reduce, cproduct)
calculate the vector of dot-products of mesh functions between two batches
Definition: mesh_batch.F90:649
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:904
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:416
this module contains the output system
Definition: output.F90:117
Some general things and nomenclature:
Definition: par_vec.F90:173
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:621
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:871
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:625
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
subroutine, public mirror_pec_boundaries_calculation(bc, st, rs_state)
subroutine td_function_mxll_init(st, namespace, hm)
subroutine, public mxll_propagate_expgauss2(hm, namespace, gr, space, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=2.
subroutine, public energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
subroutine, public calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, st_elec, hm_elec, rs_state_matter)
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, space, st, tr, time, dt, counter)
subroutine, public mxll_propagate_expgauss1(hm, namespace, gr, space, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=1.
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 get_vector_pot_and_transverse_field(namespace, trans_calc_method, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, st, poisson_solver, helmholtz, time, field, transverse_field, vector_potential)
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 transform_rs_densities(hm, mesh, rs_charge_density, rs_current_density, ff_density, sign)
subroutine, public plane_waves_in_box_calculation(bc, time, space, mesh, der, st, rs_state)
subroutine, public energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
integer, parameter, public rs_trans_backward
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)
subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_charge_density, rs_current_density)
subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, rs_current_density, rs_density_6x6)
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:188
The states_elec_t class contains all electronic wave functions.
int true(void)