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 debug_oct_m
26 use global_oct_m
29 use output_oct_m
31 use io_oct_m
36 use parser_oct_m
37 use pcm_oct_m
44
45 implicit none
46
47 private
48 public :: invert_ks_run
49
50contains
51
52 ! ---------------------------------------------------------
53 subroutine invert_ks_run(system)
54 class(*), intent(inout) :: system
55
56 push_sub(invert_ks_run)
57
58 select type (system)
59 class is (multisystem_basic_t)
60 message(1) = "CalculationMode = invert_ks not implemented for multi-system calculations"
61 call messages_fatal(1, namespace=system%namespace)
62 type is (electrons_t)
63 call invert_ks_run_legacy(system)
64 end select
65
66 pop_sub(invert_ks_run)
67 end subroutine invert_ks_run
68
69 ! ---------------------------------------------------------
70 subroutine invert_ks_run_legacy(sys)
71 type(electrons_t), intent(inout) :: sys
72
73 integer :: ii, jj, np, nspin
74 integer :: err
75 real(real64) :: diffdensity
76 real(real64), allocatable :: target_rho(:,:), rho(:)
77 type(restart_t) :: restart
78
79 push_sub(invert_ks_run_legacy)
80
81 if (sys%hm%pcm%run_pcm) then
82 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
83 end if
84
85 if (sys%kpoints%use_symmetries) then
86 call messages_experimental("KPoints symmetries with CalculationMode = invert_ks", namespace=sys%namespace)
87 end if
88
89 if (sys%st%d%ispin == spinors) then
90 call messages_not_implemented("Kohn-Sham inversion with spinors", namespace=sys%namespace)
91 end if
92
93 ! initialize KS inversion module
94 call xc_ks_inversion_write_info(sys%ks%ks_inversion, namespace=sys%namespace)
95
96 !abbreviations
97 np = sys%gr%np
98 nspin = sys%st%d%nspin
99
100 ! read target density
101 safe_allocate(target_rho(1:np, 1:nspin))
102 safe_allocate(rho(1:np))
103
104 call read_target_rho()
105
106 sys%hm%energy%intnvxc = m_zero
107 sys%hm%energy%hartree = m_zero
108 sys%hm%energy%exchange = m_zero
109 sys%hm%energy%correlation = m_zero
110 sys%hm%ks_pot%vxc = m_zero
111
112 ! calculate total density
113 call lalg_copy(np, target_rho(:, 1), rho)
114 do ii = 2, sys%st%d%spin_channels
115 call lalg_axpy(np, m_one, target_rho(:, ii), rho)
116 end do
117
118 ! calculate the Hartree potential
119 call dpoisson_solve(sys%hm%psolver, sys%namespace, sys%hm%ks_pot%vhartree, rho)
120
121 ! Copy it to vhxc
122 do ii = 1, sys%st%d%spin_channels
123 call lalg_copy(np, sys%hm%ks_pot%vhartree, sys%hm%ks_pot%vhxc(:, ii))
124 end do
125
126
127 write(message(1),'(a)') "Calculating KS potential"
128 call messages_info(1, namespace=sys%namespace)
129
130 ! Update the Hamiltonian
131 call invertks_update_hamiltonian(sys%namespace, sys%gr, sys%space, sys%ext_partners, &
132 sys%ks%ks_inversion%eigensolver, sys%ks%ks_inversion%aux_st, sys%hm, sys%ks%ks_inversion%max_iter)
133
134 ! Perform the KS Inversion
135 if (sys%ks%ks_inversion%method == xc_inv_method_two_particle) then ! 2-particle exact inversion
136
137 call invertks_2part(sys%ks%ks_inversion, target_rho, nspin, sys%hm, sys%gr, &
138 sys%ks%ks_inversion%aux_st, sys%ks%ks_inversion%eigensolver, sys%namespace, sys%space, &
139 sys%ext_partners)
140
141 else ! iterative case
142 if (sys%ks%ks_inversion%method >= xc_inv_method_vs_iter .and. &
143 sys%ks%ks_inversion%method <= xc_inv_method_iter_godby) then ! iterative procedure for v_s
144 call invertks_iter(sys%ks%ks_inversion, target_rho, sys%namespace, sys%space, sys%ext_partners, nspin, sys%hm, sys%gr, &
145 sys%ks%ks_inversion%aux_st, sys%ks%ks_inversion%eigensolver)
146 end if
147 end if
149 ! Update the Hamiltonian again
150 call invertks_update_hamiltonian(sys%namespace, sys%gr, sys%space, sys%ext_partners, &
151 sys%ks%ks_inversion%eigensolver, sys%ks%ks_inversion%aux_st, sys%hm, sys%ks%ks_inversion%max_iter)
152
153 ! output quality of KS inversion
154 diffdensity = m_zero
155 do jj = 1, nspin
156 do ii = 1, np
157 if (abs(sys%ks%ks_inversion%aux_st%rho(ii,jj)-target_rho(ii,jj)) > diffdensity) then
158 diffdensity = abs(sys%ks%ks_inversion%aux_st%rho(ii,jj)-target_rho(ii,jj))
159 end if
160 end do
161 end do
162 write (message(1),'(a,F16.6)') 'Achieved difference in densities wrt target:', &
163 diffdensity
164 call messages_info(1, namespace=sys%namespace)
166 ! output for all cases
167 call output_all(sys%outp, sys%namespace, sys%space, static_dir, sys%gr, sys%ions, -1, &
168 sys%ks%ks_inversion%aux_st, sys%hm, sys%ks)
169 call output_modelmb(sys%outp, sys%namespace, sys%space, static_dir, sys%gr, sys%ions, -1, &
170 sys%ks%ks_inversion%aux_st)
171
172 sys%ks%ks_inversion%aux_st%dom_st_kpt_mpi_grp = sys%st%dom_st_kpt_mpi_grp
173 ! save files in restart format
174 call restart%init(sys%namespace, restart_gs, restart_type_dump, sys%mc, err, mesh = sys%gr)
175 call states_elec_dump(restart, sys%space, sys%ks%ks_inversion%aux_st, sys%gr, sys%kpoints, err, 0)
176 if (err /= 0) then
177 message(1) = "Unable to write states wavefunctions."
178 call messages_warning(1, namespace=sys%namespace)
179 end if
180 call restart%end()
181
182 safe_deallocate_a(target_rho)
183 safe_deallocate_a(rho)
184
185 pop_sub(invert_ks_run_legacy)
186
187 contains
188
189 ! ---------------------------------------------------------
190 subroutine read_target_rho()
191 character(len=256) :: filename
192 integer :: pass, iunit, ierr, ii, npoints
193 real(real64) :: l_xx(sys%space%dim), l_ff(nspin), rr
194 real(real64), allocatable :: xx(:,:), ff(:,:)
195 character(len=1) :: char
196
198
199 ! FIXME: just use restart/gs/density*.obf file rather than needing to set this and use a different format.
200
201 !%Variable InvertKSTargetDensity
202 !%Type string
203 !%Default <tt>target_density.dat</tt>
204 !%Section Calculation Modes::Invert KS
205 !%Description
206 !% Name of the file that contains the density used as the target in the
207 !% inversion of the KS equations.
208 !%End
209 call parse_variable(sys%namespace, 'InvertKSTargetDensity', "target_density.dat", filename)
210
211 iunit = io_open(filename, sys%namespace, action='read', status='old')
212
213 npoints = 0
214 do pass = 1, 2
215 ii = -1
216 rewind(iunit)
217 do
218 if (ii == -1) then
219 read(iunit, '(a)', advance='no') char
220 ii = 0
221 if (char == '#') read(iunit, '(a)') char
222 end if
223 read(iunit, fmt=*, iostat=ierr) l_xx(:), l_ff(:)
224 if (ierr /= 0) exit
225 ii = ii + 1
226 if (pass == 1) npoints = npoints + 1
227 if (pass == 2) then
228 xx(ii, :) = l_xx(:)
229 ff(ii, :) = l_ff(:)
230 end if
231 end do
232 if (pass == 1) then
233 safe_allocate(xx(1:npoints, 1:sys%space%dim))
234 safe_allocate(ff(1:npoints, 1:nspin))
235 end if
236 end do
237
238 do ii = 1, nspin
239 call dmf_interpolate_points(sys%space%dim, npoints, xx, ff(:,ii), &
240 np, sys%gr%x_t, target_rho(:, ii))
241 end do
242
243 ! we now renormalize the density (necessary if we have a charged system)
244 rr = m_zero
245 do ii = 1, sys%st%d%spin_channels
246 rr = rr + dmf_integrate(sys%gr, target_rho(:, ii), reduce = .false.)
247 end do
248 call sys%gr%allreduce(rr)
249 rr = sys%st%qtot/rr
250 target_rho(:,:) = rr*target_rho(:,:)
251
252 safe_deallocate_a(xx)
253 safe_deallocate_a(ff)
254
256 end subroutine read_target_rho
257
258 end subroutine invert_ks_run_legacy
259
260
261end module invert_ks_oct_m
262
263!! Local Variables:
264!! mode: f90
265!! coding: utf-8
266!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
Copies a vector x, to a vector y.
Definition: lalg_basic.F90:188
subroutine read_target_rho()
Definition: invert_ks.F90:286
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
integer, parameter, public spinors
real(real64), parameter, public m_zero
Definition: global.F90:200
character(len= *), parameter, public static_dir
Definition: global.F90:279
real(real64), parameter, public m_one
Definition: global.F90:201
subroutine, public invert_ks_run(system)
Definition: invert_ks.F90:149
subroutine invert_ks_run_legacy(sys)
Definition: invert_ks.F90:166
Definition: io.F90:116
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
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 ...
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_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
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:117
subroutine, public output_all(outp, namespace, space, dir, gr, ions, iter, st, hm, ks)
Definition: output.F90:495
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
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_type_dump
Definition: restart.F90:184
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, 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:221
Container class for lists of system_oct_m::system_t.