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