Line data Source code
1 : !!****m* ABINIT/m_effective_potential_file
2 : !! NAME
3 : !! m_effective_potential_file
4 : !!
5 : !! FUNCTION
6 : !! This module contains all routine to read the effective potential from files
7 : !! Can also read coefficients from XML
8 : !! (XML or DDB)
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2000-2026 ABINIT group (AM)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
16 : !!
17 : !! SOURCE
18 :
19 : #if defined HAVE_CONFIG_H
20 : #include "config.h"
21 : #endif
22 :
23 : #include "abi_common.h"
24 :
25 :
26 : module m_effective_potential_file
27 :
28 : use defs_basis
29 : use m_errors
30 : use m_abicore
31 : use m_xmpi
32 : use m_harmonics_terms
33 : use m_anharmonics_terms
34 : use m_effective_potential
35 : use m_ifc
36 : use m_ddb
37 : use m_ddb_hdr
38 : use netcdf
39 :
40 : use m_io_tools, only : open_file, get_unit
41 : use m_geometry, only : xcart2xred, xred2xcart, metric
42 : use m_symfind, only : symfind, symlatt
43 : use m_crystal, only : crystal_t
44 : use m_dynmat, only : dfpt_prtph
45 : use m_abihist, only : abihist,abihist_init,abihist_free,abihist_copy,read_md_hist
46 : use m_ddb_internalstr, only : ddb_internalstr
47 :
48 : implicit none
49 :
50 : public :: effective_potential_file_getDimCoeff
51 : public :: effective_potential_file_getDimMD
52 : public :: effective_potential_file_getDimSystem
53 : public :: effective_potential_file_getDimStrainCoupling
54 : public :: effective_potential_file_getType
55 : public :: effective_potential_file_mapHistToRef
56 : public :: effective_potential_file_read
57 : public :: effective_potential_file_readDisplacement
58 : public :: effective_potential_file_readMDfile
59 : private :: coeffs_xml2effpot
60 : private :: system_getDimFromXML
61 : private :: system_xml2effpot
62 : private :: system_ddb2effpot
63 :
64 : #ifndef HAVE_XML
65 : private :: rdfromline
66 : private :: rmtabfromline
67 : private :: rdfromline_value
68 : private :: elementfromline
69 : #endif
70 :
71 : #if defined HAVE_XML
72 : public :: effpot_xml_checkXML
73 : public :: effpot_xml_getDimCoeff
74 : public :: effpot_xml_readSystem
75 : public :: effpot_xml_getValue
76 : public :: effpot_xml_getAttribute
77 : public :: effpot_xml_getDimSystem
78 :
79 : interface
80 : subroutine effpot_xml_readSystem(filename,natom,&
81 : & ntypat,nrpt,nqpt,amu,atmfrc,cell,dynmat,elastic_constants,&
82 : & energy,epsilon_inf,ewald_atmfrc,&
83 : & phfrq,rprimd,qph1l,short_atmfrc,typat,xcart,zeff)&
84 : & bind(C,name="effpot_xml_readSystem")
85 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_DOUBLE,C_INT
86 : integer(C_INT) :: natom,ntypat,nrpt,nqpt
87 : integer(C_INT) :: typat(natom)
88 : integer(C_INT) :: cell(3,nrpt)
89 : real(C_DOUBLE) :: energy
90 : real(C_DOUBLE) :: dynmat(2,3,natom,3,natom,nqpt)
91 : real(C_DOUBLE) :: phfrq(3*natom,nqpt),qph1l(3,nqpt)
92 : real(C_DOUBLE) :: atmfrc(3,natom,3,natom,nrpt)
93 : real(C_DOUBLE) :: short_atmfrc(3,natom,3,natom,nrpt)
94 : real(C_DOUBLE) :: ewald_atmfrc(3,natom,3,natom,nrpt)
95 : real(C_DOUBLE) :: amu(ntypat),rprimd(3,3),epsilon_inf(3,3)
96 : real(C_DOUBLE) :: zeff(3,3,natom)
97 : real(C_DOUBLE) :: elastic_constants(6,6),xcart(3,natom)
98 : character(kind=C_CHAR) :: filename(*)
99 : end subroutine effpot_xml_readSystem
100 : end interface
101 :
102 : interface
103 : subroutine effpot_xml_readStrainCoupling(filename,natom,&
104 : & nrpt,voigt,elastic3rd,elastic_displacement,&
105 : & strain_coupling,phonon_strain_atmfrc,phonon_straincell)&
106 : & bind(C,name="effpot_xml_readStrainCoupling")
107 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_DOUBLE,C_INT
108 : integer(C_INT) :: natom
109 : integer(C_INT) :: nrpt,voigt
110 : integer(c_INT) :: phonon_straincell(3,nrpt)
111 : real(C_DOUBLE) :: elastic3rd(6,6),elastic_displacement(6,3,natom)
112 : real(C_DOUBLE) :: strain_coupling(3,natom)
113 : real(C_DOUBLE) :: phonon_strain_atmfrc(3,natom,3,natom,nrpt)
114 : character(kind=C_CHAR) :: filename(*)
115 : end subroutine effpot_xml_readStrainCoupling
116 : end interface
117 :
118 : interface
119 : subroutine effpot_xml_readCoeff(filename,ncoeff,ndisp,nterm,&
120 : & coefficient,atindx,cell,direction,power_disp,&
121 : & power_strain,strain,weight)&
122 : & bind(C,name="effpot_xml_readCoeff")
123 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_DOUBLE,C_INT
124 : character(kind=C_CHAR) :: filename(*)
125 : integer(C_INT) :: ncoeff,ndisp,nterm
126 : integer(C_INT) :: atindx(ncoeff,nterm,2,ndisp)
127 : integer(C_INT) :: cell(ncoeff,nterm,3,2,ndisp)
128 : integer(C_INT) :: direction(ncoeff,nterm,ndisp)
129 : integer(C_INT) :: strain(ncoeff,nterm,ndisp)
130 : integer(C_INT) :: power_disp(ncoeff,nterm,ndisp)
131 : integer(C_INT) :: power_strain(ncoeff,nterm,ndisp)
132 : real(C_DOUBLE) :: coefficient(ncoeff)
133 : real(C_DOUBLE) :: weight(ncoeff,nterm)
134 : end subroutine effpot_xml_readCoeff
135 : end interface
136 :
137 : interface
138 : subroutine effpot_xml_getDimSystem(filename,natom,ntypat,nqpt,nrpt1,nrpt2)&
139 : & bind(C,name="effpot_xml_getDimSystem")
140 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_INT
141 : integer(C_INT) :: natom,ntypat,nqpt,nrpt1,nrpt2
142 : character(kind=C_CHAR) :: filename(*)
143 : end subroutine effpot_xml_getDimSystem
144 : end interface
145 :
146 : interface
147 : subroutine effpot_xml_getDimStrainCoupling(filename,nrpt,voigt)&
148 : & bind(C,name="effpot_xml_getDimStrainCoupling")
149 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_INT
150 : integer(C_INT) :: voigt
151 : integer(C_INT) :: nrpt
152 : character(kind=C_CHAR) :: filename(*)
153 : end subroutine effpot_xml_getDimStrainCoupling
154 : end interface
155 :
156 : interface
157 : subroutine effpot_xml_getDimCoeff(filename,ncoeff,nterm_max,ndisp_max)&
158 : & bind(C,name="effpot_xml_getDimCoeff")
159 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_DOUBLE,C_INT,C_PTR
160 : character(kind=C_CHAR) :: filename(*)
161 : ! character(kind=C_CHAR) :: name(*)
162 : type(C_PTR) :: name
163 : integer(C_INT) :: ncoeff,ndisp_max,nterm_max
164 : end subroutine effpot_xml_getDimCoeff
165 : end interface
166 :
167 :
168 : interface
169 : subroutine effpot_xml_checkXML(filename,name_root) &
170 : & bind(C,name="effpot_xml_checkXML")
171 : use, intrinsic :: iso_c_binding, only : C_CHAR
172 : character(kind=C_CHAR) :: filename(*),name_root(*)
173 : end subroutine effpot_xml_checkXML
174 : end interface
175 :
176 : interface
177 : subroutine effpot_xml_getValue(filename,name_value,value_result) &
178 : & bind(C,name="effpot_xml_getValue")
179 : use, intrinsic :: iso_c_binding, only : C_CHAR
180 : character(kind=C_CHAR) :: filename(*),name_value(*)
181 : character(kind=C_CHAR) :: value_result
182 : end subroutine effpot_xml_getValue
183 : end interface
184 :
185 : interface
186 : subroutine effpot_xml_getAttribute(filename,name_value,name_attribute) &
187 : & bind(C,name="effpot_xml_getAttribute")
188 : use, intrinsic :: iso_c_binding, only : C_CHAR
189 : character(kind=C_CHAR) :: filename(*),name_value(*),name_attribute(*)
190 : end subroutine effpot_xml_getAttribute
191 : end interface
192 :
193 : interface
194 : subroutine effpot_xml_getNumberKey(filename,name_value,number) &
195 : & bind(C,name="effpot_xml_getNumberKey")
196 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_INT
197 : character(kind=C_CHAR) :: filename(*),name_value(*)
198 : integer(C_INT) :: number
199 : end subroutine effpot_xml_getNumberKey
200 : end interface
201 :
202 : #endif
203 :
204 : integer,parameter :: XML_RECL = 50000
205 : !!***
206 :
207 : CONTAINS !===========================================================================================
208 :
209 :
210 : !****f* m_effective_potential_file/effective_potential_file_read
211 : !!
212 : !! NAME
213 : !! effective_potential_file_read
214 : !!
215 : !! FUNCTION
216 : !! tranfert file (XML or DDB) in effective potential type
217 : !! Also transfert coefficient from xml file for ahnarmonic part
218 : !!
219 : !! INPUTS
220 : !! filename = path of the file
221 : !! hist<type(abihist)> = optional,The history of the MD (or snapshot of DFT)
222 : !! inp<type(multibinit_dtset_type)> = optional,datatype with all the input variables (mantadory to
223 : !! read DDB file)
224 : !! comm=MPI communicator
225 : !!
226 : !! OUTPUT
227 : !! eff_pot<type(effective_potential_type)> = datatype with all the information for effective potential
228 : !!
229 : !! SOURCE
230 :
231 91 : subroutine effective_potential_file_read(filename,eff_pot,inp,comm,hist)
232 :
233 : use m_multibinit_dataset
234 : use m_strain
235 : use m_crystal, only : crystal_t
236 : use m_dynmat, only : bigbx9
237 :
238 : !Arguments ------------------------------------
239 : !scalars
240 : integer,intent(in) :: comm
241 : character(len=fnlen),intent(in) :: filename
242 : !array
243 : type(effective_potential_type), intent(inout) :: eff_pot
244 : type(multibinit_dtset_type),optional,intent(in) :: inp
245 91 : type(ddb_type) :: ddb
246 4732 : type(crystal_t) :: Crystal
247 : type(abihist),optional :: hist
248 : !Local variables------------------------------
249 : !scalars
250 : integer :: ii,filetype,natom,ntypat,nqpt,nrpt
251 : character(500) :: message
252 4732 : type(ddb_hdr_type) :: ddb_hdr
253 : ! *************************************************************************
254 :
255 91 : call effective_potential_file_getType(filename,filetype)
256 :
257 91 : if (filetype/=0) then
258 :
259 91 : if (.not.(present(inp))) then
260 : write(message, '(4a)' )&
261 0 : & ' effective_potential_file_read: you need to give input file to compute ',&
262 0 : & 'the response fonction from DDB file ',ch10
263 0 : ABI_ERROR(message)
264 : end if
265 :
266 91 : if(filetype ==1) then
267 : ! Read the DDB information, also perform some checks, and symmetrize partially the DDB
268 29 : write(message, '(3a)' )' Read the DDB information of the reference',&
269 58 : & ' system and perform some checks',ch10
270 29 : call wrtout(std_out,message,'COLL')
271 29 : call wrtout(ab_out,message,'COLL')
272 :
273 29 : call effective_potential_file_getDimSystem(filename,comm,natom,ntypat,nqpt,nrpt)!
274 :
275 29 : call ddb%from_file(filename,ddb_hdr,Crystal,comm)
276 29 : call ddb_hdr%free()
277 :
278 29 : call ddb%set_brav(inp%brav)
279 :
280 : ! Transfert the ddb to the effective potential
281 29 : call system_ddb2effpot(Crystal,ddb,eff_pot,inp,comm)
282 :
283 : ! Free memory
284 29 : call ddb%free()
285 29 : call Crystal%free()
286 :
287 : ! Generate long rage interation for the effective potential for both type and generate supercell
288 29 : call effective_potential_generateDipDip(eff_pot,inp%dipdip_range,inp%dipdip,inp%asr,comm)
289 :
290 : ! If needed, print the effective potential into the output
291 29 : if (inp%prt_model>=3.or.inp%prt_model==-1) then
292 8 : call effective_potential_print(eff_pot,-1)
293 : end if
294 : end if
295 91 : if (filetype==2 .or.filetype==23) then ! xml file
296 :
297 : ! Free the effective potential before
298 38 : call effective_potential_free(eff_pot)
299 :
300 38 : call system_xml2effpot(eff_pot,filename,comm,strcpling=inp%strcpling)
301 :
302 :
303 : ! Assign the energy of the reference from input
304 38 : if(abs(inp%energy_reference)>tol16)then
305 0 : write(message,'(11a)') ch10,&
306 0 : & ' --- !WARNING',ch10,&
307 0 : & ' Energy of the reference structure is specify in ',ch10,&
308 0 : & ' the input file. The energy is set with',ch10,&
309 0 : & ' this value.',ch10,&
310 0 : & ' ---',ch10
311 0 : call wrtout(std_out,message,'COLL')
312 0 : eff_pot%energy = inp%energy_reference
313 : end if
314 :
315 :
316 : ! Generate long rage interation for the effective potential for both type and generate supercell
317 38 : call effective_potential_generateDipDip(eff_pot,inp%dipdip_range,inp%dipdip,inp%asr,comm,1)
318 :
319 : ! If needed, print the effective potential
320 38 : call effective_potential_print(eff_pot,inp%prt_model)
321 : end if
322 91 : if (filetype==3 .or. filetype==23) then
323 : ! Read the coefficient of the fit for the anharmonic part
324 28 : write(message, '(4a)' )ch10,' Read the coefficients of the polynomial fit from XML',&
325 56 : & ' and perform some checks',ch10
326 28 : call wrtout(std_out,message,'COLL')
327 28 : call wrtout(ab_out,message,'COLL')
328 :
329 28 : if(eff_pot%anharmonics_terms%ncoeff/=0)then
330 0 : write(message,'(9a)') ch10,&
331 0 : & ' --- !WARNING',ch10,&
332 0 : & ' There is already fitted polynome set in the model',ch10,&
333 0 : & ' The previous coefficients will be remove',ch10,&
334 0 : & ' ---',ch10
335 0 : call wrtout(std_out,message,'COLL')
336 : end if
337 :
338 28 : call coeffs_xml2effpot(eff_pot,filename,comm)
339 :
340 : ! Assign the coeff number from input
341 28 : if(inp%ncoeff==0)then
342 20 : write(message,'(12a)') ch10,&
343 20 : & ' --- !WARNING',ch10,&
344 20 : & ' The values of the coefficients are set to 0',&
345 20 : & ' in the input file.',ch10,&
346 20 : & ' The values of the coefficients will be read in the XML',ch10,&
347 20 : & ' or might be fitted',ch10,&
348 40 : & ' ---',ch10
349 20 : call wrtout(std_out,message,'COLL')
350 20 : if(inp%fit_coeff <= 0 .and. &
351 : & all(abs(eff_pot%anharmonics_terms%coefficients(:)%coefficient) <tol16)) then
352 :
353 0 : write(message,'(12a)') ch10,&
354 0 : & ' --- !WARNING',ch10,&
355 0 : & ' The input for the fit process is set to 0 or -1',&
356 0 : & ' in the input file.',ch10,&
357 0 : & ' However, the values of the coefficients in the XMF files are zero,',ch10,&
358 0 : & ' So the coefficients can not be used',ch10,&
359 0 : & ' ---',ch10
360 0 : call wrtout(std_out,message,'COLL')
361 :
362 : end if
363 : else
364 8 : if (eff_pot%anharmonics_terms%ncoeff /= inp%ncoeff)then
365 : write(message, '(5a)' )&
366 0 : & ' The number of coefficients in the XML file is superior to the ',ch10,&
367 0 : & 'number of coefficients in the input ',ch10,&
368 0 : & 'Action: correct your input file or change the file'
369 0 : ABI_ERROR(message)
370 : end if
371 40 : do ii = 1,eff_pot%anharmonics_terms%ncoeff
372 : call polynomial_coeff_setCoefficient(inp%coefficients(ii),&
373 40 : & eff_pot%anharmonics_terms%coefficients(ii))
374 : end do
375 : end if
376 :
377 63 : else if(filetype==4) then
378 0 : if(present(hist))then
379 0 : write(message,'(5a)')ch10,&
380 0 : & '-Reading the file ',trim(filename),ch10,&
381 0 : & ' with NetCDF in order to fit the polynomial coefficients'
382 0 : call wrtout(std_out,message,'COLL')
383 0 : call wrtout(ab_out,message,'COLL')
384 0 : call effective_potential_file_readMDfile(filename,hist,option=inp%ts_option)
385 : else
386 : write(message, '(3a)' )&
387 0 : & 'There is no hist argument ',ch10,&
388 0 : & 'Action: add hist argument'
389 0 : ABI_ERROR(message)
390 : end if
391 : end if
392 : else
393 : write(message, '(5a)' )&
394 0 : & ' The file ',trim(filename),' is not readable with Multibinit',ch10,&
395 0 : & ' Action: Change the file.'
396 0 : ABI_BUG(message)
397 : end if
398 :
399 91 : end subroutine effective_potential_file_read
400 : !!***
401 :
402 : !!****f* m_effective_potential_file/effective_potential_file_getType
403 : !!
404 : !! NAME
405 : !! effective_potential_file_getType
406 : !!
407 : !! FUNCTION
408 : !! This routine test the xml or ddb file
409 : !!
410 : !! INPUTS
411 : !! filename = names of the files
412 : !!
413 : !! OUTPUT
414 : !! type_file = 0 no type found
415 : !! 1 DDB file
416 : !! 2 XML file the system definition and harmonic part
417 : !! 3 XML file with polynomial coefficients
418 : !! 23 XML file with both system definition and polynomial coefficients
419 : !! 40 NetCDF file with history of MD or snapshot
420 : !! 41 ASCII file with history of MD or snapshot
421 : !!
422 : !! SOURCE
423 :
424 290 : subroutine effective_potential_file_getType(filename,filetype)
425 :
426 : !Arguments ------------------------------------
427 : !scalars
428 : character(len=fnlen),intent(in) :: filename
429 : integer, intent(out) :: filetype
430 : !arrays
431 : !Local variables-------------------------------
432 : !scalar
433 : integer :: natom,nstep
434 : integer :: ddbun = 666,ios=0
435 : character(len=500) :: message
436 : character (len=1000) :: line,readline
437 : integer :: natom_id,time_id,xyz_id,six_id,ddb_version
438 : integer :: ncid,ncerr
439 : logical :: md_file
440 : ! *************************************************************************
441 :
442 290 : filetype = 0
443 :
444 290 : ddbun = get_unit()
445 :
446 290 : if (open_file(filename,message,unit=ddbun,form="formatted",status="old",action="read") /= 0) then
447 0 : ABI_ERROR(message)
448 : end if
449 :
450 : !Check if the file is a XML file or a DDB and in this case, store the DDB code.
451 290 : ios = 0
452 26199 : do while ((ios==0))
453 25909 : read(ddbun,'(a)',iostat=ios) readline
454 25909 : call rmtabfromline(readline)
455 25909 : line=adjustl(readline)
456 26199 : if(line(3:13)=="xml version") then
457 380 : do while ((ios==0))
458 190 : read(ddbun,'(a)',iostat=ios) readline
459 190 : call rmtabfromline(readline)
460 190 : line=adjustl(readline)
461 190 : if(line(1:16)==char(60)//"Heff_definition".or.&
462 : & line(1:17)==char(60)//"Terms_definition")then
463 72 : filetype = 3
464 72 : ios = -1
465 : end if
466 380 : if(line(1:18)==char(60)//"System_definition") then
467 118 : filetype = 2
468 183318 : do while ((ios==0))
469 183200 : read(ddbun,'(a)',iostat=ios) readline
470 183200 : call rmtabfromline(readline)
471 183200 : line=adjustl(readline)
472 183200 : if(line(1:16)==char(60)//"Heff_definition".or.&
473 118 : & line(1:17)==char(60)//"Terms_definition")then
474 16 : filetype = 23
475 16 : ios = -1
476 : end if
477 : end do
478 : end if
479 : end do
480 25719 : else if(line(6:24)=="DERIVATIVE DATABASE") then
481 87 : filetype = 1
482 87 : ios = -1
483 : end if
484 : end do
485 290 : close(ddbun)
486 :
487 303 : if(filetype/=0) return
488 :
489 : !try to read netcdf HIST file
490 13 : ncerr=nf90_open(path=trim(filename),mode=NF90_NOWRITE,ncid=ncid)
491 13 : if(ncerr == NF90_NOERR) then
492 13 : md_file = .TRUE.
493 13 : ncerr = nf90_inq_dimid(ncid,"natom",natom_id)
494 13 : if(ncerr /= NF90_NOERR) md_file = .FALSE.
495 13 : ncerr = nf90_inq_dimid(ncid,"xyz",xyz_id)
496 13 : if(ncerr /= NF90_NOERR) md_file = .FALSE.
497 13 : ncerr = nf90_inq_dimid(ncid,"time",time_id)
498 13 : if(ncerr /= NF90_NOERR) md_file = .FALSE.
499 13 : ncerr = nf90_inq_dimid(ncid,"six",six_id)
500 13 : if(ncerr /= NF90_NOERR) md_file = .FALSE.
501 13 : if (md_file) then
502 13 : filetype = 40
503 13 : return
504 : end if
505 : end if
506 0 : ncerr = nf90_close(ncid)
507 :
508 0 : if(filetype/=0) return
509 :
510 : ! Try to read netcdf DDB file
511 0 : ncerr=nf90_open(path=trim(filename),mode=NF90_NOWRITE,ncid=ncid)
512 0 : if(ncerr==NF90_NOERR) then
513 0 : ncerr = nf90_get_var(ncid, nctk_idname(ncid, 'ddb_version'), ddb_version)
514 0 : if (ncerr==NF90_NOERR) then
515 0 : filetype = 1
516 0 : return
517 : end if
518 : end if
519 :
520 : !Try to get the dim of MD ASCII file
521 0 : call effective_potential_file_getDimMD(filename,natom,nstep)
522 0 : if(natom /= 0 .and. nstep/=0) filetype = 41
523 :
524 91 : end subroutine effective_potential_file_getType
525 : !!***
526 :
527 : !!****f* m_effective_potential_file/effective_potential_file_getDimSystem
528 : !!
529 : !! NAME
530 : !! effective_potential_file_getDimSystem
531 : !!
532 : !! FUNCTION
533 : !! This routine test the xml or ddb file
534 : !! Return the number of atoms/ntypat in the unit cell from ddb and xml
535 : !! Return natom/ntypat/nqpt and nrpt if the file is XML file
536 : !! In case of DDB file, you have to run bigbx9 to get nrpt
537 : !!
538 : !! INPUTS
539 : !! filename = names of the files
540 : !! comm = MPI communicator
541 : !!
542 : !! OUTPUT
543 : !! natom = number of atoms
544 : !! ntypat= number of type of atoms
545 : !! nqpt = number of q points
546 : !! nrpt = number of rpt points
547 : !!
548 : !! SOURCE
549 :
550 134 : subroutine effective_potential_file_getDimSystem(filename,comm,natom,ntypat,nqpt,nrpt)
551 :
552 : !Arguments ------------------------------------
553 : !scalars
554 : character(len=fnlen),intent(in) :: filename
555 : integer,intent(out) :: natom,ntypat,nqpt,nrpt
556 : integer,intent(in) :: comm
557 : !arrays
558 :
559 : !Local variables-------------------------------
560 : !scalar
561 : integer :: filetype
562 : ! integer :: dimekb,lmnmax,mband,mtyp,msym,nblok,nkpt,usepaw
563 : character(len=500) :: message
564 6968 : type(ddb_hdr_type) :: ddb_hdr
565 : ! *************************************************************************
566 :
567 134 : natom = 0
568 134 : ntypat= 0
569 134 : nqpt = 0
570 134 : nrpt = 0
571 :
572 134 : call effective_potential_file_getType(filename,filetype)
573 :
574 134 : if(filetype==1)then
575 58 : write(message, '(6a)' )ch10,' The file ',trim(filename),ch10,&
576 116 : & ' is DDB file (extraction of the number of atoms)',ch10
577 58 : call wrtout(std_out,message,'COLL')
578 :
579 : write(message, '(8a)' )&
580 58 : & ' The file ',trim(filename),ch10,' is ddb file only the number of atoms is read,',&
581 116 : & 'if you want to predic the number of cell (nrpt)',ch10,' use bigbx9 routines',ch10
582 58 : call wrtout(std_out,message,'COLL')
583 :
584 58 : call ddb_hdr%open_read(filename,comm,dimonly=1)
585 58 : natom = ddb_hdr%natom
586 58 : ntypat = ddb_hdr%ntypat
587 58 : call ddb_hdr%free()
588 :
589 : ! Must read some value to initialze array (nprt for ifc)
590 : ! call bigbx9(inp%brav,dummy_cell,0,1,inp%ngqpt,inp%nqshft,nrpt,ddb%rprim,dummy_rpt)
591 :
592 76 : else if (filetype==2 .or. filetype==23) then
593 76 : write(message, '(5a)' )ch10,' The file ',trim(filename),&
594 152 : & ' is XML file (extraction of all information)'
595 76 : call wrtout(std_out,message,'COLL')
596 :
597 76 : call system_getDimFromXML(filename,natom,ntypat,nqpt,nrpt)
598 :
599 : else
600 : write(message, '(a,a,a,a)' )&
601 0 : & ' The file ',trim(filename),' is not compatible with multibinit',ch10
602 0 : ABI_ERROR(message)
603 : end if
604 :
605 : ! TODO hexu: temporarily disabled. Discuss with alex how to do this properly.
606 : ! Do some checks
607 : ! if (natom < 1) then
608 : ! write(message, '(a,a,a,a,a)' )&
609 : !& ' Unable to read the number of atom from ',trim(filename),ch10,&
610 : !& 'This file is not compatible with multibinit',ch10
611 : ! ABI_ERROR(message)
612 : ! end if
613 : !
614 : ! if (filetype==2 .or. filetype==23) then
615 : !
616 : ! if (natom < 1) then
617 : ! write(message, '(a,a,a)' )&
618 : !& ' Unable to read the number of atom from ',trim(filename),ch10
619 : ! ABI_ERROR(message)
620 : ! end if
621 : !
622 : ! if (nrpt < 1) then
623 : ! write(message, '(a,a,a)' )&
624 : !& ' Unable to read the number of rpt points ',trim(filename),ch10
625 : ! ABI_ERROR(message)
626 : ! end if
627 : !
628 : ! if (ntypat < 1) then
629 : ! write(message, '(a,a,a)' )&
630 : !& ' Unable to read the number of type of atoms ',trim(filename),ch10
631 : ! ABI_ERROR(message)
632 : ! end if
633 : !
634 : ! end if
635 :
636 134 : end subroutine effective_potential_file_getDimSystem
637 : !!***
638 :
639 : !!****f* m_effective_potential_file/effective_potential_file_getDimCoeff
640 : !!
641 : !! NAME
642 : !! effective_potential_file_getDimCoeff
643 : !!
644 : !! FUNCTION
645 : !! This routine test the xml with polynomial coefficients
646 : !! Return the number of coefficients and the maximum number of displacement/strain
647 : !!
648 : !! INPUTS
649 : !! filename = names of the files
650 : !!
651 : !! OUTPUT
652 : !! ncoeff = number of coefficient for the polynome
653 : !! nterm(ncoeff) = number terms per coefficient
654 : !! ndisp(nterm,ncoeff) = number displacement per term
655 : !!
656 : !! SOURCE
657 :
658 28 : subroutine effective_potential_file_getDimCoeff(filename,ncoeff,ndisp_max,nterm_max)
659 :
660 : !Arguments ------------------------------------
661 : !scalars
662 : character(len=fnlen),intent(in) :: filename
663 : integer,intent(out) :: ncoeff,ndisp_max,nterm_max
664 : !Local variables-------------------------------
665 : !scalar
666 : integer :: filetype
667 : #ifndef HAVE_XML
668 : integer :: count,count2
669 : integer :: funit = 1,ios=0
670 : logical :: found,found2
671 : #endif
672 : !arrays
673 : #ifndef HAVE_XML
674 : character (len=XML_RECL) :: line,readline
675 : #endif
676 : character(len=500) :: message
677 : ! *************************************************************************
678 :
679 28 : call effective_potential_file_getType(filename,filetype)
680 :
681 28 : if (filetype==3 .or. filetype==23) then
682 28 : write(message, '(2a)' )' Extraction of the number of coefficient in the XML ',&
683 56 : & trim(filename)
684 28 : call wrtout(std_out,message,'COLL')
685 :
686 28 : ncoeff = 0
687 28 : nterm_max = 0
688 28 : ndisp_max = 0
689 :
690 : #if defined HAVE_XML
691 : ! Read with libxml the number of coefficient
692 : call effpot_xml_getDimCoeff(char_f2c(trim(filename)),ncoeff,nterm_max,ndisp_max)
693 : #else
694 : ! Read by hand
695 : ! Start a reading loop
696 28 : found=.false.
697 : ncoeff = 0
698 :
699 28 : if (open_file(filename,message,unit=funit,form="formatted",status="old",&
700 : & action="read") /= 0) then
701 0 : ABI_ERROR(message)
702 : end if
703 :
704 : ! First parse to know the number of coefficients
705 28 : ios = 0
706 5038 : do while (ios == 0)
707 5010 : read(funit,'(a)',iostat=ios) readline
708 5038 : if(ios == 0)then
709 4982 : call rmtabfromline(readline)
710 4982 : line=adjustl(readline)
711 : ! Need test with char(9) because the old version of XML file
712 : ! from old script includes tarbulation at the begining of each line
713 4982 : if (line(1:12)==char(60)//'coefficient') then
714 1802 : ncoeff=ncoeff+1
715 1802 : count = 0
716 1802 : found = .false.
717 : do while(.not.found)
718 49004 : read(funit,'(a)',iostat=ios) readline
719 49004 : call rmtabfromline(readline)
720 49004 : line=adjustl(readline)
721 49004 : if (line(1:5)==char(60)//'term') then
722 47202 : count = count +1
723 47202 : found2 = .false.
724 47202 : count2 = 0
725 : do while(.not.found2)
726 501636 : read(funit,'(a)',iostat=ios) readline
727 501636 : call rmtabfromline(readline)
728 501636 : line=adjustl(readline)
729 501636 : if (line(1:13)==char(60)//'displacement') then
730 109854 : count2 = count2 + 1
731 391782 : else if (line(1:7)==char(60)//'strain') then
732 15018 : count2 = count2 + 1
733 376764 : else if (line(1:6)==char(60)//'/term') then
734 47202 : if (count2 > ndisp_max) ndisp_max = count2
735 : found2 = .true.
736 : else
737 329562 : cycle
738 : end if
739 : end do
740 1802 : else if (line(1:13)==char(60)//'/coefficient') then
741 1802 : if (count > nterm_max) nterm_max = count
742 : found = .true.
743 : else
744 0 : cycle
745 : end if
746 : end do
747 : cycle
748 : end if
749 : end if
750 : end do
751 :
752 28 : close(funit)
753 : #endif
754 :
755 : else
756 : ! Maybe one day add an other type of file...
757 : write(message, '(a,a,a,a)' )&
758 0 : & ' The file ',trim(filename),' is not compatible with multibinit',ch10
759 0 : ABI_ERROR(message)
760 : end if
761 :
762 : ! Do some checks
763 28 : if (ncoeff < 1) then
764 : write(message, '(5a)' )&
765 0 : & ' Unable to read the number of coeff from ',trim(filename),ch10,&
766 0 : & ' This file is not compatible with multibinit',ch10
767 0 : ABI_ERROR(message)
768 : end if
769 :
770 28 : end subroutine effective_potential_file_getDimCoeff
771 : !!***
772 :
773 :
774 : !!****f* m_effective_potential_file/effective_potential_file_getDimStrainCoupling
775 : !!
776 : !! NAME
777 : !! effective_potential_file_getDimStrainCoupling
778 : !!
779 : !! FUNCTION
780 : !! Return the number of nrpt for specific strain coupling from xml system file
781 : !!
782 : !! INPUTS
783 : !! filename = names of the files
784 : !! voigt = voigt notation of the strain
785 : !!
786 : !! OUTPUT
787 : !! nrpt = number of rpt points
788 : !!
789 : !! SOURCE
790 :
791 228 : subroutine effective_potential_file_getDimStrainCoupling(filename,nrpt,voigt)
792 :
793 : !Arguments ------------------------------------
794 : !scalars
795 : character(len=fnlen),intent(in) :: filename
796 : integer,intent(in) :: voigt
797 : integer,intent(out) :: nrpt
798 : !Local variables-------------------------------
799 : !scalar
800 : #ifndef HAVE_XML
801 : integer :: irpt,ivoigt
802 : integer :: funit = 1,ios=0
803 : logical :: found
804 : #endif
805 : !arrays
806 : #ifndef HAVE_XML
807 : character (len=XML_RECL) :: line,readline,strg,strg1
808 : character(len=500) :: message
809 : #endif
810 : ! *************************************************************************
811 :
812 228 : nrpt = 0
813 :
814 : #if defined HAVE_XML
815 : ! Read with libxml the number of coefficient
816 : call effpot_xml_getDimStrainCoupling(char_f2c(trim(filename)),nrpt,voigt)
817 : #else
818 : ! Read by hand
819 : ! Start a reading loop
820 228 : found=.false.
821 :
822 228 : if (open_file(filename,message,unit=funit,form="formatted",status="old",&
823 : & action="read") /= 0) then
824 0 : ABI_ERROR(message)
825 : end if
826 :
827 : ! First parse to know the number of atoms
828 349458 : do while (ios == 0.and.(.not.found))
829 349230 : read(funit,'(a)',iostat=ios) readline
830 349458 : if(ios == 0)then
831 349230 : call rmtabfromline(readline)
832 349230 : line=adjustl(readline)
833 349230 : if ((line(1:16)=='<strain_coupling')) then
834 798 : read(funit,'(a)',iostat=ios) readline
835 798 : call rdfromline("voigt",line,strg)
836 798 : strg1=trim(strg)
837 798 : read(strg1,*) ivoigt
838 798 : if (ivoigt == voigt)then
839 : irpt = 0
840 : do while (.not.found)
841 2592 : read(funit,'(a)',iostat=ios) readline
842 2592 : call rmtabfromline(readline)
843 2592 : line=adjustl(readline)
844 2592 : if ((line(1:26)=='<correction_force_constant')) then
845 0 : irpt = irpt + 1
846 0 : cycle
847 : end if
848 2592 : if ((line(1:17)=='</strain_coupling')) then
849 228 : found = .TRUE.
850 228 : nrpt = irpt
851 : cycle
852 : end if
853 : end do
854 : else
855 : cycle
856 : end if
857 : end if
858 : end if
859 : end do
860 :
861 228 : close(funit)
862 : #endif
863 :
864 228 : end subroutine effective_potential_file_getDimStrainCoupling
865 : !!***
866 :
867 : !!****f* m_effective_potential_file/effective_potential_file_getDimMD
868 : !!
869 : !! NAME
870 : !! effective_potential_file_getDimMD
871 : !!
872 : !! FUNCTION
873 : !! Read MD FILE (HIST or ASCII) and return the dimensions
874 : !! (natom and nstep)
875 : !!
876 : !! INPUTS
877 : !! filename = path of the file
878 : !!
879 : !! OUTPUT
880 : !! natom = number of atoms
881 : !! nstep = number of MD steps
882 : !!
883 : !! SOURCE
884 :
885 0 : subroutine effective_potential_file_getDimMD(filename,natom,nstep)
886 :
887 : !Arguments ------------------------------------
888 : !scalars
889 : integer,intent(out) :: natom,nstep
890 : !arrays
891 : character(len=fnlen),intent(in) :: filename
892 : !Local variables-------------------------------
893 : !scalar
894 : integer :: ia,natm_old,natm_new
895 : integer :: nenergy,nrprimd
896 : integer :: ios=0,ios2=0,ios3=0
897 : integer :: unit_md=24
898 : logical :: compatible,netcdf
899 : integer :: natom_id,time_id,xyz_id,six_id
900 : integer :: ncid,ncerr
901 : character(len=5) :: char_tmp
902 : !arrays
903 : character (len=10000) :: readline,line
904 : character(len=500) :: msg
905 : ! *************************************************************************
906 :
907 0 : natom = 0
908 0 : nstep = 0
909 : !try to read netcdf
910 0 : netcdf = .false.
911 0 : ncerr=nf90_open(path=trim(filename),mode=NF90_NOWRITE,ncid=ncid)
912 0 : if(ncerr == NF90_NOERR) then
913 0 : netcdf = .TRUE.
914 0 : ncerr = nf90_inq_dimid(ncid,"natom",natom_id)
915 0 : if(ncerr /= NF90_NOERR) netcdf = .FALSE.
916 0 : ncerr = nf90_inq_dimid(ncid,"xyz",xyz_id)
917 0 : if(ncerr /= NF90_NOERR) netcdf = .FALSE.
918 0 : ncerr = nf90_inq_dimid(ncid,"time",time_id)
919 0 : if(ncerr /= NF90_NOERR) netcdf = .FALSE.
920 0 : ncerr = nf90_inq_dimid(ncid,"six",six_id)
921 0 : if(ncerr /= NF90_NOERR) netcdf = .FALSE.
922 0 : if(netcdf)then
923 0 : ncerr = nf90_inquire_dimension(ncid,natom_id,char_tmp,natom)
924 0 : NCF_CHECK_MSG(ncerr," inquire dimension ID for natom")
925 0 : ncerr = nf90_inquire_dimension(ncid,time_id,char_tmp,nstep)
926 0 : NCF_CHECK_MSG(ncerr," inquire dimension ID for time")
927 : end if
928 : end if
929 :
930 0 : if(.not.netcdf) then
931 : ! try to read ASCII file...
932 0 : if (open_file(filename,msg,unit=unit_md,form="formatted",&
933 : & status="old",action="read") /= 0) then
934 0 : ABI_ERROR(msg)
935 : end if
936 :
937 : ! Start a reading loop in fortran to get the dimension of the file
938 0 : rewind(unit=unit_md)
939 0 : ios = 0
940 0 : nstep = 0
941 0 : nrprimd = 0
942 0 : natm_old= 0
943 0 : natm_new= 0
944 0 : nenergy = 0
945 0 : compatible = .TRUE.
946 :
947 0 : do while ((ios==0))
948 : ! special treatment of the first step
949 0 : if(nstep==0)then
950 0 : ios2 = 0
951 0 : do while ((ios2==0))
952 0 : read(unit_md,'(a)',iostat=ios) readline
953 0 : line=adjustl(readline)
954 0 : call elementfromline(line,ia)
955 0 : if (ia==1)then
956 0 : nstep = nstep + 1
957 0 : ios2 = 1
958 : end if
959 : end do
960 : end if
961 0 : read(unit_md,'(a)',iostat=ios) readline
962 0 : if(ios == 0)then
963 0 : line=adjustl(readline)
964 0 : call elementfromline(line,ia)
965 0 : if (ia==1)then
966 0 : nenergy = nenergy + 1
967 0 : nrprimd = 0
968 0 : else if(ia==3)then
969 0 : nrprimd = nrprimd + 1
970 : end if
971 0 : if(nrprimd == 3)then
972 0 : ios3 = 0
973 0 : natm_new = 0
974 0 : do while ((ios3==0))
975 0 : read(unit_md,'(a)',iostat=ios3) readline
976 0 : if(ios3==0)then
977 0 : line=adjustl(readline)
978 0 : call elementfromline(line,ia)
979 0 : if(ia==1)then
980 0 : if(nstep==1) then
981 : natm_old = natm_new
982 : else
983 0 : if(natm_old /= natm_new) compatible = .FALSE.
984 : end if
985 0 : ios3 = 1
986 0 : ios2 = 1
987 0 : nstep = nstep + 1
988 : end if
989 0 : if(ia==6)then
990 0 : natm_new = natm_new + 1
991 : end if
992 : end if!end if ios3
993 : end do
994 : end if ! end if nrprimd
995 : end if! end if os1
996 : end do
997 :
998 0 : natom = natm_new - 1
999 0 : if(nstep /= nenergy) compatible = .FALSE.
1000 0 : if(natom <= 0) compatible = .FALSE.
1001 0 : if(nstep <= 0) compatible = .FALSE.
1002 :
1003 0 : if(.not.compatible)then
1004 0 : natom = 0
1005 0 : nstep = 0
1006 : end if
1007 : end if! end if not netcdf
1008 :
1009 0 : end subroutine effective_potential_file_getDimMD
1010 : !!***
1011 :
1012 : !!****f* m_effective_potential_file/system_getDimFromXML
1013 : !! NAME
1014 : !! system_getDimFromXML
1015 : !!
1016 : !! FUNCTION
1017 : !! Open xml file of effective potentiel, then reads the variables that
1018 : !! must be known in order to dimension the arrays before complete reading
1019 : !!
1020 : !! INPUTS
1021 : !! character(len=*) filnam: name of input or output file
1022 : !!
1023 : !! OUTPUT
1024 : !! natom=number of atoms
1025 : !! ntypat=number of atom types
1026 : !! nrpt =number of real space points used to integrate IFC
1027 : ! nph1l =number of wavevectors for phonon
1028 : !!
1029 : !! SOURCE
1030 :
1031 76 : subroutine system_getDimFromXML(filename,natom,ntypat,nph1l,nrpt)
1032 :
1033 : !Arguments ------------------------------------
1034 : !scalars
1035 : character(len=fnlen),intent(in) :: filename
1036 : integer, intent(out) :: natom,ntypat,nph1l,nrpt
1037 : !arrays
1038 : !Local variables-------------------------------
1039 : !scalar
1040 : integer :: nrpt1,nrpt2
1041 : real :: itypat
1042 : character(len=500) :: message
1043 : #ifndef HAVE_XML
1044 : integer :: funit = 1,ios = 0
1045 : integer :: iatom
1046 : logical :: found
1047 : character (len=XML_RECL) :: line,readline
1048 : character (len=XML_RECL) :: strg,strg1
1049 : #endif
1050 : !arrays
1051 : #ifndef HAVE_XML
1052 76 : integer,allocatable :: typat(:)
1053 : #endif
1054 : ! *************************************************************************
1055 :
1056 : !Open the atomicdata XML file for reading
1057 76 : write(message,'(5a)') ' system_getDimFromXML :',&
1058 76 : & '-Opening the file ',trim(filename),' to read dimensions',&
1059 152 : & ' (before initialisation)'
1060 :
1061 76 : call wrtout(std_out,message,'COLL')
1062 :
1063 76 : natom = 0
1064 76 : ntypat= 0
1065 76 : nph1l = 0
1066 76 : nrpt = 0
1067 76 : nrpt1 = 0
1068 76 : nrpt2 = 0
1069 76 : itypat= 0
1070 :
1071 : !Open the atomicdata XML file for reading
1072 :
1073 : #if defined HAVE_XML
1074 : !Read with libxml
1075 : call effpot_xml_getDimSystem(char_f2c(trim(filename)),natom,ntypat,nph1l,nrpt1,nrpt2)
1076 : #else
1077 : !Read by hand
1078 :
1079 : !Start a reading loop
1080 76 : found=.false.
1081 :
1082 76 : if (open_file(filename,message,unit=funit,form="formatted",status="old",&
1083 : & action="read") /= 0) then
1084 0 : ABI_ERROR(message)
1085 : end if
1086 :
1087 : !First parse to know the number of atoms
1088 297112 : do while ((ios==0).and.(.not.found))
1089 297036 : read(funit,'(a)',iostat=ios) readline
1090 297112 : if(ios ==0)then
1091 296960 : call rmtabfromline(readline)
1092 296960 : line=adjustl(readline)
1093 :
1094 : !Need test with char(9) because the old version of XML file
1095 : !from old script includes tarbulation at the begining of each line
1096 296960 : if (line(1:5)==char(60)//'atom') then
1097 408 : natom=natom+1
1098 408 : cycle
1099 : end if
1100 :
1101 296552 : if (line(1:21)==char(60)//'local_force_constant') then
1102 2256 : nrpt1 = nrpt1+1
1103 2256 : cycle
1104 : end if
1105 :
1106 294296 : if (line(1:21)==char(60)//'total_force_constant') then
1107 2166 : nrpt2 = nrpt2+1
1108 2166 : cycle
1109 : end if
1110 :
1111 292130 : if (line(1:7)==char(60)//'qpoint') then
1112 284 : nph1l = nph1l+1
1113 284 : cycle
1114 : end if
1115 : end if
1116 : end do
1117 :
1118 : !second parse to get the number of typat
1119 228 : ABI_MALLOC(typat,(natom))
1120 484 : typat = 0
1121 76 : iatom = 0
1122 :
1123 76 : rewind(funit)
1124 : !Start a reading loop
1125 76 : ios = 0
1126 76 : found = .false.
1127 :
1128 5980 : do while ((ios==0).and.(.not.found))
1129 5904 : read(funit,'(a)',iostat=ios) readline
1130 5980 : if(ios == 0)then
1131 5904 : call rmtabfromline(readline)
1132 5904 : line=adjustl(readline)
1133 :
1134 5904 : if (line(1:5)==char(60)//'atom') then
1135 408 : iatom = iatom + 1
1136 408 : call rdfromline("mass",line,strg)
1137 408 : strg1=trim(strg)
1138 408 : read(unit=strg1,fmt=*) itypat
1139 2128 : if (.not.any(typat==int(itypat))) then
1140 196 : ntypat= ntypat+1
1141 : end if
1142 408 : typat(iatom) = int(itypat)
1143 : end if
1144 :
1145 5904 : if (line(1:6)==char(60)//'local') then
1146 76 : found=.true.
1147 : end if
1148 : end if
1149 : end do
1150 :
1151 76 : close(funit)
1152 76 : ABI_FREE(typat)
1153 :
1154 : #endif
1155 :
1156 : !Check the RPT
1157 76 : if (nrpt2/=nrpt1) then
1158 46 : if(nrpt1> 0 .and. nrpt2== 0) then
1159 : continue;
1160 32 : else if (nrpt1==0.and.nrpt2>=0) then
1161 0 : write(message, '(5a)' )ch10,&
1162 0 : & ' WARNING: the number of local IFC is set to 0 ',ch10,&
1163 0 : & ' Dipdip must be set to zero',ch10
1164 0 : call wrtout(std_out,message,'COLL')
1165 32 : else if (nrpt2 > nrpt1) then
1166 32 : write(message, '(2a,I0,3a,I0,5a)' )ch10,&
1167 32 : & ' WARNING: the number of total IFC (',nrpt2,') is not equal to the ',ch10,&
1168 32 : & ' the number of short range IFC (',nrpt1,') in ',trim(filename),ch10,&
1169 64 : & ' the missing ifc will be set to zero',ch10
1170 32 : call wrtout(std_out,message,'COLL')
1171 : else if(nrpt1>nrpt2)then
1172 0 : write(message, '(2a,I0,3a,I0,5a)' )ch10,&
1173 0 : & ' The number of total IFC (',nrpt2,') is inferior to ',ch10,&
1174 0 : & ' the number of short range IFC (',nrpt1,') in ',trim(filename),ch10,&
1175 0 : & ' This is not possible',ch10
1176 0 : ABI_BUG(message)
1177 : end if
1178 : end if
1179 :
1180 : !nrpt is the max between local and total:
1181 76 : nrpt = max(nrpt1,nrpt2)
1182 :
1183 :
1184 76 : end subroutine system_getDimFromXML
1185 : !!***
1186 :
1187 : !!****f* m_effective_potential_file/system_xml2effpot
1188 : !! NAME
1189 : !! system_xml2effpot
1190 : !!
1191 : !! FUNCTION
1192 : !! Open xml file of effective potentiel, then reads the variables
1193 : !! and store them in effective potentential type
1194 : !!
1195 : !! INPUTS
1196 : !! eff_pot<type(effective_potential_type)> = datatype with all the information for effective potential
1197 : !! comm=MPI communicator
1198 : !! character(len=*) filnam: name of input or output file
1199 : !! strcpling = optional,logical to disable the strcpling
1200 : !!
1201 : !! OUTPUT
1202 : !! eff_pot<type(effective_potential_type)> = datatype with all the information for effective potential
1203 : !!
1204 : !! SOURCE
1205 :
1206 38 : subroutine system_xml2effpot(eff_pot,filename,comm,strcpling)
1207 :
1208 : use m_atomdata
1209 : use m_multibinit_dataset, only : multibinit_dtset_type
1210 : use m_ab7_symmetry
1211 :
1212 : !Arguments ------------------------------------
1213 : !scalars
1214 : character(len=*),intent(in) :: filename
1215 : integer, intent(in) :: comm
1216 : integer, optional,intent(in) :: strcpling
1217 : !arrays
1218 : type(effective_potential_type), intent(inout) :: eff_pot
1219 :
1220 : !Local variables-------------------------------
1221 : !scalar
1222 : integer :: ierr,ii,itypat,my_rank,msym,natom,ncoeff,nrpt,nrpt_scoupling
1223 : integer :: ntypat,nph1l,nptsym,npsp,nproc,nsym,space_group,timrev,use_inversion,voigt
1224 : real(dp):: energy,tolsym,ucvol
1225 : character(len=500) :: message
1226 : integer,parameter :: master=0
1227 : logical :: has_anharmonics
1228 : logical :: iam_master
1229 : #ifndef HAVE_XML
1230 : integer :: funit = 1,ios=0
1231 : integer :: iatom,iamu,iph1l,irpt,irpt1,irpt2,irpt3,jj,mu,nu
1232 : real(dp):: amu
1233 : logical :: found,found2,short_range,total_range
1234 : character (len=XML_RECL) :: line,readline
1235 : character (len=XML_RECL) :: strg,strg1
1236 : logical :: has_straincoupling
1237 : #endif
1238 : !arrays
1239 : integer :: bravais(11)
1240 38 : integer,allocatable :: typat(:)
1241 38 : integer,allocatable :: symrel(:,:,:),symafm(:),ptsymrel(:,:,:)
1242 : real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3),rprimd(3,3)
1243 : real(dp) :: elastic_constants(6,6),elastic3rd(6,6,6),epsilon_inf(3,3)
1244 38 : real(dp),allocatable :: all_amu(:),cell_local(:,:),cell_total(:,:)
1245 38 : real(dp),allocatable :: elastic_displacement(:,:,:,:),dynmat(:,:,:,:,:,:)
1246 38 : real(dp),allocatable :: local_atmfrc(:,:,:,:,:),total_atmfrc(:,:,:,:,:)
1247 38 : real(dp),allocatable :: spinat(:,:),strain_coupling(:,:,:),phfrq(:,:),qph1l(:,:),tnons(:,:)
1248 38 : real(dp),allocatable :: xcart(:,:),xred(:,:),zeff(:,:,:),znucl(:),zion(:)
1249 38 : character(len=132),allocatable :: title(:)
1250 228 : type(ifc_type) :: ifcs
1251 38 : type(ifc_type),dimension(:),allocatable :: phonon_strain
1252 1976 : type(crystal_t) :: crystal
1253 : type(atomdata_t) :: atom
1254 : #ifdef HAVE_XML
1255 : real(dp),allocatable :: phonon_strain_atmfrc(:,:,:,:,:)
1256 : integer,allocatable :: phonon_straincell(:,:)
1257 : #endif
1258 : #ifndef HAVE_XML
1259 38 : real(dp),allocatable :: work2(:,:)
1260 : #endif
1261 : ! *************************************************************************
1262 :
1263 : !Open the atomicdata XML file for reading
1264 38 : write(message,'(a,a)')'-Opening the file ',trim(filename)
1265 :
1266 38 : call wrtout(ab_out,message,'COLL')
1267 38 : call wrtout(std_out,message,'COLL')
1268 :
1269 38 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1270 38 : iam_master = (my_rank == master)
1271 :
1272 : !Get Dimention of system and allocation/initialisation of array
1273 38 : call effective_potential_file_getDimSystem(filename,comm,natom,ntypat,nph1l,nrpt)
1274 38 : gmet= zero; gprimd = zero; rmet = zero; rprimd = zero
1275 38 : elastic_constants = zero; epsilon_inf = zero; ncoeff = 0
1276 114 : ABI_MALLOC(all_amu,(ntypat))
1277 114 : ABI_MALLOC(cell_local,(3,nrpt))
1278 76 : ABI_MALLOC(cell_total,(3,nrpt))
1279 114 : ABI_MALLOC(elastic_displacement,(6,6,3,natom))
1280 228 : ABI_MALLOC(ifcs%atmfrc,(3,natom,3,natom,nrpt))
1281 114 : ABI_MALLOC(ifcs%cell,(3,nrpt))
1282 152 : ABI_MALLOC(ifcs%short_atmfrc,(3,natom,3,natom,nrpt))
1283 152 : ABI_MALLOC(ifcs%ewald_atmfrc,(3,natom,3,natom,nrpt))
1284 114 : ABI_MALLOC(strain_coupling,(6,3,natom))
1285 152 : ABI_MALLOC(total_atmfrc,(3,natom,3,natom,nrpt))
1286 152 : ABI_MALLOC(local_atmfrc,(3,natom,3,natom,nrpt))
1287 228 : ABI_MALLOC(dynmat,(2,3,natom,3,natom,nph1l))
1288 114 : ABI_MALLOC(typat,(natom))
1289 152 : ABI_MALLOC(phfrq,(3*natom,nph1l))
1290 114 : ABI_MALLOC(qph1l,(3,nph1l))
1291 114 : ABI_MALLOC(xcart,(3,natom))
1292 76 : ABI_MALLOC(xred,(3,natom))
1293 114 : ABI_MALLOC(zeff,(3,3,natom))
1294 76 : ABI_MALLOC(zion,(ntypat))
1295 76 : ABI_MALLOC(znucl,(ntypat))
1296 :
1297 456 : ABI_MALLOC(phonon_strain,(6))
1298 38 : nrpt_scoupling = 0
1299 266 : do ii = 1,6
1300 : ! Get The size of the strainPhonon-coupling
1301 228 : call effective_potential_file_getDimStrainCoupling(filename,nrpt_scoupling,ii-1)
1302 1140 : ABI_MALLOC(phonon_strain(ii)%atmfrc,(3,natom,3,natom,nrpt_scoupling))
1303 684 : ABI_MALLOC(phonon_strain(ii)%cell,(3,nrpt_scoupling))
1304 228 : phonon_strain(ii)%nrpt = nrpt_scoupling
1305 228 : phonon_strain(ii)%atmfrc = zero
1306 266 : phonon_strain(ii)%cell = 0
1307 : end do
1308 :
1309 136 : all_amu(:) = zero
1310 97068 : dynmat(:,:,:,:,:,:) = zero
1311 5126 : cell_local(:,:) = 99D99
1312 5126 : cell_total(:,:) = 99D99
1313 38 : elastic3rd(:,:,:) = zero
1314 26558 : elastic_displacement(:,:,:,:) = zero
1315 38 : ifcs%nrpt = nrpt
1316 633086 : ifcs%atmfrc(:,:,:,:,:) = zero
1317 5126 : ifcs%cell(:,:) = 0
1318 633086 : ifcs%ewald_atmfrc(:,:,:,:,:) = zero
1319 633086 : ifcs%short_atmfrc(:,:,:,:,:) = zero
1320 4526 : strain_coupling(:,:,:) = zero
1321 2016 : phfrq = zero
1322 606 : qph1l = 0
1323 854 : xcart = zero
1324 2690 : zeff = zero
1325 136 : znucl = zero
1326 :
1327 38 : if(iam_master)then
1328 : !Open the atomicdata XML file for reading
1329 : #if defined HAVE_XML
1330 :
1331 : write(message,'(a,a,a,a)')'-Reading the file ',trim(filename),&
1332 : & ' with LibXML library'
1333 :
1334 : call wrtout(ab_out,message,'COLL')
1335 : call wrtout(std_out,message,'COLL')
1336 :
1337 : ! Read with libxml library
1338 : call effpot_xml_readSystem(char_f2c(trim(filename)),natom,ntypat,nrpt,nph1l,all_amu,&
1339 : & ifcs%atmfrc,ifcs%cell,dynmat,elastic_constants,energy,&
1340 : & epsilon_inf,ifcs%ewald_atmfrc,phfrq,rprimd,qph1l,&
1341 : & ifcs%short_atmfrc,typat,xcart,zeff)
1342 :
1343 : ! convert atomic mass unit to znucl
1344 : do itypat=1,ntypat
1345 : do ii=1,103
1346 : call atomdata_from_znucl(atom,real(ii,dp))
1347 : if (abs((real(atom%amu,sp)-real(all_amu(itypat),sp))&
1348 : & /real(all_amu(itypat),sp)*100)<0.1) then
1349 : znucl(itypat) = atom%znucl
1350 : exit
1351 : end if
1352 : end do
1353 : end do
1354 :
1355 : ! Get the Phonon Strain coupling
1356 : do voigt = 1,6
1357 : nrpt_scoupling = phonon_strain(voigt)%nrpt
1358 : ABI_MALLOC(phonon_straincell,(3,nrpt_scoupling))
1359 : ABI_MALLOC(phonon_strain_atmfrc,(3,natom,3,natom,nrpt_scoupling))
1360 :
1361 : ! Get The value
1362 : call effpot_xml_readStrainCoupling(char_f2c(trim(filename)),natom,nrpt_scoupling,(voigt-1),&
1363 : & elastic3rd(voigt,:,:),elastic_displacement(voigt,:,:,:),&
1364 : & strain_coupling(voigt,:,:),&
1365 : & phonon_strain_atmfrc,phonon_straincell)
1366 :
1367 : ! Check if the 3rd order strain_coupling is present
1368 : has_anharmonics = .FALSE.
1369 : if(any(elastic3rd>tol10).or.any(elastic_displacement>tol10)) has_anharmonics = .TRUE.
1370 : phonon_strain(voigt)%atmfrc(:,:,:,:,:) = phonon_strain_atmfrc(:,:,:,:,:)
1371 : phonon_strain(voigt)%cell(:,:) = phonon_straincell(:,:)
1372 : if(any(phonon_strain(voigt)%atmfrc > tol10)) has_anharmonics = .TRUE.
1373 :
1374 : ABI_FREE(phonon_straincell)
1375 : ABI_FREE(phonon_strain_atmfrc)
1376 : end do
1377 : #else
1378 :
1379 : ! Read by hand
1380 22 : write(message,'(a,a,a,a)')'-Reading the file ',trim(filename),&
1381 44 : & ' with Fortran'
1382 :
1383 22 : call wrtout(ab_out,message,'COLL')
1384 22 : call wrtout(std_out,message,'COLL')
1385 :
1386 22 : if (open_file(filename,message,unit=funit,form="formatted",&
1387 : & status="old",action="read") /= 0) then
1388 0 : ABI_ERROR(message)
1389 : end if
1390 :
1391 : !Start a reading loop in fortran
1392 22 : rewind(unit=funit)
1393 22 : found=.false.
1394 :
1395 22 : iatom = 1
1396 22 : iamu = 1
1397 22 : itypat = 1
1398 22 : irpt = 1
1399 22 : irpt1 = 0
1400 22 : irpt2 = 0
1401 22 : iph1l = 1
1402 22 : amu = zero
1403 22 : short_range = .false.
1404 22 : total_range = .false.
1405 22 : has_straincoupling = .FALSE.
1406 94533 : do while ((ios==0).and.(.not.found))
1407 94511 : read(funit,'(a)',iostat=ios) readline
1408 94533 : if(ios == 0)then
1409 94489 : call rmtabfromline(readline)
1410 94489 : line=adjustl(readline)
1411 94489 : if (.not.has_straincoupling) then
1412 :
1413 5163 : if ((line(1:7)=='<energy')) then
1414 22 : call rdfromline_value('energy',line,strg)
1415 22 : if (strg/="") then
1416 0 : strg1=trim(strg)
1417 0 : read(strg1,*) energy
1418 : else
1419 22 : read(funit,'(a)',iostat=ios) readline
1420 22 : call rmtabfromline(readline)
1421 22 : line=adjustl(readline)
1422 22 : call rdfromline_value('energy',line,strg)
1423 22 : if (strg/="") then
1424 0 : strg1=trim(strg)
1425 : else
1426 22 : strg1=trim(line)
1427 : end if
1428 22 : read(strg1,*) energy
1429 : end if
1430 : cycle
1431 : end if
1432 :
1433 5141 : if ((line(1:10)=='<unit_cell')) then
1434 22 : call rdfromline_value('unit_cell',line,strg)
1435 22 : if (strg/="") then
1436 0 : strg1=trim(strg)
1437 0 : read(strg1,*) (rprimd(1,mu),mu=1,3)
1438 0 : read(funit,*) (rprimd(2,mu),mu=1,3)
1439 : else
1440 66 : do nu=1,2
1441 66 : read(funit,*) (rprimd(nu,mu),mu=1,3)
1442 : end do
1443 : end if
1444 22 : read(funit,'(a)',iostat=ios) readline
1445 22 : call rmtabfromline(readline)
1446 22 : line=adjustl(readline)
1447 22 : call rdfromline_value('unit_cell',line,strg)
1448 22 : if (strg/="") then
1449 0 : strg1=trim(strg)
1450 : else
1451 22 : strg1=trim(line)
1452 : end if
1453 22 : read(strg1,*) (rprimd(3,mu),mu=1,3)
1454 22 : cycle
1455 : end if
1456 :
1457 5119 : if ((line(1:12)=='<epsilon_inf')) then
1458 22 : call rdfromline_value('epsilon_inf',line,strg)
1459 22 : if (strg/="") then
1460 0 : strg1=trim(strg)
1461 0 : read(strg1,*) (epsilon_inf(mu,1),mu=1,3)
1462 0 : read(funit,*) (epsilon_inf(mu,2),mu=1,3)
1463 : else
1464 66 : do nu=1,2
1465 66 : read(funit,*) (epsilon_inf(mu,nu),mu=1,3)
1466 : end do
1467 : end if
1468 22 : read(funit,'(a)',iostat=ios) readline
1469 22 : call rmtabfromline(readline)
1470 22 : line=adjustl(readline)
1471 22 : call rdfromline_value('epsilon_inf',line,strg)
1472 22 : if (strg/="") then
1473 0 : strg1=trim(strg)
1474 : else
1475 22 : strg1=trim(line)
1476 : end if
1477 22 : read(strg1,*) (epsilon_inf(mu,3),mu=1,3)
1478 22 : cycle
1479 : end if
1480 :
1481 5097 : if ((line(1:8)=='<elastic')) then
1482 22 : call rdfromline_value('elastic',line,strg)
1483 22 : if (strg/="") then
1484 0 : strg1=trim(strg)
1485 0 : read(strg1,*) (elastic_constants(mu,1),mu=1,6)
1486 0 : do nu=2,5
1487 0 : read(funit,*) (elastic_constants(mu,nu),mu=1,6)
1488 : end do
1489 : else
1490 132 : do nu=1,5
1491 132 : read(funit,*) (elastic_constants(mu,nu),mu=1,6)
1492 : end do
1493 : end if
1494 22 : read(funit,'(a)',iostat=ios) readline
1495 22 : call rmtabfromline(readline)
1496 22 : line=adjustl(readline)
1497 22 : call rdfromline_value('elastic',line,strg)
1498 22 : if (strg/="") then
1499 0 : strg1=trim(strg)
1500 : else
1501 22 : strg1=trim(line)
1502 : end if
1503 22 : read(strg1,*) (elastic_constants(mu,6),mu=1,6)
1504 22 : cycle
1505 : end if
1506 :
1507 5075 : if ((line(1:5)=='<atom')) then
1508 132 : call rdfromline("mass",line,strg)
1509 132 : strg1=trim(strg)
1510 132 : read(strg1,*) amu
1511 396 : if (.not.any(abs(all_amu-amu)<tol16)) then
1512 58 : all_amu(iamu) = amu
1513 58 : typat(iatom) = int(amu)
1514 : !convert atomic mass unit to znucl
1515 1260 : do ii=1,103
1516 1260 : call atomdata_from_znucl(atom,real(ii,dp))
1517 1260 : if (abs((real(atom%amu,sp)-real(amu,sp))&
1518 1260 : & /real(amu,sp)*100)<0.1) then
1519 58 : znucl(iamu) = atom%znucl
1520 58 : exit
1521 : end if
1522 : end do
1523 58 : iamu = iamu +1
1524 : end if
1525 496 : do itypat=1,ntypat
1526 496 : if(abs(amu-all_amu(itypat))<tol16) then
1527 132 : typat(iatom) = itypat
1528 : end if
1529 : end do
1530 : cycle
1531 : end if
1532 :
1533 4943 : if ((line(1:9)=='<position')) then
1534 132 : call rdfromline_value('position',line,strg)
1535 132 : if (strg/="") then
1536 0 : strg1=trim(strg)
1537 0 : read(strg1,*)(xcart(mu,iatom),mu=1,3)
1538 : else
1539 132 : read(funit,'(a)',iostat=ios) readline
1540 132 : call rmtabfromline(readline)
1541 132 : line=adjustl(readline)
1542 132 : call rdfromline_value('position',line,strg)
1543 132 : if (strg/="") then
1544 0 : strg1=trim(strg)
1545 : else
1546 132 : strg1=trim(line)
1547 : end if
1548 132 : read(strg1,*)(xcart(mu,iatom),mu=1,3)
1549 : end if
1550 : cycle
1551 : end if
1552 :
1553 4811 : if ((line(1:11)=='<borncharge')) then
1554 132 : call rdfromline_value('borncharge',line,strg)
1555 132 : if (strg/="") then
1556 0 : strg1=trim(strg)
1557 0 : read(strg1,*) (zeff(mu,1,iatom),mu=1,3)
1558 0 : read(funit,*) (zeff(mu,2,iatom),mu=1,3)
1559 : else
1560 396 : do nu=1,2
1561 396 : read(funit,*) (zeff(mu,nu,iatom),mu=1,3)
1562 : end do
1563 : end if
1564 132 : read(funit,'(a)',iostat=ios) readline
1565 132 : line=adjustl(readline)
1566 132 : call rdfromline_value('borncharge',line,strg)
1567 132 : if (strg/="") then
1568 0 : strg1=trim(strg)
1569 : else
1570 132 : strg1=trim(line)
1571 : end if
1572 132 : read(strg1,*) (zeff(mu,3,iatom),mu=1,3)
1573 132 : cycle
1574 : end if
1575 :
1576 4679 : if ((line(1:7)==char(60)//char(47)//'atom'//char(62))) then
1577 132 : iatom=iatom+1
1578 132 : cycle
1579 : end if
1580 :
1581 4547 : if ((line(1:12)=='<local_force')) then
1582 648 : found2 = .False.
1583 648 : irpt1 = irpt1 + 1
1584 : do while (.not.found2)
1585 1944 : read(funit,'(a)',iostat=ios) readline
1586 1944 : call rmtabfromline(readline)
1587 1944 : line=adjustl(readline)
1588 1944 : if ((line(1:5)=='<data')) then
1589 648 : call rdfromline_value('data',line,strg)
1590 648 : if (strg/="") then
1591 0 : ABI_MALLOC(work2,(3*natom,3*natom))
1592 0 : strg1=trim(strg)
1593 0 : read(strg1,*) (work2(1,nu),nu=1,3*natom)
1594 0 : do mu=2,3*natom-1
1595 0 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1596 : end do
1597 0 : read(funit,'(a)',iostat=ios) readline
1598 0 : call rmtabfromline(readline)
1599 0 : line=adjustl(readline)
1600 0 : call rdfromline_value('data',line,strg)
1601 0 : if (strg/="") then
1602 0 : strg1=trim(strg)
1603 : else
1604 0 : strg1=trim(line)
1605 : end if
1606 0 : read(strg1,*) (work2(3*natom,nu),nu=1,3*natom)
1607 0 : local_atmfrc(:,:,:,:,irpt1) = reshape(work2,(/3,natom,3,natom/))
1608 0 : ABI_FREE(work2)
1609 : else
1610 2592 : ABI_MALLOC(work2,(3*natom,3*natom))
1611 12726 : do mu=1,3*natom
1612 12726 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1613 : end do
1614 3240 : local_atmfrc(:,:,:,:,irpt1) = reshape(work2,(/3,natom,3,natom/))
1615 648 : ABI_FREE(work2)
1616 : end if
1617 : end if
1618 1944 : if ((line(1:5)=='<cell')) then
1619 648 : call rdfromline_value('cell',line,strg)
1620 648 : if (strg/="") then
1621 0 : strg1=trim(strg)
1622 0 : read(strg1,*)(cell_local(mu,irpt1),mu=1,3)
1623 : else
1624 648 : read(funit,*)(cell_local(mu,irpt1),mu=1,3)
1625 : end if
1626 : found2 = .TRUE.
1627 : cycle
1628 : end if
1629 : end do
1630 : end if
1631 :
1632 4547 : if ((line(1:12)=='<total_force')) then
1633 531 : irpt2 = irpt2 + 1
1634 531 : found2 = .False.
1635 : do while (.not.found2)
1636 1593 : read(funit,'(a)',iostat=ios) readline
1637 1593 : call rmtabfromline(readline)
1638 1593 : line=adjustl(readline)
1639 1593 : if ((line(1:5)=='<data')) then
1640 531 : call rdfromline_value('data',line,strg)
1641 531 : if (strg/="") then
1642 0 : ABI_MALLOC(work2,(3*natom,3*natom))
1643 0 : strg1=trim(strg)
1644 0 : read(strg1,*) (work2(1,nu),nu=1,3*natom)
1645 0 : do mu=2,3*natom-1
1646 0 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1647 : end do
1648 0 : read(funit,'(a)',iostat=ios) readline
1649 0 : call rmtabfromline(readline)
1650 0 : line=adjustl(readline)
1651 0 : call rdfromline_value('data',line,strg)
1652 0 : if (strg/="") then
1653 0 : strg1=trim(strg)
1654 : else
1655 0 : strg1=trim(line)
1656 : end if
1657 0 : read(strg1,*) (work2(3*natom,nu),nu=1,3*natom)
1658 0 : total_atmfrc(:,:,:,:,irpt2) = reshape(work2,(/3,natom,3,natom/))
1659 0 : ABI_FREE(work2)
1660 : else
1661 2124 : ABI_MALLOC(work2,(3*natom,3*natom))
1662 8208 : do mu=1,3*natom
1663 8208 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1664 : end do
1665 2655 : total_atmfrc(:,:,:,:,irpt2) = reshape(work2,(/3,natom,3,natom/))
1666 531 : ABI_FREE(work2)
1667 : end if
1668 : end if
1669 1593 : if ((line(1:5)=='<cell')) then
1670 531 : call rdfromline_value('cell',line,strg)
1671 531 : if (strg/="") then
1672 0 : strg1=trim(strg)
1673 0 : read(strg1,*)(cell_total(mu,irpt2),mu=1,3)
1674 : else
1675 531 : read(funit,*)(cell_total(mu,irpt2),mu=1,3)
1676 : end if
1677 : found2 = .TRUE.
1678 : cycle
1679 : end if
1680 : end do
1681 : end if
1682 :
1683 4547 : if ((line(1:7)=='<qpoint')) then
1684 74 : call rdfromline_value('qpoint',line,strg)
1685 74 : if (strg/="") then
1686 0 : strg1=trim(strg)
1687 0 : read(strg1,*)(qph1l(mu,iph1l),mu=1,3)
1688 : else
1689 74 : read(funit,*) (qph1l(mu,iph1l),mu=1,3)
1690 : end if
1691 : end if
1692 :
1693 4547 : if ((line(1:12)=='<frequencies')) then
1694 74 : call rdfromline_value('frequencies',line,strg)
1695 74 : if (strg/="") then
1696 0 : strg1=trim(strg)
1697 0 : read(strg1,*)(phfrq(mu,iph1l),mu=1,3*natom)
1698 : else
1699 410 : do nu=1,natom
1700 1418 : read(funit,*) (phfrq(((nu-1)*3)+mu,iph1l),mu=1,3)
1701 : end do
1702 : end if
1703 : end if
1704 :
1705 4547 : if ((line(1:17)=='<dynamical_matrix')) then
1706 74 : call rdfromline_value('dynamical_matrix',line,strg)
1707 74 : if (strg/="") then
1708 0 : ABI_MALLOC(work2,(3*natom,3*natom))
1709 0 : strg1=trim(strg)
1710 0 : read(strg1,*) (work2(nu,1),nu=1,3*natom)
1711 0 : do mu=2,3*natom-1
1712 0 : read(funit,*)(work2(nu,mu),nu=1,3*natom)
1713 : end do
1714 0 : read(funit,'(a)',iostat=ios) readline
1715 0 : call rmtabfromline(readline)
1716 0 : line=adjustl(readline)
1717 0 : call rdfromline_value('dynamical_matrix',line,strg)
1718 0 : if (strg/="") then
1719 0 : strg1=trim(strg)
1720 : else
1721 0 : strg1=trim(line)
1722 : end if
1723 0 : read(strg1,*) (work2(nu,3*natom),nu=1,3*natom)
1724 0 : dynmat(1,:,:,:,:,iph1l) = reshape(work2,(/3,natom,3,natom/))
1725 0 : ABI_FREE(work2)
1726 : else
1727 296 : ABI_MALLOC(work2,(3*natom,3*natom))
1728 1082 : do mu=1,3*natom
1729 1082 : read(funit,*)(work2(nu,mu),nu=1,3*natom)
1730 : end do
1731 26002 : dynmat(1,:,:,:,:,iph1l) = reshape(work2,(/3,natom,3,natom/))
1732 74 : ABI_FREE(work2)
1733 : end if
1734 : end if
1735 :
1736 4547 : if ((line(1:8)==char(60)//char(47)//'phonon')) then
1737 74 : iph1l = iph1l +1
1738 : end if
1739 :
1740 4547 : if ((line(1:16)=='<strain_coupling')) then
1741 22 : read(funit,'(a)',iostat=ios) readline
1742 22 : call rdfromline("voigt",line,strg)
1743 22 : strg1=trim(strg)
1744 22 : read(strg1,*) voigt
1745 22 : voigt = voigt + 1 ! 0 to 5 in the xml
1746 22 : has_straincoupling = .true.
1747 22 : irpt = 1
1748 : end if
1749 :
1750 : else
1751 : ! Now treat the strain phonon coupling part
1752 89326 : if ((line(1:16)=='<strain_coupling')) then
1753 110 : read(funit,'(a)',iostat=ios) readline
1754 110 : call rdfromline("voigt",line,strg)
1755 110 : strg1=trim(strg)
1756 110 : read(strg1,*) voigt
1757 110 : voigt = voigt + 1 ! 0 to 5 in the xml
1758 110 : irpt = 1
1759 110 : cycle
1760 : end if
1761 :
1762 89216 : if(voigt>6)then
1763 0 : write(message, '(4a)' )ch10,&
1764 0 : & ' WARNING: the number of strain phonon coupling is superior to 6 in ',trim(filename),ch10
1765 0 : call wrtout(std_out,message,'COLL')
1766 0 : exit
1767 : end if
1768 :
1769 89216 : if ((line(1:22)=='<correction_force unit')) then
1770 132 : call rdfromline_value('correction_force',line,strg)
1771 132 : if (strg/="") then
1772 0 : ABI_MALLOC(work2,(3,natom))
1773 0 : strg1=trim(strg)
1774 0 : read(strg1,*) (work2(nu,1),nu=1,3)
1775 0 : do mu=2,natom-1
1776 0 : read(funit,*)(work2(nu,mu),nu=1,3)
1777 : end do
1778 0 : read(funit,'(a)',iostat=ios) readline
1779 0 : call rmtabfromline(readline)
1780 0 : line=adjustl(readline)
1781 0 : call rdfromline_value('correction_force',line,strg)
1782 0 : if (strg/="") then
1783 0 : strg1=trim(strg)
1784 0 : read(strg1,*) (work2(nu,natom),nu=1,3)
1785 : else
1786 0 : strg1=trim(line)
1787 0 : read(strg1,*) (work2(nu,natom),nu=1,3)
1788 : end if
1789 0 : strain_coupling(voigt,:,:) = work2(:,:)
1790 0 : ABI_FREE(work2)
1791 : else
1792 396 : ABI_MALLOC(work2,(3,natom))
1793 924 : do mu=1,natom
1794 924 : read(funit,*)(work2(nu,mu),nu=1,3)
1795 : end do
1796 3300 : strain_coupling(voigt,:,:) = work2(:,:)
1797 132 : ABI_FREE(work2)
1798 : end if
1799 : end if
1800 :
1801 89216 : if ((line(1:11)=='<elastic3rd')) then
1802 0 : call rdfromline_value('elastic3rd',line,strg)
1803 0 : if (strg/="") then
1804 0 : strg1=trim(strg)
1805 0 : read(strg1,*) (elastic3rd(voigt,mu,1),mu=1,6)
1806 0 : do nu=2,5
1807 0 : read(funit,*) (elastic3rd(voigt,mu,nu),mu=1,6)
1808 : end do
1809 : else
1810 0 : do nu=1,5
1811 0 : read(funit,*) (elastic3rd(voigt,mu,nu),mu=1,6)
1812 : end do
1813 : end if
1814 0 : read(funit,'(a)',iostat=ios) readline
1815 0 : call rmtabfromline(readline)
1816 0 : line=adjustl(readline)
1817 0 : call rdfromline_value('elastic3rd',line,strg)
1818 0 : if (strg/="") then
1819 0 : strg1=trim(strg)
1820 0 : read(strg1,*) (elastic3rd(voigt,mu,6),mu=1,6)
1821 : else
1822 0 : strg1=trim(line)
1823 0 : read(strg1,*) (elastic3rd(voigt,mu,6),mu=1,6)
1824 : end if
1825 0 : has_anharmonics = .true.
1826 0 : cycle
1827 : end if
1828 :
1829 89216 : if ((line(1:29)=='<correction_strain_force unit')) then
1830 0 : call rdfromline_value('correction_strain_force',line,strg)
1831 0 : if (strg/="") then
1832 0 : ABI_MALLOC(work2,(3*6,natom))
1833 0 : strg1=trim(strg)
1834 0 : read(strg1,*) (work2(nu,1),nu=1,3*6)
1835 0 : do mu=2,natom-1
1836 0 : read(funit,*)(work2(nu,mu),nu=1,3*6)
1837 : end do
1838 0 : read(funit,'(a)',iostat=ios) readline
1839 0 : call rmtabfromline(readline)
1840 0 : line=adjustl(readline)
1841 0 : call rdfromline_value('correction_strain_force',line,strg)
1842 0 : if (strg/="") then
1843 0 : strg1=trim(strg)
1844 0 : read(strg1,*) (work2(nu,natom),nu=1,3*6)
1845 : else
1846 0 : strg1=trim(line)
1847 0 : read(strg1,*) (work2(nu,natom),nu=1,3*6)
1848 : end if
1849 0 : elastic_displacement(voigt,:,:,:) = reshape(work2(:,:),(/6,3,natom/))
1850 0 : ABI_FREE(work2)
1851 : else
1852 0 : ABI_MALLOC(work2,(3*6,natom))
1853 0 : do mu=1,natom
1854 0 : read(funit,*)(work2(nu,mu),nu=1,3*6)
1855 : end do
1856 0 : elastic_displacement(voigt,:,:,:) = reshape(work2(:,:),(/6,3,natom/))
1857 0 : ABI_FREE(work2)
1858 : end if
1859 : end if
1860 :
1861 89216 : if ((line(1:26)=='<correction_force_constant')) then
1862 : found2=.false.
1863 : do while (.not.found2)
1864 0 : read(funit,'(a)',iostat=ios) readline
1865 0 : call rmtabfromline(readline)
1866 0 : line=adjustl(readline)
1867 0 : if ((line(1:5)=='<data')) then
1868 0 : call rdfromline_value('data',line,strg)
1869 0 : if (strg/="") then
1870 0 : ABI_MALLOC(work2,(3*natom,3*natom))
1871 0 : strg1=trim(strg)
1872 0 : read(strg1,*) (work2(1,nu),nu=1,3*natom)
1873 0 : do mu=2,3*natom-1
1874 0 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1875 : end do
1876 0 : read(funit,'(a)',iostat=ios) readline
1877 0 : call rmtabfromline(readline)
1878 0 : line=adjustl(readline)
1879 0 : call rdfromline_value('data',line,strg)
1880 0 : if (strg/="") then
1881 0 : strg1=trim(strg)
1882 0 : read(strg1,*) (work2(3*natom,nu),nu=1,3*natom)
1883 : else
1884 0 : strg1=trim(line)
1885 0 : read(strg1,*) (work2(3*natom,nu),nu=1,3*natom)
1886 : end if
1887 : phonon_strain(voigt)%atmfrc(:,:,:,:,irpt) = &
1888 0 : & reshape(work2,(/3,natom,3,natom/))
1889 0 : ABI_FREE(work2)
1890 : else
1891 0 : ABI_MALLOC(work2,(3*natom,3*natom))
1892 0 : do mu=1,3*natom
1893 0 : read(funit,*)(work2(mu,nu),nu=1,3*natom)
1894 : end do
1895 : phonon_strain(voigt)%atmfrc(:,:,:,:,irpt) =&
1896 0 : & reshape(work2,(/3,natom,3,natom/))
1897 0 : ABI_FREE(work2)
1898 : end if
1899 0 : has_anharmonics = .true.
1900 : end if
1901 0 : if ((line(1:5)=='<cell')) then
1902 0 : call rdfromline_value('cell',line,strg)
1903 0 : if (strg/="") then
1904 0 : strg1=trim(strg)
1905 0 : read(strg1,*)(phonon_strain(voigt)%cell(mu,irpt),mu=1,3)
1906 : else
1907 0 : read(funit,*)(phonon_strain(voigt)%cell(mu,irpt),mu=1,3)
1908 : end if
1909 0 : irpt = irpt + 1
1910 : found2=.true.
1911 : cycle
1912 : end if
1913 : end do
1914 : end if
1915 :
1916 89216 : if ((line(1:17)==char(60)//char(47)//'strain_coupling')) then
1917 : ! set nrpt for the previous value of strain
1918 132 : phonon_strain(voigt)%nrpt = irpt - 1
1919 : ! restart the calculation of nrpt
1920 : end if
1921 : end if
1922 : end if
1923 : end do
1924 :
1925 :
1926 : ! Reorder the ATMFRC
1927 : ! Case 1: only local in the xml
1928 22 : if (irpt1>0 .and. irpt2==0) then
1929 763 : ifcs%cell(:,:) = int(cell_local(:,:))
1930 306916 : ifcs%atmfrc(:,:,:,:,:) = zero !local_atmfrc(:,:,:,:,:)
1931 306916 : ifcs%short_atmfrc(:,:,:,:,:) = local_atmfrc(:,:,:,:,:)
1932 306916 : ifcs%ewald_atmfrc(:,:,:,:,:) = zero
1933 :
1934 : ! Case 2: only total in the xml
1935 15 : else if(irpt1==0 .and. irpt2>0)then
1936 0 : ifcs%cell(:,:) = int(cell_total(:,:))
1937 0 : ifcs%atmfrc(:,:,:,:,:) = total_atmfrc(:,:,:,:,:)
1938 0 : ifcs%short_atmfrc(:,:,:,:,:) = zero
1939 0 : ifcs%ewald_atmfrc(:,:,:,:,:) = zero !total_atmfrc(:,:,:,:,:)
1940 :
1941 : ! Case 3: local + total in the xml
1942 15 : else if (irpt1>0 .and. irpt2>0)then
1943 15 : if(irpt1 <= irpt2)then
1944 15 : irpt3 = 0
1945 546 : do ii=1,irpt2
1946 2124 : ifcs%cell(:,ii) = int(cell_total(:,ii))
1947 159699 : ifcs%atmfrc(:,:,:,:,ii) = total_atmfrc(:,:,:,:,ii)
1948 36753 : do jj=1,irpt1
1949 46965 : if (all(abs(int(cell_local(:,jj))-ifcs%cell(:,ii))<tol16)) then
1950 144651 : ifcs%short_atmfrc(:,:,:,:,ii) = local_atmfrc(:,:,:,:,jj)
1951 459 : irpt3 = irpt3 + 1
1952 : end if
1953 : end do
1954 : end do
1955 15 : if(irpt3 /= irpt1)then
1956 0 : write(message, '(4a)' )ch10,&
1957 0 : & ' There is several similar short IFC in ',trim(filename),ch10
1958 0 : ABI_BUG(message)
1959 : end if
1960 : else
1961 0 : write(message, '(2a,I5,3a,I5,5a)' )ch10,&
1962 0 : & ' The number of total IFC (',irpt2,') is inferior to ',ch10,&
1963 0 : & ' the number of short range IFC (',irpt1,') in ',trim(filename),ch10,&
1964 0 : & ' This is not possible',ch10
1965 :
1966 0 : ABI_BUG(message)
1967 : end if
1968 : end if
1969 :
1970 : ! Do some checks
1971 154 : if (any(typat==0)) then
1972 : write(message, '(a,a,a)' )&
1973 0 : & ' Unable to read the type of atoms ',trim(filename),ch10
1974 0 : ABI_ERROR(message)
1975 : end if
1976 :
1977 80 : if (any(abs(znucl)<tol16)) then
1978 : write(message, '(a,a,a)' )&
1979 0 : & ' Unable to read the atomic number ',trim(filename),ch10
1980 0 : ABI_ERROR(message)
1981 : end if
1982 :
1983 80 : if (any(abs(all_amu)<tol16)) then
1984 : write(message, '(a,a,a)' )&
1985 0 : & ' Unable to read the atomic mass ',trim(filename),ch10
1986 0 : ABI_ERROR(message)
1987 : end if
1988 :
1989 22 : close(unit=funit)
1990 :
1991 : #endif
1992 :
1993 : end if !End if master
1994 :
1995 : !MPI BROADCAST
1996 38 : call xmpi_bcast(energy,master, comm, ierr)
1997 38 : call xmpi_bcast(all_amu,master, comm, ierr)
1998 38 : call xmpi_bcast(dynmat,master, comm, ierr)
1999 38 : call xmpi_bcast(elastic_constants,master, comm, ierr)
2000 38 : call xmpi_bcast(epsilon_inf,master, comm, ierr)
2001 38 : call xmpi_bcast(ifcs%nrpt,master, comm, ierr)
2002 38 : call xmpi_bcast(ifcs%atmfrc,master, comm, ierr)
2003 38 : call xmpi_bcast(ifcs%cell,master, comm, ierr)
2004 38 : call xmpi_bcast(ifcs%ewald_atmfrc,master, comm, ierr)
2005 38 : call xmpi_bcast(ifcs%short_atmfrc,master, comm, ierr)
2006 38 : call xmpi_bcast(strain_coupling,master, comm, ierr)
2007 38 : call xmpi_bcast(phfrq,master, comm, ierr)
2008 38 : call xmpi_bcast(qph1l,master, comm, ierr)
2009 38 : call xmpi_bcast(typat,master, comm, ierr)
2010 38 : call xmpi_bcast(rprimd,master, comm, ierr)
2011 38 : call xmpi_bcast(xcart,master, comm, ierr)
2012 38 : call xmpi_bcast(zeff,master, comm, ierr)
2013 38 : call xmpi_bcast(znucl,master, comm, ierr)
2014 266 : do ii = 1,6
2015 228 : call xmpi_bcast(phonon_strain(ii)%nrpt ,master, comm, ierr)
2016 228 : call xmpi_bcast(phonon_strain(ii)%atmfrc ,master, comm, ierr)
2017 266 : call xmpi_bcast(phonon_strain(ii)%cell ,master, comm, ierr)
2018 : end do
2019 38 : call xmpi_bcast(elastic3rd ,master, comm, ierr)
2020 38 : call xmpi_bcast(elastic_displacement ,master, comm, ierr)
2021 38 : call xmpi_bcast(has_anharmonics ,master, comm, ierr)
2022 :
2023 : !Fill somes others variables
2024 38 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
2025 38 : call xcart2xred(natom,rprimd,xcart,xred)
2026 :
2027 : !Re-generate symmetry operations from the lattice and atomic coordinates
2028 38 : tolsym=tol8
2029 38 : msym = 384
2030 114 : ABI_MALLOC(spinat,(3,natom))
2031 38 : ABI_MALLOC(ptsymrel,(3,3,msym))
2032 38 : ABI_MALLOC(symafm,(msym))
2033 38 : ABI_MALLOC(symrel,(3,3,msym))
2034 38 : ABI_MALLOC(tnons,(3,msym))
2035 38 : use_inversion=1
2036 854 : spinat = 0;
2037 189734 : symrel = 0;
2038 14630 : symafm = 0;
2039 58406 : tnons = 0 ;
2040 38 : space_group = 0;
2041 38 : call symlatt(bravais,std_out,msym,nptsym,ptsymrel,rprimd,tolsym)
2042 38 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
2043 : call symfind(gprimd,msym,natom,nptsym,0,nsym,&
2044 38 : & 0,ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,use_inversion,xred)
2045 :
2046 : !Initialisation of crystal
2047 38 : npsp = ntypat; timrev = 1
2048 114 : ABI_MALLOC(title, (ntypat))
2049 136 : do ii=1,ntypat
2050 136 : write(title(ii),'(a,i0)')"No title for typat ",ii
2051 : end do
2052 :
2053 : !Warning znucl is dimension with ntypat = nspsp hence alchemy is not supported here
2054 : call crystal%init(all_amu,space_group,natom,npsp,ntypat,nsym,rprimd,typat,xred,&
2055 : & zion,znucl,timrev,.FALSE.,.FALSE.,title,&
2056 38 : & symrel=symrel(:,:,1:nsym),tnons=tnons(:,1:nsym),symafm=symafm(1:nsym))
2057 :
2058 : !amu is not fill in crystal_init...
2059 136 : Crystal%amu(:) = all_amu(:)
2060 :
2061 38 : ABI_FREE(symrel)
2062 38 : ABI_FREE(symafm)
2063 38 : ABI_FREE(tnons)
2064 38 : ABI_FREE(spinat)
2065 38 : ABI_FREE(ptsymrel)
2066 :
2067 : !if strcpling is set to 0 by the user, need to set the flag to false for
2068 : !the initialisation of the effective potential
2069 38 : if (present(strcpling))then
2070 38 : if(strcpling == 0 )then
2071 0 : has_anharmonics = .FALSE.
2072 : end if
2073 : end if
2074 :
2075 : !Initialisation of eff_pot
2076 : call effective_potential_init(crystal,eff_pot,energy,ifcs,ncoeff,nph1l,comm,&
2077 : & dynmat=dynmat,elastic_constants=elastic_constants,&
2078 : & elastic3rd=elastic3rd,elastic_displacement=elastic_displacement,&
2079 : & epsilon_inf=epsilon_inf,strain_coupling=strain_coupling,&
2080 : & phonon_strain=phonon_strain,phfrq=phfrq,qpoints=qph1l,&
2081 38 : & has_anharmonicsTerms=has_anharmonics,zeff=zeff)
2082 :
2083 : !DEALLOCATION OF ARRAYS
2084 38 : ABI_FREE(all_amu)
2085 38 : ABI_FREE(cell_local)
2086 38 : ABI_FREE(cell_total)
2087 38 : ABI_FREE(total_atmfrc)
2088 38 : ABI_FREE(local_atmfrc)
2089 38 : ABI_FREE(ifcs%atmfrc)
2090 38 : ABI_FREE(ifcs%cell)
2091 38 : ABI_FREE(ifcs%short_atmfrc)
2092 38 : ABI_FREE(ifcs%ewald_atmfrc)
2093 38 : ABI_FREE(dynmat)
2094 38 : ABI_FREE(strain_coupling)
2095 38 : ABI_FREE(phfrq)
2096 38 : ABI_FREE(qph1l)
2097 38 : ABI_FREE(title)
2098 38 : ABI_FREE(typat)
2099 38 : ABI_FREE(xcart)
2100 38 : ABI_FREE(xred)
2101 38 : ABI_FREE(zeff)
2102 38 : ABI_FREE(zion)
2103 38 : ABI_FREE(znucl)
2104 266 : do ii = 1,6
2105 228 : phonon_strain(ii)%nrpt = nrpt
2106 228 : phonon_strain(ii)%atmfrc = zero
2107 228 : phonon_strain(ii)%cell = 0
2108 228 : ABI_FREE(phonon_strain(ii)%atmfrc)
2109 266 : ABI_FREE(phonon_strain(ii)%cell)
2110 : end do
2111 266 : ABI_FREE(phonon_strain)
2112 38 : ABI_FREE(elastic_displacement)
2113 :
2114 : !DEALLOCATION OF TYPES
2115 38 : call ifcs%free()
2116 38 : call crystal%free()
2117 :
2118 114 : end subroutine system_xml2effpot
2119 : !!***
2120 :
2121 : !!****f* m_effective_potential_file/system_ddb2effpot
2122 : !!
2123 : !! NAME
2124 : !! system_ddb2effpot
2125 : !!
2126 : !! FUNCTION
2127 : !! Transfert ddb into effective potential structure.
2128 : !! Also calculate the IFC
2129 : !!
2130 : !! INPUTS
2131 : !! crytal<type(crystal_t)> = datatype with all the information for the crystal
2132 : !! ddb<type(ddb_type)> = datatype with the ddb
2133 : !! inp<type(multibinit_dtset_type)> = datatype with the input variables of multibinit
2134 : !! comm = MPI communicator
2135 : !!
2136 : !! OUTPUT
2137 : !! effective_potantial<type(effective_potential_type)> = effective_potential datatype to be initialized
2138 : !!
2139 : !! SOURCE
2140 :
2141 29 : subroutine system_ddb2effpot(crystal,ddb, effective_potential,inp,comm)
2142 :
2143 38 : use m_dynmat
2144 :
2145 : use m_copy, only : alloc_copy
2146 : use m_crystal, only : crystal_t
2147 : use m_multibinit_dataset, only : multibinit_dtset_type
2148 :
2149 : !Arguments ------------------------------------
2150 : !scalars
2151 : integer,intent(in) :: comm
2152 : !arrays
2153 : type(ddb_type),intent(inout) :: ddb
2154 : type(effective_potential_type), intent(inout) :: effective_potential
2155 : type(crystal_t),intent(in) :: crystal
2156 : type(multibinit_dtset_type),intent(in) :: inp
2157 :
2158 : !Local variables-------------------------------
2159 : !scalar
2160 : real(dp):: wcount1,wcount2
2161 : integer :: chneut,i1,i2,i3,ia,ib,iblok,idir1,idir2,ierr,ii,ipert1,iphl1
2162 : integer :: ipert2,irpt,irpt2,ivarA,ivarB,max1,max2,max3,min1,min2,min3
2163 : integer :: msize,mpert,natom,nblok,nrpt_new,nrpt_new2,rftyp,selectz
2164 : integer :: my_rank,nproc,prt_internalstr
2165 : logical :: iam_master
2166 : integer,parameter :: master=0
2167 : integer :: nptsym,nsym
2168 : integer :: msym = 384, use_inversion = 1, space_group
2169 : real(dp):: max_phfq,eta, tolsym = tol8
2170 : !arrays
2171 : integer :: bravais(11),cell_number(3),cell2(3)
2172 : integer :: shift(3),rfelfd(4),rfphon(4),rfstrs(4)
2173 29 : integer,allocatable :: cell_red(:,:)
2174 : real(dp):: dielt(3,3),elast_clamped(6,6),fact
2175 : real(dp):: red(3,3),qphnrm(3),qphon(3,3)
2176 29 : real(dp),allocatable :: blkval(:,:,:,:,:,:),d2asr(:,:,:,:,:)
2177 29 : real(dp),allocatable :: instrain(:,:),zeff(:,:,:),qdrp_cart(:,:,:,:)
2178 58 : real(dp),pointer :: atmfrc_red(:,:,:,:,:),wghatm_red(:,:,:)
2179 : character(len=500) :: message
2180 29 : type(asrq0_t) :: asrq0
2181 174 : type(ifc_type) :: ifc
2182 29 : real(dp),allocatable :: d2cart(:,:,:,:,:),displ(:)
2183 58 : real(dp),allocatable :: eigval(:,:),eigvec(:,:,:,:,:),phfrq(:)
2184 29 : real(dp),allocatable :: spinat(:,:),tnons(:,:)
2185 29 : integer,allocatable :: symrel(:,:,:),symafm(:),ptsymrel(:,:,:)
2186 : ! *************************************************************************
2187 :
2188 : !0 MPI variables
2189 29 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2190 : iam_master=.FALSE.
2191 29 : iam_master = (my_rank == master)
2192 :
2193 : !Free the eff_pot before filling
2194 29 : call effective_potential_free(effective_potential)
2195 :
2196 : !Initialisation of usefull values
2197 29 : natom = ddb%natom
2198 29 : nblok = ddb%nblok
2199 29 : mpert= ddb%mpert
2200 29 : msize=3*mpert*3*mpert;
2201 :
2202 : !Tranfert the ddb into usable array (ipert and idir format like in abinit)
2203 174 : ABI_MALLOC(blkval,(2,3,mpert,3,mpert,nblok))
2204 :
2205 4992469 : blkval = 0
2206 116 : if(size(ddb%val) /= 2*3*mpert*3*mpert*nblok ) then
2207 0 : ABI_BUG("Size of ddb%val is not consistent.")
2208 : endif
2209 203 : blkval = reshape(ddb%val,(/2,3,mpert,3,mpert,nblok/))
2210 :
2211 :
2212 : !**********************************************************************
2213 : ! Transfert crystal values
2214 : !**********************************************************************
2215 : ! Re-generate symmetry operations from the lattice and atomic coordinates
2216 87 : ABI_MALLOC(spinat,(3,natom))
2217 87 : ABI_MALLOC(ptsymrel,(3,3,msym))
2218 87 : ABI_MALLOC(symafm,(msym))
2219 58 : ABI_MALLOC(symrel,(3,3,msym))
2220 87 : ABI_MALLOC(tnons,(3,msym))
2221 201085 : spinat = zero; symrel = 0; symafm = 0; tnons = zero ; space_group = 0;
2222 29 : call symlatt(bravais,std_out,msym,nptsym,ptsymrel,crystal%rprimd,tolsym)
2223 : call symfind(crystal%gprimd,msym,crystal%natom,nptsym,0,nsym,&
2224 : & 0,ptsymrel,spinat,symafm,symrel,tnons,tolsym,&
2225 29 : & crystal%typat,use_inversion,crystal%xred)
2226 29 : if(crystal%nsym/=nsym)then
2227 0 : write(message,'(4a,I0,3a,I0,3a)') ch10,&
2228 0 : & ' --- !WARNING:',ch10,&
2229 0 : & ' There is ',nsym,' found for the crystal',ch10,&
2230 0 : & ' but ',crystal%nsym,' found in the DDB',ch10,&
2231 0 : & ' ---'
2232 0 : call wrtout(std_out,message,'COLL')
2233 : end if
2234 : call effective_potential%crystal%init(ddb%amu,&
2235 : & space_group,crystal%natom,crystal%npsp,&
2236 : & crystal%ntypat,nsym,crystal%rprimd,&
2237 : & crystal%typat,crystal%xred,crystal%zion,&
2238 : & crystal%znucl,crystal%timrev,crystal%use_antiferro,&
2239 : & .FALSE.,crystal%title,&
2240 : & symrel=symrel,tnons=tnons,&
2241 29 : & symafm=symafm)
2242 :
2243 29 : ABI_FREE(spinat)
2244 29 : ABI_FREE(ptsymrel)
2245 29 : ABI_FREE(symafm)
2246 29 : ABI_FREE(symrel)
2247 29 : ABI_FREE(tnons)
2248 :
2249 : !**********************************************************************
2250 : ! Transfert energy from input file
2251 : !**********************************************************************
2252 2378 : write(message, '(2a,(80a),6a)') ch10,('=',ii=1,80),ch10,ch10,&
2253 2407 : & ' Extraction of the energy of the structure (unit: Hartree)',ch10
2254 29 : call wrtout(std_out,message,'COLL')
2255 29 : call wrtout(ab_out,message,'COLL')
2256 29 : if (ddb%get_etotal(effective_potential%energy) == 0) then
2257 17 : if(abs(inp%energy_reference) < tol16)then
2258 : write(message,'(5a)')&
2259 0 : & ' Warning : Energy of the reference structure is not specify in',&
2260 0 : & ' the input file.',ch10,' Energy will set to zero',ch10
2261 0 : call wrtout(std_out,message,'COLL')
2262 0 : effective_potential%energy = zero
2263 : else
2264 17 : effective_potential%energy = inp%energy_reference
2265 : end if
2266 : else
2267 12 : if(abs(inp%energy_reference) > tol16)then
2268 : write(message,'(6a)')&
2269 1 : & ' Warning : Energy of the reference structure is specify in',&
2270 1 : & ' the input file.',ch10,' and in the DDB.',&
2271 2 : & ' The value of the energy is set with the value from the input file',ch10
2272 1 : call wrtout(std_out,message,'COLL')
2273 1 : effective_potential%energy = inp%energy_reference
2274 : end if
2275 : end if
2276 29 : write(message,'(a,es25.12)') ' Energy = ',&
2277 58 : & effective_potential%energy
2278 29 : call wrtout(std_out,message,'COLL')
2279 29 : call wrtout(ab_out,message,'COLL')
2280 :
2281 : !**********************************************************************
2282 : ! Dielectric Tensor and Effective Charges
2283 : !**********************************************************************
2284 87 : ABI_MALLOC(zeff,(3,3,natom))
2285 87 : ABI_MALLOC(qdrp_cart,(3,3,3,natom))
2286 58 : ABI_MALLOC(effective_potential%harmonics_terms%zeff,(3,3,natom))
2287 :
2288 29 : rftyp = 1 ! Blocks obtained by a non-stationary formulation.
2289 29 : chneut = 1 ! The ASR for effective charges is imposed
2290 29 : selectz = 0 ! No selection of some parts of the effective charge tensor
2291 29 : iblok = ddb%get_dielt_zeff(crystal,rftyp,chneut,selectz,dielt,zeff)
2292 6109 : qdrp_cart = zero
2293 377 : if (iblok /=0 .and. maxval(abs(dielt)) < 10000) then
2294 247 : effective_potential%harmonics_terms%epsilon_inf = dielt
2295 1364 : effective_potential%harmonics_terms%zeff = zeff
2296 : else
2297 10 : effective_potential%harmonics_terms%epsilon_inf(1,1) = one
2298 10 : effective_potential%harmonics_terms%epsilon_inf(2,2) = one
2299 10 : effective_potential%harmonics_terms%epsilon_inf(3,3) = one
2300 660 : effective_potential%harmonics_terms%zeff = zero
2301 : end if
2302 :
2303 : !**********************************************************************
2304 : ! Look after the blok no. that contains the stress tensor
2305 : !**********************************************************************
2306 2378 : write(message, '(a,a,(80a),a,a,a,a,a)') ch10,('=',ii=1,80),ch10,ch10,&
2307 2407 : & ' Extraction of the stress tensor (unit: GPa) and forces (unit: Ha/bohr)'
2308 29 : call wrtout(std_out,message,'COLL')
2309 29 : call wrtout(ab_out,message,'COLL')
2310 :
2311 58 : ABI_MALLOC(effective_potential%fcart,(3,natom))
2312 637 : effective_potential%fcart = zero
2313 203 : effective_potential%strten = zero
2314 :
2315 116 : qphon(:,1)=zero
2316 29 : qphnrm(1)=zero
2317 87 : rfphon(1:2)=0
2318 87 : rfelfd(1:2)=0
2319 87 : rfstrs(1:2)=0
2320 29 : rftyp=4
2321 :
2322 29 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
2323 :
2324 29 : if (iblok /=0) then
2325 84 : if(any(abs(inp%strten_reference)>tol16))then
2326 0 : write(message,'(10a)') ch10,&
2327 0 : & ' --- !WARNING:',ch10,&
2328 0 : & ' The stress tensor of the reference structure is specify in the',ch10,&
2329 0 : & ' input file and in the DDB. The value of the stress tensor is set',ch10,&
2330 0 : & ' with the value from the input file',ch10,&
2331 0 : & ' ---'
2332 0 : call wrtout(std_out,message,'COLL')
2333 0 : call wrtout(ab_out,message,'COLL')
2334 0 : effective_potential%strten = inp%strten_reference
2335 : else
2336 : ! firts give the corect stress values store in hartree
2337 : ! diagonal parts
2338 12 : effective_potential%strten(1)=blkval(1,1,natom+3,1,1,iblok) * crystal%ucvol
2339 12 : effective_potential%strten(2)=blkval(1,2,natom+3,1,1,iblok) * crystal%ucvol
2340 12 : effective_potential%strten(3)=blkval(1,3,natom+3,1,1,iblok) * crystal%ucvol
2341 : ! the shear parts
2342 12 : effective_potential%strten(4)=blkval(1,1,natom+4,1,1,iblok) * crystal%ucvol
2343 12 : effective_potential%strten(5)=blkval(1,2,natom+4,1,1,iblok) * crystal%ucvol
2344 12 : effective_potential%strten(6)=blkval(1,3,natom+4,1,1,iblok) * crystal%ucvol
2345 : end if
2346 : ! Get forces
2347 308 : effective_potential%fcart(:,1:natom) = blkval(1,:,1:natom,1,1,iblok)
2348 : else
2349 119 : if(all(abs(inp%strten_reference(:))<tol16))then
2350 17 : write(message,'(8a)') ch10,&
2351 17 : & ' --- !WARNING:',ch10,&
2352 17 : & ' The stress tensor of the reference structure is not specify',ch10,&
2353 17 : & ' The stress tensor will be set to zero',ch10,&
2354 34 : & ' ---'
2355 17 : call wrtout(std_out,message,'COLL')
2356 17 : call wrtout(ab_out,message,'COLL')
2357 119 : effective_potential%strten = zero
2358 : else
2359 0 : effective_potential%strten = inp%strten_reference
2360 : end if
2361 : end if
2362 :
2363 131 : if(any(abs(effective_potential%strten(:)) >tol16))then
2364 12 : write(message, '(3a)' )ch10,&
2365 24 : & ' Cartesian components of forces (hartree/bohr)',ch10
2366 12 : call wrtout(ab_out,message,'COLL')
2367 12 : call wrtout(std_out, message,'COLL')
2368 86 : do ii = 1, natom
2369 : write(message, '(I4,a,3(e16.8))' ) &
2370 74 : & ii,' ',effective_potential%fcart(:,ii)
2371 :
2372 74 : call wrtout(ab_out,message,'COLL')
2373 86 : call wrtout(std_out, message,'COLL')
2374 : end do
2375 :
2376 12 : write(message, '(a,a)' )ch10,&
2377 24 : & ' Cartesian components of stress tensor (hartree/bohr^3)'
2378 12 : call wrtout(ab_out,message,'COLL')
2379 12 : call wrtout(std_out, message,'COLL')
2380 : write(message, '(a,1p,e16.8,a,1p,e16.8)' ) &
2381 12 : & ' sigma(1 1)=',effective_potential%strten(1) / crystal%ucvol,&
2382 24 : & ' sigma(3 2)=',effective_potential%strten(4) / crystal%ucvol
2383 12 : call wrtout(ab_out,message,'COLL')
2384 12 : call wrtout(std_out, message,'COLL')
2385 : write(message, '(a,1p,e16.8,a,1p,e16.8)' ) &
2386 12 : & ' sigma(2 2)=',effective_potential%strten(2) / crystal%ucvol,&
2387 24 : & ' sigma(3 1)=',effective_potential%strten(5) / crystal%ucvol
2388 12 : call wrtout(ab_out,message,'COLL')
2389 12 : call wrtout(std_out, message,'COLL')
2390 : write(message, '(a,1p,e16.8,a,1p,e16.8)' ) &
2391 12 : & ' sigma(3 3)=',effective_potential%strten(3) / crystal%ucvol,&
2392 24 : & ' sigma(2 1)=',effective_potential%strten(6) / crystal%ucvol
2393 12 : call wrtout(ab_out,message,'COLL')
2394 12 : call wrtout(std_out, message,'COLL')
2395 12 : write(message, '(a)' ) ' '
2396 12 : call wrtout(ab_out,message,'COLL')
2397 12 : call wrtout(std_out, message,'COLL')
2398 : end if
2399 :
2400 : !**********************************************************************
2401 : ! Elastic tensors at Gamma Point
2402 : !**********************************************************************
2403 2378 : write(message, '(a,a,(80a),a,a,a,a,a,a)') ch10,('=',ii=1,80),ch10,ch10,&
2404 2407 : & ' Extraction of the clamped elastic tensor (unit:10^2GPa)',ch10
2405 29 : call wrtout(std_out,message,'COLL')
2406 29 : call wrtout(ab_out,message,'COLL')
2407 :
2408 : ! look after the blok no.iblok that contains the elastic tensor
2409 116 : qphon(:,1)=zero
2410 29 : qphnrm(1)=zero
2411 87 : rfphon(1:2)=0
2412 87 : rfelfd(1:2)=0
2413 87 : rfstrs(1:2)=3 ! Need uniaxial both stresses and shear stresses
2414 29 : rftyp=1 ! Blocks obtained by a non-stationary formulation.
2415 : ! for both diagonal and shear parts
2416 29 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
2417 :
2418 29 : if (iblok /=0) then
2419 : ! extraction of the elastic constants from the blkvals (GPa)
2420 203 : do ivarA=1,6
2421 1247 : do ivarB=1,6
2422 : ! because the elastic constant is 6*6,
2423 : ! so we should judge if the idir is larger than 3
2424 : ! or not
2425 1044 : if(ivarA>3) then
2426 522 : idir1=ivarA-3
2427 522 : ipert1=natom+4 !for the shear modulus
2428 : else if(ivarA<=3) then
2429 522 : idir1=ivarA
2430 522 : ipert1=natom+3 !for the diagonal part
2431 : end if
2432 1044 : if(ivarB>3) then
2433 522 : idir2=ivarB-3
2434 522 : ipert2=natom+4 !for the shear modulus
2435 : else if(ivarB<=3) then
2436 522 : idir2=ivarB
2437 522 : ipert2=natom+3 !for the diagonal part
2438 : end if
2439 1218 : elast_clamped(ivarA,ivarB) = blkval(1,idir1,ipert1,idir2,ipert2,iblok)
2440 : end do
2441 : end do
2442 29 : fact=HaBohr3_GPa / crystal%ucvol
2443 203 : do ivarA=1,6
2444 174 : write(message,'(6f12.7)')elast_clamped(ivarA,1)*fact/100.00_dp,&
2445 174 : & elast_clamped(ivarA,2)*fact/100.00_dp,&
2446 174 : & elast_clamped(ivarA,3)*fact/100.00_dp,&
2447 174 : & elast_clamped(ivarA,4)*fact/100.00_dp,&
2448 174 : & elast_clamped(ivarA,5)*fact/100.00_dp,&
2449 348 : & elast_clamped(ivarA,6)*fact/100.00_dp
2450 174 : call wrtout(std_out,message,'COLL')
2451 203 : call wrtout(ab_out,message,'COLL')
2452 : end do
2453 :
2454 : ! Set the clamped tensor into the effective potentiel
2455 1247 : effective_potential%harmonics_terms%elastic_constants = elast_clamped
2456 :
2457 : else
2458 :
2459 0 : write(message,'(3a)')ch10,&
2460 0 : & ' Warning : Elastic Tensor is set to zero (not available in the DDB)'
2461 0 : call wrtout(std_out,message,'COLL')
2462 0 : call wrtout(ab_out,message,'COLL')
2463 :
2464 : ! Set the clamped tensor to zero into the effective potentiel (not available in the DDB)
2465 0 : effective_potential%harmonics_terms%elastic_constants = zero
2466 : end if
2467 :
2468 : !**********************************************************************
2469 : ! Acoustic Sum Rule
2470 : !***************************************************************************
2471 : ! ASR-correction (d2asr) has to be determined here from the Dynamical matrix at Gamma.
2472 145 : ABI_MALLOC(d2asr,(2,3,natom,3,natom))
2473 :
2474 2378 : write(message, '(a,a,(80a),a,a,a,a,a,a)') ch10,('=',ii=1,80),ch10,ch10,&
2475 2407 : & ' Calculation of acoustic sum rule',ch10
2476 29 : call wrtout(std_out,message,'COLL')
2477 29 : call wrtout(ab_out,message,'COLL')
2478 :
2479 : ! Find the Gamma block in the DDB (no need for E-field entries)
2480 116 : qphon(:,1)=zero
2481 29 : qphnrm(1)=zero
2482 87 : rfphon(1:2)=1
2483 29 : rfelfd(:)=0
2484 29 : rfstrs(:)=0
2485 29 : rftyp=inp%rfmeth
2486 :
2487 29 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
2488 :
2489 31477 : d2asr = zero
2490 29 : if (iblok /=0) then
2491 29 : call asria_calc(inp%asr,d2asr,ddb%val(:,:,iblok),ddb%mpert,ddb%natom)
2492 : end if
2493 :
2494 : ! Acoustic sum rule imposition (not yet applied)
2495 29 : call asrq0%init(ddb, inp%asr, inp%rfmeth, crystal, inp%sys_dim)
2496 :
2497 : !**********************************************************************
2498 : ! Interatomic Forces Calculation
2499 : !**********************************************************************
2500 : ! ifc to be calculated for interpolation
2501 2378 : write(message, '(a,a,(80a),a,a,a,a)' ) ch10,('=',ii=1,80),ch10,ch10,&
2502 2407 : & ' Calculation of the interatomic forces from DDB',ch10
2503 29 : call wrtout(std_out,message,'COLL')
2504 29 : call wrtout(ab_out,message,'COLL')
2505 :
2506 : call ifc%init(crystal,ddb,inp%brav,inp%asr,inp%symdynmat,inp%dipdip,inp%rfmeth,&
2507 : & inp%ngqpt(1:3),inp%nqshft,inp%q1shft,dielt,effective_potential%harmonics_terms%zeff,qdrp_cart,&
2508 29 : & inp%nsphere,inp%rifcsph,inp%prtsrlr,inp%enunit,inp%sys_dim,comm)
2509 : !***************************************************************************
2510 : ! Interpolation of the dynamical matrix for each qpoint from ifc
2511 : !***************************************************************************
2512 :
2513 116 : ABI_MALLOC(d2cart,(2,3,mpert,3,mpert))
2514 87 : ABI_MALLOC(displ,(2*3*natom*3*natom))
2515 58 : ABI_MALLOC(eigval,(3,natom))
2516 87 : ABI_MALLOC(eigvec,(2,3,natom,3,natom))
2517 87 : ABI_MALLOC(phfrq,(3*natom))
2518 :
2519 145 : ABI_MALLOC(effective_potential%harmonics_terms%dynmat,(2,3,natom,3,natom,inp%nph1l))
2520 116 : ABI_MALLOC(effective_potential%harmonics_terms%phfrq,(3*natom,inp%nph1l))
2521 87 : ABI_MALLOC(effective_potential%harmonics_terms%qpoints,(3,inp%nph1l))
2522 :
2523 2378 : write(message,'(a,(80a),3a)')ch10,('=',ii=1,80),ch10,ch10,&
2524 2407 : & ' Calculation of dynamical matrix for each ph1l points '
2525 29 : call wrtout(ab_out,message,'COLL')
2526 29 : call wrtout(std_out,message,'COLL')
2527 :
2528 : !Transfer value in effective_potential structure
2529 29 : effective_potential%harmonics_terms%nqpt = inp%nph1l
2530 369 : effective_potential%harmonics_terms%qpoints(:,:) = inp%qph1l(:,:)
2531 :
2532 : ! Store the highest frequency
2533 29 : max_phfq = zero
2534 :
2535 114 : do iphl1=1,inp%nph1l
2536 :
2537 : ! Initialisation of the phonon wavevector
2538 340 : qphon(:,1)=inp%qph1l(:,iphl1)
2539 85 : if (inp%nph1l /= 0) qphnrm(1) = inp%qnrml1(iphl1)
2540 :
2541 : ! Get d2cart using the interatomic forces and the
2542 : ! long-range coulomb interaction through Ewald summation
2543 : call gtdyn9(ddb%acell,ifc%atmfrc,ifc%dielt,ifc%dipdip,ifc%dyewq0,d2cart,crystal%gmet,&
2544 : & ddb%gprim,mpert,natom,ifc%nrpt,qphnrm(1),qphon(:,1),crystal%rmet,ddb%rprim,ifc%rpt,&
2545 : & ifc%trans,crystal%ucvol,ifc%wghatm,crystal%xred,zeff,qdrp_cart,ifc%ewald_option,eta,&
2546 85 : & xmpi_comm_self,ifc%sys_dim)
2547 :
2548 : ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
2549 : call dfpt_phfrq(ddb%amu,displ,d2cart,eigval,eigvec,crystal%indsym,&
2550 : & mpert,crystal%nsym,natom,crystal%nsym,crystal%ntypat,phfrq,qphnrm(1),qphon,&
2551 85 : & crystal%rprimd,inp%symdynmat,crystal%symrel,crystal%symafm,crystal%typat,crystal%ucvol)
2552 :
2553 : ! Write the phonon frequencies
2554 85 : call dfpt_prtph(displ,inp%eivec,inp%enunit,ab_out,natom,phfrq,qphnrm(1),qphon)
2555 :
2556 : ! Store the highest frequency in cmm-1
2557 1298 : max_phfq = max(maxval(phfrq*Ha_cmm1),max_phfq)
2558 :
2559 59309 : effective_potential%harmonics_terms%dynmat(:,:,:,:,:,iphl1) = d2cart(:,:,:natom,:,:natom)
2560 1242 : effective_potential%harmonics_terms%phfrq(:,iphl1) = phfrq(:) * Ha_cmm1
2561 :
2562 : end do
2563 :
2564 29 : write(message, '(2a,f15.7,a)' ) ch10,&
2565 58 : & ' The highest frequency found is ',max_phfq,' cm-1'
2566 29 : call wrtout(std_out,message,'COLL')
2567 :
2568 29 : ABI_FREE(d2cart)
2569 29 : ABI_FREE(displ)
2570 29 : ABI_FREE(eigval)
2571 29 : ABI_FREE(eigvec)
2572 29 : ABI_FREE(phfrq)
2573 :
2574 : !**********************************************************************
2575 : ! Transfert inter-atomic forces constants in reduced coordinates
2576 : !**********************************************************************
2577 :
2578 : !Reorder cell from canonical coordinates to reduced coordinates (for multibinit)
2579 : !store the number of ifc before rearrangement
2580 :
2581 : ! Store the sum of the weight of IFC for the final check
2582 29 : wcount1 = 0
2583 5112 : do irpt=1,ifc%nrpt
2584 166452 : wcount1 = wcount1 + sum(ifc%wghatm(:,:,irpt))
2585 : end do
2586 :
2587 : !Set the maximum and the miminum for the bound of the cell
2588 10195 : max1 = maxval(ifc%cell(1,:)); min1 = minval(ifc%cell(1,:))
2589 10195 : max2 = maxval(ifc%cell(2,:)); min2 = minval(ifc%cell(2,:))
2590 10195 : max3 = maxval(ifc%cell(3,:)); min3 = minval(ifc%cell(3,:))
2591 29 : cell_number(1) = max1 - min1 + 1
2592 29 : cell_number(2) = max2 - min2 + 1
2593 29 : cell_number(3) = max3 - min3 + 1
2594 :
2595 : ! set the new number of cell, sometimes, in canonical coordinates,
2596 : ! some cell are delete but they exist in reduced coordinates.
2597 116 : nrpt_new = product(cell_number(:))
2598 :
2599 : ! Allocate temporary array
2600 174 : ABI_MALLOC(atmfrc_red,(3,natom,3,natom,nrpt_new))
2601 145 : ABI_MALLOC(wghatm_red,(natom,natom,nrpt_new))
2602 87 : ABI_MALLOC(cell_red,(3,nrpt_new))
2603 :
2604 169320 : wghatm_red(:,:,:) = zero
2605 :
2606 29 : if(iam_master)then
2607 137 : do ia=1,natom
2608 1001 : do ib=1,natom
2609 :
2610 : ! Simple Lattice
2611 864 : if (inp%brav==1) then
2612 : ! In this case, it is better to work in reduced coordinates
2613 : ! As rcan is in canonical coordinates, => multiplication by gprim
2614 3456 : do ii=1,3
2615 : red(1,ii)= ifc%rcan(1,ia)*ddb%gprim(1,ii) + &
2616 : & ifc%rcan(2,ia)*ddb%gprim(2,ii) + &
2617 2592 : & ifc%rcan(3,ia)*ddb%gprim(3,ii)
2618 : red(2,ii)= ifc%rcan(1,ib)*ddb%gprim(1,ii) + &
2619 : ifc%rcan(2,ib)*ddb%gprim(2,ii) + &
2620 3456 : & ifc%rcan(3,ib)*ddb%gprim(3,ii)
2621 : end do
2622 : end if
2623 :
2624 : ! Get the shift of cell
2625 3456 : shift(:) = int(anint(red(2,:) - crystal%xred(:,ib)) - anint(red(1,:) - crystal%xred(:,ia)))
2626 :
2627 133224 : do irpt=1,ifc%nrpt
2628 :
2629 528976 : cell2(:)= int(ifc%cell(:,irpt) + shift(:))
2630 :
2631 : ! Use boundary condition to get the right cell
2632 132244 : if (cell2(1) < min1 .and. cell2(1) < max1) then
2633 915 : cell2(1) = cell2(1) + cell_number(1)
2634 131329 : else if (cell2(1) > min1 .and. cell2(1) > max1) then
2635 915 : cell2(1) = cell2(1) - cell_number(1)
2636 : end if
2637 :
2638 132244 : if (cell2(2) < min2 .and. cell2(2) < max2) then
2639 960 : cell2(2) = cell2(2) + cell_number(2)
2640 131284 : else if (cell2(2) > min2 .and. cell2(2) > max2) then
2641 960 : cell2(2) = cell2(2) - cell_number(2)
2642 : end if
2643 :
2644 132244 : if (cell2(3) < min3 .and. cell2(3) < max3) then
2645 948 : cell2(3) = cell2(3) + cell_number(3)
2646 131296 : else if (cell2(3) > min3 .and. cell2(3) > max3) then
2647 948 : cell2(3) = cell2(3) - cell_number(3)
2648 : end if
2649 :
2650 : irpt2=1
2651 1198440 : do i1=min1,max1
2652 10360972 : do i2=min2,max2
2653 91175516 : do i3=min3,max3
2654 : if (i1 == cell2(1) .and.&
2655 80946788 : i2 == cell2(2) .and.&
2656 : i3 == cell2(3)) then
2657 132244 : wghatm_red(ia,ib,irpt2) = ifc%wghatm(ia,ib,irpt)
2658 1719172 : atmfrc_red(:,ia,:,ib,irpt2) = ifc%atmfrc(:,ia,:,ib,irpt)
2659 132244 : cell_red(1,irpt2) = i1
2660 132244 : cell_red(2,irpt2) = i2
2661 132244 : cell_red(3,irpt2) = i3
2662 : end if
2663 90110184 : irpt2 = irpt2 + 1
2664 : end do
2665 : end do
2666 : end do
2667 : end do
2668 : end do
2669 : end do
2670 : end if
2671 :
2672 29 : call xmpi_bcast(atmfrc_red,master, comm, ierr)
2673 29 : call xmpi_bcast(wghatm_red,master, comm, ierr)
2674 29 : call xmpi_bcast(cell_red,master, comm, ierr)
2675 :
2676 : ! Copy ifc into effective potential
2677 : ! !!Warning eff_pot%ifcs only contains atmfrc,short_atmfrc,ewald_atmfrc,,nrpt and cell!!
2678 : ! rcan,ifc%rpt,wghatm and other quantities
2679 : ! are not needed for effective potential!!!
2680 29 : call ifc%free()
2681 29 : call effective_potential%harmonics_terms%ifcs%free()
2682 :
2683 : ! Only conserve the necessary points in rpt
2684 29 : nrpt_new2 = 0
2685 5220 : do irpt = 1, nrpt_new
2686 169320 : if (abs(sum(wghatm_red(:,:,irpt))) >tol16) then
2687 5003 : nrpt_new2 = nrpt_new2 + 1
2688 : end if
2689 : end do
2690 :
2691 : ! Set the new number of rpt
2692 29 : effective_potential%harmonics_terms%ifcs%nrpt = nrpt_new2
2693 :
2694 : ! Allocation of the final arrays
2695 174 : ABI_MALLOC(effective_potential%harmonics_terms%ifcs%atmfrc,(3,natom,3,natom,nrpt_new2))
2696 116 : ABI_MALLOC(effective_potential%harmonics_terms%ifcs%short_atmfrc,(3,natom,3,natom,nrpt_new2))
2697 116 : ABI_MALLOC(effective_potential%harmonics_terms%ifcs%ewald_atmfrc,(3,natom,3,natom,nrpt_new2))
2698 87 : ABI_MALLOC(effective_potential%harmonics_terms%ifcs%cell,(3,nrpt_new2))
2699 145 : ABI_MALLOC(effective_potential%harmonics_terms%ifcs%wghatm,(natom,natom,nrpt_new2))
2700 :
2701 29 : irpt2 = 0
2702 5220 : do irpt = 1,nrpt_new
2703 169320 : if (abs(sum(wghatm_red(:,:,irpt))) > tol16) then
2704 5003 : irpt2 = irpt2 + 1
2705 : ! Apply weight on each R point
2706 30335 : do ia=1,effective_potential%crystal%natom
2707 164743 : do ib=1,effective_potential%crystal%natom
2708 1772636 : atmfrc_red(:,ia,:,ib,irpt) = atmfrc_red(:,ia,:,ib,irpt)*wghatm_red(ia,ib,irpt)
2709 : end do
2710 : end do
2711 20012 : effective_potential%harmonics_terms%ifcs%cell(:,irpt2) = cell_red(:,irpt)
2712 1719227 : effective_potential%harmonics_terms%ifcs%atmfrc(:,:,:,:,irpt2) = atmfrc_red(:,:,:,:,irpt)
2713 5003 : if (inp%dipdip == 1) then
2714 : effective_potential%harmonics_terms%ifcs%short_atmfrc(:,:,:,:,irpt2)=&
2715 1520030 : & atmfrc_red(:,:,:,:,irpt)
2716 : else
2717 199197 : effective_potential%harmonics_terms%ifcs%short_atmfrc(:,:,:,:,irpt2) = zero
2718 : end if
2719 1719227 : effective_potential%harmonics_terms%ifcs%short_atmfrc(:,:,:,:,irpt2)=atmfrc_red(:,:,:,:,irpt)
2720 1719227 : effective_potential%harmonics_terms%ifcs%ewald_atmfrc(:,:,:,:,irpt2) = zero
2721 164743 : effective_potential%harmonics_terms%ifcs%wghatm(:,:,irpt2) = wghatm_red(:,:,irpt)
2722 : end if
2723 : end do
2724 :
2725 :
2726 29 : ABI_FREE(atmfrc_red)
2727 29 : ABI_FREE(wghatm_red)
2728 29 : ABI_FREE(cell_red)
2729 :
2730 : ! Final check
2731 29 : wcount2 = 0
2732 5032 : do irpt = 1, effective_potential%harmonics_terms%ifcs%nrpt
2733 164772 : wcount2 = wcount2 + sum(effective_potential%harmonics_terms%ifcs%wghatm(:,:,irpt))
2734 : end do
2735 :
2736 29 : if (abs(wcount1-wcount2)/(wcount1+wcount2)>tol8) then
2737 0 : write(message,'(2a,es15.4,a,es15.4,a,es15.4)')'The total wghatm has changed',ch10,&
2738 0 : & wcount1,' before and ', wcount2, ' now, difference being ',wcount1-wcount2
2739 0 : ABI_BUG(message)
2740 : end if
2741 :
2742 :
2743 : !**********************************************************************
2744 : ! Internal strain tensors at Gamma point
2745 : !**********************************************************************
2746 2378 : write(message, '(a,a,(80a),a,a,a)') ch10,('=',ii=1,80),ch10,ch10,&
2747 2407 : & ' Calculation of the internal-strain tensor'
2748 29 : call wrtout(std_out,message,'COLL')
2749 29 : call wrtout(ab_out,message,'COLL')
2750 116 : ABI_MALLOC(instrain,(3*natom,6))
2751 : ! looking after the no. of blok that contains the internal strain tensor
2752 116 : qphon(:,1)=zero
2753 29 : qphnrm(1)=zero
2754 87 : rfphon(1:2)=0
2755 : rfelfd(1:2)=0
2756 87 : rfstrs(1:2)=3
2757 29 : rftyp=1
2758 29 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
2759 :
2760 87 : ABI_MALLOC(effective_potential%harmonics_terms%strain_coupling,(6,3,natom))
2761 3373 : effective_potential%harmonics_terms%strain_coupling = zero
2762 :
2763 29 : if (iblok /=0) then
2764 :
2765 : ! then print the internal strain tensor (only the force one)
2766 29 : prt_internalstr=1
2767 : call ddb_internalstr(inp%asr,ddb%val,d2asr,iblok,instrain,&
2768 29 : & ab_out,mpert,natom,nblok,prt_internalstr)
2769 :
2770 203 : do ipert1=1,6
2771 1115 : do ipert2=1,natom
2772 3822 : do idir2=1,3
2773 2736 : ii=3*(ipert2-1)+idir2
2774 : effective_potential%harmonics_terms%strain_coupling(ipert1,idir2,ipert2)=&
2775 3648 : & (-1.0_dp)*instrain(ii,ipert1)
2776 : end do
2777 : end do
2778 : end do
2779 : else
2780 0 : write(message,'(3a)')ch10,&
2781 0 : & ' Warning : Internal strain is set to zero (not available in the DDB)'
2782 0 : call wrtout(std_out,message,'COLL')
2783 0 : call wrtout(ab_out,message,'COLL')
2784 : end if
2785 : !-------------------------------------------------------------------------------------
2786 : ! DEALLOCATION OF ARRAYS
2787 29 : ABI_FREE(blkval)
2788 29 : ABI_FREE(zeff)
2789 29 : ABI_FREE(qdrp_cart)
2790 29 : ABI_FREE(instrain)
2791 29 : ABI_FREE(d2asr)
2792 29 : call asrq0%free()
2793 :
2794 29 : write(message,'(a)')ch10
2795 29 : call wrtout(std_out,message,'COLL')
2796 29 : call wrtout(ab_out,message,'COLL')
2797 :
2798 87 : end subroutine system_ddb2effpot
2799 : !!***
2800 :
2801 : !!****f* m_effective_potential_file/coeffs_xml2effpot
2802 : !! NAME
2803 : !! coeffs_xml2effpot
2804 : !!
2805 : !! FUNCTION
2806 : !! Open xml file of effective potentiel, then reads the variables
2807 : !! and store them in effective potentential type
2808 : !!
2809 : !! INPUTS
2810 : !! filename = path of input or output file
2811 : !! comm=MPI communicator
2812 : !!
2813 : !! OUTPUT
2814 : !! eff_pot<type(effective_potential_type)> = effective_potential datatype
2815 : !!
2816 : !! SOURCE
2817 :
2818 28 : subroutine coeffs_xml2effpot(eff_pot,filename,comm)
2819 :
2820 29 : use m_atomdata
2821 : use m_polynomial_coeff
2822 : use m_polynomial_term
2823 : use m_crystal, only : symbols_crystal
2824 : #if defined HAVE_XML
2825 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_PTR,c_f_pointer
2826 : #endif
2827 :
2828 : !Arguments ------------------------------------
2829 : !scalars
2830 : character(len=*),intent(in) :: filename
2831 : integer, intent(in) :: comm
2832 : !arrays
2833 : type(effective_potential_type), intent(inout) :: eff_pot
2834 :
2835 : !Local variables-------------------------------
2836 : !scalar
2837 : integer :: ii,jj,my_rank,ndisp,ncoeff,nterm_max,nstrain,ndisp_max,nproc,nterm
2838 : ! character(len=200),allocatable :: name(:)
2839 : character(len=200) :: name
2840 : #ifdef HAVE_XML
2841 : integer :: icoeff,iterm
2842 : #endif
2843 :
2844 : #ifndef HAVE_XML
2845 : integer :: funit = 1,ios = 0
2846 : integer :: icoeff,idisp,istrain,iterm,mu
2847 : logical :: found,found2,displacement
2848 : character (len=XML_RECL) :: line,readline
2849 : character (len=XML_RECL) :: strg,strg1
2850 : #endif
2851 : character(len=500) :: message
2852 : character(len=264) :: filename_tmp
2853 28 : character(len=5),allocatable :: symbols(:)
2854 : integer,parameter :: master=0
2855 : logical :: iam_master
2856 : logical :: debug
2857 : !arrays
2858 28 : real(dp),allocatable :: coefficient(:),weight(:,:)
2859 28 : integer,allocatable :: atindx(:,:,:,:), cell(:,:,:,:,:),direction(:,:,:),power_disp(:,:,:)
2860 28 : integer,allocatable :: strain(:,:,:),power_strain(:,:,:)
2861 28 : type(polynomial_coeff_type),dimension(:),allocatable :: coeffs
2862 28 : type(polynomial_term_type),dimension(:,:),allocatable :: terms
2863 : ! *************************************************************************
2864 :
2865 28 : filename_tmp = trim(filename)
2866 : !Open the atomicdata XML file for reading
2867 28 : write(message,'(a,a)')'-Opening the file ',trim(filename_tmp)
2868 :
2869 28 : call wrtout(ab_out,message,'COLL')
2870 28 : call wrtout(std_out,message,'COLL')
2871 :
2872 28 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2873 28 : iam_master = (my_rank == master)
2874 :
2875 : !Get Dimention of system and allocation/initialisation of array
2876 : ncoeff = 0
2877 28 : nterm = 0
2878 28 : ndisp = 0
2879 28 : nstrain = 0
2880 28 : call effective_potential_file_getDimCoeff(filename,ncoeff,ndisp_max,nterm_max)
2881 :
2882 : ! Do some checks
2883 28 : if (nterm_max<=0) then
2884 : write(message, '(a,a,a)' )&
2885 0 : & ' Unable to read the number of terms in ',trim(filename),ch10
2886 0 : ABI_ERROR(message)
2887 : end if
2888 :
2889 28 : if (ndisp_max<=0) then
2890 : write(message, '(a,a,a)' )&
2891 0 : & ' Unable to read the number of displacement in ',trim(filename),ch10
2892 0 : ABI_ERROR(message)
2893 : end if
2894 :
2895 : !Allocation ov the polynomial coeff type
2896 1886 : ABI_MALLOC(coeffs,(ncoeff))
2897 :
2898 28 : if(iam_master)then
2899 :
2900 : #if defined HAVE_XML
2901 : write(message,'(3a)')'-Reading the file ',trim(filename),&
2902 : & ' with LibXML library'
2903 : #else
2904 20 : write(message,'(3a)')'-Reading the file ',trim(filename),&
2905 40 : & ' with Fortran'
2906 : #endif
2907 20 : call wrtout(ab_out,message,'COLL')
2908 20 : call wrtout(std_out,message,'COLL')
2909 :
2910 :
2911 60 : ABI_MALLOC(symbols,(eff_pot%crystal%natom))
2912 : ! Get the symbols arrays
2913 : call symbols_crystal(eff_pot%crystal%natom,eff_pot%crystal%ntypat,&
2914 20 : & eff_pot%crystal%npsp,symbols,eff_pot%crystal%typat,eff_pot%crystal%znucl)
2915 :
2916 :
2917 : !Read with libxml librarie
2918 : #if defined HAVE_XML
2919 :
2920 : ABI_MALLOC(terms,(ncoeff,nterm_max))
2921 : ABI_MALLOC(atindx,(ncoeff,nterm_max,2,ndisp_max))
2922 : ABI_MALLOC(coefficient,(ncoeff))
2923 : ABI_MALLOC(cell,(ncoeff,nterm_max,3,2,ndisp_max))
2924 : ABI_MALLOC(direction,(ncoeff,nterm_max,ndisp_max))
2925 : ABI_MALLOC(strain,(ncoeff,nterm_max,ndisp_max))
2926 : ABI_MALLOC(power_disp,(ncoeff,nterm_max,ndisp_max))
2927 : ABI_MALLOC(power_strain,(ncoeff,nterm_max,ndisp_max))
2928 : ABI_MALLOC(weight,(ncoeff,nterm_max))
2929 :
2930 : ! Read the values of this term with libxml
2931 : call effpot_xml_readCoeff(char_f2c(trim(filename)),ncoeff,ndisp_max,nterm_max,&
2932 : & coefficient,atindx,cell,direction,power_disp,power_strain,&
2933 : & strain,weight)
2934 : ! In the XML the atom index begin to zero
2935 : ! Need to shift for fortran array
2936 : atindx(:,:,:,:) = atindx(:,:,:,:) + 1
2937 :
2938 : do icoeff=1,ncoeff
2939 : do iterm=1,nterm_max
2940 : ! Initialisation of the polynomial_term structure with the values from the
2941 : call polynomial_term_init(atindx(icoeff,iterm,:,:),cell(icoeff,iterm,:,:,:),&
2942 : & direction(icoeff,iterm,:),ndisp_max,ndisp_max,terms(icoeff,iterm),&
2943 : & power_disp(icoeff,iterm,:),power_strain(icoeff,iterm,:),&
2944 : & strain(icoeff,iterm,:),weight(icoeff,iterm),check=.true.)
2945 : end do
2946 : ! Initialisation of the polynomial_coefficent structure with the values
2947 : call polynomial_coeff_init(coefficient(icoeff),nterm_max,coeffs(icoeff),&
2948 : & terms(icoeff,:), check=.true., debug_str="init from xml")
2949 : ! Set the name of the coefficient
2950 :
2951 : ! Get the name of this coefficient and set it
2952 : ! Try to find the index of the term corresponding to the interation in the
2953 : ! reference cell (000) in order to compute the name correctly...
2954 : ! If this coeff is not in the ref cell, take by default the first term
2955 : if(coeffs(icoeff)%nterm > 0)then
2956 : call polynomial_coeff_getName(name,coeffs(icoeff),symbols,recompute=.true.)
2957 : call polynomial_coeff_setName(name,coeffs(icoeff))
2958 : end if
2959 :
2960 : ! Free them all
2961 : do iterm=1,nterm_max
2962 : call polynomial_term_free(terms(icoeff,iterm))
2963 : end do
2964 : end do
2965 :
2966 : #else
2967 1884 : ABI_MALLOC(terms,(1,nterm_max))
2968 60 : ABI_MALLOC(atindx,(1,1,2,ndisp_max))
2969 20 : ABI_MALLOC(coefficient,(1))
2970 60 : ABI_MALLOC(cell,(1,1,3,2,ndisp_max))
2971 60 : ABI_MALLOC(direction,(1,1,ndisp_max))
2972 40 : ABI_MALLOC(strain,(1,1,ndisp_max))
2973 40 : ABI_MALLOC(power_disp,(1,1,ndisp_max))
2974 40 : ABI_MALLOC(power_strain,(1,1,ndisp_max))
2975 20 : ABI_MALLOC(weight,(1,1))
2976 : ! Loop over the file
2977 : ! Read the values of all the terms with fortran
2978 20 : if (open_file(filename,message,unit=funit,form="formatted",&
2979 : & status="old",action="read") /= 0) then
2980 0 : ABI_ERROR(message)
2981 : end if
2982 :
2983 : ! Start a reading loop in fortran
2984 20 : rewind(unit=funit)
2985 20 : ios = 0
2986 20 : found=.false.
2987 :
2988 : ! Initialisation of counter
2989 20 : icoeff = 0
2990 :
2991 : ! Parser
2992 4966 : do while (ios==0)
2993 4946 : read(funit,'(a)',iostat=ios) readline
2994 4966 : if (ios == 0) then
2995 4926 : call rmtabfromline(readline)
2996 4926 : line=adjustl(readline)
2997 4926 : if ((line(1:12)==char(60)//'coefficient')) then
2998 : ! Read headers of coefficient
2999 1770 : call rdfromline('text',line,strg)
3000 1770 : if (strg/="") then
3001 1770 : name=trim(strg)
3002 : end if
3003 1770 : call rdfromline('value',line,strg)
3004 1770 : if (strg/="") then
3005 1754 : strg1=trim(strg)
3006 1754 : read(strg1,*) coefficient(1)
3007 : else
3008 16 : coefficient(1) = zero
3009 : end if
3010 : ! End read headers of coefficient
3011 : ! Reset counter
3012 8833 : found = .false.
3013 220723 : atindx = 0; cell = 0 ; direction = 0
3014 65337 : strain = 0; power_strain = 0; power_disp = 0
3015 1770 : iterm = 0
3016 1770 : idisp = 0
3017 1770 : istrain = 0
3018 1770 : nterm = 0
3019 : do while (.not.found)
3020 48012 : read(funit,'(a)',iostat=ios) readline
3021 48012 : call rmtabfromline(readline)
3022 48012 : line=adjustl(readline)
3023 48012 : if ((line(1:13)==char(60)//'/coefficient')) then
3024 : found= .true.
3025 : cycle
3026 : end if
3027 46242 : if ((line(1:5)==char(60)//'term')) then
3028 46242 : nterm = nterm + 1
3029 46242 : ndisp = 0
3030 46242 : nstrain = 0
3031 46242 : idisp = 0
3032 46242 : istrain = 0
3033 46242 : displacement = .true.
3034 46242 : call rdfromline('weight',line,strg)
3035 46242 : if (strg/="") then
3036 46242 : strg1=trim(strg)
3037 46242 : read(strg1,*) weight
3038 : end if
3039 214908 : do while(displacement)
3040 168666 : read(funit,'(a)',iostat=ios) readline
3041 168666 : call rmtabfromline(readline)
3042 168666 : line=adjustl(readline)
3043 168666 : if ((line(1:6)==char(60)//'/term')) then
3044 46242 : displacement = .false.
3045 : end if
3046 168666 : if ((line(1:7)==char(60)//'strain')) then
3047 14682 : nstrain = nstrain + 1
3048 14682 : istrain = istrain + 1
3049 14682 : call rdfromline('power',line,strg)
3050 14682 : if (strg/="") then
3051 14682 : strg1=trim(strg)
3052 14682 : read(strg1,*) power_strain(1,1,istrain)
3053 : end if
3054 14682 : call rdfromline('voigt',line,strg)
3055 14682 : if (strg/="") then
3056 14682 : strg1=trim(strg)
3057 14682 : read(strg1,*) strain(1,1,istrain)
3058 : end if
3059 : end if
3060 214908 : if ((line(1:18)==char(60)//'displacement_diff')) then
3061 107742 : ndisp = ndisp + 1
3062 107742 : idisp = idisp + 1
3063 107742 : found2=.true.
3064 107742 : call rdfromline('atom_a',line,strg)
3065 107742 : if (strg/="") then
3066 107742 : strg1=trim(strg)
3067 107742 : read(strg1,*) atindx(1,1,1,idisp)
3068 : end if
3069 107742 : call rdfromline('atom_b',line,strg)
3070 107742 : if (strg/="") then
3071 107742 : strg1=trim(strg)
3072 107742 : read(strg1,*) atindx(1,1,2,idisp)
3073 : end if
3074 107742 : call rdfromline('direction',line,strg)
3075 107742 : if (strg/="") then
3076 107742 : strg1=trim(strg)
3077 107742 : if (trim(strg1).eq."x") direction(1,1,idisp) = 1
3078 107742 : if (trim(strg1).eq."y") direction(1,1,idisp) = 2
3079 107742 : if (trim(strg1).eq."z") direction(1,1,idisp) = 3
3080 : end if
3081 107742 : call rdfromline('power',line,strg)
3082 107742 : if (strg/="") then
3083 107742 : strg1=trim(strg)
3084 107742 : read(strg1,*) power_disp(1,1,idisp)
3085 : end if
3086 : do while(found2)
3087 323226 : read(funit,'(a)',iostat=ios) readline
3088 323226 : call rmtabfromline(readline)
3089 323226 : line=adjustl(readline)
3090 323226 : if ((line(1:7)==char(60)//'cell_a')) then
3091 107742 : call rdfromline_value('cell_a',line,strg)
3092 107742 : if (strg/="") then
3093 107742 : strg1=trim(strg)
3094 107742 : read(strg1,*) (cell(1,1,mu,1,idisp),mu=1,3)
3095 : else
3096 0 : read(funit,'(a)',iostat=ios) readline
3097 0 : call rmtabfromline(readline)
3098 0 : line=adjustl(readline)
3099 0 : call rdfromline_value('cell_a',line,strg)
3100 0 : if (strg/="") then
3101 0 : strg1=trim(strg)
3102 0 : read(strg1,*)(cell(1,1,mu,1,idisp),mu=1,3)
3103 : else
3104 0 : strg1=trim(line)
3105 0 : read(strg1,*)(cell(1,1,mu,1,idisp),mu=1,3)
3106 : end if
3107 : end if
3108 : end if
3109 323226 : if ((line(1:7)==char(60)//'cell_b')) then
3110 107742 : call rdfromline_value('cell_b',line,strg)
3111 107742 : if (strg/="") then
3112 107742 : strg1=trim(strg)
3113 107742 : read(strg1,*) (cell(1,1,mu,2,idisp),mu=1,3)
3114 : else
3115 0 : read(funit,'(a)',iostat=ios) readline
3116 0 : call rmtabfromline(readline)
3117 0 : line=adjustl(readline)
3118 0 : call rdfromline_value('cell_b',line,strg)
3119 0 : if (strg/="") then
3120 0 : strg1=trim(strg)
3121 0 : read(strg1,*)(cell(1,1,mu,2,idisp),mu=1,3)
3122 : else
3123 0 : strg1=trim(line)
3124 0 : read(strg1,*)(cell(1,1,mu,2,idisp),mu=1,3)
3125 : end if
3126 : end if
3127 : end if
3128 323226 : if ((line(1:19)==char(60)//'/displacement_diff')) then
3129 : found2=.false.
3130 : end if
3131 : end do
3132 : end if
3133 : end do!end do while displacement
3134 : ! In the XML the atom index begin to zero
3135 : ! Need to shift for fortran array
3136 599490 : atindx(1,1,:,:) = atindx(1,1,:,:) + 1
3137 : ! Initialisation of the polynomial_term structure with the values from the
3138 : ! previous step
3139 46242 : iterm = iterm + 1
3140 : call polynomial_term_init(atindx(1,1,:,:),cell(1,1,:,:,:),&
3141 : & direction(1,1,:),ndisp,nstrain,terms(1,iterm),&
3142 : & power_disp(1,1,:),power_strain(1,1,:),&
3143 46242 : & strain(1,1,:),weight(1,1),check=.true.)
3144 : end if!end if term
3145 : end do!end do while found (coeff)
3146 :
3147 : ! Initialisation of the polynomial_coefficent structure with the values from the
3148 : ! previous step
3149 1770 : icoeff = icoeff + 1
3150 1770 : call polynomial_coeff_init(coefficient(1),nterm,coeffs(icoeff),terms(1,:), debug_str="init from xml fortran", check=.true.)
3151 1770 : call polynomial_coeff_getName(name,coeffs(icoeff),symbols,recompute=.true.)
3152 1770 : call polynomial_coeff_setName(name,coeffs(icoeff))
3153 : ! Deallocation of the terms array for this coefficient
3154 84330 : do jj=1,nterm_max
3155 84330 : call polynomial_term_free(terms(1,jj))
3156 : end do
3157 : end if!end if line = coefficient
3158 : end if!end if ios==0
3159 : end do!end do while on file
3160 :
3161 20 : close(unit=funit)
3162 :
3163 : #endif
3164 932 : ABI_FREE(terms)
3165 20 : ABI_FREE(atindx)
3166 20 : ABI_FREE(coefficient)
3167 20 : ABI_FREE(cell)
3168 20 : ABI_FREE(direction)
3169 20 : ABI_FREE(strain)
3170 20 : ABI_FREE(power_disp)
3171 20 : ABI_FREE(power_strain)
3172 20 : ABI_FREE(weight)
3173 20 : ABI_FREE(symbols)
3174 : end if !End if master
3175 :
3176 : !9-MPI BROADCAST
3177 1830 : do ii=1,ncoeff
3178 1830 : call polynomial_coeff_broadcast(coeffs(ii),master, comm)
3179 : end do
3180 :
3181 : !10-checks
3182 :
3183 : !11-debug print
3184 28 : debug = .FALSE.
3185 : if(debug)then
3186 : do ii=1,ncoeff
3187 : do jj=1,coeffs(ii)%nterm
3188 : #if defined HAVE_XML
3189 : write(200+my_rank,*)"ii,jj,ndisp,nterm",ii,jj,coeffs(ii)%nterm,coeffs(ii)%terms(jj)%ndisp
3190 : write(200+my_rank,*)"atindx",coeffs(ii)%terms(jj)%atindx
3191 : write(200+my_rank,*)"cell1",coeffs(ii)%terms(jj)%cell(:,1,:)
3192 : write(200+my_rank,*)"cell2",coeffs(ii)%terms(jj)%cell(:,2,:)
3193 : write(200+my_rank,*)"direction",coeffs(ii)%terms(jj)%direction
3194 : write(200+my_rank,*)"power_disp",coeffs(ii)%terms(jj)%power_disp
3195 : write(200+my_rank,*)"weight",coeffs(ii)%terms(jj)%weight
3196 : #else
3197 : write(300+my_rank,*)"ii,jj,ndisp,nterm",ii,jj,coeffs(ii)%nterm,coeffs(ii)%terms(jj)%ndisp
3198 : write(300+my_rank,*)"atindx",coeffs(ii)%terms(jj)%atindx
3199 : write(300+my_rank,*)"cell1",coeffs(ii)%terms(jj)%cell(:,1,:)
3200 : write(300+my_rank,*)"cell2",coeffs(ii)%terms(jj)%cell(:,2,:)
3201 : write(300+my_rank,*)"direction",coeffs(ii)%terms(jj)%direction
3202 : write(300+my_rank,*)"power_disp",coeffs(ii)%terms(jj)%power_disp
3203 : write(300+my_rank,*)"weight",coeffs(ii)%terms(jj)%weight
3204 : #endif
3205 : end do
3206 : end do
3207 : #if defined HAVE_XML
3208 : close(200+my_rank)
3209 : #else
3210 : close(300+my_rank)
3211 : #endif
3212 : end if
3213 :
3214 : !12-Initialisation of eff_pot
3215 28 : call effective_potential_setCoeffs(coeffs,eff_pot,ncoeff)
3216 :
3217 : !13-Deallocation of type
3218 1830 : do ii=1,ncoeff
3219 1830 : call polynomial_coeff_free(coeffs(ii))
3220 : end do
3221 1830 : ABI_FREE(coeffs)
3222 :
3223 :
3224 84 : end subroutine coeffs_xml2effpot
3225 : !!***
3226 :
3227 : !!****f* m_effective_potential_file/effective_potential_file_readMDfile
3228 : !!
3229 : !! NAME
3230 : !! effective_potential_file_readMDfile
3231 : !!
3232 : !! FUNCTION
3233 : !! Read MD FILE (HIST or ASCII)
3234 : !!
3235 : !! INPUTS
3236 : !! filename = path of the file
3237 : !! option,optional = 0 (default), the stress is printed in the MD File
3238 : !! 1, the force on the cell is printed in the MD File (-1 * stress),
3239 : !! in this case, we multiply the stress by -1 in order to get the stresse
3240 : !!
3241 : !! OUTPUT
3242 : !! hist<type(abihist)> = datatype with the history of the MD
3243 : !!
3244 : !! SOURCE
3245 :
3246 13 : subroutine effective_potential_file_readMDfile(filename,hist,option)
3247 :
3248 : !Arguments ------------------------------------
3249 : !scalars
3250 : integer,optional :: option
3251 : !arrays
3252 : type(abihist),intent(inout) :: hist
3253 : character(len=fnlen),intent(in) :: filename
3254 : !Local variables-------------------------------
3255 : !scalar
3256 : integer :: ia,ii,mu,nu,natom,nstep,type,option_in
3257 : integer :: ios=0, unit_md=24
3258 : !arrays
3259 : character (len=10000) :: readline,line
3260 : real(dp) :: tmp(6)
3261 13 : real(dp),allocatable :: xcart(:,:)
3262 : ! *************************************************************************
3263 :
3264 13 : call effective_potential_file_getType(filename,type)
3265 :
3266 13 : option_in = 0
3267 : if(present(option))then
3268 : option_in = option
3269 : end if
3270 13 : if(type==40)then
3271 : ! Netcdf type
3272 13 : call read_md_hist(filename,hist,.FALSE.,.FALSE.,.FALSE.)
3273 :
3274 0 : else if(type==41)then
3275 :
3276 : ! ASCII file
3277 0 : call effective_potential_file_getDimMD(filename,natom,nstep)
3278 :
3279 0 : ii = 1
3280 0 : ios = 0
3281 :
3282 0 : ABI_MALLOC(xcart,(3,natom))
3283 0 : call abihist_free(hist)
3284 0 : call abihist_init(hist,natom,nstep,.FALSE.,.FALSE.)
3285 :
3286 : ! Start a reading loop in fortran
3287 0 : rewind(unit=unit_md)
3288 0 : do while ((ios==0).and.ii<=nstep)
3289 0 : read(unit_md,'(a)',iostat=ios) readline
3290 0 : read(unit_md,'(a)',iostat=ios) readline
3291 0 : line=adjustl(readline)
3292 0 : read(line,*) hist%etot(ii)
3293 : hist%etot(ii) = hist%etot(ii)
3294 0 : do mu=1,3
3295 0 : read(unit_md,'(a)',iostat=ios) readline
3296 0 : line=adjustl(readline)
3297 0 : read(line,*) (hist%rprimd(nu,mu,ii),nu=1,3)
3298 : end do
3299 0 : do ia=1,natom
3300 0 : read(unit_md,'(a)',iostat=ios) readline
3301 0 : line=adjustl(readline)
3302 0 : read(line,*) (tmp(mu),mu=1,6)
3303 0 : xcart(:,ia) = tmp(1:3)
3304 0 : hist%fcart(:,ia,ii) = tmp(4:6)
3305 : end do
3306 0 : call xcart2xred(natom,hist%rprimd(:,:,ii),xcart(:,:),hist%xred(:,:,ii))
3307 0 : read(unit_md,'(a)',iostat=ios) readline
3308 0 : line=adjustl(readline)
3309 0 : read(line,*) (hist%strten(mu,ii),mu=1,6)
3310 0 : ii = ii + 1
3311 : end do
3312 0 : do ii=1,nstep
3313 0 : do mu=1,3
3314 0 : hist%acell(mu,:) = hist%rprimd(mu,mu,ii)
3315 : end do
3316 : end do
3317 0 : close(unit_md)
3318 0 : ABI_FREE(xcart)
3319 :
3320 : end if!end if type
3321 :
3322 13 : if((type==40 .or. type==41).and.option == 1)then
3323 : ! multiply by -1 if the current strten -1*stress, we need only stress...
3324 0 : hist%strten(:,:) = -1 * hist%strten(:,:)
3325 : end if
3326 :
3327 :
3328 :
3329 28 : end subroutine effective_potential_file_readMDfile
3330 : !!***
3331 :
3332 : !!****f* m_effective_potential_file/effective_potential_file_mapHistToRef
3333 : !!
3334 : !! NAME
3335 : !! effective_potential_file_mapHistToRef
3336 : !!
3337 : !! FUNCTION
3338 : !! Generate the supercell in the effective potential according to the size of the
3339 : !! supercell in the hist file
3340 : !! Check if the hist file match to reference supercell in the effective potential
3341 : !! If not, the hist file is reordering
3342 : !!
3343 : !! INPUTS
3344 : !! eff_pot<type(effective_potential)> = effective potential
3345 : !! hist<type(abihist)> = The history of the MD
3346 : !! comm = MPI communicator
3347 : !!
3348 : !! OUTPUT
3349 : !! hist<type(abihist)> = The history of the MD
3350 : !!
3351 : !! SOURCE
3352 :
3353 34 : subroutine effective_potential_file_mapHistToRef(eff_pot,hist,comm,iatfix,verbose,sc_size)
3354 :
3355 : !Arguments ------------------------------------
3356 : !scalars
3357 : integer,intent(in) :: comm
3358 : logical,optional,intent(in) :: verbose
3359 : !arrays
3360 : type(effective_potential_type),intent(inout) :: eff_pot
3361 : type(abihist),intent(inout) :: hist
3362 : integer,optional,allocatable,intent(inout) :: iatfix(:,:)
3363 : integer,optional,intent(in) :: sc_size(3)
3364 : !Local variables-------------------------------
3365 : !scalar
3366 : integer :: factE_hist,ia,ib,ii,jj,natom_hist,ncells,nstep_hist
3367 : real(dp):: factor,ratio
3368 : logical :: revelant_factor,need_map,need_verbose,need_fixmap
3369 : !arrays
3370 : real(dp) :: rprimd_hist(3,3),rprimd_ref(3,3)
3371 : integer :: ncell(3),scale_cell(3)
3372 34 : integer,allocatable :: shift(:,:),iatfix_tmp(:,:)
3373 34 : integer,allocatable :: list_map(:) !blkval(:),
3374 34 : real(dp),allocatable :: xred_ref(:,:) ! xred_hist(:,:),
3375 34 : real(dp),allocatable :: list_dist(:),list_reddist(:,:),list_absdist(:,:)
3376 : character(len=500) :: msg
3377 34 : type(abihist) :: hist_tmp
3378 : ! *************************************************************************
3379 :
3380 : !Set optional values
3381 34 : need_verbose = .false.
3382 34 : need_fixmap = .FALSE.
3383 34 : if (present(verbose)) need_verbose = verbose
3384 34 : if (present(iatfix)) need_fixmap = .TRUE.
3385 :
3386 :
3387 34 : natom_hist = size(hist%xred,2)
3388 34 : nstep_hist = size(hist%xred,3)
3389 :
3390 : ! Try to set the supercell according to the hist file
3391 442 : rprimd_ref(:,:) = eff_pot%crystal%rprimd
3392 442 : rprimd_hist(:,:) = hist%rprimd(:,:,1)
3393 :
3394 :
3395 34 : if(present(sc_size))then
3396 12 : ncell(:) = sc_size
3397 : else
3398 88 : do ia=1,3
3399 66 : scale_cell(:) = 0
3400 264 : do ii=1,3
3401 264 : if(abs(rprimd_ref(ii,ia)) > tol10)then
3402 66 : scale_cell(ii) = nint(rprimd_hist(ii,ia) / rprimd_ref(ii,ia))
3403 : end if
3404 : end do
3405 : ! Check if the factor for the supercell is revelant
3406 66 : revelant_factor = .TRUE.
3407 264 : do ii=1,3
3408 198 : if(abs(scale_cell(ii)) < tol10) cycle
3409 66 : factor = abs(scale_cell(ii))
3410 264 : do jj=ii,3
3411 132 : if(abs(scale_cell(jj)) < tol10) cycle
3412 396 : if(abs(abs(scale_cell(ii))-abs(scale_cell(jj))) > tol10) revelant_factor = .FALSE.
3413 : end do
3414 : end do
3415 88 : if(.not.revelant_factor)then
3416 : write(msg, '(3a)' )&
3417 0 : & 'unable to map the hist file ',ch10,&
3418 0 : & 'Action: check/change your MD file'
3419 0 : ABI_ERROR(msg)
3420 : else
3421 66 : ncell(ia) = int(factor)
3422 : end if
3423 : end do
3424 : end if
3425 :
3426 136 : ncells = product(ncell)
3427 :
3428 : !Check if the energy stored in the hist is revelant, sometimes some MD files gives
3429 : !the energy of the unit cell... This is not suppose to happen... But just in case...
3430 705 : do ii=1,nstep_hist
3431 705 : if(abs(eff_pot%energy)>tol12)then
3432 671 : ratio=hist%etot(ii) / eff_pot%energy
3433 671 : if(abs(ratio)<real(huge(factE_hist))*half)then
3434 671 : factE_hist = nint(ratio)
3435 671 : if(factE_hist == 1) then
3436 : ! In this case we mutiply the energy of the hist by the number of cell
3437 0 : hist%etot(ii) = hist%etot(ii) * ncells
3438 : end if
3439 671 : if(factE_hist /=1 .and. factE_hist /= ncells)then
3440 31 : write(msg, '(4a,I0,a,I0,2a,I0,3a,I0,3a)' )ch10,&
3441 31 : & ' --- !WARNING',ch10,&
3442 31 : & ' The energy of the history step ',ii,' seems to be with multiplicity of ',factE_hist,ch10,&
3443 31 : & ' However, the multiplicity of the cell is ',ncells,'.',ch10,&
3444 31 : & ' Please check the energy of the step ',ii,ch10,&
3445 62 : & ' ---',ch10
3446 31 : if(need_verbose) call wrtout(std_out,msg,'COLL')
3447 : endif
3448 : else
3449 0 : write(msg, '(4a,i0,3a,es16.6,5a)' )ch10,&
3450 0 : & ' --- !WARNING',ch10,&
3451 0 : & ' The energy of the history step ',ii,' is apparently not initialized.',ch10,&
3452 0 : & ' Its current value is',hist%etot(ii),ch10,&
3453 0 : & ' This does not allow to perform checking on the multiplicity of the cell ',ch10,&
3454 0 : & ' ---',ch10
3455 0 : if(need_verbose) call wrtout(std_out,msg,'COLL')
3456 : end if
3457 : end if
3458 : end do
3459 :
3460 :
3461 : !Set the new supercell datatype into the effective potential reference
3462 34 : call effective_potential_setSupercell(eff_pot,comm,ncell)
3463 :
3464 : !allocation
3465 102 : ABI_MALLOC(shift,(3,natom_hist))
3466 102 : ABI_MALLOC(list_map,(natom_hist))
3467 102 : ABI_MALLOC(list_reddist,(3,natom_hist))
3468 68 : ABI_MALLOC(list_absdist,(3,natom_hist))
3469 102 : ABI_MALLOC(list_dist,(natom_hist))
3470 68 : ABI_MALLOC(xred_ref,(3,natom_hist))
3471 :
3472 : !Putting maping list to zero
3473 1534 : list_map = 0
3474 :
3475 : !Fill xcart_ref/hist and xred_ref/hist
3476 :
3477 : call xcart2xred(eff_pot%supercell%natom,eff_pot%supercell%rprimd,&
3478 34 : & eff_pot%supercell%xcart,xred_ref) ! Get xred_ref
3479 :
3480 :
3481 1534 : do ia=1,natom_hist !Loop over all reference atoms
3482 : ! Put temporary lists to zero
3483 310300 : list_reddist = 0
3484 310300 : list_absdist = 0
3485 78700 : list_dist = 0
3486 310300 : shift = 0
3487 78700 : do ib=1,natom_hist !Loop over all atoms of distorted structure
3488 : !Calculate list of reduced distance between reference atom ia and all others
3489 308800 : list_reddist(:,ib) = hist%xred(:,ib,1) - xred_ref(:,ia)
3490 : !If the distorted atom is further away than half the unit cell shift it.
3491 77200 : if(list_reddist(1,ib) > 0.5)then
3492 6439 : list_reddist(1,ib) = 1 - list_reddist(1,ib)
3493 6439 : shift(1,ib) = -1
3494 : end if
3495 77200 : if(list_reddist(2,ib) > 0.5)then
3496 6370 : list_reddist(2,ib) = 1 - list_reddist(2,ib)
3497 6370 : shift(2,ib) = -1
3498 : end if
3499 77200 : if(list_reddist(3,ib) > 0.5)then
3500 2541 : list_reddist(3,ib) = 1 - list_reddist(3,ib)
3501 2541 : shift(3,ib) = -1
3502 : end if
3503 77200 : if(list_reddist(1,ib) < -0.5)then
3504 9714 : list_reddist(1,ib) = -1 - list_reddist(1,ib)
3505 9714 : shift(1,ib) = 1
3506 : end if
3507 77200 : if(list_reddist(2,ib) < -0.5)then
3508 9410 : list_reddist(2,ib) = -1 - list_reddist(2,ib)
3509 9410 : shift(2,ib) = 1
3510 : end if
3511 77200 : if(list_reddist(3,ib) < -0.5)then
3512 4543 : list_reddist(3,ib) = -1 - list_reddist(3,ib)
3513 4543 : shift(3,ib) = 1
3514 : end if
3515 77200 : list_absdist(1,ib) = (rprimd_hist(1,1)+rprimd_hist(2,1)+rprimd_hist(3,1))*list_reddist(1,ib)
3516 77200 : list_absdist(2,ib) = (rprimd_hist(1,2)+rprimd_hist(2,2)+rprimd_hist(3,2))*list_reddist(2,ib)
3517 77200 : list_absdist(3,ib) = (rprimd_hist(1,3)+rprimd_hist(2,3)+rprimd_hist(3,3))*list_reddist(3,ib)
3518 78700 : list_dist(ib) = sqrt(abs(list_absdist(1,ib))**2 + abs(list_absdist(2,ib))**2 + abs(list_absdist(3,ib))**2 )
3519 : end do !ib
3520 : !find the closest atom ib
3521 78700 : list_map(ia) = minloc(list_dist,DIM=1)
3522 : !If the closest atom ib was shifted, apply and store the shift
3523 6018 : if(any(shift(:,list_map(ia)) /= 0))then
3524 16 : hist%xred(1,list_map(ia),:)= hist%xred(1,list_map(ia),:) + 1*shift(1,list_map(ia))
3525 16 : hist%xred(2,list_map(ia),:)= hist%xred(2,list_map(ia),:) + 1*shift(2,list_map(ia))
3526 16 : hist%xred(3,list_map(ia),:)= hist%xred(3,list_map(ia),:) + 1*shift(3,list_map(ia))
3527 : end if
3528 : !TEST MS
3529 : !write(*,*) 'Atom', ia,' of reference is matche with', list_map(ia)
3530 : !write(*,*) 'xred_ref(',xred_ref(:,ia),'), xred_hist(',hist%(:,list_map(ia)),')'
3531 : end do ! ia
3532 :
3533 34 : if(need_verbose) then
3534 13 : write(msg,'(2a,I3,a,I3,a,I3)') ch10,&
3535 26 : & ' The size of the supercell for the fit is ',ncell(1),' ',ncell(2),' ',ncell(3)
3536 13 : call wrtout(std_out,msg,'COLL')
3537 13 : call wrtout(ab_out,msg,'COLL')
3538 : end if
3539 :
3540 :
3541 1534 : if(any(list_map(:)==0))then
3542 : write(msg, '(5a)' )&
3543 0 : & 'Unable to map the molecular dynamic file ',ch10,&
3544 0 : & 'on the reference supercell structure',ch10,&
3545 0 : & 'Action: change the MD file'
3546 0 : ABI_ERROR(msg)
3547 : end if
3548 :
3549 34 : need_map = .FALSE.
3550 1534 : do ia=1,natom_hist
3551 1534 : if(list_map(ia) /= ia) need_map = .TRUE.
3552 : end do
3553 34 : if(need_map)then
3554 21 : if(need_verbose) then
3555 1 : write(msg, '(11a)' )ch10,&
3556 1 : & ' --- !WARNING',ch10,&
3557 1 : & ' The ordering of the atoms in the _HIST.nc file is different,',ch10,&
3558 1 : & ' of the one built by multibinit. The _HIST.nc file will be mapped,',ch10,&
3559 1 : & ' to the ordering of multibinit.',ch10,&
3560 2 : & ' ---',ch10
3561 1 : call wrtout(ab_out,msg,'COLL')
3562 1 : call wrtout(std_out,msg,'COLL')
3563 : end if
3564 :
3565 : ! Allocate hist datatype
3566 21 : call abihist_init(hist_tmp,natom_hist,nstep_hist,.false.,.false.)
3567 : ! copy all the information
3568 512 : do ia=1,nstep_hist
3569 491 : hist%ihist = ia
3570 491 : hist_tmp%ihist = ia
3571 512 : call abihist_copy(hist,hist_tmp)
3572 : end do
3573 21 : hist_tmp%mxhist = nstep_hist
3574 :
3575 : ! reoder array
3576 861 : do ia=1,natom_hist
3577 79400 : hist_tmp%xred(:,ia,:) = hist%xred(: ,list_map(ia),:)
3578 79400 : hist_tmp%fcart(:,ia,:) = hist%fcart(:,list_map(ia),:)
3579 79421 : hist_tmp%vel(:,ia,:) = hist%vel(:,list_map(ia),:)
3580 : end do
3581 :
3582 : ! free the old hist and reinit
3583 21 : call abihist_free(hist)
3584 21 : call abihist_init(hist,natom_hist,nstep_hist,.false.,.false.)
3585 : ! copy the temporary hist into output
3586 512 : do ia=1,nstep_hist
3587 491 : hist%ihist = ia
3588 491 : hist_tmp%ihist = ia
3589 512 : call abihist_copy(hist_tmp,hist)
3590 : end do
3591 : hist_tmp%mxhist = nstep_hist
3592 21 : call abihist_free(hist_tmp)
3593 :
3594 : !map also fixes if present
3595 21 : if(need_fixmap)then
3596 2 : ABI_MALLOC(iatfix_tmp,(3,natom_hist))
3597 41 : do ia=1,natom_hist
3598 161 : iatfix_tmp(:,ia) = iatfix(:,list_map(ia))
3599 : end do
3600 162 : iatfix = iatfix_tmp
3601 1 : ABI_FREE(iatfix_tmp)
3602 : end if
3603 : end if !need map
3604 :
3605 : !deallocation
3606 34 : ABI_FREE(shift)
3607 34 : ABI_FREE(list_map)
3608 34 : ABI_FREE(list_dist)
3609 34 : ABI_FREE(list_reddist)
3610 34 : ABI_FREE(list_absdist)
3611 34 : ABI_FREE(xred_ref)
3612 34 : end subroutine effective_potential_file_mapHistToRef
3613 : !!***
3614 :
3615 :
3616 : !****f* m_effective_potential_file/effective_potential_file_readDisplacement
3617 : !!
3618 : !! NAME
3619 : !! effective_potential_file_readDisplacement
3620 : !!
3621 : !! FUNCTION
3622 : !! Read a displacement ASCII file
3623 : !!
3624 : !! INPUTS
3625 : !! filename = path of the file
3626 : !! natom = number of atoms in the cell
3627 : !! nstep = number of time step
3628 : !!
3629 : !! OUTPUT
3630 : !! disp(3,natom_sc) = atomics displacement between configuration and the reference
3631 : !!
3632 : !! SOURCE
3633 :
3634 0 : subroutine effective_potential_file_readDisplacement(filename,disp,nstep,natom)
3635 :
3636 : !Arguments ------------------------------------
3637 : !scalars
3638 : integer, intent(in) :: natom,nstep
3639 : character(len=fnlen),intent(in) :: filename
3640 : !array
3641 : real(dp),intent(out) :: disp(nstep,3,natom)
3642 : !Local variables------------------------------
3643 : !scalars
3644 : integer :: ios = 0
3645 : integer :: ia,istep,mu
3646 : character(500) :: message
3647 : character (len=500000) :: line,readline
3648 : integer :: funit = 666
3649 : ! *************************************************************************
3650 :
3651 0 : if (open_file(filename,message,unit=funit,form="formatted",&
3652 : status="old",action="read") /= 0) then
3653 0 : ABI_ERROR(message)
3654 : end if
3655 :
3656 0 : write(message, '(2a)' ) " Read displacements from ", trim(filename)
3657 :
3658 0 : call wrtout(ab_out,message,'COLL')
3659 0 : call wrtout(std_out,message,'COLL')
3660 0 : do istep=1,nstep
3661 0 : do ia=1,natom
3662 0 : read(funit,'(a)',iostat=ios) readline
3663 0 : line=adjustl(readline)
3664 0 : read(unit=line,fmt=*) (disp(istep,mu,ia),mu=1,3)
3665 0 : write(111,'(3(es21.12))') disp(istep,:,ia)
3666 : end do
3667 : end do
3668 :
3669 0 : close(funit)
3670 :
3671 0 : end subroutine effective_potential_file_readDisplacement
3672 : !!***
3673 :
3674 : !!****f* m_effective_potential_file/elementfromline
3675 : !! NAME
3676 : !! elementfromline
3677 : !!
3678 : !! FUNCTION
3679 : !! Read the number of element of a line
3680 : !!
3681 : !! INPUTS
3682 : !! line= string from which the data are read
3683 : !!
3684 : !! OUTPUT
3685 : !! nelement = number of element in the line
3686 : !!
3687 : !! SOURCE
3688 :
3689 0 : subroutine elementfromline(line,nelement)
3690 :
3691 : !Arguments ---------------------------------------------
3692 : character(len=*), intent(in) :: line
3693 : integer, intent(out) :: nelement
3694 : !Local variables ---------------------------------------
3695 : integer :: ii,n
3696 : logical :: element
3697 : ! *********************************************************************
3698 :
3699 : !Set the output
3700 0 : nelement = 0
3701 0 : n = len_trim(line)
3702 0 : element = .false.
3703 0 : do ii=1,n
3704 0 : if(.not.element.and.line(ii:ii) /="") then
3705 : element=.true.
3706 : else
3707 0 : if((element.and.line(ii:ii) =="")) then
3708 0 : element=.false.
3709 0 : nelement = nelement + 1
3710 : end if
3711 : end if
3712 0 : if((element.and.ii==n)) nelement = nelement + 1
3713 : end do
3714 :
3715 0 : end subroutine elementfromline
3716 : !!***
3717 :
3718 : !!****f* m_effective_potential_file/rdfromline
3719 : !! NAME
3720 : !! rdfromline
3721 : !!
3722 : !! FUNCTION
3723 : !! Read the value of a keyword from a XML line
3724 : !! Same function than m_pawxmlps/paw_rdfromline.F90
3725 : !!
3726 : !! INPUTS
3727 : !! keyword= keyword which value has to be read
3728 : !! line= string from which the data are read (line from a XML)
3729 : !!
3730 : !! OUTPUT
3731 : !! output= (string) value of the keyword
3732 : !!
3733 : !! SOURCE
3734 :
3735 511584 : subroutine rdfromline(keyword,line,output)
3736 :
3737 : !Arguments ---------------------------------------------
3738 : character(len=*), intent(in) :: keyword,line
3739 : character(len=*), intent(out) :: output
3740 : !Local variables ---------------------------------------
3741 511584 : character(len=len(line)) :: temp
3742 : integer :: pos,pos2
3743 :
3744 : ! *********************************************************************
3745 :
3746 511584 : output=""
3747 511584 : pos=index(line,trim(keyword))
3748 511584 : if (pos>0) then
3749 511568 : temp=line(pos+len_trim(keyword):len_trim(line))
3750 511568 : pos=index(temp,char(34))
3751 511568 : if (pos>0) then
3752 511568 : pos2=index(temp(pos+1:len_trim(temp)),char(34))
3753 511568 : if (pos2>0) then
3754 511568 : output=temp(pos+1:pos+pos2-1)
3755 : end if
3756 : end if
3757 : end if
3758 :
3759 511584 : end subroutine rdfromline
3760 : !!***
3761 :
3762 :
3763 : !!****f* m_effective_potential_file/rmtabfromline
3764 : !! NAME
3765 : !! rmtabfromline
3766 : !!
3767 : !! FUNCTION
3768 : !! Read remove tab from the begining of line
3769 : !!
3770 : !! INPUTS
3771 : !! line= string from which the data are read (line from a XML)
3772 : !!
3773 : !! OUTPUT
3774 : !! output= line without tab
3775 : !!
3776 : !! SOURCE
3777 :
3778 2062683 : recursive subroutine rmtabfromline(line)
3779 :
3780 : !Arguments ---------------------------------------------
3781 : character(len=*), intent(inout) :: line
3782 : !Local variables ---------------------------------------
3783 : integer :: pos
3784 :
3785 : ! *********************************************************************
3786 :
3787 2062764 : pos=index(line,char(9))
3788 2062764 : if (pos==1) then
3789 81 : line = line(2:len_trim(line))//" "
3790 : call rmtabfromline(line)
3791 : end if
3792 :
3793 2062764 : end subroutine rmtabfromline
3794 : !!***
3795 :
3796 :
3797 :
3798 : !!****f* m_effective_potential_file/rdfromline_value
3799 : !! NAME
3800 : !! rdfromline
3801 : !!
3802 : !! FUNCTION
3803 : !! Read the value of a keyword from a XML line
3804 : !!
3805 : !! INPUTS
3806 : !! keyword= keyword which value has to be read
3807 : !! line= string from which the data are read (line from a XML)
3808 : !!
3809 : !! OUTPUT
3810 : !! output= (string) value of the keyword
3811 : !!
3812 : !! SOURCE
3813 :
3814 218900 : subroutine rdfromline_value(keyword,line,output)
3815 :
3816 : !Arguments ---------------------------------------------
3817 : character(len=*), intent(in) :: keyword,line
3818 : character(len=*), intent(out) :: output
3819 : !Local variables ---------------------------------------
3820 218900 : character(len=len(line)) :: temp
3821 : integer :: pos,pos2
3822 :
3823 : ! *********************************************************************
3824 :
3825 218900 : output=""
3826 218900 : pos=index(line,trim(keyword))
3827 218900 : if (pos==2) then
3828 218548 : pos=pos+len_trim(keyword)
3829 218548 : pos=pos+index(line(pos:len_trim(line)),char(62))
3830 218548 : temp=line(pos:len_trim(line))
3831 218548 : pos2=index(temp,char(60))
3832 218548 : if (pos2>0) then
3833 215484 : output=line(pos:pos+pos2-2)
3834 : else
3835 3064 : output=line(pos:len_trim(line))
3836 : end if
3837 : else
3838 352 : if(pos>2)then
3839 0 : output=line(1:pos-3)
3840 : end if
3841 : end if
3842 218900 : end subroutine rdfromline_value
3843 : !!***
3844 :
3845 :
3846 : !!****f* m_effpot_xml/char_f2c
3847 : !! NAME
3848 : !! char_f_to_c
3849 : !!
3850 : !! FUNCTION
3851 : !! Helper function to convert a Fortran string to a C string
3852 : !! Based on a routine by Joseph M. Krahn
3853 : !!
3854 : !! INPUTS
3855 : !! f_string=Fortran string
3856 : !!
3857 : !! OUTPUT
3858 : !! c_string=C string
3859 : !!
3860 : !! SOURCE
3861 :
3862 : #if defined HAVE_XML
3863 :
3864 : function char_f2c(f_string) result(c_string)
3865 :
3866 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_NULL_CHAR
3867 : !Arguments ------------------------------------
3868 : character(len=*),intent(in) :: f_string
3869 : character(kind=C_CHAR,len=1) :: c_string(len_trim(f_string)+1)
3870 : !Local variables -------------------------------
3871 : integer :: ii,strlen
3872 : !! *************************************************************************
3873 : strlen=len_trim(f_string)
3874 : forall(ii=1:strlen)
3875 : c_string(ii)=f_string(ii:ii)
3876 : end forall
3877 : c_string(strlen+1)=C_NULL_CHAR
3878 : end function char_f2c
3879 : !!***
3880 :
3881 : !----------------------------------------------------------------------
3882 :
3883 : !!****f* m_effpot_xml/char_c2f
3884 : !! NAME
3885 : !! char_c_to_f
3886 : !!
3887 : !! FUNCTION
3888 : !! Helper function to convert a C string to a Fortran string
3889 : !! Based on a routine by Joseph M. Krahn
3890 : !!
3891 : !! INPUTS
3892 : !! c_string=C string
3893 : !!
3894 : !! OUTPUT
3895 : !! f_string=Fortran string
3896 : !!
3897 : !! SOURCE
3898 :
3899 : subroutine char_c2f(c_string,f_string)
3900 :
3901 : use, intrinsic :: iso_c_binding, only : C_CHAR,C_NULL_CHAR
3902 : !Arguments ------------------------------------
3903 : character(kind=C_CHAR,len=1),intent(in) :: c_string(*)
3904 : character(len=*),intent(out) :: f_string
3905 : !Local variables -------------------------------
3906 : integer :: ii
3907 : !! *************************************************************************
3908 : ii=1
3909 : do while(c_string(ii)/=C_NULL_CHAR.and.ii<=len(f_string))
3910 : f_string(ii:ii)=c_string(ii) ; ii=ii+1
3911 : end do
3912 : if (ii<len(f_string)) f_string(ii:)=' '
3913 : end subroutine char_c2f
3914 : !!***
3915 : #endif
3916 :
3917 : end module m_effective_potential_file
3918 : !!***
|