101 logical :: bc_add_ab_region = .false.
102 logical :: bc_zero = .false.
103 logical :: bc_constant = .false.
104 logical :: bc_mirror_pec = .false.
105 logical :: bc_mirror_pmc = .false.
106 logical :: bc_plane_waves = .false.
107 logical :: bc_medium = .false.
108 type(exponential_t) :: te
109 logical :: plane_waves_in_box
110 integer :: tr_etrs_approx
113 integer,
public,
parameter :: &
114 RS_TRANS_FORWARD = 1, &
117 integer,
parameter :: &
118 MXWLL_ETRS_FULL = 0, &
125 type(grid_t),
intent(in) :: gr
126 type(namespace_t),
intent(in) :: namespace
127 type(states_mxll_t),
intent(inout) :: st
128 type(hamiltonian_mxll_t),
intent(inout) :: hm
129 type(propagator_mxll_t),
intent(inout) :: tr
138 select case (hm%bc%bc_type(idim))
143 tr%bc_constant = .
true.
144 tr%bc_add_ab_region = .
true.
145 hm%bc_constant = .
true.
146 hm%bc_add_ab_region = .
true.
148 tr%bc_mirror_pec = .
true.
149 hm%bc_mirror_pec = .
true.
151 tr%bc_mirror_pmc = .
true.
152 hm%bc_mirror_pmc = .
true.
154 tr%bc_plane_waves = .
true.
155 tr%bc_add_ab_region = .
true.
156 hm%plane_waves = .
true.
157 hm%bc_plane_waves = .
true.
158 hm%bc_add_ab_region = .
true.
164 safe_allocate(st%rs_state_const(1:st%dim))
165 st%rs_state_const =
m_z0
179 call parse_variable(namespace,
'MaxwellTDETRSApprox', mxwll_etrs_full, tr%tr_etrs_approx)
189 call parse_variable(namespace,
'MaxwellPlaneWavesInBox', .false., tr%plane_waves_in_box)
190 if (tr%plane_waves_in_box .and. .not. hm%bc%do_plane_waves)
then
205 subroutine mxll_propagation_step(hm, namespace, gr, space, st, tr, rs_stateb, ff_rs_inhom_t1, ff_rs_inhom_t2, time, dt)
207 type(namespace_t),
intent(in) :: namespace
209 class(
space_t),
intent(in) :: space
213 complex(real64),
contiguous,
intent(in) :: ff_rs_inhom_t1(:,:)
214 complex(real64),
contiguous,
intent(in) :: ff_rs_inhom_t2(:,:)
215 real(real64),
intent(in) :: time
216 real(real64),
intent(in) :: dt
218 integer :: ii, ff_dim, idim, istate, inter_steps
219 real(real64) :: inter_dt, inter_time
223 type(
batch_t) :: ff_rs_stateb, ff_rs_state_pmlb
224 type(
batch_t) :: ff_rs_inhom_1b, ff_rs_inhom_2b, ff_rs_inhom_meanb
225 complex(real64),
allocatable :: rs_state(:, :)
232 if (hm%ma_mx_coupling_apply)
then
233 message(1) =
"Maxwell-matter coupling not implemented yet"
236 safe_allocate(rs_state(gr%np, st%dim))
238 if (tr%plane_waves_in_box)
then
242 safe_deallocate_a(rs_state)
248 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__cpml)
then
254 if (pml_check .and. .not. hm%bc%pml%parameters_initialized) &
261 inter_dt =
m_one / inter_steps * dt
263 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
264 if (st%pack_states)
call ff_rs_stateb%do_pack(copy=.false.)
267 call ff_rs_stateb%copy_to(ff_rs_state_pmlb)
271 if ((hm%ma_mx_coupling_apply .or. hm%current_density_ext_flag .or. hm%current_density_from_medium) .and. &
273 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
274 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
275 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
277 do istate = 1, hm%dim
278 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t1(:, istate))
279 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
284 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_1b)
285 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
288 hm%cpml_hamiltonian = .false.
289 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt)
293 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
295 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, inter_dt*
m_half)
298 call ff_rs_inhom_meanb%copy_data_to(gr%np, ff_rs_inhom_2b)
300 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt*
m_half)
303 call ff_rs_inhom_2b%end()
304 call ff_rs_inhom_meanb%end()
307 do ii = 1, inter_steps
310 inter_time = time + inter_dt * (ii-1)
321 hm%cpml_hamiltonian = pml_check
322 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
323 hm%cpml_hamiltonian = .false.
330 if ((hm%ma_mx_coupling_apply) .or. hm%current_density_ext_flag .or. hm%current_density_from_medium)
then
331 if (tr%tr_etrs_approx == mxwll_etrs_full)
then
332 call ff_rs_stateb%copy_to(ff_rs_inhom_1b)
333 call ff_rs_stateb%copy_to(ff_rs_inhom_2b)
334 call ff_rs_stateb%copy_to(ff_rs_inhom_meanb)
337 do istate = 1, hm%dim
338 call batch_set_state(ff_rs_inhom_meanb, istate, gr%np, ff_rs_inhom_t2(:, istate))
339 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
343 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
344 call batch_axpy(gr%np, ii / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_2b)
345 call batch_axpy(gr%np, (ii-1) / real(inter_steps, real64) , ff_rs_inhom_meanb, ff_rs_inhom_1b)
347 hm%cpml_hamiltonian = .false.
348 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt)
353 do istate = 1, hm%dim
354 call batch_set_state(ff_rs_inhom_1b, istate, gr%np, ff_rs_inhom_t1(:, istate))
355 call batch_set_state(ff_rs_inhom_2b, istate, gr%np, ff_rs_inhom_t2(:, istate))
358 call ff_rs_inhom_1b%copy_data_to(gr%np, ff_rs_inhom_2b)
360 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_1b, inter_dt/
m_two)
361 call tr%te%apply_batch(namespace, gr, hm, ff_rs_inhom_2b, -inter_dt/
m_two)
367 call ff_rs_inhom_1b%end()
368 call ff_rs_inhom_2b%end()
369 call ff_rs_inhom_meanb%end()
383 if (tr%bc_constant)
then
386 if (st%rs_state_const_external)
then
408 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask))
then
414 if (tr%bc_plane_waves)
then
423 if (tr%tr_etrs_approx == option__maxwelltdetrsapprox__const_steps)
then
424 call ff_rs_inhom_1b%end()
427 call ff_rs_stateb%end()
430 call ff_rs_state_pmlb%end()
433 safe_deallocate_a(rs_state)
443 type(namespace_t),
intent(in) :: namespace
444 type(
grid_t),
intent(inout) :: gr
447 real(real64),
intent(in) :: time
448 real(real64),
intent(in) :: dt
449 integer,
intent(in) :: counter
455 call st%rs_stateb%copy_to(rs_state_tmpb)
463 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
474 if (counter == 0)
then
476 call batch_xpay(gr%np, st%rs_stateb, dt, rs_state_tmpb)
483 call st%rs_stateb%copy_data_to(gr%np, st%rs_state_prevb)
485 call rs_state_tmpb%copy_data_to(gr%np, st%rs_stateb)
488 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
492 call rs_state_tmpb%end()
513 type(namespace_t),
intent(in) :: namespace
514 type(
grid_t),
intent(inout) :: gr
517 real(real64),
intent(in) :: time
518 real(real64),
intent(in) :: dt
524 call st%rs_stateb%copy_to(rs_state_tmpb)
533 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
539 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
542 if (hm%current_density_ext_flag .or. hm%current_density_from_medium)
then
544 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
549 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
551 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
553 call rs_state_tmpb%end()
556 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
585 type(namespace_t),
intent(in) :: namespace
586 type(
grid_t),
intent(inout) :: gr
589 real(real64),
intent(in) :: time
590 real(real64),
intent(in) :: dt
596 call st%rs_stateb%copy_to(rs_state_tmpb)
605 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
611 call hm%zapply(namespace, gr, st%rs_stateb, rs_state_tmpb)
614 if (hm%current_density_ext_flag .or. hm%current_density_from_medium)
then
616 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
620 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
625 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 1)
627 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
628 if (hm%current_density_ext_flag .or. hm%current_density_from_medium)
then
631 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t1, gr%np, st%dim)
635 call mxll_set_batch(st%inhomogeneousb, st%rs_current_density_t2, gr%np, st%dim)
640 call tr%te%apply_phi_batch(namespace, gr, hm, rs_state_tmpb, dt, 2)
642 call batch_axpy(gr%np, dt, rs_state_tmpb, st%rs_stateb)
646 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__cpml))
then
650 call rs_state_tmpb%end()
658 type(
grid_t),
intent(in) :: gr
661 integer :: ip, ip_in, il, idim
665 assert(
allocated(st%ep) .and.
allocated(st%mu))
669 if (hm%calc_medium_box)
then
670 do il = 1,
size(hm%medium_boxes)
671 assert(.not. hm%medium_boxes(il)%has_mapping)
672 do ip = 1, hm%medium_boxes(il)%points_number
673 if (abs(hm%medium_boxes(il)%c(ip)) <=
m_epsilon) cycle
674 st%ep(ip) = hm%medium_boxes(il)%ep(ip)
675 st%mu(ip) = hm%medium_boxes(il)%mu(ip)
682 do ip_in = 1, hm%bc%medium(idim)%points_number
683 ip = hm%bc%medium(idim)%points_map(ip_in)
684 st%ep(ip) = hm%bc%medium(idim)%ep(ip_in)
685 st%mu(ip) = hm%bc%medium(idim)%mu(ip_in)
698 type(
grid_t),
intent(in) :: gr
700 type(
batch_t),
intent(inout) :: rs_stateb
701 type(
batch_t),
intent(inout) :: ff_rs_stateb
702 integer,
intent(in) :: sign
704 complex(real64),
allocatable :: rs_state(:,:)
705 complex(real64),
allocatable :: rs_state_tmp(:,:)
715 safe_allocate(rs_state(1:gr%np, 1:st%dim))
718 if (sign == rs_trans_forward)
then
727 safe_allocate(rs_state_tmp(1:gr%np, 1:st%dim))
731 rs_state(1:np, ii) =
m_half * (rs_state(1:np, ii) + conjg(rs_state_tmp(1:np, ii)))
734 safe_deallocate_a(rs_state_tmp)
737 if (sign == rs_trans_forward)
then
738 call rs_stateb%copy_data_to(gr%np, ff_rs_stateb)
740 call ff_rs_stateb%copy_data_to(gr%np, rs_stateb)
743 safe_deallocate_a(rs_state)
754 class(
mesh_t),
intent(in) :: mesh
755 complex(real64),
intent(inout) :: rs_current_density(:,:)
756 complex(real64),
intent(inout) :: ff_density(:,:)
757 integer,
intent(in) :: sign
761 assert(
size(rs_current_density, dim=2) == 3)
768 if (sign == rs_trans_forward)
then
774 if (sign == rs_trans_forward)
then
775 ff_density(1:mesh%np, 1:3) = rs_current_density(1:mesh%np, 1:3)
777 rs_current_density(1:mesh%np, 1:3) = ff_density(1:mesh%np, 1:3)
789 class(
mesh_t),
intent(in) :: mesh
790 complex(real64),
intent(in) :: rs_current_density(:,:)
791 complex(real64),
intent(inout) :: rs_density_6x6(:,:)
795 assert(
size(rs_current_density, dim=2) == 3)
796 assert(
size(rs_density_6x6, dim=2) == 6)
800 rs_density_6x6(1:mesh%np, ii) = rs_current_density(1:mesh%np, ii)
801 rs_density_6x6(1:mesh%np, ii+3) = rs_current_density(1:mesh%np, ii)
808 class(
mesh_t),
intent(in) :: mesh
809 complex(real64),
intent(in) :: rs_density_6x6(:,:)
810 complex(real64),
intent(inout) :: rs_current_density(:,:)
814 assert(
size(rs_current_density, dim=2) == 3)
815 assert(
size(rs_density_6x6, dim=2) == 6)
819 rs_current_density(1:mesh%np, ii) =
m_half * &
820 real(rs_density_6x6(1:mesh%np, ii) + rs_density_6x6(1:mesh%np, ii+3), real64)
827 type(
grid_t),
intent(in) :: gr_mxll
830 type(
grid_t),
intent(in) :: gr_elec
832 complex(real64),
intent(inout) :: rs_state_matter(:,:)
834 complex(real64),
allocatable :: tmp_pot_mx_gr(:,:), tmp_grad_mx_gr(:,:)
836 safe_allocate(tmp_pot_mx_gr(1:gr_mxll%np_part,1))
837 safe_allocate(tmp_grad_mx_gr(1:gr_mxll%np,1:gr_mxll%box%dim))
842 tmp_pot_mx_gr(:,:) =
m_zero
843 tmp_grad_mx_gr(:,:) =
m_zero
844 call zderivatives_grad(gr_mxll%der, tmp_pot_mx_gr(:,1), tmp_grad_mx_gr(:,:), set_bc = .false.)
845 tmp_grad_mx_gr = - tmp_grad_mx_gr
848 call build_rs_state(real(tmp_grad_mx_gr(1:gr_mxll%np,:)), aimag(tmp_grad_mx_gr(1:gr_mxll%np,:)), st_mxll%rs_sign, &
849 rs_state_matter(1:gr_mxll%np,:), gr_mxll, st_mxll%ep(1:gr_mxll%np), st_mxll%mu(1:gr_mxll%np), &
852 safe_deallocate_a(tmp_pot_mx_gr)
853 safe_deallocate_a(tmp_grad_mx_gr)
860 poisson_solver, helmholtz, field, transverse_field, vector_potential)
861 type(namespace_t),
intent(in) :: namespace
862 type(
grid_t),
intent(in) :: gr_mxll
867 type(
poisson_t),
intent(in) :: poisson_solver
869 complex(real64),
intent(inout) :: field(:,:)
870 complex(real64),
intent(inout) :: transverse_field(:,:)
871 real(real64),
intent(inout) :: vector_potential(:,:)
874 complex(real64),
allocatable :: rs_state_plane_waves(:, :)
878 transverse_field =
m_z0
883 if (hm_mxll%ma_mx_coupling)
then
888 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply)
then
889 safe_allocate(rs_state_plane_waves(1:gr_mxll%np, 1:st_mxll%dim))
890 call mxll_get_batch(st_mxll%rs_state_plane_wavesb, rs_state_plane_waves, gr_mxll%np, st_mxll%dim)
894 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply)
then
895 transverse_field(1:np,:) = field(1:np,:) - rs_state_plane_waves(1:np,:)
897 transverse_field(1:np,:) = field(1:np,:)
900 call helmholtz%get_trans_field(namespace, transverse_field, total_field=field)
902 if (tr_mxll%bc_plane_waves .and. hm_mxll%plane_waves_apply)
then
903 transverse_field(1:np,:) = transverse_field(1:np,:) + rs_state_plane_waves(1:np,:)
904 safe_deallocate_a(rs_state_plane_waves)
909 transverse_field(1:np,:) = field
920 type(namespace_t),
intent(in) :: namespace
922 type(
grid_t),
intent(in) :: gr
924 complex(real64),
intent(in) :: field(:,:)
925 real(real64),
contiguous,
intent(inout) :: vector_potential(:,:)
928 real(real64),
allocatable :: dtmp(:,:)
930 safe_allocate(dtmp(1:gr%np_part,1:3))
935 dtmp = vector_potential
938 call dpoisson_solve(poisson_solver, namespace, dtmp(:,idim), vector_potential(:,idim), .
true.)
942 safe_deallocate_a(dtmp)
947 subroutine energy_mxll_calc(gr, st, hm, energy_mxll, rs_field, rs_field_plane_waves)
948 type(
grid_t),
intent(in) :: gr
952 complex(real64),
intent(in) :: rs_field(:,:)
953 complex(real64),
optional,
intent(in) :: rs_field_plane_waves(:,:)
955 real(real64),
allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:), energy_density_plane_waves(:)
961 safe_allocate(energy_density(1:gr%np))
962 safe_allocate(e_energy_density(1:gr%np))
963 safe_allocate(b_energy_density(1:gr%np))
964 if (
present(rs_field_plane_waves) .and. hm%plane_waves)
then
965 safe_allocate(energy_density_plane_waves(1:gr%np))
969 b_energy_density, hm%plane_waves, rs_field_plane_waves, energy_density_plane_waves)
970 energy_mxll%energy =
dmf_integrate(gr, energy_density, mask=st%inner_points_mask)
971 energy_mxll%e_energy =
dmf_integrate(gr, e_energy_density, mask=st%inner_points_mask)
972 energy_mxll%b_energy =
dmf_integrate(gr, b_energy_density, mask=st%inner_points_mask)
973 if (
present(rs_field_plane_waves) .and. hm%plane_waves)
then
974 energy_mxll%energy_plane_waves =
dmf_integrate(gr, energy_density_plane_waves, mask=st%inner_points_mask)
976 energy_mxll%energy_plane_waves =
m_zero
979 energy_mxll%boundaries =
dmf_integrate(gr, energy_density, mask=st%boundary_points_mask)
981 safe_deallocate_a(energy_density)
982 safe_deallocate_a(e_energy_density)
983 safe_deallocate_a(b_energy_density)
984 if (
present(rs_field_plane_waves) .and. hm%plane_waves)
then
985 safe_deallocate_a(energy_density_plane_waves)
995 type(
grid_t),
intent(in) :: gr
999 type(
batch_t),
intent(in) :: rs_fieldb
1000 type(
batch_t),
intent(in) :: rs_field_plane_wavesb
1002 type(
batch_t) :: e_fieldb, b_fieldb, e_field_innerb, b_field_innerb, rs_field_plane_waves_innerb
1003 real(real64) :: tmp(1:st%dim)
1004 complex(real64) :: ztmp(1:st%dim)
1011 if (st%pack_states)
then
1012 call e_fieldb%do_pack(copy=.false.)
1014 call e_fieldb%copy_to(b_fieldb)
1015 call e_fieldb%copy_to(e_field_innerb)
1016 call e_fieldb%copy_to(b_field_innerb)
1024 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, e_fieldb, e_field_innerb)
1025 call batch_copy_with_map(st%inner_points_number, st%buff_inner_points_map, b_fieldb, b_field_innerb)
1027 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, e_fieldb, e_field_innerb)
1028 call batch_copy_with_map(st%inner_points_number, st%inner_points_map, b_fieldb, b_field_innerb)
1031 energy_mxll%e_energy = sum(tmp)
1033 energy_mxll%b_energy = sum(tmp)
1034 energy_mxll%energy = energy_mxll%e_energy + energy_mxll%b_energy
1037 energy_mxll%boundaries = sum(tmp)
1039 energy_mxll%boundaries = energy_mxll%boundaries + sum(tmp)
1040 energy_mxll%boundaries = energy_mxll%boundaries - energy_mxll%energy
1042 if (hm%plane_waves)
then
1043 call rs_field_plane_wavesb%copy_to(rs_field_plane_waves_innerb)
1047 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1050 rs_field_plane_wavesb, rs_field_plane_waves_innerb)
1053 energy_mxll%energy_plane_waves = sum(real(tmp, real64) )
1054 call rs_field_plane_waves_innerb%end()
1056 energy_mxll%energy_plane_waves =
m_zero
1061 call e_field_innerb%end()
1062 call b_field_innerb%end()
1071 type(namespace_t),
intent(in) :: namespace
1072 type(
grid_t),
intent(in) :: gr
1076 real(real64),
intent(in) :: time
1077 real(real64),
intent(in) :: dt
1078 real(real64),
intent(in) :: time_delay
1079 complex(real64),
intent(inout) :: rs_state(:,:)
1081 integer :: ip, ip_in, idim
1082 logical :: mask_check
1087 mask_check = .false.
1090 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask)
then
1095 if (mask_check)
then
1096 if (tr%bc_plane_waves .and. hm%plane_waves_apply)
then
1098 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1099 rs_state = rs_state - st%rs_state_plane_waves
1101 rs_state = rs_state + st%rs_state_plane_waves
1102 else if (tr%bc_constant .and. hm%spatial_constant_apply)
then
1105 do ip_in=1, hm%bc%constant_points_number
1106 ip = hm%bc%constant_points_map(ip_in)
1107 rs_state(ip,:) = rs_state(ip,:) - st%rs_state_const(:)
1110 do ip_in=1, hm%bc%constant_points_number
1111 ip = hm%bc%constant_points_map(ip_in)
1112 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const(:)
1127 complex(real64),
intent(inout) :: rs_state(:,:)
1129 integer :: ip, ip_in, idim
1136 if (hm%bc%bc_ab_type(idim) == option__maxwellabsorbingboundaries__mask)
then
1137 do ip_in = 1, hm%bc%mask_points_number(idim)
1138 ip = hm%bc%mask_points_map(ip_in,idim)
1139 rs_state(ip,:) = rs_state(ip,:) * hm%bc%mask(ip_in,idim)
1152 type(
grid_t),
intent(in) :: gr
1155 type(
batch_t),
intent(in) :: ff_rs_stateb
1156 type(
batch_t),
intent(inout) :: ff_rs_state_pmlb
1159 complex(real64),
allocatable :: rs_state_constant(:,:)
1160 type(
batch_t) :: rs_state_constantb
1166 if (tr%bc_plane_waves .and. hm%plane_waves_apply)
then
1168 ff_rs_state_pmlb, rs_trans_forward)
1170 else if (tr%bc_constant .and. hm%spatial_constant_apply)
then
1175 safe_allocate(rs_state_constant(1:gr%np,1:3))
1177 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1179 call ff_rs_stateb%copy_to(rs_state_constantb)
1180 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, 3)
1183 ff_rs_state_pmlb, rs_trans_forward)
1186 call rs_state_constantb%end()
1188 safe_deallocate_a(rs_state_constant)
1191 call ff_rs_stateb%copy_data_to(gr%np, ff_rs_state_pmlb)
1202 type(namespace_t),
intent(in) :: namespace
1203 type(
grid_t),
intent(in) :: gr
1206 real(real64),
intent(in) :: time
1207 real(real64),
intent(in) :: dt
1208 real(real64),
intent(in) :: time_delay
1209 type(
batch_t),
intent(inout) :: ff_rs_state_pmlb
1210 type(
batch_t),
intent(inout) :: ff_rs_stateb
1212 integer :: ii, ff_dim
1213 complex(real64),
allocatable :: rs_state_constant(:,:), ff_rs_state_constant(:,:)
1214 type(
batch_t) :: ff_rs_state_plane_wavesb, ff_rs_constantb, rs_state_constantb
1220 if (tr%bc_plane_waves .and. hm%plane_waves_apply)
then
1221 hm%cpml_hamiltonian = .
true.
1222 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1223 hm%cpml_hamiltonian = .false.
1226 call ff_rs_stateb%copy_to(ff_rs_state_plane_wavesb)
1232 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1234 call batch_add_with_map(hm%bc%plane_wave%points_number, hm%bc%plane_wave%points_map, &
1235 ff_rs_state_pmlb, ff_rs_state_plane_wavesb, ff_rs_stateb)
1238 call ff_rs_state_plane_wavesb%end()
1240 else if (tr%bc_constant .and. hm%spatial_constant_apply)
then
1241 hm%cpml_hamiltonian = .
true.
1242 call tr%te%apply_batch(namespace, gr, hm, ff_rs_state_pmlb, dt)
1243 hm%cpml_hamiltonian = .false.
1245 call ff_rs_stateb%copy_to(ff_rs_constantb)
1246 ff_dim = ff_rs_stateb%nst_linear
1247 safe_allocate(rs_state_constant(1:gr%np, 1:st%dim))
1251 rs_state_constant(1:gr%np, ii) = st%rs_state_const(ii)
1253 call ff_rs_stateb%copy_to(rs_state_constantb)
1254 call mxll_set_batch(rs_state_constantb, rs_state_constant, gr%np, st%dim)
1259 call batch_add_with_map(hm%bc%constant_points_number, hm%bc%buff_constant_points_map, &
1260 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1263 ff_rs_state_pmlb, ff_rs_constantb, ff_rs_stateb)
1266 call ff_rs_constantb%end()
1267 call rs_state_constantb%end()
1269 safe_deallocate_a(rs_state_constant)
1270 safe_deallocate_a(ff_rs_state_constant)
1281 type(
grid_t),
intent(in) :: gr
1282 type(
batch_t),
intent(inout) :: ff_rs_state_pmlb
1299 type(
grid_t),
intent(in) :: gr
1300 type(
batch_t),
intent(inout) :: ff_rs_state_pmlb
1302 integer :: ip, ip_in, np_part, rs_sign
1303 complex(real64) :: pml_a, pml_b, pml_g, grad
1304 integer :: pml_dir, field_dir, ifield, idir
1305 integer,
parameter :: field_dirs(3, 2) = reshape([2, 3, 1, 3, 1, 2], [3, 2])
1306 logical :: with_medium
1307 type(
batch_t) :: gradb(gr%der%dim)
1309 integer :: bsize, gsize
1315 assert(hm%dim == 3 .or. hm%dim == 6)
1317 np_part = gr%np_part
1318 rs_sign = hm%rs_sign
1322 with_medium = hm%dim == 6
1324 do pml_dir = 1, hm%st%dim
1325 select case (gradb(pml_dir)%status())
1327 do ip_in=1, hm%bc%pml%points_number
1328 ip = hm%bc%pml%points_map(ip_in)
1329 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1330 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1332 field_dir = field_dirs(pml_dir, ifield)
1333 grad = gradb(pml_dir)%zff_linear(ip, field_dir)
1334 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1335 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1336 if (with_medium)
then
1337 grad = gradb(pml_dir)%zff_linear(ip, field_dir+3)
1338 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1339 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1344 do ip_in=1, hm%bc%pml%points_number
1345 ip = hm%bc%pml%points_map(ip_in)
1346 pml_a = hm%bc%pml%a(ip_in,pml_dir)
1347 pml_b = hm%bc%pml%b(ip_in,pml_dir)
1349 field_dir = field_dirs(pml_dir, ifield)
1350 grad = gradb(pml_dir)%zff_pack(field_dir, ip)
1351 pml_g = hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir)
1352 hm%bc%pml%conv_plus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1353 if (with_medium)
then
1354 grad = gradb(pml_dir)%zff_pack(field_dir+3, ip)
1355 pml_g = hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir)
1356 hm%bc%pml%conv_minus(ip_in, pml_dir, field_dir) = pml_a * grad + pml_b * pml_g
1363 if (with_medium)
then
1386 do idir = 1, gr%der%dim
1387 call gradb(idir)%end()
1402 type(namespace_t),
intent(in) :: namespace
1406 integer :: il, nlines, idim, ncols, ierr
1407 real(real64) :: e_field(st%dim), b_field(st%dim)
1408 character(len=1024) :: mxf_expression
1431 if (
parse_block(namespace,
'UserDefinedConstantSpatialMaxwellField', blk) == 0)
then
1432 st%rs_state_const_external = .
true.
1434 safe_allocate(st%rs_state_const_td_function(1:nlines))
1435 safe_allocate(st%rs_state_const_amp(1:st%dim, 1:nlines))
1442 if (ncols /= 7)
then
1443 message(1) =
'Each line in the UserDefinedConstantSpatialMaxwellField block must have'
1454 call build_rs_vector(e_field, b_field, st%rs_sign, st%rs_state_const_amp(:,il))
1455 call tdf_read(st%rs_state_const_td_function(il), namespace, trim(mxf_expression), ierr)
1469 call parse_variable(namespace,
'PropagateSpatialMaxwellField', .
true., hm%spatial_constant_propagate)
1478 logical,
intent(in) :: constant_calc
1480 type(
grid_t),
intent(in) :: gr
1482 real(real64),
intent(in) :: time
1483 real(real64),
intent(in) :: dt
1484 real(real64),
intent(in) :: delay
1485 complex(real64),
intent(inout) :: rs_state(:,:)
1486 logical,
optional,
intent(in) :: set_initial_state
1488 integer :: ip, ic, icn
1489 real(real64) :: tf_old, tf_new
1490 logical :: set_initial_state_
1496 set_initial_state_ = .false.
1497 if (
present(set_initial_state)) set_initial_state_ = set_initial_state
1499 if (hm%spatial_constant_apply)
then
1500 if (constant_calc)
then
1501 icn =
size(st%rs_state_const_td_function(:))
1502 st%rs_state_const(:) =
m_z0
1504 tf_old =
tdf(st%rs_state_const_td_function(ic), time-delay-dt)
1505 tf_new =
tdf(st%rs_state_const_td_function(ic), time-delay)
1507 if (set_initial_state_ .or. (.not. hm%spatial_constant_propagate))
then
1508 rs_state(ip,:) = st%rs_state_const_amp(:,ic) * tf_new
1510 rs_state(ip,:) = rs_state(ip,:) + st%rs_state_const_amp(:,ic) * (tf_new - tf_old)
1513 st%rs_state_const(:) = st%rs_state_const(:) + st%rs_state_const_amp(:, ic)
1515 st%rs_state_const(:) = st%rs_state_const(:) * tf_new
1526 logical,
intent(in) :: constant_calc
1530 complex(real64),
intent(inout) :: rs_state(:,:)
1532 integer :: ip_in, ip
1537 if (hm%spatial_constant_apply)
then
1538 if (constant_calc)
then
1539 do ip_in = 1, bc%constant_points_number
1540 ip = bc%constant_points_map(ip_in)
1541 rs_state(ip,:) = st%rs_state_const(:)
1542 bc%constant_rs_state(ip_in,:) = st%rs_state_const(:)
1556 complex(real64),
intent(inout) :: rs_state(:,:)
1558 integer :: ip, ip_in, idim
1559 real(real64) :: e_field(st%dim), b_field(st%dim)
1565 do ip_in = 1, bc%mirror_points_number(idim)
1566 ip = bc%mirror_points_map(ip_in, idim)
1569 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1581 complex(real64),
intent(inout) :: rs_state(:,:)
1583 integer :: ip, ip_in, idim
1584 real(real64) :: e_field(st%dim), b_field(st%dim)
1590 do ip_in = 1, bc%mirror_points_number(idim)
1591 ip = bc%mirror_points_map(ip_in,idim)
1594 call build_rs_vector(e_field(:), b_field(:), st%rs_sign, rs_state(ip,:), st%ep(ip), st%mu(ip))
1606 class(
mesh_t),
intent(in) :: mesh
1607 real(real64),
intent(in) :: time
1608 real(real64),
intent(in) :: time_delay
1609 complex(real64),
intent(inout) :: rs_state(:,:)
1611 integer :: ip, ip_in, wn
1612 real(real64) :: x_prop(mesh%box%dim), rr, vv(mesh%box%dim), k_vector(mesh%box%dim)
1613 real(real64) :: k_vector_abs, nn
1614 complex(real64) :: e0(mesh%box%dim)
1615 real(real64) :: e_field(mesh%box%dim), b_field(mesh%box%dim)
1616 complex(real64) :: rs_state_add(mesh%box%dim)
1617 complex(real64) :: mx_func
1623 if (hm%plane_waves_apply)
then
1624 do wn = 1, hm%bc%plane_wave%number
1625 k_vector(:) = hm%bc%plane_wave%k_vector(1:mesh%box%dim, wn)
1626 k_vector_abs = norm2(k_vector(1:mesh%box%dim))
1627 vv(:) = hm%bc%plane_wave%v_vector(1:mesh%box%dim, wn)
1628 e0(:) = hm%bc%plane_wave%e_field(1:mesh%box%dim, wn)
1629 do ip_in = 1, hm%bc%plane_wave%points_number
1630 ip = hm%bc%plane_wave%points_map(ip_in)
1631 if (wn == 1) rs_state(ip,:) =
m_z0
1633 x_prop(1:mesh%box%dim) = mesh%x(1:mesh%box%dim, ip) - vv(1:mesh%box%dim) * (time - time_delay)
1634 rr = norm2(x_prop(1:mesh%box%dim))
1635 if (hm%bc%plane_wave%modus(wn) == option__maxwellincidentwaves__plane_wave_mx_function)
then
1637 mx_func =
mxf(hm%bc%plane_wave%mx_function(wn), x_prop(1:mesh%box%dim))
1638 e_field(1:mesh%box%dim) = real(e0(1:mesh%box%dim) * mx_func, real64)
1641 call build_rs_vector(e_field, b_field, st%rs_sign, rs_state_add, st%ep(ip), st%mu(ip))
1642 rs_state(ip, :) = rs_state(ip, :) + rs_state_add(:)
1646 do ip_in = 1, hm%bc%plane_wave%points_number
1647 ip = hm%bc%plane_wave%points_map(ip_in)
1661 type(namespace_t),
intent(in) :: namespace
1663 type(
grid_t),
intent(in) :: gr
1664 real(real64),
intent(in) :: time
1665 real(real64),
intent(in) :: dt
1666 real(real64),
intent(in) :: time_delay
1676 call zbatch_init(ff_rs_stateb, 1, 1, hm%dim, gr%np_part)
1677 if (st%pack_states)
call ff_rs_stateb%do_pack(copy=.false.)
1683 hm%cpml_hamiltonian = .false.
1684 call tr%te%apply_batch(namespace, gr, hm, ff_rs_stateb, dt)
1687 call mxll_get_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1689 call mxll_set_batch(st%rs_state_plane_wavesb, st%rs_state_plane_waves, gr%np, st%dim)
1690 call ff_rs_stateb%end()
1699 real(real64),
intent(in) :: time
1700 class(
mesh_t),
intent(in) :: mesh
1703 complex(real64),
intent(inout) :: rs_state(:,:)
1705 real(real64) :: e_field_total(mesh%np,st%dim), b_field_total(mesh%np,st%dim)
1706 complex(real64) :: rs_state_add(mesh%np,st%dim)
1716 rs_state_add(1:mesh%np,:), mesh, st%ep, st%mu)
1717 rs_state(1:mesh%np,:) = rs_state(1:mesh%np,:) + rs_state_add(1:mesh%np,:)
1729 type(
grid_t),
intent(in) :: gr
1730 type(namespace_t),
intent(in) :: namespace
1731 real(real64),
intent(in) :: time
1732 real(real64),
intent(in) :: dt
1733 type(
batch_t),
intent(inout) :: rs_stateb
1735 complex(real64),
allocatable :: rs_state(:, :)
1739 safe_allocate(rs_state(gr%np, st%dim))
1741 if (tr%bc_constant)
then
1744 if (st%rs_state_const_external)
then
1765 if (any(hm%bc%bc_ab_type == option__maxwellabsorbingboundaries__mask))
then
1772 if (tr%bc_plane_waves)
then
1779 safe_deallocate_a(rs_state)
batchified version of the BLAS axpy routine:
scale a batch by a constant or vector
There are several ways how to call batch_set_state and batch_get_state:
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
subroutine, public accel_finish()
pure logical function, public accel_is_enabled()
integer pure function, public accel_max_block_size()
This module implements batches of mesh functions.
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
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
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
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
This module implements common operations on batches of mesh functions.
subroutine, public batch_split_complex(np, xx, yy, zz)
extract the real and imaginary parts of a complex batch
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
This module implements a calculator for the density and defines related functions.
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 ...
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_fourth
real(real64), parameter, public p_mu
real(real64), parameter, public p_ep
complex(real64), parameter, public m_z0
complex(real64), parameter, public m_zi
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
real(real64), parameter, public m_one
real(real64), parameter, public m_three
This module implements the underlying real-space grid.
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.
This module is intended to contain "only mathematical" functions and procedures.
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
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.
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
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
this module contains the output system
Some general things and nomenclature:
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
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...
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.
Class defining batches of mesh functions.
class representing derivatives
Description of the grid, containing information on derivatives, stencil, and symmetries.
Describes mesh distribution to nodes.