Branch data Line data Source code
1 : : !!****m*ABINIT/m_anaddb_driver
2 : : !! NAME
3 : : !! m_anaddb_driver
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 2014-2026 ABINIT group (GA)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! SOURCE
14 : :
15 : : #if defined HAVE_CONFIG_H
16 : : #include "config.h"
17 : : #endif
18 : :
19 : : #include "abi_common.h"
20 : :
21 : : module m_anaddb_driver
22 : :
23 : : use defs_basis
24 : : use m_abicore
25 : : use m_xmpi
26 : : use m_errors
27 : : use m_nctk
28 : : use netcdf
29 : : use m_ifc
30 : : use m_ddb_hdr
31 : : use m_phonons
32 : : use m_supercell
33 : : use m_raman
34 : :
35 : : use m_fstrings, only : strcat
36 : : use m_crystal, only : crystal_t
37 : : use m_anaddb_dataset, only : anaddb_dataset_type
38 : : use m_ddb, only : ddb_type, asrq0_t
39 : : use m_dynmat, only : gtdyn9, dfpt_phfrq, dfpt_prtph
40 : : use m_ddb_interpolate, only : ddb_interpolate
41 : : use m_harmonic_thermo, only : harmonic_thermo
42 : : use m_elphon, only : elphon
43 : : use m_thmeig, only : thmeig
44 : : use m_relaxpol, only : relaxpol
45 : : use m_ddb_diel, only : ddb_diel
46 : : use m_ddb_elast, only : ddb_elast
47 : : use m_ddb_piezo, only : ddb_piezo
48 : : use m_ddb_internalstr, only : ddb_internalstr
49 : : use m_gruneisen, only : gruns_anaddb
50 : : use m_ddb_flexo, only : ddb_flexo, ddb_phi1
51 : : use m_lwf, only : run_lattice_wannier
52 : :
53 : : implicit none
54 : :
55 : : private
56 : :
57 : : public:: anaddb_driver_type
58 : :
59 : : !----------------------------------------------------------------------
60 : :
61 : : !!****t* m_anaddb_driver/anaddb_driver_type
62 : : !! NAME
63 : : !! anaddb_driver_type
64 : : !!
65 : : !! FUNCTION
66 : : !! The anaddb_driver_type structured datatype
67 : : !! Main subroutines run by anaddb.
68 : : !!
69 : : !! SOURCE
70 : :
71 : : type anaddb_driver_type
72 : :
73 : : integer:: natom
74 : : integer:: msize
75 : : integer:: mpert
76 : :
77 : : logical:: do_ifc=.false.
78 : : logical:: do_electric_tensors=.false.
79 : : logical:: do_dielectric_q0=.false.
80 : : logical:: do_dielectric_nonana=.false.
81 : : logical:: do_phonon_dos=.false.
82 : : logical:: do_phonon_bs=.false.
83 : :
84 : : real(dp):: epsinf(3, 3)
85 : : real(dp):: dchide(3,3,3)
86 : : real(dp):: dielt_rlx(3, 3)
87 : : real(dp):: elast(6, 6)
88 : :
89 : : real(dp), allocatable:: d2cart(:,:)
90 : : ! d2cart(2,msize)
91 : :
92 : : real(dp), allocatable:: displ(:)
93 : : ! displ(2*3*natom*3*natom)
94 : :
95 : : real(dp), allocatable:: phfrq(:)
96 : : ! phfrq(3*natom)
97 : :
98 : : real(dp), allocatable:: instrain(:,:)
99 : : ! instrain(3*natom,6)
100 : :
101 : : real(dp), allocatable:: dchidt(:,:,:,:)
102 : : ! dchidt(natom,3,3,3)
103 : :
104 : : real(dp), allocatable:: fact_oscstr(:,:,:)
105 : : ! fact_oscstr(2,3,3*natom)
106 : :
107 : : real(dp), allocatable:: zeff(:,:,:)
108 : : ! zeff(3,3,natom)
109 : :
110 : : real(dp), allocatable:: qdrp_cart(:,:,:,:)
111 : : ! qdrp_cart(3,3,3,natom)
112 : :
113 : : real(dp), allocatable:: dcdq(:,:,:,:,:)
114 : : ! dcdq(3,natom,3,natom,3)
115 : :
116 : : real(dp), allocatable:: dcdqdq(:,:,:,:,:)
117 : : ! dcdqdq(3,natom,3,3,3)
118 : :
119 : : contains
120 : :
121 : : procedure :: init => anaddb_driver_init
122 : : ! Initialize object
123 : :
124 : : procedure :: free => anaddb_driver_free
125 : : ! Free memory
126 : :
127 : : procedure :: open_write_nc => anaddb_driver_open_write_nc
128 : : ! Open netcdf output and write some info
129 : :
130 : : procedure :: electric_tensors => anaddb_driver_electric_tensors
131 : : ! Compute dielectric tensor, born effective charges, and quadrupoles
132 : :
133 : : procedure :: structural_response => anaddb_driver_structural_response
134 : : ! Structural response at fixed polarization
135 : :
136 : : procedure :: susceptibilities => anaddb_driver_susceptibilities
137 : : ! Compute non-linear optical susceptibilities and first-order derivatives
138 : :
139 : : procedure :: interatomic_force_constants => anaddb_driver_interatomic_force_constants
140 : : ! Compute the interatomic force constants from a ddb
141 : :
142 : : procedure :: phdos => anaddb_driver_phdos
143 : : ! Compute phonon density of states
144 : :
145 : : procedure :: thermal_supercell => anaddb_driver_thermal_supercell
146 : : ! Thermal supercell calculation
147 : :
148 : : procedure :: harmonic_thermo => anaddb_driver_harmonic_thermo
149 : : ! Phonon density of states and thermodynamical properties
150 : :
151 : : procedure :: dielectric_q0 => anaddb_driver_dielectric_q0
152 : : ! Dielectric tensor and related properties
153 : :
154 : : procedure :: nonlinear_response => anaddb_driver_nonlinear_response
155 : : ! Non-linear response: electrooptic and Raman
156 : :
157 : : procedure :: dielectric_nonana => anaddb_driver_dielectric_nonana
158 : : ! Non-analyticity in the dielectric matrix and raman susceptibility
159 : :
160 : : procedure :: internal_strain => anaddb_driver_internal_strain
161 : : ! Internal strain
162 : :
163 : : procedure :: elastic_tensor => anaddb_driver_elastic_tensor
164 : : ! Elastic tensor
165 : :
166 : : procedure :: piezoelectric_tensor => anaddb_driver_piezoelectric_tensor
167 : : ! Piezoelectric tensor
168 : :
169 : : procedure :: flexoelectric_tensor => anaddb_driver_flexoelectric_tensor
170 : : ! Flexoelectric tensor
171 : :
172 : : procedure :: get_dcdq => anaddb_driver_get_dcdq
173 : : ! Get IFCs derivatives for the imposition of rotational invariance
174 : :
175 : : procedure :: lattice_wannier => anaddb_driver_lattice_wannier
176 : : ! Construct the Lattice Wannier functions
177 : :
178 : : procedure :: convertdim_dielt => anaddb_driver_convertdim_dielt
179 : : ! Extract low-dimmensional dielectric response from periodic calculations
180 : :
181 : : end type anaddb_driver_type
182 : : !!***
183 : :
184 : : contains
185 : :
186 : : !!****f* m_anaddb_driver/anaddb_driver_init
187 : : !! NAME
188 : : !! anaddb_driver_init
189 : : !!
190 : : !! FUNCTION
191 : : !! Initialize object
192 : : !!
193 : : !! INPUTS
194 : : !!
195 : : !! OUTPUT
196 : : !!
197 : : !! SOURCE
198 : :
199 : 81 : subroutine anaddb_driver_init(driver, dtset)
200 : :
201 : : !Arguments -------------------------------
202 : : class(anaddb_driver_type), intent(inout):: driver
203 : : type(anaddb_dataset_type), intent(in):: dtset
204 : : ! ************************************************************************
205 : :
206 : : ! Set control flags
207 [ + + ]: 81 : if (dtset%ifcflag == 1) then
208 : 55 : driver%do_ifc = .true.
209 : : end if
210 : :
211 : : if (dtset%ifcflag /= 0 .or. dtset%dieflag /= 0 &
212 : : & .or. dtset%dipdip /= 0 .or. dtset%dipquad /= 0 .or. dtset%quadquad /= 0 &
213 : : & .or. dtset%nph2l /= 0 .or. dtset%nlflag /= 0 &
214 : : & .or. dtset%piezoflag /= 0 .or. dtset%flexoflag /= 0 &
215 [ + + + + : 81 : & .or. dtset%polflag /= 0) then
+ - + - +
- + - + -
+ - - + ]
216 : 77 : driver%do_electric_tensors = .true.
217 : : end if
218 : :
219 : : if ((dtset%dieflag /= 0 .and. dtset%dieflag /= 2) &
220 : : & .or. dtset%nph2l /= 0 .or. dtset%nlflag == 1 &
221 [ + + + + : 81 : & .or. dtset%piezoflag /= 0) then
+ - + + ]
222 : 27 : driver%do_dielectric_q0 = .true.
223 : : end if
224 : :
225 [ + + ]: 81 : if (dtset%nph2l /= 0) then
226 : 24 : driver%do_dielectric_nonana = .true.
227 : : end if
228 : :
229 [ + + + + ]: 81 : if (dtset%ifcflag == 1 .and. any(dtset%prtdos==[1, 2])) then
230 : 11 : driver%do_phonon_dos = .true.
231 : : end if
232 : :
233 [ + + + + ]: 81 : if (dtset%nph1l /= 0 .or. dtset%nqpath /= 0) then
234 : 66 : driver%do_phonon_bs = .true.
235 : : end if
236 : :
237 [ + + ]: 81 : if (dtset%gruns_nddbs /= 0) then
238 : 1 : driver%do_ifc = .false.
239 : 1 : driver%do_electric_tensors = .false.
240 : 1 : driver%do_dielectric_q0 = .false.
241 : 1 : driver%do_dielectric_nonana = .false.
242 : 1 : driver%do_phonon_bs = .false.
243 : 1 : driver%do_phonon_dos = .false.
244 : : end if
245 : :
246 : : ! Copy dimensions
247 : 81 : driver%natom = dtset%natom
248 : 81 : driver%msize = dtset%msize
249 : 81 : driver%mpert = dtset%mpert
250 : :
251 : : ! Allocate memory
252 [ - + + - : 243 : ABI_MALLOC(driver%d2cart, (2, driver%msize))
+ - + - -
+ - + -
+ ]
253 [ + - - + : 243 : ABI_MALLOC(driver%displ, (2*3*driver%natom*3*driver%natom))
+ - + - +
- - + - +
- + ]
254 [ + - - + : 243 : ABI_MALLOC(driver%phfrq, (3*driver%natom))
+ - + - +
- - + - +
- + ]
255 [ - + + - : 324 : ABI_MALLOC(driver%instrain, (3*driver%natom, 6))
+ - + - +
- - + - +
- + ]
256 [ - + + - : 486 : ABI_MALLOC(driver%dcdq, (3, driver%natom, 3, driver%natom, 3))
+ - - + +
- + - + -
+ - - + -
+ - + ]
257 [ - + + - : 405 : ABI_MALLOC(driver%dcdqdq, (3, driver%natom, 3, 3, 3))
+ - + - +
- + - - +
- + - + ]
258 [ + + + + : 50820 : driver%dcdq = zero
+ + + + +
+ ]
259 [ + + + + : 31320 : driver%dcdqdq = zero
+ + + + +
+ ]
260 : : ! Electric tensors
261 [ - + + - : 243 : ABI_MALLOC(driver%zeff, (3, 3, driver%natom))
+ - + - -
+ - + -
+ ]
262 [ - + + - : 243 : ABI_MALLOC(driver%qdrp_cart, (3, 3, 3, driver%natom))
+ - + - -
+ - + -
+ ]
263 : :
264 : : ! oscillator strength and Lyddane-Sachs-Teller relation
265 [ - + + - : 162 : ABI_MALLOC(driver%fact_oscstr, (2, 3, 3*driver%natom))
- + - + -
+ ]
266 : :
267 : : ! Susceptibilities
268 [ + + ]: 81 : if (dtset%nlflag > 0) then
269 [ - + + - : 8 : ABI_MALLOC(driver%dchidt, (driver%natom, 3, 3, 3))
- + - + -
+ ]
270 : : end if
271 : :
272 : 81 : end subroutine anaddb_driver_init
273 : : !!***
274 : :
275 : :
276 : : !!****f* m_anaddb_driver/anaddb_driver_free
277 : : !! NAME
278 : : !! anaddb_driver_free
279 : : !!
280 : : !! FUNCTION
281 : : !! Deallocate memory
282 : : !!
283 : : !! INPUTS
284 : : !!
285 : : !! OUTPUT
286 : : !!
287 : : !! SOURCE
288 : :
289 : 81 : subroutine anaddb_driver_free(driver)
290 : :
291 : : !Arguments -------------------------------
292 : : class(anaddb_driver_type), intent(inout):: driver
293 : : ! ************************************************************************
294 : :
295 [ + - ]: 81 : ABI_SFREE(driver%zeff)
296 [ + - ]: 81 : ABI_SFREE(driver%qdrp_cart)
297 [ + - ]: 81 : ABI_SFREE(driver%d2cart)
298 [ + - ]: 81 : ABI_SFREE(driver%displ)
299 [ + - ]: 81 : ABI_SFREE(driver%phfrq)
300 [ + + ]: 81 : ABI_SFREE(driver%dchidt)
301 [ + - ]: 81 : ABI_SFREE(driver%instrain)
302 [ + - ]: 81 : ABI_SFREE(driver%fact_oscstr)
303 [ + - ]: 81 : ABI_SFREE(driver%dcdq)
304 [ + - ]: 81 : ABI_SFREE(driver%dcdqdq)
305 : :
306 : 81 : end subroutine anaddb_driver_free
307 : : !!***
308 : :
309 : : !!****f* m_anaddb_driver/anaddb_driver_open_write_nc
310 : : !! NAME
311 : : !! anaddb_driver_open_write_nc
312 : : !!
313 : : !! FUNCTION
314 : : !! Open anaddb netcdf output and define dimensions.
315 : : !!
316 : : !! INPUTS
317 : : !!
318 : : !! OUTPUT
319 : : !!
320 : : !! SOURCE
321 : :
322 : 81 : subroutine anaddb_driver_open_write_nc(driver, ana_ncid, dtset, crystal, comm)
323 : :
324 : : !Arguments -------------------------------
325 : : class(anaddb_driver_type), intent(inout):: driver
326 : : type(anaddb_dataset_type), intent(in):: dtset
327 : : type(crystal_t),intent(in):: crystal
328 : : integer,intent(in):: comm
329 : : integer, intent(out):: ana_ncid
330 : :
331 : : !Local variables -------------------------------
332 : : integer, parameter:: master = 0
333 : : integer:: natom,lenstr
334 : : integer:: ncerr
335 : : integer:: my_rank
336 : : ! ************************************************************************
337 : :
338 : 81 : my_rank = xmpi_comm_rank(comm)
339 : :
340 : 81 : natom = driver%natom
341 : 81 : lenstr = dtset%lenstr
342 : :
343 : : ! Open the netcdf file that will contain the anaddb results
344 : 81 : ana_ncid = nctk_noid
345 [ + - ]: 81 : if (my_rank == master) then
346 [ - + - - ]: 81 : NCF_CHECK_MSG(nctk_open_create(ana_ncid, trim(dtset%prefix_outdata)//"_anaddb.nc", xmpi_comm_self), "Creating anaddb.nc")
347 : : ncerr = nctk_def_dims(ana_ncid, [ &
348 : : nctkdim_t('number_of_atoms', natom), &
349 : : nctkdim_t('natom3', 3*natom), &
350 : : nctkdim_t('number_of_phonon_modes', 3*natom), &
351 : : nctkdim_t('anaddb_input_len', lenstr) &
352 [ + + ]: 405 : ], defmode=.True.)
353 [ - + ]: 81 : NCF_CHECK(ncerr)
354 : : ncerr = nctk_def_arrays(ana_ncid, [ &
355 : : nctkarr_t("anaddb_input_string", "char", "anaddb_input_len") &
356 [ + + ]: 162 : ])
357 [ - + ]: 81 : NCF_CHECK(ncerr)
358 : : !NCF_CHECK(nctk_defnwrite_ivars(ana_ncid, ["anaddb_version"], [1]))
359 : :
360 : : ncerr = nctk_def_iscalars(ana_ncid, [character(len = nctk_slen) :: &
361 [ + + ]: 567 : "asr", "chneut", "dipdip", "symdynmat", "dipquad", "quadquad"])
362 [ - + ]: 81 : NCF_CHECK(ncerr)
363 : :
364 [ - + ]: 81 : NCF_CHECK(nctk_set_datamode(ana_ncid))
365 : 81 : ncerr = nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "anaddb_input_string"), dtset%input_string(:lenstr))
366 [ - + ]: 81 : NCF_CHECK(ncerr)
367 [ - + ]: 81 : NCF_CHECK(crystal%ncwrite(ana_ncid))
368 : :
369 : : ncerr = nctk_write_iscalars(ana_ncid, [character(len = nctk_slen) :: &
370 : : "asr", "chneut", "dipdip", "symdynmat", "dipquad", "quadquad"], &
371 : : [dtset%asr, dtset%chneut, dtset%dipdip, &
372 [ + + + + ]: 1053 : dtset%symdynmat, dtset%dipquad, dtset%quadquad])
373 [ - + ]: 81 : NCF_CHECK(ncerr)
374 : : end if
375 : :
376 : 81 : end subroutine anaddb_driver_open_write_nc
377 : : !!***
378 : :
379 : : !!****f* m_anaddb_driver/anaddb_driver_electric_tensors
380 : : !! NAME
381 : : !! anaddb_driver_electric_tensors
382 : : !!
383 : : !! FUNCTION
384 : : !! get Dielectric tensor, born effective charges, and quadrupole tensor,
385 : : !! and write them to netcdf output.
386 : : !!
387 : : !! INPUTS
388 : : !!
389 : : !! OUTPUT
390 : : !!
391 : : !! SOURCE
392 : :
393 : 76 : subroutine anaddb_driver_electric_tensors(driver, dtset, crystal, ddb, ddb_lw, ddb_hdr, ana_ncid, comm)
394 : :
395 : : !Arguments -------------------------------
396 : : class(anaddb_driver_type), intent(inout):: driver
397 : : type(anaddb_dataset_type), intent(inout):: dtset
398 : : type(crystal_t), intent(in):: crystal
399 : : type(ddb_type), intent(inout):: ddb
400 : : type(ddb_type), intent(inout):: ddb_lw
401 : : type(ddb_hdr_type), intent(in):: ddb_hdr
402 : : integer, intent(in):: ana_ncid
403 : : integer, intent(in):: comm
404 : :
405 : : !Local variables -------------------------------
406 : : integer, parameter:: master = 0
407 : : integer:: my_rank
408 : : integer:: ii
409 : : integer:: iblok, iblok_quadrupoles, iblok_epsinf
410 : : integer:: ncerr
411 : : integer:: lwsym
412 : : character(len = 500):: msg
413 : : integer:: units(2)
414 : : ! ************************************************************************
415 : :
416 [ + + ]: 228 : units = [std_out, ab_out]
417 : :
418 : : ! Get Quadrupole tensor
419 : 76 : iblok_quadrupoles = 0
420 [ + + + + : 9596 : driver%qdrp_cart = zero
+ + + + ]
421 [ + + ]: 76 : if (ddb_hdr%has_d3E_lw) then
422 [ + - + + ]: 648 : write(msg, '(2a, (80a), 2a)') ch10, ('=',ii = 1, 80)
423 : 8 : call wrtout(units, msg)
424 : 8 : lwsym = 1
425 : 8 : iblok_quadrupoles = ddb_lw%get_quadrupoles(ddb_hdr%ddb_version, lwsym, BLKTYP_d3E_lw, driver%qdrp_cart)
426 : : end if
427 : :
428 : : ! Get the electronic dielectric tensor (epsinf) and Born effective charges (zeff)
429 : : ! (initialized to one_3D and zero if the derivatives are not available in the DDB file)
430 : 76 : iblok = ddb%get_dielt_zeff(crystal, dtset%rfmeth, dtset%chneut, dtset%selectz, driver%epsinf, driver%zeff)
431 : :
432 : : ! Try to get epsinf, in case just the DDE are present
433 [ + + ]: 76 : if (iblok == 0) then
434 : 32 : iblok_epsinf = ddb%get_dielt(dtset%rfmeth, driver%epsinf)
435 : : end if
436 : :
437 : : !if (iblok_epsinf == 0) then
438 : : !GA: Not the greatest way of checking
439 [ + + + - : 76 : if (driver%epsinf(1, 1)==one .and. driver%epsinf(2, 2)==one .and. driver%epsinf(3, 3)==one) then
+ - ]
440 : 33 : write(msg, '(5a)') ch10, &
441 : 33 : ' The DDB file does not contain the derivatives w.r.t. electric field perturbation. ',ch10, &
442 : 66 : ' The program will continue by setting the electronic dielectric tensor to 1. ',ch10
443 : : ! call wrtout([ab_out], msg)
444 : 33 : ABI_WARNING(msg)
445 : : end if
446 : :
447 : : !**********************************************************************
448 : : ! Write Dielectric tensor, born effective charges, and quadrupoles to netcdf output.
449 : :
450 : 76 : my_rank = xmpi_comm_rank(comm)
451 [ + - ]: 76 : if (my_rank == master) then
452 : : ncerr = nctk_def_arrays(ana_ncid, [&
453 : : nctkarr_t('emacro_cart', "dp", 'number_of_cartesian_directions, number_of_cartesian_directions'), &
454 : : nctkarr_t('quadrupoles_cart', "dp", 'three, three, three, number_of_atoms'), &
455 : : nctkarr_t('becs_cart', "dp", "number_of_cartesian_directions, number_of_cartesian_directions, number_of_atoms")],&
456 [ + + ]: 304 : defmode=.True.)
457 [ - + ]: 76 : NCF_CHECK(ncerr)
458 : :
459 [ - + ]: 76 : NCF_CHECK(nctk_set_datamode(ana_ncid))
460 [ - + ]: 76 : NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'emacro_cart'), driver%epsinf))
461 [ - + ]: 76 : NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'quadrupoles_cart'), driver%qdrp_cart))
462 [ - + ]: 76 : NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'becs_cart'), driver%zeff))
463 : : end if
464 : :
465 : 76 : end subroutine anaddb_driver_electric_tensors
466 : : !!***
467 : :
468 : : !!****f* m_anaddb_driver/anaddb_driver_structural_response
469 : : !! NAME
470 : : !! anaddb_driver_structural_response
471 : : !!
472 : : !! FUNCTION
473 : : !! Compute structural response at fixed polarization
474 : : !!
475 : : !! INPUTS
476 : : !!
477 : : !! OUTPUT
478 : : !!
479 : : !! SOURCE
480 : :
481 : 3 : subroutine anaddb_driver_structural_response(driver, dtset, crystal, ddb)
482 : :
483 : : !Arguments -------------------------------
484 : : class(anaddb_driver_type), intent(inout):: driver
485 : : type(anaddb_dataset_type), intent(in):: dtset
486 : : type(crystal_t), intent(in):: crystal
487 : : type(ddb_type), intent(inout):: ddb
488 : :
489 : : !Local variables -------------------------------
490 : : integer:: iblok
491 : : integer:: msize
492 : : real(dp):: etotal
493 : : character(len = 500):: msg
494 : : integer:: rfelfd(4), rfphon(4), rfstrs(4)
495 : : real(dp):: red_ptot(3)
496 : : real(dp):: pel(3)
497 : : real(dp):: strten(6)
498 : : real(dp) :: targetpol(3)
499 : : real(dp):: qphnrm(3), qphon(3, 3)
500 : 3 : integer, allocatable:: d2flg(:)
501 : 3 : real(dp), allocatable:: gred(:,:)
502 : : ! ************************************************************************
503 : :
504 : 3 : msize = dtset%msize
505 [ - + + - : 9 : ABI_MALLOC(d2flg, (msize))
+ - + - -
+ - + ]
506 : :
507 : : ! Look for the Gamma Block in the DDB
508 [ + + ]: 12 : qphon(:,1)=zero
509 : 3 : qphnrm(1)=zero
510 [ + + ]: 9 : rfphon(1:2)=1
511 [ + + ]: 9 : rfelfd(1:2)=2
512 [ + + ]: 9 : rfstrs(1:2)=0
513 : :
514 : : !write(std_out,*)"ddb%mpert",ddb%mpert
515 : 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
516 : : !iblok = ddb%get_dielt_zeff(crystal, dtset%rfmeth, dtset%chneut, dtset%selectz, driver%epsinf, driver%zeff)
517 : :
518 [ + + ]: 3 : if(iblok /= 0)then
519 : : ! Save the second-order derivatives
520 [ + + + + ]: 17984 : driver%d2cart(1:2, 1:msize) = ddb%val(1:2, 1:msize, iblok)
521 [ + + ]: 5996 : d2flg(1:msize) = ddb%flg(1:msize, iblok)
522 : :
523 : : else
524 : : ! the gamma blok has not been found
525 [ + - + - ]: 1 : if (dtset%relaxat == 0 .and. dtset%relaxstr == 0) then
526 : : ! The gamma blok is not needed
527 [ + + + + ]: 6076 : driver%d2cart(1:2, 1:msize)=zero
528 [ + + ]: 2026 : d2flg(1:msize)=1
529 : : else
530 : : ! There is a problem !
531 : : write(msg, '(7a)' )&
532 : 0 : 'The dynamical matrix at Gamma is needed, in order to perform ',ch10, &
533 : 0 : "relaxation at constant polarisation (Na Sai's method)",ch10, &
534 : 0 : 'However, this was not found in the DDB.',ch10, &
535 : 0 : 'Action: complete your DDB with the dynamical matrix at Gamma.'
536 : 0 : ABI_ERROR(msg)
537 : : end if
538 : : end if ! iblok not found
539 : :
540 : : ! Extract the block with the total energy
541 [ - + ]: 3 : if (ddb%get_etotal(etotal) == 0) then
542 : 0 : ABI_ERROR("DDB file does not contain GS etotal")
543 : : end if
544 : :
545 : : ! Extract the polarizability
546 : 3 : iblok = ddb%get_pel(pel, dtset%relaxat, dtset%relaxstr)
547 : :
548 : : ! Extract the forces
549 [ - + ]: 3 : iblok = ddb%get_gred(gred, dtset%relaxat, dtset%relaxstr)
550 : :
551 : : ! Extract the stress tensor
552 : 3 : iblok = ddb%get_strten(strten, dtset%relaxat, dtset%relaxstr)
553 : :
554 : : ! when called from here red_ptot is not set ! So set it to zero
555 : 3 : red_ptot(:) = zero
556 : :
557 [ + + ]: 12 : targetpol(:) = dtset%targetpol
558 : :
559 : : call relaxpol(crystal, d2flg, driver%d2cart, etotal, gred, dtset%iatfix, &
560 : : & ab_out, dtset%istrfix, dtset%mpert, dtset%msize, dtset%natfix, crystal%natom, &
561 : : & dtset%nstrfix, pel, red_ptot, dtset%relaxat, dtset%relaxstr, &
562 : 3 : & strten, targetpol)
563 : :
564 [ + - ]: 3 : ABI_SFREE(gred)
565 [ - + ]: 3 : ABI_FREE(d2flg)
566 : :
567 [ - + ]: 3 : end subroutine anaddb_driver_structural_response
568 : : !!***
569 : :
570 : : !!****f* m_anaddb_driver/anaddb_driver_susceptibilities
571 : : !! NAME
572 : : !! anaddb_driver_susceptibilities
573 : : !!
574 : : !! FUNCTION
575 : : !! Compute non-linear optical susceptibilities,
576 : : !! and if dtset%nlflag < 3, compute first-order change
577 : : !! in the linear dielectric susceptibility induced by an atomic displacement.
578 : : !! Then write susceptibilites to netcdf output.
579 : : !!
580 : : !! INPUTS
581 : : !!
582 : : !! OUTPUT
583 : : !!
584 : : !! SOURCE
585 : :
586 : 4 : subroutine anaddb_driver_susceptibilities(driver, dtset, ddb, ana_ncid, comm)
587 : :
588 : : !Arguments -------------------------------
589 : : class(anaddb_driver_type), intent(inout):: driver
590 : : type(anaddb_dataset_type), intent(in):: dtset
591 : : type(ddb_type), intent(in):: ddb
592 : : integer, intent(in):: ana_ncid
593 : : integer, intent(in):: comm
594 : :
595 : : !Local variables -------------------------------
596 : : integer, parameter:: master = 0
597 : : integer:: my_rank
598 : : integer:: ncerr
599 : : ! ************************************************************************
600 : :
601 [ - + ]: 4 : if (ddb%get_dchidet(dtset%ramansr, dtset%nlflag, driver%dchide, driver%dchidt) == 0) then
602 : 0 : ABI_ERROR("Cannot find block corresponding to non-linear optical susceptibilities in DDB file")
603 : : end if
604 : :
605 : : ! Save to the netcdf
606 : 4 : my_rank = xmpi_comm_rank(comm)
607 [ + - ]: 4 : if (my_rank == master) then
608 [ + + ]: 8 : ncerr = nctk_def_arrays(ana_ncid, [nctkarr_t("dchide", "dp", "three, three, three")], defmode=.True.)
609 [ - + ]: 4 : NCF_CHECK(ncerr)
610 [ - + ]: 4 : NCF_CHECK(nctk_set_datamode(ana_ncid))
611 [ - + ]: 4 : NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "dchide"), driver%dchide))
612 : :
613 : : ! dchidt only present if nlflag == 1 or 2
614 [ + + ]: 4 : if (dtset%nlflag < 3) then
615 : : ncerr = nctk_def_arrays(ana_ncid, [nctkarr_t("dchidt", "dp", &
616 [ + + ]: 6 : "number_of_atoms, three, three, three")], defmode=.True.)
617 [ - + ]: 3 : NCF_CHECK(ncerr)
618 [ - + ]: 3 : NCF_CHECK(nctk_set_datamode(ana_ncid))
619 [ - + ]: 3 : NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "dchidt"), driver%dchidt))
620 : : end if
621 : : end if
622 : :
623 : 4 : end subroutine anaddb_driver_susceptibilities
624 : : !!***
625 : :
626 : : !!****f* m_anaddb_driver/anaddb_driver_interatomic_force_constants
627 : : !! NAME
628 : : !! anaddb_driver_interatomic_force_constants
629 : : !!
630 : : !! FUNCTION
631 : : !! Interatomic forces calculation
632 : : !! Compute the interatomic force constants from a ddb.
633 : : !!
634 : : !! INPUTS
635 : : !!
636 : : !! OUTPUT
637 : : !!
638 : : !! SOURCE
639 : :
640 [ - + - + : 486 : subroutine anaddb_driver_interatomic_force_constants(driver, ifc, dtset, crystal, ddb, ana_ncid, comm)
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + + +
+ + ]
641 : :
642 : : !Arguments -------------------------------
643 : : class(anaddb_driver_type), intent(inout):: driver
644 : : type(ifc_type), intent(out):: ifc
645 : : type(anaddb_dataset_type), intent(in):: dtset
646 : : type(crystal_t), intent(in):: crystal
647 : : type(ddb_type), intent(in):: ddb
648 : : integer, intent(in):: ana_ncid
649 : : integer, intent(in):: comm
650 : :
651 : : !Local variables -------------------------------
652 : : integer, parameter:: master = 0
653 : : integer:: my_rank
654 : : integer:: ii
655 [ + + + + : 378 : type(ifc_type):: Ifc_coarse
- + ]
656 : : character(len = 500):: msg
657 : : integer:: ngqpt_coarse(3)
658 : : integer:: units(2)
659 : : ! ************************************************************************
660 : :
661 [ + + ]: 162 : units = [std_out, ab_out]
662 : :
663 [ + + ]: 4428 : write(msg, '(a, a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, &
664 [ + - ]: 4482 : ' Calculation of the interatomic forces ',ch10
665 : 54 : call wrtout(units, msg)
666 : :
667 [ + + + + : 213 : if (any(dtset%qrefine(:) > 1)) then
+ + ]
668 : : ! Gaal-Nagy's algorithm in PRB 73 014117 [[cite:GaalNagy2006]]
669 : : ! Build the IFCs using the coarse q-mesh.
670 [ + + ]: 4 : do ii = 1, 3
671 : 4 : ngqpt_coarse(ii) = dtset%ngqpt(ii) / dtset%qrefine(ii)
672 : : end do
673 : : call Ifc_coarse%init(crystal, ddb, &
674 : : dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, ngqpt_coarse, dtset%nqshft, dtset%q1shft, &
675 : : driver%epsinf, driver%zeff, driver%qdrp_cart, &
676 : : dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
677 : 1 : dipquad=dtset%dipquad, quadquad=dtset%quadquad, dielt_env=dtset%dielt_env,dielt_thick=dtset%dielt_thick)
678 : :
679 : : ! Now use the coarse q-mesh to fill the entries in dynmat(q)
680 : : ! on the dense q-mesh that cannot be obtained from the DDB file.
681 : : call ifc%init(crystal, ddb, &
682 : : dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, &
683 : : dtset%ngqpt(1:3), dtset%nqshft, dtset%q1shft, driver%epsinf, driver%zeff, driver%qdrp_cart, &
684 : : dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
685 : : Ifc_coarse=Ifc_coarse, dipquad=dtset%dipquad, quadquad=dtset%quadquad, &
686 : 1 : dielt_env=dtset%dielt_env, dielt_thick=dtset%dielt_thick)
687 : 1 : call Ifc_coarse%free()
688 : :
689 : : else
690 : : call ifc%init(crystal, ddb, &
691 : : dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, &
692 : : dtset%ngqpt(1:3), dtset%nqshft, dtset%q1shft, driver%epsinf, driver%zeff, driver%qdrp_cart, &
693 : : dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
694 : 53 : dipquad=dtset%dipquad, quadquad=dtset%quadquad, dielt_env=dtset%dielt_env, dielt_thick=dtset%dielt_thick)
695 : : end if
696 : :
697 [ + + ]: 108 : call ifc%print([std_out])
698 : :
699 : : ! If asr==6 (rotational invariance) we also need the estimation of the IFCs moments from real space.
700 [ + + - + ]: 54 : if (dtset%asr==6 .and. dtset%flexoflag==0) then
701 : 0 : write(msg, '(a, a)' )' Rotational invariance: will generate IFCs derivatives from IFCs moments',ch10
702 : 0 : call ifc%get_dcdq(crystal,driver%dcdq,driver%dcdqdq, comm)
703 : : ! If phi1 is not available from DDB, compute rotational invariance based on dcdq
704 : : ! For polar materials, we have to be extra cautious: indeed the typical electrostatics
705 : : ! model used to remove the non-analytical part is not invariant under rotation !
706 : : ! In 3D, the model leads to a divergent IFCs derivatives -> we cannot correct anything !
707 : : ! In 2D, the model leads to a finite torque and IFCs derivatives. We can add them back
708 : : ! during the imposition of rotational invariance...
709 : : end if
710 : :
711 : : ! Compute speed of sound.
712 [ - + ]: 54 : if (dtset%vs_qrad_tolkms(1) > zero) then
713 : 0 : call ifc%speedofsound(crystal, dtset%vs_qrad_tolkms, ana_ncid, comm)
714 : : end if
715 : :
716 : : ! Print analysis of the real-space interatomic force constants
717 : : ! TODO: ifc_out should not have side effects
718 : 54 : my_rank = xmpi_comm_rank(comm)
719 [ + - + + ]: 54 : if (my_rank == master .and. dtset%ifcout /= 0) then
720 : 13 : call ifc%write(dtset%ifcana, dtset%atifcflg, dtset%ifcout, dtset%prt_ifc, ana_ncid, dtset%prefix_outdata)
721 : : end if
722 : :
723 [ - + - + : 54 : end subroutine anaddb_driver_interatomic_force_constants
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
724 : : !!***
725 : :
726 : : !!****f* m_anaddb_driver/anaddb_driver_phdos
727 : : !! NAME
728 : : !! anaddb_driver_phdos
729 : : !!
730 : : !! FUNCTION
731 : : !! Compute phonon density of states.
732 : : !!
733 : : !! INPUTS
734 : : !!
735 : : !! OUTPUT
736 : : !!
737 : : !! SOURCE
738 : :
739 : 11 : subroutine anaddb_driver_phdos(driver, dtset, crystal, ifc, comm)
740 : :
741 : : !Arguments -------------------------------
742 : : class(anaddb_driver_type), intent(inout):: driver
743 : : type(anaddb_dataset_type), intent(in):: dtset
744 : : type(crystal_t), intent(in):: crystal
745 : : type(ifc_type), intent(in):: ifc
746 : : integer, intent(in):: comm
747 : :
748 : : !Local variables -------------------------------
749 : : integer, parameter:: master = 0
750 : : integer:: my_rank
751 : : integer:: ii
752 : : integer:: phdos_ncid, ncerr
753 : : character(len = fnlen):: phibz_prefix
754 : : character(len = 500):: msg
755 [ + + + + ]: 143 : type(phdos_t):: Phdos
756 : : integer:: units(2)
757 : : integer:: count_wminmax(2)
758 : : real(dp):: wminmax(2)
759 : : ! ************************************************************************
760 : :
761 : : ABI_UNUSED(driver%natom)
762 : 11 : my_rank = xmpi_comm_rank(comm)
763 [ + + ]: 33 : units = [std_out, ab_out]
764 : :
765 [ + - + + ]: 891 : write(msg, '(a, (80a), 4a)')ch10, ('=',ii = 1, 80), ch10, ch10, ' Calculation of phonon density of states ',ch10
766 : 11 : call wrtout(units, msg)
767 : :
768 : : ! Only 1 shift in q-mesh
769 : 11 : wminmax = zero
770 : 11 : phibz_prefix = trim(" ")
771 : : !phibz_prefix = "freq_displ" ! Uncomment this line to activate output of PHIBZ
772 : : ! ^^^^ GA: What the hell? FIXME ^^^^^
773 : 0 : do
774 : : call Phdos%init(crystal, Ifc, dtset%prtdos, dtset%dosdeltae, dtset%dossmear, dtset%ng2qpt, 1, dtset%q2shft, &
775 : 11 : phibz_prefix, wminmax, count_wminmax, comm, dos_maxmode=dtset%dos_maxmode)
776 [ + + + - : 33 : if (all(count_wminmax == 0)) exit
- + ]
777 : 0 : wminmax(1) = wminmax(1) - abs(wminmax(1)) * 0.05; wminmax(2) = wminmax(2) + abs(wminmax(2)) * 0.05
778 : 0 : call phdos%free()
779 : 0 : write(msg, "(a, 2f8.5)")"Initial frequency mesh not large enough. Recomputing PHDOS with wmin, wmax: ",wminmax
780 : 0 : call wrtout(std_out, msg)
781 : : end do
782 : :
783 [ + - ]: 11 : if (my_rank == master) then
784 : 11 : call phdos%print_msqd(dtset%prefix_outdata, dtset%ntemper, dtset%tempermin, dtset%temperinc)
785 : 11 : call phdos%print(strcat(dtset%prefix_outdata, "_PHDOS"))
786 : 11 : call phdos%print_debye(crystal%ucvol)
787 : 11 : call phdos%print_thermo(strcat(dtset%prefix_outdata, "_THERMO"), dtset%ntemper, dtset%tempermin, dtset%temperinc)
788 : :
789 : 11 : ncerr = nctk_open_create(phdos_ncid, strcat(dtset%prefix_outdata, "_PHDOS.nc"), xmpi_comm_self)
790 [ - + ]: 11 : NCF_CHECK_MSG(ncerr, "Creating PHDOS.nc file")
791 [ - + ]: 11 : NCF_CHECK(crystal%ncwrite(phdos_ncid))
792 : 11 : call phdos%ncwrite(phdos_ncid)
793 [ - + ]: 11 : NCF_CHECK(nf90_close(phdos_ncid))
794 : : end if
795 : :
796 : 11 : call phdos%free()
797 : :
798 [ - + - + : 11 : end subroutine anaddb_driver_phdos
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
799 : : !!***
800 : :
801 : : !!****f* m_anaddb_driver/anaddb_driver_thermal_supercell
802 : : !! NAME
803 : : !! anaddb_driver_thermal_supercell
804 : : !!
805 : : !! FUNCTION
806 : : !!
807 : : !! INPUTS
808 : : !!
809 : : !! OUTPUT
810 : : !!
811 : : !! SOURCE
812 : :
813 : 1 : subroutine anaddb_driver_thermal_supercell(driver, dtset, crystal, ifc)
814 : :
815 : : !Arguments -------------------------------
816 : : class(anaddb_driver_type), intent(in):: driver
817 : : type(anaddb_dataset_type), intent(in):: dtset
818 : : type(crystal_t), intent(in):: crystal
819 : : type(ifc_type), intent(in):: ifc
820 : :
821 : : !Local variables -------------------------------
822 : 1 : type(supercell_type), allocatable:: thm_scells(:)
823 : : ! ************************************************************************
824 : :
825 : : ABI_UNUSED(driver%natom)
826 [ - + + - : 13 : ABI_MALLOC(thm_scells, (dtset%ntemper))
+ - + - -
+ - + +
+ ]
827 : 1 : call zacharias_supercell_make(crystal, ifc, dtset%ntemper, dtset%thermal_supercell, dtset%tempermin, dtset%temperinc, thm_scells)
828 : 1 : call zacharias_supercell_print(dtset%prefix_outdata, dtset%ntemper, dtset%tempermin, dtset%temperinc, thm_scells)
829 : 1 : call thermal_supercell_free(dtset%ntemper, thm_scells)
830 [ + - + + : 11 : ABI_FREE(thm_scells)
- + - + -
+ - + - +
- + - + -
+ ]
831 : :
832 : 1 : end subroutine anaddb_driver_thermal_supercell
833 : : !!***
834 : :
835 : : !!****f* m_anaddb_driver/anaddb_driver_harmonic_thermo
836 : : !! NAME
837 : : !! anaddb_driver_harmonic_thermo
838 : : !!
839 : : !! FUNCTION
840 : : !! Phonon density of states and thermodynamical properties calculation
841 : : !!
842 : : !! INPUTS
843 : : !!
844 : : !! OUTPUT
845 : : !!
846 : : !! SOURCE
847 : :
848 : 4 : subroutine anaddb_driver_harmonic_thermo(driver, dtset, crystal, ifc, comm)
849 : :
850 : : !Arguments -------------------------------
851 : : class(anaddb_driver_type), intent(in):: driver
852 : : type(anaddb_dataset_type), intent(in):: dtset
853 : : type(crystal_t), intent(in):: crystal
854 : : type(ifc_type), intent(in):: ifc
855 : : integer, intent(in):: comm
856 : :
857 : : !Local variables -------------------------------
858 : : integer:: ii
859 : : character(len = 500):: msg
860 : : integer:: units(2)
861 : : ! ************************************************************************
862 : :
863 : : ABI_UNUSED(driver%natom)
864 [ + + ]: 12 : units = [std_out, ab_out]
865 : :
866 [ + + ]: 328 : write(msg, '(a, (80a), a, a, a, a, a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, &
867 : 4 : ' Calculation of phonon density of states, ',ch10, &
868 : 4 : ' thermodynamical properties, ',ch10, &
869 [ + - ]: 332 : ' and Debye-Waller factors.',ch10
870 : 4 : call wrtout(units, msg)
871 : :
872 [ + - ]: 4 : if (dtset%thmflag == 1) then
873 : 4 : call harmonic_thermo(Ifc, crystal, ifc%amu, dtset, ab_out, dtset%prefix_outdata, comm)
874 : :
875 [ # # ]: 0 : else if (dtset%thmflag == 2) then
876 [ # # # # ]: 0 : write(msg, '(a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, ' Entering thm9 routine with thmflag = 2 ',ch10
877 : 0 : call wrtout(units, msg)
878 : 0 : call harmonic_thermo(Ifc, crystal, ifc%amu, dtset, ab_out, dtset%prefix_outdata, comm, thmflag=dtset%thmflag)
879 : : end if
880 : :
881 : 4 : end subroutine anaddb_driver_harmonic_thermo
882 : : !!***
883 : :
884 : : !!****f* m_anaddb_driver/anaddb_driver_dielectric_q0
885 : : !! NAME
886 : : !! anaddb_driver_dielectric_q0
887 : : !!
888 : : !! FUNCTION
889 : : !! Compute dielectric tensor at Gamma and related properties:
890 : : !! mode effective charges, oscillator strength.
891 : : !!
892 : : !! INPUTS
893 : : !!
894 : : !! OUTPUT
895 : : !!
896 : : !! SOURCE
897 : :
898 : 27 : subroutine anaddb_driver_dielectric_q0(driver, dtset, crystal, ifc, ddb, asrq0, ana_ncid, comm)
899 : :
900 : : !Arguments -------------------------------
901 : : class(anaddb_driver_type), intent(inout):: driver
902 : : type(anaddb_dataset_type), intent(in):: dtset
903 : : type(crystal_t), intent(in):: crystal
904 : : type(ifc_type), intent(in):: ifc
905 : : type(ddb_type), intent(in):: ddb
906 : : type(asrq0_t), intent(inout):: asrq0
907 : : integer, intent(in):: ana_ncid
908 : : integer, intent(in):: comm
909 : :
910 : : !Local variables -------------------------------
911 : : integer:: ii, iblok
912 : : integer:: rfelfd(4), rfphon(4), rfstrs(4)
913 : : integer:: units(2)
914 : : real(dp) :: eta
915 : : character(len = 500):: msg
916 : : real(dp):: qphnrm(3), qphon(3, 3)
917 : 27 : real(dp), allocatable:: eigval(:,:)
918 : 27 : real(dp), allocatable:: eigvec(:,:,:,:,:)
919 : 27 : real(dp), allocatable:: lst(:)
920 : : ! ************************************************************************
921 : :
922 [ + + ]: 81 : units = [std_out, ab_out]
923 : :
924 [ - + + - : 81 : ABI_MALLOC(eigval, (3, driver%natom))
+ - + - -
+ - + ]
925 [ - + + - : 135 : ABI_MALLOC(eigvec, (2, 3, driver%natom, 3, driver%natom))
+ - - + +
- + - + -
- + - + ]
926 [ + - - + : 81 : ABI_MALLOC(lst, (dtset%nph2l+1))
+ - + - +
- - + -
+ ]
927 : :
928 [ + + ]: 91 : lst = zero
929 : :
930 : : !***************************************************************
931 : : ! Generates the dynamical matrix at Gamma
932 [ + + ]: 108 : qphon(:,1)=zero; qphnrm(1)=zero
933 : : ! Generation of the dynamical matrix in cartesian coordinates
934 [ + + ]: 27 : if (dtset%ifcflag == 1) then
935 : : ! Get d2cart using the interatomic forces and the
936 : : ! long-range coulomb interaction through Ewald summation
937 : : call gtdyn9(Ifc%acell, Ifc%atmfrc, driver%epsinf, Ifc%dipdip, &
938 : : Ifc%dyewq0, driver%d2cart, crystal%gmet, Ifc%gprim, dtset%mpert, crystal%natom, &
939 : : Ifc%nrpt, qphnrm(1), qphon, crystal%rmet, Ifc%rprim, Ifc%rpt, &
940 : : Ifc%trans, crystal%ucvol, Ifc%wghatm, crystal%xred, driver%zeff, driver%qdrp_cart, &
941 : : Ifc%ewald_option, eta, xmpi_comm_self, dtset%sys_dim,&
942 : : dipquad=Ifc%dipquad, quadquad=Ifc%quadquad, dielt_thick=dtset%dielt_thick,&
943 : 15 : dielt_env=dtset%dielt_env)
944 : :
945 [ + - ]: 12 : else if (dtset%ifcflag == 0) then
946 : : ! Look for the information in the DDB
947 [ + + + + : 108 : rfphon(1:2)=1; rfelfd(1:2)=2; rfstrs(1:2)=0
+ + ]
948 : 12 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
949 [ + + ]: 12 : if (iblok == 0) then
950 [ + + + + ]: 3268 : driver%d2cart(:,1:dtset%msize)=zero
951 : : ! GA: I notice this situation happen in test tutorespfn[telast_3]
952 : : ! and I dont understand why the block is not found.
953 : : else
954 : : ! Copy the dynamical matrix in d2cart
955 [ + + + + ]: 898112 : driver%d2cart(:,1:dtset%msize)=ddb%val(:,:,iblok)
956 : : ! Eventually impose the acoustic sum rule
957 : 11 : call asrq0%apply(crystal%natom, dtset%mpert, dtset%msize, qphon, Crystal, driver%d2cart)
958 : : end if
959 : :
960 : : end if ! end of the generation of the dynamical matrix at gamma.
961 : : !***************************************************************
962 : :
963 : : ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
964 : : call dfpt_phfrq(ddb%amu, driver%displ, driver%d2cart, eigval, eigvec, crystal%indsym, &
965 : : dtset%mpert, crystal%nsym, crystal%natom, crystal%nsym, crystal%ntypat, driver%phfrq, qphnrm(1), qphon, &
966 : 27 : crystal%rprimd, dtset%symdynmat, crystal%symrel, crystal%symafm, crystal%typat, crystal%ucvol)
967 : :
968 : : ! calculation of the oscillator strengths, mode effective charge and
969 : : ! dielectric tensor, frequency dependent dielectric tensor (dieflag)
970 : : ! and mode by mode decomposition of epsilon if dieflag == 3
971 [ + + ]: 27 : if (dtset%dieflag /= 0) then
972 [ - + - - : 17 : if (driver%epsinf(1, 1)==one .and. driver%epsinf(2, 2)==one .and. driver%epsinf(3, 3)==one) then
- - ]
973 : 0 : write(msg, '(7a)') ch10, &
974 : 0 : ' The DDB file does not contain the derivatives w.r.t. electric field perturbation. ',ch10, &
975 : 0 : ' This is mandatory to calculate the dielectric constant, ',ch10, &
976 : 0 : ' Please check your DDB file or use dieflag = 0.',ch10
977 : 0 : ABI_ERROR(msg)
978 : : end if
979 : :
980 [ + - + + ]: 1377 : write(msg, '(a, (80a), a)' ) ch10, ('=',ii = 1, 80), ch10
981 : 17 : call wrtout(units, msg)
982 : :
983 : : ! Print the electronic contribution to the dielectric tensor
984 : : ! It can be extracted directly from the DDB if perturbation with E-field is present
985 : : call ddb_diel(crystal, ddb%amu, dtset, driver%dielt_rlx, driver%displ, driver%d2cart, driver%epsinf, driver%fact_oscstr, &
986 : 17 : ab_out, lst, dtset%mpert, crystal%natom, 0, driver%phfrq, comm, ana_ncid)
987 : : end if
988 : :
989 [ + - ]: 27 : ABI_SFREE(eigval)
990 [ + - ]: 27 : ABI_SFREE(eigvec)
991 [ + - ]: 27 : ABI_SFREE(lst)
992 : :
993 : 27 : end subroutine anaddb_driver_dielectric_q0
994 : : !!***
995 : :
996 : : !!****f* m_anaddb_driver/anaddb_driver_nonlinear_response
997 : : !! NAME
998 : : !! anaddb_driver_nonlinear_response
999 : : !!
1000 : : !! FUNCTION
1001 : : !! Non-linear response: electrooptic and Raman (q = Gamma, TO modes only)
1002 : : !!
1003 : : !! INPUTS
1004 : : !!
1005 : : !! OUTPUT
1006 : : !!
1007 : : !! SOURCE
1008 : :
1009 : 2 : subroutine anaddb_driver_nonlinear_response(driver, dtset, crystal, ana_ncid, comm)
1010 : :
1011 : : !Arguments -------------------------------
1012 : : class(anaddb_driver_type), intent(inout):: driver
1013 : : type(anaddb_dataset_type), intent(in):: dtset
1014 : : type(crystal_t), intent(in):: crystal
1015 : : integer, intent(in):: ana_ncid
1016 : : integer, intent(in):: comm
1017 : :
1018 : : !Local variables -------------------------------
1019 : : integer, parameter:: master = 0
1020 : : integer:: my_rank
1021 : : real(dp):: qphnrm(3), qphon(3, 3)
1022 : 2 : real(dp), allocatable:: rsus(:,:,:)
1023 : : ! ************************************************************************
1024 : :
1025 : 2 : my_rank = xmpi_comm_rank(comm)
1026 : :
1027 [ + - - + : 10 : ABI_MALLOC(rsus, (3*driver%natom, 3, 3))
+ - + - +
- + - + -
- + + - ]
1028 : :
1029 : : ! Raman susceptibilities for the 1st list (only TO modes at q = Gamma)
1030 [ + + ]: 8 : qphon(:,1)=zero
1031 : 2 : qphnrm(1)=zero
1032 : 2 : call ramansus(driver%d2cart, driver%dchide, driver%dchidt, driver%displ, dtset%mpert, crystal%natom, driver%phfrq, qphon, qphnrm(1), rsus, crystal%ucvol)
1033 : :
1034 [ + - ]: 2 : if (my_rank == master) then
1035 : 2 : call defwrite_raman_terms(ana_ncid, crystal%natom, rsus, driver%phfrq)
1036 : : end if
1037 : :
1038 : : ! EO coef:
1039 : 2 : call electrooptic(driver%dchide, dtset%dieflag, driver%epsinf, driver%fact_oscstr, crystal%natom, driver%phfrq, dtset%prtmbm, rsus, crystal%ucvol)
1040 : :
1041 [ + - ]: 2 : ABI_SFREE(rsus)
1042 : :
1043 : 2 : end subroutine anaddb_driver_nonlinear_response
1044 : : !!***
1045 : :
1046 : : !!****f* m_anaddb_driver/anaddb_driver_dielectric_nonana
1047 : : !! NAME
1048 : : !! anaddb_driver_dielectric_nonana
1049 : : !!
1050 : : !! FUNCTION
1051 : : !! Compute non-analyticity in the dielectric matrix and raman susceptibility
1052 : : !!
1053 : : !! INPUTS
1054 : : !!
1055 : : !! OUTPUT
1056 : : !!
1057 : : !! SOURCE
1058 : :
1059 : 24 : subroutine anaddb_driver_dielectric_nonana(driver, dtset, crystal, ddb, ana_ncid, comm)
1060 : :
1061 : : !Arguments -------------------------------
1062 : : class(anaddb_driver_type), intent(inout):: driver
1063 : : type(anaddb_dataset_type), intent(in):: dtset
1064 : : type(crystal_t), intent(in):: crystal
1065 : : type(ddb_type), intent(in):: ddb
1066 : : integer, intent(in):: ana_ncid
1067 : : integer, intent(in):: comm
1068 : :
1069 : : !Local variables -------------------------------
1070 : : integer, parameter:: master = 0
1071 : : integer:: ii, iphl2
1072 : : integer:: natom, nph2l
1073 : : integer:: my_rank
1074 : : integer:: units(2)
1075 : : character(len = 500):: msg
1076 : : real(dp):: qphnrm(3), qphon(3, 3)
1077 : 24 : real(dp), allocatable:: eigval(:,:)
1078 : 24 : real(dp), allocatable:: eigvec(:,:,:,:,:)
1079 : 24 : real(dp), allocatable:: rsus(:,:,:)
1080 : 24 : real(dp), allocatable:: lst(:)
1081 : : ! ************************************************************************
1082 : :
1083 : 24 : my_rank = xmpi_comm_rank(comm)
1084 [ + + ]: 72 : units = [std_out, ab_out]
1085 : :
1086 : 24 : natom = dtset%natom
1087 : 24 : nph2l = dtset%nph2l
1088 [ - + + - : 72 : ABI_MALLOC(eigval, (3, natom))
+ - + - -
+ - + ]
1089 [ - + + - : 120 : ABI_MALLOC(eigvec, (2, 3, natom, 3, natom))
+ - - + +
- + - + -
- + - + ]
1090 [ + - - + : 120 : ABI_MALLOC(rsus, (3*natom, 3, 3))
+ - + - +
- + - + -
- + - + ]
1091 [ + - - + : 72 : ABI_MALLOC(lst, (nph2l+1))
+ - + - +
- - + -
+ ]
1092 [ + + ]: 85 : lst = zero
1093 : :
1094 [ + - + + ]: 1944 : write(msg, '(a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, ' Treat the second list of vectors ',ch10
1095 : 24 : call wrtout(units, msg)
1096 : :
1097 [ + - ]: 24 : if (my_rank == master) then
1098 : 24 : iphl2 = 0
1099 : 24 : call defwrite_nonana_terms(ana_ncid, iphl2, nph2l, dtset%qph2l, dtset%natom, driver%phfrq, driver%displ, "define")
1100 [ + + ]: 24 : if (dtset%nlflag == 1) then
1101 : 2 : call defwrite_nonana_raman_terms(ana_ncid, iphl2, nph2l, dtset%natom, rsus, "define")
1102 : : end if
1103 : : end if
1104 : :
1105 : : !Get the log of product of the square of the phonon frequencies without non-analyticities (q = 0)
1106 : : !For the Lyddane-Sachs-Teller relation, it is stored in lst(nph2+1)
1107 [ + + ]: 24 : if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
1108 [ + + ]: 108 : do ii = 4, 3*crystal%natom
1109 : 108 : lst(nph2l+1)=lst(nph2l+1)+2*log(driver%phfrq(ii))
1110 : : end do
1111 : : end if
1112 : :
1113 : : ! Examine every wavevector of this list
1114 [ + + ]: 61 : do iphl2 = 1, nph2l
1115 : :
1116 : : ! Initialisation of the phonon wavevector
1117 [ + + ]: 148 : qphon(:,1)=dtset%qph2l(:,iphl2)
1118 : 37 : qphnrm(1)=dtset%qnrml2(iphl2)
1119 : :
1120 : : ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
1121 : : ! for the second list of wv (can include non-analyticities if q /= 0)
1122 : : call dfpt_phfrq(ddb%amu, driver%displ, driver%d2cart, eigval, eigvec, crystal%indsym, &
1123 : : dtset%mpert, crystal%nsym, crystal%natom, crystal%nsym, crystal%ntypat, driver%phfrq, qphnrm(1), qphon, &
1124 : 37 : crystal%rprimd, dtset%symdynmat, crystal%symrel, crystal%symafm, crystal%typat, crystal%ucvol)
1125 : :
1126 : : ! Write the phonon frequencies for the second list of wv (can include non-analyticities if q /= 0)
1127 : 37 : call dfpt_prtph(driver%displ, dtset%eivec, dtset%enunit, ab_out, dtset%natom, driver%phfrq, qphnrm(1), qphon)
1128 : : ! TODO: Mode effective charge could be printed here for LO modes (EB)
1129 : :
1130 [ + - ]: 37 : if (my_rank == master) then
1131 : : ! Loop is not MPI-parallelized--> no need for MPI-IO API.
1132 : 37 : call defwrite_nonana_terms(ana_ncid, iphl2, nph2l, dtset%qph2l, dtset%natom, driver%phfrq, driver%displ, "write")
1133 : : end if
1134 : :
1135 : : ! Get the log of product of the square of the phonon frequencies with non-analyticities (q-->0)
1136 : : ! for the Lyddane-Sachs-Teller relation
1137 : : ! The fourth mode should have positive frequency otherwise there is an instability: LST relationship should not be evaluated
1138 : : ! Isn't it tested somewhere else (i.e. stop of the code if there are imaginary freq.)? (EB)
1139 [ + + ]: 37 : if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
1140 [ + + ]: 149 : do ii = 4, 3*crystal%natom
1141 : 149 : lst(iphl2)=lst(iphl2)+2*log(driver%phfrq(ii))
1142 : : end do
1143 : : end if
1144 : :
1145 : : ! Write Raman susceptibilities for the 2nd list (can includes LO modes if q /= 0 0 0)
1146 [ + + ]: 61 : if (dtset%nlflag == 1) then
1147 : 4 : call ramansus(driver%d2cart, driver%dchide, driver%dchidt, driver%displ, dtset%mpert, crystal%natom, driver%phfrq, qphon, qphnrm(1), rsus, crystal%ucvol)
1148 [ + - ]: 4 : if (my_rank == master) then
1149 : 4 : call defwrite_nonana_raman_terms(ana_ncid, iphl2, nph2l, dtset%natom, rsus, "write")
1150 : : end if
1151 : : end if ! nlflag = 1 (Raman suscep for the 2nd list of wv.)
1152 : : end do ! iphl2
1153 : :
1154 : : ! Lyddane-Sachs-Teller relation:
1155 [ + + ]: 24 : if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
1156 : : call ddb_diel(crystal, ddb%amu, dtset, driver%dielt_rlx, driver%displ, driver%d2cart, driver%epsinf, driver%fact_oscstr, &
1157 : 9 : ab_out, lst, dtset%mpert, crystal%natom, nph2l, driver%phfrq, comm, ana_ncid)
1158 : : end if
1159 : :
1160 [ + - ]: 24 : ABI_SFREE(eigval)
1161 [ + - ]: 24 : ABI_SFREE(eigvec)
1162 [ + - ]: 24 : ABI_SFREE(rsus)
1163 [ + - ]: 24 : ABI_SFREE(lst)
1164 : :
1165 : 24 : end subroutine anaddb_driver_dielectric_nonana
1166 : : !!***
1167 : :
1168 : : !!****f* m_anaddb_driver/anaddb_driver_internal_strain
1169 : : !! NAME
1170 : : !! anaddb_driver_internal_strain
1171 : : !!
1172 : : !! FUNCTION
1173 : : !!
1174 : : !! INPUTS
1175 : : !!
1176 : : !! OUTPUT
1177 : : !!
1178 : : !! SOURCE
1179 : :
1180 : 6 : subroutine anaddb_driver_internal_strain(driver, dtset, ddb, asrq0)
1181 : :
1182 : : !Arguments -------------------------------
1183 : : class(anaddb_driver_type), intent(inout):: driver
1184 : : type(anaddb_dataset_type), intent(in):: dtset
1185 : : type(ddb_type), intent(in):: ddb
1186 : : type(asrq0_t), intent(in):: asrq0
1187 : :
1188 : : !Local variables -------------------------------
1189 : : integer:: ii, iblok
1190 : : integer:: prt_internalstr
1191 : : integer:: units(2)
1192 : : integer:: rfelfd(4), rfphon(4), rfstrs(4)
1193 : : character(len = 500):: msg
1194 : : real(dp):: qphnrm(3), qphon(3, 3)
1195 : : ! ************************************************************************
1196 : :
1197 [ + + ]: 18 : units = [std_out, ab_out]
1198 : :
1199 : : ! Here treating the internal strain tensors at Gamma point
1200 [ + + ]: 492 : write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
1201 [ + - ]: 498 : ' Calculation of the internal-strain tensor',ch10
1202 : 6 : call wrtout(units, msg)
1203 : :
1204 [ + - ]: 6 : if (dtset%instrflag == 1) then
1205 : 6 : call wrtout(std_out, 'instrflag = 1, so extract the internal strain constant from the 2DTE')
1206 : :
1207 : : ! looking after the no. of blok that contains the internal strain tensor
1208 [ + + ]: 24 : qphon(:,1)=zero; qphnrm(1)=zero
1209 [ + + + + : 54 : rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
+ + ]
1210 : :
1211 : 6 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
1212 [ - + ]: 6 : if (iblok == 0) then
1213 : 0 : ABI_ERROR("DDB file must contain both uniaxial and shear strain for piezoelectric, Check your calculations")
1214 : : end if
1215 : :
1216 : : ! then print the internal stain tensor
1217 : 6 : prt_internalstr = 2
1218 : 6 : call ddb_internalstr(dtset%asr, ddb%val, asrq0%d2asr, iblok, driver%instrain, ab_out, dtset%mpert, ddb%natom, ddb%nblok, prt_internalstr)
1219 : : end if
1220 : :
1221 : 6 : end subroutine anaddb_driver_internal_strain
1222 : : !!***
1223 : :
1224 : : !!****f* m_anaddb_driver/anaddb_driver_elastic_tensor
1225 : : !! NAME
1226 : : !! anaddb_driver_elastic_tensor
1227 : : !!
1228 : : !! FUNCTION
1229 : : !!
1230 : : !! INPUTS
1231 : : !!
1232 : : !! OUTPUT
1233 : : !!
1234 : : !! SOURCE
1235 : :
1236 : 6 : subroutine anaddb_driver_elastic_tensor(driver, dtset, crystal, ddb, asrq0, ana_ncid)
1237 : :
1238 : : !Arguments -------------------------------
1239 : : class(anaddb_driver_type), intent(inout):: driver
1240 : : type(anaddb_dataset_type), intent(in):: dtset
1241 : : type(crystal_t), intent(in):: crystal
1242 : : type(ddb_type), intent(in):: ddb
1243 : : type(asrq0_t), intent(inout):: asrq0
1244 : : integer, intent(in):: ana_ncid
1245 : :
1246 : : !Local variables -------------------------------
1247 : : integer:: ii, iblok, iblok_stress
1248 : : integer:: units(2)
1249 : : character(len = 500):: msg
1250 : : integer:: rfelfd(4), rfphon(4), rfstrs(4)
1251 : : real(dp):: qphnrm(3), qphon(3, 3)
1252 : : real(dp):: compl(6, 6), compl_clamped(6, 6), compl_stress(6, 6)
1253 : : real(dp):: elast_clamped(6, 6), elast_stress(6, 6)
1254 : : ! ************************************************************************
1255 : :
1256 [ + + ]: 18 : units = [std_out, ab_out]
1257 : :
1258 : : ! here treating the elastic tensors at Gamma Point
1259 [ + + ]: 492 : write(msg, '(a, a, (80a), a, a, a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
1260 [ + - ]: 498 : ' Calculation of the elastic and compliances tensor (Voigt notation)',ch10
1261 : 6 : call wrtout(units, msg)
1262 : :
1263 : 6 : call wrtout(std_out, 'so extract the elastic constant from the 2DTE')
1264 : :
1265 : : ! look after the blok no. that contains the stress tensor
1266 [ + + ]: 24 : qphon(:,1)=zero; qphnrm(1)=zero
1267 [ + + + + : 54 : rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=0
+ + ]
1268 : :
1269 : 6 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx)
1270 : 6 : iblok_stress = iblok
1271 : :
1272 : : ! look after the blok no.iblok that contains the elastic tensor
1273 [ + + ]: 24 : qphon(:,1)=zero; qphnrm(1)=zero
1274 [ + + + + : 54 : rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
+ + ]
1275 : :
1276 : : ! for both diagonal and shear parts
1277 : 6 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
1278 [ - + ]: 6 : if (iblok == 0) then
1279 : 0 : ABI_ERROR("DDB file must contain both uniaxial and shear strain when elaflag != 0, Check your calculations")
1280 : : end if
1281 : :
1282 : : ! print the elastic tensor
1283 : : call ddb_elast(dtset, crystal, ddb%val, compl, compl_clamped, compl_stress, asrq0%d2asr, &
1284 : : driver%elast, elast_clamped, elast_stress, iblok, iblok_stress, &
1285 : 6 : driver%instrain, ab_out, dtset%mpert, crystal%natom, ddb%nblok, ana_ncid)
1286 : :
1287 : 6 : end subroutine anaddb_driver_elastic_tensor
1288 : : !!***
1289 : :
1290 : : !!****f* m_anaddb_driver/anaddb_driver_piezoelectric_tensor
1291 : : !! NAME
1292 : : !! anaddb_driver_piezoelectric_tensor
1293 : : !!
1294 : : !! FUNCTION
1295 : : !!
1296 : : !! INPUTS
1297 : : !!
1298 : : !! OUTPUT
1299 : : !!
1300 : : !! SOURCE
1301 : :
1302 : 5 : subroutine anaddb_driver_piezoelectric_tensor(driver, dtset, crystal, ddb, ana_ncid)
1303 : :
1304 : : !Arguments -------------------------------
1305 : : class(anaddb_driver_type), intent(inout):: driver
1306 : : type(anaddb_dataset_type), intent(in):: dtset
1307 : : type(crystal_t), intent(in):: crystal
1308 : : type(ddb_type), intent(in):: ddb
1309 : : integer, intent(in):: ana_ncid
1310 : :
1311 : : !Local variables -------------------------------
1312 : : integer:: ii, iblok
1313 : : integer:: units(2)
1314 : : character(len = 500):: msg
1315 : : integer:: rfelfd(4), rfphon(4), rfstrs(4)
1316 : : real(dp):: qphnrm(3), qphon(3, 3)
1317 : : real(dp):: piezo(6, 3)
1318 : : ! ************************************************************************
1319 : :
1320 [ + + ]: 15 : units = [std_out, ab_out]
1321 : :
1322 : : ! Here treating the piezoelectric tensor at Gamma Point
1323 [ + + ]: 410 : write(msg, '(a, a, (80a), a, a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
1324 : 5 : ' Calculation of the tensor related to piezoelectric effetc',ch10, &
1325 [ + - ]: 415 : ' (Elastic indices in Voigt notation)',ch10
1326 : 5 : call wrtout(units, msg)
1327 : :
1328 : 5 : call wrtout(std_out, 'extract the piezoelectric constant from the 2DTE')
1329 : :
1330 : : ! Looking for the gamma point block
1331 [ + + ]: 20 : qphon(:,1)=zero; qphnrm(1)=zero
1332 [ + + + + : 45 : rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
+ + ]
1333 : :
1334 : : ! For both diagonal and shear parts
1335 : 5 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
1336 [ - + ]: 5 : if (iblok == 0) then
1337 : 0 : ABI_ERROR("DDB file must contain both uniaxial and shear strain for piezoelectric, Check your calculations")
1338 : : end if
1339 : :
1340 : : ! Then print out the piezoelectric constants
1341 : : call ddb_piezo(dtset, ddb%val, driver%dielt_rlx, driver%elast, iblok, &
1342 : : & driver%instrain, ab_out, dtset%mpert, crystal%natom, ddb%nblok, piezo, &
1343 : 5 : & crystal%ucvol, ana_ncid)
1344 : :
1345 : 5 : end subroutine anaddb_driver_piezoelectric_tensor
1346 : : !!***
1347 : :
1348 : : !!****f* m_anaddb_driver/anaddb_driver_flexoelectric_tensor
1349 : : !! NAME
1350 : : !! anaddb_driver_flexoelectric_tensor
1351 : : !!
1352 : : !! FUNCTION
1353 : : !!
1354 : : !! INPUTS
1355 : : !!
1356 : : !! OUTPUT
1357 : : !!
1358 : : !! SOURCE
1359 : :
1360 : 2 : subroutine anaddb_driver_flexoelectric_tensor(driver, dtset, crystal, ddb, ddb_lw, ddb_hdr, asrq0)
1361 : :
1362 : : !Arguments -------------------------------
1363 : : class(anaddb_driver_type), intent(in):: driver
1364 : : type(anaddb_dataset_type), intent(in):: dtset
1365 : : type(crystal_t), intent(in):: crystal
1366 : : type(ddb_type), intent(in):: ddb, ddb_lw
1367 : : type(ddb_hdr_type), intent(in):: ddb_hdr
1368 : : type(asrq0_t), intent(in):: asrq0
1369 : :
1370 : : !Local variables -------------------------------
1371 : : integer:: ii
1372 : : integer:: units(2)
1373 : : character(len = 500):: msg
1374 : : ! ************************************************************************
1375 : :
1376 [ + + ]: 6 : units = [std_out, ab_out]
1377 : :
1378 : : ! Here treating the flexoelectric tensor
1379 [ + + ]: 164 : write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
1380 [ + - ]: 166 : ' Calculation of the tensors related to flexoelectric effect',ch10
1381 : 2 : call wrtout(units, msg)
1382 : :
1383 : : ! Compute and print the contributions to the flexoelectric tensor
1384 : : call ddb_flexo(dtset%asr, asrq0%d2asr, ddb, ddb_lw, ddb_hdr%ddb_version, crystal, &
1385 : 2 : & dtset%filename_ddb, dtset%flexoflag, dtset%prtvol, driver%zeff)
1386 : :
1387 : 2 : end subroutine anaddb_driver_flexoelectric_tensor
1388 : :
1389 : : !!***
1390 : :
1391 : : !!****f* m_anaddb_driver/anaddb_driver_get_dcdq
1392 : : !! NAME
1393 : : !! anaddb_driver_get_dcdq
1394 : : !!
1395 : : !! FUNCTION
1396 : : !!
1397 : : !! INPUTS
1398 : : !!
1399 : : !! OUTPUT
1400 : : !!
1401 : : !! SOURCE
1402 : :
1403 : 1 : subroutine anaddb_driver_get_dcdq(driver, dtset, ddb, ddb_lw, ddb_hdr)
1404 : :
1405 : : !Arguments -------------------------------
1406 : : class(anaddb_driver_type), intent(inout):: driver
1407 : : type(anaddb_dataset_type), intent(in):: dtset
1408 : : type(ddb_type), intent(in):: ddb, ddb_lw
1409 : : type(ddb_hdr_type), intent(in):: ddb_hdr
1410 : :
1411 : : !Local variables -------------------------------
1412 : : integer:: ii
1413 : : integer:: units(2)
1414 : : character(len = 500):: msg
1415 : : !real(dp):: dcdq(3,ddb%natom,3,ddb%natom,3)
1416 : :
1417 : : ! ************************************************************************
1418 : :
1419 [ + + ]: 3 : units = [std_out, ab_out]
1420 : :
1421 : : ! Here treating the flexoelectric tensor
1422 [ + + ]: 82 : write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
1423 [ + - ]: 83 : ' Extraction from DDB of the IFCs derivatives',ch10
1424 : 1 : call wrtout(units, msg)
1425 : :
1426 : : ! Compute and print the contributions to the flexoelectric tensor
1427 : 1 : call ddb_phi1(ddb,ddb_lw,ddb_hdr%ddb_version, dtset%filename_ddb, driver%dcdq, driver%dcdqdq,ddb%natom)
1428 : :
1429 : 1 : end subroutine anaddb_driver_get_dcdq
1430 : :
1431 : : !!***
1432 : :
1433 : : !!****f* m_anaddb_driver/anaddb_driver_lattice_wannier
1434 : : !! NAME
1435 : : !! anaddb_driver_lattice_wannier
1436 : : !!
1437 : : !! FUNCTION
1438 : : !! Lattice Wannier function calculation.
1439 : : !! Compute the Dynamical matrix for a dense Q-mesh
1440 : : !! Input the eigenvectors and eigenvalues to the Lattcie Wannier module
1441 : : !! Construct the Lattice Wannier functions
1442 : : !!
1443 : : !! INPUTS
1444 : : !!
1445 : : !! OUTPUT
1446 : : !!
1447 : : !! SOURCE
1448 : :
1449 : 3 : subroutine anaddb_driver_lattice_wannier(driver, dtset, crystal, ifc, comm)
1450 : :
1451 : : !Arguments -------------------------------
1452 : : class(anaddb_driver_type), intent(in):: driver
1453 : : type(anaddb_dataset_type), intent(in):: dtset
1454 : : type(crystal_t),intent(in):: crystal
1455 : : type(ifc_type), intent(in):: ifc
1456 : : integer,intent(in):: comm
1457 : :
1458 : : !Local variables -------------------------------
1459 : : integer:: ii
1460 : : character(len = 500):: msg
1461 : : integer:: units(2)
1462 : : ! ************************************************************************
1463 : :
1464 [ + + ]: 9 : units = [std_out, ab_out]
1465 : : ABI_UNUSED(driver%natom)
1466 : :
1467 [ + - + + ]: 243 : write(msg, '(a, (80a), 4a)')ch10, ('=',ii = 1, 80), ch10, ch10, ' Calculation of lattice Wannier functions ',ch10
1468 : 3 : call wrtout(units, msg)
1469 : 3 : call run_lattice_wannier(ifc=ifc, crystal=crystal, dtset=dtset, prefix=dtset%prefix_outdata, comm=comm)
1470 [ + - + + ]: 243 : write(msg, '(a, (80a))')ch10, ('=',ii = 1, 80)
1471 : 3 : call wrtout(units, msg)
1472 : :
1473 : 3 : end subroutine anaddb_driver_lattice_wannier
1474 : : !!***
1475 : :
1476 : : !!***
1477 : :
1478 : : !!****f* m_anaddb_driver/anaddb_driver_convertdim_dielt
1479 : : !! NAME
1480 : : !! anaddb_driver_convertdim_dielt
1481 : : !!
1482 : : !! FUNCTION
1483 : : !! Supposing a reduced dimensionality of the problem, convert DDB dielectric tensor
1484 : : !! to the low-dimensionality dielectric tensor of the isolated material. Indeed,
1485 : : !! first-principles calculations requires vacuum buffer(s) to isolate the low-dimensional
1486 : : !! materials, that spuriously contributes to the dielectric response of the whole slab
1487 : : !!
1488 : : !! INPUTS
1489 : : !!
1490 : : !! OUTPUT
1491 : : !!
1492 : : !! SOURCE
1493 : :
1494 : 2 : subroutine anaddb_driver_convertdim_dielt(driver, rprimd, sys_dim, dielt_thick)
1495 : :
1496 : : !Arguments -------------------------------
1497 : : class(anaddb_driver_type), intent(inout):: driver
1498 : : integer,intent(in):: sys_dim
1499 : : real(dp) :: dielt_thick(2), rprimd(3,3)
1500 : :
1501 : : !Local variables -------------------------------
1502 : : integer:: idir, jdir, kdir, bool_isolated(3)
1503 : : real(dp) :: thick, epsinf_conv(3,3), acell(3)
1504 : : character(len = 500):: msg
1505 : :
1506 : : ! ************************************************************************
1507 : 2 : epsinf_conv=zero
1508 : 2 : thick = dielt_thick(1)-dielt_thick(2)
1509 : 2 : bool_isolated(:) = 0
1510 : : ! When periodic, additional variable spaces coming from dynamical matrices derivatives
1511 [ + - ]: 2 : if (sys_dim == 1) then ! 3D
1512 : : bool_isolated = 0
1513 [ - + ]: 2 : elseif (sys_dim == 2) then ! 2D yz
1514 : 0 : bool_isolated(1) = 1
1515 [ - + ]: 2 : elseif (sys_dim == 3) then ! 2D xz
1516 : 0 : bool_isolated(2) = 1
1517 [ + - ]: 2 : elseif (sys_dim == 4) then ! 2D xy
1518 : 2 : bool_isolated(3) = 1
1519 : : else
1520 : : write(msg,'(3a,i0)') &
1521 : 0 : 'For dipole-dipole in 2D, the argument sys_dim should',ch10,&
1522 : 0 : 'be between 1 and 4. However, sys_dim = ',sys_dim
1523 : 0 : ABI_ERROR(msg)
1524 : : end if
1525 [ + + ]: 8 : do idir = 1,3
1526 [ + + ]: 26 : do jdir =1,3
1527 [ + + + + : 24 : if (bool_isolated(idir)==1 .and. bool_isolated(jdir)==0 .and. driver%epsinf(idir,jdir)>tol2) then
- + ]
1528 : : write(msg,'(3a)')&
1529 : 0 : 'Along a confined + periodic directions, the dielectric tensor should be 0.',ch10,&
1530 : 0 : 'However, a component is found to be larger than 1e-6. Please check your DDB file'
1531 : 0 : ABI_ERROR(msg)
1532 : : end if
1533 : : end do
1534 : : end do
1535 [ + + ]: 8 : do idir=1,3
1536 [ + + ]: 26 : acell(idir)= sqrt(dot_product(rprimd(idir,:),rprimd(idir,:)))
1537 : : end do
1538 : : write(msg,'(2a)') &
1539 : 2 : 'Conversion of the dielectric tensor for 2D materials to account for vacuum',ch10
1540 [ + + ]: 6 : call wrtout([std_out, ab_out],msg)
1541 [ + + ]: 8 : do kdir=1,3
1542 [ + + ]: 8 : if (bool_isolated(kdir)==1) then
1543 [ + + ]: 8 : do idir=1,3
1544 [ + + ]: 26 : do jdir=1,3
1545 [ + + + + ]: 24 : if (bool_isolated(idir)==0 .and. bool_isolated(jdir)==0) then
1546 : : ! Capacitors in parallel for periodic directions between 2D and vacuum
1547 [ + + ]: 8 : if (idir==jdir) then
1548 : 4 : epsinf_conv(idir,jdir)=one-acell(kdir)/dielt_thick(1)*(one-driver%epsinf(idir,jdir))
1549 : : else
1550 : 4 : epsinf_conv(idir,jdir)=acell(kdir)/dielt_thick(1)*driver%epsinf(idir,jdir)
1551 : : end if
1552 [ + + + + ]: 10 : elseif (bool_isolated(idir)==1 .and. bool_isolated(jdir)==1) then
1553 : : ! Capacitors in series for confined direction between 2D and vacuum
1554 : 2 : epsinf_conv(idir,jdir)= one/(one-acell(kdir)/thick*(one-one/driver%epsinf(idir,jdir)))
1555 : : end if
1556 : : end do
1557 : : end do
1558 : : end if
1559 : : end do
1560 : : write(msg,'(a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a)')&
1561 : 2 : 'Converted dielectric tensor',epsinf_conv(1,1),' ',epsinf_conv(1,2), ' ', epsinf_conv(1,3),' '&
1562 : 2 : ,epsinf_conv(2,1),' ',epsinf_conv(2,2), ' ', epsinf_conv(2,3),' '&
1563 : 4 : ,epsinf_conv(3,1),' ',epsinf_conv(3,2), ' ', epsinf_conv(3,3), ch10
1564 [ + + ]: 6 : call wrtout([std_out, ab_out],msg)
1565 [ + + + + ]: 26 : driver%epsinf = epsinf_conv
1566 : :
1567 : 2 : end subroutine anaddb_driver_convertdim_dielt
1568 : :
1569 [ # # # # : 0 : end module m_anaddb_driver
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
1570 : : !!***
|