Octopus
external_potential.F90
Go to the documentation of this file.
1!! Copyright (C) 2020 N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18#include "global.h"
19
21 use debug_oct_m
22 use global_oct_m
23 use iihash_oct_m
31 use mesh_oct_m
34 use parser_oct_m
38 use space_oct_m
39 use string_oct_m
40 use unit_oct_m
43 implicit none
44
45 private
46 public :: &
50
52 private
53
54 type(space_t) :: space
55
56 integer, public :: type
57
58 character(len=1024) :: potential_formula
59 character(len=200) :: density_formula
60 character(len=MAX_PATH_LEN) :: filename
61 real(real64) :: omega
62
63 real(real64), allocatable, public :: pot(:)
64
65 real(real64), allocatable, public :: b_field(:)
66 integer :: gauge_2D
67 real(real64), allocatable, public :: a_static(:,:)
68 real(real64), allocatable, public :: e_field(:)
69 !Auxiliary arrays for the electrons only
70 !TODO: Suppress once electrons fully use the new framework
71 real(real64), allocatable, public :: v_ext(:)
72
73 contains
74 procedure :: calculate => external_potential_calculate
75 procedure :: allocate_memory => external_potential_allocate
76 procedure :: deallocate_memory => external_potential_deallocate
77 procedure :: init_interaction_as_partner => external_potential_init_interaction_as_partner
78 procedure :: copy_quantities_to_interaction => external_potential_copy_quantities_to_interaction
81
82 integer, public, parameter :: &
83 EXTERNAL_POT_USDEF = 201, & !< user-defined function for local potential
88
89
90 interface external_potential_t
91 module procedure external_potential_init
92 end interface external_potential_t
93
94contains
95
96 ! ---------------------------------------------------------
98 subroutine external_potential_clone(pot_out, pot_in)
99 class(external_potential_t), pointer, intent(out) :: pot_out
100 class(external_potential_t), intent(in) :: pot_in
101
102 type(quantity_iterator_t) :: iter
103 class(quantity_t), pointer :: quantity
104
106
107 allocate(pot_out)
108
109 pot_out%namespace = pot_in%namespace
110 pot_out%space = pot_in%space
111 pot_out%type = pot_in%type
112 pot_out%potential_formula = pot_in%potential_formula
113 pot_out%density_formula = pot_in%density_formula
114 pot_out%filename = pot_in%filename
115 pot_out%omega = pot_in%omega
116 pot_out%gauge_2D = pot_in%gauge_2D
117
118 if (allocated(pot_in%pot)) then
119 allocate(pot_out%pot, source=pot_in%pot)
120 end if
121 if (allocated(pot_in%b_field)) then
122 allocate(pot_out%b_field, source=pot_in%b_field)
123 end if
124 if (allocated(pot_in%a_static)) then
125 allocate(pot_out%a_static, source=pot_in%a_static)
126 end if
127 if (allocated(pot_in%e_field)) then
128 allocate(pot_out%e_field, source=pot_in%e_field)
129 end if
130 if (allocated(pot_in%v_ext)) then
131 allocate(pot_out%v_ext, source=pot_in%v_ext)
132 end if
133
134 if (allocated(pot_in%supported_interactions_as_partner)) then
135 allocate(pot_out%supported_interactions_as_partner, source=pot_in%supported_interactions_as_partner)
136 else
137 allocate(pot_out%supported_interactions_as_partner(0))
138 end if
139
140 call iter%start(pot_in%quantities)
141 do while (iter%has_next())
142 quantity => iter%get_next()
143 call pot_out%quantities%add(quantity)
144 end do
145
147 end subroutine external_potential_clone
148
149 function external_potential_init(namespace) result(this)
150 class(external_potential_t), pointer :: this
151 type(namespace_t), intent(in) :: namespace
152
155 allocate(this)
157 this%namespace = namespace_t("ExternalPotential", parent=namespace)
158 this%space = space_t(namespace)
159
160 this%type = -1
162 allocate(this%supported_interactions_as_partner(0))
164 call this%quantities%add(quantity_t("E field", always_available = .true., updated_on_demand = .false., &
165 iteration = iteration_counter_t()))
166 call this%quantities%add(quantity_t("B field", always_available = .true., updated_on_demand = .false., &
167 iteration = iteration_counter_t()))
168
172 ! ---------------------------------------------------------
174 type(external_potential_t), intent(inout) :: this
175
178 call this%deallocate_memory()
179
181 end subroutine external_potential_finalize
182
183 ! ---------------------------------------------------------
184 subroutine external_potential_allocate(this, mesh)
185 class(external_potential_t), intent(inout) :: this
186 class(mesh_t), intent(in) :: mesh
187
189
190 select case (this%type)
191 case (external_pot_usdef, external_pot_from_file, external_pot_charge_density)
192 safe_allocate(this%pot(1:mesh%np))
194 safe_allocate(this%a_static(1:mesh%np, 1:this%space%dim))
196 if (this%space%periodic_dim < this%space%dim) then
197 safe_allocate(this%pot(1:mesh%np))
198 safe_allocate(this%v_ext(1:mesh%np_part))
199 end if
200 end select
201
203 end subroutine external_potential_allocate
204
205 ! ---------------------------------------------------------
206 subroutine external_potential_deallocate(this)
207 class(external_potential_t), intent(inout) :: this
208
210
211 safe_deallocate_a(this%pot)
212 safe_deallocate_a(this%b_field)
213 safe_deallocate_a(this%a_static)
214 safe_deallocate_a(this%e_field)
215 safe_deallocate_a(this%v_ext)
216
218 end subroutine external_potential_deallocate
219
220 ! ---------------------------------------------------------
221 subroutine external_potential_init_interaction_as_partner(partner, interaction)
222 class(external_potential_t), intent(in) :: partner
223 class(interaction_surrogate_t), intent(inout) :: interaction
224
226
227 select type (interaction)
228 type is (lorentz_force_t)
229 ! Nothing to be initialized for the Lorentz force.
230 class default
231 message(1) = "Unsupported interaction."
232 call messages_fatal(1, namespace=partner%namespace)
233 end select
234
237
238 ! ---------------------------------------------------------
239 subroutine external_potential_copy_quantities_to_interaction(partner, interaction)
240 class(external_potential_t), intent(inout) :: partner
241 class(interaction_surrogate_t), intent(inout) :: interaction
242
243 integer :: ip
246
247 select type (interaction)
248 type is (lorentz_force_t)
249 if (partner%type == external_pot_static_efield) then
250 do ip = 1, interaction%system_np
251 interaction%partner_e_field(:, ip) = partner%e_field
252 interaction%partner_b_field(:, ip) = m_zero
253 end do
254 else if (partner%type == external_pot_static_bfield) then
255 do ip = 1, interaction%system_np
256 interaction%partner_e_field(:, ip) = m_zero
257 interaction%partner_b_field(:, ip) = partner%b_field
258 end do
259 else
260 assert(.false.) !This should never occur.
261 end if
262
263 class default
264 message(1) = "Unsupported interaction."
265 call messages_fatal(1, namespace=partner%namespace)
266 end select
267
270
271
272 ! ---------------------------------------------------------
273 subroutine external_potential_calculate(this, namespace, mesh, poisson)
274 class(external_potential_t), intent(inout) :: this
275 type(namespace_t), intent(in) :: namespace
276 class(mesh_t), intent(in) :: mesh
277 type(poisson_t), intent(in) :: poisson
278
279 real(real64) :: pot_re, pot_im, r, xx(this%space%dim)
280 real(real64), allocatable :: den(:), grx(:)
281 integer :: ip, err
282
284
285 select case (this%type)
286
287 case (external_pot_usdef)
288 assert(allocated(this%pot))
289
290 do ip = 1, mesh%np
291 call mesh_r(mesh, ip, r, coords = xx)
292 call parse_expression(pot_re, pot_im, this%space%dim, xx, r, m_zero, this%potential_formula)
293 this%pot(ip) = pot_re
294 end do
295
297 assert(allocated(this%pot))
298
299 call dio_function_input(trim(this%filename), namespace, this%space, mesh, this%pot, err)
300 if (err /= 0) then
301 write(message(1), '(a)') 'Error loading file '//trim(this%filename)//'.'
302 write(message(2), '(a,i4)') 'Error code returned = ', err
303 call messages_fatal(2, namespace=namespace)
304 end if
305
307 assert(allocated(this%pot))
308
309 safe_allocate(den(1:mesh%np))
310
311 do ip = 1, mesh%np
312 call mesh_r(mesh, ip, r, coords = xx)
313 call parse_expression(pot_re, pot_im, this%space%dim, xx, r, m_zero, this%potential_formula)
314 den(ip) = pot_re
315 end do
317 call dpoisson_solve(poisson, namespace, this%pot, den, all_nodes = .false.)
318
319 safe_deallocate_a(den)
320
322 assert(allocated(this%b_field))
323
324 ! Compute the vector potential from a uniform B field.
325 ! The sign is determined by the relation $\vec{B} = \nabla \times \vec{A}$.
326 ! This leads to $\vec{A} = -\frac{1}{2}\vec{r}\times\vec{B}$.
327 ! A factor 1/c is already added, to avoid adding it everytime we update the Hamiltonian
328 safe_allocate(grx(1:this%space%dim))
329
330 select case (this%space%dim)
331 case (2)
332 select case (this%gauge_2d)
333 case (0) ! linear_xy
334 if (this%space%periodic_dim == 1) then
335 message(1) = "For 2D system, 1D-periodic, StaticMagneticField can only be "
336 message(2) = "applied for StaticMagneticField2DGauge = linear_y."
337 call messages_fatal(2, namespace=namespace)
338 end if
339 !$omp parallel do private(grx)
340 do ip = 1, mesh%np
341 grx(1:this%space%dim) = mesh%x(1:this%space%dim, ip)
342 this%a_static(ip, 1) = -m_half/p_c * grx(2) * this%b_field(3)
343 this%a_static(ip, 2) = m_half/p_c * grx(1) * this%b_field(3)
344 end do
345 case (1) ! linear y
346 !$omp parallel do private(grx)
347 do ip = 1, mesh%np
348 grx(1:this%space%dim) = mesh%x(1:this%space%dim, ip)
349 this%a_static(ip, 1) = -m_one/p_c * grx(2) * this%b_field(3)
350 this%a_static(ip, 2) = m_zero
351 end do
352 end select
353 case (3)
354 !$omp parallel do private(grx)
355 do ip = 1, mesh%np
356 grx(1:this%space%dim) = mesh%x(1:this%space%dim, ip)
357 this%a_static(ip, 1) = -m_half/p_c*(grx(2) * this%b_field(3) - grx(3) * this%b_field(2))
358 this%a_static(ip, 2) = -m_half/p_c*(grx(3) * this%b_field(1) - grx(1) * this%b_field(3))
359 this%a_static(ip, 3) = -m_half/p_c*(grx(1) * this%b_field(2) - grx(2) * this%b_field(1))
360 end do
361 case default
362 assert(.false.)
363 end select
364
365 safe_deallocate_a(grx)
366
368 assert(allocated(this%e_field))
369
370 if (this%space%periodic_dim < this%space%dim) then
371 ! Compute the scalar potential
372 !
373 ! Note that the -1 sign is missing. This is because we
374 ! consider the electrons with +1 charge. The electric field
375 ! however retains the sign because we also consider protons to
376 ! have +1 charge when calculating the force.
377 !
378 ! NTD: This comment is very confusing and prone to error
379 ! TODO: Fix this to have physically sound quantities and interactions
380 do ip = 1, mesh%np
381 this%pot(ip) = sum(mesh%x(this%space%periodic_dim + 1:this%space%dim, ip) &
382 * this%e_field(this%space%periodic_dim + 1:this%space%dim))
383 end do
384 ! The following is needed to make interpolations.
385 ! It is used by PCM.
386 this%v_ext(1:mesh%np) = this%pot(1:mesh%np)
387 do ip = mesh%np+1, mesh%np_part
388 this%v_ext(ip) = sum(mesh%x(this%space%periodic_dim + 1:this%space%dim, ip) &
389 * this%e_field(this%space%periodic_dim + 1:this%space%dim))
390 end do
391 end if
392
393 end select
394
396 end subroutine external_potential_calculate
397
398 subroutine load_external_potentials(external_potentials, namespace)
399 class(partner_list_t), intent(inout) :: external_potentials
400 type(namespace_t), intent(in) :: namespace
401
402 integer :: n_pot_block, row, read_data
403 type(block_t) :: blk
404 class(external_potential_t), pointer :: pot
405
406 integer :: dim, periodic_dim, idir
407
409
410 !%Variable StaticExternalPotentials
411 !%Type block
412 !%Section System
413 !%Description
414 !% An static external potential is a model potential added to the local potential of the Hamiltonian
415 !%
416 !% The format of this block is the following:
417 !% The first field defines the type of species (the valid options are detailed
418 !% below).
419 !%
420 !% Then a list of parameters follows. The parameters are specified
421 !% by a first field with the parameter name and the field that
422 !% follows with the value of the parameter. Some parameters are
423 !% specific to a certain species while others are accepted by all
424 !% species. These are <tt>mass</tt>, <tt>max_spacing</tt>, and <tt>min_radius</tt>.
425 !%
426 !% These are examples of possible species:
427 !%
428 !% <tt>%ExternalPotential
429 !% <br>&nbsp;&nbsp; potential_user_defined | potential_formula | "1/2*r^2"
430 !% <br>%</tt>
431 !%Option potential_from_file -202
432 !% The potential is read from a file. Accepted file formats, detected by extension: obf, ncdf and csv.
433 !%Option potential_user_defined -201
434 !% Species with user-defined potential. The potential for the
435 !% species is defined by the formula given by the <tt>potential_formula</tt>
436 !% parameter.
437 !%Option potential_charge_density -203
438 !% The potential for this species is created from the distribution
439 !% of charge given by the <tt>density_formula</tt> parameter.
440 !%Option file -10010
441 !% The path for the file that describes the species.
442 !%Option potential_formula -10012
443 !% Mathematical expression that defines the potential for <tt>species_user_defined</tt>. You can use
444 !% any of the <i>x</i>, <i>y</i>, <i>z</i> or <i>r</i> variables.
445 !%Option density_formula -10013
446 !% Mathematical expression that defines the charge density for <tt>species_charge_density</tt>. You can use
447 !% any of the <i>x</i>, <i>y</i>, <i>z</i> or <i>r</i> variables.
448 !%End
449
450 ! First, find out if there is a Species block.
451 n_pot_block = 0
452 if (parse_block(namespace, 'StaticExternalPotentials', blk) == 0) then
453 n_pot_block = parse_block_n(blk)
454
455 do row = 0, n_pot_block-1
456 !Create a potential
457 pot => external_potential_t(namespace)
458 !Parse the information from the block
459 call read_from_block(pot, namespace, blk, row, read_data)
460 assert(read_data > 0)
461 !Add this to the list
462 call external_potentials%add(pot)
463 end do
464 call parse_block_end(blk)
465 end if
466
467
468 !Here I am parsing the variables Dimensions et PeriodicDimensions because we do not have access
469 !to this information here.
470 !TODO: This needs to be removed and replaced by something better
471 call parse_variable(namespace, 'Dimensions', 3, dim)
472 call parse_variable(namespace, 'PeriodicDimensions', 0, periodic_dim)
473
474
475 !%Variable StaticMagneticField
476 !%Type block
477 !%Section Hamiltonian
478 !%Description
479 !% A static constant magnetic field may be added to the usual Hamiltonian,
480 !% by setting the block <tt>StaticMagneticField</tt>.
481 !% The three possible components of the block (which should only have one
482 !% line) are the three components of the magnetic field vector. Note that
483 !% if you are running the code in 1D mode, this will not work, and if you
484 !% are running the code in 2D mode the magnetic field will have to be in
485 !% the <i>z</i>-direction, so that the first two columns should be zero.
486 !% Possible in periodic system only in these cases: 2D system, 1D periodic,
487 !% with <tt>StaticMagneticField2DGauge = linear_y</tt>;
488 !% 3D system, 1D periodic, field is zero in <i>y</i>- and <i>z</i>-directions (given
489 !% currently implemented gauges).
490 !%
491 !% The magnetic field should always be entered in atomic units, regardless
492 !% of the <tt>Units</tt> variable. Note that we use the "Gaussian" system
493 !% meaning 1 au[B] = <math> 2.350517568\times 10^9</math> Gauss, which corresponds to
494 !% <math>2.3505175678\times 10^5</math> Tesla.
495 !%End
496 if (parse_block(namespace, 'StaticMagneticField', blk) == 0) then
497 !Create a potential
498 pot => external_potential_t(namespace)
500 pot%supported_interactions_as_partner = [lorentz_force]
501
502 !%Variable StaticMagneticField2DGauge
503 !%Type integer
504 !%Default linear_xy
505 !%Section Hamiltonian
506 !%Description
507 !% The gauge of the static vector potential <math>A</math> when a magnetic field
508 !% <math>B = \left( 0, 0, B_z \right)</math> is applied to a 2D-system.
509 !%Option linear_xy 0
510 !% Linear gauge with <math>A = \frac{1}{2c} \left( -y, x \right) B_z</math>. (Cannot be used for periodic systems.)
511 !%Option linear_y 1
512 !% Linear gauge with <math>A = \frac{1}{c} \left( -y, 0 \right) B_z</math>. Can be used for <tt>PeriodicDimensions = 1</tt>
513 !% but not <tt>PeriodicDimensions = 2</tt>.
514 !%End
515 call parse_variable(namespace, 'StaticMagneticField2DGauge', 0, pot%gauge_2d)
516 if (.not. varinfo_valid_option('StaticMagneticField2DGauge', pot%gauge_2d)) then
517 call messages_input_error(namespace, 'StaticMagneticField2DGauge')
518 end if
519
520 safe_allocate(pot%b_field(1:3))
521 do idir = 1, 3
522 call parse_block_float(blk, 0, idir - 1, pot%b_field(idir))
523 end do
524 select case (dim)
525 case (1)
526 call messages_input_error(namespace, 'StaticMagneticField')
527 case (2)
528 if (periodic_dim == 2) then
529 message(1) = "StaticMagneticField cannot be applied in a 2D, 2D-periodic system."
530 call messages_fatal(1, namespace=namespace)
531 end if
532 if (pot%b_field(1)**2 + pot%b_field(2)**2 > m_zero) then
533 call messages_input_error(namespace, 'StaticMagneticField')
534 end if
535 case (3)
536 ! Consider cross-product below: if grx(1:this%space%periodic_dim) is used, it is not ok.
537 ! Therefore, if idir is periodic, b_field for all other directions must be zero.
538 ! 1D-periodic: only Bx. 2D-periodic or 3D-periodic: not allowed. Other gauges could allow 2D-periodic case.
539 if (periodic_dim >= 2) then
540 message(1) = "In 3D, StaticMagneticField cannot be applied when the system is 2D- or 3D-periodic."
541 call messages_fatal(1, namespace=namespace)
542 else if (periodic_dim == 1 .and. any(abs(pot%b_field(2:3)) > m_zero)) then
543 message(1) = "In 3D, 1D-periodic, StaticMagneticField must be zero in the y- and z-directions."
544 call messages_fatal(1, namespace=namespace)
545 end if
546 end select
547 call parse_block_end(blk)
548
549 if (dim > 3) call messages_not_implemented('Magnetic field for dim > 3', namespace=namespace)
550
551 !Add this to the list
552 call external_potentials%add(pot)
553
554 !The corresponding A field on the mesh is computed in the routine external_potential_calculate
555
556 end if
557
558 !%Variable StaticElectricField
559 !%Type block
560 !%Default 0
561 !%Section Hamiltonian
562 !%Description
563 !% A static constant electric field may be added to the usual Hamiltonian,
564 !% by setting the block <tt>StaticElectricField</tt>.
565 !% The three possible components of the block (which should only have one
566 !% line) are the three components of the electric field vector.
567 !% It can be applied in a periodic direction of a large supercell via
568 !% the single-point Berry phase.
569 !%End
570 if (parse_block(namespace, 'StaticElectricField', blk) == 0) then
571 !Create a potential
572 pot => external_potential_t(namespace)
574 pot%supported_interactions_as_partner = [lorentz_force]
575
576 safe_allocate(pot%e_field(1:dim))
577 do idir = 1, dim
578 call parse_block_float(blk, 0, idir - 1, pot%e_field(idir), units_inp%energy / units_inp%length)
579
580 !Electron-specific checks (k-points) are done in the hamiltonian_elec.F90 file
581 if (idir <= periodic_dim .and. abs(pot%e_field(idir)) > m_epsilon) then
582 message(1) = "Applying StaticElectricField in a periodic direction is only accurate for large supercells."
583 call messages_warning(1, namespace=namespace)
584 end if
585 end do
586 call parse_block_end(blk)
587
588 !Add this to the list
589 call external_potentials%add(pot)
590
591 !The corresponding A field on the mesh is computed in the routine external_potential_calculate
592 end if
593
594
596 end subroutine load_external_potentials
597
598 ! ---------------------------------------------------------
599 subroutine read_from_block(pot, namespace, blk, row, read_data)
600 type(external_potential_t), intent(inout) :: pot
601 type(namespace_t), intent(in) :: namespace
602 type(block_t), intent(in) :: blk
603 integer, intent(in) :: row
604 integer, intent(out) :: read_data
605
606 integer :: ncols, icol, flag
607 type(iihash_t) :: read_parameters
608
609
610 push_sub(read_from_block)
611
612 ncols = parse_block_cols(blk, row)
613 read_data = 0
614
615 call parse_block_integer(blk, row, 0, pot%type)
616
617 ! To detect the old species block format, options are represented
618 ! as negative values. If we get a non-negative value we know we
619 ! are reading a mass.
620 if (pot%type >= 0) then
621 message(1) = 'Error in reading the ExternalPotentials block'
622 call messages_fatal(1, namespace=namespace)
623 end if
624
625 ! now we convert back to positive
626 pot%type = -pot%type
627
628 read_data = 1
629
630 if (pot%type /= external_pot_charge_density .and. pot%type /= external_pot_usdef .and. pot%type /= external_pot_from_file) then
631 call messages_input_error(namespace, 'ExternalPotentials', "Unknown type of external potential")
632 end if
633
634 call iihash_init(read_parameters)
635
636 icol = read_data
637 do
638 if (icol >= ncols) exit
639
640 call parse_block_integer(blk, row, icol, flag)
641
642 select case (flag)
643
644 case (option__staticexternalpotentials__file)
645 call check_duplication(option__staticexternalpotentials__file)
646 call parse_block_string(blk, row, icol + 1, pot%filename)
647
648 case (option__staticexternalpotentials__potential_formula)
649 call check_duplication(option__staticexternalpotentials__potential_formula)
650 call parse_block_string(blk, row, icol + 1, pot%potential_formula, convert_to_c=.true.)
651
652 if (pot%type /= external_pot_usdef) then
653 call messages_input_error(namespace, 'ExternalPotentials', 'potential_formula can only be used with user_defined')
654 end if
655
656 case (option__staticexternalpotentials__density_formula)
657 call check_duplication(option__staticexternalpotentials__density_formula)
658 call parse_block_string(blk, row, icol + 1, pot%density_formula, convert_to_c=.true.)
659
660 if (pot%type /= external_pot_charge_density) then
661 call messages_input_error(namespace, 'ExternalPotentials', 'density_formula can only be used with charge_density')
662 end if
663
664 case default
665 call messages_input_error(namespace, 'ExternalPotentials', "Unknown parameter ")
666
667 end select
668
669 icol = icol + 2
670 end do
671 ! CHECK THAT WHAT WE PARSED MAKES SENSE
672
673
674 if (pot%type == external_pot_usdef .and. &
675 .not. parameter_defined(option__staticexternalpotentials__potential_formula)) then
676 call messages_input_error(namespace, 'ExternalPotentials', "The 'potential_formula' parameter is missing.")
677 end if
678
679 if (pot%type == external_pot_charge_density .and. &
680 .not. parameter_defined(option__staticexternalpotentials__density_formula)) then
681 call messages_input_error(namespace, 'ExternalPotentials', "The 'density_formula' parameter is missing.")
682 end if
683
684 if (pot%type == external_pot_from_file .and. .not. (parameter_defined(option__staticexternalpotentials__file))) then
685 call messages_input_error(namespace, 'ExternalPotentials', "The 'file' parameter is missing.")
686 end if
687
688 call iihash_end(read_parameters)
689
690 pop_sub(read_from_block)
691
692 contains
693
694 logical function parameter_defined(param) result(defined)
695 integer(int64), intent(in) :: param
696
697 integer :: tmp
698
700
701 tmp = iihash_lookup(read_parameters, int(-param), defined)
702
704 end function parameter_defined
705
706 !------------------------------------------------------
707
708 subroutine check_duplication(param)
709 integer(int64), intent(in) :: param
710
712
713 if (parameter_defined(param)) then
714 call messages_input_error(namespace, 'ExternalPotentials', "Duplicated parameter in external potential.")
715 end if
716
717 call iihash_insert(read_parameters, int(-param), 1)
718
720 end subroutine check_duplication
721
722 end subroutine read_from_block
723 ! ---------------------------------------------------------
724
725
727
728!! Local Variables:
729!! mode: f90
730!! coding: utf-8
731!! End:
subroutine check_duplication(param)
logical function parameter_defined(param)
integer, parameter, public external_pot_from_file
potential, defined in a file
subroutine, public load_external_potentials(external_potentials, namespace)
class(external_potential_t) function, pointer external_potential_init(namespace)
subroutine read_from_block(pot, namespace, blk, row, read_data)
integer, parameter, public external_pot_charge_density
user-defined function for charge density
subroutine external_potential_finalize(this)
subroutine external_potential_calculate(this, namespace, mesh, poisson)
subroutine external_potential_init_interaction_as_partner(partner, interaction)
subroutine external_potential_deallocate(this)
subroutine external_potential_copy_quantities_to_interaction(partner, interaction)
integer, parameter, public external_pot_static_efield
Static electric field.
integer, parameter, public external_pot_static_bfield
Static magnetic field.
subroutine external_potential_allocate(this, mesh)
subroutine, public external_potential_clone(pot_out, pot_in)
Deep-clone an external potential instance.
real(real64), parameter, public m_zero
Definition: global.F90:191
real(real64), parameter, public m_epsilon
Definition: global.F90:207
real(real64), parameter, public m_half
Definition: global.F90:197
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:233
real(real64), parameter, public m_one
Definition: global.F90:192
This module implements a simple hash table for non-negative integer keys and integer values.
Definition: iihash.F90:127
subroutine, public iihash_end(h)
Free a hash table.
Definition: iihash.F90:186
subroutine, public iihash_insert(h, key, val)
Insert a (key, val) pair into the hash table h.
Definition: iihash.F90:208
integer function, public iihash_lookup(h, key, found)
Look up a value in the hash table h. If found is present, it indicates if key could be found in the t...
Definition: iihash.F90:233
subroutine, public iihash_init(h)
Initialize a hash table h.
Definition: iihash.F90:163
integer, parameter, public lorentz_force
This module defines classes and functions for interaction partners.
subroutine, public dio_function_input(filename, namespace, space, mesh, ff, ierr, map)
Reads a mesh function from file filename, and puts it into ff. If the map argument is passed,...
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:342
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1091
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:810
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:615
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:875
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
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
abstract class for general interaction partners
surrogate interaction class to avoid circular dependencies between modules.
This class implements the iteration counter used by the multisystem algorithms. As any iteration coun...
Lorenz force between a systems of particles and an electromagnetic field.
Describes mesh distribution to nodes.
Definition: mesh.F90:187
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
Definition: quantity.F90:173
int true(void)