Octopus
ion_electron_local_potential.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2021 Nicolas Tancogne-Dejean
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use atom_oct_m
24 use comm_oct_m
25 use debug_oct_m
27 use epot_oct_m
28 use global_oct_m
31 use ions_oct_m
32 use, intrinsic :: iso_fortran_env
35 use mesh_oct_m
41 use ps_oct_m
44 use space_oct_m
50
51 implicit none
52
53 private
54 public :: &
56
58 private
59
60 type(poisson_t), pointer :: psolver
61 type(mesh_t), pointer :: mesh
62 type(space_t), pointer :: space
63
64 ! This information should be copied, and not obtained thanks to pointer
65 ! This is a temporary change here
66 type(distributed_t), pointer, public :: atoms_dist => null()
67 type(atom_t), pointer, public :: atom(:) => null()
68 real(real64), pointer, public :: pos(:,:) => null()
69 type(lattice_vectors_t), pointer :: latt => null()
70
71 ! Temporary pointer to namespace
72 type(namespace_t), pointer :: namespace
73
74 logical :: have_density
75
76 contains
77 procedure :: init => ion_electron_local_potential_init
78 procedure :: bind => ion_electron_local_potential_bind
79 procedure :: calculate => ion_electron_local_potential_calculate
80 procedure :: calculate_energy => ion_electron_local_potential_calculate_energy
81 procedure :: end => ion_electron_local_potential_end
84
88
89contains
90
91 ! ---------------------------------------------------------
92 function ion_electron_local_potential_constructor(partner) result(this)
93 class(interaction_partner_t), target, intent(inout) :: partner
94 class(ion_electron_local_potential_t), pointer :: this
95
97
98 allocate(this)
99
100 this%label = "ion-electron local"
101
102 this%partner => partner
103
106
107 ! ---------------------------------------------------------
108 subroutine ion_electron_local_potential_init(this, mesh, psolver, ions, namespace)
109 class(ion_electron_local_potential_t), intent(inout) :: this
110 class(mesh_t), target, intent(in) :: mesh
111 type(poisson_t), target, intent(in) :: psolver
112 type(ions_t), target, intent(in) :: ions
113 type(namespace_t), target, intent(in) :: namespace
114
115 integer :: ia
116
118
119 this%mesh => mesh
120 this%psolver => psolver
121
122 safe_allocate(this%potential(1:mesh%np, 1))
123
124 this%have_density = .false.
125 do ia = 1, ions%nspecies
126 if (local_potential_has_density(ions%space, ions%species(ia)%s)) then
127 this%have_density = .true.
128 exit
129 end if
130 end do
131
132 this%atoms_dist => ions%atoms_dist
133 this%atom => ions%atom
134 this%space => ions%space
135 this%pos => ions%pos
136 this%latt => ions%latt
137
138 this%namespace => namespace
139
142
143 ! ---------------------------------------------------------
146 subroutine ion_electron_local_potential_bind(this, psolver, ions)
147 class(ion_electron_local_potential_t), intent(inout) :: this
148 type(poisson_t), target, intent(in) :: psolver
149 type(ions_t), target, intent(in) :: ions
150
153 this%psolver => psolver
154 this%atoms_dist => ions%atoms_dist
155 this%atom => ions%atom
156 this%space => ions%space
157 this%pos => ions%pos
158 this%latt => ions%latt
159
163 ! ---------------------------------------------------------
164 ! Note: this code is adapted from epot_local_potential. There are code duplication at the moment
166 class(ion_electron_local_potential_t), intent(inout) :: this
168 real(real64), allocatable :: density(:), rho(:), vl(:)
169 type(submesh_t) :: sphere
170 type(ps_t), pointer :: ps
171 integer :: ia, ip
172 real(real64) :: radius
173 logical :: sphere_init
177 call profiling_in("ION_ELEC_LOC_INTER")
178
179 this%potential(:,1) = m_zero
180
181 if (this%have_density) then
182 safe_allocate(density(1:this%mesh%np))
183 density = m_zero
184 end if
185
186 sphere_init = .false.
188 do ia = this%atoms_dist%start, this%atoms_dist%end
189 ! Local potential, we can get it by solving the Poisson equation
190 ! (for all-electron species or pseudopotentials in periodic
191 ! systems) or by applying it directly to the grid
192
193 if (local_potential_has_density(this%space, this%atom(ia)%species)) then
194
195 safe_allocate(rho(1:this%mesh%np))
196 call species_get_long_range_density(this%atom(ia)%species, this%namespace, this%space, this%latt, &
197 this%pos(:, ia), this%mesh, rho, sphere)
198 call lalg_axpy(this%mesh%np, m_one, rho, density)
199 safe_deallocate_a(rho)
200 sphere_init = .true.
201
202 else
204 safe_allocate(vl(1:this%mesh%np))
205 call species_get_local(this%atom(ia)%species, this%namespace, this%space, this%latt, &
206 this%pos(:, ia), this%mesh, vl)
207 call lalg_axpy(this%mesh%np, m_one, vl, this%potential(:,1))
208 safe_deallocate_a(vl)
209
210 end if
211
212 !then we add the localized part
213 select type(spec=>this%atom(ia)%species)
214 type is(pseudopotential_t)
215
216 ps => spec%ps
217
218 radius = min(ps%vl%x_threshold*1.05_real64, spline_range_max(ps%vl))
219 if (sphere_init) then
220 if ( .not. submesh_compatible(sphere,radius,this%pos(:,ia), minval(this%mesh%spacing(1:this%space%dim))) ) then
221 call submesh_init(sphere, this%space, this%mesh, this%latt, this%pos(:, ia), radius)
222 end if
223 else
224 call submesh_init(sphere, this%space, this%mesh, this%latt, this%pos(:, ia), radius)
225 end if
226 safe_allocate(vl(1:sphere%np))
227
228 do ip = 1, sphere%np
229 if(sphere%r(ip) <= radius) then
230 vl(ip) = spline_eval(ps%vl, sphere%r(ip))
231 else
232 vl(ip) = 0
233 end if
234 end do
235
236 call submesh_add_to_mesh(sphere, vl, this%potential(:,1))
237
238 safe_deallocate_a(vl)
239 nullify(ps)
240 end select
241 call submesh_end(sphere)
242 end do
243
244 ! reduce over atoms if required
245 if (this%atoms_dist%parallel) then
246 call comm_allreduce(this%atoms_dist%mpi_grp, this%potential(:,1), dim = this%mesh%np)
247 if (this%have_density) then
248 call comm_allreduce(this%atoms_dist%mpi_grp, density, dim = this%mesh%np)
249 end if
250 end if
251
252 ! now we solve the poisson equation with the density of all nodes
253 if (this%have_density) then
254
255 safe_allocate(vl(1:this%mesh%np_part))
256 call dpoisson_solve(this%psolver, this%namespace, vl, density)
257 call lalg_axpy(this%mesh%np, m_one, vl, this%potential(:,1))
258 safe_deallocate_a(vl)
259
260 end if
261 safe_deallocate_a(density)
262
263 call profiling_out("ION_ELEC_LOC_INTER")
264
267
268 ! ---------------------------------------------------------
269 subroutine ion_electron_local_potential_end(this)
270 class(ion_electron_local_potential_t), intent(inout) :: this
271
273
274 safe_deallocate_a(this%potential)
275 nullify(this%mesh)
276 nullify(this%psolver)
277
278 call interaction_end(this)
279
282
283
284 ! ---------------------------------------------------------
286 type(ion_electron_local_potential_t), intent(inout) :: this
287
289
291
294
295 ! ---------------------------------------------------------
297 class(ion_electron_local_potential_t), intent(inout) :: this
298
300
302 assert(.false.)
303
305
307
308
310
311!! Local Variables:
312!! mode: f90
313!! coding: utf-8
314!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
logical pure function, public local_potential_has_density(space, species)
Definition: epot.F90:502
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_one
Definition: global.F90:201
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
subroutine, public interaction_end(this)
This module defines classes and functions for interaction partners.
class(ion_electron_local_potential_t) function, pointer ion_electron_local_potential_constructor(partner)
subroutine ion_electron_local_potential_bind(this, psolver, ions)
Rebind ion-electron local potential helper pointers after a Hamiltonian copy. Ensure the local potent...
subroutine ion_electron_local_potential_init(this, mesh, psolver, ions, namespace)
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
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
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
Definition: ps.F90:116
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
subroutine, public species_get_local(species, namespace, space, latt, pos, mesh, vl)
used when the density is not available, or otherwise the Poisson eqn would be used instead
subroutine, public species_get_long_range_density(species, namespace, space, latt, pos, mesh, rho, sphere_inout, nlr_x)
real(real64) function, public spline_eval(spl, x)
Definition: splines.F90:441
real(real64) pure function, public spline_range_max(this)
Definition: splines.F90:1109
subroutine, public submesh_end(this)
Definition: submesh.F90:677
logical function, public submesh_compatible(this, radius, center, dx)
Definition: submesh.F90:659
subroutine, public submesh_init(this, space, mesh, latt, center, rc)
Definition: submesh.F90:226
A type storing the information and data about a pseudopotential.
Definition: ps.F90:188
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...
Definition: submesh.F90:174
int true(void)