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