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_periodic = .false.
107 logical :: bc_plane_waves = .false.
108 logical :: bc_medium = .false.
109 type(exponential_t) :: te
110 logical :: plane_waves_in_box
111 integer :: tr_etrs_approx
112 end type propagator_mxll_t
114 integer, public, parameter :: &
115 RS_TRANS_FORWARD = 1, &
117
118 integer, parameter :: &
119 MXWLL_ETRS_FULL = 0, &
121
122contains
123
124 ! ---------------------------------------------------------
125 subroutine propagator_mxll_init(gr, namespace, st, hm, tr)
126 type(grid_t), intent(in) :: gr
127 type(namespace_t), intent(in) :: namespace
128 type(states_mxll_t), intent(inout) :: st
129 type(hamiltonian_mxll_t), intent(inout) :: hm
130 type(propagator_mxll_t), intent(inout) :: tr
131
132 integer :: nlines, ncols, icol
133 type(block_t) :: blk
134 character(len=256) :: string
135 logical :: plane_waves_set
136
137 push_sub(propagator_mxll_init)
138
139 call profiling_in("PROPAGATOR_MXLL_INIT")
140
141 plane_waves_set = .false.
142 hm%bc%bc_type(:) = mxll_bc_zero ! default boundary condition is zero
143
144 !%Variable MaxwellBoundaryConditions
145 !%Type block
146 !%Section Maxwell
147 !%Description
148 !% Defines boundary conditions for the electromagnetic field propagation.
149 !%
150 !% Example:
151 !%
152 !% <tt>%MaxwellBoundaryConditions
153 !% <br>&nbsp;&nbsp; zero | mirror_pec | constant
154 !% <br>%</tt>
155 !%
156 !%
157 !%Option zero 0
158 !% Boundaries are set to zero.
159 !%Option constant 1
160 !% Boundaries are set to a constant.
161 !%Option mirror_pec 2
162 !% Perfect electric conductor.
163 !%Option mirror_pmc 3
164 !% Perfect magnetic conductor.
165 !%Option plane_waves 4
166 !% Boundaries feed in plane waves.
167 !%Option periodic 5
168 !% Periodic boundary conditions (not yet implemented).
169 !%Option medium 6
170 !% Boundaries as linear medium (not yet implemented).
171 !%End
172 if (parse_block(namespace, 'MaxwellBoundaryConditions', blk) == 0) then
173
174 call messages_print_with_emphasis(msg='Maxwell Boundary Conditions:', namespace=namespace)
175 ! find out how many lines (i.e. states) the block has
176 nlines = parse_block_n(blk)
177 if (nlines /= 1) then
178 call messages_input_error(namespace, 'MaxwellBoundaryConditions', 'should consist of one line')
179 end if
180 ncols = parse_block_cols(blk, 0)
181 if (ncols /= 3) then
182 call messages_input_error(namespace, 'MaxwellBoundaryConditions', 'should consist of three columns')
183 end if
184 do icol = 1, ncols
185 call parse_block_integer(blk, 0, icol-1, hm%bc%bc_type(icol))
186 end do
187 call parse_block_end(blk)
188 end if
189
190 do icol = 1, 3
191 select case (hm%bc%bc_type(icol))
192 case (mxll_bc_zero)
193 string = 'Zero'
194 hm%bc_zero = .true.
195 tr%bc_zero = .true.
197 string = 'Constant'
198 tr%bc_constant = .true.
199 tr%bc_add_ab_region = .true.
200 hm%bc_constant = .true.
201 hm%bc_add_ab_region = .true.
203 string = 'PEC Mirror'
204 tr%bc_mirror_pec = .true.
205 hm%bc_mirror_pec = .true.
206 case (mxll_bc_mirror_pmc)
207 string = 'PMC Mirror'
208 tr%bc_mirror_pmc = .true.
209 hm%bc_mirror_pmc = .true.
210 case (mxll_bc_periodic)
211 string = 'Periodic'
212 tr%bc_periodic = .true.
213 hm%bc_periodic = .true.
215 string = 'Plane waves'
216 plane_waves_set = .true.
217 tr%bc_plane_waves = .true.
218 tr%bc_add_ab_region = .true.
219 hm%plane_waves = .true.
220 hm%bc_plane_waves = .true.
221 hm%bc_add_ab_region = .true.
222 case (mxll_bc_medium)
223 string = 'Medium boundary'
224 case default
225 write(message(1),'(a)') 'Unknown Maxwell boundary condition'
226 call messages_fatal(1, namespace=namespace)
227 end select
228 write(message(1),'(a,I1,a,a)') 'Maxwell boundary condition in direction ', icol, ': ', trim(string)
229 call messages_info(1, namespace=namespace)
230 if (plane_waves_set .and. .not. (parse_is_defined(namespace, 'MaxwellIncidentWaves'))) then
231 write(message(1),'(a)') 'Input: Maxwell boundary condition option is set to "plane_waves".'
232 write(message(2),'(a)') 'Input: User defined Maxwell plane waves have to be defined!'
233 call messages_fatal(2, namespace=namespace)
234 end if
235 end do
236
237 if (any(hm%bc%bc_type(1:3) == mxll_bc_constant)) then
238 call td_function_mxll_init(st, namespace, hm)
239 safe_allocate(st%rs_state_const(1:st%dim))
240 st%rs_state_const = m_z0
241 end if
242
243 !%Variable MaxwellTDETRSApprox
244 !%Type integer
245 !%Default no
246 !%Section Maxwell::TD Propagation
247 !%Description
248 !% Whether to perform approximations to the ETRS propagator.
249 !%Option no 0
250 !% No approximations.
251 !%Option const_steps 1
252 !% Use constant current density.
253 !%End
254 call parse_variable(namespace, 'MaxwellTDETRSApprox', mxwll_etrs_full, tr%tr_etrs_approx)
255
256 !%Variable MaxwellPlaneWavesInBox
257 !%Type logical
258 !%Default no
259 !%Section Maxwell
260 !%Description
261 !% Analytic evaluation of the incoming waves inside the box,
262 !% not doing any numerical propagation of Maxwells equations.
263 !%End
264 call parse_variable(namespace, 'MaxwellPlaneWavesInBox', .false., tr%plane_waves_in_box)
265 if (tr%plane_waves_in_box .and. .not. hm%bc%do_plane_waves) then
266 call external_waves_init(hm%bc%plane_wave, namespace)
267 end if
268
269 call messages_print_with_emphasis(namespace=namespace)
270
271 call derivatives_boundary_mask(hm%bc, gr, hm)
272
273 !tr%te%exp = .true.
274 call exponential_init(tr%te, namespace, full_batch=.true.) ! initialize Maxwell propagator
275
276 call profiling_out("PROPAGATOR_MXLL_INIT")
277
278 pop_sub(propagator_mxll_init)
279 end subroutine propagator_mxll_init
280
281 ! ---------------------------------------------------------
282 subroutine mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
283 type(hamiltonian_mxll_t), intent(inout) :: hm
284 type(namespace_t), intent(in) :: namespace
285 type(grid_t), intent(inout) :: gr
286 class(space_t), intent(in) :: space
287 type(states_mxll_t), intent(inout) :: st
288 type(propagator_mxll_t), intent(inout) :: tr
289 type(batch_t), intent(inout) :: rs_stateb
290 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t1(:,:)
291 complex(real64), contiguous, intent(in) :: ff_rs_inhom_t2(:,:)
292 real(real64), intent(in) :: time
293 real(real64), intent(in) :: dt
294
295 integer :: ii, ff_dim, idim, istate, inter_steps
296 real(real64) :: inter_dt, inter_time
297
298
299 logical :: pml_check
300 type(batch_t) :: ff_rs_stateb, ff_rs_state_pmlb
301 type(batch_t) :: ff_rs_inhom_1b, ff_rs_inhom_2b, ff_rs_inhom_meanb
302 complex(real64), allocatable :: rs_state(:, :)
303
304 push_sub(mxll_propagation_step)
305
306 call profiling_in('MXLL_PROPAGATOR_STEP')
307 pml_check = .false.
308
309 if (hm%ma_mx_coupling_apply) then
310 message(1) = "Maxwell-matter coupling not implemented yet"
311 call messages_fatal(1, namespace=namespace)
312 end if
313 safe_allocate(rs_state(gr%np, st%dim))
314
315 if (tr%plane_waves_in_box) then
316 rs_state = m_z0
317 call plane_waves_in_box_calculation(hm%bc, time+dt, space, gr, gr%der, st, rs_state)
318 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
319 safe_deallocate_a(rs_state)
320 pop_sub(mxll_propagation_step)
321 return
322 end if
323
324 do idim = 1, 3
325 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__cpml) then
326 pml_check = .true.
327 end if
328 end do
329
330 ! this must be called only once, but can not be placed in init routines because PML parameters need to know about dt
331 if (pml_check .and. .not. hm%bc%pml%parameters_initialized) &
332 call bc_mxll_generate_pml_parameters(hm%bc, space, gr, hm%c_factor, dt)
333
334 ff_dim = hm%dim
335
336 ! intermediate step variables
337 inter_steps = 1
338 inter_dt = m_one / inter_steps * dt
339
340 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
341 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
342
343 if (pml_check) then
344 call ff_rs_stateb%copy_to(ff_rs_state_pmlb)
345 end if
346
347 ! first step of Maxwell inhomogeneity propagation with constant current density
348 if ((hm%ma_mx_coupling_apply .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) .and. &
349 tr%tr_etrs_approx == mxwll_etrs_const) then
350 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
351 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
352 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
353
354 do istate = 1, hm%dim
355 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t1(:, istate))
356 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
357 end do
358 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_meanb)
359 call batch_scal(gr%np, m_half, ff_rs_inhom_meanb)
360
361 ! inhomogeneity propagation
362 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_1b)
363 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
364
365 call hamiltonian_mxll_update(hm, time=time)
366 hm%cpml_hamiltonian = .false.
367 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt)
368
369 ! add term U(time+dt,time)J(time)
370 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
371 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
372 call hamiltonian_mxll_update(hm, time=time)
373 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt*m_half)
374 ! add term U(time+dt/2,time)J(time)
375 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
376 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
377 call hamiltonian_mxll_update(hm, time=time)
378 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt*m_half)
379 ! add term U(time,time+dt/2)J(time)
380 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
381 call ff_rs_inhom_2b%end()
382 call ff_rs_inhom_meanb%end()
383 end if
384
385 do ii = 1, inter_steps
386
387 ! intermediate time
388 inter_time = time + inter_dt * (ii-1)
389
390 ! transformation of RS state into 3x3 or 4x4 representation
391 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_forward)
392
393 ! RS state propagation
394 call hamiltonian_mxll_update(hm, time=inter_time)
395 if (pml_check) then
396 call pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
397 end if
398
399 hm%cpml_hamiltonian = pml_check
400 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
401 hm%cpml_hamiltonian = .false.
402
403 if (pml_check) then
404 call pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, inter_time, inter_dt, m_zero, ff_rs_state_pmlb, ff_rs_stateb)
405 end if
406
407 !Below we add the contribution from the inhomogeneous terms
408 if ((hm%ma_mx_coupling_apply) .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) then
409 if (tr%tr_etrs_approx == mxwll_etrs_full) then
410 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
411 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
412 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
413
414 ! Interpolation of the external current
415 do istate = 1, hm%dim
416 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t2(:, istate))
417 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
418 end do
419 ! store t1 - t2 for the interpolation in mean
420 call batch_axpy(gr%np, -m_one, ff_rs_inhom_1b, ff_rs_inhom_meanb)
421 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
422 call batch_axpy(gr%np, ii / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_2b)
423 call batch_axpy(gr%np, (ii-1) / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_1b)
424
425 hm%cpml_hamiltonian = .false.
426 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt)
427 ! add terms U(time+dt,time)J(time) and J(time+dt)
428 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
429 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
430
431 do istate = 1, hm%dim
432 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
433 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
434 end do
435 call batch_axpy(gr%np, m_one, ff_rs_inhom_2b, ff_rs_inhom_1b)
436 call batch_scal(gr%np, m_half, ff_rs_inhom_1b)
437 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
438
439 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt/m_two)
440 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt/m_two)
441
442 ! add terms U(time+dt/2,time)J(time) and U(time,time+dt/2)J(time+dt)
443 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
444 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_2b, ff_rs_stateb)
445
446 call ff_rs_inhom_1b%end()
447 call ff_rs_inhom_2b%end()
448 call ff_rs_inhom_meanb%end()
449 else if (tr%tr_etrs_approx == mxwll_etrs_const) then
450 call batch_axpy(gr%np, -m_fourth * inter_dt, ff_rs_inhom_1b, ff_rs_stateb)
451 end if
452 end if
453
454 ! PML convolution function update
455 if (pml_check) then
456 call cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
457 end if
458
459 ! back transformation of RS state representation
460 call transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, rs_trans_backward)
461
462 if (tr%bc_constant) then
463 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
464 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
465 if (st%rs_state_const_external) then
466 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, inter_time, inter_dt, m_zero, rs_state)
467 end if
468 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
469 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
470 end if
471
472 ! Propagation dt with H(inter_time+inter_dt) for PEC mirror boundaries
473 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
474 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
475 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
476 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
477 end if
478
479 ! Propagation dt with H(inter_time+inter_dt) for PMC mirror boundaries
480 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
481 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
482 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
483 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
484 end if
485
486 ! Apply mask absorbing boundaries
487 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
488 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
489 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, inter_time, inter_dt, m_zero, rs_state)
490 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
491 end if
492
493 if (tr%bc_plane_waves) then
494 ! Propagation dt with H(inter_time+inter_dt) for plane waves boundaries
495 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
496 call plane_waves_boundaries_calculation(hm, st, gr, inter_time+inter_dt, m_zero, rs_state)
497 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
498 end if
499
500 end do
501
502 if (tr%tr_etrs_approx == option__maxwelltdetrsapprox__const_steps) then
503 call ff_rs_inhom_1b%end()
504 end if
505
506 call ff_rs_stateb%end()
507
508 if (pml_check) then
509 call ff_rs_state_pmlb%end()
510 end if
511
512 safe_deallocate_a(rs_state)
513
514 call profiling_out('MXLL_PROPAGATOR_STEP')
515
516 pop_sub(mxll_propagation_step)
517 end subroutine mxll_propagation_step
518
519 ! ---------------------------------------------------------
520 subroutine mxll_propagate_leapfrog(hm, namespace, gr, space, st, tr, time, dt, counter)
521 type(hamiltonian_mxll_t), intent(inout) :: hm
522 type(namespace_t), intent(in) :: namespace
523 type(grid_t), intent(inout) :: gr
524 class(space_t), intent(in) :: space
525 type(states_mxll_t), intent(inout) :: st
526 type(propagator_mxll_t), intent(inout) :: tr
527 real(real64), intent(in) :: time
528 real(real64), intent(in) :: dt
529 integer, intent(in) :: counter
530
531 type(batch_t) :: rs_state_tmpb
532
533 push_sub_with_profile(mxll_propagate_leapfrog)
534
535 call st%rs_stateb%copy_to(rs_state_tmpb)
536
537 call hamiltonian_mxll_update(hm, time)
538
539 ! do boundaries at the beginning
540 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, st%rs_stateb)
541
542 ! update PML convolution values
543 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
544 call mxll_update_pml_simple(hm, st%rs_stateb)
545 end if
546
547 ! apply hamiltonian
548 call hamiltonian_mxll_apply_simple(hm, namespace, gr, st%rs_stateb, rs_state_tmpb)
549 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
550
551 ! add inhomogeneous terms
552 call batch_xpay(gr%np, st%inhomogeneousb, m_one, rs_state_tmpb)
553
554 if (counter == 0) then
555 ! for the first step, we do one forward Euler step
556 call batch_xpay(gr%np, st%rs_stateb, dt, rs_state_tmpb)
557 else
558 ! the leapfrog step depends on the previous state
559 call batch_xpay(gr%np, st%rs_state_prevb, m_two*dt, rs_state_tmpb)
560 end if
561
562 ! save the current rs state
563 call st%rs_stateb%copy_data_to(gr%np, st%rs_state_prevb)
564 ! update to new timestep
565 call rs_state_tmpb%copy_data_to(gr%np, st%rs_stateb)
566
567 ! update PML convolution values
568 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
569 call mxll_copy_pml_simple(hm, st%rs_stateb)
570 end if
571
572 call rs_state_tmpb%end()
573
574 pop_sub_with_profile(mxll_propagate_leapfrog)
575 end subroutine mxll_propagate_leapfrog
576
577 ! ---------------------------------------------------------
591 subroutine mxll_propagate_expgauss1(hm, namespace, gr, space, st, tr, time, dt)
592 type(hamiltonian_mxll_t), intent(inout) :: hm
593 type(namespace_t), intent(in) :: namespace
594 type(grid_t), intent(inout) :: gr
595 class(space_t), intent(in) :: space
596 type(states_mxll_t), intent(inout) :: st
597 type(propagator_mxll_t), intent(inout) :: tr
598 real(real64), intent(in) :: time
599 real(real64), intent(in) :: dt
600
601 type(batch_t) :: rs_state_tmpb
602
603 push_sub_with_profile(mxll_propagate_expgauss1)
604
605 call st%rs_stateb%copy_to(rs_state_tmpb)
606
607 call hamiltonian_mxll_update(hm, time)
608
609 ! do boundaries at the beginning (should be included in Hamiltonian?)
610 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
611 dt, st%rs_stateb)
612
613 ! update PML convolution values
614 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
615 call mxll_update_pml_simple(hm, st%rs_stateb)
616 end if
617
618 ! accumulate -i H F_n - J_1 in rs_state_tmpb
619 ! compute H F_n
620 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
621 ! compute -i H F_n
622 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
623 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
624 ! set J_1
625 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
626 ! accumulate -J_1 to rs_state_tmpb
627 call batch_axpy(gr%np, -m_one, st%inhomogeneousb, rs_state_tmpb)
628 end if
629 ! compute phi_1
630 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
631 ! F_{n+1} = F_n + dt * phi_1 (...)
632 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
633
634 call rs_state_tmpb%end()
635
636 ! update PML convolution values
637 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
638 call mxll_copy_pml_simple(hm, st%rs_stateb)
639 end if
640
641 pop_sub_with_profile(mxll_propagate_expgauss1)
642 end subroutine mxll_propagate_expgauss1
643
644 ! ---------------------------------------------------------
664 subroutine mxll_propagate_expgauss2(hm, namespace, gr, space, st, tr, time, dt)
665 type(hamiltonian_mxll_t), intent(inout) :: hm
666 type(namespace_t), intent(in) :: namespace
667 type(grid_t), intent(inout) :: gr
668 class(space_t), intent(in) :: space
669 type(states_mxll_t), intent(inout) :: st
670 type(propagator_mxll_t), intent(inout) :: tr
671 real(real64), intent(in) :: time
672 real(real64), intent(in) :: dt
673
674 type(batch_t) :: rs_state_tmpb
675
676 push_sub_with_profile(mxll_propagate_expgauss2)
677
678 call st%rs_stateb%copy_to(rs_state_tmpb)
679
680 call hamiltonian_mxll_update(hm, time)
681
682 ! do boundaries at the beginning (should be included in Hamiltonian?)
683 call mxll_apply_boundaries(tr, st, hm, gr, namespace, time, &
684 dt, st%rs_stateb)
685
686 ! update PML convolution values
687 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
688 call mxll_update_pml_simple(hm, st%rs_stateb)
689 end if
690
691 ! accumulate -i H F_n - a_1 J_1 - a_2 J_2 in rs_state_tmpb
692 ! compute H F_n
693 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
694 ! compute -i H F_n
695 call batch_scal(gr%np, -m_zi, rs_state_tmpb)
696 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
697 ! set J_1
698 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
699 ! accumulate -a_1 J_1 to rs_state_tmpb
700 call batch_axpy(gr%np, -m_half*(m_one+sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
701 ! set J_2
702 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
703 ! accumulate -a_2 J_2 to rs_state_tmpb
704 call batch_axpy(gr%np, -m_half*(m_one-sqrt(m_three)), st%inhomogeneousb, rs_state_tmpb)
705 end if
706 ! compute phi_1
707 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
708 ! accumulate phi_1 term: F_{n+1} = F_n + dt * phi_1 (...)
709 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
710 if (hm%current_density_ext_flag .or. hm%current_density_from_medium) then
711 call batch_set_zero(rs_state_tmpb)
712 ! set J_1
713 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
714 ! accumulate -b_1 J_1 to rs_state_tmpb
715 call batch_axpy(gr%np, sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
716 ! set J_2
717 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
718 ! accumulate -b_2 J_2 to rs_state_tmpb
719 call batch_axpy(gr%np, -sqrt(m_three), st%inhomogeneousb, rs_state_tmpb)
720
721 ! compute phi_2
722 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 2)
723 ! accumulate phi_2 term: F_{n+1} = F_n + dt * phi_2 (...)
724 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
725 end if
726
727 ! update PML convolution values
728 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml)) then
729 call mxll_copy_pml_simple(hm, st%rs_stateb)
730 end if
731
732 call rs_state_tmpb%end()
733
734 pop_sub_with_profile(mxll_propagate_expgauss2)
735 end subroutine mxll_propagate_expgauss2
736
737 ! ---------------------------------------------------------
738 subroutine set_medium_rs_state(st, gr, hm)
739 type(states_mxll_t), intent(inout) :: st
740 type(grid_t), intent(in) :: gr
741 type(hamiltonian_mxll_t), intent(in) :: hm
742
743 integer :: ip, ip_in, il, idim
744
745 push_sub(set_medium_rs_state)
746
747 assert(allocated(st%ep) .and. allocated(st%mu))
748
749 call profiling_in('SET_MEDIUM_RS_STATE')
750
751 if (hm%calc_medium_box) then
752 do il = 1, size(hm%medium_boxes)
753 assert(.not. hm%medium_boxes(il)%has_mapping)
754 do ip = 1, hm%medium_boxes(il)%points_number
755 if (abs(hm%medium_boxes(il)%c(ip)) <= m_epsilon) cycle
756 st%ep(ip) = hm%medium_boxes(il)%ep(ip)
757 st%mu(ip) = hm%medium_boxes(il)%mu(ip)
758 end do
759 end do
760 end if
761
762 do idim = 1, st%dim
763 if (hm%bc%bc_type(idim) == mxll_bc_medium) then
764 do ip_in = 1, hm%bc%medium(idim)%points_number
765 ip = hm%bc%medium(idim)%points_map(ip_in)
766 st%ep(ip) = hm%bc%medium(idim)%ep(ip_in)
767 st%mu(ip) = hm%bc%medium(idim)%mu(ip_in)
768 end do
769 end if
770 end do
771
772 call profiling_out('SET_MEDIUM_RS_STATE')
773
774 pop_sub(set_medium_rs_state)
775 end subroutine set_medium_rs_state
776
777 ! ---------------------------------------------------------
778 subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
779 type(hamiltonian_mxll_t), intent(in) :: hm
780 type(grid_t), intent(in) :: gr
781 type(states_mxll_t), intent(in) :: st
782 type(batch_t), intent(inout) :: rs_stateb
783 type(batch_t), intent(inout) :: ff_rs_stateb
784 integer, intent(in) :: sign
785
786 complex(real64), allocatable :: rs_state(:,:)
787 complex(real64), allocatable :: rs_state_tmp(:,:)
788 integer :: ii, np
789
791
792 call profiling_in('TRANSFORM_RS_STATE')
793
794 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
795
796 np = gr%np
797 safe_allocate(rs_state(1:gr%np, 1:st%dim))
798
799 if (hm%operator == faraday_ampere_medium) then
800 if (sign == rs_trans_forward) then
801 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
802 ! 3 to 6
803 do ii = 1, 3
804 call batch_set_state(ff_rs_stateb, ii, np, rs_state(:, ii))
805 call batch_set_state(ff_rs_stateb, ii+3, np, conjg(rs_state(:, ii)))
806 end do
807 else
808 ! 6 to 3
809 safe_allocate(rs_state_tmp(1:gr%np, 1:st%dim))
810 do ii = 1, 3
811 call batch_get_state(ff_rs_stateb, ii, np, rs_state(:, ii))
812 call batch_get_state(ff_rs_stateb, ii+3, np, rs_state_tmp(:, ii))
813 rs_state(1:np, ii) = m_half * (rs_state(1:np, ii) + conjg(rs_state_tmp(1:np, ii)))
814 end do
815 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
816 safe_deallocate_a(rs_state_tmp)
817 end if
818 else
819 if (sign == rs_trans_forward) then
820 call rs_stateb%copy_data_to(gr%np, ff_rs_stateb)
821 else
822 call ff_rs_stateb%copy_data_to(gr%np, rs_stateb)
823 end if
824 end if
825 safe_deallocate_a(rs_state)
826
827 call profiling_out('TRANSFORM_RS_STATE')
828
830
832
833 ! ---------------------------------------------------------
834 subroutine transform_rs_densities(hm, mesh, rs_charge_density, rs_current_density, ff_density, sign)
835 type(hamiltonian_mxll_t), intent(in) :: hm
836 class(mesh_t), intent(in) :: mesh
837 complex(real64), intent(inout) :: rs_charge_density(:)
838 complex(real64), intent(inout) :: rs_current_density(:,:)
839 complex(real64), intent(inout) :: ff_density(:,:)
840 integer, intent(in) :: sign
841
842
843 assert(sign == rs_trans_forward .or. sign == rs_trans_backward)
844 assert(size(rs_charge_density) == mesh%np .or. size(rs_charge_density) == mesh%np_part)
845 assert(size(rs_current_density, dim=1) == size(rs_charge_density))
846 assert(size(rs_current_density, dim=2) == 3)
847
848 push_sub(transform_rs_densities)
849
850 call profiling_in('TRANSFORM_RS_DENSITIES')
851
852 if (hm%operator == faraday_ampere_medium) then
853 if (sign == rs_trans_forward) then
854 call transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, &
855 rs_current_density, ff_density)
856 else
858 rs_charge_density, rs_current_density)
859 end if
860 else
861 if (sign == rs_trans_forward) then
862 ff_density(1:mesh%np, 1:3) = rs_current_density(1:mesh%np, 1:3)
863 else
864 rs_current_density(1:mesh%np, 1:3) = ff_density(1:mesh%np, 1:3)
865 end if
866 end if
867
868 call profiling_out('TRANSFORM_RS_DENSITIES')
869
872 end subroutine transform_rs_densities
873
874 !----------------------------------------------------------
875 subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, rs_current_density, rs_density_6x6)
876 class(mesh_t), intent(in) :: mesh
877 complex(real64), intent(in) :: rs_charge_density(:)
878 complex(real64), intent(in) :: rs_current_density(:,:)
879 complex(real64), intent(inout) :: rs_density_6x6(:,:)
880
881 integer :: ii
882
883 assert(size(rs_current_density, dim=2) == 3)
884 assert(size(rs_density_6x6, dim=2) == 6)
885
886 ! no push_sub, called to frequently
887 do ii = 1, 3
888 rs_density_6x6(1:mesh%np, ii) = rs_current_density(1:mesh%np, ii)
889 rs_density_6x6(1:mesh%np, ii+3) = rs_current_density(1:mesh%np, ii)
890 end do
891
893
894 !----------------------------------------------------------
895 subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_charge_density, rs_current_density)
896 class(mesh_t), intent(in) :: mesh
897 complex(real64), intent(in) :: rs_density_6x6(:,:)
898 complex(real64), intent(inout) :: rs_charge_density(:)
899 complex(real64), intent(inout) :: rs_current_density(:,:)
900
901 integer :: ii
902
903 assert(size(rs_current_density, dim=2) == 3)
904 assert(size(rs_density_6x6, dim=2) == 6)
905
906 ! no push_sub, called to frequently
907 do ii = 1, 3
908 rs_current_density(1:mesh%np, ii) = m_half * &
909 real(rs_density_6x6(1:mesh%np, ii) + rs_density_6x6(1:mesh%np, ii+3), real64)
910 end do
911
913
914 !----------------------------------------------------------
915 subroutine calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, st_elec, hm_elec, rs_state_matter)
916 type(grid_t), intent(in) :: gr_mxll
917 type(states_mxll_t), intent(in) :: st_mxll
918 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
919 type(grid_t), intent(in) :: gr_elec
920 type(states_elec_t), intent(in) :: st_elec
921 type(hamiltonian_elec_t), intent(in) :: hm_elec
922 complex(real64), intent(inout) :: rs_state_matter(:,:)
923
924 complex(real64), allocatable :: tmp_pot_mx_gr(:,:), tmp_grad_mx_gr(:,:)
925
926 safe_allocate(tmp_pot_mx_gr(1:gr_mxll%np_part,1))
927 safe_allocate(tmp_grad_mx_gr(1:gr_mxll%np,1:gr_mxll%box%dim))
928 ! this subroutine needs the matter part
929
931
932 tmp_pot_mx_gr(:,:) = m_zero
933 tmp_grad_mx_gr(:,:) = m_zero
934 call zderivatives_grad(gr_mxll%der, tmp_pot_mx_gr(:,1), tmp_grad_mx_gr(:,:), set_bc = .false.)
935 tmp_grad_mx_gr = - tmp_grad_mx_gr
936
937 rs_state_matter = m_z0
938 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, &
939 rs_state_matter(1:gr_mxll%np,:), gr_mxll, st_mxll%ep(1:gr_mxll%np), st_mxll%mu(1:gr_mxll%np), &
940 gr_mxll%np)
941
942 safe_deallocate_a(tmp_pot_mx_gr)
943 safe_deallocate_a(tmp_grad_mx_gr)
944
947
948 !----------------------------------------------------------
949 subroutine get_vector_pot_and_transverse_field(namespace, trans_calc_method, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, st, &
950 poisson_solver, helmholtz, time, field, transverse_field, vector_potential)
951 type(namespace_t), intent(in) :: namespace
952 integer, intent(in) :: trans_calc_method
953 type(grid_t), intent(in) :: gr_mxll
954 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
955 type(states_mxll_t), intent(in) :: st_mxll
956 type(propagator_mxll_t), intent(in) :: tr_mxll
957 type(hamiltonian_elec_t), intent(in) :: hm
958 type(states_elec_t), intent(in) :: st
959 type(poisson_t), intent(in) :: poisson_solver
960 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
961 real(real64), intent(in) :: time
962 complex(real64), intent(inout) :: field(:,:)
963 complex(real64), intent(inout) :: transverse_field(:,:)
964 real(real64), intent(inout) :: vector_potential(:,:)
965
966 integer :: np
967 complex(real64), allocatable :: rs_state_plane_waves(:, :)
970
971 transverse_field = m_z0
973
974 np = gr_mxll%np
975
976 if (hm_mxll%ma_mx_coupling) then
977
978 ! check what other transverse field methods are needed
979
980 ! trans_calc_method == OPTION__MAXWELLTRANSFIELDCALCULATIONMETHOD__TRANS_FIELD_POISSON
981 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
982 safe_allocate(rs_state_plane_waves(1:gr_mxll%np, 1:st_mxll%dim))
983 call mxll_get_batch(st_mxll%rs_state_plane_wavesb, rs_state_plane_waves, gr_mxll%np, st_mxll%dim)
984 end if
985
986 ! plane waves subtraction
987 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
988 transverse_field(1:np,:) = field(1:np,:) - rs_state_plane_waves(1:np,:)
989 else
990 transverse_field(1:np,:) = field(1:np,:)
991 end if
992 ! apply helmholtz decomposition for transverse field
993 call helmholtz%get_trans_field(namespace, transverse_field, total_field=field)
994 ! plane waves addition
995 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply) then
996 transverse_field(1:np,:) = transverse_field(1:np,:) + rs_state_plane_waves(1:np,:)
997 safe_deallocate_a(rs_state_plane_waves)
998 end if
999
1000 else
1001
1002 transverse_field(1:np,:) = field
1003
1004 end if
1005
1006
1010
1011 ! ---------------------------------------------------------
1012 subroutine calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
1013 type(namespace_t), intent(in) :: namespace
1014 type(poisson_t), intent(in) :: poisson_solver
1015 type(grid_t), intent(in) :: gr
1016 type(states_mxll_t), intent(in) :: st
1017 complex(real64), intent(in) :: field(:,:)
1018 real(real64), intent(inout) :: vector_potential(:,:)
1019
1020 integer :: idim
1021 real(real64), allocatable :: dtmp(:,:)
1022
1023 safe_allocate(dtmp(1:gr%np_part,1:3))
1024
1025 dtmp = m_zero
1026
1027 call get_magnetic_field_state(field, gr, st%rs_sign, vector_potential, st%mu, gr%np_part)
1028 dtmp = vector_potential
1029 call dderivatives_curl(gr%der, dtmp, vector_potential, set_bc = .false.)
1030 do idim=1, st%dim
1031 call dpoisson_solve(poisson_solver, namespace, dtmp(:,idim), vector_potential(:,idim), .true.)
1032 end do
1034
1035 safe_deallocate_a(dtmp)
1036
1037 end subroutine calculate_vector_potential
1038
1039 ! ---------------------------------------------------------
1040 subroutine derivatives_boundary_mask(bc, mesh, hm)
1041 type(bc_mxll_t), intent(inout) :: bc
1042 class(mesh_t), intent(in) :: mesh
1043 type(hamiltonian_mxll_t), intent(in) :: hm
1044
1045 integer :: ip, ip_in, point_info, idim, dim
1046 real(real64) :: bounds(2, mesh%box%dim), xx(mesh%box%dim)
1047 real(real64) :: ddv(mesh%box%dim), tmp(mesh%box%dim), width(mesh%box%dim)
1048 real(real64), allocatable :: mask(:)
1049
1051
1052 call profiling_in('DERIVATIVES_BOUNDARY_MASK')
1053 dim = mesh%box%dim
1054
1055 if (hm%bc_zero .or. hm%bc_constant .or. hm%bc_plane_waves) then
1056 bounds(1,1:dim) = (mesh%idx%nr(2,1:dim) - 2 * mesh%idx%enlarge(1:dim)) * mesh%spacing(1:dim)
1057 bounds(2,1:dim) = (mesh%idx%nr(2,1:dim) - mesh%idx%enlarge(1:dim)) * mesh%spacing(1:dim)
1058 end if
1059
1060 ip_in=0
1061 do ip=1, mesh%np
1062 xx(1:dim) = mesh%x(ip,1:dim)
1063 if ((abs(xx(1)) <= bounds(2,1)) .and. (abs(xx(2)) <= bounds(2,2)) .and. (abs(xx(3)) <= bounds(2,3))) then
1064 if ((abs(xx(1)) > bounds(1,1)) .or. (abs(xx(2)) > bounds(1,2)) .or. (abs(xx(3)) > bounds(1,3))) then
1065 point_info = 1
1066 else
1067 point_info = 0
1068 end if
1069 else
1070 point_info = -1
1071 end if
1072 if (point_info == 1) then
1073 ip_in = ip_in + 1
1074 end if
1075 end do
1076 bc%der_bndry_mask_points_number = ip_in
1077 safe_allocate(bc%der_bndry_mask(1:ip_in))
1078 safe_allocate(bc%der_bndry_mask_points_map(1:ip_in))
1079
1080 ip_in=0
1081 do ip=1, mesh%np
1082 xx(1:dim) = mesh%x(ip,1:dim)
1083 if ((abs(xx(1)) <= bounds(2,1)) .and. (abs(xx(2)) <= bounds(2,2)) .and. (abs(xx(3)) <= bounds(2,3))) then
1084 if ((abs(xx(1)) > bounds(1,1)) .or. (abs(xx(2)) > bounds(1,2)) .or. (abs(xx(3)) > bounds(1,3))) then
1085 point_info = 1
1086 else
1087 point_info = 0
1088 end if
1089 else
1090 point_info = -1
1091 end if
1092 if (point_info == 1) then
1093 ip_in = ip_in + 1
1094 bc%der_bndry_mask_points_map(ip_in) = ip
1095 end if
1096 end do
1097
1098 safe_allocate(mask(1:mesh%np))
1099 mask(:) = m_one
1100 width(:) = bounds(2,:) - bounds(1,:)
1101 tmp(:) = m_zero
1102
1103 do ip = 1, mesh%np
1104 tmp = m_one
1105 mask(ip) = m_one
1106 ddv(1:dim) = abs(mesh%x(ip,1:dim)) - bounds(1,1:dim)
1107 do idim = 1, mesh%box%dim
1108 if (ddv(idim) >= m_zero) then
1109 if (ddv(idim) <= width(idim)) then
1110 tmp(idim) = m_one - sin(ddv(idim) * m_pi / (m_two * (width(idim))))**2
1111 else
1112 tmp(idim) = m_one
1113 end if
1114 end if
1115 mask(ip) = mask(ip) * tmp(idim)
1116 end do
1117 end do
1118
1119 do idim = 1, mesh%box%dim
1120 do ip_in = 1, bc%der_bndry_mask_points_number
1121 ip = bc%der_bndry_mask_points_map(ip_in)
1122 bc%der_bndry_mask(ip_in) = mask(ip)
1123 end do
1124 end do
1125
1126 safe_deallocate_a(mask)
1127 call profiling_out('DERIVATIVES_BOUNDARY_MASK')
1128
1130 end subroutine derivatives_boundary_mask
1131
1132
1133 !----------------------------------------------------------
1134 subroutine energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
1135 type(grid_t), intent(in) :: gr
1136 type(states_mxll_t), intent(in) :: st
1137 type(hamiltonian_mxll_t), intent(in) :: hm
1138 type(energy_mxll_t), intent(inout) :: energy_mxll
1139 complex(real64), intent(in) :: rs_field(:,:)
1140 complex(real64), optional, intent(in) :: rs_field_plane_waves(:,:)
1141
1142 real(real64), allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:), energy_density_plane_waves(:)
1143
1144 push_sub(energy_mxll_calc)
1145
1146 call profiling_in('ENERGY_MXLL_CALC')
1147
1148 safe_allocate(energy_density(1:gr%np))
1149 safe_allocate(e_energy_density(1:gr%np))
1150 safe_allocate(b_energy_density(1:gr%np))
1151 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
1152 safe_allocate(energy_density_plane_waves(1:gr%np))
1153 end if
1154
1155 call energy_density_calc(gr, st, rs_field, energy_density, e_energy_density, &
1156 b_energy_density, hm%plane_waves, rs_field_plane_waves, energy_density_plane_waves)
1157 energy_mxll%energy = dmf_integrate(gr, energy_density, mask=st%inner_points_mask)
1158 energy_mxll%e_energy = dmf_integrate(gr, e_energy_density, mask=st%inner_points_mask)
1159 energy_mxll%b_energy = dmf_integrate(gr, b_energy_density, mask=st%inner_points_mask)
1160 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
1161 energy_mxll%energy_plane_waves = dmf_integrate(gr, energy_density_plane_waves, mask=st%inner_points_mask)
1162 else
1163 energy_mxll%energy_plane_waves = m_zero
1164 end if
1165
1166 energy_mxll%boundaries = dmf_integrate(gr, energy_density, mask=st%boundary_points_mask)
1167
1168 safe_deallocate_a(energy_density)
1169 safe_deallocate_a(e_energy_density)
1170 safe_deallocate_a(b_energy_density)
1171 if (present(rs_field_plane_waves) .and. hm%plane_waves) then
1172 safe_deallocate_a(energy_density_plane_waves)
1173 end if
1174
1175 call profiling_out('ENERGY_MXLL_CALC')
1176
1177 pop_sub(energy_mxll_calc)
1178 end subroutine energy_mxll_calc
1179
1180 !----------------------------------------------------------
1181 subroutine energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
1182 type(grid_t), intent(in) :: gr
1183 type(states_mxll_t), intent(in) :: st
1184 type(hamiltonian_mxll_t), intent(in) :: hm
1185 type(energy_mxll_t), intent(inout) :: energy_mxll
1186 type(batch_t), intent(in) :: rs_fieldb
1187 type(batch_t), intent(in) :: rs_field_plane_wavesb
1188
1189 type(batch_t) :: e_fieldb, b_fieldb, e_field_innerb, b_field_innerb, rs_field_plane_waves_innerb
1190 real(real64) :: tmp(1:st%dim)
1191 complex(real64) :: ztmp(1:st%dim)
1192
1193 push_sub(energy_mxll_calc_batch)
1194
1195 call profiling_in('ENERGY_MXLL_CALC_BATCH')
1196
1197 call dbatch_init(e_fieldb, 1, 1, st%dim, gr%np)
1198 if (st%pack_states) then
1199 call e_fieldb%do_pack(copy=.false.)
1200 end if
1201 call e_fieldb%copy_to(b_fieldb)
1202 call e_fieldb%copy_to(e_field_innerb)
1203 call e_fieldb%copy_to(b_field_innerb)
1204
1205 call batch_split_complex(gr%np, rs_fieldb, e_fieldb, b_fieldb)
1206
1207 ! subtract energy of inner points
1208 call batch_set_zero(e_field_innerb)
1209 call batch_set_zero(b_field_innerb)
1210 if (accel_is_enabled()) then
1211 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, e_fieldb, e_field_innerb)
1212 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, b_fieldb, b_field_innerb)
1213 else
1214 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, e_fieldb, e_field_innerb)
1215 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, b_fieldb, b_field_innerb)
1216 end if
1217 call dmesh_batch_dotp_vector(gr, e_field_innerb, e_field_innerb, tmp)
1218 energy_mxll%e_energy = sum(tmp)
1219 call dmesh_batch_dotp_vector(gr, b_field_innerb, b_field_innerb, tmp)
1220 energy_mxll%b_energy = sum(tmp)
1221 energy_mxll%energy = energy_mxll%e_energy + energy_mxll%b_energy
1222
1223 call dmesh_batch_dotp_vector(gr, e_fieldb, e_fieldb, tmp)
1224 energy_mxll%boundaries = sum(tmp)
1225 call dmesh_batch_dotp_vector(gr, b_fieldb, b_fieldb, tmp)
1226 energy_mxll%boundaries = energy_mxll%boundaries + sum(tmp)
1227 energy_mxll%boundaries = energy_mxll%boundaries - energy_mxll%energy
1228
1229 if (hm%plane_waves) then
1230 call rs_field_plane_wavesb%copy_to(rs_field_plane_waves_innerb)
1231 call batch_set_zero(rs_field_plane_waves_innerb)
1232 if (accel_is_enabled()) then
1233 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, &
1234 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1235 else
1236 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, &
1237 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1238 end if
1239 call zmesh_batch_dotp_vector(gr, rs_field_plane_waves_innerb, rs_field_plane_waves_innerb, ztmp)
1240 energy_mxll%energy_plane_waves = sum(real(tmp, real64) )
1241 call rs_field_plane_waves_innerb%end()
1242 else
1243 energy_mxll%energy_plane_waves = m_zero
1244 end if
1245
1246 call e_fieldb%end()
1247 call b_fieldb%end()
1248 call e_field_innerb%end()
1249 call b_field_innerb%end()
1250
1251 call profiling_out('ENERGY_MXLL_CALC_BATCH')
1252
1253 pop_sub(energy_mxll_calc_batch)
1254 end subroutine energy_mxll_calc_batch
1255
1256 ! ---------------------------------------------------------
1257 subroutine mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
1258 type(namespace_t), intent(in) :: namespace
1259 type(grid_t), intent(in) :: gr
1260 type(hamiltonian_mxll_t), intent(inout) :: hm
1261 type(states_mxll_t), intent(inout) :: st
1262 type(propagator_mxll_t), intent(inout) :: tr
1263 real(real64), intent(in) :: time
1264 real(real64), intent(in) :: dt
1265 real(real64), intent(in) :: time_delay
1266 complex(real64), intent(inout) :: rs_state(:,:)
1267
1268 integer :: ip, ip_in, idim
1269 logical :: mask_check
1270
1272
1273 call profiling_in('MASK_ABSORBING_BOUNDARIES')
1274 mask_check = .false.
1275
1276 do idim = 1, 3
1277 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1278 mask_check = .true.
1279 end if
1280 end do
1281
1282 if (mask_check) then
1283 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1284 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1285 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1286 rs_state = rs_state - st%rs_state_plane_waves
1287 call maxwell_mask(hm, rs_state)
1288 rs_state = rs_state + st%rs_state_plane_waves
1289 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1290 !call constant_at_absorbing_boundaries_calculation(st, hm%bc)
1291 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1292 do ip_in=1, hm%bc%constant_points_number
1293 ip = hm%bc%constant_points_map(ip_in)
1294 rs_state(ip,:) = rs_state(ip,:) - st%rs_state_const(:)
1295 end do
1296 call maxwell_mask(hm, rs_state)
1297 do ip_in=1, hm%bc%constant_points_number
1298 ip = hm%bc%constant_points_map(ip_in)
1299 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const(:)
1300 end do
1301 else
1302 call maxwell_mask(hm, rs_state)
1303 end if
1304 end if
1305
1306 call profiling_out('MASK_ABSORBING_BOUNDARIES')
1307
1309 end subroutine mask_absorbing_boundaries
1310
1311 ! ---------------------------------------------------------
1312 subroutine maxwell_mask(hm, rs_state)
1313 type(hamiltonian_mxll_t), intent(in) :: hm
1314 complex(real64), intent(inout) :: rs_state(:,:)
1315
1316 integer :: ip, ip_in, idim
1317
1318 push_sub(maxwell_mask)
1319
1320 call profiling_in('MAXWELL_MASK')
1321
1322 do idim = 1, 3
1323 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask) then
1324 do ip_in = 1, hm%bc%mask_points_number(idim)
1325 ip = hm%bc%mask_points_map(ip_in,idim)
1326 rs_state(ip,:) = rs_state(ip,:) * hm%bc%mask(ip_in,idim)
1327 end do
1328 end if
1329 end do
1330
1331 call profiling_out('MAXWELL_MASK')
1332
1333 pop_sub(maxwell_mask)
1334 end subroutine maxwell_mask
1335
1336 ! ---------------------------------------------------------
1337 subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
1338 type(hamiltonian_mxll_t), intent(inout) :: hm
1339 type(grid_t), intent(in) :: gr
1340 type(states_mxll_t), intent(inout) :: st
1341 type(propagator_mxll_t), intent(inout) :: tr
1342 type(batch_t), intent(in) :: ff_rs_stateb
1343 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1344
1345 integer :: ii
1346 complex(real64), allocatable :: rs_state_constant(:,:)
1347 type(batch_t) :: rs_state_constantb
1348
1351 call profiling_in('PML_PROP_STAGE_1_BATCH')
1352
1353 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1354 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, &
1355 ff_rs_state_pmlb, rs_trans_forward)
1356 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1357 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1358 ! this could be optimized: right now we broadcast the constant value
1359 ! to the full mesh to be able to use the batch functions easily.
1360 ! in principle, we would need to do the transform only for one point
1361 ! and then subtract that value from all points of the state
1362 safe_allocate(rs_state_constant(1:gr%np,1:3))
1363 do ii = 1, 3
1364 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1365 end do
1366 call ff_rs_stateb%copy_to(rs_state_constantb)
1367 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, 3)
1368
1369 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, &
1370 ff_rs_state_pmlb, rs_trans_forward)
1371 call batch_xpay(gr%np, ff_rs_stateb, -m_one, ff_rs_state_pmlb)
1372
1373 call rs_state_constantb%end()
1374
1375 safe_deallocate_a(rs_state_constant)
1376 else
1377 ! this copy should not be needed
1378 call ff_rs_stateb%copy_data_to(gr%np, ff_rs_state_pmlb)
1379 end if
1380
1381 call profiling_out('PML_PROP_STAGE_1_BATCH')
1382
1384 end subroutine pml_propagation_stage_1_batch
1385
1386 ! ---------------------------------------------------------
1387 subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
1388 type(hamiltonian_mxll_t), intent(inout) :: hm
1389 type(namespace_t), intent(in) :: namespace
1390 type(grid_t), intent(in) :: gr
1391 type(states_mxll_t), intent(inout) :: st
1392 type(propagator_mxll_t), intent(inout) :: tr
1393 real(real64), intent(in) :: time
1394 real(real64), intent(in) :: dt
1395 real(real64), intent(in) :: time_delay
1396 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1397 type(batch_t), intent(inout) :: ff_rs_stateb
1398
1399 integer :: ii, ff_dim
1400 complex(real64), allocatable :: rs_state_constant(:,:), ff_rs_state_constant(:,:)
1401 type(batch_t) :: ff_rs_state_plane_wavesb, ff_rs_constantb, rs_state_constantb
1402
1404
1405 call profiling_in('PML_PROP_STAGE_2_BATCH')
1406
1407 if (tr%bc_plane_waves .and. hm%plane_waves_apply) then
1408 hm%cpml_hamiltonian = .true.
1409 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1410 hm%cpml_hamiltonian = .false.
1411 call plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1412
1413 call ff_rs_stateb%copy_to(ff_rs_state_plane_wavesb)
1414 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_state_plane_wavesb, rs_trans_forward)
1415
1416 if (ff_rs_stateb%status() == batch_device_packed) then
1417 ! use the map of points stored on the GPU in this case
1418 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%buff_map, &
1419 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1420 else
1421 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%points_map, &
1422 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1423 end if
1424
1425 call ff_rs_state_plane_wavesb%end()
1426
1427 else if (tr%bc_constant .and. hm%spatial_constant_apply) then
1428 hm%cpml_hamiltonian = .true.
1429 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1430 hm%cpml_hamiltonian = .false.
1431
1432 call ff_rs_stateb%copy_to(ff_rs_constantb)
1433 ff_dim = ff_rs_stateb%nst_linear
1434 safe_allocate(rs_state_constant(1:gr%np, 1:st%dim))
1435 ! copy the value to the full mesh to be able to use batches
1436 ! this is in principle unneeded, but otherwise we could not use batches...
1437 do ii = 1, st%dim
1438 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1439 end do
1440 call ff_rs_stateb%copy_to(rs_state_constantb)
1441 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, st%dim)
1442
1443 call transform_rs_state_batch(hm, gr, st, rs_state_constantb, ff_rs_constantb, rs_trans_forward)
1444 if (ff_rs_stateb%status() == batch_device_packed) then
1445 ! use the map of points stored on the GPU in this case
1446 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%buff_constant_points_map, &
1447 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1448 else
1449 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%constant_points_map, &
1450 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1451 end if
1452
1453 call ff_rs_constantb%end()
1454 call rs_state_constantb%end()
1455
1456 safe_deallocate_a(rs_state_constant)
1457 safe_deallocate_a(ff_rs_state_constant)
1458 end if
1459
1460 call profiling_out('PML_PROP_STAGE_2_BATCH')
1461
1463 end subroutine pml_propagation_stage_2_batch
1464
1465 ! ---------------------------------------------------------
1466 subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
1467 type(hamiltonian_mxll_t), intent(inout) :: hm
1468 type(grid_t), intent(in) :: gr
1469 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1470
1471
1473
1474 call profiling_in('CPML_CONV_FUNCTION_UPDATE')
1475
1476 call cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1477
1478 call profiling_out('CPML_CONV_FUNCTION_UPDATE')
1479
1481 end subroutine cpml_conv_function_update
1482
1483 ! ---------------------------------------------------------
1484 subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
1485 type(hamiltonian_mxll_t), intent(inout) :: hm
1486 type(grid_t), intent(in) :: gr
1487 type(batch_t), intent(inout) :: ff_rs_state_pmlb
1488
1489 integer :: ip, ip_in, np_part, rs_sign
1490 complex(real64) :: pml_a, pml_b, pml_g, grad
1491 integer :: pml_dir, field_dir, ifield, idir
1492 integer, parameter :: field_dirs(3, 2) = reshape([2, 3, 1, 3, 1, 2], [3, 2])
1493 logical :: with_medium
1494 type(batch_t) :: gradb(gr%der%dim)
1495 type(accel_kernel_t), save :: ker_pml
1496 integer :: wgsize
1497
1499
1500 call profiling_in('CPML_CONV_UPDATE_VIA_RS')
1501
1502 assert(hm%dim == 3 .or. hm%dim == 6)
1503
1504 np_part = gr%np_part
1505 rs_sign = hm%rs_sign
1506
1507 call zderivatives_batch_grad(gr%der, ff_rs_state_pmlb, gradb)
1508
1509 with_medium = hm%dim == 6
1510
1511 do pml_dir = 1, hm%st%dim
1512 select case (gradb(pml_dir)%status())
1513 case (batch_not_packed)
1514 do ip_in=1, hm%bc%pml%points_number
1515 ip = hm%bc%pml%points_map(ip_in)
1516 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1517 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1518 do ifield = 1, 2
1519 field_dir = field_dirs(pml_dir, ifield)
1520 grad = gradb(pml_dir)%zff_linear(ip, field_dir)
1521 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1522 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1523 if (with_medium) then
1524 grad = gradb(pml_dir)%zff_linear(ip, field_dir+3)
1525 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1526 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1527 end if
1528 end do
1529 end do
1530 case (batch_packed)
1531 do ip_in=1, hm%bc%pml%points_number
1532 ip = hm%bc%pml%points_map(ip_in)
1533 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1534 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1535 do ifield = 1, 2
1536 field_dir = field_dirs(pml_dir, ifield)
1537 grad = gradb(pml_dir)%zff_pack(field_dir, ip)
1538 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1539 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1540 if (with_medium) then
1541 grad = gradb(pml_dir)%zff_pack(field_dir+3, ip)
1542 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1543 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1544 end if
1545 end do
1546 end do
1547 case (batch_device_packed)
1548 call accel_kernel_start_call(ker_pml, 'pml.cl', 'pml_update_conv')
1549
1550 if (with_medium) then
1551 call accel_set_kernel_arg(ker_pml, 0, 1_int32)
1552 else
1553 call accel_set_kernel_arg(ker_pml, 0, 0_int32)
1554 end if
1555 call accel_set_kernel_arg(ker_pml, 1, hm%bc%pml%points_number)
1556 call accel_set_kernel_arg(ker_pml, 2, pml_dir-1)
1557 call accel_set_kernel_arg(ker_pml, 3, hm%bc%pml%buff_map)
1558 call accel_set_kernel_arg(ker_pml, 4, gradb(pml_dir)%ff_device)
1559 call accel_set_kernel_arg(ker_pml, 5, log2(int(gradb(pml_dir)%pack_size(1), int32)))
1560 call accel_set_kernel_arg(ker_pml, 6, hm%bc%pml%buff_a)
1561 call accel_set_kernel_arg(ker_pml, 7, hm%bc%pml%buff_b)
1562 call accel_set_kernel_arg(ker_pml, 8, hm%bc%pml%buff_conv_plus)
1563 call accel_set_kernel_arg(ker_pml, 9, hm%bc%pml%buff_conv_minus)
1564
1565 wgsize = accel_max_workgroup_size()
1566 call accel_kernel_run(ker_pml, (/ accel_padded_size(hm%bc%pml%points_number) /), (/ wgsize /))
1567 end select
1568 end do
1569
1570 do idir = 1, gr%der%dim
1571 call gradb(idir)%end()
1572 end do
1573
1574 if (accel_is_enabled()) then
1575 call accel_finish()
1576 end if
1578 call profiling_out('CPML_CONV_UPDATE_VIA_RS')
1579
1582
1583 ! ---------------------------------------------------------
1584 subroutine td_function_mxll_init(st, namespace, hm)
1585 type(states_mxll_t), intent(inout) :: st
1586 type(namespace_t), intent(in) :: namespace
1587 type(hamiltonian_mxll_t), intent(inout) :: hm
1588
1589 type(block_t) :: blk
1590 integer :: il, nlines, idim, ncols, ierr
1591 real(real64) :: e_field(st%dim), b_field(st%dim)
1592 character(len=1024) :: mxf_expression
1593
1594 push_sub(td_function_mxll_init)
1595
1596 call profiling_in('TD_FUNCTION_MXLL_INIT')
1597
1598 !%Variable UserDefinedConstantSpatialMaxwellField
1599 !%Type block
1600 !%Section Maxwell
1601 !%Description
1602 !% Define parameters of spatially constant field.
1603 !%
1604 !% Example:
1605 !%
1606 !% <tt>%UserDefinedConstantSpatialMaxwellFields
1607 !% <br>&nbsp;&nbsp; plane_wave_parser | E_x | E_y | E_z | B_x | B_y | B_z | "tdf_function"
1608 !% <br>%</tt>
1609 !%
1610 !% This block defines three components of E field, three components of B field, and reference to
1611 !% the TD function.
1612 !%
1613 !%End
1614
1615 if (parse_block(namespace, 'UserDefinedConstantSpatialMaxwellField', blk) == 0) then
1616 st%rs_state_const_external = .true.
1617 nlines = parse_block_n(blk)
1618 safe_allocate(st%rs_state_const_td_function(1:nlines))
1619 safe_allocate(st%rs_state_const_amp(1:st%dim, 1:nlines))
1620 ! read all lines
1621 do il = 1, nlines
1622 e_field = m_zero
1623 b_field = m_zero
1624 ! Check that number of columns is five or six.
1625 ncols = parse_block_cols(blk, il - 1)
1626 if (ncols /= 7) then
1627 message(1) = 'Each line in the UserDefinedConstantSpatialMaxwellField block must have'
1628 message(2) = 'seven columns.'
1629 call messages_fatal(2, namespace=namespace)
1630 end if
1631 do idim = 1, st%dim
1632 call parse_block_float( blk, il - 1, idim-1, e_field(idim))
1633 end do
1634 do idim = 1, st%dim
1635 call parse_block_float( blk, il - 1, idim+2, b_field(idim))
1636 end do
1637 call parse_block_string( blk, il - 1, 6, mxf_expression)
1638 call build_rs_vector(e_field, b_field, st%rs_sign, st%rs_state_const_amp(:,il))
1639 call tdf_read(st%rs_state_const_td_function(il), namespace, trim(mxf_expression), ierr)
1640 end do
1641 end if
1642 call parse_block_end(blk)
1643
1644 !%Variable PropagateSpatialMaxwellField
1645 !%Type logical
1646 !%Default yes
1647 !%Section Maxwell::TD Propagation
1648 !%Description
1649 !% Allow for numerical propagation of Maxwells equations of spatially constant field.
1650 !% If set to no, do only analytic evaluation of the field inside the box.
1651 !%End
1652
1653 call parse_variable(namespace, 'PropagateSpatialMaxwellField', .true., hm%spatial_constant_propagate)
1654
1655 call profiling_out('TD_FUNCTION_MXLL_INIT')
1656
1657 pop_sub(td_function_mxll_init)
1658 end subroutine td_function_mxll_init
1659
1660 ! ---------------------------------------------------------
1661 subroutine spatial_constant_calculation(constant_calc, st, gr, hm, time, dt, delay, rs_state, set_initial_state)
1662 logical, intent(in) :: constant_calc
1663 type(states_mxll_t), intent(inout) :: st
1664 type(grid_t), intent(in) :: gr
1665 type(hamiltonian_mxll_t), intent(in) :: hm
1666 real(real64), intent(in) :: time
1667 real(real64), intent(in) :: dt
1668 real(real64), intent(in) :: delay
1669 complex(real64), intent(inout) :: rs_state(:,:)
1670 logical, optional, intent(in) :: set_initial_state
1671
1672 integer :: ip, ic, icn
1673 real(real64) :: tf_old, tf_new
1674 logical :: set_initial_state_
1675
1678 call profiling_in('SPATIAL_CONSTANT_CALCULATION')
1679
1680 set_initial_state_ = .false.
1681 if (present(set_initial_state)) set_initial_state_ = set_initial_state
1682
1683 if (hm%spatial_constant_apply) then
1684 if (constant_calc) then
1685 icn = size(st%rs_state_const_td_function(:))
1686 st%rs_state_const(:) = m_z0
1687 do ic = 1, icn
1688 tf_old = tdf(st%rs_state_const_td_function(ic), time-delay-dt)
1689 tf_new = tdf(st%rs_state_const_td_function(ic), time-delay)
1690 do ip = 1, gr%np
1691 if (set_initial_state_ .or. (.not. hm%spatial_constant_propagate)) then
1692 rs_state(ip,:) = st%rs_state_const_amp(:,ic) * tf_new
1693 else
1694 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const_amp(:,ic) * (tf_new - tf_old)
1695 end if
1696 end do
1697 st%rs_state_const(:) = st%rs_state_const(:) + st%rs_state_const_amp(:, ic)
1698 end do
1699 st%rs_state_const(:) = st%rs_state_const(:) * tf_new
1700 end if
1701 end if
1702
1703 call profiling_out('SPATIAL_CONSTANT_CALCULATION')
1704
1706 end subroutine spatial_constant_calculation
1707
1708 ! ---------------------------------------------------------
1709 subroutine constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
1710 logical, intent(in) :: constant_calc
1711 type(bc_mxll_t), intent(inout) :: bc
1712 type(states_mxll_t), intent(in) :: st
1713 type(hamiltonian_mxll_t), intent(in) :: hm
1714 complex(real64), intent(inout) :: rs_state(:,:)
1715
1716 integer :: ip_in, ip
1717
1719 call profiling_in('CONSTANT_BOUNDARIES_CALC')
1720
1721 if (hm%spatial_constant_apply) then
1722 if (constant_calc) then
1723 do ip_in = 1, bc%constant_points_number
1724 ip = bc%constant_points_map(ip_in)
1725 rs_state(ip,:) = st%rs_state_const(:)
1726 bc%constant_rs_state(ip_in,:) = st%rs_state_const(:)
1727 end do
1728 end if
1729 end if
1730
1731 call profiling_out('CONSTANT_BOUNDARIES_CALC')
1732
1734 end subroutine constant_boundaries_calculation
1735
1736 ! ---------------------------------------------------------
1737 subroutine mirror_pec_boundaries_calculation(bc, st, rs_state)
1738 type(bc_mxll_t), intent(in) :: bc
1739 type(states_mxll_t), intent(in) :: st
1740 complex(real64), intent(inout) :: rs_state(:,:)
1741
1742 integer :: ip, ip_in, idim
1743 real(real64) :: e_field(st%dim), b_field(st%dim)
1744
1746
1747 do idim = 1, 3
1748 if (bc%bc_type(idim) == mxll_bc_mirror_pec) then
1749 do ip_in = 1, bc%mirror_points_number(idim)
1750 ip = bc%mirror_points_map(ip_in, idim)
1751 e_field(:) = m_zero
1752 call get_magnetic_field_vector(rs_state(ip,:), st%rs_sign, b_field(:), st%mu(ip))
1753 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1754 end do
1755 end if
1756 end do
1757
1760
1761 ! ---------------------------------------------------------
1762 subroutine mirror_pmc_boundaries_calculation(bc, st, rs_state)
1763 type(bc_mxll_t), intent(in) :: bc
1764 type(states_mxll_t), intent(in) :: st
1765 complex(real64), intent(inout) :: rs_state(:,:)
1766
1767 integer :: ip, ip_in, idim
1768 real(real64) :: e_field(st%dim), b_field(st%dim)
1769
1771
1772 do idim = 1, 3
1773 if (bc%bc_type(idim) == mxll_bc_mirror_pmc) then
1774 do ip_in = 1, bc%mirror_points_number(idim)
1775 ip = bc%mirror_points_map(ip_in,idim)
1776 b_field(:) = m_zero
1777 call get_electric_field_vector(rs_state(ip,:), e_field(:), st%ep(ip))
1778 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1779 end do
1780 end if
1781 end do
1782
1785
1786 ! ---------------------------------------------------------
1787 subroutine plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
1788 type(hamiltonian_mxll_t), intent(in) :: hm
1789 type(states_mxll_t), intent(in) :: st
1790 class(mesh_t), intent(in) :: mesh
1791 real(real64), intent(in) :: time
1792 real(real64), intent(in) :: time_delay
1793 complex(real64), intent(inout) :: rs_state(:,:)
1794
1795 integer :: ip, ip_in, wn
1796 real(real64) :: x_prop(mesh%box%dim), rr, vv(mesh%box%dim), k_vector(mesh%box%dim)
1797 real(real64) :: k_vector_abs, nn
1798 complex(real64) :: e0(mesh%box%dim)
1799 real(real64) :: e_field(mesh%box%dim), b_field(mesh%box%dim)
1800 complex(real64) :: rs_state_add(mesh%box%dim)
1801 complex(real64) :: mx_func
1804
1805 call profiling_in('PLANE_WAVES_BOUNDARIES_C')
1806
1807 if (hm%plane_waves_apply) then
1808 do wn = 1, hm%bc%plane_wave%number
1809 k_vector(:) = hm%bc%plane_wave%k_vector(1:mesh%box%dim, wn)
1810 k_vector_abs = norm2(k_vector(1:mesh%box%dim))
1811 vv(:) = hm%bc%plane_wave%v_vector(1:mesh%box%dim, wn)
1812 e0(:) = hm%bc%plane_wave%e_field(1:mesh%box%dim, wn)
1813 do ip_in = 1, hm%bc%plane_wave%points_number
1814 ip = hm%bc%plane_wave%points_map(ip_in)
1815 if (wn == 1) rs_state(ip,:) = m_z0
1816 nn = sqrt(st%ep(ip)/p_ep*st%mu(ip)/p_mu)
1817 x_prop(1:mesh%box%dim) = mesh%x(ip,1:mesh%box%dim) - vv(1:mesh%box%dim) * (time - time_delay)
1818 rr = norm2(x_prop(1:mesh%box%dim))
1819 if (hm%bc%plane_wave%modus(wn) == option__maxwellincidentwaves__plane_wave_mx_function) then
1820 ! Temporary variable assigned due to macro line length
1821 mx_func = mxf(hm%bc%plane_wave%mx_function(wn), x_prop(1:mesh%box%dim))
1822 e_field(1:mesh%box%dim) = real(e0(1:mesh%box%dim) * mx_func, real64)
1823 end if
1824 b_field(1:3) = dcross_product(k_vector, e_field) / p_c / k_vector_abs
1825 call build_rs_vector(e_field, b_field, st%rs_sign, rs_state_add, st%ep(ip), st%mu(ip))
1826 rs_state(ip, :) = rs_state(ip, :) + rs_state_add(:)
1827 end do
1828 end do
1829 else
1830 do ip_in = 1, hm%bc%plane_wave%points_number
1831 ip = hm%bc%plane_wave%points_map(ip_in)
1832 rs_state(ip,:) = m_z0
1833 end do
1834 end if
1835
1836 call profiling_out('PLANE_WAVES_BOUNDARIES_C')
1837
1840
1841 ! ---------------------------------------------------------
1842 subroutine plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
1843 type(hamiltonian_mxll_t), intent(inout) :: hm
1844 type(propagator_mxll_t), intent(inout) :: tr
1845 type(namespace_t), intent(in) :: namespace
1846 type(states_mxll_t), intent(inout) :: st
1847 type(grid_t), intent(in) :: gr
1848 real(real64), intent(in) :: time
1849 real(real64), intent(in) :: dt
1850 real(real64), intent(in) :: time_delay
1851
1852 type(batch_t) :: ff_rs_stateb
1853 integer :: ff_dim
1854
1856
1857 call profiling_in('PLANE_WAVES_PROPAGATION')
1858
1859 ff_dim = hm%dim
1860 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
1861 if (st%pack_states) call ff_rs_stateb%do_pack(copy=.false.)
1862
1863 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_forward)
1864
1865 ! Time evolution of RS plane waves state without any coupling with H(inter_time)
1866 call hamiltonian_mxll_update(hm, time=time)
1867 hm%cpml_hamiltonian = .false.
1868 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
1869
1870 call transform_rs_state_batch(hm, gr, st, st%rs_state_plane_wavesb, ff_rs_stateb, rs_trans_backward)
1871 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1872 call plane_waves_boundaries_calculation(hm, st, gr, time+dt, time_delay, st%rs_state_plane_waves)
1873 call mxll_set_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1874 call ff_rs_stateb%end()
1875
1876 call profiling_out('PLANE_WAVES_PROPAGATION')
1878 end subroutine plane_waves_propagation
1879
1880 ! ---------------------------------------------------------
1881 subroutine plane_waves_in_box_calculation(bc, time, space, mesh, der, st, rs_state)
1882 type(bc_mxll_t), intent(inout) :: bc
1883 real(real64), intent(in) :: time
1884 class(space_t), intent(in) :: space
1885 class(mesh_t), intent(in) :: mesh
1886 type(derivatives_t), intent(in) :: der
1887 type(states_mxll_t), intent(in) :: st
1888 complex(real64), intent(inout) :: rs_state(:,:)
1889
1890 real(real64) :: e_field_total(mesh%np,st%dim), b_field_total(mesh%np,st%dim)
1891 complex(real64) :: rs_state_add(mesh%np,st%dim)
1892
1894
1895 call profiling_in('PLANE_WAVES_IN_BOX_CALCULATION')
1896
1897 call external_waves_eval(bc%plane_wave, time, mesh, e_field, e_field_total)
1898 call external_waves_eval(bc%plane_wave, time, mesh, b_field, b_field_total, der=der)
1899
1900 call build_rs_state(e_field_total, b_field_total, st%rs_sign, &
1901 rs_state_add(1:mesh%np,:), mesh, st%ep, st%mu)
1902 rs_state(1:mesh%np,:) = rs_state(1:mesh%np,:) + rs_state_add(1:mesh%np,:)
1903
1904 call profiling_out('PLANE_WAVES_IN_BOX_CALCULATION')
1905
1907 end subroutine plane_waves_in_box_calculation
1908
1909 ! ---------------------------------------------------------
1910 subroutine mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
1911 type(propagator_mxll_t), intent(inout) :: tr
1912 type(states_mxll_t), intent(inout) :: st
1913 type(hamiltonian_mxll_t),intent(inout) :: hm
1914 type(grid_t), intent(in) :: gr
1915 type(namespace_t), intent(in) :: namespace
1916 real(real64), intent(in) :: time
1917 real(real64), intent(in) :: dt
1918 type(batch_t), intent(inout) :: rs_stateb
1919
1920 complex(real64), allocatable :: rs_state(:, :)
1921
1922 push_sub(mxll_apply_boundaries)
1923
1924 safe_allocate(rs_state(gr%np, st%dim))
1925
1926 if (tr%bc_constant) then
1927 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1928 ! Propagation dt with H(inter_time+inter_dt) for constant boundaries
1929 if (st%rs_state_const_external) then
1930 call spatial_constant_calculation(tr%bc_constant, st, gr, hm, time, dt, m_zero, rs_state)
1931 end if
1932 call constant_boundaries_calculation(tr%bc_constant, hm%bc, hm, st, rs_state)
1933 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1934 end if
1936 ! PEC mirror boundaries
1937 if (any(hm%bc%bc_type == mxll_bc_mirror_pec)) then
1938 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1939 call mirror_pec_boundaries_calculation(hm%bc, st, rs_state)
1940 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1941 end if
1942
1943 ! PMC mirror boundaries
1944 if (any(hm%bc%bc_type == mxll_bc_mirror_pmc)) then
1945 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1946 call mirror_pmc_boundaries_calculation(hm%bc, st, rs_state)
1947 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1948 end if
1949
1950 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask)) then
1951 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1952 ! Apply mask absorbing boundaries
1953 call mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, m_zero, rs_state)
1954 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1955 end if
1956
1957 if (tr%bc_plane_waves) then
1958 call mxll_get_batch(rs_stateb, rs_state, gr%np, st%dim)
1959 ! calculate plane waves boundaries at t
1960 call plane_waves_boundaries_calculation(hm, st, gr, time, m_zero, rs_state)
1961 call mxll_set_batch(rs_stateb, rs_state, gr%np, st%dim)
1962 end if
1963
1964 safe_deallocate_a(rs_state)
1965
1966 pop_sub(mxll_apply_boundaries)
1967 end subroutine mxll_apply_boundaries
1968
1969end module propagator_mxll_oct_m
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:152
scale a batch by a constant or vector
Definition: batch_ops.F90:160
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:199
batchified version of
Definition: batch_ops.F90:168
double sin(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:2144
subroutine, public accel_finish()
Definition: accel.F90:1296
pure logical function, public accel_is_enabled()
Definition: accel.F90:400
integer pure function, public accel_max_workgroup_size()
Definition: accel.F90:1472
This module implements batches of mesh functions.
Definition: batch.F90:133
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:276
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:276
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:1774
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:1469
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:276
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
subroutine, public batch_split_complex(np, xx, yy, zz)
extract the real and imaginary parts of a complex batch
Definition: batch_ops.F90:586
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
Definition: batch_ops.F90:240
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
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, metric, 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:118
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_four
Definition: global.F90:191
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
real(real64), parameter, public m_fourth
Definition: global.F90:196
real(real64), parameter, public p_mu
Definition: global.F90:228
real(real64), parameter, public p_ep
Definition: global.F90:227
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_epsilon
Definition: global.F90:203
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:223
real(real64), parameter, public m_one
Definition: global.F90:188
real(real64), parameter, public m_three
Definition: global.F90:190
This module implements the underlying real-space grid.
Definition: grid.F90:117
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:122
Definition: io.F90:114
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1833
integer, parameter, public mxll_bc_mirror_pmc
integer, parameter, public mxll_bc_periodic
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:116
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:632
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:930
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
this module contains the output system
Definition: output.F90:115
Some general things and nomenclature:
Definition: par_vec.F90:171
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:502
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
subroutine, public mirror_pec_boundaries_calculation(bc, st, rs_state)
subroutine td_function_mxll_init(st, namespace, hm)
subroutine, public mxll_propagate_expgauss2(hm, namespace, gr, space, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=2.
subroutine, public energy_mxll_calc_batch(gr, st, hm, energy_mxll, rs_fieldb, rs_field_plane_wavesb)
subroutine, public calculate_matter_longitudinal_field(gr_mxll, st_mxll, hm_mxll, gr_elec, st_elec, hm_elec, rs_state_matter)
subroutine plane_waves_propagation(hm, tr, namespace, st, gr, time, dt, time_delay)
subroutine derivatives_boundary_mask(bc, mesh, hm)
subroutine cpml_conv_function_update(hm, gr, ff_rs_state_pmlb)
subroutine transform_rs_state_batch(hm, gr, st, rs_stateb, ff_rs_stateb, sign)
subroutine, public mxll_propagate_leapfrog(hm, namespace, gr, space, st, tr, time, dt, counter)
subroutine, public mxll_propagate_expgauss1(hm, namespace, gr, space, st, tr, time, dt)
Exponential propagation scheme with Gauss collocation points, s=1.
subroutine, public constant_boundaries_calculation(constant_calc, bc, hm, st, rs_state)
subroutine, public mask_absorbing_boundaries(namespace, gr, hm, st, tr, time, dt, time_delay, rs_state)
subroutine, public calculate_vector_potential(namespace, poisson_solver, gr, st, field, vector_potential)
subroutine pml_propagation_stage_2_batch(hm, namespace, gr, st, tr, time, dt, time_delay, ff_rs_state_pmlb, ff_rs_stateb)
subroutine, public mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
subroutine, public plane_waves_boundaries_calculation(hm, st, mesh, time, time_delay, rs_state)
subroutine, public get_vector_pot_and_transverse_field(namespace, trans_calc_method, gr_mxll, hm_mxll, st_mxll, tr_mxll, hm, st, poisson_solver, helmholtz, time, field, transverse_field, vector_potential)
subroutine, public spatial_constant_calculation(constant_calc, st, gr, hm, time, dt, delay, rs_state, set_initial_state)
subroutine, public set_medium_rs_state(st, gr, hm)
subroutine cpml_conv_function_update_via_riemann_silberstein(hm, gr, ff_rs_state_pmlb)
subroutine maxwell_mask(hm, rs_state)
integer, parameter mxwll_etrs_const
subroutine, public transform_rs_densities(hm, mesh, rs_charge_density, rs_current_density, ff_density, sign)
subroutine, public plane_waves_in_box_calculation(bc, time, space, mesh, der, st, rs_state)
subroutine, public energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
integer, parameter, public rs_trans_backward
subroutine, public mirror_pmc_boundaries_calculation(bc, st, rs_state)
subroutine, public mxll_apply_boundaries(tr, st, hm, gr, namespace, time, dt, rs_stateb)
subroutine pml_propagation_stage_1_batch(hm, gr, st, tr, ff_rs_stateb, ff_rs_state_pmlb)
subroutine, public propagator_mxll_init(gr, namespace, st, hm, tr)
subroutine transform_rs_densities_to_6x6_rs_densities_backward(mesh, rs_density_6x6, rs_charge_density, rs_current_density)
subroutine transform_rs_densities_to_6x6_rs_densities_forward(mesh, rs_charge_density, rs_current_density, rs_density_6x6)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:137
integer, parameter, public b_field
Definition: quantity.F90:146
integer, parameter, public vector_potential
Definition: quantity.F90:146
integer, parameter, public e_field
Definition: quantity.F90:146
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:218
Class defining batches of mesh functions.
Definition: batch.F90:159
class representing derivatives
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
int true(void)