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
113
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
181
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(:)
191
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 type(mpi_grp_t) :: system_grp
199#ifdef HAVE_SCALAPACK
200 type(blacs_proc_grid_t) :: dom_st_proc_grid
201#endif
202 type(distributed_t) :: dist
203 logical :: scalapack_compatible
204 integer :: lnst
205 integer :: st_start, st_end
206 integer, allocatable :: node(:)
208 type(poisson_t) :: poisson
209 integer :: transverse_field_mode
211 end type states_mxll_t
213 integer, public, parameter :: &
217contains
218
219 ! ---------------------------------------------------------
220 subroutine states_mxll_init(st, namespace, space)
221 type(states_mxll_t), target, intent(inout) :: st
222 type(namespace_t), intent(in) :: namespace
223 class(space_t), intent(in) :: space
225 type(block_t) :: blk
226 integer :: idim, nlines, ncols, il
227 real(real64), allocatable :: pos(:)
228 integer :: ix_max, iy_max, iz_max
232 call profiling_in('STATES_MXLL_INIT')
233
234 st%fromScratch = .true. ! this will be reset if restart_read is called
236 assert(space%dim == 3)
237 st%dim = space%dim
238 st%nst = 1
240 safe_allocate(st%user_def_e_field(1:st%dim))
241 safe_allocate(st%user_def_b_field(1:st%dim))
243 st%st_start = 1
244 st%st_end = st%nst
245 st%lnst = st%nst
246
247 safe_allocate(st%node(1:st%nst))
248 st%node(1:st%nst) = 0
250 call mpi_grp_init(st%mpi_grp, mpi_comm_undefined)
251 st%parallel_in_states = .false.
252 st%packed = .false.
254 ! The variable StatesPack is documented in states_elec.F90.
255 ! We cannot include the documentation twice.
256 ! TODO: We should think whether these variables could be moved to a higher (abstract) class.
258 call parse_variable(namespace, 'StatesPack', .true., st%pack_states)
260 call messages_print_var_value('StatesPack', st%pack_states, namespace=namespace)
262 !rs_sign is not defined any more by the user, since it does not influence
263 !the results of the simulations.
264 st%rs_sign = 1
266 !%Variable MaxwellFieldsCoordinate
267 !%Type block
268 !%Section Maxwell::Output
269 !%Description
270 !% The Maxwell MaxwellFieldsCoordinate block allows to output Maxwell fields at particular
271 !% points in space. For each point a new line with three columns has to be added to the block,
272 !% where the columns denote the x, y, and z coordinate of the point.
273 !%
274 !% <tt>%MaxwellFieldsCoordinate
275 !% <br>&nbsp;&nbsp; -1.0 | 2.0 | 4.0
276 !% <br>&nbsp;&nbsp; 0.0 | 1.0 | -2.0
277 !% <br>%</tt>
278 !%
279 !%End
281 safe_allocate(pos(1:st%dim))
282 st%selected_points_number = 1
283 if (parse_block(namespace, 'MaxwellFieldsCoordinate', blk) == 0) then
284 nlines = parse_block_n(blk)
285 st%selected_points_number = nlines
286 safe_allocate(st%selected_points_coordinate(1:st%dim,1:nlines))
287 safe_allocate(st%selected_points_rs_state(1:st%dim,1:nlines))
288 safe_allocate(st%selected_points_rs_state_long(1:st%dim,1:nlines))
289 safe_allocate(st%selected_points_rs_state_trans(1:st%dim,1:nlines))
290 safe_allocate(st%selected_points_map(1:nlines))
291 do il = 1, nlines
292 ncols = parse_block_cols(blk,0)
293 if (ncols < 3 .or. ncols > 3) then
294 message(1) = 'MaxwellFieldCoordinate must have 3 columns.'
295 call messages_fatal(1, namespace=namespace)
296 end if
297 do idim = 1, st%dim
298 call parse_block_float(blk, il-1, idim-1, pos(idim), units_inp%length)
299 end do
300 st%selected_points_coordinate(:,il) = pos
301 st%selected_points_rs_state(:,il) = m_z0
302 st%selected_points_rs_state_long(:,il) = m_z0
303 st%selected_points_rs_state_trans(:,il) = m_z0
304 end do
305 call parse_block_end(blk)
306 else
307 safe_allocate(st%selected_points_coordinate(1:st%dim, 1))
308 safe_allocate(st%selected_points_rs_state(1:st%dim, 1))
309 safe_allocate(st%selected_points_rs_state_long(1:st%dim, 1))
310 safe_allocate(st%selected_points_rs_state_trans(1:st%dim, 1))
311 safe_allocate(st%selected_points_map(1))
312 st%selected_points_coordinate(:,:) = m_zero
313 st%selected_points_rs_state(:,:) = m_z0
314 st%selected_points_rs_state_long(:,:) = m_z0
315 st%selected_points_rs_state_trans(:,:) = m_z0
316 st%selected_points_map(:) = -1
317 end if
318
319 safe_deallocate_a(pos)
320
321 st%surface_grid_rows_number(1) = 3
322 ix_max = st%surface_grid_rows_number(1)
323 st%surface_grid_rows_number(2) = 3
324 iy_max = st%surface_grid_rows_number(2)
325 st%surface_grid_rows_number(3) = 3
326 iz_max = st%surface_grid_rows_number(3)
327
328 safe_allocate(st%surface_grid_center(1:2, 1:st%dim, 1:ix_max, 1:iy_max))
329 safe_allocate(st%surface_grid_points_number(1:st%dim, 1:ix_max, 1:iy_max))
330
331 !%Variable TransverseFieldCalculation
332 !%Type integer
333 !%Default no
334 !%Section Maxwell
335 !%Description
336 !% This variable selects the method for the calculation of the transverse field.
337 !%Option helmholtz 1
338 !% Transverse field calculated from Helmholtz decompisition (unreliable at the moment).
339 !%Option total_minus_long 2
340 !% Total field minus longitudinal field.
341 !%End
342 call parse_variable(namespace, 'TransverseFieldCalculation', transverse_from_helmholtz, &
343 st%transverse_field_mode)
344
345 call profiling_out('STATES_MXLL_INIT')
346
347 pop_sub(states_mxll_init)
348
349 end subroutine states_mxll_init
350
351 ! ---------------------------------------------------------
353 subroutine states_mxll_allocate(st, mesh)
354 type(states_mxll_t), intent(inout) :: st
355 class(mesh_t), intent(in) :: mesh
356
357
358 push_sub(states_mxll_allocate)
359
360 call profiling_in('STATES_MXLL_ALLOCATE')
361
362 safe_allocate(st%rs_state(1:mesh%np_part, 1:st%dim))
363 st%rs_state(:,:) = m_z0
364
365 safe_allocate(st%rs_state_prev(1:mesh%np_part, 1:st%dim))
366 st%rs_state_prev(:,:) = m_z0
367
368 safe_allocate(st%rs_state_trans(1:mesh%np_part, 1:st%dim))
369 st%rs_state_trans(:,:) = m_z0
370
371 safe_allocate(st%rs_state_long(1:mesh%np_part, 1:st%dim))
372 st%rs_state_long(:,:) = m_z0
373
374 safe_allocate(st%rs_state_plane_waves(1:mesh%np_part, 1:st%dim))
375 st%rs_state_plane_waves(:,:) = m_z0
376
377 safe_allocate(st%rs_current_density_t1(1:mesh%np, 1:st%dim))
378 st%rs_current_density_t1 = m_z0
379
380 safe_allocate(st%rs_current_density_t2(1:mesh%np, 1:st%dim))
381 st%rs_current_density_t2 = m_z0
382
383 safe_allocate(st%rs_current_density_restart_t1(1:mesh%np_part, 1:st%dim))
384 st%rs_current_density_restart_t1 = m_z0
385
386 safe_allocate(st%rs_current_density_restart_t2(1:mesh%np_part, 1:st%dim))
387 st%rs_current_density_restart_t2 = m_z0
388
389 safe_allocate(st%ep(1:mesh%np_part))
390 safe_allocate(st%mu(1:mesh%np_part))
391 st%ep = p_ep
392 st%mu = p_mu
393
394 call profiling_out('STATES_MXLL_ALLOCATE')
395
396 pop_sub(states_mxll_allocate)
397 end subroutine states_mxll_allocate
398
399 ! ---------------------------------------------------------
400 subroutine states_mxll_end(st)
401 type(states_mxll_t), intent(inout) :: st
402
403
404 push_sub(states_mxll_end)
405
406 call profiling_in('STATES_MXLL_END')
407
408 safe_deallocate_a(st%rs_state)
409 safe_deallocate_a(st%rs_state_prev)
410 safe_deallocate_a(st%rs_state_trans)
411 safe_deallocate_a(st%selected_points_coordinate)
412 safe_deallocate_a(st%selected_points_rs_state)
413 safe_deallocate_a(st%selected_points_rs_state_long)
414 safe_deallocate_a(st%selected_points_rs_state_trans)
415 safe_deallocate_a(st%rs_current_density_t1)
416 safe_deallocate_a(st%rs_current_density_t2)
417 safe_deallocate_a(st%rs_state_long)
418 safe_deallocate_a(st%rs_current_density_restart_t1)
419 safe_deallocate_a(st%rs_current_density_restart_t2)
420 safe_deallocate_a(st%user_def_e_field)
421 safe_deallocate_a(st%user_def_b_field)
422
423 safe_deallocate_a(st%rs_state_const)
424 safe_deallocate_a(st%rs_state_const_td_function)
425 safe_deallocate_a(st%rs_state_const_amp)
426 safe_deallocate_a(st%rs_state_plane_waves)
427
428 safe_deallocate_a(st%surface_grid_center)
429 safe_deallocate_a(st%surface_grid_points_number)
430 safe_deallocate_a(st%surface_grid_points_map)
431 safe_deallocate_a(st%inner_points_map)
432 safe_deallocate_a(st%boundary_points_map)
433 safe_deallocate_a(st%inner_points_mask)
434 safe_deallocate_a(st%boundary_points_mask)
435 safe_deallocate_a(st%ep)
436 safe_deallocate_a(st%mu)
437 if (accel_is_enabled()) then
438 call accel_free_buffer(st%buff_inner_points_map)
439 call accel_free_buffer(st%buff_boundary_points_map)
440 call accel_free_buffer(st%buff_selected_points_map)
441 end if
442#ifdef HAVE_SCALAPACK
443 call blacs_proc_grid_end(st%dom_st_proc_grid)
444#endif
445 safe_deallocate_a(st%external_current_modus)
446 safe_deallocate_a(st%external_current_string)
447 safe_deallocate_a(st%external_current_amplitude)
448 safe_deallocate_a(st%external_current_td_function)
449 safe_deallocate_a(st%external_current_omega)
450 safe_deallocate_a(st%external_current_td_phase)
451
452 call distributed_end(st%dist)
453 safe_deallocate_a(st%node)
454
455 call profiling_out('STATES_MXLL_END')
456
457 pop_sub(states_mxll_end)
458 end subroutine states_mxll_end
459
460
461 !----------------------------------------------------------
462 subroutine build_rs_element(e_element, b_element, rs_sign, rs_element, ep_element, mu_element)
463 real(real64), intent(in) :: e_element, b_element
464 complex(real64), intent(inout) :: rs_element
465 integer, intent(in) :: rs_sign
466 real(real64), optional, intent(in) :: ep_element
467 real(real64), optional, intent(in) :: mu_element
468
469 ! no PUSH_SUB, called too often
470
471 if (present(ep_element) .and. present(mu_element)) then
472 rs_element = sqrt(ep_element/m_two) * e_element + m_zi * rs_sign * sqrt(m_one/(m_two*mu_element)) * b_element
473 else
474 rs_element = sqrt(p_ep/m_two) * e_element + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_element
475 end if
476
477 end subroutine build_rs_element
478
479
480 !----------------------------------------------------------
481 subroutine build_rs_vector(e_vector, b_vector, rs_sign, rs_vector, ep_element, mu_element)
482 real(real64), intent(in) :: e_vector(:), b_vector(:)
483 complex(real64), intent(inout) :: rs_vector(:)
484 integer, intent(in) :: rs_sign
485 real(real64), optional, intent(in) :: ep_element
486 real(real64), optional, intent(in) :: mu_element
487
488 ! no PUSH_SUB, called too often
489
490 if (present(ep_element) .and. present(mu_element)) then
491 rs_vector = sqrt(ep_element/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*mu_element)) * b_vector
492 else
493 rs_vector = sqrt(p_ep/m_two) * e_vector + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_vector
494 end if
496 end subroutine build_rs_vector
497
498
499 !----------------------------------------------------------
500 subroutine build_rs_state(e_field, b_field, rs_sign, rs_state, mesh, ep_field, mu_field, np)
501 real(real64), intent(in) :: e_field(:,:), b_field(:,:)
502 complex(real64), intent(inout) :: rs_state(:,:)
503 integer, intent(in) :: rs_sign
504 class(mesh_t), intent(in) :: mesh
505 real(real64), optional, intent(in) :: ep_field(:)
506 real(real64), optional, intent(in) :: mu_field(:)
507 integer, optional, intent(in) :: np
508
509 integer :: ip, np_
510
511 push_sub(build_rs_state)
512
513 call profiling_in('BUILD_RS_STATE')
514
515 np_ = optional_default(np, mesh%np)
516
517 do ip = 1, np_
518 if (present(ep_field) .and. present(mu_field)) then
519 rs_state(ip, :) = sqrt(ep_field(ip)/m_two) * e_field(ip, :) &
520 + m_zi * rs_sign * sqrt(m_one/(m_two*mu_field(ip))) * b_field(ip, :)
521 else
522 rs_state(ip, :) = sqrt(p_ep/m_two) * e_field(ip, :) &
523 + m_zi * rs_sign * sqrt(m_one/(m_two*p_mu)) * b_field(ip, :)
524 end if
525 end do
526
527 call profiling_out('BUILD_RS_STATE')
528
529 pop_sub(build_rs_state)
530
531 end subroutine build_rs_state
532
533
534 !----------------------------------------------------------
535 subroutine build_rs_current_element(current_element, rs_current_element, ep_element)
536 real(real64), intent(in) :: current_element
537 complex(real64), intent(inout) :: rs_current_element
538 real(real64), optional, intent(in) :: ep_element
539
540 ! no PUSH_SUB, called too often
541
542 if (present(ep_element)) then
543 rs_current_element = m_one/sqrt(m_two*ep_element) * current_element
544 else
545 rs_current_element = m_one/sqrt(m_two*p_ep) * current_element
546 end if
547
548 end subroutine build_rs_current_element
549
550
551 !----------------------------------------------------------
552 subroutine build_rs_current_vector(current_vector, rs_current_vector, ep_element)
553 real(real64), intent(in) :: current_vector(:)
554 complex(real64), intent(inout) :: rs_current_vector(:)
555 real(real64), optional, intent(in) :: ep_element
556
557 ! no PUSH_SUB, called too often
558 if (present(ep_element)) then
559 rs_current_vector = m_one/sqrt(m_two*ep_element) * current_vector
560 else
561 rs_current_vector = m_one/sqrt(m_two*p_ep) * current_vector
562 end if
563
564 end subroutine build_rs_current_vector
565
566
567 !----------------------------------------------------------
568 subroutine build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
569 real(real64), intent(in) :: current_state(:,:)
570 class(mesh_t), intent(in) :: mesh
571 complex(real64), intent(inout) :: rs_current_state(:,:)
572 real(real64), optional, intent(in) :: ep_field(:)
573 integer, optional, intent(in) :: np
574
575 integer :: ip, idim, np_, ff_dim
577 ! no PUSH_SUB, called too often
578
579 call profiling_in("BUILD_RS_CURRENT_STATE")
580
581 np_ = optional_default(np, mesh%np)
582 ff_dim = size(current_state, dim=2)
583
584 if (present(ep_field)) then
585 do idim = 1, ff_dim
586 do ip = 1, np_
587 rs_current_state(ip, idim) = m_one/sqrt(m_two*ep_field(ip)) * current_state(ip, idim)
588 end do
589 end do
590 else
591 do idim = 1, ff_dim
592 do ip = 1, np_
593 rs_current_state(ip, idim) = m_one/sqrt(m_two*p_ep) * current_state(ip, idim)
594 end do
595 end do
596 end if
597
598 call profiling_out("BUILD_RS_CURRENT_STATE")
599
600 end subroutine build_rs_current_state
601
602
603 !----------------------------------------------------------
604 subroutine get_electric_field_vector(rs_state_vector, electric_field_vector, ep_element)
605 complex(real64), intent(in) :: rs_state_vector(:)
606 real(real64), intent(out) :: electric_field_vector(:)
607 real(real64), optional, intent(in) :: ep_element
608
609 ! no PUSH_SUB, called too often
610
611 if (present(ep_element)) then
612 electric_field_vector(:) = sqrt(m_two/ep_element) * real(rs_state_vector(:), real64)
613 else
614 electric_field_vector(:) = sqrt(m_two/p_ep) * real(rs_state_vector(:), real64)
615 end if
616
617 end subroutine get_electric_field_vector
618
619
620 !----------------------------------------------------------
621 subroutine get_magnetic_field_vector(rs_state_vector, rs_sign, magnetic_field_vector, mu_element)
622 complex(real64), intent(in) :: rs_state_vector(:)
623 integer, intent(in) :: rs_sign
624 real(real64), intent(out) :: magnetic_field_vector(:)
625 real(real64), optional, intent(in) :: mu_element
626
627 ! no PUSH_SUB, called too often
628
629 if (present(mu_element)) then
630 magnetic_field_vector(:) = sqrt(m_two*mu_element) * rs_sign * aimag(rs_state_vector(:))
631 else
632 magnetic_field_vector(:) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state_vector(:))
633 end if
634
635 end subroutine get_magnetic_field_vector
636
637
638 !----------------------------------------------------------
639 subroutine get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
640 complex(real64), intent(in) :: rs_state(:,:)
641 class(mesh_t), intent(in) :: mesh
642 real(real64), intent(out) :: electric_field(:,:)
643 real(real64), optional, intent(in) :: ep_field(:)
644 integer, optional, intent(in) :: np
645
646 integer :: ip, np_
649
650 call profiling_in('GET_ELECTRIC_FIELD_STATE')
651
652 np_ = optional_default(np, mesh%np)
653
654 do ip = 1, np_
655 if (present(ep_field)) then
656 electric_field(ip, :) = sqrt(m_two/ep_field(ip)) * real(rs_state(ip, :), real64)
657 else
658 electric_field(ip,:) = sqrt(m_two/p_ep) * real(rs_state(ip, :), real64)
659 end if
660 end do
661
662 call profiling_out('GET_ELECTRIC_FIELD_STATE')
665
666 end subroutine get_electric_field_state
667
668
669 !----------------------------------------------------------
670 subroutine get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
671 complex(real64), intent(in) :: rs_state(:,:)
672 class(mesh_t), intent(in) :: mesh
673 integer, intent(in) :: rs_sign
674 real(real64), intent(out) :: magnetic_field(:,:)
675 real(real64), optional, intent(in) :: mu_field(:)
676 integer, optional, intent(in) :: np
677
678 integer :: ip, np_
679
681
682 call profiling_in('GET_MAGNETIC_FIELD_STATE')
683
684 np_ = optional_default(np, mesh%np)
685
686 if (present(mu_field)) then
687 do ip = 1, np_
688 magnetic_field(ip, :) = sqrt(m_two*mu_field(ip)) * rs_sign * aimag(rs_state(ip, :))
689 end do
690 else
691 do ip = 1, np_
692 magnetic_field(ip, :) = sqrt(m_two*p_mu) * rs_sign * aimag(rs_state(ip, :))
693 end do
694 end if
695
696 call profiling_out('GET_MAGNETIC_FIELD_STATE')
697
700 end subroutine get_magnetic_field_state
701
702 !----------------------------------------------------------
703 subroutine get_current_element(rs_current_element, current_element, ep_element)
704 complex(real64), intent(in) :: rs_current_element
705 real(real64), intent(inout) :: current_element
706 real(real64), optional, intent(in) :: ep_element
707
708 ! no PUSH_SUB, called too often
709
710 if (present(ep_element)) then
711 current_element = sqrt(m_two*ep_element) * real(rs_current_element, real64)
712 else
713 current_element = sqrt(m_two*p_ep) * real(rs_current_element, real64)
714 end if
715
716 end subroutine get_current_element
717
718
719 !----------------------------------------------------------
720 subroutine get_current_vector(rs_current_vector, current_vector, ep_element)
721 complex(real64), intent(in) :: rs_current_vector(:)
722 real(real64), intent(inout) :: current_vector(:)
723 real(real64), optional, intent(in) :: ep_element
724
725 ! no PUSH_SUB, called too often
726
727 if (present(ep_element)) then
728 current_vector(:) = sqrt(m_two*ep_element) * real(rs_current_vector(:), real64)
729 else
730 current_vector(:) = sqrt(m_two*p_ep) * real(rs_current_vector(:), real64)
731 end if
732
733 end subroutine get_current_vector
735
736 !----------------------------------------------------------
737 subroutine get_current_state(rs_current_field, current_field, mesh, ep_field, np)
738 complex(real64), intent(in) :: rs_current_field(:,:)
739 real(real64), intent(inout) :: current_field(:,:)
740 real(real64), optional, intent(in) :: ep_field(:)
741 class(mesh_t), intent(in) :: mesh
742 integer, optional, intent(in) :: np
743
744 integer :: ip, np_
745
746 push_sub(get_current_state)
747
748 np_ = optional_default(np, mesh%np)
749
750 do ip = 1, np_
751 if (present(ep_field)) then
752 current_field(ip, :) = sqrt(m_two*ep_field(ip)) * real(rs_current_field(ip, :), real64)
753 else
754 current_field(ip, :) = sqrt(m_two*p_ep) * real(rs_current_field(ip, :), real64)
755 end if
756 end do
757
758 pop_sub(get_current_state)
759
760 end subroutine get_current_state
761
762
763 !----------------------------------------------------------
764 subroutine get_rs_state_at_point(rs_state_point, rs_state, pos, st, mesh)
766 complex(real64), intent(inout) :: rs_state_point(:,:)
767 complex(real64), intent(in) :: rs_state(:,:)
768 real(real64), intent(in) :: pos(:,:)
769 type(states_mxll_t), intent(in) :: st
770 class(mesh_t), intent(in) :: mesh
771
772 integer :: ip, pos_index, rankmin
773 real(real64) :: dmin
774 complex(real64), allocatable :: ztmp(:)
775
776 push_sub(get_rs_state_at_point)
777
778 safe_allocate(ztmp(1:size(rs_state, dim=2)))
779
780 do ip = 1, st%selected_points_number
781 pos_index = mesh_nearest_point(mesh, pos(:,ip), dmin, rankmin)
782 if (mesh%mpi_grp%rank == rankmin) then
783 ztmp(:) = rs_state(pos_index, :)
784 end if
785 if (mesh%parallel_in_domains) then
786 call mesh%mpi_grp%bcast(ztmp, st%dim, mpi_double_complex, rankmin)
787 end if
788 rs_state_point(:, ip) = ztmp(:)
789 end do
790
791 safe_deallocate_a(ztmp)
792
793
794 pop_sub(get_rs_state_at_point)
795 end subroutine get_rs_state_at_point
796
797
798 !----------------------------------------------------------
799 subroutine get_rs_state_batch_selected_points(rs_state_point, rs_stateb, st, mesh)
800 complex(real64), contiguous, intent(inout) :: rs_state_point(:,:)
801 type(batch_t), intent(in) :: rs_stateb
802 type(states_mxll_t), intent(in) :: st
803 class(mesh_t), intent(in) :: mesh
804
805 integer :: ip_in, ip
806 complex(real64) :: rs_state_tmp(1:st%dim, 1:st%selected_points_number)
807 type(accel_kernel_t), save :: kernel
808 type(accel_mem_t) :: buff_points
809 integer(int64), dimension(3) :: gsizes, bsizes
810
812
813 rs_state_tmp(:,:) = m_z0
814
815 select case (rs_stateb%status())
816 case (batch_not_packed)
817 do ip_in = 1, st%selected_points_number
818 ip = st%selected_points_map(ip_in)
819 if (ip >= 0) then
820 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_linear(ip, 1:st%dim)
821 end if
822 end do
823 case (batch_packed)
824 do ip_in = 1, st%selected_points_number
825 ip = st%selected_points_map(ip_in)
826 if (ip >= 0) then
827 rs_state_tmp(1:st%dim, ip_in) = rs_stateb%zff_pack(1:st%dim, ip)
828 end if
829 end do
831 call accel_kernel_start_call(kernel, 'get_points.cu', 'get_selected_points')
834 st%selected_points_number*st%dim)
835 call accel_set_buffer_to_zero(buff_points, type_integer, st%selected_points_number*st%dim)
836
837 call accel_set_kernel_arg(kernel, 0, st%selected_points_number)
838 call accel_set_kernel_arg(kernel, 1, st%buff_selected_points_map)
839 call accel_set_kernel_arg(kernel, 2, rs_stateb%ff_device)
840 call accel_set_kernel_arg(kernel, 3, log2(int(rs_stateb%pack_size_real(1), int32)))
841 call accel_set_kernel_arg(kernel, 4, buff_points)
842 call accel_set_kernel_arg(kernel, 5, st%dim*2)
843
844 ! Compute the grid (extend to another dimensions if the size of the problem is too big)
845 call accel_grid_size_extend_dim(int(st%selected_points_number, int64), rs_stateb%pack_size_real(1), &
846 gsizes, bsizes, kernel)
847
848 call accel_kernel_run(kernel, gsizes, bsizes)
849
850 call accel_read_buffer(buff_points, st%dim, st%selected_points_number, rs_state_tmp)
851 call accel_free_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, poynting_vector, orbital_angular_momentum)
934 type(mesh_t), intent(in) :: mesh
935 real(real64), intent(in) :: poynting_vector(:,:)
936 real(real64), intent(out) :: orbital_angular_momentum(:,:)
937
938 integer :: ip
939
941
942 do ip = 1, mesh%np
943 orbital_angular_momentum(ip,1:3) = dcross_product(real(mesh%x(1:3, ip), real64) , &
944 poynting_vector(ip, 1:3))
945 end do
946
948 end subroutine get_orbital_angular_momentum
949
950 ! ---------------------------------------------------------
951 subroutine mxll_set_batch(rs_stateb, rs_state, np, dim, offset)
952 type(batch_t), intent(inout) :: rs_stateb
953 complex(real64), contiguous, intent(in) :: rs_state(:, :)
954 integer, intent(in) :: np
955 integer, intent(in) :: dim
956 integer, optional, intent(in) :: offset
957
958 integer :: offset_, idir
959
960 push_sub(mxll_set_batch)
961
962 offset_ = optional_default(offset, 1)
963
964 do idir = offset_, offset_ + dim - 1
965 call batch_set_state(rs_stateb, idir, np, rs_state(:, idir))
966 end do
967
968 pop_sub(mxll_set_batch)
969 end subroutine mxll_set_batch
970
971 ! ---------------------------------------------------------
972 subroutine mxll_get_batch(rs_stateb, rs_state, np, dim, offset)
973 type(batch_t), intent(in) :: rs_stateb
974 complex(real64), contiguous, intent(out) :: rs_state(:, :)
975 integer, intent(in) :: np
976 integer, intent(in) :: dim
977 integer, optional, intent(in) :: offset
978
979 integer :: offset_, idir
980
981 push_sub(mxll_get_batch)
982
983 offset_ = optional_default(offset, 1)
984
985 do idir = offset_, offset_ + dim - 1
986 call batch_get_state(rs_stateb, idir, np, rs_state(:, idir))
987 end do
988
989 pop_sub(mxll_get_batch)
990 end subroutine mxll_get_batch
991
992 !----------------------------------------------------------
993 subroutine get_transverse_rs_state(helmholtz, st, namespace)
994 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
995 type(states_mxll_t), intent(inout) :: st
996 type(namespace_t), intent(in) :: namespace
997
998
1000
1001 call profiling_in('GET_TRANSVERSE_RS_STATE')
1002
1003 select case (st%transverse_field_mode)
1005 call helmholtz%get_trans_field(namespace, st%rs_state_trans, total_field=st%rs_state)
1007 call helmholtz%get_long_field(namespace, st%rs_state_long, total_field=st%rs_state)
1008 st%rs_state_trans = st%rs_state - st%rs_state_long
1009 case default
1010 message(1) = 'Unknown transverse field calculation mode.'
1011 call messages_fatal(1, namespace=namespace)
1012 end select
1013
1014 call profiling_out('GET_TRANSVERSE_RS_STATE')
1015
1017
1018 end subroutine get_transverse_rs_state
1019
1020
1021end module states_mxll_oct_m
1022
1023
1024
1025!! Local Variables:
1026!! mode: f90
1027!! coding: utf-8
1028!! End:
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:203
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:1004
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1392
integer, parameter, public accel_mem_read_write
Definition: accel.F90:184
pure logical function, public accel_is_enabled()
Definition: accel.F90:401
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:193
real(real64), parameter, public m_zero
Definition: global.F90:191
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
complex(real64), parameter, public m_zi
Definition: global.F90:205
real(real64), parameter, public m_one
Definition: global.F90:192
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:1941
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: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
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)
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 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)
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
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)