Line data Source code
1 : !!****m* ABINIT/m_frskerker2
2 : !! NAME
3 : !! m_frskerker2
4 : !!
5 : !! FUNCTION
6 : !! provide the ability to compute the
7 : !! penalty function and its first derivative associated
8 : !! with some residuals and a real space dielectric function
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, MT)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~ABINIT/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !! For the initials of contributors, see ~ABINIT/Infos/contributors .
16 : !!
17 : !! NOTES
18 : !! this is neither a function nor a subroutine. This is a module
19 : !! It is made of two functions and one init subroutine
20 : !!
21 : !! SOURCE
22 :
23 : #if defined HAVE_CONFIG_H
24 : #include "config.h"
25 : #endif
26 :
27 : #include "abi_common.h"
28 :
29 : module m_frskerker2
30 :
31 : use defs_basis
32 : use m_abicore
33 : use m_dtset
34 :
35 : use defs_abitypes, only : MPI_type
36 : use m_spacepar, only : laplacian
37 : use m_numeric_tools, only : dotproduct
38 :
39 : implicit none
40 :
41 : !! common variables copied from input
42 : integer,save,private :: nfft,nspden,ngfft(18)
43 : real(dp),save,allocatable,private :: deltaW(:,:),mat(:,:),rdielng(:)
44 : real(dp),save,private :: gprimd(3,3)
45 : type(dataset_type),pointer,save,private :: dtset_ptr
46 : type(MPI_type),pointer,save,private :: mpi_enreg_ptr
47 : !! common variables computed
48 : logical,save,private :: ok=.false.
49 : ! *************************************************************************
50 :
51 : contains
52 : !!***
53 :
54 : !!****f* m_frskerker2/frskerker2__init
55 : !! NAME
56 : !! frskerker2__init
57 : !!
58 : !! FUNCTION
59 : !! initialisation subroutine
60 : !! Copy every variables required for the energy calculation
61 : !! Allocate the required memory
62 : !!
63 : !! INPUTS
64 : !!
65 : !! OUTPUT
66 : !!
67 : !! SOURCE
68 :
69 8 : subroutine frskerker2__init(dtset_in,mpi_enreg_in,nfft_in,ngfft_in,nspden_in,rdielng_in,deltaW_in,gprimd_in,mat_in )
70 :
71 : !Arguments ------------------------------------
72 : type(dataset_type),target,intent(in) :: dtset_in
73 : integer,intent(in) :: nfft_in,ngfft_in(18),nspden_in
74 : real(dp),intent(in) :: deltaW_in(nfft_in,nspden_in),mat_in(nfft_in,nspden_in)
75 : real(dp),intent(in) :: rdielng_in(nfft_in)
76 : real(dp),intent(in) :: gprimd_in(3,3)
77 : type(MPI_type),target,intent(in) :: mpi_enreg_in
78 :
79 : ! *************************************************************************
80 : ! !allocation and data transfer
81 : ! !Thought it would have been more logical to use the privates intrinsic of the module as
82 : ! !input variables it seems that it is not possible...
83 8 : if(.not.ok) then
84 8 : dtset_ptr => dtset_in
85 8 : mpi_enreg_ptr => mpi_enreg_in
86 8 : nspden=nspden_in
87 8 : ngfft=ngfft_in
88 8 : nfft=nfft_in
89 32 : ABI_MALLOC(deltaW,(size(deltaW_in,1),size(deltaW_in,2)))
90 24 : ABI_MALLOC(mat,(size(mat_in,1),size(mat_in,2)))
91 24 : ABI_MALLOC(rdielng,(size(rdielng_in)))
92 80024 : deltaW=deltaW_in
93 80016 : rdielng=rdielng_in
94 80024 : mat=mat_in
95 8 : gprimd=gprimd_in
96 8 : ok = .true.
97 : end if
98 :
99 8 : end subroutine frskerker2__init
100 : !!***
101 :
102 : !!****f* m_frskerker2/frskerker2__end
103 : !! NAME
104 : !! frskerker2__end
105 : !!
106 : !! FUNCTION
107 : !! ending subroutine
108 : !! deallocate memory areas
109 : !!
110 : !! INPUTS
111 : !!
112 : !! OUTPUT
113 : !!
114 : !! SOURCE
115 :
116 8 : subroutine frskerker2__end()
117 :
118 : ! *************************************************************************
119 8 : if(ok) then
120 : ! ! set ok to false which prevent using the pf and dpf
121 8 : ok = .false.
122 : ! ! free memory
123 8 : ABI_FREE(deltaW)
124 8 : ABI_FREE(mat)
125 8 : ABI_FREE(rdielng)
126 : end if
127 :
128 8 : end subroutine frskerker2__end
129 : !!***
130 :
131 : !!****f* m_frskerker2/frskerker2__newvres2
132 : !! NAME
133 : !! frskerker2__newvres2
134 : !!
135 : !! FUNCTION
136 : !! affectation subroutine
137 : !! do the required renormalisation when providing a new value for
138 : !! the density after application of the gradient
139 : !!
140 : !! INPUTS
141 : !!
142 : !! OUTPUT
143 : !!
144 : !! SOURCE
145 :
146 114 : subroutine frskerker2__newvres2(nv1,nv2,x, grad, vrespc)
147 :
148 : !Arguments ------------------------------------
149 : integer,intent(in) :: nv1,nv2
150 : real(dp),intent(in) :: x
151 : real(dp),intent(inout)::grad(nv1,nv2)
152 : real(dp),intent(inout)::vrespc(nv1,nv2)
153 :
154 : ! *************************************************************************
155 1140228 : grad(:,:)=x*grad(:,:)
156 1140228 : vrespc(:,:)=vrespc(:,:)+grad(:,:)
157 :
158 114 : end subroutine frskerker2__newvres2
159 : !!***
160 :
161 : !!****f* m_frskerker2/frskerker2__pf
162 : !! NAME
163 : !! frskerker2__pf
164 : !!
165 : !! FUNCTION
166 : !! penalty function associated with the preconditionned residuals
167 : !!
168 : !! INPUTS
169 : !!
170 : !! OUTPUT
171 : !!
172 : !! SOURCE
173 :
174 1347 : function frskerker2__pf(nv1,nv2,vrespc)
175 :
176 : !Arguments ------------------------------------
177 : integer,intent(in) :: nv1,nv2
178 : real(dp),intent(in) ::vrespc(nv1,nv2)
179 : real(dp) ::frskerker2__pf
180 :
181 : !Local variables-------------------------------
182 2694 : real(dp) :: buffer1(nv1,nv2),buffer2(nv1,nv2)
183 : integer :: ispden
184 : ! *************************************************************************
185 :
186 1347 : if(ok) then
187 13472694 : buffer1=vrespc
188 1347 : call laplacian(gprimd,mpi_enreg_ptr,nfft,nspden,ngfft,rdfuncr=buffer1,laplacerdfuncr=buffer2)
189 2694 : do ispden=1,nspden
190 : buffer2(:,ispden)=(vrespc(:,ispden)-((rdielng(:))**2)*buffer2(:,ispden)) &
191 13472694 : & *half - deltaW(:,ispden)
192 : end do
193 : ! pf_rscgres=dotproduct(vrespc,buffer2)*half-dotproduct(vrespc,deltaW)
194 1347 : frskerker2__pf=dotproduct(nv1,nv2,vrespc,buffer2)
195 : else
196 : frskerker2__pf=zero
197 : end if
198 1347 : end function frskerker2__pf
199 : !!***
200 :
201 : !!****f* m_frskerker2/frskerker2__dpf
202 : !! NAME
203 : !! frskerker2__dpf
204 : !!
205 : !! FUNCTION
206 : !! derivative of the penalty function
207 : !! actually not the derivative but something allowing minimization
208 : !! at constant density
209 : !! formula from the work of rackowski,canning and wang
210 : !! H*phi - int(phi**2H d3r)phi
211 : !! that is the simple projection of the change on a direction
212 : !! normal to the density changes
213 : !!
214 : !! INPUTS
215 : !!
216 : !! OUTPUT
217 : !!
218 : !! SOURCE
219 :
220 2643 : function frskerker2__dpf(nv1,nv2,vrespc)
221 :
222 : !Arguments ------------------------------------
223 : integer,intent(in) :: nv1,nv2
224 : real(dp),intent(in)::vrespc(nv1,nv2)
225 : real(dp) :: frskerker2__dpf(nv1,nv2)
226 :
227 : !Local variables-------------------------------
228 881 : real(dp):: buffer1(nv1,nv2),buffer2(nv1,nv2)
229 : integer :: ispden
230 :
231 : ! *************************************************************************
232 :
233 881 : if(ok) then
234 8811762 : buffer1=vrespc
235 881 : call laplacian(gprimd,mpi_enreg_ptr,nfft,nspden,ngfft,rdfuncr=buffer1,laplacerdfuncr=buffer2)
236 1762 : do ispden=1,nspden
237 8811762 : frskerker2__dpf(:,ispden)= vrespc(:,ispden)-deltaW(:,ispden)-((rdielng(:))**2)*buffer2(:,ispden)
238 : end do
239 : else
240 0 : frskerker2__dpf = zero
241 : end if
242 :
243 : end function frskerker2__dpf
244 : !!***
245 :
246 : end module m_frskerker2
247 : !!***
|