Octopus
states_mxll.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 R. Jestaedt, F. Bonafe, H. Appel, A. Rubio
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
22 use batch_oct_m
25 use debug_oct_m
28 use global_oct_m
29 use grid_oct_m
31 use math_oct_m
32 use mesh_oct_m
35 use mpi_oct_m
38#ifdef HAVE_OPENMP
39 use omp_lib
40#endif
41 use parser_oct_m
45 use space_oct_m
50 use types_oct_m
51 use unit_oct_m
54
55 implicit none
56
57 private
58
59 public :: &
79
80 type :: states_mxll_t
81 ! Components are public by default
82 integer :: dim
83 integer :: rs_sign
84 logical :: pack_states
85 logical :: parallel_in_states = .false.
86 integer, public :: nst
87 logical, public :: packed
88
89 complex(real64), allocatable :: rs_state_plane_waves(:,:)
90 complex(real64), allocatable :: rs_state(:,:)
91 complex(real64), allocatable :: rs_state_prev(:,:)
92 complex(real64), allocatable :: rs_state_trans(:,:)
93 complex(real64), allocatable :: rs_state_long(:,:)
94 complex(real64), allocatable :: rs_current_density_t1(:,:)
95 complex(real64), allocatable :: rs_current_density_t2(:,:)
96
97 logical :: rs_current_density_restart = .false.
98 complex(real64), allocatable :: rs_current_density_restart_t1(:,:)
99 complex(real64), allocatable :: rs_current_density_restart_t2(:,:)
100
101 type(batch_t) :: rs_stateb
102 type(batch_t) :: rs_state_prevb
103 type(batch_t) :: inhomogeneousb
104 type(batch_t) :: rs_state_plane_wavesb
105
106 real(real64), allocatable :: ep(:)
107 real(real64), allocatable :: mu(:)
108
109 integer, allocatable :: rs_state_fft_map(:,:,:)
110 integer, allocatable :: rs_state_fft_map_inv(:,:)
111
112 real(real64) :: energy_rate
113 real(real64) :: delta_energy
114 real(real64) :: energy_via_flux_calc
116 real(real64) :: trans_energy_rate
117 real(real64) :: trans_delta_energy
118 real(real64) :: trans_energy_via_flux_calc
119
120 real(real64) :: plane_waves_energy_rate
121 real(real64) :: plane_waves_delta_energy
122 real(real64) :: plane_waves_energy_via_flux_calc
123
124 real(real64) :: poynting_vector_box_surface(1:2,1:3,1:3) = m_zero
125 real(real64) :: poynting_vector_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
126 real(real64) :: electric_field_box_surface(1:2,1:3,1:3) = m_zero
127 real(real64) :: electric_field_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
128 real(real64) :: magnetic_field_box_surface(1:2,1:3,1:3) = m_zero
129 real(real64) :: magnetic_field_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
130
131 logical :: rs_state_const_external = .false.
132 complex(real64), allocatable :: rs_state_const(:)
133 complex(real64), allocatable :: rs_state_const_amp(:,:)
134 type(tdf_t), allocatable :: rs_state_const_td_function(:)
135
136 integer :: inner_points_number
137 integer, allocatable :: inner_points_map(:)
138 logical, allocatable :: inner_points_mask(:)
139 integer :: boundary_points_number
140 integer, allocatable :: boundary_points_map(:)
141 logical, allocatable :: boundary_points_mask(:)
142 type(accel_mem_t) :: buff_inner_points_map, buff_boundary_points_map
143
144 integer :: surface_points_number(3)
145 integer, allocatable :: surface_points_map(:,:,:)
146 real(real64) :: surface_element(3)
147
148 integer :: surface_grid_rows_number(3)
149 integer, allocatable :: surface_grid_points_number(:,:,:)
150 integer(int64), allocatable :: surface_grid_points_map(:,:,:,:,:)
151 integer, allocatable :: surface_grid_center(:,:,:,:)
152 real(real64) :: surface_grid_element(3)
153
154 type(mesh_plane_t) :: surface(2,3)
155
156 integer :: selected_points_number
157 real(real64), allocatable :: selected_points_coordinate(:,:)
158 complex(real64), allocatable :: selected_points_rs_state(:,:)
159 complex(real64), allocatable :: selected_points_rs_state_long(:,:)
160 complex(real64), allocatable :: selected_points_rs_state_trans(:,:)
161 integer, allocatable :: selected_points_map(:)
162 type(accel_mem_t) :: buff_selected_points_map
163 real(real64) :: rs_state_trans_var
164
165 real(real64), allocatable :: grid_rho(:,:)
166 complex(real64), allocatable :: kappa_psi(:,:)
167
168 character(len=1024), allocatable :: user_def_e_field(:)
169 character(len=1024), allocatable :: user_def_b_field(:)
170
171 integer :: energy_incident_waves_calc_iter
172 logical :: energy_incident_waves_calc
173
174 ! external current variables
175 integer :: external_current_number
176 integer, allocatable :: external_current_modus(:)
177 character(len=1024), allocatable :: external_current_string(:,:)
178 real(real64), allocatable :: external_current_amplitude(:,:,:)
179 type(tdf_t), allocatable :: external_current_td_function(:)
180 type(tdf_t), allocatable :: external_current_td_phase(:)
181 real(real64), allocatable :: external_current_omega(:)
182 real(real64), allocatable :: external_current_phase(:)
183
185 character(len=1024), allocatable :: user_def_states(:,:,:)
186 logical :: fromscratch = .true.
187 type(mpi_grp_t) :: mpi_grp
188 type(mpi_grp_t) :: dom_st_mpi_grp
189 type(mpi_grp_t) :: system_grp
191#ifdef HAVE_SCALAPACK
192 type(blacs_proc_grid_t) :: dom_st_proc_grid
193#endif
194 type(distributed_t) :: dist
195 logical :: scalapack_compatible
196 integer :: lnst
197 integer :: st_start, st_end
198 integer, allocatable :: node(:)
200 type(poisson_t) :: poisson
201 integer :: transverse_field_mode
203 end type states_mxll_t
205 integer, public, parameter :: &
209contains
210
211 ! ---------------------------------------------------------
212 subroutine states_mxll_init(st, namespace, space)
213 type(states_mxll_t), target, intent(inout) :: st
214 type(namespace_t), intent(in) :: namespace
215 class(space_t), intent(in) :: space
217 type(block_t) :: blk
218 integer :: idim, nlines, ncols, il
219 real(real64), allocatable :: pos(:)
220 integer :: ix_max, iy_max, iz_max
224 call profiling_in('STATES_MXLL_INIT')
225
226 st%fromScratch = .true. ! this will be reset if restart_read is called
228 assert(space%dim == 3)
229 st%dim = space%dim
230 st%nst = 1
232 safe_allocate(st%user_def_e_field(1:st%dim))
233 safe_allocate(st%user_def_b_field(1:st%dim))
235 st%st_start = 1
236 st%st_end = st%nst
237 st%lnst = st%nst
238
239 safe_allocate(st%node(1:st%nst))
240 st%node(1:st%nst) = 0
242 call mpi_grp_init(st%mpi_grp, mpi_comm_undefined)
243 st%parallel_in_states = .false.
244 st%packed = .false.
246 ! The variable StatesPack is documented in states_elec.F90.
247 ! We cannot include the documentation twice.
248 ! TODO: We should think whether these variables could be moved to a higher (abstract) class.
250 call parse_variable(namespace, 'StatesPack', .true., st%pack_states)
252 call messages_print_var_value('StatesPack', st%pack_states, namespace=namespace)
254 !rs_sign is not defined any more by the user, since it does not influence
255 !the results of the simulations.
256 st%rs_sign = 1
258 !%Variable MaxwellFieldsCoordinate
259 !%Type block
260 !%Section Maxwell::Output
261 !%Description
262 !% The Maxwell MaxwellFieldsCoordinate block allows to output Maxwell fields at particular
263 !% points in space. For each point a new line with three columns has to be added to the block,
264 !% where the columns denote the x, y, and z coordinate of the point.
265 !%
266 !% <tt>%MaxwellFieldsCoordinate
267 !% <br>&nbsp;&nbsp; -1.0 | 2.0 | 4.0
268 !% <br>&nbsp;&nbsp; 0.0 | 1.0 | -2.0
269 !% <br>%</tt>
270 !%
271 !%End
273 safe_allocate(pos(1:st%dim))
274 st%selected_points_number = 1
275 if (parse_block(namespace, 'MaxwellFieldsCoordinate', blk) == 0) then
276 nlines = parse_block_n(blk)
277 st%selected_points_number = nlines
278 safe_allocate(st%selected_points_coordinate(1:st%dim,1:nlines))
279 safe_allocate(st%selected_points_rs_state(1:st%dim,1:nlines))
280 safe_allocate(st%selected_points_rs_state_long(1:st%dim,1:nlines))
281 safe_allocate(st%selected_points_rs_state_trans(1:st%dim,1:nlines))
282 safe_allocate(st%selected_points_map(1:nlines))
283 do il = 1, nlines
284 ncols = parse_block_cols(blk,0)
285 if (ncols < 3 .or. ncols > 3) then
286 message(1) = 'MaxwellFieldCoordinate must have 3 columns.'
287 call messages_fatal(1, namespace=namespace)
288 end if
289 do idim = 1, st%dim
290 call parse_block_float(blk, il-1, idim-1, pos(idim), units_inp%length)
291 end do
292 st%selected_points_coordinate(:,il) = pos
293 st%selected_points_rs_state(:,il) = m_z0
294 st%selected_points_rs_state_long(:,il) = m_z0
295 st%selected_points_rs_state_trans(:,il) = m_z0
296 end do
297 call parse_block_end(blk)
298 else
299 safe_allocate(st%selected_points_coordinate(1:st%dim, 1))
300 safe_allocate(st%selected_points_rs_state(1:st%dim, 1))
301 safe_allocate(st%selected_points_rs_state_long(1:st%dim, 1))
302 safe_allocate(st%selected_points_rs_state_trans(1:st%dim, 1))
303 safe_allocate(st%selected_points_map(1))
304 st%selected_points_coordinate(:,:) = m_zero
305 st%selected_points_rs_state(:,:) = m_z0
306 st%selected_points_rs_state_long(:,:) = m_z0
307 st%selected_points_rs_state_trans(:,:) = m_z0
308 st%selected_points_map(:) = -1
309 end if
310
311 safe_deallocate_a(pos)
312
313 st%surface_grid_rows_number(1) = 3
314 ix_max = st%surface_grid_rows_number(1)
315 st%surface_grid_rows_number(2) = 3
316 iy_max = st%surface_grid_rows_number(2)
317 st%surface_grid_rows_number(3) = 3
318 iz_max = st%surface_grid_rows_number(3)
319
320 safe_allocate(st%surface_grid_center(1:2, 1:st%dim, 1:ix_max, 1:iy_max))
321 safe_allocate(st%surface_grid_points_number(1:st%dim, 1:ix_max, 1:iy_max))
322
323 !%Variable TransverseFieldCalculation
324 !%Type integer
325 !%Default no
326 !%Section Maxwell
327 !%Description
328 !% This variable selects the method for the calculation of the transverse field.
329 !%Option helmholtz 1
330 !% Transverse field calculated from Helmholtz decompisition (unreliable at the moment).
331 !%Option total_minus_long 2
332 !% Total field minus longitudinal field.
333 !%End
334 call parse_variable(namespace, 'TransverseFieldCalculation', transverse_from_helmholtz, &
335 st%transverse_field_mode)
336
337 call profiling_out('STATES_MXLL_INIT')
338
339 pop_sub(states_mxll_init)
340
341 end subroutine states_mxll_init
342
343 ! ---------------------------------------------------------
345 subroutine states_mxll_allocate(st, mesh)
346 type(states_mxll_t), intent(inout) :: st
347 class(mesh_t), intent(in) :: mesh
348
349
350 push_sub(states_mxll_allocate)
351
352 call profiling_in('STATES_MXLL_ALLOCATE')
353
354 safe_allocate(st%rs_state(1:mesh%np_part, 1:st%dim))
355 st%rs_state(:,:) = m_z0
356
357 safe_allocate(st%rs_state_prev(1:mesh%np_part, 1:st%dim))
358 st%rs_state_prev(:,:) = m_z0
359
360 safe_allocate(st%rs_state_trans(1:mesh%np_part, 1:st%dim))
361 st%rs_state_trans(:,:) = m_z0
362
363 safe_allocate(st%rs_state_long(1:mesh%np_part, 1:st%dim))
364 st%rs_state_long(:,:) = m_z0
365
366 safe_allocate(st%rs_state_plane_waves(1:mesh%np_part, 1:st%dim))
367 st%rs_state_plane_waves(:,:) = m_z0
368
369 safe_allocate(st%rs_current_density_t1(1:mesh%np, 1:st%dim))
370 st%rs_current_density_t1 = m_z0
371
372 safe_allocate(st%rs_current_density_t2(1:mesh%np, 1:st%dim))
373 st%rs_current_density_t2 = m_z0
374
375 safe_allocate(st%rs_current_density_restart_t1(1:mesh%np_part, 1:st%dim))
376 st%rs_current_density_restart_t1 = m_z0
377
378 safe_allocate(st%rs_current_density_restart_t2(1:mesh%np_part, 1:st%dim))
379 st%rs_current_density_restart_t2 = m_z0
380
381 safe_allocate(st%ep(1:mesh%np_part))
382 safe_allocate(st%mu(1:mesh%np_part))
383 st%ep = p_ep
384 st%mu = p_mu
385
386 call profiling_out('STATES_MXLL_ALLOCATE')
387
388 pop_sub(states_mxll_allocate)
389 end subroutine states_mxll_allocate
390
391 ! ---------------------------------------------------------
392 subroutine states_mxll_end(st)
393 type(states_mxll_t), intent(inout) :: st
394
395
396 push_sub(states_mxll_end)
397
398 call profiling_in('STATES_MXLL_END')
399
400 safe_deallocate_a(st%rs_state)
401 safe_deallocate_a(st%rs_state_prev)
402 safe_deallocate_a(st%rs_state_trans)
403 safe_deallocate_a(st%selected_points_coordinate)
404 safe_deallocate_a(st%selected_points_rs_state)
405 safe_deallocate_a(st%selected_points_rs_state_long)
406 safe_deallocate_a(st%selected_points_rs_state_trans)
407 safe_deallocate_a(st%rs_current_density_t1)
408 safe_deallocate_a(st%rs_current_density_t2)
409 safe_deallocate_a(st%rs_state_long)
410 safe_deallocate_a(st%rs_current_density_restart_t1)
411 safe_deallocate_a(st%rs_current_density_restart_t2)
412 safe_deallocate_a(st%user_def_e_field)
413 safe_deallocate_a(st%user_def_b_field)
414
415 safe_deallocate_a(st%rs_state_const)
416 safe_deallocate_a(st%rs_state_const_td_function)
417 safe_deallocate_a(st%rs_state_const_amp)
418 safe_deallocate_a(st%rs_state_plane_waves)
419
420 safe_deallocate_a(st%surface_grid_center)
421 safe_deallocate_a(st%surface_grid_points_number)
422 safe_deallocate_a(st%surface_grid_points_map)
423 safe_deallocate_a(st%inner_points_map)
424 safe_deallocate_a(st%boundary_points_map)
425 safe_deallocate_a(st%inner_points_mask)
426 safe_deallocate_a(st%boundary_points_mask)
427 safe_deallocate_a(st%ep)
428 safe_deallocate_a(st%mu)
429 if (accel_is_enabled()) then
430 call accel_free_buffer(st%buff_inner_points_map)
431 call accel_free_buffer(st%buff_boundary_points_map)
432 call accel_free_buffer(st%buff_selected_points_map)
433 end if
434#ifdef HAVE_SCALAPACK
435 call blacs_proc_grid_end(st%dom_st_proc_grid)
436#endif
437 safe_deallocate_a(st%external_current_modus)
438 safe_deallocate_a(st%external_current_string)
439 safe_deallocate_a(st%external_current_amplitude)
440 safe_deallocate_a(st%external_current_td_function)
441 safe_deallocate_a(st%external_current_omega)
442 safe_deallocate_a(st%external_current_td_phase)
443
444 call distributed_end(st%dist)
445 safe_deallocate_a(st%node)
446
447 call profiling_out('STATES_MXLL_END')
448
449 pop_sub(states_mxll_end)
450 end subroutine states_mxll_end
451
452
453 !----------------------------------------------------------
454 subroutine build_rs_vector(e_vector, b_vector, rs_sign, rs_vector, ep_element, mu_element)
455 real(real64), intent(in) :: e_vector(:), b_vector(:)
456 complex(real64), intent(inout) :: rs_vector(:)
457 integer, intent(in) :: rs_sign
458 real(real64), optional, intent(in) :: ep_element
459 real(real64), optional, intent(in) :: mu_element
460
461 ! no PUSH_SUB, called too often
462
463 if (present(ep_element) .and. present(mu_element)) then
464 rs_vector = sqrt(ep_element/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*mu_element)) * b_vector
465 else
466 rs_vector = sqrt(p_ep/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_vector
467 end if
468
469 end subroutine build_rs_vector
470
471
472 !----------------------------------------------------------
473 subroutine build_rs_state(e_field, b_field, rs_sign, rs_state, mesh, ep_field, mu_field, np)
474 real(real64), intent(in) :: e_field(:,:), b_field(:,:)
475 complex(real64), intent(inout) :: rs_state(:,:)
476 integer, intent(in) :: rs_sign
477 class(mesh_t), intent(in) :: mesh
478 real(real64), optional, intent(in) :: ep_field(:)
479 real(real64), optional, intent(in) :: mu_field(:)
480 integer, optional, intent(in) :: np
481
482 integer :: ip, np_
483
484 push_sub(build_rs_state)
485
486 call profiling_in('BUILD_RS_STATE')
488 np_ = optional_default(np, mesh%np)
489
490 do ip = 1, np_
491 if (present(ep_field) .and. present(mu_field)) then
492 rs_state(ip, :) = sqrt(ep_field(ip)/m_two) * e_field(ip, :) &
493 + m_zi * rs_sign * sqrt(m_one/(m_two*mu_field(ip))) * b_field(ip, :)
494 else
495 rs_state(ip, :) = sqrt(p_ep/m_two) * e_field(ip, :) &
496 + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_field(ip, :)
497 end if
498 end do
499
500 call profiling_out('BUILD_RS_STATE')
501
502 pop_sub(build_rs_state)
503
504 end subroutine build_rs_state
505
506
507 !----------------------------------------------------------
508 subroutine build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
509 real(real64), intent(in) :: current_state(:,:)
510 class(mesh_t), intent(in) :: mesh
511 complex(real64), intent(inout) :: rs_current_state(:,:)
512 real(real64), optional, intent(in) :: ep_field(:)
513 integer, optional, intent(in) :: np
514
515 integer :: ip, idim, np_, ff_dim
516
517 ! no PUSH_SUB, called too often
518
519 call profiling_in("BUILD_RS_CURRENT_STATE")
520
521 np_ = optional_default(np, mesh%np)
522 ff_dim = size(current_state, dim=2)
523
524 if (present(ep_field)) then
525 do idim = 1, ff_dim
526 do ip = 1, np_
527 rs_current_state(ip, idim) = m_one/sqrt(m_two*ep_field(ip)) * current_state(ip, idim)
528 end do
529 end do
530 else
531 do idim = 1, ff_dim
532 do ip = 1, np_
533 rs_current_state(ip, idim) = m_one/sqrt(m_two*p_ep) * current_state(ip, idim)
534 end do
535 end do
536 end if
537
538 call profiling_out("BUILD_RS_CURRENT_STATE")
539
540 end subroutine build_rs_current_state
541
542
543 !----------------------------------------------------------
544 subroutine get_electric_field_vector(rs_state_vector, electric_field_vector, ep_element)
545 complex(real64), intent(in) :: rs_state_vector(:)
546 real(real64), intent(out) :: electric_field_vector(:)
547 real(real64), optional, intent(in) :: ep_element
548
549 ! no PUSH_SUB, called too often
550
551 if (present(ep_element)) then
552 electric_field_vector(:) = sqrt(m_two/ep_element) * real(rs_state_vector(:), real64)
553 else
554 electric_field_vector(:) = sqrt(m_two/p_ep) * real(rs_state_vector(:), real64)
555 end if
556
557 end subroutine get_electric_field_vector
558
559
560 !----------------------------------------------------------
561 subroutine get_magnetic_field_vector(rs_state_vector, rs_sign, magnetic_field_vector, mu_element)
562 complex(real64), intent(in) :: rs_state_vector(:)
563 integer, intent(in) :: rs_sign
564 real(real64), intent(out) :: magnetic_field_vector(:)
565 real(real64), optional, intent(in) :: mu_element
566
567 ! no PUSH_SUB, called too often
569 if (present(mu_element)) then
570 magnetic_field_vector(:) = sqrt(m_two*mu_element) * rs_sign * aimag(rs_state_vector(:))
571 else
572 magnetic_field_vector(:) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state_vector(:))
573 end if
574
575 end subroutine get_magnetic_field_vector
576
577
578 !----------------------------------------------------------
579 subroutine get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
580 complex(real64), intent(in) :: rs_state(:,:)
581 class(mesh_t), intent(in) :: mesh
582 real(real64), intent(out) :: electric_field(:,:)
583 real(real64), optional, intent(in) :: ep_field(:)
584 integer, optional, intent(in) :: np
585
586 integer :: ip, np_
587
589
590 call profiling_in('GET_ELECTRIC_FIELD_STATE')
591
592 np_ = optional_default(np, mesh%np)
593
594 do ip = 1, np_
595 if (present(ep_field)) then
596 electric_field(ip, :) = sqrt(m_two/ep_field(ip)) * real(rs_state(ip, :), real64)
597 else
598 electric_field(ip,:) = sqrt(m_two/p_ep) * real(rs_state(ip, :), real64)
599 end if
600 end do
601
602 call profiling_out('GET_ELECTRIC_FIELD_STATE')
605
606 end subroutine get_electric_field_state
607
608
609 !----------------------------------------------------------
610 subroutine get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
611 complex(real64), intent(in) :: rs_state(:,:)
612 class(mesh_t), intent(in) :: mesh
613 integer, intent(in) :: rs_sign
614 real(real64), intent(out) :: magnetic_field(:,:)
615 real(real64), optional, intent(in) :: mu_field(:)
616 integer, optional, intent(in) :: np
617
618 integer :: ip, np_
619
621
622 call profiling_in('GET_MAGNETIC_FIELD_STATE')
623
624 np_ = optional_default(np, mesh%np)
625
626 if (present(mu_field)) then
627 do ip = 1, np_
628 magnetic_field(ip, :) = sqrt(m_two*mu_field(ip)) * rs_sign * aimag(rs_state(ip, :))
629 end do
630 else
631 do ip = 1, np_
632 magnetic_field(ip, :) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state(ip, :))
633 end do
634 end if
635
636 call profiling_out('GET_MAGNETIC_FIELD_STATE')
637
640 end subroutine get_magnetic_field_state
641
642 !----------------------------------------------------------
643 subroutine get_rs_state_at_point(rs_state_point, rs_state, pos, st, mesh)
644
645 complex(real64), intent(inout) :: rs_state_point(:,:)
646 complex(real64), intent(in) :: rs_state(:,:)
647 real(real64), intent(in) :: pos(:,:)
648 type(states_mxll_t), intent(in) :: st
649 class(mesh_t), intent(in) :: mesh
650
651 integer :: ip, pos_index, rankmin
652 real(real64) :: dmin
653 complex(real64), allocatable :: ztmp(:)
654
655 push_sub(get_rs_state_at_point)
657 safe_allocate(ztmp(1:size(rs_state, dim=2)))
658
659 do ip = 1, st%selected_points_number
660 pos_index = mesh_nearest_point(mesh, pos(:,ip), dmin, rankmin)
661 if (mesh%mpi_grp%rank == rankmin) then
662 ztmp(:) = rs_state(pos_index, :)
663 end if
664 if (mesh%parallel_in_domains) then
665 call mesh%mpi_grp%bcast(ztmp, st%dim, mpi_double_complex, rankmin)
666 end if
667 rs_state_point(:, ip) = ztmp(:)
668 end do
669
670 safe_deallocate_a(ztmp)
671
672
673 pop_sub(get_rs_state_at_point)
675
676
677 !----------------------------------------------------------
678 subroutine get_rs_state_batch_selected_points(rs_state_point, rs_stateb, st, mesh)
679 complex(real64), contiguous, intent(inout) :: rs_state_point(:,:)
680 type(batch_t), intent(in) :: rs_stateb
681 type(states_mxll_t), intent(in) :: st
682 class(mesh_t), intent(in) :: mesh
683
684 integer :: ip_in, ip
685 complex(real64) :: rs_state_tmp(1:st%dim, 1:st%selected_points_number)
686 type(accel_kernel_t), save :: kernel
687 type(accel_mem_t) :: buff_points
688 integer(int64), dimension(3) :: gsizes, bsizes
689
691
692 rs_state_tmp(:,:) = m_z0
693
694 select case (rs_stateb%status())
695 case (batch_not_packed)
696 do ip_in = 1, st%selected_points_number
697 ip = st%selected_points_map(ip_in)
698 if (ip >= 0) then
699 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_linear(ip, 1:st%dim)
700 end if
701 end do
702 case (batch_packed)
703 do ip_in = 1, st%selected_points_number
704 ip = st%selected_points_map(ip_in)
705 if (ip >= 0) then
706 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_pack(1:st%dim, ip)
707 end if
708 end do
710 call accel_kernel_start_call(kernel, 'get_points.cu', 'get_selected_points')
711
713 st%selected_points_number*st%dim)
714 call accel_set_buffer_to_zero(buff_points, type_integer, st%selected_points_number*st%dim)
715
716 call accel_set_kernel_arg(kernel, 0, st%selected_points_number)
717 call accel_set_kernel_arg(kernel, 1, st%buff_selected_points_map)
718 call accel_set_kernel_arg(kernel, 2, rs_stateb%ff_device)
719 call accel_set_kernel_arg(kernel, 3, log2(int(rs_stateb%pack_size_real(1), int32)))
720 call accel_set_kernel_arg(kernel, 4, buff_points)
721 call accel_set_kernel_arg(kernel, 5, st%dim*2)
722
723 ! Compute the grid (extend to another dimensions if the size of the problem is too big)
724 call accel_grid_size_extend_dim(int(st%selected_points_number, int64), rs_stateb%pack_size_real(1), &
725 gsizes, bsizes, kernel)
726
727 call accel_kernel_run(kernel, gsizes, bsizes)
728
729 call accel_read_buffer(buff_points, st%dim, st%selected_points_number, rs_state_tmp)
730 call accel_free_buffer(buff_points)
731 end select
732
733 call mesh%mpi_grp%allreduce(rs_state_tmp, rs_state_point, st%selected_points_number*st%dim, mpi_double_complex, mpi_sum)
734
737
738 !----------------------------------------------------------
739 subroutine get_divergence_field(gr, field, field_div, charge_density)
740 type(grid_t), intent(in) :: gr
741 real(real64), contiguous, intent(inout) :: field(:,:)
742 real(real64), contiguous, intent(inout) :: field_div(:)
743 logical, intent(in) :: charge_density
744
745 push_sub(get_divergence_field)
746
747 call dderivatives_div(gr%der, field, field_div)
748
749 if (optional_default(charge_density,.false.)) then
750 field_div = p_ep * field_div
751 end if
752
753 pop_sub(get_divergence_field)
754 end subroutine get_divergence_field
755
756
757 ! ---------------------------------------------------------
758 subroutine get_poynting_vector(mesh, st, rs_state, rs_sign, poynting_vector, ep_field, mu_field)
759 class(mesh_t), intent(in) :: mesh
760 type(states_mxll_t), intent(in) :: st
761 complex(real64), intent(in) :: rs_state(:,:)
762 integer, intent(in) :: rs_sign
763 real(real64), intent(out) :: poynting_vector(:,:)
764 real(real64), optional, intent(in) :: ep_field(:)
765 real(real64), optional, intent(in) :: mu_field(:)
766
767 integer :: ip
768
769 push_sub(get_poynting_vector)
770 if (present(ep_field) .and. present(mu_field)) then
771 do ip = 1, mesh%np
772 poynting_vector(ip, 1:3) = m_one/mu_field(ip) * sqrt(m_two/ep_field(ip)) &
773 * sqrt(m_two*mu_field(ip)) &
774 * dcross_product(real(rs_state(ip, 1:3), real64) , &
775 rs_sign*aimag(rs_state(ip,1:3)))
776 end do
777 else
778 do ip = 1, mesh%np
779 poynting_vector(ip, 1:3) = m_one/st%mu(ip) * sqrt(m_two/st%ep(ip)) &
780 * sqrt(m_two*st%mu(ip)) &
781 * dcross_product(real(rs_state(ip, 1:3), real64) , &
782 rs_sign*aimag(rs_state(ip, 1:3)))
783 end do
784 end if
785
786 pop_sub(get_poynting_vector)
787 end subroutine get_poynting_vector
788
789
790 ! ---------------------------------------------------------
791 subroutine get_orbital_angular_momentum(mesh, poynting_vector, orbital_angular_momentum)
792 type(mesh_t), intent(in) :: mesh
793 real(real64), intent(in) :: poynting_vector(:,:)
794 real(real64), intent(out) :: orbital_angular_momentum(:,:)
795
796 integer :: ip
797
799
800 do ip = 1, mesh%np
801 orbital_angular_momentum(ip,1:3) = dcross_product(real(mesh%x(1:3, ip), real64) , &
802 poynting_vector(ip, 1:3))
803 end do
804
806 end subroutine get_orbital_angular_momentum
807
808 ! ---------------------------------------------------------
809 subroutine mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
810 type(batch_t), intent(inout) :: rs_stateb
811 complex(real64), contiguous, intent(in) :: rs_state(:, :)
812 integer, intent(in) :: np
813 integer, intent(in) :: dim
814 integer, optional, intent(in) :: offset
815
816 integer :: offset_, idir
817
818 push_sub(mxll_set_batch)
819
820 offset_ = optional_default(offset, 1)
821
822 do idir = offset_, offset_ + dim - 1
823 call batch_set_state(rs_stateb, idir, np, rs_state(:, idir))
824 end do
825
826 pop_sub(mxll_set_batch)
827 end subroutine mxll_set_batch
828
829 ! ---------------------------------------------------------
830 subroutine mxll_get_batch(rs_stateb, rs_state, np, dim, offset)
831 type(batch_t), intent(in) :: rs_stateb
832 complex(real64), contiguous, intent(out) :: rs_state(:, :)
833 integer, intent(in) :: np
834 integer, intent(in) :: dim
835 integer, optional, intent(in) :: offset
836
837 integer :: offset_, idir
838
839 push_sub(mxll_get_batch)
840
841 offset_ = optional_default(offset, 1)
842
843 do idir = offset_, offset_ + dim - 1
844 call batch_get_state(rs_stateb, idir, np, rs_state(:, idir))
845 end do
846
847 pop_sub(mxll_get_batch)
848 end subroutine mxll_get_batch
849
850 !----------------------------------------------------------
851 subroutine get_transverse_rs_state(helmholtz, st, namespace)
852 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
853 type(states_mxll_t), intent(inout) :: st
854 type(namespace_t), intent(in) :: namespace
855
856
858
859 call profiling_in('GET_TRANSVERSE_RS_STATE')
860
861 select case (st%transverse_field_mode)
863 call helmholtz%get_trans_field(namespace, st%rs_state_trans, total_field=st%rs_state)
865 call helmholtz%get_long_field(namespace, st%rs_state_long, total_field=st%rs_state)
866 st%rs_state_trans = st%rs_state - st%rs_state_long
867 case default
868 message(1) = 'Unknown transverse field calculation mode.'
869 call messages_fatal(1, namespace=namespace)
870 end select
871
872 call profiling_out('GET_TRANSVERSE_RS_STATE')
873
875
876 end subroutine get_transverse_rs_state
877
878
879end module states_mxll_oct_m
880
881
882
883!! Local Variables:
884!! mode: f90
885!! coding: utf-8
886!! End:
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:218
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:182
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:1006
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1439
integer, parameter, public accel_mem_read_write
Definition: accel.F90:186
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
This module implements batches of mesh functions.
Definition: batch.F90:135
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:286
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:286
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:286
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module provides the BLACS processor grid.
subroutine, public blacs_proc_grid_end(this)
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_div(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the divergence operator to a vector of mesh functions
subroutine, public distributed_end(this)
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public p_mu
Definition: global.F90:247
real(real64), parameter, public p_ep
Definition: global.F90:246
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
The Helmholtz decomposition is intended to contain "only mathematical" functions and procedures to co...
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1901
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
integer function, public mesh_nearest_point(mesh, pos, dmin, rankmin)
Returns the index of the point which is nearest to a given vector position pos.
Definition: mesh.F90:386
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
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:138
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
Definition: mpi.F90:341
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
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
This module handles spin dimensions of the states and the k-point distribution.
This module handles groups of electronic batches and their parallel distribution.
subroutine, public mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
subroutine, public get_orbital_angular_momentum(mesh, poynting_vector, orbital_angular_momentum)
integer, parameter, public transverse_from_helmholtz
subroutine, public get_rs_state_at_point(rs_state_point, rs_state, pos, st, mesh)
subroutine, public get_electric_field_vector(rs_state_vector, electric_field_vector, ep_element)
subroutine, public build_rs_vector(e_vector, b_vector, rs_sign, rs_vector, ep_element, mu_element)
subroutine, public get_transverse_rs_state(helmholtz, st, namespace)
subroutine, public mxll_get_batch(rs_stateb, rs_state, np, dim, offset)
subroutine, public get_rs_state_batch_selected_points(rs_state_point, rs_stateb, st, mesh)
subroutine, public states_mxll_end(st)
subroutine, public states_mxll_allocate(st, mesh)
Allocates the Maxwell states defined within a states_mxll_t structure.
subroutine, public build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
integer, parameter, public transverse_as_total_minus_long
subroutine, public build_rs_state(e_field, b_field, rs_sign, rs_state, mesh, ep_field, mu_field, np)
subroutine, public states_mxll_init(st, namespace, space)
subroutine, public get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
subroutine, public get_poynting_vector(mesh, st, rs_state, rs_sign, poynting_vector, ep_field, mu_field)
subroutine, public get_divergence_field(gr, field, field_div, charge_density)
subroutine, public get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
subroutine, public get_magnetic_field_vector(rs_state_vector, rs_sign, magnetic_field_vector, mu_element)
type(type_t), parameter, public type_cmplx
Definition: types.F90:136
type(type_t), parameter, 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
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
Class defining batches of mesh functions.
Definition: batch.F90:161
Distribution of N instances over mpi_grpsize processes, for the local rank mpi_grprank....
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
Describes mesh distribution to nodes.
Definition: mesh.F90:187
This is defined even when running serial.
Definition: mpi.F90:144
int true(void)