Octopus
invert_ks.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
19#include "global.h"
20
21module invert_ks_oct_m
22 use comm_oct_m
23 use debug_oct_m
27 use global_oct_m
30 use output_oct_m
32 use io_oct_m
37 use parser_oct_m
38 use pcm_oct_m
45
46 implicit none
47
48 private
49 public :: invert_ks_run
50
51contains
52
53 ! ---------------------------------------------------------
54 subroutine invert_ks_run(system)
55 class(*), intent(inout) :: system
56
57 push_sub(invert_ks_run)
58
59 select type (system)
60 class is (multisystem_basic_t)
61 message(1) = "CalculationMode = invert_ks not implemented for multi-system calculations"
62 call messages_fatal(1, namespace=system%namespace)
63 type is (electrons_t)
64 call invert_ks_run_legacy(system)
65 end select
66
67 pop_sub(invert_ks_run)
68 end subroutine invert_ks_run
69
70 ! ---------------------------------------------------------
71 subroutine invert_ks_run_legacy(sys)
72 type(electrons_t), intent(inout) :: sys
73
74 integer :: ii, jj, np, nspin
75 integer :: err
76 real(real64) :: diffdensity
77 real(real64), allocatable :: target_rho(:,:), rho(:)
78 type(restart_t) :: restart
79
80 push_sub(invert_ks_run_legacy)
81
82 if (sys%hm%pcm%run_pcm) then
83 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
84 end if
85
86 if (sys%kpoints%use_symmetries) then
87 call messages_experimental("KPoints symmetries with CalculationMode = invert_ks", namespace=sys%namespace)
88 end if
89
90 if (sys%st%d%ispin == spinors) then
91 call messages_not_implemented("Kohn-Sham inversion with spinors", namespace=sys%namespace)
92 end if
93
94 ! initialize KS inversion module
95 call xc_ks_inversion_write_info(sys%ks%ks_inversion, namespace=sys%namespace)
96
97 !abbreviations
98 np = sys%gr%np
99 nspin = sys%st%d%nspin
100
101 ! read target density
102 safe_allocate(target_rho(1:np, 1:nspin))
103 safe_allocate(rho(1:np))
104
105 call read_target_rho()
106
107 sys%hm%energy%intnvxc = m_zero
108 sys%hm%energy%hartree = m_zero
109 sys%hm%energy%exchange = m_zero
110 sys%hm%energy%correlation = m_zero
111 sys%hm%vxc = m_zero
112
113 ! calculate total density
114 call lalg_copy(np, target_rho(:, 1), rho)
115 do ii = 2, sys%st%d%spin_channels
116 call lalg_axpy(np, m_one, target_rho(:, ii), rho)
117 end do
118
119 ! calculate the Hartree potential
120 call dpoisson_solve(sys%hm%psolver, sys%namespace, sys%hm%vhartree, rho)
121
122 ! Copy it to vhxc
123 do ii = 1, sys%st%d%spin_channels
124 call lalg_copy(np, sys%hm%vhartree, sys%hm%vhxc(:, ii))
125 end do
126
127
128 write(message(1),'(a)') "Calculating KS potential"
129 call messages_info(1, namespace=sys%namespace)
130
131 ! Update the Hamiltonian
132 call invertks_update_hamiltonian(sys%namespace, sys%gr, sys%space, sys%ext_partners, &
133 sys%ks%ks_inversion%eigensolver, sys%ks%ks_inversion%aux_st, sys%hm, sys%ks%ks_inversion%max_iter)
134
135 ! Perform the KS Inversion
136 if (sys%ks%ks_inversion%method == xc_inv_method_two_particle) then ! 2-particle exact inversion
137
138 call invertks_2part(sys%ks%ks_inversion, target_rho, nspin, sys%hm, sys%gr, &
139 sys%ks%ks_inversion%aux_st, sys%ks%ks_inversion%eigensolver, sys%namespace, sys%space, &
140 sys%ext_partners)
141
142 else ! iterative case
143 if (sys%ks%ks_inversion%method >= xc_inv_method_vs_iter .and. &
144 sys%ks%ks_inversion%method <= xc_inv_method_iter_godby) then ! iterative procedure for v_s
145 call invertks_iter(sys%ks%ks_inversion, target_rho, sys%namespace, sys%space, sys%ext_partners, nspin, sys%hm, sys%gr, &
146 sys%ks%ks_inversion%aux_st, sys%ks%ks_inversion%eigensolver)
147 end if
148 end if
149
150 ! Update the Hamiltonian again
151 call invertks_update_hamiltonian(sys%namespace, sys%gr, sys%space, sys%ext_partners, &
152 sys%ks%ks_inversion%eigensolver, sys%ks%ks_inversion%aux_st, sys%hm, sys%ks%ks_inversion%max_iter)
153
154 ! output quality of KS inversion
155 diffdensity = m_zero
156 do jj = 1, nspin
157 do ii = 1, np
158 if (abs(sys%ks%ks_inversion%aux_st%rho(ii,jj)-target_rho(ii,jj)) > diffdensity) then
159 diffdensity = abs(sys%ks%ks_inversion%aux_st%rho(ii,jj)-target_rho(ii,jj))
160 end if
161 end do
162 end do
163 write (message(1),'(a,F16.6)') 'Achieved difference in densities wrt target:', &
164 diffdensity
165 call messages_info(1, namespace=sys%namespace)
166
167 ! output for all cases
168 call output_all(sys%outp, sys%namespace, sys%space, static_dir, sys%gr, sys%ions, -1, &
169 sys%ks%ks_inversion%aux_st, sys%hm, sys%ks)
170 call output_modelmb(sys%outp, sys%namespace, sys%space, static_dir, sys%gr, sys%ions, -1, &
171 sys%ks%ks_inversion%aux_st)
172
173 sys%ks%ks_inversion%aux_st%dom_st_kpt_mpi_grp = sys%st%dom_st_kpt_mpi_grp
174 ! save files in restart format
175 call restart_init(restart, sys%namespace, restart_gs, restart_type_dump, sys%mc, err, mesh = sys%gr)
176 call states_elec_dump(restart, sys%space, sys%ks%ks_inversion%aux_st, sys%gr, sys%kpoints, err, 0)
177 if (err /= 0) then
178 message(1) = "Unable to write states wavefunctions."
179 call messages_warning(1, namespace=sys%namespace)
180 end if
181 call restart_end(restart)
182
183 safe_deallocate_a(target_rho)
184 safe_deallocate_a(rho)
185
186 pop_sub(invert_ks_run_legacy)
187
188 contains
189
190 ! ---------------------------------------------------------
191 subroutine read_target_rho()
192 character(len=256) :: filename
193 integer :: pass, iunit, ierr, ii, npoints
194 real(real64) :: l_xx(sys%space%dim), l_ff(nspin), rr
195 real(real64), allocatable :: xx(:,:), ff(:,:)
196 character(len=1) :: char
197
199
200 ! FIXME: just use restart/gs/density*.obf file rather than needing to set this and use a different format.
201
202 !%Variable InvertKSTargetDensity
203 !%Type string
204 !%Default <tt>target_density.dat</tt>
205 !%Section Calculation Modes::Invert KS
206 !%Description
207 !% Name of the file that contains the density used as the target in the
208 !% inversion of the KS equations.
209 !%End
210 call parse_variable(sys%namespace, 'InvertKSTargetDensity', "target_density.dat", filename)
211
212 iunit = io_open(filename, sys%namespace, action='read', status='old')
213
214 npoints = 0
215 do pass = 1, 2
216 ii = -1
217 rewind(iunit)
218 do
219 if (ii == -1) then
220 read(iunit, '(a)', advance='no') char
221 ii = 0
222 if (char == '#') read(iunit, '(a)') char
223 end if
224 read(iunit, fmt=*, iostat=ierr) l_xx(:), l_ff(:)
225 if (ierr /= 0) exit
226 ii = ii + 1
227 if (pass == 1) npoints = npoints + 1
228 if (pass == 2) then
229 xx(ii, :) = l_xx(:)
230 ff(ii, :) = l_ff(:)
231 end if
232 end do
233 if (pass == 1) then
234 safe_allocate(xx(1:npoints, 1:sys%space%dim))
235 safe_allocate(ff(1:npoints, 1:nspin))
236 end if
237 end do
238
239 do ii = 1, nspin
240 call dmf_interpolate_points(sys%space%dim, npoints, xx, ff(:,ii), &
241 np, sys%gr%x, target_rho(:, ii))
242 end do
243
244 ! we now renormalize the density (necessary if we have a charged system)
245 rr = m_zero
246 do ii = 1, sys%st%d%spin_channels
247 rr = rr + dmf_integrate(sys%gr, target_rho(:, ii), reduce = .false.)
248 end do
249 if (sys%gr%parallel_in_domains) then
250 call sys%gr%allreduce(rr)
251 end if
252 rr = sys%st%qtot/rr
253 target_rho(:,:) = rr*target_rho(:,:)
254
255 safe_deallocate_a(xx)
256 safe_deallocate_a(ff)
257
259 end subroutine read_target_rho
260
261 end subroutine invert_ks_run_legacy
262
263
264end module invert_ks_oct_m
265
266!! Local Variables:
267!! mode: f90
268!! coding: utf-8
269!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:170
Copies a vector x, to a vector y.
Definition: lalg_basic.F90:185
subroutine read_target_rho()
Definition: invert_ks.F90:285
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
integer, parameter, public spinors
real(real64), parameter, public m_zero
Definition: global.F90:187
character(len= *), parameter, public static_dir
Definition: global.F90:251
real(real64), parameter, public m_one
Definition: global.F90:188
subroutine, public invert_ks_run(system)
Definition: invert_ks.F90:148
subroutine invert_ks_run_legacy(sys)
Definition: invert_ks.F90:165
Definition: io.F90:114
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
This module defines various routines, operating on mesh functions.
subroutine, public dmf_interpolate_points(ndim, npoints_in, x_in, f_in, npoints_out, x_out, f_out)
This function receives a function f_in defined in a mesh, and returns the interpolated values of the ...
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1125
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1097
This module implements the basic mulsisystem class, a container system for other systems.
subroutine, public output_modelmb(outp, namespace, space, dir, gr, ions, iter, st)
this module contains the output system
Definition: output.F90:115
subroutine, public output_all(outp, namespace, space, dir, gr, ions, iter, st, hm, ks)
Definition: output.F90:491
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
integer, parameter, public restart_gs
Definition: restart.F90:229
subroutine, public restart_init(restart, namespace, data_type, type, mc, ierr, mesh, dir, exact)
Initializes a restart object.
Definition: restart.F90:514
integer, parameter, public restart_type_dump
Definition: restart.F90:225
subroutine, public restart_end(restart)
Definition: restart.F90:720
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_dump(restart, space, st, mesh, kpoints, ierr, iter, lr, st_start_writing, verbose)
integer, parameter, public xc_inv_method_iter_godby
subroutine, public invertks_2part(ks_inv, target_rho, nspin, aux_hm, gr, st, eigensolver, namespace, space, ext_partners)
Given a density, it performs the Kohn-Sham inversion, assuming a two-particle, one orbital case.
integer, parameter, public xc_inv_method_two_particle
KS inversion methods/algorithms.
integer, parameter, public xc_inv_method_vs_iter
subroutine, public xc_ks_inversion_write_info(ks_inversion, iunit, namespace)
subroutine, public invertks_iter(ks_inv, target_rho, namespace, space, ext_partners, nspin, aux_hm, gr, st, eigensolver)
Iterative inversion of KS potential from the density.
subroutine, public invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, hm, max_iter)
A small auxiliary function to perform the update of the Hamiltonian, run the eigensolver,...
Class describing the electron system.
Definition: electrons.F90:214
Container class for lists of system_oct_m::system_t.