Branch data Line data Source code
1 : :
2 : : !!****m* ABINIT/m_opt_effpot
3 : : !!
4 : : !! NAME
5 : : !! m_opt_effpot
6 : : !!
7 : : !! FUNCTION
8 : : !!
9 : : !!
10 : : !!
11 : : !! COPYRIGHT
12 : : !! Copyright (C) 2010-2026 ABINIT group (AM)
13 : : !! This file is distributed under the terms of the
14 : : !! GNU General Public Licence, see ~abinit/COPYING
15 : : !! or http://www.gnu.org/copyleft/gpl.txt .
16 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
17 : : !!
18 : : !! SOURCE
19 : :
20 : :
21 : :
22 : : #if defined HAVE_CONFIG_H
23 : : #include "config.h"
24 : : #endif
25 : :
26 : : #include "abi_common.h"
27 : : !#include "trace.h"
28 : :
29 : :
30 : : module m_opt_effpot
31 : :
32 : : use defs_basis
33 : : use defs_datatypes
34 : : use defs_abitypes
35 : : use m_errors
36 : : use m_abicore
37 : : use m_xmpi
38 : : use m_effective_potential
39 : : use m_effective_potential_file, only : effective_potential_file_mapHistToRef
40 : : use m_fit_data
41 : : use m_fit_polynomial_coeff
42 : : use m_polynomial_coeff
43 : : use m_polynomial_term
44 : : use m_crystal,only : symbols_crystal
45 : :
46 : : implicit none
47 : :
48 : : public :: opt_effpot
49 : : public :: opt_effpotbound
50 : : public :: opt_getHOforterm
51 : : public :: opt_getCombisforterm
52 : : public :: opt_getHoTerms
53 : : public :: opt_getHOstrain
54 : : public :: opt_getHOcrossdisp
55 : : public :: opt_filterdisp
56 : : public :: opt_getSingleDispTerms
57 : : public :: opt_getHOSingleDispTerms
58 : : private :: opt_boundcoeff
59 : : private :: check_to_skip
60 : : !!****
61 : : CONTAINS
62 : :
63 : : !!****f* m_opt_effpot/opt_effpot
64 : : !!
65 : : !! NAME
66 : : !! opt_effpot
67 : : !!
68 : : !! FUNCTION
69 : : !! Optimize Effective Potential by fitting the value of certain
70 : : !! coefficients while keeping the values of the others
71 : : !!
72 : : !! INPUTS
73 : : !! eff_pot<type(effective_potential)> = effective potential
74 : : !!
75 : : !! opt_coeff(opt_ncoeff) = list of terms whose coefficients are to be
76 : : !! optimized
77 : : !!
78 : : !! hist<type(abihist)> = Training set Data(or snapshot of DFT)
79 : : !! comm = MPI communicator
80 : : !!
81 : : !! OUTPUT
82 : : !! eff_pot<type(effective_potential)> = effective potential datatype with new fitted coefficients
83 : : !!
84 : : !! SOURCE
85 : :
86 : 1 : subroutine opt_effpot(eff_pot,opt_ncoeff,opt_coeff,hist,opt_on,opt_factors,comm, fit_weight_T, print_anh)
87 : :
88 : : !Arguments ------------------------------------
89 : : !scalars
90 : : integer,intent(in) :: comm,opt_ncoeff
91 : : type(effective_potential_type),intent(inout) :: eff_pot
92 : : type(abihist),intent(inout) :: hist
93 : : !arrays
94 : : integer,intent(in) :: opt_coeff(opt_ncoeff)
95 : : real(dp),intent(in) :: opt_factors(3)
96 : : real(dp), intent(in):: fit_weight_T
97 : : !Logicals
98 : : logical,intent(in) :: opt_on(3)
99 : : logical,optional,intent(in) :: print_anh
100 : : !Strings
101 : : !Local variables ------------------------------
102 : : !scalars
103 : : integer :: ii, info,natom_sc,ntime,unit_anh1,unit_anh2
104 : : integer :: master,nproc,my_rank
105 : : real(dp) :: factor,mse,msef,mses
106 : : real(dp),parameter :: HaBohr_eVAng = Ha_eV /Bohr_Ang
107 : : !arrays
108 : : integer :: sc_size(3)
109 : 2 : integer :: coeff_inds(opt_ncoeff)
110 : 1 : type(fit_data_type) :: fit_data
111 [ + + + + : 11 : type(polynomial_coeff_type) :: my_coeffs(opt_ncoeff)
+ + + - -
- - - - -
- - - - -
- - - -
- ]
112 : 2 : real(dp) :: coeff_values(opt_ncoeff), coeff_init_values(opt_ncoeff)
113 : 1 : real(dp), allocatable :: energy_coeffs(:,:),fcart_coeffs(:,:,:,:)
114 : 1 : real(dp), allocatable :: strten_coeffs(:,:,:)
115 : 1 : real(dp), allocatable :: my_weights(:)
116 : : !Logicals
117 : : logical :: need_print_anh,file_opened,iam_master
118 : : !Strings
119 : : character(len=1000) :: message
120 : : character(len=1000) :: frmt
121 : : character(len=fnlen) :: fn_bf='before_opt_diff', fn_af='after_opt_diff'
122 : : ! *************************************************************************
123 : : !MPI
124 : 1 : master = 0
125 : 1 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
126 : : iam_master = (my_rank == master)
127 : :
128 : : !Setting/Initializing Variables
129 : 1 : ntime = hist%mxhist
130 : 1 : natom_sc = size(hist%xred,2)
131 : 1 : factor = 1._dp/natom_sc
132 : 1 : need_print_anh =.False.
133 : :
134 : 1 : call get_weight_from_hist(hist, fit_weight_T, ntime, natom_sc, my_weights, comm)
135 : :
136 : :
137 [ - + ]: 1 : if(present(print_anh)) then
138 [ + - ]: 1 : if(print_anh) need_print_anh=.True.
139 : : end if
140 : : !if the number of atoms in reference supercell into effpot is not correct,
141 : : !wrt to the number of atom in the hist, we set map the hist and set the good supercell
142 [ - + ]: 1 : if (natom_sc /= eff_pot%supercell%natom) then
143 : 0 : call effective_potential_file_mapHistToRef(eff_pot,hist,comm,verbose=.TRUE.)
144 : : end if
145 : :
146 : : !we get the size of the supercell in the hist file
147 : : ! This is only valid for diagonal sc_size.
148 : : ! F08: sc_size(:) = int(anint( norm2(eff_pot%supercell%rprimd, dim=2) / &
149 : : ! & norm2(eff_pot%crystal%rprimd, dim=2) ))
150 [ + + ]: 4 : do ii=1,3
151 : : sc_size(ii) = int(anint(sqrt(eff_pot%supercell%rprimd(ii,1)**2+&
152 : : & eff_pot%supercell%rprimd(ii,2)**2+&
153 : : & eff_pot%supercell%rprimd(ii,3)**2) / &
154 : : & sqrt(eff_pot%crystal%rprimd(ii,1)**2+&
155 : : & eff_pot%crystal%rprimd(ii,2)**2+&
156 : 4 : & eff_pot%crystal%rprimd(ii,3)**2)))
157 : : end do
158 : :
159 : :
160 : : !Before the fit, compute constants with fit_data_compute.
161 : : !Compute the strain of each configuration.
162 : : !Compute the displacmeent of each configuration.
163 : : !Compute the variation of the displacement due to strain of each configuration.
164 : : !Compute fixed forces and stresse and get the standard deviation.
165 : : !Compute Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
166 : 1 : call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
167 : :
168 : :
169 [ - + ]: 1 : if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
170 : 0 : & fn_bf,eff_pot%anharmonics_terms)
171 : :
172 : : !Before deleting coefficients calculate MSD of initial model
173 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
174 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
175 : 1 : & compute_anharmonic=.TRUE.,print_file=.TRUE.,filename=fn_bf)
176 : :
177 : :
178 : : ! Print the standard devition of initial model
179 : 1 : write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
180 : 1 : & ' Mean Standard Deviation values of the effective-potential',ch10,&
181 : 1 : & ' with respect to the training-set before optimization (meV^2/atm):',&
182 : 1 : & ch10,' Energy : ',&
183 : 1 : & mse* (Ha_EV*1000)**2 *factor ,ch10,&
184 : 1 : & ' Goal function values of the effective.potential',ch10,&
185 : 1 : & ' with respect to the test-set (eV^2/A^2):',ch10,&
186 : 1 : & ' Forces+Stresses : ',&
187 : 1 : & (msef+mses)*(HaBohr_eVAng)**2,ch10,&
188 : 1 : & ' Forces : ',&
189 : 1 : & msef*(HaBohr_eVAng)**2,ch10,&
190 : 1 : & ' Stresses : ',&
191 : 2 : & mses*(HaBohr_eVAng)**2,ch10
192 : 1 : call wrtout(ab_out,message,'COLL')
193 : 1 : call wrtout(std_out,message,'COLL')
194 : :
195 : :
196 : : ! Write terms to my_coeffs(ii) and zero them in eff_pot
197 [ + + ]: 3 : do ii=1,opt_ncoeff
198 : : !Store indices for later
199 : 2 : coeff_inds(ii) = ii
200 : : !Initialize coefficients for optimizing
201 : : call polynomial_coeff_init(coeff_values(ii),eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%nterm,&
202 : : & my_coeffs(ii), eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%terms, &
203 : 2 : & check=.TRUE.)
204 : :
205 : : !DMSG(my_coeffs(ii)%debug_str)
206 : :
207 : : !Store initial values of coefficients
208 : 2 : coeff_init_values(ii) = eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient
209 : : !Put them temporarely to zero
210 : 3 : eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = zero
211 : : end do
212 : :
213 : : !Before the fit, compute constants with fit_data_compute.
214 : : !And coefficients to be optimized put to zero
215 : : !Conpute the strain of each configuration.
216 : : !Compute the displacmeent of each configuration.
217 : : !Compute the variation of the displacement due to strain of each configuration.
218 : : !Compute fixed forces and stresse and get the standard deviation.
219 : : !Compute Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
220 : 1 : call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.TRUE.)
221 : :
222 : : !After deleting coefficients calculate MSD
223 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
224 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
225 : 1 : & compute_anharmonic=.TRUE.)
226 : :
227 : :
228 : : ! Print the standard deviation after deleting
229 : 1 : write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
230 : 1 : & ' Mean Standard Deviation values of the effective-potential',ch10,&
231 : 1 : & ' with respect to the training-set after deleting selected terms (meV^2/atm):',&
232 : 1 : & ch10,' Energy : ',&
233 : 1 : & mse* (Ha_EV*1000)**2 *factor ,ch10,&
234 : 1 : & ' Goal function values of the effective.potential',ch10,&
235 : 1 : & ' with respect to the test-set (eV^2/A^2):',ch10,&
236 : 1 : & ' Forces+Stresses : ',&
237 : 1 : & (msef+mses)*(HaBohr_eVAng)**2,ch10,&
238 : 1 : & ' Forces : ',&
239 : 1 : & msef*(HaBohr_eVAng)**2,ch10,&
240 : 1 : & ' Stresses : ',&
241 : 2 : & mses*(HaBohr_eVAng)**2,ch10
242 : 1 : call wrtout(ab_out,message,'COLL')
243 : 1 : call wrtout(std_out,message,'COLL')
244 : :
245 : :
246 : :
247 : : ! Allocate necessary arrays for the fit-data
248 [ - + + - : 4 : ABI_MALLOC(energy_coeffs,(opt_ncoeff,ntime))
- + + - +
- + - - +
- + ]
249 [ - + + - : 5 : ABI_MALLOC(fcart_coeffs,(3,natom_sc,opt_ncoeff,ntime))
- + + - -
+ + - + -
+ - - + -
+ ]
250 [ - + + - : 4 : ABI_MALLOC(strten_coeffs,(6,ntime,opt_ncoeff))
- + + - +
- + - - +
- + ]
251 : : ! Calculate forces and stresses per coefficient, which are to be optimized
252 : : call fit_polynomial_coeff_getFS(my_coeffs,fit_data%training_set%du_delta,&
253 : : & fit_data%training_set%displacement,&
254 : : & energy_coeffs,fcart_coeffs,natom_sc,eff_pot%crystal%natom,&
255 : : & opt_ncoeff,ntime,sc_size,fit_data%training_set%strain,&
256 : 1 : & strten_coeffs,fit_data%training_set%ucvol,coeff_inds,opt_ncoeff)
257 : :
258 : :
259 : : ! call the fit process routine
260 : : ! This routine solves the linear system proposed
261 : : ! by C.Escorihuela-Sayalero see PRB95,094115(2017) [[cite:Escorihuela-Sayalero2017]]
262 : : call fit_polynomial_coeff_solve(coeff_values(1:opt_ncoeff),fcart_coeffs,fit_data%fcart_diff,&
263 : : & energy_coeffs,fit_data%energy_diff,info,&
264 : : & coeff_inds,natom_sc,opt_ncoeff,opt_ncoeff,ntime,&
265 : : & strten_coeffs,fit_data%strten_diff,&
266 : : & fit_data%training_set%sqomega,opt_on,opt_factors, &
267 : 1 : & weights=my_weights)
268 [ + - - + : 1 : if (info /= 0 .and. all(coeff_values < tol16))then
- + - - ]
269 : 0 : write(frmt,*) opt_ncoeff
270 : 0 : write(message, '(2a,'//ADJUSTR(frmt)//'I4,8a)' ) ch10,&
271 : 0 : & ' The attempt to optimize the terms: ', opt_coeff ,ch10,&
272 : 0 : & ' , returned a singular solution', ch10,&
273 : 0 : & ' The terms could not be optimized ',ch10,&
274 : 0 : & ' and the effective potential has not been altered.', ch10,&
275 : 0 : & ' Action: Change training set or coefficients to be optimized.'
276 : 0 : ABI_WARNING(message)
277 [ # # ]: 0 : do ii=1,opt_ncoeff
278 : 0 : eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = coeff_init_values(ii)
279 : 0 : call polynomial_coeff_free(my_coeffs(ii))
280 : : end do
281 : : else
282 : : ! Transfer new fitted values to coefficients and write them into effective potential
283 : : ! Deallcoate temporary coefficients my_coeffs
284 [ + + ]: 3 : do ii=1,opt_ncoeff
285 : 2 : eff_pot%anharmonics_terms%coefficients(opt_coeff(ii))%coefficient = coeff_values(ii)
286 : 3 : call polynomial_coeff_free(my_coeffs(ii))
287 : : end do
288 : : !Recalculate MSD of Final Model
289 : :
290 : : !Conpute the strain of each configuration.
291 : : !Compute the displacmeent of each configuration.
292 : : !Compute the variation of the displacement due to strain of each configuration.
293 : : !Compute fixed forces and stresse and get the standard deviation.
294 : : !Compute Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
295 : 1 : call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.TRUE.)
296 : :
297 : :
298 [ - + ]: 1 : if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
299 : 0 : & fn_af,eff_pot%anharmonics_terms)
300 : :
301 : : !After optimization of coefficients opt_coeff recalculate MSD
302 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
303 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
304 : 1 : & compute_anharmonic=.TRUE.,print_file=.TRUE.,filename=fn_af)
305 : :
306 : :
307 : : ! Print the standard deviation after optimization
308 : 1 : write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
309 : 1 : & ' Mean Standard Deviation values of the effective-potential',ch10,&
310 : 1 : & ' with respect to the training-set after optimizing selected terms (meV^2/atm):',&
311 : 1 : & ch10,' Energy : ',&
312 : 1 : & mse* (Ha_EV*1000)**2 *factor ,ch10,&
313 : 1 : & ' Goal function values of the effective.potential',ch10,&
314 : 1 : & ' with respect to the test-set (eV^2/A^2):',ch10,&
315 : 1 : & ' Forces+Stresses : ',&
316 : 1 : & (msef+mses)*(HaBohr_eVAng)**2,ch10,&
317 : 1 : & ' Forces : ',&
318 : 1 : & msef*(HaBohr_eVAng)**2,ch10,&
319 : 1 : & ' Stresses : ',&
320 : 2 : & mses*(HaBohr_eVAng)**2,ch10
321 : 1 : call wrtout(ab_out,message,'COLL')
322 : 1 : call wrtout(std_out,message,'COLL')
323 : : end if
324 : :
325 : : !Deallocation of fitting variables
326 [ + - ]: 1 : ABI_SFREE(energy_coeffs)
327 [ + - ]: 1 : ABI_SFREE(fcart_coeffs)
328 [ + - ]: 1 : ABI_SFREE(strten_coeffs)
329 [ + - ]: 1 : ABI_SFREE(my_weights)
330 : :
331 [ - + ]: 1 : if(need_print_anh)then
332 : 0 : INQUIRE(FILE='before_opt_diff_anharmonic_terms_energy.dat',OPENED=file_opened,number=unit_anh1)
333 [ # # ]: 0 : if(file_opened) close(unit_anh1)
334 : 0 : INQUIRE(FILE='after_opt_diff_anharmonic_terms_energy.dat',OPENED=file_opened,number=unit_anh2)
335 [ # # ]: 0 : if(file_opened) close(unit_anh2)
336 : : end if
337 : : ! Deallocate and delete the fit-date
338 : 1 : call fit_data_free(fit_data)
339 [ - + - + : 7 : end subroutine opt_effpot
- + - + -
+ - + - +
- + - + ]
340 : : !!***
341 : :
342 : : !!****f* m_opt_effpot/opt_effpotbound
343 : : !!
344 : : !! NAME
345 : : !! opt_effpotbound
346 : : !!
347 : : !! FUNCTION
348 : : !! Compute and add high order terms to existing odd or negative even anharmonic terms
349 : : !! Fix the coefficient of the added new high order terms to a value such that it
350 : : !! doesn't influence the precision of the existing anharmonic potential with respect
351 : : !! to a relevent training set (ATTENTIION: A user must know what a relevant training set
352 : : !! is for the system he want's to study. Typically something oscillating around its ground-state.)
353 : : !! Finally optimize the coefficients of the orignal anharmonic terms under the presence of the
354 : : !! added high order terms.
355 : : !!
356 : : !! INPUTS
357 : : !! eff_pot: existing effective potential
358 : : !! order: order for which bounding terms are generated
359 : : !! order_ran: ?
360 : : !! bound_EFS:
361 : : !! bound_factors:
362 : : !! bound_penalty:
363 : : !! comm: MPI communicator
364 : : !! fit_weight_T: ?
365 : : !! print_anh: ?
366 : : !! bound_option: 1 or 2. Whether the bounding term should be the same nbody with the term to be bounded. 1. Yes (default), 2. No
367 : : !!
368 : : !!
369 : : !! OUTPUT
370 : : !! eff_pot new effective potential
371 : : !!
372 : : !!
373 : : !! SOURCE
374 : :
375 : 1 : subroutine opt_effpotbound(eff_pot,order_ran,hist,bound_EFS,bound_factors,bound_penalty,comm, fit_weight_T,bound_option, print_anh)
376 : :
377 : : !Arguments ------------------------------------
378 : : !scalars
379 : : integer,intent(in) :: comm
380 : : type(effective_potential_type),target,intent(inout) :: eff_pot
381 : : type(abihist),intent(inout) :: hist
382 : : real(dp) :: bound_penalty
383 : : !arrays
384 : : integer,intent(in) :: order_ran(2),bound_EFS(3)
385 : : integer, intent(in) :: bound_option
386 : : real(dp),intent(in) :: bound_factors(3)
387 : : real(dp), intent(in) :: fit_weight_T
388 : : !Logicals
389 : : logical,optional,intent(in) :: print_anh
390 : : !Strings
391 : : !Local variables ------------------------------
392 : : !scalars
393 : : integer :: i,ii,natom_sc,ntime,iterm,nterm, icombi3, nbody_term
394 : : integer :: jterm, ncombi,ncombi1,ncombi2, ncombi1_real, ncombi2_real
395 : : integer :: icombi
396 : : integer :: nterm_start,nterm2
397 : : integer :: nproc,my_rank,master
398 : : !1406
399 : : real(dp) :: factor,mse_ini,msef_ini,mses_ini,mse,msef,mses
400 : : real(dp) :: coeff_tmp
401 : : real(dp),parameter :: HaBohr_eVAng = Ha_eV /Bohr_Ang
402 : : !arrays
403 : : integer :: sc_size(3),temp_cntr
404 : 1 : integer,allocatable :: terms(:)
405 : 1 : logical,allocatable :: exists(:)
406 : : logical :: any_exists
407 : 1 : type(fit_data_type) :: fit_data
408 : : real(dp) :: GF_arr(2),coeff_opt(2)
409 : 1 : real(dp), allocatable :: my_weights(:)
410 : : !real(dp), allocatable :: energy_coeffs(:,:),fcart_coeffs(:,:,:,:)
411 : : !real(dp), allocatable :: strten_coeffs(:,:,:)
412 : : !1406 strain_temrs_tmp
413 : 1 : type(polynomial_coeff_type),target,allocatable :: my_coeffs(:),my_coeffs_tmp(:)
414 : 1 : type(polynomial_coeff_type),allocatable :: singledisp_terms(:),HOsingledisp_terms(:)
415 : 1 : type(polynomial_coeff_type),allocatable :: HOcrossdisp_terms(:)
416 : : !Logicals
417 : : logical :: need_print_anh ! MARCUS FOR THE MOMENT PRINT NO FILES
418 : : logical :: to_skip,iam_master
419 : : !Strings
420 : : character(len=5),allocatable :: symbols(:)
421 : : character(len=200):: name
422 : : character(len=1000) :: message
423 : : character(len=fnlen) :: fn_bf='before_opt_diff'!, fn_af='after_opt_diff'
424 : : ! types
425 : 1 : type(SymPairs_t) :: sympairs
426 : : !*************************************************************************
427 : : !MPI variables
428 : 1 : master = 0
429 : 1 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
430 : : iam_master = (my_rank == master)
431 : :
432 : : ! Say hello to the world!
433 : 1 : write(message, '(3a)' )'-Start Bound optimization of Anharmonic Potential ',ch10
434 : 1 : call wrtout(ab_out,message,'COLL')
435 : 1 : call wrtout(std_out,message,'COLL')
436 : :
437 : : !Setting/Initializing Variables
438 : 1 : ntime = hist%mxhist
439 : :
440 : :
441 : 1 : natom_sc = size(hist%xred,2)
442 : 1 : factor = 1._dp/natom_sc
443 : 1 : nterm =eff_pot%anharmonics_terms%ncoeff
444 : 1 : need_print_anh=.False.
445 [ + - ]: 1 : if(present(print_anh))then
446 [ # # ]: 0 : if(print_anh) need_print_anh = .True.
447 : : endif
448 : 1 : call get_weight_from_hist(hist, fit_weight_T, ntime, natom_sc, my_weights, comm )
449 : :
450 [ - + + - : 3 : ABI_MALLOC(symbols,(eff_pot%crystal%natom))
+ - + - -
+ - + ]
451 [ - + + - : 3 : ABI_MALLOC(terms,(nterm))
+ - + - -
+ - + ]
452 : : call symbols_crystal(eff_pot%crystal%natom,eff_pot%crystal%ntypat,eff_pot%crystal%npsp,&
453 : 1 : & symbols,eff_pot%crystal%typat,eff_pot%crystal%znucl)
454 : :
455 : :
456 : : !if the number of atoms in reference supercell into effpot is not correct,
457 : : !wrt to the number of atom in the hist, we set map the hist and set the good supercell
458 [ - + ]: 1 : if (natom_sc /= eff_pot%supercell%natom) then
459 : 0 : call effective_potential_file_mapHistToRef(eff_pot,hist,comm,verbose=.TRUE.)
460 : : end if
461 : :
462 : : !Check if input of order is correct
463 : : ! TODO write error message here
464 [ + + + - : 3 : if (any(mod(order_ran,2) /= 0)) return
+ - ]
465 : :
466 : : !we get the size of the supercell in the hist file
467 [ + + ]: 4 : do ii=1,3
468 : : sc_size(ii) = int(anint(sqrt(eff_pot%supercell%rprimd(ii,1)**2+&
469 : : & eff_pot%supercell%rprimd(ii,2)**2+&
470 : : & eff_pot%supercell%rprimd(ii,3)**2) / &
471 : : & sqrt(eff_pot%crystal%rprimd(ii,1)**2+&
472 : : & eff_pot%crystal%rprimd(ii,2)**2+&
473 : 4 : & eff_pot%crystal%rprimd(ii,3)**2)))
474 : : end do
475 : :
476 : :
477 : : !Before the fit, compute constants with fit_data_compute.
478 : : !Conpute the strain of each configuration.
479 : : !Compute the displacmeent of each configuration.
480 : : !Compute the variation of the displacement due to strain of each configuration.
481 : : !Compute fixed forces and stresse and get the standard deviation.
482 : : !Compute Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]].
483 : : !call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
484 : 1 : call fit_data_compute(fit_data,eff_pot,hist,comm,verbose=.FALSE.)
485 : :
486 [ - + ]: 1 : if(need_print_anh) call effective_potential_writeAnhHead(eff_pot%anharmonics_terms%ncoeff,&
487 : 0 : & fn_bf,eff_pot%anharmonics_terms)
488 : :
489 : : !Before adding bound coefficients calculate MSD of initial model
490 : : !MS FOR THE MOMENT PRINT NO FILE
491 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse_ini,msef_ini,mses_ini,&
492 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
493 : 1 : & compute_anharmonic=.TRUE.,print_file=.FALSE.)
494 : :
495 : :
496 : : ! Print the standard devition of initial model
497 : 1 : write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
498 : 1 : & ' Mean Standard Deviation values of the effective-potential',ch10,&
499 : 1 : & ' with respect to the training-set before attempted bounding (meV^2/atm):',&
500 : 1 : & ch10,' Energy : ',&
501 : 1 : & mse_ini* (Ha_EV*1000)**2 *factor ,ch10,&
502 : 1 : & ' Goal function values of the effective.potential',ch10,&
503 : 1 : & ' with respect to the test-set (eV^2/A^2):',ch10,&
504 : 1 : & ' Forces+Stresses : ',&
505 : 1 : & (msef_ini+mses_ini)*(HaBohr_eVAng)**2,ch10,&
506 : 1 : & ' Forces : ',&
507 : 1 : & msef_ini*(HaBohr_eVAng)**2,ch10,&
508 : 1 : & ' Stresses : ',&
509 : 2 : & mses_ini*(HaBohr_eVAng)**2,ch10
510 : 1 : call wrtout(ab_out,message,'COLL')
511 : 1 : call wrtout(std_out,message,'COLL')
512 : :
513 : : !MS DEV
514 : : ! single displacement terms with second order only.
515 : 1 : call opt_getSingleDispTerms(singledisp_terms,eff_pot%crystal, sc_size,comm)
516 : :
517 : :
518 : : ! create pair list:
519 : 1 : call sympairs%init(eff_pot%crystal, sc_size)
520 : :
521 : : !For the moment order loop commented
522 : : !do iorder=order(1),order(2),2, Order will be done per term
523 : : !Loop over all original terms + 1
524 : : ! + 1 to bound pure strain
525 [ + + ]: 3 : do iterm =1,nterm +1
526 [ + + ]: 2 : if(iterm <=nterm)then
527 : 1 : ncombi1=0
528 : 1 : ncombi2=0
529 : 1 : ncombi1_real=0
530 : 1 : ncombi2_real=0
531 : : !Store for optimization
532 : 1 : terms(iterm) = iterm
533 : : !Message: The world wants to know where we stand Batman
534 : 1 : write(message, '(a,(80a),a)' ) ch10,&
535 [ + - + + ]: 81 : & ('_',ii=1,80),ch10
536 : 1 : call wrtout(ab_out,message,'COLL')
537 : 1 : call wrtout(std_out,message,'COLL')
538 : 1 : write(message,'(2a,I3,a,I3,3a)' )ch10,&
539 [ + - ]: 2 : & ' Check term (',iterm,'/',nterm,'): ', trim(eff_pot%anharmonics_terms%coefficients(iterm)%name),ch10
540 : 1 : call wrtout(ab_out,message,'COLL')
541 : 1 : call wrtout(std_out,message,'COLL')
542 : 1 : to_skip = .FALSE.
543 : 1 : to_skip = check_to_skip(eff_pot%anharmonics_terms%coefficients(iterm))
544 : : !Skip term if it doesn't need bounding
545 [ + - ]: 1 : if(.not. to_skip)then
546 : : associate(term1=>eff_pot%anharmonics_terms%coefficients(iterm)%terms(1))
547 : 1 : nbody_term = term1%get_nbody()
548 : :
549 : : !Get List of high order single Terms for terms
550 : : call opt_getHOSingleDispTerms(eff_pot%anharmonics_terms%coefficients(iterm),&
551 [ - - - - : 1 : & HOsingledisp_terms,symbols,singledisp_terms,order_ran,ncombi1)
- - - - -
- - - - -
- - - - -
- - + ]
552 : :
553 [ - + + - : 4 : ABI_MALLOC(my_coeffs,(size(eff_pot%anharmonics_terms%coefficients)))
+ - + - -
+ - + - +
+ + ]
554 : 1 : my_coeffs=eff_pot%anharmonics_terms%coefficients
555 : 1 : do icombi3=1, size(my_coeffs)
556 : : !DMSG(my_coeffs(icombi3)%debug_str)
557 : : end do
558 : :
559 : : ! then add the single disp terms.
560 [ + - ]: 1 : if (ncombi1>0) then
561 [ + + ]: 3 : do icombi3=1,ncombi1
562 [ + - - + ]: 3 : if (HOsingledisp_terms(icombi3)%terms(1)%get_nbody() == nbody_term .or. bound_option/=1) then
563 : 0 : call coeffs_list_append(my_coeffs,HOsingledisp_terms(icombi3), check=.TRUE.)
564 : : !DMSG(my_coeffs(icombi3)%debug_str)
565 : 0 : ncombi1_real = ncombi1_real + 1
566 : : endif
567 : : end do
568 : : endif
569 : :
570 [ + - ]: 1 : if(allocated(HOsingledisp_terms)) call polynomial_coeff_list_free(HOsingledisp_terms)
571 : :
572 : :
573 : : !Get List of high order cross Terms for term if ndisp > 1
574 [ - + - - : 1 : if(term1%ndisp>1 .or. &
- - ]
575 : : & term1%ndisp /= 0 .and. & ! why >1 or /=0?
576 : : & term1%nstrain /= 0)then
577 : : ! output HOcrossdisp_terms, ncombi2.
578 : 1 : call opt_getHOcrossdisp(HOcrossdisp_terms,ncombi2,eff_pot%anharmonics_terms%coefficients(iterm),order_ran)
579 : : endif
580 : : ! then add the crossdisp terms.
581 [ + - ]: 1 : if(ncombi2 > 0)then
582 [ + + ]: 4 : do icombi3=1,ncombi2
583 : : !call coeffs_list_conc_onsite(my_coeffs, HOcrossdisp_terms(icombi3))
584 [ + + - + ]: 4 : if (HOcrossdisp_terms(icombi3)%terms(1)%get_nbody() == nbody_term .or. bound_option/=1) then
585 : 1 : call coeffs_list_append(my_coeffs,HOcrossdisp_terms(icombi3), check=.TRUE.)
586 : 1 : ncombi2_real = ncombi2_real + 1
587 : : !DMSG(my_coeffs(ncombi2_real)%debug_str)
588 : : endif
589 : : end do
590 : : endif
591 [ - + + - ]: 2 : if(allocated(HOcrossdisp_terms)) call polynomial_coeff_list_free(HOcrossdisp_terms)
592 : : end associate
593 : : else ! to_skip
594 : : ncombi2=0
595 : : ncombi1=0
596 [ # # # # : 0 : ABI_MALLOC(my_coeffs,(size(eff_pot%anharmonics_terms%coefficients)))
# # # # #
# # # # #
# # ]
597 : 0 : my_coeffs = eff_pot%anharmonics_terms%coefficients
598 : : endif
599 : 1 : ncombi = ncombi1_real + ncombi2_real
600 : 1 : nterm_start = eff_pot%anharmonics_terms%ncoeff
601 : : else ! if iterm = nterm + 1 => Take care about strain
602 : : block
603 : 1 : integer :: max_nbody_tmp(order_ran(2))
604 [ + - ]: 1 : if (bound_option==1) then
605 [ + + ]: 7 : max_nbody_tmp(:) = 1
606 : : else
607 [ # # ]: 0 : max_nbody_tmp(:) = 888
608 : : endif
609 : 1 : call opt_getHOstrain(my_coeffs,ncombi,nterm_start,eff_pot,order_ran,comm, max_nbody=max_nbody_tmp)
610 : : end block
611 : : endif !
612 : :
613 : :
614 : : ! Modification of Alireza.
615 : : !---------------------------------------------
616 : : !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!!
617 : :
618 : : ! 1. We need to use generateTermsFromList module to create terms.
619 : : ! 2. The generateTermsFromList module accepts list combinations of terms: (\1,1,1,1,7,7\)
620 : : ! 3. We need to convert the terms from bounding process to a list like (\1,1,1,1,7,7\)
621 : : ! 4. use polynomial_coeff_getList to get pairs.
622 : : ! 5. compare th list and the terms and find out what is the number of diplacement in list for a term.
623 : : ! 6. convert term to list.
624 : : ! 7. ask for the temrs from generateTermsFromList
625 : : ! 8. check and see if the coeff is already considered or not. use coeffs_compare function
626 : : !! strain the same thing should be done for the strain
627 : : !! find the list of all the list_str,
628 : : !! fond what is number of strain in the displacemt comapring it to
629 : : !! the list_str and give this to
630 : : ! get coeff from > generateTermsFromList(list_disp,****)
631 : : ! setcoeff_to_tmp_coeffs
632 : : ! generateTermsFromList(cell,index_coeff,list_coeff,list_str,ncoeff,ndisp_max,nrpt,nstr,nsym,nterm,terms)
633 : :
634 : : ! call the new function to get the data required to call polynomial_coeff_getList
635 : :
636 : :
637 : 2 : call generate_bounding_term_and_add_to_list( sympairs, nterm_start, ncombi, my_coeffs, temp_cntr)
638 : :
639 : :
640 : :
641 [ + - ]: 2 : if (temp_cntr>0) then
642 [ + + ]: 5 : do icombi=1,temp_cntr
643 : : ! Copy all the terms in eff pot
644 : : call polynomial_coeff_getName(name, &
645 : 3 : & my_coeffs(nterm_start+icombi),symbols,recompute=.TRUE.)
646 : 3 : call polynomial_coeff_SetName(name,my_coeffs(nterm_start+icombi))
647 : :
648 : : ! Set dimensions of temporary my_coeffs array
649 : 3 : nterm2 = eff_pot%anharmonics_terms%ncoeff + 1
650 [ - + + - : 18 : ABI_MALLOC(my_coeffs_tmp,(nterm2))
+ - + - -
+ - + - +
+ + ]
651 : : ! Copy terms of previous cycle
652 : 3 : my_coeffs_tmp(1:nterm2-1) = eff_pot%anharmonics_terms%coefficients
653 : : !Put new term to my_coeffs_tmp
654 [ + - + - : 33 : my_coeffs_tmp(nterm2) = my_coeffs(nterm_start+icombi)
+ + + - +
- + - + -
+ - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- ]
655 : :
656 : :
657 : : !call polynomial_coeff_init(my_coeffs(nterm_start+icombi)%coefficient, &
658 : : ! & my_coeffs(nterm_start+icombi)%nterm, &
659 : : ! & my_coeffs_tmp(nterm2),my_coeffs(nterm_start+icombi)%terms, &
660 : : ! &my_coeffs(nterm_start+icombi)%name)
661 : :
662 : : ! DMSG(my_coeffs_tmp(nterm2)%debug_str)
663 : :
664 : : ! If order is greater than specified cycle
665 [ + + + + : 14 : if(sum(my_coeffs_tmp(nterm2)%terms(1)%power_disp) &
+ + - + ]
666 : : & +sum(my_coeffs_tmp(nterm2)%terms(1)%power_strain) > maxval(order_ran))then
667 : 0 : call polynomial_coeff_list_free(my_coeffs_tmp)
668 : 0 : cycle
669 : : endif
670 : : ! Message to Output
671 : 3 : write(message,'(5a)' )ch10,&
672 [ + - ]: 6 : & ' ==> high order term: ', trim(my_coeffs_tmp(nterm2)%name),' created',ch10
673 : 3 : call wrtout(ab_out,message,'COLL')
674 : 3 : call wrtout(std_out,message,'COLL')
675 : : ! Check if generated term is not already contained in effpot
676 : : ! If yes cycle
677 [ - + + - : 9 : ABI_MALLOC(exists, (nterm2))
+ - + - -
+ - + -
+ ]
678 [ + + ]: 12 : exists=.FALSE.
679 [ + + ]: 9 : do jterm=1,nterm2-1
680 : 9 : exists(jterm) = coeffs_compare(my_coeffs_tmp(jterm),my_coeffs_tmp(nterm2))
681 : : enddo !jterm
682 [ + + + - ]: 12 : any_exists=any(exists)
683 [ + - ]: 3 : ABI_SFREE(exists)
684 [ - + ]: 3 : if(any_exists)then
685 : 0 : write(message,'(3a)' )ch10,&
686 : 0 : & ' ==> Term exists already. We cycle',ch10
687 : 0 : call wrtout(ab_out,message,'COLL')
688 : 0 : call wrtout(std_out,message,'COLL')
689 : 0 : call polynomial_coeff_list_free(my_coeffs_tmp)
690 : 0 : cycle
691 : : endif
692 : :
693 : :
694 : : ! Set new term into effective potential
695 : 3 : call effective_potential_setCoeffs(my_coeffs_tmp,eff_pot,nterm2)
696 : :
697 : : ! Tell the world what we do, They want to know.
698 : 3 : write(message,'(3a)' )ch10,&
699 : 6 : & ' ==> Optimizing coefficient',ch10
700 : 3 : call wrtout(ab_out,message,'COLL')
701 : 3 : call wrtout(std_out,message,'COLL')
702 : :
703 : : ! Deallocation in loop
704 : 3 : call polynomial_coeff_list_free(my_coeffs_tmp)
705 : : !Optimizing coefficient old style
706 : :
707 [ + + ]: 5 : if(iterm>nterm)then
708 : : ! MS 2006 Decomment for old style optimization
709 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
710 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
711 : 2 : & compute_anharmonic=.TRUE.,print_file=.FALSE., weights=my_weights)
712 : 2 : i = 0
713 : 2 : write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses)/(msef_ini+mses_ini): ", (msef+mses)/(msef_ini+mses_ini)
714 : 2 : call wrtout(std_out,message,'COLL')
715 : 2 : write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses): ", (msef+mses)
716 : 2 : call wrtout(std_out,message,'COLL')
717 [ - + ]: 2 : do while((msef+mses)/(msef_ini+mses_ini) >= 1.001)
718 : 0 : i = i + 1
719 : : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = &!coeff_ini / 2**i
720 : 0 : & eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient / 2**1
721 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
722 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
723 : 0 : & compute_anharmonic=.TRUE.,print_file=.FALSE., weights=my_weights)
724 : :
725 : 0 : write(message,'(a,I2,a,ES24.16)') "cycle ",i," (msef+mses)/(msef_ini+mses_ini): ",(msef+mses)/(msef_ini+mses_ini)
726 : 0 : call wrtout(std_out,message,'COLL')
727 : 0 : write(message,'(a,I2,a,ES24.16)') "cycle ", i ," (msef+mses): ", (msef+mses)
728 : 0 : call wrtout(std_out,message,'COLL')
729 : : enddo ! while mse/mse_ini>1.0001
730 : 2 : write(message,'(a,ES24.16)') "coeff after opt:", eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
731 : 2 : call wrtout(std_out,message,'COLL')
732 : 2 : msef_ini = msef
733 : 2 : mses_ini = mses
734 : : ! !Optimize coefficient with opt routine
735 : : ! optterm(1)= nterm2
736 : : ! nterm_opt = 1
737 : : ! call opt_effpot(eff_pot,nterm_opt,optterm,hist,comm,print_anh=.FALSE.)
738 : : ! write(*,*) "coeff after opt:", eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
739 : : ! !Store new "inital precision for next coefficient
740 : : ! msef_ini = msef
741 : : ! mses_ini = mses
742 : :
743 : : else
744 : : !Optimizing coefficient with GF criterion
745 : 1 : coeff_opt = 0
746 : 1 : GF_arr = 0
747 : 1 : i = 1
748 [ + + ]: 3 : do while(i<=2)
749 : : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = &
750 [ + - ]: 2 : & eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient/ 2**(i-1)
751 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
752 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
753 : 2 : & compute_anharmonic=.TRUE.,print_file=.FALSE.)
754 : : GF_arr(i) = (bound_factors(1)*bound_EFS(1)*mse+bound_factors(2)*bound_EFS(2)*msef&
755 : : & +bound_factors(3)*bound_EFS(3)*mses) / &
756 : : & (bound_factors(1)*bound_EFS(1)*mse_ini+bound_factors(2)*bound_EFS(2)*msef_ini&
757 : 2 : & +bound_factors(3)*bound_EFS(3)*mses_ini)
758 : 2 : write(message,'(a,I2,a,ES24.16)') "cycle ",i," GF/GF_ini: ",GF_arr(i)
759 : 2 : call wrtout(std_out,message,'COLL')
760 : 2 : write(message,'(a,I2,a,ES24.16)') "cycle ", i ," GF: ",(bound_factors(1)*bound_EFS(1)*mse&
761 : : & +bound_factors(2)*bound_EFS(2)*msef&
762 : 4 : & +bound_factors(3)*bound_EFS(3)*mses)
763 : 2 : call wrtout(std_out,message,'COLL')
764 : 2 : coeff_opt(i) = eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
765 [ + + - + ]: 3 : if(i==2 .and. abs(GF_arr(1)-GF_arr(2)) < tol8)then
766 : : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient =&
767 : 0 : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient*10d5
768 : 0 : write(message,'(5a)') ch10,"Differences between test-cycles to small increase",ch10, &
769 : 0 : & "test coefficient value by factor 1000",ch10
770 : 0 : call wrtout(std_out,message,'COLL')
771 : 0 : i = i+1
772 : : ! This is weird, it keeps on increasing the coefficient by 1000, until a NaN is reached.
773 : : else
774 : 2 : i=i+1
775 : : end if
776 : : enddo ! while mse/mse_ini>10
777 [ - + ]: 1 : if (eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient /= eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient) then
778 : 0 : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = 0.0_dp
779 : : end if
780 : :
781 : 1 : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = opt_boundcoeff(GF_arr,coeff_opt,bound_penalty)
782 [ - + ]: 1 : if (eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient /= eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient) then
783 : 0 : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = 0.0_dp
784 : : end if
785 : :
786 : 1 : write(message,'(a,ES24.16)') "coeff after opt1:", eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
787 : 1 : call wrtout(std_out,message,'COLL')
788 : 1 : coeff_tmp = ANINT(eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient*10d10)
789 : 1 : eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient = coeff_tmp/10d10
790 : 1 : write(message,'(a,ES24.16)') "coeff after opt2:", eff_pot%anharmonics_terms%coefficients(nterm2)%coefficient
791 : 1 : call wrtout(std_out,message,'COLL')
792 : : call fit_polynomial_coeff_computeMSD(eff_pot,hist,mse,msef,mses,&
793 : : & natom_sc,ntime,fit_data%training_set%sqomega,comm,&
794 : 1 : & compute_anharmonic=.TRUE.,print_file=.FALSE.)
795 : 1 : write(message,'(a,ES24.16)') "GF/GF_ini after_opt: ", (bound_factors(1)*bound_EFS(1)*mse&
796 : : & +bound_factors(2)*bound_EFS(2)*msef&
797 : : & +bound_factors(3)*bound_EFS(3)*mses) / &
798 : : & (bound_factors(1)*bound_EFS(1)*mse_ini&
799 : : & +bound_factors(2)*bound_EFS(2)*msef_ini&
800 : 2 : & +bound_factors(3)*bound_EFS(3)*mses_ini)
801 : 1 : call wrtout(std_out,message,'COLL')
802 : 1 : mse_ini = mse
803 : 1 : msef_ini = msef
804 : 1 : mses_ini = mses
805 : : endif
806 : : !DEALLOCATION
807 : : !ABI_FREE(exists)
808 : : enddo ! icombi
809 : : end if
810 : :
811 : 5 : call polynomial_coeff_list_free(my_coeffs)
812 : : end do !iterm
813 : : !enddo ! order
814 : :
815 [ + - ]: 1 : if(allocated(singledisp_terms)) call polynomial_coeff_list_free(singledisp_terms)
816 : :
817 : 1 : write(message, '(a,(80a),a)' ) ch10,&
818 [ + - + + ]: 81 : &('_',ii=1,80),ch10
819 : 1 : call wrtout(ab_out,message,'COLL')
820 : 1 : call wrtout(std_out,message,'COLL')
821 : :
822 : 1 : write(message,'(3a)' )ch10,&
823 : 2 : & ' Finished creating high-order terms',ch10 !,&
824 : : !& ' Optimize initial anharmonic terms !NOT IS COMMENTED NOW!',ch10
825 : 1 : call wrtout(ab_out,message,'COLL')
826 : 1 : call wrtout(std_out,message,'COLL')
827 : : ! call opt_effpot(eff_pot,nterm,terms,hist,comm,print_anh=.FALSE.)
828 : :
829 : : ! Print the standard devition of final model
830 : 1 : write(message,'(6a,ES24.16,6a,ES24.16,2a,ES24.16,2a,ES24.16,a)' )ch10,&
831 : 1 : & ' Mean Standard Deviation values of the effective-potential',ch10,&
832 : 1 : & ' with respect to the training-set after attempted bounding (meV^2/atm):',&
833 : 1 : & ch10,' Energy : ',&
834 : 1 : & mse_ini* (Ha_EV*1000)**2 *factor ,ch10,&
835 : 1 : & ' Goal function values of the effective.potential',ch10,&
836 : 1 : & ' with respect to the test-set (eV^2/A^2):',ch10,&
837 : 1 : & ' Forces+Stresses : ',&
838 : 1 : & (msef_ini+mses_ini)*(HaBohr_eVAng)**2,ch10,&
839 : 1 : & ' Forces : ',&
840 : 1 : & msef_ini*(HaBohr_eVAng)**2,ch10,&
841 : 1 : & ' Stresses : ',&
842 : 2 : & mses_ini*(HaBohr_eVAng)**2,ch10
843 : 1 : call wrtout(ab_out,message,'COLL')
844 : 1 : call wrtout(std_out,message,'COLL')
845 : :
846 : :
847 : : !DEALLOCATION
848 [ + - ]: 1 : ABI_SFREE(symbols)
849 [ + - ]: 1 : ABI_SFREE(terms)
850 [ + - ]: 1 : ABI_SFREE(my_weights)
851 : :
852 : : !ABI_FREE(my_coeffs)
853 : 1 : call fit_data_free(fit_data)
854 : 1 : call sympairs%free()
855 : :
856 : :
857 [ - + - + : 1 : end subroutine opt_effpotbound
- + - - -
- - - - -
- - - - -
- - - - -
- - - + -
+ - - - -
- - - - -
- - - - -
- - - - -
- - + - -
- - - - -
- - - - -
- - - - -
- - - - +
- - - - -
- - - - -
- - - - -
- - - - -
- + - - -
- - - - -
- - - - -
- - - - -
- - - + -
+ - + - +
- + - + -
+ - + -
+ ]
858 : : !!***
859 : :
860 : :
861 : : !!****f* m_opt_effpot/opt_getHOforterm
862 : : !!
863 : : !! NAME
864 : : !! opt_effpotbound
865 : : !!
866 : : !! FUNCTION
867 : : !! Compute possible high orders for a given anharmonic term.
868 : : !! In the range of order_start,order_stop
869 : : !!
870 : : !!
871 : : !! INPUTS
872 : : !! term<polynomial_coeff_type>:anharmonic term
873 : : !! order_range(2):start and stop order desired by user
874 : : !!
875 : : !!
876 : : !! OUTPUT
877 : : !! order_start:possible start order
878 : : !! order_stop: possible stop order
879 : : !!
880 : : !! SOURCE
881 : :
882 : 2 : subroutine opt_getHOforterm(term,order_range,order_start,order_stop)
883 : :
884 : : !Arguments ------------------------------------
885 : : !scalars
886 : : type(polynomial_coeff_type),intent(in) :: term
887 : : !arrays
888 : : integer,intent(in) :: order_range(2)
889 : : integer,intent(out) :: order_start, order_stop
890 : : !Logicals
891 : : !Strings
892 : : !Local variables ------------------------------
893 : : !scalars
894 : : integer :: idisp,ndisp,nstrain,nterm_of_term,power_tot
895 : : integer :: nbody_tot
896 : : !arrays
897 : 2 : integer,allocatable :: powers(:)
898 : : !Logicals
899 : : !Strings
900 : : !*************************************************************************
901 : :
902 : : !Get/Initialize variables
903 : 2 : ndisp = term%terms(1)%ndisp
904 : 2 : nstrain = term%terms(1)%nstrain
905 : 2 : nbody_tot = ndisp + nstrain
906 : 2 : nterm_of_term = term%nterm
907 : :
908 [ - + + - : 6 : ABI_MALLOC(powers,(nbody_tot))
+ - + - -
+ - + ]
909 [ + + ]: 6 : powers(:ndisp) = term%terms(1)%power_disp
910 [ + + ]: 3 : powers(ndisp+1:) = term%terms(1)%power_strain
911 : 7 : power_tot = 0
912 : : !write(std_out,*) "powers in getHOforterm", powers
913 : :
914 : : !Get rid off odd displacements
915 [ + + ]: 7 : do idisp=1,nbody_tot
916 [ + + + + ]: 7 : if(idisp <= ndisp .and. mod(powers(idisp),2) == 1)then
917 : 2 : powers(idisp) = powers(idisp) + 1
918 [ + + ]: 3 : else if(mod(powers(idisp),2) == 1)then
919 : 1 : powers(idisp) = powers(idisp) + 1
920 : : endif
921 : : enddo !idisp
922 : : ! Count order
923 [ + + ]: 7 : do idisp=1,nbody_tot
924 : 7 : power_tot = power_tot + powers(idisp)
925 : : enddo
926 : : ! Get start and stop order for this term
927 : : ! If term doesn't fit in order range give back order_start = order_stop = 0
928 [ + + + - ]: 2 : if(power_tot >= order_range(1) .and. power_tot <=order_range(2))then
929 : 1 : order_start = power_tot
930 : 1 : order_stop = order_range(2)
931 [ + - ]: 1 : elseif(power_tot < order_range(1))then
932 : 1 : order_start = order_range(1)
933 : 1 : order_stop = order_range(2)
934 [ # # ]: 0 : elseif(power_tot > order_range(2))then
935 : 0 : order_start = 0
936 : 0 : order_stop = 0
937 : : endif
938 : :
939 [ + - ]: 2 : ABI_SFREE(powers)
940 : :
941 : 2 : end subroutine opt_getHOforterm
942 : : !!***
943 : :
944 : :
945 : : !!****f* m_opt_effpot/opt_getCombisforterm
946 : : !!
947 : : !! NAME
948 : : !! opt_getCombisforterm
949 : : !!
950 : : !! FUNCTION
951 : : !! For a given order range: order_start, order_stop
952 : : !! calculate number of total possible combinations ncombi
953 : : !! and calculat combinations per order ncombi_order(i)
954 : : !!
955 : : !!
956 : : !! INPUTS
957 : : !! order_start: start order for bounding terms
958 : : !! order_end: end order for bounding terms
959 : : !! ndisp: number of displacements a given term contains
960 : : !!
961 : : !!
962 : : !! OUTPUT
963 : : !! ncombi: total number of combinations
964 : : !! ncombi_order: array with number of combinations per order
965 : : !!
966 : : !!
967 : : !! SOURCE
968 : :
969 [ - + ]: 2 : subroutine opt_getCombisforterm(order_start,order_end,ndisp,ncombi,ncombi_order)
970 : :
971 : : !Arguments ------------------------------------
972 : : !scalars
973 : : integer,intent(in) :: ndisp
974 : : integer,intent(in) :: order_start, order_end
975 : : !arrays
976 : : integer,intent(out) :: ncombi
977 : : integer,intent(out) :: ncombi_order(:)
978 : : !Logicals
979 : : !Strings
980 : : !Local variables ------------------------------
981 : : !scalars
982 : : integer :: i
983 : : integer :: order,iorder1,iorder2
984 : : !arrays
985 : : !integer
986 : : !Logicals
987 : : !Strings
988 : : character(len=1000) :: message
989 : : !*************************************************************************
990 : :
991 : : !Test
992 [ + - - + ]: 2 : if(mod(order_start,2) /= 0 .or. mod(order_end,2) /= 0)then
993 : : ! Message to Output
994 : 0 : write(message,'(4a)' )ch10,&
995 : 0 : & 'Either start or stop order are not even numbers',ch10,&
996 : 0 : & 'Action: change bound_range in input',ch10
997 : 0 : ABI_ERROR(message)
998 : : endif
999 : :
1000 : : !Initialize Variables
1001 : 2 : i = 0
1002 : 2 : ncombi = 0
1003 [ + + ]: 4 : ncombi_order = 0
1004 : :
1005 : : !Calculate Combinations
1006 [ + - + - ]: 4 : do order=order_start,order_end,2
1007 : 2 : i = i+1
1008 [ - + ]: 4 : if(ndisp == 1)then
1009 : 0 : ncombi = ncombi + 1
1010 : 0 : ncombi_order(i) = 1
1011 : : else
1012 [ + - + + ]: 5 : do iorder1 = 2,order-2*(ndisp-1),2
1013 [ + + ]: 3 : if(ndisp*iorder1 == order)then
1014 : 1 : ncombi = ncombi + 1
1015 : 1 : ncombi_order(i) = ncombi_order(i) + 1
1016 : 1 : cycle
1017 : : endif
1018 [ + + + - ]: 5 : do iorder2=iorder1+2,order-2*(ndisp-1),2
1019 [ + - ]: 3 : if( iorder1 + (ndisp-1)*iorder2 == order)then
1020 : 1 : ncombi = ncombi + ndisp
1021 : 1 : ncombi_order(i) = ncombi_order(i) + ndisp
1022 [ # # ]: 0 : elseif(iorder1 * (ndisp-1) + iorder2 == order)then
1023 : 0 : ncombi = ncombi + ndisp
1024 : 0 : ncombi_order(i) = ncombi_order(i) + ndisp
1025 : : endif
1026 : : enddo !iorder2
1027 : : enddo !iorder1 !
1028 : : endif
1029 : : !write(*,*) 'ncombi(',i,') for order',order,' is:', ncombi_order(i), 'are we happy?'
1030 : : enddo !order
1031 : :
1032 : : !write(*,*) ncombi_order(:)
1033 : : !write(*,*) 'ncombi for term is:', ncombi, 'are we happy?'
1034 : :
1035 : :
1036 : 2 : end subroutine opt_getCombisforterm
1037 : : !!***
1038 : :
1039 : : !!****f* m_opt_effpot/opt_getHoTerms
1040 : : !!
1041 : : !! NAME
1042 : : !! opt_geHoTerms
1043 : : !!
1044 : : !! FUNCTION
1045 : : !! For a term give all possible high order terms
1046 : : !! Attention order_start, order_stop, ncombi and
1047 : : !! ncombi_order have to be calculated before!
1048 : : !!
1049 : : !!
1050 : : !!
1051 : : !! INPUTS
1052 : : !! eff_pot: existing effective potential
1053 : : !! order: order for which bounding terms are generated
1054 : : !!
1055 : : !!
1056 : : !! OUTPUT
1057 : : !! eff_pot new effective potential
1058 : : !!
1059 : : !!
1060 : : !! SOURCE
1061 : :
1062 [ - + - + ]: 2 : subroutine opt_getHoTerms(terms,order_start,order_stop,ndisp,ncombi_order)
1063 : :
1064 : : !Arguments ------------------------------------
1065 : : !scalars
1066 : : integer,intent(in) :: ndisp
1067 : : integer,intent(in) :: order_start, order_stop
1068 : : !arrays
1069 : : integer,intent(in) :: ncombi_order(:)
1070 : : !Logicals
1071 : : type(polynomial_coeff_type),intent(inout) :: terms(:)
1072 : : !Strings
1073 : : !Local variables ------------------------------
1074 : : !scalars
1075 : : integer :: i,icombi,icombi2,icombi_start,icombi_stop,idisp,nterm_of_term
1076 : : integer :: order,iterm_of_term,jdisp,power_tot
1077 : : integer :: jdisp1,jdisp2,sec,nstrain,nbody_tot
1078 : : real(sp) :: to_divide,divider1,divider2,divided
1079 : : !arrays
1080 : : !integer
1081 : : !Logicals
1082 : : logical :: equal_term_done
1083 : : !Strings
1084 : : character(len=1000) :: message
1085 : : !*************************************************************************
1086 : : !Get Variables
1087 : 2 : nterm_of_term = terms(1)%nterm
1088 : 2 : nstrain = terms(1)%terms(1)%nstrain
1089 : 2 : nbody_tot = ndisp + nstrain
1090 : :
1091 : : ! Create all possible combinaions for the specified orders
1092 : : ! If anybody has ever, ever to read and understand this I'm terribly sorry
1093 : : ! ---this will be quite hell---
1094 : 2 : power_tot = 0
1095 : 2 : icombi_start = 1
1096 : 2 : i = 0
1097 : : !write(*,*) "what is ncombi?", ncombi
1098 : : !write(*,*) "what is ncmobi_order", ncombi_order
1099 : :
1100 : : !write(*,*) "order_start", order_start
1101 : : !write(*,*) "order_stop", order_stop
1102 : 2 : order = order_start
1103 : : ! TODO work here icombi start and order counting does not work yet.
1104 [ - + - + ]: 4 : do order=order_start,order_stop,2
1105 : : !write(std_out,*) 'Was I now here?!(order-loop)'
1106 : 2 : i = i + 1
1107 : 2 : icombi_stop = icombi_start + ncombi_order(i) - 1
1108 : 2 : equal_term_done = .FALSE.
1109 : : !write(std_out,*) 'order', order
1110 : : !write(std_out,*) 'icombi_start', icombi_start
1111 : : !write(std_out,*) 'icombi_stop', icombi_stop
1112 : 2 : icombi=icombi_start
1113 [ + + ]: 6 : do while (icombi<=icombi_stop)
1114 : : power_tot = 0
1115 [ + + ]: 7 : do idisp=1,nbody_tot
1116 : : !write(*,*) "what is icombi here?", icombi
1117 : : !write(*,*) "what is icombi_stop here?", icombi_stop
1118 [ + + ]: 7 : if(idisp<=ndisp)then
1119 : 4 : power_tot = power_tot + terms(icombi)%terms(1)%power_disp(idisp)
1120 : : else
1121 : 1 : power_tot = power_tot + terms(icombi)%terms(1)%power_strain(idisp-ndisp)
1122 : : endif
1123 : : enddo
1124 : : ! Probably have to increase order at same time
1125 : : ! If the term already has the right order we cycle
1126 : : ! we increase icombi_start and icombi to go to the next term in the array
1127 [ + + ]: 4 : if(power_tot == order)then
1128 : 1 : icombi_start = icombi_start + 1
1129 : 1 : icombi = icombi + 1
1130 : : !write(*,*) 'icombi-start in if', icombi_start
1131 : 1 : cycle
1132 : : ! If the term is not already in the right order, we manipulate it until
1133 : : ! it is
1134 : : else
1135 : : jdisp1 = 1
1136 : 3 : sec = 1
1137 : : !write(*,*) 'what is ndisp actually', ndisp
1138 : : ! Treat single permutations from the bottom of the order
1139 : : ! so start from ^2^2^2 and get ^6^2^2,^2^6^2, and ^2^2^6 f.E.
1140 : : ! do loop over displacements
1141 [ + + ]: 3 : do while(jdisp1<=nbody_tot .and. sec < 100)
1142 : : !write(*,*) "what is jdisp1 here?", jdisp1
1143 : : !write(*,*) "what is icombi here?", icombi
1144 : : !write(*,*) "what is icombi_sotp?", icombi_stop
1145 : : ! Increase the order of the displacements
1146 [ + + ]: 50 : do iterm_of_term=1,nterm_of_term
1147 [ + - ]: 50 : if(jdisp1 <= ndisp)then
1148 : : terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) =&
1149 : 48 : & terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) + 2
1150 : : else
1151 : : terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) =&
1152 : 0 : & terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) + 2
1153 : :
1154 : : endif
1155 : : enddo
1156 : : ! Check total order of term after increase
1157 : : power_tot=0
1158 [ + + ]: 6 : do jdisp2=1,nbody_tot
1159 [ + - ]: 6 : if(jdisp2 <= ndisp)then
1160 : 4 : power_tot = power_tot + terms(icombi)%terms(1)%power_disp(jdisp2)
1161 : : else
1162 : 0 : power_tot = power_tot + terms(icombi)%terms(1)%power_strain(jdisp2-ndisp)
1163 : : endif
1164 : : enddo
1165 : : ! If the term is at the right order do next displacement
1166 : : ! increase icombi and icombi_start to go to next term in array
1167 [ - + ]: 3 : if(power_tot == order)then
1168 : 2 : icombi = icombi + 1
1169 : 2 : icombi_start = icombi_start +1
1170 : : !write(*,*) 'what is icombi_start here', icombi_start
1171 : 2 : jdisp1 = jdisp1 + 1
1172 : : !write(*,*) 'and what is jdisp1?', jdisp1
1173 : :
1174 : : endif
1175 : : enddo!jdisp1
1176 : : !Treat permutations in terms ndisp > 2 and order >= 10
1177 : : !Start f.E. from ^4^4^4 and get ^4^2^4, ^2^4^4,^4^4^2
1178 [ - + - - ]: 1 : if(icombi_stop - icombi > 1 .and. nbody_tot >2 )then
1179 [ # # ]: 0 : do icombi2=icombi,icombi+nbody_tot-1
1180 [ # # ]: 0 : do jdisp=1,nbody_tot
1181 [ # # ]: 0 : do iterm_of_term=1,nterm_of_term
1182 [ # # ]: 0 : if(jdisp <= ndisp)then
1183 : : terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) = &
1184 : 0 : & terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) +2
1185 : : !write(*,*) "What's the power now?", terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp)
1186 : : else
1187 : : terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = &
1188 : 0 : & terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) +2
1189 : : endif
1190 : : enddo
1191 : : enddo !jdisp
1192 : : enddo
1193 : : jdisp1 = 1
1194 [ # # ]: 0 : do while(jdisp1<=nbody_tot .and. sec < 100)
1195 : 0 : sec = sec + 1
1196 : : !write(*,*) "how often did I go here, hu ?"
1197 : : !write(*,*) "I did at least one displacement"
1198 [ # # ]: 0 : do iterm_of_term=1,nterm_of_term
1199 [ # # ]: 0 : if(jdisp1 <= ndisp)then
1200 : : terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) =&
1201 : 0 : & terms(icombi)%terms(iterm_of_term)%power_disp(jdisp1) + 2
1202 : : else
1203 : : terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) =&
1204 : 0 : & terms(icombi)%terms(iterm_of_term)%power_strain(jdisp1-ndisp) + 2
1205 : :
1206 : : endif
1207 : : enddo
1208 : : power_tot=0
1209 [ # # ]: 0 : do jdisp2=1,nbody_tot
1210 [ # # ]: 0 : if(jdisp2 <= ndisp)then
1211 : 0 : power_tot = power_tot + terms(icombi)%terms(1)%power_disp(jdisp2)
1212 : : else
1213 : 0 : power_tot = power_tot + terms(icombi)%terms(1)%power_strain(jdisp2-ndisp)
1214 : : endif
1215 : : enddo
1216 [ # # ]: 0 : if(power_tot == order)then
1217 : 0 : icombi = icombi + 1
1218 : 0 : icombi_start = icombi_start +1
1219 : : !write(*,*) 'what is icombi_start here', icombi_start
1220 : 0 : jdisp1 = jdisp1 + 1
1221 : : !write(*,*) 'and what is jdisp1?', jdisp1
1222 : : endif
1223 : : enddo!jdisp1
1224 : : ! Message to Output
1225 : : if(sec>100)then
1226 : : write(message,'(4a)' )ch10,&
1227 : : & "You're stuck in a while loop.",ch10,&
1228 : : & 'Action: Contact Abinit Group',ch10
1229 : : ABI_ERROR(message)
1230 : : endif
1231 : : endif! (icombi_stop - icombi)
1232 : : !write(*,*) 'I was here!'
1233 : 1 : to_divide = real(order)
1234 : 1 : divider1 = real(nbody_tot)
1235 : 1 : divided = real(to_divide/divider1)
1236 : 1 : divider2 = real(2)
1237 : : !write(*,*) 'divided', divided, 'divider2', divider2
1238 : : !Treat terms with even power f.E. ^2^2^2^2, ^4^4 etc...
1239 [ + - - - ]: 1 : if(mod(divided,divider2) == 0 .and. .not. equal_term_done .and. nbody_tot > 1)then
1240 : : !write(*,*) "Sometimes I should be here sometimes I shouldn't"
1241 [ # # ]: 0 : do jdisp=1,nbody_tot
1242 [ # # ]: 0 : do iterm_of_term=1,nterm_of_term
1243 [ # # ]: 0 : if(jdisp<=ndisp)then
1244 : 0 : terms(icombi)%terms(iterm_of_term)%power_disp(jdisp) = order/ndisp
1245 : : else
1246 : 0 : terms(icombi)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = order/ndisp
1247 : : endif
1248 : : enddo
1249 : : enddo !jdisp
1250 [ # # ]: 0 : if(order < order_stop)then
1251 [ # # ]: 0 : do icombi2=icombi+1,icombi+nbody_tot
1252 [ # # ]: 0 : do jdisp=1,nbody_tot
1253 [ # # ]: 0 : do iterm_of_term=1,nterm_of_term
1254 [ # # ]: 0 : if(jdisp<=ndisp)then
1255 : 0 : terms(icombi2)%terms(iterm_of_term)%power_disp(jdisp) = order/ndisp
1256 : : else
1257 : 0 : terms(icombi2)%terms(iterm_of_term)%power_strain(jdisp-ndisp) = order/ndisp
1258 : : endif
1259 : : enddo
1260 : : enddo !jdisp
1261 : : enddo
1262 : : endif
1263 : 0 : equal_term_done = .TRUE.
1264 : 0 : icombi = icombi + 1
1265 : 0 : icombi_start = icombi_start +1
1266 : : endif ! equal term if
1267 : : endif ! power_tot == order
1268 : : enddo !icombination
1269 : : enddo !order
1270 : :
1271 : 2 : end subroutine opt_getHoTerms
1272 : : !!***
1273 : :
1274 : : !!****f* m_opt_effpot/opt_filterdisp
1275 : : !!
1276 : : !! NAME
1277 : : !! opt_opt_filterdisp
1278 : : !!
1279 : : !! FUNCTION
1280 : : !! If a anharmonic term represents a strain-phonon coupling
1281 : : !! delete the strain and only keep the displacement part.
1282 : : !!
1283 : : !!
1284 : : !! INPUTS
1285 : : !! term<polynomial_coeff_type>: anharmonic term to check
1286 : : !! nterm_of_term: number of symmetry equivalent terms for term
1287 : : !!
1288 : : !! OUTPUT
1289 : : !! term<polynomial_coeff_type>: only the displacement part of original term
1290 : : !!
1291 : : !! SOURCE
1292 : :
1293 : 1 : subroutine opt_filterdisp(term,nterm_of_term)
1294 : :
1295 : : !Arguments ------------------------------------
1296 : : !scalars
1297 : : type(polynomial_coeff_type),intent(inout) :: term
1298 : : integer,intent(in) :: nterm_of_term
1299 : : !arrays
1300 : : !Logicals
1301 : : !Strings
1302 : : !Local variables ------------------------------
1303 : : !scalars
1304 : : integer :: iterm_of_term
1305 : : !reals
1306 : : real(dp) :: coeff
1307 : : !arrays
1308 [ + + + + : 242 : type(polynomial_term_type) :: terms(nterm_of_term)
+ + + - +
- + - + -
+ - + - +
- ]
1309 : : !Logicals
1310 : : !Strings
1311 : : !*************************************************************************
1312 : :
1313 [ + + ]: 25 : do iterm_of_term=1,nterm_of_term
1314 : : !terms(iterm_of_term) = term%terms(iterm_of_term)
1315 : :
1316 : : call polynomial_term_init(term%terms(iterm_of_term)%atindx, &
1317 : : & term%terms(iterm_of_term)%cell,&
1318 : : & term%terms(iterm_of_term)%direction,&
1319 : : & term%terms(iterm_of_term)%ndisp, &
1320 : : & term%terms(iterm_of_term)%nstrain, &
1321 : : & terms(iterm_of_term),&
1322 : : & term%terms(iterm_of_term)%power_disp, &
1323 : : & term%terms(iterm_of_term)%power_strain,&
1324 : : & term%terms(iterm_of_term)%strain, &
1325 : : & term%terms(iterm_of_term)%weight, &
1326 : 24 : & check=.TRUE.)
1327 : 24 : terms(iterm_of_term)%nstrain = 0
1328 [ + + ]: 48 : terms(iterm_of_term)%power_strain = 0
1329 [ + + ]: 49 : terms(iterm_of_term)%strain = 0
1330 : : !DMSG(terms(iterm_of_term)%debug_str)
1331 : : enddo
1332 : :
1333 : 1 : call polynomial_coeff_free(term)
1334 : : !Reinitial term
1335 : : !check=.TRUE. checks for duplicate terms
1336 : 1 : call polynomial_coeff_init(coeff,nterm_of_term,term,terms, check=.TRUE.)
1337 : : !DMSG(term%debug_str)
1338 : :
1339 : :
1340 [ + + ]: 25 : do iterm_of_term=1,nterm_of_term
1341 : 25 : call polynomial_term_free(terms(iterm_of_term))
1342 : : enddo
1343 : : !if(nterm_of_term /= term%nterm)then
1344 : : ! write(*,*) "nterm_of_term changed after deleting strain"
1345 : : !endif
1346 : :
1347 : :
1348 : 192 : end subroutine opt_filterdisp
1349 : : !!***
1350 : :
1351 : : !!****f* m_opt_effpot/opt_getHOstrain
1352 : : !!
1353 : : !! NAME
1354 : : !! opt_getHOstrain
1355 : : !!
1356 : : !! FUNCTION
1357 : : !! Get HO anharmnonic strain terms for bounding and add them to list
1358 : : !! of existing terms in effective potential
1359 : : !!
1360 : : !! INPUTS
1361 : : !! eff_pot<effective_potential_type>: datatype with all the information
1362 : : !! about the effective potential
1363 : : !! power_strain(2): start and stop order for strain terms
1364 : : !! comm: mpi communicator (at the moment only sequential tested)
1365 : : !!
1366 : : !! OUTPUT
1367 : : !! terms<polynomial_coeff_type>: list with original terms in effective
1368 : : !! potential + HO even strain terms
1369 : : !!
1370 : : !! SOURCE
1371 : :
1372 [ - + ]: 1 : subroutine opt_getHOstrain(terms,ncombi,nterm_start,eff_pot,power_strain,comm, max_nbody)
1373 : :
1374 : : !Arguments ------------------------------------
1375 : : !scalars
1376 : : integer,intent(in) :: comm
1377 : : type(polynomial_coeff_type),allocatable,intent(inout) :: terms(:)
1378 : : type(effective_potential_type), intent(in) :: eff_pot
1379 : : integer,intent(in) :: power_strain(2), max_nbody(:)
1380 : : integer,intent(out) :: ncombi,nterm_start
1381 : : !arrays
1382 : : !Logicals
1383 : : !Strings
1384 : : !Local variables ------------------------------
1385 : : !scalars
1386 : : integer :: nterm_tot_tmp
1387 : : integer :: i,ii
1388 : : !integer :: nbody, ref_nbody
1389 : : real(dp) :: coeff_ini
1390 : : !reals
1391 [ + + + + : 68 : type(crystal_t) :: crystal
+ + + + +
+ + + + +
+ + + + +
+ ]
1392 : : !arrays
1393 : 1 : type(polynomial_coeff_type),allocatable :: strain_terms_tmp(:)
1394 : : !Logicals
1395 : : !Strings
1396 : : character(len=1000) :: message
1397 : : !*************************************************************************
1398 : : !Get variables
1399 [ + - + - : 1 : crystal = eff_pot%crystal
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
1400 : 1 : coeff_ini = 1000000
1401 : :
1402 : 1 : write(message, '(a,(80a),a)' ) ch10,&
1403 [ + - + + ]: 81 : & ('_',ii=1,80),ch10
1404 : 1 : call wrtout(ab_out,message,'COLL')
1405 : 1 : call wrtout(std_out,message,'COLL')
1406 : 1 : write(message,'(3a)' )ch10,&
1407 : 2 : & ' Chreate high order strain terms ',ch10
1408 : 1 : call wrtout(ab_out,message,'COLL')
1409 : 1 : call wrtout(std_out,message,'COLL')
1410 : :
1411 : :
1412 : : !1406 get count of high order even anharmonic strain terms and the strain terms itself
1413 : 1 : call polynomial_coeff_getEvenAnhaStrain(strain_terms_tmp,crystal,ncombi,power_strain,comm, max_nbody)
1414 : : ! Allocate my_coeffs with ncombi free space to work with
1415 : :
1416 : :
1417 : :
1418 : 1 : nterm_start = eff_pot%anharmonics_terms%ncoeff
1419 : 1 : nterm_tot_tmp = eff_pot%anharmonics_terms%ncoeff + ncombi
1420 [ - + + - : 7 : ABI_MALLOC(terms,(nterm_tot_tmp))
+ - + - -
+ - + - +
+ + + - ]
1421 [ + + ]: 5 : do i=1,nterm_tot_tmp
1422 [ + + ]: 5 : if(i<=nterm_start)then
1423 : : call polynomial_coeff_init(coeff_ini,eff_pot%anharmonics_terms%coefficients(i)%nterm,terms(i),&
1424 : : & eff_pot%anharmonics_terms%coefficients(i)%terms,eff_pot%anharmonics_terms%coefficients(i)%name,&
1425 : 2 : & check=.TRUE.)
1426 : : !DMSG(terms(i)%debug_str)
1427 : : else
1428 [ - + ]: 2 : if (.not.allocated(strain_terms_tmp(i-nterm_start)%terms)) then
1429 : 0 : write(message,'(4a)' )ch10,&
1430 : 0 : & 'Error in opt_getHOstrain: strain_terms_tmp(i-nterm_start)%terms not allocated',ch10,&
1431 : 0 : & 'Action: Contact Abinit Group',ch10
1432 : 0 : ABI_ERROR(message)
1433 : : endif
1434 : : call polynomial_coeff_init(coeff_ini,strain_terms_tmp(i-nterm_start)%nterm,terms(i),&
1435 : : & strain_terms_tmp(i-nterm_start)%terms,strain_terms_tmp(i-nterm_start)%name,&
1436 : 2 : & check=.TRUE.)
1437 : : !DMSG(strain_terms_tmp(i-nterm_start)%debug_str)
1438 : : endif
1439 : : enddo
1440 : :
1441 : 1 : call polynomial_coeff_list_free(strain_terms_tmp)
1442 : :
1443 [ - + - - : 1 : end subroutine opt_getHOstrain
- - - - -
- - - - -
- - - - -
- - - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
1444 : : !!***
1445 : :
1446 : : !!****f* m_opt_effpot/opt_getHOcrossdisp
1447 : : !!
1448 : : !! NAME
1449 : : !! opt_getHOcrossdisp
1450 : : !!
1451 : : !! FUNCTION
1452 : : !! Get even high order displacement terms for a given input term and
1453 : : !! add them to an excisting list of terms. If the term is strain phonon type
1454 : : !! the strain part gets deleted and the high order terms for the displacement
1455 : : !! part are computed.
1456 : : !! Example: for a tree linear term with three displacements x*y*z the even high order
1457 : : !! possibilites are computed and stored.
1458 : : !! 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.
1459 : : !!
1460 : : !! INPUTS
1461 : : !! eff_pot<effective_potential_type>: datatype with all the information
1462 : : !! about the effective potential
1463 : : !! power_disp(2): start and stop order for disp terms
1464 : : !! comm: mpi communicator (at the moment only sequential tested)
1465 : : !!
1466 : : !! OUTPUT
1467 : : !! terms<polynomial_coeff_type>: list with original terms in effective
1468 : : !! potential + HO even disp terms
1469 : : !!
1470 : : !! SOURCE
1471 : :
1472 : 1 : subroutine opt_getHOcrossdisp(terms_out,ncombi,term_in,power_disp)
1473 : :
1474 : : !Arguments ------------------------------------
1475 : : !scalars
1476 : : type(polynomial_coeff_type),allocatable,intent(inout) :: terms_out(:)
1477 : : type(polynomial_coeff_type),intent(inout) :: term_in
1478 : : integer,intent(in) :: power_disp(2)
1479 : : integer,intent(out) :: ncombi
1480 : : !arrays
1481 : : !Logicals
1482 : : !Strings
1483 : : !Local variables ------------------------------
1484 : : !scalars
1485 : : integer :: ndisp,nterm_of_term,nstrain,nbody_tot
1486 : : integer :: order_start,order_stop,norder
1487 : : integer :: order_start_str,order_stop_str
1488 : : integer :: icombi,idisp,iterm_of_term
1489 : : integer :: ncombi_tot,ncombi_str
1490 : : !reals
1491 : : real(dp) :: coeff_ini=1
1492 : : !arrays
1493 : 1 : type(polynomial_coeff_type) :: term
1494 : : integer,allocatable :: ncombi_order(:),ncombi_order_str(:)
1495 : : !Logicals
1496 : : logical :: had_strain
1497 : : !Strings
1498 : : character(len=1000) :: message
1499 : : !*************************************************************************
1500 : : !Get/Set Variables
1501 : 1 : norder = abs(((power_disp(2)-power_disp(1))/2)) + 1
1502 [ - + + - : 3 : ABI_MALLOC(ncombi_order,(norder))
+ - - + -
+ ]
1503 [ - + + - : 2 : ABI_MALLOC(ncombi_order_str,(norder))
- + - + ]
1504 [ + + ]: 2 : ncombi_order = 0
1505 [ + + ]: 2 : ncombi_order_str = 0
1506 : 1 : order_start_str = 0
1507 : 1 : order_stop_str = 0
1508 : :
1509 : 1 : ncombi = 0
1510 : : !Get this term (iterm) and infromations about it
1511 : : !Get number of displacements and equivalent terms for this term
1512 : : !Chose term one to get ndisp. ndisp is equal for all terms of the term
1513 : : !Get minimum oder for this term
1514 : : !Get total number of terms in effpot for message
1515 : 1 : ndisp = term_in%terms(1)%ndisp
1516 : 1 : nstrain = term_in%terms(1)%nstrain
1517 : 1 : nbody_tot = ndisp + nstrain
1518 : 1 : nterm_of_term = term_in%nterm
1519 : 1 : call polynomial_coeff_init(coeff_ini,nterm_of_term,term,term_in%terms,term_in%name, check=.true.)
1520 : : !DMSG(term%debug_str)
1521 : : ! Check if term has strain component.
1522 : : ! If yes filter strain and fit high order atomic displacement terms
1523 : 1 : had_strain = .FALSE.
1524 [ + - ]: 1 : if(term%terms(1)%nstrain /= 0)then
1525 : : ! Message to Output
1526 : 1 : write(message,'(5a)' )ch10,&
1527 : 1 : & '- Term has strain compenent',ch10,&
1528 : 2 : & ' -> Filter Displacement',ch10
1529 : 1 : call wrtout(ab_out,message,'COLL')
1530 : 1 : call wrtout(std_out,message,'COLL')
1531 : 1 : call opt_filterdisp(term,nterm_of_term)
1532 : : !Get new value of symmetry equivalent term nterm_of_term
1533 : 1 : nterm_of_term = term%nterm
1534 : : !Remember if this term had strain
1535 : 1 : had_strain = .TRUE.
1536 : : !cycle
1537 : : endif
1538 : : ! Ok we want it. Let's go.
1539 : :
1540 : : ! get start and stop order for this term
1541 : 1 : call opt_getHOforterm(term,power_disp,order_start,order_stop)
1542 [ + - ]: 1 : if(had_strain) call opt_getHOforterm(term_in,power_disp,order_start_str,order_stop_str)
1543 [ - + ]: 1 : if(order_start == 0)then
1544 : : ! Message to Output
1545 : 0 : write(message,'(5a,I2,a,I2,3a)' )ch10,&
1546 : 0 : & " ==> High order cross product terms for term ", trim(term%name),ch10,&
1547 : 0 : & " ==> do not fit into specified order range from ", power_disp(1),' to ',power_disp(2),ch10,&
1548 : 0 : & " ==> Can not construct high order cross product bounding term",ch10
1549 : 0 : call wrtout(ab_out,message,'COLL')
1550 : 0 : call wrtout(std_out,message,'COLL')
1551 [ # # ]: 0 : ABI_SFREE(ncombi_order)
1552 [ # # ]: 0 : ABI_SFREE(ncombi_order_str)
1553 : 0 : return
1554 : : end if
1555 : :
1556 [ - + - - ]: 1 : if(order_start_str == 0 .and. had_strain)then
1557 : : ! Message to Output
1558 : 0 : write(message,'(5a,I2,a,I2,3a)' )ch10,&
1559 : 0 : & " ==> High order cross product terms for term ", trim(term_in%name),ch10,&
1560 : 0 : & " ==> do not fit into specified order range from ", power_disp(1),' to ',power_disp(2),ch10,&
1561 : 0 : & " ==> Can not construct high order cross product bounding term",ch10
1562 : 0 : call wrtout(ab_out,message,'COLL')
1563 : 0 : call wrtout(std_out,message,'COLL')
1564 : 0 : had_strain = .FALSE.
1565 : : end if
1566 : : ! get total amount of combinations and combinations per order for the term
1567 : 1 : call opt_getCombisforterm(order_start,order_stop,ndisp,ncombi,ncombi_order)
1568 [ + - ]: 1 : if(had_strain)then
1569 : 1 : call opt_getCombisforterm(order_start_str,order_stop_str,nbody_tot,ncombi_str,ncombi_order_str)
1570 : : !write(std_out,*) "I was here ncombi_str is: ", ncombi_str
1571 [ - + + - : 6 : ABI_MALLOC(terms_out,(ncombi+ncombi_str))
+ - + - -
+ - + - +
+ + + - ]
1572 : 2 : ncombi_tot = ncombi+ncombi_str
1573 : : else
1574 [ # # # # : 0 : ABI_MALLOC(terms_out,(ncombi))
# # # # #
# # # # #
# # # # ]
1575 : 0 : ncombi_tot = ncombi
1576 : : endif
1577 : : ! Copy current term to the ncombination elemenst a the end in array terms
1578 : : ! change the value of their coefficient to a start value
1579 : : ! The start is estimed to not be larger then half the initial term's value
1580 : : ! This is because higher order terms should have smaller coefficients
1581 [ + + ]: 4 : do icombi=1,ncombi_tot
1582 [ + + ]: 3 : if(icombi <= ncombi)then
1583 : 2 : coeff_ini = 1 !abs(terms_out(icombi)%coefficient / 2)
1584 : 2 : nterm_of_term = term%nterm
1585 : 2 : call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out(icombi),term%terms, check=.true.)
1586 : : !DMSG(terms_out(icombi)%debug_str)
1587 : : else
1588 : 1 : coeff_ini = 10d3
1589 : 1 : nterm_of_term = term_in%nterm
1590 : 1 : call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out(icombi),term_in%terms, check=.true.)
1591 : : !DMSG(terms_out(icombi)%debug_str)
1592 : : endif
1593 : : ! Set the power of all terms we want to add to two. We find the correct power later
1594 : : ! Change the weight of the term to 1 (even terms have allways weight=1)
1595 [ + + ]: 76 : do iterm_of_term=1,nterm_of_term
1596 : 72 : terms_out(icombi)%terms(iterm_of_term)%weight = 1
1597 [ + + ]: 72 : if(icombi > ncombi)then
1598 [ + + ]: 48 : terms_out(icombi)%terms(iterm_of_term)%power_strain = 2
1599 : 24 : coeff_ini = 10d3 !abs(terms_out(icombi)%coefficient / 2)
1600 : 24 : terms_out(icombi)%coefficient = coeff_ini
1601 : : ! elseif(icombi>2*ncombi)then
1602 : : ! terms_out(icombi)%terms(iterm_of_term)%power_strain = 4
1603 : : ! coeff_ini = 10d5 !abs(terms_out(icombi)%coefficient / 2)
1604 : : ! terms_out(icombi)%coefficient = coeff_ini
1605 : : endif
1606 [ + + ]: 219 : do idisp=1,ndisp
1607 : 216 : terms_out(icombi)%terms(iterm_of_term)%power_disp(idisp) = 2
1608 : : enddo !idisp
1609 : : enddo !iterm_of_term
1610 : : enddo !icombi
1611 : :
1612 : : !If term had strain we had to reinitialize it in the process
1613 : : !Refree memory
1614 : : !if(had_strain)
1615 : 1 : call polynomial_coeff_free(term)
1616 : :
1617 : : ! Get high order combinations
1618 [ + - ]: 1 : if(had_strain)then
1619 : 1 : call opt_getHoTerms(terms_out(:ncombi),order_start,order_stop,ndisp,ncombi_order)
1620 : 1 : call opt_getHoTerms(terms_out(ncombi+1:),order_start_str,order_stop_str,ndisp,ncombi_order_str)
1621 : 1 : ncombi = ncombi_tot
1622 : : else
1623 : 0 : call opt_getHoTerms(terms_out,order_start,order_stop,ndisp,ncombi_order)
1624 : : endif
1625 : : !DEALLOCATION
1626 [ + - ]: 1 : ABI_SFREE(ncombi_order)
1627 [ + - ]: 1 : ABI_SFREE(ncombi_order_str)
1628 : :
1629 [ - + - - : 3 : end subroutine opt_getHOcrossdisp
- - - - -
- - - - -
- - - - -
+ - + ]
1630 : : !!***
1631 : :
1632 : : !!****f* m_opt_effpot/opt_getSingleDispTerms
1633 : : !!
1634 : : !! NAME
1635 : : !! opt_getSingleDispTerms
1636 : : !!
1637 : : !! FUNCTION
1638 : : !! Get polynomial terms (<polynomial_coeff_type>) with single displacements
1639 : : !! at second order inside a given range defined by the supercell size
1640 : : !!
1641 : : !! INPUTS
1642 : : !! sc_size(3): supercell size
1643 : : !! crystal<type(crystal_t)>: all information about the crystal
1644 : : !! comm: mpi communicator (at the moment only sequential tested)
1645 : : !!
1646 : : !! OUTPUT
1647 : : !! terms<polynomial_coeff_type>: list single displacement polynomial_coeffs
1648 : : !!
1649 : : !! SOURCE
1650 : :
1651 : 1 : subroutine opt_getSingleDispTerms(terms,crystal, sc_size,comm)
1652 : :
1653 : : !Arguments ------------------------------------
1654 : : !scalars
1655 : : integer,intent(in) :: comm
1656 : : type(polynomial_coeff_type),allocatable,intent(inout) :: terms(:)
1657 : : type(crystal_t),intent(inout) :: crystal
1658 : : real(dp) :: cutoff
1659 : : !arrays
1660 : : integer :: sc_size(3)
1661 : :
1662 : : !Logicals
1663 : : !Strings
1664 : : !Local variables ------------------------------
1665 : : !scalars
1666 : : integer :: natom,nsym,nrpt,ncoeff_sym,nstr_sym
1667 : : integer :: ncoeff,ncoeff_out,power_strph,option_GN,option
1668 : : integer :: nterms_out,nterm1,iterm1,iterm2,ind,iatom,i
1669 : : integer :: ncopy
1670 : : integer :: ii !,ia,ib,r1,r2,r3
1671 : : !integer :: irpt,irpt_ref
1672 : : integer :: master,nproc,my_rank
1673 : : !arrays
1674 : : integer :: power_disp(2)
1675 : 1 : integer,allocatable :: cell(:,:)
1676 : 1 : integer,allocatable :: list_symcoeff(:,:,:),list_symstr(:,:,:)
1677 : 1 : logical,allocatable :: terms_to_copy(:)
1678 : 1 : type(polynomial_coeff_type),allocatable :: terms_tmp(:),terms_tmp2(:)
1679 : : !type(polynomial_coeff_type),allocatable :: terms(:)
1680 : : !real(dp),allocatable :: xcart(:,:),xred(:,:),rpt(:,:)
1681 : : real(dp) :: rprimd(3,3),range_ifc(3)
1682 : 1 : real(dp),allocatable :: dist(:,:,:,:)
1683 : 1 : character(len=5),allocatable :: symbols(:)
1684 : : !Logicals
1685 : : logical :: iam_master,need_verbose
1686 : : !Strings
1687 : : character(len=1000) :: message
1688 : : !*************************************************************************
1689 : :
1690 : 1 : option = 2
1691 : :
1692 : : if(option == 1)then
1693 : : !MPI variables
1694 : : master = 0
1695 : : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1696 : : iam_master = (my_rank == master)
1697 : :
1698 : : !Set/Get other variables
1699 : : !natom = crystal%natom
1700 : : !nsym = crystal%nsym
1701 : : rprimd = crystal%rprimd
1702 : : need_verbose = .TRUE.
1703 : :
1704 : :
1705 : : call prepare_for_getList(crystal,sc_size, dist, cell, natom, nsym, nrpt, range_ifc , symbols)
1706 : :
1707 : : ! FIXME: this is dangerous!
1708 : : ! It assumes that the structure is cubic in a usual axis setting.
1709 : : cutoff = rprimd(1,1)
1710 : :
1711 : : if(need_verbose)then
1712 : : write(message,'(1a)')' Generation of the list of all the possible coefficients'
1713 : : call wrtout(std_out,message,'COLL')
1714 : : end if
1715 : : call polynomial_coeff_getList(cell,crystal,dist,list_symcoeff,list_symstr,&
1716 : : & natom,nstr_sym,ncoeff_sym,nrpt,range_ifc,cutoff,sc_size=sc_size)
1717 : :
1718 : : ABI_SFREE(dist)
1719 : : !ABI_FREE(rpt)
1720 : :
1721 : : !write(*,*) "polynomial_getList worked"
1722 : :
1723 : : !Get Order1 term s
1724 : : !Check difference between ncoeff_out, ncoeff
1725 : : call polynomial_coeff_getOrder1(cell,terms,list_symcoeff,natom,nterms_out,ncoeff_sym,nrpt,nsym,symbols)
1726 : :
1727 : : !do ii=1,nterms_out
1728 : : ! write(*,*) "Term(",ii,"/",nterms_out,"): ", terms(ii)%name
1729 : : !enddo
1730 : :
1731 : : elseif(option == 2)then
1732 : : !Get/set variables
1733 : : ! FIXME: hexu: check these values of 2. Why are they are hard coded here.
1734 : : ! Does this mean we only generate high-order terms in 2x2x2 cell?
1735 : 1 : power_disp = (/2,2/)
1736 : 1 : power_strph = zero
1737 : 1 : option_GN = 0
1738 : 1 : sc_size = (/2,2,2/)
1739 : 1 : cutoff = 0
1740 : 1 : natom = crystal%natom
1741 : : ! XXX: hexu: why cutoff = sum of axis lengths?
1742 [ + + ]: 4 : do ii=1,3
1743 : : cutoff = cutoff + sqrt(crystal%rprimd(ii,1)**2 + &
1744 : : & crystal%rprimd(ii,2)**2 + &
1745 : 4 : & crystal%rprimd(ii,3)**2)
1746 : : enddo
1747 : :
1748 : :
1749 : : !do iatom=1,3
1750 [ + + ]: 6 : do iatom=1,natom !Subhadeep
1751 : : ! TODO: to be validated.
1752 : : !do iatom=1,crystal%nirredat
1753 : : call polynomial_coeff_getNorder(terms_tmp,crystal,cutoff,ncoeff,ncoeff_out,power_disp,&
1754 : : & power_strph,option_GN,sc_size,comm,anharmstr=.false.,spcoupling=.false.,&
1755 : : & only_odd_power=.false.,only_even_power=.true.,verbose=.false.,&
1756 : : & compute_symmetric=.false.,fit_iatom=iatom, &
1757 : 5 : & max_nbody=[999,999,999,999,999,999, 999,999,999,999])
1758 : : !TEST MS
1759 : : ! write(std_out,*) "behind call getNorder"
1760 : : ! write(std_out,*) "ncoeff_out: ", ncoeff_out
1761 : : ! do ii=1,ncoeff_out
1762 : : ! write(*,*) "Term(",ii,"/",ncoeff_out,"): ", terms_tmp(ii)%name
1763 : : ! enddo
1764 : : !TEST MS
1765 [ + + ]: 6 : if(iatom == 1)then
1766 [ - + + - : 13 : ABI_MALLOC(terms,(size(terms_tmp)))
+ - + - -
+ - + - +
+ + + - ]
1767 : 1 : call coeffs_list_copy(terms,terms_tmp)
1768 : : else
1769 [ + + + - : 12 : ABI_MALLOC(terms_to_copy,(size(terms_tmp)))
+ - + + -
+ - + -
+ ]
1770 : : ! note: when iatom>1, terms is already initialized.
1771 : 4 : nterm1 = size(terms)
1772 [ - + + - : 145 : ABI_MALLOC(terms_tmp2,(nterm1))
+ - + - -
+ - + - +
+ + ]
1773 : 4 : terms_tmp2 = terms
1774 [ + + ]: 44 : terms_to_copy = .TRUE.
1775 [ + + ]: 44 : do iterm1=1,size(terms_tmp)
1776 [ + + ]: 795 : do iterm2=1,size(terms)
1777 [ - + ]: 791 : if(terms_tmp(iterm1) == terms(iterm2))then
1778 : 0 : terms_to_copy(iterm1) = .FALSE.
1779 : 0 : exit
1780 : : endif
1781 : : enddo!iterm1
1782 : : enddo!iterm2
1783 [ + + + - ]: 44 : ncopy = count(terms_to_copy)
1784 : 4 : call polynomial_coeff_list_free(terms)
1785 [ - + + - : 185 : ABI_MALLOC(terms,(nterm1+ncopy))
+ - + - -
+ - + - +
+ + + - ]
1786 : 4 : call coeffs_list_copy(terms(:nterm1),terms_tmp2)
1787 : 4 : ind = 0
1788 [ + + ]: 44 : do i =1,size(terms_tmp)
1789 [ + - ]: 44 : if(terms_to_copy(i))then
1790 : 40 : ind=ind+1
1791 : : call polynomial_coeff_init(terms_tmp(i)%coefficient,terms_tmp(i)%nterm,terms(nterm1+ind),terms_tmp(i)%terms,&
1792 : 40 : & terms_tmp(i)%name,check=.TRUE.)
1793 : : !DMSG(terms(nterm1+ind)%debug_str)
1794 : : endif
1795 : : enddo!i=1,nterm1+ncopy
1796 : 4 : call polynomial_coeff_list_free(terms_tmp)
1797 : 4 : call polynomial_coeff_list_free(terms_tmp2)
1798 [ - + ]: 4 : ABI_SFREE(terms_to_copy)
1799 : : endif!iatom==1
1800 : : enddo !iatom=1,natom
1801 : : ! call polynomial_coeff_getNorder(terms,crystal,cutoff,ncoeff,ncoeff_out,power_disp,&
1802 : : !& power_strph,option_GN,sc_size,comm,anharmstr=.false.,spcoupling=.false.,&
1803 : : !& only_odd_power=.false.,only_even_power=.true.,verbose=.false.,&
1804 : : !& compute_symmetric=.false.)
1805 : :
1806 : : endif !option
1807 : : !TEST MS
1808 : : ! write(std_out,*) "behind call getNorder"
1809 : : ! write(std_out,*) "ncoeff_out: ", size(terms)
1810 : : ! do ii=1,size(terms)
1811 : : ! write(*,*) "Term(",ii,"/",size(terms),"): ", terms(ii)%name
1812 : : ! enddo
1813 : : !TEST MS
1814 : :
1815 [ - + - + : 1 : end subroutine opt_getSingleDispTerms
- - - - -
- - - - -
- - - - -
- - - - -
- + - - -
- - - - -
- - - - -
- - - - -
- - ]
1816 : : !!***
1817 : :
1818 : : !!****f* m_opt_effpot/opt_getHOSingleDispTerms
1819 : : !!
1820 : : !! NAME
1821 : : !! opt_getHOSingleDispTerms
1822 : : !!
1823 : : !! FUNCTION
1824 : : !! For a given anharmonic term that might consits of product of
1825 : : !! terms find all even high order single displacement terms
1826 : : !! Example: Input term: x*y*z
1827 : : !! Input HO-range: 6 8
1828 : : !! Output terms: x^6,x^8,y^6,y^8,z^6,z^8
1829 : : !! Caution only atomic displacements are taken into account
1830 : : !!
1831 : : !! INPUTS
1832 : : !! term_in<polynomial_coeff_type>: input anharmonic term
1833 : : !! crystal<type(crystal_t)>: all information about the crystal
1834 : : !! single_disp_terms<polynomial_coeff_out>: list of single disp terms at
1835 : : !! second order to select terms from
1836 : : !! power_disp(2): Start and stop power for HO terms
1837 : : !! comm: mpi communicator (at the moment only sequential tested)
1838 : : !!
1839 : : !! OUTPUT
1840 : : !! terms_out<polynomial_coeff_out>: output high order even terms
1841 : : !! ncoeff: number of coefficients
1842 : : !!
1843 : : !! SOURCE
1844 : :
1845 [ - + - + ]: 1 : subroutine opt_getHOSingleDispTerms(term_in,terms_out,symbols,single_disp_terms,power_disp,ncoeff)
1846 : :
1847 : : !Arguments ------------------------------------
1848 : : !scalars
1849 : : integer,intent(out) :: ncoeff
1850 : : type(polynomial_coeff_type),intent(in) :: term_in
1851 : : type(polynomial_coeff_type),intent(in) :: single_disp_terms(:)
1852 : : type(polynomial_coeff_type),allocatable,intent(out) :: terms_out(:)
1853 : : !type(crystal_t),intent(inout) :: crystal
1854 : : !arrays
1855 : : integer, intent(in) :: power_disp(2)
1856 : : character(len=5),intent(in) :: symbols(:)
1857 : : !Logicals
1858 : : !Strings
1859 : : !Local variables ------------------------------
1860 : : !scalars
1861 : : integer :: ndisp,norder, nterm_of_term
1862 : : integer :: icoeff,iorder,idisp, iterm1,iterm2,iterm3
1863 : : real(dp) :: coeff_ini = 1
1864 : : !Strings
1865 : : character(len=200):: name
1866 : : !arrays
1867 : : type(polynomial_coeff_type),allocatable :: terms_out_tmp(:)
1868 : : !Logicals
1869 : 1 : logical,allocatable :: found(:)
1870 : : !*************************************************************************
1871 : : !Get/Set Variables
1872 : : !Number of output terms
1873 : 1 : ndisp = term_in%terms(1)%ndisp
1874 : 1 : norder = abs(power_disp(2)-power_disp(1))/2 + 1
1875 : 1 : ncoeff = norder * ndisp
1876 : : !Allocate output terms
1877 [ - + + - : 5 : ABI_MALLOC(terms_out_tmp,(ncoeff))
+ - + - -
+ - + +
+ ]
1878 : : !find equivalent second order terms in list of single disp terms
1879 : : !for each displacement in input term
1880 : : !Transfer to output term and increase order
1881 : 1 : icoeff = 0
1882 [ + + ]: 3 : do idisp=1,ndisp
1883 [ + + ]: 103 : do iterm1=1,size(single_disp_terms)
1884 [ + + ]: 2346 : do iterm2=1,single_disp_terms(iterm1)%nterm
1885 [ + + + + : 2980 : if(all(term_in%terms(1)%atindx(:,idisp) == single_disp_terms(iterm1)%terms(iterm2)%atindx(:,1)))then
+ + ]
1886 [ + + + + : 606 : if(all(term_in%terms(1)%cell(:,:,idisp) == single_disp_terms(iterm1)%terms(iterm2)%cell(:,:,1)))then
+ + + + ]
1887 [ + + ]: 6 : if(term_in%terms(1)%direction(idisp) == single_disp_terms(iterm1)%terms(iterm2)%direction(1))then
1888 [ + + ]: 4 : do iorder=1,norder
1889 : 2 : icoeff = icoeff + 1
1890 [ + - + - : 32 : terms_out_tmp(icoeff) = single_disp_terms(iterm1)
+ + + - +
- + - + -
+ - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- ]
1891 : 2 : nterm_of_term = single_disp_terms(iterm1)%nterm
1892 : : !Change order of term
1893 : : call polynomial_coeff_init(coeff_ini,nterm_of_term,terms_out_tmp(icoeff),&
1894 : 2 : & single_disp_terms(iterm1)%terms(:), check=.true.)
1895 : : !DMSG(terms_out_tmp(icoeff)%debug_str)
1896 : :
1897 [ + + ]: 34 : do iterm3=1,nterm_of_term
1898 [ + + ]: 62 : terms_out_tmp(icoeff)%terms(iterm3)%power_disp = power_disp(1) + (iorder-1)*2
1899 : : enddo !iterm3
1900 : : enddo !iorder
1901 : : endif
1902 : : endif
1903 : : endif
1904 : : enddo !iterm2
1905 : : enddo !iterm1
1906 : : enddo!idisp
1907 : : !Change Name
1908 [ + + ]: 3 : do icoeff=1,ncoeff
1909 : 2 : call polynomial_coeff_getName(name,terms_out_tmp(icoeff),symbols,recompute=.TRUE.)
1910 : 3 : call polynomial_coeff_SetName(name,terms_out_tmp(icoeff))
1911 : : enddo
1912 : :
1913 : : !Check for doubles and delete them
1914 : : !First count irreducible terms
1915 [ - + + - : 3 : ABI_MALLOC(found,(ncoeff))
+ - + - -
+ - + ]
1916 [ + + ]: 3 : found = .FALSE.
1917 : : iterm3 = 0
1918 [ + + ]: 3 : do iterm1=1,ncoeff
1919 [ + + ]: 4 : do iterm2=iterm1+1,ncoeff
1920 [ - + - - ]: 3 : if(terms_out_tmp(iterm1) == terms_out_tmp(iterm2) .and. .not. found(iterm2))then
1921 : 0 : found(iterm2) = .TRUE.
1922 : 0 : iterm3 = iterm3 + 1
1923 : : endif
1924 : : enddo
1925 : : enddo
1926 : 1 : iterm3 = ncoeff - iterm3
1927 [ - + + - : 5 : ABI_MALLOC(terms_out,(iterm3))
+ - + - -
+ - + - +
+ + + - ]
1928 : 1 : iterm3 = 0
1929 [ + + ]: 3 : do iterm1=1,ncoeff
1930 [ + - ]: 3 : if(.not. found(iterm1))then
1931 : 2 : iterm3 = iterm3 + 1
1932 : : call polynomial_coeff_init(coeff_ini,terms_out_tmp(iterm1)%nterm,terms_out(iterm3),&
1933 : 2 : & terms_out_tmp(iterm1)%terms,terms_out_tmp(iterm1)%name, check=.TRUE.)
1934 : : !DMSG(terms_out(iterm3)%debug_str)
1935 : : endif
1936 : : enddo
1937 [ + - ]: 1 : ABI_SFREE(found)
1938 : 1 : call polynomial_coeff_list_free(terms_out_tmp)
1939 : 1 : ncoeff = iterm3
1940 [ - + - - : 1 : end subroutine opt_getHOSingleDispTerms
- - - - -
- - - - -
- - - - -
- - - ]
1941 : : !!***
1942 : :
1943 : :
1944 : :
1945 : : !!****f* m_opt_effpot/opt_boundcoeff
1946 : : !! NAME
1947 : : !! opt_boundcoeff
1948 : : !!
1949 : : !! FUNCTION
1950 : : !!
1951 : : !! optimize a bound coefficient if optimized value is negative
1952 : : !! put an positive value that respects a precision penalty
1953 : : !!
1954 : : !! INPUTS
1955 : : !!
1956 : : !! OUTPUT
1957 : : !!
1958 : : !! SOURCE
1959 : :
1960 : 1 : function opt_boundcoeff(yvalues,cvalues,penalty_in) result (coeff)
1961 : : !Arguments ------------------------------------
1962 : :
1963 : : !Arguments ------------------------------------
1964 : : real(dp),intent(in) :: yvalues(2),cvalues(2),penalty_in
1965 : : real(dp) :: coeff
1966 : : !local
1967 : : !variable
1968 : : real(dp) :: a,b,coeff_tmp,x1,x2,penalty
1969 : : !array
1970 : : ! *************************************************************************
1971 : :
1972 : 1 : a = ( (yvalues(1) - 1) - (yvalues(2)-1)*(cvalues(1)/cvalues(2))) / (cvalues(1)**2 - cvalues(1)*cvalues(2))
1973 : :
1974 : : b = ( (yvalues(2) - 1)/cvalues(2) ) - ( (yvalues(1) -1)*cvalues(2) - (yvalues(2) - 1)*cvalues(1) )&
1975 : 1 : & / (cvalues(1)**2 - cvalues(1)*cvalues(2))
1976 : :
1977 : 1 : penalty = penalty_in - 1
1978 [ + - + - ]: 1 : if (a/=a .or. b/=b .or. a==0) then
1979 : 1 : coeff = 0.0_dp
1980 : : return
1981 : : end if
1982 : 1 : coeff_tmp = -b/(2*a)
1983 : : !write(*,*) "coeff_tmp", coeff_tmp
1984 [ + - ]: 1 : if(coeff_tmp > 0)then
1985 : : coeff = coeff_tmp
1986 : : else
1987 : 1 : x1 = (-b + sqrt(b**2 + 4*a*penalty)) / (2*a) ! 1.001 penalty value
1988 : 1 : x2 = (-b - sqrt(b**2 + 4*a*penalty)) / (2*a)
1989 [ - + ]: 1 : if(x1>0)then
1990 : : coeff = x1
1991 : : else
1992 : 0 : coeff = x2
1993 : : endif
1994 : : endif
1995 : :
1996 : : end function opt_boundcoeff
1997 : : !!***
1998 : :
1999 : : !!****f* m_opt_effpot/check_to_skip
2000 : : !! NAME
2001 : : !! check_to_skip
2002 : : !!
2003 : : !! FUNCTION
2004 : : !!
2005 : : !! Check if term contains only bodies with even power
2006 : : !! and has a positive coefficient. If yes term doesn't need
2007 : : !! a bounding high order equivalent and we can skip it.
2008 : : !! Function retursn logical to_skip.
2009 : : !!
2010 : : !! INPUTS
2011 : : !!
2012 : : !! term<polynomial_coeff_type>:anharmonic term
2013 : : !!
2014 : : !! OUTPUT
2015 : : !!
2016 : : !! logical: to_skip
2017 : : !!
2018 : : !! SOURCE
2019 : :
2020 : 1 : function check_to_skip(term) result (to_skip)
2021 : : !Arguments ------------------------------------
2022 : : type(polynomial_coeff_type),intent(in) :: term
2023 : : logical :: to_skip
2024 : : ! ------------------------------------
2025 : : !local
2026 : : !variable
2027 : : character(len=1000) :: message
2028 : : !array
2029 : : ! *************************************************************************
2030 : :
2031 : 1 : to_skip = .FALSE.
2032 : : ! Let's check if we really want all this mess
2033 : : ! 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
2034 [ + - + + : 2 : if(term%coefficient > 0 .and. .not. any(mod(term%terms(1)%power_disp(:),2) /= 0))then
- + - - ]
2035 [ # # # # : 0 : if(.not. any(mod(term%terms(1)%power_strain(:),2) /= 0))then
# # ]
2036 : : ! Message to Output
2037 : 0 : write(message,'(3a)' )ch10,&
2038 : 0 : & ' ==> No need for high order bounding term',ch10
2039 : 0 : call wrtout(ab_out,message,'COLL')
2040 : 0 : call wrtout(std_out,message,'COLL')
2041 : 0 : to_skip = .TRUE.
2042 : 0 : return
2043 : : end if
2044 : : end if
2045 : :
2046 : : end function check_to_skip
2047 : : !!***
2048 : :
2049 : 2 : subroutine generate_bounding_term_and_add_to_list(sympairs, nterm_start, ncombi, my_coeffs, temp_cntr)
2050 : : ! check if myterm
2051 : : !type(polynomial_coeff_type),target, intent(in) :: terms(:)
2052 : :
2053 : : type(polynomial_coeff_type), allocatable, intent(inout) :: my_coeffs(:)
2054 : : type(SymPairs_t), intent(inout) :: sympairs
2055 : : integer, intent(in) :: nterm_start, ncombi
2056 : : integer, intent(out) :: temp_cntr
2057 : :
2058 : 2 : type(polynomial_term_type), allocatable :: terms2(:)
2059 : : type(polynomial_term_type), pointer :: myterm=> null()
2060 : : type(polynomial_coeff_type), target, allocatable :: my_coeffs_tmp(:)
2061 : : integer :: idisp, my_nrpt, list_cntr, number_coeff, icombi
2062 : : integer :: jterm
2063 : : integer :: tmp_list(5), pwr
2064 : : logical :: found
2065 : : logical :: reverse_i, any_exists
2066 : 2 : logical, allocatable :: reverse(:), false_reverse(:), exists(:)
2067 : : integer :: counter, nterm, tot_power
2068 : 2 : type(polynomial_coeff_type):: temp_coeff
2069 : 2 : integer, allocatable :: list_disp(:)
2070 : : character(len=200):: name
2071 : : integer :: ncoeff
2072 : :
2073 : : ! copy the coefficients to a temporary array my_coeffs_tmp
2074 : 2 : ncoeff=size(my_coeffs)
2075 : :
2076 : :
2077 [ - + + - : 12 : ABI_MALLOC(my_coeffs_tmp,(ncoeff))
+ - + - -
+ - + +
+ ]
2078 : :
2079 : : ! check if my_coeffs i allocated and has the right size
2080 [ - + ]: 2 : if(.not. allocated(my_coeffs)) then
2081 : 0 : ABI_BUG("my_coeffs is not allocated")
2082 : : end if
2083 [ - + ]: 2 : if(size(my_coeffs) /= ncoeff) then
2084 : 0 : ABI_BUG("my_coeffs has the wrong size")
2085 : : end if
2086 [ - + ]: 2 : if(size(my_coeffs_tmp) /= ncoeff) then
2087 : 0 : ABI_BUG("my_coeffs_tmp has the wrong size")
2088 : : end if
2089 : :
2090 : 2 : my_coeffs_tmp=my_coeffs
2091 : :
2092 : : !call coeffs_list_copy(my_coeffs_tmp, my_coeffs)
2093 : :
2094 : : ! free the original array and allocate a new one with the correct size
2095 : 2 : call polynomial_coeff_list_free(my_coeffs)
2096 [ - + + - : 10 : ABI_MALLOC(my_coeffs, (ncoeff))
- + - + -
+ + + +
- ]
2097 : : !my_coeffs(1:nterm_start) = my_coeffs_tmp(1:nterm_start)
2098 : 2 : call coeffs_list_copy(my_coeffs(1:nterm_start), my_coeffs_tmp(1:nterm_start))
2099 : :
2100 : :
2101 : :
2102 : 2 : temp_cntr =0
2103 [ + + ]: 5 : do icombi=1, ncombi
2104 [ + - ]: 3 : if(size( my_coeffs_tmp(nterm_start+icombi)%terms) == 0) cycle
2105 : 3 : myterm=> my_coeffs_tmp(nterm_start+icombi)%terms(1)
2106 [ + + + + ]: 8 : tot_power=sum(myterm%power_disp) + sum(myterm%power_strain)
2107 [ - + + - : 9 : ABI_MALLOC(list_disp, (tot_power))
+ - + - -
+ - + -
+ ]
2108 [ - + + - : 6 : ABI_MALLOC(reverse, (tot_power))
- + - + -
+ ]
2109 [ - + + - : 6 : ABI_MALLOC(false_reverse, (tot_power))
- + - + -
+ ]
2110 : :
2111 [ + + ]: 21 : list_disp(:)=0
2112 [ + + ]: 21 : reverse(:)=.False.
2113 [ + + ]: 21 : false_reverse(:)=.False.
2114 : 3 : counter=0
2115 : : ! put the indices of the disp terms into a list
2116 [ + + ]: 5 : do idisp=1,myterm%ndisp
2117 : : ! for each disp, find its index in the pair list.
2118 : 2 : my_nrpt=find_irpt(cells=sympairs%cell, cell=myterm%cell(:, 2, idisp))
2119 : : tmp_list(:) = (/myterm%direction(idisp),myterm%atindx(1,idisp), &
2120 [ + + ]: 12 : & myterm%atindx(2,idisp),my_nrpt,int(myterm%weight) /)
2121 : 2 : found=.False. ! to find if the symmetry adapted term already exist.
2122 : 2 : reverse_i=.False.
2123 [ + + ]: 1518 : do list_cntr=1,size(sympairs%list_symcoeff, 2)
2124 : : !do isym=1, sympairs%nsym
2125 [ + + + + : 2220 : if (all(tmp_list(:4)==sympairs%list_symcoeff(:4,list_cntr,1))) then
+ + ]
2126 : 2 : number_coeff = sympairs%list_symcoeff(6,list_cntr,1)
2127 : 2 : found = .True.
2128 : : !if (found) exit
2129 : : end if
2130 : : !end do
2131 : : !if(found) exit
2132 : : end do
2133 [ - + ]: 2 : if(.not. found) then
2134 : 0 : reverse_i=.True.
2135 [ # # # # ]: 0 : my_nrpt=find_irpt(cells=sympairs%cell, cell=-myterm%cell(:, 2, idisp))
2136 : : tmp_list(:) = (/myterm%direction(idisp),myterm%atindx(2,idisp), &
2137 [ # # ]: 0 : & myterm%atindx(1,idisp),my_nrpt,-int(myterm%weight) /)
2138 [ # # ]: 0 : do list_cntr=1,size(sympairs%list_symcoeff, 2)
2139 : : !do isym=1, sympairs%nsym
2140 [ # # # # : 0 : if (all(tmp_list(:4)==sympairs%list_symcoeff(:4,list_cntr,1))) then
# # ]
2141 : 0 : number_coeff = sympairs%list_symcoeff(6,list_cntr,1)
2142 : 0 : found = .True.
2143 : : !if (found) exit
2144 : : end if
2145 : : !end do
2146 : : !if(found) exit
2147 : : end do
2148 : : end if
2149 : :
2150 [ - - ]: 3 : if (found )then
2151 [ + + ]: 6 : do pwr=1,myterm%power_disp(idisp)
2152 : 4 : counter=counter+1
2153 : 4 : list_disp(counter) = number_coeff
2154 : 6 : reverse(counter) = reverse_i
2155 : : end do
2156 : : else
2157 : 0 : ABI_BUG("The pair is not found in generated bounding terms.")
2158 : : end if
2159 : : end do
2160 : :
2161 [ + + ]: 6 : do idisp=1,myterm%nstrain
2162 [ + + ]: 20 : do pwr=1,myterm%power_strain(idisp)
2163 : 14 : counter = counter+1
2164 : 17 : list_disp(counter) = myterm%strain(idisp)+size(sympairs%list_symcoeff,2)
2165 : : end do
2166 : : end do
2167 : 3 : nullify(myterm)
2168 : :
2169 : : ! generate the terms with false reverse, and save to the temp_coeff.
2170 : 3 : nterm=sympairs%nsym
2171 [ - + + - : 153 : ABI_MALLOC(terms2, (nterm))
+ - + - -
+ - + - +
+ + ]
2172 : 3 : call sympairs%generateTerms(list_disp, tot_power, nterm, terms2, reverse=false_reverse)
2173 : : call polynomial_coeff_init(one,nterm,temp_coeff, &
2174 : 3 : &terms2(1:nterm), check=.true.)
2175 : 3 : call polynomial_term_list_free(terms2)
2176 : : !DMSG(temp_coeff%debug_str)
2177 : :
2178 : : call polynomial_coeff_getName(name, &
2179 : 3 : & temp_coeff,sympairs%symbols,recompute=.TRUE.)
2180 : :
2181 : : ! check if temp coeff already exists in the list of coeffs my_coeffs
2182 [ + - - + : 9 : ABI_MALLOC(exists, (nterm_start+icombi-1))
+ - + - +
- - + -
+ ]
2183 [ + + ]: 9 : exists=.False.
2184 [ + + ]: 9 : do jterm=1,(nterm_start+icombi-1)
2185 : 9 : exists(jterm) = coeffs_compare(my_coeffs(jterm),temp_coeff)
2186 : : enddo !jterm
2187 : 3 : call polynomial_coeff_free(temp_coeff)
2188 : :
2189 [ + + + - ]: 9 : any_exists=any(exists)
2190 [ - + ]: 3 : ABI_FREE(exists)
2191 : :
2192 : : ! if the term already exists, we skip it. Otherwise we add also the reverse.
2193 [ + - ]: 3 : if (.not. any_exists) then
2194 : 3 : temp_cntr = temp_cntr+1
2195 [ - + + - : 153 : ABI_MALLOC(terms2, (nterm))
+ - + - -
+ - + - +
+ + ]
2196 : 3 : call sympairs%generateTerms(list_disp, tot_power, nterm, terms2, reverse=reverse)
2197 : : call polynomial_coeff_init(one,nterm, &
2198 : 3 : & my_coeffs(nterm_start+temp_cntr),terms2, check=.true.)
2199 : : !DMSG(my_coeffs(nterm_start+temp_cntr)%debug_str)
2200 : 3 : call polynomial_term_list_free(terms2)
2201 : : end if
2202 : :
2203 [ + - ]: 3 : ABI_SFREE(list_disp)
2204 [ + - ]: 3 : ABI_SFREE(reverse)
2205 [ - + ]: 5 : ABI_SFREE(false_reverse)
2206 : : end do
2207 : :
2208 : 2 : call polynomial_coeff_list_free(my_coeffs_tmp)
2209 : :
2210 : : ! truncate my_coeffs.
2211 : 2 : call coeffs_list_truncate(my_coeffs, nterm_start+temp_cntr)
2212 [ - + - - : 2 : end subroutine generate_bounding_term_and_add_to_list
- - - - -
- - - - -
- - - - -
+ - - - -
- - - - -
- - - - -
- - - + -
- - - - -
- - - - -
- - - - -
- - - - -
+ - + ]
2213 : :
2214 : :
2215 : : end module m_opt_effpot
2216 : : !!***
|