TABLE OF CONTENTS


ABINIT/m_opt_effpot [ Modules ]

[ Top ] [ Modules ]

NAME

 m_opt_effpot

FUNCTION

COPYRIGHT

 Copyright (C) 2010-2024 ABINIT group (AM)
 This file is distributed under the terms of the
 GNU General Public Licence, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .
 For the initials of contributors, see ~abinit/doc/developers/contributors.txt .

SOURCE

21 #if defined HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "abi_common.h"
26 
27 module m_opt_effpot
28 
29 use defs_basis
30 use defs_datatypes
31 use defs_abitypes
32 use m_errors
33 use m_abicore
34 use m_xmpi
35 use m_effective_potential
36 use m_effective_potential_file, only : effective_potential_file_mapHistToRef
37 use m_fit_data
38 use m_fit_polynomial_coeff
39 use m_polynomial_coeff
40 use m_polynomial_term
41 use m_crystal,only : symbols_crystal
42 
43 implicit none
44 
45 public :: opt_effpot
46 public :: opt_effpotbound
47 public :: opt_getHOforterm
48 public :: opt_getCombisforterm
49 public :: opt_getHoTerms
50 public :: opt_getHOstrain
51 public :: opt_getHOcrossdisp
52 public :: opt_filterdisp
53 public :: opt_getSingleDispTerms
54 public :: opt_getHOSingleDispTerms
55 private :: opt_boundcoeff
56 private :: check_to_skip

m_opt_effpot/check_to_skip [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 check_to_skip

FUNCTION

 Check if term contains only bodies with even power
 and has a positive coefficient. If yes term doesn't need
 a bounding high order equivalent and we can skip it.
 Function retursn logical to_skip.

INPUTS

 term<polynomial_coeff_type>:anharmonic term

OUTPUT

 logical: to_skip

SOURCE

2001 function check_to_skip(term) result (to_skip)
2002   !Arguments ------------------------------------
2003   implicit none
2004   type(polynomial_coeff_type),intent(in) :: term
2005   logical :: to_skip
2006   ! ------------------------------------
2007   !local
2008   !variable
2009   character(len=1000) :: message
2010   !array
2011   ! *************************************************************************
2012 
2013   to_skip = .FALSE.
2014   ! Let's check if we really want all this mess
2015   ! If the term is even and its coefficient positive we skip it. Also here we take terms(1) as example for all equivalent terms of term
2016   if(term%coefficient > 0 .and. .not. any(mod(term%terms(1)%power_disp(:),2) /= 0))then
2017     if(.not. any(mod(term%terms(1)%power_strain(:),2) /= 0))then
2018       ! Message to Output
2019       write(message,'(3a)' )ch10,&
2020         &         ' ==> No need for high order bounding term',ch10
2021       call wrtout(ab_out,message,'COLL')
2022       call wrtout(std_out,message,'COLL')
2023       to_skip = .TRUE.
2024       return
2025     end if
2026   end if
2027 
2028 end function check_to_skip

m_opt_effpot/opt_boundcoeff [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_boundcoeff

FUNCTION

 optimize a bound coefficient if optimized value is negative
 put an positive value that respects a precision penalty

INPUTS

OUTPUT

SOURCE

1940 function opt_boundcoeff(yvalues,cvalues,penalty_in) result (coeff)
1941   !Arguments ------------------------------------
1942   implicit none
1943 
1944   !Arguments ------------------------------------
1945   real(dp),intent(in) :: yvalues(2),cvalues(2),penalty_in
1946   real(dp) :: coeff
1947   !local
1948   !variable
1949   real(dp) :: a,b,coeff_tmp,x1,x2,penalty
1950   !array
1951   ! *************************************************************************
1952 
1953   a = ( (yvalues(1) - 1) - (yvalues(2)-1)*(cvalues(1)/cvalues(2))) / (cvalues(1)**2 - cvalues(1)*cvalues(2))
1954 
1955   b = ( (yvalues(2) - 1)/cvalues(2) ) - ( (yvalues(1) -1)*cvalues(2) - (yvalues(2) - 1)*cvalues(1) )&
1956     &    / (cvalues(1)**2 - cvalues(1)*cvalues(2))
1957 
1958   !write(*,*) "a", a
1959   !write(*,*) "b", b
1960   penalty = penalty_in - 1
1961   coeff_tmp = -b/(2*a)
1962   !write(*,*) "coeff_tmp", coeff_tmp
1963   if(coeff_tmp > 0)then
1964     coeff = coeff_tmp
1965   elseif(coeff_tmp <= 0)then
1966     x1 = (-b + sqrt(b**2 + 4*a*penalty)) / (2*a) ! 1.001 penalty value
1967     x2 = (-b - sqrt(b**2 + 4*a*penalty)) / (2*a)
1968     !write(*,*) "x1", x1
1969     !write(*,*) "x2", x2
1970     if(x1>0)then
1971       coeff = x1
1972     else
1973       coeff = x2
1974     endif
1975   endif
1976 
1977 end function opt_boundcoeff

m_opt_effpot/opt_effpot [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_effpot

FUNCTION

 Optimize Effective Potential by fitting the value of certain
 coefficients while keeping the values of the others

INPUTS

 eff_pot<type(effective_potential)> = effective potential

 opt_coeff(opt_ncoeff) = list of terms whose coefficients are to be
 optimized

 hist<type(abihist)> = Training set Data(or snapshot of DFT)
 comm = MPI communicator

OUTPUT

 eff_pot<type(effective_potential)> = effective potential datatype with new fitted coefficients

SOURCE

 83 subroutine opt_effpot(eff_pot,opt_ncoeff,opt_coeff,hist,opt_on,opt_factors,comm,print_anh)
 84 
 85   implicit none
 86 
 87   !Arguments ------------------------------------
 88   !scalars
 89   integer,intent(in) :: comm,opt_ncoeff
 90   type(effective_potential_type),intent(inout) :: eff_pot
 91   type(abihist),intent(inout) :: hist
 92   !arrays
 93   integer,intent(in) :: opt_coeff(opt_ncoeff)
 94   real(dp),intent(in) :: opt_factors(3)
 95   !Logicals
 96   logical,intent(in) :: opt_on(3)
 97   logical,optional,intent(in) :: print_anh
 98   !Strings
 99   !Local variables ------------------------------
100   !scalars
101   integer :: ii, info,natom_sc,ntime,unit_anh1,unit_anh2
102   integer :: master,nproc,my_rank
103   real(dp) :: factor,mse,msef,mses
104   real(dp),parameter :: HaBohr_eVAng = 27.21138386 / 0.529177249
105   !arrays
106   integer :: sc_size(3)
107   integer :: coeff_inds(opt_ncoeff)
108   type(fit_data_type) :: fit_data
109   type(polynomial_coeff_type) :: my_coeffs(opt_ncoeff)
110   real(dp) :: coeff_values(opt_ncoeff), coeff_init_values(opt_ncoeff)
111   real(dp), allocatable :: energy_coeffs(:,:),fcart_coeffs(:,:,:,:)
112   real(dp), allocatable :: strten_coeffs(:,:,:)
113   !Logicals
114   logical :: need_print_anh,file_opened,iam_master
115   !Strings
116   character(len=1000) :: message
117   character(len=1000) :: frmt
118   character(len=fnlen) :: fn_bf='before_opt_diff', fn_af='after_opt_diff'
119   ! *************************************************************************
120   !MPI
121   master = 0
122   nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
123   iam_master = (my_rank == master)
124 
125   !Setting/Initializing Variables
126   ntime = hist%mxhist
127   natom_sc = size(hist%xred,2)
128   factor   = 1._dp/natom_sc
129   need_print_anh =.False.
130   
131   if(present(print_anh)) then
132     if(print_anh) need_print_anh=.True.
133   end if
134   !if the number of atoms in reference supercell into effpot is not correct,
135   !wrt to the number of atom in the hist, we set map the hist and set the good supercell
136   if (natom_sc /= eff_pot%supercell%natom) then
137     call effective_potential_file_mapHistToRef(eff_pot,hist,comm,verbose=.TRUE.)
138   end if
139 
140   !we get the size of the supercell in the hist file
141   ! This is only valid for diagonal sc_size.
142   ! F08: sc_size(:) = int(anint( norm2(eff_pot%supercell%rprimd, dim=2) / &
143   !   & norm2(eff_pot%crystal%rprimd, dim=2) ))
144   do ii=1,3
145     sc_size(ii) = int(anint(sqrt(eff_pot%supercell%rprimd(ii,1)**2+&
146       &                               eff_pot%supercell%rprimd(ii,2)**2+&
147       &                               eff_pot%supercell%rprimd(ii,3)**2) / &
148       &                          sqrt(eff_pot%crystal%rprimd(ii,1)**2+&
149       &                               eff_pot%crystal%rprimd(ii,2)**2+&
150       &                               eff_pot%crystal%rprimd(ii,3)**2)))
151   end do
152 
153 
154   !Before the fit, compute constants with fit_data_compute.
155   !Compute the strain of each configuration.
156   !Compute the displacmeent of each configuration.
157   !Compute the variation of the displacement due to strain of each configuration.
158   !Compute fixed forces and stresse and get the standard deviation.
159   !Compute Sheppard and al Factors  \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
160   call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
161 
162 
163   if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
164     &                            fn_bf,eff_pot%anharmonics_terms)
165 
166   !Before deleting coefficients calculate MSD of initial model
167   call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
168     &                                     natom_sc,ntime,fit_data%training_set%sqomega,comm,&
169     &                                     compute_anharmonic=.TRUE.,print_file=.TRUE.,filename=fn_bf)
170 
171 
172   !  Print the standard devition of initial model
173   write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
174     &                    ' Mean Standard Deviation values of the effective-potential',ch10,&
175     &                    ' with respect to the training-set before optimization (meV^2/atm):',&
176     &               ch10,'   Energy          : ',&
177     &               mse* (Ha_EV*1000)**2 *factor ,ch10,&
178     &                    ' Goal function values of the effective.potential',ch10,&
179     &                    ' with respect to the test-set (eV^2/A^2):',ch10,&
180     &                    '   Forces+Stresses : ',&
181     &               (msef+mses)*(HaBohr_eVAng)**2,ch10,&
182     &                    '   Forces          : ',&
183     &               msef*(HaBohr_eVAng)**2,ch10,&
184     &                    '   Stresses        : ',&
185     &               mses*(HaBohr_eVAng)**2,ch10
186   call wrtout(ab_out,message,'COLL')
187   call wrtout(std_out,message,'COLL')
188 
189 
190   ! Write terms to my_coeffs(ii) and zero them in eff_pot
191   do ii=1,opt_ncoeff
192     !Store indices for later
193     coeff_inds(ii) = ii
194     !Initialize coefficients for optimizing
195     call polynomial_coeff_init(coeff_values(ii),eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%nterm,&
196       &                            my_coeffs(ii), eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%terms, &
197       &                            check=.TRUE.)
198     !Store initial values of coefficients
199     coeff_init_values(ii) = eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient
200     !Put them temporarely to zero
201     eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = zero
202   end do
203 
204   !Before the fit, compute constants with fit_data_compute.
205   !And coefficients to be optimized put to zero
206   !Conpute the strain of each configuration.
207   !Compute the displacmeent of each configuration.
208   !Compute the variation of the displacement due to strain of each configuration.
209   !Compute fixed forces and stresse and get the standard deviation.
210   !Compute Sheppard and al Factors  \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
211   call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.TRUE.)
212 
213   !After deleting coefficients calculate MSD
214   call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
215     &                                     natom_sc,ntime,fit_data%training_set%sqomega,comm,&
216     &                                      compute_anharmonic=.TRUE.)
217 
218 
219   !  Print the standard deviation after deleting
220   write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
221     &                    ' Mean Standard Deviation values of the effective-potential',ch10,&
222     &                    ' with respect to the training-set after deleting selected terms (meV^2/atm):',&
223     &               ch10,'   Energy          : ',&
224     &               mse* (Ha_EV*1000)**2 *factor ,ch10,&
225     &                    ' Goal function values of the effective.potential',ch10,&
226     &                    ' with respect to the test-set (eV^2/A^2):',ch10,&
227     &                    '   Forces+Stresses : ',&
228     &               (msef+mses)*(HaBohr_eVAng)**2,ch10,&
229     &                    '   Forces          : ',&
230     &               msef*(HaBohr_eVAng)**2,ch10,&
231     &                    '   Stresses        : ',&
232     &               mses*(HaBohr_eVAng)**2,ch10
233   call wrtout(ab_out,message,'COLL')
234   call wrtout(std_out,message,'COLL')
235 
236 
237 
238   ! Allocate necessary arrays for the fit-data
239   ABI_MALLOC(energy_coeffs,(opt_ncoeff,ntime))
240   ABI_MALLOC(fcart_coeffs,(3,natom_sc,opt_ncoeff,ntime))
241   ABI_MALLOC(strten_coeffs,(6,ntime,opt_ncoeff))
242   ! Calculate forces and stresses per coefficient, which are to be optimized
243   call fit_polynomial_coeff_getFS(my_coeffs,fit_data%training_set%du_delta,&
244     &                                 fit_data%training_set%displacement,&
245     &                                 energy_coeffs,fcart_coeffs,natom_sc,eff_pot%crystal%natom,&
246     &                                 opt_ncoeff,ntime,sc_size,fit_data%training_set%strain,&
247     &                                 strten_coeffs,fit_data%training_set%ucvol,coeff_inds,opt_ncoeff)
248 
249 
250   !  call the fit process routine
251   !  This routine solves the linear system proposed
252   !  by C.Escorihuela-Sayalero see PRB95,094115(2017) [[cite:Escorihuela-Sayalero2017]]
253   call fit_polynomial_coeff_solve(coeff_values(1:opt_ncoeff),fcart_coeffs,fit_data%fcart_diff,&
254     &                                  energy_coeffs,fit_data%energy_diff,info,&
255     &                                  coeff_inds,natom_sc,opt_ncoeff,opt_ncoeff,ntime,&
256     &                                  strten_coeffs,fit_data%strten_diff,&
257     &                                  fit_data%training_set%sqomega,opt_on,opt_factors)
258 
259   if (info /= 0 .and. all(coeff_values < tol16))then
260     write(frmt,*) opt_ncoeff
261     write(message, '(2a,'//ADJUSTR(frmt)//'I4,8a)' ) ch10,&
262       &        '     The attempt to optimize the terms: ', opt_coeff ,ch10,&
263       &        '     , returned a singular solution', ch10,&
264       &        '     The terms could not be optimized ',ch10,&
265       &        '     and the effective potential has not been altered.', ch10,&
266       &        '     Action: Change training set or coefficients to be optimized.'
267     ABI_WARNING(message)
268     do ii=1,opt_ncoeff
269       eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = coeff_init_values(ii)
270       call polynomial_coeff_free(my_coeffs(ii))
271     end do
272   else
273     ! Transfer new fitted values to coefficients and write them into effective potential
274     ! Deallcoate temporary coefficients my_coeffs
275     do ii=1,opt_ncoeff
276       eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = coeff_values(ii)
277       call polynomial_coeff_free(my_coeffs(ii))
278     end do
279     !Recalculate MSD of Final Model
280 
281     !Conpute the strain of each configuration.
282     !Compute the displacmeent of each configuration.
283     !Compute the variation of the displacement due to strain of each configuration.
284     !Compute fixed forces and stresse and get the standard deviation.
285     !Compute Sheppard and al Factors  \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
286     call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.TRUE.)
287 
288 
289     if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
290       &                            fn_af,eff_pot%anharmonics_terms)
291 
292     !After optimization of coefficients opt_coeff recalculate MSD
293     call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
294       &                                     natom_sc,ntime,fit_data%training_set%sqomega,comm,&
295       &                                     compute_anharmonic=.TRUE.,print_file=.TRUE.,filename=fn_af)
296 
297 
298     !  Print the standard deviation after optimization
299     write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
300       &                    ' Mean Standard Deviation values of the effective-potential',ch10,&
301       &                    ' with respect to the training-set after optimizing selected terms (meV^2/atm):',&
302       &               ch10,'   Energy          : ',&
303       &               mse* (Ha_EV*1000)**2 *factor ,ch10,&
304       &                    ' Goal function values of the effective.potential',ch10,&
305       &                    ' with respect to the test-set (eV^2/A^2):',ch10,&
306       &                    '   Forces+Stresses : ',&
307       &               (msef+mses)*(HaBohr_eVAng)**2,ch10,&
308       &                    '   Forces          : ',&
309       &               msef*(HaBohr_eVAng)**2,ch10,&
310       &                    '   Stresses        : ',&
311       &               mses*(HaBohr_eVAng)**2,ch10
312     call wrtout(ab_out,message,'COLL')
313     call wrtout(std_out,message,'COLL')
314   end if
315 
316   !Deallocation of fitting variables
317   ABI_FREE(energy_coeffs)
318   ABI_FREE(fcart_coeffs)
319   ABI_FREE(strten_coeffs)
320 
321   if(need_print_anh)then
322     INQUIRE(FILE='before_opt_diff_anharmonic_terms_energy.dat',OPENED=file_opened,number=unit_anh1)
323     if(file_opened) close(unit_anh1)
324     INQUIRE(FILE='after_opt_diff_anharmonic_terms_energy.dat',OPENED=file_opened,number=unit_anh2)
325     if(file_opened) close(unit_anh2)
326   end if
327   ! Deallocate and delete the fit-date
328   call fit_data_free(fit_data)
329 end subroutine opt_effpot

m_opt_effpot/opt_effpotbound [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_effpotbound

FUNCTION

 Compute and add high order terms to existing odd or negative even anharmonic terms
 Fix the coefficient of the added new high order terms to a value such that it
 doesn't influence the precision of the existing anharmonic potential with respect
 to a relevent training set (ATTENTIION: A user must know what a relevant training set
 is for the system he want's to study. Typically something oscillating around its ground-state.)
 Finally optimize the coefficients of the orignal anharmonic terms under the presence of the
 added high order terms.

INPUTS

 eff_pot: existing effective potential
 order: order for which bounding terms are generated
 order_ran: ?
 bound_EFS:
 bound_factors:
 bound_penalty:

OUTPUT

 eff_pot new effective potential

SOURCE

361 subroutine opt_effpotbound(eff_pot,order_ran,hist,bound_EFS,bound_factors,bound_penalty,comm,print_anh)
362 
363   implicit none
364 
365   !Arguments ------------------------------------
366   !scalars
367   integer,intent(in) :: comm
368   type(effective_potential_type),target,intent(inout) :: eff_pot
369   type(abihist),intent(inout) :: hist
370   real(dp) :: bound_penalty
371   !arrays
372   integer,intent(in) :: order_ran(2),bound_EFS(3)
373   real(dp),intent(in) :: bound_factors(3)
374   !Logicals
375   logical,optional,intent(in) :: print_anh
376   !Strings
377   !Local variables ------------------------------
378   !scalars
379   integer :: i,ii,natom_sc,ntime,iterm,nterm
380   integer :: jterm, ncombi,ncombi1,ncombi2
381   integer :: icombi
382   integer :: nterm_start,nterm2
383   integer :: nproc,my_rank,master
384   !1406
385   real(dp) :: factor,mse_ini,msef_ini,mses_ini,mse,msef,mses
386   real(dp) :: coeff_tmp
387   real(dp),parameter :: HaBohr_eVAng = 27.21138386 / 0.529177249
388   !arrays
389   integer :: sc_size(3),temp_cntr
390   integer,allocatable :: terms(:)
391   logical,allocatable :: exists(:)
392   logical :: any_exists
393   type(fit_data_type) :: fit_data
394   real(dp) :: GF_arr(2),coeff_opt(2)
395   !real(dp), allocatable :: energy_coeffs(:,:),fcart_coeffs(:,:,:,:)
396   !real(dp), allocatable :: strten_coeffs(:,:,:)
397   !1406 strain_temrs_tmp
398   type(polynomial_coeff_type),target,allocatable :: my_coeffs(:),my_coeffs_tmp(:)
399   type(polynomial_coeff_type),allocatable :: singledisp_terms(:),HOsingledisp_terms(:)
400   type(polynomial_coeff_type),allocatable :: HOcrossdisp_terms(:)
401   !Logicals
402   logical :: need_print_anh ! MARCUS FOR THE MOMENT PRINT NO FILES
403   logical :: to_skip,iam_master
404   !Strings
405   character(len=5),allocatable :: symbols(:)
406   character(len=200):: name
407   character(len=1000) :: message
408   character(len=fnlen) :: fn_bf='before_opt_diff'!, fn_af='after_opt_diff'
409   ! types
410   type(SymPairs_t) :: sympairs
411   !*************************************************************************
412   !MPI variables
413   master = 0
414   nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
415   iam_master = (my_rank == master)
416 
417   ! Say hello to the world!
418   write(message, '(3a)' )'-Start Bound optimization of Anharmonic Potential ',ch10
419   call wrtout(ab_out,message,'COLL')
420   call wrtout(std_out,message,'COLL')
421 
422   !Setting/Initializing Variables
423   ntime = hist%mxhist
424   natom_sc = size(hist%xred,2)
425   factor   = 1._dp/natom_sc
426   nterm =eff_pot%anharmonics_terms%ncoeff
427   need_print_anh=.False.
428   if(present(print_anh))then
429     if(print_anh) need_print_anh = .True.
430   endif
431 
432 
433   ABI_MALLOC(symbols,(eff_pot%crystal%natom))
434   ABI_MALLOC(terms,(nterm))
435   call symbols_crystal(eff_pot%crystal%natom,eff_pot%crystal%ntypat,eff_pot%crystal%npsp,&
436     &                     symbols,eff_pot%crystal%typat,eff_pot%crystal%znucl)
437 
438 
439   !if the number of atoms in reference supercell into effpot is not correct,
440   !wrt to the number of atom in the hist, we set map the hist and set the good supercell
441   if (natom_sc /= eff_pot%supercell%natom) then
442     call effective_potential_file_mapHistToRef(eff_pot,hist,comm,verbose=.TRUE.)
443   end if
444 
445   !Check if input of order is correct
446   ! TODO write error message here
447   if (any(mod(order_ran,2) /= 0)) return
448 
449   !we get the size of the supercell in the hist file
450   do ii=1,3
451     sc_size(ii) = int(anint(sqrt(eff_pot%supercell%rprimd(ii,1)**2+&
452       &                               eff_pot%supercell%rprimd(ii,2)**2+&
453       &                               eff_pot%supercell%rprimd(ii,3)**2) / &
454       &                          sqrt(eff_pot%crystal%rprimd(ii,1)**2+&
455       &                               eff_pot%crystal%rprimd(ii,2)**2+&
456       &                               eff_pot%crystal%rprimd(ii,3)**2)))
457   end do
458 
459 
460   !Before the fit, compute constants with fit_data_compute.
461   !Conpute the strain of each configuration.
462   !Compute the displacmeent of each configuration.
463   !Compute the variation of the displacement due to strain of each configuration.
464   !Compute fixed forces and stresse and get the standard deviation.
465   !Compute Sheppard and al Factors  \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
466   !call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
467   call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
468 
469   if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
470     &                            fn_bf,eff_pot%anharmonics_terms)
471 
472   !Before adding bound coefficients calculate MSD of initial model
473   !MS FOR THE MOMENT PRINT NO FILE
474   call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse_ini,msef_ini,mses_ini,&
475     &                                  natom_sc,ntime,fit_data%training_set%sqomega,comm,&
476     &                                  compute_anharmonic=.TRUE.,print_file=.FALSE.)
477 
478 
479   !  Print the standard devition of initial model
480   write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
481     &           ' Mean Standard Deviation values of the effective-potential',ch10,&
482     &           ' with respect to the training-set before attempted bounding (meV^2/atm):',&
483     &           ch10,'   Energy          : ',&
484     &           mse_ini* (Ha_EV*1000)**2 *factor ,ch10,&
485     &           ' Goal function values of the effective.potential',ch10,&
486     &           ' with respect to the test-set (eV^2/A^2):',ch10,&
487     &           '   Forces+Stresses : ',&
488     &           (msef_ini+mses_ini)*(HaBohr_eVAng)**2,ch10,&
489     &           '   Forces          : ',&
490     &           msef_ini*(HaBohr_eVAng)**2,ch10,&
491     &           '   Stresses        : ',&
492     &           mses_ini*(HaBohr_eVAng)**2,ch10
493   call wrtout(ab_out,message,'COLL')
494   call wrtout(std_out,message,'COLL')
495 
496   !MS DEV
497   ! single displacement terms with second order only.
498   call opt_getSingleDispTerms(singledisp_terms,eff_pot%crystal, sc_size,comm)
499 
500 
501   ! create pair list:
502   call sympairs%init(eff_pot%crystal, sc_size)
503 
504   !For the moment order loop commented
505   !do iorder=order(1),order(2),2, Order will be done per term
506   !Loop over all original terms + 1
507   ! + 1 to bound pure strain
508   do iterm =1,nterm +1
509     if(iterm <=nterm)then
510       ncombi1=0
511       ncombi2=0
512       !Store for optimization
513       terms(iterm) = iterm
514       !Message: The world wants to know where we stand Batman
515       write(message, '(a,(80a),a)' ) ch10,&
516         &      ('_',ii=1,80),ch10
517       call wrtout(ab_out,message,'COLL')
518       call wrtout(std_out,message,'COLL')
519       write(message,'(2a,I3,a,I3,3a)' )ch10,&
520         &       ' Check term (',iterm,'/',nterm,'): ', trim(eff_pot%anharmonics_terms%coefficients(iterm)%name),ch10
521       call wrtout(ab_out,message,'COLL')
522       call wrtout(std_out,message,'COLL')
523       to_skip = .FALSE.
524       to_skip = check_to_skip(eff_pot%anharmonics_terms%coefficients(iterm))
525       !Skip term if it doesn't need bounding
526       if(.not. to_skip)then
527         !Get List of high order single Terms for terms
528         call opt_getHOSingleDispTerms(eff_pot%anharmonics_terms%coefficients(iterm),&
529           &                                      HOsingledisp_terms,symbols,singledisp_terms,order_ran,ncombi1)
530 
531 
532         ABI_MALLOC(my_coeffs,(size(eff_pot%anharmonics_terms%coefficients)))
533         my_coeffs=eff_pot%anharmonics_terms%coefficients
534         call coeffs_list_conc_onsite(my_coeffs, HOsingledisp_terms)
535         if(allocated(HOsingledisp_terms)) call polynomial_coeff_list_free(HOsingledisp_terms)
536         !Get List of high order cross Terms for term if ndisp > 1
537         associate(term1=>eff_pot%anharmonics_terms%coefficients(iterm)%terms(1))
538           if(term1%ndisp>1 .or. &
539             & term1%ndisp /= 0 .and. & ! why >1 or /=0?
540             & term1%nstrain /= 0)then
541             ! output HOcrossdisp_terms, ncombi2.
542             call opt_getHOcrossdisp(HOcrossdisp_terms,ncombi2,eff_pot%anharmonics_terms%coefficients(iterm),order_ran)
543           endif
544         end associate
545         ! then add the crossdisp terms.
546         if(ncombi2 > 0)then
547           call coeffs_list_conc_onsite(my_coeffs, HOcrossdisp_terms)
548 
549         endif
550         if(allocated(HOcrossdisp_terms)) call polynomial_coeff_list_free(HOcrossdisp_terms)
551       else  ! to_skip
552         ncombi2=0
553         ncombi1=0
554         ABI_MALLOC(my_coeffs,(size(eff_pot%anharmonics_terms%coefficients)))
555         my_coeffs = eff_pot%anharmonics_terms%coefficients
556       endif
557       ncombi = ncombi1 + ncombi2
558       nterm_start = eff_pot%anharmonics_terms%ncoeff
559     else ! if iterm = nterm + 1 => Take care about strain
560       call opt_getHOstrain(my_coeffs,ncombi,nterm_start,eff_pot,order_ran,comm)
561     endif !
562 
563 
564     ! Modification of Alireza.
565     !---------------------------------------------
566 !Here my_coeffs contains the previous coeff and the new bounding ones. wight is allways +1 so the power in SAT generation does not matter!!
567 
568     ! 1. We need to use generateTermsFromList module to create terms.
569     ! 2. The  generateTermsFromList module accepts list combinations of terms: (\1,1,1,1,7,7\)
570     ! 3. We need to convert the terms from bounding process to a list like (\1,1,1,1,7,7\)
571     ! 4. use polynomial_coeff_getList to get pairs.
572     ! 5. compare th list and the terms and find out what is the number of diplacement in list for a term.
573     ! 6. convert term to list.
574     ! 7. ask for the temrs from generateTermsFromList
575     ! 8. check and see if the coeff is already considered or not. use coeffs_compare function
576     !! strain??? the same thing should be done for the strain
577     !! find the list of all the list_str,
578     !! fond what is number of strain in the displacemt comapring it to
579     !! the list_str and give this to
580 
581     !     get coeff from > generateTermsFromList(list_disp,****)
582     !     setcoeff_to_tmp_coeffs
583     ! generateTermsFromList(cell,index_coeff,list_coeff,list_str,ncoeff,ndisp_max,nrpt,nstr,nsym,nterm,terms)
584 
585 ! call the new function to get the data required to call polynomial_coeff_getList
586 
587     call generate_bounding_term_and_add_to_list( sympairs, nterm_start, ncombi, my_coeffs, temp_cntr)
588 
589 
590     if (temp_cntr>0) then
591       do icombi=1,temp_cntr
592         ! Copy all the terms in eff pot
593         ! Get new name of term and set new terms to potential
594         !write(*,*) 'ndisp of term', my_coeffs(nterm_start+icombi)%nterm
595         !write(*,*) 'and wath is nterm_start', nterm_start,'and icomb btw', icomb
596         !write(std_out,*) 'get name in main bound'
597         call polynomial_coeff_getName(name, &
598           & my_coeffs(nterm_start+icombi),symbols,recompute=.TRUE.)
599         call polynomial_coeff_SetName(name,my_coeffs(nterm_start+icombi))
600 
601 
602         ! Set dimensions of temporary my_coeffs array
603         nterm2 = eff_pot%anharmonics_terms%ncoeff + 1
604         ABI_MALLOC(my_coeffs_tmp,(nterm2))
605         ! Copy terms of previous cycle
606         my_coeffs_tmp(1:nterm2-1) = eff_pot%anharmonics_terms%coefficients
607         !Put new term to my_coeffs_tmp
608         !my_coeffs_tmp(nterm2) = my_coeffs(nterm_start+icombi)
609         call polynomial_coeff_init(my_coeffs(nterm_start+icombi)%coefficient, &
610           & my_coeffs(nterm_start+icombi)%nterm, &
611           & my_coeffs_tmp(nterm2),my_coeffs(nterm_start+icombi)%terms, &
612           &my_coeffs(nterm_start+icombi)%name)
613         ! If order is greater than specified cycle
614         if(sum(my_coeffs_tmp(nterm2)%terms(1)%power_disp) &
615           &             +sum(my_coeffs_tmp(nterm2)%terms(1)%power_strain) > maxval(order_ran))then
616           call polynomial_coeff_list_free(my_coeffs_tmp)
617           cycle
618         endif
619         ! Message to Output
620         write(message,'(5a)' )ch10,&
621           &            ' ==> high order term: ', trim(my_coeffs_tmp(nterm2)%name),' created',ch10
622         call wrtout(ab_out,message,'COLL')
623         call wrtout(std_out,message,'COLL')
624         ! Check if generated term is not already contained in effpot
625         ! If yes cycle
626         ABI_MALLOC(exists, (nterm2))
627         exists=.FALSE.
628         do jterm=1,nterm2-1
629           exists(jterm) = coeffs_compare(my_coeffs_tmp(jterm),my_coeffs_tmp(nterm2))
630         enddo !jterm
631         any_exists=any(exists)
632         ABI_FREE(exists)
633         if(any_exists)then
634           write(message,'(3a)' )ch10,&
635             &              '   ==> Term exists already. We cycle',ch10
636           call wrtout(ab_out,message,'COLL')
637           call wrtout(std_out,message,'COLL')
638           call polynomial_coeff_list_free(my_coeffs_tmp)
639           cycle
640         endif
641 
642 
643         ! Set new term into effective potential
644         call effective_potential_setCoeffs(my_coeffs_tmp,eff_pot,nterm2)
645 
646         ! Tell the world what we do, They want to know.
647         write(message,'(3a)' )ch10,&
648           &           '   ==> Optimizing coefficient',ch10
649         call wrtout(ab_out,message,'COLL')
650         call wrtout(std_out,message,'COLL')
651 
652         ! Deallocation in loop
653         call polynomial_coeff_list_free(my_coeffs_tmp)
654         !Optimizing coefficient old style
655 
656         if(iterm>nterm)then
657           ! MS 2006 Decomment for old style optimization
658           call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
659             &                                           natom_sc,ntime,fit_data%training_set%sqomega,comm,&
660             &                                           compute_anharmonic=.TRUE.,print_file=.FALSE.)
661           i = 0
662           write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses)/(msef_ini+mses_ini): ", (msef+mses)/(msef_ini+mses_ini)
663           call wrtout(std_out,message,'COLL')
664           write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses): ", (msef+mses)
665           call wrtout(std_out,message,'COLL')
666           do  while((msef+mses)/(msef_ini+mses_ini) >= 1.001)
667             i = i + 1
668             eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = &!coeff_ini / 2**i
669               &                  eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient / 2**1
670             call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
671               &                                              natom_sc,ntime,fit_data%training_set%sqomega,comm,&
672               &                                              compute_anharmonic=.TRUE.,print_file=.FALSE.)
673 
674             write(message,'(a,I2,a,ES24.16)') "cycle ",i," (msef+mses)/(msef_ini+mses_ini): ",(msef+mses)/(msef_ini+mses_ini)
675             call wrtout(std_out,message,'COLL')
676             write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses): ", (msef+mses)
677             call wrtout(std_out,message,'COLL')
678           enddo ! while mse/mse_ini>1.0001
679           write(message,'(a,ES24.16)') "coeff after opt:",   eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
680           call wrtout(std_out,message,'COLL')
681           msef_ini = msef
682           mses_ini = mses
683           !           !Optimize coefficient with opt routine
684           !           optterm(1)= nterm2
685           !           nterm_opt = 1
686           !           call opt_effpot(eff_pot,nterm_opt,optterm,hist,comm,print_anh=.FALSE.)
687           !           write(*,*) "coeff after opt:",   eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
688           !            !Store new "inital precision for next coefficient
689           !            msef_ini = msef
690           !            mses_ini = mses
691 
692         else
693           !Optimizing coefficient with GF criterion
694           coeff_opt = 0
695           GF_arr = 0
696           i = 1
697           do while(i<=2)
698             eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = &
699               &                eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient/ 2**(i-1)
700             call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
701               &                                              natom_sc,ntime,fit_data%training_set%sqomega,comm,&
702               &                                              compute_anharmonic=.TRUE.,print_file=.FALSE.)
703             GF_arr(i) =  (bound_factors(1)*bound_EFS(1)*mse+bound_factors(2)*bound_EFS(2)*msef&
704               &                             +bound_factors(3)*bound_EFS(3)*mses) / &
705               &                             (bound_factors(1)*bound_EFS(1)*mse_ini+bound_factors(2)*bound_EFS(2)*msef_ini&
706               &                             +bound_factors(3)*bound_EFS(3)*mses_ini)
707             write(message,'(a,I2,a,ES24.16)') "cycle ",i," GF/GF_ini: ",GF_arr(i)
708             call wrtout(std_out,message,'COLL')
709             write(message,'(a,I2,a,ES24.16)') "cycle ", i ," GF: ",(bound_factors(1)*bound_EFS(1)*mse&
710               &                                                                       +bound_factors(2)*bound_EFS(2)*msef&
711               &                                                                       +bound_factors(3)*bound_EFS(3)*mses)
712             call wrtout(std_out,message,'COLL')
713             coeff_opt(i) =  eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
714             if(i==2 .and. abs(GF_arr(1)-GF_arr(2)) < tol8)then
715               eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient =&
716                 eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient*10d5
717               write(message,'(5a)') ch10,"Differences between test-cycles to small increase",ch10, &
718                 &                                          "test coefficient value by factor 1000",ch10
719               call wrtout(std_out,message,'COLL')
720               i = 1
721             else
722               i=i+1
723             end if
724           enddo ! while mse/mse_ini>10
725           eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = opt_boundcoeff(GF_arr,coeff_opt,bound_penalty)
726           write(message,'(a,ES24.16)') "coeff after opt1:",   eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
727           call wrtout(std_out,message,'COLL')
728           coeff_tmp = ANINT(eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient*10d10)
729           eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = coeff_tmp/10d10
730           write(message,'(a,ES24.16)') "coeff after opt2:",   eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
731           call wrtout(std_out,message,'COLL')
732           call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
733             &                                               natom_sc,ntime,fit_data%training_set%sqomega,comm,&
734             &                                               compute_anharmonic=.TRUE.,print_file=.FALSE.)
735           write(message,'(a,ES24.16)') "GF/GF_ini after_opt: ", (bound_factors(1)*bound_EFS(1)*mse&
736             &                                                                     +bound_factors(2)*bound_EFS(2)*msef&
737             &                                                                     +bound_factors(3)*bound_EFS(3)*mses) / &
738             &                                                                     (bound_factors(1)*bound_EFS(1)*mse_ini&
739             &                                                                     +bound_factors(2)*bound_EFS(2)*msef_ini&
740             &                                                                     +bound_factors(3)*bound_EFS(3)*mses_ini)
741           call wrtout(std_out,message,'COLL')
742           mse_ini  = mse
743           msef_ini = msef
744           mses_ini = mses
745         endif
746         !DEALLOCATION
747         !ABI_FREE(exists)
748       enddo ! icombi
749     end if
750 
751     call polynomial_coeff_list_free(my_coeffs)
752   end do !iterm
753   !enddo ! order
754 
755   if(allocated(singledisp_terms)) call polynomial_coeff_list_free(singledisp_terms)
756 
757   write(message, '(a,(80a),a)' ) ch10,&
758     &('_',ii=1,80),ch10
759   call wrtout(ab_out,message,'COLL')
760   call wrtout(std_out,message,'COLL')
761 
762   write(message,'(3a)' )ch10,&
763     &     ' Finished creating high-order terms',ch10  !,&
764   !&     ' Optimize initial anharmonic terms !NOT IS COMMENTED NOW!',ch10
765   call wrtout(ab_out,message,'COLL')
766   call wrtout(std_out,message,'COLL')
767   !  call opt_effpot(eff_pot,nterm,terms,hist,comm,print_anh=.FALSE.)
768 
769   !  Print the standard devition of final model
770   write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
771     &                    ' Mean Standard Deviation values of the effective-potential',ch10,&
772     &                    ' with respect to the training-set after attempted bounding (meV^2/atm):',&
773     &               ch10,'   Energy          : ',&
774     &               mse_ini* (Ha_EV*1000)**2 *factor ,ch10,&
775     &                    ' Goal function values of the effective.potential',ch10,&
776     &                    ' with respect to the test-set (eV^2/A^2):',ch10,&
777     &                    '   Forces+Stresses : ',&
778     &               (msef_ini+mses_ini)*(HaBohr_eVAng)**2,ch10,&
779     &                    '   Forces          : ',&
780     &               msef_ini*(HaBohr_eVAng)**2,ch10,&
781     &                    '   Stresses        : ',&
782     &               mses_ini*(HaBohr_eVAng)**2,ch10
783   call wrtout(ab_out,message,'COLL')
784   call wrtout(std_out,message,'COLL')
785 
786 
787   !DEALLOCATION
788   ABI_FREE(symbols)
789   ABI_FREE(terms)
790 
791   !ABI_FREE(my_coeffs)
792   call fit_data_free(fit_data)
793   call sympairs%free()
794 
795 
796 end subroutine opt_effpotbound

m_opt_effpot/opt_filterdisp [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_opt_filterdisp

FUNCTION

 If a anharmonic term represents a strain-phonon coupling
 delete the strain and only keep the displacement part.

INPUTS

 term<polynomial_coeff_type>: anharmonic term to check
 nterm_of_term: number of symmetry equivalent terms for term

OUTPUT

 term<polynomial_coeff_type>: only the displacement part of original term

SOURCE

1239 subroutine opt_filterdisp(term,nterm_of_term)
1240 
1241   implicit none
1242 
1243   !Arguments ------------------------------------
1244   !scalars
1245   type(polynomial_coeff_type),intent(inout) :: term
1246   integer,intent(in) :: nterm_of_term
1247   !arrays
1248   !Logicals
1249   !Strings
1250   !Local variables ------------------------------
1251   !scalars
1252   integer :: iterm_of_term
1253   !reals
1254   real(dp) :: coeff
1255   !arrays
1256   type(polynomial_term_type) :: terms(nterm_of_term)
1257   !Logicals
1258   !Strings
1259   !*************************************************************************
1260 
1261   !Initialize/Get Variables
1262   !nterm_of_term = term%nterm
1263 
1264   ! Set strain to zero in terms
1265   do iterm_of_term = 1, nterm_of_term
1266     !Set strain in all terms to zero
1267     !terms(iterm_of_term)%nstrain = 0
1268     !Free initial strain array
1269     !ABI_FREE(term%terms(iterm_of_term)%strain)
1270     !ABI_FREE(term%terms(iterm_of_term)%power_strain)
1271     !Reallocate them with size zero
1272   enddo ! iterm_of term
1273 
1274   do iterm_of_term=1,nterm_of_term
1275     !terms(iterm_of_term) = term%terms(iterm_of_term)
1276     call polynomial_term_init(term%terms(iterm_of_term)%atindx, &
1277       & term%terms(iterm_of_term)%cell,&
1278       & term%terms(iterm_of_term)%direction,&
1279       & term%terms(iterm_of_term)%ndisp, &
1280       & term%terms(iterm_of_term)%nstrain, &
1281       & terms(iterm_of_term),&
1282       & term%terms(iterm_of_term)%power_disp, &
1283       & term%terms(iterm_of_term)%power_strain,&
1284       & term%terms(iterm_of_term)%strain, &
1285       & term%terms(iterm_of_term)%weight, &
1286       & check=.TRUE.)
1287     terms(iterm_of_term)%nstrain = 0
1288     terms(iterm_of_term)%power_strain = 0
1289     terms(iterm_of_term)%strain = 0
1290   enddo
1291 
1292   call polynomial_coeff_free(term)
1293   !Reinitial term
1294   !check=.TRUE. checks for duplicate terms
1295   call polynomial_coeff_init(coeff,nterm_of_term,term,terms,check=.TRUE.)
1296 
1297   do iterm_of_term=1,nterm_of_term
1298     call polynomial_term_free(terms(iterm_of_term))
1299   enddo
1300   !if(nterm_of_term /= term%nterm)then
1301   !  write(*,*) "nterm_of_term changed after deleting strain"
1302   !endif
1303 
1304 
1305 end subroutine opt_filterdisp

m_opt_effpot/opt_getCombisforterm [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_getCombisforterm

FUNCTION

 For a given order range: order_start, order_stop
 calculate number of total possible combinations ncombi
 and calculat combinations per order ncombi_order(i)

INPUTS

 order_start: start order for bounding terms
 order_end: end order for bounding terms
 ndisp: number of displacements a given term contains

OUTPUT

 ncombi: total number of combinations
 ncombi_order: array with number of combinations per order

SOURCE

911 subroutine opt_getCombisforterm(order_start,order_end,ndisp,ncombi,ncombi_order)
912 
913   implicit none
914 
915   !Arguments ------------------------------------
916   !scalars
917   integer,intent(in) :: ndisp
918   integer,intent(in) :: order_start, order_end
919   !arrays
920   integer,intent(out) :: ncombi
921   integer,intent(out) :: ncombi_order(:)
922   !Logicals
923   !Strings
924   !Local variables ------------------------------
925   !scalars
926   integer :: i
927   integer :: order,iorder1,iorder2
928   !arrays
929   !integer
930   !Logicals
931   !Strings
932   character(len=1000) :: message
933   !*************************************************************************
934 
935   !Test
936   if(mod(order_start,2) /= 0 .or. mod(order_end,2) /= 0)then
937     ! Message to Output
938     write(message,'(4a)' )ch10,&
939       &  'Either start or stop order are not even numbers',ch10,&
940       &  'Action: change bound_range in input',ch10
941     ABI_ERROR(message)
942   endif
943 
944   !Initialize Variables
945   i = 0
946   ncombi = 0
947   ncombi_order = 0
948 
949   !Calculate Combinations
950   do order=order_start,order_end,2
951     i = i+1
952     if(ndisp == 1)then
953       ncombi = ncombi + 1
954       ncombi_order(i) = 1
955     else
956       do iorder1 = 2,order-2*(ndisp-1),2
957         if(ndisp*iorder1 == order)then
958           ncombi = ncombi + 1
959           ncombi_order(i) = ncombi_order(i) + 1
960           cycle
961         endif
962         do iorder2=iorder1+2,order-2*(ndisp-1),2
963           if( iorder1 + (ndisp-1)*iorder2 == order)then
964             ncombi = ncombi + ndisp
965             ncombi_order(i) = ncombi_order(i) + ndisp
966           elseif(iorder1 * (ndisp-1) + iorder2 == order)then
967             ncombi = ncombi + ndisp
968             ncombi_order(i) = ncombi_order(i) + ndisp
969           endif
970         enddo !iorder2
971       enddo !iorder1 !
972     endif
973     !write(*,*) 'ncombi(',i,') for order',order,' is:', ncombi_order(i), 'are we happy?'
974   enddo !order
975 
976   !write(*,*) ncombi_order(:)
977   !write(*,*) 'ncombi for term is:', ncombi, 'are we happy?'
978 
979 
980 end subroutine opt_getCombisforterm

m_opt_effpot/opt_getHOcrossdisp [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_getHOcrossdisp

FUNCTION

 Get even high order displacement terms for a given input term and
 add them to an excisting list of terms. If the term is strain phonon type
 the strain part gets deleted and the high order terms for the displacement
 part are computed.
 Example: for a tree linear term with three displacements x*y*z the even high order
          possibilites are computed and stored.
          For range 6 to 8: x^2*y^2*z^2,x^4*y^2*z^2,x^2*y^4*z^2,x^2*y^2*z^4.

INPUTS

 eff_pot<effective_potential_type>: datatype with all the information
                                    about the effective potential
 power_disp(2): start and stop order for disp terms
 comm: mpi communicator (at the moment only sequential tested)

OUTPUT

 terms<polynomial_coeff_type>: list with original terms in effective
                               potential + HO even disp terms

SOURCE

1417 subroutine opt_getHOcrossdisp(terms_out,ncombi,term_in,power_disp)
1418 
1419   implicit none
1420 
1421   !Arguments ------------------------------------
1422   !scalars
1423   type(polynomial_coeff_type),allocatable,intent(inout) :: terms_out(:)
1424   type(polynomial_coeff_type),intent(inout) :: term_in
1425   integer,intent(in) :: power_disp(2)
1426   integer,intent(out) :: ncombi
1427   !arrays
1428   !Logicals
1429   !Strings
1430   !Local variables ------------------------------
1431   !scalars
1432   integer ::  ndisp,nterm_of_term,nstrain,nbody_tot
1433   integer ::  order_start,order_stop,norder
1434   integer ::  order_start_str,order_stop_str
1435   integer ::  icombi,idisp,iterm_of_term
1436   integer ::  ncombi_tot,ncombi_str
1437   !reals
1438   real(dp) :: coeff_ini=1
1439   !arrays
1440   type(polynomial_coeff_type) :: term
1441   integer,allocatable :: ncombi_order(:),ncombi_order_str(:),dummy(:)
1442   !Logicals
1443   logical :: had_strain
1444   !Strings
1445   character(len=1000) :: message
1446   !*************************************************************************
1447   !Get/Set Variables
1448   norder = abs(((power_disp(2)-power_disp(1))/2)) + 1
1449   ABI_MALLOC(ncombi_order,(norder))
1450   ABI_MALLOC(ncombi_order_str,(norder))
1451   ncombi_order = 0
1452   ncombi_order_str = 0
1453 
1454   ncombi = 0
1455   !Get this term (iterm) and infromations about it
1456   !Get number of displacements and equivalent terms for this term
1457   !Chose term one to get ndisp. ndisp is equal for all terms of the term
1458   !Get minimum oder for this term
1459   !Get total number of terms in effpot for message
1460   ndisp = term_in%terms(1)%ndisp
1461   nstrain = term_in%terms(1)%nstrain
1462   nbody_tot = ndisp + nstrain
1463   nterm_of_term = term_in%nterm
1464   ABI_MALLOC(dummy,(5)) ! XXX: why?
1465   call polynomial_coeff_init(coeff_ini,nterm_of_term,term,term_in%terms,term_in%name,check=.true.)
1466   ABI_FREE(dummy)
1467   ! Check if term has strain component.
1468   ! If yes filter strain and fit high order atomic displacement terms
1469   had_strain = .FALSE.
1470   ABI_MALLOC(dummy,(5))  ! XXX: again. why?
1471   if(term%terms(1)%nstrain /= 0)then
1472     ! Message to Output
1473     write(message,'(5a)' )ch10,&
1474       &               '- Term has strain compenent',ch10,&
1475       &               ' -> Filter Displacement',ch10
1476     call wrtout(ab_out,message,'COLL')
1477     call wrtout(std_out,message,'COLL')
1478     call opt_filterdisp(term,nterm_of_term)
1479     !Get new value of symmetry equivalent term nterm_of_term
1480     nterm_of_term = term%nterm
1481     !Remember if this term had strain
1482     had_strain = .TRUE.
1483     !cycle
1484   endif
1485   ABI_FREE(dummy)
1486   ! Ok we want it. Let's go.
1487 
1488   ! get start and stop order for this term
1489   call opt_getHOforterm(term,power_disp,order_start,order_stop)
1490   if(had_strain) call opt_getHOforterm(term_in,power_disp,order_start_str,order_stop_str)
1491   if(order_start == 0)then
1492     ! Message to Output
1493     write(message,'(5a,I2,a,I2,3a)' )ch10,&
1494       &               " ==> High order cross product terms for term ", trim(term%name),ch10,&
1495       &               " ==> do not fit into specified order range from ", power_disp(1),' to ',power_disp(2),ch10,&
1496       &               " ==> Can not construct high order cross product bounding term",ch10
1497     call wrtout(ab_out,message,'COLL')
1498     call wrtout(std_out,message,'COLL')
1499     ABI_FREE(ncombi_order)
1500     ABI_FREE(ncombi_order_str)
1501     return
1502   end if
1503 
1504   if(order_start_str == 0 .and. had_strain)then
1505     ! Message to Output
1506     write(message,'(5a,I2,a,I2,3a)' )ch10,&
1507       &               " ==> High order cross product terms for term ", trim(term_in%name),ch10,&
1508       &               " ==> do not fit into specified order range from ", power_disp(1),' to ',power_disp(2),ch10,&
1509       &               " ==> Can not construct high order cross product bounding term",ch10
1510     call wrtout(ab_out,message,'COLL')
1511     call wrtout(std_out,message,'COLL')
1512     had_strain = .FALSE.
1513   end if
1514   ! get total amount of combinations and combinations per order for the term
1515   call opt_getCombisforterm(order_start,order_stop,ndisp,ncombi,ncombi_order)
1516   !write(std_out,*) "I was here ncombi is: ", ncombi
1517   ! Allocate terms with ncombi free space to work with
1518   if(had_strain)then
1519     call opt_getCombisforterm(order_start_str,order_stop_str,nbody_tot,ncombi_str,ncombi_order_str)
1520     !write(std_out,*) "I was here ncombi_str is: ", ncombi_str
1521     ABI_MALLOC(terms_out,(ncombi+ncombi_str))
1522     ncombi_tot = ncombi+ncombi_str
1523   else
1524     ABI_MALLOC(terms_out,(ncombi))
1525     ncombi_tot = ncombi
1526   endif
1527   ! Copy current term to the ncombination elemenst a the end in array terms
1528   ! change the value of their coefficient to a start value
1529   ! The start is estimed to not be larger then half the initial term's value
1530   ! This is because higher order terms should have smaller coefficients
1531   do icombi=1,ncombi_tot
1532     if(icombi <= ncombi)then
1533       coeff_ini = 1 !abs(terms_out(icombi)%coefficient / 2)
1534       nterm_of_term = term%nterm
1535       call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out(icombi),term%terms,check=.true.)
1536     else
1537       coeff_ini = 10d3
1538       nterm_of_term = term_in%nterm
1539       call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out(icombi),term_in%terms,check=.true.)
1540     endif
1541     ! Set the power of all terms we want to add to two. We find the correct power later
1542     ! Change the weight of the term to 1 (even terms have allways weight=1)
1543     do iterm_of_term=1,nterm_of_term
1544       terms_out(icombi)%terms(iterm_of_term)%weight = 1
1545       if(icombi > ncombi)then
1546         terms_out(icombi)%terms(iterm_of_term)%power_strain = 2
1547         coeff_ini = 10d3 !abs(terms_out(icombi)%coefficient / 2)
1548         terms_out(icombi)%coefficient = coeff_ini
1549         !             elseif(icombi>2*ncombi)then
1550         !                terms_out(icombi)%terms(iterm_of_term)%power_strain = 4
1551         !                coeff_ini = 10d5 !abs(terms_out(icombi)%coefficient / 2)
1552         !                terms_out(icombi)%coefficient = coeff_ini
1553       endif
1554       do idisp=1,ndisp
1555         terms_out(icombi)%terms(iterm_of_term)%power_disp(idisp) = 2
1556       enddo !idisp
1557     enddo !iterm_of_term
1558   enddo !icombi
1559 
1560   !If term had strain we had to reinitialize it in the process
1561   !Refree memory
1562   !if(had_strain)
1563   call polynomial_coeff_free(term)
1564 
1565   ! Get high order combinations
1566   if(had_strain)then
1567     call opt_getHoTerms(terms_out(:ncombi),order_start,order_stop,ndisp,ncombi_order)
1568     call opt_getHoTerms(terms_out(ncombi+1:),order_start_str,order_stop_str,ndisp,ncombi_order_str)
1569     ncombi = ncombi_tot
1570   else
1571     call opt_getHoTerms(terms_out,order_start,order_stop,ndisp,ncombi_order)
1572   endif
1573   !DEALLOCATION
1574   ABI_FREE(ncombi_order)
1575   ABI_FREE(ncombi_order_str)
1576 
1577 end subroutine opt_getHOcrossdisp

m_opt_effpot/opt_getHOforterm [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_effpotbound

FUNCTION

 Compute possible high orders for a given anharmonic term.
 In the range of order_start,order_stop

INPUTS

 term<polynomial_coeff_type>:anharmonic term
 order_range(2):start and stop order desired by user

OUTPUT

 order_start:possible start order
 order_stop: possible stop order

SOURCE

821 subroutine opt_getHOforterm(term,order_range,order_start,order_stop)
822 
823   implicit none
824 
825   !Arguments ------------------------------------
826   !scalars
827   type(polynomial_coeff_type),intent(in) :: term
828   !arrays
829   integer,intent(in) :: order_range(2)
830   integer,intent(out) :: order_start, order_stop
831   !Logicals
832   !Strings
833   !Local variables ------------------------------
834   !scalars
835   integer :: idisp,ndisp,nstrain,nterm_of_term,power_tot
836   integer :: nbody_tot
837   !arrays
838   integer,allocatable :: powers(:)
839   !Logicals
840   !Strings
841   !*************************************************************************
842 
843   !Get/Initialize variables
844   ndisp = term%terms(1)%ndisp
845   nstrain = term%terms(1)%nstrain
846   nbody_tot = ndisp + nstrain
847   nterm_of_term = term%nterm
848 
849   ABI_MALLOC(powers,(nbody_tot))
850   powers(:ndisp) = term%terms(1)%power_disp
851   powers(ndisp+1:) = term%terms(1)%power_strain
852   power_tot = 0
853   !write(std_out,*) "powers in getHOforterm", powers
854 
855   !Get rid off odd displacements
856   ! XXX:  Should be simplified. The if /else is useless.
857   do idisp=1,nbody_tot
858     if(idisp <= ndisp .and. mod(powers(idisp),2) == 1)then
859       powers(idisp) = powers(idisp) + 1
860     else if(mod(powers(idisp),2) == 1)then
861       powers(idisp) = powers(idisp) + 1
862     endif
863   enddo !idisp
864   ! Count order
865   do idisp=1,nbody_tot
866     power_tot = power_tot + powers(idisp)
867   enddo
868   ! Get start and stop order for this term
869   ! If term doesn't fit in order range give back order_start = order_stop = 0
870   if(power_tot >= order_range(1) .and. power_tot <=order_range(2))then
871     order_start = power_tot
872     order_stop  = order_range(2)
873   elseif(power_tot < order_range(1))then
874     order_start = order_range(1)
875     order_stop  = order_range(2)
876   elseif(power_tot > order_range(2))then
877     order_start = 0
878     order_stop  = 0
879   endif
880 
881   ABI_FREE(powers)
882 
883 end subroutine opt_getHOforterm

m_opt_effpot/opt_getHOSingleDispTerms [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_getHOSingleDispTerms

FUNCTION

 For a given anharmonic term that might consits of product of
 terms find all even high order single displacement terms
 Example: Input term: x*y*z
          Input HO-range: 6 8
          Output terms: x^6,x^8,y^6,y^8,z^6,z^8
          Caution only atomic displacements are taken into account

INPUTS

 term_in<polynomial_coeff_type>: input anharmonic term
 crystal<type(crystal_t)>: all information about the crystal
 single_disp_terms<polynomial_coeff_out>: list of single disp terms at
                                          second order to select terms from
 power_disp(2): Start and stop power for HO terms
 comm: mpi communicator (at the moment only sequential tested)

OUTPUT

 terms_out<polynomial_coeff_out>: output high order even terms
 ncoeff: number of coefficients

SOURCE

1800 subroutine opt_getHOSingleDispTerms(term_in,terms_out,symbols,single_disp_terms,power_disp,ncoeff)
1801 
1802   implicit none
1803 
1804   !Arguments ------------------------------------
1805   !scalars
1806   integer,intent(out) :: ncoeff
1807   type(polynomial_coeff_type),intent(in) :: term_in
1808   type(polynomial_coeff_type),intent(in) :: single_disp_terms(:)
1809   type(polynomial_coeff_type),allocatable,intent(out) :: terms_out(:)
1810   !type(crystal_t),intent(inout) :: crystal
1811   !arrays
1812   integer, intent(in) :: power_disp(2)
1813   character(len=5),intent(in) :: symbols(:)
1814   !Logicals
1815   !Strings
1816   !Local variables ------------------------------
1817   !scalars
1818   integer :: ndisp,norder, nterm_of_term
1819   integer :: icoeff,iorder,idisp, iterm1,iterm2,iterm3
1820   real(dp) :: coeff_ini = 1
1821   !Strings
1822   character(len=200):: name
1823   !arrays
1824   type(polynomial_coeff_type),allocatable :: terms_out_tmp(:)
1825   !Logicals
1826   logical,allocatable :: found(:)
1827   !*************************************************************************
1828   !Get/Set Variables
1829   !Number of output terms
1830   ndisp = term_in%terms(1)%ndisp
1831   norder = abs(power_disp(2)-power_disp(1))/2 + 1
1832   ncoeff = norder * ndisp
1833   !Allocate output terms
1834   ABI_MALLOC(terms_out_tmp,(ncoeff))
1835 
1836   !find equivalent second order terms in list of single disp terms
1837   !for each displacement in input term
1838   !Transfer to output term and increase order
1839   icoeff = 0
1840   do idisp=1,ndisp
1841     do iterm1=1,size(single_disp_terms)
1842       do iterm2=1,single_disp_terms(iterm1)%nterm
1843         if(all(term_in%terms(1)%atindx(:,idisp) == single_disp_terms(iterm1)%terms(iterm2)%atindx(:,1)))then
1844           if(all(term_in%terms(1)%cell(:,:,idisp) == single_disp_terms(iterm1)%terms(iterm2)%cell(:,:,1)))then
1845             if(term_in%terms(1)%direction(idisp) == single_disp_terms(iterm1)%terms(iterm2)%direction(1))then
1846               do iorder=1,norder
1847                 icoeff = icoeff + 1
1848                 terms_out_tmp(icoeff) = single_disp_terms(iterm1)
1849                 nterm_of_term = single_disp_terms(iterm1)%nterm
1850                 !Change order of term
1851                 call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out_tmp(icoeff),&
1852                   &                                               single_disp_terms(iterm1)%terms(:),check=.true.)
1853 
1854                 do iterm3=1,nterm_of_term
1855                   terms_out_tmp(icoeff)%terms(iterm3)%power_disp = power_disp(1) + (iorder-1)*2
1856                 enddo !iterm3
1857               enddo !iorder
1858             endif
1859           endif
1860         endif
1861       enddo !iterm2
1862     enddo !iterm1
1863   enddo!idisp
1864   !Change Name
1865   do icoeff=1,ncoeff
1866     !   write(std_out,*) "DEBUG icoeff: ", icoeff
1867     !   write(std_out,*) "Term(",icoeff,"/",ncoeff,"): ", terms_out_tmp(icoeff)%name, "name before set name"
1868     !   write(std_out,*) "Term(",icoeff,"/",ncoeff,") nterm: ", terms_out_tmp(icoeff)%nterm
1869     call polynomial_coeff_getName(name,terms_out_tmp(icoeff),symbols,recompute=.TRUE.)
1870     call polynomial_coeff_SetName(name,terms_out_tmp(icoeff))
1871     !   write(*,*) "Term(",icoeff,"/",ncoeff,"): ", terms_out_tmp(icoeff)%name, "after set name"
1872   enddo
1873 
1874   !Check for doubles and delete them
1875   !First count irreducible terms
1876   ABI_MALLOC(found,(ncoeff))
1877   found = .FALSE.
1878   iterm3 = 0
1879   do iterm1=1,ncoeff
1880     do iterm2=iterm1+1,ncoeff
1881       if(terms_out_tmp(iterm1) == terms_out_tmp(iterm2) .and. .not. found(iterm2))then
1882         found(iterm2) = .TRUE.
1883         iterm3 = iterm3 + 1
1884       endif
1885     enddo
1886   enddo
1887   iterm3 = ncoeff - iterm3
1888   ABI_MALLOC(terms_out,(iterm3))
1889   !Second copy them
1890   iterm3 = 0
1891   do iterm1=1,ncoeff
1892     if(.not. found(iterm1))then
1893       iterm3 = iterm3 + 1
1894       !      terms_out(iterm3) = terms_out_tmp(iterm1)
1895       call polynomial_coeff_init(coeff_ini,terms_out_tmp(iterm1)%nterm,terms_out(iterm3),&
1896         &                                terms_out_tmp(iterm1)%terms,terms_out_tmp(iterm1)%name,check=.TRUE.)
1897     endif
1898   enddo
1899   !ABI_FREE(terms_out_tmp)
1900   ABI_FREE(found)
1901   call polynomial_coeff_list_free(terms_out_tmp)
1902   ncoeff = iterm3
1903   !TEST MS
1904   !  write(*,*) "behind call getNorder"
1905   !  write(*,*) "ncoeff_out: ", ncoeff_out
1906   !  do ii=1,ncoeff_out
1907   !     write(*,*) "Term(",ii,"/",ncoeff_out,"): ", terms(ii)%name
1908   !  enddo
1909   !TEST MS
1910 
1911   !!Check after reduction
1912   !do icoeff=1,ncoeff
1913   !   write(std_out,*) "DEBUG icoeff: ", icoeff
1914   !   write(*,*) "Term(",icoeff,"/",ncoeff,"): ", terms_out(icoeff)%name, "name before set name"
1915   !  call polynomial_coeff_getName(name,terms_out(icoeff),symbols,recompute=.TRUE.)
1916   !  call polynomial_coeff_SetName(name,terms_out(icoeff))
1917   !   write(*,*) "Term(",icoeff,"/",ncoeff,"): ", terms_out(icoeff)%name, "after set name"
1918   !enddo
1919 
1920 end subroutine opt_getHOSingleDispTerms

m_opt_effpot/opt_getHOstrain [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_getHOstrain

FUNCTION

 Get HO anharmnonic strain terms for bounding and add them to list
 of existing terms in effective potential

INPUTS

 eff_pot<effective_potential_type>: datatype with all the information
                                    about the effective potential
 power_strain(2): start and stop order for strain terms
 comm: mpi communicator (at the moment only sequential tested)

OUTPUT

 terms<polynomial_coeff_type>: list with original terms in effective
                               potential + HO even strain terms

SOURCE

1329 subroutine opt_getHOstrain(terms,ncombi,nterm_start,eff_pot,power_strain,comm)
1330 
1331   implicit none
1332 
1333   !Arguments ------------------------------------
1334   !scalars
1335   integer,intent(in) :: comm
1336   type(polynomial_coeff_type),allocatable,intent(inout) :: terms(:)
1337   type(effective_potential_type), intent(in) :: eff_pot
1338   integer,intent(in) :: power_strain(2)
1339   integer,intent(out) :: ncombi,nterm_start
1340   !arrays
1341   !Logicals
1342   !Strings
1343   !Local variables ------------------------------
1344   !scalars
1345   integer ::  nterm_tot_tmp
1346   integer :: i,ii
1347   real(dp) :: coeff_ini
1348   !reals
1349   type(crystal_t) :: crystal
1350   !arrays
1351   type(polynomial_coeff_type),allocatable :: strain_terms_tmp(:)
1352   !Logicals
1353   !Strings
1354   character(len=1000) :: message
1355   !*************************************************************************
1356   !Get variables
1357   crystal = eff_pot%crystal
1358   coeff_ini = 1000000
1359 
1360   write(message, '(a,(80a),a)' ) ch10,&
1361     &   ('_',ii=1,80),ch10
1362   call wrtout(ab_out,message,'COLL')
1363   call wrtout(std_out,message,'COLL')
1364   write(message,'(3a)' )ch10,&
1365     &    ' Chreate high order strain terms ',ch10
1366   call wrtout(ab_out,message,'COLL')
1367   call wrtout(std_out,message,'COLL')
1368 
1369   !1406 get count of high order even anharmonic strain terms and the strain terms itself
1370   call polynomial_coeff_getEvenAnhaStrain(strain_terms_tmp,crystal,ncombi,power_strain,comm)
1371   ! Allocate my_coeffs with ncombi free space to work with
1372 
1373   nterm_start = eff_pot%anharmonics_terms%ncoeff
1374   nterm_tot_tmp = eff_pot%anharmonics_terms%ncoeff + ncombi
1375   ABI_MALLOC(terms,(nterm_tot_tmp))
1376   do i=1,nterm_tot_tmp
1377     if(i<=nterm_start)then
1378       call polynomial_coeff_init(coeff_ini,eff_pot%anharmonics_terms%coefficients(i)%nterm,terms(i),&
1379         & eff_pot%anharmonics_terms%coefficients(i)%terms,eff_pot%anharmonics_terms%coefficients(i)%name,check=.TRUE.)
1380     else
1381       call polynomial_coeff_init(coeff_ini,strain_terms_tmp(i-nterm_start)%nterm,terms(i),&
1382         &         strain_terms_tmp(i-nterm_start)%terms,strain_terms_tmp(i-nterm_start)%name,check=.TRUE.)
1383     endif
1384   enddo
1385 
1386   call polynomial_coeff_list_free(strain_terms_tmp)
1387 
1388 end subroutine opt_getHOstrain

m_opt_effpot/opt_getHoTerms [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_geHoTerms

FUNCTION

 For a term give all possible high order terms
 Attention order_start, order_stop, ncombi and
 ncombi_order have to be calculated before!

INPUTS

 eff_pot: existing effective potential
 order: order for which bounding terms are generated

OUTPUT

 eff_pot new effective potential

SOURCE

1006 subroutine opt_getHoTerms(terms,order_start,order_stop,ndisp,ncombi_order)
1007 
1008   implicit none
1009 
1010   !Arguments ------------------------------------
1011   !scalars
1012   integer,intent(in) :: ndisp
1013   integer,intent(in) :: order_start, order_stop
1014   !arrays
1015   integer,intent(in) :: ncombi_order(:)
1016   !Logicals
1017   type(polynomial_coeff_type),intent(inout) :: terms(:)
1018   !Strings
1019   !Local variables ------------------------------
1020   !scalars
1021   integer :: i,icombi,icombi2,icombi_start,icombi_stop,idisp,nterm_of_term
1022   integer :: order,iterm_of_term,jdisp,power_tot
1023   integer :: jdisp1,jdisp2,sec,nstrain,nbody_tot
1024   real(sp) :: to_divide,divider1,divider2,divided
1025   !arrays
1026   !integer
1027   !Logicals
1028   logical :: equal_term_done
1029   !Strings
1030   character(len=1000) :: message
1031   !*************************************************************************
1032   !Get Variables
1033   nterm_of_term = terms(1)%nterm
1034   nstrain = terms(1)%terms(1)%nstrain
1035   nbody_tot = ndisp + nstrain
1036 
1037   ! Create all possible combinaions for the specified orders
1038   ! If anybody has ever, ever to read and understand this I'm terribly sorry
1039   ! ---this will be quite hell---
1040   power_tot = 0
1041   icombi_start = 1
1042   i = 0
1043   !write(*,*) "what is ncombi?", ncombi
1044   !write(*,*) "what is ncmobi_order", ncombi_order
1045 
1046   !write(*,*) "order_start", order_start
1047   !write(*,*) "order_stop", order_stop
1048   order = order_start
1049   ! TODO work here icombi start and order counting does not work yet.
1050   do order=order_start,order_stop,2
1051     !write(std_out,*) 'Was I now here?!(order-loop)'
1052     i = i + 1
1053     icombi_stop = icombi_start + ncombi_order(i) - 1
1054     equal_term_done = .FALSE.
1055     !write(std_out,*) 'order', order
1056     !write(std_out,*) 'icombi_start', icombi_start
1057     !write(std_out,*) 'icombi_stop', icombi_stop
1058     icombi=icombi_start
1059     do while (icombi<=icombi_stop)
1060       power_tot = 0
1061       do idisp=1,nbody_tot
1062         !write(*,*) "what is icombi here?", icombi
1063         !write(*,*) "what is icombi_stop here?", icombi_stop
1064         if(idisp<=ndisp)then
1065           power_tot = power_tot + terms(icombi)%terms(1)%power_disp(idisp)
1066         else
1067           power_tot = power_tot + terms(icombi)%terms(1)%power_strain(idisp-ndisp)
1068         endif
1069       enddo
1070       ! Probably have to increase order at same time
1071       ! If the term already has the right order we cycle
1072       ! we increase icombi_start and icombi to go to the next term in the array
1073       if(power_tot == order)then
1074         icombi_start = icombi_start + 1
1075         icombi = icombi + 1
1076         !write(*,*) 'icombi-start in if', icombi_start
1077         cycle
1078         ! If the term is not already in the right order, we manipulate it until
1079         ! it is
1080       else
1081         jdisp1 = 1
1082         sec = 1
1083         !write(*,*) 'what is ndisp actually', ndisp
1084         ! Treat single permutations from the bottom of the order
1085         ! so start from ^2^2^2 and get ^6^2^2,^2^6^2, and ^2^2^6 f.E.
1086         ! do loop over displacements
1087         do while(jdisp1<=nbody_tot .and. sec < 100)
1088           !write(*,*) "what is jdisp1 here?", jdisp1
1089           !write(*,*) "what is icombi here?", icombi
1090           !write(*,*) "what is icombi_sotp?", icombi_stop
1091           ! Increase the order of the displacements
1092           do iterm_of_term=1,nterm_of_term
1093             if(jdisp1 <= ndisp)then
1094               terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) =&
1095                 &                            terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) + 2
1096             else
1097               terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) =&
1098                 &                            terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) + 2
1099 
1100             endif
1101           enddo
1102           ! Check total order of term after increase
1103           power_tot=0
1104           do jdisp2=1,nbody_tot
1105             if(jdisp2 <= ndisp)then
1106               power_tot = power_tot + terms(icombi)%terms(1)%power_disp(jdisp2)
1107             else
1108               power_tot = power_tot + terms(icombi)%terms(1)%power_strain(jdisp2-ndisp)
1109             endif
1110           enddo
1111           ! If the term is at the right order do next displacement
1112           ! increase icombi and icombi_start to go to next term in array
1113           if(power_tot == order)then
1114             icombi = icombi + 1
1115             icombi_start = icombi_start +1
1116             !write(*,*) 'what is icombi_start here', icombi_start
1117             jdisp1 = jdisp1 + 1
1118             !write(*,*) 'and what is jdisp1?', jdisp1
1119 
1120           endif
1121         enddo!jdisp1
1122         !Treat permutations in terms ndisp > 2 and order >= 10
1123         !Start f.E. from ^4^4^4 and get ^4^2^4, ^2^4^4,^4^4^2
1124         if(icombi_stop - icombi > 1 .and. nbody_tot >2 )then
1125           do icombi2=icombi,icombi+nbody_tot-1
1126             do jdisp=1,nbody_tot
1127               do iterm_of_term=1,nterm_of_term
1128                 if(jdisp <= ndisp)then
1129                   terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) = &
1130                     &                                    terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) +2
1131                   !write(*,*) "What's the power now?", terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp)
1132                 else
1133                   terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = &
1134                     &                                    terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) +2
1135                 endif
1136               enddo
1137             enddo !jdisp
1138           enddo
1139           jdisp1 = 1
1140           do while(jdisp1<=nbody_tot .and. sec < 100)
1141             sec = sec + 1
1142             !write(*,*) "how often did I go here, hu ?"
1143             !write(*,*) "I did at least one displacement"
1144             do iterm_of_term=1,nterm_of_term
1145               if(jdisp1 <= ndisp)then
1146                 terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) =&
1147                   &                                terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) + 2
1148               else
1149                 terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) =&
1150                   &                                terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) + 2
1151 
1152               endif
1153             enddo
1154             power_tot=0
1155             do jdisp2=1,nbody_tot
1156               if(jdisp2 <= ndisp)then
1157                 power_tot = power_tot + terms(icombi)%terms(1)%power_disp(jdisp2)
1158               else
1159                 power_tot = power_tot + terms(icombi)%terms(1)%power_strain(jdisp2-ndisp)
1160               endif
1161             enddo
1162             if(power_tot == order)then
1163               icombi = icombi + 1
1164               icombi_start = icombi_start +1
1165               !write(*,*) 'what is icombi_start here', icombi_start
1166               jdisp1 = jdisp1 + 1
1167               !write(*,*) 'and what is jdisp1?', jdisp1
1168             endif
1169           enddo!jdisp1
1170           ! Message to Output
1171           if(sec>100)then
1172             write(message,'(4a)' )ch10,&
1173               &                     "You're stuck in a while loop.",ch10,&
1174               &                     'Action: Contact Abinit Group',ch10
1175             ABI_ERROR(message)
1176           endif
1177         endif! (icombi_stop - icombi)
1178         !write(*,*) 'I was here!'
1179         to_divide = real(order)
1180         divider1 = real(nbody_tot)
1181         divided = real(to_divide/divider1)
1182         divider2 = real(2)
1183         !write(*,*) 'divided', divided, 'divider2', divider2
1184         !Treat terms with even power f.E. ^2^2^2^2, ^4^4 etc...
1185         if(mod(divided,divider2) == 0 .and. .not. equal_term_done .and. nbody_tot > 1)then
1186           !write(*,*) "Sometimes I should be here sometimes I shouldn't"
1187           do jdisp=1,nbody_tot
1188             do iterm_of_term=1,nterm_of_term
1189               if(jdisp<=ndisp)then
1190                 terms(icombi)%terms(iterm_of_term)%power_disp(jdisp) = order/ndisp
1191               else
1192                 terms(icombi)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = order/ndisp
1193               endif
1194             enddo
1195           enddo !jdisp
1196           if(order < order_stop)then
1197             do icombi2=icombi+1,icombi+nbody_tot
1198               do jdisp=1,nbody_tot
1199                 do iterm_of_term=1,nterm_of_term
1200                   if(jdisp<=ndisp)then
1201                     terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) = order/ndisp
1202                   else
1203                     terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = order/ndisp
1204                   endif
1205                 enddo
1206               enddo !jdisp
1207             enddo
1208           endif
1209           equal_term_done = .TRUE.
1210           icombi = icombi + 1
1211           icombi_start = icombi_start +1
1212         endif ! equal term if
1213       endif ! power_tot == order
1214     enddo !icombination
1215   enddo !order
1216 
1217 end subroutine opt_getHoTerms

m_opt_effpot/opt_getSingleDispTerms [ Functions ]

[ Top ] [ m_opt_effpot ] [ Functions ]

NAME

 opt_getSingleDispTerms

FUNCTION

 Get polynomial terms (<polynomial_coeff_type>) with single displacements
 at second order inside a given range defined by the supercell size

INPUTS

 sc_size(3): supercell size
 crystal<type(crystal_t)>: all information about the crystal
 comm: mpi communicator (at the moment only sequential tested)

OUTPUT

 terms<polynomial_coeff_type>: list single displacement polynomial_coeffs

SOURCE

1599 subroutine opt_getSingleDispTerms(terms,crystal, sc_size,comm)
1600 
1601   implicit none
1602 
1603   !Arguments ------------------------------------
1604   !scalars
1605   integer,intent(in) :: comm
1606   type(polynomial_coeff_type),allocatable,intent(inout) :: terms(:)
1607   type(crystal_t),intent(inout) :: crystal
1608   real(dp) ::  cutoff
1609   !arrays
1610   integer :: sc_size(3)
1611 
1612   !Logicals
1613   !Strings
1614   !Local variables ------------------------------
1615   !scalars
1616   integer :: natom,nsym,nrpt,ncoeff_sym,nstr_sym
1617   integer :: ncoeff,ncoeff_out,power_strph,option_GN,option
1618   integer :: nterms_out,nterm1,iterm1,iterm2,ind,iatom,i
1619   integer :: ncopy
1620   integer :: ii !,ia,ib,r1,r2,r3
1621   !integer :: irpt,irpt_ref
1622   integer :: master,nproc,my_rank
1623   !arrays
1624   integer :: power_disp(2)
1625   integer,allocatable :: cell(:,:)
1626   integer,allocatable :: list_symcoeff(:,:,:),list_symstr(:,:,:)
1627   logical,allocatable :: terms_to_copy(:)
1628   type(polynomial_coeff_type),allocatable :: terms_tmp(:),terms_tmp2(:)
1629   !type(polynomial_coeff_type),allocatable :: terms(:)
1630   !real(dp),allocatable :: xcart(:,:),xred(:,:),rpt(:,:)
1631   real(dp) :: rprimd(3,3),range_ifc(3)
1632   real(dp),allocatable :: dist(:,:,:,:)
1633   character(len=5),allocatable :: symbols(:)
1634   !Logicals
1635   logical :: iam_master,need_verbose
1636   !Strings
1637   character(len=1000) :: message
1638   !*************************************************************************
1639 
1640   option = 2
1641 
1642   if(option == 1)then
1643     !MPI variables
1644     master = 0
1645     nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1646     iam_master = (my_rank == master)
1647 
1648     !Set/Get other variables
1649     !natom  = crystal%natom
1650     !nsym   = crystal%nsym
1651     rprimd = crystal%rprimd
1652     need_verbose = .TRUE.
1653 
1654 
1655     call prepare_for_getList(crystal,sc_size, dist, cell, natom, nsym, nrpt, range_ifc , symbols)
1656 
1657     ! FIXME: this is dangerous!
1658     ! It assumes that the structure is cubic in a usual axis setting.
1659     cutoff = rprimd(1,1)
1660 
1661     if(need_verbose)then
1662       write(message,'(1a)')' Generation of the list of all the possible coefficients'
1663       call wrtout(std_out,message,'COLL')
1664     end if
1665     call polynomial_coeff_getList(cell,crystal,dist,list_symcoeff,list_symstr,&
1666       &                              natom,nstr_sym,ncoeff_sym,nrpt,range_ifc,cutoff,sc_size=sc_size)
1667 
1668     ABI_FREE(dist)
1669     !ABI_FREE(rpt)
1670 
1671     !write(*,*) "polynomial_getList worked"
1672 
1673     !Get Order1 term s
1674     !Check difference between ncoeff_out, ncoeff
1675     call polynomial_coeff_getOrder1(cell,terms,list_symcoeff,natom,nterms_out,ncoeff_sym,nrpt,nsym,symbols)
1676 
1677     !do ii=1,nterms_out
1678     !   write(*,*) "Term(",ii,"/",nterms_out,"): ", terms(ii)%name
1679     !enddo
1680 
1681   elseif(option == 2)then
1682     !Get/set variables
1683     ! FIXME: hexu: check these values of 2. Why are they are hard coded here.
1684     ! Does this mean we only generate high-order terms in 2x2x2 cell?
1685     power_disp = (/2,2/)
1686     power_strph = zero
1687     option_GN = 0
1688     sc_size = (/2,2,2/)
1689     cutoff = 0
1690     natom  = crystal%natom
1691     ! XXX: hexu: why cutoff = sum of axis lengths?
1692     do ii=1,3
1693       cutoff = cutoff + sqrt(crystal%rprimd(ii,1)**2 + &
1694         &                            crystal%rprimd(ii,2)**2 + &
1695         &                            crystal%rprimd(ii,3)**2)
1696     enddo
1697 
1698 
1699     !do iatom=1,3
1700     do iatom=1,natom !Subhadeep
1701     ! TODO: to be validated.
1702     !do iatom=1,crystal%nirredat
1703       call polynomial_coeff_getNorder(terms_tmp,crystal,cutoff,ncoeff,ncoeff_out,power_disp,&
1704         &                               power_strph,option_GN,sc_size,comm,anharmstr=.false.,spcoupling=.false.,&
1705         &                               only_odd_power=.false.,only_even_power=.true.,verbose=.false.,&
1706         &                               compute_symmetric=.false.,fit_iatom=iatom)
1707       !TEST MS
1708       !  write(std_out,*) "behind call getNorder"
1709       !  write(std_out,*) "ncoeff_out: ", ncoeff_out
1710       !  do ii=1,ncoeff_out
1711       !     write(*,*) "Term(",ii,"/",ncoeff_out,"): ", terms_tmp(ii)%name
1712       !  enddo
1713       !TEST MS
1714       if(iatom == 1)then
1715         ABI_MALLOC(terms,(size(terms_tmp)))
1716         call coeffs_list_copy(terms,terms_tmp)
1717       else
1718         ABI_MALLOC(terms_to_copy,(size(terms_tmp)))
1719         ! note: when iatom>1, terms is already initialized.
1720         nterm1 = size(terms)
1721         ABI_MALLOC(terms_tmp2,(nterm1))
1722         terms_tmp2 = terms
1723         terms_to_copy = .TRUE.
1724         do iterm1=1,size(terms_tmp)
1725           do iterm2=1,size(terms)
1726             if(terms_tmp(iterm1) == terms(iterm2))then
1727               terms_to_copy(iterm1) = .FALSE.
1728               exit
1729             endif
1730           enddo!iterm1
1731         enddo!iterm2
1732         ncopy = count(terms_to_copy)
1733         !         write(std_out,*) "ncopy", ncopy
1734         !         write(std_out,*) "behind iatom>1"
1735         !
1736         !         write(std_out,*) "ncoeff_out: ", size(terms_tmp2)
1737         !         do ii=1,size(terms_tmp2)
1738         !           write(*,*) "Term(",ii,"/",size(terms_tmp2),"): ", terms_tmp2(ii)%name
1739         !         enddo
1740         call polynomial_coeff_list_free(terms)
1741         ABI_MALLOC(terms,(nterm1+ncopy))
1742         call coeffs_list_copy(terms(:nterm1),terms_tmp2)
1743         ind = 0
1744         do i =1,size(terms_tmp)
1745           if(terms_to_copy(i))then
1746             ind=ind+1
1747             call polynomial_coeff_init(terms_tmp(i)%coefficient,terms_tmp(i)%nterm,terms(nterm1+ind),terms_tmp(i)%terms,&
1748               &                              terms_tmp(i)%name,check=.TRUE.)
1749           endif
1750         enddo!i=1,nterm1+ncopy
1751         call polynomial_coeff_list_free(terms_tmp)
1752         call polynomial_coeff_list_free(terms_tmp2)
1753         ABI_FREE(terms_to_copy)
1754       endif!iatom==1
1755     enddo !iatom=1,natom
1756     !      call polynomial_coeff_getNorder(terms,crystal,cutoff,ncoeff,ncoeff_out,power_disp,&
1757     !&                               power_strph,option_GN,sc_size,comm,anharmstr=.false.,spcoupling=.false.,&
1758     !&                               only_odd_power=.false.,only_even_power=.true.,verbose=.false.,&
1759     !&                               compute_symmetric=.false.)
1760 
1761   endif !option
1762   !TEST MS
1763   !  write(std_out,*) "behind call getNorder"
1764   !  write(std_out,*) "ncoeff_out: ", size(terms)
1765   !  do ii=1,size(terms)
1766   !     write(*,*) "Term(",ii,"/",size(terms),"): ", terms(ii)%name
1767   !  enddo
1768   !TEST MS
1769 
1770 end subroutine opt_getSingleDispTerms