Line data Source code
1 :
2 : !****f* ABINIT/m_polynomal_coeff
3 : !!
4 : !! NAME
5 : !! m_polynomial_coeff
6 : !!
7 : !! FUNCTION
8 : !! Module with the datatype polynomial coefficients
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2010-2026 ABINIT group (AM)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public Licence, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
16 : !!
17 : !! SOURCE
18 :
19 :
20 : #if defined HAVE_CONFIG_H
21 : #include "config.h"
22 : #endif
23 :
24 : #include "abi_common.h"
25 : !#include "trace.h"
26 :
27 :
28 : module m_polynomial_coeff
29 :
30 : use defs_basis
31 : use m_errors
32 : use m_abicore
33 : use m_polynomial_term
34 : USE_MPI
35 : use m_xmpi
36 :
37 : use m_sort, only : sort_dp
38 : use m_io_tools, only : open_file, get_unit
39 : use m_symtk, only : symchk, symatm
40 : use m_crystal, only : crystal_t,symbols_crystal
41 : use m_supercell, only : getPBCIndexes_supercell,distance_supercell,findBound_supercell
42 : !use m_geometry, only : xcart2xred,metric
43 : use m_dtfil, only : isfile
44 : use m_hashtable_strval, only: hash_table_t
45 : use m_dynamic_array, only: int2d_array_type
46 :
47 :
48 : implicit none
49 : private
50 :
51 : ! symmetric pairs and information about it.
52 : type,public :: SymPairs_t
53 : integer :: ncoeff_sym,nstr_sym
54 : integer,allocatable :: list_symcoeff(:,:,:),list_symstr(:,:,:)
55 : integer :: natom,nrpt, nsym
56 : real(dp) :: cutoff
57 : !arrays
58 : type(crystal_t), pointer :: crystal
59 : integer, allocatable :: cell(:,:)
60 : real(dp), allocatable:: dist(:, :, :, :)
61 : character(len=5),allocatable :: symbols(:)
62 : integer :: sc_size(3)
63 : real(dp):: range_ifc(3)
64 : integer :: fit_iatom=-1
65 : contains
66 : procedure :: init => SymPairs_t_init
67 : procedure :: free => SymPairs_t_free
68 : procedure :: generateTerms => SymPairs_t_generateTerms
69 : final :: SymPairs_t_final
70 : end type SymPairs_T
71 :
72 : type, private :: symlist_t
73 : integer(dp) :: nsym=0, power=0
74 : integer(dp) :: max=0
75 : integer(dp) :: counter=0
76 : integer, allocatable :: list(:)
77 : contains
78 : procedure :: init=> symlist_init
79 : procedure :: next => symlist_next
80 : procedure :: free => symlist_free
81 : end type symlist_t
82 :
83 : type, private :: IrreducibleCombinations_t
84 : ! use the hash table to see if the term is already there. And the values of the table is -1 if the term is not bounding term.
85 : type(hash_table_t) :: table
86 : type(int2d_array_type) :: array
87 : contains
88 : procedure :: init => IrreducibleCombinations_init
89 : procedure :: free => IrreducibleCombinations_free
90 : procedure :: reset_array => IrreducibleCombinations_reset_array
91 : procedure :: add_irr => IrreducibleCombinations_add_irr
92 : end type IrreducibleCombinations_T
93 :
94 : type, private :: polyform_t
95 : integer :: n=0
96 : integer, allocatable :: ind(:) ! ind(n)
97 : integer, allocatable :: order(:) ! orders(n)
98 : integer, allocatable :: expansion(:) ! orders(power), where power=sum(order)
99 : contains
100 : procedure:: init => polyform_init
101 : procedure:: free => polyform_free
102 : procedure:: expand => polyform_expand
103 : procedure:: from_expansion=> polyform_from_expansion
104 : end type polyform_t
105 :
106 : public :: polynomial_coeff_broadcast
107 : public :: polynomial_coeff_evaluate
108 : public :: polynomial_coeff_free
109 : public :: polynomial_coeff_init
110 : public :: prepare_for_getList
111 : public :: get_crystal_cutoff
112 : public :: polynomial_coeff_getList
113 : public :: polynomial_coeff_getName
114 : public :: polynomial_coeff_getNorder
115 : public :: polynomial_coeff_getOrder1
116 : public :: polynomial_coeff_MPIrecv
117 : public :: polynomial_coeff_MPIsend
118 : public :: polynomial_coeff_setName
119 : public :: polynomial_coeff_setCoefficient
120 : public :: polynomial_coeff_writeXML
121 : public :: polynomial_coeff_getEvenAnhaStrain
122 : public :: coeffs_list_copy
123 : public :: coeffs_list_conc
124 : public :: coeffs_list_conc_onsite
125 : public :: coeffs_list_append
126 : public :: coeffs_list_truncate
127 : public :: polynomial_coeff_list_free
128 : public :: generateTermsFromList
129 : public :: find_irpt
130 : public :: coeffs_compare
131 : public :: coeffs_list_reduce_duplicate
132 : public :: operator(==)
133 : public :: assignment(=)
134 : public :: operator(+)
135 :
136 :
137 : private :: computeNorder
138 : private :: computeCombinationFromList
139 : private :: computeSymmetricCombinations
140 : !private :: computeSymmetricCombinations_old
141 : private :: getCoeffFromList
142 : private :: reduce_zero_combinations
143 : !private :: check_irreducibility
144 : private :: sort_combination_list
145 : private :: sort_combination
146 :
147 :
148 : !!***
149 :
150 : !!****t* m_polynomial_coeff/polynomial_coeff_type
151 : !! NAME
152 : !! polynomial_coeff_type
153 : !!
154 : !! FUNCTION
155 : !! structure for a polynomial coefficient
156 : !! contains the value of the coefficient and a
157 : !! list of terms (displacements and/or strain) relating to the coefficient by symmetry
158 : !!
159 : !! SOURCE
160 :
161 : type, public :: polynomial_coeff_type
162 :
163 : character(len=200) :: name = ""
164 : ! Name of the polynomial_coeff (Sr_y-O1_y)^3) for example
165 :
166 : integer :: nterm = 0
167 : ! Number of terms (short range interaction) for this polynomial_coeff
168 :
169 : real(dp) :: coefficient = zero
170 : ! coefficient = value of the coefficient of this term
171 : ! \frac{\partial E^{k}}{\partial \tau^{k}}
172 :
173 : type(polynomial_term_type),dimension(:),allocatable :: terms
174 : ! polynomial_term(nterm)<type(polynomial_term)>
175 : ! contains all the displacements for this coefficient
176 :
177 : character(len=500) :: debug_str="uninitialized"
178 :
179 : contains
180 : !final :: polynomial_coeff_final
181 : end type polynomial_coeff_type
182 : !!***
183 :
184 :
185 : interface operator (==)
186 : module procedure coeffs_compare
187 : end interface operator (==)
188 :
189 : interface operator (+)
190 : module procedure coeffs_list_conc
191 : end interface operator (+)
192 :
193 : interface assignment (=)
194 : module procedure coeffs_list_copy
195 : end interface assignment (=)
196 :
197 :
198 :
199 : CONTAINS !===========================================================================================
200 :
201 :
202 : !!****f* m_polynomial_coeff/polynomial_coeff_init
203 : !!
204 : !! NAME
205 : !! polynomial_coeff_init
206 : !!
207 : !! FUNCTION
208 : !! Initialize a polynomial_coeff datatype
209 : !!
210 : !! INPUTS
211 : !! name = Name of the polynomial_coeff (Sr_y-O1_y)^3) for example
212 : !! nterm = Number of terms (short range interaction) for this polynomial_coeff
213 : !! coefficient = Value of the coefficient of this term
214 : !! terms(nterm)<type(polynomial_term)> = array of polynomial_term_type
215 : !! check = TRUE if this list of terms has to be check. We remove the symetric of equivalent terms
216 : !! for example: ((Sr_y-O1_y)^1 and -1*(Sr_y-O1_y)^1 => zero
217 : !! FALSE, defaut, do nothing
218 : !! OUTPUT
219 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype to be initialized
220 : !!
221 : !! SOURCE
222 :
223 32 : subroutine polynomial_coeff_init(coefficient,nterm,polynomial_coeff,terms,name, check, debug_str)
224 :
225 : !Arguments ------------------------------------
226 : !scalars
227 : integer, intent(in) :: nterm
228 : real(dp),intent(in) :: coefficient
229 : logical,optional,intent(in) :: check
230 : !arrays
231 : character(len=200),optional,intent(in) :: name
232 : type(polynomial_term_type),intent(in) :: terms(nterm)
233 : type(polynomial_coeff_type), intent(out) :: polynomial_coeff
234 : !Local variables-------------------------------
235 : !scalar
236 : integer :: iterm1,iterm2
237 : integer :: ii,nterm_tmp
238 : real(dp):: coefficient_tmp
239 : logical :: check_in
240 : !arrays
241 53304 : real(dp) :: weights(nterm)
242 : character(len=200) :: name_tmp
243 : character(*), optional :: debug_str
244 : ! *************************************************************************
245 : !First free before initilisation
246 : !call polynomial_coeff_free(polynomial_coeff)
247 26652 : check_in = .false.
248 26652 : if(present(check)) check_in = check
249 :
250 26652 : if (present(debug_str)) then
251 1770 : polynomial_coeff%debug_str = debug_str
252 : else
253 24882 : polynomial_coeff%debug_str = "initialized"
254 : end if
255 :
256 26652 : if(check_in)then
257 : ! Check if the list of term is available or contains identical terms
258 : ! in this case, remove all the not needed terms
259 800823 : nterm_tmp = 0
260 800823 : weights(:) = one
261 800823 : do iterm1=1,nterm
262 781301 : if(abs(weights(iterm1)) < tol16)cycle ! FIXME: do nothing?
263 663057 : weights(iterm1) = terms(iterm1)%weight
264 15005735 : do iterm2=iterm1+1,nterm
265 14342678 : if(abs(weights(iterm2)) < tol16)cycle
266 : ! if the terms are identical we check the weight
267 14857002 : if(terms(iterm1)==terms(iterm2))then
268 118244 : weights(iterm1) = weights(iterm1) + terms(iterm2)%weight
269 118244 : weights(iterm2) = 0
270 : end if
271 : end do
272 682579 : if(abs(weights(iterm1)) > tol16) then
273 619796 : weights(iterm1)= anint(weights(iterm1)/weights(iterm1))
274 : end if
275 : end do
276 :
277 :
278 : ! Count the number of terms
279 800823 : nterm_tmp=count(abs(weights) > tol16)
280 19522 : if (nterm_tmp ==0)then
281 : coefficient_tmp = 0.0
282 : else
283 17327 : coefficient_tmp = coefficient
284 : end if
285 : else
286 7130 : nterm_tmp = nterm
287 7130 : coefficient_tmp = coefficient
288 249512 : weights(:) = terms(:)%weight
289 : end if!end Check
290 :
291 26652 : if(present(name))then
292 17610 : name_tmp = name
293 : else
294 9042 : name_tmp = ""
295 : end if
296 :
297 : !Initilisation
298 26652 : polynomial_coeff%name = name_tmp
299 26652 : polynomial_coeff%nterm = nterm_tmp
300 26652 : polynomial_coeff%coefficient = coefficient_tmp
301 942134 : ABI_MALLOC(polynomial_coeff%terms,(polynomial_coeff%nterm))
302 26652 : iterm1 = 0
303 1050335 : do ii = 1,nterm
304 1050335 : if(abs(weights(ii)) > tol16)then
305 862178 : iterm1 = iterm1 + 1
306 862178 : call polynomial_term_copy(terms(ii), polynomial_coeff%terms(iterm1))
307 862178 : if(sum(polynomial_coeff%terms(iterm1)%power_strain)>1) then
308 : endif
309 : end if
310 : end do
311 26652 : end subroutine polynomial_coeff_init
312 : !!***
313 :
314 : !!****f* m_polynomial_coeff/polynomial_coeff_free
315 : !!
316 : !! NAME
317 : !! polynomial_coeff_free
318 : !!
319 : !! FUNCTION
320 : !! Free polynomial_coeff datatype
321 : !!
322 : !! INPUTS
323 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
324 : !!
325 : !! OUTPUT
326 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
327 : !!
328 : !! SOURCE
329 :
330 29362 : subroutine polynomial_coeff_free(polynomial_coeff)
331 :
332 : !Arguments ------------------------------------
333 : !scalars
334 : !arrays
335 : type(polynomial_coeff_type), intent(inout) :: polynomial_coeff
336 : !Local variables-------------------------------
337 : !scalar
338 : integer :: ii
339 : !arrays
340 :
341 : ! *************************************************************************
342 :
343 29362 : if(allocated(polynomial_coeff%terms))then
344 895935 : do ii = 1,polynomial_coeff%nterm
345 895935 : call polynomial_term_free(polynomial_coeff%terms(ii))
346 : end do
347 : end if
348 898458 : ABI_SFREE(polynomial_coeff%terms)
349 29362 : polynomial_coeff%name = ""
350 29362 : polynomial_coeff%nterm = 0
351 29362 : polynomial_coeff%coefficient = zero
352 :
353 : !if(trim(polynomial_coeff%debug_str) == "uninitialized") then
354 : ! ABI_WARNING("Polynomial coeff: is freed before initialization")
355 : !else
356 : !if (trim(polynomial_coeff%debug_str) == "freed") then
357 : ! print *, "- Polynomial coeff: ", trim(polynomial_coeff%debug_str), " ->freed"
358 : !ABI_ERROR("Polynomial coeff: is freed twice")
359 : !endif
360 : !else
361 : ! print *, "- Polynomial coeff: ", trim(polynomial_coeff%debug_str), " ->freed"
362 : ! end if
363 : ! if debug_str starts with freed
364 : !if(trim(polynomial_coeff%debug_str(1:5)) == "freed") then
365 : ! print *, "- Polynomial coeff: ", trim(polynomial_coeff%debug_str), " ->freed"
366 : !end if
367 :
368 : !polynomial_coeff%debug_str = "freed "//polynomial_coeff%debug_str
369 :
370 29362 : end subroutine polynomial_coeff_free
371 : !!***
372 :
373 : !!****f* m_polynomial_coeff/polynomial_coeff_list_free
374 : !!
375 : !! NAME
376 : !! polynomial_coeff_list_free
377 : !!
378 : !! FUNCTION
379 : !! Free polynomial_coeff datatype
380 : !!
381 : !! INPUTS
382 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
383 : !!
384 : !! OUTPUT
385 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
386 : !!
387 : !! SOURCE
388 :
389 155 : subroutine polynomial_coeff_list_free(polynomial_coeff_list)
390 :
391 : !Arguments ------------------------------------
392 : !scalars
393 : !arrays
394 : type(polynomial_coeff_type),allocatable, intent(inout) :: polynomial_coeff_list(:)
395 : !Local variables-------------------------------
396 : !scalar
397 : integer :: i,ncoeff
398 : !arrays
399 :
400 : ! *************************************************************************
401 :
402 : !Free output
403 155 : if(allocated(polynomial_coeff_list))then
404 117 : ncoeff = size(polynomial_coeff_list)
405 12796 : do i=1,ncoeff
406 12796 : call polynomial_coeff_free(polynomial_coeff_list(i))
407 : enddo
408 : endif
409 12834 : ABI_SFREE(polynomial_coeff_list)
410 :
411 155 : end subroutine polynomial_coeff_list_free
412 : !!***
413 :
414 :
415 :
416 : !!****f* m_polynomial_coeff/polynomial_coeff_setCoefficient
417 : !!
418 : !! NAME
419 : !! polynomial_coeff_setCoefficient
420 : !!
421 : !! FUNCTION
422 : !! set the coefficient for of polynomial_coeff
423 : !!
424 : !! INPUTS
425 : !! coefficient = coefficient of this coefficient
426 : !!
427 : !! OUTPUT
428 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
429 : !!
430 : !! SOURCE
431 :
432 32 : subroutine polynomial_coeff_setCoefficient(coefficient,polynomial_coeff)
433 :
434 : !Arguments ------------------------------------
435 : !scalars
436 : real(dp),intent(in) :: coefficient
437 : !arrays
438 : type(polynomial_coeff_type), intent(inout) :: polynomial_coeff
439 : !Local variables-------------------------------
440 : !scalar
441 : !arrays
442 : ! *************************************************************************
443 :
444 32 : polynomial_coeff%coefficient = coefficient
445 :
446 32 : end subroutine polynomial_coeff_setCoefficient
447 : !!***
448 :
449 : !!****f* m_polynomial_coeff/polynomial_coeff_setName
450 : !!
451 : !! NAME
452 : !! polynomial_coeff_setName
453 : !!
454 : !! FUNCTION
455 : !! set the name of a polynomial_coeff type
456 : !!
457 : !! INPUTS
458 : !! name = name of the coeff
459 : !!
460 : !! OUTPUT
461 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
462 : !!
463 : !! SOURCE
464 :
465 1863 : subroutine polynomial_coeff_setName(name,polynomial_coeff)
466 :
467 : !Arguments ------------------------------------
468 : !scalars
469 : !arrays
470 : character(len=200),intent(in) :: name
471 : type(polynomial_coeff_type), intent(inout) :: polynomial_coeff
472 : !Local variables-------------------------------
473 : !scalar
474 : !arrays
475 : ! *************************************************************************
476 :
477 1863 : polynomial_coeff%name = name
478 :
479 1863 : end subroutine polynomial_coeff_setName
480 : !!***
481 :
482 :
483 : !!****f* m_polynomial_coeff/polynomial_coeff_getName
484 : !!
485 : !! NAME
486 : !! polynomial_coeff_getName
487 : !!
488 : !! FUNCTION
489 : !! get the name of a polynomial coefficient
490 : !!
491 : !! INPUTS
492 : !! natom = number of atoms
493 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
494 : !! symbols(natom) = array with the atomic symbol:["Sr","Ru","O1","O2","O3"]
495 : !! recompute = (optional) flag to set if the name has to be recomputed
496 : !! iterm = (optional) number of the term used for the name
497 : !!
498 : !! OUTPUT
499 : !! name = name xof the coefficients
500 : !!
501 : !! SOURCE
502 :
503 6841 : subroutine polynomial_coeff_getName(name,polynomial_coeff,symbols,recompute,iterm)
504 :
505 : !Arguments ------------------------------------
506 : !scalars
507 : integer,optional,intent(in) :: iterm
508 : !arrays
509 : character(len=5),intent(in) :: symbols(:)
510 : character(len=200),intent(out):: name
511 : type(polynomial_coeff_type),optional, intent(in) :: polynomial_coeff
512 : logical,optional,intent(in) :: recompute
513 : !Local variables-------------------------------
514 : !scalar
515 : integer :: ii,idisp,iterm_in
516 : logical :: need_recompute
517 : !arrays
518 : integer :: cell_atm1(3),cell_atm2(3)
519 : character(len=1) :: mutodir(9) = (/"x","y","z","1","2","3","4","5","6"/)
520 : character(len=1) :: dir
521 : character(len=2) :: power_disp,power_dispchar
522 : character(len=20) :: atm1,atm2
523 : character(len=100):: atm1_tmp,atm2_tmp
524 : character(len=200):: text
525 : character(len=500):: message
526 : ! *************************************************************************
527 :
528 : !Reset output
529 6841 : name=""
530 6841 : iterm_in = 1
531 :
532 : !Set the optional arguments
533 6841 : need_recompute = .FALSE.
534 6841 : if(present(recompute)) need_recompute = recompute
535 6841 : if(present(iterm)) then
536 0 : iterm_in = iterm
537 : else
538 6841 : if(need_recompute)then
539 6841 : iterm_in = -1
540 157125 : do ii=1,polynomial_coeff%nterm
541 : ! Find the index of the ref
542 157125 : if(iterm_in==-1) then !Need to find the reference term
543 208611 : do idisp=1,polynomial_coeff%terms(ii)%ndisp
544 208611 : if(polynomial_coeff%terms(ii)%direction(idisp) > 0) then
545 205088 : iterm_in = ii
546 1112463 : if(any(polynomial_coeff%terms(ii)%cell(:,1,idisp) /= 0).or.&
547 : & any(polynomial_coeff%terms(ii)%cell(:,2,idisp) /= 0)) then
548 : iterm_in = -1
549 : exit
550 : end if
551 : end if
552 : end do!end do disp
553 : else
554 : exit
555 : end if
556 : end do!end do term
557 : ! If not find, we set to the first element
558 6841 : if(iterm_in==-1) iterm_in = 1
559 : else
560 : iterm_in = 1
561 : end if
562 : end if
563 : !Do check
564 6841 : if(iterm_in > polynomial_coeff%nterm.or.iterm_in < 0) then
565 : write(message, '(5a)')&
566 0 : & ' The number of the requested term for the generation of',ch10,&
567 0 : & 'the name of the coefficient is not possible.',ch10,&
568 0 : & 'Action: Contact Abinit group.'
569 0 : ABI_BUG(message)
570 : end if
571 :
572 6841 : if(polynomial_coeff%name /= "".and..not.need_recompute)then
573 0 : name = polynomial_coeff%name
574 : else
575 : ! Nedd to recompute
576 22904 : do idisp=1,polynomial_coeff%terms(iterm_in)%ndisp
577 16063 : text = ""
578 : !Fill variables for this displacement
579 16063 : write(power_dispchar,'(I0)') polynomial_coeff%terms(iterm_in)%power_disp(idisp)
580 16063 : power_disp=trim(power_dispchar)
581 :
582 16063 : atm1=symbols(polynomial_coeff%terms(iterm_in)%atindx(1,idisp))
583 16063 : atm2=symbols(polynomial_coeff%terms(iterm_in)%atindx(2,idisp))
584 16063 : dir=mutodir(polynomial_coeff%terms(iterm_in)%direction(idisp))
585 64252 : cell_atm1=polynomial_coeff%terms(iterm_in)%cell(:,1,idisp)
586 64252 : cell_atm2=polynomial_coeff%terms(iterm_in)%cell(:,2,idisp)
587 : ! Construct ATM1
588 64252 : if (any(cell_atm1(:) /= 0) )then
589 0 : write(atm1_tmp,'(4a,I0,a,I0,a,I0,a)') trim(atm1),"_",dir,"[",cell_atm1(1)," ",&
590 0 : & cell_atm1(2)," ",cell_atm1(3),"]"
591 : else
592 16063 : atm1_tmp = trim(atm1)//"_"//dir
593 : end if
594 : ! Construct ATM2
595 52604 : if(any(cell_atm2(:) /= 0))then
596 4876 : write(atm2_tmp,'(4a,I0,a,I0,a,I0,a)') trim(atm2),"_",dir,"[",cell_atm2(1)," ",&
597 9752 : & cell_atm2(2)," ",cell_atm2(3),"]"
598 : else
599 11187 : atm2_tmp = trim(atm2)//"_"//dir
600 : end if
601 16063 : text="("//trim(atm1_tmp)//"-"//trim(atm2_tmp)//")^"//power_disp
602 22904 : name = trim(name)//trim(text)
603 : end do
604 : !Strain case
605 9594 : do idisp=1,polynomial_coeff%terms(iterm_in)%nstrain
606 2753 : write(power_dispchar,'(I0)') polynomial_coeff%terms(iterm_in)%power_strain(idisp)
607 2753 : power_disp=trim(power_dispchar)
608 2753 : dir=mutodir(3+polynomial_coeff%terms(iterm_in)%strain(idisp))
609 2753 : text="("//"eta_"//trim(dir)//")^"//power_disp
610 9594 : name = trim(name)//trim(text)
611 : end do
612 : end if
613 :
614 6841 : end subroutine polynomial_coeff_getName
615 : !!***
616 :
617 : !!****f* m_polynomial_coeff/polynomial_coeff_broadcast
618 : !! NAME
619 : !! polynomial_coeff_broadcast
620 : !!
621 : !! FUNCTION
622 : !! MPI broadcast polynomial_coefficent datatype
623 : !!
624 : !! INPUTS
625 : !! source = rank of source
626 : !! comm = MPI communicator
627 : !!
628 : !! SIDE EFFECTS
629 : !! coefficients<type(polynomial_coefficent_type)>= Input if node is source,
630 : !! other nodes returns with a completely initialized instance.
631 : !!
632 : !! SOURCE
633 :
634 2500 : subroutine polynomial_coeff_broadcast(coefficients, source, comm)
635 :
636 : !Arguments ------------------------------------
637 : !array
638 : type(polynomial_coeff_type),intent(inout) :: coefficients
639 : integer, intent(in) :: source,comm
640 :
641 : !Local variables-------------------------------
642 : !scalars
643 : integer :: ierr,ii
644 : !arrays
645 :
646 : ! *************************************************************************
647 :
648 :
649 2068 : if (xmpi_comm_size(comm) == 1) return
650 :
651 : ! Free the output
652 144 : if (xmpi_comm_rank(comm) /= source) then
653 96 : call polynomial_coeff_free(coefficients)
654 : end if
655 :
656 : ! Transmit variables
657 144 : call xmpi_bcast(coefficients%name, source, comm, ierr)
658 144 : call xmpi_bcast(coefficients%nterm, source, comm, ierr)
659 144 : call xmpi_bcast(coefficients%coefficient, source, comm, ierr)
660 :
661 : !Allocate arrays on the other nodes.
662 144 : if (xmpi_comm_rank(comm) /= source) then
663 3504 : ABI_MALLOC(coefficients%terms,(coefficients%nterm))
664 3312 : do ii=1,coefficients%nterm
665 3312 : call polynomial_term_free(coefficients%terms(ii))
666 : end do
667 : end if
668 : ! Set the number of term on each node (needed for allocations of array)
669 4968 : do ii = 1,coefficients%nterm
670 4824 : call xmpi_bcast(coefficients%terms(ii)%ndisp, source, comm, ierr)
671 4824 : call xmpi_bcast(coefficients%terms(ii)%nstrain, source, comm, ierr)
672 4968 : call xmpi_bcast(coefficients%terms(ii)%nindex, source, comm, ierr)
673 : end do
674 :
675 : ! Allocate arrays on the other nodes
676 144 : if (xmpi_comm_rank(comm) /= source) then
677 3312 : do ii = 1,coefficients%nterm
678 9648 : ABI_MALLOC(coefficients%terms(ii)%atindx,(2,coefficients%terms(ii)%ndisp))
679 27984 : coefficients%terms(ii)%atindx = 0
680 9648 : ABI_MALLOC(coefficients%terms(ii)%direction,(coefficients%terms(ii)%ndisp))
681 9648 : ABI_MALLOC(coefficients%terms(ii)%cell,(3,2,coefficients%terms(ii)%ndisp))
682 9648 : ABI_MALLOC(coefficients%terms(ii)%power_disp,(coefficients%terms(ii)%ndisp))
683 9648 : ABI_MALLOC(coefficients%terms(ii)%power_strain,(coefficients%terms(ii)%nstrain))
684 9648 : ABI_MALLOC(coefficients%terms(ii)%strain,(coefficients%terms(ii)%nstrain))
685 3312 : if(coefficients%terms(ii)%nindex>-1) then
686 5472 : ABI_MALLOC(coefficients%terms(ii)%index_coeff,(coefficients%terms(ii)%nindex))
687 : end if
688 : end do
689 : end if
690 :
691 : ! Transfert value
692 4968 : do ii = 1,coefficients%nterm
693 4824 : call xmpi_bcast(coefficients%terms(ii)%weight, source, comm, ierr)
694 4824 : call xmpi_bcast(coefficients%terms(ii)%atindx, source, comm, ierr)
695 4824 : call xmpi_bcast(coefficients%terms(ii)%direction, source, comm, ierr)
696 4824 : call xmpi_bcast(coefficients%terms(ii)%cell, source, comm, ierr)
697 4824 : call xmpi_bcast(coefficients%terms(ii)%power_disp, source, comm, ierr)
698 4824 : call xmpi_bcast(coefficients%terms(ii)%power_strain, source, comm, ierr)
699 4824 : call xmpi_bcast(coefficients%terms(ii)%strain, source, comm, ierr)
700 4968 : if(coefficients%terms(ii)%nindex>-1) then
701 2736 : call xmpi_bcast(coefficients%terms(ii)%index_coeff, source, comm, ierr)
702 : end if
703 : end do
704 : end subroutine polynomial_coeff_broadcast
705 : !!***
706 :
707 : !!****f* m_polynomial_coeff/polynomial_coeff_MPIsend
708 : !! NAME
709 : !! polynomial_coeff_MPIsend
710 : !!
711 : !! FUNCTION
712 : !! MPI send the polynomial_coefficent datatype
713 : !!
714 : !! INPUTS
715 : !! tag = tag of the message to send
716 : !! dest= rank of Dest
717 : !! comm= MPI communicator
718 : !!
719 : !! SIDE EFFECTS
720 : !! polynomial_coeff<type(polynomial_coeff)> = polynomial_coeff datatype
721 : !!
722 : !! SOURCE
723 :
724 88 : subroutine polynomial_coeff_MPIsend(coefficients, tag, dest, comm)
725 :
726 : !Arguments ------------------------------------
727 : !array
728 : type(polynomial_coeff_type),intent(inout) :: coefficients
729 : integer, intent(in) :: dest,comm,tag
730 :
731 : !Local variables-------------------------------
732 : !scalars
733 : integer :: ierr,ii
734 : integer :: my_rank
735 : !arrays
736 :
737 : ! *************************************************************************
738 :
739 88 : if (xmpi_comm_size(comm) == 1) return
740 :
741 88 : my_rank = xmpi_comm_rank(comm)
742 : ! Transmit variables
743 88 : call xmpi_send(coefficients%name, dest, 9*tag+0, comm, ierr)
744 88 : call xmpi_send(coefficients%nterm, dest, 9*tag+1, comm, ierr)
745 88 : call xmpi_send(coefficients%coefficient, dest, 9*tag+2, comm, ierr)
746 :
747 : ! Set the number of term on each node (needed for allocations of array)
748 3760 : do ii = 1,coefficients%nterm
749 3672 : call xmpi_send(coefficients%terms(ii)%ndisp, dest, 9*tag+3, comm, ierr)
750 3672 : call xmpi_send(coefficients%terms(ii)%nstrain, dest, 9*tag+4, comm, ierr)
751 3760 : call xmpi_send(coefficients%terms(ii)%nindex, dest, 9*tag+13, comm, ierr)
752 : end do
753 :
754 : ! Transfert value
755 3760 : do ii = 1,coefficients%nterm
756 3672 : call xmpi_send(coefficients%terms(ii)%weight, dest, 9*tag+5, comm, ierr)
757 3672 : call xmpi_send(coefficients%terms(ii)%atindx, dest, 9*tag+6, comm, ierr)
758 3672 : call xmpi_send(coefficients%terms(ii)%direction, dest, 9*tag+7, comm, ierr)
759 3672 : call xmpi_send(coefficients%terms(ii)%cell, dest, 9*tag+8, comm, ierr)
760 3672 : call xmpi_send(coefficients%terms(ii)%power_disp, dest, 9*tag+9, comm, ierr)
761 3672 : call xmpi_send(coefficients%terms(ii)%power_strain, dest, 9*tag+10, comm, ierr)
762 3672 : call xmpi_send(coefficients%terms(ii)%strain, dest, 9*tag+11, comm, ierr)
763 3760 : if (coefficients%terms(ii)%nindex>-1) then
764 3672 : call xmpi_send(coefficients%terms(ii)%index_coeff, dest, 9*tag+14, comm, ierr)
765 : end if
766 : end do
767 : end subroutine polynomial_coeff_MPIsend
768 : !!***
769 :
770 : !!****f* m_polynomial_coeff/polynomial_coeff_MPIrecv
771 : !! NAME
772 : !! polynomial_coeff_MPIrecv
773 : !!
774 : !! FUNCTION
775 : !! MPI receive the polynomial_coefficent datatype
776 : !!
777 : !! INPUTS
778 : !! tag = tag of the message to receive
779 : !! source = rank of Source
780 : !! comm = MPI communicator
781 : !!
782 : !! SIDE EFFECTS
783 : !! coefficients<type(polynomial_coefficent_type)>= polynomial_coeff datatype
784 : !!
785 : !! SOURCE
786 :
787 88 : subroutine polynomial_coeff_MPIrecv(coefficients, tag, source, comm)
788 :
789 : !Arguments ------------------------------------
790 : !array
791 : type(polynomial_coeff_type),intent(inout) :: coefficients
792 : integer, intent(in) :: source,comm,tag
793 :
794 : !Local variables-------------------------------
795 : !scalars
796 : integer :: ierr,ii
797 : !arrays
798 :
799 : ! *************************************************************************
800 :
801 88 : if (xmpi_comm_size(comm) == 1) return
802 :
803 :
804 : ! Free the output
805 88 : call polynomial_coeff_free(coefficients)
806 :
807 : ! Transmit variables
808 88 : call xmpi_recv(coefficients%name, source, 9*tag+0, comm, ierr)
809 88 : call xmpi_recv(coefficients%nterm, source, 9*tag+1, comm, ierr)
810 88 : call xmpi_recv(coefficients%coefficient, source, 9*tag+2, comm, ierr)
811 :
812 : !Allocate arrays on the other nodes.
813 3936 : ABI_MALLOC(coefficients%terms,(coefficients%nterm))
814 3760 : do ii=1,coefficients%nterm
815 3760 : call polynomial_term_free(coefficients%terms(ii))
816 : end do
817 :
818 : ! Set the number of term on each node (needed for allocations of array)
819 3760 : do ii = 1,coefficients%nterm
820 3672 : call xmpi_recv(coefficients%terms(ii)%ndisp, source, 9*tag+3, comm, ierr)
821 3672 : call xmpi_recv(coefficients%terms(ii)%nstrain, source, 9*tag+4, comm, ierr)
822 3760 : call xmpi_recv(coefficients%terms(ii)%nindex, source, 9*tag+13, comm, ierr)
823 : end do
824 :
825 : ! Allocate arrays on the other nodes
826 3760 : do ii = 1,coefficients%nterm
827 11016 : ABI_MALLOC(coefficients%terms(ii)%atindx,(2,coefficients%terms(ii)%ndisp))
828 32256 : coefficients%terms(ii)%atindx = 0
829 11016 : ABI_MALLOC(coefficients%terms(ii)%direction,(coefficients%terms(ii)%ndisp))
830 11016 : ABI_MALLOC(coefficients%terms(ii)%cell,(3,2,coefficients%terms(ii)%ndisp))
831 11016 : ABI_MALLOC(coefficients%terms(ii)%power_disp,(coefficients%terms(ii)%ndisp))
832 11016 : ABI_MALLOC(coefficients%terms(ii)%power_strain,(coefficients%terms(ii)%nstrain))
833 11016 : ABI_MALLOC(coefficients%terms(ii)%strain,(coefficients%terms(ii)%nstrain))
834 3760 : if (coefficients%terms(ii)%nindex>-1) then
835 11016 : ABI_MALLOC(coefficients%terms(ii)%index_coeff,(coefficients%terms(ii)%nindex))
836 : end if
837 : end do
838 :
839 : ! Transfert value
840 3760 : do ii = 1,coefficients%nterm
841 3672 : call xmpi_recv(coefficients%terms(ii)%weight, source, 9*tag+5, comm, ierr)
842 3672 : call xmpi_recv(coefficients%terms(ii)%atindx, source, 9*tag+6, comm, ierr)
843 3672 : call xmpi_recv(coefficients%terms(ii)%direction, source, 9*tag+7, comm, ierr)
844 3672 : call xmpi_recv(coefficients%terms(ii)%cell, source, 9*tag+8, comm, ierr)
845 3672 : call xmpi_recv(coefficients%terms(ii)%power_disp, source, 9*tag+9, comm, ierr)
846 3672 : call xmpi_recv(coefficients%terms(ii)%power_strain, source, 9*tag+10, comm, ierr)
847 3672 : call xmpi_recv(coefficients%terms(ii)%strain, source, 9*tag+11, comm, ierr)
848 3760 : if (coefficients%terms(ii)%nindex>-1) then
849 3672 : call xmpi_recv(coefficients%terms(ii)%index_coeff, source , 9*tag+14, comm, ierr)
850 : end if
851 : end do
852 :
853 : end subroutine polynomial_coeff_MPIrecv
854 : !!***
855 :
856 :
857 :
858 :
859 : !!****f*m_polynomial_coeff/polynomial_coeff_writeXML
860 : !! NAME
861 : !! polynomial_coeff_writeXML
862 : !!
863 : !! FUNCTION
864 : !! This routine print the coefficents into XML format
865 : !!
866 : !! COPYRIGHT
867 : !! Copyright (C) 2000-2026 ABINIT group (AM)
868 : !! This file is distributed under the terms of the
869 : !! GNU General Public License, see ~abinit/COPYING
870 : !! or http://www.gnu.org/copyleft/gpl.txt .
871 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
872 : !!
873 : !! INPUTS
874 : !! coeffs(ncoeffs)<type(polynomial_coeff)> = array of polynomial_coeff datatype
875 : !! ncoeff = number of coeffs to print
876 : !! filename = optional,the name of output file
877 : !! default is coefficients.xml
878 : !! unit = optional,unit of the output file
879 : !! newfile = optional, TRUE the coefficients are print in new XML (print the headers)
880 : !! FALSE (requieres unit) will not print the headers
881 : !! replace = optional, TRUE replace filename if filename exists
882 : !! FALSE, default not replace if filename exists
883 : !!
884 : !! OUTPUT
885 : !!
886 : !! SOURCE
887 :
888 15 : subroutine polynomial_coeff_writeXML(coeffs,ncoeff,filename,unit,newfile,replace)
889 :
890 : !Arguments ------------------------------------
891 : !scalars
892 : integer, intent(in) :: ncoeff
893 : integer,optional,intent(in) :: unit
894 : logical,optional,intent(in) :: newfile,replace
895 : !arrays
896 : type(polynomial_coeff_type), intent(in) :: coeffs(ncoeff)
897 : character(len=fnlen),optional,intent(in) :: filename
898 : !Local variables-------------------------------
899 : !scalar
900 : integer :: icoeff,idisp,iterm
901 : integer :: unit_xml
902 : logical :: need_header,need_to_replace
903 : character(len=500) :: message
904 : character(len=fnlen) :: namefile
905 : character(len=1) :: direction
906 :
907 : !arrays
908 :
909 : ! *************************************************************************
910 :
911 : !fill the default
912 15 : unit_xml = get_unit()
913 :
914 : !Check the inputs
915 15 : if(present(filename))then
916 15 : namefile=trim(filename)
917 : else
918 0 : namefile='coefficients.xml'
919 : end if
920 :
921 15 : need_to_replace = .FALSE.
922 15 : if(present(replace))then
923 0 : need_to_replace = replace
924 : end if
925 :
926 15 : need_header = .TRUE.
927 15 : if(present(newfile))then
928 15 : if (newfile) then
929 12 : unit_xml = get_unit()
930 12 : need_header = .TRUE.
931 :
932 12 : if(.not. need_to_replace) call isfile(namefile,'new')
933 : else
934 3 : if(.not.present(unit))then
935 0 : write(message,'(a,a)')' You need to specified the unit'
936 0 : ABI_ERROR(message)
937 : else
938 3 : need_header = .FALSE.
939 3 : unit_xml = unit
940 : end if
941 : end if
942 : end if
943 15 : if (size(coeffs) /= ncoeff) then
944 0 : write(message,'(a,a)')' The number of coeffs does not correspond to ncoeff'
945 0 : ABI_ERROR(message)
946 : end if
947 :
948 : !Print the coefficients into XML file
949 15 : if(ncoeff>0)then
950 15 : if(need_header)then
951 : ! open new file
952 12 : if (open_file(namefile,message,unit=unit_xml,form="formatted",&
953 : & status="new",action="write") /= 0) then
954 0 : ABI_ERROR(message)
955 : end if
956 : else
957 : ! just open the file to append the coefficient
958 3 : open(unit=unit_xml,file=namefile,position="append")
959 : end if
960 :
961 : ! Write header
962 15 : if (need_header)then
963 12 : write(message,'(a,a,a)')ch10,&
964 24 : & ' Generation of the xml file for the fitted polynomial in ',trim(namefile)
965 :
966 12 : call wrtout(ab_out,message,'COLL')
967 12 : call wrtout(std_out,message,'COLL')
968 12 : WRITE(unit_xml,'("<?xml version=""1.0"" ?>")')
969 : end if
970 15 : WRITE(unit_xml,'("<Heff_definition>")')
971 : ! Close header
972 95 : do icoeff = 1, ncoeff
973 : WRITE(unit_xml,'(" <coefficient number=""",I0,""" value=""",E19.10,""" text=""",a,""">")') &
974 80 : icoeff,coeffs(icoeff)%coefficient,trim(coeffs(icoeff)%name)
975 2438 : do iterm = 1,coeffs(icoeff)%nterm
976 : WRITE(unit_xml,'(" <term weight=""",F9.6,""">")') &
977 2358 : coeffs(icoeff)%terms(iterm)%weight
978 8022 : do idisp=1,coeffs(icoeff)%terms(iterm)%ndisp
979 : ! Atomic displacement case
980 7552 : select case(coeffs(icoeff)%terms(iterm)%direction(idisp))
981 : case(1)
982 1888 : direction ="x"
983 : case(2)
984 1888 : direction ="y"
985 : case(3)
986 5664 : direction ="z"
987 : end select
988 5664 : WRITE(unit_xml,'(a,I0,a,I0,3a,I0,a)') " <displacement_diff atom_a=""",&
989 5664 : & coeffs(icoeff)%terms(iterm)%atindx(1,idisp)-1,""" atom_b=""",&
990 5664 : & coeffs(icoeff)%terms(iterm)%atindx(2,idisp)-1,""" direction=""",&
991 5664 : & direction,""" power=""",coeffs(icoeff)%terms(iterm)%power_disp(idisp),&
992 11328 : & """>"
993 5664 : WRITE(unit_xml,'(" <cell_a>")',advance='no')
994 : WRITE(unit_xml,'(3(I0,a,I0,a,I0))',advance='no')&
995 5664 : & coeffs(icoeff)%terms(iterm)%cell(1,1,idisp)," ",&
996 5664 : & coeffs(icoeff)%terms(iterm)%cell(2,1,idisp)," ",&
997 11328 : & coeffs(icoeff)%terms(iterm)%cell(3,1,idisp)
998 5664 : WRITE(unit_xml,'("</cell_a>")')
999 5664 : WRITE(unit_xml,'(" <cell_b>")',advance='no')
1000 : WRITE(unit_xml,'(3(I0,a,I0,a,I0))',advance='no')&
1001 5664 : & coeffs(icoeff)%terms(iterm)%cell(1,2,idisp)," ",&
1002 5664 : & coeffs(icoeff)%terms(iterm)%cell(2,2,idisp)," ",&
1003 11328 : & coeffs(icoeff)%terms(iterm)%cell(3,2,idisp)
1004 5664 : WRITE(unit_xml,'("</cell_b>")')
1005 8022 : WRITE(unit_xml,'(" </displacement_diff>")')
1006 : end do
1007 2892 : do idisp=1,coeffs(icoeff)%terms(iterm)%nstrain
1008 : ! Strain case
1009 : WRITE(unit_xml,'(" <strain power=""",i2,""" voigt=""",i2,"""/>")')&
1010 534 : & coeffs(icoeff)%terms(iterm)%power_strain(idisp),&
1011 3426 : & coeffs(icoeff)%terms(iterm)%strain(idisp)
1012 : end do
1013 2438 : WRITE(unit_xml,'(" </term>")')
1014 : end do
1015 95 : WRITE(unit_xml,'(" </coefficient>")')
1016 : end do
1017 15 : WRITE(unit_xml,'("</Heff_definition>")')
1018 : ! Close file
1019 15 : CLOSE(unit_xml)
1020 : end if
1021 :
1022 15 : end subroutine polynomial_coeff_writeXML
1023 :
1024 :
1025 : !!***
1026 :
1027 : !!****f* m_polynomial_coeff/polynomial_coeff_evaluate
1028 : !! NAME
1029 : !! polynomial_coeff_evaluate
1030 : !!
1031 : !! FUNCTION
1032 : !! Compute the energy related to the coefficients from
1033 : !! fitted polynome
1034 : !!
1035 : !! INPUTS
1036 : !! coefficients(ncoeff)<type(polynomial_coeff_type)> = list of coefficients
1037 : !! disp(3,natom_sc) = atomics displacement between configuration and the reference
1038 : !! natom_sc = number of atoms in the supercell
1039 : !! natom_uc = number of atoms in the unit cell
1040 : !! ncoeff = number of coefficients
1041 : !! sc_size(3) = size of the supercell (2 2 2 for example)
1042 : !! strain(6) = strain between configuration and the reference
1043 : !! cells(ncell) = number of the cells into the supercell (1,2,3,4,5)
1044 : !! ncell = total number of cell to treat by this cpu
1045 : !! index_cells(3,ncell) = indexes of the cells into supercell (-1 -1 -1 ,...,1 1 1)
1046 : !! comm=MPI communicator
1047 : !!
1048 : !! OUTPUT
1049 : !! energy = contribution to the energy
1050 : !! energy_coeff(ncoeff) = energy contribution of each anharmonic term
1051 : !! fcart(3,natom) = contribution to the forces
1052 : !! strten(6) = contribution to the stress tensor
1053 : !!
1054 : !! SOURCE
1055 : !!
1056 10265 : subroutine polynomial_coeff_evaluate(coefficients,disp,energy,energy_coeff,fcart,natom_sc,natom_uc,ncoeff,sc_size,&
1057 10265 : & strain,strten,ncell,index_cells,comm,filename)
1058 :
1059 : !Arguments ------------------------------------
1060 : ! scalar
1061 : real(dp),intent(out):: energy
1062 : integer, intent(in) :: ncell,ncoeff,natom_sc,natom_uc
1063 : integer, intent(in) :: comm
1064 : character(len=fnlen),optional,intent(in) :: filename
1065 : ! array
1066 : real(dp),intent(out):: strten(6)
1067 : real(dp),intent(in) :: strain(6)
1068 : real(dp),intent(out):: fcart(3,natom_sc)
1069 : real(dp),intent(in) :: disp(3,natom_sc)
1070 : real(dp),optional,intent(out):: energy_coeff(ncoeff)
1071 : integer,intent(in) :: index_cells(4,ncell)
1072 : integer,intent(in) :: sc_size(3)
1073 : type(polynomial_coeff_type),intent(in) :: coefficients(ncoeff)
1074 : !Local variables-------------------------------
1075 : ! scalar
1076 : integer :: i1,i2,i3,ia1,ib1,ia2,ib2,idir1,idir2,ierr,ii
1077 : integer :: icoeff,iterm,idisp1,idisp2,idisp1_strain,idisp2_strain,icell,ndisp
1078 : integer :: nstrain,ndisp_tot,power_disp,power_strain,unit_out
1079 : real(dp):: coeff,disp1,disp2,tmp1,tmp2,tmp3,weight
1080 : logical :: file_opened
1081 : ! array
1082 : integer :: cell_atoma1(3),cell_atoma2(3)
1083 : integer :: cell_atomb1(3),cell_atomb2(3)
1084 : character(len=500) :: msg
1085 : character(len=fnlen) :: name_file
1086 : ! *************************************************************************
1087 :
1088 : ! Check
1089 41060 : if (any(sc_size <= 0)) then
1090 0 : write(msg,'(a,a)')' No supercell found for getEnergy'
1091 0 : ABI_ERROR(msg)
1092 : end if
1093 :
1094 10265 : if(present(filename)) name_file = filename
1095 :
1096 : ! Initialisation of variables
1097 10265 : energy = zero
1098 35095225 : fcart(:,:) = zero
1099 10265 : strten(:) = zero
1100 876307 : energy_coeff(:) = zero
1101 1758409 : do icell = 1,ncell
1102 1748144 : ii = index_cells(4,icell);
1103 1748144 : i1=index_cells(1,icell); i2=index_cells(2,icell); i3=index_cells(3,icell)
1104 1748144 : ia1 = 0 ; ib1 = 0
1105 : ! Loop over coefficients
1106 173401737 : do icoeff=1,ncoeff
1107 : ! Set the value of the coefficient
1108 171643328 : coeff = coefficients(icoeff)%coefficient
1109 : ! Loop over terms of this coefficient
1110 2165241000 : do iterm=1,coefficients(icoeff)%nterm
1111 : ! Set the weight of this term
1112 1991849528 : weight =coefficients(icoeff)%terms(iterm)%weight
1113 1991849528 : tmp1 = one
1114 1991849528 : ndisp = coefficients(icoeff)%terms(iterm)%ndisp
1115 1991849528 : nstrain = coefficients(icoeff)%terms(iterm)%nstrain
1116 1991849528 : ndisp_tot = ndisp + nstrain
1117 : ! Loop over displacement and strain
1118 6148709792 : do idisp1=1,ndisp_tot
1119 : ! Set to one the acculation of forces and strain
1120 4156860264 : tmp2 = one
1121 4156860264 : tmp3 = zero
1122 :
1123 : ! Strain case idisp > ndisp
1124 4156860264 : if (idisp1 > ndisp)then
1125 1477156968 : tmp3 = one
1126 : ! Set the power_strain of the strain:
1127 1477156968 : idisp1_strain = idisp1 - ndisp
1128 1477156968 : power_strain = coefficients(icoeff)%terms(iterm)%power_strain(idisp1_strain)
1129 : ! Get the direction of the displacement or strain
1130 1477156968 : idir1 = coefficients(icoeff)%terms(iterm)%strain(idisp1_strain)
1131 1477156968 : if(abs(strain(idir1)) > tol10)then
1132 : ! Accumulate energy fo each displacement (\sum ((A_x-O_x)^Y(A_y-O_c)^Z))
1133 4049736 : tmp1 = tmp1 * (strain(idir1))**power_strain
1134 4049736 : if(power_strain > 1) then
1135 : ! Accumulate stress for each strain (\sum (Y(eta_2)^Y-1(eta_2)^Z+...))
1136 523872 : tmp3 = tmp3 * power_strain*(strain(idir1))**(power_strain-1)
1137 : end if
1138 : else
1139 1473107232 : tmp1 = zero
1140 1473107232 : if(power_strain > 1) then
1141 1338078744 : tmp3 = zero
1142 : end if
1143 : end if
1144 : else
1145 : ! Set the power_disp of the displacement:
1146 2679703296 : power_disp = coefficients(icoeff)%terms(iterm)%power_disp(idisp1)
1147 : ! Get the direction of the displacement or strain
1148 2679703296 : idir1 = coefficients(icoeff)%terms(iterm)%direction(idisp1)
1149 : ! Displacement case idir = 1, 2 or 3
1150 : ! indexes of the cell of the atom a
1151 10718813184 : cell_atoma1 = coefficients(icoeff)%terms(iterm)%cell(:,1,idisp1)
1152 2679703296 : if(cell_atoma1(1)/=0.or.cell_atoma1(2)/=0.or.cell_atoma1(3)/=0) then
1153 : ! if the cell is not 0 0 0 we apply PBC:
1154 64800 : cell_atoma1(1) = i1 + cell_atoma1(1)
1155 64800 : cell_atoma1(2) = i2 + cell_atoma1(2)
1156 64800 : cell_atoma1(3) = i3 + cell_atoma1(3)
1157 64800 : call getPBCIndexes_supercell(cell_atoma1(1:3),sc_size(1:3))
1158 : ! index of the first atom (position in the supercell if the cell is not 0 0 0)
1159 : ia1 = (cell_atoma1(1)-1)*sc_size(2)*sc_size(3)*natom_uc+&
1160 : & (cell_atoma1(2)-1)*sc_size(3)*natom_uc+&
1161 : & (cell_atoma1(3)-1)*natom_uc+&
1162 64800 : & coefficients(icoeff)%terms(iterm)%atindx(1,idisp1)
1163 : else
1164 : ! index of the first atom (position in the supercell if the cell is 0 0 0)
1165 2679638496 : ia1 = ii + coefficients(icoeff)%terms(iterm)%atindx(1,idisp1)
1166 : end if
1167 :
1168 : ! indexes of the cell of the atom b (with PBC) same as ia1
1169 10718813184 : cell_atomb1 = coefficients(icoeff)%terms(iterm)%cell(:,2,idisp1)
1170 2679703296 : if(cell_atomb1(1)/=0.or.cell_atomb1(2)/=0.or.cell_atomb1(3)/=0) then
1171 1728987576 : cell_atomb1(1) = i1 + cell_atomb1(1)
1172 1728987576 : cell_atomb1(2) = i2 + cell_atomb1(2)
1173 1728987576 : cell_atomb1(3) = i3 + cell_atomb1(3)
1174 1728987576 : call getPBCIndexes_supercell(cell_atomb1(1:3),sc_size(1:3))
1175 :
1176 : ! index of the second atom in the (position in the supercell if the cell is not 0 0 0)
1177 : ib1 = (cell_atomb1(1)-1)*sc_size(2)*sc_size(3)*natom_uc+&
1178 : & (cell_atomb1(2)-1)*sc_size(3)*natom_uc+&
1179 : & (cell_atomb1(3)-1)*natom_uc+&
1180 1728987576 : & coefficients(icoeff)%terms(iterm)%atindx(2,idisp1)
1181 : else
1182 : ! index of the first atom (position in the supercell if the cell is 0 0 0)
1183 950715720 : ib1 = ii + coefficients(icoeff)%terms(iterm)%atindx(2,idisp1)
1184 : end if
1185 :
1186 : ! Get the displacement for the both atoms
1187 2679703296 : disp1 = disp(idir1,ia1)
1188 2679703296 : disp2 = disp(idir1,ib1)
1189 :
1190 2679703296 : if(abs(disp1) > tol10 .or. abs(disp2)> tol10)then
1191 : ! Accumulate energy fo each displacement (\sum ((A_x-O_x)^Y(A_y-O_c)^Z))
1192 2675133608 : tmp1 = tmp1 * (disp1-disp2)**power_disp
1193 2675133608 : if(power_disp > 1) then
1194 : ! Accumulate forces for each displacement (\sum (Y(A_x-O_x)^Y-1(A_y-O_c)^Z+...))
1195 2398068632 : tmp2 = tmp2 * power_disp*(disp1-disp2)**(power_disp-1)
1196 : end if
1197 : else
1198 4569688 : tmp1 = zero
1199 4569688 : if(power_disp > 1) then
1200 3520840 : tmp2 = zero
1201 : end if
1202 : end if
1203 : end if
1204 :
1205 13733453856 : do idisp2=1,ndisp_tot
1206 :
1207 13733453856 : if(idisp2 /= idisp1) then
1208 5419733328 : if (idisp2 > ndisp)then
1209 2187237792 : idisp2_strain = idisp2 - ndisp
1210 2187237792 : idir2 = coefficients(icoeff)%terms(iterm)%strain(idisp2_strain)
1211 : ! Strain case
1212 : ! Set the power_strain of the strain:
1213 2187237792 : power_strain = coefficients(icoeff)%terms(iterm)%power_strain(idisp2_strain)
1214 : ! Accumulate energy forces
1215 2187237792 : tmp2 = tmp2 * (strain(idir2))**power_strain
1216 : ! Accumulate stress for each strain (\sum (Y(eta_2)^Y-1(eta_2)^Z+...))
1217 2187237792 : tmp3 = tmp3 * (strain(idir2))**power_strain
1218 : else
1219 3232495536 : idir2 = coefficients(icoeff)%terms(iterm)%direction(idisp2)
1220 12929982144 : cell_atoma2=coefficients(icoeff)%terms(iterm)%cell(:,1,idisp2)
1221 3232495536 : if(cell_atoma2(1)/=0.or.cell_atoma2(2)/=0.or.cell_atoma2(3)/=0) then
1222 64800 : cell_atoma2(1) = i1 + cell_atoma2(1)
1223 64800 : cell_atoma2(2) = i2 + cell_atoma2(2)
1224 64800 : cell_atoma2(3) = i3 + cell_atoma2(3)
1225 64800 : call getPBCIndexes_supercell(cell_atoma2(1:3),sc_size(1:3))
1226 : ! index of the first atom (position in the supercell and direction)
1227 : ! if the cell of the atom a is not 0 0 0 (may happen)
1228 : ia2 = (cell_atoma2(1)-1)*sc_size(2)*sc_size(3)*natom_uc+&
1229 : & (cell_atoma2(2)-1)*sc_size(3)*natom_uc+&
1230 : & (cell_atoma2(3)-1)*natom_uc+&
1231 64800 : & coefficients(icoeff)%terms(iterm)%atindx(1,idisp2)
1232 : else
1233 : ! index of the first atom (position in the supercell and direction)
1234 3232430736 : ia2 = ii + coefficients(icoeff)%terms(iterm)%atindx(1,idisp2)
1235 : end if
1236 :
1237 12929982144 : cell_atomb2= coefficients(icoeff)%terms(iterm)%cell(:,2,idisp2)
1238 :
1239 3232495536 : if(cell_atomb2(1)/=0.or.cell_atomb2(2)/=0.or.cell_atomb2(3)/=0) then
1240 : ! indexes of the cell2 (with PBC)
1241 2010815736 : cell_atomb2(1) = i1 + cell_atomb2(1)
1242 2010815736 : cell_atomb2(2) = i2 + cell_atomb2(2)
1243 2010815736 : cell_atomb2(3) = i3 + cell_atomb2(3)
1244 2010815736 : call getPBCIndexes_supercell(cell_atomb2(1:3),sc_size(1:3))
1245 :
1246 : ! index of the second atom in the (position in the supercell)
1247 : ib2 = (cell_atomb2(1)-1)*sc_size(2)*sc_size(3)*natom_uc+&
1248 : & (cell_atomb2(2)-1)*sc_size(3)*natom_uc+&
1249 : & (cell_atomb2(3)-1)*natom_uc+&
1250 2010815736 : & coefficients(icoeff)%terms(iterm)%atindx(2,idisp2)
1251 : else
1252 1221679800 : ib2 = ii + coefficients(icoeff)%terms(iterm)%atindx(2,idisp2)
1253 : end if
1254 :
1255 3232495536 : disp1 = disp(idir2,ia2)
1256 3232495536 : disp2 = disp(idir2,ib2)
1257 :
1258 : ! Set the power_disp of the displacement:
1259 3232495536 : power_disp = coefficients(icoeff)%terms(iterm)%power_disp(idisp2)
1260 3232495536 : tmp2 = tmp2 * (disp1-disp2)**power_disp
1261 3232495536 : tmp3 = tmp3 * (disp1-disp2)**power_disp
1262 :
1263 : end if
1264 : end if
1265 : end do
1266 :
1267 6148709792 : if(idisp1 > ndisp)then
1268 : ! Accumule stress tensor
1269 1477156968 : strten(idir1) = strten(idir1) + coeff * weight * tmp3
1270 : else
1271 : ! Accumule forces
1272 2679703296 : fcart(idir1,ia1) = fcart(idir1,ia1) + coeff * weight * tmp2
1273 2679703296 : fcart(idir1,ib1) = fcart(idir1,ib1) - coeff * weight * tmp2
1274 : end if
1275 : end do
1276 :
1277 1991849528 : energy_coeff(icoeff) = energy_coeff(icoeff) + coeff * weight * tmp1
1278 : ! accumule energy
1279 2163492856 : energy = energy + coeff * weight * tmp1
1280 :
1281 : end do
1282 : end do
1283 : end do
1284 :
1285 :
1286 : ! MPI_SUM
1287 10265 : call xmpi_sum(energy, comm, ierr)
1288 10265 : call xmpi_sum(fcart , comm, ierr)
1289 10265 : call xmpi_sum(strten , comm, ierr)
1290 :
1291 : !Write to anharmonic_energy_terms.out ORIGINAL
1292 10265 : INQUIRE(FILE=name_file,OPENED=file_opened,number=unit_out)
1293 10265 : if(file_opened .eqv. .TRUE.)then
1294 6161 : do icoeff=1,ncoeff
1295 6060 : call xmpi_sum(energy_coeff(icoeff), comm, ierr)
1296 : ! Marcus write energy contributions of anharmonic terms to file
1297 6161 : if(icoeff <ncoeff)then
1298 5959 : write(unit_out,'(A,1ES24.16)',advance='no') ' ',energy_coeff(icoeff)
1299 : else if(icoeff==ncoeff)then
1300 101 : write(unit_out,'(A,1ES24.16)',advance='yes') ' ',energy_coeff(icoeff)
1301 : end if
1302 : enddo
1303 : end if
1304 :
1305 :
1306 10265 : end subroutine polynomial_coeff_evaluate
1307 : !!***
1308 :
1309 1 : function get_crystal_cutoff(crystal) result(cutoff)
1310 : type(crystal_t), intent(inout) :: crystal
1311 : real(dp) :: cutoff
1312 : integer :: ii
1313 : ! XXX: hexu: why cutoff + sum of axis lengths?
1314 1 : cutoff=0.1
1315 4 : do ii=1,3
1316 : cutoff = cutoff + sqrt(crystal%rprimd(ii,1)**2 + &
1317 : & crystal%rprimd(ii,2)**2 + &
1318 4 : & crystal%rprimd(ii,3)**2)
1319 : enddo
1320 1 : end function get_crystal_cutoff
1321 :
1322 45 : subroutine prepare_for_getList(crystal,sc_size, dist, cell, natom, nsym, nrpt, range_ifc, symbols )
1323 : type(crystal_t), intent(inout) :: crystal
1324 : integer, intent(in) :: sc_size(3)
1325 : integer, intent(inout) :: natom, nsym, nrpt
1326 : integer, allocatable, intent(inout) :: cell(:, :)
1327 : character(len=5),allocatable, intent(inout) :: symbols(:)
1328 :
1329 45 : real(dp), allocatable:: xcart(:, :), xred(:,:), rpt(:, :)
1330 : real(dp), allocatable:: dist(:, :, :, :)
1331 : real(dp) :: rprimd(3,3), range_ifc(3)
1332 : integer :: ii, ncell(3), lim1, lim2, lim3
1333 : real(dp) :: norm
1334 : integer :: irpt, irpt_ref, r1, r2, r3, ia, ib
1335 :
1336 45 : natom = crystal%natom
1337 45 : nsym = crystal%nsym
1338 585 : rprimd = crystal%rprimd
1339 :
1340 135 : ABI_MALLOC(xcart,(3,natom))
1341 90 : ABI_MALLOC(xred,(3,natom))
1342 945 : xcart(:,:) = crystal%xcart(:,:)
1343 945 : xred(:,:) = crystal%xred(:,:)
1344 :
1345 : !Compute the max range of the ifc with respect to the trainning set
1346 45 : range_ifc(:) = zero
1347 180 : do ii=1,3
1348 135 : norm = sqrt(rprimd(ii,1)**2+ rprimd(ii,2)**2+rprimd(ii,3)**2)
1349 180 : range_ifc(ii) = range_ifc(ii) + norm * sc_size(ii) / 2.0
1350 : end do
1351 :
1352 :
1353 : !compute new ncell
1354 45 : ncell = sc_size
1355 45 : lim1=((ncell(1)/2)) + 1
1356 45 : lim2=((ncell(2)/2)) + 1
1357 45 : lim3=((ncell(3)/2)) + 1
1358 45 : if(mod(ncell(1),2)/=0) lim1=lim1+1
1359 45 : if(mod(ncell(2),2)/=0) lim2=lim2+1
1360 45 : if(mod(ncell(3),2)/=0) lim3=lim3+1
1361 45 : nrpt=(2*lim1+1)*(2*lim2+1)*(2*lim3+1)
1362 :
1363 45 : ncell(1) = 2*lim1+1
1364 45 : ncell(2) = 2*lim2+1
1365 45 : ncell(3) = 2*lim3+1
1366 :
1367 : !Build the rpt point
1368 135 : ABI_MALLOC(rpt,(3,nrpt))
1369 135 : ABI_MALLOC(cell,(3,nrpt))
1370 :
1371 : !WARNING:
1372 : !Put the reference cell into the first element
1373 : !the code will first deal with the atoms of the first cell
1374 45 : irpt = 1
1375 45 : irpt_ref = 1
1376 180 : rpt(:,1) = zero
1377 180 : cell(:,irpt)=0
1378 : !Fill other rpt:
1379 270 : do r1=lim1,-lim1,-1
1380 1395 : do r2=lim2,-lim2,-1
1381 6975 : do r3=lim3,-lim3,-1
1382 5625 : if(r1==0.and.r2==0.and.r3==0) then
1383 : cycle
1384 : end if
1385 5580 : irpt=irpt+1
1386 5580 : rpt(1,irpt)=r1*rprimd(1,1)+r2*rprimd(1,2)+r3*rprimd(1,3)
1387 5580 : rpt(2,irpt)=r1*rprimd(2,1)+r2*rprimd(2,2)+r3*rprimd(2,3)
1388 5580 : rpt(3,irpt)=r1*rprimd(3,1)+r2*rprimd(3,2)+r3*rprimd(3,3)
1389 6750 : cell(1,irpt)=r1;cell(2,irpt)=r2;cell(3,irpt)=r3
1390 : end do
1391 : end do
1392 : end do
1393 :
1394 45 : if (.not.(allocated(symbols))) then
1395 135 : ABI_MALLOC(symbols,(natom))
1396 : endif
1397 : call symbols_crystal(crystal%natom,crystal%ntypat,crystal%npsp,&
1398 45 : & symbols,crystal%typat,crystal%znucl)
1399 :
1400 : !Compute the distances between atoms
1401 : !Now dist(3,ia,ib,irpt) contains the distance from atom ia to atom ib in unit cell irpt.
1402 225 : ABI_MALLOC(dist,(3,natom,natom,nrpt))
1403 596295 : dist = zero
1404 270 : do ia=1,natom
1405 1395 : do ib=1,natom
1406 141975 : do irpt=1,nrpt
1407 140625 : dist(1,ia,ib,irpt) = xcart(1,ib)-xcart(1,ia)+rpt(1,irpt)
1408 140625 : dist(2,ia,ib,irpt) = xcart(2,ib)-xcart(2,ia)+rpt(2,irpt)
1409 141750 : dist(3,ia,ib,irpt) = xcart(3,ib)-xcart(3,ia)+rpt(3,irpt)
1410 : end do
1411 : end do
1412 : end do
1413 :
1414 : !call polynomial_coeff_getList(cell,crystal,dist,list_symcoeff,list_symstr,&
1415 : ! & natom,nstr_sym,ncoeff_sym,nrpt,range_ifc,cutoff,sc_size=sc_size,&
1416 : ! & fit_iatom=fit_iatom_in)
1417 45 : ABI_SFREE(xcart)
1418 45 : ABI_SFREE(xred)
1419 45 : ABI_SFREE(rpt)
1420 45 : end subroutine prepare_for_getList
1421 :
1422 : !!****f* m_polynomial_coeff/polynomial_coeff_getList
1423 : !!
1424 : !! NAME
1425 : !! polynomial_coeff_getList
1426 : !!
1427 : !! FUNCTION
1428 : !! Get the list of all the possible coefficients for the polynome
1429 : !!
1430 : !! INPUTS
1431 : !! cell(3,nrpt) = indexes of the cells into the supercell (-1 -1 -1, 0 0 0 ...)
1432 : !! dist(3,natom,natom,nrpt) = distance between atoms atm1 is in the cell 0 0 0
1433 : !! atm2 is in the nrpt cell (see cell(3,nrpt))
1434 : !! for each component x,y and z
1435 : !! crystal<type(crystal_t)> = datatype with all the information for the crystal
1436 : !! natom = number of atoms in the unit cell
1437 : !! nrpt = number of cell in the supercell
1438 : !!
1439 : !! OUTPUT
1440 : !! list_symcoeff(6,ncoeff_sym,nsym) = array with the list of the coefficients,
1441 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
1442 : !! the 6th first dimensions are :
1443 : !! 1 = direction of the IFC
1444 : !! 2 = index of the atom number 1 (1=>natom)
1445 : !! 3 = index of the atom number 2 (1=>natom)
1446 : !! 4 = indexes of the cell of the second atom
1447 : !! (the atom number 1 is always in the cell 0 0 0)
1448 : !! 5 = weight of the term (-1 or 1)
1449 : !! 6 = indexes of the symmetric
1450 : !! list_symstr(nstr_sym,nsym) = array with the list of the strain and the symmetrics
1451 : !! nstr_sym = number of coefficient for the strain
1452 : !! ncoeff_sym = number of coefficient for the IFC
1453 : !! range_ifc(3) = maximum cut-off for the inter atomic forces constants in each direction
1454 : !! sc_size(3) = optional,size of the supercell used for the fit.
1455 : !! For example if you want to fit 2x2x2 cell the interation
1456 : !! Sr-Ti and Sr-Ti[2 0 0] will be identical for the fit process
1457 : !! If check_pbc is true we remove these kind of terms
1458 : !!
1459 : !! SOURCE
1460 :
1461 29 : subroutine polynomial_coeff_getList(cell,crystal,dist,list_symcoeff,list_symstr,&
1462 : & natom,nstr_sym,ncoeff_sym,nrpt,range_ifc,cutoff,sc_size,&
1463 : & fit_iatom)
1464 :
1465 : !Arguments ------------------------------------
1466 : !scalars
1467 : integer,intent(in) :: natom,nrpt
1468 : real(dp), intent(in) :: cutoff
1469 : integer,intent(out) :: ncoeff_sym,nstr_sym
1470 : integer,optional,intent(in):: fit_iatom
1471 : !arrays
1472 : integer,intent(in) :: cell(3,nrpt)
1473 : real(dp),intent(in):: dist(3,natom,natom,nrpt)
1474 : type(crystal_t), intent(in) :: crystal
1475 : integer,allocatable,intent(out) :: list_symcoeff(:,:,:),list_symstr(:,:,:)
1476 : integer,optional,intent(in) :: sc_size(3)
1477 : real(dp),intent(in):: range_ifc(3)
1478 : !Local variables-------------------------------
1479 : !scalar
1480 : integer :: ia,ib,icoeff,icoeff2,icoeff_tot,icoeff_tmp,idisy1,idisy2,ii
1481 : integer :: ipesy1,ipesy2,isym,irpt,irpt3,irpt_ref,irpt_sym
1482 : integer :: jj,jsym,mu,fit_iatom_in
1483 : integer :: ncoeff,ncoeff2,ncoeff3,ncoeff_max,nu
1484 : integer :: nsym,shift_atm1(3)
1485 : integer :: shift_atm2(3)
1486 : real(dp):: dist_orig,dist_sym,tolsym8
1487 : logical :: found,check_pbc,possible
1488 : !arrays
1489 : integer :: isym_rec(3,3),isym_rel(3,3),sc_size_in(3)
1490 : integer :: transl(3),min_range(3),max_range(3)
1491 29 : integer,allocatable :: blkval(:,:,:,:,:),list(:),list_symcoeff_tmp(:,:,:),list_symcoeff_tmp2(:,:,:)
1492 29 : integer,allocatable :: list_symstr_tmp(:,:,:),indsym(:,:,:) ,symrec(:,:,:),symrel(:,:,:),list_symcoeff_tmp3(:,:,:)
1493 29 : integer,allocatable :: index_irred(:)
1494 29 : real(dp),allocatable :: tnons(:,:)
1495 29 : real(dp),allocatable :: wkdist(:),distance(:,:,:)
1496 : real(dp) :: difmin(3)
1497 : real(dp) :: rprimd(3,3)
1498 : real(dp) :: tratom(3)
1499 : character(len=500) :: message
1500 :
1501 :
1502 :
1503 : !Initialisation of variables
1504 29 : irpt_sym = 0
1505 29 : nsym = crystal%nsym
1506 : rprimd = crystal%rprimd
1507 : !ABI_MALLOC(xcart,(3,natom))
1508 : !ABI_MALLOC(xred,(3,natom))
1509 : !xcart(:,:) = crystal%xcart(:,:)
1510 : !xred(:,:) = crystal%xred(:,:)
1511 29 : ncoeff_max = nrpt*natom*natom*3*3
1512 :
1513 : !Found the ref cell
1514 29 : irpt_ref = 1
1515 3654 : do irpt=1,nrpt
1516 4553 : if(all(cell(:,irpt)==0))then
1517 29 : irpt_ref = irpt
1518 : ! exit
1519 : end if
1520 : end do
1521 :
1522 : !Set the size of the interaction
1523 29 : check_pbc = .FALSE.
1524 29 : sc_size_in = 0
1525 29 : min_range = 0; max_range = 0
1526 29 : if(present(sc_size))then
1527 29 : sc_size_in = sc_size
1528 116 : do mu=1,3
1529 116 : call findBound_supercell(min_range(mu),max_range(mu),sc_size_in(mu))
1530 : end do
1531 : end if
1532 :
1533 : !Check which atom to fit, if not present do all atoms
1534 29 : if(present(fit_iatom))then
1535 28 : fit_iatom_in = fit_iatom
1536 : else
1537 : fit_iatom_in = -1
1538 : endif
1539 29 : if(fit_iatom_in > natom)then
1540 : write(message, '(3a)' )&
1541 0 : & 'fit_iatom cannot be greater than the number of atoms on the reference unit cell',ch10,&
1542 0 : & 'Action: Change input'
1543 0 : ABI_ERROR(message)
1544 : end if
1545 :
1546 : !Obtain a list of rotated atom labels:
1547 116 : ABI_MALLOC(indsym,(4,nsym,natom))
1548 87 : ABI_MALLOC(symrec,(3,3,nsym))
1549 58 : ABI_MALLOC(symrel,(3,3,nsym))
1550 87 : ABI_MALLOC(tnons,(3,nsym))
1551 18154 : symrec = crystal%symrec
1552 18154 : symrel = crystal%symrel
1553 5626 : tnons = crystal%tnons
1554 :
1555 29 : tolsym8=tol13
1556 : call symatm(indsym,natom,nsym,symrec,tnons,&
1557 29 : & tolsym8,crystal%typat,crystal%xred)
1558 174 : ABI_MALLOC(blkval,(3,natom,3,natom,nrpt))
1559 87 : ABI_MALLOC(list,(natom*nrpt))
1560 116 : ABI_MALLOC(list_symcoeff_tmp,(5,ncoeff_max,nsym))
1561 87 : ABI_MALLOC(wkdist,(natom*nrpt))
1562 :
1563 : !1-Fill strain list
1564 116 : ABI_MALLOC(list_symstr_tmp,(6,nsym,2))
1565 19575 : list_symstr_tmp = 1
1566 203 : do ia=1,6
1567 174 : if(list_symstr_tmp(ia,1,1)==0)cycle
1568 : ! Transform the voigt notation
1569 174 : if(ia<=3)then
1570 : mu=ia;nu=ia
1571 : else
1572 : select case(ia)
1573 : case(4)
1574 29 : mu=2;nu=3
1575 : case(5)
1576 29 : mu=1;nu=3
1577 : case(6)
1578 87 : mu=1;nu=2
1579 : end select
1580 : end if
1581 8555 : do isym=1,nsym
1582 : ! Get the symmetry matrix
1583 108576 : isym_rel(:,:) = crystal%symrel(:,:,isym)
1584 33582 : do idisy1=1,3
1585 108576 : do idisy2=1,3
1586 100224 : if((isym_rel(mu,idisy1)/=0.and.isym_rel(nu,idisy2)/=0)) then
1587 : ! Transform to the voig notation
1588 8352 : if(idisy1==idisy2)then
1589 4176 : list_symstr_tmp(ia,isym,1) = idisy1
1590 4176 : list_symstr_tmp(ia,isym,2) = isym_rel(mu,idisy1)
1591 : else
1592 4176 : if(idisy1==1.or.idisy2==1)then
1593 2784 : if(idisy1==2.or.idisy2==2)then
1594 1392 : list_symstr_tmp(ia,isym,1) = 6
1595 : end if
1596 2784 : if(idisy1==3.or.idisy2==3)then
1597 1392 : list_symstr_tmp(ia,isym,1) = 5
1598 : end if
1599 : else
1600 1392 : list_symstr_tmp(ia,isym,1) = 4
1601 : end if
1602 : end if
1603 8352 : list_symstr_tmp(ia,isym,2) = isym_rel(mu,idisy1) * isym_rel(nu,idisy2)
1604 : end if
1605 : end do
1606 : end do
1607 : ! Remove the symetric
1608 : ! if(list_symstr_tmp(ia,isym,1) > ia) then
1609 : ! list_symstr_tmp(list_symstr_tmp(ia,isym,1),:,1) = 0
1610 : ! end if
1611 : end do
1612 : end do
1613 :
1614 : !Count the number of strain and transfert into the final array
1615 29 : nstr_sym = 0
1616 203 : do ia=1,6
1617 203 : if(list_symstr_tmp(ia,1,1)/=0) nstr_sym = nstr_sym + 1
1618 : end do
1619 :
1620 29 : if(allocated(list_symstr))then
1621 0 : ABI_SFREE(list_symstr)
1622 : end if
1623 145 : ABI_MALLOC(list_symstr,(nstr_sym,nsym,2))
1624 :
1625 29 : icoeff_tmp = 1
1626 203 : do ia=1,6
1627 203 : if(list_symstr_tmp(ia,1,1)/=0) then
1628 17226 : list_symstr(icoeff_tmp,:,:) = list_symstr_tmp(ia,:,:)
1629 174 : icoeff_tmp = icoeff_tmp + 1
1630 : end if
1631 : end do
1632 : !END STRAIN
1633 :
1634 : !Compute the distance between each atoms. Indeed the dist array contains the difference of
1635 : !cartesian coordinate for each direction
1636 : ! dist: vector between atom a, (0,0,0) and atom b (rpt)
1637 :
1638 145 : ABI_MALLOC(distance,(natom,natom,nrpt))
1639 : ! Fortran 2008: distance = norm2(dist, dim=1)
1640 174 : do ia=1,natom
1641 899 : do ib=1,natom
1642 91495 : do irpt=1,nrpt
1643 : distance(ia,ib,irpt) = ((dist(1,ia,ib,irpt))**2+(dist(2,ia,ib,irpt))**2+&
1644 91350 : & (dist(3,ia,ib,irpt))**2)**0.5
1645 : end do
1646 : end do
1647 : end do
1648 :
1649 :
1650 : !Set to one blkval, all the coeff have to be compute
1651 1163654 : blkval = 1
1652 29 : icoeff = 1
1653 29 : icoeff_tot = 1
1654 234901421 : list_symcoeff_tmp = 0
1655 :
1656 : !2-Fill atom list
1657 : !Big loop over generic atom
1658 174 : do ia=1,natom
1659 290 : wkdist(:)=reshape(distance(ia,:,:),(/natom*nrpt/))
1660 90770 : do ii=1,natom*nrpt
1661 90770 : list(ii)=ii
1662 : end do
1663 : ! FIXME: hexu: I think this should be improved.
1664 : ! It seems that it depends on the specific order of the
1665 : ! cell, and the implementation of sort algorithm.
1666 : ! The sort should preserve the order if two distances are the same.
1667 : ! In the future, the order of the cell might need to be unified
1668 : ! Also it seems to depend on the cubic cell.
1669 145 : call sort_dp(natom*nrpt,wkdist,list,tol8)
1670 90799 : do ii=1,natom*nrpt
1671 : ! Get the irpt and ib
1672 90625 : irpt=(list(ii)-1)/natom+1
1673 90625 : ib=list(ii)-natom*(irpt-1)
1674 90625 : possible = .true.
1675 : !Old way with the cut off
1676 90625 : if(cutoff < distance(ia,ib,irpt))then
1677 : possible = .false.
1678 : else
1679 : ! in each direction jj, the d component d(jj) should be smaller than range_ifc(jj)
1680 66196 : do jj=1,3
1681 : ! if(abs(dist(jj,ia,ib,irpt)) - range_ifc(jj) > tol10.or.&
1682 : ! & abs(abs(dist(jj,ia,ib,irpt)) - range_ifc(jj)) < tol10)then
1683 66196 : if(abs(dist(jj,ia,ib,irpt)) - range_ifc(jj) > tol10)then
1684 19296 : possible = .false.
1685 : end if
1686 : end do
1687 : endif
1688 :
1689 : ! If this distance is superior to the cutoff, we don't compute that term
1690 16549 : if(.not.possible)then
1691 1129908 : blkval(:,ia,:,ib,irpt)= 0
1692 : ! remove duplication: if in reference cell, only consider ab, not ba.
1693 88116 : if(irpt==irpt_ref)blkval(:,ib,:,ia,irpt)= 0
1694 : ! Stop the loop
1695 : cycle
1696 : end if
1697 :
1698 : ! If this coefficient is not possible, we cycle...
1699 3709 : if (all(blkval(:,ia,:,ib,irpt)==0)) cycle
1700 :
1701 : ! Save the distance between the two atoms for futur checks
1702 3709 : dist_orig = (dist(1,ia,ib,irpt)**2+dist(2,ia,ib,irpt)**2+dist(3,ia,ib,irpt)**2)**0.5
1703 :
1704 14981 : do mu=1,3
1705 48217 : do nu=1,3
1706 : ! Check if : - The coefficient is not yet compute
1707 : ! - The directions are the same
1708 : ! - The atoms are not equivalent
1709 33381 : if (mu/=nu) then
1710 22254 : blkval(mu,ia,nu,ib,irpt)=0
1711 22254 : blkval(nu,ia,mu,ib,irpt)=0
1712 22254 : cycle
1713 : end if
1714 : ! Pass if the atoms are identical and in the ref cell
1715 11127 : if(irpt==irpt_ref.and.ia==ib) then
1716 435 : blkval(mu,ia,nu,ib,irpt)=0
1717 435 : blkval(nu,ib,mu,ia,irpt)=0
1718 435 : cycle
1719 : end if
1720 10692 : if(blkval(mu,ia,nu,ib,irpt)==1)then
1721 : ! Loop over symmetries
1722 523908 : do isym=1,nsym
1723 : ! Get the symmetry matrix for this sym
1724 6671808 : isym_rec(:,:) = crystal%symrec(:,:,isym)
1725 6671808 : isym_rel(:,:) = crystal%symrel(:,:,isym)
1726 : ! Get the corresponding atom and shift with the symetries
1727 : ! For atom 1
1728 513216 : ipesy1 = indsym(4,isym,ia)
1729 2052864 : shift_atm1 = indsym(1:3,isym,ia)
1730 : ! And atom 2
1731 2052864 : do jj=1,3 ! Apply transformation to original coordinates.
1732 : tratom(jj) = dble(isym_rec(1,jj))*(crystal%xred(1,ib)+cell(1,irpt)-tnons(1,isym))&
1733 : & +dble(isym_rec(2,jj))*(crystal%xred(2,ib)+cell(2,irpt)-tnons(2,isym))&
1734 2052864 : & +dble(isym_rec(3,jj))*(crystal%xred(3,ib)+cell(3,irpt)-tnons(3,isym))
1735 :
1736 : end do
1737 :
1738 : ! Find symmetrically equivalent atom
1739 : call symchk(difmin,ipesy2,natom,tratom,transl,crystal%typat(ib),&
1740 513216 : & crystal%typat,crystal%xred(:,:))
1741 :
1742 : ! Put information into array indsym: translations and label
1743 2052864 : shift_atm2(:)= transl(:) - shift_atm1(:)
1744 : found = .false.
1745 64665216 : do irpt3=1,nrpt
1746 : if(cell(1,irpt3)==shift_atm2(1).and.&
1747 64152000 : & cell(2,irpt3)==shift_atm2(2).and.&
1748 513216 : & cell(3,irpt3)==shift_atm2(3))then
1749 64152000 : found = .true.
1750 64152000 : irpt_sym = irpt3
1751 : end if
1752 : end do
1753 :
1754 : ! Check the distance
1755 : dist_sym = (dist(1,ipesy1,ipesy2,irpt_sym)**2+&
1756 : & dist(2,ipesy1,ipesy2,irpt_sym)**2+&
1757 513216 : & dist(3,ipesy1,ipesy2,irpt_sym)**2)**0.5
1758 513216 : if(abs(dist_orig - dist_sym) > tol10)then
1759 : write(message, '(a,i0,2a,I0,a,es15.8,2a,es15.8,2a)' )&
1760 0 : & 'The distance between the atoms for the coefficient number ',icoeff,ch10,&
1761 0 : & 'with the symmetry ',isym,' is ',dist_sym,ch10,'but the original distance is',&
1762 0 : & dist_orig,ch10,&
1763 0 : & 'Action: Contact abinit group'
1764 0 : ABI_BUG(message)
1765 : end if
1766 : ! Now that a symmetric perturbation has been obtained,
1767 : ! including the expression of the symmetry matrix, see
1768 : ! if the symmetric perturbations are available
1769 2576772 : do idisy1=1,3
1770 6671808 : do idisy2=1,3
1771 6158592 : if (idisy1/=idisy2) then
1772 : ! Remove this term (is not computed)
1773 : ! Also remove opposite term... (Srx-Tix) = (Tix-Srx)
1774 3079296 : blkval(idisy1,ipesy1,idisy2,ipesy2,irpt_sym) = 0
1775 3079296 : blkval(idisy2,ipesy1,idisy1,ipesy2,irpt_sym) = 0
1776 3079296 : cycle
1777 : else
1778 1539648 : if(isym_rel(mu,idisy1)/=0.and.isym_rel(nu,idisy2)/=0)then
1779 513216 : if(.not.found.or.(irpt_sym==irpt_ref.and.ipesy1==ipesy2)) then
1780 : ! Remove this term (is not computed) Sr-Sr or not include in the cell
1781 : ! Also remove oposite term... (Srx-Tix) = (Ti-Srx)
1782 0 : blkval(idisy1,ipesy1,idisy2,ipesy2,irpt_sym) = 0
1783 0 : blkval(idisy2,ipesy2,idisy1,ipesy1,irpt_sym) = 0
1784 0 : cycle
1785 : else
1786 : ! Fill the list with the coeff and symmetric (need all symmetrics)
1787 2566080 : list_symcoeff_tmp(1:4,icoeff,isym)=(/idisy1,ipesy1,ipesy2,irpt_sym/)
1788 : ! Check the sign
1789 513216 : if(isym_rel(mu,idisy1)/=isym_rel(nu,idisy2))then
1790 : write(message, '(a,i0,a,I0,4a)' )&
1791 0 : & 'The sign of coefficient number ',icoeff,' with the symmetry ',isym,ch10,&
1792 0 : & 'can not be found... Something is going wrong',ch10,&
1793 0 : & 'Action: Contact abinit group'
1794 0 : ABI_BUG(message)
1795 : end if
1796 513216 : list_symcoeff_tmp(5,icoeff,isym)= isym_rel(nu,idisy2)
1797 : end if
1798 : end if
1799 : end if
1800 : end do
1801 : end do
1802 : end do ! end loop sym
1803 10692 : icoeff = icoeff + 1
1804 : end if
1805 : ! This coeff is now computed
1806 21819 : blkval(mu,ia,nu,ib,irpt)= 0
1807 : end do ! end loop nu
1808 : end do ! end loop mu
1809 : end do ! end loop ii: iatom and irpt.
1810 : end do ! end loop ia
1811 :
1812 : !Reset the output
1813 29 : ABI_SFREE(list_symcoeff)
1814 :
1815 29 : ABI_SFREE(distance)
1816 :
1817 : !Transfert the final array with all the coefficients
1818 : !With this array, we can access to all the terms presents
1819 : !ncoeff1 + symetrics
1820 : !first dimension is 4 (mu,ia,ib,irpt)
1821 : !irpt is the index of the cell of the atom ib in the cell array
1822 : !example cell(:,irpt=12) can be (-1 0 -2). The cell of ia is
1823 : !always 0 0 0
1824 : !Transfert the final array for the list of irreductible coeff and symetries
1825 : !With this array, we can access to the irretuctible coefficients (ncoeff1) and
1826 : !all the symetrics of these coefficients (nsym)
1827 : !first dimension is 5 (mu,ia,ib,irpt,icoeff)
1828 : !icoeff is the position of this coefficients in the list_fullcoeff array
1829 :
1830 : !1/ step remove the zero coeff in this array
1831 29 : ncoeff = 0
1832 815654 : do icoeff = 1,ncoeff_max
1833 4840319 : if(.not.(all(list_symcoeff_tmp(:,icoeff,1)==0)))then
1834 10692 : ncoeff = ncoeff + 1
1835 : end if
1836 : end do
1837 :
1838 116 : ABI_MALLOC(list_symcoeff_tmp2,(6,ncoeff,nsym))
1839 3593933 : list_symcoeff_tmp2 = 0
1840 29 : icoeff = 0
1841 815654 : do icoeff_tmp = 1,ncoeff_max
1842 4840319 : if(.not.(all(list_symcoeff_tmp(:,icoeff_tmp,1)==0)))then
1843 10692 : icoeff = icoeff + 1
1844 3089988 : list_symcoeff_tmp2(1:5,icoeff,:) = list_symcoeff_tmp(1:5,icoeff_tmp,:)
1845 : end if
1846 : end do
1847 :
1848 :
1849 : !2/ set the dimension six of list_symcoeff_tmp2(6,icoeffs,1)
1850 : ! and check is a symetric coeff is not coresspondig to an other
1851 : ! one, in this case we set this coeff to 0
1852 : ! ncoeff2 = zero
1853 10721 : do icoeff = 1,ncoeff
1854 : ! found the index of each coeff in list_fullcoeff
1855 523937 : do isym = 1,nsym
1856 : icoeff2 = getCoeffFromList(list_symcoeff_tmp2(:,:,1),&
1857 : & list_symcoeff_tmp2(2,icoeff,isym),&
1858 : & list_symcoeff_tmp2(3,icoeff,isym),&
1859 : & list_symcoeff_tmp2(4,icoeff,isym),&
1860 : & list_symcoeff_tmp2(1,icoeff,isym),&
1861 513216 : & ncoeff)
1862 523908 : list_symcoeff_tmp2(6,icoeff,isym) = icoeff2
1863 : end do
1864 : end do
1865 :
1866 :
1867 :
1868 :
1869 : ! filter the list_symcoeff_tmp2 to remove the terms which the equivalent cannot be found.
1870 : ! This can happen when the cell is too small and the equivalent is out of the cell
1871 :
1872 : block
1873 58 : integer :: list_symcoeff_tmp3(6,ncoeff,nsym)
1874 : integer :: counter_good, counter_bad, ncoeff_orig
1875 58 : integer :: coeffmap(ncoeff)
1876 29 : ncoeff_orig=ncoeff
1877 29 : counter_bad=0
1878 29 : counter_good=0
1879 10721 : coeffmap(:)=0
1880 : ! copy the list_symcoeff_tmp2 to list_symcoeff_tmp3
1881 3593933 : list_symcoeff_tmp3 = list_symcoeff_tmp2
1882 :
1883 10721 : do icoeff = 1,ncoeff
1884 523937 : if(any(list_symcoeff_tmp2(6,icoeff,:)==0)) then
1885 0 : counter_bad=counter_bad+1
1886 : else
1887 10692 : counter_good=counter_good+1
1888 10692 : coeffmap(icoeff)=counter_good
1889 : endif
1890 : end do
1891 :
1892 29 : ABI_SFREE(list_symcoeff_tmp2)
1893 29 : ncoeff=ncoeff-counter_bad
1894 116 : ABI_MALLOC(list_symcoeff_tmp2,(6,ncoeff,nsym))
1895 29 : counter_good=0
1896 10721 : do icoeff = 1,ncoeff_orig
1897 523937 : if(.not. (any(list_symcoeff_tmp3(6,icoeff,:)==0))) then
1898 10692 : counter_good=counter_good+1
1899 3603204 : list_symcoeff_tmp2(:,counter_good,:)=list_symcoeff_tmp3(:,icoeff,:)
1900 523908 : do isym = 1,nsym
1901 523908 : if(coeffmap(list_symcoeff_tmp2(6,counter_good,isym)) /= 0) then
1902 513216 : list_symcoeff_tmp2(6,counter_good,isym)=coeffmap(list_symcoeff_tmp2(6,counter_good,isym))
1903 : else
1904 0 : ABI_BUG("coeffmap is not correct.")
1905 : endif
1906 : end do
1907 : endif
1908 : end do
1909 :
1910 :
1911 :
1912 : end block
1913 :
1914 :
1915 : !2.5/do checks
1916 10721 : do icoeff = 1,ncoeff
1917 523937 : do isym = 1,nsym
1918 523908 : if(list_symcoeff_tmp2(6,icoeff,isym)==0)then
1919 : write(message, '(a,i0,a,I0,4a)' )&
1920 0 : & 'The coefficient number ',icoeff,' with the symetrie ',isym,ch10,&
1921 0 : & 'has no equivalent',ch10,&
1922 0 : & 'Action: Contact abinit group'
1923 0 : ABI_BUG(message)
1924 : else
1925 513216 : if(icoeff /= list_symcoeff_tmp2(6,icoeff,isym))then
1926 487632 : if(list_symcoeff_tmp2(1,icoeff,isym)/=&
1927 : & list_symcoeff_tmp2(1,list_symcoeff_tmp2(6,icoeff,isym),1))then
1928 : write(message, '(a,i0,a,I0,2a,I0,4a)' )&
1929 0 : & 'The coefficient number ',icoeff,' with the symetrie ',isym,ch10,&
1930 0 : & 'does not refer to the same coefficient ',list_symcoeff_tmp2(6,icoeff,1),ch10,&
1931 0 : & 'because the direction is different:',ch10,&
1932 0 : & 'Action: Contact abinit group'
1933 0 : ABI_BUG(message)
1934 : end if
1935 487632 : if(list_symcoeff_tmp2(4,icoeff,isym)/=&
1936 : & list_symcoeff_tmp2(4,list_symcoeff_tmp2(6,icoeff,isym),1))then
1937 : write(message, '(a,i0,a,I0,2a,I0,4a)' )&
1938 0 : & 'The coefficient number ',icoeff,' with the symetrie ',isym,ch10,&
1939 0 : & 'does not refer to the same coefficient ',list_symcoeff_tmp2(6,icoeff,1),ch10,&
1940 0 : & 'because the cell is different',ch10,&
1941 0 : & 'Action: Contact abinit group'
1942 0 : ABI_BUG(message)
1943 : end if
1944 : if((list_symcoeff_tmp2(2,icoeff,isym)/=&
1945 : & list_symcoeff_tmp2(2,list_symcoeff_tmp2(6,icoeff,isym),1).and.&
1946 : & list_symcoeff_tmp2(3,icoeff,isym)/=&
1947 487632 : & list_symcoeff_tmp2(3,list_symcoeff_tmp2(6,icoeff,isym),1)).and.&
1948 : & (list_symcoeff_tmp2(2,icoeff,isym)/=&
1949 : & list_symcoeff_tmp2(3,list_symcoeff_tmp2(6,icoeff,isym),1).and.&
1950 : & list_symcoeff_tmp2(3,icoeff,isym)/=&
1951 : & list_symcoeff_tmp2(2,list_symcoeff_tmp2(6,icoeff,isym),1)))then
1952 : write(message, '(a,i0,a,I0,2a,I0,4a)' )&
1953 0 : & 'The coefficient number ',icoeff,' with the symetrie ',isym,ch10,&
1954 0 : & 'does not refer to the same coefficient ',list_symcoeff_tmp2(6,icoeff,1),ch10,&
1955 0 : & 'because the atoms different',ch10,&
1956 0 : & 'Action: Contact abinit group'
1957 0 : ABI_BUG(message)
1958 : end if
1959 : end if
1960 : end if
1961 : end do
1962 : end do
1963 :
1964 :
1965 : !Check if the atom 2 is not (with the PBC) is in the same cell than
1966 : !the atom 1. For example if you want to fit 2x2x2 cell the interation
1967 : !Sr-Ti and Sr-Ti[2 0 0] will be identical for the fit process...
1968 10721 : do icoeff = 1,ncoeff
1969 10692 : if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0)))then
1970 42768 : do mu=1,3
1971 : ! out of max_range(mu)
1972 32076 : if( -max_range(mu) > cell(mu,list_symcoeff_tmp2(4,icoeff,1)) .or. &
1973 10692 : & cell(mu,list_symcoeff_tmp2(4,icoeff,1)) > max_range(mu))then
1974 :
1975 : ! FIXME: hexu: cell(mu, irpt). But why -1?
1976 : ! The if above looks sufficient.
1977 : !if(cell(mu,list_symcoeff_tmp2(4,icoeff,1)) < -1)then
1978 0 : list_symcoeff_tmp2(:,icoeff,:)=0
1979 : exit
1980 : !end if
1981 : end if
1982 : end do
1983 : end if
1984 : !MS only keep terms with ia == fit_iatom or ib == fit_iatom specified in input
1985 10721 : if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0)) .and. fit_iatom_in > 0)then
1986 9390 : if (list_symcoeff_tmp2(2,icoeff,1) /= fit_iatom_in) then !& LB
1987 : !& list_symcoeff_tmp2(3,icoeff,1) /= fit_iatom_in)then LB
1988 53214 : list_symcoeff_tmp2(:,icoeff,1) = 0
1989 : ! else if(list_symcoeff_tmp2(2,icoeff,1) /= fit_iatom_in) then ! &
1990 : !& .and. list_symcoeff_tmp2(3,icoeff,1) == fit_iatom_in & !LB
1991 : !& .and. any(cell(:,list_symcoeff_tmp2(4,icoeff,1)) /= 0))then !LB
1992 : ! list_symcoeff_tmp2(:,icoeff,1) = 0
1993 : endif
1994 : endif
1995 : !For Debugging keep only terms A_x-A_x[100] etc. comment if above
1996 : ! if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0)))then
1997 : ! if (list_symcoeff_tmp2(2,icoeff,1) /= 1 .or. list_symcoeff_tmp2(3,icoeff,1) /= 1)then
1998 : ! list_symcoeff_tmp2(:,icoeff,1) = 0
1999 : ! endif !MS only keep terms with ia == 1
2000 : ! endif
2001 : end do
2002 :
2003 :
2004 : !3/ Remove useless terms like opposites
2005 10721 : do icoeff = 1,ncoeff
2006 60612 : if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0)) .and. & ! valid term.
2007 29 : & list_symcoeff_tmp2(2,icoeff,1) /= list_symcoeff_tmp2(3,icoeff,1))then ! on-site term. ! FIXME: hexu:I don't understand if iatom=jatom but rpt/=0, it is not onsite.
2008 78008 : do isym = 1,nsym
2009 : !icoeff2 = list_symcoeff_tmp2(6,icoeff,isym)
2010 : !if (icoeff2> icoeff)then
2011 : ! list_symcoeff_tmp2(:,icoeff2,1) = 0
2012 : !end if
2013 3745976 : do jsym=1,nsym
2014 : ! FIXME: Should the rpt be -rpt??
2015 : ! icoeff2 = getCoeffFromList(list_symcoeff_tmp2(:,:,jsym),&
2016 : !& list_symcoeff_tmp2(3,icoeff,isym),&
2017 : !& list_symcoeff_tmp2(2,icoeff,isym),&
2018 : !& list_symcoeff_tmp2(4,icoeff,isym),& !rpt
2019 : !& list_symcoeff_tmp2(1,icoeff,isym),&
2020 : !& ncoeff)
2021 : icoeff2 = getCoeffFromList(list_symcoeff_tmp2(:,:,jsym),&
2022 : & list_symcoeff_tmp2(3,icoeff,isym),&
2023 : & list_symcoeff_tmp2(2,icoeff,isym),&
2024 : & list_symcoeff_tmp2(4,icoeff,isym),& !rpt
2025 : & find_opposite_irpt(cell, list_symcoeff_tmp2(1,icoeff,isym)),&
2026 3667968 : & ncoeff)
2027 :
2028 3744384 : if (icoeff2> icoeff)then
2029 2091530 : list_symcoeff_tmp2(:,icoeff2,1) = 0
2030 : end if
2031 : end do
2032 : end do
2033 : end if
2034 : end do
2035 :
2036 : !4/ Recount the number of coeff after step 3
2037 29 : ncoeff2 = 0
2038 29 : isym = 0
2039 10721 : do icoeff = 1,ncoeff
2040 60641 : if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0)))then
2041 2372 : ncoeff2 = ncoeff2 + 1
2042 : end if
2043 : end do
2044 :
2045 :
2046 29 : ABI_SFREE(list_symcoeff_tmp)
2047 87 : ABI_MALLOC(list_symcoeff_tmp,(6,ncoeff,nsym))
2048 3593962 : list_symcoeff_tmp = list_symcoeff_tmp2
2049 :
2050 : !4.1 Count irreducible terms
2051 10721 : do icoeff = 1,ncoeff
2052 523937 : do isym = 1,nsym
2053 513216 : icoeff2 = list_symcoeff_tmp2(6,icoeff,isym)
2054 523908 : if (icoeff2> icoeff)then
2055 1706712 : list_symcoeff_tmp(:,icoeff2,1) = 0
2056 : end if
2057 : end do
2058 : end do
2059 :
2060 29 : ncoeff3 = 0
2061 10721 : do icoeff = 1,ncoeff
2062 73937 : if(.not.(all(list_symcoeff_tmp(:,icoeff,1)==0)))then
2063 156 : ncoeff3 = ncoeff3 + 1
2064 : end if
2065 : end do
2066 :
2067 : !4.2 Put irreducible terms in front of list_symcoeff_tmp3
2068 : ! Store index of irreducible terms
2069 116 : ABI_MALLOC(list_symcoeff_tmp3,(6,ncoeff2,nsym))
2070 87 : ABI_MALLOC(index_irred,(ncoeff3))
2071 29 : icoeff_tmp = 0
2072 10721 : do icoeff = 1,ncoeff
2073 73937 : if(.not.(all(list_symcoeff_tmp(:,icoeff,1)==0)))then
2074 156 : icoeff_tmp = icoeff_tmp+1
2075 156 : index_irred(icoeff_tmp) = icoeff
2076 52572 : list_symcoeff_tmp3(:,icoeff_tmp,:) = list_symcoeff_tmp(:,icoeff,:)
2077 : endif
2078 : enddo
2079 :
2080 : !4.3 Put symmetric equivalents behind in list_symcoeff_tmp3
2081 : ! Attention icoeff_tmps keeps it's value of loop before
2082 : ! TODO for check should be equal to ncoeff2
2083 10721 : do icoeff = 1,ncoeff
2084 : if(.not.(all(list_symcoeff_tmp2(:,icoeff,1)==0))&
2085 186342 : & .and..not. any(index_irred == icoeff))then
2086 2216 : icoeff_tmp = icoeff_tmp+1
2087 746792 : list_symcoeff_tmp3(:,icoeff_tmp,:) = list_symcoeff_tmp2(:,icoeff,:)
2088 : endif
2089 : enddo
2090 :
2091 : !4.4 A little copy round
2092 29 : ABI_SFREE(list_symcoeff_tmp)
2093 87 : ABI_MALLOC(list_symcoeff_tmp,(6,ncoeff2,nsym))
2094 798442 : list_symcoeff_tmp = list_symcoeff_tmp3
2095 :
2096 : !5/ Final transfert
2097 87 : ABI_MALLOC(list_symcoeff,(6,ncoeff2,nsym))
2098 798413 : list_symcoeff = 0
2099 : icoeff = 0
2100 2401 : do icoeff = 1,ncoeff2
2101 799364 : list_symcoeff(1:6,icoeff,:) = list_symcoeff_tmp(1:6,icoeff,:)
2102 116257 : do isym=1,nsym
2103 : end do
2104 : end do
2105 :
2106 : !6/ reset the dimension six of list_symcoeff_tmp2(6,icoeffs,1)
2107 : ! and check is a symetric coeff is not coresspondig to an other
2108 : ! one, in this case we set this coeff to 0
2109 2401 : do icoeff = 1,ncoeff2
2110 : ! found the index of each coeff in list_fullcoeff
2111 116257 : do isym = 1,nsym
2112 : icoeff2 = getCoeffFromList(list_symcoeff(:,:,1),&
2113 : & list_symcoeff(2,icoeff,isym),&
2114 : & list_symcoeff(3,icoeff,isym),&
2115 : & list_symcoeff(4,icoeff,isym),&
2116 : & list_symcoeff(1,icoeff,isym),&
2117 113856 : & ncoeff2)
2118 116228 : list_symcoeff(6,icoeff,isym) = icoeff2
2119 : ! list_symcoeff(6,icoeff2,isym) = icoeff
2120 : end do
2121 : end do
2122 :
2123 : !Set the max number of coeff inside list_symcoeff
2124 29 : ncoeff_sym = ncoeff3
2125 :
2126 :
2127 : !Deallocation
2128 29 : ABI_SFREE(blkval)
2129 29 : ABI_SFREE(list)
2130 29 : ABI_SFREE(list_symcoeff_tmp)
2131 29 : ABI_SFREE(list_symcoeff_tmp2)
2132 29 : ABI_SFREE(list_symcoeff_tmp3)
2133 29 : ABI_SFREE(list_symstr_tmp)
2134 29 : ABI_SFREE(index_irred)
2135 29 : ABI_SFREE(indsym)
2136 29 : ABI_SFREE(symrec)
2137 29 : ABI_SFREE(symrel)
2138 29 : ABI_SFREE(tnons)
2139 : !ABI_FREE(xcart)
2140 : !ABI_FREE(xred )
2141 29 : ABI_SFREE(wkdist)
2142 29 : end subroutine polynomial_coeff_getList
2143 : !!***
2144 :
2145 :
2146 : !!****f* m_polynomial_coeff/polynomial_coeff_getNorder
2147 : !!
2148 : !! NAME
2149 : !! polynomial_coeff_getNorder
2150 : !!
2151 : !! FUNCTION
2152 : !! Compute and store into the datatype coefficients, all the possible
2153 : !! coefficients for given orders
2154 : !!
2155 : !! INPUTS
2156 : !! cutoff = cut-off for the inter atomic forces constants
2157 : !! crystal<type(crystal_t)> = datatype with all the information for the crystal
2158 : !! power_disps(2) = array with the minimal and maximal power_disp to be computed
2159 : !! max_power_strain = maximum order of the strain of the strain phonon coupling
2160 : !! option = 0 compute all terms
2161 : !! 1 still in development
2162 : !! sc_size(3) = size of the supercell used for the fit.
2163 : !! For example if you want to fit 2x2x2 cell the interation
2164 : !! Sr-Ti and Sr-Ti[2 0 0] will be identical for the fit process
2165 : !! If check_pbc is true we remove these kind of terms
2166 : !! comm = MPI communicator
2167 : !! anharmstr = logical, optional : TRUE, the anharmonic strain is computed (\eta)^power_disp ...
2168 : !! FALSE, (default) the anharmonic strain are not computed
2169 : !! spcoupling= logical, optional : TRUE(default) the anharmonic strain-phonon coupling is computed
2170 : !! only_odd_power = logical, optional : if TRUE return only odd power
2171 : !! only_even_power= logical, optional : if TRUe return only even power
2172 : !! distributed = logical, optional : True, the coefficients will be distributed on the CPU
2173 : !! verbose = optional, flag for the verbose mode
2174 : !!
2175 : !! OUTPUT
2176 : !! polynomial_coeff<(type(polynomial_coeff_type)>(ncoeff) = array of datatype with the polynomial_coeff
2177 : !! ncoeff = number of coefficients for this CPU if distributed == true, all otherwise
2178 : !! ncoeff_tot = total number of coefficient over the CPU
2179 : !!
2180 : !! SOURCE
2181 :
2182 44 : subroutine polynomial_coeff_getNorder(coefficients,crystal,cutoff,ncoeff,ncoeff_tot,power_disps,&
2183 : & max_power_strain,option,sc_size,comm,anharmstr,spcoupling,&
2184 : & distributed,only_odd_power,only_even_power,fit_iatom,&
2185 44 : & compute_symmetric,dispterms,verbose, max_nbody)
2186 :
2187 : !FIXME: There is a bug that the onebody term are duplicated.
2188 : ! e.g. (Bx-O1x)^6 and (O1x-Bx)^6 both appears
2189 : ! We can force ia<ib if onebody.
2190 :
2191 : !Arguments ------------------------------------
2192 : !scalars
2193 : integer,intent(in) :: max_power_strain,option,comm
2194 : integer,intent(out):: ncoeff,ncoeff_tot
2195 : integer,optional,intent(in) :: fit_iatom
2196 : real(dp),intent(in):: cutoff
2197 : logical,optional,intent(in) :: anharmstr,spcoupling,distributed,verbose,dispterms
2198 : logical,optional,intent(in) :: only_odd_power,only_even_power,compute_symmetric
2199 : !arrays
2200 : integer,intent(in) :: power_disps(2),sc_size(3), max_nbody(:)
2201 : type(crystal_t), intent(inout) :: crystal
2202 : type(polynomial_coeff_type),allocatable,intent(inout) :: coefficients(:)
2203 : !Local variables-------------------------------
2204 : !scalar
2205 : integer :: icoeff,icoeff2,icoeff3,ierr,ii,iterm
2206 : integer :: i
2207 : integer :: master,my_rank,my_ncoeff,my_newncoeff,natom,ncombination,ncoeff_max,ncoeff_sym
2208 : integer :: ncoeff_symsym,nirred_comb,iirred_comb,ndisp,nstrain,fit_iatom_in
2209 : integer :: ncoeff_alone,ndisp_max,nproc,nrpt,nsym,nterm,nstr_sym,my_size
2210 : integer :: my_icoeff,rank_to_send,rank_to_receive,rank_to_send_save
2211 : integer :: ncombi_alone,my_ncombi_simple,my_ncombi_start,my_ncombi_end,my_ncombi,my_nirred
2212 : logical :: iam_master,need_anharmstr,need_spcoupling,need_distributed,need_verbose
2213 : logical :: need_only_odd_power,need_only_even_power,compute_sym,irreducible,need_compute_symmetric
2214 : logical :: need_dispterms
2215 : !arrays
2216 : integer :: shape_listsymcoeff(3),shape_listsymstr(3)
2217 44 : integer,allocatable :: buffsize(:),buffdispl(:) !,dummylist(:) ,index_irred(:)
2218 44 : integer,allocatable :: offsets(:)
2219 44 : integer,allocatable :: cell(:,:),compatibleCoeffs(:,:)
2220 44 : integer,allocatable :: list_symcoeff(:,:,:),list_symstr(:,:,:),list_coeff(:),list_combination(:,:)
2221 44 : integer,allocatable :: list_combination_tmp(:,:)
2222 44 : integer,allocatable :: irank_ncombi(:),my_index_irredcomb(:)
2223 44 : integer,allocatable :: my_coefflist(:),my_coeffindexes(:),my_newcoeffindexes(:),my_list_combination(:,:)
2224 44 : type(int2d_array_type) :: my_array_combination
2225 44 : integer,allocatable :: my_list_combination_tmp(:,:)
2226 : real(dp) :: rprimd(3,3),range_ifc(3)
2227 44 : real(dp),allocatable :: dist(:,:,:,:)
2228 44 : character(len=5),allocatable :: symbols(:)
2229 : character(len=200):: name
2230 : character(len=500) :: message
2231 44 : type(polynomial_coeff_type),dimension(:),allocatable :: coeffs_tmp
2232 44 : type(polynomial_term_type),dimension(:),allocatable :: terms
2233 : character(len=fnlen) :: filename
2234 : ! *************************************************************************
2235 : !Hide filename for debugging
2236 : ABI_UNUSED(filename)
2237 :
2238 44 : call get_mpi_params()
2239 44 : call free_output_coefficients()
2240 44 : call check_and_normalize_input_params()
2241 44 : call getList() ! of pairs
2242 44 : call get_combinations_of_lists()
2243 44 : call get_symmetric_combinations()
2244 44 : call combinations_to_terms()
2245 44 : call distribute_coefficients_over_cpu()
2246 44 : call free_memory()
2247 : contains
2248 44 : subroutine get_mpi_params()
2249 : !MPI variables
2250 44 : master = 0
2251 44 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2252 44 : iam_master = (my_rank == master)
2253 :
2254 :
2255 44 : end subroutine get_mpi_params
2256 :
2257 44 : subroutine free_output_coefficients()
2258 : !Free the output
2259 44 : if(allocated(coefficients))then
2260 11 : do ii =1,size(coefficients)
2261 11 : call polynomial_coeff_free(coefficients(ii))
2262 : end do
2263 11 : ABI_SFREE(coefficients)
2264 : end if
2265 44 : end subroutine free_output_coefficients
2266 :
2267 44 : subroutine check_and_normalize_input_params()
2268 : !Check
2269 44 : if(option > power_disps(2))then
2270 : write(message, '(3a)' )&
2271 0 : & 'Option can not be superior to the maximum order ',ch10,&
2272 0 : & 'Action: contact abinit group'
2273 0 : ABI_ERROR(message)
2274 : end if
2275 :
2276 : !Initialisation of variables
2277 44 : need_anharmstr = .TRUE.
2278 44 : if(present(anharmstr)) need_anharmstr = anharmstr
2279 44 : need_spcoupling = .TRUE.
2280 44 : if(present(spcoupling)) need_spcoupling = spcoupling
2281 44 : need_distributed = .FALSE.
2282 44 : if(present(distributed)) need_distributed = distributed
2283 44 : need_verbose = .TRUE.
2284 44 : if(present(verbose)) need_verbose = verbose
2285 44 : need_only_odd_power = .FALSE.
2286 44 : if(present(only_odd_power)) need_only_odd_power = only_odd_power
2287 44 : need_only_even_power = .FALSE.
2288 44 : if(present(only_even_power)) need_only_even_power = only_even_power
2289 44 : need_compute_symmetric = .TRUE.
2290 44 : if(present(compute_symmetric)) need_compute_symmetric = compute_symmetric
2291 44 : need_dispterms = .TRUE.
2292 44 : if(present(dispterms)) need_dispterms = dispterms
2293 :
2294 44 : if(need_only_odd_power.and.need_only_even_power)then
2295 : write(message, '(3a)' )&
2296 0 : & 'need_only_odd_power and need_only_even_power are both true',ch10,&
2297 0 : & 'Action: contact abinit group'
2298 0 : ABI_ERROR(message)
2299 : end if
2300 :
2301 : !Check which atom to fit, if not present do all atoms
2302 44 : if(present(fit_iatom))then
2303 : ! FIXME: the fit_iatom as the input is the index of the atom
2304 : ! but in the fitting subroutine, it is the irreducible atom.
2305 43 : fit_iatom_in = fit_iatom
2306 : else
2307 1 : fit_iatom_in = -1
2308 : endif
2309 :
2310 44 : end subroutine check_and_normalize_input_params
2311 :
2312 44 : subroutine getList()
2313 572 : rprimd = crystal%rprimd
2314 44 : call prepare_for_getList(crystal,sc_size, dist, cell, natom, nsym, nrpt, range_ifc , symbols)
2315 :
2316 44 : if(iam_master)then
2317 28 : if(need_verbose)then
2318 22 : write(message,'(1a)')' Generation of the list of all the possible pairs of atoms within cutoff'
2319 22 : call wrtout(std_out,message,'COLL')
2320 : end if
2321 : call polynomial_coeff_getList(cell,crystal,dist,list_symcoeff,list_symstr,&
2322 : & natom,nstr_sym,ncoeff_sym,nrpt,range_ifc,cutoff,sc_size=sc_size,&
2323 28 : & fit_iatom=fit_iatom_in)
2324 112 : shape_listsymcoeff = shape(list_symcoeff)
2325 112 : shape_listsymstr = shape(list_symstr)
2326 : endif!if iam master
2327 :
2328 : !Broadcast Results of getList
2329 44 : call xmpi_bcast(shape_listsymcoeff, master, comm, ierr)
2330 44 : call xmpi_bcast(shape_listsymstr, master, comm, ierr)
2331 : call xmpi_bcast(nstr_sym, master, comm, ierr)
2332 : call xmpi_bcast(ncoeff_sym, master, comm, ierr)
2333 44 : if(.not. iam_master )then
2334 80 : ABI_MALLOC(list_symcoeff,(shape_listsymcoeff(1),shape_listsymcoeff(2),shape_listsymcoeff(3)))
2335 80 : ABI_MALLOC(list_symstr,(shape_listsymstr(1),shape_listsymstr(2),shape_listsymstr(3)))
2336 : endif
2337 : call xmpi_bcast(list_symcoeff, master, comm, ierr)
2338 : call xmpi_bcast(list_symstr, master, comm, ierr)
2339 44 : call xmpi_barrier(comm)
2340 :
2341 44 : ncoeff_symsym = size(list_symcoeff(1,:,1))
2342 :
2343 : !Compute the total number of coefficient
2344 44 : ncoeff_tot = ncoeff_sym+nstr_sym
2345 :
2346 :
2347 : !if(iam_master)then
2348 : !Check the distanceance bewteen coefficients and store integer:
2349 : ! 0: the mix between these coefficient is not possible
2350 : ! 1: the mix between these coefficient is possible
2351 176 : ABI_MALLOC(compatibleCoeffs,(ncoeff_symsym+nstr_sym,ncoeff_symsym+nstr_sym))
2352 280808 : compatibleCoeffs(:,:) = 1
2353 :
2354 44 : if(need_verbose)then
2355 38 : write(message,'(1a)')' Check the compatible coefficients with respect to the cutoff'
2356 38 : call wrtout(std_out,message,'COLL')
2357 : end if
2358 :
2359 2318 : do icoeff=1,ncoeff_symsym+nstr_sym
2360 280808 : do icoeff2=1,ncoeff_symsym+nstr_sym
2361 : ! Select case:
2362 : ! if both icoeff are displacement => check the distance
2363 : ! if both icoeff are strain => check the flag
2364 : ! Otherwise cycle (we keep the term)
2365 : ! if(icoeff>ncoeff_sym.and.icoeff2<=ncoeff_sym)cycle
2366 : ! if(icoeff<=ncoeff_sym.and.icoeff2>ncoeff_sym)cycle
2367 : !Forbid anharmonic strain terms if not wanted
2368 278490 : if((icoeff>ncoeff_symsym .and. icoeff2>ncoeff_symsym).and.&
2369 : & .not.need_anharmstr) then
2370 1440 : compatibleCoeffs(icoeff,icoeff2) = 0
2371 1440 : compatibleCoeffs(icoeff2,icoeff) = 0
2372 : end if
2373 : !Forbid strain phonon terms if not wanted
2374 278490 : if((icoeff>ncoeff_symsym.or.icoeff2>ncoeff_symsym).and.&
2375 : & .not.need_spcoupling) then
2376 12888 : compatibleCoeffs(icoeff,icoeff2) = 0
2377 12888 : compatibleCoeffs(icoeff2,icoeff) = 0
2378 : end if
2379 :
2380 :
2381 280764 : if(icoeff<=ncoeff_symsym.and.icoeff2<=ncoeff_symsym)then !Check combination of irreducible bodies and their symmetric equivalent
2382 252786 : if(list_symcoeff(2,icoeff,1)/= list_symcoeff(2,icoeff2,1)) then
2383 0 : ABI_BUG("The first components of the pairs in the coefficient are not equivalent.")
2384 : end if
2385 :
2386 : if(abs(dist(1,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff,1),list_symcoeff(4,icoeff,1)) & ! rx(a, b)
2387 : & -dist(1,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff2,1),list_symcoeff(4,icoeff2,1))) & ! rx(a, d )
2388 : & >= (rprimd(1,1) + rprimd(1,2) + rprimd(1,3))*sc_size(1) .or. &
2389 : abs(dist(2,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff,1),list_symcoeff(4,icoeff,1)) & ! ry(a, b)
2390 : & -dist(2,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff2,1),list_symcoeff(4,icoeff2,1))) & ! ry(a, d)
2391 252786 : & >= (rprimd(2,1) + rprimd(2,2) + rprimd(2,3))*sc_size(2) .or. &
2392 : abs(dist(3,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff,1),list_symcoeff(4,icoeff,1)) & ! rz(a, b)
2393 : & -dist(3,list_symcoeff(2,icoeff,1),list_symcoeff(3,icoeff2,1),list_symcoeff(4,icoeff2,1))) & ! rz(a, d)
2394 : & >= (rprimd(3,1) + rprimd(3,2) + rprimd(3,3))*sc_size(3))then
2395 63216 : compatibleCoeffs(icoeff,icoeff2) = 0
2396 63216 : compatibleCoeffs(icoeff2,icoeff) = 0
2397 : endif
2398 : endif
2399 : end do !end icoeff
2400 : end do !icoeff2
2401 :
2402 44 : ABI_SFREE(dist)
2403 : ! Compute all the combination of coefficient up to the given order (get the number)
2404 44 : if(need_verbose)then
2405 38 : write(message,'(1a)')' Compute the number of possible combinations'
2406 38 : call wrtout(std_out,message,'COLL')
2407 : end if
2408 :
2409 88 : end subroutine getList
2410 :
2411 44 : subroutine get_combinations_of_lists()
2412 44 : ABI_MALLOC(list_coeff,(0))
2413 44 : ABI_MALLOC(list_combination,(0,0))
2414 44 : icoeff = 1
2415 44 : icoeff2 = 0
2416 44 : nirred_comb = 0
2417 44 : iirred_comb = 0
2418 : call computeCombinationFromList(cell,compatibleCoeffs,list_symcoeff,list_symstr,&
2419 : & list_coeff,list_combination,icoeff,max_power_strain,natom,ncoeff_sym,&
2420 : & ncoeff_symsym,iirred_comb,nirred_comb,nstr_sym,icoeff,nrpt,nsym,1,power_disps(1),power_disps(2),symbols,comm,&
2421 : & nbody=option,compute=.false.,anharmstr=need_anharmstr,spcoupling=need_spcoupling,&
2422 44 : & only_odd_power=need_only_odd_power,only_even_power=need_only_even_power,disp=need_dispterms)
2423 44 : ABI_SFREE(list_coeff)
2424 44 : ABI_SFREE(list_combination)
2425 : ! Output how much we found
2426 44 : if(need_verbose)then
2427 38 : write(message,"(1a,I10)") " -Number of irreducible pairs within cutoff: ", ncoeff_sym
2428 38 : call wrtout(std_out,message,'COLL')
2429 38 : write(message,"(1a,I10)") " -Number of combinations of irreducible pairs: ", nirred_comb
2430 38 : call wrtout(std_out,message,'COLL')
2431 : !write(message,"(1a,I10)") " -Number of possible symmetric combinations: ", ncombination
2432 : !call wrtout(std_out,message,'COLL')
2433 38 : write(message,'(a,a)') ch10,' Compute the combinations of irreducible pairs'
2434 38 : call wrtout(std_out,message,'COLL')
2435 : end if
2436 44 : ABI_MALLOC(list_coeff,(0))
2437 176 : ABI_MALLOC(list_combination_tmp,(power_disps(2),nirred_comb))
2438 44 : icoeff = 1
2439 44 : icoeff2 = 0
2440 44 : iirred_comb = 0
2441 13689 : list_combination_tmp = 0
2442 : ! Compute all the combination of coefficient up to the given order
2443 : call computeCombinationFromList(cell,compatibleCoeffs,list_symcoeff,list_symstr,&
2444 : & list_coeff,list_combination_tmp,icoeff,max_power_strain,natom,&
2445 : & ncoeff_sym,ncoeff_symsym,iirred_comb,nirred_comb,nstr_sym,ncombination,nrpt,nsym,1,power_disps(1),&
2446 : & power_disps(2),symbols,comm,nbody=option,compute=.true.,&
2447 : & anharmstr=need_anharmstr,spcoupling=need_spcoupling,&
2448 44 : & only_odd_power=need_only_odd_power,only_even_power=need_only_even_power,disp=need_dispterms)
2449 44 : ABI_SFREE(list_coeff)
2450 44 : nirred_comb = size(list_combination_tmp,2)
2451 :
2452 44 : end subroutine get_combinations_of_lists
2453 :
2454 :
2455 44 : subroutine get_symmetric_combinations()
2456 44 : type(IrreducibleCombinations_T) :: irred_combinations
2457 : ! If we want to compute equivalent symmetric combinations go here.
2458 44 : if(need_compute_symmetric)then
2459 38 : if(need_verbose)then
2460 38 : write(message,'(1a)')' Distribute irreducible combinations over CPU'
2461 38 : call wrtout(std_out,message,'COLL')
2462 38 : write(message,'(1a)')' Compute symmetric combinations of combinations of irreducible pairs'
2463 38 : call wrtout(std_out,message,'COLL')
2464 38 : write(message,'(3a)')' ---> Try to match number of CPU to number combinations of irreducible pairs',ch10,&
2465 76 : & ' for max. speedup'
2466 38 : call wrtout(std_out,message,'COLL')
2467 : endif
2468 :
2469 : ! COUNT IRREDUCIBLE COMBINATIONS FOR EACH PROCESSOR
2470 38 : ncombi_alone = mod(nirred_comb,nproc)
2471 38 : my_ncombi_simple = int(aint(real(nirred_comb,sp)/(nproc)))
2472 38 : if(ncombi_alone == 0 .and. nirred_comb >= nproc)then !ncombi > nproc and no remainder
2473 22 : my_ncombi_start = (my_ncombi_simple * my_rank) + 1
2474 22 : my_ncombi_end = my_ncombi_start + my_ncombi_simple - 1
2475 16 : else if(nirred_comb < nproc)then !ncombi smaller than nproc
2476 0 : if(my_rank + 1 <= nirred_comb)then !myrank smaller than ncombi
2477 0 : my_ncombi_start = my_rank + 1
2478 0 : my_ncombi_end = my_ncombi_start
2479 : else
2480 0 : my_ncombi_start = nirred_comb + 1 !myrank bigger than ncombi
2481 0 : my_ncombi_end = nirred_comb + 1
2482 : endif
2483 16 : else if(nirred_comb > nproc .and. ncombi_alone /= 0)then !ncombi > nproc and remainder
2484 16 : if(my_rank >= (nproc-ncombi_alone)) then
2485 8 : my_ncombi_start = (my_ncombi_simple * my_rank) + 1 + (my_rank - nproc + ncombi_alone)
2486 8 : my_ncombi_end = my_ncombi_start + my_ncombi_simple
2487 : else
2488 8 : my_ncombi_start = (my_ncombi_simple * my_rank) + 1
2489 8 : my_ncombi_end = my_ncombi_start + my_ncombi_simple - 1
2490 : endif
2491 : end if
2492 :
2493 38 : if(my_ncombi_end <= nirred_comb)then
2494 38 : my_nirred = my_ncombi_end+1-my_ncombi_start
2495 : else
2496 0 : my_nirred = 0
2497 : endif
2498 : !write(std_out,*) "my_rank", my_rank, "my_ncmobi_start", my_ncombi_start, "my_ncombi_end", my_ncombi_end,'my_nirred',my_nirred
2499 :
2500 : !COPY IRREDUCIBLE COMBINTATIONS TO BE DONE TO EACH PROCESSOR
2501 : !my_nirred = my_ncombi_end - my_ncombi_start + 1
2502 152 : ABI_MALLOC(my_list_combination_tmp,(power_disps(2),my_nirred))
2503 9173 : if(my_nirred /= 0) my_list_combination_tmp(:,:) = list_combination_tmp(:,my_ncombi_start:my_ncombi_end)
2504 :
2505 :
2506 114 : ABI_MALLOC(my_index_irredcomb,(my_nirred))
2507 38 : ABI_SFREE(list_combination_tmp)
2508 :
2509 : !COUNT SYMMETRIC COMBINATIONS TO IRREDUCIBLE COMBINATIONS ON EACH PROCESSOR
2510 :
2511 : !COMPUTE SYMMETRIC COMBINATIONS
2512 :
2513 38 : call irred_combinations%init()
2514 2309 : do i=1,my_nirred
2515 38 : associate(comb => my_list_combination_tmp(:, i))
2516 : !ABI_MALLOC(dummylist,(0))
2517 : ! Get number of strain and displacements for this term
2518 2271 : ndisp = 0
2519 2271 : nstrain = 0
2520 9135 : do ii = 1,power_disps(2)
2521 9135 : if(comb(ii) > 0 .and. comb(ii) <= ncoeff_symsym)then
2522 4010 : ndisp = ndisp + 1
2523 2854 : else if(comb(ii) >= ncoeff_symsym)then
2524 2832 : nstrain = nstrain + 1
2525 : endif
2526 : enddo
2527 2271 : compute_sym = .true.
2528 2271 : iterm = my_index_irredcomb(i)-1
2529 :
2530 : call computeSymmetricCombinations(my_array_combination,list_symcoeff,list_symstr,ndisp,nsym,&
2531 : & comb(:ndisp+nstrain),power_disps(2),&
2532 : & ncoeff_symsym,nstr_sym,nstrain, &
2533 : & compatibleCoeffs,compute_sym,comm, &
2534 : & only_even=need_only_even_power, max_nbody=max_nbody, &
2535 4542 : & irred_combinations=irred_combinations, cell=cell)
2536 : end associate
2537 : enddo
2538 38 : call irred_combinations%free()
2539 :
2540 38 : ABI_SFREE(my_list_combination_tmp)
2541 :
2542 : ! Delete double combinations on each processor
2543 38 : if(need_verbose .and. my_nirred /= 0)then
2544 38 : write(message,'(1a,I4)')' Reduce reducible symmetric combinations on processor: ', my_rank+1
2545 38 : call wrtout(std_out,message,'PERS')
2546 : endif
2547 : !call reduce_zero_combinations(my_list_combination)
2548 38 : call my_array_combination%tostatic(my_list_combination, size1=power_disps(2))
2549 38 : call my_array_combination%finalize()
2550 :
2551 :
2552 : ! Gather the Results into list_combination_tmp
2553 38 : my_ncombi = size(my_list_combination,2)
2554 114 : ABI_MALLOC(irank_ncombi,(nproc))
2555 : call xmpi_allgather(my_ncombi,irank_ncombi,comm,ierr)
2556 38 : if(need_verbose)then
2557 38 : write(message,'(1a)')' Reduction on all processors finished. Gather results.'
2558 38 : call wrtout(std_out,message,'COLL')
2559 : endif
2560 246 : ABI_MALLOC(list_combination_tmp,(power_disps(2),sum(irank_ncombi)))
2561 :
2562 :
2563 114 : ABI_MALLOC(offsets,(nproc))
2564 38 : offsets(1) = 0
2565 132 : do i=1,nproc
2566 236 : offsets(i) = sum(irank_ncombi(:i-1))*power_disps(2)
2567 : enddo
2568 :
2569 51284 : list_combination_tmp = 0
2570 114 : ABI_MALLOC(buffsize,(nproc))
2571 132 : do i = 1,nproc
2572 132 : buffsize(i) = irank_ncombi(i)*power_disps(2)
2573 : enddo
2574 :
2575 :
2576 114 : call xmpi_gatherv(my_list_combination,size(my_list_combination),list_combination_tmp,buffsize,offsets,master,comm,ierr)
2577 :
2578 :
2579 : !Deallocation of variables inside need_symmetric
2580 38 : ABI_SFREE(buffsize)
2581 38 : ABI_SFREE(my_list_combination)
2582 38 : ABI_SFREE(my_index_irredcomb)
2583 38 : ABI_SFREE(irank_ncombi)
2584 76 : ABI_SFREE(offsets)
2585 : endif !compute_symmetric
2586 :
2587 : !Deallocation of arrays outside need_symmetric
2588 44 : ABI_SFREE(compatibleCoeffs)
2589 :
2590 44 : if(iam_master)then
2591 28 : call reduce_zero_combinations(list_combination_tmp)
2592 28 : ncombination = size(list_combination_tmp,2)
2593 : !ABI_MALLOC(index_irred,(1))
2594 : !index_irred = 1
2595 : !============ Strain phonon coupling===================
2596 28 : if(need_spcoupling)then !Check irreducibility of strain-phonon terms
2597 22 : if(need_verbose)then
2598 22 : write(message,'(1a)')' Reduce reducible Strain-Phonon combinations on master'
2599 22 : call wrtout(std_out,message,'COLL')
2600 : endif
2601 22 : call irred_combinations%init()
2602 7278 : do i=1, ncombination
2603 26268 : if(any(list_combination_tmp(:,i) > ncoeff_symsym))then
2604 : irreducible=irred_combinations%add_irr(list_combination_tmp(:,i), &
2605 2990 : & list_symcoeff, list_symstr, ncoeff_symsym, nsym, power_disps(2),cell)
2606 3302 : if(.not. irreducible) list_combination_tmp(:,i) = 0
2607 : endif
2608 : end do
2609 22 : call reduce_zero_combinations(list_combination_tmp)
2610 22 : ncombination = size(list_combination_tmp,2)
2611 22 : call irred_combinations%free()
2612 : endif
2613 :
2614 : end if !iam_master
2615 44 : if(need_verbose)then
2616 38 : write(message,'(1x,I0,1a)') ncombination,' irreducible combinations generated '
2617 38 : call wrtout(std_out,message,'COLL')
2618 38 : write(message,'(1a)') ' Finished generating irreducible combinations'
2619 38 : call wrtout(std_out,message,'COLL')
2620 : endif
2621 :
2622 : !MPI
2623 44 : if(need_verbose .and. nproc > 1)then
2624 24 : write(message,'(a,a)') ch10,' Redistribute the combinations over the CPU'
2625 24 : call wrtout(std_out,message,'COLL')
2626 : end if
2627 :
2628 : call xmpi_bcast(ncombination, master, comm, ierr)
2629 :
2630 44 : ncoeff_alone = mod(ncombination,nproc)
2631 44 : my_ncoeff = int(aint(real(ncombination,sp)/(nproc)))
2632 :
2633 44 : if(my_rank >= (nproc-ncoeff_alone)) then
2634 6 : my_ncoeff = my_ncoeff + 1
2635 : end if
2636 :
2637 : !Set the buffsize for mpi scatterv
2638 132 : ABI_MALLOC(buffsize,(nproc))
2639 88 : ABI_MALLOC(buffdispl,(nproc))
2640 144 : do ii = 1,nproc
2641 100 : buffsize(ii) = int(aint(real(ncombination,sp)/(nproc))*power_disps(2))
2642 144 : if(ii > (nproc-ncoeff_alone)) then
2643 20 : buffsize(ii) = buffsize(ii) + power_disps(2)
2644 : end if
2645 : end do
2646 :
2647 44 : buffdispl(1) = 0
2648 100 : do ii = 2,nproc
2649 100 : buffdispl(ii) = buffdispl(ii-1) + buffsize(ii-1)
2650 : end do
2651 :
2652 176 : ABI_MALLOC(list_combination,(power_disps(2),my_ncoeff))
2653 29688 : list_combination = 0
2654 :
2655 44 : my_size = my_ncoeff*power_disps(2)
2656 : call xmpi_scatterv(list_combination_tmp,buffsize,buffdispl,list_combination,my_size,master,&
2657 : & comm,ierr)
2658 :
2659 44 : ABI_SFREE(buffdispl)
2660 44 : ABI_SFREE(buffsize)
2661 44 : ABI_SFREE(list_combination_tmp)
2662 :
2663 132 : end subroutine get_symmetric_combinations
2664 :
2665 44 : subroutine combinations_to_terms()
2666 44 : logical, allocatable :: reverse(:)
2667 44 : if(need_verbose .and. nproc > 1)then
2668 24 : write(message,'(1a)')' Compute the coefficients'
2669 24 : call wrtout(std_out,message,'COLL')
2670 : end if
2671 7390 : ABI_MALLOC(coeffs_tmp,(my_ncoeff))
2672 44 : nterm = nsym
2673 44 : ndisp_max = power_disps(2)
2674 44 : ncoeff_max = my_ncoeff
2675 7302 : do ii=1,my_ncoeff
2676 370158 : ABI_MALLOC(terms,(nterm))
2677 21774 : ABI_MALLOC(reverse,(ndisp_max))
2678 29644 : reverse=.False.
2679 : call generateTermsFromList(cell,list_combination(:,ii),list_symcoeff,list_symstr,ncoeff_symsym,&
2680 7258 : & ndisp_max,nrpt,nstr_sym,nsym,nterm,terms, reverse=reverse)
2681 :
2682 :
2683 7258 : call polynomial_coeff_init(one,nterm,coeffs_tmp(ii),terms(1:nterm), check=.true.)
2684 : !DMSG(coeffs_tmp(ii)%debug_str)
2685 7258 : ABI_SFREE(reverse)
2686 : ! Free the terms array
2687 355642 : do iterm=1,nterm
2688 355642 : call polynomial_term_free(terms(iterm))
2689 : end do
2690 355686 : ABI_SFREE(terms)
2691 : end do
2692 44 : ABI_SFREE(cell)
2693 44 : ABI_SFREE(list_combination)
2694 44 : ABI_SFREE(list_symcoeff)
2695 44 : ABI_SFREE(list_symstr)
2696 :
2697 : !Final tranfert
2698 : !1- Count the total number of coefficient
2699 44 : ncoeff = 0
2700 7302 : do icoeff=1,ncoeff_max
2701 7302 : if (abs(coeffs_tmp(icoeff)%coefficient) >tol16) then
2702 5063 : ncoeff = ncoeff + 1
2703 : end if
2704 : end do
2705 :
2706 : !Get the total number of coefficients
2707 : !ncoeff_max is the number of total coefficients before the symetries check
2708 : !ncoeff_tot is the number of total coefficients after the symetries check
2709 44 : ncoeff_tot = ncoeff!set the output
2710 : call xmpi_sum(ncoeff_tot,comm,ierr)
2711 : call xmpi_sum(ncoeff_max,comm,ierr)
2712 44 : end subroutine combinations_to_terms
2713 :
2714 :
2715 44 : subroutine distribute_coefficients_over_cpu()
2716 : !Need to redistribute the coefficients over the CPU
2717 : !Get the list with the number of coeff on each CPU
2718 : !In order to be abble to compute the my_coeffindexes array which is for example:
2719 : ! if CPU0 has 200 Coeff and CPU1 has 203 Coeff then
2720 : ! for CPU0:my_coeffindexes=>1-200 and for CPU1:my_coeffindexes=>201-403
2721 44 : if(need_verbose .and. nproc > 1)then
2722 24 : write(message,'(1a)')' Redistribute the coefficients over the CPU'
2723 24 : call wrtout(std_out,message,'COLL')
2724 : end if
2725 :
2726 132 : ABI_MALLOC(buffdispl,(nproc))
2727 144 : buffdispl = 0
2728 44 : buffdispl(my_rank+1) = my_ncoeff
2729 : call xmpi_sum(buffdispl,comm,ierr)
2730 132 : ABI_MALLOC(my_coeffindexes,(my_ncoeff))
2731 88 : ABI_MALLOC(my_coefflist,(my_ncoeff))
2732 7302 : my_coeffindexes = 0
2733 7302 : my_coefflist = 0
2734 7302 : do icoeff=1,my_ncoeff
2735 7258 : my_coefflist(icoeff) = icoeff
2736 7302 : if(my_rank==0) then
2737 5621 : my_coeffindexes(icoeff) = icoeff
2738 : else
2739 4257 : my_coeffindexes(icoeff) = sum(buffdispl(1:my_rank)) + icoeff
2740 : end if
2741 : end do
2742 44 : ABI_SFREE(buffdispl)
2743 :
2744 : !Compute the new number of coefficient per CPU
2745 44 : if(need_distributed) then
2746 38 : ncoeff_alone = mod(ncoeff_tot,nproc)
2747 38 : my_newncoeff = int(aint(real(ncoeff_tot,sp)/(nproc)))
2748 38 : if(my_rank >= (nproc-ncoeff_alone)) then
2749 0 : my_newncoeff = my_newncoeff + 1
2750 : end if
2751 : else
2752 6 : my_newncoeff = ncoeff_tot
2753 : end if
2754 :
2755 44 : ncoeff = my_newncoeff ! Set the output
2756 :
2757 : !2:compute the number of coefficients and the list of the corresponding
2758 : ! coefficients for each CPU.
2759 132 : ABI_MALLOC(my_newcoeffindexes,(my_newncoeff))
2760 44 : if(need_distributed) then
2761 4995 : do icoeff=1,my_newncoeff
2762 4995 : if(my_rank >= (nproc-ncoeff_alone))then
2763 : my_newcoeffindexes(icoeff)=int(aint(real(ncoeff_tot,sp)/(nproc)))*(my_rank)+&
2764 0 : & (my_rank - (nproc-ncoeff_alone)) + icoeff
2765 : else
2766 4957 : my_newcoeffindexes(icoeff)=(my_newncoeff)*(my_rank) + icoeff
2767 : end if
2768 : end do
2769 : else
2770 112 : do icoeff=1,my_newncoeff
2771 112 : my_newcoeffindexes(icoeff) = icoeff
2772 : end do
2773 : end if
2774 :
2775 : !2- Transfer
2776 44 : if(.not.need_distributed)then
2777 6 : if(.not.allocated(coefficients))then
2778 124 : ABI_MALLOC(coefficients,(my_newncoeff))
2779 : end if
2780 : end if
2781 : icoeff = 0! icoeff is the current index in the total list of coefficients
2782 44 : icoeff2 = 0! icoeff2 is the current index in the output coefficients array on each CPU
2783 44 : icoeff3 = 0! icoeff3 is the current index in total new list of coefficients
2784 44 : rank_to_send_save = 0
2785 :
2786 12534 : do icoeff=1,ncoeff_max
2787 : ! Need to send the rank with the chosen coefficient
2788 12490 : rank_to_send = 0
2789 12490 : my_icoeff = 0
2790 2331761 : do ii=1,my_ncoeff
2791 2331761 : if (my_coeffindexes(ii)==icoeff) then
2792 7258 : my_icoeff = ii
2793 7258 : if (abs(coeffs_tmp(my_icoeff)%coefficient) > tol16)then
2794 5063 : rank_to_send = my_rank
2795 : else
2796 2195 : rank_to_send = -1
2797 : ! Free the coefficient
2798 2195 : call polynomial_coeff_free(coeffs_tmp(ii))
2799 : end if
2800 : exit
2801 : end if
2802 : end do
2803 : call xmpi_sum(rank_to_send, comm, ierr)
2804 : ! This coefficient is not compute
2805 12490 : if (rank_to_send == -1) cycle
2806 :
2807 : ! increase icoeff3
2808 8759 : icoeff3 = icoeff3 + 1
2809 :
2810 : ! Find the receiver CPU
2811 8759 : rank_to_receive = 0
2812 2032208 : do ii=1,my_newncoeff
2813 2032208 : if (my_newcoeffindexes(ii)==icoeff3) then
2814 5063 : rank_to_receive = my_rank
2815 : end if
2816 : end do
2817 : call xmpi_sum(rank_to_receive, comm, ierr)
2818 :
2819 8759 : if(need_distributed.and.rank_to_send /= rank_to_send_save) then
2820 : if(my_rank == rank_to_send_save)then
2821 : !call polynomial_coeff_list_free(coeffs_tmp)
2822 : !ABI_SFREE(coeffs_tmp)!Free memory if the current CPU has already distribute
2823 : !all its own coefficients
2824 : end if
2825 56 : rank_to_send_save = rank_to_send
2826 : end if
2827 :
2828 8759 : if(need_distributed.and.my_rank == rank_to_receive)then
2829 4957 : if(.not.allocated(coefficients))then
2830 5071 : ABI_MALLOC(coefficients,(my_newncoeff))
2831 : end if
2832 : end if
2833 :
2834 :
2835 30052 : if (need_distributed)then
2836 8653 : if(my_rank==rank_to_send)then
2837 774525 : if(any(my_newcoeffindexes(:)==icoeff3))then
2838 4869 : icoeff2 = icoeff2 + 1
2839 : ! Get the name of this coefficient
2840 4869 : call polynomial_coeff_getName(name,coeffs_tmp(my_icoeff),symbols,recompute=.TRUE.)
2841 : call polynomial_coeff_init(one,coeffs_tmp(my_icoeff)%nterm,coefficients(icoeff2),&
2842 : & coeffs_tmp(my_icoeff)%terms,name=name, &
2843 4869 : & check=.false.)
2844 : !DMSG(coefficients(icoeff2)%debug_str)
2845 : else
2846 88 : call polynomial_coeff_MPIsend(coeffs_tmp(my_icoeff), icoeff, rank_to_receive, comm)
2847 : end if
2848 : ! Free the coefficient
2849 : !call polynomial_coeff_free(coeffs_tmp(my_icoeff))
2850 : else
2851 479557 : if(any(my_newcoeffindexes(:)==icoeff3))then
2852 88 : icoeff2 = icoeff2 + 1
2853 88 : call polynomial_coeff_MPIrecv(coefficients(icoeff2), icoeff, rank_to_send, comm)
2854 88 : call polynomial_coeff_getName(name,coefficients(icoeff2),symbols,recompute=.TRUE.)
2855 88 : call polynomial_coeff_SetName(name,coefficients(icoeff2))
2856 : !DMSG(coefficients(icoeff2)%debug_str)
2857 : end if
2858 : end if
2859 : else
2860 106 : icoeff2 = icoeff2 + 1
2861 : ! Get the name of this coefficient
2862 106 : if(my_rank==rank_to_send)then
2863 106 : call polynomial_coeff_getName(name,coeffs_tmp(my_icoeff),symbols,recompute=.TRUE.)
2864 : call polynomial_coeff_init(one,coeffs_tmp(my_icoeff)%nterm,coefficients(icoeff2),&
2865 : & coeffs_tmp(my_icoeff)%terms,name=name, &
2866 106 : & check=.false.)
2867 : !DMSG(coefficients(icoeff2)%debug_str)
2868 : ! Free the coefficient
2869 : !call polynomial_coeff_free(coeffs_tmp(my_icoeff))
2870 : end if
2871 106 : call polynomial_coeff_broadcast(coefficients(icoeff2),rank_to_send, comm)
2872 : end if
2873 : end do
2874 :
2875 :
2876 44 : if(need_verbose)then
2877 38 : write(message,'(1x,I0,2a)') ncoeff_tot,' coefficients generated ',ch10
2878 38 : call wrtout(ab_out,message,'COLL')
2879 38 : call wrtout(std_out,message,'COLL')
2880 : end if
2881 :
2882 :
2883 44 : end subroutine distribute_coefficients_over_cpu
2884 :
2885 44 : subroutine free_memory()
2886 : !Final deallocation
2887 44 : ABI_SFREE(symbols)
2888 44 : ABI_SFREE(my_coeffindexes)
2889 44 : ABI_SFREE(my_newcoeffindexes)
2890 44 : ABI_SFREE(my_coefflist)
2891 44 : call polynomial_coeff_list_free(coeffs_tmp)
2892 : !ABI_SFREE(coeffs_tmp)
2893 44 : end subroutine free_memory
2894 :
2895 : end subroutine polynomial_coeff_getNorder
2896 : !!***
2897 :
2898 :
2899 : !!****f* m_polynomial_coeff/computeNorder
2900 : !! NAME
2901 : !! computeNorder
2902 : !!
2903 : !! FUNCTION
2904 : !! Recursive routine to compute the order N of a all the possible coefficient
2905 : !! from the list list_symcoeff and list_symstr.
2906 : !!
2907 : !! INPUTS
2908 : !! cell(3,nrpt) = indexes of the cells into the supercell (-1 -1 -1, 0 0 0 ...)
2909 : !! compatibleCoeffs(ncoeff+nstr,ncoeff+nstr) = array with the list of compatible coefficients 0 or 1
2910 : !! list_symcoeff(6,ncoeff_sym,nsym) = array with the list of the coefficients,
2911 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
2912 : !! the 6th first dimensions are :
2913 : !! 1 = direction of the IFC
2914 : !! 2 = index of the atom number 1 (1=>natom)
2915 : !! 3 = index of the atom number 2 (1=>natom)
2916 : !! 4 = indexes of the cell of the second atom
2917 : !! (the atom number 1 is always in the cell 0 0 0)
2918 : !! 5 = weight of the term (-1 or 1)
2919 : !! 6 = indexes of the symmetric
2920 : !! list_symstr(nstr_sym,nsym) = array with the list of the strain and the symmetrics
2921 : !! index_coeff_in(power_disp-1) = list of previous coefficients computed (start with 0)
2922 : !! icoeff = current indexes of the cofficients (start we 1)
2923 : !! icoeff_tot = current number of coefficients already computed (start we 0)
2924 : !! natom = number of atoms in the unit cell
2925 : !! nstr = number of coefficient for related to the atomic displacment into list_symcoeff
2926 : !! nstr = number of coefficient for related to the strain into list_symstr
2927 : !! ncoeff_out = number of maximum coefficients
2928 : !! nrpt = number of cell
2929 : !! nsym = number of symmetries in the system
2930 : !! power_disp = initial power_disp to be computed (can be < power_disp_min,
2931 : !! this routine will skip the firts power_disp)
2932 : !! power_disp_min = minimal power_disp to be computed
2933 : !! power_disp_max = maximum power_disp to be computed
2934 : !! symbols(natom) = array with the symbols of each atoms (Sr,O,Ti,...)
2935 : !! nbody = optional, number of body for the coefficients, for example:
2936 : !! 0 => all the terms
2937 : !! 1 => only (Sr_x-T_y)^power_disp and (Sr_x-T_y)^power_disp\eta^power_disp ...
2938 : !! compute = logical, optional: TRUE if we store the coefficients
2939 : !! FALSE just to count the number of coefficient
2940 : !! anharmstr = logical, optional : TRUE, the anharmonic strain are computed
2941 : !! FALSE, (default) the anharmonic strain are not computed
2942 : !! distributed = logical, optional : True, the coefficients will be distributed on the CPU
2943 : !!
2944 : !! OUTPUT
2945 : !! icoeff = current indexes of the cofficients (start we 1)
2946 : !! icoeff_tot = current number of coefficients already computed (start we 0)
2947 : !! polynomial_coeff<(type(polynomial_coeff_type)>(ncoeff_out) = array of datatype with
2948 : !! the polynomial_coeff
2949 : !!
2950 : !! SOURCE
2951 :
2952 : recursive subroutine computeNorder(cell,coeffs_out,compatibleCoeffs,list_coeff,list_str,&
2953 : & index_coeff_in,icoeff,icoeff_tot,natom,ncoeff,nstr,ncoeff_out,&
2954 : & nrpt,nsym,power_disp,power_disp_min,power_disp_max,symbols,nbody,&
2955 : & compute,anharmstr,spcoupling,distributed)
2956 :
2957 : !Arguments ---------------------------------------------
2958 : !scalar
2959 : integer,intent(in) :: natom,ncoeff,power_disp,power_disp_min,power_disp_max,ncoeff_out,nsym,nrpt,nstr,icoeff
2960 : integer,intent(inout) :: icoeff_tot
2961 : logical,optional,intent(in) :: compute,anharmstr,spcoupling,distributed
2962 : integer,optional,intent(in) :: nbody
2963 : !arrays
2964 : integer,intent(in) :: cell(3,nrpt),compatibleCoeffs(ncoeff+nstr,ncoeff+nstr)
2965 : integer,intent(in) :: list_coeff(6,ncoeff,nsym),list_str(nstr,nsym,2)
2966 : integer,intent(in) :: index_coeff_in(power_disp-1)
2967 : type(polynomial_coeff_type),intent(inout) :: coeffs_out(ncoeff_out)
2968 : character(len=5),intent(in) :: symbols(natom)
2969 : !Local variables ---------------------------------------
2970 : !scalar
2971 : integer :: ia,ib,ii,icoeff1,icoeff_tmp
2972 : integer :: iterm,nbody_in,ncoeff_max,pa,pb
2973 : integer :: ndisp_max,nterm_max
2974 : real(dp):: coefficient
2975 : logical :: need_compute,compatible,possible,need_anharmstr,need_spcoupling,need_distributed
2976 : !arrays
2977 : integer,allocatable :: index_coeff(:)
2978 : character(len=200):: name
2979 : type(polynomial_term_type),dimension(:),allocatable :: terms
2980 : type(polynomial_coeff_type),allocatable :: coeffs_tmp(:)
2981 : logical, allocatable :: reverse(:)
2982 : ! *************************************************************************
2983 :
2984 : !Set the inputs
2985 : need_compute = .TRUE.
2986 : need_anharmstr = .TRUE.
2987 : need_spcoupling = .TRUE.
2988 : need_distributed = .FALSE.
2989 : nbody_in = 0 !all kind of terms
2990 : if(present(compute)) need_compute = compute
2991 : if(present(nbody)) nbody_in = nbody
2992 : if(present(anharmstr)) need_anharmstr = anharmstr
2993 : if(present(spcoupling)) need_spcoupling = spcoupling
2994 : if(present(distributed)) need_distributed = distributed
2995 : if(power_disp <= power_disp_max)then
2996 :
2997 : ! Initialisation of variables
2998 : nterm_max = nsym
2999 : ncoeff_max = (ncoeff+nstr)
3000 : ndisp_max = power_disp
3001 : icoeff_tmp = 0
3002 : ABI_MALLOC(coeffs_tmp,(ncoeff_max))
3003 : ABI_MALLOC(terms,(nterm_max))
3004 : ABI_MALLOC(index_coeff,(power_disp))
3005 :
3006 : index_coeff(1:power_disp-1) = index_coeff_in(:)
3007 :
3008 : do icoeff1=icoeff,ncoeff+nstr
3009 : ! If the distance between the 2 coefficients is superior than the cut-off,
3010 : ! we cycle
3011 : ! If the power_disp is one check if icoeff1 is compatible with itself
3012 : if(power_disp==1) then
3013 : if(icoeff1 <= ncoeff .and. compatibleCoeffs(icoeff1,icoeff1)==0)then
3014 : cycle
3015 : end if
3016 : end if
3017 : if(compatibleCoeffs(icoeff,icoeff1)==0) cycle
3018 :
3019 : ! Reset the flag compatible and possible
3020 : compatible = .TRUE.
3021 : possible = .TRUE.
3022 :
3023 : index_coeff(power_disp) = icoeff1
3024 : iterm = 0
3025 : coefficient = one
3026 :
3027 : if(power_disp >= power_disp_min) then
3028 : ABI_MALLOC(reverse,(ndisp_max))
3029 : reverse(:) = .False.
3030 : call generateTermsFromList(cell,index_coeff,list_coeff,list_str,ncoeff,&
3031 : & ndisp_max,nrpt,nstr,nsym,iterm,terms, reverse=reverse)
3032 : ABI_SFREE(reverse)
3033 :
3034 : if(iterm > 0)then
3035 : ! Do some checks
3036 : ! -------------
3037 : ! 1-Check if the coefficient is full anharmonic strain and if we need to compute it
3038 : if(terms(1)%ndisp == 0)then
3039 : compatible = (need_anharmstr .or. need_spcoupling)
3040 : possible = need_anharmstr
3041 : end if
3042 : ! 1-Check if the coefficient is strain-coupling and if we need to compute it
3043 : if(terms(1)%nstrain > 0.and.terms(1)%ndisp > 0)then
3044 : possible = need_spcoupling
3045 : compatible = need_spcoupling
3046 : end if
3047 : ! ------------
3048 : ! 2-Check if this terms is compatible with nbody
3049 : if(nbody_in > 0)then
3050 : pa = 1 ; pb = 1
3051 : ia = 0 ; ib = 0
3052 : ! Count the number of terms and the power_disp
3053 : do ii=1,terms(1)%ndisp
3054 : if(terms(1)%nstrain > 0) then
3055 : pb = pb*terms(1)%power_disp(ii)
3056 : ib = ib + 1
3057 : else
3058 : pa = pa*terms(1)%power_disp(ii)
3059 : ia = ia + 1
3060 : end if
3061 : end do
3062 : if(ia <= nbody_in)then
3063 : if(ia==nbody_in.and.abs(mod(pa,2)) < tol16)then
3064 : if(ib==0)then
3065 : compatible = .FALSE.
3066 : possible = .TRUE.
3067 : else if (ib==nbody_in.and.abs(mod(pb,2)) < tol16) then
3068 : compatible = .FALSE.
3069 : possible = .TRUE.
3070 : else
3071 : possible = .FALSE.
3072 : compatible = .FALSE.
3073 : end if
3074 : else
3075 : possible = .FALSE.
3076 : compatible = .FALSE.
3077 : end if
3078 : else
3079 : compatible = .FALSE.
3080 : possible = .FALSE.
3081 : end if
3082 : end if
3083 :
3084 : if(possible)then
3085 : ! increase coefficients and set it
3086 : icoeff_tmp = icoeff_tmp + 1
3087 : icoeff_tot = icoeff_tot + 1
3088 : call polynomial_coeff_init(coefficient,iterm,coeffs_tmp(icoeff_tmp),&
3089 : & terms(1:iterm), check=.true.)
3090 : !DMSG(coeffs_tmp(icoeff_tmp)%debug_str)
3091 : end if
3092 : end if
3093 :
3094 : ! Deallocate the terms
3095 : do iterm=1,nterm_max
3096 : call polynomial_term_free(terms(iterm))
3097 : end do
3098 : end if!end if power_disp < power_disp_min
3099 :
3100 : if(compatible)then
3101 : call computeNorder(cell,coeffs_out,compatibleCoeffs,list_coeff,list_str,index_coeff,&
3102 : & icoeff1,icoeff_tot,natom,ncoeff,nstr,ncoeff_out,nrpt,nsym,power_disp+1,&
3103 : & power_disp_min,power_disp_max,symbols,nbody=nbody_in,compute=need_compute,&
3104 : & anharmstr=need_anharmstr,spcoupling=need_spcoupling)
3105 : end if
3106 : end do
3107 :
3108 : ABI_SFREE(terms)
3109 : ABI_SFREE(index_coeff)
3110 :
3111 : ! Transfer in the final array
3112 : icoeff1 = 0
3113 : do icoeff_tmp=1,ncoeff_max
3114 : if (abs(coeffs_tmp(icoeff_tmp)%coefficient) > tol16)then
3115 : ! Increase icoeff and fill the coeffs_out array
3116 : icoeff_tot = icoeff_tot + 1
3117 : if(need_compute)then
3118 : name = ''
3119 : ! Get the name of this coefficient
3120 : call polynomial_coeff_getName(name,coeffs_tmp(icoeff_tmp),symbols,recompute=.TRUE.)
3121 : call polynomial_coeff_init(one,coeffs_tmp(icoeff_tmp)%nterm,&
3122 : & coeffs_out(icoeff_tot),coeffs_tmp(icoeff_tmp)%terms,&
3123 : & name=name)
3124 : !DMSG(coeffs_out(icoeff_tot)%debug_str)
3125 : end if
3126 : end if
3127 : end do
3128 : ! Deallocation
3129 : do icoeff1=1,ncoeff_max
3130 : call polynomial_coeff_free(coeffs_tmp(icoeff1))
3131 : end do
3132 : ABI_SFREE(coeffs_tmp)
3133 : end if
3134 :
3135 : end subroutine computeNorder
3136 : !!***
3137 :
3138 :
3139 : !!****f* m_polynomial_coeff/computeCombinationFromList
3140 : !! NAME
3141 : !! computeCombinationFromList
3142 : !!
3143 : !! FUNCTION
3144 : !! Recursive routine to compute the order N of a all the possible coefficient
3145 : !! from the list list_symcoeff and list_symstr.
3146 : !!
3147 : !! INPUTS
3148 : !! cell(3,nrpt) = indexes of the cells into the supercell (-1 -1 -1, 0 0 0 ...)
3149 : !! compatibleCoeffs(ncoeff+nstr,ncoeff+nstr) = array with the list of compatible coefficients 0 or 1
3150 : !! list_coeff(6,ncoeff_sym,nsym) = array with the list of the coefficients,
3151 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
3152 : !! the 6th first dimensions are :
3153 : !! 1 = direction of the IFC
3154 : !! 2 = index of the atom number 1 (1=>natom)
3155 : !! 3 = index of the atom number 2 (1=>natom)
3156 : !! 4 = indexes of the cell of the second atom
3157 : !! (the atom number 1 is always in the cell 0 0 0)
3158 : !! 5 = weight of the term (-1 or 1)
3159 : !! 6 = indexes of the symmetric
3160 : !! list_str(nstr_sym,nsym) = array with the list of the strain and the symmetrics
3161 : !! index_coeff_in(power_disp-1) = list of previous coefficients computed (start with 0)
3162 : !! icoeff = current indexes of the combination (start with 1)
3163 : !! max_power_strain = maximum order of the strain of the strain phonon coupling
3164 : !! nmodel_tot = current number of combination already computed (start with 0)
3165 : !! natom = number of atoms in the unit cell
3166 : !! ncoeff = number of coefficient for related to the atomic displacment into list_symcoeff
3167 : !! nstr = number of coefficient for related to the strain into list_symstr
3168 : !! nmodel = number of maximum models
3169 : !! nrpt = number of cell
3170 : !! nsym = number of symmetries in the system
3171 : !! For example, the sum of all the term like (Sr_y-O_y)^odd, are 0 by symetrie in cubic system.
3172 : !! Here, we build a list with: 0 this term is not allowed for odd
3173 : !! 1 this term is allowed for odd
3174 : !! power_disp = initial power_disp to be computed (can be < power_disp_min,
3175 : !! this routine will skip the first power_disp)
3176 : !! power_disp_min = minimal power_disp to be computed
3177 : !! power_disp_max = maximum power_disp to be computed
3178 : !! symbols(natom) = array with the symbols of each atoms (Sr,O,Ti,...)
3179 : !! nbody = optional, number of body for the coefficients, for example:
3180 : !! 0 => all the terms
3181 : !! 1 => only (Sr_x-T_y)^power_disp and (Sr_x-T_y)^power_disp\eta^power_disp ...
3182 : !! compute = logical, optional: TRUE if we store the coefficients
3183 : !! FALSE just to count the number of coefficient
3184 : !! anharmstr = logical, optional : TRUE, the anharmonic strain are computed
3185 : !! FALSE, (default) the anharmonic strain are not computed
3186 : !! distributed = logical, optional : True, the coefficients will be distributed on the CPU
3187 : !! only_odd_power = logical, optional : if TRUE return only odd power
3188 : !! only_even_power= logical, optional : if TRUe return only even power
3189 : !!
3190 : !! OUTPUT
3191 : !! icoeff = current indexes of the cofficients (start we 1)
3192 : !! nmodel_tot = current number of coefficients already computed (start we 0)
3193 : !! list_combination = list of the possible combination of coefficients
3194 : !!
3195 : !! SOURCE
3196 :
3197 18044 : recursive subroutine computeCombinationFromList(cell,compatibleCoeffs,list_coeff,list_str,&
3198 18044 : & index_coeff_in,list_combination,icoeff,max_power_strain,&
3199 : & natom,ncoeff,ncoeff_sym,iirred_comb,nirred_comb,nstr,nmodel,nrpt,nsym,power_disp,power_disp_min,&
3200 18044 : & power_disp_max,symbols,comm,nbody,only_odd_power,only_even_power,&
3201 : & compute,anharmstr,spcoupling,disp)
3202 :
3203 : !Arguments ---------------------------------------------
3204 : !scalar
3205 : integer,intent(in) :: natom,ncoeff,ncoeff_sym,power_disp,power_disp_min,power_disp_max
3206 : integer,intent(in) :: max_power_strain,nmodel,nsym,nrpt,nstr,comm,icoeff
3207 : integer,intent(inout) :: nirred_comb,iirred_comb
3208 : logical,optional,intent(in) :: compute,anharmstr,spcoupling,disp
3209 : integer,optional,intent(in) :: nbody
3210 : logical,optional,intent(in) :: only_odd_power,only_even_power
3211 : !arrays
3212 : integer,intent(in) :: cell(3,nrpt),compatibleCoeffs(ncoeff_sym+nstr,ncoeff_sym+nstr)
3213 : integer,intent(in) :: list_coeff(6,ncoeff_sym,nsym),list_str(nstr,nsym,2)
3214 : integer,intent(in) :: index_coeff_in(power_disp-1)
3215 : integer,intent(out) :: list_combination(power_disp_max,nirred_comb)
3216 : character(len=5),intent(in) :: symbols(natom)
3217 : !Local variables ---------------------------------------
3218 : !scalar
3219 : integer :: icoeff1,icoeff2,nbody_in,nbody_count, ii
3220 : integer :: ndisp_out,nstrain
3221 : logical :: need_compute,compatible,possible,need_anharmstr,need_spcoupling
3222 : logical :: need_only_odd_power,need_only_even_power,compute_sym,need_disp
3223 : !arrays
3224 36088 : integer :: powers(power_disp)
3225 18044 : integer,allocatable :: index_coeff(:)
3226 : ! *************************************************************************
3227 :
3228 : !Set the inputs
3229 18044 : need_compute = .TRUE.
3230 18044 : need_anharmstr = .TRUE.
3231 18044 : need_spcoupling = .TRUE.
3232 18044 : need_disp = .TRUE.
3233 18044 : need_only_odd_power = .FALSE.
3234 18044 : need_only_even_power = .FALSE.
3235 18044 : compute_sym = .FALSE. !Never compute the symmetric combinations here
3236 18044 : nbody_in = 0 !all kind of terms
3237 18044 : if(present(compute)) need_compute = compute
3238 18044 : if(present(nbody)) nbody_in = nbody
3239 18044 : if(present(anharmstr)) need_anharmstr = anharmstr
3240 18044 : if(present(spcoupling)) need_spcoupling = spcoupling
3241 18044 : if(present(disp)) need_disp = disp
3242 18044 : if(present(only_odd_power)) need_only_odd_power = only_odd_power
3243 18044 : if(present(only_even_power)) need_only_even_power = only_even_power
3244 :
3245 :
3246 18044 : if(power_disp <= power_disp_max)then
3247 :
3248 : ! Initialisation of variables
3249 16590 : ABI_MALLOC(index_coeff,(power_disp))
3250 17898 : index_coeff(1:power_disp-1) = index_coeff_in(:)
3251 : ! Loop over ncoeff+nstr
3252 27884 : do icoeff1=icoeff,ncoeff+nstr
3253 :
3254 : ! Reset the flag compatible and possible
3255 22354 : compatible = .TRUE.
3256 22354 : possible = .TRUE.
3257 :
3258 : ! If the power_disp is one, we need to set icoeff to icoeff1
3259 22354 : if(power_disp==1) then
3260 860 : if(icoeff1<=ncoeff .and. compatibleCoeffs(icoeff,icoeff1)==0)then
3261 : ! is_displacement and compatible
3262 22354 : compatible = .FALSE.
3263 : end if
3264 : end if
3265 : ! If the distance between the 2 coefficients is superior than the cut-off, we cycle.
3266 64544 : do icoeff2=1,power_disp-1
3267 : ! write(std_out,*) "icoeff1: ", icoeff1
3268 : ! write(std_out,*) "icoeff2: ", icoeff2, "index_icoeff2: ", index_coeff(icoeff2)
3269 64544 : if(icoeff1 <= ncoeff .and. index_coeff(icoeff2) <=ncoeff)then
3270 4354 : if(compatibleCoeffs(index_coeff(icoeff2),icoeff1)==0)then
3271 42190 : compatible = .FALSE.
3272 : end if
3273 : endif
3274 : end do
3275 :
3276 22354 : if (.not.compatible) cycle !The distance is not compatible
3277 :
3278 : ! Set the index of the new coeff in the list
3279 22354 : index_coeff(power_disp) = icoeff1
3280 : ! Do some checks
3281 : ! -------------
3282 : ! 1-Check if the coefficient is full anharmonic strain and if we need to compute it
3283 49342 : if(all(index_coeff > ncoeff))then
3284 8466 : compatible = (need_anharmstr .or. need_spcoupling)
3285 8466 : possible = need_anharmstr
3286 : end if
3287 : ! 2-Check if the coefficient is strain-coupling and if we need to compute it
3288 93688 : if(any(index_coeff <= ncoeff) .and. any(index_coeff > ncoeff))then
3289 : ! write(std_out,*) "index_coeff", index_coeff,"need_spcoupling",need_spcoupling
3290 10566 : possible = need_spcoupling
3291 10566 : compatible = need_spcoupling
3292 40446 : if(count(index_coeff > ncoeff) > max_power_strain)then
3293 4338 : possible = .false.
3294 4338 : compatible = .false.
3295 : end if
3296 : end if
3297 : ! 3-Check if the coefficient is only disp and if we need to compute it
3298 44346 : if(all(index_coeff <= ncoeff))then
3299 : ! write(std_out,*) "index_coeff", index_coeff,"need_dis",need_disp
3300 3322 : compatible = (need_disp .or. need_spcoupling)
3301 3322 : possible = need_disp
3302 : end if
3303 : ! 4-Count number of Strain and number of displacements for compute symmetric terms
3304 22354 : nstrain = 0
3305 22354 : ndisp_out = 0
3306 86898 : do ii=1,power_disp
3307 86898 : if(index_coeff(ii) > 0 .and. index_coeff(ii) <= ncoeff)then
3308 21992 : ndisp_out = ndisp_out + 1
3309 : else
3310 42552 : nstrain = nstrain +1
3311 42552 : index_coeff(ii) = index_coeff(ii) - ncoeff + ncoeff_sym
3312 : end if
3313 : end do
3314 :
3315 :
3316 22354 : if(power_disp >= power_disp_min) then
3317 : ! count the number of body
3318 17008 : call get_powers(index_coeff, power_disp, powers)
3319 17008 : nbody_count = count(powers /= 0)
3320 24752 : if(any(mod(powers(1:power_disp),2) /=0) .and. need_only_even_power) then
3321 2360 : possible = .false.
3322 : end if
3323 47796 : if(any(mod(powers(1:power_disp),2) ==0) .and. need_only_odd_power)then
3324 0 : possible = .false.
3325 : end if
3326 : !if(nbody_count==1) then
3327 : ! possible = .False.
3328 : !end if
3329 :
3330 : ! Check the nbody flag
3331 17008 : if(nbody_in /= 0)then
3332 0 : if(power_disp-count(powers==0) > nbody_in) then
3333 : possible = .false.
3334 : compatible = .false.
3335 : end if
3336 : end if
3337 :
3338 17008 : if(possible) then
3339 : ! increase coefficients and set it
3340 : ! nmodel_tot = nmodel_tot + 1
3341 : ! if(need_compute)then
3342 : ! list_combination(1:power_disp,nmodel_tot) = index_coeff
3343 : ! end if
3344 : !nmodel_tot_test = 0
3345 : ! !Start from second symmetry in Symmetric Combinations
3346 : ! isym_in_test = 2
3347 : ! idisp_in_test = power_disp
3348 : ! ndisp_test = power_disp
3349 : ! index_coeff_tmp = index_coeff
3350 : !Count anharmonic strain terms
3351 6738 : if(ndisp_out == 0 .and. nstrain > 0)then
3352 448 : nirred_comb = nirred_comb +1
3353 448 : iirred_comb = iirred_comb +1
3354 448 : if(need_compute)then
3355 1064 : list_combination(1:power_disp,iirred_comb) = index_coeff
3356 : endif
3357 : else !Else counst symmetric terms of atomic displacement (pure disp or disp/strain)
3358 : !Store index for each combination of irreducible terms to later parallely compute symmetric combinations
3359 6290 : nirred_comb = nirred_comb +1
3360 6290 : iirred_comb = iirred_comb +1
3361 6290 : if(need_compute)then
3362 12581 : list_combination(:,iirred_comb) = 0
3363 12559 : list_combination(:ndisp_out+nstrain,iirred_comb) = index_coeff
3364 : endif
3365 : end if !ndisp_out == 0 .and.n nstrain >0
3366 : end if!possible
3367 : end if!end if power_disp < power_disp_min
3368 :
3369 : !Change back to irreducible terms ncoeff_limit
3370 86898 : do ii=1,power_disp
3371 86898 : if(index_coeff(ii) > ncoeff_sym)then
3372 42552 : index_coeff(ii) = index_coeff(ii) + ncoeff - ncoeff_sym
3373 : end if
3374 : end do
3375 :
3376 : ! If the model is still compatbile with the input flags, we continue.
3377 27884 : if(compatible)then
3378 : call computeCombinationFromList(cell,compatibleCoeffs,list_coeff,list_str,&
3379 : & index_coeff,list_combination,icoeff1,max_power_strain,&
3380 : & natom,ncoeff,ncoeff_sym,iirred_comb,nirred_comb,nstr,nmodel,nrpt,nsym,power_disp+1,&
3381 : & power_disp_min,power_disp_max,symbols,comm,nbody=nbody_in,&
3382 : & compute=need_compute,anharmstr=need_anharmstr,&
3383 : & spcoupling=need_spcoupling,only_odd_power=need_only_odd_power,&
3384 17956 : & only_even_power=need_only_even_power,disp=need_disp)
3385 : end if
3386 : end do
3387 5530 : ABI_SFREE(index_coeff)
3388 : end if
3389 :
3390 18044 : end subroutine computeCombinationFromList
3391 : !!***
3392 :
3393 1404 : subroutine symlist_init(self, nsym, power)
3394 : class(symlist_t), intent(inout) :: self
3395 : integer, intent(in) :: nsym, power
3396 1404 : if(power>7) then
3397 0 : ABI_ERROR("The nbody or power of terms being generate is too large.")
3398 : end if
3399 1404 : if (power>0) then
3400 1256 : self%nsym = nsym
3401 1256 : self%power = power
3402 1256 : self%max=self%nsym**self%power
3403 1256 : self%counter=0
3404 3768 : ABI_MALLOC(self%list, (self%power))
3405 148 : else if (power==0) then
3406 148 : self%max= 1
3407 148 : self%nsym = nsym
3408 148 : self%power = power
3409 148 : self%counter= 0
3410 444 : ABI_MALLOC(self%list, (self%power))
3411 : else
3412 0 : ABI_BUG("The power of the combination should be at least 1")
3413 : end if
3414 1404 : end subroutine symlist_init
3415 :
3416 58274260 : subroutine symlist_next(self)
3417 : class(symlist_t), intent(inout) :: self
3418 : integer(dp) :: j, res
3419 : integer(dp) :: d
3420 252668692 : self%list(:) = 0
3421 58274260 : self%counter = self%counter +1
3422 58274260 : if(self%counter>self%max) then
3423 0 : ABI_BUG("The iteration exceeded the number limit in symlist_next().")
3424 : end if
3425 58274260 : if (self%power>0) then
3426 58274112 : self%list(1) = 1
3427 58274112 : d=self%counter-1
3428 252668544 : do j=1, self%power
3429 194394432 : res=mod(d, self%nsym)
3430 194394432 : d=d/self%nsym
3431 252668544 : self%list(self%power-j+1) = res+1
3432 : end do
3433 : end if
3434 58274260 : end subroutine symlist_next
3435 :
3436 1404 : subroutine symlist_free(self)
3437 : class(symlist_t) :: self
3438 1404 : self%max=0
3439 1404 : self%nsym = 0
3440 1404 : self%power = 0
3441 1404 : self%counter=0
3442 1404 : ABI_SFREE(self%list)
3443 1404 : end subroutine symlist_free
3444 :
3445 :
3446 2271 : subroutine computeSymmetricCombinations(array_combination, &
3447 2271 : & list_symcoeff, list_symstr, ndisp, nsym, index_coeff_in, &
3448 : & ndisp_max, ncoeff, nsym_str, nstrain, &
3449 2271 : & compatibleCoeffs, compute, comm, only_even, max_nbody , irred_combinations , cell)
3450 :
3451 : integer,intent(in) :: ndisp,nsym,ndisp_max, ncoeff,nstrain,nsym_str
3452 : integer,intent(in) :: comm
3453 : logical,intent(in) :: compute
3454 : logical,optional,intent(in) :: only_even
3455 : !scalar
3456 : !arrays
3457 : !integer,intent(inout) ::
3458 : type(int2d_array_type), intent(inout) :: array_combination ! list_combination(ndisp_max, nirred*nsym**(ndisp-1))
3459 : integer,intent(in) :: list_symcoeff(6,ncoeff,nsym),index_coeff_in(ndisp+nstrain)
3460 : integer,intent(in) :: list_symstr(6,nsym,2),compatibleCoeffs(ncoeff+nsym_str,ncoeff+nsym_str)
3461 : integer, intent(in) :: max_nbody(:), cell(:, :)
3462 : type(IrreducibleCombinations_T), intent(inout) :: irred_combinations
3463 2271 : type(symlist_t), target :: symlist
3464 : !Local variables-------------------------------
3465 :
3466 : integer :: idisp,idisp2
3467 : logical :: irreducible, need_only_even,possible
3468 :
3469 : !arrays
3470 5946 : integer :: index_coeff_tmp(ndisp),powers(ndisp),symcoeff_found(nsym)
3471 4542 : integer :: comb_to_test(ndisp_max)
3472 : !integer,allocatable :: index_isym(:)
3473 : !integer,allocatable :: symlist(:, :)
3474 : integer(dp) :: isymlist
3475 : !integer, pointer :: symlist_i(:)
3476 : integer :: nbody, totpower, nbody_strain, totpower_strain, nbody_disp, totpower_disp
3477 2271 : type(polyform_t) :: polyform
3478 2271 : integer :: max_nbody_copy(size(max_nbody))
3479 : !Source
3480 :
3481 : ABI_UNUSED(compute)
3482 : ABI_UNUSED(comm)
3483 :
3484 4542 : call irred_combinations%reset_array()
3485 2271 : need_only_even = .FALSE.
3486 2271 : if(present(only_even))need_only_even=only_even
3487 111279 : symcoeff_found = 0
3488 :
3489 2271 : irreducible = .TRUE.
3490 :
3491 2271 : call get_totpower_and_nbody(index_coeff_in(ndisp+1:ndisp+nstrain), nstrain, nbody_strain, totpower_strain)
3492 2271 : call get_totpower_and_nbody(index_coeff_in(1:ndisp), ndisp, nbody_disp, totpower_disp)
3493 2271 : totpower=totpower_disp+totpower_strain
3494 2271 : nbody=nbody_disp+nbody_strain
3495 :
3496 2271 : if(nbody_disp==1) then
3497 1120 : if(.not. is_right_order(index_coeff_in(1))) return
3498 : end if
3499 :
3500 33726 : max_nbody_copy(:)=max_nbody(:)
3501 1606 : if(max_nbody(totpower)==-1) then
3502 0 : max_nbody_copy(totpower)=1
3503 1606 : else if(max_nbody(totpower)>=0) then
3504 1606 : max_nbody_copy(totpower)=max_nbody(totpower)
3505 : else
3506 0 : ABI_ERROR("max_nbody should be -1, 0, or positive.")
3507 : end if
3508 :
3509 : ! skip if max_nbody=0,
3510 : ! and skip if nbody>max_nbody
3511 1606 : if(max_nbody_copy(totpower)==0 .or. nbody> max_nbody_copy(totpower)) then
3512 : return
3513 : end if
3514 :
3515 :
3516 : block
3517 : logical:: allsym
3518 2808 : integer :: ibody, ind(nbody_disp)
3519 : ! allsym: allow all combination of symmetry adapted terms.
3520 1404 : allsym= ( max_nbody_copy(totpower)>=totpower)
3521 3621 : ind(:)=0
3522 :
3523 1404 : if(allsym) then
3524 1282 : call symlist%init(nsym, ndisp)
3525 : else
3526 122 : call polyform%from_expansion(index_coeff_in(1:ndisp), ndisp)
3527 122 : call symlist%init(nsym, nbody_disp)
3528 : end if
3529 58275664 : do isymlist=1, symlist%max
3530 : ! apply symmetry to the term, and check irreducibility
3531 58274260 : call symlist%next()
3532 :
3533 58274260 : if(allsym) then
3534 252428656 : do idisp=1,ndisp
3535 252428656 : index_coeff_tmp(idisp) = list_symcoeff(6,index_coeff_in(idisp), symlist%list(idisp))
3536 : end do !idisp=1,ndisp
3537 : else
3538 240036 : do ibody=1, nbody_disp
3539 240036 : ind(ibody)= list_symcoeff(6,polyform%ind(ibody), symlist%list(ibody))
3540 : end do
3541 80868 : call expand_poly(ind, polyform%order, nbody_disp, index_coeff_tmp(:ndisp) )
3542 : end if
3543 :
3544 :
3545 58274260 : call get_powers(index_coeff_tmp, ndisp, powers)
3546 58274260 : if(.not. allsym) then
3547 : ! only treat the terms with nbody< nbody_max
3548 319908 : nbody=count(powers/=0)+nbody_strain
3549 319908 : totpower=sum(powers) + totpower_strain
3550 80868 : if(totpower==0) cycle
3551 45622 : if(nbody> max_nbody_copy(totpower)) cycle
3552 : end if
3553 110573158 : if(any(mod(powers(1:ndisp),2) /=0) .and. need_only_even) then
3554 0 : index_coeff_tmp(:) = 0
3555 : end if
3556 :
3557 :
3558 : !Check if symmetric combination is allowed
3559 178858900 : if(.not. any(index_coeff_tmp == 0))then ! Check if term is allowed by distance
3560 109592554 : do idisp=1,ndisp-1
3561 231469162 : do idisp2=idisp+1,ndisp
3562 231469162 : if(compatibleCoeffs(index_coeff_tmp(idisp),index_coeff_tmp(idisp2)) == 0) then
3563 0 : index_coeff_tmp = 0
3564 : exit
3565 : end if
3566 : enddo
3567 109592554 : if(all(index_coeff_tmp == 0))exit
3568 : enddo
3569 : endif
3570 :
3571 :
3572 178858900 : if(any(index_coeff_tmp == 0))then ! If symmetry doesn't point to another term or isn't allowed due to distance write zeros to filter after
3573 : possible = .FALSE.
3574 : else
3575 : possible = .TRUE.
3576 : endif
3577 1404 : if(possible)then
3578 : !loop over displacements in term
3579 142133064 : comb_to_test(:) = 0
3580 29637330 : if(.not. (all(index_coeff_tmp == 0)))then ! If symmetry doesn't point to another term or isn't allowed due to distance write zeros to filter after
3581 139229588 : comb_to_test(:ndisp) = index_coeff_tmp
3582 : end if! (any(index_coeff_tmp ==0))
3583 29637330 : if(nstrain /= 0)then !If SP coupling copy strain index
3584 5080504 : comb_to_test(ndisp+1:ndisp+nstrain) = index_coeff_in(ndisp+1:ndisp+nstrain)
3585 : end if
3586 29637330 : if(.not. (all(index_coeff_tmp == 0) .and. nstrain==0)) then
3587 29637330 : irreducible=irred_combinations%add_irr(comb_to_test, list_symcoeff, list_symstr, ncoeff, nsym, ndisp_max, cell)
3588 : endif
3589 : end if ! need compute
3590 : end do
3591 1404 : if(.not. allsym) then
3592 122 : call polyform%free()
3593 : endif
3594 : end block
3595 :
3596 1404 : call array_combination%concate(irred_combinations%array)
3597 1404 : call symlist%free()
3598 :
3599 : contains
3600 1120 : function is_right_order(index) result(right)
3601 : integer, intent(in) :: index
3602 : logical :: right
3603 : integer :: ia, ib, ico
3604 1120 : ico=list_symcoeff(6, index, 1)
3605 1120 : ia=list_symcoeff(1, ico, 1)
3606 1120 : ib=list_symcoeff(2, ico, 1)
3607 1120 : right=ia>=ib
3608 1120 : end function is_right_order
3609 : end subroutine computeSymmetricCombinations
3610 :
3611 : !!****f* m_polynomial_coeff/getCoeffFromList
3612 : !!
3613 : !! NAME
3614 : !! getCoeffFromList
3615 : !!
3616 : !! FUNCTION
3617 : !! get the index of a coefficient into the list_coeff
3618 : !!
3619 : !! INPUTS
3620 : !! list_symcoeff(6,ncoeff_sym,nsym) = array with the list of the coefficients,
3621 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
3622 : !! the 6th first dimensions are :
3623 : !! 1 = direction of the IFC
3624 : !! 2 = index of the atom number 1 (1=>natom)
3625 : !! 3 = index of the atom number 2 (1=>natom)
3626 : !! 4 = indexes of the cell of the second atom
3627 : !! (the atom number 1 is always in the cell 0 0 0)
3628 : !! 5 = weight of the term (-1 or 1)
3629 : !! 6 = indexes of the symmetric
3630 : !! ia = index of the atom 1
3631 : !! ib = index of the atom 1
3632 : !! irpt = indexes of the cell of the second atom
3633 : !! mu = direction of the IFC
3634 : !! ncoeff = number of total coefficients in the list
3635 : !!
3636 : !! OUTPUT
3637 : !! coeff = index of the coefficient
3638 : !!
3639 : !! SOURCE
3640 :
3641 4295040 : function getCoeffFromList(list_coeff,ia,ib,irpt,mu,ncoeff) result(coeff)
3642 :
3643 : !Arguments ------------------------------------
3644 : !scalar
3645 : integer,intent(in) :: ia,ib,irpt,mu,ncoeff
3646 : integer :: coeff
3647 : !arrays
3648 : integer,intent(in) :: list_coeff(6,ncoeff)
3649 : !Local variables-------------------------------
3650 : !scalar
3651 : integer :: icoeff
3652 : !arrays
3653 :
3654 : ! *************************************************************************
3655 4295040 : coeff = 0
3656 3140190700 : do icoeff = 1,ncoeff
3657 : if(mu==list_coeff(1,icoeff).and.&
3658 : & ia==list_coeff(2,icoeff).and.&
3659 3136923190 : & ib==list_coeff(3,icoeff).and.&
3660 3267510 : & irpt==list_coeff(4,icoeff))then!.and.&
3661 : !& abs(weight-list_coeff(5,icoeff)) < tol16) then
3662 : coeff = icoeff
3663 : exit
3664 : end if
3665 : end do
3666 :
3667 4295040 : end function getCoeffFromList
3668 : !!***
3669 :
3670 :
3671 : !!****f* m_polynomial_coeff/generateTermsFromList
3672 : !!
3673 : !! NAME
3674 : !! generateTermsFromList
3675 : !!
3676 : !! FUNCTION
3677 : !! Compute for a given list of index the correspondig set of terms
3678 : !!
3679 : !! INPUTS
3680 : !! cell(3,nrpt) = indexes of the cells into the supercell (-1 -1 -1, 0 0 0 ...)
3681 : !! index_coeff_in(ndisp) = list of coefficients to be computed
3682 : !! list_symcoeff(6,ncoeff,nsym) = array with the list of the coefficients,
3683 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
3684 : !! the 6th first dimensions are :
3685 : !! 1 = direction of the IFC
3686 : !! 2 = index of the atom number 1 (1=>natom)
3687 : !! 3 = index of the atom number 2 (1=>natom)
3688 : !! 4 = indexes of the cell of the second atom
3689 : !! (the atom number 1 is always in the cell 0 0 0)
3690 : !! 5 = weight of the term (-1 or 1)
3691 : !! 6 = indexes of the symmetry
3692 : !! list_symstr(nstr,nsym) = array with the list of the strain and the symmetrics
3693 : !! ncoeff = number of maximum coefficients in the list_symcoeff
3694 : !! ndisp = number of maximum diplacement (phonon + strain)
3695 : !! nrpt = number of cell
3696 : !! nsym = number of symmetries in the system
3697 : !!
3698 : !! OUTPUT
3699 : !! terms<(type(polynomial_term_type)>(nterm) = list of terms
3700 : !! nterm = number of ouput terms
3701 : !!
3702 : !! SOURCE
3703 :
3704 704608 : subroutine generateTermsFromList(cell,index_coeff,list_coeff,list_str,ncoeff,ndisp_max,&
3705 7264 : & nrpt,nstr,nsym,nterm,terms, reverse)
3706 :
3707 : !Arguments ------------------------------------
3708 : !scalar
3709 : integer,intent(in) :: ndisp_max,ncoeff,nrpt,nstr,nsym
3710 : integer,intent(out):: nterm
3711 : !arrays
3712 : integer,intent(in) :: index_coeff(ndisp_max)
3713 : integer,intent(in) :: cell(3,nrpt),list_coeff(6,ncoeff,nsym)
3714 : integer,intent(in) :: list_str(nstr,nsym,2)
3715 : logical, intent(in) :: reverse(ndisp_max)
3716 : type(polynomial_term_type),intent(out) :: terms(nsym)
3717 : !Local variables-------------------------------
3718 : !scalar
3719 : integer :: ia,ib,icoeff_str,idisp,irpt
3720 : integer :: isym,ndisp,nstrain,mu
3721 : real(dp):: weight
3722 : !arrays
3723 14528 : integer :: atindx(2,ndisp_max),cells(3,2,ndisp_max),dir_int(ndisp_max),strain(ndisp_max)
3724 7264 : integer :: power_disps(ndisp_max),power_strain(ndisp_max)
3725 :
3726 : ! *************************************************************************
3727 7264 : nterm = 0
3728 : !Loop over symetries
3729 355936 : do isym=1,nsym
3730 : !Treat this coeff
3731 348672 : weight = 1
3732 348672 : ndisp = 0
3733 348672 : nstrain = 0
3734 1424928 : do idisp=1,ndisp_max
3735 : ! Get index of this displacement term
3736 : ! Check if the index is not zero
3737 1076256 : if(index_coeff(idisp)==0) cycle
3738 1421280 : if(index_coeff(idisp)<=ncoeff)then
3739 904800 : ndisp = ndisp + 1
3740 904800 : mu = list_coeff(1,index_coeff(idisp),isym)
3741 904800 : if( reverse(idisp)) then
3742 0 : ia = list_coeff(3,index_coeff(idisp),isym)
3743 0 : ib = list_coeff(2,index_coeff(idisp),isym)
3744 0 : irpt = list_coeff(4,index_coeff(idisp),isym)
3745 0 : irpt = find_opposite_irpt(cell, irpt)
3746 0 : weight = -weight*list_coeff(5,index_coeff(idisp),isym)
3747 : else
3748 904800 : ia = list_coeff(2,index_coeff(idisp),isym)
3749 904800 : ib = list_coeff(3,index_coeff(idisp),isym)
3750 904800 : irpt = list_coeff(4,index_coeff(idisp),isym)
3751 904800 : weight = weight*list_coeff(5,index_coeff(idisp),isym)
3752 : end if
3753 : ! Fill First term arrays
3754 904800 : atindx(1,idisp) = ia; atindx(2,idisp) = ib;
3755 904800 : dir_int(idisp) = mu
3756 904800 : power_disps(idisp) = 1
3757 3619200 : cells(:,1,idisp) = (/0,0,0/)
3758 3619200 : cells(:,2,idisp) = cell(:,irpt)
3759 : else
3760 167808 : nstrain = nstrain + 1
3761 167808 : icoeff_str = index_coeff(idisp)-ncoeff
3762 167808 : strain(nstrain) = list_str(icoeff_str,isym,1)
3763 167808 : power_strain(nstrain) = 1
3764 167808 : weight = weight*list_str(icoeff_str,isym,2)
3765 : end if
3766 : end do
3767 348672 : nterm = nterm + 1
3768 :
3769 : call polynomial_term_init(atindx,cells,dir_int,ndisp,nstrain,terms(nterm),power_disps,&
3770 355936 : & power_strain,strain,weight,check=.true., index_coeff=index_coeff)
3771 : end do!end do sym
3772 7264 : end subroutine generateTermsFromList
3773 : !!***
3774 :
3775 :
3776 : !!****f* m_polynomial_coeff/polynomial_coeff_getOrder1
3777 : !!
3778 : !! NAME
3779 : !! polynomial_coeff_getOrder1
3780 : !!
3781 : !! FUNCTION
3782 : !! Compute the first order polynomial coefficients from the list
3783 : !!
3784 : !! INPUTS
3785 : !! cell(3,nrpt) = indexes of the cells into the supercell (-1 -1 -1, 0 0 0 ...)
3786 : !! cutoff_in = cut-off for the inter atomic forces constants
3787 : !! list_symcoeff(6,ncoeff_sym,nsym) = array with the list of the coefficients,
3788 : !! for each coefficients (ncoeff_sym), we store the symmetrics(nsym)
3789 : !! the 6th first dimensions are :
3790 : !! 1 = direction of the IFC
3791 : !! 2 = index of the atom number 1 (1=>natom)
3792 : !! 3 = index of the atom number 2 (1=>natom)
3793 : !! 4 = indexes of the cell of the second atom
3794 : !! (the atom number 1 is always in the cell 0 0 0)
3795 : !! 5 = weight of the term (-1 or 1)
3796 : !! 6 = indexes of the symmetric
3797 : !! natom = number of atoms in the unit cell
3798 : !! nrpt = number of cell
3799 : !! nsym = number of symmetries in the system
3800 : !! symbols(natom) = array with the symbols of each atoms (Sr,O,Ti,...)
3801 : !! comm = MPI communicator
3802 : !!
3803 : !! OUTPUT
3804 : !! polynomial_coeff<(type(polynomial_coeff_type)>(ncoeff_out) = array of datatype with
3805 : !! the polynomial_coeff
3806 : !! ncoeff_out = number of coefficients
3807 : !!
3808 : !! SOURCE
3809 :
3810 0 : subroutine polynomial_coeff_getOrder1(cell,coeffs_out,list_symcoeff,&
3811 : & natom,ncoeff_out,ncoeff,nrpt,nsym,&
3812 0 : & symbols)
3813 :
3814 : !Arguments ------------------------------------
3815 : !scalars
3816 : integer,intent(in) :: natom,ncoeff,nsym,nrpt
3817 : integer,intent(out) :: ncoeff_out
3818 : !arrays
3819 : integer,intent(in) :: cell(3,nrpt)
3820 : integer,intent(in) :: list_symcoeff(6,ncoeff,nsym)
3821 : character(len=5),intent(in) :: symbols(natom)
3822 : type(polynomial_coeff_type),allocatable,intent(inout) :: coeffs_out(:)
3823 : !Local variables-------------------------------
3824 : !scalar
3825 : integer :: ia,ib,icoeff,icoeff_tmp,irpt,irpt_ref
3826 : integer :: isym,iterm,mu,ncoeff_max,ndisp,nstrain,nterm_max
3827 : real(dp):: coefficient,weight
3828 : !arrays
3829 0 : integer,allocatable :: atindx(:,:),cells(:,:,:),dir_int(:)
3830 0 : integer,allocatable :: power_disps(:),power_strain(:),strain(:)
3831 : character(len=1) :: mutodir(9) = (/"x","y","z","1","2","3","4","5","6"/)
3832 : character(len=200):: name
3833 : character(len=500) :: message
3834 0 : type(polynomial_term_type),dimension(:),allocatable :: terms
3835 0 : type(polynomial_coeff_type),allocatable :: coeffs_tmp(:)
3836 : !TEST_AM
3837 : character(len=fnlen) :: filename
3838 : !TEST_AM
3839 : ! *************************************************************************
3840 :
3841 : !Initialisation of variables
3842 0 : nterm_max = nsym
3843 0 : ncoeff_max = ncoeff
3844 0 : ndisp = 1
3845 0 : nstrain = 0
3846 0 : ABI_MALLOC(coeffs_tmp,(ncoeff_max))
3847 0 : ABI_MALLOC(terms,(nterm_max))
3848 :
3849 :
3850 0 : icoeff_tmp = 0
3851 0 : ABI_MALLOC(atindx,(2,ndisp))
3852 0 : ABI_MALLOC(cells,(3,2,ndisp))
3853 0 : ABI_MALLOC(dir_int,(ndisp))
3854 0 : ABI_MALLOC(power_disps,(ndisp))
3855 0 : ABI_MALLOC(power_strain,(nstrain))
3856 0 : ABI_MALLOC(strain,(nstrain))
3857 :
3858 : !Found the ref cell
3859 0 : irpt_ref = 1
3860 0 : do irpt=1,nrpt
3861 : if(all(cell(:,irpt)==0))then
3862 0 : irpt_ref = irpt
3863 : exit
3864 : end if
3865 : end do
3866 :
3867 0 : write(message,'(3a)') " Irreductible coefficient and associated atom 1, atom 2 and direction:",ch10,&
3868 0 : & " for the 1st order"
3869 0 : call wrtout(std_out,message,'COLL')
3870 :
3871 0 : do icoeff=1,ncoeff
3872 : ! Reset counter
3873 0 : iterm = 0
3874 0 : coefficient = one
3875 0 : do isym=1,nsym
3876 : ndisp = 1
3877 : nstrain = 0
3878 0 : mu = list_symcoeff(1,icoeff,isym)
3879 0 : ia = list_symcoeff(2,icoeff,isym)
3880 0 : ib = list_symcoeff(3,icoeff,isym)
3881 0 : irpt = list_symcoeff(4,icoeff,isym)
3882 0 : weight = list_symcoeff(5,icoeff,isym)
3883 : ! Fill First term arrays
3884 0 : atindx(1,1) = ia; atindx(2,1) = ib;
3885 0 : dir_int(1) = mu
3886 0 : power_disps(1) = 1
3887 0 : cells(:,1,1) = (/0,0,0/)
3888 0 : cells(:,2,1) = cell(:,irpt)
3889 0 : iterm = iterm + 1
3890 : call polynomial_term_init(atindx,cells,dir_int,ndisp,nstrain,terms(iterm),&
3891 0 : & power_disps,power_strain,strain,weight,check=.true.)
3892 : end do!end do sym
3893 :
3894 0 : if(iterm > 0)then
3895 : ! increase coefficients and set it
3896 0 : icoeff_tmp = icoeff_tmp + 1
3897 : call polynomial_coeff_init(coefficient,iterm,coeffs_tmp(icoeff_tmp), &
3898 0 : & terms(1:iterm),check=.true.)
3899 : !DMSG(coeffs_tmp(icoeff_tmp)%debug_str)
3900 : end if
3901 :
3902 : ! Deallocate the terms
3903 0 : do iterm=1,nterm_max
3904 0 : call polynomial_term_free(terms(iterm))
3905 : end do
3906 : end do!end do coeff_sym
3907 :
3908 0 : ABI_SFREE(terms)
3909 0 : ABI_SFREE(atindx)
3910 0 : ABI_SFREE(cells)
3911 0 : ABI_SFREE(dir_int)
3912 0 : ABI_SFREE(power_disps)
3913 0 : ABI_SFREE(power_strain)
3914 0 : ABI_SFREE(strain)
3915 :
3916 : !Count the number of terms
3917 0 : ncoeff_out = 0
3918 0 : do icoeff_tmp=1,ncoeff_max
3919 0 : if (abs(coeffs_tmp(icoeff_tmp)%coefficient) > tol16)then
3920 0 : ncoeff_out = ncoeff_out + 1
3921 : end if
3922 : end do
3923 :
3924 : !Transfer in the final array
3925 0 : ABI_MALLOC(coeffs_out,(ncoeff_out))
3926 0 : icoeff = 0
3927 0 : do icoeff_tmp=1,ncoeff_max
3928 0 : if (abs(coeffs_tmp(icoeff_tmp)%coefficient) > tol16)then
3929 : ! Get the name of this coefficient
3930 0 : call polynomial_coeff_getName(name,coeffs_tmp(icoeff_tmp),symbols,recompute=.TRUE.)
3931 : ! Increase icoeff and fill the coeffs_out array
3932 0 : icoeff = icoeff + 1
3933 : call polynomial_coeff_init(one,coeffs_tmp(icoeff_tmp)%nterm,&
3934 : & coeffs_out(icoeff),coeffs_tmp(icoeff_tmp)%terms,&
3935 0 : & name=name)
3936 : !DMSG(coeffs_out(icoeff)%debug_str)
3937 :
3938 0 : write(message,'(2a)')' ',trim(name)
3939 0 : call wrtout(std_out,message,'COLL')
3940 :
3941 0 : do iterm = 1,coeffs_tmp(icoeff_tmp)%nterm
3942 0 : write(message,'(a,I0,a,I0,2a)') ' Atom ',coeffs_tmp(icoeff_tmp)%terms(iterm)%atindx(1,1),&
3943 0 : & ' and atom ',coeffs_tmp(icoeff_tmp)%terms(iterm)%atindx(2,1),&
3944 0 : & ' in the direction ',mutodir(coeffs_tmp(icoeff_tmp)%terms(iterm)%direction(1))
3945 0 : if(any(coeffs_tmp(icoeff_tmp)%terms(iterm)%cell(:,2,1)/=0))then
3946 0 : write(message,'(2a,I0,a,I0,a,I0,a)') trim(message),' in the cell ',&
3947 0 : & coeffs_tmp(icoeff_tmp)%terms(iterm)%cell(1,2,1),' ',&
3948 0 : & coeffs_tmp(icoeff_tmp)%terms(iterm)%cell(2,2,1),' ',&
3949 0 : & coeffs_tmp(icoeff_tmp)%terms(iterm)%cell(3,2,1),'.'
3950 : end if
3951 0 : call wrtout(std_out,message,'COLL')
3952 : end do
3953 : end if
3954 : end do
3955 :
3956 : !TEST_AM
3957 0 : filename = "terms_1st_order.xml"
3958 0 : call polynomial_coeff_writeXML(coeffs_out,ncoeff_out,filename=filename)
3959 : !TEST_AM
3960 :
3961 0 : write(message,'(a,1x,I0,a)') ch10,&
3962 0 : & ncoeff_out,' fitted coefficients for the 1st order '
3963 0 : call wrtout(ab_out,message,'COLL')
3964 0 : call wrtout(std_out,message,'COLL')
3965 :
3966 : !Deallocation
3967 0 : do icoeff=1,ncoeff_max
3968 0 : call polynomial_coeff_free(coeffs_tmp(icoeff))
3969 : end do
3970 0 : ABI_SFREE(coeffs_tmp)
3971 :
3972 0 : end subroutine polynomial_coeff_getOrder1
3973 : !!***
3974 :
3975 : !!****f* m_polynomial_coeff/polynomial_coeff_getEvenAnhaStrain
3976 : !!
3977 : !! NAME
3978 : !! polynomial_coeff_getEvenAnhaStrain
3979 : !!
3980 : !! FUNCTION
3981 : !! Get even anharmonic strain terms in defined range of order
3982 : !!
3983 : !! INPUTS
3984 : !!
3985 : !!
3986 : !! OUTPUT
3987 : !! polynomial_coeff<(type(polynomial_coeff_type)>(ncoeff_out) = array of datatype with
3988 : !! the polynomial_coeff
3989 : !! ncoeff_out = number of coefficients
3990 : !!
3991 : !! SOURCE
3992 1 : subroutine polynomial_coeff_getEvenAnhaStrain(strain_terms,crystal,irred_ncoeff,power_strain,comm, max_nbody)
3993 :
3994 : !Arguments ------------------------------------
3995 : type(polynomial_coeff_type),allocatable,intent(inout) :: strain_terms(:)
3996 : type(crystal_t), intent(inout) :: crystal
3997 : integer,intent(out) :: irred_ncoeff
3998 : integer,intent(in) :: power_strain(2), max_nbody(:)
3999 : integer,intent(in) :: comm
4000 : !Local variables-------------------------------
4001 : real(dp) :: cutoff,coeff_ini
4002 : integer :: ncoeff,ncoeff_out,power_strph,option
4003 : integer :: icoeff1,icoeff2
4004 : integer:: nbody, npower
4005 1 : type(polynomial_coeff_type),allocatable :: strain_terms_tmp(:)
4006 : integer :: sc_size(3)
4007 : logical :: is_duplicate
4008 : ! *************************************************************************
4009 :
4010 : !Initialize empty strain_terms array
4011 : !ABI_MALLOC(strain_terms,(0))
4012 1 : irred_ncoeff = 0
4013 :
4014 : !Initial setup for call to polynomial_coeff_getNorder
4015 1 : cutoff = zero
4016 1 : power_strph = zero
4017 1 : option = 0
4018 1 : sc_size = (/1,1,1/)
4019 1 : coeff_ini = 1000000
4020 :
4021 : ! Get the higher order terms.
4022 : call polynomial_coeff_getNorder(strain_terms_tmp,crystal,cutoff,ncoeff,ncoeff_out,power_strain,&
4023 : & power_strph,option,sc_size,comm,anharmstr=.true.,spcoupling=.false.,&
4024 : & only_odd_power=.false.,only_even_power=.true.,compute_symmetric=.false.,&
4025 1 : verbose=.false., max_nbody=max_nbody)
4026 1 : if(allocated(strain_terms))then
4027 0 : ABI_ERROR("strain_terms should be unallocated")
4028 0 : call polynomial_coeff_list_free(strain_terms)
4029 0 : ABI_SFREE(strain_terms)
4030 : end if
4031 :
4032 : !Build unique list of terms by direct comparison and append
4033 57 : do icoeff1=1,ncoeff_out
4034 : !block
4035 : !Get nbody and power for current term
4036 56 : nbody=strain_terms_tmp(icoeff1)%terms(1)%get_nbody()
4037 56 : npower=strain_terms_tmp(icoeff1)%terms(1)%get_total_power()
4038 :
4039 : !Check if term is duplicate of any previously added term
4040 56 : is_duplicate = .false.
4041 : ! TODO : move this to a function
4042 56 : if(allocated(strain_terms)) then
4043 115 : do icoeff2=1,size(strain_terms)
4044 115 : if(coeffs_compare(strain_terms_tmp(icoeff1),strain_terms(icoeff2))) then
4045 : is_duplicate = .true.
4046 : exit
4047 : endif
4048 : enddo
4049 : endif
4050 :
4051 : !Append if unique
4052 : !print *, nbody , npower, is_duplicate
4053 : !print *, "nbody:", nbody, "npower:", npower, "max_nbody(npower):", max_nbody(npower)
4054 : !print *, "is_duplicate:", is_duplicate
4055 :
4056 :
4057 57 : if((.not. is_duplicate) .and. nbody<=max_nbody(npower) ) then
4058 2 : irred_ncoeff = irred_ncoeff + 1
4059 2 : call coeffs_list_append(strain_terms, strain_terms_tmp(icoeff1), .TRUE.)
4060 : !DMSG(strain_terms(irred_ncoeff)%debug_str)
4061 : endif
4062 : !end block
4063 : enddo
4064 :
4065 1 : call polynomial_coeff_list_free(strain_terms_tmp)
4066 :
4067 :
4068 1 : end subroutine polynomial_coeff_getEvenAnhaStrain
4069 : !!***
4070 :
4071 : !!****f* m_polynomial_coeff/coeffs_compare
4072 : !! NAME
4073 : !! equal
4074 : !!
4075 : !! FUNCTION
4076 : !!
4077 : !! INPUTS
4078 : !!
4079 : !! OUTPUT
4080 : !!
4081 : !! SOURCE
4082 :
4083 828 : function coeffs_compare(c1,c2) result (res)
4084 : !Arguments ------------------------------------
4085 :
4086 : !Arguments ------------------------------------
4087 : type(polynomial_coeff_type), intent(in) :: c1,c2
4088 : logical :: res
4089 : !local
4090 : !variable
4091 : integer :: iterm1,iterm2
4092 : !array
4093 : !integer,allocatable :: blkval(:,:)
4094 1656 : integer :: blkval(2, max(c1%nterm,c2%nterm))
4095 : ! *************************************************************************
4096 828 : res = .false.
4097 65916 : blkval = 0
4098 18936 : do iterm1=1,c1%nterm
4099 18108 : if(blkval(1,iterm1)==1)cycle!already found
4100 384354 : do iterm2=1,c2%nterm
4101 365418 : if(blkval(2,iterm2)==1)cycle!already found
4102 383514 : if(c1%terms(iterm1)==c2%terms(iterm2)) then
4103 12 : blkval(1,iterm1) = 1
4104 12 : blkval(2,iterm2) = 1
4105 : end if
4106 : end do
4107 : end do
4108 864 : if(.not.any(blkval(:,:)==0))res = .true.
4109 :
4110 828 : end function coeffs_compare
4111 : !!***
4112 :
4113 :
4114 : !!****f* m_polynomial_coeff/coeffs_list_conc
4115 : !! NAME
4116 : !! coeff_list_conc
4117 : !!
4118 : !! FUNCTION
4119 : !!
4120 : !! Concatenate list1 and list2 of type polynomial_coeff and store it in list_out
4121 : !!
4122 : !! INPUTS
4123 : !!
4124 : !! OUTPUT
4125 : !!
4126 : !! SOURCE
4127 :
4128 0 : function coeffs_list_conc(coeff_list1,coeff_list2) result (coeff_list_out)
4129 : !Arguments ------------------------------------
4130 :
4131 : !Arguments ------------------------------------
4132 : type(polynomial_coeff_type), intent(in) :: coeff_list1(:),coeff_list2(:)
4133 : type(polynomial_coeff_type) :: coeff_list_out(size(coeff_list1)+size(coeff_list2))
4134 : !local
4135 : !variable
4136 : integer :: ncoeff1,ncoeff2,ncoeff_out,i,j
4137 : !array
4138 : ! *************************************************************************
4139 :
4140 : !Get sizes of coeff_list1/2
4141 0 : ncoeff1 = size(coeff_list1)
4142 0 : ncoeff2 = size(coeff_list2)
4143 0 : ncoeff_out = ncoeff1 + ncoeff2
4144 :
4145 0 : if(ncoeff_out/= size(coeff_list_out))then
4146 0 : ABI_ERROR("coeff_list_out should be allocated with the size of coeff_list1+coeff_list2")
4147 : endif
4148 :
4149 :
4150 0 : if (.not. allocated(coeff_list1(i)%terms)) then
4151 0 : ABI_ERROR("copying coeff_list1(i) but coeff_list1(i)%terms is not allocated")
4152 : endif
4153 :
4154 0 : do i=1,ncoeff_out
4155 0 : if(i<=ncoeff1)then
4156 : call polynomial_coeff_init(coeff_list1(i)%coefficient,coeff_list1(i)%nterm,coeff_list_out(i),coeff_list1(i)%terms,&
4157 0 : & coeff_list1(i)%name, check=.TRUE.)
4158 : !if (trim(coeff_list1(i)%debug_str)=="unintialized" &
4159 : !& .or. trim(coeff_list1(i)%debug_str)=="freed") then
4160 : ! ABI_ERROR("coeff_list1(i) is uninitialized or freed")
4161 : !else
4162 : ! coeff_list_out(i)%debug_str = "copied from" // trim(coeff_list1(i)%debug_str)
4163 : !end if
4164 : else
4165 0 : j=i-ncoeff1
4166 : call polynomial_coeff_init(coeff_list2(j)%coefficient,coeff_list2(j)%nterm,coeff_list_out(i),coeff_list2(j)%terms,&
4167 0 : & coeff_list2(j)%name,check=.TRUE.)
4168 : !if (trim(coeff_list2(j)%debug_str)=="unintialized" &
4169 : !& .or. trim(coeff_list2(j)%debug_str)=="freed") then
4170 : ! ABI_ERROR("coeff_list2(j) is uninitialized or freed")
4171 : !else
4172 : ! coeff_list_out(i)%debug_str = "copied from" // trim(coeff_list2(j)%debug_str)
4173 : !end if
4174 : endif
4175 : enddo
4176 :
4177 0 : end function coeffs_list_conc
4178 : !!***
4179 :
4180 :
4181 : !!****f* m_polynomial_coeff/coeffs_list_conc_onsite
4182 : !! NAME
4183 : !! coeff_list_conc_onsite
4184 : !!
4185 : !! FUNCTION
4186 : !!
4187 : !! Concatenate list1 and list2 of type polynomial_coeff and store it in list1
4188 : !!
4189 : !! INPUTS
4190 : !!
4191 : !! OUTPUT
4192 : !!
4193 : !! SOURCE
4194 0 : subroutine coeffs_list_conc_onsite(coeff_list1,coeff_list2)
4195 : !Arguments ------------------------------------
4196 :
4197 : !Arguments ------------------------------------
4198 : type(polynomial_coeff_type), allocatable, intent(inout) :: coeff_list1(:)
4199 : type(polynomial_coeff_type), intent(in) ::coeff_list2(:)
4200 : !local
4201 : !variable
4202 : integer :: ncoeff1,ncoeff2,ncoeff_out
4203 : !array
4204 : type(polynomial_coeff_type), allocatable :: coeff_list_tmp(:)
4205 : ! *************************************************************************
4206 :
4207 0 : ncoeff1=size(coeff_list1)
4208 0 : ncoeff2=size(coeff_list2)
4209 0 : ncoeff_out = ncoeff1+ncoeff2
4210 :
4211 : ! copy list1 to tmp
4212 0 : ABI_MALLOC(coeff_list_tmp,(ncoeff1))
4213 : !coeff_list_tmp=coeff_list1
4214 0 : call coeffs_list_copy(coeff_list_tmp, coeff_list1)
4215 :
4216 : ! allocate new list1
4217 0 : call polynomial_coeff_list_free(coeff_list1)
4218 0 : ABI_MALLOC(coeff_list1,(ncoeff_out))
4219 0 : coeff_list1(1:ncoeff1) = coeff_list_tmp
4220 0 : coeff_list1(ncoeff1+1:ncoeff_out) = coeff_list2
4221 0 : call polynomial_coeff_list_free(coeff_list_tmp)
4222 :
4223 0 : end subroutine coeffs_list_conc_onsite
4224 : !!***
4225 :
4226 :
4227 :
4228 :
4229 : !!****f* m_polynomial_coeff/coeffs_list_append
4230 : !! NAME
4231 : !! coeff_list_append
4232 : !!
4233 : !! FUNCTION
4234 : !!
4235 : !! append on coeff to the list of coeffs: coeff_list
4236 : !!
4237 : !! INPUTS
4238 : !!
4239 : !! OUTPUT
4240 : !!
4241 : !! SOURCE
4242 3 : subroutine coeffs_list_append(coeff_list,coeff, check)
4243 : !Arguments ------------------------------------
4244 :
4245 : !Arguments ------------------------------------
4246 : type(polynomial_coeff_type), allocatable, intent(inout) ::coeff_list(:)
4247 : type(polynomial_coeff_type), intent(inout) :: coeff
4248 : logical, intent(in) :: check
4249 : !local variable
4250 3 : type(polynomial_coeff_type), allocatable :: tmp(:)
4251 : integer :: n1, n2
4252 : !array
4253 : ! *************************************************************************
4254 :
4255 : ! check if coeff is initialized
4256 3 : if (.not.allocated(coeff%terms)) then
4257 0 : ABI_BUG("terms for append is not allocated.")
4258 : endif
4259 :
4260 3 : if (.not. allocated(coeff_list)) then
4261 1 : n1 = 0
4262 1 : n2= 1
4263 3 : ABI_MALLOC(coeff_list,(n2))
4264 : call polynomial_coeff_init(coeff%coefficient,coeff%nterm,coeff_list(1),coeff%terms,&
4265 1 : & coeff%name, check=check)
4266 : !coeff_list(n2)%debug_str = "copied from" // trim(coeff%debug_str)
4267 : else
4268 2 : n1=size(coeff_list)
4269 2 : n2= n1+1
4270 : ! copy list1 to tmp
4271 8 : ABI_MALLOC(tmp,(n1))
4272 2 : tmp=coeff_list
4273 : ! allocate new list1
4274 2 : call polynomial_coeff_list_free(coeff_list)
4275 10 : ABI_MALLOC(coeff_list,(n2))
4276 :
4277 2 : call coeffs_list_copy(coeff_list(:n1), tmp)
4278 :
4279 : call polynomial_coeff_init(coeff%coefficient,coeff%nterm,coeff_list(n2),coeff%terms,&
4280 2 : & coeff%name, check=check)
4281 :
4282 : !coeff_list(n2)%debug_str = "copied from" // trim(coeff%debug_str)
4283 2 : call polynomial_coeff_list_free(tmp)
4284 2 : ABI_SFREE(tmp)
4285 : end if
4286 :
4287 3 : end subroutine coeffs_list_append
4288 : !!***
4289 :
4290 : !!****f* m_polynomial_coeff/coeffs_list_truncate
4291 : !! NAME
4292 : !! coeffs_list_truncate
4293 : !!
4294 : !! FUNCTION
4295 : !!
4296 : !! Truncate a list of coeffs to keep only the first n elements
4297 : !!
4298 : !! INPUTS
4299 : !! coeff_list = list of coefficients to truncate
4300 : !! n = number of coefficients to keep
4301 : !!
4302 : !! OUTPUT
4303 : !! coeff_list = truncated list with only first n coefficients
4304 : !!
4305 : !! SOURCE
4306 :
4307 2 : subroutine coeffs_list_truncate(coeff_list, n)
4308 : !Arguments ------------------------------------
4309 :
4310 : !Arguments ------------------------------------
4311 : type(polynomial_coeff_type), allocatable, intent(inout) :: coeff_list(:)
4312 : integer, intent(in) :: n
4313 : !local variables
4314 2 : type(polynomial_coeff_type), allocatable :: tmp(:)
4315 : character(len=500) :: message
4316 : ! *************************************************************************
4317 :
4318 2 : if(.not. allocated(coeff_list)) then
4319 0 : write(message,'(a)')'The input list of polynomial_coefficients is not allocated'
4320 0 : ABI_ERROR(message)
4321 : endif
4322 :
4323 2 : if(n > size(coeff_list)) then
4324 0 : write(message,'(a)')'n is larger than size of input list'
4325 0 : ABI_ERROR(message)
4326 : endif
4327 :
4328 2 : if(n < 0) then
4329 0 : write(message,'(a)')'n must be non-negative'
4330 0 : ABI_ERROR(message)
4331 : endif
4332 :
4333 : !Copy first n elements to temp array
4334 12 : ABI_MALLOC(tmp,(n))
4335 2 : call coeffs_list_copy(tmp, coeff_list(1:n))
4336 :
4337 : !Free original array
4338 2 : call polynomial_coeff_list_free(coeff_list)
4339 :
4340 : !Reallocate and copy back
4341 10 : ABI_MALLOC(coeff_list,(n))
4342 2 : call coeffs_list_copy(coeff_list, tmp)
4343 :
4344 : !Clean up
4345 2 : call polynomial_coeff_list_free(tmp)
4346 2 : ABI_SFREE(tmp)
4347 :
4348 2 : end subroutine coeffs_list_truncate
4349 : !!***
4350 :
4351 :
4352 0 : subroutine coeffs_list_reduce_duplicate(self, crystal, sc_size, fit_iatom_in, cutoff_in , ndispmax )
4353 : type(polynomial_coeff_type), allocatable, target, intent(inout) ::self(:)
4354 0 : type(polynomial_coeff_type), allocatable :: tmp(:)
4355 0 : type(IrreducibleCombinations_T) :: irred_combinations
4356 : type(crystal_t), target, intent(inout) :: crystal
4357 : integer, intent(in) :: sc_size(3)
4358 : integer, intent(in), optional :: fit_iatom_in
4359 : real(dp), intent(in), optional :: cutoff_in
4360 : integer , intent(in) :: ndispmax
4361 0 : type(sympairs_t) :: sympairs
4362 : !integer :: list_symcoeff(:,:,:),list_symstr(:,:,:), ncoeff_symsym, nsym, power_disps(:), cell(:,:)
4363 0 : logical :: mask(size(self))
4364 : integer :: i, n, counter
4365 0 : call SymPairs_t_init(sympairs, crystal, sc_size, fit_iatom_in, cutoff_in)
4366 0 : mask=.True.
4367 0 : call irred_combinations%init()
4368 : ! Find ir terms
4369 0 : do i=1, size(self)
4370 : mask(i)=irred_combinations%add_irr(self(i)%terms(1)%index_coeff, &
4371 : & sympairs%list_symcoeff, sympairs%list_symstr, size(sympairs%list_symcoeff(:,1,:)), &
4372 0 : & sympairs%nsym, ndispmax, sympairs%cell)
4373 : end do
4374 0 : n=count(mask)
4375 :
4376 : ! copy self to tmp
4377 0 : ABI_MALLOC(tmp,( size(self)))
4378 0 : do i=1, size(self)
4379 : call polynomial_coeff_init(self(i)%coefficient,self(i)%nterm,tmp(i),self(i)%terms,&
4380 : & self(i)%name, check=.True. &
4381 0 : )
4382 : end do
4383 :
4384 :
4385 0 : call polynomial_coeff_list_free(self)
4386 0 : ABI_MALLOC(self,(n))
4387 0 : counter=0
4388 0 : do i=1, size(tmp)
4389 0 : if(mask(i)) then
4390 0 : counter =counter +1
4391 : call polynomial_coeff_init(tmp(i)%coefficient,tmp(i)%nterm,self(counter),tmp(i)%terms,&
4392 : & tmp(i)%name, check=.True. &
4393 0 : )
4394 : end if
4395 : end do
4396 0 : call polynomial_coeff_list_free(tmp)
4397 0 : call sympairs%free()
4398 0 : call irred_combinations%free()
4399 0 : end subroutine coeffs_list_reduce_duplicate
4400 :
4401 : !!****f* m_polynomial_coeff/coeffs_list_copy
4402 : !! NAME
4403 : !! coeff_list_copy
4404 : !!
4405 : !! FUNCTION
4406 : !!
4407 : !! Copy list1 to list2 of type polynomial_coeff
4408 : !!
4409 : !! INPUTS
4410 : !!
4411 : !! OUTPUT
4412 : !!
4413 : !! SOURCE
4414 :
4415 10593 : subroutine coeffs_list_copy(coeff_list_out,coeff_list_in)
4416 : !Arguments ------------------------------------
4417 :
4418 : !Arguments ------------------------------------
4419 : type(polynomial_coeff_type), intent(in) :: coeff_list_in(:)
4420 : type(polynomial_coeff_type),intent(out) :: coeff_list_out(:)
4421 : !local
4422 : !variable
4423 : integer :: ncoeff_in,ncoeff_out,ii
4424 : logical :: check
4425 : character(len=500):: message
4426 : !array
4427 : ! *************************************************************************
4428 :
4429 63 : check = .true.
4430 :
4431 : !Get size of coeff_lists
4432 63 : ncoeff_in = size(coeff_list_in)
4433 63 : ncoeff_out = size(coeff_list_out)
4434 :
4435 63 : if(ncoeff_in > ncoeff_out)then
4436 0 : write(message,'(a,a,a)')'The input list of polynomial_coefficients is larger',ch10,&
4437 0 : & 'than the output list you want it assign to. Check size of lists.'
4438 0 : ABI_ERROR(message)
4439 : endif
4440 :
4441 5328 : do ii=1,ncoeff_in
4442 :
4443 5265 : if(.not. allocated(coeff_list_in(ii)%terms)) then
4444 0 : ABI_BUG("terms for copy is not allocated.")
4445 : endif
4446 : call polynomial_coeff_init(coeff_list_in(ii)%coefficient,coeff_list_in(ii)%nterm,&
4447 : & coeff_list_out(ii),coeff_list_in(ii)%terms, &
4448 5328 : & coeff_list_in(ii)%name, check)
4449 :
4450 : !coeff_list_out%debug_str = "copied from " // coeff_list_in(ii)%debug_str
4451 : enddo
4452 63 : end subroutine coeffs_list_copy
4453 : !!***
4454 :
4455 : !!****f* m_polynomial_coeff/sort_combination
4456 : !! NAME
4457 : !! sort_combination
4458 : !!
4459 : !! FUNCTION
4460 : !!
4461 : !! Sort a list of integer from small to large if it contains zeros will be put to highest indexe
4462 : !!
4463 : !! INPUTS
4464 : !!
4465 : !! OUTPUT
4466 : !!
4467 : !! SOURCE
4468 :
4469 638298090 : subroutine sort_combination(combination,n_int)
4470 : !Arguments ------------------------------------
4471 :
4472 : !Arguments ------------------------------------
4473 : !scalar
4474 : integer,intent(in) :: n_int
4475 : !array
4476 : integer,intent(inout) :: combination(n_int)
4477 : !local
4478 : !variable
4479 : integer :: j,k,cnt,tmp_int1,tmp_int2
4480 : !array
4481 : ! *************************************************************************
4482 :
4483 638298090 : j=2
4484 2423729328 : do while(j <= n_int)
4485 : k = j
4486 : cnt = 1
4487 4451760567 : do while(k >= 2 .and. cnt == 1)
4488 4451760567 : if(combination(k-1) > combination(k) .and. combination(k) > 0)then
4489 1446388836 : tmp_int1 = combination(k-1)
4490 1446388836 : tmp_int2 = combination(k)
4491 1446388836 : combination(k) = tmp_int1
4492 1446388836 : combination(k-1) = tmp_int2
4493 1446388836 : k=k-1
4494 : else
4495 : cnt = cnt + 1
4496 : end if
4497 : end do
4498 1785431238 : j = j+1
4499 : end do
4500 :
4501 638298090 : end subroutine sort_combination
4502 : !!***
4503 :
4504 : !!****f* m_polynomial_coeff/sort_combination_list
4505 : !! NAME
4506 : !! sort_combination_list
4507 : !!
4508 : !! FUNCTION
4509 : !!
4510 : !! Sort a list of integer list from small to large if it contains zeros will be put to highest index
4511 : !!
4512 : !! INPUTS
4513 : !!
4514 : !! OUTPUT
4515 : !!
4516 : !! SOURCE
4517 :
4518 : subroutine sort_combination_list(combination_list,n_int,n_list)
4519 : !Arguments ------------------------------------
4520 :
4521 : !Arguments ------------------------------------
4522 : !scalar
4523 : integer,intent(in) :: n_int,n_list
4524 : !array
4525 : integer,intent(inout) :: combination_list(n_int,n_list)
4526 : !local
4527 : !variable
4528 : integer :: i
4529 : !array
4530 : ! *************************************************************************
4531 :
4532 : do i=1,n_list
4533 : call sort_combination(combination_list(:,i),n_int)
4534 : end do
4535 :
4536 : end subroutine sort_combination_list
4537 : !!***
4538 :
4539 :
4540 : !!****f* m_polynomial_coeff/reduce_zero_combinations
4541 : !! NAME
4542 : !! reduce_zero_combinations
4543 : !!
4544 : !! FUNCTION
4545 : !!
4546 : !! Sort out list of zeros in a list of integers
4547 : !!
4548 : !! INPUTS
4549 : !!
4550 : !! OUTPUT
4551 : !!
4552 : !! SOURCE
4553 :
4554 50 : subroutine reduce_zero_combinations(combination_list)
4555 : !Arguments ------------------------------------
4556 :
4557 : !Arguments ------------------------------------
4558 : !scalar
4559 : !array
4560 : integer,allocatable,intent(inout) :: combination_list(:,:)
4561 : !local
4562 : !variable
4563 : integer :: i,j
4564 50 : integer,allocatable :: combination_list_tmp(:,:)
4565 : !array
4566 : ! *************************************************************************
4567 :
4568 : !Reduce zero combinations
4569 50 : i = 0
4570 14668 : do j=1,size(combination_list,2)
4571 14980 : if(any(combination_list(:,j) /= 0))then
4572 14514 : i = i + 1
4573 : endif
4574 : enddo
4575 :
4576 200 : ABI_MALLOC(combination_list_tmp,(size(combination_list,1),i))
4577 50 : i = 0
4578 14668 : do j=1,size(combination_list,2)
4579 14980 : if(any(combination_list(:,j) /= 0))then
4580 14514 : i = i + 1
4581 59162 : combination_list_tmp(:,i) = combination_list(:,j)
4582 : endif
4583 : enddo
4584 50 : ABI_SFREE(combination_list)
4585 200 : ABI_MALLOC(combination_list,(size(combination_list_tmp,1),i))
4586 59262 : combination_list = combination_list_tmp
4587 50 : ABI_SFREE(combination_list_tmp)
4588 :
4589 50 : end subroutine reduce_zero_combinations
4590 : !!***
4591 :
4592 3667970 : function find_irpt(cells, cell) result(my_irpt)
4593 : integer, intent(in) :: cells(:, :), cell(:)
4594 : integer :: my_irpt, i
4595 3667970 : my_irpt=-1
4596 462164220 : do i =1, size(cells, 2)
4597 575871290 : if (all(cell==cells(:, i))) my_irpt=i
4598 : end do
4599 3667970 : if(my_irpt==-1) ABI_BUG("cell not found.")
4600 3667970 : end function find_irpt
4601 :
4602 : ! for one r in a list of rpts, find the index of -r
4603 3667968 : function find_opposite_irpt(cells, irpt) result(n)
4604 : integer, intent(in) :: cells(:, :), irpt
4605 : integer :: n
4606 14671872 : n=find_irpt(cells, -cells(:, irpt))
4607 3667968 : end function find_opposite_irpt
4608 :
4609 1 : subroutine SymPairs_t_init(self, crystal, sc_size, fit_iatom_in, cutoff_in)
4610 : class(SymPairs_t), intent(inout) ::self
4611 : type(crystal_t), target, intent(inout) :: crystal
4612 : integer, intent(in) :: sc_size(3)
4613 : integer, intent(in), optional :: fit_iatom_in
4614 : real(dp), intent(in), optional :: cutoff_in
4615 1 : self%crystal=> crystal
4616 4 : self%sc_size(:) = sc_size(:)
4617 1 : if(present(fit_iatom_in)) then
4618 0 : self%fit_iatom = fit_iatom_in
4619 : else
4620 1 : self%fit_iatom = -1
4621 : end if
4622 1 : if(present(cutoff_in)) then
4623 0 : self%cutoff=cutoff_in
4624 : else
4625 1 : self%cutoff=get_crystal_cutoff(crystal)
4626 : end if
4627 : call prepare_for_getList(crystal, sc_size, self%dist, self%cell, &
4628 1 : & self%natom, self%nsym, self%nrpt, self%range_ifc, self%symbols)
4629 : call polynomial_coeff_getList(self%cell,self%crystal,self%dist, &
4630 : &self%list_symcoeff,self%list_symstr,&
4631 : &self%natom,self%nstr_sym,self%ncoeff_sym,self%nrpt, &
4632 : &self%range_ifc,self%cutoff,sc_size=self%sc_size,&
4633 1 : &fit_iatom=fit_iatom_in)
4634 1 : end subroutine SymPairs_t_init
4635 :
4636 2 : subroutine SymPairs_t_free(self)
4637 : class(SymPairs_t), intent(inout) ::self
4638 2 : nullify(self%crystal)
4639 2 : ABI_SFREE(self%list_symcoeff)
4640 2 : ABI_SFREE(self%list_symstr)
4641 2 : ABI_SFREE(self%cell)
4642 2 : ABI_SFREE(self%dist)
4643 2 : ABI_SFREE(self%symbols)
4644 2 : end subroutine SymPairs_t_free
4645 :
4646 588 : subroutine SymPairs_t_generateTerms(self, index_coeff, power, nterm, terms, reverse)
4647 : class(SymPairs_t), intent(inout) ::self
4648 : integer,intent(in) :: index_coeff(:)
4649 : integer, intent(in) :: power
4650 : integer, intent(out) :: nterm
4651 : type(polynomial_term_type),intent(out) :: terms(self%nsym)
4652 : logical, optional, intent(in) :: reverse(power)
4653 6 : logical :: reverse_a(power)
4654 : integer :: ndisp_max
4655 6 : if(present(reverse))then
4656 42 : reverse_a(:) = reverse(:)
4657 : else
4658 0 : reverse_a(:) = .False.
4659 : end if
4660 6 : ndisp_max=size(index_coeff)
4661 : ! Note that ncoeff_sym is not the same as ncoeff_symsym
4662 : call generateTermsFromList(self%cell,index_coeff,self%list_symcoeff, &
4663 : &self%list_symstr,size(self%list_symcoeff, 2),power,self%nrpt,self%nstr_sym,self%nsym, &
4664 6 : &nterm,terms, reverse=reverse_a)
4665 6 : end subroutine SymPairs_t_generateTerms
4666 :
4667 1 : subroutine SymPairs_t_final(self)
4668 : type(SymPairs_t), intent(inout) :: self
4669 : ! Call the free method to ensure proper cleanup
4670 0 : call self%free()
4671 1 : end subroutine SymPairs_t_final
4672 :
4673 60 : subroutine IrreducibleCombinations_init(self)
4674 : class(IrreducibleCombinations_t), intent(inout) :: self
4675 60 : call self%table%init(2023)
4676 60 : end subroutine IrreducibleCombinations_init
4677 :
4678 60 : subroutine IrreducibleCombinations_free(self)
4679 : class(IrreducibleCombinations_t), intent(inout) :: self
4680 60 : call self%table%free()
4681 60 : call self%array%finalize()
4682 60 : end subroutine IrreducibleCombinations_free
4683 :
4684 2271 : subroutine IrreducibleCombinations_reset_array(self)
4685 : class(IrreducibleCombinations_t), intent(inout) :: self
4686 2271 : call self%array%finalize()
4687 0 : end subroutine IrreducibleCombinations_Reset_Array
4688 :
4689 :
4690 59280640 : function IrreducibleCombinations_add_irr(self, combination, list_symcoeff, &
4691 29640320 : & list_symstr, ncoeff_sym, nsym, ndisp, cell ) result(irreducible)
4692 : class(IrreducibleCombinations_t), intent(inout) :: self
4693 : integer, intent(inout) :: combination(:)
4694 : integer,intent(in) :: ncoeff_sym,ndisp,nsym
4695 : integer,intent(in) :: list_symcoeff(6,ncoeff_sym,nsym)
4696 : integer,intent(in) :: list_symstr(6,nsym,2), cell(:, :)
4697 :
4698 59280640 : integer :: combination_cmp_tmp(ndisp), combination_sorted(ndisp)
4699 : logical :: irreducible
4700 : integer :: n, isym
4701 : ! check if the combination, or its symmetry equivalent are already in the
4702 : ! table. If not, add it to the table.
4703 :
4704 : ABI_UNUSED(cell)
4705 29640320 : irreducible=.True.
4706 142145284 : combination_sorted(:)=combination(:)
4707 29640320 : call sort_combination(combination_sorted,size(combination))
4708 29640320 : n=size(combination)
4709 29640320 : if ( self%table%has_key_intn(combination_sorted, n)) then
4710 29630178 : irreducible=.False.
4711 29630178 : return
4712 : else
4713 28127608 : isym = 2
4714 608667912 : do while(isym <= nsym)
4715 608657770 : call symcomb(combination_sorted, combination_cmp_tmp, isym)
4716 608657770 : call sort_combination(combination_cmp_tmp,size(combination_cmp_tmp))
4717 608667912 : if (self%table%has_key_intn(combination_cmp_tmp, n)) then
4718 28117466 : irreducible=.False.
4719 28117466 : return
4720 : else
4721 580540304 : isym = isym + 1
4722 : end if
4723 : end do
4724 : end if
4725 10142 : call self%table%put_intn(combination_sorted, 0.0_dp, n)
4726 10142 : call self%array%push(combination)
4727 : contains
4728 :
4729 : function reverse(combination, isym, cell) result(rcomb)
4730 : integer :: combination(:), isym, cell(:, :)
4731 : integer :: rcomb(size(combination))
4732 : integer :: ia, ib, irpt, weight, idisp
4733 : do idisp=1,ndisp
4734 : if(combination(idisp) /= 0 .and. combination(idisp) <= ncoeff_sym)then
4735 : ia = list_symcoeff(3,combination(idisp),isym)
4736 : ib = list_symcoeff(2,combination(idisp),isym)
4737 : irpt = list_symcoeff(4,combination(idisp),isym)
4738 : irpt = find_opposite_irpt(cell, irpt)
4739 : rcomb(idisp)=getCoeffFromList(list_symcoeff, ia, ib, irpt, weight, ncoeff_sym)
4740 : else
4741 : rcomb(idisp)=combination(idisp)
4742 : end if
4743 : end do
4744 : end function reverse
4745 :
4746 :
4747 : ! function is_onebody_term_in_right_order(combination) result(ret)
4748 : ! integer :: combination(:)
4749 : ! integer :: ia, ib, irpt, weight, idisp
4750 : ! do idisp=1,ndisp
4751 : ! if(combination(idisp) /= 0 .and. combination(idisp) <= ncoeff_sym)then
4752 : ! ia = list_symcoeff(2,combination(idisp),isym)
4753 : ! ib = list_symcoeff(3,combination(idisp),isym)
4754 : ! !irpt = list_symcoeff(4,combination(idisp),isym)
4755 : ! !rcomb(idisp)=getCoeffFromList(list_symcoeff, ia, ib, irpt, weight, ncoeff_sym)
4756 : ! end if
4757 : ! end do
4758 : ! end function is_onebody_term_in_right_order
4759 :
4760 :
4761 : ! get the symmetry equivalent combination with symmetry index isym.
4762 608657770 : subroutine symcomb(combination, combination_cmp_tmp, isym)
4763 : integer :: combination(:), combination_cmp_tmp(:), isym
4764 : integer :: idisp, istrain
4765 2919882134 : do idisp=1,ndisp
4766 2919882134 : if(combination(idisp) /= 0 .and. combination(idisp) <= ncoeff_sym)then
4767 2252390476 : combination_cmp_tmp(idisp)=list_symcoeff(6,combination(idisp),isym)
4768 58833888 : else if(combination(idisp) > ncoeff_sym)then
4769 51841488 : istrain = combination(idisp) - ncoeff_sym
4770 51841488 : combination_cmp_tmp(idisp)=list_symstr(istrain,isym,1) + ncoeff_sym
4771 : else
4772 6992400 : combination_cmp_tmp(idisp) = 0
4773 : endif
4774 : enddo
4775 608657770 : end subroutine symcomb
4776 : end function IrreducibleCombinations_add_irr
4777 :
4778 :
4779 58295932 : subroutine get_powers(index_coeff_tmp, ndisp, powers)
4780 : integer, intent(in) :: ndisp
4781 : integer, intent(in) :: index_coeff_tmp(:) ! size ndisp
4782 : integer, intent(inout) :: powers(ndisp) ! size ndisp
4783 : integer :: ii, jj
4784 252829848 : powers(:) = 1
4785 252829848 : do ii=1,ndisp
4786 194533916 : if(index_coeff_tmp(ii)==0) then
4787 62684658 : powers(ii)=0
4788 62684658 : cycle
4789 : end if
4790 131849258 : if (powers(ii) == 0) cycle
4791 347664292 : do jj=ii+1,ndisp
4792 169106858 : if (powers(jj) == 0) cycle
4793 296993428 : if(index_coeff_tmp(ii)==index_coeff_tmp(jj))then
4794 11587756 : powers(ii) = powers(ii) + 1
4795 11587756 : powers(jj) = 0
4796 : end if
4797 : end do
4798 : end do
4799 58295932 : end subroutine get_powers
4800 :
4801 :
4802 4542 : subroutine get_totpower_and_nbody(index_coeff_tmp, ndisp, nbody, totpower)
4803 : ! get the total power and number of body in the polynomial
4804 : integer, intent(in) :: ndisp
4805 : integer, intent(in) :: index_coeff_tmp(:) ! size ndisp
4806 : integer, intent(inout) :: nbody, totpower
4807 9084 : integer :: powers(ndisp), i, p ! size ndisp
4808 4542 : nbody=0
4809 4542 : totpower=0
4810 4542 : call get_powers(index_coeff_tmp, ndisp, powers)
4811 11384 : do i=1, ndisp
4812 6842 : p=powers(i)
4813 11384 : if(p>0) then
4814 5732 : nbody=nbody+1
4815 5732 : totpower=totpower+p
4816 : end if
4817 : end do
4818 4542 : end subroutine get_totpower_and_nbody
4819 :
4820 :
4821 0 : subroutine polyform_init(self, n)
4822 : class(polyform_t), intent(inout) :: self
4823 : integer, intent(in) :: n
4824 0 : self%n=n
4825 0 : ABI_MALLOC(self%ind, (n))
4826 0 : ABI_MALLOC(self%order, (n))
4827 0 : end subroutine polyform_init
4828 :
4829 122 : subroutine polyform_free(self)
4830 : class(polyform_t), intent(inout) :: self
4831 122 : self%n=0
4832 122 : ABI_SFREE(self%ind)
4833 122 : ABI_SFREE(self%order)
4834 122 : ABI_SFREE(self%expansion)
4835 122 : end subroutine polyform_free
4836 :
4837 122 : subroutine polyform_from_expansion(polyform, ind, ndisp)
4838 : class(polyform_t) , intent(inout):: polyform
4839 : integer, intent(in) :: ind(:) ! size ndisp
4840 : integer, intent(in) :: ndisp
4841 244 : integer :: ii, jj, powers(ndisp)
4842 122 : call get_powers(ind, ndisp, powers)
4843 308 : polyform%n=count(powers>0)
4844 366 : ABI_MALLOC(polyform%ind, (polyform%n))
4845 244 : ABI_MALLOC(polyform%order, (polyform%n))
4846 122 : jj=1
4847 308 : do ii=1, ndisp
4848 308 : if(powers(ii)>0) then
4849 120 : polyform%ind(jj)=ind(ii)
4850 120 : polyform%order(jj)=powers(ii)
4851 120 : jj=jj+1
4852 : end if
4853 : end do
4854 122 : end subroutine polyform_from_expansion
4855 :
4856 :
4857 80868 : subroutine expand_poly(ind, order, n, list)
4858 : integer, intent(in) :: ind(:), order(:), n
4859 : integer, intent(out) :: list(:)
4860 : integer :: i, j,s, e ! s,e: start, end
4861 80868 : s=1
4862 240036 : do i=1, n
4863 159168 : e=s+order(i)-1
4864 398208 : do j=s, e
4865 398208 : list(j) = ind(i)
4866 : end do
4867 240036 : s=e+1
4868 : end do
4869 80868 : end subroutine expand_poly
4870 :
4871 :
4872 0 : subroutine polyform_expand(self, expansion)
4873 : class(polyform_t), intent(inout) :: self
4874 : integer, allocatable, intent(out) :: expansion(:)
4875 0 : ABI_MALLOC(expansion, (sum(self%order)))
4876 0 : call expand_poly(self%ind, self%order, self%n, expansion)
4877 0 : end subroutine polyform_expand
4878 :
4879 :
4880 : !!****f* m_polynomial_coeff/polynomial_coeff_final
4881 : !! NAME
4882 : !! polynomial_coeff_final
4883 : !!
4884 : !! FUNCTION
4885 : !! Finalizer for polynomial_coeff_type to properly clean up allocated memory
4886 : !!
4887 : !! INPUTS
4888 : !! self = The polynomial_coeff_type instance being finalized
4889 : !!
4890 : !! SOURCE
4891 :
4892 : subroutine polynomial_coeff_final(self)
4893 : type(polynomial_coeff_type), intent(inout) :: self
4894 : !print *, "Finalizing polynomial_coeff_type: ", trim(self%debug_str)
4895 : call polynomial_coeff_free(self)
4896 : end subroutine polynomial_coeff_final
4897 : !!***
4898 :
4899 : subroutine starts_with(str, prefix, result)
4900 : character(len=*), intent(in) :: str
4901 : character(len=*), intent(in) :: prefix
4902 : logical, intent(out) :: result
4903 : result = str(1:len(prefix)) == prefix
4904 : end subroutine starts_with
4905 :
4906 :
4907 4 : end module m_polynomial_coeff
4908 : !!***
|