Line data Source code
1 : !!****m* ABINIT/m_tdep_solver
2 : !! NAME
3 : !! m_tdep_solver
4 : !!
5 : !! FUNCTION
6 : !! This module contains the TDEP Solver data type
7 : !! which fits the IFC on the forces and displacements of the sampling.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2011-2026 ABINIT group (GA,FB,JB)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_tdep_solver
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_xmpi
29 : use m_io_tools
30 : use m_numeric_tools
31 : use m_linalg_interfaces
32 : use m_tdep_dataset, only : atdep_dataset_type, MPI_enreg_type
33 : use m_tdep_shell, only : Shell_type
34 : use m_tdep_sym, only : Symmetries_type
35 : use m_tdep_sampling, only : tdep_Sampling_type
36 : use m_tdep_model, only : tdep_Model_type
37 : use m_tdep_constraints, only : Constraints_type, tdep_calc_orthonorm
38 :
39 : implicit none
40 :
41 : type tdep_Solver_type
42 :
43 : integer :: order
44 : ! Maximum IFC order (2, 3, or 4)
45 :
46 : integer :: natom
47 : ! Number of atoms in the supercell
48 :
49 : integer :: natom_unitcell
50 : ! Number of atoms in the unitcell
51 :
52 : integer :: my_nstep
53 : ! Number of MD steps
54 :
55 : integer :: ntotcoeff
56 : ! Total number of coefficients
57 :
58 : integer :: ntotconst
59 : ! Total number of constraints
60 :
61 : integer :: ncoeff1st
62 : ! Number of 1st order coefficients
63 :
64 : integer :: ncoeff2nd
65 : ! Number of 2nd order coefficients
66 :
67 : integer :: ncoeff3rd
68 : ! Number of 3rd order coefficients
69 :
70 : integer :: ncoeff4th
71 : ! Number of 4th order coefficients
72 :
73 : integer :: nconst_1st
74 : ! Number of 1st order constraints
75 :
76 : integer :: nconst_2nd
77 : ! Number of 2nd order constraints
78 :
79 : integer :: nconst_3rd
80 : ! Number of 3rd order constraints
81 :
82 : integer :: nconst_4th
83 : ! Number of 4th order constraints
84 :
85 : integer :: nconst_rot2nd
86 : integer :: nconst_huang
87 : integer :: nconst_dynmat
88 : integer :: nconst_rot3rd
89 : integer :: nconst_asr3rd
90 : integer :: nconst_rot4th
91 : integer :: nconst_asr4th
92 :
93 : double precision, allocatable :: fcoeff(:,:)
94 : ! fcoeff(3*natom*my_nstep,ntotcoeff)
95 : ! All the cartesian displacement matrices
96 : ! at every order (u, u*u, u*u*u, u*u*u*u).
97 :
98 : double precision, allocatable :: const(:,:)
99 : ! const(ntotconst,ntotcoeff)
100 : ! The constraint matrices.
101 :
102 : double precision, allocatable :: theta(:)
103 : ! theta(ntotcoeff)
104 : ! The IFC coefficients at all orders, as a flat array.
105 :
106 : double precision, allocatable :: Forces(:)
107 : ! Forces(3*natom*my_nstep)
108 : ! The cartesian forces for all configurations, as a flat array.
109 : ! These are weighted by the number of configurations.
110 : ! In case of dipole-dipole interaction, the long-range part of the
111 : ! forces should be removed.
112 :
113 : end type tdep_Solver_type
114 :
115 : public :: tdep_solver_init
116 : public :: tdep_solver_free
117 : public :: tdep_solver_set_residual_forces
118 : public :: tdep_calc_phi1fcoeff
119 : public :: tdep_calc_phi2fcoeff
120 : public :: tdep_calc_phi3fcoeff
121 : public :: tdep_calc_phi4fcoeff
122 : public :: tdep_calc_MoorePenrose
123 : public :: tdep_calc_constraints
124 :
125 : contains
126 :
127 : !=====================================================================================================
128 :
129 44 : subroutine tdep_solver_init(Solver, Invar, Shell1at, Shell2at, Shell3at, Shell4at)
130 :
131 : type(tdep_Solver_type), intent(inout) :: Solver
132 : type(atdep_dataset_type),intent(in) :: Invar
133 : type(Shell_type),intent(in) :: Shell1at, Shell2at, Shell3at, Shell4at
134 :
135 44 : Solver%order = Invar%order
136 44 : Solver%natom = Invar%natom
137 44 : Solver%natom_unitcell = Invar%natom_unitcell
138 44 : Solver%my_nstep = Invar%my_nstep
139 :
140 : !Rotational invariances (1st order)
141 : ! constraints = 3
142 44 : Solver%nconst_1st = 3**2
143 :
144 : !Rotational invariances (2nd order) + Symetry of the Dynamical Matrix + Huang invariances
145 : ! constraints = natom*3**2 + (3*natom_unitcell)**2 + 3**4
146 44 : Solver%nconst_rot2nd = 3**3*Solver%natom_unitcell
147 44 : Solver%nconst_dynmat = (3*Solver%natom_unitcell)**2
148 44 : Solver%nconst_huang = 3**4
149 44 : Solver%nconst_2nd = Solver%nconst_rot2nd + Solver%nconst_dynmat + Solver%nconst_huang
150 :
151 : !Rotational invariances (3rd order) + acoustic sum rules (3rd order)
152 44 : Solver%nconst_3rd=0
153 44 : if (Solver%order.ge.3) then
154 : ! constraints = natom_unitcell*natom*3**4 + natom_unitcell*natom*3**3
155 14 : Solver%nconst_rot3rd = 3**4 * Solver%natom_unitcell * Solver%natom
156 14 : Solver%nconst_asr3rd = 3**3 * Solver%natom_unitcell * Solver%natom
157 14 : Solver%nconst_3rd = Solver%nconst_rot3rd + Solver%nconst_asr3rd
158 : end if
159 :
160 : !Rotational invariances (4th order) + acoustic sum rules (4th order)
161 44 : Solver%nconst_4th=0
162 44 : if (Solver%order.ge.4) then
163 : ! constraints = natom_unitcell*natom**2*3**5 + natom_unitcell*natom**2*3**4
164 : !FB Solver%nconst_rot4th = 3**5*natom_unitcell*natom**2
165 : !FB4TH Solver%nconst_asr4th = 3**4*natom_unitcell*natom**2
166 8 : Solver%nconst_rot4th = 0
167 8 : Solver%nconst_asr4th = 0
168 : Solver%nconst_4th = Solver%nconst_rot4th + Solver%nconst_asr4th
169 : end if
170 :
171 44 : Solver%ncoeff1st = Shell1at%ntotcoeff
172 44 : Solver%ncoeff2nd = Shell2at%ntotcoeff
173 44 : Solver%ncoeff3rd = 0
174 44 : Solver%ncoeff4th = 0
175 44 : if (Solver%order.ge.3) Solver%ncoeff3rd = Shell3at%ntotcoeff
176 44 : if (Solver%order.ge.4) Solver%ncoeff4th = Shell4at%ntotcoeff
177 :
178 44 : Solver%ntotcoeff = Solver%ncoeff1st + Solver%ncoeff2nd + Solver%ncoeff3rd + Solver%ncoeff4th
179 44 : Solver%ntotconst = Solver%nconst_1st + Solver%nconst_2nd + Solver%nconst_3rd + Solver%nconst_4th
180 :
181 25945165 : ABI_CALLOC(Solver%fcoeff, (3*Solver%natom*Solver%my_nstep,Solver%ntotcoeff))
182 50744071 : ABI_CALLOC(Solver%const, (Solver%ntotconst,Solver%ntotcoeff))
183 417588 : ABI_CALLOC(Solver%Forces, (3*Solver%natom*Solver%my_nstep))
184 2873 : ABI_CALLOC(Solver%theta, (Solver%ntotcoeff))
185 :
186 44 : end subroutine tdep_solver_init
187 :
188 : !=====================================================================================================
189 :
190 44 : subroutine tdep_solver_free(Solver)
191 :
192 : type(tdep_Solver_type), intent(inout) :: Solver
193 :
194 44 : ABI_FREE(Solver%fcoeff)
195 44 : ABI_FREE(Solver%const)
196 44 : ABI_FREE(Solver%Forces)
197 44 : ABI_FREE(Solver%theta)
198 :
199 44 : end subroutine tdep_solver_free
200 :
201 : !=====================================================================================================
202 :
203 : !!***
204 : !!****f* ABINIT/m_tdep_solver/tdep_solver_set_residual_forces
205 : !! NAME
206 : !! tdep_solver_set_residual_forces
207 : !!
208 : !! FUNCTION
209 : !! Compute the residual forces into the solver, that is, the differences
210 : !! between the MD forces and the ones from the TDEP model.
211 : !! The model forces may be zero, but they are non-zero when we remove
212 : !! the long-range part of the IFC forces, or when we solve each IFC order
213 : !! successively, and we remove the forces from the previously computed orders.
214 : !!
215 : !! INPUTS
216 : !! Solver = TDEP Solver object that will compute the coefficients.
217 : !! MD = TDEP Sampling object containing the input positions and forces.
218 : !! Model = TDEP Model object containing the IFC and corresponding forces.
219 : !!
220 : !! OUTPUT
221 : !!
222 : !! SIDE EFFECTS
223 : !! The following quantities in MD are computed:
224 : !!
225 : !! NOTES
226 : !!
227 : !! SOURCE
228 :
229 47 : subroutine tdep_solver_set_residual_forces(Solver, MD, Model)
230 :
231 : type(tdep_Solver_type), intent(inout) :: Solver
232 : type(tdep_Sampling_type), intent(in) :: MD
233 : type(tdep_Model_type), intent(in) :: Model
234 :
235 : integer :: ii,jj,istep,iatom
236 :
237 1059 : do istep=1,MD%my_nstep
238 151731 : do iatom=1,MD%natom
239 603700 : do ii=1,3
240 452016 : jj = ii + 3*(iatom-1) + 3*MD%natom*(istep-1)
241 602688 : Solver%Forces(jj) = (MD%Forces(jj) - Model%Forces(jj)) * MD%weights(istep)
242 : end do
243 : end do
244 : end do
245 :
246 47 : end subroutine tdep_solver_set_residual_forces
247 :
248 : !====================================================================================================
249 :
250 43 : subroutine tdep_calc_phi1fcoeff(Solver,Invar,Shell1at,Sym)
251 :
252 : type(tdep_Solver_type), intent(inout) :: Solver
253 : type(atdep_dataset_type),intent(in) :: Invar
254 : type(Shell_type),intent(in) :: Shell1at
255 : type(Symmetries_type),intent(in) :: Sym
256 :
257 : integer :: ishell,ncoeff,ncoeff_prev,istep,iatom,iatshell,iat_mod
258 : integer :: icoeff,isym,mu,iatref
259 : double precision :: terme
260 :
261 43 : write(Invar%stdout,*) ' '
262 43 : write(Invar%stdout,*) '#############################################################################'
263 43 : write(Invar%stdout,*) '############## Fill the matrices used in the pseudo-inverse #################'
264 43 : write(Invar%stdout,*) '#############################################################################'
265 :
266 43 : write(Invar%stdout,*) ' Compute the coefficients (at the 1st order) used in the Moore-Penrose...'
267 105 : do ishell=1,Shell1at%nshell
268 62 : if (Shell1at%neighbours(1,ishell)%n_interactions.eq.0) cycle
269 43 : do iatshell=1,Shell1at%neighbours(1,ishell)%n_interactions
270 0 : iatom=Shell1at%neighbours(1,ishell)%atomj_in_shell(iatshell)
271 0 : iat_mod=mod(iatom+Invar%natom_unitcell-1,Invar%natom_unitcell)+1
272 0 : if (iat_mod==1) cycle
273 0 : iatref=Shell1at%iatref(ishell)
274 0 : isym=Shell1at%neighbours(1,ishell)%sym_in_shell(iatshell)
275 0 : ncoeff =Shell1at%ncoeff(ishell)
276 0 : ncoeff_prev=Shell1at%ncoeff_prev(ishell)
277 62 : do mu=1,3
278 0 : do icoeff=1,ncoeff
279 0 : terme=sum(Sym%S_ref(mu,:,isym,1)*Shell1at%proj(:,icoeff,ishell))
280 0 : do istep=1,Invar%my_nstep
281 : Solver%fcoeff(mu+3*(iatom-1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)= &
282 0 : & Solver%fcoeff(mu+3*(iatom-1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)+terme
283 : ! Add all the other contributions, when iat_mod==1 (due to ASR)
284 : Solver%fcoeff(mu+3*(iatom-iat_mod+1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)= &
285 0 : & Solver%fcoeff(mu+3*(iatom-iat_mod+1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)-terme
286 : end do !istep
287 : end do
288 : end do
289 : end do !iatshell
290 : end do !ishell
291 43 : write(Invar%stdout,*) ' ------- achieved'
292 :
293 43 : end subroutine tdep_calc_phi1fcoeff
294 :
295 : !====================================================================================================
296 :
297 43 : subroutine tdep_calc_phi2fcoeff(Solver,Invar,Shell2at,Sym,MD)
298 :
299 : type(tdep_Solver_type), intent(inout) :: Solver
300 : type(atdep_dataset_type),intent(in) :: Invar
301 : type(Shell_type),intent(in) :: Shell2at
302 : type(Symmetries_type),intent(in) :: Sym
303 : type(tdep_Sampling_type), intent(in) :: MD
304 :
305 : integer :: ishell,ncoeff,ncoeff_prev,istep,iatom,jatom,iatshell
306 : integer :: icoeff,isym
307 : integer :: mu,nu,alpha,beta,itrans
308 : double precision :: terme,temp
309 : double precision :: udiff(3),SSu(3,9)
310 43 : double precision, allocatable :: SS_ref(:,:,:,:,:)
311 :
312 : ! For each couple of atoms, transform the Phi2 (3x3) ifc matrix using the symetry operation (S)
313 : ! Note: iatom=1 is excluded in order to take into account the atomic sum rule (see below)
314 358210 : ABI_MALLOC(SS_ref,(3,9,3,Sym%nsym,2)); SS_ref(:,:,:,:,:)=zero
315 1641 : do isym=1,Sym%nsym
316 6435 : do mu=1,3
317 20774 : do alpha=1,3
318 62322 : do nu=1,3
319 186966 : do beta=1,3
320 129438 : temp=Sym%S_ref(mu,alpha,isym,1)*Sym%S_ref(nu,beta,isym,1)
321 129438 : SS_ref(mu,beta+(alpha-1)*3,nu,isym,1)=temp
322 172584 : SS_ref(mu,alpha+(beta-1)*3,nu,isym,2)=temp
323 : end do
324 : end do
325 : end do
326 : end do
327 : end do
328 :
329 43 : write(Invar%stdout,*) ' Compute the coefficients (at the 2nd order) used in the Moore-Penrose...'
330 522 : do ishell=1,Shell2at%nshell
331 68344 : do iatom=1,Invar%natom
332 67822 : if (Shell2at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
333 462411 : do iatshell=1,Shell2at%neighbours(iatom,ishell)%n_interactions
334 405630 : jatom=Shell2at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
335 405630 : if (iatom==jatom) cycle
336 399260 : isym=Shell2at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
337 399260 : itrans=Shell2at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
338 399260 : ncoeff =Shell2at%ncoeff(ishell)
339 399260 : ncoeff_prev=Shell2at%ncoeff_prev(ishell)+Solver%ncoeff1st
340 :
341 8424474 : do istep=1,Invar%my_nstep
342 : ! In order to impose the acoustic sum rule we use (u(j)-u(i))==u_j^\nu
343 7957392 : udiff(1)=(MD%ucart(1,jatom,istep)-MD%ucart(1,iatom,istep))*MD%weights(istep)
344 7957392 : udiff(2)=(MD%ucart(2,jatom,istep)-MD%ucart(2,iatom,istep))*MD%weights(istep)
345 7957392 : udiff(3)=(MD%ucart(3,jatom,istep)-MD%ucart(3,iatom,istep))*MD%weights(istep)
346 :
347 : ! F_i^\mu(t)=\sum_{\alpha\beta,j,\nu}S^{\mu\alpha}.S^{\nu\beta}.\Phi_{ij}^{\alpha\beta}.u_j^\nu(t)
348 7957392 : SSu(:,:)=zero
349 31829568 : do nu=1,3
350 891227904 : SSu(:,:)=SSu(:,:)+SS_ref(:,:,nu,isym,itrans)*udiff(nu)
351 : end do
352 32235198 : do mu=1,3
353 134399328 : do icoeff=1,ncoeff
354 1025697600 : terme=sum(SSu(mu,:)*Shell2at%proj(:,icoeff,ishell))
355 : !FB write(Invar%stdlog,*) 'indices=', mu+3*(iatom-1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev
356 : Solver%fcoeff(mu+3*(iatom-1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)= &
357 126441936 : & Solver%fcoeff(mu+3*(iatom-1)+3*Invar%natom*(istep-1),icoeff+ncoeff_prev)+terme
358 : end do
359 : end do
360 :
361 : end do !istep
362 : end do !iatshell
363 : end do !iatom
364 : end do !ishell
365 43 : write(Invar%stdout,*) ' ------- achieved'
366 43 : ABI_FREE(SS_ref)
367 :
368 43 : end subroutine tdep_calc_phi2fcoeff
369 :
370 : !====================================================================================================
371 :
372 14 : subroutine tdep_calc_phi3fcoeff(Solver,Invar,Shell3at,Sym,MD)
373 :
374 : type(tdep_Solver_type), intent(inout) :: Solver
375 : type(atdep_dataset_type),intent(in) :: Invar
376 : type(Shell_type),intent(in) :: Shell3at
377 : type(Symmetries_type),intent(in) :: Sym
378 : type(tdep_Sampling_type), intent(in) :: MD
379 :
380 : integer :: ishell,ncoeff,ncoeff_prev,istep,iatom,jatom,katom
381 : integer :: icoeff,isym,itrans,iatshell
382 : integer :: mu,nu,xi,alpha,beta,gama,iindex
383 : double precision :: temp
384 : double precision :: udiff_ki(3),udiff_ji(3)
385 14 : double precision, allocatable :: SSS_proj(:,:,:,:)
386 : double precision :: SSS_tmp(27), proj_tmp(27)
387 14 : type(Constraints_type) :: Const
388 :
389 3102 : ABI_MALLOC(Const%Sprod,(Sym%nsym,6))
390 510 : do isym=1,Sym%nsym
391 3486 : do itrans=1,6
392 2931856 : ABI_MALLOC(Const%Sprod(isym,itrans)%SSS,(3,27,3,3)); Const%Sprod(isym,itrans)%SSS(:,:,:,:)=zero
393 : end do
394 : end do
395 :
396 : ! For each couple of atoms, transform the Phi3 (3x3x3) ifc matrix using the symetry operation (S)
397 : ! Note: iatom=1 is excluded in order to take into account the atomic sum rule (see below)
398 510 : do isym=1,Sym%nsym
399 1998 : do mu=1,3
400 6448 : do alpha=1,3
401 19344 : do nu=1,3
402 58032 : do beta=1,3
403 174096 : do xi=1,3
404 522288 : do gama=1,3
405 361584 : temp=Sym%S_ref(mu,alpha,isym,1)*Sym%S_ref(nu,beta,isym,1)*Sym%S_ref(xi,gama,isym,1)
406 361584 : Const%Sprod(isym,1)%SSS(mu,gama+(beta-1)*3+(alpha-1)*9,nu,xi)=temp !\Phi3_efg
407 361584 : Const%Sprod(isym,2)%SSS(mu,gama+(beta-1)*3+(alpha-1)*9,xi,nu)=temp !\Phi3_egf
408 361584 : Const%Sprod(isym,3)%SSS(nu,gama+(beta-1)*3+(alpha-1)*9,mu,xi)=temp !\Phi3_feg
409 361584 : Const%Sprod(isym,4)%SSS(nu,gama+(beta-1)*3+(alpha-1)*9,xi,mu)=temp !\Phi3_fge
410 361584 : Const%Sprod(isym,5)%SSS(xi,gama+(beta-1)*3+(alpha-1)*9,mu,nu)=temp !\Phi3_gef
411 482112 : Const%Sprod(isym,6)%SSS(xi,gama+(beta-1)*3+(alpha-1)*9,nu,mu)=temp !\Phi3_gfe
412 : end do
413 : end do
414 : end do
415 : end do
416 : end do
417 : end do
418 : end do
419 :
420 14 : write(Invar%stdout,*) ' Compute the coefficients (at the 3rd order) used in the Moore-Penrose...'
421 63 : do ishell=1,Shell3at%nshell
422 8391 : do iatom=1,Invar%natom
423 8328 : if (Shell3at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
424 86485 : do iatshell=1,Shell3at%neighbours(iatom,ishell)%n_interactions
425 79388 : jatom=Shell3at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
426 79388 : katom=Shell3at%neighbours(iatom,ishell)%atomk_in_shell(iatshell)
427 : !FB if (iatom==jatom.or.iatom==katom) cycle
428 79388 : isym =Shell3at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
429 79388 : itrans=Shell3at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
430 79388 : ncoeff =Shell3at%ncoeff(ishell)
431 79388 : ncoeff_prev=Shell3at%ncoeff_prev(ishell)+Solver%ncoeff2nd+Solver%ncoeff1st
432 :
433 20913204 : ABI_MALLOC(SSS_proj,(3,3,3,ncoeff)) ; SSS_proj(:,:,:,:)=zero
434 317552 : do mu=1,3
435 1032044 : do nu=1,3
436 3096132 : do xi=1,3
437 60017328 : SSS_tmp(:)=Const%Sprod(isym,itrans)%SSS(mu,:,nu,xi)
438 16813620 : do icoeff=1,ncoeff
439 390758256 : proj_tmp(:)=Shell3at%proj(:,icoeff,ishell)
440 16099128 : SSS_proj(mu,nu,xi,icoeff)=DDOT(27,SSS_tmp,1,proj_tmp,1)
441 : end do
442 : end do
443 : end do
444 : end do
445 1667148 : do istep=1,Invar%my_nstep
446 1587760 : iindex=3*(iatom-1)+3*Invar%natom*(istep-1)
447 : ! In order to impose the acoustic sum rule we use :
448 : !FB udiff_ji(:)=MD%ucart(:,jatom,istep)-MD%ucart(:,iatom,istep)
449 : !FB udiff_ki(:)=MD%ucart(:,katom,istep)-MD%ucart(:,iatom,istep)
450 6351040 : udiff_ji(:)=MD%ucart(:,jatom,istep)
451 6351040 : udiff_ki(:)=MD%ucart(:,katom,istep)
452 : ! F_i^{\mu}(t)=\sum_{\alpha\beta\gamma,jk,\nu\xi} S^{\mu\alpha}.S^{\nu\beta}.S^{\xi\gamma}.
453 : ! \Phi3_{ijk}^{\alpha\beta\gamma}.udiff_k^\xi(t).udiff_j^\nu(t)
454 6430428 : do nu=1,3
455 20640880 : do xi=1,3
456 : Solver%fcoeff(iindex+1:iindex+3,ncoeff_prev+1:ncoeff_prev+ncoeff)= &
457 : & Solver%fcoeff(iindex+1:iindex+3,ncoeff_prev+1:ncoeff_prev+ncoeff)+&
458 391203840 : & SSS_proj(1:3,nu,xi,1:ncoeff)*udiff_ji(nu)*udiff_ki(xi)/2.d0*MD%weights(istep)
459 : end do
460 : end do
461 : end do !istep
462 87716 : ABI_FREE(SSS_proj)
463 : end do !iatshell
464 : end do !iatom
465 : end do !ishell
466 14 : write(Invar%stdout,*) ' ------- achieved'
467 510 : do isym=1,Sym%nsym
468 3486 : do itrans=1,6
469 3472 : ABI_FREE(Const%Sprod(isym,itrans)%SSS)
470 : end do
471 : end do
472 3004 : ABI_FREE(Const%Sprod)
473 :
474 14 : end subroutine tdep_calc_phi3fcoeff
475 :
476 : !====================================================================================================
477 :
478 8 : subroutine tdep_calc_phi4fcoeff(Solver,Invar,Shell4at,Sym,MD)
479 :
480 : type(tdep_Solver_type), intent(inout) :: Solver
481 : type(atdep_dataset_type),intent(in) :: Invar
482 : type(Shell_type),intent(in) :: Shell4at
483 : type(Symmetries_type),intent(in) :: Sym
484 : type(tdep_Sampling_type), intent(inout) :: MD
485 :
486 : integer :: ishell,ncoeff,ncoeff_prev,istep,iatom,jatom,katom,latom
487 : integer :: icoeff,isym,iatshell,itrans,counter
488 : integer :: mu,nu,xi,zeta,alpha,beta,gama,delta,iindex_l,iindex_h
489 : integer :: ncoeff_prev_l,ncoeff_prev_h
490 : double precision :: temp,SSSS_tmp(81),proj_tmp(81)
491 8 : double precision, allocatable :: SSSS_proj(:,:,:,:,:)
492 8 : type(Constraints_type) :: Const
493 :
494 7032 : ABI_MALLOC(Const%Sprod,(Sym%nsym,24))
495 292 : do isym=1,Sym%nsym
496 7108 : do itrans=1,24
497 59899292 : ABI_MALLOC(Const%Sprod(isym,itrans)%SSSS,(3,81,3,3,3)); Const%Sprod(isym,itrans)%SSSS(:,:,:,:,:)=zero
498 : end do
499 : end do
500 :
501 : ! For each couple of atoms, transform the Phi4 (3x3x3) ifc matrix using the symetry operation (S)
502 : ! Note: iatom=1 is excluded in order to take into account the atomic sum rule (see below)
503 292 : do isym=1,Sym%nsym
504 1144 : do mu=1,3
505 3692 : do alpha=1,3
506 11076 : do nu=1,3
507 33228 : do beta=1,3
508 99684 : do xi=1,3
509 299052 : do gama=1,3
510 897156 : do zeta=1,3
511 2691468 : do delta=1,3
512 : #if defined FC_NVHPC
513 : if (itrans == -1) write(std_out, *)"NVHPC freezes here that is fixed by this print statement."
514 : #endif
515 :
516 1863324 : counter=delta+(gama-1)*3+(beta-1)*9+(alpha-1)*27
517 : temp=Sym%S_ref(mu,alpha,isym,1)*Sym%S_ref(nu ,beta ,isym,1)*&
518 1863324 : & Sym%S_ref(xi,gama ,isym,1)*Sym%S_ref(zeta,delta,isym,1)
519 1863324 : Const%Sprod(isym,1 )%SSSS(mu,counter,nu,xi,zeta)=temp !\Phi4_efgh
520 1863324 : Const%Sprod(isym,2 )%SSSS(mu,counter,xi,nu,zeta)=temp !\Phi4_egfh
521 1863324 : Const%Sprod(isym,3 )%SSSS(nu,counter,mu,xi,zeta)=temp !\Phi4_fegh
522 1863324 : Const%Sprod(isym,4 )%SSSS(nu,counter,xi,mu,zeta)=temp !\Phi4_fgeh
523 1863324 : Const%Sprod(isym,5 )%SSSS(xi,counter,mu,nu,zeta)=temp !\Phi4_gefh
524 1863324 : Const%Sprod(isym,6 )%SSSS(xi,counter,nu,mu,zeta)=temp !\Phi4_gfeh
525 :
526 1863324 : Const%Sprod(isym,7 )%SSSS(mu,counter,nu,zeta,xi)=temp !\Phi4_efhg
527 1863324 : Const%Sprod(isym,8 )%SSSS(mu,counter,xi,zeta,nu)=temp !\Phi4_eghf
528 1863324 : Const%Sprod(isym,9 )%SSSS(nu,counter,mu,zeta,xi)=temp !\Phi4_fehg
529 1863324 : Const%Sprod(isym,10)%SSSS(nu,counter,xi,zeta,mu)=temp !\Phi4_fghe
530 1863324 : Const%Sprod(isym,11)%SSSS(xi,counter,mu,zeta,nu)=temp !\Phi4_gehf
531 1863324 : Const%Sprod(isym,12)%SSSS(xi,counter,nu,zeta,mu)=temp !\Phi4_gfhe
532 :
533 1863324 : Const%Sprod(isym,13)%SSSS(mu,counter,zeta,nu,xi)=temp !\Phi4_ehfg
534 1863324 : Const%Sprod(isym,14)%SSSS(mu,counter,zeta,xi,nu)=temp !\Phi4_ehgf
535 1863324 : Const%Sprod(isym,15)%SSSS(nu,counter,zeta,mu,xi)=temp !\Phi4_fheg
536 1863324 : Const%Sprod(isym,16)%SSSS(nu,counter,zeta,xi,mu)=temp !\Phi4_fhge
537 1863324 : Const%Sprod(isym,17)%SSSS(xi,counter,zeta,mu,nu)=temp !\Phi4_ghef
538 1863324 : Const%Sprod(isym,18)%SSSS(xi,counter,zeta,nu,mu)=temp !\Phi4_ghfe
539 :
540 1863324 : Const%Sprod(isym,19)%SSSS(zeta,counter,mu,nu,xi)=temp !\Phi4_hefg
541 1863324 : Const%Sprod(isym,20)%SSSS(zeta,counter,mu,xi,nu)=temp !\Phi4_hegf
542 1863324 : Const%Sprod(isym,21)%SSSS(zeta,counter,nu,mu,xi)=temp !\Phi4_hfeg
543 1863324 : Const%Sprod(isym,22)%SSSS(zeta,counter,nu,xi,mu)=temp !\Phi4_hfge
544 1863324 : Const%Sprod(isym,23)%SSSS(zeta,counter,xi,mu,nu)=temp !\Phi4_hgef
545 2484432 : Const%Sprod(isym,24)%SSSS(zeta,counter,xi,nu,mu)=temp !\Phi4_hgfe
546 :
547 : end do
548 : end do
549 : end do
550 : end do
551 : end do
552 : end do
553 : end do
554 : end do
555 : end do
556 :
557 8 : write(Invar%stdout,*) ' Compute the coefficients (at the 4th order) used in the Moore-Penrose...'
558 54 : do ishell=1,Shell4at%nshell
559 7886 : do iatom=1,Invar%natom
560 7832 : if (Shell4at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
561 250586 : do iatshell=1,Shell4at%neighbours(iatom,ishell)%n_interactions
562 243732 : jatom=Shell4at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
563 243732 : katom=Shell4at%neighbours(iatom,ishell)%atomk_in_shell(iatshell)
564 243732 : latom=Shell4at%neighbours(iatom,ishell)%atoml_in_shell(iatshell)
565 243732 : isym =Shell4at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
566 243732 : itrans=Shell4at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
567 243732 : ncoeff =Shell4at%ncoeff(ishell)
568 243732 : ncoeff_prev=Shell4at%ncoeff_prev(ishell)+Solver%ncoeff3rd+Solver%ncoeff2nd+Solver%ncoeff1st
569 243732 : ncoeff_prev_l=ncoeff_prev+1
570 243732 : ncoeff_prev_h=ncoeff_prev+ncoeff
571 : #if defined FC_NVHPC
572 : if (itrans == -1) write(std_out, *)"NVHPC freezes here that is fixed by this print statement."
573 : #endif
574 699105928 : ABI_MALLOC(SSSS_proj,(3,3,3,3,ncoeff)) ; SSSS_proj(:,:,:,:,:)=zero
575 974928 : do mu=1,3
576 3168516 : do nu=1,3
577 9505548 : do xi=1,3
578 28516644 : do zeta=1,3
579 1618867944 : SSSS_tmp(:)=Const%Sprod(isym,itrans)%SSSS(mu,:,nu,xi,zeta)
580 493830108 : do icoeff=1,ncoeff
581 38335578264 : proj_tmp(:)=Shell4at%proj(:,icoeff,ishell)
582 : ! SSSS_proj(mu,nu,xi,zeta,icoeff)=DDOT(81,Const%Sprod(isym,itrans)%SSSS(mu,:,nu,xi,zeta),1,proj(:,icoeff,ishell),1)
583 487249344 : SSSS_proj(mu,nu,xi,zeta,icoeff)=DDOT(81,SSSS_tmp,1,proj_tmp,1)
584 : end do
585 : end do
586 : end do
587 : end do
588 : end do
589 5118372 : do istep=1,Invar%my_nstep
590 4874640 : iindex_l=3*(iatom-1)+3*Invar%natom*(istep-1)+1
591 4874640 : iindex_h=3*(iatom-1)+3*Invar%natom*(istep-1)+3
592 : ! F_i^{\mu}(t)=\sum_{\alpha\beta\gamma\delta,jkl,\nu\xi\zeta} S^{\mu\alpha}.S^{\nu\beta}.S^{\xi\gamma}.S^{\zeta\delta}.
593 : ! \Phi4_{ijkl}^{\alpha\beta\gamma\delta}.u_l^\zeta(t).u_k^\xi(t).u_j^\nu(t)
594 19742292 : do nu=1,3
595 63370320 : do xi=1,3
596 190110960 : do zeta=1,3
597 : Solver%fcoeff(iindex_l:iindex_h,ncoeff_prev_l:ncoeff_prev_h)= &
598 : & Solver%fcoeff(iindex_l:iindex_h,ncoeff_prev_l:ncoeff_prev_h)+&
599 : & SSSS_proj(1:3,nu,xi,zeta,1:ncoeff)*MD%ucart(nu,jatom,istep)*MD%ucart(xi,katom,istep)*MD%ucart(zeta,latom,istep)/6.d0 *&
600 12642341760 : & MD%weights(istep)
601 : end do
602 : end do
603 : end do
604 : end do !istep
605 251564 : ABI_FREE(SSSS_proj)
606 : end do !iatshell
607 : end do !iatom
608 : end do !ishell
609 8 : write(Invar%stdout,*) ' ------- achieved'
610 292 : do isym=1,Sym%nsym
611 7108 : do itrans=1,24
612 7100 : ABI_FREE(Const%Sprod(isym,itrans)%SSSS)
613 : end do
614 : end do
615 6832 : ABI_FREE(Const%Sprod)
616 :
617 8 : end subroutine tdep_calc_phi4fcoeff
618 :
619 : !=====================================================================================================
620 :
621 45 : subroutine tdep_calc_MoorePenrose(Solver,simult,Invar,MPIdata)
622 :
623 : type(tdep_Solver_type), intent(inout) :: Solver
624 : type(atdep_dataset_type),intent(in) :: Invar
625 : type(MPI_enreg_type), intent(in) :: MPIdata
626 : integer, intent(in) :: simult
627 :
628 : integer :: INFO,ntotcoeff,ntotconst
629 : integer :: natnstep,nconcoef,ierr,ncoeff_prev,nconst_prev,iconst,icoeff
630 45 : integer, allocatable :: IPIV(:)
631 45 : double precision, allocatable :: WORK(:)
632 45 : double precision, allocatable :: ffcoeff_tmp(:,:),fforces_tmp(:),b_const(:)
633 45 : double precision, allocatable :: A_tot(:,:),A_inv(:,:),b_tot(:),x_tot(:)
634 :
635 45 : write(Invar%stdout,*) '################### And compute the pseudo-inverse ##########################'
636 45 : write(Invar%stdout,*) '#############################################################################'
637 :
638 45 : natnstep = 3 * Solver%natom * Solver%my_nstep
639 :
640 45 : if (simult.eq.0) then
641 : ! Simultaneously (Invar%together=1)
642 42 : ncoeff_prev=0
643 42 : nconst_prev=0
644 42 : ntotcoeff=Solver%ntotcoeff
645 42 : ntotconst=Solver%ntotconst
646 3 : else if (simult.eq.1) then
647 : ! Successively (Invar%together=0 and Invar%order=2)
648 1 : ncoeff_prev=0
649 1 : nconst_prev=0
650 1 : ntotcoeff=Solver%ncoeff1st +Solver%ncoeff2nd
651 1 : ntotconst=Solver%nconst_1st+Solver%nconst_2nd
652 2 : else if (simult.eq.2) then
653 : ! Successively (Invar%together=0 and Invar%order=3)
654 1 : ncoeff_prev=Solver%ncoeff1st +Solver%ncoeff2nd
655 1 : nconst_prev=Solver%nconst_1st+Solver%nconst_2nd
656 1 : ntotcoeff=Solver%ncoeff3rd
657 1 : ntotconst=Solver%nconst_3rd
658 1 : else if (simult.eq.3) then
659 : ! Successively (Invar%together=0 and Invar%order=4)
660 1 : ncoeff_prev=Solver%ncoeff1st +Solver%ncoeff2nd +Solver%ncoeff3rd
661 1 : nconst_prev=Solver%nconst_1st+Solver%nconst_2nd+Solver%nconst_3rd
662 1 : ntotcoeff=Solver%ncoeff4th
663 1 : ntotconst=Solver%nconst_4th
664 : end if
665 45 : nconcoef=ntotcoeff+ntotconst
666 45 : if ((ntotconst.gt.0).and.(simult.ge.2)) then
667 23 : ABI_MALLOC(b_const,(ntotconst)) ; b_const(:)=0.d0
668 21 : do iconst=1,ntotconst
669 521 : do icoeff=1,ncoeff_prev
670 : b_const(iconst)=b_const(iconst)+&
671 520 : & Solver%const(nconst_prev+iconst,icoeff)*Solver%theta(icoeff)
672 : end do
673 : end do
674 : end if
675 :
676 461308 : ABI_CALLOC(ffcoeff_tmp,(ntotcoeff,ntotcoeff))
677 2780 : ABI_CALLOC(fforces_tmp,(ntotcoeff))
678 653574 : ABI_CALLOC(A_tot,(nconcoef,nconcoef))
679 653574 : ABI_CALLOC(A_inv,(nconcoef,nconcoef))
680 3194 : ABI_CALLOC(b_tot,(nconcoef))
681 3149 : ABI_CALLOC(x_tot,(nconcoef))
682 : call DGEMM('T','N',ntotcoeff,ntotcoeff,natnstep,2.d0,&
683 : & Solver%fcoeff(:,ncoeff_prev+1:ncoeff_prev+ntotcoeff),natnstep,&
684 : & Solver%fcoeff(:,ncoeff_prev+1:ncoeff_prev+ntotcoeff),natnstep,&
685 45 : & 0.d0,ffcoeff_tmp,ntotcoeff)
686 : ! NOTE, we have to solve F_ij = -\sum_j \Phi_ij u_j, so we add a minus sign
687 : call DGEMV('T',natnstep,ntotcoeff,-2.d0,&
688 : & Solver%fcoeff(:,ncoeff_prev+1:ncoeff_prev+ntotcoeff),natnstep,&
689 45 : & Solver%Forces,1,0.d0,fforces_tmp,1)
690 45 : call xmpi_sum(ffcoeff_tmp,MPIdata%comm_step,ierr)
691 45 : call xmpi_sum(fforces_tmp,MPIdata%comm_step,ierr)
692 :
693 461173 : A_tot(1:ntotcoeff,1:ntotcoeff)=ffcoeff_tmp(1:ntotcoeff,1:ntotcoeff)
694 45 : ABI_FREE(ffcoeff_tmp)
695 45 : if (ntotconst.gt.0) then
696 : A_tot(ntotcoeff+1:nconcoef,1:ntotcoeff)=&
697 88222 : & Solver%const(nconst_prev+1:nconst_prev+ntotconst,ncoeff_prev+1:ncoeff_prev+ntotcoeff)
698 : A_tot(1:ntotcoeff,ntotcoeff+1:nconcoef)=&
699 86382 : & transpose(Solver%const(nconst_prev+1:nconst_prev+ntotconst,ncoeff_prev+1:ncoeff_prev+ntotcoeff))
700 : !FB ABI_FREE(Solver%const)
701 : end if
702 2690 : b_tot(1:ntotcoeff)=fforces_tmp(:)
703 45 : if ((ntotconst.gt.0).and.(simult.ge.2)) then
704 21 : b_tot(ntotcoeff+1:nconcoef)=-b_const(1:ntotconst)
705 1 : ABI_FREE(b_const)
706 : end if
707 45 : ABI_FREE(fforces_tmp)
708 :
709 15205 : ABI_MALLOC(WORK, (5 * nconcoef)); WORK(:) = 0.d0
710 3194 : ABI_MALLOC(IPIV, (nconcoef)); IPIV(:) = 0
711 653439 : A_inv(:,:) = A_tot(:,:)
712 : !BEGIN DEBUG
713 : !write(Invar%stdout,*) ' '
714 : !write(Invar%stdout,*) ' The matrix A_inv is (before DGETRF):'
715 : !do icoeff=1,nconcoef
716 : ! write(Invar%stdout,*) (A_inv(icoeff,iconst), iconst=1, nconcoef)
717 : !end do
718 : !END DEBUG
719 :
720 : ! Check for small pivot elements
721 3059 : do icoeff=1,nconcoef
722 3059 : if (abs(A_inv(icoeff, icoeff)) < tol12) then
723 369 : write(Invar%stdlog,*) ' WARNING: Small pivot value at index ', icoeff, ' : ', A_inv(icoeff, icoeff)
724 : ! A_inv(icoeff, icoeff) = tol14 ! Regularization to avoid numerical issues
725 50146203 : A_inv(icoeff, icoeff) = max(EPSILON(1.0_dp) * maxval(abs(A_inv)), tol12)
726 : end if
727 : end do
728 :
729 : ! Perform LU factorization
730 45 : call DGETRF(nconcoef, nconcoef, A_inv, nconcoef, IPIV, INFO)
731 45 : if (INFO.ne.0) then
732 0 : write(Invar%stdout,*) 'ERROR: Singular matrix detected in DGETRF. INFO=', INFO
733 0 : stop
734 : end if
735 :
736 : ! Check for small pivot elements
737 3059 : do icoeff=1,nconcoef
738 3059 : if (abs(A_inv(icoeff, icoeff)) < tol12) then
739 0 : write(Invar%stdlog,*) ' WARNING: Small pivot value at index ', icoeff, ' : ', A_inv(icoeff, icoeff)
740 : ! A_inv(icoeff, icoeff) = tol14 ! Regularization to avoid numerical issues
741 0 : A_inv(icoeff, icoeff) = max(EPSILON(1.0_dp) * maxval(abs(A_inv)), tol12)
742 : end if
743 : end do
744 :
745 : ! Compute matrix inverse using LU decomposition
746 45 : call DGETRI(nconcoef, A_inv, nconcoef, IPIV, WORK, 5 * nconcoef, INFO)
747 45 : if (INFO.ne.0) then
748 0 : write(Invar%stdout,*) 'ERROR: Matrix inversion failed in DGETRI. INFO=', INFO
749 0 : stop
750 : end if
751 : ! BEGIN DEBUG
752 : !write(Invar%stdout,*) ' '
753 : !write(Invar%stdout,*) ' The inverse matrix is (after DGETRI):'
754 : !do icoeff=1,nconcoef
755 : ! write(Invar%stdout,*) (A_inv(icoeff,iconst), iconst=1, nconcoef)
756 : !end do
757 : ! END DEBUG
758 :
759 45 : ABI_FREE(WORK)
760 45 : ABI_FREE(IPIV)
761 :
762 45 : call DGEMV('N',nconcoef,nconcoef,1.d0,A_inv,nconcoef,b_tot,1,0.d0,x_tot,1)
763 45 : write(Invar%stdout,*) ' The problem is solved'
764 45 : write(Invar%stdout,*) ' '
765 : !BEGIN DEBUG
766 : !write(Invar%stdout,*) ' The solutions are:'
767 : !do icoeff=1,nconcoef
768 : ! write(Invar%stdout,'(1x,i4,1x,f15.10)') icoeff,x_tot(icoeff)
769 : !end do
770 : !write(Invar%stdout,'(a,1x,f15.10)')' condition number=',maxval(x_tot(:))/minval(x_tot(:))
771 : !END DEBUG
772 :
773 2690 : Solver%theta(ncoeff_prev+1:ncoeff_prev+ntotcoeff)=x_tot(1:ntotcoeff)
774 45 : ABI_FREE(A_tot)
775 45 : ABI_FREE(A_inv)
776 45 : ABI_FREE(b_tot)
777 45 : ABI_FREE(x_tot)
778 :
779 90 : end subroutine tdep_calc_MoorePenrose
780 :
781 :
782 : !====================================================================================================
783 :
784 44 : subroutine tdep_calc_constraints(Solver,distance,Invar,MPIdata,Sym,&
785 : & Shell1at,Shell2at,Shell3at,Shell4at)
786 :
787 : type(tdep_Solver_type), intent(inout) :: Solver
788 : type(atdep_dataset_type),intent(in) :: Invar
789 : type(Symmetries_type),intent(in) :: Sym
790 : type(MPI_enreg_type), intent(in) :: MPIdata
791 : type(Shell_type),intent(in) :: Shell1at
792 : type(Shell_type),intent(in) :: Shell2at
793 : type(Shell_type),optional,intent(in) :: Shell3at
794 : type(Shell_type),optional,intent(in) :: Shell4at
795 : double precision, intent(in) :: distance(Invar%natom,Invar%natom,4)
796 :
797 : integer :: ishell,ncoeff,ncoeff_prev,iatom,jatom,katom,latom,iatshell,counter
798 : integer :: icoeff,iconst,nconst_loc,iconst_loc,iconst_new,isym,itrans,ntotcoeff,iat_mod
799 : integer :: mu,nu,xi,zeta,alpha,beta,gama,delta,lambda,natom_unitcell,natom,ii
800 : double precision :: terme,temp,terme1,terme2,terme3,terme4
801 44 : double precision, allocatable :: SS_ref(:,:,:,:,:)
802 44 : double precision, allocatable :: vect(:,:)
803 44 : double precision, allocatable :: const_rot1st(:,:,:)
804 44 : double precision, allocatable :: const_rot2nd(:,:,:,:,:)
805 44 : double precision, allocatable :: const_dynmat(:,:,:,:,:)
806 44 : double precision, allocatable :: const_huang(:,:,:,:,:)
807 : !FB double precision, allocatable :: const_asr4th(:,:,:,:,:,:)
808 : !FB double precision, allocatable :: const_rot4th(:,:,:,:,:,:,:)
809 44 : type(Constraints_type) :: Const3,Const4
810 : logical :: order2,order3,order4
811 :
812 : !TODO Move parts of this routine into m_tdep_constraints
813 :
814 44 : natom_unitcell=Invar%natom_unitcell
815 44 : natom =Invar%natom
816 :
817 44 : order2 = .false.
818 44 : order3 = .false.
819 44 : order4 = .false.
820 44 : if (Invar%order.ge.2) order2=.true.
821 44 : if (Invar%order.ge.3) order3=.true.
822 : !FB4th if (Invar%order.ge.4) order4=.true.
823 : if (Invar%order.ge.4) order4=.false.
824 :
825 44 : write(Invar%stdout,*) ' '
826 44 : write(Invar%stdout,*) '#############################################################################'
827 44 : write(Invar%stdout,*) '###################### Compute the constraints ##############################'
828 :
829 : ! For each couple of atoms, transform the Phi2 (3x3) ifc matrix using the symetry operation (S)
830 44 : if (order2.or.order3) then
831 363592 : ABI_CALLOC(SS_ref,(3,9,3,Sym%nsym,2))
832 1666 : do isym=1,Sym%nsym
833 6532 : do alpha=1,3
834 21086 : do mu=1,3
835 63258 : do beta=1,3
836 189774 : do nu=1,3
837 131382 : temp=Sym%S_ref(alpha,mu,isym,1)*Sym%S_ref(beta,nu,isym,1)
838 131382 : SS_ref(alpha,nu+(mu-1)*3,beta,isym,1)=temp
839 175176 : SS_ref(alpha,mu+(nu-1)*3,beta,isym,2)=temp
840 : end do
841 : end do
842 : end do
843 : end do
844 : end do
845 : end if
846 : ! For each couple of atoms, transform the Phi3 (3x3x3) ifc matrix using the symetry operation (S)
847 44 : if (order3.or.order4) then
848 3102 : ABI_MALLOC(Const3%Sprod,(Sym%nsym,6))
849 510 : do isym=1,Sym%nsym
850 3486 : do itrans=1,6
851 2931856 : ABI_CALLOC(Const3%Sprod(isym,itrans)%SSS,(3,27,3,3))
852 : end do
853 : end do
854 510 : do isym=1,Sym%nsym
855 1998 : do alpha=1,3
856 6448 : do mu=1,3
857 19344 : do beta=1,3
858 58032 : do nu=1,3
859 174096 : do gama=1,3
860 522288 : do xi=1,3
861 361584 : temp=Sym%S_ref(alpha,mu,isym,1)*Sym%S_ref(beta,nu,isym,1)*Sym%S_ref(gama,xi,isym,1)
862 361584 : Const3%Sprod(isym,1)%SSS(alpha,xi+(nu-1)*3+(mu-1)*9,beta ,gama) =temp !\Phi3_efg
863 361584 : Const3%Sprod(isym,2)%SSS(alpha,xi+(nu-1)*3+(mu-1)*9,gama ,beta) =temp !\Phi3_egf
864 361584 : Const3%Sprod(isym,3)%SSS(beta ,xi+(nu-1)*3+(mu-1)*9,alpha,gama) =temp !\Phi3_feg
865 361584 : Const3%Sprod(isym,4)%SSS(beta ,xi+(nu-1)*3+(mu-1)*9,gama ,alpha)=temp !\Phi3_fge
866 361584 : Const3%Sprod(isym,5)%SSS(gama ,xi+(nu-1)*3+(mu-1)*9,alpha,beta) =temp !\Phi3_gef
867 482112 : Const3%Sprod(isym,6)%SSS(gama ,xi+(nu-1)*3+(mu-1)*9,beta ,alpha)=temp !\Phi3_gfe
868 : end do
869 : end do
870 : end do
871 : end do
872 : end do
873 : end do
874 : end do
875 : end if
876 :
877 : ! For each couple of atoms, transform the Phi4 (3x3x3x3) ifc matrix using the symetry operation (S)
878 : if (order4) then
879 : ABI_MALLOC(Const4%Sprod,(Sym%nsym,24))
880 : do isym=1,Sym%nsym
881 : do itrans=1,24
882 : ABI_CALLOC(Const4%Sprod(isym,itrans)%SSSS,(3,81,3,3,3))
883 : end do
884 : end do
885 : do isym=1,Sym%nsym
886 : do alpha=1,3
887 : do mu=1,3
888 : do beta=1,3
889 : do nu=1,3
890 : do gama=1,3
891 : do xi=1,3
892 : do delta=1,3
893 : do zeta=1,3
894 : counter=zeta+(xi-1)*3+(nu-1)*9+(mu-1)*27
895 : temp=Sym%S_ref(alpha,mu,isym,1)*Sym%S_ref(beta ,nu ,isym,1)*&
896 : & Sym%S_ref(gama,xi ,isym,1)*Sym%S_ref(delta,zeta,isym,1)
897 : Const4%Sprod(isym,1 )%SSSS(alpha,counter,beta,gama,delta)=temp !\Phi4_efgh
898 : Const4%Sprod(isym,2 )%SSSS(alpha,counter,gama,beta,delta)=temp !\Phi4_egfh
899 : Const4%Sprod(isym,3 )%SSSS(beta,counter,alpha,gama,delta)=temp !\Phi4_fegh
900 : Const4%Sprod(isym,4 )%SSSS(beta,counter,gama,alpha,delta)=temp !\Phi4_fgeh
901 : Const4%Sprod(isym,5 )%SSSS(gama,counter,alpha,beta,delta)=temp !\Phi4_gefh
902 : Const4%Sprod(isym,6 )%SSSS(gama,counter,beta,alpha,delta)=temp !\Phi4_gfeh
903 :
904 : Const4%Sprod(isym,7 )%SSSS(alpha,counter,beta,delta,gama)=temp !\Phi4_efhg
905 : Const4%Sprod(isym,8 )%SSSS(alpha,counter,gama,delta,beta)=temp !\Phi4_eghf
906 : Const4%Sprod(isym,9 )%SSSS(beta,counter,alpha,delta,gama)=temp !\Phi4_fehg
907 : Const4%Sprod(isym,10)%SSSS(beta,counter,gama,delta,alpha)=temp !\Phi4_fghe
908 : Const4%Sprod(isym,11)%SSSS(gama,counter,alpha,delta,beta)=temp !\Phi4_gehf
909 : Const4%Sprod(isym,12)%SSSS(gama,counter,beta,delta,alpha)=temp !\Phi4_gfhe
910 :
911 : Const4%Sprod(isym,13)%SSSS(alpha,counter,delta,beta,gama)=temp !\Phi4_ehfg
912 : Const4%Sprod(isym,14)%SSSS(alpha,counter,delta,gama,beta)=temp !\Phi4_ehgf
913 : Const4%Sprod(isym,15)%SSSS(beta,counter,delta,alpha,gama)=temp !\Phi4_fheg
914 : Const4%Sprod(isym,16)%SSSS(beta,counter,delta,gama,alpha)=temp !\Phi4_fhge
915 : Const4%Sprod(isym,17)%SSSS(gama,counter,delta,alpha,beta)=temp !\Phi4_ghef
916 : Const4%Sprod(isym,18)%SSSS(gama,counter,delta,beta,alpha)=temp !\Phi4_ghfe
917 :
918 : Const4%Sprod(isym,19)%SSSS(delta,counter,alpha,beta,gama)=temp !\Phi4_hefg
919 : Const4%Sprod(isym,20)%SSSS(delta,counter,alpha,gama,beta)=temp !\Phi4_hegf
920 : Const4%Sprod(isym,21)%SSSS(delta,counter,beta,alpha,gama)=temp !\Phi4_hfeg
921 : Const4%Sprod(isym,22)%SSSS(delta,counter,beta,gama,alpha)=temp !\Phi4_hfge
922 : Const4%Sprod(isym,23)%SSSS(delta,counter,gama,alpha,beta)=temp !\Phi4_hgef
923 : Const4%Sprod(isym,24)%SSSS(delta,counter,gama,beta,alpha)=temp !\Phi4_hgfe
924 :
925 : end do
926 : end do
927 : end do
928 : end do
929 : end do
930 : end do
931 : end do
932 : end do
933 : end do
934 : end if
935 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
936 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Compute the constraints !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
937 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
938 44 : ntotcoeff=Solver%ntotcoeff
939 : ! First order only
940 44 : write(Invar%stdout,*) '########################## At the 1st order #################################'
941 44 : if (order2) then
942 35765 : ABI_CALLOC(const_rot1st, (3,3,ntotcoeff))
943 541517 : ABI_CALLOC(const_rot2nd, (3,3,3,natom_unitcell,ntotcoeff))
944 1855835 : ABI_CALLOC(const_dynmat, (3,3,natom_unitcell,natom_unitcell,ntotcoeff))
945 331793 : ABI_CALLOC(const_huang, (3,3,3,3,ntotcoeff))
946 107 : do ishell=1,Shell1at%nshell
947 63 : if (Shell1at%neighbours(1,ishell)%n_interactions.eq.0) cycle
948 44 : do iatshell=1,Shell1at%neighbours(1,ishell)%n_interactions
949 0 : iatom=Shell1at%neighbours(1,ishell)%atomj_in_shell(iatshell)
950 0 : if (iatom.ge.natom_unitcell) cycle
951 0 : if (iatom.eq.1) cycle
952 0 : isym=Shell1at%neighbours(1,ishell)%sym_in_shell(iatshell)
953 0 : ncoeff =Shell1at%ncoeff(ishell)
954 0 : ncoeff_prev=Shell1at%ncoeff_prev(ishell)
955 63 : do alpha=1,3
956 0 : do beta=1,3
957 0 : do icoeff=1,ncoeff
958 : ! 1/ Rotational invariances (1st order)
959 0 : terme1=sum(Sym%S_ref(alpha,:,isym,1)*Shell1at%proj(:,icoeff,ishell))*distance(1,iatom,beta +1)
960 0 : terme2=sum(Sym%S_ref(beta ,:,isym,1)*Shell1at%proj(:,icoeff,ishell))*distance(1,iatom,alpha+1)
961 : const_rot1st(alpha,beta,icoeff+ncoeff_prev)= &
962 0 : & const_rot1st(alpha,beta,icoeff+ncoeff_prev)+terme1-terme2
963 :
964 : ! 2/ Rotational invariances (for the 2nd order)
965 0 : do gama=1,3
966 0 : terme1=zero ; terme2=zero
967 0 : if (alpha.eq.gama) terme1=sum(Sym%S_ref(beta,:,isym,1)*Shell1at%proj(:,icoeff,ishell))
968 0 : if (alpha.eq.beta) terme2=sum(Sym%S_ref(gama,:,isym,1)*Shell1at%proj(:,icoeff,ishell))
969 : const_rot2nd(alpha,beta,gama,iatom,icoeff+ncoeff_prev)=&
970 0 : & const_rot2nd(alpha,beta,gama,iatom,icoeff+ncoeff_prev)+terme1-terme2
971 : const_rot2nd(alpha,beta,gama,1,icoeff+ncoeff_prev)=&
972 0 : & const_rot2nd(alpha,beta,gama,1,icoeff+ncoeff_prev)-terme1+terme2
973 : end do
974 : end do
975 : end do
976 : end do
977 : end do !iatshell
978 : end do !ishell
979 :
980 : ! First + second order
981 44 : write(Invar%stdout,*) '########################## At the 2nd order #################################'
982 544 : do ishell=1,Shell2at%nshell
983 2830 : do iatom=1,natom_unitcell
984 2286 : if (Shell2at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
985 6867 : do iatshell=1,Shell2at%neighbours(iatom,ishell)%n_interactions
986 5268 : jatom=Shell2at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
987 5268 : if (iatom==jatom) cycle
988 5162 : isym=Shell2at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
989 5162 : itrans=Shell2at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
990 5162 : ncoeff =Shell2at%ncoeff(ishell)
991 5162 : ncoeff_prev=Shell2at%ncoeff_prev(ishell)+Solver%ncoeff1st
992 5162 : iat_mod=mod(jatom+natom_unitcell-1,natom_unitcell)+1
993 : ! 1/ Rotational invariances (2nd order). Number of constraints = natom_unitcell*3**2
994 20648 : do alpha=1,3
995 67106 : do beta=1,3
996 201318 : do gama=1,3
997 834156 : do icoeff=1,ncoeff
998 6483240 : terme1=sum(SS_ref(alpha,:,beta,isym,itrans)*Shell2at%proj(:,icoeff,ishell))*distance(iatom,jatom,gama+1)
999 6483240 : terme2=sum(SS_ref(alpha,:,gama,isym,itrans)*Shell2at%proj(:,icoeff,ishell))*distance(iatom,jatom,beta+1)
1000 : const_rot2nd(alpha,beta,gama,iatom,icoeff+ncoeff_prev)=&
1001 787698 : & const_rot2nd(alpha,beta,gama,iatom,icoeff+ncoeff_prev)+terme1-terme2
1002 : end do
1003 : end do
1004 : end do
1005 : end do
1006 : ! 2/ Enforce the symetry of the dynamical matrix. Number of constraints = (3*natom_unitcell)**2
1007 : ! Note that we are unable to enforce the symetry when iatom=jatom (We have to write the equations)
1008 20648 : do alpha=1,3
1009 67106 : do beta=1,3
1010 278052 : do icoeff=1,ncoeff
1011 : terme=sum(SS_ref(alpha,:,beta,isym,itrans)*Shell2at%proj(:,icoeff,ishell))-&
1012 4106052 : & sum(SS_ref(beta,:,alpha,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1013 : const_dynmat(alpha,beta,iatom,iat_mod,icoeff+ncoeff_prev)=&
1014 262566 : & const_dynmat(alpha,beta,iatom,iat_mod,icoeff+ncoeff_prev)+terme
1015 : end do
1016 : end do
1017 : end do
1018 : ! 3/ Huang invariances. Number of constraints = 3**4
1019 22934 : do alpha=1,3
1020 67212 : do beta=1,3
1021 201318 : do gama=1,3
1022 603954 : do lambda=1,3
1023 2502468 : do icoeff=1,ncoeff
1024 : terme=sum(SS_ref(alpha,:,beta,isym,itrans)*Shell2at%proj(:,icoeff,ishell))*&
1025 : & distance(iatom,jatom,gama+1)*&
1026 : & distance(iatom,jatom,lambda+1)-&
1027 : & sum(SS_ref(gama,:,lambda,isym,itrans)*Shell2at%proj(:,icoeff,ishell))*&
1028 : & distance(iatom,jatom,alpha+1)*&
1029 36954468 : & distance(iatom,jatom,beta+1)
1030 : const_huang(alpha,beta,gama,lambda,icoeff+ncoeff_prev)=&
1031 2363094 : & const_huang(alpha,beta,gama,lambda,icoeff+ncoeff_prev)+terme
1032 : end do
1033 : end do
1034 : end do
1035 : end do
1036 : end do
1037 : end do !iatshell
1038 : end do !iatom
1039 : end do !ishell
1040 : end if !order=1,2
1041 :
1042 : ! Third order
1043 44 : if (order3) then
1044 14 : write(Invar%stdout,*) '########################## At the 3rd order #################################'
1045 659640 : ABI_MALLOC(Const3%AsrRot3,(natom_unitcell,natom,ntotcoeff))
1046 42 : do iatom=1,natom_unitcell
1047 4930 : do jatom=1,natom
1048 457300 : do icoeff=1,ntotcoeff
1049 18095360 : ABI_MALLOC(Const3%AsrRot3(iatom,jatom,icoeff)%ABG, (3,3,3)); Const3%AsrRot3(iatom,jatom,icoeff)%ABG(:,:,:) =zero
1050 54743352 : ABI_MALLOC(Const3%AsrRot3(iatom,jatom,icoeff)%ABGD,(3,3,3,3)); Const3%AsrRot3(iatom,jatom,icoeff)%ABGD(:,:,:,:)=zero
1051 : end do
1052 : end do
1053 : end do
1054 165 : do ishell=1,Shell2at%nshell
1055 476 : do iatom=1,natom_unitcell
1056 311 : if (Shell2at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
1057 2266 : do iatshell=1,Shell2at%neighbours(iatom,ishell)%n_interactions
1058 1856 : jatom=Shell2at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
1059 1856 : if (iatom==jatom) cycle
1060 1828 : isym=Shell2at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
1061 1828 : itrans=Shell2at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
1062 1828 : ncoeff =Shell2at%ncoeff(ishell)
1063 1828 : ncoeff_prev=Shell2at%ncoeff_prev(ishell)+Solver%ncoeff1st
1064 1828 : iat_mod=mod(jatom+natom_unitcell-1,natom_unitcell)+1
1065 : ! 1/ Rotational invariances (coming from the 2nd order). Number of constraints = natom_unitcell*natom*3**3
1066 2139 : if (Invar%order.ge.3) then
1067 7312 : do alpha=1,3
1068 23764 : do beta=1,3
1069 71292 : do gama=1,3
1070 213876 : do lambda=1,3
1071 824364 : do icoeff=1,ncoeff
1072 626940 : terme1=zero ; terme2=zero ; terme3=zero ; terme4=zero ;
1073 2507760 : if (alpha.eq.lambda) terme1=sum(SS_ref(gama ,:,beta ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1074 2507760 : if (beta.eq.lambda) terme2=sum(SS_ref(alpha ,:,gama ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1075 2507760 : if (alpha.eq.gama) terme3=sum(SS_ref(lambda,:,beta ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1076 2507760 : if (beta.eq.gama) terme4=sum(SS_ref(alpha ,:,lambda,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1077 626940 : if (distance(iatom,jatom,1).lt.Invar%rcut3) then
1078 : Const3%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1079 34668 : & Const3%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)+terme1+terme2-terme3-terme4
1080 : end if
1081 : Const3%AsrRot3(iatom,iatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1082 775008 : & Const3%AsrRot3(iatom,iatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)-terme1-terme2+terme3+terme4
1083 : end do
1084 : end do
1085 : end do
1086 : end do
1087 : end do
1088 : end if !proj3rd
1089 : end do !iatshell
1090 : end do !iatom
1091 : end do !ishell
1092 63 : do ishell=1,Shell3at%nshell
1093 176 : do iatom=1,natom_unitcell
1094 113 : if (Shell3at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
1095 1286 : do iatshell=1,Shell3at%neighbours(iatom,ishell)%n_interactions
1096 1144 : jatom=Shell3at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
1097 1144 : katom=Shell3at%neighbours(iatom,ishell)%atomk_in_shell(iatshell)
1098 1144 : isym =Shell3at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
1099 1144 : itrans=Shell3at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
1100 1144 : ncoeff =Shell3at%ncoeff(ishell)
1101 1144 : ncoeff_prev=Shell3at%ncoeff_prev(ishell)+Solver%ncoeff2nd+Solver%ncoeff1st
1102 : ! 2/ Acoustic sum rules (3rd order). Number of constraints = natom_unitcell*natom*3**3
1103 4576 : do alpha=1,3
1104 14872 : do beta=1,3
1105 44616 : do gama=1,3
1106 236826 : do icoeff=1,ncoeff
1107 5477976 : terme =sum(Const3%Sprod(isym,itrans)%SSS(alpha,:,beta,gama)*Shell3at%proj(:,icoeff,ishell))
1108 : Const3%AsrRot3(iatom,katom,icoeff+ncoeff_prev)%ABG(alpha,beta,gama)=&
1109 226530 : & Const3%AsrRot3(iatom,katom,icoeff+ncoeff_prev)%ABG(alpha,beta,gama)+terme
1110 : end do
1111 : end do
1112 : end do
1113 : end do
1114 : ! 2/ Rotational invariances (coming from the 3rd order). Number of constraints = natom_unitcell*natom*3**4
1115 4689 : do alpha=1,3
1116 14872 : do beta=1,3
1117 44616 : do gama=1,3
1118 133848 : do lambda=1,3
1119 710478 : do icoeff=1,ncoeff
1120 : terme1=sum(Const3%Sprod(isym,itrans)%SSS(alpha,:,beta,gama )&
1121 16433928 : & *Shell3at%proj(:,icoeff,ishell))*distance(iatom,katom,lambda+1)
1122 : terme2=sum(Const3%Sprod(isym,itrans)%SSS(alpha,:,beta,lambda)&
1123 16433928 : & *Shell3at%proj(:,icoeff,ishell))*distance(iatom,katom,gama+1)
1124 : Const3%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1125 679590 : & Const3%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)+terme1-terme2
1126 : end do
1127 : end do
1128 : end do
1129 : end do
1130 : end do
1131 : end do !iatshell
1132 : end do !iatom
1133 : end do !ishell
1134 : end if !order=3
1135 :
1136 : ! Fourth order
1137 : if (order4) then
1138 : write(Invar%stdout,*) '########################## At the 4th order #################################'
1139 : ABI_MALLOC(Const4%AsrRot4,(natom_unitcell,natom,natom,ntotcoeff))
1140 : do iatom=1,natom_unitcell
1141 : do jatom=1,natom
1142 : do katom=1,natom
1143 : do icoeff=1,ntotcoeff
1144 : ABI_MALLOC(Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGD, (3,3,3,3))
1145 : Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGD(:,:,:,:) =zero
1146 : !FB ABI_MALLOC(Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGDE,(3,3,3,3,3))
1147 : !FB Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGDE(:,:,:,:,:)=zero
1148 : end do
1149 : end do
1150 : end do
1151 : end do
1152 : !FB do ishell=1,Shell2at%nshell
1153 : !FB do iatom=1,natom_unitcell
1154 : !FB if (Shell2at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
1155 : !FB do iatshell=1,Shell2at%neighbours(iatom,ishell)%n_interactions
1156 : !FB jatom=Shell2at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
1157 : !FB if (iatom==jatom) cycle
1158 : !FB isym=Shell2at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
1159 : !FB itrans=Shell2at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
1160 : !FB ncoeff =Shell2at%ncoeff(ishell)
1161 : !FB ncoeff_prev=Shell2at%ncoeff_prev(ishell)+Solver%ncoeff1st
1162 : !FB iat_mod=mod(jatom+natom_unitcell-1,natom_unitcell)+1
1163 : !FB! 1/ Rotational invariances (coming from the 2nd order). Number of constraints = natom_unitcell*natom*3**3
1164 : !FB if (Invar%order.ge.3) then
1165 : !FB do alpha=1,3
1166 : !FB do beta=1,3
1167 : !FB do gama=1,3
1168 : !FB do lambda=1,3
1169 : !FB do icoeff=1,ncoeff
1170 : !FB terme1=zero ; terme2=zero ; terme3=zero ; terme4=zero ;
1171 : !FB if (alpha.eq.lambda) terme1=sum(SS_ref(gama ,:,beta ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1172 : !FB if (beta.eq.lambda) terme2=sum(SS_ref(alpha ,:,gama ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1173 : !FB if (alpha.eq.gama) terme3=sum(SS_ref(lambda,:,beta ,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1174 : !FB if (beta.eq.gama) terme4=sum(SS_ref(alpha ,:,lambda,isym,itrans)*Shell2at%proj(:,icoeff,ishell))
1175 : !FB if (distance(iatom,jatom,1).lt.Invar%rcut3) then
1176 : !FB Const4%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1177 : !FB& Const4%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)+terme1+terme2-terme3-terme4
1178 : !FB end if
1179 : !FB Const4%AsrRot3(iatom,iatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1180 : !FB& Const4%AsrRot3(iatom,iatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)-terme1-terme2+terme3+terme4
1181 : !FB end do
1182 : !FB end do
1183 : !FB end do
1184 : !FB end do
1185 : !FB end do
1186 : !FB end if !proj3rd
1187 : !FB end do !iatshell
1188 : !FB end do !iatom
1189 : !FB end do !ishell
1190 : do ishell=1,Shell4at%nshell
1191 : do iatom=1,natom_unitcell
1192 : if (Shell4at%neighbours(iatom,ishell)%n_interactions.eq.0) cycle
1193 : do iatshell=1,Shell4at%neighbours(iatom,ishell)%n_interactions
1194 : jatom=Shell4at%neighbours(iatom,ishell)%atomj_in_shell(iatshell)
1195 : katom=Shell4at%neighbours(iatom,ishell)%atomk_in_shell(iatshell)
1196 : latom=Shell4at%neighbours(iatom,ishell)%atoml_in_shell(iatshell)
1197 : isym =Shell4at%neighbours(iatom,ishell)%sym_in_shell(iatshell)
1198 : itrans=Shell4at%neighbours(iatom,ishell)%transpose_in_shell(iatshell)
1199 : ncoeff =Shell4at%ncoeff(ishell)
1200 : ncoeff_prev=Shell4at%ncoeff_prev(ishell)+Solver%ncoeff3rd+Solver%ncoeff2nd+Solver%ncoeff1st
1201 : ! 2/ Acoustic sum rules (4th order). Number of constraints = natom_unitcell*natom**2*3**4
1202 : do alpha=1,3
1203 : do beta=1,3
1204 : do gama=1,3
1205 : do delta=1,3
1206 : do icoeff=1,ncoeff
1207 : terme =sum(Const4%Sprod(isym,itrans)%SSSS(alpha,:,beta,gama,delta)*Shell4at%proj(:,icoeff,ishell))
1208 : Const4%AsrRot4(iatom,katom,latom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,delta)=&
1209 : & Const4%AsrRot4(iatom,katom,latom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,delta)+terme
1210 : end do
1211 : end do
1212 : end do
1213 : end do
1214 : end do
1215 : !FB! 2/ Rotational invariances (coming from the 3rd order). Number of constraints = natom_unitcell*natom*3**4
1216 : !FB do alpha=1,3
1217 : !FB do beta=1,3
1218 : !FB do gama=1,3
1219 : !FB do lambda=1,3
1220 : !FB do icoeff=1,ncoeff
1221 : !FB terme1=sum(Const4%Sprod(isym,itrans)%SSS(alpha,:,beta,gama )&
1222 : !FB &*Shell3at%proj(:,icoeff,ishell))*distance(iatom,katom,lambda+1)
1223 : !FB terme2=sum(Const4%Sprod(isym,itrans)%SSS(alpha,:,beta,lambda)&
1224 : !FB &*Shell3at%proj(:,icoeff,ishell))*distance(iatom,katom,gama+1)
1225 : !FB Const4%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)=&
1226 : !FB& Const4%AsrRot3(iatom,jatom,icoeff+ncoeff_prev)%ABGD(alpha,beta,gama,lambda)+terme1-terme2
1227 : !FB end do
1228 : !FB end do
1229 : !FB end do
1230 : !FB end do
1231 : !FB end do
1232 : end do !iatshell
1233 : end do !iatom
1234 : end do !ishell
1235 : end if !order=4
1236 :
1237 44 : if (order2.or.order3) then
1238 44 : ABI_FREE(SS_ref)
1239 : end if
1240 44 : if (order3.or.order4) then
1241 510 : do isym=1,Sym%nsym
1242 3486 : do itrans=1,6
1243 3472 : ABI_FREE(Const3%Sprod(isym,itrans)%SSS)
1244 : end do
1245 : end do
1246 2990 : ABI_FREE(Const3%Sprod)
1247 : end if
1248 : if (order4) then
1249 : do isym=1,Sym%nsym
1250 : do itrans=1,24
1251 : ABI_FREE(Const4%Sprod(isym,itrans)%SSSS)
1252 : end do
1253 : end do
1254 : ABI_FREE(Const4%Sprod)
1255 : end if
1256 :
1257 : ! Reduce the number of constraints by selecting the non-zero equations
1258 44 : write(Invar%stdout,*) '################## Reduce the number of constraints #########################'
1259 44 : iconst_new=0
1260 44 : if (order2) then
1261 : ! 1/ For Rotational invariances (1st order)
1262 44 : iconst=0
1263 25241 : ABI_MALLOC(vect,(ntotcoeff,Solver%nconst_1st)) ; vect(:,:)=zero
1264 176 : do alpha=1,3
1265 572 : do beta=1,3
1266 396 : iconst=iconst+1
1267 25197 : vect(:,iconst)=const_rot1st(alpha,beta,:)
1268 : end do
1269 : end do
1270 44 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_1st,nconst_loc,vect)
1271 44 : if (nconst_loc.ne.0) then
1272 0 : do iconst_loc=1,nconst_loc
1273 0 : iconst_new=iconst_new+1
1274 0 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1275 : end do
1276 : end if
1277 44 : ABI_FREE(vect)
1278 44 : ABI_FREE(const_rot1st)
1279 44 : Solver%nconst_1st=nconst_loc
1280 :
1281 : ! 2/ For Rotational invariances (2nd order)
1282 44 : iconst=0
1283 366593 : ABI_MALLOC(vect,(ntotcoeff,Solver%nconst_rot2nd)) ; vect(:,:)=zero
1284 150 : do iatom=1,natom_unitcell
1285 468 : do alpha=1,3
1286 1378 : do beta=1,3
1287 4134 : do gama=1,3
1288 2862 : iconst=iconst+1
1289 367371 : vect(:,iconst)=const_rot2nd(alpha,beta,gama,iatom,:)
1290 : end do
1291 : end do
1292 : end do
1293 : end do
1294 44 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_rot2nd,nconst_loc,vect)
1295 44 : if (nconst_loc.ne.0) then
1296 113 : do iconst_loc=1,nconst_loc
1297 100 : iconst_new=iconst_new+1
1298 33151 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1299 : end do
1300 : end if
1301 44 : ABI_FREE(vect)
1302 44 : ABI_FREE(const_rot2nd)
1303 44 : Solver%nconst_rot2nd=nconst_loc
1304 :
1305 : ! 3/ For symetry of the dynamical matrix
1306 44 : iconst=0
1307 1278239 : ABI_MALLOC(vect,(ntotcoeff,Solver%nconst_dynmat)) ; vect(:,:)=zero
1308 150 : do iatom=1,natom_unitcell
1309 664 : do jatom=1,natom_unitcell
1310 2162 : do alpha=1,3
1311 6682 : do beta=1,3
1312 4626 : iconst=iconst+1
1313 1279605 : vect(:,iconst)=const_dynmat(alpha,beta,iatom,jatom,:)
1314 : end do
1315 : end do
1316 : end do
1317 : end do
1318 44 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_dynmat,nconst_loc,vect)
1319 44 : if (nconst_loc.ne.0) then
1320 69 : do iconst_loc=1,nconst_loc
1321 65 : iconst_new=iconst_new+1
1322 26885 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1323 : end do
1324 : end if
1325 44 : ABI_FREE(vect)
1326 44 : ABI_FREE(const_dynmat)
1327 44 : Solver%nconst_dynmat=nconst_loc
1328 :
1329 : ! 4/ For Huang invariances
1330 44 : iconst=0
1331 225761 : ABI_MALLOC(vect,(ntotcoeff,Solver%nconst_huang)) ; vect(:,:)=zero
1332 176 : do alpha=1,3
1333 572 : do beta=1,3
1334 1716 : do gama=1,3
1335 5148 : do lambda=1,3
1336 3564 : iconst=iconst+1
1337 226773 : vect(:,iconst)=const_huang(alpha,beta,gama,lambda,:)
1338 : end do
1339 : end do
1340 : end do
1341 : end do
1342 44 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_huang,nconst_loc,vect)
1343 44 : if (nconst_loc.ne.0) then
1344 70 : do iconst_loc=1,nconst_loc
1345 51 : iconst_new=iconst_new+1
1346 6515 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1347 : end do
1348 : end if
1349 44 : ABI_FREE(vect)
1350 44 : ABI_FREE(const_huang)
1351 44 : Solver%nconst_huang=nconst_loc
1352 220 : Solver%nconst_2nd=Solver%nconst_rot2nd+Solver%nconst_dynmat+Solver%nconst_huang
1353 : end if
1354 :
1355 44 : if (order3) then
1356 : ! 1/ For acoustic sum rules (3rd order)
1357 14 : iconst=0
1358 12346400 : ABI_MALLOC(vect ,(ntotcoeff,Solver%nconst_asr3rd)) ; vect (:,:)=zero
1359 42 : do iatom=1,natom_unitcell
1360 4930 : do jatom=1,natom
1361 19580 : do alpha=1,3
1362 63544 : do beta=1,3
1363 190632 : do gama=1,3
1364 131976 : iconst=iconst+1
1365 12390336 : do ii=1,ntotcoeff
1366 12346344 : vect(ii,iconst)=Const3%AsrRot3(iatom,jatom,ii)%ABG(alpha,beta,gama)
1367 : end do
1368 : end do
1369 : end do
1370 : end do
1371 : end do
1372 : end do
1373 14 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_asr3rd,nconst_loc,vect)
1374 14 : if (nconst_loc.ne.0) then
1375 75 : do iconst_loc=1,nconst_loc
1376 64 : iconst_new=iconst_new+1
1377 8571 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1378 : end do
1379 : end if
1380 14 : ABI_FREE(vect)
1381 14 : Solver%nconst_asr3rd=nconst_loc
1382 :
1383 : ! 2/ For Rotational invariances (3rd order)
1384 14 : iconst=0
1385 37039088 : ABI_MALLOC(vect ,(ntotcoeff,Solver%nconst_rot3rd)) ; vect(:,:)=zero
1386 42 : do iatom=1,natom_unitcell
1387 4930 : do jatom=1,natom
1388 19580 : do alpha=1,3
1389 63544 : do beta=1,3
1390 190632 : do gama=1,3
1391 571896 : do lambda=1,3
1392 395928 : iconst=iconst+1
1393 37171008 : do ii=1,ntotcoeff
1394 37039032 : vect(ii,iconst)=Const3%AsrRot3(iatom,jatom,ii)%ABGD(alpha,beta,gama,lambda)
1395 : end do
1396 : end do
1397 : end do
1398 : end do
1399 : end do
1400 : end do
1401 : end do
1402 14 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_rot3rd,nconst_loc,vect)
1403 14 : if (nconst_loc.ne.0) then
1404 101 : do iconst_loc=1,nconst_loc
1405 90 : iconst_new=iconst_new+1
1406 13631 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1407 : end do
1408 : end if
1409 14 : ABI_FREE(vect)
1410 42 : do iatom=1,natom_unitcell
1411 4930 : do jatom=1,natom
1412 457300 : do icoeff=1,ntotcoeff
1413 452384 : ABI_FREE(Const3%AsrRot3(iatom,jatom,icoeff)%ABG)
1414 457272 : ABI_FREE(Const3%AsrRot3(iatom,jatom,icoeff)%ABGD)
1415 : end do
1416 : end do
1417 : end do
1418 452398 : ABI_FREE(Const3%AsrRot3)
1419 14 : Solver%nconst_rot3rd=nconst_loc
1420 42 : Solver%nconst_3rd=Solver%nconst_asr3rd+Solver%nconst_rot3rd
1421 : end if
1422 :
1423 : if (order4) then
1424 : ! 1/ For acoustic sum rules (4th order)
1425 : iconst=0
1426 : ABI_MALLOC(vect ,(ntotcoeff,Solver%nconst_asr4th)) ; vect (:,:)=zero
1427 : do iatom=1,natom_unitcell
1428 : do jatom=1,natom
1429 : do katom=1,natom
1430 : do alpha=1,3
1431 : do beta=1,3
1432 : do gama=1,3
1433 : do delta=1,3
1434 : iconst=iconst+1
1435 : do ii=1,ntotcoeff
1436 : vect(ii,iconst)=Const4%AsrRot4(iatom,jatom,katom,ii)%ABGD(alpha,beta,gama,delta)
1437 : end do
1438 : end do
1439 : end do
1440 : end do
1441 : end do
1442 : end do
1443 : end do
1444 : end do
1445 : call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_asr4th,nconst_loc,vect)
1446 : if (nconst_loc.ne.0) then
1447 : do iconst_loc=1,nconst_loc
1448 : iconst_new=iconst_new+1
1449 : Solver%const(iconst_new,:)=vect(:,iconst_loc)
1450 : end do
1451 : end if
1452 : ABI_FREE(vect)
1453 : Solver%nconst_asr4th=nconst_loc
1454 :
1455 : !FB! 2/ For Rotational invariances (3rd order)
1456 : !FB iconst=0
1457 : !FB ABI_MALLOC(vect ,(ntotcoeff,Solver%nconst_rot3rd)) ; vect(:,:)=zero
1458 : !FB do iatom=1,natom_unitcell
1459 : !FB do jatom=1,natom
1460 : !FB do alpha=1,3
1461 : !FB do beta=1,3
1462 : !FB do gama=1,3
1463 : !FB do lambda=1,3
1464 : !FB iconst=iconst+1
1465 : !FB vect(:,iconst)=Const4%AsrRot3(iatom,jatom,:)%ABGD(alpha,beta,gama,lambda)
1466 : !FB end do
1467 : !FB end do
1468 : !FB end do
1469 : !FB end do
1470 : !FB end do
1471 : !FB end do
1472 : !FB call tdep_calc_orthonorm(ntotcoeff,Solver%nconst_rot3rd,nconst_loc,vect)
1473 : !FB if (nconst_loc.ne.0) then
1474 : !FB do iconst_loc=1,nconst_loc
1475 : !FB iconst_new=iconst_new+1
1476 : !FB Solver%const(iconst_new,:)=vect(:,iconst_loc)
1477 : !FB end do
1478 : !FB end if
1479 : !FB ABI_FREE(vect)
1480 : !FB Solver%nconst_rot3rd=nconst_loc
1481 : do iatom=1,natom_unitcell
1482 : do jatom=1,natom
1483 : do katom=1,natom
1484 : do icoeff=1,ntotcoeff
1485 : ABI_FREE(Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGD)
1486 : !FB ABI_FREE(Const4%AsrRot4(iatom,jatom,katom,icoeff)%ABGDE)
1487 : end do
1488 : end do
1489 : end do
1490 : end do
1491 : ABI_FREE(Const4%AsrRot4)
1492 : Solver%nconst_rot4th=0
1493 : Solver%nconst_4th=Solver%nconst_asr4th+Solver%nconst_rot4th
1494 : end if
1495 :
1496 : ! Finalize the orthonormalization
1497 : !FB nconst=iconst_new
1498 : !FB ABI_MALLOC(vect,(ntotcoeff,nconst)) ; vect(:,:)=zero
1499 : !FB do iconst=1,nconst
1500 : !FB vect(:,iconst)=Solver%const(iconst,:)
1501 : !FB end do
1502 : !FB ABI_FREE(Solver%const)
1503 : !FB call tdep_calc_orthonorm(ntotcoeff,nconst,nconst_loc,vect)
1504 : !FB Solver%ntotconst=nconst_loc
1505 : !FB if (nconst_loc.ne.0) then
1506 : !FB ABI_MALLOC(Solver%const ,(Solver%ntotconst,ntotcoeff)); Solver%const (:,:)=0.d0
1507 : !FB do iconst_loc=1,nconst_loc
1508 : !FB Solver%const(iconst_loc,:)=vect(:,iconst_loc)
1509 : !FB end do
1510 : !FB end if
1511 : !FB ABI_FREE(vect)
1512 44 : Solver%ntotconst=iconst_new
1513 44 : if (MPIdata%iam_master) then
1514 44 : open(unit=16,file=trim(Invar%output_prefix)//'_constraints.dat')
1515 44 : write(16,*) ' ======== Constraints at the 1st order (Rotational Invariances) ========'
1516 44 : write(16,*) ' Number of constraints =',Solver%nconst_1st
1517 44 : write(16,*) ' ======== Constraints at the 2nd order (Rotational Invariances) ========'
1518 44 : write(16,*) ' Number of constraints =',Solver%nconst_rot2nd
1519 44 : write(16,*) ' ======== Constraints at the 2nd order (Dynamical Matrix) =============='
1520 44 : write(16,*) ' Number of constraints =',Solver%nconst_dynmat
1521 44 : write(16,*) ' ======== Constraints at the 2nd order (Huang) ========================='
1522 44 : write(16,*) ' Number of constraints =',Solver%nconst_huang
1523 44 : if (Invar%order.ge.3) then
1524 14 : write(16,*) ' ======== Constraints at the 3rd order (Acoustic sum rules) ============'
1525 14 : write(16,*) ' Number of constraints =',Solver%nconst_asr3rd
1526 14 : write(16,*) ' ======== Constraints at the 3rd order (Rotational Invariances) ========'
1527 14 : write(16,*) ' Number of constraints =',Solver%nconst_rot3rd
1528 : end if
1529 44 : if (Invar%order.ge.4) then
1530 8 : write(16,*) ' ======== Constraints at the 4th order (Acoustic sum rules) ============'
1531 8 : write(16,*) ' Number of constraints =',Solver%nconst_asr4th
1532 8 : write(16,*) ' ======== Constraints at the 4th order (Rotational Invariances) ========'
1533 8 : write(16,*) ' Number of constraints =',Solver%nconst_rot4th
1534 : end if
1535 44 : write(16,*) ' ======================================================================='
1536 44 : write(16,*) ' Total number of constraints =',Solver%ntotconst
1537 44 : close(16)
1538 : end if
1539 :
1540 44 : end subroutine tdep_calc_constraints
1541 :
1542 : !====================================================================================================
1543 :
1544 0 : end module m_tdep_solver
1545 : !!***
|