Octopus
maxwell_boundary_op.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 R. Jestaedt, H. Appel, F. Bonafe, M. Oliveira, N. Tancogne-Dejean
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
25 use debug_oct_m
28 use global_oct_m
29 use grid_oct_m
30 use index_oct_m
31 use io_oct_m
33 use math_oct_m
35 use math_oct_m
38 use mesh_oct_m
40 use mpi_oct_m
42 use parser_oct_m
45 use types_oct_m
46 use unit_oct_m
49 use space_oct_m
51
52 implicit none
53
54 private
55 public :: &
58 bc_mxll_t, &
63
64 type pml_t
65 real(real64) :: width
66 integer :: points_number
67 integer, allocatable :: points_map(:)
68 integer, allocatable :: points_map_inv(:)
69 real(real64) :: power
70 real(real64) :: refl_error
71 real(real64), allocatable :: kappa(:,:)
72 real(real64), allocatable :: sigma_e(:,:)
73 real(real64), allocatable :: sigma_m(:,:)
74 real(real64), allocatable :: a(:,:)
75 real(real64), allocatable :: b(:,:)
76 real(real64), allocatable :: c(:,:)
77 real(real64), allocatable :: mask(:)
78 complex(real64), allocatable :: aux_ep(:,:,:)
79 complex(real64), allocatable :: aux_mu(:,:,:)
80 complex(real64), allocatable :: conv_plus(:,:,:)
81 complex(real64), allocatable :: conv_minus(:,:,:)
82 complex(real64), allocatable :: conv_plus_old(:,:,:)
83 complex(real64), allocatable :: conv_minus_old(:,:,:)
84 logical :: parameters_initialized = .false.
85 ! GPU buffers
86 type(accel_mem_t) :: buff_a, buff_b, buff_c, buff_conv_plus, buff_conv_minus, buff_map, buff_conv_plus_old
87 end type pml_t
88
89 type bc_mxll_t
90 integer :: bc_type(3)
91 integer :: bc_ab_type(3)
92 real(real64) :: bc_bounds(2, 3)
93 logical :: ab_user_def
94 real(real64), allocatable :: ab_ufn(:)
95
96 real(real64) :: ab_width
97 real(real64) :: mask_width
98 integer :: mask_points_number(3)
99 integer, allocatable :: mask_points_map(:,:)
100 real(real64), allocatable :: mask(:,:)
101
102 type(pml_t) :: pml
103 type(single_medium_box_t) :: medium(3)
104
105 integer :: constant_points_number
106 integer, allocatable :: constant_points_map(:)
107 complex(real64), allocatable :: constant_rs_state(:,:)
108 type(accel_mem_t) :: buff_constant_points_map
109
110 integer :: mirror_points_number(3)
111 integer, allocatable :: mirror_points_map(:,:)
112
113 logical :: do_plane_waves = .false. !! look here afterwards
114 type(external_waves_t) :: plane_wave
115 logical :: plane_waves_dims(1:3) = .false.
116
117 real(real64) :: zero_width
118 integer :: zero_points_number(3)
119 integer, allocatable :: zero_points_map(:,:)
120 real(real64), allocatable :: zero(:,:)
121 end type bc_mxll_t
122
123 integer, public, parameter :: &
124 MXLL_BC_ZERO = 0, &
125 mxll_bc_constant = 1, &
126 mxll_bc_mirror_pec = 2, &
127 mxll_bc_mirror_pmc = 3, &
130
131 integer, parameter :: &
132 MXLL_PLANE_WAVES_NEGATIVE_SIDE = -1, &
134
135 integer, public, parameter :: &
136 MXLL_AB_NOT_ABSORBING = 0, &
137 mxll_ab_mask = 1, &
138 mxll_ab_cpml = 2, &
140
141contains
142
143 ! ---------------------------------------------------------
144 subroutine bc_mxll_init(bc, namespace, space, gr, st)
145 type(bc_mxll_t), intent(inout) :: bc
146 type(namespace_t), intent(in) :: namespace
147 class(space_t), intent(in) :: space
148 type(grid_t), intent(in) :: gr
149 type(states_mxll_t), intent(inout) :: st
150
151 integer :: idim, nlines, icol, ncols, ab_shape_dim
152 real(real64) :: bounds(2, space%dim), ab_bounds(2, space%dim)
153 type(block_t) :: blk
154 character(len=1024) :: string
155 character(len=50) :: ab_type_str
156 character(len=1), dimension(3), parameter :: dims = ["x", "y", "z"]
157 logical :: plane_waves_check, ab_mask_check, ab_pml_check, plane_waves_set
158 logical :: constant_check, zero_check
159 real(real64) :: ep_factor, mu_factor, sigma_e_factor, sigma_m_factor
161 push_sub(bc_mxll_init)
163 call profiling_in('BC_MXLL_INIT')
165 plane_waves_set = .false.
166 bc%bc_type(:) = mxll_bc_zero ! default boundary condition is zero
167 bc%medium(:)%points_number = 0
168 bc%medium(:)%bdry_number = 0
170 !%Variable MaxwellBoundaryConditions
171 !%Type block
172 !%Section Maxwell
173 !%Description
174 !% Defines boundary conditions for the electromagnetic field propagation.
175 !%
176 !% Example:
177 !%
178 !% <tt>%MaxwellBoundaryConditions
179 !% <br>&nbsp;&nbsp; zero | mirror_pec | constant
180 !% <br>%</tt>
181 !%
182 !%
183 !%Option zero 0
184 !% Boundaries are not touched by the Maxwell code - they are set by the normal boundary conditions.
185 !% This is zero boundary conditions for non-periodic systems and periodic boundary conditions if
186 !% PeriodicDimensions is set.
187 !%Option constant 1
188 !% Boundaries are set to a constant.
189 !%Option mirror_pec 2
190 !% Perfect electric conductor.
191 !%Option mirror_pmc 3
192 !% Perfect magnetic conductor.
193 !%Option plane_waves 4
194 !% Boundaries feed in plane waves.
195 !%Option medium 6
196 !% Boundaries as linear medium (not yet implemented).
197 !%End
198 if (parse_block(namespace, 'MaxwellBoundaryConditions', blk) == 0) then
199
200 call messages_print_with_emphasis(msg='Maxwell Boundary Conditions:', namespace=namespace)
201 ! find out how many lines (i.e. states) the block has
202 nlines = parse_block_n(blk)
203 if (nlines /= 1) then
204 call messages_input_error(namespace, 'MaxwellBoundaryConditions', 'should consist of one line')
205 end if
206 ncols = parse_block_cols(blk, 0)
207 if (ncols /= 3) then
208 call messages_input_error(namespace, 'MaxwellBoundaryConditions', 'should consist of three columns')
209 end if
210 do icol = 1, ncols
211 call parse_block_integer(blk, 0, icol-1, bc%bc_type(icol))
212 end do
214 end if
216 do icol = 1, 3
217 select case (bc%bc_type(icol))
218 case (mxll_bc_zero)
219 string = 'Zero'
220 case (mxll_bc_constant)
221 string = 'Constant'
222 case (mxll_bc_mirror_pec)
223 string = 'PEC Mirror'
224 case (mxll_bc_mirror_pmc)
225 string = 'PMC Mirror'
227 string = 'Plane waves'
228 case (mxll_bc_medium)
229 string = 'Medium boundary'
230 case default
231 write(message(1),'(a)') 'Unknown Maxwell boundary condition'
232 call messages_fatal(1, namespace=namespace)
233 end select
234 write(message(1),'(a,I1,a,a)') 'Maxwell boundary condition in direction ', icol, ': ', trim(string)
235 call messages_info(1, namespace=namespace)
236 if (plane_waves_set .and. .not. (parse_is_defined(namespace, 'MaxwellIncidentWaves'))) then
237 write(message(1),'(a)') 'Input: Maxwell boundary condition option is set to "plane_waves".'
238 write(message(2),'(a)') 'Input: User defined Maxwell plane waves have to be defined!'
239 call messages_fatal(2, namespace=namespace)
240 end if
241 end do
242
243 plane_waves_check = .false.
244 ab_mask_check = .false.
245 ab_pml_check = .false.
246 constant_check = .false.
247 zero_check = .false.
248
249 bc%ab_user_def = .false.
250 bc%bc_ab_type(:) = mxll_ab_not_absorbing ! default option
251
252 !%Variable MaxwellAbsorbingBoundaries
253 !%Type block
254 !%Section Maxwell
255 !%Description
256 !% Type of absorbing boundaries used for Maxwell propagation in each direction.
257 !%
258 !% Example:
259 !%
260 !% <tt>%MaxwellAbsorbingBoundaries
261 !% <br>&nbsp;&nbsp; cpml | cpml | cpml
262 !% <br>%</tt>
263 !%
264 !%Option not_absorbing 0
265 !% No absorbing boundaries.
266 !%Option mask 1
267 !% A mask equal to the wavefunctions mask is applied to the Maxwell states at the boundaries
268 !%Option cpml 2
269 !% Perfectly matched layer absorbing boundary
270 !%Option mask_zero 7
271 !% Absorbing boundary region is set to zero
272 !%End
273
274 if (parse_block(namespace, 'MaxwellAbsorbingBoundaries', blk) == 0) then
275 ! find out how many lines (i.e. states) the block has
276 nlines = parse_block_n(blk)
277 if (nlines /= 1) then
278 message(1) = 'MaxwellAbsorbingBounaries has to consist of one line!'
279 call messages_fatal(1, namespace=namespace)
280 end if
281
282 ncols = parse_block_cols(blk, 0)
283 if (ncols /= 3) then
284 message(1) = 'MaxwellAbsorbingBoundaries has to consist of three columns!'
285 call messages_fatal(1, namespace=namespace)
286 end if
287
288 do icol = 1, ncols
289 call parse_block_integer(blk, 0, icol-1, bc%bc_ab_type(icol))
290 end do
291
292 call parse_block_end(blk)
293 end if
294
295 do idim = 1, 3
296 if (bc%bc_ab_type(idim) == mxll_ab_mask) ab_mask_check = .true.
297 if (bc%bc_ab_type(idim) == mxll_ab_cpml) ab_pml_check = .true.
298 if (bc%bc_type(idim) == mxll_bc_constant) constant_check = .true.
299 if (bc%bc_type(idim) == mxll_bc_zero) zero_check = .true.
300 end do
301
302 if (ab_mask_check .or. ab_pml_check) then
303
304 call messages_print_with_emphasis(msg='Maxwell Absorbing Boundaries', namespace=namespace)
305 write(message(1),'(a)') "Please keep in mind that"
306 write(message(2),'(a)') "with larger ABWidth, comes great responsibility."
307 write(message(3),'(a)') "AbsorbingBoundaries occupy space in the simulation box,"
308 write(message(4),'(a)') "hence choose your Lsize wisely."
309 call messages_info(4, namespace=namespace)
310
311 end if
312
313 bounds(1, :) = (gr%idx%nr(2, :) - gr%idx%enlarge(:))*gr%spacing(:)
314 bounds(2, :) = gr%idx%nr(2, :) * gr%spacing(:)
315 do idim = 1, st%dim
316 select case (bc%bc_type(idim))
317
318 case (mxll_bc_zero, mxll_bc_mirror_pec, mxll_bc_mirror_pmc)
319
320 bounds(1, idim) = (gr%idx%nr(2, idim) - gr%idx%enlarge(idim))*gr%spacing(idim)
321 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
322
323 case (mxll_bc_constant)
324
325 bounds(1, idim) = (gr%idx%nr(2, idim) - 2*gr%idx%enlarge(idim))*gr%spacing(idim)
326 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
327
329
330 bounds(1, idim) = (gr%idx%nr(2, idim) - 2*gr%idx%enlarge(idim))*gr%spacing(idim)
331 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
332 plane_waves_check = .true.
333 bc%do_plane_waves = .true.
334
335 case (mxll_bc_medium)
336 call bc_mxll_medium_init(gr, namespace, bounds, idim, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
337 call maxwell_medium_points_mapping(bc, gr, bounds)
338 call bc_mxll_generate_medium(bc, space, gr, bounds, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
339
340 end select
341
342 select type (box => gr%box)
343 type is (box_sphere_t)
344 ab_shape_dim = 1
345 if (space%is_periodic()) then
346 message(1) = "Sphere box shape can only work for non-periodic systems"
347 call messages_fatal(1, namespace=namespace)
348 end if
349 type is (box_parallelepiped_t)
350 if (.not. box%axes%orthogonal) then
351 message(1) = "Maxwell propagation does not work for non-orthogonal grids."
352 call messages_fatal(1, namespace=namespace)
353 end if
354
355 ab_shape_dim = space%dim
356 ab_bounds(1, idim) = bounds(1, idim)
357 ab_bounds(2, idim) = bounds(1, idim)
358 class default
359 message(1) = "Box shape for Maxwell propagation not supported yet"
360 call messages_fatal(1, namespace=namespace)
361 end select
362
363 if (bc%bc_ab_type(idim) /= mxll_ab_not_absorbing) then
364
365 call messages_print_var_option("MaxwellAbsorbingBoundaries", bc%bc_ab_type(idim), namespace=namespace)
366
367 select case (bc%bc_ab_type(idim))
368 case (mxll_ab_mask_zero)
369 call bc_mxll_ab_bounds_init(bc, gr, namespace, ab_bounds, idim)
370 bc%zero_width = bc%ab_width
371
372 case (mxll_ab_mask)
373 call bc_mxll_ab_bounds_init(bc, gr, namespace, ab_bounds, idim)
374 bc%mask_width = bc%ab_width
375
376 case (mxll_ab_cpml)
377 call bc_mxll_pml_init(bc, gr, namespace, ab_bounds, idim)
378
379 case default
380 message(1) = "Absorbing boundary type not implemented for Maxwell propagation"
381 call messages_fatal(1, namespace=namespace)
382 end select
383
384 end if
385
386 select case (bc%bc_ab_type(idim))
388 bounds(1, idim) = ab_bounds(1, idim)
389 bounds(2, idim) = bounds(2, idim)
390 bc%bc_bounds(:, idim) = bounds(:, idim)
391 case default
392 bc%bc_bounds(:, idim) = bounds(:, idim)
393 end select
394
395 select type (box => gr%box)
396 type is (box_parallelepiped_t)
397 select case (bc%bc_ab_type(idim))
398 case (mxll_ab_cpml)
399 ab_type_str = "PML"
400 case (mxll_ab_mask)
401 ab_type_str = "Mask"
402 case (mxll_ab_mask_zero)
403 ab_type_str = "Zero"
404 case default
405 ab_type_str = ""
406 end select
407
408 if (bc%bc_ab_type(idim) == mxll_ab_cpml .or. bc%bc_ab_type(idim) == mxll_ab_mask .or. &
409 bc%bc_ab_type(idim) == mxll_ab_mask_zero) then
410 string = trim(ab_type_str)//" Absorbing Boundary"
411 write(string,'(2a, f10.3,3a)') trim(string), " in "//dims(idim)//' direction spans from: ', &
412 units_from_atomic(units_inp%length, ab_bounds(1, idim) ), ' [', &
413 trim(units_abbrev(units_inp%length)), ']'
414 write(message(1),'(a)') trim(string)
415
416 string = "to "
417 write(string,'(a,f10.3,3a)') trim(string),&
418 units_from_atomic(units_inp%length, ab_bounds(2, idim) ), ' [', &
419 trim(units_abbrev(units_inp%length)), ']'
420
421 write(message(2),'(a)') trim(string)
422 call messages_info(2, namespace=namespace)
423 end if
424
425 class default
426
427 write(message(1),'(a,es10.3,3a)') &
428 " Lower bound = ", units_from_atomic(units_inp%length, ab_bounds(1, idim) ),&
429 ' [', trim(units_abbrev(units_inp%length)), ']'
430 write(message(2),'(a,es10.3,3a)') &
431 " Upper bound = ", units_from_atomic(units_inp%length, ab_bounds(2, idim) ),&
432 ' [', trim(units_abbrev(units_inp%length)), ']'
433 call messages_info(2, namespace=namespace)
434
435 end select
436
437 end do
438
439 ! initialization of surfaces
440 call maxwell_surfaces_init(gr, st, bounds)
441
442 ! mapping of mask boundary points
443 if (ab_mask_check) then
444 call maxwell_mask_points_mapping(bc, gr, ab_bounds)
445 end if
446
447 ! mapping of pml boundary points
448 if (ab_pml_check) then
449 call maxwell_pml_points_mapping(bc, gr, ab_bounds)
450 end if
451
452 ! mapping of constant boundary points
453 if (constant_check) then
454 bounds(1, :) = gr%idx%nr(2, :) * gr%spacing(:)
455 bounds(2, :) = gr%idx%nr(2, :) * gr%spacing(:)
456 do idim = 1, st%dim
457 if (bc%bc_type(idim) == mxll_bc_constant) then
458 bounds(1, idim) = (gr%idx%nr(2, idim) - 2*gr%idx%enlarge(idim))*gr%spacing(idim)
459 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
460 end if
461 end do
462 call maxwell_constant_points_mapping(bc, gr, bounds)
463 end if
464
465 ! mapping of plane waves boundary points
466 if (plane_waves_check) then
467 bounds(1, :) = gr%idx%nr(2, :) * gr%spacing(:)
468 bounds(2, :) = gr%idx%nr(2, :) * gr%spacing(:)
469 do idim = 1, st%dim
470 if (bc%bc_type(idim) == mxll_bc_plane_waves) then
471 bounds(1, idim) = (gr%idx%nr(2, idim) - 2*gr%idx%enlarge(idim))*gr%spacing(idim)
472 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
473 end if
474 end do
475 call maxwell_plane_waves_points_mapping(bc, gr, bounds)
476 call external_waves_init(bc%plane_wave, namespace)
477 end if
478
479 ! mapping of zero points
480 if (zero_check) then
481 bounds(1, :) = gr%idx%nr(2, :) * gr%spacing(:)
482 bounds(2, :) = gr%idx%nr(2, :) * gr%spacing(:)
483 do idim = 1, st%dim
484 if (bc%bc_type(idim) == mxll_bc_zero) then
485 bounds(1, idim) = (gr%idx%nr(2, idim) - gr%idx%enlarge(idim))*gr%spacing(idim)
486 bounds(2, idim) = (gr%idx%nr(2, idim)) * gr%spacing(idim)
487 end if
488 end do
489 call maxwell_zero_points_mapping(bc, gr, bounds)
490 end if
491
492 if (ab_mask_check) then
493 call bc_mxll_generate_mask(bc, gr, ab_bounds)
494 end if
495
496 if (ab_pml_check) then
497 call bc_mxll_generate_pml(bc, space)
498 end if
499
500 !call bc_generate_zero(bc, gr, ab_bounds)
501
502 if (debug%info) call bc_mxll_write_info(bc, gr, namespace, space)
503
504 if (ab_mask_check .or. ab_pml_check) then
505 call messages_print_with_emphasis(namespace=namespace)
506 end if
507
508 call profiling_out('BC_MXLL_INIT')
509
510 pop_sub(bc_mxll_init)
511 end subroutine bc_mxll_init
512
513 ! ---------------------------------------------------------
514 subroutine bc_mxll_end(bc)
515 type(bc_mxll_t), intent(inout) :: bc
516
517 integer :: idim
518
519 push_sub(bc_mxll_end)
520
521 safe_deallocate_a(bc%ab_ufn)
522
523 safe_deallocate_a(bc%mask_points_map)
524 safe_deallocate_a(bc%mask)
525
526 call pml_end(bc%pml)
527 do idim = 1, 3
528 call single_medium_box_end(bc%medium(idim))
529 end do
530
531 safe_deallocate_a(bc%constant_points_map)
532 safe_deallocate_a(bc%constant_rs_state)
533 if (accel_is_enabled()) then
534 call accel_free_buffer(bc%buff_constant_points_map)
535 end if
536
537 safe_deallocate_a(bc%mirror_points_map)
538
539 call external_waves_end(bc%plane_wave)
540
541 safe_deallocate_a(bc%zero_points_map)
542 safe_deallocate_a(bc%zero)
543
544 pop_sub(bc_mxll_end)
545 end subroutine bc_mxll_end
546
547 ! ---------------------------------------------------------
548 subroutine pml_end(pml)
549 type(pml_t), intent(inout) :: pml
550
551 push_sub(pml_end)
552
553 safe_deallocate_a(pml%points_map)
554 safe_deallocate_a(pml%points_map_inv)
555 safe_deallocate_a(pml%kappa)
556 safe_deallocate_a(pml%sigma_e)
557 safe_deallocate_a(pml%sigma_m)
558 safe_deallocate_a(pml%a)
559 safe_deallocate_a(pml%b)
560 safe_deallocate_a(pml%c)
561 safe_deallocate_a(pml%mask)
562 safe_deallocate_a(pml%aux_ep)
563 safe_deallocate_a(pml%aux_mu)
564 safe_deallocate_a(pml%conv_plus)
565 safe_deallocate_a(pml%conv_minus)
566 safe_deallocate_a(pml%conv_plus_old)
567 safe_deallocate_a(pml%conv_minus_old)
568 if (accel_is_enabled()) then
569 call accel_free_buffer(pml%buff_map)
570 call accel_free_buffer(pml%buff_a)
571 call accel_free_buffer(pml%buff_b)
572 call accel_free_buffer(pml%buff_c)
573 call accel_free_buffer(pml%buff_conv_plus)
574 call accel_free_buffer(pml%buff_conv_minus)
575 call accel_free_buffer(pml%buff_conv_plus_old)
576 end if
577
578
579 pop_sub(pml_end)
580 end subroutine pml_end
581
582
583
584 ! ---------------------------------------------------------
585 subroutine bc_mxll_medium_init(gr, namespace, bounds, idim, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
586 type(grid_t), intent(in) :: gr
587 type(namespace_t), intent(in) :: namespace
588 real(real64), intent(inout) :: bounds(:,:)
589 integer, intent(in) :: idim
590 real(real64), intent(out) :: ep_factor
591 real(real64), intent(out) :: mu_factor
592 real(real64), intent(out) :: sigma_e_factor
593 real(real64), intent(out) :: sigma_m_factor
594
595 real(real64) :: width
596
597 push_sub(bc_mxll_medium_init)
598
599 call profiling_in('BC_MXLL_MEDIUM_INIT')
600
601 !%Variable MediumWidth
602 !%Type float
603 !%Default 0.0 a.u.
604 !%Section Maxwell::Boundaries
605 !%Description
606 !% Width of the boundary region with medium
607 !%End
608 call parse_variable(namespace, 'MediumWidth', m_zero, width, units_inp%length)
609 bounds(1,idim) = ( gr%idx%nr(2, idim) - gr%idx%enlarge(idim) ) * gr%spacing(idim)
610 bounds(1,idim) = bounds(1,idim) - width
611 bounds(2,idim) = ( gr%idx%nr(2, idim) ) * gr%spacing(idim)
612
613 !%Variable MediumEpsilonFactor
614 !%Type float
615 !%Default 1.0.
616 !%Section Maxwell::Boundaries
617 !%Description
618 !% Linear medium electric susceptibility.
619 !%End
620 call parse_variable(namespace, 'MediumEpsilonFactor', m_one, ep_factor, unit_one)
621
622 !%Variable MediumMuFactor
623 !%Type float
624 !%Default 1.0
625 !%Section Maxwell::Boundaries
626 !%Description
627 !% Linear medium magnetic susceptibility.
628 !%End
629 call parse_variable(namespace, 'MediumMuFactor', m_one, mu_factor, unit_one)
630
631 !%Variable MediumElectricSigma
632 !%Type float
633 !%Default 0.
634 !%Section Maxwell::Boundaries
635 !%Description
636 !% Electric conductivity of the linear medium.
637 !%End
638
639 call parse_variable(namespace, 'MediumElectricSigma', m_zero, sigma_e_factor, unit_one)
640 !%Variable MediumMagneticSigma
641 !%Type float
642 !%Default 0.
643 !%Section Maxwell::Boundaries
644 !%Description
645 !% Magnetic conductivity of the linear medium.
646 !%End
647 call parse_variable(namespace, 'MediumMagneticSigma', m_zero, sigma_m_factor, unit_one)
648
649 call profiling_out('BC_MXLL_MEDIUM_INIT')
650
651 pop_sub(bc_mxll_medium_init)
652 end subroutine bc_mxll_medium_init
653
654 ! ---------------------------------------------------------
655 subroutine bc_mxll_ab_bounds_init(bc, gr, namespace, ab_bounds, idim)
656 type(bc_mxll_t), intent(inout) :: bc
657 type(grid_t), intent(in) :: gr
658 type(namespace_t), intent(in) :: namespace
659 real(real64), intent(inout) :: ab_bounds(:,:)
660 integer, intent(in) :: idim
661
662 real(real64) :: default_width
663
664 push_sub(bc_mxll_ab_bounds_init)
665
666 !%Variable MaxwellABWidth
667 !%Type float
668 !%Section Maxwell::Boundaries
669 !%Description
670 !% Width of the region used to apply the absorbing boundaries. The default value is twice
671 !% the derivative order.
672 !%End
673
674 default_width = m_two * gr%der%order * maxval(gr%spacing(1:3))
675 call parse_variable(namespace, 'MaxwellABWidth', default_width, bc%ab_width, units_inp%length)
676
677 if (bc%ab_width < default_width) then
678 bc%ab_width = default_width
679 write(message(1),'(a)') 'Absorbing boundary width has to be larger or equal than twice the derivatives order times spacing!'
680 write(message(2),'(a,es10.3)') 'Absorbing boundary width is set to: ', default_width
681 call messages_info(2, namespace=namespace)
682 end if
683
684 ab_bounds(1, idim) = ab_bounds(2, idim) - bc%ab_width
685
687 end subroutine bc_mxll_ab_bounds_init
688
689 ! ---------------------------------------------------------
690 subroutine bc_mxll_pml_init(bc, gr, namespace, ab_bounds, idim)
691 type(bc_mxll_t), intent(inout) :: bc
692 type(grid_t), intent(in) :: gr
693 type(namespace_t), intent(in) :: namespace
694 real(real64), intent(inout) :: ab_bounds(:,:)
695 integer, intent(in) :: idim
696
697 push_sub(bc_mxll_pml_init)
698
699 call bc_mxll_ab_bounds_init(bc, gr, namespace, ab_bounds, idim)
700 bc%pml%width = bc%ab_width
701
702 !%Variable MaxwellABPMLPower
703 !%Type float
704 !%Default 3.5
705 !%Section Maxwell::Boundaries
706 !%Description
707 !% Exponential of the polynomial profile for the non-physical conductivity of the PML.
708 !% Should be between 2 and 4
709 !%End
710 call parse_variable(namespace, 'MaxwellABPMLPower', 3.5_real64, bc%pml%power, unit_one)
711
712 !%Variable MaxwellABPMLReflectionError
713 !%Type float
714 !%Default 1.0e-16
715 !%Section Maxwell::Boundaries
716 !%Description
717 !% Tolerated reflection error for the PML
718 !%End
719 call parse_variable(namespace, 'MaxwellABPMLReflectionError', 1.0e-16_real64, bc%pml%refl_error, unit_one)
720
721 pop_sub(bc_mxll_pml_init)
722 end subroutine bc_mxll_pml_init
723
724 ! ---------------------------------------------------------
725 subroutine bc_mxll_write_info(bc, mesh, namespace, space)
726 type(bc_mxll_t), intent(in) :: bc
727 class(mesh_t), intent(in) :: mesh
728 type(namespace_t), intent(in) :: namespace
729 class(space_t), intent(in) :: space
730
731 integer :: err, idim, idim2
732 real(real64), allocatable :: tmp(:)
733 logical :: mask_check, pml_check, medium_check
734 character(1) :: dim_label(3)
735
736 push_sub(bc_mxll_write_info)
737
738 call profiling_in('BC_MXLL_WRITE_INFO')
739
740 mask_check = .false.
741 pml_check = .false.
742 medium_check = .false.
743
744 dim_label = (/'x', 'y', 'z'/)
745
746 do idim = 1, 3
747 if (bc%bc_ab_type(idim) == mxll_ab_mask) then
748 mask_check = .true.
749 end if
750 if (bc%bc_ab_type(idim) == mxll_ab_cpml) then
751 pml_check = .true.
752 end if
753 if (bc%bc_type(idim) == mxll_bc_medium) then
754 medium_check = .true.
755 end if
756 end do
757
758 if (mask_check) then
759 safe_allocate(tmp(1:mesh%np))
760 do idim = 1, 3
761 tmp(:) = m_zero
762 call get_mask_io_function(bc%mask, bc, tmp, idim)
763 call write_files("maxwell_mask", tmp)
764 end do
765 safe_deallocate_a(tmp)
766 else if (pml_check) then
767 safe_allocate(tmp(1:mesh%np))
768 do idim = 1, 3
769 ! sigma for electric field dim = idim
770 tmp(:) = m_one
771 call get_pml_io_function(bc%pml%sigma_e(:, idim), bc, tmp)
772 call write_files("maxwell_sigma_e-"//dim_label(idim), tmp)
773
774 ! sigma for magnetic dim = idim
775 tmp(:) = m_zero
776 call get_pml_io_function(bc%pml%sigma_m(:, 1), bc, tmp)
777 call write_files("maxwell_sigma_m-"//dim_label(idim), tmp)
778
779 ! pml_a for electric field dim = idim
780 tmp(:) = m_zero
781 call get_pml_io_function(real(bc%pml%a(:, idim), real64), bc, tmp)
782 call write_files("maxwell_sigma_pml_a_e-"//dim_label(idim), tmp)
783 end do
784 safe_deallocate_a(tmp)
785 end if
786
787 if (medium_check) then
788 safe_allocate(tmp(1:mesh%np))
789 do idim = 1, 3
790 ! medium epsilon
791 tmp(:) = p_ep
792 call get_medium_io_function(bc%medium(idim)%ep, bc, tmp, idim)
793 call write_files("maxwell_ep"//dim_label(idim), tmp)
794 ! medium mu
795 tmp(:) = p_mu
796 call get_medium_io_function(bc%medium(idim)%mu, bc, tmp, idim)
797 call write_files("maxwell_mu"//dim_label(idim), tmp)
798 ! medium epsilon
799 tmp(:) = p_c
800 call get_medium_io_function(bc%medium(idim)%c, bc, tmp, idim)
801 call write_files("maxwell_c"//dim_label(idim), tmp)
802 do idim2 = 1, 3
803 ! medium epsilon aux field dim = idim
804 tmp(:) = m_zero
805 call get_medium_io_function(bc%medium(idim)%aux_ep(:, idim2), bc, tmp, idim)
806 call write_files("maxwell_aux_ep-"//dim_label(idim)//"-"//dim_label(idim2), tmp)
807
808 ! medium mu aux field dim = idim
809 tmp(:) = m_zero
810 call get_medium_io_function(bc%medium(idim)%aux_mu(:, idim2), bc, tmp, idim)
811 call write_files("maxwell_aux_mu-"//dim_label(idim)//"-"//dim_label(idim2), tmp)
812 end do
813 end do
814
815 safe_deallocate_a(tmp)
816 end if
817
818 call profiling_out('BC_MXLL_WRITE_INFO')
819
821 contains
822
823 subroutine get_pml_io_function(pml_func, bc, io_func)
824 real(real64), intent(in) :: pml_func(:)
825 type(bc_mxll_t), intent(in) :: bc
826 real(real64), intent(inout) :: io_func(:)
827
828 integer :: ip, ip_in
829
830 do ip_in = 1, bc%pml%points_number
831 ip = bc%pml%points_map(ip_in)
832 io_func(ip) = pml_func(ip_in)
833 end do
834
835 end subroutine get_pml_io_function
836
837 subroutine get_mask_io_function(mask_func, bc, io_func, idim)
838 real(real64), intent(in) :: mask_func(:,:)
839 type(bc_mxll_t), intent(in) :: bc
840 real(real64), intent(inout) :: io_func(:)
841 integer, intent(in) :: idim
842
843 integer :: ip, ip_in
844
845 do ip_in = 1, bc%mask_points_number(idim)
846 ip = bc%mask_points_map(ip_in, idim)
847 io_func(ip) = mask_func(ip_in, idim)
848 end do
849
850 end subroutine get_mask_io_function
851
852 subroutine get_medium_io_function(medium_func, bc, io_func, idim)
853 real(real64), intent(in) :: medium_func(:)
854 type(bc_mxll_t), intent(in) :: bc
855 real(real64), intent(inout) :: io_func(:)
856 integer, intent(in) :: idim
857
858 integer :: ip, ip_in
859
860 do ip_in = 1, bc%medium(idim)%points_number
861 ip = bc%medium(idim)%points_map(ip_in)
862 io_func(ip) = medium_func(ip_in)
863 end do
864
865 end subroutine get_medium_io_function
866
867 subroutine write_files(filename, tmp)
868 character(len=*), intent(in) :: filename
869 real(real64), intent(in) :: tmp(:)
870
871 call dio_function_output(io_function_fill_how("VTK"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
872 unit_one, err)
873 call dio_function_output(io_function_fill_how("AxisX"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
874 unit_one, err)
875 call dio_function_output(io_function_fill_how("AxisY"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
876 unit_one, err)
877 call dio_function_output(io_function_fill_how("AxisZ"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
878 unit_one, err)
879 call dio_function_output(io_function_fill_how("PlaneX"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
880 unit_one, err)
881 call dio_function_output(io_function_fill_how("PlaneY"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
882 unit_one, err)
883 call dio_function_output(io_function_fill_how("PlaneZ"), "./td.general", trim(filename), namespace, space, mesh, tmp, &
884 unit_one, err)
885 end subroutine write_files
886
887 end subroutine bc_mxll_write_info
888
889 ! ---------------------------------------------------------
890 subroutine maxwell_mask_points_mapping(bc, mesh, bounds)
891 type(bc_mxll_t), intent(inout) :: bc
892 class(mesh_t), intent(in) :: mesh
893 real(real64), intent(in) :: bounds(:,:)
894
895 integer :: ip, ip_in, ip_in_max, point_info, idim
896
898
899 call profiling_in('MAXWELL_MASK_POINTS_MAPPING')
900 ip_in_max = 1
901 do idim = 1, 3
902 if (bc%bc_ab_type(idim) == mxll_ab_mask) then
903 ! allocate mask points map
904 ip_in = 0
905 do ip = 1, mesh%np
906 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
907 if ((point_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
908 ip_in = ip_in + 1
909 end if
910 end do
911 if (ip_in > ip_in_max) ip_in_max = ip_in
912 bc%mask_points_number(idim) = ip_in
913 end if
914 end do
915 safe_allocate(bc%mask(1:ip_in_max, 1:idim))
916 safe_allocate(bc%mask_points_map(1:ip_in_max, 1:idim))
917
918 do idim = 1, 3
919 if (bc%bc_ab_type(idim) == mxll_ab_mask) then
920 ! mask points mapping
921 ip_in = 0
922 do ip = 1, mesh%np
923 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
924 if ((point_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
925 ip_in = ip_in + 1
926 bc%mask_points_map(ip_in, idim) = ip
927 end if
928 end do
929 end if
930 end do
931
932 call profiling_out('MAXWELL_MASK_POINTS_MAPPING')
934 end subroutine maxwell_mask_points_mapping
935
936 ! ---------------------------------------------------------
937 subroutine maxwell_pml_points_mapping(bc, mesh, bounds)
938 type(bc_mxll_t), intent(inout) :: bc
939 class(mesh_t), intent(in) :: mesh
940 real(real64), intent(in) :: bounds(:,:)
941
942 integer :: ip, ip_in, point_info
943
945
946 call profiling_in('MXWL_PML_POINTS_MAPPING')
948 ! allocate pml points map
949 ip_in = 0
950 do ip = 1, mesh%np
951 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
952 if (point_info == 1) then
953 ip_in = ip_in + 1
954 end if
955 end do
956 bc%pml%points_number = ip_in
957 safe_allocate(bc%pml%points_map(1:ip_in))
958 safe_allocate(bc%pml%points_map_inv(1:mesh%np))
959 bc%pml%points_map_inv = 0
960 ip_in = 0
961 do ip = 1, mesh%np
962 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
963 if (point_info == 1) then
964 ip_in = ip_in + 1
965 bc%pml%points_map(ip_in) = ip
966 bc%pml%points_map_inv(ip) = ip_in
967 end if
968 end do
969
970 call profiling_out('MXWL_PML_POINTS_MAPPING')
971
973 end subroutine maxwell_pml_points_mapping
974
975 ! ---------------------------------------------------------
976 subroutine maxwell_constant_points_mapping(bc, mesh, bounds)
977 type(bc_mxll_t), intent(inout) :: bc
978 class(mesh_t), intent(in) :: mesh
979 real(real64), intent(in) :: bounds(:,:)
980
981 integer :: ip, ip_in, point_info
982
984
985 call profiling_in('MAXWELL_CONSTANT_POINTS_MAP')
986
987 ! allocate constant points map
988 ip_in = 0
989 do ip = 1, mesh%np
990 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
991 if (point_info == 1) then
992 ip_in = ip_in + 1
993 end if
994 end do
995 bc%constant_points_number = ip_in
996 safe_allocate(bc%constant_points_map(1:ip_in))
997 safe_allocate(bc%constant_rs_state(1:ip_in, 1:3))
998
999 ! zero constant mapping
1000 ip_in = 0
1001 do ip = 1, mesh%np
1002 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1003 if (point_info == 1) then
1004 ip_in = ip_in + 1
1005 bc%constant_points_map(ip_in) = ip
1006 end if
1007 end do
1008
1009 if (accel_is_enabled()) then
1010 call accel_create_buffer(bc%buff_constant_points_map, accel_mem_read_only, type_integer, bc%constant_points_number)
1011 call accel_write_buffer(bc%buff_constant_points_map, bc%constant_points_number, bc%constant_points_map)
1012 end if
1013
1014 call profiling_out('MAXWELL_CONSTANT_POINTS_MAP')
1015
1017 end subroutine maxwell_constant_points_mapping
1018
1019 ! ---------------------------------------------------------
1020 subroutine maxwell_plane_waves_points_mapping(bc, mesh, bounds)
1021 type(bc_mxll_t), intent(inout) :: bc
1022 class(mesh_t), intent(in) :: mesh
1023 real(real64), intent(in) :: bounds(:,:)
1024
1025 integer :: ip, ip_in, point_info
1026
1028
1029 call profiling_in('MXLL_PW_POINTS_MAP')
1030
1031 bc%plane_waves_dims = (bc%bc_type(1:3) == mxll_bc_plane_waves)
1033 ! allocate map
1034 ip_in = 0
1035 do ip = 1, mesh%np
1036 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1037 if (point_info == 1) then
1038 ip_in = ip_in + 1
1039 end if
1040 end do
1041 bc%plane_wave%points_number = ip_in
1042 safe_allocate(bc%plane_wave%points_map(1:ip_in))
1043
1044 ! mapping
1045 ip_in = 0
1046 do ip = 1, mesh%np
1047 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1048 if (point_info == 1) then
1049 ip_in = ip_in + 1
1050 bc%plane_wave%points_map(ip_in) = ip
1051 end if
1052 end do
1053
1054 if (accel_is_enabled()) then
1055 call accel_create_buffer(bc%plane_wave%buff_map, accel_mem_read_only, type_integer, bc%plane_wave%points_number)
1056 call accel_write_buffer(bc%plane_wave%buff_map, bc%plane_wave%points_number, bc%plane_wave%points_map)
1057 end if
1058
1059 call profiling_out('MXLL_PW_POINTS_MAP')
1060
1063
1064 ! ---------------------------------------------------------
1065 subroutine maxwell_zero_points_mapping(bc, mesh, bounds)
1066 type(bc_mxll_t), intent(inout) :: bc
1067 class(mesh_t), intent(in) :: mesh
1068 real(real64), intent(in) :: bounds(:,:)
1069
1070 integer :: ip, ip_in, ip_in_max, point_info, idim
1073
1074 call profiling_in('MXLL_ZERO_POINTS_MAPPING')
1075
1076 ip_in_max = 0
1077 do idim = 1, 3
1078 if (bc%bc_type(idim) == mxll_bc_zero) then
1079 ! allocate zero points map
1080 ip_in = 0
1081 do ip = 1, mesh%np
1082 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1083 if ((point_info == 1) .and. (abs(mesh%x(idim, ip)) >= bounds(1, idim))) then
1084 ip_in = ip_in + 1
1085 end if
1086 end do
1087 if (ip_in > ip_in_max) ip_in_max = ip_in
1088 end if
1089 end do
1090 bc%zero_points_number = ip_in
1091 safe_allocate(bc%zero(1:ip_in_max,3))
1092 safe_allocate(bc%zero_points_map(1:ip_in_max, 1:3))
1093
1094 do idim = 1, 3
1095 if (bc%bc_type(idim) == mxll_bc_zero) then
1096 ! zero points mapping
1097 ip_in = 0
1098 do ip = 1, mesh%np
1099 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1100 if ((point_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
1101 ip_in = ip_in + 1
1102 bc%zero_points_map(ip_in, idim) = ip
1103 end if
1104 end do
1105 end if
1106 end do
1107
1108 call profiling_out('MXLL_ZERO_POINTS_MAPPING')
1109
1111 end subroutine maxwell_zero_points_mapping
1112
1113 ! ---------------------------------------------------------
1114 subroutine maxwell_medium_points_mapping(bc, mesh, bounds)
1115 type(bc_mxll_t), intent(inout) :: bc
1116 class(mesh_t), intent(in) :: mesh
1117 real(real64), intent(in) :: bounds(:,:)
1118
1119 integer :: ip, ip_in, ip_in_max, ip_bd, ip_bd_max, point_info, boundary_info, idim
1120
1122
1123 call profiling_in('MXLL_MEDIUM_POINTS_MAPPING')
1124
1125 bc%medium(:)%points_number = 0
1126 bc%medium(:)%bdry_number = 0
1127
1128 ip_in_max = 0
1129 ip_bd_max = 0
1130 do idim = 1, 3
1131 if (bc%bc_type(idim) == mxll_bc_medium) then
1132 ! allocate pml points map
1133 ip_in = 0
1134 ip_bd = 0
1135 do ip = 1, mesh%np
1136 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1137 call maxwell_boundary_point_info(mesh, ip, bounds, boundary_info)
1138 if ((point_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
1139 ip_in = ip_in + 1
1140 end if
1141 if ((boundary_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
1142 ip_bd = ip_bd + 1
1143 end if
1144 end do
1145 bc%medium(idim)%points_number = ip_in
1146 bc%medium(idim)%bdry_number = ip_bd
1147 ip_in_max = max(ip_in_max, ip_in)
1148 ip_bd_max = max(ip_bd_max, ip_bd)
1149 end if
1150 end do
1151 do idim = 1, 3
1152 safe_allocate(bc%medium(idim)%points_map(1:ip_in_max))
1153 safe_allocate(bc%medium(idim)%bdry_map(1:ip_bd_max))
1154 end do
1155
1156 do idim = 1, 3
1157 if (bc%bc_type(idim) == mxll_bc_medium) then
1158 ip_in = 0
1159 ip_bd = 0
1160 do ip = 1, mesh%np
1161 call maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1162 call maxwell_boundary_point_info(mesh, ip, bounds, boundary_info)
1163 if ((point_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
1164 ip_in = ip_in + 1
1165 bc%medium(idim)%points_map(ip_in) = ip
1166 end if
1167 if ((boundary_info == 1) .and. (abs(mesh%x_t(ip, idim)) >= bounds(1, idim))) then
1168 ip_bd = ip_bd + 1
1169 bc%medium(idim)%bdry_map(ip_bd) = ip
1170 end if
1171 end do
1172 end if
1173 end do
1174
1175 call profiling_out('MXLL_MEDIUM_POINTS_MAPPING')
1176
1178 end subroutine maxwell_medium_points_mapping
1179
1180 ! ---------------------------------------------------------
1181 subroutine bc_mxll_generate_pml(bc, space)
1182 type(bc_mxll_t), intent(inout) :: bc
1183 class(space_t), intent(in) :: space
1184
1185
1186 push_sub(bc_mxll_generate_pml)
1187
1188 call profiling_in('BC_MXLL_GENERATE_PML')
1189
1190 safe_allocate(bc%pml%kappa(1:bc%pml%points_number, 1:space%dim))
1191 safe_allocate(bc%pml%sigma_e(1:bc%pml%points_number, 1:space%dim))
1192 safe_allocate(bc%pml%sigma_m(1:bc%pml%points_number, 1:space%dim))
1193 safe_allocate(bc%pml%a(1:bc%pml%points_number, 1:space%dim))
1194 safe_allocate(bc%pml%b(1:bc%pml%points_number, 1:space%dim))
1195 safe_allocate(bc%pml%c(1:bc%pml%points_number, 1:3))
1196 safe_allocate(bc%pml%mask(1:bc%pml%points_number))
1197 safe_allocate(bc%pml%conv_plus(1:bc%pml%points_number, 1:3, 1:3))
1198 safe_allocate(bc%pml%conv_minus(1:bc%pml%points_number, 1:3, 1:3))
1199 safe_allocate(bc%pml%conv_plus_old(1:bc%pml%points_number, 1:3, 1:3))
1200 safe_allocate(bc%pml%conv_minus_old(1:bc%pml%points_number, 1:3, 1:3))
1201 safe_allocate(bc%pml%aux_ep(1:bc%pml%points_number, 1:3, 1:3))
1202 safe_allocate(bc%pml%aux_mu(1:bc%pml%points_number, 1:3, 1:3))
1203
1204 bc%pml%kappa = m_one
1205 bc%pml%sigma_e = m_zero
1206 bc%pml%sigma_m = m_zero
1207 bc%pml%a = m_zero
1208 bc%pml%b = m_zero
1209 bc%pml%c = m_zero
1210 bc%pml%mask = m_one
1211 bc%pml%conv_plus = m_z0
1212 bc%pml%conv_minus = m_z0
1213 bc%pml%conv_plus_old = m_z0
1214 bc%pml%conv_minus_old = m_z0
1215
1216 if (accel_is_enabled()) then
1217 call accel_create_buffer(bc%pml%buff_map, accel_mem_read_only, type_integer, bc%pml%points_number)
1218 call accel_create_buffer(bc%pml%buff_a, accel_mem_read_only, type_float, int(bc%pml%points_number, int64)*space%dim)
1219 call accel_create_buffer(bc%pml%buff_b, accel_mem_read_only, type_float, int(bc%pml%points_number, int64)*space%dim)
1220 call accel_create_buffer(bc%pml%buff_c, accel_mem_read_only, type_float, int(bc%pml%points_number, int64)*space%dim)
1221 call accel_create_buffer(bc%pml%buff_conv_plus, accel_mem_read_write, type_cmplx, &
1222 int(bc%pml%points_number, int64)*space%dim*space%dim)
1223 call accel_create_buffer(bc%pml%buff_conv_minus, accel_mem_read_write, type_cmplx, &
1224 int(bc%pml%points_number, int64)*space%dim*space%dim)
1225 call accel_create_buffer(bc%pml%buff_conv_plus_old, accel_mem_read_write, type_cmplx, &
1226 int(bc%pml%points_number, int64)*space%dim*space%dim)
1227
1228 call accel_write_buffer(bc%pml%buff_a, bc%pml%points_number, space%dim, bc%pml%a)
1229 call accel_write_buffer(bc%pml%buff_b, bc%pml%points_number, space%dim, bc%pml%b)
1230 call accel_write_buffer(bc%pml%buff_c, bc%pml%points_number, space%dim, bc%pml%c)
1231 call accel_write_buffer(bc%pml%buff_conv_plus, bc%pml%points_number, space%dim, space%dim, bc%pml%conv_plus)
1232 call accel_write_buffer(bc%pml%buff_conv_minus, bc%pml%points_number, space%dim, space%dim, bc%pml%conv_minus)
1233 call accel_write_buffer(bc%pml%buff_conv_plus_old, bc%pml%points_number, space%dim, space%dim, bc%pml%conv_plus_old)
1234 end if
1235
1236 call profiling_out('BC_MXLL_GENERATE_PML')
1237
1238 pop_sub(bc_mxll_generate_pml)
1239 end subroutine bc_mxll_generate_pml
1240
1241
1242 ! ---------------------------------------------------------
1243 subroutine bc_mxll_generate_pml_parameters(bc, space, gr, c_factor, dt)
1244 type(bc_mxll_t), intent(inout) :: bc
1245 class(space_t), intent(in) :: space
1246 type(grid_t), intent(in) :: gr
1247 real(real64), intent(in) :: c_factor
1248 real(real64), optional, intent(in) :: dt
1249
1250 integer :: ip, ip_in, idim
1251 real(real64) :: width(3)
1252 real(real64) :: ddv(3), ss_e, ss_m, ss_max, aa_e, aa_m, bb_e, bb_m, gg, hh, kk, ll_e, ll_m
1253 real(real64), allocatable :: tmp(:), tmp_grad(:,:)
1254
1255
1257 safe_allocate(tmp(gr%np_part))
1258 safe_allocate(tmp_grad(gr%np, 1:space%dim))
1259 ! here bounds are ab_bounds, for which ab_bounds(1,:) = bc%bounds(1,:)
1260 ! width is stored in bc%pml%width
1261 ! assuming that the width is the same in the 3 dimensions (only case implemented now), we can change the following line:
1262 ! width(1:3) = bounds(2, 1:3) - bounds(1, 1:3) !! original line
1263 ! by
1264 width(1:3) = (/ bc%pml%width, bc%pml%width, bc%pml%width /)
1265
1266 ! PML variables for all boundary points
1267 do ip_in = 1, bc%pml%points_number
1268 ip = bc%pml%points_map(ip_in)
1269 ddv(1:3) = abs(gr%x(1:3, ip)) - bc%bc_bounds(1, 1:3)
1270 do idim = 1, space%dim
1271 if (ddv(idim) >= m_zero) then
1272 gg = (ddv(idim)/bc%pml%width)**bc%pml%power
1273 hh = (m_one-ddv(idim)/bc%pml%width)**bc%pml%power
1274 kk = m_one
1275 ss_max = -(bc%pml%power + m_one)*p_c*c_factor*p_ep*log(bc%pml%refl_error)/(m_two * bc%pml%width)
1276 ss_e = gg * ss_max
1277 ss_m = gg * ss_max
1278 ll_e = ss_e*kk
1279 ll_m = ss_m*kk
1280 aa_e = expm1(-(ss_e/(p_ep))*dt)
1281 aa_m = expm1(-(ss_m/(p_ep))*dt)
1282 if (abs(ll_e) < m_epsilon) aa_e = m_zero
1283 if (abs(ll_m) < m_epsilon) aa_m = m_zero
1284 bb_e = m_one + aa_e
1285 bb_m = m_one + aa_m
1286 bc%pml%sigma_e(ip_in, idim) = ss_e
1287 bc%pml%sigma_m(ip_in, idim) = ss_m
1288 bc%pml%a(ip_in, idim) = aa_e
1289 bc%pml%b(ip_in, idim) = bb_e
1290 bc%pml%kappa(ip_in, idim) = kk
1291 bc%pml%mask(ip_in) = bc%pml%mask(ip_in) * (m_one - sin(ddv(idim)*m_pi/(m_two*(width(idim))))**2)
1292 else
1293 bc%pml%kappa(ip_in, idim) = m_one
1294 bc%pml%sigma_e(ip_in, idim) = m_zero
1295 bc%pml%sigma_m(ip_in, idim) = m_zero
1296 bc%pml%a(ip_in, idim) = m_zero
1297 bc%pml%b(ip_in, idim) = m_zero
1298 bc%pml%mask(ip_in) = m_one
1299 end if
1300 end do
1301 end do
1302
1303 ! PML auxiliary epsilon for all boundary points
1304 do idim = 1, space%dim
1305 tmp = p_ep
1306 do ip_in = 1, bc%pml%points_number
1307 ip = bc%pml%points_map(ip_in)
1308 tmp(ip) = p_ep / bc%pml%kappa(ip_in, idim)
1309 end do
1310 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
1311 do ip_in = 1, bc%pml%points_number
1312 ip = bc%pml%points_map(ip_in)
1313 bc%pml%aux_ep(ip_in, :, idim) = tmp_grad(ip, :)/(m_four*p_ep*bc%pml%kappa(ip_in, idim))
1314 end do
1315 end do
1316
1317 ! PML auxiliary mu
1318 do idim = 1, space%dim
1319 ! P_mu is proportional to 1/P_c**2, so we need to devide by c_factor
1320 tmp = p_mu/c_factor**2
1321 do ip_in = 1, bc%pml%points_number
1322 ip = bc%pml%points_map(ip_in)
1323 tmp(ip) = p_mu/c_factor**2 / bc%pml%kappa(ip_in, idim)
1324 end do
1325 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
1326 do ip_in = 1, bc%pml%points_number
1327 ip = bc%pml%points_map(ip_in)
1328 bc%pml%aux_mu(ip_in, :, idim) = tmp_grad(ip, :)/(m_four*p_mu/c_factor**2 * bc%pml%kappa(ip_in, idim))
1329 end do
1330 end do
1331
1332 ! PML auxiliary c for all boundary points
1333 do idim = 1, space%dim
1334 do ip_in = 1, bc%pml%points_number
1335 bc%pml%c(ip_in, idim) = p_c*c_factor/bc%pml%kappa(ip_in, idim)
1336 end do
1337 end do
1338 safe_deallocate_a(tmp)
1339 safe_deallocate_a(tmp_grad)
1340
1341 if (accel_is_enabled()) then
1342 call accel_write_buffer(bc%pml%buff_map, bc%pml%points_number, bc%pml%points_map)
1343 call accel_write_buffer(bc%pml%buff_a, bc%pml%points_number, space%dim, bc%pml%a)
1344 call accel_write_buffer(bc%pml%buff_b, bc%pml%points_number, space%dim, bc%pml%b)
1345 call accel_write_buffer(bc%pml%buff_c, bc%pml%points_number, space%dim, bc%pml%c)
1346 call accel_write_buffer(bc%pml%buff_conv_plus, bc%pml%points_number, space%dim, space%dim, bc%pml%conv_plus)
1347 call accel_write_buffer(bc%pml%buff_conv_minus, bc%pml%points_number, space%dim, space%dim, bc%pml%conv_minus)
1348 end if
1349
1350 bc%pml%parameters_initialized = .true.
1351
1353
1354 end subroutine bc_mxll_generate_pml_parameters
1355
1356 ! ---------------------------------------------------------
1357 subroutine bc_mxll_initialize_pml_simple(bc, space, gr, c_factor, dt)
1358 type(bc_mxll_t), intent(inout) :: bc
1359 class(space_t), intent(in) :: space
1360 type(grid_t), intent(in) :: gr
1361 real(real64), intent(in) :: c_factor
1362 real(real64), intent(in) :: dt
1363
1364 integer :: ip_in, ip, idir
1365 real(real64) :: ddv(1:space%dim), kappa, sigma, alpha
1367
1368 ! PML variables for all boundary points
1369 do ip_in = 1, bc%pml%points_number
1370 ip = bc%pml%points_map(ip_in)
1371 ddv(1:3) = abs(gr%x(1:3, ip)) - bc%bc_bounds(1, 1:3)
1372 do idir = 1, space%dim
1373 if (ddv(idir) >= m_zero) then
1374 sigma = (ddv(idir)/bc%pml%width)**bc%pml%power * &
1375 (-(bc%pml%power + m_one)*p_c*c_factor*p_ep*log(bc%pml%refl_error)/(m_two * bc%pml%width))
1376 ! kappa and alpha could be set to different values, but these seem to be fine
1377 kappa = m_one
1378 ! non-zero values for alpha can be used to modify the low-frequency behavior
1379 alpha = m_zero
1380 bc%pml%b(ip_in, idir) = exp(-(alpha + sigma/kappa)/p_ep*dt)
1381 if (abs(sigma) < m_epsilon) then
1382 bc%pml%c(ip_in, idir) = m_zero
1383 else
1384 bc%pml%c(ip_in, idir) = m_one/(kappa + kappa**2*alpha/sigma) * &
1385 (bc%pml%b(ip_in, idir) - 1)
1386 end if
1387 else
1388 bc%pml%b(ip_in, idir) = m_zero
1389 bc%pml%c(ip_in, idir) = m_zero
1390 end if
1391 end do
1392 end do
1393 if (accel_is_enabled()) then
1394 call accel_write_buffer(bc%pml%buff_map, bc%pml%points_number, bc%pml%points_map)
1395 call accel_write_buffer(bc%pml%buff_b, bc%pml%points_number, space%dim, bc%pml%b)
1396 call accel_write_buffer(bc%pml%buff_c, bc%pml%points_number, space%dim, bc%pml%c)
1397 end if
1399 end subroutine bc_mxll_initialize_pml_simple
1400
1401 ! ---------------------------------------------------------
1402 subroutine bc_mxll_generate_mask(bc, mesh, bounds)
1403 type(bc_mxll_t), intent(inout) :: bc
1404 class(mesh_t), intent(in) :: mesh
1405 real(real64), intent(in) :: bounds(:,:)
1406
1407 integer :: ip, ip_in, idim, ip_in_max
1408 real(real64) :: ddv(3), tmp(3), width(3)
1409 real(real64), allocatable :: mask(:)
1410
1411 push_sub(bc_mxll_generate_mask)
1412
1413 call profiling_in('BC_MXLL_GENERATE_MASK')
1414
1415 ip_in_max = maxval(bc%mask_points_number(:))
1416
1417 safe_allocate(mask(1:mesh%np))
1418
1419 mask(:) = m_one
1420
1421 width(1:3) = bounds(2, 1:3) - bounds(1, 1:3)
1422 tmp(:) = m_zero
1423
1424 do ip = 1, mesh%np
1425 tmp = m_one
1426 mask(ip) = m_one
1427 ddv(1:3) = abs(mesh%x(1:3, ip)) - bounds(1, 1:3)
1428 do idim = 1, mesh%box%dim
1429 if (ddv(idim) >= m_zero) then
1430 if (ddv(idim) <= width(idim)) then
1431 tmp(idim) = m_one - sin(ddv(idim) * m_pi / (m_two * (width(idim))))**2
1432 else
1433 tmp(idim) = m_one
1434 end if
1435 end if
1436 mask(ip) = mask(ip) * tmp(idim)
1437 end do
1438 end do
1439
1440 do idim = 1, mesh%box%dim
1441 do ip_in = 1, bc%mask_points_number(idim)
1442 ip = bc%mask_points_map(ip_in, idim)
1443 bc%mask(ip_in,idim) = mask(ip)
1444 end do
1445 end do
1446
1447 safe_deallocate_a(mask)
1448
1449 call profiling_out('BC_MXLL_GENERATE_MASK')
1450
1451 pop_sub(bc_mxll_generate_mask)
1453
1454 ! ---------------------------------------------------------
1455 subroutine bc_mxll_generate_medium(bc, space, gr, bounds, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
1456 type(bc_mxll_t), intent(inout) :: bc
1457 class(space_t), intent(in) :: space
1458 type(grid_t), intent(in) :: gr
1459 real(real64), intent(in) :: bounds(:,:)
1460 real(real64), intent(in) :: ep_factor
1461 real(real64), intent(in) :: mu_factor
1462 real(real64), intent(in) :: sigma_e_factor
1463 real(real64), intent(in) :: sigma_m_factor
1464
1465 integer :: ip, ipp, ip_in, ip_in_max, ip_bd, idim, point_info
1466 integer :: medium_points_number(3)
1467 real(real64) :: dd, dd_min, dd_max, xx(3), xxp(3)
1468 real(real64), allocatable :: tmp(:), tmp_grad(:,:)
1469
1470 push_sub(bc_mxll_generate_medium)
1471
1472 call profiling_in('BC_MXLL_GENERATE_MEDIUM')
1473
1474 ip_in_max = max(bc%medium(1)%points_number, bc%medium(2)%points_number, bc%medium(3)%points_number)
1475 medium_points_number(:) = [bc%medium(1)%points_number, bc%medium(2)%points_number, bc%medium(3)%points_number]
1476 dd_max = max(2*gr%spacing(1), 2*gr%spacing(2), 2*gr%spacing(3))
1477 safe_allocate(tmp(gr%np_part))
1478 safe_allocate(tmp_grad(1:gr%np_part,1:space%dim))
1479
1480 do idim = 1, 3
1481 call single_medium_box_allocate(bc%medium(idim), ip_in_max)
1482 bc%medium(idim)%points_number = medium_points_number(idim)
1483 bc%medium(idim)%aux_ep = m_zero
1484 bc%medium(idim)%aux_mu = m_zero
1485 bc%medium(idim)%c = p_c
1486 if (bc%bc_type(idim) /= mxll_bc_medium) cycle
1487
1488 tmp = p_ep
1489 do ip = 1, gr%np_part
1490 call maxwell_box_point_info(bc, gr, ip, bounds, point_info)
1491 if ((point_info /= 0) .and. (abs(gr%x_t(ip, idim)) <= bounds(1, idim))) then
1492 xx(:) = gr%x(:, ip)
1493 dd_min = m_huge
1494 do ip_bd = 1, bc%medium(idim)%bdry_number
1495 ipp = bc%medium(idim)%bdry_map(ip_bd)
1496 xxp(:) = gr%x(:, ipp)
1497 dd = norm2(xx(1:3) - xxp(1:3))
1498 if (dd < dd_min) dd_min = dd
1499 end do
1500 tmp(ip) = p_ep * (m_one + ep_factor * m_one/(m_one + exp(-m_five/dd_max * (dd_min-m_two*dd_max))))
1501 end if
1502 end do
1503 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
1504 do ip_in = 1, bc%medium(idim)%points_number
1505 ip = bc%medium(idim)%points_map(ip_in)
1506 bc%medium(idim)%aux_ep(ip_in, :) = &
1507 tmp_grad(ip, :)/(m_four*p_ep*ep_factor * m_one/(m_one + exp(-m_five/dd_max-dd)))
1508 end do
1509 end do
1510
1511 do idim = 1, 3
1512 if (bc%bc_type(idim) /= mxll_bc_medium) cycle
1513 tmp = p_mu
1514 do ip = 1, gr%np_part
1515 call maxwell_box_point_info(bc, gr, ip, bounds, point_info)
1516 if ((point_info == 1) .and. (abs(gr%x_t(ip, idim)) <= bounds(1, idim))) then
1517 xx(:) = gr%x(:, ip)
1518 dd_min = m_huge
1519 do ip_bd = 1, bc%medium(idim)%bdry_number
1520 ipp = bc%medium(idim)%bdry_map(ip_bd)
1521 xxp(:) = gr%x(:, ipp)
1522 dd = norm2(xx(1:3) - xxp(1:3))
1523 if (dd < dd_min) dd_min = dd
1524 end do
1525 tmp(ip) = p_mu * (m_one + mu_factor * m_one/(m_one + exp(-m_five/dd_max * (dd_min - m_two*dd_max))))
1526 end if
1527 end do
1528 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
1529 do ip_in = 1, bc%medium(idim)%points_number
1530 ip = bc%medium(idim)%points_map(ip_in)
1531 bc%medium(idim)%aux_mu(ip_in, :) = &
1532 tmp_grad(ip, :)/(m_four * p_mu * mu_factor * m_one/(m_one + exp(-m_five/dd_max-dd)))
1533 end do
1534 end do
1535
1536 do idim = 1, 3
1537 if (bc%bc_type(idim) /= mxll_bc_medium) cycle
1538 do ip_in = 1, bc%medium(idim)%points_number
1539 ip = bc%medium(idim)%points_map(ip_in)
1540 xx(:) = gr%x(:, ip)
1541 dd_min = m_huge
1542 do ip_bd = 1, bc%medium(idim)%bdry_number
1543 ipp = bc%medium(idim)%bdry_map(ip_bd)
1544 xxp(:) = gr%x(:, ipp)
1545 dd = norm2(xx(1:3) - xxp(1:3))
1546 if (dd < dd_min) dd_min = dd
1547 end do
1548 bc%medium(idim)%ep(ip_in) = p_ep * (m_one + ep_factor &
1549 * m_one/(m_one + exp(-m_five / dd_max * (dd_min - m_two * dd_max))))
1550 bc%medium(idim)%mu(ip_in) = p_mu * (m_one + mu_factor &
1551 * m_one/(m_one + exp(-m_five / dd_max * (dd_min - m_two * dd_max))))
1552 bc%medium(idim)%sigma_e(ip_in) = (m_one + sigma_e_factor &
1553 * m_one/(m_one + exp(-m_five / dd_max * (dd_min - m_two * dd_max))))
1554 bc%medium(idim)%sigma_m(ip_in) = (m_one + sigma_m_factor &
1555 * m_one/(m_one + exp(-m_five / dd_max * (dd_min - m_two * dd_max))))
1556 bc%medium(idim)%c(ip_in) = m_one / sqrt(bc%medium(idim)%ep(ip_in) * bc%medium(idim)%mu(ip_in))
1557 end do
1558 end do
1559
1560 safe_deallocate_a(tmp)
1561 safe_deallocate_a(tmp_grad)
1562
1563 call profiling_out('BC_MXLL_GENERATE_MEDIUM')
1564
1566 end subroutine bc_mxll_generate_medium
1567
1568 ! ---------------------------------------------------------
1569 subroutine maxwell_surfaces_init(mesh, st, bounds)
1570 class(mesh_t), intent(in) :: mesh
1571 type(states_mxll_t), intent(inout) :: st
1572 real(real64), intent(in) :: bounds(:,:)
1573
1574
1575 push_sub(maxwell_surfaces_init)
1576
1577 call profiling_in('MAXWELL_SURFACES_INIT')
1578
1579 ! y-z surface at -x boundary
1580 st%surface(1, 1)%spacing = m_half*(mesh%spacing(2) + mesh%spacing(3))
1581 st%surface(1, 1)%origin(:) = m_zero
1582 st%surface(1, 1)%origin(1) = -bounds(1, 1)
1583 st%surface(1, 1)%n(:) = m_zero
1584 st%surface(1, 1)%n(1) = -m_one
1585 st%surface(1, 1)%u(:) = m_zero
1586 st%surface(1, 1)%u(2) = -m_one
1587 st%surface(1, 1)%v(:) = m_zero
1588 st%surface(1, 1)%v(3) = m_one
1589 st%surface(1, 1)%nu = -int(bounds(1, 2)/mesh%spacing(2))
1590 st%surface(1, 1)%mu = int(bounds(1, 2)/mesh%spacing(2))
1591 st%surface(1, 1)%nv = -int(bounds(1, 3)/mesh%spacing(3))
1592 st%surface(1, 1)%mv = int(bounds(1, 3)/mesh%spacing(3))
1593
1594 ! y-z surface at +x boundary
1595 st%surface(2, 1)%spacing = m_half*(mesh%spacing(2) + mesh%spacing(3))
1596 st%surface(2, 1)%origin(:) = m_zero
1597 st%surface(2, 1)%origin(1) = bounds(1, 1)
1598 st%surface(2, 1)%n(:) = m_zero
1599 st%surface(2, 1)%n(1) = m_one
1600 st%surface(2, 1)%u(:) = m_zero
1601 st%surface(2, 1)%u(2) = m_one
1602 st%surface(2, 1)%v(:) = m_zero
1603 st%surface(2, 1)%v(3) = m_one
1604 st%surface(2, 1)%nu = -int(bounds(1, 2)/mesh%spacing(2))
1605 st%surface(2, 1)%mu = int(bounds(1, 2)/mesh%spacing(2))
1606 st%surface(2, 1)%nv = -int(bounds(1, 3)/mesh%spacing(3))
1607 st%surface(2, 1)%mv = int(bounds(1, 3)/mesh%spacing(3))
1608
1609 ! x-z surface at -y boundary
1610 st%surface(1, 2)%spacing = m_half*(mesh%spacing(1) + mesh%spacing(3))
1611 st%surface(1, 2)%origin(:) = m_zero
1612 st%surface(1, 2)%origin(2) = -bounds(1, 2)
1613 st%surface(1, 2)%n(:) = m_zero
1614 st%surface(1, 2)%n(2) = -m_one
1615 st%surface(1, 2)%u(:) = m_zero
1616 st%surface(1, 2)%u(1) = m_one
1617 st%surface(1, 2)%v(:) = m_zero
1618 st%surface(1, 2)%v(3) = m_one
1619 st%surface(1, 2)%nu = -int(bounds(1, 1)/mesh%spacing(1))
1620 st%surface(1, 2)%mu = int(bounds(1, 1)/mesh%spacing(1))
1621 st%surface(1, 2)%nv = -int(bounds(1, 3)/mesh%spacing(3))
1622 st%surface(1, 2)%mv = int(bounds(1, 3)/mesh%spacing(3))
1623
1624 ! x-z surface at +y boundary
1625 st%surface(2, 2)%spacing = m_half*(mesh%spacing(1) + mesh%spacing(3))
1626 st%surface(2, 2)%origin(:) = m_zero
1627 st%surface(2, 2)%origin(2) = bounds(1, 2)
1628 st%surface(2, 2)%n(:) = m_zero
1629 st%surface(2, 2)%n(2) = m_one
1630 st%surface(2, 2)%u(:) = m_zero
1631 st%surface(2, 2)%u(1) = m_one
1632 st%surface(2, 2)%v(:) = m_zero
1633 st%surface(2, 2)%v(3) = -m_one
1634 st%surface(2, 2)%nu = -int(bounds(1, 1)/mesh%spacing(1))
1635 st%surface(2, 2)%mu = int(bounds(1, 1)/mesh%spacing(1))
1636 st%surface(2, 2)%nv = -int(bounds(1, 3)/mesh%spacing(3))
1637 st%surface(2, 2)%mv = int(bounds(1, 3)/mesh%spacing(3))
1638
1639 ! x-y surface at -z boundary
1640 st%surface(1, 3)%spacing = m_half*(mesh%spacing(1) + mesh%spacing(2))
1641 st%surface(1, 3)%origin(:) = m_zero
1642 st%surface(1, 3)%origin(3) = -bounds(1, 3)
1643 st%surface(1, 3)%n(:) = m_zero
1644 st%surface(1, 3)%n(3) = -m_one
1645 st%surface(1, 3)%u(:) = m_zero
1646 st%surface(1, 3)%u(1) = m_one
1647 st%surface(1, 3)%v(:) = m_zero
1648 st%surface(1, 3)%v(2) = -m_one
1649 st%surface(1, 3)%nu = -int(bounds(1, 1)/mesh%spacing(1))
1650 st%surface(1, 3)%mu = int(bounds(1, 1)/mesh%spacing(1))
1651 st%surface(1, 3)%nv = -int(bounds(1, 2)/mesh%spacing(2))
1652 st%surface(1, 3)%mv = int(bounds(1, 2)/mesh%spacing(2))
1653
1654 ! x-y surface at +z boundary
1655 st%surface(2, 3)%spacing = m_half*(mesh%spacing(1) + mesh%spacing(2))
1656 st%surface(2, 3)%origin(:) = m_zero
1657 st%surface(2, 3)%origin(3) = bounds(1, 3)
1658 st%surface(2, 3)%n(:) = m_zero
1659 st%surface(2, 3)%n(3) = m_one
1660 st%surface(2, 3)%u(:) = m_zero
1661 st%surface(2, 3)%u(1) = m_one
1662 st%surface(2, 3)%v(:) = m_zero
1663 st%surface(2, 3)%v(2) = m_one
1664 st%surface(2, 3)%nu = -int(bounds(1, 1)/mesh%spacing(1))
1665 st%surface(2, 3)%mu = int(bounds(1, 1)/mesh%spacing(1))
1666 st%surface(2, 3)%nv = -int(bounds(1, 2)/mesh%spacing(2))
1667 st%surface(2, 3)%mv = int(bounds(1, 2)/mesh%spacing(2))
1668
1669 call profiling_out('MAXWELL_SURFACES_INIT')
1670
1671 pop_sub(maxwell_surfaces_init)
1672 end subroutine maxwell_surfaces_init
1673
1674 ! ---------------------------------------------------------
1675 subroutine maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
1676 type(bc_mxll_t), intent(inout) :: bc
1677 class(mesh_t), intent(in) :: mesh
1678 integer, intent(in) :: ip
1679 real(real64), intent(in) :: bounds(:,:)
1680 integer, intent(out) :: point_info
1681
1682 real(real64) :: rr, dd, xx(3), width(3)
1683
1684 point_info = 0
1685
1686 width(1:3) = bounds(2, 1:3) - bounds(1, 1:3)
1687 xx = m_zero
1688 xx(1:mesh%box%dim) = mesh%x(1:mesh%box%dim, ip)
1689
1690 if (bc%ab_user_def) then
1691
1692 dd = bc%ab_ufn(ip) - bounds(1, 1)
1693 if (dd > m_zero) then
1694 if (bc%ab_ufn(ip) < bounds(2, 1)) then
1695 point_info = 1
1696 end if
1697 end if
1698
1699 else ! bc%ab_user_def == .false.
1700
1701 select type (box => mesh%box)
1702 type is (box_sphere_t)
1703 rr = norm2(xx - box%center)
1704 dd = rr - bounds(1, 1)
1705 if (dd > m_zero) then
1706 if (dd < width(1)) then
1707 point_info = 1
1708 end if
1709 end if
1710
1711 type is (box_parallelepiped_t)
1712 ! Limits of boundary region
1713 if (all(abs(xx(1:3) - box%center) <= bounds(2, 1:3))) then
1714 if (any(abs(xx(1:3) - box%center) > bounds(1, 1:3))) then
1715 point_info = 1
1716 else
1717 point_info = 0
1718 end if
1719 else
1720 point_info = -1
1721 end if
1722
1723 class default
1724 ! Other box shapes are not supported.
1725 assert(.false.)
1726 end select
1727 end if
1728
1729 end subroutine maxwell_box_point_info
1730
1731 ! ---------------------------------------------------------
1732 subroutine maxwell_boundary_point_info(mesh, ip, bounds, boundary_info)
1733 class(mesh_t), intent(in) :: mesh
1734 integer, intent(in) :: ip
1735 real(real64), intent(in) :: bounds(:,:)
1736 integer, intent(out) :: boundary_info
1737
1738 real(real64) :: xx(3)
1739
1740 boundary_info = 0
1741
1742 xx = m_zero
1743 xx(1:mesh%box%dim) = mesh%x(1:mesh%box%dim, ip)
1744 if (is_close(abs(xx(1)), bounds(1, 1)) .and. (all(abs(xx(2:3)) <= bounds(1, 2:3))) .or. &
1745 is_close(abs(xx(2)), bounds(1, 2)) .and. (all(abs(xx(1:3:2)) <= bounds(1, 1:3:2))) .or. &
1746 is_close(abs(xx(3)), bounds(1, 3)) .and. (all(abs(xx(1:2)) <= bounds(1, 1:2)))) then
1747 boundary_info = 1
1748 else
1749 boundary_info = 0
1750 end if
1751
1752 end subroutine maxwell_boundary_point_info
1753
1754 ! ---------------------------------------------------------
1755 subroutine inner_and_outer_points_mapping(mesh, st, bounds)
1756 class(mesh_t), intent(in) :: mesh
1757 type(states_mxll_t), intent(inout) :: st
1758 real(real64), intent(in) :: bounds(:,:)
1759
1760 integer :: ip, ip_in, ip_bd, point_info
1761 real(real64) :: xx(mesh%box%dim)
1762
1764
1765 call profiling_in('IN_OUT_POINTS_MAP')
1766
1767 ! allocate inner and boundary points points map
1768 ip_in = 0
1769 ip_bd = 0
1770 do ip = 1, mesh%np
1771 xx = mesh%x(:, ip)
1772 if (all(abs(xx) <= bounds(2,1:mesh%box%dim))) then
1773 if (any(abs(xx) > bounds(1,1:mesh%box%dim))) then
1774 point_info = 1
1775 else
1776 point_info = 0
1777 end if
1778 else
1779 point_info = -1
1780 end if
1781 if (point_info == 0) then
1782 ip_in = ip_in + 1
1783 else
1784 ip_bd = ip_bd + 1
1785 end if
1786 end do
1787 st%inner_points_number = ip_in
1788 safe_allocate(st%inner_points_map(1:ip_in))
1789 safe_allocate(st%inner_points_mask(1:mesh%np))
1790 st%boundary_points_number = ip_bd
1791 safe_allocate(st%boundary_points_map(1:ip_bd))
1792 safe_allocate(st%boundary_points_mask(1:mesh%np))
1793 st%inner_points_mask = .false.
1794 st%boundary_points_mask = .false.
1795
1796 ! inner and boundary points mapping
1797 ip_in = 0
1798 ip_bd = 0
1799 do ip = 1, mesh%np
1800 xx = mesh%x(:, ip)
1801 if (all(abs(xx) <= bounds(2,1:mesh%box%dim))) then
1802 if (any(abs(xx) > bounds(1,1:mesh%box%dim))) then
1803 point_info = 1
1804 else
1805 point_info = 0
1806 end if
1807 else
1808 point_info = -1
1809 end if
1810 if (point_info == 0) then
1811 ip_in = ip_in + 1
1812 st%inner_points_map(ip_in) = ip
1813 st%inner_points_mask(ip) = .true.
1814 else
1815 ip_bd = ip_bd + 1
1816 st%boundary_points_map(ip_bd) = ip
1817 st%boundary_points_mask(ip) = .true.
1818 end if
1819 end do
1820
1821 if (accel_is_enabled()) then
1822 call accel_create_buffer(st%buff_inner_points_map, accel_mem_read_only, type_integer, st%inner_points_number)
1823 call accel_write_buffer(st%buff_inner_points_map, st%inner_points_number, st%inner_points_map)
1824 call accel_create_buffer(st%buff_boundary_points_map, accel_mem_read_only, type_integer, st%boundary_points_number)
1825 call accel_write_buffer(st%buff_boundary_points_map, st%boundary_points_number, st%boundary_points_map)
1826 end if
1828 call profiling_out('IN_OUT_POINTS_MAP')
1829
1831 end subroutine inner_and_outer_points_mapping
1832
1833 ! ---------------------------------------------------------
1834 subroutine surface_grid_points_mapping(mesh, st, bounds)
1835 class(mesh_t), intent(in) :: mesh
1836 type(states_mxll_t), intent(inout) :: st
1837 real(real64), intent(in) :: bounds(:,:)
1838
1839 integer :: ix, ix_max, iix, iy, iy_max, iiy, iz, iz_max, iiz, idx1, idx2, nn_max
1840 integer(int64) :: ip_global
1841 integer, allocatable :: nn(:,:,:,:)
1842 real(real64) :: rr(3), delta(3), vec(2), min_1(3), max_1(3), min_2(3), max_2(3)
1843
1845
1846 call profiling_in('SURF_GRID_POINTS_MAPPING')
1847
1848 st%surface_grid_rows_number(1) = 3
1849 ix_max = st%surface_grid_rows_number(1)
1850 st%surface_grid_rows_number(2) = 3
1851 iy_max = st%surface_grid_rows_number(2)
1852 st%surface_grid_rows_number(3) = 3
1853 iz_max = st%surface_grid_rows_number(3)
1854
1855 delta(1) = m_two * abs(bounds(1,1)) / real(ix_max, real64)
1856 delta(2) = m_two * abs(bounds(1,2)) / real(iy_max, real64)
1857 delta(3) = m_two * abs(bounds(1,3)) / real(iz_max, real64)
1858
1859 st%surface_grid_element(1) = delta(2) * delta(3)
1860 st%surface_grid_element(2) = delta(1) * delta(3)
1861 st%surface_grid_element(3) = delta(1) * delta(2)
1862
1863 safe_allocate(nn(1:2, 1:3, 1:3, 1:3))
1864
1865 st%surface_grid_center(1, 1, :, :) = -int(bounds(1,1))
1866 do iy = 1, iy_max
1867 do iz = 1, iz_max
1868 rr(2) = -bounds(1,2) + delta(2)/m_two + (iy-1) * delta(2)
1869 rr(3) = -bounds(1,3) + delta(3)/m_two + (iz-1) * delta(3)
1870 st%surface_grid_center(1, 2, iy, iz) = int(rr(2))
1871 st%surface_grid_center(1, 3, iy, iz) = int(rr(3))
1872 end do
1873 end do
1874 st%surface_grid_center(2, 1, :, :) = int(bounds(1,1))
1875 do iy = 1, iy_max
1876 do iz = 1, iz_max
1877 rr(2) = -bounds(1,2) + delta(2)/m_two + (iy-1) * delta(2)
1878 rr(3) = -bounds(1,3) + delta(3)/m_two + (iz-1) * delta(3)
1879 st%surface_grid_center(2, 2, iy, iz) = int(rr(2))
1880 st%surface_grid_center(2, 3, iy, iz) = int(rr(3))
1881 end do
1882 end do
1883
1884 st%surface_grid_center(1, 2, :, :) = -int(bounds(1,2))
1885 do ix = 1, ix_max
1886 do iz = 1, iz_max
1887 rr(1) = -bounds(1,1) + delta(1)/m_two + (ix-1) * delta(1)
1888 rr(3) = -bounds(1,3) + delta(3)/m_two + (iz-1) * delta(3)
1889 st%surface_grid_center(1, 1, ix, iz) = int(rr(1))
1890 st%surface_grid_center(1, 3, ix, iz) = int(rr(3))
1891 end do
1892 end do
1893 st%surface_grid_center(2, 2, :, :) = int(bounds(1,2))
1894 do ix = 1, ix_max
1895 do iz = 1, iz_max
1896 rr(1) = -bounds(1,2) + delta(1)/m_two + (ix-1) * delta(1)
1897 rr(3) = -bounds(1,3) + delta(3)/m_two + (iz-1) * delta(3)
1898 st%surface_grid_center(2, 1, ix, iz) = int(rr(1))
1899 st%surface_grid_center(2, 3, ix, iz) = int(rr(3))
1900 end do
1901 end do
1902
1903 st%surface_grid_center(1, 3, :, :) = -int(bounds(1,3))
1904 do ix = 1, ix_max
1905 do iy = 1, iy_max
1906 rr(1) = -bounds(1,1) + delta(1)/m_two + (ix-1) * delta(1)
1907 rr(2) = -bounds(1,2) + delta(2)/m_two + (iy-1) * delta(2)
1908 st%surface_grid_center(1, 1, ix, iy) = int(rr(1))
1909 st%surface_grid_center(1, 2, ix, iy) = int(rr(2))
1910 end do
1911 end do
1912 st%surface_grid_center(2, 3, :, :) = int(bounds(1,3))
1913 do ix = 1, ix_max
1914 do iy = 1, iy_max
1915 rr(1) = -bounds(1,2) + delta(1)/m_two + (ix-1) * delta(1)
1916 rr(2) = -bounds(1,2) + delta(2)/m_two + (iy-1) * delta(2)
1917 st%surface_grid_center(2, 1, ix, iy) = int(rr(1))
1918 st%surface_grid_center(2, 2, ix, iy) = int(rr(2))
1919 end do
1920 end do
1921
1922 st%surface_grid_points_number(:,:,:) = 0
1923
1924 nn_max = 0
1925
1926 do iy = 1, iy_max
1927 do iz = 1, iz_max
1928 min_1(iy) = -bounds(1,2) + (iy-1) * delta(2)
1929 max_1(iy) = -bounds(1,2) + iy * delta(2)
1930 min_2(iz) = -bounds(1,3) + (iz-1) * delta(3)
1931 max_2(iz) = -bounds(1,3) + iz * delta(3)
1932 end do
1933 end do
1934 do iiy = mesh%idx%nr(1,2), mesh%idx%nr(2,2)
1935 do iiz = mesh%idx%nr(1,3), mesh%idx%nr(2,3)
1936 vec(1) = iiy * mesh%spacing(2)
1937 vec(2) = iiz * mesh%spacing(3)
1938 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
1939 if (idx1 /= 0 .and. idx2 /= 0) then
1940 st%surface_grid_points_number(1, idx1, idx2) = st%surface_grid_points_number(1, idx1, idx2) + 1
1941 if (nn_max < st%surface_grid_points_number(1, idx1, idx2)) then
1942 nn_max = st%surface_grid_points_number(1, idx1, idx2)
1943 end if
1944 end if
1945 end do
1946 end do
1947
1948 do ix = 1, ix_max
1949 do iz = 1, iz_max
1950 min_1(ix) = -bounds(1,1) + (ix-1) * delta(1)
1951 max_1(ix) = -bounds(1,1) + ix * delta(1)
1952 min_2(iz) = -bounds(1,3) + (iz-1) * delta(3)
1953 max_2(iz) = -bounds(1,3) + iz * delta(3)
1954 end do
1955 end do
1956 do iix = mesh%idx%nr(1, 1), mesh%idx%nr(2, 1)
1957 do iiz = mesh%idx%nr(1, 3), mesh%idx%nr(2, 3)
1958 vec(1) = iix * mesh%spacing(1)
1959 vec(2) = iiz * mesh%spacing(3)
1960 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
1961 if (idx1 /= 0 .and. idx2 /= 0) then
1962 st%surface_grid_points_number(2,idx1,idx2) = st%surface_grid_points_number(2,idx1,idx2)+1
1963 if (nn_max < st%surface_grid_points_number(2, idx1, idx2)) then
1964 nn_max = st%surface_grid_points_number(2, idx1, idx2)
1965 end if
1966 end if
1967 end do
1968 end do
1969
1970 do ix = 1, ix_max
1971 do iy = 1, iy_max
1972 min_1(ix) = -bounds(1,1) + (ix-1) * delta(1)
1973 max_1(ix) = -bounds(1,1) + ix * delta(1)
1974 min_2(iy) = -bounds(1,2) + (iy-1) * delta(2)
1975 max_2(iy) = -bounds(1,2) + iy * delta(2)
1976 end do
1977 end do
1978 do iix = mesh%idx%nr(1,1), mesh%idx%nr(2,1)
1979 do iiy = mesh%idx%nr(1,2), mesh%idx%nr(2,2)
1980 vec(1) = iix * mesh%spacing(1)
1981 vec(2) = iiy * mesh%spacing(2)
1982 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
1983 if (idx1 /= 0 .and. idx2 /= 0) then
1984 st%surface_grid_points_number(3, idx1, idx2) = st%surface_grid_points_number(3, idx1, idx2) + 1
1985 if (nn_max < st%surface_grid_points_number(3, idx1, idx2)) then
1986 nn_max = st%surface_grid_points_number(3, idx1, idx2)
1987 end if
1988 end if
1989 end do
1990 end do
1991
1992 ! originally there were three allocated of the same pointer here
1993 safe_allocate(st%surface_grid_points_map(1:2, 1:st%dim, 1:ix_max, 1:iy_max, 1:nn_max))
1994
1995 nn(:,:,:,:) = 0
1996
1997 do iy = 1, iy_max
1998 do iz = 1, iz_max
1999 min_1(iy) = -bounds(1,2) + (iy-1) * delta(2)
2000 max_1(iy) = -bounds(1,2) + iy * delta(2)
2001 min_2(iz) = -bounds(1,3) + (iz-1) * delta(3)
2002 max_2(iz) = -bounds(1,3) + iz * delta(3)
2003 end do
2004 end do
2005 do iiy = mesh%idx%nr(1,2), mesh%idx%nr(2,2)
2006 do iiz = mesh%idx%nr(1,3), mesh%idx%nr(2,3)
2007 vec(1) = iiy * mesh%spacing(2)
2008 vec(2) = iiz * mesh%spacing(3)
2009 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
2010 if (idx1 /= 0 .and. idx2 /= 0) then
2011 nn(1, 1, idx1, idx2) = nn(1, 1, idx1, idx2) + 1
2012 rr(1) = -bounds(1, 1)
2013 rr(2) = iiy * mesh%spacing(2)
2014 rr(3) = iiz * mesh%spacing(3)
2015 iix = int(-bounds(1,1)/mesh%spacing(1))
2016 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2017 st%surface_grid_points_map(1, 1, idx1, idx2, nn(1, 1, idx1, idx2)) = ip_global
2018 nn(2, 1, idx1, idx2) = nn(2, 1, idx1, idx2) + 1
2019 rr(1) = bounds(1,1)
2020 rr(2) = iiy * mesh%spacing(2)
2021 rr(3) = iiz * mesh%spacing(3)
2022 iix = int(bounds(1,1)/mesh%spacing(1))
2023 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2024 st%surface_grid_points_map(2, 1, idx1, idx2, nn(2, 1, idx1, idx2)) = ip_global
2025 end if
2026 end do
2027 end do
2028
2029 do ix = 1, ix_max
2030 do iz = 1, iz_max
2031 min_1(ix) = -bounds(1,1) + (ix-1) * delta(1)
2032 max_1(ix) = -bounds(1,1) + ix * delta(1)
2033 min_2(iz) = -bounds(1,3) + (iz-1) * delta(3)
2034 max_2(iz) = -bounds(1,3) + iz * delta(3)
2035 end do
2036 end do
2037 do iix = mesh%idx%nr(1,1), mesh%idx%nr(2,1)
2038 do iiz = mesh%idx%nr(1,3), mesh%idx%nr(2,3)
2039 vec(1) = iix * mesh%spacing(1)
2040 vec(2) = iiz * mesh%spacing(3)
2041 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
2042 if (idx1 /= 0 .and. idx2 /= 0) then
2043 nn(1, 2, idx1, idx2) = nn(1, 2, idx1, idx2) + 1
2044 rr(1) = iix * mesh%spacing(1)
2045 rr(2) = -bounds(1, 2)
2046 rr(3) = iiz * mesh%spacing(3)
2047 iiy = int(-bounds(1,2)/mesh%spacing(2))
2048 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2049 st%surface_grid_points_map(1, 2, idx1, idx2, nn(1, 2, idx1, idx2)) = ip_global
2050 nn(2, 2, idx1, idx2) = nn(2, 2, idx1, idx2) + 1
2051 rr(1) = iix * mesh%spacing(1)
2052 rr(2) = bounds(1,2)
2053 rr(3) = iiz * mesh%spacing(3)
2054 iiy = int(bounds(1,2)/mesh%spacing(2))
2055 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2056 st%surface_grid_points_map(2, 2, idx1, idx2, nn(2, 2, idx1, idx2)) = ip_global
2057 end if
2058 end do
2059 end do
2060
2061 do ix = 1, ix_max
2062 do iy = 1, iy_max
2063 min_1(ix) = -bounds(1,1) + (ix-1) * delta(1)
2064 max_1(ix) = -bounds(1,1) + ix * delta(1)
2065 min_2(iy) = -bounds(1,2) + (iy-1) * delta(2)
2066 max_2(iy) = -bounds(1,2) + iy * delta(2)
2067 end do
2068 end do
2069 do iix = mesh%idx%nr(1,1), mesh%idx%nr(2,1)
2070 do iiy = mesh%idx%nr(1,2), mesh%idx%nr(2,2)
2071 vec(1) = iix * mesh%spacing(1)
2072 vec(2) = iiy * mesh%spacing(2)
2073 call get_surface_indices(vec, min_1, max_1, min_2, max_2, idx1, idx2)
2074 if (idx1 /= 0 .and. idx2 /= 0) then
2075 nn(1, 3, idx1, idx2) = nn(1, 3, idx1, idx2) + 1
2076 rr(1) = iix * mesh%spacing(1)
2077 rr(2) = iiy * mesh%spacing(2)
2078 rr(3) = -bounds(1,3)
2079 iiz = int(-bounds(1,3)/mesh%spacing(3))
2080 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2081 st%surface_grid_points_map(1, 3, idx1, idx2, nn(1, 3, idx1, idx2)) = ip_global
2082 nn(2, 3, idx1, idx2) = nn(2, 3, idx1, idx2) + 1
2083 rr(1) = iix * mesh%spacing(1)
2084 rr(2) = iiy * mesh%spacing(2)
2085 rr(3) = bounds(1,3)
2086 iiz = int(bounds(1,3)/mesh%spacing(3))
2087 ip_global = mesh_global_index_from_coords(mesh, [iix, iiy, iiz])
2088 st%surface_grid_points_map(2, 3, idx1, idx2, nn(2, 3, idx1, idx2)) = ip_global
2089 end if
2090 end do
2091 end do
2092
2093 safe_deallocate_a(nn)
2094
2095 call profiling_out('SURF_GRID_POINTS_MAPPING')
2096
2098 contains
2099
2100 subroutine get_surface_indices(vec, min_1, max_1, min_2, max_2, index_1, index_2)
2101 real(real64), intent(in) :: vec(:)
2102 real(real64), intent(in) :: min_1(:)
2103 real(real64), intent(in) :: max_1(:)
2104 real(real64), intent(in) :: min_2(:)
2105 real(real64), intent(in) :: max_2(:)
2106 integer, intent(out) :: index_1
2107 integer, intent(out) :: index_2
2108
2109 if (vec(1) >= min_1(1) .and. vec(1) <= max_1(1) .and. vec(2) >= min_2(1) .and. vec(2) <= max_2(1)) then
2110 index_1 = 1
2111 index_2 = 1
2112 else if (vec(1) >= min_1(2) .and. vec(1) <= max_1(2) .and. vec(2) >= min_2(1) .and. vec(2) <= max_2(1)) then
2113 index_1 = 2
2114 index_2 = 1
2115 else if (vec(1) >= min_1(3) .and. vec(1) <= max_1(3) .and. vec(2) >= min_2(1) .and. vec(2) <= max_2(1)) then
2116 index_1 = 3
2117 index_2 = 1
2118 else if (vec(1) >= min_1(1) .and. vec(1) <= max_1(1) .and. vec(2) >= min_2(2) .and. vec(2) <= max_2(2)) then
2119 index_1 = 1
2120 index_2 = 2
2121 else if (vec(1) >= min_1(2) .and. vec(1) <= max_1(2) .and. vec(2) >= min_2(2) .and. vec(2) <= max_2(2)) then
2122 index_1 = 2
2123 index_2 = 2
2124 else if (vec(1) >= min_1(3) .and. vec(1) <= max_1(3) .and. vec(2) >= min_2(2) .and. vec(2) <= max_2(2)) then
2125 index_1 = 3
2126 index_2 = 2
2127 else if (vec(1) >= min_1(1) .and. vec(1) <= max_1(1) .and. vec(2) >= min_2(3) .and. vec(2) <= max_2(3)) then
2128 index_1 = 1
2129 index_2 = 3
2130 else if (vec(1) >= min_1(2) .and. vec(1) <= max_1(2) .and. vec(2) >= min_2(3) .and. vec(2) <= max_2(3)) then
2131 index_1 = 2
2132 index_2 = 3
2133 else if (vec(1) >= min_1(3) .and. vec(1) <= max_1(3) .and. vec(2) >= min_2(3) .and. vec(2) <= max_2(3)) then
2134 index_1 = 3
2135 index_2 = 3
2136 else
2137 index_1 = 0
2138 index_2 = 0
2139 end if
2140
2141 end subroutine get_surface_indices
2142
2143 end subroutine surface_grid_points_mapping
2144
2146
2147!! Local Variables:
2148!! mode: f90
2149!! coding: utf-8
2150!! End:
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
subroutine get_surface_indices(vec, min_1, max_1, min_2, max_2, index_1, index_2)
subroutine get_medium_io_function(medium_func, bc, io_func, idim)
subroutine get_mask_io_function(mask_func, bc, io_func, idim)
subroutine write_files(filename, tmp)
subroutine get_pml_io_function(pml_func, bc, io_func)
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:1006
integer, parameter, public accel_mem_read_write
Definition: accel.F90:186
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
integer, parameter, public accel_mem_read_only
Definition: accel.F90:186
type(debug_t), save, public debug
Definition: debug.F90:158
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public external_waves_end(external_waves)
subroutine, public external_waves_init(external_waves, namespace)
Here, plane wave is evaluated from analytical formulae on grid.
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_huge
Definition: global.F90:218
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_four
Definition: global.F90:204
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
real(real64), parameter, public p_mu
Definition: global.F90:247
real(real64), parameter, public p_ep
Definition: global.F90:246
complex(real64), parameter, public m_z0
Definition: global.F90:210
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:242
real(real64), parameter, public m_one
Definition: global.F90:201
real(real64), parameter, public m_five
Definition: global.F90:205
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module implements the index, used for the mesh points.
Definition: index.F90:124
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
integer(int64) function, public io_function_fill_how(where)
Use this function to quickly plot functions for debugging purposes: call dio_function_output(io_funct...
Definition: io.F90:116
subroutine, public single_medium_box_allocate(medium_box, n_points)
Allocation of medium_box components.
subroutine, public single_medium_box_end(medium_box)
Deallocation of medium_box components.
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
integer, parameter, public mxll_ab_mask_zero
subroutine maxwell_zero_points_mapping(bc, mesh, bounds)
integer, parameter, public mxll_bc_mirror_pmc
integer, parameter mxll_plane_waves_positive_side
subroutine maxwell_boundary_point_info(mesh, ip, bounds, boundary_info)
subroutine, public bc_mxll_init(bc, namespace, space, gr, st)
subroutine bc_mxll_generate_medium(bc, space, gr, bounds, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
subroutine maxwell_surfaces_init(mesh, st, bounds)
subroutine maxwell_box_point_info(bc, mesh, ip, bounds, point_info)
integer, parameter, public mxll_bc_mirror_pec
integer, parameter, public mxll_ab_mask
subroutine bc_mxll_medium_init(gr, namespace, bounds, idim, ep_factor, mu_factor, sigma_e_factor, sigma_m_factor)
subroutine, public surface_grid_points_mapping(mesh, st, bounds)
integer, parameter, public mxll_bc_plane_waves
subroutine, public bc_mxll_initialize_pml_simple(bc, space, gr, c_factor, dt)
integer, parameter, public mxll_bc_medium
subroutine maxwell_constant_points_mapping(bc, mesh, bounds)
subroutine bc_mxll_generate_pml(bc, space)
subroutine bc_mxll_write_info(bc, mesh, namespace, space)
subroutine, public bc_mxll_generate_pml_parameters(bc, space, gr, c_factor, dt)
subroutine bc_mxll_generate_mask(bc, mesh, bounds)
subroutine maxwell_plane_waves_points_mapping(bc, mesh, bounds)
subroutine, public inner_and_outer_points_mapping(mesh, st, bounds)
integer, parameter, public mxll_bc_constant
subroutine bc_mxll_pml_init(bc, gr, namespace, ab_bounds, idim)
subroutine maxwell_medium_points_mapping(bc, mesh, bounds)
subroutine bc_mxll_ab_bounds_init(bc, gr, namespace, ab_bounds, idim)
subroutine, public bc_mxll_end(bc)
integer, parameter, public mxll_ab_cpml
subroutine maxwell_pml_points_mapping(bc, mesh, bounds)
subroutine maxwell_mask_points_mapping(bc, mesh, bounds)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
integer(int64) function, public mesh_global_index_from_coords(mesh, ix)
This function returns the true global index of the point for a given vector of integer coordinates.
Definition: mesh.F90:919
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
character(len=512), private msg
Definition: messages.F90:167
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
Some general things and nomenclature:
Definition: par_vec.F90:173
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:463
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
type(type_t), parameter, public type_cmplx
Definition: types.F90:136
type(type_t), parameter, public type_integer
Definition: types.F90:137
type(type_t), parameter, public type_float
Definition: types.F90:135
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
This module defines the unit system, used for input and output.
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
Class implementing a parallelepiped box. Currently this is restricted to a rectangular cuboid (all th...
Class implementing a spherical box.
Definition: box_sphere.F90:134
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)