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 comm_oct_m
26 use debug_oct_m
29 use global_oct_m
30 use grid_oct_m
32 use math_oct_m
33 use mesh_oct_m
36 use mpi_oct_m
39#ifdef HAVE_OPENMP
40 use omp_lib
41#endif
42 use parser_oct_m
46 use space_oct_m
51 use types_oct_m
52 use unit_oct_m
55
56 implicit none
57
58 private
59
60 public :: &
87
88 type :: states_mxll_t
89 ! Components are public by default
90 integer :: dim
91 integer :: rs_sign
92 logical :: pack_states
93 logical :: parallel_in_states = .false.
94 integer, public :: nst
95 logical, public :: packed
96
97 complex(real64), allocatable :: rs_state_plane_waves(:,:)
98 complex(real64), allocatable :: rs_state(:,:)
99 complex(real64), allocatable :: rs_state_prev(:,:)
100 complex(real64), allocatable :: rs_state_trans(:,:)
101 complex(real64), allocatable :: rs_state_long(:,:)
102 complex(real64), allocatable :: rs_current_density_t1(:,:)
103 complex(real64), allocatable :: rs_current_density_t2(:,:)
104
105 logical :: rs_current_density_restart = .false.
106 complex(real64), allocatable :: rs_current_density_restart_t1(:,:)
107 complex(real64), allocatable :: rs_current_density_restart_t2(:,:)
108
109 type(batch_t) :: rs_stateb
110 type(batch_t) :: rs_state_prevb
111 type(batch_t) :: inhomogeneousb
112 type(batch_t) :: rs_state_plane_wavesb
114 real(real64), allocatable :: ep(:)
115 real(real64), allocatable :: mu(:)
116
117 integer, allocatable :: rs_state_fft_map(:,:,:)
118 integer, allocatable :: rs_state_fft_map_inv(:,:)
119
120 real(real64) :: energy_rate
121 real(real64) :: delta_energy
122 real(real64) :: energy_via_flux_calc
123
124 real(real64) :: trans_energy_rate
125 real(real64) :: trans_delta_energy
126 real(real64) :: trans_energy_via_flux_calc
127
128 real(real64) :: plane_waves_energy_rate
129 real(real64) :: plane_waves_delta_energy
130 real(real64) :: plane_waves_energy_via_flux_calc
131
132 real(real64) :: poynting_vector_box_surface(1:2,1:3,1:3) = m_zero
133 real(real64) :: poynting_vector_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
134 real(real64) :: electric_field_box_surface(1:2,1:3,1:3) = m_zero
135 real(real64) :: electric_field_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
136 real(real64) :: magnetic_field_box_surface(1:2,1:3,1:3) = m_zero
137 real(real64) :: magnetic_field_box_surface_plane_waves(1:2,1:3,1:3) = m_zero
138
139 logical :: rs_state_const_external = .false.
140 complex(real64), allocatable :: rs_state_const(:)
141 complex(real64), allocatable :: rs_state_const_amp(:,:)
142 type(tdf_t), allocatable :: rs_state_const_td_function(:)
143
144 integer :: inner_points_number
145 integer, allocatable :: inner_points_map(:)
146 logical, allocatable :: inner_points_mask(:)
147 integer :: boundary_points_number
148 integer, allocatable :: boundary_points_map(:)
149 logical, allocatable :: boundary_points_mask(:)
150 type(accel_mem_t) :: buff_inner_points_map, buff_boundary_points_map
151
152 integer :: surface_points_number(3)
153 integer, allocatable :: surface_points_map(:,:,:)
154 real(real64) :: surface_element(3)
155
156 integer :: surface_grid_rows_number(3)
157 integer, allocatable :: surface_grid_points_number(:,:,:)
158 integer(int64), allocatable :: surface_grid_points_map(:,:,:,:,:)
159 integer, allocatable :: surface_grid_center(:,:,:,:)
160 real(real64) :: surface_grid_element(3)
161
162 type(mesh_plane_t) :: surface(2,3)
163
164 integer :: selected_points_number
165 real(real64), allocatable :: selected_points_coordinate(:,:)
166 complex(real64), allocatable :: selected_points_rs_state(:,:)
167 complex(real64), allocatable :: selected_points_rs_state_long(:,:)
168 complex(real64), allocatable :: selected_points_rs_state_trans(:,:)
169 integer, allocatable :: selected_points_map(:)
170 type(accel_mem_t) :: buff_selected_points_map
171 real(real64) :: rs_state_trans_var
172
173 real(real64), allocatable :: grid_rho(:,:)
174 complex(real64), allocatable :: kappa_psi(:,:)
175
176 character(len=1024), allocatable :: user_def_e_field(:)
177 character(len=1024), allocatable :: user_def_b_field(:)
178
179 integer :: energy_incident_waves_calc_iter
180 logical :: energy_incident_waves_calc
182 ! external current variables
183 integer :: external_current_number
184 integer, allocatable :: external_current_modus(:)
185 character(len=1024), allocatable :: external_current_string(:,:)
186 real(real64), allocatable :: external_current_amplitude(:,:,:)
187 type(tdf_t), allocatable :: external_current_td_function(:)
188 type(tdf_t), allocatable :: external_current_td_phase(:)
189 real(real64), allocatable :: external_current_omega(:)
190 real(real64), allocatable :: external_current_phase(:)
193 character(len=1024), allocatable :: user_def_states(:,:,:)
194 logical :: fromscratch = .true.
195 type(mpi_grp_t) :: mpi_grp
196 type(mpi_grp_t) :: dom_st_mpi_grp
197
198#ifdef HAVE_SCALAPACK
199 type(blacs_proc_grid_t) :: dom_st_proc_grid
200#endif
201 type(distributed_t) :: dist
202 logical :: scalapack_compatible
203 integer :: lnst
204 integer :: st_start, st_end
205 integer, allocatable :: node(:)
206
207 type(poisson_t) :: poisson
208 integer :: transverse_field_mode
209
212 integer, public, parameter :: &
216contains
218 ! ---------------------------------------------------------
219 subroutine states_mxll_init(st, namespace, space)
220 type(states_mxll_t), target, intent(inout) :: st
221 type(namespace_t), intent(in) :: namespace
222 class(space_t), intent(in) :: space
224 type(block_t) :: blk
225 integer :: idim, nlines, ncols, il
226 real(real64), allocatable :: pos(:)
227 integer :: ix_max, iy_max, iz_max
231 call profiling_in('STATES_MXLL_INIT')
233 st%fromScratch = .true. ! this will be reset if restart_read is called
235 assert(space%dim == 3)
236 st%dim = space%dim
237 st%nst = 1
239 safe_allocate(st%user_def_e_field(1:st%dim))
240 safe_allocate(st%user_def_b_field(1:st%dim))
242 st%st_start = 1
243 st%st_end = st%nst
244 st%lnst = st%nst
246 safe_allocate(st%node(1:st%nst))
247 st%node(1:st%nst) = 0
248
250 st%parallel_in_states = .false.
251 st%packed = .false.
253 ! The variable StatesPack is documented in states_elec.F90.
254 ! We cannot include the documentation twice.
255 ! TODO: We should think whether these variables could be moved to a higher (abstract) class.
256
257 call parse_variable(namespace, 'StatesPack', .true., st%pack_states)
259 call messages_print_var_value('StatesPack', st%pack_states, namespace=namespace)
261 !rs_sign is not defined any more by the user, since it does not influence
262 !the results of the simulations.
263 st%rs_sign = 1
265 !%Variable MaxwellFieldsCoordinate
266 !%Type block
267 !%Section Maxwell::Output
268 !%Description
269 !% The Maxwell MaxwellFieldsCoordinate block allows to output Maxwell fields at particular
270 !% points in space. For each point a new line with three columns has to be added to the block,
271 !% where the columns denote the x, y, and z coordinate of the point.
272 !%
273 !% <tt>%MaxwellFieldsCoordinate
274 !% <br>&nbsp;&nbsp; -1.0 | 2.0 | 4.0
275 !% <br>&nbsp;&nbsp; 0.0 | 1.0 | -2.0
276 !% <br>%</tt>
277 !%
278 !%End
280 safe_allocate(pos(1:st%dim))
281 st%selected_points_number = 1
282 if (parse_block(namespace, 'MaxwellFieldsCoordinate', blk) == 0) then
283 nlines = parse_block_n(blk)
284 st%selected_points_number = nlines
285 safe_allocate(st%selected_points_coordinate(1:st%dim,1:nlines))
286 safe_allocate(st%selected_points_rs_state(1:st%dim,1:nlines))
287 safe_allocate(st%selected_points_rs_state_long(1:st%dim,1:nlines))
288 safe_allocate(st%selected_points_rs_state_trans(1:st%dim,1:nlines))
289 safe_allocate(st%selected_points_map(1:nlines))
290 do il = 1, nlines
291 ncols = parse_block_cols(blk,0)
292 if (ncols < 3 .or. ncols > 3) then
293 message(1) = 'MaxwellFieldCoordinate must have 3 columns.'
294 call messages_fatal(1, namespace=namespace)
295 end if
296 do idim = 1, st%dim
297 call parse_block_float(blk, il-1, idim-1, pos(idim), units_inp%length)
298 end do
299 st%selected_points_coordinate(:,il) = pos
300 st%selected_points_rs_state(:,il) = m_z0
301 st%selected_points_rs_state_long(:,il) = m_z0
302 st%selected_points_rs_state_trans(:,il) = m_z0
303 end do
304 call parse_block_end(blk)
305 else
306 safe_allocate(st%selected_points_coordinate(1:st%dim, 1))
307 safe_allocate(st%selected_points_rs_state(1:st%dim, 1))
308 safe_allocate(st%selected_points_rs_state_long(1:st%dim, 1))
309 safe_allocate(st%selected_points_rs_state_trans(1:st%dim, 1))
310 safe_allocate(st%selected_points_map(1))
311 st%selected_points_coordinate(:,:) = m_zero
312 st%selected_points_rs_state(:,:) = m_z0
313 st%selected_points_rs_state_long(:,:) = m_z0
314 st%selected_points_rs_state_trans(:,:) = m_z0
315 st%selected_points_map(:) = -1
316 end if
317
318 safe_deallocate_a(pos)
319
320 st%surface_grid_rows_number(1) = 3
321 ix_max = st%surface_grid_rows_number(1)
322 st%surface_grid_rows_number(2) = 3
323 iy_max = st%surface_grid_rows_number(2)
324 st%surface_grid_rows_number(3) = 3
325 iz_max = st%surface_grid_rows_number(3)
326
327 safe_allocate(st%surface_grid_center(1:2, 1:st%dim, 1:ix_max, 1:iy_max))
328 safe_allocate(st%surface_grid_points_number(1:st%dim, 1:ix_max, 1:iy_max))
329
330 !%Variable TransverseFieldCalculation
331 !%Type integer
332 !%Default no
333 !%Section Maxwell
334 !%Description
335 !% This variable selects the method for the calculation of the transverse field.
336 !%Option helmholtz 1
337 !% Transverse field calculated from Helmholtz decompisition (unreliable at the moment).
338 !%Option total_minus_long 2
339 !% Total field minus longitudinal field.
340 !%End
341 call parse_variable(namespace, 'TransverseFieldCalculation', transverse_from_helmholtz, &
342 st%transverse_field_mode)
343
344 call profiling_out('STATES_MXLL_INIT')
345
346 pop_sub(states_mxll_init)
347
348 end subroutine states_mxll_init
349
350 ! ---------------------------------------------------------
352 subroutine states_mxll_allocate(st, mesh)
353 type(states_mxll_t), intent(inout) :: st
354 class(mesh_t), intent(in) :: mesh
355
356
357 push_sub(states_mxll_allocate)
358
359 call profiling_in('STATES_MXLL_ALLOCATE')
360
361 safe_allocate(st%rs_state(1:mesh%np_part, 1:st%dim))
362 st%rs_state(:,:) = m_z0
363
364 safe_allocate(st%rs_state_prev(1:mesh%np_part, 1:st%dim))
365 st%rs_state_prev(:,:) = m_z0
366
367 safe_allocate(st%rs_state_trans(1:mesh%np_part, 1:st%dim))
368 st%rs_state_trans(:,:) = m_z0
369
370 safe_allocate(st%rs_state_long(1:mesh%np_part, 1:st%dim))
371 st%rs_state_long(:,:) = m_z0
372
373 safe_allocate(st%rs_state_plane_waves(1:mesh%np_part, 1:st%dim))
374 st%rs_state_plane_waves(:,:) = m_z0
375
376 safe_allocate(st%rs_current_density_t1(1:mesh%np, 1:st%dim))
377 st%rs_current_density_t1 = m_z0
378
379 safe_allocate(st%rs_current_density_t2(1:mesh%np, 1:st%dim))
380 st%rs_current_density_t2 = m_z0
381
382 safe_allocate(st%rs_current_density_restart_t1(1:mesh%np_part, 1:st%dim))
383 st%rs_current_density_restart_t1 = m_z0
384
385 safe_allocate(st%rs_current_density_restart_t2(1:mesh%np_part, 1:st%dim))
386 st%rs_current_density_restart_t2 = m_z0
387
388 safe_allocate(st%ep(1:mesh%np_part))
389 safe_allocate(st%mu(1:mesh%np_part))
390 st%ep = p_ep
391 st%mu = p_mu
392
393 call profiling_out('STATES_MXLL_ALLOCATE')
394
395 pop_sub(states_mxll_allocate)
396 end subroutine states_mxll_allocate
397
398 ! ---------------------------------------------------------
399 subroutine states_mxll_end(st)
400 type(states_mxll_t), intent(inout) :: st
401
402
403 push_sub(states_mxll_end)
404
405 call profiling_in('STATES_MXLL_END')
406
407 safe_deallocate_a(st%rs_state)
408 safe_deallocate_a(st%rs_state_prev)
409 safe_deallocate_a(st%rs_state_trans)
410 safe_deallocate_a(st%selected_points_coordinate)
411 safe_deallocate_a(st%selected_points_rs_state)
412 safe_deallocate_a(st%selected_points_rs_state_long)
413 safe_deallocate_a(st%selected_points_rs_state_trans)
414 safe_deallocate_a(st%rs_current_density_t1)
415 safe_deallocate_a(st%rs_current_density_t2)
416 safe_deallocate_a(st%rs_state_long)
417 safe_deallocate_a(st%rs_current_density_restart_t1)
418 safe_deallocate_a(st%rs_current_density_restart_t2)
419 safe_deallocate_a(st%user_def_e_field)
420 safe_deallocate_a(st%user_def_b_field)
421
422 safe_deallocate_a(st%rs_state_const)
423 safe_deallocate_a(st%rs_state_const_td_function)
424 safe_deallocate_a(st%rs_state_const_amp)
425 safe_deallocate_a(st%rs_state_plane_waves)
426
427 safe_deallocate_a(st%surface_grid_center)
428 safe_deallocate_a(st%surface_grid_points_number)
429 safe_deallocate_a(st%surface_grid_points_map)
430 safe_deallocate_a(st%inner_points_map)
431 safe_deallocate_a(st%boundary_points_map)
432 safe_deallocate_a(st%inner_points_mask)
433 safe_deallocate_a(st%boundary_points_mask)
434 safe_deallocate_a(st%ep)
435 safe_deallocate_a(st%mu)
436 if (accel_is_enabled()) then
437 call accel_release_buffer(st%buff_inner_points_map)
438 call accel_release_buffer(st%buff_boundary_points_map)
439 call accel_release_buffer(st%buff_selected_points_map)
440 end if
441#ifdef HAVE_SCALAPACK
442 call blacs_proc_grid_end(st%dom_st_proc_grid)
443#endif
444 safe_deallocate_a(st%external_current_modus)
445 safe_deallocate_a(st%external_current_string)
446 safe_deallocate_a(st%external_current_amplitude)
447 safe_deallocate_a(st%external_current_td_function)
448 safe_deallocate_a(st%external_current_omega)
449 safe_deallocate_a(st%external_current_td_phase)
450
451 call distributed_end(st%dist)
452 safe_deallocate_a(st%node)
453
454 call profiling_out('STATES_MXLL_END')
455
456 pop_sub(states_mxll_end)
457 end subroutine states_mxll_end
458
459
460 !----------------------------------------------------------
461 subroutine build_rs_element(e_element, b_element, rs_sign, rs_element, ep_element, mu_element)
462 real(real64), intent(in) :: e_element, b_element
463 complex(real64), intent(inout) :: rs_element
464 integer, intent(in) :: rs_sign
465 real(real64), optional, intent(in) :: ep_element
466 real(real64), optional, intent(in) :: mu_element
467
468 ! no PUSH_SUB, called too often
469
470 if (present(ep_element) .and. present(mu_element)) then
471 rs_element = sqrt(ep_element/m_two) * e_element + m_zi * rs_sign * sqrt(m_one/(m_two*mu_element)) * b_element
472 else
473 rs_element = sqrt(p_ep/m_two) * e_element + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_element
474 end if
475
476 end subroutine build_rs_element
477
478
479 !----------------------------------------------------------
480 subroutine build_rs_vector(e_vector, b_vector, rs_sign, rs_vector, ep_element, mu_element)
481 real(real64), intent(in) :: e_vector(:), b_vector(:)
482 complex(real64), intent(inout) :: rs_vector(:)
483 integer, intent(in) :: rs_sign
484 real(real64), optional, intent(in) :: ep_element
485 real(real64), optional, intent(in) :: mu_element
486
487 ! no PUSH_SUB, called too often
488
489 if (present(ep_element) .and. present(mu_element)) then
490 rs_vector = sqrt(ep_element/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*mu_element)) * b_vector
491 else
492 rs_vector = sqrt(p_ep/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_vector
493 end if
494
495 end subroutine build_rs_vector
496
497
498 !----------------------------------------------------------
499 subroutine build_rs_state(e_field, b_field, rs_sign, rs_state, mesh, ep_field, mu_field, np)
500 real(real64), intent(in) :: e_field(:,:), b_field(:,:)
501 complex(real64), intent(inout) :: rs_state(:,:)
502 integer, intent(in) :: rs_sign
503 class(mesh_t), intent(in) :: mesh
504 real(real64), optional, intent(in) :: ep_field(:)
505 real(real64), optional, intent(in) :: mu_field(:)
506 integer, optional, intent(in) :: np
507
508 integer :: ip, np_
509
510 push_sub(build_rs_state)
511
512 call profiling_in('BUILD_RS_STATE')
513
514 np_ = optional_default(np, mesh%np)
515
516 do ip = 1, np_
517 if (present(ep_field) .and. present(mu_field)) then
518 rs_state(ip, :) = sqrt(ep_field(ip)/m_two) * e_field(ip, :) &
519 + m_zi * rs_sign * sqrt(m_one/(m_two*mu_field(ip))) * b_field(ip, :)
520 else
521 rs_state(ip, :) = sqrt(p_ep/m_two) * e_field(ip, :) &
522 + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_field(ip, :)
523 end if
524 end do
525
526 call profiling_out('BUILD_RS_STATE')
527
528 pop_sub(build_rs_state)
529
530 end subroutine build_rs_state
531
532
533 !----------------------------------------------------------
534 subroutine build_rs_current_element(current_element, rs_current_element, ep_element)
535 real(real64), intent(in) :: current_element
536 complex(real64), intent(inout) :: rs_current_element
537 real(real64), optional, intent(in) :: ep_element
538
539 ! no PUSH_SUB, called too often
540
541 if (present(ep_element)) then
542 rs_current_element = m_one/sqrt(m_two*ep_element) * current_element
543 else
544 rs_current_element = m_one/sqrt(m_two*p_ep) * current_element
545 end if
546
547 end subroutine build_rs_current_element
548
549
550 !----------------------------------------------------------
551 subroutine build_rs_current_vector(current_vector, rs_current_vector, ep_element)
552 real(real64), intent(in) :: current_vector(:)
553 complex(real64), intent(inout) :: rs_current_vector(:)
554 real(real64), optional, intent(in) :: ep_element
555
556 ! no PUSH_SUB, called too often
557 if (present(ep_element)) then
558 rs_current_vector = m_one/sqrt(m_two*ep_element) * current_vector
559 else
560 rs_current_vector = m_one/sqrt(m_two*p_ep) * current_vector
561 end if
562
563 end subroutine build_rs_current_vector
564
565
566 !----------------------------------------------------------
567 subroutine build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
568 real(real64), intent(in) :: current_state(:,:)
569 class(mesh_t), intent(in) :: mesh
570 complex(real64), intent(inout) :: rs_current_state(:,:)
571 real(real64), optional, intent(in) :: ep_field(:)
572 integer, optional, intent(in) :: np
574 integer :: ip, idim, np_, ff_dim
575
576 ! no PUSH_SUB, called too often
577
578 call profiling_in("BUILD_RS_CURRENT_STATE")
579
580 np_ = optional_default(np, mesh%np)
581 ff_dim = size(current_state, dim=2)
582
583 if (present(ep_field)) then
584 do idim = 1, ff_dim
585 do ip = 1, np_
586 rs_current_state(ip, idim) = m_one/sqrt(m_two*ep_field(ip)) * current_state(ip, idim)
587 end do
588 end do
589 else
590 do idim = 1, ff_dim
591 do ip = 1, np_
592 rs_current_state(ip, idim) = m_one/sqrt(m_two*p_ep) * current_state(ip, idim)
593 end do
594 end do
595 end if
596
597 call profiling_out("BUILD_RS_CURRENT_STATE")
598
599 end subroutine build_rs_current_state
600
601
602 !----------------------------------------------------------
603 subroutine get_electric_field_vector(rs_state_vector, electric_field_vector, ep_element)
604 complex(real64), intent(in) :: rs_state_vector(:)
605 real(real64), intent(out) :: electric_field_vector(:)
606 real(real64), optional, intent(in) :: ep_element
607
608 ! no PUSH_SUB, called too often
609
610 if (present(ep_element)) then
611 electric_field_vector(:) = sqrt(m_two/ep_element) * real(rs_state_vector(:), real64)
612 else
613 electric_field_vector(:) = sqrt(m_two/p_ep) * real(rs_state_vector(:), real64)
614 end if
615
616 end subroutine get_electric_field_vector
617
618
619 !----------------------------------------------------------
620 subroutine get_magnetic_field_vector(rs_state_vector, rs_sign, magnetic_field_vector, mu_element)
621 complex(real64), intent(in) :: rs_state_vector(:)
622 integer, intent(in) :: rs_sign
623 real(real64), intent(out) :: magnetic_field_vector(:)
624 real(real64), optional, intent(in) :: mu_element
625
626 ! no PUSH_SUB, called too often
628 if (present(mu_element)) then
629 magnetic_field_vector(:) = sqrt(m_two*mu_element) * rs_sign * aimag(rs_state_vector(:))
630 else
631 magnetic_field_vector(:) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state_vector(:))
632 end if
633
634 end subroutine get_magnetic_field_vector
635
636
637 !----------------------------------------------------------
638 subroutine get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
639 complex(real64), intent(in) :: rs_state(:,:)
640 class(mesh_t), intent(in) :: mesh
641 real(real64), intent(out) :: electric_field(:,:)
642 real(real64), optional, intent(in) :: ep_field(:)
643 integer, optional, intent(in) :: np
645 integer :: ip, np_
646
648
649 call profiling_in('GET_ELECTRIC_FIELD_STATE')
650
651 np_ = optional_default(np, mesh%np)
652
653 do ip = 1, np_
654 if (present(ep_field)) then
655 electric_field(ip, :) = sqrt(m_two/ep_field(ip)) * real(rs_state(ip, :), real64)
656 else
657 electric_field(ip,:) = sqrt(m_two/p_ep) * real(rs_state(ip, :), real64)
658 end if
659 end do
661 call profiling_out('GET_ELECTRIC_FIELD_STATE')
662
664
665 end subroutine get_electric_field_state
666
667
668 !----------------------------------------------------------
669 subroutine get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
670 complex(real64), intent(in) :: rs_state(:,:)
671 class(mesh_t), intent(in) :: mesh
672 integer, intent(in) :: rs_sign
673 real(real64), intent(out) :: magnetic_field(:,:)
674 real(real64), optional, intent(in) :: mu_field(:)
675 integer, optional, intent(in) :: np
676
677 integer :: ip, np_
678
680
681 call profiling_in('GET_MAGNETIC_FIELD_STATE')
682
683 np_ = optional_default(np, mesh%np)
684
685 if (present(mu_field)) then
686 do ip = 1, np_
687 magnetic_field(ip, :) = sqrt(m_two*mu_field(ip)) * rs_sign * aimag(rs_state(ip, :))
688 end do
689 else
690 do ip = 1, np_
691 magnetic_field(ip, :) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state(ip, :))
692 end do
693 end if
694
695 call profiling_out('GET_MAGNETIC_FIELD_STATE')
698
699 end subroutine get_magnetic_field_state
700
701 !----------------------------------------------------------
702 subroutine get_current_element(rs_current_element, current_element, ep_element)
703 complex(real64), intent(in) :: rs_current_element
704 real(real64), intent(inout) :: current_element
705 real(real64), optional, intent(in) :: ep_element
706
707 ! no PUSH_SUB, called too often
708
709 if (present(ep_element)) then
710 current_element = sqrt(m_two*ep_element) * real(rs_current_element, real64)
711 else
712 current_element = sqrt(m_two*p_ep) * real(rs_current_element, real64)
713 end if
714
715 end subroutine get_current_element
716
717
718 !----------------------------------------------------------
719 subroutine get_current_vector(rs_current_vector, current_vector, ep_element)
720 complex(real64), intent(in) :: rs_current_vector(:)
721 real(real64), intent(inout) :: current_vector(:)
722 real(real64), optional, intent(in) :: ep_element
723
724 ! no PUSH_SUB, called too often
725
726 if (present(ep_element)) then
727 current_vector(:) = sqrt(m_two*ep_element) * real(rs_current_vector(:), real64)
728 else
729 current_vector(:) = sqrt(m_two*p_ep) * real(rs_current_vector(:), real64)
730 end if
732 end subroutine get_current_vector
733
734
735 !----------------------------------------------------------
736 subroutine get_current_state(rs_current_field, current_field, mesh, ep_field, np)
737 complex(real64), intent(in) :: rs_current_field(:,:)
738 real(real64), intent(inout) :: current_field(:,:)
739 real(real64), optional, intent(in) :: ep_field(:)
740 class(mesh_t), intent(in) :: mesh
741 integer, optional, intent(in) :: np
742
743 integer :: ip, np_
744
745 push_sub(get_current_state)
746
747 np_ = optional_default(np, mesh%np)
748
749 do ip = 1, np_
750 if (present(ep_field)) then
751 current_field(ip, :) = sqrt(m_two*ep_field(ip)) * real(rs_current_field(ip, :), real64)
752 else
753 current_field(ip, :) = sqrt(m_two*p_ep) * real(rs_current_field(ip, :), real64)
754 end if
755 end do
756
757 pop_sub(get_current_state)
758
759 end subroutine get_current_state
760
761
762 !----------------------------------------------------------
763 subroutine get_rs_state_at_point(rs_state_point, rs_state, pos, st, mesh)
764
765 complex(real64), intent(inout) :: rs_state_point(:,:)
766 complex(real64), intent(in) :: rs_state(:,:)
767 real(real64), intent(in) :: pos(:,:)
768 type(states_mxll_t), intent(in) :: st
769 class(mesh_t), intent(in) :: mesh
770
771 integer :: ip, pos_index, rankmin
772 real(real64) :: dmin
773 complex(real64), allocatable :: ztmp(:)
774
775 push_sub(get_rs_state_at_point)
776
777 safe_allocate(ztmp(1:size(rs_state, dim=2)))
778
779 do ip = 1, st%selected_points_number
780 pos_index = mesh_nearest_point(mesh, pos(:,ip), dmin, rankmin)
781 if (mesh%mpi_grp%rank == rankmin) then
782 ztmp(:) = rs_state(pos_index, :)
783 end if
784 if (mesh%parallel_in_domains) then
785 call mesh%mpi_grp%bcast(ztmp, st%dim, mpi_double_complex, rankmin)
786 end if
787 rs_state_point(:, ip) = ztmp(:)
788 end do
789
790 safe_deallocate_a(ztmp)
791
792
793 pop_sub(get_rs_state_at_point)
794 end subroutine get_rs_state_at_point
796
797 !----------------------------------------------------------
798 subroutine get_rs_state_batch_selected_points(rs_state_point, rs_stateb, st, mesh)
799 complex(real64), contiguous, intent(inout) :: rs_state_point(:,:)
800 type(batch_t), intent(in) :: rs_stateb
801 type(states_mxll_t), intent(in) :: st
802 class(mesh_t), intent(in) :: mesh
803
804 integer :: ip_in, ip
805 complex(real64) :: rs_state_tmp(1:st%dim, 1:st%selected_points_number)
806 type(accel_kernel_t), save :: kernel
807 type(accel_mem_t) :: buff_points
808 integer(int64) :: localsize, dim3, dim2
809
811
812 rs_state_tmp(:,:) = m_z0
813
814 select case (rs_stateb%status())
815 case (batch_not_packed)
816 do ip_in = 1, st%selected_points_number
817 ip = st%selected_points_map(ip_in)
818 if (ip >= 0) then
819 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_linear(ip, 1:st%dim)
820 end if
821 end do
822 case (batch_packed)
823 do ip_in = 1, st%selected_points_number
824 ip = st%selected_points_map(ip_in)
825 if (ip >= 0) then
826 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_pack(1:st%dim, ip)
827 end if
828 end do
830 call accel_kernel_start_call(kernel, 'get_points.cl', 'get_selected_points')
831
833 st%selected_points_number*st%dim)
834 call accel_set_buffer_to_zero(buff_points, type_integer, st%selected_points_number*st%dim)
835
836 call accel_set_kernel_arg(kernel, 0, st%selected_points_number)
837 call accel_set_kernel_arg(kernel, 1, st%buff_selected_points_map)
838 call accel_set_kernel_arg(kernel, 2, rs_stateb%ff_device)
839 call accel_set_kernel_arg(kernel, 3, log2(int(rs_stateb%pack_size_real(1), int32)))
840 call accel_set_kernel_arg(kernel, 4, buff_points)
841 call accel_set_kernel_arg(kernel, 5, st%dim*2)
842
843 localsize = accel_kernel_workgroup_size(kernel)/rs_stateb%pack_size_real(1)
844
845 dim3 = st%selected_points_number/(accel_max_size_per_dim(2)*localsize) + 1
846 dim2 = min(accel_max_size_per_dim(2)*localsize, pad(st%selected_points_number, localsize))
847
848 call accel_kernel_run(kernel, (/rs_stateb%pack_size_real(1), dim2, dim3/), &
849 (/rs_stateb%pack_size_real(1), localsize, 1_int64/))
850 call accel_read_buffer(buff_points, st%selected_points_number*st%dim, rs_state_tmp)
851 call accel_release_buffer(buff_points)
852 end select
853
854 call mesh%mpi_grp%allreduce(rs_state_tmp, rs_state_point, st%selected_points_number*st%dim, mpi_double_complex, mpi_sum)
855
858
859 !----------------------------------------------------------
860 subroutine get_divergence_field(gr, field, field_div, charge_density)
861 type(grid_t), intent(in) :: gr
862 real(real64), contiguous, intent(inout) :: field(:,:)
863 real(real64), contiguous, intent(inout) :: field_div(:)
864 logical, intent(in) :: charge_density
865
866 push_sub(get_divergence_field)
867
868 call dderivatives_div(gr%der, field, field_div)
869
870 if (optional_default(charge_density,.false.)) then
871 field_div = p_ep * field_div
872 end if
873
874 pop_sub(get_divergence_field)
875 end subroutine get_divergence_field
876
877
878 ! ---------------------------------------------------------
879 subroutine get_poynting_vector(mesh, st, rs_state, rs_sign, poynting_vector, ep_field, mu_field)
880 class(mesh_t), intent(in) :: mesh
881 type(states_mxll_t), intent(in) :: st
882 complex(real64), intent(in) :: rs_state(:,:)
883 integer, intent(in) :: rs_sign
884 real(real64), intent(out) :: poynting_vector(:,:)
885 real(real64), optional, intent(in) :: ep_field(:)
886 real(real64), optional, intent(in) :: mu_field(:)
887
888 integer :: ip
889
890 push_sub(get_poynting_vector)
891 if (present(ep_field) .and. present(mu_field)) then
892 do ip = 1, mesh%np
893 poynting_vector(ip, 1:3) = m_one/mu_field(ip) * sqrt(m_two/ep_field(ip)) &
894 * sqrt(m_two*mu_field(ip)) &
895 * dcross_product(real(rs_state(ip, 1:3), real64) , &
896 rs_sign*aimag(rs_state(ip,1:3)))
897 end do
898 else
899 do ip = 1, mesh%np
900 poynting_vector(ip, 1:3) = m_one/st%mu(ip) * sqrt(m_two/st%ep(ip)) &
901 * sqrt(m_two*st%mu(ip)) &
902 * dcross_product(real(rs_state(ip, 1:3), real64) , &
903 rs_sign*aimag(rs_state(ip, 1:3)))
904 end do
905 end if
906
907 pop_sub(get_poynting_vector)
908 end subroutine get_poynting_vector
909
910
911 ! ---------------------------------------------------------
912 subroutine get_poynting_vector_plane_waves(mesh, st, rs_sign, poynting_vector)
913 class(mesh_t), intent(in) :: mesh
914 type(states_mxll_t), intent(in) :: st
915 integer, intent(in) :: rs_sign
916 real(real64), intent(out) :: poynting_vector(:,:)
917
918 integer :: ip
919
921
922 do ip = 1, mesh%np
923 poynting_vector(ip, :) = m_one/p_mu * sqrt(m_two/p_ep) * sqrt(m_two*p_mu) &
924 * dcross_product(real(st%rs_state_plane_waves(ip,:), real64) , &
925 rs_sign*aimag(st%rs_state_plane_waves(ip,:)))
926 end do
927
930
931
932 ! ---------------------------------------------------------
933 subroutine get_orbital_angular_momentum(mesh, st, poynting_vector, orbital_angular_momentum)
934 type(mesh_t), intent(in) :: mesh
935 type(states_mxll_t), intent(in) :: st
936 real(real64), intent(in) :: poynting_vector(:,:)
937 real(real64), intent(out) :: orbital_angular_momentum(:,:)
938
939 integer :: ip
940
942
943 do ip = 1, mesh%np
944 orbital_angular_momentum(ip,1:3) = dcross_product(real(mesh%x(ip, 1:3), real64) , &
945 poynting_vector(ip, 1:3))
946 end do
947
949 end subroutine get_orbital_angular_momentum
950
951 ! ---------------------------------------------------------
952 subroutine mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
953 type(batch_t), intent(inout) :: rs_stateb
954 complex(real64), contiguous, intent(in) :: rs_state(:, :)
955 integer, intent(in) :: np
956 integer, intent(in) :: dim
957 integer, optional, intent(in) :: offset
958
959 integer :: offset_, idir
960
961 push_sub(mxll_set_batch)
962
963 offset_ = optional_default(offset, 1)
964
965 do idir = offset_, offset_ + dim - 1
966 call batch_set_state(rs_stateb, idir, np, rs_state(:, idir))
967 end do
968
969 pop_sub(mxll_set_batch)
970 end subroutine mxll_set_batch
971
972 ! ---------------------------------------------------------
973 subroutine mxll_get_batch(rs_stateb, rs_state, np, dim, offset)
974 type(batch_t), intent(in) :: rs_stateb
975 complex(real64), contiguous, intent(out) :: rs_state(:, :)
976 integer, intent(in) :: np
977 integer, intent(in) :: dim
978 integer, optional, intent(in) :: offset
979
980 integer :: offset_, idir
981
982 push_sub(mxll_get_batch)
983
984 offset_ = optional_default(offset, 1)
985
986 do idir = offset_, offset_ + dim - 1
987 call batch_get_state(rs_stateb, idir, np, rs_state(:, idir))
988 end do
989
990 pop_sub(mxll_get_batch)
991 end subroutine mxll_get_batch
992
993 !----------------------------------------------------------
994 subroutine get_transverse_rs_state(helmholtz, st, namespace)
995 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
996 type(states_mxll_t), intent(inout) :: st
997 type(namespace_t), intent(in) :: namespace
998
999
1000 push_sub(get_transverse_rs_state)
1001
1002 call profiling_in('GET_TRANSVERSE_RS_STATE')
1003
1004 select case (st%transverse_field_mode)
1006 call helmholtz%get_trans_field(namespace, st%rs_state_trans, total_field=st%rs_state)
1008 call helmholtz%get_long_field(namespace, st%rs_state_long, total_field=st%rs_state)
1009 st%rs_state_trans = st%rs_state - st%rs_state_long
1010 case default
1011 message(1) = 'Unknown transverse field calculation mode.'
1012 call messages_fatal(1, namespace=namespace)
1013 end select
1014
1015 call profiling_out('GET_TRANSVERSE_RS_STATE')
1016
1018
1019 end subroutine get_transverse_rs_state
1020
1021
1022end module states_mxll_oct_m
1023
1024
1025
1026!! Local Variables:
1027!! mode: f90
1028!! coding: utf-8
1029!! End:
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:199
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:180
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:2144
integer, parameter, public accel_mem_read_write
Definition: accel.F90:183
integer pure function, public accel_max_size_per_dim(dim)
Definition: accel.F90:2179
subroutine, public accel_release_buffer(this)
Definition: accel.F90:1246
pure logical function, public accel_is_enabled()
Definition: accel.F90:400
integer function, public accel_kernel_workgroup_size(kernel)
Definition: accel.F90:1478
This module implements batches of mesh functions.
Definition: batch.F90:133
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:276
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:276
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:276
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
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:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public p_mu
Definition: global.F90:228
real(real64), parameter, public p_ep
Definition: global.F90:227
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_one
Definition: global.F90:188
This module implements the underlying real-space grid.
Definition: grid.F90:117
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:115
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1833
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
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:380
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:136
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
Definition: mpi.F90:346
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
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 get_poynting_vector_plane_waves(mesh, st, rs_sign, poynting_vector)
subroutine, public mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
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 get_current_vector(rs_current_vector, current_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 build_rs_current_element(current_element, rs_current_element, ep_element)
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_element(e_element, b_element, rs_sign, rs_element, ep_element, mu_element)
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_current_element(rs_current_element, current_element, ep_element)
subroutine, public get_current_state(rs_current_field, current_field, mesh, ep_field, np)
subroutine, public get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
subroutine, public build_rs_current_vector(current_vector, rs_current_vector, ep_element)
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)
subroutine, public get_orbital_angular_momentum(mesh, st, poynting_vector, orbital_angular_momentum)
type(type_t), public type_cmplx
Definition: types.F90:134
type(type_t), public type_integer
Definition: types.F90:135
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
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:159
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:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
This is defined even when running serial.
Definition: mpi.F90:142
int true(void)