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