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, 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_axpby(gr%np, m_half, ff_rs_inhom_2b, m_half, ff_rs_inhom_meanb)
282
283 ! inhomogeneity propagation
284 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_1b)
285 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
286
287 call hamiltonian_mxll_update(hm, time=time)
288 hm%cpml_hamiltonian = .false.
289 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt)
290
291 ! add term U(time+dt,time)J(time)
292 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
293 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
294 call hamiltonian_mxll_update(hm, time=time)
295 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt*m_half)
296 ! add term U(time+dt/2,time)J(time)
297 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
298 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
299 call hamiltonian_mxll_update(hm, time=time)
300 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt*m_half)
301 ! add term U(time,time+dt/2)J(time)
302 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
303 call ff_rs_inhom_2b%end()
304 call ff_rs_inhom_meanb%end()
305 end if
306
307 do ii = 1, inter_steps
308
309 ! intermediate time
310 inter_time = time + inter_dt * (ii-1)
311
312 ! transformation of RS state into 3x3 or 4x4 representation
313 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_forward)
314
315 ! RS state propagation
316 call hamiltonian_mxll_update(hm, time=inter_time)
317 if (pml_check) then
318 call pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
319 end if
320
321 hm%cpml_hamiltonian = pml_check
322 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
323 hm%cpml_hamiltonian = .false.
324
325 if (pml_check) then
326 call pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, inter_time, inter_dt, m_zero, ff_rs_state_pmlb, ff_rs_stateb)
327 end if
328
329 !Below we add the contribution from the inhomogeneous terms
330 if ((hm%ma_mx_coupling_apply) .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) then
331 if (tr%tr_etrs_approx == mxwll_etrs_full) then
332 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
333 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
334 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
335
336 ! Interpolation of the external current
337 do istate = 1, hm%dim
338 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t2(:, istate))
339 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
340 end do
341 ! store t1 - t2 for the interpolation in mean
342 call batch_axpy(gr%np, -m_one, ff_rs_inhom_1b, ff_rs_inhom_meanb)
343 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
344 call batch_axpy(gr%np, ii / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_2b)
345 call batch_axpy(gr%np, (ii-1) / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_1b)
346
347 hm%cpml_hamiltonian = .false.
348 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt)
349 ! add terms U(time+dt,time)J(time) and J(time+dt)
350 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
351 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
352
353 do istate = 1, hm%dim
354 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
355 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
356 end do
357 call batch_axpby(gr%np, m_half, ff_rs_inhom_2b, m_half, ff_rs_inhom_1b)
358 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
359
360 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt/m_two)
361 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt/m_two)
362
363 ! add terms U(time+dt/2,time)J(time) and U(time,time+dt/2)J(time+dt)
364 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
365 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
366
367 call ff_rs_inhom_1b%end()
368 call ff_rs_inhom_2b%end()
369 call ff_rs_inhom_meanb%end()
370 else if (tr%tr_etrs_approx == mxwll_etrs_const) then
371 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
372 end if
373 end if
374
375 ! PML convolution function update
376 if (pml_check) then
377 call cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
378 end if
379
380 ! back transformation of RS state representation
381 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_backward)
382
383 if (tr%bc_constant) then
384 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
385 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
386 if (st%rs_state_const_external) then
387 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, inter_time, inter_dt, m_zero, rs_state)
388 end if
389 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
390 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
391 end if
392
393 ! Propagation dt with H(inter_time+inter_dt) for PEC mirror boundaries
394 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
395 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
396 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
397 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
398 end if
399
400 ! Propagation dt with H(inter_time+inter_dt) for PMC mirror boundaries
401 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
402 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
403 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
404 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
405 end if
406
407 ! Apply mask absorbing boundaries
408 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
409 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
410 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, inter_time, inter_dt, m_zero, rs_state)
411 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
412 end if
413
414 if (tr%bc_plane_waves) then
415 ! Propagation dt with H(inter_time+inter_dt) for plane waves boundaries
416 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
417 call plane_waves_boundaries_calculation(hm, st, gr, inter_time+inter_dt, m_zero, rs_state)
418 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
419 end if
420
421 end do
422
423 if (tr%tr_etrs_approx == option__maxwelltdetrsapprox__const_steps) then
424 call ff_rs_inhom_1b%end()
425 end if
426
427 call ff_rs_stateb%end()
428
429 if (pml_check) then
430 call ff_rs_state_pmlb%end()
431 end if
432
433 safe_deallocate_a(rs_state)
434
435 call profiling_out('MXLL_PROPAGATOR_STEP')
436
437 pop_sub(mxll_propagation_step)
438 end subroutine mxll_propagation_step
439
440 ! ---------------------------------------------------------
441 subroutine mxll_propagate_leapfrog(hm, namespace, gr, st, tr, time, dt, counter)
442 type(hamiltonian_mxll_t), intent(inout) :: hm
443 type(namespace_t), intent(in) :: namespace
444 type(grid_t), intent(inout) :: gr
445 type(states_mxll_t), intent(inout) :: st
446 type(propagator_mxll_t), intent(inout) :: tr
447 real(real64), intent(in) :: time
448 real(real64), intent(in) :: dt
449 integer, intent(in) :: counter
450
451 type(batch_t) :: rs_state_tmpb
452
453 push_sub_with_profile(mxll_propagate_leapfrog)
454
455 call st%rs_stateb%copy_to(rs_state_tmpb)
456
457 call hamiltonian_mxll_update(hm, time)
458
459 ! do boundaries at the beginning
460 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, st%rs_stateb)
461
462 ! update PML convolution values
463 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
464 call mxll_update_pml_simple(hm, st%rs_stateb)
465 end if
466
467 ! apply hamiltonian
468 call hamiltonian_mxll_apply_simple(hm, namespace, gr, st%rs_stateb, rs_state_tmpb)
469 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
470
471 ! add inhomogeneous terms
472 call batch_xpay(gr%np, st%inhomogeneousb, m_one, rs_state_tmpb)
473
474 if (counter == 0) then
475 ! for the first step, we do one forward Euler step
476 call batch_xpay(gr%np, st%rs_stateb, dt, rs_state_tmpb)
477 else
478 ! the leapfrog step depends on the previous state
479 call batch_xpay(gr%np, st%rs_state_prevb, m_two*dt, rs_state_tmpb)
480 end if
481
482 ! save the current rs state
483 call st%rs_stateb%copy_data_to(gr%np, st%rs_state_prevb)
484 ! update to new timestep
485 call rs_state_tmpb%copy_data_to(gr%np, st%rs_stateb)
486
487 ! update PML convolution values
488 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
489 call mxll_copy_pml_simple(hm, st%rs_stateb)
490 end if
491
492 call rs_state_tmpb%end()
493
494 pop_sub_with_profile(mxll_propagate_leapfrog)
495 end subroutine mxll_propagate_leapfrog
496
497 ! ---------------------------------------------------------
511 subroutine mxll_propagate_expgauss1(hm, namespace, gr, st, tr, time, dt)
512 type(hamiltonian_mxll_t), intent(inout) :: hm
513 type(namespace_t), intent(in) :: namespace
514 type(grid_t), intent(inout) :: gr
515 type(states_mxll_t), intent(inout) :: st
516 type(propagator_mxll_t), intent(inout) :: tr
517 real(real64), intent(in) :: time
518 real(real64), intent(in) :: dt
519
520 type(batch_t) :: rs_state_tmpb
521
522 push_sub_with_profile(mxll_propagate_expgauss1)
523
524 call st%rs_stateb%copy_to(rs_state_tmpb)
525
526 call hamiltonian_mxll_update(hm, time)
527
528 ! do boundaries at the beginning (should be included in Hamiltonian?)
529 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
530 dt, st%rs_stateb)
531
532 ! update PML convolution values
533 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
534 call mxll_update_pml_simple(hm, st%rs_stateb)
535 end if
537 ! accumulate -i H F_n - J_1 in rs_state_tmpb
538 ! compute H F_n
539 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
540 ! compute -i H F_n
541 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
542 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
543 ! set J_1
544 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
545 ! accumulate -J_1 to rs_state_tmpb
546 call batch_axpy(gr%np, -m_one, st%inhomogeneousb, rs_state_tmpb)
547 end if
548 ! compute phi_1
549 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
550 ! F_{n+1} = F_n + dt * phi_1 (...)
551 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
552
553 call rs_state_tmpb%end()
554
555 ! update PML convolution values
556 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
557 call mxll_copy_pml_simple(hm, st%rs_stateb)
558 end if
559
560 pop_sub_with_profile(mxll_propagate_expgauss1)
561 end subroutine mxll_propagate_expgauss1
562
563 ! ---------------------------------------------------------
583 subroutine mxll_propagate_expgauss2(hm, namespace, gr, st, tr, time, dt)
584 type(hamiltonian_mxll_t), intent(inout) :: hm
585 type(namespace_t), intent(in) :: namespace
586 type(grid_t), intent(inout) :: gr
587 type(states_mxll_t), intent(inout) :: st
588 type(propagator_mxll_t), intent(inout) :: tr
589 real(real64), intent(in) :: time
590 real(real64), intent(in) :: dt
591
592 type(batch_t) :: rs_state_tmpb
593
594 push_sub_with_profile(mxll_propagate_expgauss2)
595
596 call st%rs_stateb%copy_to(rs_state_tmpb)
597
598 call hamiltonian_mxll_update(hm, time)
599
600 ! do boundaries at the beginning (should be included in Hamiltonian?)
601 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
602 dt, st%rs_stateb)
603
604 ! update PML convolution values
605 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
606 call mxll_update_pml_simple(hm, st%rs_stateb)
607 end if
608
609 ! accumulate -i H F_n - a_1 J_1 - a_2 J_2 in rs_state_tmpb
610 ! compute H F_n
611 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
612 ! compute -i H F_n
613 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
614 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
615 ! set J_1
616 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
617 ! accumulate -a_1 J_1 to rs_state_tmpb
618 call batch_axpy(gr%np, -m_half*(m_one+sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
619 ! set J_2
620 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
621 ! accumulate -a_2 J_2 to rs_state_tmpb
622 call batch_axpy(gr%np, -m_half*(m_one-sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
623 end if
624 ! compute phi_1
625 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
626 ! accumulate phi_1 term: F_{n+1} = F_n + dt * phi_1 (...)
627 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
628 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
629 call batch_set_zero(rs_state_tmpb)
630 ! set J_1
631 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
632 ! accumulate -b_1 J_1 to rs_state_tmpb
633 call batch_axpy(gr%np, sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
634 ! set J_2
635 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
636 ! accumulate -b_2 J_2 to rs_state_tmpb
637 call batch_axpy(gr%np, -sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
638
639 ! compute phi_2
640 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 2)
641 ! accumulate phi_2 term: F_{n+1} = F_n + dt * phi_2 (...)
642 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
643 end if
644
645 ! update PML convolution values
646 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
647 call mxll_copy_pml_simple(hm, st%rs_stateb)
648 end if
649
650 call rs_state_tmpb%end()
651
652 pop_sub_with_profile(mxll_propagate_expgauss2)
653 end subroutine mxll_propagate_expgauss2
654
655 ! ---------------------------------------------------------
656 subroutine set_medium_rs_state(st, gr, hm)
657 type(states_mxll_t), intent(inout) :: st
658 type(grid_t), intent(in) :: gr
659 type(hamiltonian_mxll_t), intent(in) :: hm
660
661 integer :: ip, ip_in, il, idim
662
663 push_sub(set_medium_rs_state)
664
665 assert(allocated(st%ep) .and. allocated(st%mu))
666
667 call profiling_in('SET_MEDIUM_RS_STATE')
668
669 if (hm%calc_medium_box) then
670 do il = 1, size(hm%medium_boxes)
671 assert(.not. hm%medium_boxes(il)%has_mapping)
672 do ip = 1, hm%medium_boxes(il)%points_number
673 if (abs(hm%medium_boxes(il)%c(ip)) <= m_epsilon) cycle
674 st%ep(ip) = hm%medium_boxes(il)%ep(ip)
675 st%mu(ip) = hm%medium_boxes(il)%mu(ip)
676 end do
677 end do
678 end if
679
680 do idim = 1, st%dim
681 if (hm%bc%bc_type(idim) == mxll_bc_medium) then
682 do ip_in = 1, hm%bc%medium(idim)%points_number
683 ip = hm%bc%medium(idim)%points_map(ip_in)
684 st%ep(ip) = hm%bc%medium(idim)%ep(ip_in)
685 st%mu(ip) = hm%bc%medium(idim)%mu(ip_in)
686 end do
687 end if
688 end do
689
690 call profiling_out('SET_MEDIUM_RS_STATE')
691
692 pop_sub(set_medium_rs_state)
693 end subroutine set_medium_rs_state
694
695 ! ---------------------------------------------------------
696 subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
697 type(hamiltonian_mxll_t), intent(in) :: hm
698 type(grid_t), intent(in) :: gr
699 type(states_mxll_t), intent(in) :: st
700 type(batch_t), intent(inout) :: rs_stateb
701 type(batch_t), intent(inout) :: ff_rs_stateb
702 integer, intent(in) :: sign
703
704 complex(real64), allocatable :: rs_state(:,:)
705 complex(real64), allocatable :: rs_state_tmp(:,:)
706 integer :: ii, np
707
709
710 call profiling_in('TRANSFORM_RS_STATE')
711
712 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
713
714 np = gr%np
715 safe_allocate(rs_state(1:gr%np, 1:st%dim))
716
717 if (hm%operator == faraday_ampere_medium) then
718 if (sign == rs_trans_forward) then
719 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
720 ! 3 to 6
721 do ii = 1, 3
722 call batch_set_state(ff_rs_stateb, ii, np, rs_state(:, ii))
723 call batch_set_state(ff_rs_stateb, ii+3, np, conjg(rs_state(:, ii)))
724 end do
725 else
726 ! 6 to 3
727 safe_allocate(rs_state_tmp(1:gr%np, 1:st%dim))
728 do ii = 1, 3
729 call batch_get_state(ff_rs_stateb, ii, np, rs_state(:, ii))
730 call batch_get_state(ff_rs_stateb, ii+3, np, rs_state_tmp(:, ii))
731 rs_state(1:np, ii) = m_half * (rs_state(1:np, ii) + conjg(rs_state_tmp(1:np, ii)))
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
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 do ii = 1, 3
819 rs_current_density(1:mesh%np, ii) = m_half * &
820 real(rs_density_6x6(1:mesh%np, ii) + rs_density_6x6(1:mesh%np, ii+3), real64)
821 end do
822
824
825 !----------------------------------------------------------
826 subroutine calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, hm_elec, rs_state_matter)
827 type(grid_t), intent(in) :: gr_mxll
828 type(states_mxll_t), intent(in) :: st_mxll
829 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
830 type(grid_t), intent(in) :: gr_elec
831 type(hamiltonian_elec_t), intent(in) :: hm_elec
832 complex(real64), intent(inout) :: rs_state_matter(:,:)
833
834 complex(real64), allocatable :: tmp_pot_mx_gr(:,:), tmp_grad_mx_gr(:,:)
835
836 safe_allocate(tmp_pot_mx_gr(1:gr_mxll%np_part,1))
837 safe_allocate(tmp_grad_mx_gr(1:gr_mxll%np,1:gr_mxll%box%dim))
838 ! this subroutine needs the matter part
839
841
842 tmp_pot_mx_gr(:,:) = m_zero
843 tmp_grad_mx_gr(:,:) = m_zero
844 call zderivatives_grad(gr_mxll%der, tmp_pot_mx_gr(:,1), tmp_grad_mx_gr(:,:), set_bc = .false.)
845 tmp_grad_mx_gr = - tmp_grad_mx_gr
846
847 rs_state_matter = m_z0
848 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, &
849 rs_state_matter(1:gr_mxll%np,:), gr_mxll, st_mxll%ep(1:gr_mxll%np), st_mxll%mu(1:gr_mxll%np), &
850 gr_mxll%np)
851
852 safe_deallocate_a(tmp_pot_mx_gr)
853 safe_deallocate_a(tmp_grad_mx_gr)
854
857
858 !----------------------------------------------------------
859 subroutine get_vector_pot_and_transverse_field(namespace, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, &
860 poisson_solver, helmholtz, field, transverse_field, vector_potential)
861 type(namespace_t), intent(in) :: namespace
862 type(grid_t), intent(in) :: gr_mxll
863 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
864 type(states_mxll_t), intent(in) :: st_mxll
865 type(propagator_mxll_t), intent(in) :: tr_mxll
866 type(hamiltonian_elec_t), intent(in) :: hm
867 type(poisson_t), intent(in) :: poisson_solver
868 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
869 complex(real64), intent(inout) :: field(:,:)
870 complex(real64), intent(inout) :: transverse_field(:,:)
871 real(real64), intent(inout) :: vector_potential(:,:)
872
873 integer :: np
874 complex(real64), allocatable :: rs_state_plane_waves(:, :)
875
877
878 transverse_field = m_z0
879 vector_potential = m_zero
880
881 np = gr_mxll%np
882
883 if (hm_mxll%ma_mx_coupling) then
884
885 ! check what other transverse field methods are needed
886
887 ! trans_calc_method == OPTION__MAXWELLTRANSFIELDCALCULATIONMETHOD__TRANS_FIELD_POISSON
888 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
889 safe_allocate(rs_state_plane_waves(1:gr_mxll%np, 1:st_mxll%dim))
890 call mxll_get_batch(st_mxll%rs_state_plane_wavesb, rs_state_plane_waves, gr_mxll%np, st_mxll%dim)
891 end if
892
893 ! plane waves subtraction
894 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
895 transverse_field(1:np,:) = field(1:np,:) - rs_state_plane_waves(1:np,:)
896 else
897 transverse_field(1:np,:) = field(1:np,:)
898 end if
899 ! apply helmholtz decomposition for transverse field
900 call helmholtz%get_trans_field(namespace, transverse_field, total_field=field)
901 ! plane waves addition
902 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
903 transverse_field(1:np,:) = transverse_field(1:np,:) + rs_state_plane_waves(1:np,:)
904 safe_deallocate_a(rs_state_plane_waves)
905 end if
906
907 else
908
909 transverse_field(1:np,:) = field
910
911 end if
912
913
915
917
918 ! ---------------------------------------------------------
919 subroutine calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
920 type(namespace_t), intent(in) :: namespace
921 type(poisson_t), intent(in) :: poisson_solver
922 type(grid_t), intent(in) :: gr
923 type(states_mxll_t), intent(in) :: st
924 complex(real64), intent(in) :: field(:,:)
925 real(real64), contiguous, intent(inout) :: vector_potential(:,:)
926
927 integer :: idim
928 real(real64), allocatable :: dtmp(:,:)
929
930 safe_allocate(dtmp(1:gr%np_part,1:3))
931
932 dtmp = m_zero
933
934 call get_magnetic_field_state(field, gr, st%rs_sign, vector_potential, st%mu, gr%np_part)
935 dtmp = vector_potential
936 call dderivatives_curl(gr%der, dtmp, vector_potential, set_bc = .false.)
937 do idim=1, st%dim
938 call dpoisson_solve(poisson_solver, namespace, dtmp(:,idim), vector_potential(:,idim), .true.)
939 end do
940 vector_potential = m_one / (m_four * m_pi) * vector_potential
941
942 safe_deallocate_a(dtmp)
943
944 end subroutine calculate_vector_potential
945
946 !----------------------------------------------------------
947 subroutine energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
948 type(grid_t), intent(in) :: gr
949 type(states_mxll_t), intent(in) :: st
950 type(hamiltonian_mxll_t), intent(in) :: hm
951 type(energy_mxll_t), intent(inout) :: energy_mxll
952 complex(real64), intent(in) :: rs_field(:,:)
953 complex(real64), optional, intent(in) :: rs_field_plane_waves(:,:)
955 real(real64), allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:), energy_density_plane_waves(:)
956
957 push_sub(energy_mxll_calc)
958
959 call profiling_in('ENERGY_MXLL_CALC')
960
961 safe_allocate(energy_density(1:gr%np))
962 safe_allocate(e_energy_density(1:gr%np))
963 safe_allocate(b_energy_density(1:gr%np))
964 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
965 safe_allocate(energy_density_plane_waves(1:gr%np))
966 end if
967
968 call energy_density_calc(gr, st, rs_field, energy_density, e_energy_density, &
969 b_energy_density, hm%plane_waves, rs_field_plane_waves, energy_density_plane_waves)
970 energy_mxll%energy = dmf_integrate(gr, energy_density, mask=st%inner_points_mask)
971 energy_mxll%e_energy = dmf_integrate(gr, e_energy_density, mask=st%inner_points_mask)
972 energy_mxll%b_energy = dmf_integrate(gr, b_energy_density, mask=st%inner_points_mask)
973 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
974 energy_mxll%energy_plane_waves = dmf_integrate(gr, energy_density_plane_waves, mask=st%inner_points_mask)
975 else
976 energy_mxll%energy_plane_waves = m_zero
977 end if
978
979 energy_mxll%boundaries = dmf_integrate(gr, energy_density, mask=st%boundary_points_mask)
980
981 safe_deallocate_a(energy_density)
982 safe_deallocate_a(e_energy_density)
983 safe_deallocate_a(b_energy_density)
984 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
985 safe_deallocate_a(energy_density_plane_waves)
986 end if
987
988 call profiling_out('ENERGY_MXLL_CALC')
989
990 pop_sub(energy_mxll_calc)
991 end subroutine energy_mxll_calc
992
993 !----------------------------------------------------------
994 subroutine energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
995 type(grid_t), intent(in) :: gr
996 type(states_mxll_t), intent(in) :: st
997 type(hamiltonian_mxll_t), intent(in) :: hm
998 type(energy_mxll_t), intent(inout) :: energy_mxll
999 type(batch_t), intent(in) :: rs_fieldb
1000 type(batch_t), intent(in) :: rs_field_plane_wavesb
1001
1002 type(batch_t) :: e_fieldb, b_fieldb, e_field_innerb, b_field_innerb, rs_field_plane_waves_innerb
1003 real(real64) :: tmp(1:st%dim)
1004 complex(real64) :: ztmp(1:st%dim)
1005
1006 push_sub(energy_mxll_calc_batch)
1007
1008 call profiling_in('ENERGY_MXLL_CALC_BATCH')
1009
1010 call dbatch_init(e_fieldb, 1, 1, st%dim, gr%np)
1011 if (st%pack_states) then
1012 call e_fieldb%do_pack(copy=.false.)
1013 end if
1014 call e_fieldb%copy_to(b_fieldb)
1015 call e_fieldb%copy_to(e_field_innerb)
1016 call e_fieldb%copy_to(b_field_innerb)
1017
1018 call batch_split_complex(gr%np, rs_fieldb, e_fieldb, b_fieldb)
1019
1020 ! subtract energy of inner points
1021 call batch_set_zero(e_field_innerb)
1022 call batch_set_zero(b_field_innerb)
1023 if (accel_is_enabled()) then
1024 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, e_fieldb, e_field_innerb)
1025 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, b_fieldb, b_field_innerb)
1026 else
1027 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, e_fieldb, e_field_innerb)
1028 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, b_fieldb, b_field_innerb)
1029 end if
1030 call dmesh_batch_dotp_vector(gr, e_field_innerb, e_field_innerb, tmp)
1031 energy_mxll%e_energy = sum(tmp)
1032 call dmesh_batch_dotp_vector(gr, b_field_innerb, b_field_innerb, tmp)
1033 energy_mxll%b_energy = sum(tmp)
1034 energy_mxll%energy = energy_mxll%e_energy + energy_mxll%b_energy
1035
1036 call dmesh_batch_dotp_vector(gr, e_fieldb, e_fieldb, tmp)
1037 energy_mxll%boundaries = sum(tmp)
1038 call dmesh_batch_dotp_vector(gr, b_fieldb, b_fieldb, tmp)
1039 energy_mxll%boundaries = energy_mxll%boundaries + sum(tmp)
1040 energy_mxll%boundaries = energy_mxll%boundaries - energy_mxll%energy
1041
1042 if (hm%plane_waves) then
1043 call rs_field_plane_wavesb%copy_to(rs_field_plane_waves_innerb)
1044 call batch_set_zero(rs_field_plane_waves_innerb)
1045 if (accel_is_enabled()) then
1046 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, &
1047 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1048 else
1049 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, &
1050 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1051 end if
1052 call zmesh_batch_dotp_vector(gr, rs_field_plane_waves_innerb, rs_field_plane_waves_innerb, ztmp)
1053 energy_mxll%energy_plane_waves = sum(real(tmp, real64) )
1054 call rs_field_plane_waves_innerb%end()
1055 else
1056 energy_mxll%energy_plane_waves = m_zero
1057 end if
1058
1059 call e_fieldb%end()
1060 call b_fieldb%end()
1061 call e_field_innerb%end()
1062 call b_field_innerb%end()
1063
1064 call profiling_out('ENERGY_MXLL_CALC_BATCH')
1065
1066 pop_sub(energy_mxll_calc_batch)
1067 end subroutine energy_mxll_calc_batch
1068
1069 ! ---------------------------------------------------------
1070 subroutine mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
1071 type(namespace_t), intent(in) :: namespace
1072 type(grid_t), intent(in) :: gr
1073 type(hamiltonian_mxll_t), intent(inout) :: hm
1074 type(states_mxll_t), intent(inout) :: st
1075 type(propagator_mxll_t), intent(inout) :: tr
1076 real(real64), intent(in) :: time
1077 real(real64), intent(in) :: dt
1078 real(real64), intent(in) :: time_delay
1079 complex(real64), intent(inout) :: rs_state(:,:)
1080
1081 integer :: ip, ip_in, idim
1082 logical :: mask_check
1083
1085
1086 call profiling_in('MASK_ABSORBING_BOUNDARIES')
1087 mask_check = .false.
1088
1089 do idim = 1, 3
1090 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1091 mask_check = .true.
1092 end if
1093 end do
1094
1095 if (mask_check) then
1096 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1097 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1098 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1099 rs_state = rs_state - st%rs_state_plane_waves
1100 call maxwell_mask(hm, rs_state)
1101 rs_state = rs_state + st%rs_state_plane_waves
1102 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1103 !call constant_at_absorbing_boundaries_calculation(st, hm%bc)
1104 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1105 do ip_in=1, hm%bc%constant_points_number
1106 ip = hm%bc%constant_points_map(ip_in)
1107 rs_state(ip,:) = rs_state(ip,:) - st%rs_state_const(:)
1108 end do
1109 call maxwell_mask(hm, rs_state)
1110 do ip_in=1, hm%bc%constant_points_number
1111 ip = hm%bc%constant_points_map(ip_in)
1112 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const(:)
1113 end do
1114 else
1115 call maxwell_mask(hm, rs_state)
1116 end if
1117 end if
1118
1119 call profiling_out('MASK_ABSORBING_BOUNDARIES')
1120
1122 end subroutine mask_absorbing_boundaries
1123
1124 ! ---------------------------------------------------------
1125 subroutine maxwell_mask(hm, rs_state)
1126 type(hamiltonian_mxll_t), intent(in) :: hm
1127 complex(real64), intent(inout) :: rs_state(:,:)
1128
1129 integer :: ip, ip_in, idim
1130
1131 push_sub(maxwell_mask)
1132
1133 call profiling_in('MAXWELL_MASK')
1134
1135 do idim = 1, 3
1136 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1137 do ip_in = 1, hm%bc%mask_points_number(idim)
1138 ip = hm%bc%mask_points_map(ip_in,idim)
1139 rs_state(ip,:) = rs_state(ip,:) * hm%bc%mask(ip_in,idim)
1140 end do
1141 end if
1142 end do
1143
1144 call profiling_out('MAXWELL_MASK')
1145
1146 pop_sub(maxwell_mask)
1147 end subroutine maxwell_mask
1148
1149 ! ---------------------------------------------------------
1150 subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
1151 type(hamiltonian_mxll_t), intent(inout) :: hm
1152 type(grid_t), intent(in) :: gr
1153 type(states_mxll_t), intent(inout) :: st
1154 type(propagator_mxll_t), intent(inout) :: tr
1155 type(batch_t), intent(in) :: ff_rs_stateb
1156 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1157
1158 integer :: ii
1159 complex(real64), allocatable :: rs_state_constant(:,:)
1160 type(batch_t) :: rs_state_constantb
1161
1163
1164 call profiling_in('PML_PROP_STAGE_1_BATCH')
1166 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1167 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, &
1168 ff_rs_state_pmlb, rs_trans_forward)
1169 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1170 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1171 ! this could be optimized: right now we broadcast the constant value
1172 ! to the full mesh to be able to use the batch functions easily.
1173 ! in principle, we would need to do the transform only for one point
1174 ! and then subtract that value from all points of the state
1175 safe_allocate(rs_state_constant(1:gr%np,1:3))
1176 do ii = 1, 3
1177 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1178 end do
1179 call ff_rs_stateb%copy_to(rs_state_constantb)
1180 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, 3)
1181
1182 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, &
1183 ff_rs_state_pmlb, rs_trans_forward)
1184 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1185
1186 call rs_state_constantb%end()
1187
1188 safe_deallocate_a(rs_state_constant)
1189 else
1190 ! this copy should not be needed
1191 call ff_rs_stateb%copy_data_to(gr%np, ff_rs_state_pmlb)
1192 end if
1193
1194 call profiling_out('PML_PROP_STAGE_1_BATCH')
1195
1197 end subroutine pml_propagation_stage_1_batch
1198
1199 ! ---------------------------------------------------------
1200 subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
1201 type(hamiltonian_mxll_t), intent(inout) :: hm
1202 type(namespace_t), intent(in) :: namespace
1203 type(grid_t), intent(in) :: gr
1204 type(states_mxll_t), intent(inout) :: st
1205 type(propagator_mxll_t), intent(inout) :: tr
1206 real(real64), intent(in) :: time
1207 real(real64), intent(in) :: dt
1208 real(real64), intent(in) :: time_delay
1209 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1210 type(batch_t), intent(inout) :: ff_rs_stateb
1211
1212 integer :: ii, ff_dim
1213 complex(real64), allocatable :: rs_state_constant(:,:), ff_rs_state_constant(:,:)
1214 type(batch_t) :: ff_rs_state_plane_wavesb, ff_rs_constantb, rs_state_constantb
1215
1217
1218 call profiling_in('PML_PROP_STAGE_2_BATCH')
1219
1220 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1221 hm%cpml_hamiltonian = .true.
1222 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1223 hm%cpml_hamiltonian = .false.
1224 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1225
1226 call ff_rs_stateb%copy_to(ff_rs_state_plane_wavesb)
1227 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_state_plane_wavesb, rs_trans_forward)
1228
1229 if (ff_rs_stateb%status() == batch_device_packed) then
1230 ! use the map of points stored on the GPU in this case
1231 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%buff_map, &
1232 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1233 else
1234 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%points_map, &
1235 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1236 end if
1237
1238 call ff_rs_state_plane_wavesb%end()
1239
1240 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1241 hm%cpml_hamiltonian = .true.
1242 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1243 hm%cpml_hamiltonian = .false.
1244
1245 call ff_rs_stateb%copy_to(ff_rs_constantb)
1246 ff_dim = ff_rs_stateb%nst_linear
1247 safe_allocate(rs_state_constant(1:gr%np, 1:st%dim))
1248 ! copy the value to the full mesh to be able to use batches
1249 ! this is in principle unneeded, but otherwise we could not use batches...
1250 do ii = 1, st%dim
1251 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1252 end do
1253 call ff_rs_stateb%copy_to(rs_state_constantb)
1254 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, st%dim)
1255
1256 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, ff_rs_constantb, rs_trans_forward)
1257 if (ff_rs_stateb%status() == batch_device_packed) then
1258 ! use the map of points stored on the GPU in this case
1259 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%buff_constant_points_map, &
1260 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1261 else
1262 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%constant_points_map, &
1263 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1264 end if
1265
1266 call ff_rs_constantb%end()
1267 call rs_state_constantb%end()
1268
1269 safe_deallocate_a(rs_state_constant)
1270 safe_deallocate_a(ff_rs_state_constant)
1271 end if
1272
1273 call profiling_out('PML_PROP_STAGE_2_BATCH')
1274
1276 end subroutine pml_propagation_stage_2_batch
1277
1278 ! ---------------------------------------------------------
1279 subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
1280 type(hamiltonian_mxll_t), intent(inout) :: hm
1281 type(grid_t), intent(in) :: gr
1282 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1283
1284
1286
1287 call profiling_in('CPML_CONV_FUNCTION_UPDATE')
1288
1289 call cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1290
1291 call profiling_out('CPML_CONV_FUNCTION_UPDATE')
1292
1294 end subroutine cpml_conv_function_update
1296 ! ---------------------------------------------------------
1297 subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1298 type(hamiltonian_mxll_t), intent(inout) :: hm
1299 type(grid_t), intent(in) :: gr
1300 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1301
1302 integer :: ip, ip_in, np_part, rs_sign
1303 complex(real64) :: pml_a, pml_b, pml_g, grad
1304 integer :: pml_dir, field_dir, ifield, idir
1305 integer, parameter :: field_dirs(3, 2) = reshape([2, 3, 1, 3, 1, 2], [3, 2])
1306 logical :: with_medium
1307 type(batch_t) :: gradb(gr%der%dim)
1308 type(accel_kernel_t), save :: ker_pml
1309 integer :: bsize, gsize
1310
1312
1313 call profiling_in('CPML_CONV_UPDATE_VIA_RS')
1314
1315 assert(hm%dim == 3 .or. hm%dim == 6)
1316
1317 np_part = gr%np_part
1318 rs_sign = hm%rs_sign
1319
1320 call zderivatives_batch_grad(gr%der, ff_rs_state_pmlb, gradb)
1321
1322 with_medium = hm%dim == 6
1323
1324 do pml_dir = 1, hm%st%dim
1325 select case (gradb(pml_dir)%status())
1326 case (batch_not_packed)
1327 do ip_in=1, hm%bc%pml%points_number
1328 ip = hm%bc%pml%points_map(ip_in)
1329 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1330 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1331 do ifield = 1, 2
1332 field_dir = field_dirs(pml_dir, ifield)
1333 grad = gradb(pml_dir)%zff_linear(ip, field_dir)
1334 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1335 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1336 if (with_medium) then
1337 grad = gradb(pml_dir)%zff_linear(ip, field_dir+3)
1338 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1339 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1340 end if
1341 end do
1342 end do
1343 case (batch_packed)
1344 do ip_in=1, hm%bc%pml%points_number
1345 ip = hm%bc%pml%points_map(ip_in)
1346 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1347 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1348 do ifield = 1, 2
1349 field_dir = field_dirs(pml_dir, ifield)
1350 grad = gradb(pml_dir)%zff_pack(field_dir, ip)
1351 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1352 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1353 if (with_medium) then
1354 grad = gradb(pml_dir)%zff_pack(field_dir+3, ip)
1355 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1356 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1357 end if
1358 end do
1359 end do
1360 case (batch_device_packed)
1361 call accel_kernel_start_call(ker_pml, 'pml.cu', 'pml_update_conv')
1362
1363 if (with_medium) then
1364 call accel_set_kernel_arg(ker_pml, 0, 1_int32)
1365 else
1366 call accel_set_kernel_arg(ker_pml, 0, 0_int32)
1367 end if
1368 call accel_set_kernel_arg(ker_pml, 1, hm%bc%pml%points_number)
1369 call accel_set_kernel_arg(ker_pml, 2, pml_dir-1)
1370 call accel_set_kernel_arg(ker_pml, 3, hm%bc%pml%buff_map)
1371 call accel_set_kernel_arg(ker_pml, 4, gradb(pml_dir)%ff_device)
1372 call accel_set_kernel_arg(ker_pml, 5, log2(int(gradb(pml_dir)%pack_size(1), int32)))
1373 call accel_set_kernel_arg(ker_pml, 6, hm%bc%pml%buff_a)
1374 call accel_set_kernel_arg(ker_pml, 7, hm%bc%pml%buff_b)
1375 call accel_set_kernel_arg(ker_pml, 8, hm%bc%pml%buff_conv_plus)
1376 call accel_set_kernel_arg(ker_pml, 9, hm%bc%pml%buff_conv_minus)
1377
1378 ! Compute the grid size
1379 bsize = accel_max_block_size()
1380 call accel_grid_size(hm%bc%pml%points_number, bsize, gsize)
1381
1382 call accel_kernel_run(ker_pml, (/ gsize /), (/ bsize /))
1383 end select
1384 end do
1385
1386 do idir = 1, gr%der%dim
1387 call gradb(idir)%end()
1388 end do
1389
1390 if (accel_is_enabled()) then
1391 call accel_finish()
1392 end if
1393
1394 call profiling_out('CPML_CONV_UPDATE_VIA_RS')
1395
1398
1399 ! ---------------------------------------------------------
1400 subroutine td_function_mxll_init(st, namespace, hm)
1401 type(states_mxll_t), intent(inout) :: st
1402 type(namespace_t), intent(in) :: namespace
1403 type(hamiltonian_mxll_t), intent(inout) :: hm
1404
1405 type(block_t) :: blk
1406 integer :: il, nlines, idim, ncols, ierr
1407 real(real64) :: e_field(st%dim), b_field(st%dim)
1408 character(len=1024) :: mxf_expression
1409
1410 push_sub(td_function_mxll_init)
1411
1412 call profiling_in('TD_FUNCTION_MXLL_INIT')
1413
1414 !%Variable UserDefinedConstantSpatialMaxwellField
1415 !%Type block
1416 !%Section Maxwell
1417 !%Description
1418 !% Define parameters of spatially constant field.
1419 !%
1420 !% Example:
1421 !%
1422 !% <tt>%UserDefinedConstantSpatialMaxwellFields
1423 !% <br>&nbsp;&nbsp; plane_wave_parser | E_x | E_y | E_z | B_x | B_y | B_z | "tdf_function"
1424 !% <br>%</tt>
1425 !%
1426 !% This block defines three components of E field, three components of B field, and reference to
1427 !% the TD function.
1428 !%
1429 !%End
1430
1431 if (parse_block(namespace, 'UserDefinedConstantSpatialMaxwellField', blk) == 0) then
1432 st%rs_state_const_external = .true.
1433 nlines = parse_block_n(blk)
1434 safe_allocate(st%rs_state_const_td_function(1:nlines))
1435 safe_allocate(st%rs_state_const_amp(1:st%dim, 1:nlines))
1436 ! read all lines
1437 do il = 1, nlines
1438 e_field = m_zero
1439 b_field = m_zero
1440 ! Check that number of columns is five or six.
1441 ncols = parse_block_cols(blk, il - 1)
1442 if (ncols /= 7) then
1443 message(1) = 'Each line in the UserDefinedConstantSpatialMaxwellField block must have'
1444 message(2) = 'seven columns.'
1445 call messages_fatal(2, namespace=namespace)
1446 end if
1447 do idim = 1, st%dim
1448 call parse_block_float( blk, il - 1, idim-1, e_field(idim))
1449 end do
1450 do idim = 1, st%dim
1451 call parse_block_float( blk, il - 1, idim+2, b_field(idim))
1452 end do
1453 call parse_block_string( blk, il - 1, 6, mxf_expression)
1454 call build_rs_vector(e_field, b_field, st%rs_sign, st%rs_state_const_amp(:,il))
1455 call tdf_read(st%rs_state_const_td_function(il), namespace, trim(mxf_expression), ierr)
1456 end do
1457 end if
1458 call parse_block_end(blk)
1459
1460 !%Variable PropagateSpatialMaxwellField
1461 !%Type logical
1462 !%Default yes
1463 !%Section Maxwell::TD Propagation
1464 !%Description
1465 !% Allow for numerical propagation of Maxwells equations of spatially constant field.
1466 !% If set to no, do only analytic evaluation of the field inside the box.
1467 !%End
1468
1469 call parse_variable(namespace, 'PropagateSpatialMaxwellField', .true., hm%spatial_constant_propagate)
1470
1471 call profiling_out('TD_FUNCTION_MXLL_INIT')
1472
1473 pop_sub(td_function_mxll_init)
1474 end subroutine td_function_mxll_init
1475
1476 ! ---------------------------------------------------------
1477 subroutine spatial_constant_calculation(constant_calc, st, gr, hm, time, dt, delay, rs_state, set_initial_state)
1478 logical, intent(in) :: constant_calc
1479 type(states_mxll_t), intent(inout) :: st
1480 type(grid_t), intent(in) :: gr
1481 type(hamiltonian_mxll_t), intent(in) :: hm
1482 real(real64), intent(in) :: time
1483 real(real64), intent(in) :: dt
1484 real(real64), intent(in) :: delay
1485 complex(real64), intent(inout) :: rs_state(:,:)
1486 logical, optional, intent(in) :: set_initial_state
1487
1488 integer :: ip, ic, icn
1489 real(real64) :: tf_old, tf_new
1490 logical :: set_initial_state_
1491
1493
1494 call profiling_in('SPATIAL_CONSTANT_CALCULATION')
1496 set_initial_state_ = .false.
1497 if (present(set_initial_state)) set_initial_state_ = set_initial_state
1498
1499 if (hm%spatial_constant_apply) then
1500 if (constant_calc) then
1501 icn = size(st%rs_state_const_td_function(:))
1502 st%rs_state_const(:) = m_z0
1503 do ic = 1, icn
1504 tf_old = tdf(st%rs_state_const_td_function(ic), time-delay-dt)
1505 tf_new = tdf(st%rs_state_const_td_function(ic), time-delay)
1506 do ip = 1, gr%np
1507 if (set_initial_state_ .or. (.not. hm%spatial_constant_propagate)) then
1508 rs_state(ip,:) = st%rs_state_const_amp(:,ic) * tf_new
1509 else
1510 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const_amp(:,ic) * (tf_new - tf_old)
1511 end if
1512 end do
1513 st%rs_state_const(:) = st%rs_state_const(:) + st%rs_state_const_amp(:, ic)
1514 end do
1515 st%rs_state_const(:) = st%rs_state_const(:) * tf_new
1516 end if
1517 end if
1518
1519 call profiling_out('SPATIAL_CONSTANT_CALCULATION')
1520
1522 end subroutine spatial_constant_calculation
1523
1524 ! ---------------------------------------------------------
1525 subroutine constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
1526 logical, intent(in) :: constant_calc
1527 type(bc_mxll_t), intent(inout) :: bc
1528 type(states_mxll_t), intent(in) :: st
1529 type(hamiltonian_mxll_t), intent(in) :: hm
1530 complex(real64), intent(inout) :: rs_state(:,:)
1531
1532 integer :: ip_in, ip
1533
1535 call profiling_in('CONSTANT_BOUNDARIES_CALC')
1536
1537 if (hm%spatial_constant_apply) then
1538 if (constant_calc) then
1539 do ip_in = 1, bc%constant_points_number
1540 ip = bc%constant_points_map(ip_in)
1541 rs_state(ip,:) = st%rs_state_const(:)
1542 bc%constant_rs_state(ip_in,:) = st%rs_state_const(:)
1543 end do
1544 end if
1545 end if
1546
1547 call profiling_out('CONSTANT_BOUNDARIES_CALC')
1548
1550 end subroutine constant_boundaries_calculation
1551
1552 ! ---------------------------------------------------------
1553 subroutine mirror_pec_boundaries_calculation(bc, st, rs_state)
1554 type(bc_mxll_t), intent(in) :: bc
1555 type(states_mxll_t), intent(in) :: st
1556 complex(real64), intent(inout) :: rs_state(:,:)
1557
1558 integer :: ip, ip_in, idim
1559 real(real64) :: e_field(st%dim), b_field(st%dim)
1560
1562
1563 do idim = 1, 3
1564 if (bc%bc_type(idim) == mxll_bc_mirror_pec) then
1565 do ip_in = 1, bc%mirror_points_number(idim)
1566 ip = bc%mirror_points_map(ip_in, idim)
1567 e_field(:) = m_zero
1568 call get_magnetic_field_vector(rs_state(ip,:), st%rs_sign, b_field(:), st%mu(ip))
1569 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1570 end do
1571 end if
1572 end do
1573
1576
1577 ! ---------------------------------------------------------
1578 subroutine mirror_pmc_boundaries_calculation(bc, st, rs_state)
1579 type(bc_mxll_t), intent(in) :: bc
1580 type(states_mxll_t), intent(in) :: st
1581 complex(real64), intent(inout) :: rs_state(:,:)
1582
1583 integer :: ip, ip_in, idim
1584 real(real64) :: e_field(st%dim), b_field(st%dim)
1585
1587
1588 do idim = 1, 3
1589 if (bc%bc_type(idim) == mxll_bc_mirror_pmc) then
1590 do ip_in = 1, bc%mirror_points_number(idim)
1591 ip = bc%mirror_points_map(ip_in,idim)
1592 b_field(:) = m_zero
1593 call get_electric_field_vector(rs_state(ip,:), e_field(:), st%ep(ip))
1594 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1595 end do
1596 end if
1597 end do
1598
1601
1602 ! ---------------------------------------------------------
1603 subroutine plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
1604 type(hamiltonian_mxll_t), intent(in) :: hm
1605 type(states_mxll_t), intent(in) :: st
1606 class(mesh_t), intent(in) :: mesh
1607 real(real64), intent(in) :: time
1608 real(real64), intent(in) :: time_delay
1609 complex(real64), intent(inout) :: rs_state(:,:)
1610
1611 integer :: ip, ip_in, wn
1612 real(real64) :: x_prop(mesh%box%dim), rr, vv(mesh%box%dim), k_vector(mesh%box%dim)
1613 real(real64) :: k_vector_abs, nn
1614 complex(real64) :: e0(mesh%box%dim)
1615 real(real64) :: e_field(mesh%box%dim), b_field(mesh%box%dim)
1616 complex(real64) :: rs_state_add(mesh%box%dim)
1617 complex(real64) :: mx_func
1618
1621 call profiling_in('PLANE_WAVES_BOUNDARIES_C')
1622
1623 if (hm%plane_waves_apply) then
1624 do wn = 1, hm%bc%plane_wave%number
1625 k_vector(:) = hm%bc%plane_wave%k_vector(1:mesh%box%dim, wn)
1626 k_vector_abs = norm2(k_vector(1:mesh%box%dim))
1627 vv(:) = hm%bc%plane_wave%v_vector(1:mesh%box%dim, wn)
1628 e0(:) = hm%bc%plane_wave%e_field(1:mesh%box%dim, wn)
1629 do ip_in = 1, hm%bc%plane_wave%points_number
1630 ip = hm%bc%plane_wave%points_map(ip_in)
1631 if (wn == 1) rs_state(ip,:) = m_z0
1632 nn = sqrt(st%ep(ip)/p_ep*st%mu(ip)/p_mu)
1633 x_prop(1:mesh%box%dim) = mesh%x(1:mesh%box%dim, ip) - vv(1:mesh%box%dim) * (time - time_delay)
1634 rr = norm2(x_prop(1:mesh%box%dim))
1635 if (hm%bc%plane_wave%modus(wn) == option__maxwellincidentwaves__plane_wave_mx_function) then
1636 ! Temporary variable assigned due to macro line length
1637 mx_func = mxf(hm%bc%plane_wave%mx_function(wn), x_prop(1:mesh%box%dim))
1638 e_field(1:mesh%box%dim) = real(e0(1:mesh%box%dim) * mx_func, real64)
1639 end if
1640 b_field(1:3) = dcross_product(k_vector, e_field) / p_c / k_vector_abs
1641 call build_rs_vector(e_field, b_field, st%rs_sign, rs_state_add, st%ep(ip), st%mu(ip))
1642 rs_state(ip, :) = rs_state(ip, :) + rs_state_add(:)
1643 end do
1644 end do
1645 else
1646 do ip_in = 1, hm%bc%plane_wave%points_number
1647 ip = hm%bc%plane_wave%points_map(ip_in)
1648 rs_state(ip,:) = m_z0
1649 end do
1650 end if
1651
1652 call profiling_out('PLANE_WAVES_BOUNDARIES_C')
1653
1656
1657 ! ---------------------------------------------------------
1658 subroutine plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1659 type(hamiltonian_mxll_t), intent(inout) :: hm
1660 type(propagator_mxll_t), intent(inout) :: tr
1661 type(namespace_t), intent(in) :: namespace
1662 type(states_mxll_t), intent(inout) :: st
1663 type(grid_t), intent(in) :: gr
1664 real(real64), intent(in) :: time
1665 real(real64), intent(in) :: dt
1666 real(real64), intent(in) :: time_delay
1667
1668 type(batch_t) :: ff_rs_stateb
1669 integer :: ff_dim
1670
1671 push_sub(plane_waves_propagation)
1672
1673 call profiling_in('PLANE_WAVES_PROPAGATION')
1674
1675 ff_dim = hm%dim
1676 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
1677 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
1678
1679 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_forward)
1680
1681 ! Time evolution of RS plane waves state without any coupling with H(inter_time)
1682 call hamiltonian_mxll_update(hm, time=time)
1683 hm%cpml_hamiltonian = .false.
1684 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
1685
1686 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_backward)
1687 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1688 call plane_waves_boundaries_calculation(hm, st, gr, time+dt, time_delay, st%rs_state_plane_waves)
1689 call mxll_set_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1690 call ff_rs_stateb%end()
1691
1692 call profiling_out('PLANE_WAVES_PROPAGATION')
1694 end subroutine plane_waves_propagation
1695
1696 ! ---------------------------------------------------------
1697 subroutine plane_waves_in_box_calculation(bc, time, mesh, der, st, rs_state)
1698 type(bc_mxll_t), intent(inout) :: bc
1699 real(real64), intent(in) :: time
1700 class(mesh_t), intent(in) :: mesh
1701 type(derivatives_t), intent(in) :: der
1702 type(states_mxll_t), intent(in) :: st
1703 complex(real64), intent(inout) :: rs_state(:,:)
1704
1705 real(real64) :: e_field_total(mesh%np,st%dim), b_field_total(mesh%np,st%dim)
1706 complex(real64) :: rs_state_add(mesh%np,st%dim)
1707
1709
1710 call profiling_in('PLANE_WAVES_IN_BOX_CALCULATION')
1711
1712 call external_waves_eval(bc%plane_wave, time, mesh, "E field", e_field_total)
1713 call external_waves_eval(bc%plane_wave, time, mesh, "B field", b_field_total, der=der)
1714
1715 call build_rs_state(e_field_total, b_field_total, st%rs_sign, &
1716 rs_state_add(1:mesh%np,:), mesh, st%ep, st%mu)
1717 rs_state(1:mesh%np,:) = rs_state(1:mesh%np,:) + rs_state_add(1:mesh%np,:)
1718
1719 call profiling_out('PLANE_WAVES_IN_BOX_CALCULATION')
1720
1722 end subroutine plane_waves_in_box_calculation
1723
1724 ! ---------------------------------------------------------
1725 subroutine mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
1726 type(propagator_mxll_t), intent(inout) :: tr
1727 type(states_mxll_t), intent(inout) :: st
1728 type(hamiltonian_mxll_t),intent(inout) :: hm
1729 type(grid_t), intent(in) :: gr
1730 type(namespace_t), intent(in) :: namespace
1731 real(real64), intent(in) :: time
1732 real(real64), intent(in) :: dt
1733 type(batch_t), intent(inout) :: rs_stateb
1734
1735 complex(real64), allocatable :: rs_state(:, :)
1736
1737 push_sub(mxll_apply_boundaries)
1738
1739 safe_allocate(rs_state(gr%np, st%dim))
1740
1741 if (tr%bc_constant) then
1742 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1743 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
1744 if (st%rs_state_const_external) then
1745 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, time, dt, m_zero, rs_state)
1746 end if
1747 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1748 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1749 end if
1750
1751 ! PEC mirror boundaries
1752 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
1753 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1754 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
1755 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1756 end if
1757
1758 ! PMC mirror boundaries
1759 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
1760 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1761 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
1762 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1763 end if
1764
1765 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
1766 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1767 ! Apply mask absorbing boundaries
1768 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, m_zero, rs_state)
1769 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1770 end if
1771
1772 if (tr%bc_plane_waves) then
1773 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1774 ! calculate plane waves boundaries at t
1775 call plane_waves_boundaries_calculation(hm, st, gr, time, m_zero, rs_state)
1776 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1777 end if
1778
1779 safe_deallocate_a(rs_state)
1780
1781 pop_sub(mxll_apply_boundaries)
1782 end subroutine mxll_apply_boundaries
1783
1784end 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
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1413
subroutine, public accel_finish()
Definition: accel.F90:1098
pure logical function, public accel_is_enabled()
Definition: accel.F90:402
integer pure function, public accel_max_block_size()
Definition: accel.F90:1182
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:1923
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:1613
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:731
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:1895
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:650
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:810
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:615
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:863
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)