Line data Source code
1 : !!****m* ABINIT/m_ddb
2 : !! NAME
3 : !! m_ddb
4 : !!
5 : !! FUNCTION
6 : !! This module contains the declaration of data types and methods
7 : !! used to handle the blocks of data in DDB files:
8 : !! blkval, nrm, qpt, flg, and associated dimensions
9 : !! Main entry point for client code that needs to read the DDB data.
10 : !!
11 : !! COPYRIGHT
12 : !! Copyright (C) 2011-2026 ABINIT group (MJV, XG, MT, MM, MVeithen, MG, PB, JCC, SP, GA, MMignolet)
13 : !! This file is distributed under the terms of the
14 : !! GNU General Public License, see ~abinit/COPYING
15 : !! or http://www.gnu.org/copyleft/gpl.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 : module m_ddb
26 :
27 : use defs_basis
28 : use m_abicore
29 : use m_errors
30 : use m_xmpi
31 : use m_ddb_hdr
32 : use m_dtset
33 : use m_nctk
34 : use netcdf
35 :
36 : use m_io_tools, only : iomode_from_fname
37 : use defs_datatypes, only : pseudopotential_type
38 : use m_fstrings, only : sjoin, itoa, ktoa, endswith
39 : use m_numeric_tools, only : mkherm
40 : use m_matrix, only : mati3inv, matr3inv
41 : use m_symtk, only : littlegroup_q, symatm
42 : use m_io_tools, only : get_unit
43 : use m_copy, only : alloc_copy
44 : use m_geometry, only : phdispl_cart2red, mkrdim, xred2xcart, metric, d3lwsym
45 : use m_crystal, only : crystal_t
46 : use m_dynmat, only : cart29, d2sym3, cart39, d3sym, chneu9, asria_calc, asria_corr,&
47 : msria_calc, msria_apply, asrprs, dfpt_phfrq, sytens
48 : use m_pawtab, only : pawtab_type, pawtab_nullify, pawtab_free
49 : use m_psps, only : psps_copy, psps_free
50 :
51 : implicit none
52 :
53 : private
54 :
55 : public :: rdddb9 ! This routine reads the derivative database entirely,
56 : public :: nlopt ! Output of all quantities related to third-order derivatives of the energy.
57 : public :: chkin9
58 : public :: gamma9
59 : public :: carttransf ! Transform a second-derivative matrix (EIG2D) from reduced
60 : ! coordinates to cartesian coordinates.
61 : public :: lwcart ! Transform a 3rd order derivative tensor (long-wave) from reduced (actually
62 : ! mixed since strain derivatives are already in cartesian) to cartesian
63 : ! coordinates
64 : public :: ddb_lw_copy ! Copy the ddb object after reading the long wave 3rd order derivatives
65 : ! into a new ddb_lw and resizes ddb as for 2nd order derivatives
66 :
67 : public :: symdm9
68 :
69 : real(dp),public,parameter :: DDB_QTOL=2.0d-8
70 : ! Tolerance for the identification of two wavevectors
71 : !!***
72 :
73 : !----------------------------------------------------------------------
74 :
75 : !!****t* m_ddb/ddb_type
76 : !! NAME
77 : !! ddb_type
78 : !!
79 : !! FUNCTION
80 : !! Provides methods to extract and post-process the results in the derivative database (DDB)
81 : !!
82 : !! SOURCE
83 :
84 : type,public :: ddb_type
85 :
86 : logical :: has_ncid_open
87 : ! Is currently reading a netcdf file
88 :
89 : integer :: iblock_d2eig_nc
90 : ! Is currently reading a netcdf file
91 :
92 : integer :: msize
93 : ! Maximum size of dynamical matrices and other perturbations (ddk, dde...)
94 :
95 : integer :: mpert
96 : ! Maximum number of perturbations
97 :
98 : integer :: nblok
99 : ! Number of 2dte blocks in present object
100 :
101 : integer :: natom
102 : ! Number of atoms in the unit cell.
103 :
104 : integer :: ntypat
105 : ! Number of type of atoms.
106 :
107 : integer :: occopt
108 : ! Occupation option.
109 :
110 : integer :: prtvol
111 : ! Verbosity level.
112 :
113 : integer :: nband
114 : ! Number of bands for eigenvalues derivatives
115 : ! This corresponds to d2eig arrary shape,
116 : ! but the actual number of band is nband / nsppol
117 :
118 : integer :: nkpt
119 : ! Number of k-points for eigenvalues derivatives
120 :
121 : ! GA: FIXME
122 : integer :: nsppol
123 : ! Number of spin components for eigenvalues derivatives
124 : ! This index is absorbed into nband, to limit array ranks to 7.
125 :
126 : integer :: current_iblok
127 : ! Number of k-points for eigenvalues derivatives
128 :
129 : ! These values are used to call the anaddb routines that don't use rprimd, gprimd.
130 : real(dp) :: rprim(3,3)
131 : real(dp) :: gprim(3,3)
132 : real(dp) :: acell(3)
133 :
134 :
135 : ! Many of these variables should become private so that one can refactor the ddb_t implementation
136 : integer,allocatable :: flg(:,:)
137 : ! flg(msize,nblok)
138 : ! Flag to indicate presence of a given block
139 :
140 : integer,allocatable :: typ(:)
141 : ! typ(nblok)
142 : ! Type of each block - nth-order derivatives of energy or eigenvalues.
143 : ! (0 => total energy)
144 : ! (1=> non-stationary block),
145 : ! (2=> stationary block),
146 : ! (3=> third order derivative).
147 : ! (4 => first-order derivatives of total energy)
148 : ! (5 => 2nd-order derivatives of eigenvalues)
149 : ! (33 => long wave third order derivatives of total energy)
150 : ! (85 => Molecular Berry curvature, 2nd-order derivative)
151 : ! See m_ddb_hdr for the definition of various block types
152 :
153 : real(dp),allocatable :: amu(:)
154 : ! amu(ntypat)
155 : ! Mass of the atoms (atomic mass unit)
156 :
157 : real(dp),allocatable :: omega(:,:)
158 : ! omega(3,nblok)
159 : ! Frequency of the perturbations
160 : ! Three possible frequencies can be specified for 3rd order derivatives.
161 :
162 : real(dp),allocatable :: qpt(:,:)
163 : ! qpt(9,nblok)
164 : ! q-point vector in reciprocal space (reduced lattice coordinates) for each block
165 : ! Three possible phonon wavevectors can be specified for 3rd order derivatives,
166 : ! but only one should be used in case of second derivative of total energy,
167 : ! because we know that the second is the opposite of this value.
168 :
169 : real(dp),allocatable :: nrm(:,:)
170 : ! nrm(3,nblok)
171 : ! Normalization factors of the wavevectors for each block - can be 0 to indicate a direction of approach to gamma
172 :
173 : real(dp),allocatable :: val(:,:,:)
174 : ! val(2,msize,nblok)
175 : ! Values of the second energy derivatives in each block
176 :
177 : real(dp),allocatable :: val_fs(:,:,:)
178 : ! val_fs(2,msize,nblok)
179 : ! Values of the second energy derivatives in each block, at fixed-spin magnetic boundary conditions.
180 :
181 : real(dp),allocatable :: val_rs(:,:,:)
182 : ! val_rs(2,msize,nblok)
183 : ! Values of the second energy derivatives in each block, at relaxed-spin magnetic boundary conditions.
184 :
185 : real(dp),allocatable :: kpt(:,:)
186 : ! kpt(3,nkpt)
187 : ! k-point vector in reciprocal space for eigenvalues derivatives
188 :
189 : real(dp),allocatable :: eig2dval(:,:,:,:)
190 : ! eig2dval(2,msize,nband,nkpt)
191 : ! Values of the second derivatives of eigenvalues
192 : ! Only a single block (a single q-point) is held in memory.
193 : ! Note that isppol index is wrapped into nband index.
194 :
195 : contains
196 :
197 : procedure :: init => ddb_init
198 : ! Construct the object from the dtset.
199 :
200 : procedure :: free => ddb_free
201 : ! Free dynamic memory.
202 :
203 : procedure :: malloc => ddb_malloc
204 : ! Allocate dynamic memory
205 :
206 : procedure :: malloc_d2eig => ddb_malloc_d2eig
207 : ! Allocate dynamic memory
208 :
209 : procedure :: copy => ddb_copy
210 : ! Copy the object.
211 :
212 : procedure :: set_omega => ddb_set_omega
213 : ! Set the frequency
214 :
215 : !procedure :: get_qptopt => ddb_get_qptopt
216 :
217 : procedure :: set_qpt => ddb_set_qpt
218 : ! Set the wavevector
219 :
220 : procedure :: set_d1matr => ddb_set_d1matr
221 : ! Set values for the first-order derivative matrix in tensor shape
222 :
223 : procedure :: get_d1matr => ddb_get_d1matr
224 : ! Transform the first-order derivative matrix in tensor shape
225 :
226 : procedure :: set_d2matr => ddb_set_d2matr
227 : ! Set values for the second-order derivative matrix
228 :
229 : procedure :: get_d2matr => ddb_get_d2matr
230 : ! Transform the second-order derivative matrix in tensor shape
231 :
232 : procedure :: set_d3matr => ddb_set_d3matr
233 : ! Set values for the third-order derivative matrix
234 :
235 : procedure :: get_d3matr => ddb_get_d3matr
236 : ! Transform the third-order derivative matrix in tensor shape
237 :
238 : procedure :: get_d2eig => ddb_get_d2eig
239 : ! Transform the second-order derivative matrix of eigs in tensor shape
240 :
241 : procedure :: set_d2eig => ddb_set_d2eig
242 : ! Set values for the second-order derivative matrix of eigs
243 :
244 : procedure :: set_d2eig_reshape => ddb_set_d2eig_reshape
245 : ! Set values for the second-order derivative matrix of eigs
246 : ! with band index before perturbation indices
247 :
248 : procedure :: set_gred => ddb_set_gred
249 : ! Set the gradient of total energy in reduced coordinates
250 :
251 : procedure :: set_pel => ddb_set_pel
252 : ! Set the electronic polarization
253 :
254 : procedure :: set_strten => ddb_set_strten
255 : ! Set the stress tensor
256 :
257 : procedure :: set_etotal => ddb_set_etotal
258 : ! Set the total energy
259 :
260 : procedure :: set_brav => ddb_set_brav
261 : ! Set the bravais lattice.
262 :
263 : procedure :: to_d2etot => ddb_to_d2etot
264 : ! Converts physical quantities stored in ddb into mathematical
265 : ! second-order derivatives of total energy
266 :
267 : procedure :: set_typ => ddb_set_typ
268 : ! Set the typ of one block
269 :
270 : procedure :: bcast => ddb_bcast
271 : ! Broadcast the object.
272 :
273 : procedure :: get_etotal => ddb_get_etotal
274 : ! Read the GS total energy.
275 :
276 : procedure :: get_gred => ddb_get_gred
277 : ! Get the gradient of total energy in reduced coordinates
278 :
279 : procedure :: get_pel => ddb_get_pel
280 : ! Get the electronic polarization
281 :
282 : procedure :: get_strten => ddb_get_strten
283 : ! Get the stress tensor
284 :
285 : procedure :: get_dielt_zeff => ddb_get_dielt_zeff
286 : ! Reads the Dielectric Tensor and the Effective Charges
287 :
288 : procedure :: get_dielt => ddb_get_dielt
289 : ! Reads the Dielectric Tensor
290 :
291 : procedure :: get_quadrupoles => ddb_get_quadrupoles
292 : ! Reads the Quadrupoles
293 :
294 : procedure :: get_dchidet => ddb_get_dchidet
295 : ! Reads the non-linear optical susceptibility tensor and the
296 : ! first-order change in the linear dielectric susceptibility
297 :
298 : procedure :: diagoq => ddb_diagoq
299 : ! Compute the phonon frequencies at the specified q-point by performing
300 : ! a direct diagonalizatin of the dynamical matrix.
301 :
302 : procedure :: symmetrize_and_transform => ddb_symmetrize_and_transform
303 : ! Symmetrize, transform cartesian coordinates, and add missing components
304 :
305 : procedure :: write_block_txt => ddb_write_block_txt
306 : ! Writes blocks of data in the DDB in text format.
307 :
308 : procedure :: write => ddb_write
309 : ! Write the DDB file in either txt or netcdf format.
310 :
311 : procedure :: write_txt => ddb_write_txt
312 : ! Write the body of the DDB text file.
313 :
314 : procedure :: write_nc => ddb_write_nc
315 : ! Write the netcdf file (DDB.nc).
316 :
317 : procedure :: read_block_txt => ddb_read_block_txt
318 : ! Read blocks of data in the DDB.
319 :
320 : procedure :: get_block => ddb_get_block
321 : ! Finds the block containing the derivatives of the total energy.
322 :
323 : procedure :: read_d2eig => ddb_read_d2eig
324 : ! Read the next DDB block containing 2nd order derivatives of eigenvalues.
325 :
326 : procedure :: read_d2eig_txt => ddb_read_d2eig_txt
327 : ! Read the next DDB block containing 2nd order derivatives of eigenvalues.
328 :
329 : procedure :: read_d2eig_nc => ddb_read_d2eig_nc
330 : ! Read the next DDB block containing 2nd order derivatives of eigenvalues.
331 :
332 : procedure :: write_d2eig => ddb_write_d2eig
333 : ! Read the current DDB block containing 2nd order derivatives of eigenvalues.
334 :
335 : procedure :: write_d2eig_txt => ddb_write_d2eig_txt
336 : ! Read the current DDB block containing 2nd order derivatives of eigenvalues.
337 :
338 : procedure :: write_d2eig_nc => ddb_write_d2eig_nc
339 : ! Write the current DDB block containing 2nd order derivatives of eigenvalues.
340 :
341 : procedure :: read_d0E_nc => ddb_read_d0E_nc
342 : ! Read the next DDB block containing 0th order derivatives of energy.
343 :
344 : procedure :: read_d1E_nc => ddb_read_d1E_nc
345 : ! Read the next DDB block containing 1st order derivatives of energy.
346 :
347 : procedure :: read_d2E_nc => ddb_read_d2E_nc
348 : ! Read the next DDB block containing 2nd order derivatives of energy.
349 :
350 : procedure :: read_d3E_nc => ddb_read_d3E_nc
351 : ! Read the next DDB block containing 3rd order derivatives of energy.
352 :
353 : procedure :: from_file => ddb_from_file
354 : ! Construct the object from the DDB file.
355 :
356 : procedure :: read_txt => ddb_read_txt
357 : ! Construct the object from the DDB file in text format.
358 :
359 : procedure :: read_nc => ddb_read_nc
360 : ! Construct the object from the DDB file in netcdf format.
361 :
362 : procedure :: can_merge_blocks => ddb_can_merge_blocks
363 : ! Tell if two blocks can be merged
364 :
365 : procedure :: merge_blocks => ddb_merge_blocks
366 : ! Merge a block of an other ddb to the current object.
367 :
368 : end type ddb_type
369 :
370 : public :: ddb_to_dtset ! Transfer ddb_hdr to dtset datatype
371 : public :: merge_ddb ! Read a list of ddb files and merge them into a single ddb object
372 :
373 : !!***
374 :
375 : !!****t* m_ddb/asr_t
376 : !! NAME
377 : !! asr_t
378 : !!
379 : !! FUNCTION
380 : !! Object used to enforce the acoustic sum rule from the Dynamical matrix at Gamma.
381 : !! Wraps several approaches that can be activated via the `asr` option.
382 : !!
383 : !! SOURCE
384 :
385 : type,public :: asrq0_t
386 :
387 : integer :: iblok = 0
388 : ! Index of the Gamma block in the DDB.
389 : ! Set to 0 if no block was found. Client code can use this flag to understand
390 : ! if ASR can be enforced.
391 :
392 : integer :: asr
393 : ! Option for the application of the ASR (input variable).
394 :
395 : integer :: natom
396 : ! Number of atoms.
397 :
398 : real(dp),allocatable :: d2asr(:,:,:,:,:)
399 : ! d2asr,(2,3,natom,3,natom))
400 : ! In case the interatomic forces are not calculated, the
401 : ! ASR-correction (d2asr) has to be determined here from the Dynamical matrix at Gamma.
402 :
403 : real(dp),allocatable :: d2dqmsr(:,:,:,:,:)
404 : ! d2dqmsr,(3,natom,3,natom,3))
405 : ! Corrections to the IFCs first derivatives from translational + rotational invariance.
406 :
407 : real(dp),allocatable :: d2dqdqmsr(:,:,:,:,:,:)
408 : ! d2dqmsr,(3,natom,3,natom,3,3))
409 : ! Corrections to the IFCs second derivatives from translational + rotational invariance.
410 :
411 : ! singular, uinvers and vtinvers are allocated and used only if asr in [3,4]
412 : ! i.e. Rotational invariance for 1D and 0D systems. dims=3*natom*(3*natom-1)/2
413 : real(dp),allocatable :: singular(:)
414 : ! singular,(1:dims))
415 :
416 : real(dp),allocatable :: uinvers(:,:)
417 : ! uinvers,(1:dims,1:dims))
418 :
419 : real(dp),allocatable :: vtinvers(:,:)
420 : ! vtinvers,(1:dims,1:dims))
421 :
422 : contains
423 :
424 : procedure :: init => asrq0_init
425 : ! Init the object from a ddb.
426 :
427 : procedure :: apply => asrq0_apply
428 : ! Impose the acoustic sum rule based on the q=0 block found in the DDB file.
429 :
430 : procedure :: free => asrq0_free
431 : ! Free memory
432 :
433 : end type asrq0_t
434 : !!***
435 :
436 : CONTAINS !===========================================================
437 : !!***
438 :
439 : !----------------------------------------------------------------------
440 :
441 : !!****f* m_ddb/ddb_init
442 : !! NAME
443 : !! ddb_init
444 : !!
445 : !! FUNCTION
446 : !! Initialize a new ddb object for the current calculation.
447 : !!
448 : !! INPUTS
449 : !! ddb=the new ddb object
450 : !! dtset=dtset object of the current calculation
451 : !! nblok=number of blocks
452 : !! mpert=maximum number of perturbations (atom displacements + electric field + ...)
453 : !! with_d0E=this ddb contains 0th order derivatives
454 : !! with_d1E=this ddb contains 1st order derivatives
455 : !! with_d2E=this ddb contains 2nd order derivatives
456 : !! with_d3E=this ddb contains 3rd order derivatives
457 : !! with_d2eig=this ddb contains 2nd order derivatives of eigenvalues
458 : !! mband='number of bands' dimension of the d2eig array.
459 : !! Should actually correspond to the maximum number of bands for one kpoint
460 : !! multiplied by the number of spin polarization (mband*nsppol).
461 : !! nkpt=number of kpoints
462 : !! kpt=reduced coordinates of kpoints
463 : !!
464 : !! SOURCE
465 :
466 3399 : subroutine ddb_init(ddb, dtset, nblok, mpert, &
467 3399 : mband, nkpt, kpt,&
468 : with_d0E, with_d1E, with_d2E, with_d3E, with_d2eig)
469 :
470 : !Arguments -------------------------------
471 : class(ddb_type),intent(inout) :: ddb
472 : type(dataset_type),intent(in) :: dtset
473 : integer,intent(in) :: nblok, mpert
474 : integer,intent(in),optional :: mband,nkpt
475 : real(dp),intent(in),optional :: kpt(:,:)
476 : logical,intent(in),optional :: with_d0E, with_d1E, with_d2E, with_d3E, with_d2eig
477 :
478 : !Local variables -------------------------------
479 : integer :: msize_, ii, ikpt
480 : logical :: with_d0E_, with_d1E_, with_d2E_, with_d3E_, with_d2eig_
481 : ! ************************************************************************
482 :
483 3399 : with_d0E_ = .false. ; if (present(with_d0E)) with_d0E_ = with_d0E
484 3399 : with_d1E_ = .false. ; if (present(with_d1E)) with_d1E_ = with_d1E
485 3399 : with_d2E_ = .false. ; if (present(with_d2E)) with_d2E_ = with_d2E
486 3399 : with_d3E_ = .false. ; if (present(with_d3E)) with_d3E_ = with_d3E
487 3399 : with_d2eig_ = .false. ; if (present(with_d2eig)) with_d2eig_ = with_d2eig
488 :
489 3399 : msize_ = 0
490 3399 : if (with_d0E_) msize_ = 1
491 3399 : if (with_d1E_) msize_ = 3 * mpert
492 3399 : if (with_d2E_ .or. with_d2eig_) msize_ = 3 * mpert * 3 * mpert
493 3399 : if (with_d3E_) msize_ = 3 * mpert * 3 * mpert * 3 * mpert
494 :
495 3399 : call ddb%malloc(msize_, nblok, dtset%natom, dtset%ntypat, mpert)
496 :
497 3399 : ddb%occopt = dtset%occopt
498 3399 : ddb%prtvol = dtset%prtvol
499 :
500 44187 : ddb%rprim(:,:) = dtset%rprim_orig(1:3,1:3,1)
501 13596 : ddb%acell(:) = dtset%acell_orig(1:3,1)
502 :
503 3399 : call matr3inv(ddb%rprim, ddb%gprim)
504 :
505 28179 : ddb%omega(:,:) = zero
506 65349 : ddb%qpt(:,:) = zero
507 28179 : ddb%nrm(:,:) = one
508 3399 : if (with_d0E_) then
509 0 : ddb%typ(:) = BLKTYP_d0E_xx
510 3399 : else if (with_d1E_) then
511 8402 : ddb%typ(:) = BLKTYP_d1E_xx
512 596 : else if (with_d2E_) then
513 836 : ddb%typ(:) = BLKTYP_d2E_ns
514 178 : else if (with_d3E_) then
515 82 : ddb%typ(:) = BLKTYP_d3E_xx
516 137 : else if (with_d2eig_) then
517 274 : ddb%typ(:) = BLKTYP_d2eig_re
518 : end if
519 :
520 2755731 : ddb%flg(:,:) = 0
521 7689 : ddb%amu(:) = dtset%amu_orig(:,1)
522 :
523 3399 : ddb%nsppol = dtset%nsppol
524 :
525 3399 : if (present(mband)) then
526 137 : ddb%nband = mband
527 : else
528 3262 : ddb%nband = dtset%mband * ddb%nsppol
529 : end if
530 :
531 3399 : if (present(nkpt)) then
532 137 : ddb%nkpt = nkpt
533 : else
534 3262 : ddb%nkpt = dtset%nkpt
535 : end if
536 :
537 : ! TODO: Allocate d2eig here instead of leaving it to the calling routine.
538 3399 : if (with_d2eig_) call ddb%malloc_d2eig(ddb%nband*ddb%nsppol, ddb%nkpt)
539 :
540 3399 : if (present(kpt)) then
541 2200 : do ikpt=1,ddb%nkpt
542 8389 : do ii = 1,3
543 8252 : ddb%kpt(ii,ikpt) = kpt(ii,ikpt)
544 : end do
545 : end do
546 : end if
547 :
548 3399 : end subroutine ddb_init
549 : !!***
550 :
551 : !----------------------------------------------------------------------
552 :
553 : !!****f* m_ddb/ddb_free
554 : !! NAME
555 : !! ddb_free
556 : !!
557 : !! FUNCTION
558 : !! Clean and deallocate types for the ddb_type structure
559 : !!
560 : !! SOURCE
561 :
562 4100 : subroutine ddb_free(ddb)
563 :
564 : !Arguments -------------------------------
565 : class(ddb_type),intent(inout) :: ddb
566 : ! ************************************************************************
567 :
568 : !integer
569 4100 : ABI_SFREE(ddb%flg)
570 4100 : ABI_SFREE(ddb%typ)
571 :
572 : ! real
573 4100 : ABI_SFREE(ddb%amu)
574 4100 : ABI_SFREE(ddb%qpt)
575 4100 : ABI_SFREE(ddb%omega)
576 4100 : ABI_SFREE(ddb%nrm)
577 4100 : ABI_SFREE(ddb%val_fs)
578 4100 : ABI_SFREE(ddb%val_rs)
579 4100 : ABI_SFREE(ddb%kpt)
580 4100 : ABI_SFREE(ddb%val)
581 4100 : ABI_SFREE(ddb%eig2dval)
582 :
583 4100 : end subroutine ddb_free
584 : !!***
585 :
586 : !----------------------------------------------------------------------
587 :
588 : !!****f* m_ddb/ddb_copy
589 : !! NAME
590 : !! ddb_copy
591 : !!
592 : !! FUNCTION
593 : !! Create object and copy all types for the ddb_type structure
594 : !!
595 : !! SOURCE
596 :
597 9 : subroutine ddb_copy(iddb, oddb)
598 :
599 : !Arguments -------------------------------
600 : class(ddb_type),intent(in) :: iddb
601 : class(ddb_type),intent(out) :: oddb
602 : ! ************************************************************************
603 :
604 : ! Copy dimensions and static variables.
605 9 : oddb%msize = iddb%msize
606 9 : oddb%mpert = iddb%mpert
607 9 : oddb%nblok = iddb%nblok
608 9 : oddb%natom = iddb%natom
609 9 : oddb%ntypat = iddb%ntypat
610 9 : oddb%occopt = iddb%occopt
611 9 : oddb%prtvol = iddb%prtvol
612 :
613 117 : oddb%rprim = iddb%rprim
614 117 : oddb%gprim = iddb%gprim
615 36 : oddb%acell = iddb%acell
616 :
617 : ! Allocate and copy the allocatable arrays.
618 9 : call alloc_copy(iddb%flg, oddb%flg)
619 9 : call alloc_copy(iddb%typ, oddb%typ)
620 9 : call alloc_copy(iddb%amu, oddb%amu)
621 9 : call alloc_copy(iddb%nrm, oddb%nrm)
622 9 : call alloc_copy(iddb%omega, oddb%omega)
623 9 : call alloc_copy(iddb%qpt, oddb%qpt)
624 9 : call alloc_copy(iddb%val, oddb%val)
625 : ! call alloc_copy(iddb%val_fs, oddb%val_fs)
626 : ! call alloc_copy(iddb%val_rs, oddb%val_rs)
627 :
628 9 : end subroutine ddb_copy
629 : !!***
630 :
631 : !----------------------------------------------------------------------
632 :
633 : !!****f* m_ddb/ddb_malloc
634 : !! NAME
635 : !! ddb_malloc
636 : !!
637 : !! FUNCTION
638 : !! Allocate dynamic memory.
639 : !!
640 : !! INPUTS
641 : !! msize=maximum size of one block of the ddb
642 : !! (e.g. 3*mpert * 3*mpert)
643 : !! nblok=number of blocks in the ddb
644 : !! natom=number of atoms
645 : !! ntypat=number of atom types
646 : !! mpert=maximum number of perturbations
647 : !! (atom displacements + electric field + ...)
648 : !! nkpt=number of k-points. Optional, indicates the use of eig2d.
649 : !! nband='number of bands' dimension of the d2eig array.
650 : !! Should actually correspond to the maximum number of bands for one kpoint
651 : !! multiplied by the number of spin polarization (mband*nsppol).
652 : !!
653 : !! SOURCE
654 :
655 3930 : subroutine ddb_malloc(ddb, msize, nblok, natom, ntypat, mpert, nkpt, nband)
656 :
657 : !Arguments -------------------------------
658 : class(ddb_type),intent(inout) :: ddb
659 : integer,intent(in) :: msize,nblok,natom,ntypat,mpert
660 : integer,intent(in),optional :: nkpt,nband
661 : ! ************************************************************************
662 :
663 3930 : ddb%msize = msize
664 3930 : ddb%nblok = nblok
665 3930 : ddb%natom = natom
666 : !ddb%mpert = natom + MPERT_MAX
667 3930 : ddb%mpert = mpert
668 3930 : ddb%ntypat = ntypat
669 :
670 : ! integer
671 53908384 : ABI_CALLOC(ddb%flg, (msize, nblok))
672 20767 : ABI_CALLOC(ddb%typ, (nblok))
673 :
674 : ! real
675 11790 : ABI_MALLOC(ddb%amu, (ntypat))
676 11790 : ABI_MALLOC(ddb%nrm, (3, nblok))
677 7860 : ABI_MALLOC(ddb%omega, (3, nblok))
678 11790 : ABI_MALLOC(ddb%qpt, (9, nblok))
679 15720 : ABI_MALLOC(ddb%val, (2, msize, nblok))
680 161663968 : ddb%val = huge(one)
681 :
682 : ! FIXME: should really add nsppol argument (see thmeig).
683 3930 : if (present(nkpt) .and. present(nband)) then
684 184 : call ddb%malloc_d2eig(nband, nkpt)
685 : end if
686 :
687 3930 : end subroutine ddb_malloc
688 : !!***
689 :
690 : !----------------------------------------------------------------------
691 :
692 : !!****f* m_ddb/ddb_malloc_d2eig
693 : !! NAME
694 : !! ddb_malloc_d2eig
695 : !!
696 : !! FUNCTION
697 : !! Allocate dynamic memory for second derivatives of eigenvalues.
698 : !!
699 : !! INPUTS
700 : !! mband='number of bands' dimension of the d2eig array.
701 : !! Should actually correspond to the maximum number of bands for one kpoint
702 : !! multiplied by the number of spin polarization (mband*nsppol).
703 : !! nkpt=number of kpoints
704 : !!
705 : !! OUTPUT
706 : !!
707 : !! SOURCE
708 :
709 321 : subroutine ddb_malloc_d2eig(ddb, mband, nkpt)
710 :
711 : !Arguments -------------------------------
712 : class(ddb_type),intent(inout) :: ddb
713 : integer,intent(in) :: mband, nkpt
714 : ! ************************************************************************
715 :
716 321 : ddb%nband = mband / ddb%nsppol
717 321 : ddb%nkpt = nkpt
718 963 : ABI_MALLOC(ddb%kpt, (3, nkpt))
719 1605 : ABI_MALLOC(ddb%eig2dval, (2, ddb%msize, mband, nkpt))
720 :
721 321 : end subroutine ddb_malloc_d2eig
722 : !!***
723 :
724 : !----------------------------------------------------------------------
725 :
726 : !!****f* m_ddb/ddb_set_qpt
727 : !! NAME
728 : !! ddb_set_qpt
729 : !!
730 : !! FUNCTION
731 : !! Set the q-point wavevector for a certain block.
732 : !! In case of 3rd order derivatives, three q-points need to be specified
733 : !! with the constraint q1 + q2 + q3 = 0 (not checked).
734 : !! The norm is set to one automatically.
735 : !!
736 : !! INPUTS
737 : !! iblok=index of the block being set.
738 : !! qpt=reduced coordinates of first qpoint
739 : !! qpt2=reduced coordinates of second qpoint
740 : !! qpt3=reduced coordinates of third qpoint
741 : !!
742 : !! OUTPUT
743 : !!
744 : !! SOURCE
745 :
746 572 : subroutine ddb_set_qpt(ddb, iblok, qpt, qpt2, qpt3)
747 :
748 : !Arguments -------------------------------
749 : class(ddb_type),intent(inout) :: ddb
750 : integer,intent(in) :: iblok
751 : !arrays
752 : real(dp), intent(in) :: qpt(3)
753 : real(dp), intent(in),optional :: qpt2(3), qpt3(3)
754 : ! ************************************************************************
755 :
756 5720 : ddb%qpt(:,iblok)=zero
757 2288 : ddb%nrm(:,iblok)=one
758 :
759 2288 : ddb%qpt(1:3,iblok) = qpt(1:3)
760 :
761 572 : if (present(qpt2)) then
762 0 : ddb%qpt(4:6,iblok) = qpt2(1:3)
763 : end if
764 :
765 572 : if (present(qpt3)) then
766 0 : ddb%qpt(7:9,iblok) = qpt3(1:3)
767 : end if
768 :
769 572 : end subroutine ddb_set_qpt
770 : !!***
771 :
772 : !----------------------------------------------------------------------
773 :
774 : !!****f* m_ddb/ddb_set_omega
775 : !! NAME
776 : !! ddb_set_omega
777 : !!
778 : !! FUNCTION
779 : !! Set the frequencies for a certain block.
780 : !! In case of 3rd order derivatives, three frequencies need to be specified
781 : !! with the constraint omegaq1 + omega2 + omega3 = 0 (not checked).
782 : !!
783 : !! INPUTS
784 : !! iblok=index of the block being set.
785 : !!
786 : !! OUTPUT
787 : !!
788 : !! SOURCE
789 :
790 435 : subroutine ddb_set_omega(ddb, iblok, omega, omega2, omega3)
791 :
792 : !Arguments ------------------------------------
793 : !array
794 : class(ddb_type),intent(inout) :: ddb
795 : real(dp), intent(in) :: omega
796 : real(dp), intent(in),optional :: omega2
797 : real(dp), intent(in),optional :: omega3
798 : !scalars
799 : integer,intent(in) :: iblok
800 :
801 : ! ************************************************************************
802 :
803 1740 : ddb%omega(:,iblok)=zero
804 :
805 435 : ddb%omega(1,iblok) = omega
806 435 : if (present(omega2)) ddb%omega(2,iblok) = omega2
807 435 : if (present(omega3)) ddb%omega(3,iblok) = omega3
808 :
809 435 : end subroutine ddb_set_omega
810 : !!***
811 :
812 : !----------------------------------------------------------------------
813 :
814 : !!****f* m_ddb/ddb_set_d2matr
815 : !! NAME
816 : !! ddb_set_d2matr
817 : !!
818 : !! FUNCTION
819 : !! Set values for the second-order derivative matrix.
820 : !!
821 : !! INPUTS
822 : !! iblok=index of the block being set.
823 : !! d2matr=the second-order derivative matrix.
824 : !! flg=flag to indicate presence of a given element.
825 : !!
826 : !! SOURCE
827 :
828 2913 : subroutine ddb_set_d2matr(ddb, iblok, d2matr, flg)
829 :
830 : !Arguments -------------------------------
831 : !scalars
832 : class(ddb_type),intent(inout) :: ddb
833 : integer,intent(in) :: iblok
834 : !arrays
835 : real(dp), intent(in) :: d2matr(2,3,ddb%mpert,3,ddb%mpert)
836 : integer, intent(in) :: flg(3,ddb%mpert,3,ddb%mpert)
837 :
838 : !Local variables -------------------------
839 : integer :: idir1,idir2,ii,ipert1,ipert2
840 : ! ************************************************************************
841 :
842 2913 : ii=0
843 30251 : do ipert2=1,ddb%mpert
844 112265 : do idir2=1,3
845 998852 : do ipert1=1,ddb%mpert
846 3640014 : do idir1=1,3
847 2668500 : ii=ii+1
848 2668500 : ddb%flg(ii,iblok) = flg(idir1,ipert1,idir2,ipert2)
849 2668500 : ddb%val(1,ii,iblok) = d2matr(1,idir1,ipert1,idir2,ipert2)
850 3558000 : ddb%val(2,ii,iblok) = d2matr(2,idir1,ipert1,idir2,ipert2)
851 : end do
852 : end do
853 : end do
854 : end do
855 :
856 2913 : end subroutine ddb_set_d2matr
857 : !!***
858 :
859 : !----------------------------------------------------------------------
860 :
861 : !!****f* m_ddb/ddb_get_d2matr
862 : !! NAME
863 : !! ddb_get_d2matr
864 : !!
865 : !! FUNCTION
866 : !! Transform the second-order derivative matrix
867 : !! from flat indices to real tensor d2matr(cplex,ncart,natom,ncart,natom)
868 : !!
869 : !! INPUTS
870 : !! iblok=index of the block to get.
871 : !!
872 : !! OUTPUT
873 : !! d2matr=the second-order derivative matrix.
874 : !! flg=flag to indicate presence of a given element.
875 : !!
876 : !! SOURCE
877 :
878 670 : subroutine ddb_get_d2matr(ddb, iblok, d2matr, flg)
879 :
880 : !Arguments -------------------------------
881 : !scalars
882 : class(ddb_type),intent(inout) :: ddb
883 : integer,intent(in) :: iblok
884 : !arrays
885 : real(dp), allocatable, intent(out) :: d2matr(:,:,:,:,:)
886 : integer, allocatable, intent(out) :: flg(:,:,:,:)
887 :
888 : !Local variables -------------------------
889 : integer :: ii,idir1,idir2,ipert1,ipert2
890 : ! ************************************************************************
891 :
892 3350 : ABI_MALLOC(d2matr, (2,3,ddb%mpert,3,ddb%mpert))
893 3350 : ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert))
894 :
895 2821800 : d2matr = zero
896 :
897 : ii=0
898 7995 : do ipert2=1,ddb%mpert
899 29970 : do idir2=1,3
900 308483 : do ipert1=1,ddb%mpert
901 1138707 : do idir1=1,3
902 837549 : ii=ii+1
903 837549 : flg(idir1,ipert1,idir2,ipert2) = ddb%flg(ii,iblok)
904 1116732 : if (ddb%flg(ii,iblok) > 0) then
905 44806 : d2matr(1,idir1,ipert1,idir2,ipert2) = ddb%val(1,ii,iblok)
906 44806 : d2matr(2,idir1,ipert1,idir2,ipert2) = ddb%val(2,ii,iblok)
907 : end if
908 : end do
909 : end do
910 : end do
911 : end do
912 :
913 670 : end subroutine ddb_get_d2matr
914 : !!***
915 :
916 : !----------------------------------------------------------------------
917 :
918 : !!****f* m_ddb/ddb_set_gred
919 : !! NAME
920 : !! ddb_set_gred
921 : !!
922 : !! FUNCTION
923 : !! Set the forces in reduced coordinates (Hartree).
924 : !!
925 : !! INPUTS
926 : !! gred=the gradient of the total energy with respect
927 : !! to change of reduced coordinates
928 : !! iblok=index of the block being set.
929 : !!
930 : !! SOURCE
931 :
932 2796 : subroutine ddb_set_gred(ddb, gred, iblok)
933 :
934 : !Arguments -------------------------------
935 : !scalars
936 : class(ddb_type),intent(inout) :: ddb
937 : integer,intent(in) :: iblok
938 : !arrays
939 : real(dp), intent(in) :: gred(3,ddb%natom)
940 :
941 : !Local variables -------------------------
942 : integer :: idir, iatom, indx
943 : ! ************************************************************************
944 :
945 2796 : ddb%typ(iblok) = BLKTYP_d1E_xx
946 2796 : indx = 0
947 9331 : do iatom = 1, ddb%natom
948 28936 : do idir = 1, 3
949 19605 : indx = indx + 1
950 19605 : ddb%flg(indx,iblok) = 1
951 19605 : ddb%val(1,indx,iblok) = gred(idir,iatom)
952 26140 : ddb%val(2,indx,iblok) = zero
953 : end do
954 : end do
955 :
956 2796 : end subroutine ddb_set_gred
957 : !!***
958 :
959 : !----------------------------------------------------------------------
960 :
961 : !!****f* m_ddb/ddb_set_pel
962 : !! NAME
963 : !! ddb_set_gred
964 : !!
965 : !! FUNCTION
966 : !! Set the electronic polarization.
967 : !!
968 : !! INPUTS
969 : !! pel=ucvol times the electronic polarization in reduced coordinates.
970 : !! flg=flag to indicate presence of a given element.
971 : !! iblok=index of the block being set.
972 : !!
973 : !! OUTPUT
974 : !!
975 : !! SOURCE
976 :
977 45 : subroutine ddb_set_pel(ddb, pel, flg, iblok)
978 :
979 : !Arguments -------------------------------
980 : !array
981 : class(ddb_type),intent(inout) :: ddb
982 : real(dp), intent(in) :: pel(3)
983 : integer,intent(in) :: flg(3)
984 : !scalars
985 : integer,intent(in) :: iblok
986 :
987 : !Local variables -------------------------
988 : integer :: idir, indx
989 : ! ************************************************************************
990 :
991 45 : ddb%typ(iblok) = BLKTYP_d1E_xx
992 45 : indx = 3*ddb%natom + 3
993 180 : do idir = 1, 3
994 135 : indx = indx + 1
995 135 : ddb%flg(indx,iblok) = flg(idir)
996 135 : ddb%val(1,indx,iblok) = pel(idir)
997 180 : ddb%val(2,indx,iblok) = zero
998 : end do
999 :
1000 45 : end subroutine ddb_set_pel
1001 : !!***
1002 :
1003 : !----------------------------------------------------------------------
1004 :
1005 : !!****f* m_ddb/ddb_set_strten
1006 : !! NAME
1007 : !! ddb_set_strten
1008 : !!
1009 : !! FUNCTION
1010 : !! Set the stress tensor.
1011 : !!
1012 : !! INPUTS
1013 : !! strten=the stress tensor in cartesian coordinates.
1014 : !! iblok=index of the block we are setting.
1015 : !!
1016 : !! OUTPUT
1017 : !!
1018 : !! SOURCE
1019 :
1020 2796 : subroutine ddb_set_strten(ddb, strten, iblok)
1021 :
1022 : !Arguments -------------------------------
1023 : !array
1024 : class(ddb_type),intent(inout) :: ddb
1025 : real(dp), intent(in) :: strten(6)
1026 : !scalars
1027 : integer,intent(in) :: iblok
1028 :
1029 : !Local variables -------------------------
1030 : integer :: indx
1031 : ! ************************************************************************
1032 :
1033 2796 : ddb%typ(iblok) = BLKTYP_d1E_xx
1034 2796 : indx = 3*ddb%natom + 6
1035 :
1036 19572 : ddb%flg(indx+1:indx+6,1) = 1
1037 19572 : ddb%val(1,indx+1:indx+6,1) = strten(1:6)
1038 19572 : ddb%val(2,indx+1:indx+6,1) = zero
1039 :
1040 2796 : end subroutine ddb_set_strten
1041 : !!***
1042 :
1043 : !----------------------------------------------------------------------
1044 :
1045 : !!****f* m_ddb/ddb_get_d1matr
1046 : !! NAME
1047 : !! ddb_get_d1matr
1048 : !!
1049 : !! FUNCTION
1050 : !! Transform the first-order derivative matrix
1051 : !! from flat indices to real tensor d1matr(cplex,ncart,natom)
1052 : !!
1053 : !! INPUTS
1054 : !! iblok=index of the block to get.
1055 : !!
1056 : !! OUTPUT
1057 : !! d1matr=the first-order derivative matrix.
1058 : !! flg=flag to indicate presence of a given element.
1059 : !!
1060 : !! SOURCE
1061 :
1062 2730 : subroutine ddb_get_d1matr(ddb, iblok, d1matr, flg)
1063 :
1064 : !Arguments -------------------------------
1065 : !array
1066 : class(ddb_type),intent(inout) :: ddb
1067 : integer,intent(in) :: iblok
1068 : real(dp), allocatable, intent(out) :: d1matr(:,:,:)
1069 : integer, allocatable, intent(out) :: flg(:,:)
1070 : !scalars
1071 :
1072 : !Local variables -------------------------
1073 : integer :: ii,idir1,ipert1
1074 : ! ************************************************************************
1075 :
1076 8190 : ABI_MALLOC(d1matr, (2,3,ddb%mpert))
1077 8190 : ABI_MALLOC(flg, (3,ddb%mpert))
1078 :
1079 230960 : d1matr = zero
1080 :
1081 : ii=0
1082 25553 : do ipert1=1,ddb%mpert
1083 94022 : do idir1=1,3
1084 68469 : ii=ii+1
1085 68469 : flg(idir1,ipert1) = ddb%flg(ii,iblok)
1086 91292 : if (ddb%flg(ii,iblok) > 0) then
1087 35613 : d1matr(1,idir1,ipert1) = ddb%val(1,ii,iblok)
1088 35613 : d1matr(2,idir1,ipert1) = ddb%val(2,ii,iblok)
1089 : end if
1090 : end do
1091 : end do
1092 :
1093 2730 : end subroutine ddb_get_d1matr
1094 : !!***
1095 :
1096 : !----------------------------------------------------------------------
1097 :
1098 : !!****f* m_ddb/ddb_set_d1matr
1099 : !! NAME
1100 : !! ddb_set_d1matr
1101 : !!
1102 : !! FUNCTION
1103 : !! Set values for the first-order derivative matrix.
1104 : !!
1105 : !! INPUTS
1106 : !! iblok=index of the block being set.
1107 : !! d1matr=the first-order derivative matrix.
1108 : !! flg=flag to indicate presence of a given element.
1109 : !!
1110 : !! SOURCE
1111 :
1112 10 : subroutine ddb_set_d1matr(ddb, iblok, d1matr, flg)
1113 :
1114 : !Arguments -------------------------------
1115 : !array
1116 : class(ddb_type),intent(inout) :: ddb
1117 : real(dp), intent(in) :: d1matr(2,3,ddb%mpert)
1118 : integer, intent(in) :: flg(3,ddb%mpert)
1119 : !scalars
1120 : integer,intent(in) :: iblok
1121 :
1122 : !Local variables -------------------------
1123 : integer :: ii,ipert1,idir1
1124 : ! ************************************************************************
1125 :
1126 10 : ii=0
1127 105 : do ipert1=1,ddb%mpert
1128 390 : do idir1=1,3
1129 285 : ii=ii+1
1130 285 : ddb%val(1,ii,iblok) = d1matr(1,idir1,ipert1)
1131 285 : ddb%val(2,ii,iblok) = d1matr(2,idir1,ipert1)
1132 380 : ddb%flg(ii,iblok) = flg(idir1,ipert1)
1133 : end do
1134 : end do
1135 :
1136 10 : end subroutine ddb_set_d1matr
1137 : !!***
1138 :
1139 : !----------------------------------------------------------------------
1140 :
1141 : !!****f* m_ddb/ddb_set_etotal
1142 : !! NAME
1143 : !! ddb_set_etotal
1144 : !!
1145 : !! FUNCTION
1146 : !! Set the total energy
1147 : !!
1148 : !! INPUTS
1149 : !! etotal=the total energy.
1150 : !! iblok=index of the block we are setting.
1151 : !!
1152 : !! SOURCE
1153 :
1154 2796 : subroutine ddb_set_etotal(ddb, etotal, iblok)
1155 :
1156 : !Arguments -------------------------------
1157 : !array
1158 : class(ddb_type),intent(inout) :: ddb
1159 : !scalars
1160 : real(dp),intent(in) :: etotal
1161 : integer,intent(in) :: iblok
1162 : ! ************************************************************************
1163 :
1164 2796 : ddb%typ(iblok) = BLKTYP_d0E_xx
1165 2796 : ddb%val(1,1,iblok) = etotal
1166 2796 : ddb%val(2,1,iblok) = zero
1167 2796 : ddb%flg(1,iblok) = 1
1168 :
1169 2796 : end subroutine ddb_set_etotal
1170 : !!***
1171 :
1172 : !----------------------------------------------------------------------
1173 :
1174 : !!****f* m_ddb/ddb_set_brav
1175 : !! NAME
1176 : !! ddb_set_brav
1177 : !!
1178 : !! FUNCTION
1179 : !! Modify the current values of rprim according to bravais lattice.
1180 : !! Perform some checks on the primitive vectors
1181 : !! before rescaling them such that rprim(1,2)=0.5
1182 : !!
1183 : !! INPUTS
1184 : !! brav
1185 : !! 1 -> No rescaling.
1186 : !! other -> Check and rescale.
1187 : !!
1188 : !! The meaning of brav is
1189 : !! 1 or -1 -> simple lattice
1190 : !! 2 -> face-centered cubic
1191 : !! 3 -> body-centered lattice
1192 : !! 4 -> hexagonal lattice (D6h)
1193 : !!
1194 : !! OUTPUT
1195 : !!
1196 : !! NOTE
1197 : !! The use of brav is deprecated, but it is still used for initializing IFC.
1198 : !! We should try to remove its occurence.
1199 : !!
1200 : !! SOURCE
1201 :
1202 234 : subroutine ddb_set_brav(ddb, brav)
1203 :
1204 : !Arguments -------------------------------
1205 : !array
1206 : class(ddb_type),intent(inout) :: ddb
1207 : !scalars
1208 : integer,intent(in) :: brav
1209 :
1210 : !Local variables-------------------------------
1211 : !scalars
1212 : real(dp) :: factor
1213 : character(len=500) :: msg
1214 : ! *************************************************************************
1215 :
1216 : ! Renormalize rprim to possibly satisfy the constraint abs(rprim(1,2))=half when abs(brav)/=1
1217 : ! This section is needed to preserve the behaviour of the old implementation.
1218 234 : if (abs(brav)/=1 .and. abs(abs(ddb%rprim(1,2))-half)>tol10) then
1219 2 : if(abs(ddb%rprim(1,2))<tol6)then
1220 : write(msg, '(a,i0,7a)' )&
1221 0 : 'The input DDB value of brav is ',brav,',',ch10,&
1222 0 : 'and the one of rprim(1,2) is zero.',ch10,&
1223 0 : 'These are incompatible',ch10,&
1224 0 : 'Action: check the value of brav and rprim(1,2) in your DDB.'
1225 0 : ABI_ERROR(msg)
1226 : end if
1227 2 : factor = abs(ddb%rprim(1,2)) * two
1228 8 : ddb%acell(:) = ddb%acell(:) * factor
1229 26 : ddb%rprim(:,:) = ddb%rprim(:,:) / factor
1230 26 : ddb%gprim(:,:) = ddb%gprim(:,:) * factor
1231 : end if
1232 :
1233 234 : end subroutine ddb_set_brav
1234 : !!***
1235 :
1236 : !----------------------------------------------------------------------
1237 :
1238 : !!****f* m_ddb/ddb_to_d2etot
1239 : !!
1240 : !! NAME
1241 : !! ddb_to_d2etot
1242 : !!
1243 : !! FUNCTION
1244 : !! Convert the physical quantities (Born charges, dielectric tensor,
1245 : !! magnetic susceptibility, etc...)
1246 : !! stored in ddb%val to mathematical second-derivatives of the total energy
1247 : !!
1248 : !! INPUTS
1249 : !! ddb<type(ddb_type)>=Derivative Database.
1250 : !! option= 0 transform ddb to d2etot
1251 : !! 1 transform d2etot to ddb
1252 : !! optgb= 0 do the transform even it ddb might be zeros
1253 : !! 1 check whether the corresponding quantity is present in the ddb data
1254 : !! qeq0= called from a Gamma point blok
1255 : !! ucvol= unit cell volume
1256 : !!
1257 : !! OUTPUT
1258 : !! ddb<type(ddb_type)>=Derivative Database.
1259 : !!
1260 : !! SOURCE
1261 :
1262 106 : subroutine ddb_to_d2etot(ddb,blkval,kblok,option,qeq0,qphon,qphnrm,ucvol,optgb,omega)
1263 :
1264 : !Arguments -------------------------------
1265 : !scalars
1266 : class(ddb_type),intent(inout) :: ddb
1267 : integer,intent(in) :: kblok,option,optgb
1268 : real(dp),intent(in) :: ucvol
1269 : logical,intent(in) :: qeq0
1270 : !arrays
1271 : real(dp),intent(inout) :: blkval(2,3,ddb%mpert,3,ddb%mpert,ddb%nblok)
1272 : real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
1273 : real(dp),optional,intent(in) :: omega(3)
1274 :
1275 : !Local variables -------------------------
1276 : !scalars
1277 : integer :: iblok,rftyp
1278 : integer :: idir1,idir2,ipert1,ipert2
1279 : real(dp) :: fac
1280 : !arrays
1281 : integer :: rfelfd(4),rfmagn(4),rfphon(4),rfstrs(4)
1282 : real(dp) :: val(2)
1283 :
1284 : ! *********************************************************************
1285 :
1286 106 : rfelfd(:)=0
1287 106 : rfphon(:)=0
1288 106 : rfstrs(:)=0
1289 : rfmagn(:)=0
1290 106 : rftyp=1
1291 :
1292 : !IFCs are equal to the d2etot
1293 :
1294 106 : if (qeq0) then
1295 :
1296 : !Born charges
1297 72 : if (optgb==1) then
1298 36 : rfphon(1:2)=1
1299 36 : rfelfd(1:2)=2
1300 12 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1301 : end if
1302 72 : if ((iblok/=0.and.iblok==kblok).or.optgb==0) then
1303 72 : ipert1= ddb%natom + 2
1304 504 : do ipert2= 1, ddb%natom
1305 1800 : do idir2= 1, 3
1306 5616 : do idir1= 1, 3
1307 11664 : val(:)=blkval(:,idir1,ipert1,idir2,ipert2,kblok)
1308 11664 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)=-val(:)
1309 11664 : val(:)=blkval(:,idir2,ipert2,idir1,ipert1,kblok)
1310 12960 : blkval(:,idir2,ipert2,idir1,ipert1,kblok)=-val(:)
1311 : end do
1312 : end do
1313 : end do
1314 : end if
1315 :
1316 : !Dielectric tensor
1317 72 : if (optgb==1) then
1318 : iblok=0
1319 12 : rfphon(:)=0
1320 36 : rfelfd(1:2)=2
1321 12 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1322 : end if
1323 72 : if ((iblok/=0.and.iblok==kblok).or.optgb==0) then
1324 72 : ipert1= ddb%natom + 2
1325 72 : ipert2= ddb%natom + 2
1326 288 : do idir2= 1, 3
1327 936 : do idir1= 1, 3
1328 1944 : val(:)=blkval(:,idir1,ipert1,idir2,ipert2,kblok)
1329 864 : if (option==0) then
1330 207 : if (idir1==idir2) then
1331 207 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)= (one - val(:))*ucvol/four_pi
1332 : else
1333 414 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)= -ucvol/four_pi*val(:)
1334 : end if
1335 441 : else if (option==1) then
1336 441 : if (idir1==idir2) then
1337 441 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)= one - four_pi/ucvol*val(:)
1338 : else
1339 882 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)= -four_pi/ucvol*val(:)
1340 : end if
1341 : end if
1342 : end do
1343 : end do
1344 : end if
1345 :
1346 72 : if (option==0) fac=-ucvol
1347 72 : if (option==1) fac=-one/ucvol
1348 : !Magnetoelectric susceptibility
1349 72 : if (optgb==1) then
1350 : iblok=0
1351 12 : rfphon(:)=0
1352 12 : rfelfd(1)=0
1353 12 : rfelfd(2)=2
1354 : rfmagn(1)=1
1355 : rfmagn(2)=0
1356 12 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1357 : end if
1358 72 : if ((iblok/=0.and.iblok==kblok).or.optgb==0) then
1359 72 : ipert1= ddb%natom + 5
1360 72 : ipert2= ddb%natom + 2
1361 288 : do idir2= 1, 3
1362 936 : do idir1= 1, 3
1363 1944 : val(:)=blkval(:,idir1,ipert1,idir2,ipert2,kblok)
1364 1944 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)=val(:)*fac
1365 1944 : val(:)=blkval(:,idir2,ipert2,idir1,ipert1,kblok)
1366 2160 : blkval(:,idir2,ipert2,idir1,ipert1,kblok)=val(:)*fac
1367 : end do
1368 : end do
1369 : end if
1370 :
1371 : end if
1372 :
1373 : !Magnetic susceptibility
1374 106 : if (option==0) fac=-ucvol
1375 106 : if (option==1) fac=-one/ucvol
1376 106 : if (optgb==1) then
1377 : iblok=0
1378 16 : rfphon(:)=0
1379 48 : rfelfd(1:2)=0
1380 : rfmagn(1:2)=1
1381 16 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1382 : end if
1383 106 : if ((iblok/=0.and.iblok==kblok).or.optgb==0) then
1384 106 : ipert2= ddb%natom + 5
1385 106 : ipert1= ddb%natom + 5
1386 424 : do idir2= 1, 3
1387 1378 : do idir1= 1, 3
1388 2862 : val(:)=blkval(:,idir1,ipert1,idir2,ipert2,kblok)
1389 3180 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)=val(:)*fac
1390 : end do
1391 : end do
1392 : end if
1393 :
1394 : !Forces induced by magnetic field
1395 106 : if (optgb==1) then
1396 : iblok=0
1397 16 : rfelfd(:)=0
1398 : rfmagn(:)=0
1399 16 : rfphon(2)=1
1400 : rfmagn(1)=1
1401 16 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1402 : end if
1403 106 : if ((iblok/=0.and.iblok==kblok).or.optgb==0) then
1404 106 : ipert1= ddb%natom + 5
1405 742 : do ipert2= 1, ddb%natom
1406 2650 : do idir2= 1, 3
1407 8268 : do idir1= 1, 3
1408 17172 : val(:)=blkval(:,idir1,ipert1,idir2,ipert2,kblok)
1409 17172 : blkval(:,idir1,ipert1,idir2,ipert2,kblok)=-val(:)
1410 17172 : val(:)=blkval(:,idir2,ipert2,idir1,ipert1,kblok)
1411 19080 : blkval(:,idir2,ipert2,idir1,ipert1,kblok)=-val(:)
1412 : end do
1413 : end do
1414 : end do
1415 : end if
1416 :
1417 106 : end subroutine ddb_to_d2etot
1418 : !!***
1419 :
1420 : !----------------------------------------------------------------------
1421 : !!****f* m_ddb/ddb_set_typ
1422 : !! NAME
1423 : !! ddb_set_typ
1424 : !!
1425 : !! FUNCTION
1426 : !! Set the blok typ for one block
1427 : !!
1428 : !! INPUTS
1429 : !! iblok: block index
1430 : !! typ: type of block
1431 : !!
1432 : !! OUTPUT
1433 : !!
1434 : !! SOURCE
1435 :
1436 0 : subroutine ddb_set_typ(ddb, iblok, typ)
1437 :
1438 : !Arguments -------------------------------
1439 : !array
1440 : class(ddb_type),intent(inout) :: ddb
1441 : !scalars
1442 : integer,intent(in) :: iblok,typ
1443 : ! *************************************************************************
1444 :
1445 0 : ddb%typ(iblok) = typ
1446 :
1447 0 : end subroutine ddb_set_typ
1448 : !!***
1449 :
1450 : !----------------------------------------------------------------------
1451 :
1452 : !!****f* m_ddb/ddb_bcast
1453 : !! NAME
1454 : !! ddb_bcast
1455 : !!
1456 : !! FUNCTION
1457 : !! MPI broadcast all types for the ddb_type structure
1458 : !!
1459 : !! INPUTS
1460 : !! comm=MPI communicator
1461 : !!
1462 : !! SIDE EFFECTS
1463 : !! Ddb<type(ddb_type)>= Input if node is master, other nodes returns with a completely initialized instance.
1464 : !!
1465 : !! SOURCE
1466 :
1467 12 : subroutine ddb_bcast(ddb, comm)
1468 :
1469 : !Arguments -------------------------------
1470 : !array
1471 : class(ddb_type),intent(inout) :: ddb
1472 : integer, intent(in) :: comm
1473 :
1474 : !Local variables-------------------------------
1475 : !scalars
1476 : integer, parameter :: master=0
1477 : integer :: ierr
1478 : ! *************************************************************************
1479 :
1480 12 : if (xmpi_comm_size(comm) == 1) return
1481 :
1482 : DBG_ENTER("COLL")
1483 :
1484 : ! Transmit dimensions and static variables.
1485 12 : call xmpi_bcast(ddb%nblok, master, comm, ierr)
1486 12 : call xmpi_bcast(ddb%natom, master, comm, ierr)
1487 12 : call xmpi_bcast(ddb%ntypat, master, comm, ierr)
1488 12 : call xmpi_bcast(ddb%nsppol, master, comm, ierr)
1489 12 : call xmpi_bcast(ddb%mpert, master, comm, ierr)
1490 12 : call xmpi_bcast(ddb%msize, master, comm, ierr)
1491 :
1492 12 : call xmpi_bcast(ddb%occopt, master, comm, ierr)
1493 12 : call xmpi_bcast(ddb%prtvol, master, comm, ierr)
1494 :
1495 : !real
1496 12 : call xmpi_bcast(ddb%rprim, master, comm, ierr)
1497 12 : call xmpi_bcast(ddb%gprim, master, comm, ierr)
1498 12 : call xmpi_bcast(ddb%acell, master, comm, ierr)
1499 :
1500 : ! Allocate arrays on the other nodes.
1501 12 : if (xmpi_comm_rank(comm) /= master) then
1502 8 : call ddb%malloc(ddb%msize, ddb%nblok, ddb%natom, ddb%ntypat, ddb%mpert)
1503 : end if
1504 :
1505 12 : call xmpi_bcast(ddb%flg, master, comm, ierr)
1506 12 : call xmpi_bcast(ddb%typ, master, comm, ierr)
1507 12 : call xmpi_bcast(ddb%amu, master, comm, ierr)
1508 12 : call xmpi_bcast(ddb%nrm, master, comm, ierr)
1509 12 : call xmpi_bcast(ddb%omega, master, comm, ierr)
1510 12 : call xmpi_bcast(ddb%qpt, master, comm, ierr)
1511 12 : call xmpi_bcast(ddb%val, master, comm, ierr)
1512 : ! call xmpi_bcast(ddb%val_fs, master, comm, ierr)
1513 : ! call xmpi_bcast(ddb%val_rs, master, comm, ierr)
1514 :
1515 : DBG_EXIT("COLL")
1516 :
1517 : end subroutine ddb_bcast
1518 : !!***
1519 :
1520 : !----------------------------------------------------------------------
1521 :
1522 : !!****f* m_ddb/ddb_get_block
1523 : !!
1524 : !! NAME
1525 : !! ddb_get_block
1526 : !!
1527 : !! FUNCTION
1528 : !! This routine finds the block that contains the
1529 : !! information on the derivatives of the total energy specified
1530 : !! by the parameters rfphon,rfelfd,rfstrs,rftyp and
1531 : !! the phonon wavevectors qphon (and their normalisation).
1532 : !! In case the DDB does not contain this information, the subroutine returns iblok=0
1533 : !!
1534 : !! INPUTS
1535 : !! ddb = ddb blok datastructure
1536 : !! flg(msize,nblok)=flag for every matrix element:
1537 : !! 0 => the element is not in the data block.
1538 : !! 1 => the element is in the data blok.
1539 : !! nrm(3,nblok)=normalization factors for the three allowed wavevectors
1540 : !! qpt(3,nblok)=wavevector of the perturbation(s). The elements
1541 : !! typ(nblok)=type of the block.
1542 : !! (1=> non-stationary block),
1543 : !! (2=> stationary block),
1544 : !! (3=> third order derivative).
1545 : !! omega(3)= frequency of the perturbation
1546 : !! qphon(3,3)=wavevectors for the three possible phonons
1547 : !! (note : only one should be used in case of second derivative of total energy,
1548 : !! because we know that the second is the opposite of this value)
1549 : !! qphnrm(3) =normalisation factors for the three possible phonons
1550 : !! rfphon(4) = 1=> response to phonons
1551 : !! 2=> second derivative of total energy
1552 : !! rfelfd(4) = 1=> d/dk, 2=> electric field only, 3=> both (see comment on rfphon)
1553 : !! rfstrs(4) = 1=> uniaxial stresses, 2=> shear stresses, 3=> both (see comment on rfphon)
1554 : !! rftyp =
1555 : !! 0 => total energy
1556 : !! 1 => non-stationary formulation of the 2nd derivative
1557 : !! 2 => stationary formulation of the 2nd derivative
1558 : !! 3 => third derivative of total energy
1559 : !! 4 => first-order derivatives of total energy
1560 : !! 33 => long wave third order derivatives of total energy
1561 : !! [rffreq(4)] = 1=> d/dw (optional)
1562 : !! [rfmagn(4)] = 1=> Uniform Zeeman, 2 => Local Zeeman (optional)
1563 : !! 85 => molecular Berry curvature
1564 : !! [rfqvec(4)] = 1=> d/dq (optional)
1565 : !! [mpatpol(2)] = atoms on which the magnetic penalty was applied (optional)
1566 : !! [mpdir(3)] = directions alongw which the magnetic penalty was applied (optional)
1567 : !!
1568 : !! OUTPUT
1569 : !! iblok= number of the block that corresponds to the specifications. 0 if not found.
1570 : !!
1571 : !! SOURCE
1572 :
1573 887 : subroutine ddb_get_block(ddb, iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
1574 : & mpatpol,mpdir,omega,rffreq,rfmagn,rfqvec)
1575 :
1576 : !Arguments -------------------------------
1577 : !scalars
1578 : class(ddb_type),intent(in) :: ddb
1579 : integer,intent(out) :: iblok
1580 : integer,intent(in) :: rftyp
1581 : !arrays
1582 : integer,intent(in) :: rfelfd(4),rfphon(4),rfstrs(4)
1583 : real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
1584 : integer,optional,intent(in) :: mpatpol(2),mpdir(3)
1585 : integer,optional,intent(in) :: rfmagn(4),rffreq(4),rfqvec(4)
1586 : real(dp),optional,intent(in) :: omega(3)
1587 :
1588 : !Local variables -------------------------
1589 : !scalars
1590 : integer, parameter :: cvrsio9_new=20240201
1591 : integer :: blkgam,ider,idir,idir1,idir2,idir3,ii,index,ipert,ipert1,ipert2
1592 : integer :: ipert3,nder,ok,mpert,natom,ndir3
1593 : character(len=500) :: msg
1594 : !arrays
1595 : integer :: gamma(3)
1596 887 : integer,allocatable :: worki(:,:)
1597 : real(dp) :: omega_(3),qpt(3)
1598 : integer :: mpatpol_(2),mpdir_(3)
1599 : integer :: rfmagn_(4),rffreq_(4),rfqvec_(4)
1600 :
1601 : ! *********************************************************************
1602 :
1603 887 : mpert = ddb%mpert
1604 887 : natom = ddb%natom
1605 :
1606 : ! Get the number of derivative
1607 887 : if (is_type_d2E(rftyp)) then
1608 : nder=2
1609 119 : else if (is_type_d3E(rftyp)) then
1610 : nder=3
1611 80 : else if (is_type_d0E(rftyp)) then
1612 : nder=0
1613 48 : else if (is_type_d1E(rftyp)) then
1614 : nder=1
1615 : else
1616 0 : write(msg, '(a,i0,a)')' rftyp is equal to ',rftyp,'. The only allowed values are 0, 1, 2, 3, 5, 6, 33 or 85.'
1617 0 : ABI_BUG(msg)
1618 : end if
1619 :
1620 : ! Default optionals
1621 887 : rfqvec_(:)=0; if (present(rfqvec)) rfqvec_(:)=rfqvec(:)
1622 887 : rfmagn_(:)=0; if (present(rfmagn)) rfmagn_(:)=rfmagn(:)
1623 887 : rffreq_(:)=0; if (present(rffreq)) rffreq_(:)=rffreq(:)
1624 887 : mpatpol_(:)=0; if (present(mpatpol)) mpatpol_(:)=mpatpol(:)
1625 887 : mpdir_(:)=0; if (present(mpdir)) mpdir_(:)=mpdir(:)
1626 887 : omega_(:)=0; if (present(omega)) omega_(:)=omega(:)
1627 :
1628 : ! In case of a second-derivative, a second phonon wavevector is provided.
1629 887 : if(nder==2)then
1630 3072 : do ii=1,3
1631 3072 : qphon(ii,2)=-qphon(ii,1)
1632 : end do
1633 768 : qphnrm(2)=qphnrm(1)
1634 : end if
1635 :
1636 : ! In case of a third derivative, the sum of wavevectors to gamma is checked
1637 887 : if (nder == 3.and.rffreq_(3)==0) then
1638 96 : qpt(:) = qphon(:,1)/qphnrm(1) + qphon(:,2)/qphnrm(2) + qphon(:,3)/qphnrm(3)
1639 24 : call gamma9(gamma(nder),qpt,qphnrm(1),DDB_QTOL)
1640 24 : if (gamma(nder) == 0) then
1641 : write(msg,'(a,a,a)')&
1642 0 : 'the sum of the wavevectors of the third-order energy is ',ch10,&
1643 0 : 'not equal to zero'
1644 0 : ABI_ERROR(msg)
1645 : end if
1646 : end if
1647 :
1648 : ! Check the validity of the requirement
1649 2588 : do ider=1,nder
1650 : ! Identifies if qphon is at gamma
1651 1701 : call gamma9(gamma(ider),qphon(1:3,ider),qphnrm(ider),DDB_QTOL)
1652 :
1653 2588 : if(gamma(ider)==0)then
1654 131 : if(rfstrs(ider)/=0.or.rfelfd(ider)/=0.or.rfqvec_(ider)/=0)then
1655 : write(msg, '(a,a)' )&
1656 0 : 'Not yet able to handle stresses or electric fields',ch10,&
1657 0 : 'with non-zero wavevector.'
1658 0 : ABI_BUG(msg)
1659 : end if
1660 : end if
1661 : end do
1662 :
1663 : ! Initialise the perturbation table
1664 2661 : ABI_MALLOC(worki,(mpert,4))
1665 32757 : worki(:,1:nder)=0
1666 :
1667 : ! Build the perturbation table
1668 2588 : do ider=1,nder
1669 : ! First the phonons
1670 1701 : if(rfphon(ider)==1)then ! what about the rfphon = 2 case ?
1671 3573 : do ipert=1,natom
1672 3573 : worki(ipert,ider)=1
1673 : end do
1674 : end if
1675 : ! Then the d/dk
1676 1701 : if (rfelfd(ider)==1.or.rfelfd(ider)==3) worki(natom+1,ider)=1
1677 : ! Then the electric field
1678 1701 : if (rfelfd(ider)==2.or.rfelfd(ider)==3) worki(natom+2,ider)=1
1679 : ! Then the ddq
1680 1701 : if (rfqvec_(ider)==1) worki(natom+8,ider)=1
1681 : ! Then the uniaxial stress
1682 1701 : if (rfstrs(ider)==1.or.rfstrs(ider)==3) worki(natom+3,ider)=1
1683 : ! Then the shear stress
1684 1701 : if (rfstrs(ider)==2.or.rfstrs(ider)==3) worki(natom+4,ider)=1
1685 : ! Then the uniform Zeeman field
1686 1701 : if (rfmagn_(ider)==1) worki(natom+5,ider)=1
1687 : ! Then the ddw
1688 1701 : if (rffreq_(ider)==1) worki(natom+9,ider)=1
1689 : ! At last, the local Zeeman fields
1690 2588 : if (rfmagn_(ider)==2) then
1691 81 : do ipert=natom+11+mpatpol_(1),natom+11+mpatpol_(2)
1692 81 : worki(ipert,ider)=1
1693 : end do
1694 : end if
1695 : end do
1696 :
1697 : ! Examine every blok:
1698 3159 : do iblok=1,ddb%nblok
1699 :
1700 : ! If this variable is still 1 at the end of the examination, the blok is the good one...
1701 2937 : ok=1
1702 :
1703 : ! Check the type
1704 2937 : if(rftyp/=ddb%typ(iblok)) ok=0
1705 :
1706 : ! Check the wavevector
1707 : if( ok==1 )then
1708 :
1709 1824 : if (nder == 2) then
1710 1744 : call gamma9(blkgam,ddb%qpt(1:3,iblok),ddb%nrm(1,iblok),DDB_QTOL)
1711 1744 : if(blkgam/=gamma(1))then
1712 : ok=0
1713 927 : else if(blkgam==0)then
1714 796 : do idir=1,3
1715 796 : if( abs( ddb%qpt(idir,iblok)/ddb%nrm(1,iblok) - qphon(idir,1)/qphnrm(1) )>DDB_QTOL ) ok=0
1716 : end do
1717 : end if
1718 :
1719 80 : else if (nder == 3) then
1720 156 : do ider = 1, nder
1721 507 : do idir=1,3
1722 468 : if( abs( ddb%qpt(idir+3*(ider-1),iblok)/ddb%nrm(ider,iblok) - qphon(idir,ider)/qphnrm(ider) )>DDB_QTOL )then
1723 2 : ok=0
1724 : end if ! qphon
1725 : end do ! idir
1726 : end do ! nder
1727 : end if ! nder
1728 :
1729 : end if ! ok
1730 :
1731 : ! ! Check the frequency
1732 : ! if( ok==1 .and. ddb_version>=cvrsio9_new )then
1733 : !TODO: This might fail if previous DDB files are read
1734 1007 : if( ok==1 )then
1735 865 : if (nder == 2) then
1736 786 : if( abs( ddb%omega(1,iblok) - omega_(1) )>DDB_QTOL ) ok=0
1737 79 : else if (nder == 3) then
1738 152 : do ider=1,3
1739 152 : if( abs( ddb%omega(ider,iblok) - omega_(ider) )>DDB_QTOL ) ok=0
1740 : end do
1741 : end if
1742 : end if !ok
1743 :
1744 : ! Check if there is enough information in this blok
1745 835 : if( ok==1 )then
1746 :
1747 835 : if (nder == 0) then
1748 15 : if (ddb%flg(1,iblok) /= 1) then
1749 0 : ok = 0
1750 0 : if (ddb%prtvol > 1) then
1751 : write(msg,'(a,i0,3a)' )&
1752 0 : 'The block ',iblok,' does not match the requirement',ch10,&
1753 0 : 'because it lacks the total energy'
1754 0 : ABI_COMMENT(msg)
1755 : end if
1756 : end if
1757 : end if
1758 :
1759 15706 : do ipert1=1,mpert
1760 :
1761 : if ((nder == 4).and.(worki(ipert1,4) == 1).and.(ok == 1)) then
1762 : do idir1 = 1, 3
1763 : index = 3*(ipert1 - 1) + idir1
1764 : if (ddb%flg(index,iblok) /= 1) ok = 0
1765 : end do
1766 : end if
1767 :
1768 15706 : if (worki(ipert1,1)==1 .and. ok==1 )then
1769 43058 : do ipert2=1,mpert
1770 43058 : if (worki(ipert2,2)==1 .and. ok==1 )then
1771 31172 : do idir1=1,3
1772 23379 : if (ipert1>natom+11.and.ipert1<=2*natom+11.and.mpdir_(idir1)==0) cycle
1773 97073 : do idir2=1,3
1774 66960 : if (ipert2>natom+11.and.ipert2<=2*natom+11.and.mpdir_(idir2)==0) cycle
1775 :
1776 88986 : if (nder == 2) then
1777 57847 : index=idir1+ 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1778 123425 : if (ddb%flg(index,iblok)/=1) ok=0
1779 :
1780 7760 : else if (nder == 3) then
1781 52392 : do ipert3 = 1, mpert
1782 52392 : if (worki(ipert3,3) == 1 .and. ok == 1) then
1783 2388 : if (ipert3==natom+9) then
1784 : ndir3= 1
1785 : else
1786 955 : ndir3= 3
1787 : end if
1788 6686 : do idir3 = 1, ndir3
1789 : index = idir1 + &
1790 : 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1791 4298 : 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1792 6686 : if (ddb%flg(index,iblok) /= 1) ok = 0
1793 : end do ! idir3
1794 : end if ! worki(ipert3,3)
1795 : end do ! i3pert
1796 : end if
1797 :
1798 : end do
1799 : end do
1800 : end if
1801 : end do
1802 : end if
1803 : end do
1804 : end if
1805 :
1806 : ! Now that everything has been checked, eventually end the search
1807 1057 : if(ok==1)exit
1808 : end do
1809 :
1810 887 : if(ok==0)then
1811 222 : iblok=0
1812 :
1813 222 : if (ddb%prtvol > 1) then
1814 : write(msg, '(3a)' )&
1815 49 : ' gtblk9 : ',ch10,&
1816 98 : ' Unable to find block corresponding to the following specifications :'
1817 49 : call wrtout(std_out,msg)
1818 49 : write(msg, '(a,i3)' )' Type (rfmeth) =',rftyp
1819 49 : call wrtout(std_out,msg)
1820 49 : write(msg, '(a)' ) ' ider qphon(3) qphnrm rfphon rfelfd rfstrs rfmagn rfqvec rffreq'
1821 49 : call wrtout(std_out,msg)
1822 98 : do ider=1,nder
1823 : write(msg, '(i4,4f6.2,6i7)' )&
1824 49 : ider,(qphon(ii,ider),ii=1,3),qphnrm(ider),rfphon(ider),rfelfd(ider),rfstrs(ider),&
1825 98 : & rfmagn_(ider),rfqvec_(ider),rffreq_(ider)
1826 98 : call wrtout(std_out,msg)
1827 : end do
1828 : end if
1829 : end if
1830 :
1831 665 : if (ok==1 .and. ddb%prtvol > 1) then
1832 290 : write(msg,'(a,i0,2a)')' gtblk9: found block number ',iblok,' agree with',' specifications '
1833 290 : call wrtout(std_out,msg)
1834 : end if
1835 :
1836 887 : ABI_FREE(worki)
1837 :
1838 887 : end subroutine ddb_get_block
1839 : !!***
1840 :
1841 : !----------------------------------------------------------------------
1842 :
1843 : !!****f* m_ddb/gamma9
1844 : !!
1845 : !! NAME
1846 : !! gamma9
1847 : !!
1848 : !! FUNCTION
1849 : !! This small routine checks if the wavevector qphon and the
1850 : !! corresponding normalisation factor represent a phonon at Gamma.
1851 : !!
1852 : !! INPUTS
1853 : !! qphon(3)=wavevector
1854 : !! qphnrm=normalisation factor
1855 : !! qtol=tolerance
1856 : !!
1857 : !! OUTPUT
1858 : !! gamma= if 1, means that the wavevector is indeed at Gamma otherwise 0.
1859 : !!
1860 : !! SOURCE
1861 :
1862 5816 : subroutine gamma9(gamma,qphon,qphnrm,qtol)
1863 :
1864 : !Arguments -------------------------------
1865 : !scalars
1866 : integer,intent(out) :: gamma
1867 : real(dp),intent(in) :: qphnrm,qtol
1868 : !arrays
1869 : real(dp),intent(in) :: qphon(3)
1870 : ! *********************************************************************
1871 :
1872 5816 : if( (abs(qphon(1))<qtol .and. abs(qphon(2))<qtol .and. abs(qphon(3))<qtol) .or. abs(qphnrm)<qtol ) then
1873 2415 : gamma=1
1874 : else
1875 3401 : gamma=0
1876 : end if
1877 :
1878 5816 : end subroutine gamma9
1879 : !!***
1880 :
1881 : !----------------------------------------------------------------------
1882 :
1883 : !!****f* m_ddb/ddb_read_block_txt
1884 : !!
1885 : !! NAME
1886 : !! ddb_read_block_txt
1887 : !!
1888 : !! FUNCTION
1889 : !! Read the next block of data from a DDB in text format.
1890 : !!
1891 : !! INPUTS
1892 : !! iblok=the blok index to be assigned
1893 : !! mpert=maximum number of ipert
1894 : !! msize=maximum size of the arrays flags and values
1895 : !! nunit=unit number for the data block file
1896 : !!
1897 : !! OUTPUT
1898 : !! (see side effects)
1899 : !!
1900 : !! SIDE EFFECTS
1901 : !! Input/Output
1902 : !! ddb = ddb block datastructure
1903 : !! ddb%typ=type of the block:
1904 : !! 0 => total energy
1905 : !! 1 => second-order energy derivatives, non-stationary block
1906 : !! 2 => second-order energy derivatives, stationary block
1907 : !! 3 => third-order energy derivatives
1908 : !! 4 => first-order energy derivatives: forces, stresses and polarization
1909 : !! 5 => second-order eigenvalue derivatives
1910 : !! ddb%flg(msize)=flag for every matrix element (0=> the element is
1911 : !! not in the data block), (1=> the element is in the data blok)
1912 : !! ddb%qpt(9)=wavevector of the perturbation(s). The elements from
1913 : !! 1 to 3 are used if we are dealing with the 2nd derivative of
1914 : !! total energy (only one wavevector), while all elements are
1915 : !! used in case of a third order derivative of total energy (three wavevector could be present)
1916 : !! ddb%nrm(3)=normalization factors for the three allowed wavevectors.
1917 : !! ddb%val(2,msize)=real(dp), complex, value of the matrix elements that are present in the data block
1918 : !! [blkval2(2,msize,mband,nkpt)]= value of the matrix elements that are present in a block of EIGR2D/EIGI2D
1919 : !!
1920 : !! NOTES
1921 : !! only executed by one processor.
1922 : !!
1923 : !! SOURCE
1924 :
1925 2081 : subroutine ddb_read_block_txt(ddb,iblok,mband,mpert,msize,nkpt,nunit,&
1926 48 : blkval2,kpt,ddb_version) !optional
1927 :
1928 : !Arguments -------------------------------
1929 : !scalars
1930 : integer,intent(in) :: mband,mpert,msize,nkpt,nunit
1931 : integer,intent(in) :: iblok
1932 : integer,intent(in) :: ddb_version
1933 : !logical, intent(in), optional :: eig2d
1934 : class(ddb_type),intent(inout) :: ddb
1935 : !arrays
1936 : real(dp),intent(out),optional :: kpt(3,nkpt)
1937 : real(dp),intent(out),optional :: blkval2(2,msize,mband,nkpt)
1938 :
1939 : !Local variables -------------------------
1940 : !scalars
1941 : integer, parameter :: cvrsio9_new=20240201
1942 : integer :: band,iband,idir1,idir2,idir3,ii,ikpt,index,ipert1,ipert2,ipert3,nelmts
1943 : logical :: eig2d_
1944 : real(dp) :: ai,ar
1945 : character(len=32) :: name
1946 : character(len=500) :: msg
1947 : ! *********************************************************************
1948 :
1949 : ! Zero every flag
1950 44797259 : ddb%flg(1:msize, iblok)=0
1951 :
1952 2081 : eig2d_ = .false.
1953 :
1954 :
1955 2081 : if(present(kpt).and.present(blkval2)) then
1956 : ! GA: Weird that it is not allocated here
1957 126924 : blkval2(:,:,:,:)=zero
1958 1000 : kpt(:,:)=zero
1959 : eig2d_ = .true.
1960 : end if
1961 :
1962 : !if (present(eig2d)) then
1963 : ! eig2d_ = eig2d
1964 : !end if
1965 :
1966 : ! Read the block type and number of elements
1967 2081 : read(nunit,*)
1968 2081 : read(nunit, '(a32,12x,i12)' )name,nelmts
1969 :
1970 : ! TODO: Replace with STRING_d2E, etc.
1971 : ! GA: Note that older versions used the expression '2rd' instead of '2nd'
1972 : ! So this substitution needs to be checked for backward compatibility.
1973 : ! Also, the strings for d2eig and d2eig_brd are undistinguishable
1974 : ! I don't think the d2eig_brd was ever read by abinit or anaddb.
1975 2081 : if(name==' 2nd derivatives (non-stat.) - ' .or. name==' 2rd derivatives (non-stat.) - ')then
1976 1913 : ddb%typ(iblok)=BLKTYP_d2E_ns
1977 168 : else if(name==' 2nd derivatives (stationary) - ' .or. name==' 2rd derivatives (stationary) - ')then
1978 54 : ddb%typ(iblok)=BLKTYP_d2E_st
1979 114 : else if(name==' 3rd derivatives - ')then
1980 4 : ddb%typ(iblok)=BLKTYP_d3E_xx
1981 110 : else if(name==' Total energy - ')then
1982 34 : ddb%typ(iblok)=BLKTYP_d0E_xx
1983 76 : else if(name==' 1st derivatives - ')then
1984 34 : ddb%typ(iblok)=BLKTYP_d1E_xx
1985 42 : else if(name==' 2nd eigenvalue derivatives - ' .or. name==' 2rd eigenvalue derivatives - ')then
1986 24 : ddb%typ(iblok)=BLKTYP_d2eig_re
1987 18 : else if(name==' 3rd derivatives (long wave) - ')then
1988 18 : ddb%typ(iblok)=BLKTYP_d3E_lw
1989 0 : else if(name==' 2nd derivatives (MBC) - ')then
1990 0 : ddb%typ(iblok)=BLKTYP_d2E_mbc
1991 : else
1992 : write(msg,'(6a)')&
1993 0 : 'The following string appears in the DDB in place of',&
1994 0 : ' the block type description :',ch10,trim(name),ch10,&
1995 0 : 'Action: check your DDB.'
1996 0 : ABI_ERROR(msg)
1997 : end if
1998 :
1999 : ! Read the 2nd derivative block
2000 2081 : if (is_type_d2E(ddb%typ(iblok))) then
2001 :
2002 : ! First check if there is enough space to read it
2003 1967 : if(msize<(3*mpert*3*mpert))then
2004 : write(msg,'(3a)')&
2005 0 : 'There is not enough space to read a second-derivative block.',ch10,&
2006 0 : 'Action: increase msize and recompile.'
2007 0 : ABI_ERROR(msg)
2008 : end if
2009 :
2010 : ! Read the phonon wavevector
2011 7868 : read(nunit, '(4x,3es16.8,f6.1)' )(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
2012 :
2013 : ! Read the perturbation frequency
2014 1967 : if (ddb_version>=cvrsio9_new) then
2015 565 : read(nunit, '(10x,1es16.8)' ) ddb%omega(1,iblok)
2016 : else
2017 1402 : ddb%omega(1,iblok)=0.d0
2018 : end if
2019 5901 : ddb%omega(2:3,iblok)=0.d0
2020 :
2021 : ! Read every element
2022 324735 : do ii=1,nelmts
2023 322768 : read(nunit,*)idir1,ipert1,idir2,ipert2,ar,ai
2024 322768 : index=idir1+3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
2025 322768 : ddb%flg(index,iblok)=1
2026 322768 : ddb%val(1,index,iblok)=ar
2027 324735 : ddb%val(2,index,iblok)=ai
2028 : end do
2029 :
2030 114 : else if (is_type_d3E(ddb%typ(iblok))) then
2031 : ! Read the 3rd derivative block
2032 :
2033 : ! First check if there is enough space to read it
2034 22 : if(msize<(3*mpert*3*mpert*3*mpert))then
2035 : write(msg, '(a,a,a,i10,a,i10,a,a,a)' )&
2036 0 : 'There is not enough space to read a third-derivative block.',ch10,&
2037 0 : 'The size provided is only ',msize,' although ',3*mpert*3*mpert*3*mpert,' is needed.',ch10,&
2038 0 : 'Action: increase msize and recompile.'
2039 0 : ABI_ERROR(msg)
2040 : end if
2041 :
2042 : ! Read the perturbation wavevectors
2043 88 : read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
2044 88 : read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=4,6),ddb%nrm(2,iblok)
2045 88 : read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=7,9),ddb%nrm(3,iblok)
2046 :
2047 : ! Read the perturbation frequency
2048 22 : if (ddb_version>=cvrsio9_new) then
2049 18 : read(nunit, '(10x,1es16.8)' ) ddb%omega(1,iblok)
2050 18 : read(nunit, '(10x,1es16.8)' ) ddb%omega(2,iblok)
2051 18 : read(nunit, '(10x,1es16.8)' ) ddb%omega(3,iblok)
2052 : else
2053 16 : ddb%omega(:,iblok)=0.d0
2054 : end if
2055 :
2056 : ! Read every element
2057 5703 : do ii=1,nelmts
2058 5681 : read(nunit,*)idir1,ipert1,idir2,ipert2,idir3,ipert3,ar,ai
2059 : index=idir1+ &
2060 : 3*((ipert1-1)+mpert*((idir2-1)+ &
2061 5681 : 3*((ipert2-1)+mpert*((idir3-1)+3*(ipert3-1)))))
2062 5681 : ddb%flg(index,iblok)=1
2063 5681 : ddb%val(1,index,iblok)=ar
2064 5703 : ddb%val(2,index,iblok)=ai
2065 : end do
2066 :
2067 92 : else if (is_type_d0E(ddb%typ(iblok))) then
2068 : ! Read the total energy
2069 : ! First check if there is enough space to read it
2070 34 : if(msize<1)then
2071 : write(msg, '(3a,i0,3a)' )&
2072 0 : 'There is not enough space to read a total energy block.',ch10,&
2073 0 : 'The size provided is only ',msize,' although 1 is needed.',ch10,&
2074 0 : 'Action: increase msize and recompile.'
2075 0 : ABI_ERROR(msg)
2076 : end if
2077 :
2078 : ! Read the total energy
2079 34 : read(nunit,'(2d22.14)')ar,ai
2080 34 : ddb%flg(1,iblok)=1
2081 34 : ddb%val(1,1,iblok)=ar
2082 34 : ddb%val(2,1,iblok)=ai
2083 :
2084 :
2085 58 : else if (is_type_d1E(ddb%typ(iblok))) then
2086 : ! Read the 1st derivative block
2087 : ! First check if there is enough space to read it
2088 34 : if (msize < (3*mpert)) then
2089 : write(msg, '(3a,i0,a,i0,3a)' )&
2090 0 : 'There is not enough space to read a first-derivative block.',ch10,&
2091 0 : 'The size provided is only ',msize,' although ',3*mpert,' is needed.',ch10,&
2092 0 : 'Action: increase msize and recompile.'
2093 0 : ABI_ERROR(msg)
2094 : end if
2095 :
2096 : ! Read every element
2097 658 : do ii=1,nelmts
2098 624 : read(nunit,*)idir1,ipert1,ar,ai
2099 624 : index=idir1 + 3*(ipert1 - 1)
2100 624 : ddb%flg(index,iblok)=1
2101 624 : ddb%val(1,index,iblok)=ar
2102 658 : ddb%val(2,index,iblok)=ai
2103 : end do
2104 :
2105 :
2106 24 : else if (is_type_d2eig(ddb%typ(iblok))) then
2107 :
2108 : ! Read the 2nd eigenvalue derivative block
2109 : ! First check if there is enough space to read it
2110 24 : if(msize<(3*mpert*3*mpert))then
2111 : write(msg, '(3a,i0,a,i0,3a)' )&
2112 0 : 'There is not enough space to read a second-derivative block.',ch10,&
2113 0 : 'The size provided is only ',msize,' although ',3*mpert*3*mpert*mband*nkpt,' is needed.',ch10,&
2114 0 : 'Action: increase msize and recompile.'
2115 0 : ABI_ERROR(msg)
2116 : end if
2117 :
2118 : ! Read the phonon wavevector
2119 96 : read(nunit, '(4x,3es16.8,f6.1)' )(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
2120 :
2121 : ! Read the K point and band
2122 24 : if (eig2d_) then
2123 268 : do ikpt=1,nkpt
2124 244 : read(nunit, '(9x,3es16.8)')(kpt(ii,ikpt),ii=1,3)
2125 1644 : do iband=1,mband
2126 1376 : read(nunit, '(6x,i3)') band
2127 : ! Read every element
2128 43380 : do ii=1,nelmts
2129 41760 : read(nunit,*)idir1,ipert1,idir2,ipert2,ar,ai
2130 41760 : index=idir1+3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
2131 41760 : ddb%flg(index,iblok)=1
2132 41760 : blkval2(1,index,iband,ikpt)=ar
2133 43136 : blkval2(2,index,iband,ikpt)=ai
2134 : end do !nelmts
2135 : end do !band
2136 : end do !kpt
2137 : end if
2138 : end if
2139 :
2140 2105 : end subroutine ddb_read_block_txt
2141 : !!***
2142 :
2143 : !----------------------------------------------------------------------
2144 :
2145 : !!****f* m_ddb/ddb_read_d2eig
2146 : !!
2147 : !! NAME
2148 : !! ddb_read_d2eig
2149 : !!
2150 : !! FUNCTION
2151 : !! Read the next DDB block containing second-order derivatives of eigenvalues
2152 : !! and store it in block number iblok.
2153 : !! The values of nband and nkpt must be set.
2154 : !!
2155 : !! INPUTS
2156 : !! ddb_hdr=ddb header object with open file.
2157 : !! iblok_store=the block index in the ddb object
2158 : !! iblok_read=the block index in the ddb file
2159 : !!
2160 : !! OUTPUT
2161 : !!
2162 : !! NOTE
2163 : !! The ddb object must be allocated becore calling this routine.
2164 : !!
2165 : !! SOURCE
2166 :
2167 :
2168 48 : subroutine ddb_read_d2eig(ddb, ddb_hdr, iblok_store, iblok_read, comm)
2169 :
2170 : !Arguments -------------------------------
2171 : !scalars
2172 : class(ddb_type),intent(inout) :: ddb
2173 : type(ddb_hdr_type),intent(in) :: ddb_hdr
2174 : integer, intent(in) :: iblok_store
2175 : integer, intent(in),optional :: iblok_read
2176 : integer, intent(in),optional :: comm
2177 :
2178 : !Local variables -------------------------
2179 : !scalars
2180 : integer,parameter :: master=0
2181 : integer :: comm_
2182 : character(len=500) :: msg
2183 : ! *********************************************************************
2184 :
2185 48 : if (present(comm)) then
2186 0 : comm_ = comm
2187 : else
2188 48 : comm_ = xmpi_comm_self
2189 : end if
2190 :
2191 48 : if (xmpi_comm_rank(comm_) == master) then
2192 :
2193 48 : if (ddb_hdr%has_open_file_nc) then
2194 :
2195 : ! Read the specified block and store it
2196 24 : call ddb%read_d2eig_nc(ddb_hdr%ncid, iblok_store, iblok_read)
2197 :
2198 24 : else if (ddb_hdr%has_open_file_txt) then
2199 :
2200 : ! Read the next block and store it
2201 24 : call ddb%read_d2eig_txt(ddb_hdr%unddb, iblok_store,ddb_hdr%ddb_version)
2202 :
2203 : else
2204 : write(msg, '(3a)' )&
2205 : ! File has not beed open by ddb_hdr
2206 0 : 'Attempting to read from unopen file DDB.',ch10,&
2207 0 : 'Action: contact Abinit group.'
2208 0 : ABI_ERROR(msg)
2209 : end if
2210 :
2211 : end if
2212 :
2213 : ! GA: Should in principle broadcast the d2eig array,
2214 : ! but I dont think it is required yet.
2215 :
2216 48 : end subroutine ddb_read_d2eig
2217 : !!***
2218 :
2219 : !----------------------------------------------------------------------
2220 :
2221 : !!****f* m_ddb/ddb_read_d2eig_txt
2222 : !!
2223 : !! NAME
2224 : !! ddb_read_d2eig_txt
2225 : !!
2226 : !! FUNCTION
2227 : !! Read the next DDB block containing second-order derivatives of eigenvalues
2228 : !! and store it in block number iblok.
2229 : !! The ddb object must have been allocated with nband and nkpt.
2230 : !!
2231 : !! INPUTS
2232 : !! unddb=unit for the open file in text format
2233 : !! iblok=the block index in the ddb object
2234 : !!
2235 : !! OUTPUT
2236 : !!
2237 : !! SOURCE
2238 :
2239 :
2240 24 : subroutine ddb_read_d2eig_txt(ddb, unddb, iblok, ddbvsn)
2241 :
2242 : !Arguments -------------------------------
2243 : !scalars
2244 : class(ddb_type),intent(inout) :: ddb
2245 : integer, intent(in) :: unddb, ddbvsn
2246 : integer, intent(in), optional :: iblok
2247 : !Local variables -------------------------
2248 : !scalars
2249 : integer :: iblok_eig2d
2250 : ! *********************************************************************
2251 :
2252 24 : iblok_eig2d = 1
2253 24 : if (present(iblok)) iblok_eig2d = iblok
2254 :
2255 : call ddb%read_block_txt(iblok_eig2d,ddb%nband*ddb%nsppol,ddb%mpert,ddb%msize,ddb%nkpt,unddb,&
2256 24 : ddb%eig2dval(:,:,:,:),ddb%kpt(:,:),ddb_version=ddbvsn)
2257 :
2258 24 : end subroutine ddb_read_d2eig_txt
2259 : !!***
2260 :
2261 : !----------------------------------------------------------------------
2262 :
2263 : !!****f* m_ddb/rdddb9
2264 : !! NAME
2265 : !! rdddb9
2266 : !!
2267 : !! FUNCTION
2268 : !! This routine reads the derivative database entirely,
2269 : !! for use in ppddb9, and performs some checks and symmetrisation
2270 : !! At the end, the whole DDB is in central memory, contained in the array ddb%val(2,msize,ddb%nblok).
2271 : !!
2272 : !! The information on it is contained in the four arrays
2273 : !! ddb%flg(msize,ddb%nblok) : blok flag for each element
2274 : !! ddb%qpt(9,ddb%nblok) : blok wavevector (unnormalized)
2275 : !! ddb%nrm(3,ddb%nblok) : blok wavevector normalization
2276 : !! ddb%typ(ddb%nblok) : blok type
2277 : !!
2278 : !! INPUTS
2279 : !! unddb = unit number for DDB io
2280 : !! dimekb=dimension of ekb (for the time being, only for norm- conserving psps)
2281 : !! iout=unit number for output of formatted data
2282 : !! lmnmax=if useylm=1, max number of (l,m,n) comp. over all type of psps
2283 : !! =if useylm=0, max number of (l,n) comp. over all type of psps
2284 : !! mband=maximum number of bands
2285 : !! mpert =maximum number of ipert
2286 : !! msize=maximum size of data blocks
2287 : !! msym =maximum number of symmetry elements in space group
2288 : !! natom = number of atoms
2289 : !! ntypat=number of atom types
2290 : !! usepaw= 0 for non paw calculation; =1 for paw calculation
2291 : !! [raw] = 1 -> do not perform any symetrization or transformation to cartesian coordinates.
2292 : !! 0 (default) -> do perform these transformations.
2293 : !!
2294 : !! OUTPUT
2295 : !! acell(3)=length scales of cell (bohr)
2296 : !! amu(ntypat)=mass of the atoms (atomic mass unit)
2297 : !! ddb: ddb blok datatype
2298 : !! contents: ddb%flg(msize,nblok)= flag of existence for each element of the DDB
2299 : !! ddb%nrm(3,nblok) : blok wavevector normalization
2300 : !! ddb%qpt(9,nblok) : blok wavevector (unnormalized)
2301 : !! ddb%typ(nblok) : blok type
2302 : !! ddb%val(2,msize,nblok)= value of each complex element of the DDB
2303 : !! ddb%nblok= number of bloks in the DDB
2304 : !! gmet(3,3)=reciprocal space metric tensor in bohr**-2
2305 : !! gprim(3,3)=dimensionless reciprocal space primitive translations
2306 : !! indsym(4,msym,natom)=indirect indexing array for symmetries
2307 : !! natom=number of atoms in cell
2308 : !! nsym=number of space group symmetries
2309 : !! rmet(3,3)=metric tensor in real space (bohr^2)
2310 : !! rprim(3,3)= primitive translation vectors
2311 : !! symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space)
2312 : !! symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
2313 : !! symafm(nsym)=Anti-ferromagnetic symmetries.
2314 : !! tnons(3,nsym)=fractional nonsymmorphic translations
2315 : !! typat(natom)=type integer for each atom in cell
2316 : !! ucvol=unit cell volume in bohr**3
2317 : !! xcart(3,natom)=atomic cartesian coordinates
2318 : !! xred(3,natom)=fractional dimensionless atomic coordinates
2319 : !! zion(ntypat)=charge on each type of atom (real number)
2320 : !! znucl(ntypat)=Nuclear charge for each type of pseudopotential
2321 : !!
2322 : !! SOURCE
2323 :
2324 288 : subroutine rdddb9(ddb,ddb_hdr,unddb,&
2325 288 : acell,amu,gmet,gprim,indsym,&
2326 : mband,mpert,msize,msym,natom,nkpt,nsym,ntypat,&
2327 288 : rmet,rprim,symrec,symrel,symafm,tnons,typat,ucvol,&
2328 288 : xcart,xred,zion,znucl,raw)
2329 :
2330 : !Arguments -------------------------------
2331 : ! NOTE: these are used for dimensioning and then re-assigned in ioddb8.
2332 : ! This is almost definitely bad practice. In particular
2333 : ! it should be indsym(4,msym,natom),
2334 : ! and
2335 : ! the allocation allocate(kpt(3,nkpt)) is strange
2336 : !scalars
2337 : class(ddb_type),intent(inout) :: ddb
2338 : integer,intent(in) :: unddb,mband,mpert,msize,msym
2339 : integer,intent(inout) :: natom,nkpt,nsym,ntypat
2340 : real(dp),intent(out) :: ucvol
2341 : type(ddb_hdr_type),intent(inout) :: ddb_hdr
2342 : integer,optional,intent(in) :: raw
2343 : !arrays
2344 : integer,intent(inout) :: indsym(4,msym,natom)
2345 : integer,intent(out) :: symrec(3,3,msym),symrel(3,3,msym),symafm(msym)
2346 : integer,intent(out) :: typat(natom)
2347 : real(dp),intent(out) :: acell(3),amu(ntypat)
2348 : real(dp),intent(out) :: gmet(3,3),gprim(3,3),rmet(3,3)
2349 : real(dp),intent(out) :: rprim(3,3),tnons(3,msym),xcart(3,natom),xred(3,natom)
2350 : real(dp),intent(out) :: zion(ntypat),znucl(ntypat)
2351 :
2352 : !Local variables -------------------------
2353 : !mtyplo=maximum number of type, locally
2354 : !scalars
2355 : integer,parameter :: msppol=2,mtyplo=6
2356 : integer :: raw_
2357 : integer :: iblok,isym
2358 : integer :: ddb_version
2359 : real(dp),parameter :: tolsym8=tol8
2360 : !arrays
2361 : real(dp) :: gprimd(3,3),rprimd(3,3)
2362 : ! *********************************************************************
2363 :
2364 : DBG_ENTER("COLL")
2365 :
2366 288 : if (present(raw)) then
2367 83 : raw_ = raw
2368 : else
2369 : raw_ = 0
2370 : end if
2371 :
2372 : ! FIXME
2373 : ! GA: Most of this stuff could be moved up to the calling routine
2374 :
2375 288 : nsym = ddb_hdr%nsym
2376 1152 : acell = ddb_hdr%acell
2377 3744 : rprim = ddb_hdr%rprim
2378 288 : ddb_version = ddb_hdr%ddb_version
2379 :
2380 826 : amu(:) = ddb_hdr%amu(1:ntypat)
2381 1110 : typat(:) = ddb_hdr%typat(1:natom)
2382 826 : zion(:) = ddb_hdr%zion(1:ntypat)
2383 826 : znucl(:) = ddb_hdr%znucl(1:ntypat)
2384 :
2385 55584 : symafm(:) = ddb_hdr%symafm(:)
2386 719136 : symrel(:,:,:) = ddb_hdr%symrel(:,:,:)
2387 221472 : tnons(:,:) = ddb_hdr%tnons(:,:)
2388 :
2389 3576 : xred(:,:) = ddb_hdr%xred(:,:)
2390 :
2391 : !call ddb_hdr%free()
2392 :
2393 : ! Compute different matrices in real and reciprocal space, also
2394 : ! checks whether ucvol is positive.
2395 288 : call mkrdim(acell,rprim,rprimd)
2396 :
2397 : ! call metric without printing to output
2398 288 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
2399 :
2400 : ! Obtain reciprocal space primitive transl g from inverse trans of r
2401 : ! (Unlike in abinit, gprim is used throughout ifc; should be changed, later)
2402 288 : call matr3inv(rprim,gprim)
2403 :
2404 : ! Generate atom positions in cartesian coordinates
2405 288 : call xred2xcart(natom,rprimd,xcart,xred)
2406 :
2407 : ! Transposed inversion of the symmetry matrices, for use in the reciprocal space
2408 11061 : do isym=1,nsym
2409 11061 : call mati3inv(symrel(:,:,isym),symrec(:,:,isym))
2410 : end do
2411 :
2412 : ! SYMATM generates for all the atoms and all the symmetries, the atom
2413 : ! on which the referenced one is sent and also the translation bringing
2414 : ! back this atom to the referenced unit cell
2415 : ! GA: symatm was already called in crystal_init, no need to do it again.
2416 288 : call symatm(indsym,natom,nsym,symrec,tnons,tolsym8,typat,xred)
2417 :
2418 : !write(msg, '(3a,i0,a)' )ch10,ch10,' rdddb9: read ',ddb%nblok,' blocks from the input DDB '
2419 : !call wrtout(std_out,msg)
2420 :
2421 : ! Read the blocks from the input database, and close it.
2422 2345 : do iblok=1,ddb%nblok
2423 :
2424 2057 : call ddb%read_block_txt(iblok,mband,mpert,msize,nkpt,unddb, ddb_version=ddb_version)
2425 :
2426 2345 : if (raw_ == 0) then
2427 1949 : call ddb%symmetrize_and_transform(ddb_hdr%crystal,iblok)
2428 : end if
2429 :
2430 : end do ! iblok
2431 :
2432 : DBG_EXIT("COLL")
2433 :
2434 288 : end subroutine rdddb9
2435 : !!***
2436 :
2437 : !----------------------------------------------------------------------
2438 :
2439 : !!****f* m_ddb/chkin9
2440 : !! NAME
2441 : !! chkin9
2442 : !!
2443 : !! FUNCTION
2444 : !! Construct flags for the computation of IFC for each atoms.
2445 : !! Also check that the value of natifc makes sense.
2446 : !!
2447 : !! INPUTS
2448 : !! atifc(natifc)=list of the atom ifc to be analysed
2449 : !! natifc= number of atom ifc to be analysed
2450 : !! natom= number of atoms
2451 : !!
2452 : !! OUTPUT
2453 : !! atifcflg(natom) = atifcflg(ia) equals 1 if the analysis of ifc
2454 : !! has to be done for atom ia; otherwise 0.
2455 : !!
2456 : !! NOTES
2457 : !! Only for one processor (no use of wrtout)
2458 : !!
2459 : !! SOURCE
2460 :
2461 81 : subroutine chkin9(atifcflg,atifc,natifc,natom)
2462 :
2463 : ! GA: FIXME Move this subroutine into m_anaddb_dataset
2464 : !Arguments -------------------------------
2465 : !scalars
2466 : integer,intent(in) :: natifc,natom
2467 : !arrays
2468 : integer,intent(in) :: atifc(natifc)
2469 : integer,intent(out) :: atifcflg(natom)
2470 :
2471 : !Local variables -------------------------
2472 : !scalars
2473 : integer :: iatifc
2474 : character(len=500) :: msg
2475 : !arrays
2476 : !integer,allocatable :: work(:)
2477 : ! *********************************************************************
2478 :
2479 81 : if(natifc>natom)then
2480 : write(msg, '(a,i0,3a,i0,3a)' )&
2481 0 : 'The number of atom ifc in the input files',natifc,',',ch10,&
2482 0 : 'is larger than the number of atoms',natom,'.',ch10,&
2483 0 : 'Action: change natifc in the input file.'
2484 0 : ABI_ERROR(msg)
2485 : end if
2486 :
2487 341 : atifcflg = zero
2488 81 : if(natifc>=1)then
2489 :
2490 42 : do iatifc=1,natifc
2491 26 : if(atifc(iatifc)<=0.or.atifc(iatifc)>natom)then
2492 : write(msg, '(a,i0,5a,i0,3a)' )&
2493 0 : 'For iatifc=',iatifc,', the number of the atom ifc to be ',ch10,&
2494 0 : 'analysed is not valid : either negative, ',ch10,&
2495 0 : 'zero, or larger than natom =',natom,'.',ch10,&
2496 0 : 'Action: change atifc in your input file.'
2497 0 : ABI_ERROR(msg)
2498 : end if
2499 42 : atifcflg(atifc(iatifc))=1
2500 : end do
2501 :
2502 : end if
2503 :
2504 81 : end subroutine chkin9
2505 : !!***
2506 :
2507 : !----------------------------------------------------------------------
2508 :
2509 : !!****f* m_ddb/nlopt
2510 : !! NAME
2511 : !! nlopt
2512 : !!
2513 : !! FUNCTION
2514 : !! Output of all quantities related to third-order derivatives of the energy.
2515 : !! Compute the permutations of the three perturbations, then
2516 : !! write out the whole matrix of third order derivatives
2517 : !! in reduced coordinates. Finally, compute the non-linear optical
2518 : !! susceptibility d and the first-order change in the dielectric
2519 : !! susceptibility tensor induced by an atomic displacement.
2520 : !!
2521 : !! INPUTS
2522 : !! blkflg(3,mpert,3,mpert,3,mpert)= ( 1 if the element of the 3dte
2523 : !! has been calculated ; 0 otherwise )
2524 : !! d3(2,3,mpert,3,mpert,3,mpert)= matrix of the 3DTE
2525 : !! gprimd(3,3)=dimensional primitive translations for reciprocal space(bohr^-1)
2526 : !! mpert =maximum number of ipert
2527 : !! natom= number of atoms
2528 : !! rprimd(3,3)=dimensional primitive translations (bohr)
2529 : !! ucvol=unit cell volume (bohr^3)
2530 : !!
2531 : !! OUTPUT
2532 : !! carflg(3,mpert,3,mpert,3,mpert)=1 if the element of d3cart has been calculated, 0 otherwise
2533 : !! d3cart(2,3,mpert,3,mpert,3,mpert)=matrix of third-order energy derivatives in cartesian coordinates
2534 : !!
2535 : !! SOURCE
2536 :
2537 37 : subroutine nlopt(blkflg,carflg,d3,d3cart,gprimd,mpert,natom,rprimd,ucvol)
2538 :
2539 : !Arguments -------------------------------
2540 : !scalars
2541 : integer,intent(in) :: mpert,natom
2542 : real(dp),intent(in) :: ucvol
2543 : !arrays
2544 : integer,intent(in) :: blkflg(3,mpert,3,mpert,3,mpert)
2545 : integer,intent(out) :: carflg(3,mpert,3,mpert,3,mpert)
2546 : real(dp),intent(in) :: d3(2,3,mpert,3,mpert,3,mpert),gprimd(3,3),rprimd(3,3)
2547 : real(dp),intent(out) :: d3cart(2,3,mpert,3,mpert,3,mpert)
2548 :
2549 : !Local variables -------------------------
2550 : !scalars
2551 : integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert
2552 : !arrays
2553 : integer :: flg1(3),flg2(3)
2554 : real(dp) :: vec1(3),vec2(3)
2555 :
2556 : ! *******************************************************************
2557 :
2558 : !Compute the permutations of the perturbations
2559 :
2560 2773117 : d3cart(:,:,:,:,:,:,:) = 0._dp
2561 :
2562 361 : do i1pert = 1,mpert
2563 3373 : do i2pert = 1,mpert
2564 33732 : do i3pert = 1,mpert
2565 124596 : do i1dir=1,3
2566 395148 : do i2dir=1,3
2567 1185444 : do i3dir=1,3
2568 :
2569 : ! Check if all elements are available
2570 :
2571 : if ((blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/=0).and. &
2572 : (blkflg(i1dir,i1pert,i3dir,i3pert,i2dir,i2pert)/=0).and. &
2573 : (blkflg(i2dir,i2pert,i1dir,i1pert,i3dir,i3pert)/=0).and. &
2574 : (blkflg(i2dir,i2pert,i3dir,i3pert,i1dir,i1pert)/=0).and. &
2575 820692 : (blkflg(i3dir,i3pert,i1dir,i1pert,i2dir,i2pert)/=0).and. &
2576 273564 : (blkflg(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert)/=0)) then
2577 :
2578 : d3cart(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = &
2579 : ( d3(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) + &
2580 : d3(:,i1dir,i1pert,i3dir,i3pert,i2dir,i2pert) + &
2581 : d3(:,i2dir,i2pert,i1dir,i1pert,i3dir,i3pert) + &
2582 : d3(:,i2dir,i2pert,i3dir,i3pert,i1dir,i1pert) + &
2583 : d3(:,i3dir,i3pert,i1dir,i1pert,i2dir,i2pert) + &
2584 16611 : d3(:,i3dir,i3pert,i2dir,i2pert,i1dir,i1pert))*sixth
2585 :
2586 : end if
2587 : end do
2588 : end do
2589 : end do
2590 : end do
2591 : end do
2592 : end do
2593 :
2594 : !Transform to cartesian coordinates
2595 1131733 : carflg(:,:,:,:,:,:) = 0
2596 :
2597 361 : do i1pert = 1, mpert
2598 3373 : do i2pert = 1, mpert
2599 33732 : do i3pert = 1, mpert
2600 :
2601 121584 : do i2dir = 1, 3
2602 395148 : do i3dir = 1, 3
2603 :
2604 1094256 : vec1(:) = d3cart(1,:,i1pert,i2dir,i2pert,i3dir,i3pert)
2605 1094256 : flg1(:) = blkflg(:,i1pert,i2dir,i2pert,i3dir,i3pert)
2606 273564 : call cart39(flg1,flg2,gprimd,i1pert,natom,rprimd,vec1,vec2)
2607 1094256 : d3cart(1,:,i1pert,i2dir,i2pert,i3dir,i3pert) = vec2(:)
2608 1185444 : carflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) = flg2(:)
2609 :
2610 : end do
2611 : end do
2612 :
2613 121584 : do i1dir = 1, 3
2614 395148 : do i3dir = 1, 3
2615 1094256 : vec1(:) = d3cart(1,i1dir,i1pert,:,i2pert,i3dir,i3pert)
2616 1094256 : flg1(:) = blkflg(i1dir,i1pert,:,i2pert,i3dir,i3pert)
2617 273564 : call cart39(flg1,flg2,gprimd,i2pert,natom,rprimd,vec1,vec2)
2618 1094256 : d3cart(1,i1dir,i1pert,:,i2pert,i3dir,i3pert) = vec2(:)
2619 1185444 : carflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) = flg2(:)
2620 : end do
2621 : end do
2622 :
2623 124596 : do i1dir = 1, 3
2624 395148 : do i2dir = 1, 3
2625 1094256 : vec1(:) = d3cart(1,i1dir,i1pert,i2dir,i2pert,:,i3pert)
2626 1094256 : flg1(:) = blkflg(i1dir,i1pert,i2dir,i2pert,:,i3pert)
2627 273564 : call cart39(flg1,flg2,gprimd,i3pert,natom,rprimd,vec1,vec2)
2628 1094256 : d3cart(1,i1dir,i1pert,i2dir,i2pert,:,i3pert) = vec2(:)
2629 1185444 : carflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) = flg2(:)
2630 : end do
2631 : end do
2632 :
2633 : end do
2634 : end do
2635 : end do
2636 :
2637 : ! Compute non linear-optical coefficients d_ijk (atomic units)
2638 37 : i1pert = natom+2
2639 3478 : d3cart(:,:,i1pert,:,i1pert,:,i1pert) = -3._dp*d3cart(:,:,i1pert,:,i1pert,:,i1pert)/(ucvol*2._dp)
2640 :
2641 : ! Compute first-order change in the electronic dielectric
2642 : ! susceptibility (Bohr^-1) induced by an atomic displacement
2643 7141 : d3cart(1:2,1:3,1:natom,1:3,natom + 2,1:3,natom + 2) = -6._dp*d3cart(1:2,1:3,1:natom,1:3,natom + 2,1:3,natom + 2)/ucvol
2644 :
2645 37 : end subroutine nlopt
2646 : !!***
2647 :
2648 : !----------------------------------------------------------------------
2649 :
2650 : !!****f* m_ddb/ddb_from_file
2651 : !! NAME
2652 : !! ddb_from_file
2653 : !!
2654 : !! FUNCTION
2655 : !! This subroutine reads data from the DDB file and constructs an instance of ddb_type
2656 : !! It also returns an instance of crystal_t with the crystalline structure reported in the DDB file
2657 : !! and the DDB header.
2658 : !!
2659 : !! INPUTS
2660 : !! filename=DDB filename.
2661 : !! comm=MPI communicator.
2662 : !! [prtvol] = Verbosity level
2663 : !! raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates.
2664 : !! 0 (default) -> do perform these transformations.
2665 : !!
2666 : !! OUTPUT
2667 : !! ddb<type(ddb_type)>=Object storing the DDB results.
2668 : !! crystal<type(crystal_t)>=Crystal structure parameters
2669 : !! ddb_hdr<type(ddb_hdr_type)>= Header of the DDB file.
2670 : !!
2671 : !! SOURCE
2672 :
2673 52771 : subroutine ddb_from_file(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw)
2674 :
2675 : !Arguments -------------------------------
2676 : !scalars
2677 : class(ddb_type),intent(inout) :: ddb
2678 : integer,intent(in) :: comm
2679 : integer,optional,intent(in) :: prtvol, raw
2680 : character(len=*),intent(in) :: filename
2681 : type(crystal_t),intent(out) :: crystal
2682 : type(ddb_hdr_type),intent(out) :: ddb_hdr
2683 : !array
2684 :
2685 : !Local variables-------------------------------
2686 : integer :: iomode
2687 : character(len=fnlen) :: filename_
2688 : integer :: prtvol_
2689 : character(len=500) :: msg
2690 : ! ************************************************************************
2691 :
2692 : DBG_ENTER("COLL")
2693 :
2694 467 : prtvol_ = 0; if (present(prtvol)) prtvol_ = prtvol
2695 :
2696 467 : call ddb_hdr%get_iomode(filename, 1, iomode, filename_)
2697 :
2698 467 : if (iomode==IO_MODE_ETSF) then
2699 171 : call ddb%read_nc(filename_, ddb_hdr, crystal, comm, prtvol, raw)
2700 296 : else if (iomode==IO_MODE_FORTRAN) then
2701 296 : call ddb%read_txt(filename_, ddb_hdr, crystal, comm, prtvol, raw)
2702 : end if
2703 :
2704 : ! Print out info on the crystal
2705 467 : if (prtvol_ >= -1) then
2706 :
2707 467 : call ddb_hdr%crystal%print(unit=std_out)
2708 467 : if (prtvol_ >= 0) then
2709 224 : call ddb_hdr%crystal%print(unit=ab_out)
2710 : end if
2711 :
2712 467 : write(msg, '(2a,i0,a)' )ch10,' DDB file with ',ddb%nblok,' blocks has been read.'
2713 467 : call wrtout(std_out,msg)
2714 467 : if (prtvol_ >= 0) then
2715 224 : call wrtout(ab_out,msg)
2716 : end if
2717 :
2718 : end if
2719 :
2720 : DBG_EXIT("COLL")
2721 :
2722 467 : end subroutine ddb_from_file
2723 : !!***
2724 :
2725 : !----------------------------------------------------------------------
2726 :
2727 : !!****f* m_ddb/ddb_read_txt
2728 : !! NAME
2729 : !! ddb_read_txt
2730 : !!
2731 : !! FUNCTION
2732 : !! This subroutine reads data from the DDB file and constructs an instance of ddb_type
2733 : !! It also returns an instance of crystal_t with the crystalline structure reported in the DDB file
2734 : !! and the DDB header.
2735 : !!
2736 : !! INPUTS
2737 : !! filename=DDB filename.
2738 : !! comm=MPI communicator.
2739 : !! prtvol=Verbosity level
2740 : !! raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates.
2741 : !! 0 (default) -> do perform these transformations.
2742 : !!
2743 : !! OUTPUT
2744 : !! ddb<type(ddb_type)>=Object storing the DDB results.
2745 : !! crystal<type(crystal_t)>=Crystal structure parameters
2746 : !! ddb_hdr= Header of the DDB file.
2747 : !!
2748 : !! SOURCE
2749 :
2750 33448 : subroutine ddb_read_txt(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw)
2751 :
2752 : !Arguments -------------------------------
2753 : !scalars
2754 : class(ddb_type),intent(inout) :: ddb
2755 : integer,intent(in) :: comm
2756 : integer,optional,intent(in) :: prtvol, raw
2757 : character(len=*),intent(in) :: filename
2758 : type(crystal_t),intent(out) :: Crystal
2759 : type(ddb_hdr_type),intent(out) :: ddb_hdr
2760 :
2761 : !Local variables-------------------------------
2762 : !scalars
2763 : integer,parameter :: master=0
2764 : integer :: msym,dimekb,lmnmax,mband,nkpt,ntypat,nsym,usepaw
2765 : integer :: mpert,msize,natom,nblok,occopt,nsppol
2766 : real(dp) :: ucvol
2767 :
2768 : !arrays
2769 296 : integer,allocatable :: symrec(:,:,:),symrel(:,:,:),symafm(:),indsym(:,:,:),typat(:)
2770 : real(dp) :: acell(3),gmet(3,3),gprim(3,3),rmet(3,3),rprim(3,3)
2771 296 : real(dp),allocatable :: amu(:),xcart(:),xred(:,:),zion(:),znucl(:),tnons(:,:)
2772 : ! ************************************************************************
2773 :
2774 : DBG_ENTER("COLL")
2775 :
2776 : ! Must read natom from the DDB before being able to allocate some arrays needed for invars9
2777 296 : call ddb_hdr%open_read_txt(filename, comm)
2778 :
2779 : ! GA: clean this up. Not all of it is useful
2780 296 : nblok = ddb_hdr%nblok
2781 296 : msym = ddb_hdr%msym
2782 296 : natom = ddb_hdr%natom
2783 296 : ntypat = ddb_hdr%ntypat
2784 296 : mband = ddb_hdr%mband
2785 296 : nkpt = ddb_hdr%nkpt
2786 296 : nsppol = ddb_hdr%nsppol
2787 296 : usepaw = ddb_hdr%usepaw
2788 296 : dimekb = ddb_hdr%psps%dimekb
2789 296 : lmnmax = ddb_hdr%psps%lmnmax
2790 296 : occopt = ddb_hdr%occopt
2791 296 : mpert = ddb_hdr%mpert
2792 296 : msize = ddb_hdr%msize
2793 :
2794 : ! Master reads and then broadcasts data.
2795 296 : if (xmpi_comm_rank(comm) == master) then
2796 :
2797 : ! Allocate arrays depending on msym (which is actually fixed to nsym inside inprep8)
2798 864 : ABI_MALLOC(symrel,(3,3,msym))
2799 864 : ABI_MALLOC(symafm,(msym))
2800 864 : ABI_MALLOC(tnons,(3,msym))
2801 864 : ABI_MALLOC(typat,(natom))
2802 864 : ABI_MALLOC(xred,(3,natom))
2803 864 : ABI_MALLOC(zion,(ntypat))
2804 576 : ABI_MALLOC(znucl,(ntypat))
2805 :
2806 576 : ABI_MALLOC(symrec,(3,3,msym))
2807 1152 : ABI_MALLOC(indsym,(4,msym,natom))
2808 864 : ABI_MALLOC(xcart,(3*natom))
2809 576 : ABI_MALLOC(amu,(ntypat))
2810 :
2811 288 : ddb%nsppol = nsppol
2812 288 : call ddb%malloc(msize, nblok, natom, ntypat, mpert)
2813 :
2814 : ! GA: FIXME
2815 : ! Should clean this up. Lots of the arguments are not needed.
2816 : ! In particular, rprim and acell could be taken from ddb_hdr%crystal
2817 : ! which is already initialized at this point
2818 : call rdddb9(ddb, ddb_hdr, ddb_hdr%unddb,&
2819 : acell,amu,gmet,gprim,indsym,&
2820 : mband,mpert,msize,msym,&
2821 : natom,nkpt,nsym,ntypat,&
2822 : rmet,rprim,symrec,symrel,symafm,&
2823 288 : tnons,typat,ucvol,xcart,xred,zion,znucl,raw)
2824 :
2825 288 : ABI_FREE(symrec)
2826 288 : ABI_FREE(indsym)
2827 288 : ABI_FREE(xcart)
2828 :
2829 : ! Save variables needed to call legacy code.
2830 1152 : ddb%acell = acell
2831 3744 : ddb%rprim = rprim
2832 3744 : ddb%gprim = gprim
2833 :
2834 : !call ddb%set_brav(brav)
2835 :
2836 : ! Other useful quantities.
2837 : ! 2 is to preserve the old behaviour
2838 288 : ddb%prtvol = 2; if (present(prtvol)) ddb%prtvol = prtvol
2839 288 : ddb%occopt = occopt
2840 1114 : ddb%amu = amu
2841 288 : ABI_FREE(amu)
2842 :
2843 : ! These were not needed because crystal is already initialized in the header.
2844 288 : ABI_FREE(symrel)
2845 288 : ABI_FREE(symafm)
2846 288 : ABI_FREE(tnons)
2847 288 : ABI_FREE(typat)
2848 288 : ABI_FREE(xred)
2849 288 : ABI_FREE(zion)
2850 576 : ABI_FREE(znucl)
2851 :
2852 : end if
2853 :
2854 296 : call ddb_hdr%close()
2855 :
2856 296 : if (xmpi_comm_size(comm) > 1) then
2857 12 : call ddb%bcast(comm)
2858 12 : call ddb_hdr%bcast(comm)
2859 :
2860 : !! GA: This seems superfluous now...
2861 : !call xmpi_bcast(nsym, master, comm, ierr)
2862 : !call xmpi_bcast(symrel, master, comm, ierr)
2863 : !call xmpi_bcast(symafm, master, comm, ierr)
2864 : !call xmpi_bcast(typat, master, comm, ierr)
2865 : !call xmpi_bcast(acell, master, comm, ierr)
2866 : !call xmpi_bcast(occopt, master, comm, ierr)
2867 : !call xmpi_bcast(gprim, master, comm, ierr)
2868 : !call xmpi_bcast(rprim, master, comm, ierr)
2869 : !call xmpi_bcast(tnons, master, comm, ierr)
2870 : !call xmpi_bcast(xred, master, comm, ierr)
2871 : !call xmpi_bcast(zion, master, comm, ierr)
2872 : !call xmpi_bcast(znucl, master, comm, ierr)
2873 : end if
2874 :
2875 296 : call ddb_hdr%crystal%copy(Crystal)
2876 :
2877 : !! Initialize crystal_t object.
2878 : !call mkrdim(acell,rprim,rprimd)
2879 :
2880 : !! GA: These variables are hardcoded which means the crystal object
2881 : !! is not reliable for antiferro systems or alchemical potentials
2882 : !! when it is read from a text DDB file.
2883 : !npsp = ntypat; space_group = 0; timrev = 2
2884 : !use_antiferro=.FALSE. !; use_antiferro=(nspden==2.and.nsppol==1)
2885 : !ABI_MALLOC(title, (ntypat))
2886 :
2887 : !do ii=1,ntypat
2888 : ! write(title(ii),'(a,i0)')"No title for typat ",ii
2889 : !end do
2890 :
2891 : !! Warning znucl is dimensioned with ntypat = nspsp hence alchemy is not supported here
2892 : !call crystal%init(ddb%amu,space_group,natom,npsp,ntypat,nsym,rprimd,typat,xred,&
2893 : ! zion,znucl,timrev,use_antiferro,.FALSE.,title,&
2894 : ! symrel=symrel(:,:,1:nsym),tnons=tnons(:,1:nsym),symafm=symafm(1:nsym))
2895 :
2896 : !ABI_FREE(title)
2897 : !ABI_FREE(symrel)
2898 : !ABI_FREE(symafm)
2899 : !ABI_FREE(tnons)
2900 : !ABI_FREE(typat)
2901 : !ABI_FREE(xred)
2902 : !ABI_FREE(zion)
2903 : !ABI_FREE(znucl)
2904 :
2905 : DBG_EXIT("COLL")
2906 :
2907 296 : end subroutine ddb_read_txt
2908 : !!***
2909 :
2910 : !----------------------------------------------------------------------
2911 :
2912 : !!****f* m_ddb/ddb_read_nc
2913 : !! NAME
2914 : !! ddb_read_nc
2915 : !!
2916 : !! FUNCTION
2917 : !! This subroutine reads data from the DDB.nc file and constructs an instance of ddb_type
2918 : !! It also returns an instance of crystal_t with the crystalline structure reported in the DDB file
2919 : !! and the DDB header.
2920 : !!
2921 : !! INPUTS
2922 : !! filename=DDB filename.
2923 : !! comm=MPI communicator.
2924 : !! prtvol=Verbosity level
2925 : !! raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates.
2926 : !! 0 (default) -> do perform these transformations.
2927 : !!
2928 : !! OUTPUT
2929 : !! ddb<type(ddb_type)>=Object storing the DDB results.
2930 : !! crystal<type(crystal_t)>=Crystal structure parameters
2931 : !! ddb_hdr= Header of the DDB file.
2932 : !!
2933 : !! SOURCE
2934 :
2935 17955 : subroutine ddb_read_nc(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw)
2936 :
2937 : !Arguments -------------------------------
2938 : !scalars
2939 : class(ddb_type),intent(inout) :: ddb
2940 : integer,intent(in) :: comm
2941 : integer,optional,intent(in) :: prtvol, raw
2942 : character(len=*),intent(in) :: filename
2943 : type(crystal_t),intent(out) :: crystal
2944 : type(ddb_hdr_type),intent(out) :: ddb_hdr
2945 : !array
2946 :
2947 : !Local variables-------------------------------
2948 : !scalars
2949 : integer,parameter :: master=0
2950 : integer :: prtvol_, raw_
2951 : integer :: ncid, ddb_version
2952 : integer :: iblok,iblok_d0E,iblok_d1E,iblok_d2E,iblok_d3E,iblok_d2eig
2953 :
2954 : !arrays
2955 : !character(len=132),allocatable :: title(:)
2956 : ! ************************************************************************
2957 :
2958 : DBG_ENTER("COLL")
2959 :
2960 171 : if (present(raw)) then
2961 160 : raw_ = raw
2962 : else
2963 : raw_ = 0
2964 : end if
2965 :
2966 : ! GA: Not really used so far
2967 : if (present(prtvol)) then
2968 : prtvol_ = prtvol
2969 : else
2970 : prtvol_ = 0
2971 : end if
2972 :
2973 : ! Read header
2974 171 : call ddb_hdr%open_read_nc(filename, comm)
2975 171 : ncid = ddb_hdr%ncid
2976 :
2977 171 : if (xmpi_comm_rank(comm) == master) then
2978 :
2979 171 : ddb%nsppol = ddb_hdr%nsppol
2980 :
2981 : ! Copy dimensions from header and allocate arrays
2982 : call ddb%malloc(ddb_hdr%msize, ddb_hdr%nblok, ddb_hdr%natom, &
2983 : ddb_hdr%ntypat, ddb_hdr%mpert,&
2984 171 : ddb_hdr%nkpt, ddb_hdr%mband*ddb_hdr%nsppol)
2985 :
2986 : ! Copy arrays from header
2987 358 : ddb%typ(:) = ddb_hdr%typ(:)
2988 408 : ddb%amu(:) = ddb_hdr%crystal%amu(:)
2989 :
2990 : ! GA: Note that these quantities are stored twice in the nc file.
2991 : ! We could also use those quantities in ddb_hdr.
2992 684 : ddb%acell(:) = one
2993 2223 : ddb%rprim(:,:) = ddb_hdr%crystal%rprimd(:,:)
2994 2223 : ddb%gprim(:,:) = ddb_hdr%crystal%gprimd(:,:)
2995 171 : ddb_version = ddb_hdr%ddb_version
2996 : !ddb%acell(:) = ddb_hdr%acell
2997 : !ddb%rprim(:,:) = ddb_hdr%rprim(:,:)
2998 : !ddb%gprim(:,:) = ddb_hdr%gprim(:,:)
2999 :
3000 : ! ---------------
3001 : ! Read all blocks
3002 : ! ---------------
3003 171 : iblok_d0E = 0
3004 171 : iblok_d1E = 0
3005 171 : iblok_d2E = 0
3006 171 : iblok_d3E = 0
3007 171 : iblok_d2eig = 0
3008 :
3009 358 : do iblok=1,ddb%nblok
3010 :
3011 187 : if (is_type_d0E(ddb%typ(iblok))) then
3012 6 : iblok_d0E = iblok_d0E + 1
3013 6 : call ddb%read_d0E_nc(ncid, iblok, iblok_d0E)
3014 :
3015 181 : else if (is_type_d1E(ddb%typ(iblok))) then
3016 10 : iblok_d1E = iblok_d1E + 1
3017 10 : call ddb%read_d1E_nc(ncid, iblok, iblok_d1E)
3018 :
3019 171 : else if (is_type_d2E(ddb%typ(iblok))) then
3020 148 : iblok_d2E = iblok_d2E + 1
3021 148 : call ddb%read_d2E_nc(ncid, iblok, iblok_d2E, ddb_version)
3022 :
3023 23 : else if (is_type_d3E(ddb%typ(iblok))) then
3024 3 : iblok_d3E = iblok_d3E + 1
3025 3 : call ddb%read_d3E_nc(ncid, iblok, iblok_d3E, ddb_version)
3026 :
3027 20 : else if (is_type_d2eig(ddb%typ(iblok))) then
3028 20 : iblok_d2eig = iblok_d2eig + 1
3029 : ! GA: It is kind of weird to call this function inside a loop,
3030 : ! because the ddb can only hold a single block of d2eig data.
3031 20 : call ddb%read_d2eig_nc(ncid, iblok, iblok_d2eig)
3032 :
3033 : end if
3034 :
3035 : ! Symmetrize and transform if raw==0
3036 358 : if (raw_==0) then
3037 11 : call ddb%symmetrize_and_transform(ddb_hdr%crystal,iblok)
3038 : end if
3039 :
3040 : end do
3041 :
3042 : end if
3043 :
3044 : ! Close the file
3045 171 : call ddb_hdr%close()
3046 :
3047 : ! --------------
3048 : ! Broadcast data
3049 : ! --------------
3050 171 : if (xmpi_comm_size(comm) > 1) then
3051 0 : call ddb%bcast(comm)
3052 0 : call ddb_hdr%bcast(comm)
3053 : end if
3054 :
3055 : ! Copy crystal
3056 171 : call ddb_hdr%crystal%copy(crystal)
3057 :
3058 : DBG_EXIT("COLL")
3059 :
3060 171 : end subroutine ddb_read_nc
3061 : !!***
3062 :
3063 : !----------------------------------------------------------------------
3064 :
3065 : !!****f* m_ddb/ddb_can_merge_blocks
3066 : !! NAME
3067 : !! ddb_can_merge_blocks
3068 : !!
3069 : !! FUNCTION
3070 : !! Return true if iblok1 of ddb1 can be merged to iblok2 of ddb2
3071 : !!
3072 : !! INPUTS
3073 : !! ddb1=ddb object 1
3074 : !! ddb2=ddb object 2
3075 : !! iblok1=block index from ddb1
3076 : !! iblok2=block index from ddb2
3077 : !!
3078 : !! OUTPUT
3079 : !! can_merge=.true. if the blocks are compatible for merging.
3080 : !!
3081 : !! SOURCE
3082 :
3083 784 : logical function ddb_can_merge_blocks(ddb1, ddb2, iblok1, iblok2, ddbvsn) result(can_merge)
3084 :
3085 : !Arguments -------------------------------
3086 : !array
3087 : class(ddb_type),intent(inout) :: ddb1
3088 : type(ddb_type),intent(inout) :: ddb2
3089 : integer,intent(in) :: iblok1
3090 : integer,intent(in) :: iblok2
3091 : integer,intent(in) :: ddbvsn
3092 :
3093 : !local variables
3094 : !scalars
3095 : integer :: nq, ii, blktyp
3096 : integer,parameter :: cvrsio9_new=20240201
3097 : real(dp),parameter :: qtol=2.0d-8
3098 : real(dp) :: diff
3099 : ! ************************************************************************
3100 :
3101 784 : can_merge = .false.
3102 784 : if(ddb1%typ(iblok1)/=ddb2%typ(iblok2)) return
3103 :
3104 674 : blktyp = ddb1%typ(iblok1)
3105 :
3106 674 : can_merge = .true.
3107 :
3108 674 : if (is_type_d0E(blktyp) .or. is_type_d1E(blktyp)) return
3109 :
3110 : ! Compare wavevectors
3111 670 : if (is_type_d2E(blktyp).or.is_type_d2eig(blktyp))then
3112 : nq=1
3113 4 : else if (is_type_d3E(blktyp))then
3114 4 : nq=3
3115 : end if
3116 :
3117 1348 : do ii=1,nq
3118 : diff = (ddb1%qpt(1+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) &
3119 678 : - ddb2%qpt(1+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2))
3120 678 : if (abs(diff) > qtol) can_merge = .false.
3121 : diff = (ddb1%qpt(2+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) &
3122 678 : - ddb2%qpt(2+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2))
3123 678 : if (abs(diff) > qtol) can_merge = .false.
3124 : diff = (ddb1%qpt(3+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) &
3125 678 : - ddb2%qpt(3+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2))
3126 1348 : if (abs(diff) > qtol) can_merge = .false.
3127 : end do
3128 670 : if(ddbvsn >= cvrsio9_new)then
3129 680 : do ii=1,nq
3130 344 : diff=ddb1%omega(ii,iblok1)-ddb2%omega(ii,iblok2)
3131 680 : if (abs(diff) > qtol) can_merge = .false.
3132 : end do
3133 : end if
3134 :
3135 : end function ddb_can_merge_blocks
3136 : !!***
3137 :
3138 : !----------------------------------------------------------------------
3139 :
3140 : !!****f* m_ddb/ddb_merge_blocks
3141 : !! NAME
3142 : !! ddb_merge_blocks
3143 : !!
3144 : !! FUNCTION
3145 : !! Merge block number iblok2 from ddb2 into block number iblok1 in ddb1.
3146 : !!
3147 : !! INPUTS
3148 : !! ddb1=ddb object 1
3149 : !! ddb2=ddb object 2
3150 : !! iblok1=block index from ddb1
3151 : !! iblok2=block index from ddb2
3152 : !!
3153 : !! OUTPUT
3154 : !!
3155 : !! SOURCE
3156 :
3157 284 : subroutine ddb_merge_blocks(ddb1, ddb2, iblok1, iblok2, ddbvsn)
3158 :
3159 : !Arguments -------------------------------
3160 : !array
3161 : class(ddb_type),intent(inout) :: ddb1
3162 : class(ddb_type),intent(inout) :: ddb2
3163 : integer,intent(in) :: iblok1
3164 : integer,intent(in) :: iblok2
3165 : integer,intent(in) :: ddbvsn
3166 :
3167 : !local variables
3168 : !scalars
3169 : integer :: ii, blktyp, mpert1, mpert2
3170 : integer :: idir1, idir2, idir3, ipert1, ipert2, ipert3
3171 : real(dp),parameter :: qtol=2.0d-8
3172 : integer,parameter :: cvrsio9_new=20240201
3173 : !arrays
3174 284 : real(dp), allocatable :: d1matr(:,:,:)
3175 284 : real(dp), allocatable :: d2matr(:,:,:,:,:)
3176 284 : real(dp), allocatable :: d3matr(:,:,:,:,:,:,:)
3177 284 : integer, allocatable :: d1flg(:,:)
3178 284 : integer, allocatable :: d2flg(:,:,:,:)
3179 284 : integer, allocatable :: d3flg(:,:,:,:,:,:)
3180 : ! ************************************************************************
3181 :
3182 : ! Note that ddb and ddb2 may have a different values for mpert
3183 : !mpert = min(ddb1%mpert, ddb2%mpert)
3184 284 : mpert1 = ddb1%mpert
3185 284 : mpert2 = ddb2%mpert
3186 :
3187 : ! Add the blok to the output ddb
3188 284 : blktyp = ddb2%typ(iblok2)
3189 284 : ddb1%typ(iblok1) = blktyp
3190 :
3191 : ! Copy q-point
3192 2840 : do ii=1,9
3193 2840 : ddb1%qpt(ii,iblok1) = ddb2%qpt(ii,iblok2)
3194 : end do
3195 284 : if(ddbvsn >= cvrsio9_new)then
3196 740 : do ii=1,3
3197 740 : ddb1%omega(ii,iblok1) = ddb2%omega(ii,iblok2)
3198 : end do
3199 : else
3200 396 : ddb1%omega(:,iblok1) = 0.d0
3201 : endif
3202 1136 : do ii=1,3
3203 1136 : ddb1%nrm(ii,iblok1) = ddb2%nrm(ii,iblok2)
3204 : end do
3205 :
3206 284 : if (is_type_d0E(blktyp)) then
3207 : ! --------------
3208 : ! Copy d0E block
3209 : ! --------------
3210 7 : if (ddb2%flg(1,iblok2) > 0) then
3211 7 : ddb1%val(1,1,iblok1) = ddb2%val(1,1,iblok2)
3212 7 : ddb1%val(2,1,iblok1) = ddb2%val(2,1,iblok2)
3213 7 : ddb1%flg(1,iblok1) = ddb2%flg(1,iblok2)
3214 : end if
3215 :
3216 277 : else if (is_type_d1E(blktyp)) then
3217 : ! --------------
3218 : ! Copy d1E block
3219 : ! --------------
3220 11 : call ddb2%get_d1matr(iblok2, d1matr, d1flg)
3221 : !call ddb%set_d1matr(iblok, d1matr, d1flg)
3222 11 : ii=0
3223 138 : do ipert1=1,mpert1
3224 519 : do idir1=1,3
3225 381 : ii=ii+1
3226 508 : if (ipert1 <= mpert2) then
3227 348 : if (d1flg(idir1,ipert1)>0) then
3228 114 : ddb1%val(1,ii,iblok1) = d1matr(1,idir1,ipert1)
3229 114 : ddb1%val(2,ii,iblok1) = d1matr(2,idir1,ipert1)
3230 114 : ddb1%flg(ii,iblok1) = d1flg(idir1,ipert1)
3231 : end if
3232 : end if
3233 : end do
3234 : end do
3235 11 : ABI_SFREE(d1matr)
3236 11 : ABI_SFREE(d1flg)
3237 :
3238 266 : else if (is_type_d2E(blktyp)) then
3239 : ! --------------
3240 : ! Copy d2E block
3241 : ! --------------
3242 234 : call ddb2%get_d2matr(iblok2, d2matr, d2flg)
3243 : !call ddb%set_d2matr(iblok, d2matr, d2flg)
3244 234 : ii=0
3245 3448 : do ipert2=1,mpert1
3246 13090 : do idir2=1,3
3247 166096 : do ipert1=1,mpert1
3248 622602 : do idir1=1,3
3249 459720 : ii=ii+1
3250 612960 : if ((ipert1 <= mpert2).and.(ipert2<=mpert2)) then
3251 444168 : if (d2flg(idir1,ipert1,idir2,ipert2)>0) then
3252 16470 : ddb1%val(1,ii,iblok1) = d2matr(1,idir1,ipert1,idir2,ipert2)
3253 16470 : ddb1%val(2,ii,iblok1) = d2matr(2,idir1,ipert1,idir2,ipert2)
3254 16470 : ddb1%flg(ii,iblok1) = d2flg(idir1,ipert1,idir2,ipert2)
3255 : end if
3256 : end if
3257 : end do
3258 : end do
3259 : end do
3260 : end do
3261 234 : ABI_SFREE(d2matr)
3262 234 : ABI_SFREE(d2flg)
3263 :
3264 32 : else if (is_type_d3E(blktyp)) then
3265 : ! --------------
3266 : ! Copy d3E block
3267 : ! --------------
3268 12 : call ddb2%get_d3matr(iblok2, d3matr, d3flg)
3269 : !call ddb%set_d3matr(iblok, d3matr, d3flg)
3270 12 : ii=0
3271 222 : do ipert1=1,mpert1
3272 852 : do idir1=1,3
3273 13116 : do ipert2=1,mpert1
3274 49734 : do idir2=1,3
3275 816930 : do ipert3=1,mpert1
3276 3108132 : do idir3=1,3
3277 :
3278 :
3279 : !ii=ii+1 ! GA: This is not equivalent
3280 : ii = idir1 + 3*((ipert1-1)+mpert1*((idir2-1) &
3281 : + 3*((ipert2-1)+mpert1*((idir3-1) &
3282 2303478 : + 3*(ipert3-1)))))
3283 :
3284 : ! Note that the loop order (1,2,3) is not really consistent
3285 : ! with the d2E case (2, 1)
3286 : ! TODO Clean this up
3287 :
3288 3071304 : if ((ipert1 <= mpert2).and.(ipert2<=mpert2).and.(ipert3<=mpert2)) then
3289 2285901 : if (d3flg(idir1,ipert1,idir2,ipert2,idir3,ipert3)>0) then
3290 1353 : ddb1%flg(ii,iblok1) = d3flg(idir1,ipert1,idir2,ipert2,idir3,ipert3)
3291 4059 : ddb1%val(:,ii,iblok1) = d3matr(:,idir1,ipert1,idir2,ipert2,idir3,ipert3)
3292 : end if
3293 : end if
3294 :
3295 : end do
3296 : end do
3297 : end do
3298 : end do
3299 : end do
3300 : end do
3301 12 : ABI_SFREE(d3matr)
3302 12 : ABI_SFREE(d3flg)
3303 :
3304 : else if (is_type_d2eig(blktyp)) then
3305 : ! ----------------
3306 : ! Skip d2eig block
3307 : ! ----------------
3308 :
3309 : ! TODO need a function ddb_merge_d2eig(filename1, filename2, )
3310 :
3311 : end if ! blktyp
3312 :
3313 284 : end subroutine ddb_merge_blocks
3314 : !!***
3315 :
3316 : !----------------------------------------------------------------------
3317 :
3318 : !!****f* m_ddb/carttransf
3319 : !! NAME
3320 : !! carttransf
3321 : !!
3322 : !! FUNCTION
3323 : !! Transform a second-derivative matrix (EIG2D) from reduced
3324 : !! coordinates to cartesian coordinates.
3325 : !!
3326 : !! INPUTS
3327 : !! blkflg(msize,nblok)=
3328 : !! ( 1 if the element of the dynamical matrix has been calculated ;
3329 : !! 0 otherwise )
3330 : !! gprimd(3,3)=basis vector in the reciprocal space
3331 : !! iqpt = number of the Q-point currently used
3332 : !! mband = maximal number of bands
3333 : !! mpert = maximum number of ipert
3334 : !! msize = size of the EIG2D arrays (3*mpert*3*mpert)
3335 : !! natom = number of atom
3336 : !! nblok = number of bloks in blkflg
3337 : !! nkpt = number of K-points
3338 : !! rprimd(3,3) = basis vector in the real space
3339 : !!
3340 : !! OUTPUT
3341 : !! carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian
3342 : !! EIG2D matrix has been calculated correctly ; 0 otherwise )
3343 : !!
3344 : !! SIDE EFFECT
3345 : !! blkval2(2,msize,mband,nkpt)=Second order eigenvalues (EIG2D)
3346 : !! is transformed from reduced coordinates to cartesian coordinates
3347 : !!
3348 : !! SOURCE
3349 :
3350 28 : subroutine carttransf(blkflg,blkval2,carflg,gprimd,iqpt,mband, mpert,msize,natom,nblok,nkpt,rprimd)
3351 :
3352 : !Arguments -------------------------------
3353 : !scalars
3354 : integer,intent(in) :: mband,msize
3355 : integer,intent(in) :: iqpt
3356 : integer,intent(in) :: mpert,nblok
3357 : integer,intent(inout) :: natom,nkpt
3358 : !arrays
3359 : integer,intent(in) :: blkflg(msize,nblok)
3360 : integer,intent(out) :: carflg(3,mpert,3,mpert)
3361 : real(dp),intent(in) :: gprimd(3,3),rprimd(3,3)
3362 : real(dp),intent(inout) :: blkval2(2,msize,mband,nkpt)
3363 :
3364 : !Local variables-------------------------------
3365 : !scalars
3366 : integer :: iatom1,iatom2,iband,idir1,idir2,ikpt, index
3367 : !arrays
3368 28 : real(dp),allocatable :: blkflgtmp(:,:,:,:,:), blkval2tmp(:,:,:,:,:,:), d2cart(:,:,:,:,:)
3369 : ! *********************************************************************
3370 :
3371 : ! Start by allocating local arrays
3372 140 : ABI_MALLOC(blkflgtmp,(3,mpert,3,mpert,1))
3373 140 : ABI_MALLOC(blkval2tmp,(2,3,mpert,3,mpert,1))
3374 84 : ABI_MALLOC(d2cart,(2,3,mpert,3,mpert))
3375 :
3376 : ! Begin by formating the arrays to be compatible with cart29
3377 : ! Then call cart29 to transform the arrays in cartesian coordinates
3378 : ! Finally reformat the cartesian arrays in old format
3379 276 : do ikpt=1,nkpt
3380 1720 : do iband=1,mband
3381 :
3382 5776 : do idir1=1,3
3383 14728 : do iatom1=1,mpert
3384 40140 : do idir2=1,3
3385 114576 : do iatom2=1,mpert
3386 78768 : index = idir1 + 3*((iatom1 - 1) + natom * ((idir2-1)+3*(iatom2-1)))
3387 78768 : blkflgtmp(idir1,iatom1,idir2,iatom2,1) = blkflg(index,iqpt)
3388 263160 : blkval2tmp(:,idir1,iatom1,idir2,iatom2,1) = blkval2(:,index,iband,ikpt)
3389 : end do
3390 : end do
3391 : end do
3392 : end do
3393 :
3394 : ! The 1sin the argument of cart29 are respectively iblok and nblok. We are doing only one blok.
3395 1444 : call carteig2d(blkflg(:,iqpt),blkval2tmp,carflg,d2cart,gprimd,1,mpert,natom,1,rprimd)
3396 :
3397 6024 : do idir1=1,3
3398 14728 : do iatom1=1,mpert
3399 40140 : do idir2=1,3
3400 114576 : do iatom2=1,mpert
3401 78768 : index = idir1 + 3*((iatom1 - 1) + natom * ((idir2-1)+3*(iatom2-1)))
3402 263160 : blkval2(:,index,iband,ikpt) = d2cart(:,idir1,iatom1,idir2,iatom2)
3403 : end do
3404 : end do
3405 : end do
3406 : end do
3407 :
3408 : end do
3409 : end do
3410 :
3411 28 : ABI_FREE(blkflgtmp)
3412 28 : ABI_FREE(blkval2tmp)
3413 28 : ABI_FREE(d2cart)
3414 :
3415 28 : end subroutine carttransf
3416 : !!***
3417 :
3418 : !----------------------------------------------------------------------
3419 :
3420 : !!****f* m_ddb/carteig2d
3421 : !! NAME
3422 : !! carteig2d
3423 : !!
3424 : !! FUNCTION
3425 : !! Transform a second-derivative matrix (EIG2D) from reduced
3426 : !! coordinates to cartesian coordinates
3427 : !!
3428 : !! INPUTS
3429 : !! blkflg(3,mpert,3,mpert,nblok)=
3430 : !! ( 1 if the element of the dynamical matrix has been calculated ;
3431 : !! 0 otherwise )
3432 : !! blkval(2,3,mpert,3,mpert,nblok)=DDB values
3433 : !! gprimd(3,3)=basis vector in the reciprocal space
3434 : !! iblok=number of the blok that will be transformed
3435 : !! mpert =maximum number of ipert
3436 : !! natom=number of atom
3437 : !! nblok=number of blocks (dimension of blkflg and blkval)
3438 : !! rprimd(3,3)=basis vector in the real space
3439 : !!
3440 : !! OUTPUT
3441 : !! carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian
3442 : !! 2DTE matrix has been calculated correctly ; 0 otherwise )
3443 : !! d2cart(2,3,mpert,3,mpert)=
3444 : !! dynamical matrix, effective charges, dielectric tensor,....
3445 : !! all in cartesian coordinates
3446 : !!
3447 : !! SOURCE
3448 :
3449 1444 : subroutine carteig2d(blkflg,blkval,carflg,d2cart,gprimd,iblok,mpert,natom,nblok,rprimd)
3450 :
3451 : !Arguments -------------------------------
3452 : !scalars
3453 : integer,intent(in) :: iblok,mpert,natom,nblok
3454 : !arrays
3455 : integer,intent(in) :: blkflg(3,mpert,3,mpert,nblok)
3456 : integer,intent(out) :: carflg(3,mpert,3,mpert)
3457 : real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok),gprimd(3,3),rprimd(3,3)
3458 : real(dp),intent(out) :: d2cart(2,3,mpert,3,mpert)
3459 :
3460 : !Local variables -------------------------
3461 : !scalars
3462 : integer :: idir1,idir2,ii,ipert1,ipert2
3463 : !arrays
3464 : integer :: flg1(3),flg2(3)
3465 : real(dp) :: vec1(3),vec2(3)
3466 : ! *********************************************************************
3467 :
3468 : ! First, copy the data blok in place.
3469 275940 : d2cart(:,:,:,:,:)=blkval(:,:,:,:,:,iblok)
3470 :
3471 : ! Cartesian coordinates transformation (in two steps)
3472 : ! First step
3473 4428 : do ipert1=1,mpert
3474 13180 : do ipert2=1,mpert
3475 29240 : do ii=1,2
3476 78768 : do idir1=1,3
3477 210048 : do idir2=1,3
3478 157536 : vec1(idir2)=d2cart(ii,idir1,ipert1,idir2,ipert2)
3479 : ! Note here blkflg
3480 210048 : flg1(idir2)=blkflg(idir1,ipert1,idir2,ipert2,iblok)
3481 : end do
3482 52512 : call cart39(flg1,flg2,gprimd,ipert2,natom,rprimd,vec1,vec2)
3483 227552 : do idir2=1,3
3484 157536 : d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir2)
3485 : ! And here carflg
3486 210048 : carflg(idir1,ipert1,idir2,ipert2)=flg2(idir2)
3487 : end do
3488 : end do
3489 : end do
3490 : end do
3491 : end do
3492 :
3493 : ! Second step
3494 4428 : do ipert1=1,mpert
3495 13180 : do ipert2=1,mpert
3496 29240 : do ii=1,2
3497 78768 : do idir2=1,3
3498 210048 : do idir1=1,3
3499 157536 : vec1(idir1)=d2cart(ii,idir1,ipert1,idir2,ipert2)
3500 : ! Note here carflg
3501 210048 : flg1(idir1)=carflg(idir1,ipert1,idir2,ipert2)
3502 : end do
3503 52512 : call cart39(flg1,flg2,gprimd,ipert1,natom,rprimd,vec1,vec2)
3504 227552 : do idir1=1,3
3505 157536 : d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir1)
3506 : ! And here carflg again
3507 210048 : carflg(idir1,ipert1,idir2,ipert2)=flg2(idir1)
3508 : end do
3509 : end do
3510 : end do
3511 : end do
3512 : end do
3513 :
3514 1444 : end subroutine carteig2d
3515 : !!***
3516 :
3517 : !----------------------------------------------------------------------
3518 :
3519 : !!****f* m_ddb/dtech9
3520 : !!
3521 : !! NAME
3522 : !! dtech9
3523 : !!
3524 : !! FUNCTION
3525 : !! Reads the Dielectric Tensor and the Effective Charges in the
3526 : !! Gamma Block coming from the Derivative Data Base.
3527 : !!
3528 : !! INPUTS
3529 : !! natom= number of atoms in unit cell
3530 : !! iblok= index of the Gamma block
3531 : !! mpert =maximum number of ipert
3532 : !! nblok= number of blocks in the DDB
3533 : !! blkval(2,3*mpert*3*mpert,nblok)= dynamical matrices
3534 : !! In our case, the nblok is restricted to iblok
3535 : !! [unit]=Output unit number
3536 : !!
3537 : !! OUTPUT
3538 : !! zeff(3,3,natom)=effective charge on each atom, versus electric
3539 : !! field and atomic displacement. Note the following convention:
3540 : !! zeff(electric field direction, atomic direction, atom index)
3541 : !! dielt(3,3)=dielectric tensor
3542 : !!
3543 : !! SOURCE
3544 :
3545 256 : subroutine dtech9(blkval,dielt,iblok,mpert,natom,nblok,zeff,unit)
3546 :
3547 : !Arguments -------------------------------
3548 : !scalars
3549 : integer,intent(in) :: iblok,mpert,natom,nblok
3550 : integer,intent(in),optional :: unit
3551 : !arrays
3552 : real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok)
3553 : real(dp),intent(out) :: dielt(3,3),zeff(3,3,natom)
3554 :
3555 : !Local variables -------------------------
3556 : !scalars
3557 : integer :: depl,elec,elec1,elec2,iatom, unt
3558 : character(len=1000) :: msg
3559 : ! *********************************************************************
3560 :
3561 256 : unt = std_out; if (present(unit)) unt = unit
3562 :
3563 : ! Extraction of effectives charges
3564 1090 : do iatom=1,natom
3565 3592 : do elec=1,3
3566 10842 : do depl=1,3
3567 : zeff(elec,depl,iatom)=0.5*&
3568 : (blkval(1,depl,iatom,elec,natom+2,iblok)+&
3569 10008 : blkval(1,elec,natom+2,depl,iatom,iblok))
3570 : end do
3571 : end do
3572 : end do
3573 :
3574 : ! Extraction of dielectric tensor
3575 1024 : do elec1=1,3
3576 3328 : do elec2=1,3
3577 3072 : dielt(elec1,elec2)=blkval(1,elec1,natom+2,elec2,natom+2,iblok)
3578 : end do
3579 : end do
3580 :
3581 256 : write(msg,'(a,3es16.6,3es16.6,3es16.6)' )' Dielectric Tensor ',&
3582 256 : dielt(1,1),dielt(1,2),dielt(1,3),&
3583 256 : dielt(2,1),dielt(2,2),dielt(2,3),&
3584 512 : dielt(3,1),dielt(3,2),dielt(3,3)
3585 256 : call wrtout(unt, msg)
3586 :
3587 256 : call wrtout(unt, ' Effectives Charges ')
3588 1090 : do iatom=1,natom
3589 834 : write(msg,'(a,i4,3es16.6,3es16.6,3es16.6)' )' atom ',iatom,&
3590 834 : zeff(1,1,iatom),zeff(1,2,iatom),zeff(1,3,iatom),&
3591 834 : zeff(2,1,iatom),zeff(2,2,iatom),zeff(2,3,iatom),&
3592 1668 : zeff(3,1,iatom),zeff(3,2,iatom),zeff(3,3,iatom)
3593 1090 : call wrtout(unt, msg)
3594 : end do
3595 :
3596 256 : end subroutine dtech9
3597 : !!***
3598 :
3599 : !----------------------------------------------------------------------
3600 :
3601 : !!****f* m_ddb/dtchi
3602 : !! NAME
3603 : !! dtchi
3604 : !!
3605 : !! FUNCTION
3606 : !! Reads the non-linear optical susceptibility tensor and the
3607 : !! first-order change in the linear dielectric susceptibility
3608 : !! induced by an atomic displacement in the Gamma Block coming from the Derivative Data Base
3609 : !! (third-order derivatives).
3610 : !!
3611 : !! INPUTS
3612 : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies
3613 : !! natom= number of atoms in unit cell
3614 : !! mpert =maximum number of ipert
3615 : !! ramansr= if /= 0, impose sum rule on first-order derivatives
3616 : !! of the electronic susceptibility with respect
3617 : !! to atomic displacements
3618 : !! nlflag= if =3, only the non-linear optical susceptibilities is computed
3619 : !!
3620 : !! OUTPUT
3621 : !! dchide(3,3,3) = non-linear optical coefficients
3622 : !! dchidt(natom,3,3,3) = first-order change of the electronic dielectric
3623 : !! tensor induced by an individual atomic displacement
3624 : !!
3625 : !! SOURCE
3626 :
3627 4 : subroutine dtchi(blkval,dchide,dchidt,mpert,natom,ramansr,nlflag)
3628 :
3629 : !Arguments -------------------------------
3630 : !scalars
3631 : integer,intent(in) :: mpert,natom,ramansr,nlflag
3632 : !arrays
3633 : real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
3634 : real(dp),intent(out) :: dchide(3,3,3),dchidt(natom,3,3,3)
3635 :
3636 : !Local variables -------------------------
3637 : !scalars
3638 : integer :: depl,elfd1,elfd2,elfd3,iatom,ivoigt
3639 : logical :: iwrite
3640 : real(dp) :: wttot
3641 : !arrays
3642 : integer :: voigtindex(6,2)
3643 8 : real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert),dvoigt(3,6),sumrule(3,3,3)
3644 8 : real(dp) :: wghtat(natom)
3645 : ! *********************************************************************
3646 :
3647 497068 : d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
3648 497068 : d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
3649 :
3650 : ! Extraction of non-linear optical coefficients
3651 16 : do elfd1 = 1,3
3652 52 : do elfd2 = 1,3
3653 156 : do elfd3 = 1,3
3654 144 : dchide(elfd1,elfd2,elfd3) = d3cart(1,elfd1,natom+2,elfd2,natom+2,elfd3,natom+2)
3655 : end do
3656 : end do
3657 : end do
3658 :
3659 : ! Transform to Voigt notations
3660 28 : voigtindex(:,1) = (/1,2,3,2,1,1/)
3661 28 : voigtindex(:,2) = (/1,2,3,3,3,2/)
3662 28 : do ivoigt = 1, 6
3663 24 : elfd2 = voigtindex(ivoigt,1)
3664 24 : elfd3 = voigtindex(ivoigt,2)
3665 100 : do elfd1 = 1, 3
3666 96 : dvoigt(elfd1,ivoigt) = 0.5_dp*(dchide(elfd1,elfd2,elfd3) + dchide(elfd1,elfd3,elfd2))
3667 : end do
3668 : end do
3669 :
3670 : ! Transform to pm/V
3671 100 : dvoigt(:,:) = dvoigt(:,:)*16*(pi**2)*(Bohr_Ang**2)*1.0d-8*eps0/e_Cb
3672 :
3673 : ! Extraction of $\frac{d \chi}{d \tau}$
3674 4 : if (nlflag < 3) then
3675 9 : do iatom = 1, natom
3676 27 : do depl = 1,3
3677 78 : do elfd1 = 1,3
3678 234 : do elfd2 = 1,3
3679 216 : dchidt(iatom,depl,elfd1,elfd2) = d3cart(1,depl,iatom,elfd1,natom+2,elfd2,natom+2)
3680 : end do
3681 : end do
3682 : end do
3683 : end do
3684 : end if
3685 :
3686 12 : wghtat(:) = zero
3687 4 : if (ramansr == 1) then
3688 9 : wghtat(:) = one/dble(natom)
3689 :
3690 1 : else if (ramansr == 2) then
3691 :
3692 0 : wttot = zero
3693 0 : do iatom = 1, natom
3694 0 : do depl = 1,3
3695 0 : do elfd1 = 1,3
3696 0 : do elfd2 = 1,3
3697 0 : wghtat(iatom) = wghtat(iatom) + abs(dchidt(iatom,depl,elfd1,elfd2))
3698 : end do
3699 : end do
3700 : end do
3701 0 : wttot = wttot + wghtat(iatom)
3702 : end do
3703 :
3704 0 : wghtat(:) = wghtat(:)/wttot
3705 : end if
3706 :
3707 4 : iwrite = ab_out > 0
3708 :
3709 4 : if (iwrite) then
3710 4 : write(ab_out,*)ch10
3711 4 : write(ab_out,*)'Non-linear optical coefficients d (pm/V)'
3712 4 : write(ab_out,'(6f12.6)')dvoigt(1,:)
3713 4 : write(ab_out,'(6f12.6)')dvoigt(2,:)
3714 4 : write(ab_out,'(6f12.6)')dvoigt(3,:)
3715 : end if
3716 :
3717 4 : if (ramansr /= 0) then
3718 3 : if (iwrite) then
3719 3 : write(ab_out,*)ch10
3720 3 : write(ab_out,*)'The violation of the Raman sum rule'
3721 3 : write(ab_out,*)'by the first-order electronic dielectric tensors ','is as follows'
3722 3 : write(ab_out,*)' atom'
3723 3 : write(ab_out,*)' displacement'
3724 : end if
3725 :
3726 3 : sumrule(:,:,:) = zero
3727 12 : do elfd2 = 1,3
3728 39 : do elfd1 = 1,3
3729 117 : do depl = 1,3
3730 243 : do iatom = 1, natom
3731 243 : sumrule(depl,elfd1,elfd2) = sumrule(depl,elfd1,elfd2) + dchidt(iatom,depl,elfd1,elfd2)
3732 : end do
3733 270 : do iatom = 1, natom
3734 243 : dchidt(iatom,depl,elfd1,elfd2) = dchidt(iatom,depl,elfd1,elfd2) - wghtat(iatom)*sumrule(depl,elfd1,elfd2)
3735 : end do
3736 : end do
3737 : end do
3738 : end do
3739 :
3740 3 : if (iwrite) then
3741 12 : do depl = 1,3
3742 9 : write(ab_out,'(6x,i2,3(3x,f16.9))') depl,sumrule(depl,1,1:3)
3743 9 : write(ab_out,'(8x,3(3x,f16.9))') sumrule(depl,2,1:3)
3744 9 : write(ab_out,'(8x,3(3x,f16.9))') sumrule(depl,3,1:3)
3745 12 : write(ab_out,*)
3746 : end do
3747 : end if
3748 : end if ! ramansr
3749 :
3750 4 : if (nlflag < 3) then
3751 3 : if (iwrite) then
3752 3 : write(ab_out,*)ch10
3753 3 : write(ab_out,*)' First-order change in the electronic dielectric '
3754 3 : write(ab_out,*)' susceptibility tensor (Bohr^-1)'
3755 3 : write(ab_out,*)' induced by an atomic displacement'
3756 3 : if (ramansr /= 0) then
3757 3 : write(ab_out,*)' (after imposing the sum over all atoms to vanish)'
3758 : end if
3759 3 : write(ab_out,*)' atom displacement'
3760 :
3761 9 : do iatom = 1,natom
3762 24 : do depl = 1,3
3763 18 : write(ab_out,'(1x,i4,9x,i2,3(3x,f16.9))')iatom,depl,dchidt(iatom,depl,1,:)
3764 18 : write(ab_out,'(16x,3(3x,f16.9))')dchidt(iatom,depl,2,:)
3765 24 : write(ab_out,'(16x,3(3x,f16.9))')dchidt(iatom,depl,3,:)
3766 : end do
3767 :
3768 9 : write(ab_out,*)
3769 : end do
3770 : end if
3771 : end if
3772 :
3773 4 : end subroutine dtchi
3774 : !!***
3775 :
3776 : !----------------------------------------------------------------------
3777 :
3778 : !!****f* m_ddb/ddb_get_etotal
3779 : !!
3780 : !! NAME
3781 : !! ddb_get_etotal
3782 : !!
3783 : !! FUNCTION
3784 : !! Read the GS total energy from the DDB file.
3785 : !!
3786 : !! INPUTS
3787 : !! ddb<type(ddb_type)>=Derivative database.
3788 : !!
3789 : !! OUTPUT
3790 : !! etotal=GS Total energy in Hartree
3791 : !! iblok=Index of the block in the DDB file. 0 if not found.
3792 : !!
3793 : !! SOURCE
3794 :
3795 32 : integer function ddb_get_etotal(ddb, etotal) result(iblok)
3796 :
3797 : !Arguments -------------------------------
3798 : !scalars
3799 : class(ddb_type),intent(in) :: ddb
3800 : real(dp),intent(out) :: etotal
3801 :
3802 : !Local variables -------------------------
3803 : !scalars
3804 : integer :: rftyp
3805 : !arrays
3806 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
3807 : real(dp) :: qphnrm(3),qphon(3,3)
3808 : ! *********************************************************************
3809 :
3810 : ! Extract the block with the total energy
3811 32 : qphon(:,:) = zero
3812 32 : qphnrm(:) = zero
3813 32 : rfphon(:) = 0
3814 32 : rfelfd(:) = 0
3815 32 : rfstrs(:) = 0
3816 32 : rftyp = BLKTYP_d0E_xx
3817 :
3818 32 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
3819 :
3820 32 : if (iblok /= 0) then
3821 15 : etotal = ddb%val(1,1,iblok)
3822 : else
3823 17 : etotal = huge(one)
3824 : end if
3825 :
3826 32 : end function ddb_get_etotal
3827 : !!***
3828 :
3829 : !----------------------------------------------------------------------
3830 :
3831 : !!****f* m_ddb/ddb_get_dielt_zeff
3832 : !!
3833 : !! NAME
3834 : !! ddb_get_dielt_zeff
3835 : !!
3836 : !! FUNCTION
3837 : !! Reads the Dielectric Tensor and the Effective Charges from the DDB file
3838 : !! Impose the charge neutrality on the effective charges and eventually select some parts of the effective charges
3839 : !!
3840 : !! INPUTS
3841 : !! Crystal<type(crystal_t)>=Crystal structure parameters
3842 : !! rftyp = 1 if non-stationary block
3843 : !! 2 if stationary block
3844 : !! 3 if third order derivatives
3845 : !! chneut=(0 => no ASR, 1 => equal repartition,2 => weighted repartition )
3846 : !! selectz=selection of some parts of the effective charge tensor attached to one atom.
3847 : !! (0=> no selection, 1=> trace only, 2=> symmetric part only)
3848 : !!
3849 : !! SIDE EFFECTS
3850 : !! ddb<type(ddb_type)>=
3851 : !! The block with the effective charges is modified if charge neutrality is imposed.
3852 : !!
3853 : !! OUTPUT
3854 : !! iblok=Index of the block containing the data. 0 if block is not found.
3855 : !! dielt(3,3) = Macroscopic dielectric tensor
3856 : !! zeff(3,3,natom)=effective charge on each atom, versus electric field and atomic displacement
3857 : !! [zeff_raw(3,3,natom)]=effective charge on each atom before enforcing charge-neutrality.
3858 : !!
3859 : !! NOTES
3860 : !! dielt and zeff are initialized to one_3D and zero if the derivatives are not available in the DDB file.
3861 : !!
3862 : !! SOURCE
3863 :
3864 219 : integer function ddb_get_dielt_zeff(ddb, crystal, rftyp, chneut, selectz, dielt, zeff, zeff_raw) result(iblok)
3865 :
3866 : !Arguments -------------------------------
3867 : !scalars
3868 : class(ddb_type),intent(inout) :: ddb
3869 : integer,intent(in) :: rftyp,chneut,selectz
3870 : type(crystal_t),intent(in) :: crystal
3871 : !arrays
3872 : real(dp),intent(out) :: dielt(3,3),zeff(3,3,crystal%natom)
3873 : real(dp),optional,intent(out) :: zeff_raw(3,3,crystal%natom)
3874 :
3875 : !Local variables -------------------------
3876 : !scalars
3877 : integer :: ii, units(2)
3878 : character(len=500) :: msg
3879 : !arrays
3880 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
3881 438 : real(dp) :: qphnrm(3),qphon(3,3), my_zeff_raw(3,3,crystal%natom)
3882 : ! *********************************************************************
3883 :
3884 657 : units = [std_out, ab_out]
3885 :
3886 : ! Look for the Gamma Block in the DDB
3887 876 : qphon(:,1)=zero
3888 219 : qphnrm(1)=zero
3889 : !rfphon(1:2)=1
3890 : !rfelfd(1:2)=2
3891 : ! For effective charges: perturbation 1 = phonons, perturbation 2 = electric field
3892 219 : rfphon(1)=1; rfphon(2)=0
3893 219 : rfelfd(1)=0; rfelfd(2)=2
3894 657 : rfstrs(1:2)=0
3895 :
3896 : !write(std_out,*)"ddb%mpert",ddb%mpert
3897 219 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp)
3898 :
3899 : ! Compute effective charges and dielectric tensor only if the Gamma-blok was found in the DDB
3900 : ! In case it was not found, iblok = 0
3901 8188 : zeff=zero; dielt=zero; dielt(1,1)=one; dielt(2,2)=one; dielt(3,3)=one
3902 8188 : my_zeff_raw = zero
3903 :
3904 219 : if (iblok /= 0) then
3905 10496 : write(msg, '(2a,(80a),4a)' ) ch10,('=',ii=1,80),ch10,ch10,&
3906 10624 : ' Dielectric Tensor and Effective Charges ',ch10
3907 128 : call wrtout(units, msg)
3908 :
3909 : ! Make the imaginary part of the Gamma block vanish
3910 128 : write(msg, '(5a)' ) ch10,&
3911 128 : ' anaddb : Zero the imaginary part of the Dynamical Matrix at Gamma,',ch10,&
3912 256 : ' and impose the ASR on the effective charges ',ch10
3913 128 : call wrtout(units, msg)
3914 :
3915 : ! Extrac Zeff before enforcing sum rule.
3916 128 : call dtech9(ddb%val, dielt, iblok, ddb%mpert, ddb%natom, ddb%nblok, my_zeff_raw, unit=dev_null)
3917 :
3918 : ! Impose the charge neutrality on the effective charges and eventually select some parts of the effective charges
3919 128 : call chneu9(chneut,ddb%val(:,:,iblok),ddb%mpert,ddb%natom,ddb%ntypat,selectz,Crystal%typat,Crystal%zion)
3920 :
3921 : ! Extraction of the dielectric tensor and the effective charges
3922 128 : call dtech9(ddb%val, dielt, iblok, ddb%mpert, ddb%natom, ddb%nblok, zeff)
3923 : end if ! iblok not found
3924 :
3925 3058 : if (present(zeff_raw)) zeff_raw = my_zeff_raw
3926 :
3927 219 : end function ddb_get_dielt_zeff
3928 : !!***
3929 :
3930 : !----------------------------------------------------------------------
3931 :
3932 : !!****f* m_ddb/ddb_get_dielt
3933 : !!
3934 : !! NAME
3935 : !! ddb_get_dielt
3936 : !!
3937 : !! FUNCTION
3938 : !! Reads the electronic dielectric tensor from the DDB file
3939 : !!
3940 : !! INPUTS
3941 : !! ddb<type(ddb_type)>=Derivative database.
3942 : !! rftyp = 1 if non-stationary block
3943 : !! 2 if stationary block
3944 : !! 3 if third order derivatives
3945 : !!
3946 : !! OUTPUT
3947 : !! dielt(3,3) = Macroscopic dielectric tensor (electronic contribution)
3948 : !! iblok=Index of the block containing the data. 0 if block is not found.
3949 : !!
3950 : !! NOTES
3951 : !! dielt is initialized to one_3D if the derivatives are not available in the DDB file.
3952 : !!
3953 : !! SOURCE
3954 :
3955 141 : integer function ddb_get_dielt(ddb, rftyp, dielt) result(iblok)
3956 :
3957 : !Arguments -------------------------------
3958 : !scalars
3959 : integer,intent(in) :: rftyp
3960 : class(ddb_type),intent(in) :: ddb
3961 : !arrays
3962 : real(dp),intent(out) :: dielt(3,3)
3963 :
3964 : !Local variables -------------------------
3965 : !scalars
3966 : integer :: mpert
3967 : character(len=1000) :: msg
3968 : !arrays
3969 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
3970 : real(dp) :: qphnrm(3),qphon(3,3)
3971 141 : real(dp),allocatable :: tmpval(:,:,:,:)
3972 : ! *********************************************************************
3973 :
3974 : ! Look for the Gamma Block in the DDB
3975 564 : qphon(:,1)=zero
3976 141 : qphnrm(1)=zero
3977 423 : rfphon(1:2)=0
3978 423 : rfelfd(1:2)=2
3979 423 : rfstrs(1:2)=0
3980 :
3981 141 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
3982 :
3983 : ! Read the dielectric tensor only if the Gamma-block was found in the DDB
3984 : ! In case it was not found, iblok = 0
3985 141 : dielt=zero; dielt(1,1)=one; dielt(2,2)=one; dielt(3,3)=one
3986 :
3987 141 : if (iblok/=0) then
3988 : !Extration of dielectric tensor
3989 60 : mpert = ddb%mpert
3990 :
3991 300 : ABI_MALLOC(tmpval,(3,mpert,3,mpert))
3992 300 : tmpval(:,:,:,:) = reshape(ddb%val(1,:,iblok), shape = (/3,mpert,3,mpert/))
3993 780 : dielt=tmpval(1:3,ddb%natom+2,1:3,ddb%natom+2)
3994 :
3995 : write(msg,'(a,3es16.6,3es16.6,3es16.6)' )&
3996 60 : ' Dielectric Tensor ',&
3997 60 : dielt(1,1),dielt(1,2),dielt(1,3),&
3998 60 : dielt(2,1),dielt(2,2),dielt(2,3),&
3999 120 : dielt(3,1),dielt(3,2),dielt(3,3)
4000 :
4001 60 : call wrtout(std_out,msg)
4002 :
4003 60 : ABI_FREE(tmpval)
4004 : end if ! iblok not found
4005 :
4006 141 : end function ddb_get_dielt
4007 : !!***
4008 :
4009 : !----------------------------------------------------------------------
4010 :
4011 : !!****f* m_ddb/ddb_get_quadrupoles
4012 : !!
4013 : !! NAME
4014 : !! ddb_get_quadrupoles
4015 : !!
4016 : !! FUNCTION
4017 : !! Reads the Dynamic Quadrupoles or the P^(1) tensor from the DDB file
4018 : !!
4019 : !! INPUTS
4020 : !! ddb<type(ddb_type)>=Derivative database.
4021 : !! ddb_version = 6 digit integer giving date. To mantain compatibility with old DDB files.
4022 : !! lwsym = 0 do not symmetrize the tensor wrt efield and qvec derivative
4023 : !! |-> 1st gradient of polarization response to atomic displacement
4024 : !! = 1 symmetrize the tensor wrt efield and qvec derivative
4025 : !! |-> dynamic quadrupoles
4026 : !! rftyp = 1 if non-stationary block
4027 : !! 2 if stationary block
4028 : !! 3 if third order derivatives
4029 : !! 33 if long wave third order derivatives
4030 : !!
4031 : !! OUTPUT
4032 : !! quadrupoles(3,3,3,natom) = Dynamic Quadrupole tensor
4033 : !! iblok=Index of the block containing the data. 0 if block is not found.
4034 : !!
4035 : !! NOTES
4036 : !! quadrupoles is initialized to zero if the derivatives are not available in the DDB file.
4037 : !!
4038 : !! SOURCE
4039 :
4040 22 : integer function ddb_get_quadrupoles(ddb, ddb_version, lwsym, rftyp, quadrupoles) result(iblok)
4041 :
4042 : !Arguments -------------------------------
4043 : !scalars
4044 : integer,intent(in) :: ddb_version,lwsym,rftyp
4045 : class(ddb_type),intent(in) :: ddb
4046 : !arrays
4047 : real(dp),intent(out) :: quadrupoles(3,3,3,ddb%natom)
4048 :
4049 : !Local variables -------------------------
4050 : !scalars
4051 : character(len=500) :: msg
4052 : !arrays
4053 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4054 : integer :: rfqvec(4)
4055 : real(dp) :: qphnrm(3),qphon(3,3)
4056 : ! *********************************************************************
4057 :
4058 : ! Look for the Gamma Block in the DDB
4059 11 : qphon(:,:)=zero
4060 44 : qphnrm(:)=one
4061 11 : rfphon(:)=0
4062 11 : rfelfd(:)=0
4063 11 : rfqvec(:)=0
4064 11 : rfstrs(:)=0
4065 11 : rfelfd(1)=2
4066 11 : rfphon(2)=1
4067 11 : rfqvec(3)=1
4068 :
4069 11 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp,rfqvec=rfqvec)
4070 :
4071 : ! Compute the quadrupole tensor only if the Gamma-block was found in the DDB
4072 : ! In case it was not found, iblok = 0
4073 1451 : quadrupoles=zero
4074 :
4075 11 : if (iblok /= 0) then
4076 9 : write(msg,'(2a)') ch10, ' Extract quadrupoles or P^(1) coefficients from 3DTE'
4077 9 : call wrtout(std_out, msg)
4078 :
4079 9 : if (lwsym==1) then
4080 7 : write(msg, '(3a)' ) ch10, ' Dynamical Quadrupoles Tensor (units: e Bohr)',ch10
4081 2 : else if (lwsym==0) then
4082 2 : write(msg, '(3a)' ) ch10, &
4083 4 : ' First moment of Polarization induced by atomic displacement (1/ucvol factor not included) (units: e Bohr) ',ch10
4084 : endif
4085 27 : call wrtout([std_out, ab_out], msg)
4086 :
4087 9 : call dtqdrp(ddb%val(:,:,iblok),ddb_version,lwsym,ddb%mpert,ddb%natom,quadrupoles)
4088 : end if
4089 :
4090 11 : end function ddb_get_quadrupoles
4091 : !!***
4092 :
4093 : !----------------------------------------------------------------------
4094 :
4095 : !!****f* m_ddb/ddb_get_dchidet
4096 : !!
4097 : !! NAME
4098 : !! ddb_get_dchidet
4099 : !!
4100 : !! FUNCTION
4101 : !! Reads the non-linear optical susceptibility tensor and the
4102 : !! first-order change in the linear dielectric susceptibility
4103 : !!
4104 : !! INPUTS
4105 : !! ddb<type(ddb_type)>=Derivative Database.
4106 : !! ramansr= if /= 0, impose sum rule on first-order derivatives
4107 : !! of the electronic susceptibility with respect
4108 : !! to atomic displacements
4109 : !! nlflag= if =3, only the non-linear optical susceptibilities is computed
4110 : !!
4111 : !! OUTPUT
4112 : !! dchide(3,3,3) = non-linear optical coefficients
4113 : !! dchidt(natom,3,3,3) = first-order change of the electronic dielectric
4114 : !! tensor induced by an individual atomic displacement
4115 : !! iblok=Index of the block containing the data. 0 if block is not found.
4116 : !! The caller should check the returned value.
4117 : !!
4118 : !! SOURCE
4119 :
4120 8 : integer function ddb_get_dchidet(ddb, ramansr, nlflag, dchide, dchidt) result(iblok)
4121 :
4122 : !Arguments -------------------------------
4123 : !scalars
4124 : integer,intent(in) :: ramansr, nlflag
4125 : class(ddb_type),intent(in) :: ddb
4126 : !arrays
4127 : real(dp),intent(out) :: dchide(3,3,3),dchidt(ddb%natom,3,3,3)
4128 :
4129 : !Local variables -------------------------
4130 : !scalars
4131 : integer :: rftyp
4132 : !arrays
4133 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4134 : real(dp) :: qphnrm(3),qphon(3,3)
4135 : ! *********************************************************************
4136 :
4137 4 : qphon(:,:) = zero
4138 16 : qphnrm(:) = one
4139 : ! rfphon(1) = 1 ; rfphon(2:3) = 0
4140 20 : rfelfd(:) = 2
4141 4 : rfstrs(:) = 0
4142 4 : rftyp = BLKTYP_d3E_xx
4143 :
4144 4 : if (nlflag < 3) then
4145 9 : rfphon(1) = 1 ; rfphon(2:3) = 0
4146 : else
4147 3 : rfphon(1) = 0 ; rfphon(2:3) = 0
4148 : end if
4149 :
4150 4 : call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
4151 :
4152 4 : if (iblok /= 0) then
4153 4 : call dtchi(ddb%val(:,:,iblok),dchide,dchidt,ddb%mpert,ddb%natom,ramansr,nlflag)
4154 : else
4155 : ! Let the caller handle the error.
4156 0 : dchide = huge(one); dchidt = huge(one)
4157 : end if
4158 :
4159 4 : end function ddb_get_dchidet
4160 : !!***
4161 :
4162 : !----------------------------------------------------------------------
4163 :
4164 : !!****f* m_ddb/ddb_get_pel
4165 : !!
4166 : !! NAME
4167 : !! ddb_get_pel
4168 : !!
4169 : !! FUNCTION
4170 : !! Get the electronic polarizability vector from the database.
4171 : !!
4172 : !! INPUTS
4173 : !! ddb<type(ddb_type)>=Derivative database.
4174 : !! relaxat
4175 : !! 0 => without relaxation of the atoms
4176 : !! 1 => with relaxation of the atoms
4177 : !! relaxstr
4178 : !! 0 => without relaxed lattice constants
4179 : !! 1 => with relaxed lattice constants at constrained polarization
4180 : !!
4181 : !! OUTPUT
4182 : !! pel(3) = Macroscopic polarizability vector (electronic contribution)
4183 : !! iblok=Index of the block containing the data. 0 if block is not found.
4184 : !!
4185 : !! NOTES
4186 : !!
4187 : !! SOURCE
4188 :
4189 3 : integer function ddb_get_pel(ddb, pel, relaxat, relaxstr) result(iblok)
4190 :
4191 : !Arguments -------------------------------
4192 : !scalars
4193 : class(ddb_type),intent(in) :: ddb
4194 : integer, intent(in) :: relaxat
4195 : integer, intent(in) :: relaxstr
4196 : !arrays
4197 : real(dp),intent(out) :: pel(3)
4198 :
4199 : !Local variables -------------------------
4200 : !scalars
4201 : integer :: natom
4202 : !arrays
4203 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4204 : real(dp) :: qphnrm(3),qphon(3,3)
4205 : ! *********************************************************************
4206 :
4207 3 : natom = ddb%natom
4208 :
4209 3 : qphon(:,:) = zero; qphnrm(:) = zero
4210 15 : rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2
4211 13 : if (relaxat == 1) rfphon(:) = 1
4212 13 : if (relaxstr == 1) rfstrs(:) = 3
4213 :
4214 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx)
4215 :
4216 3 : if (iblok/=0) then
4217 12 : pel(1:3) = ddb%val(1, 3*natom+4:3*natom+6, iblok)
4218 : end if
4219 :
4220 3 : end function ddb_get_pel
4221 : !!***
4222 :
4223 : !----------------------------------------------------------------------
4224 :
4225 : !!****f* m_ddb/ddb_get_gred
4226 : !!
4227 : !! NAME
4228 : !! ddb_get_gred
4229 : !!
4230 : !! FUNCTION
4231 : !! Get the forces in reduced coordinates (Hartree).
4232 : !!
4233 : !! INPUTS
4234 : !! ddb<type(ddb_type)>=Derivative database.
4235 : !! relaxat
4236 : !! 0 => without relaxation of the atoms
4237 : !! 1 => with relaxation of the atoms
4238 : !! relaxstr
4239 : !! 0 => without relaxed lattice constants
4240 : !! 1 => with relaxed lattice constants at constrained polarization
4241 : !!
4242 : !! OUTPUT
4243 : !! gred(3,natom)=the gradient of the total energy with respect
4244 : !! to change of reduced coordinates
4245 : !! iblok=Index of the block containing the data. 0 if block is not found.
4246 : !!
4247 : !! NOTES
4248 : !!
4249 : !! SOURCE
4250 :
4251 3 : integer function ddb_get_gred(ddb, gred, relaxat, relaxstr) result(iblok)
4252 :
4253 : !Arguments -------------------------------
4254 : !scalars
4255 : class(ddb_type),intent(in) :: ddb
4256 : integer, intent(in) :: relaxat
4257 : integer, intent(in) :: relaxstr
4258 : !arrays
4259 : real(dp),intent(out),allocatable :: gred(:,:)
4260 :
4261 : !Local variables -------------------------
4262 : !scalars
4263 : integer :: natom
4264 : integer :: idir, iatom, index
4265 : !arrays
4266 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4267 : real(dp) :: qphnrm(3),qphon(3,3)
4268 : ! *********************************************************************
4269 :
4270 3 : natom = ddb%natom
4271 :
4272 9 : ABI_MALLOC(gred, (3, natom))
4273 :
4274 3 : qphon(:,:) = zero; qphnrm(:) = zero
4275 15 : rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2
4276 13 : if (relaxat == 1) rfphon(:) = 1
4277 13 : if (relaxstr == 1) rfstrs(:) = 3
4278 :
4279 : ! GA: I dont see why relaxstr is relevant as an input
4280 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx)
4281 :
4282 3 : if (iblok/=0) then
4283 3 : if (relaxat == 1) then
4284 : index = 0
4285 9 : do iatom = 1, natom
4286 30 : do idir = 1, 3
4287 21 : index = index+1
4288 28 : gred(idir, iatom) = ddb%val(1, index, iblok)
4289 : end do
4290 : end do
4291 : end if
4292 : end if
4293 :
4294 3 : end function ddb_get_gred
4295 : !!***
4296 :
4297 : !----------------------------------------------------------------------
4298 :
4299 : !!****f* m_ddb/ddb_get_strten
4300 : !!
4301 : !! NAME
4302 : !! ddb_get_strten
4303 : !!
4304 : !! FUNCTION
4305 : !! Get the stress tensor.
4306 : !!
4307 : !! INPUTS
4308 : !! ddb<type(ddb_type)>=Derivative database.
4309 : !! relaxat
4310 : !! 0 => without relaxation of the atoms
4311 : !! 1 => with relaxation of the atoms
4312 : !! relaxstr
4313 : !! 0 => without relaxed lattice constants
4314 : !! 1 => with relaxed lattice constants at constrained polarization
4315 : !!
4316 : !! OUTPUT
4317 : !! strten(6)=the stress tensor in cartesian coordinates.
4318 : !! iblok=Index of the block containing the data. 0 if block is not found.
4319 : !!
4320 : !! NOTES
4321 : !!
4322 : !! SOURCE
4323 :
4324 3 : integer function ddb_get_strten(ddb, strten, relaxat, relaxstr) result(iblok)
4325 :
4326 : !Arguments -------------------------------
4327 : !scalars
4328 : class(ddb_type),intent(in) :: ddb
4329 : integer, intent(in) :: relaxat
4330 : integer, intent(in) :: relaxstr
4331 : !arrays
4332 : real(dp),intent(out) :: strten(6)
4333 :
4334 : !Local variables -------------------------
4335 : !scalars
4336 : integer :: natom
4337 : integer :: ii, index
4338 : !arrays
4339 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4340 : real(dp) :: qphnrm(3),qphon(3,3)
4341 : ! *********************************************************************
4342 :
4343 3 : natom = ddb%natom
4344 :
4345 3 : qphon(:,:) = zero; qphnrm(:) = zero
4346 15 : rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2
4347 13 : if (relaxat == 1) rfphon(:) = 1
4348 13 : if (relaxstr == 1) rfstrs(:) = 3
4349 :
4350 : ! GA: I dont see why relaxstr is relevant as an input
4351 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx)
4352 :
4353 3 : if (iblok/=0) then
4354 3 : if (relaxstr == 1) then
4355 2 : index = 3*natom+6
4356 14 : do ii = 1, 6
4357 12 : index = index+1
4358 14 : strten(ii) = ddb%val(1, index, iblok)
4359 : end do
4360 : end if
4361 : end if
4362 :
4363 3 : end function ddb_get_strten
4364 : !!***
4365 :
4366 : !----------------------------------------------------------------------
4367 :
4368 : !!****f* m_ddb/asrq0_init
4369 : !! NAME
4370 : !! asrq0_init
4371 : !!
4372 : !! FUNCTION
4373 : !! Initialize an asrq0 object for the imposition
4374 : !! of the accoustic sum rule (ASR) at q=0.
4375 : !! In case the interatomic forces are not calculated, the
4376 : !! ASR-correction has to be determined here from the Dynamical matrix at Gamma.
4377 : !! In case the DDB does not contain this information, the subroutine returns iblok=0
4378 : !! %d2asr is initialized and set to zero to preserve the old behaviour.
4379 : !!
4380 : !! INPUTS
4381 : !! asr=Input variable selecting the method for the ASR
4382 : !! rftyp = 1 if non-stationary block
4383 : !! 2 if stationary block
4384 : !! 3 if third order derivatives
4385 : !! Crystal<type(crystal_t)>=Crystal structure parameter
4386 : !! sys_dim=System dimensionality (0D, 1D, ...) used for rotational invariance
4387 : !! dcdq = derivative of interatomic force constants at the zone center
4388 : !! dcdqdq = second derivative of interatomic force constants at the zone center
4389 : !!
4390 : !! SIDE EFFECTS
4391 : !! ddb<type(ddb_type)>= Database with the derivates. The routine does not change it
4392 : !! except when asr is in [3,4]. TODO This should not happen.
4393 : !!
4394 : !! OUTPUT
4395 : !! asrq0<asrq0_t>
4396 : !! iblok= is set to 0 if the Gamma block is not found
4397 : !!
4398 : !! SOURCE
4399 :
4400 110 : subroutine asrq0_init(asrq0, ddb, asr, rftyp, crystal, sys_dim, dcdq, dcdqdq)
4401 :
4402 : !Arguments -------------------------------
4403 : !scalars
4404 : integer,intent(in) :: asr,sys_dim,rftyp
4405 : class(ddb_type),intent(inout) :: ddb
4406 : type(crystal_t),intent(in) :: crystal
4407 : class(asrq0_t), intent(out) :: asrq0
4408 : !arrays
4409 : real(dp), optional, intent(in) :: dcdq(3,crystal%natom,3,crystal%natom,3)
4410 : real(dp), optional, intent(in) :: dcdqdq(3,crystal%natom,3,3,3)
4411 : !Local variables-------------------------------
4412 : !scalars
4413 : integer :: dims,iblok
4414 : !character(len=500) :: msg
4415 : !arrays
4416 : integer :: rfelfd(4),rfphon(4),rfstrs(4)
4417 : real(dp) :: qphnrm(3),qphon(3,3)
4418 110 : real(dp),allocatable :: d2asr_res(:,:,:,:,:),d2cart(:,:)
4419 : ! ************************************************************************
4420 :
4421 110 : asrq0%asr = asr; asrq0%natom = ddb%natom
4422 : ! Find the Gamma block in the DDB (no need for E-field entries)
4423 440 : qphon(:,1)=zero
4424 110 : qphnrm(1)=zero
4425 330 : rfphon(1:2)=1
4426 110 : rfelfd(:)=0
4427 110 : rfstrs(:)=0
4428 :
4429 110 : call ddb%get_block(asrq0%iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp)
4430 : ! this is to maintain the old behaviour in which the arrays where allocated and set to zero in anaddb.
4431 550 : ABI_MALLOC(asrq0%d2asr, (2,3,ddb%natom,3,ddb%natom))
4432 660 : ABI_MALLOC(asrq0%d2dqmsr, (3,ddb%natom,3,ddb%natom,3))
4433 770 : ABI_MALLOC(asrq0%d2dqdqmsr, (3,ddb%natom,3,ddb%natom,3,3))
4434 72078 : asrq0%d2asr = zero
4435 89768 : asrq0%d2dqmsr = zero
4436 269414 : asrq0%d2dqdqmsr = zero
4437 :
4438 110 : if (asrq0%iblok == 0) return
4439 108 : iblok = asrq0%iblok
4440 :
4441 108 : select case (asrq0%asr)
4442 : case (0)
4443 100 : continue
4444 :
4445 : case (1,2)
4446 100 : call asria_calc(asr,asrq0%d2asr,ddb%val(:,:,iblok),ddb%mpert,ddb%natom)
4447 :
4448 : case (3,4)
4449 : ! Rotational invariance for 1D and 0D systems
4450 : ! Compute uinvers, vtinvers and singular matrices.
4451 2 : dims = 3*ddb%natom*(3*ddb%natom-1) / 2
4452 488 : ABI_CALLOC(asrq0%uinvers, (dims, dims))
4453 486 : ABI_CALLOC(asrq0%vtinvers,(dims, dims))
4454 36 : ABI_CALLOC(asrq0%singular, (dims))
4455 :
4456 : call asrprs(asr,1,3,asrq0%uinvers,asrq0%vtinvers,asrq0%singular,&
4457 2 : ddb%val(:,:,iblok),ddb%mpert,ddb%natom,crystal%xcart)
4458 :
4459 : case (5)
4460 : ! d2cart is a temp variable here
4461 0 : ABI_MALLOC(d2cart,(2,ddb%msize))
4462 0 : d2cart = ddb%val(:,:,iblok)
4463 : ! calculate diagonal correction
4464 0 : call asria_calc(2,asrq0%d2asr,d2cart,ddb%mpert,ddb%natom)
4465 : ! apply diagonal correction
4466 0 : call asria_corr(2,asrq0%d2asr,d2cart,ddb%mpert,ddb%natom)
4467 : ! hermitianize
4468 0 : call mkherm(d2cart,3*ddb%mpert)
4469 : ! remove remaining ASR rupture due to Hermitianization
4470 0 : ABI_MALLOC(d2asr_res,(2,3,ddb%natom,3,ddb%natom))
4471 0 : call asria_calc(asr,d2asr_res,d2cart,ddb%mpert,ddb%natom)
4472 : ! full correction is sum of both
4473 0 : asrq0%d2asr = asrq0%d2asr + d2asr_res
4474 :
4475 0 : ABI_FREE(d2cart)
4476 0 : ABI_FREE(d2asr_res)
4477 : case (6)
4478 : call msria_calc(asr,crystal,asrq0%d2asr,ddb%val(:,:,iblok),&
4479 2 : dcdq,dcdqdq,asrq0%d2dqmsr,asrq0%d2dqdqmsr,sys_dim,ddb%mpert,ddb%natom)
4480 : case default
4481 108 : ABI_ERROR(sjoin("Wrong value for asr:", itoa(asr)))
4482 : end select
4483 :
4484 : end subroutine asrq0_init
4485 : !!***
4486 :
4487 : !----------------------------------------------------------------------
4488 :
4489 : !!****f* m_ddb/ddb_symmetrize_and_transform
4490 : !! NAME
4491 : !! ddb_symmetrize_and_transform
4492 : !!
4493 : !! FUNCTION
4494 : !! First apply symmetry operations, then
4495 : !! transform the second-derivative matrix from reduced
4496 : !! coordinates to cartesian coordinates, and also
4497 : !! 1) add the ionic part of the effective charges,
4498 : !! 2) normalize the electronic dielectric tensor, and
4499 : !! add the vacuum polarisation
4500 : !!
4501 : !! INPUTS
4502 : !! crystal<type(crystal_t)>
4503 : !! iblock=the block index on which to act
4504 : !!
4505 : !! SIDE EFFECTS
4506 : !! ddb<type(ddb_type)>=
4507 : !!
4508 : !! OUTPUT
4509 : !!
4510 : !! SOURCE
4511 :
4512 1960 : subroutine ddb_symmetrize_and_transform(ddb, crystal, iblok)
4513 :
4514 : !Arguments -------------------------------
4515 : !scalars
4516 : class(ddb_type),intent(inout) :: ddb
4517 : class(crystal_t),intent(in) :: crystal
4518 : integer,intent(in) :: iblok
4519 : !integer,intent(inout) :: indsym(4,msym,natom)
4520 : !integer,intent(out) :: symrec(3,3,msym),symrel(3,3,msym),symafm(msym)
4521 :
4522 : !Local variables-------------------------------
4523 : !scalars
4524 : integer :: mpert,natom,nsym,ntypat
4525 : integer :: nsize,timrev
4526 : integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert
4527 : !arrays
4528 : !integer :: symq(4,2,msym)
4529 1960 : integer,allocatable :: symq(:,:,:)
4530 1960 : integer,allocatable :: car3flg(:,:,:,:,:,:),carflg(:,:,:,:)
4531 1960 : integer,allocatable :: tmpflg(:,:,:,:,:,:),rfpert(:,:,:,:,:,:)
4532 : real(dp) :: gprimd(3,3),qpt(3),rprimd(3,3)
4533 1960 : real(dp),allocatable :: d2cart(:,:,:,:,:),d3cart(:,:,:,:,:,:,:)
4534 1960 : real(dp),allocatable :: tmpval(:,:,:,:,:,:,:)
4535 : ! ************************************************************************
4536 :
4537 1960 : mpert = ddb%mpert
4538 1960 : natom = ddb%natom
4539 1960 : ntypat = crystal%ntypat
4540 :
4541 1960 : nsym = crystal%nsym
4542 25480 : rprimd(:,:) = crystal%rprimd(:,:)
4543 25480 : gprimd(:,:) = crystal%gprimd(:,:)
4544 :
4545 5880 : ABI_MALLOC(symq,(4,2,nsym))
4546 :
4547 : ! Here complete the matrix by symmetrisation of the existing elements
4548 1960 : if (ddb%typ(iblok) == BLKTYP_d2E_ns .or. ddb%typ(iblok) == BLKTYP_d2E_st) then
4549 :
4550 1881 : qpt(1)=ddb%qpt(1,iblok)/ddb%nrm(1,iblok)
4551 1881 : qpt(2)=ddb%qpt(2,iblok)/ddb%nrm(1,iblok)
4552 1881 : qpt(3)=ddb%qpt(3,iblok)/ddb%nrm(1,iblok)
4553 :
4554 : ! Examine the symmetries of the q wavevector
4555 1881 : call littlegroup_q(crystal%nsym,qpt,symq,crystal%symrec,crystal%symafm,timrev,prtvol=0)
4556 :
4557 : ! Deactuvate TRS for finite-omega calculations
4558 7521 : if (any(abs(ddb%omega(:,iblok)) > tol8)) timrev=0
4559 :
4560 : !GA: Note that d2sym3 and cart29 expect different shapes for tmpflg and tmpval
4561 : ! hence the extra dimensions
4562 1881 : nsize=3*mpert*3*mpert
4563 9405 : ABI_MALLOC(tmpflg,(3,mpert,3,mpert,1,1))
4564 9405 : ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,1,1))
4565 :
4566 9405 : tmpflg(:,:,:,:,1,1) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert/))
4567 8191397 : tmpval(1,:,:,:,:,1,1) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert/))
4568 8191397 : tmpval(2,:,:,:,:,1,1) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert/))
4569 :
4570 : ! Then apply symmetry operations
4571 1881 : call d2sym3(tmpflg,tmpval,crystal%indsym,mpert,natom,nsym,qpt,symq,crystal%symrec,crystal%symrel,timrev,1)
4572 :
4573 : ! Transform the dynamical matrix in cartesian coordinates
4574 5643 : ABI_MALLOC(carflg,(3,mpert,3,mpert))
4575 5643 : ABI_MALLOC(d2cart,(2,3,mpert,3,mpert))
4576 :
4577 1881 : call cart29(tmpflg,tmpval,carflg,d2cart,gprimd,1,mpert,natom,1,ntypat,rprimd,crystal%typat,crystal%ucvol,crystal%zion)
4578 :
4579 6036606 : ddb%flg(1:nsize,iblok) = reshape(carflg,shape = (/3*mpert*3*mpert/))
4580 6036606 : ddb%val(1,1:nsize,iblok) = reshape(d2cart(1,:,:,:,:), shape = (/3*mpert*3*mpert/))
4581 6036606 : ddb%val(2,1:nsize,iblok) = reshape(d2cart(2,:,:,:,:), shape = (/3*mpert*3*mpert/))
4582 :
4583 1881 : ABI_FREE(carflg)
4584 1881 : ABI_FREE(d2cart)
4585 1881 : ABI_FREE(tmpflg)
4586 1881 : ABI_FREE(tmpval)
4587 :
4588 79 : else if (ddb%typ(iblok) == BLKTYP_d3E_xx) then
4589 :
4590 4 : nsize=3*mpert*3*mpert*3*mpert
4591 28 : ABI_MALLOC(tmpflg,(3,mpert,3,mpert,3,mpert))
4592 28 : ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,3,mpert))
4593 16 : ABI_MALLOC(rfpert,(3,mpert,3,mpert,3,mpert))
4594 :
4595 28 : tmpflg(:,:,:,:,:,:) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4596 497068 : tmpval(1,:,:,:,:,:,:) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4597 497068 : tmpval(2,:,:,:,:,:,:) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4598 :
4599 : ! Set the elements that are zero by symmetry for raman and
4600 : ! non-linear optical susceptibility tensors
4601 497044 : rfpert = 0
4602 160 : rfpert(:,natom+2,:,natom+2,:,natom+2) = 1
4603 340 : rfpert(:,1:natom,:,natom+2,:,natom+2) = 1
4604 328 : rfpert(:,natom+2,:,1:natom,:,natom+2) = 1
4605 324 : rfpert(:,natom+2,:,natom+2,:,1:natom) = 1
4606 4 : call sytens(crystal%indsym,mpert,natom,nsym,rfpert,crystal%symrec,crystal%symrel)
4607 64 : do i1pert = 1,mpert
4608 964 : do i2pert = 1,mpert
4609 14460 : do i3pert = 1,mpert
4610 54900 : do i1dir=1,3
4611 175500 : do i2dir=1,3
4612 526500 : do i3dir=1,3
4613 364500 : if ((rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==-2) .and. &
4614 121500 : (tmpflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/=1)) then
4615 0 : tmpval(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = zero
4616 0 : tmpflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)=1
4617 : end if
4618 : end do
4619 : end do
4620 : end do
4621 : end do
4622 : end do
4623 : end do
4624 :
4625 4 : call d3sym(tmpflg,tmpval,crystal%indsym,mpert,natom,nsym,crystal%symrec,crystal%symrel)
4626 :
4627 16 : ABI_MALLOC(d3cart,(2,3,mpert,3,mpert,3,mpert))
4628 16 : ABI_MALLOC(car3flg,(3,mpert,3,mpert,3,mpert))
4629 :
4630 4 : call nlopt(tmpflg,car3flg,tmpval,d3cart,gprimd,mpert,natom,rprimd,crystal%ucvol)
4631 :
4632 364508 : ddb%flg(1:nsize,iblok) = reshape(car3flg, shape = (/3*mpert*3*mpert*3*mpert/))
4633 364508 : ddb%val(1,1:nsize,iblok) = reshape(d3cart(1,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/))
4634 364508 : ddb%val(2,1:nsize,iblok) = reshape(d3cart(2,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/))
4635 :
4636 4 : ABI_FREE(d3cart)
4637 4 : ABI_FREE(car3flg)
4638 4 : ABI_FREE(tmpflg)
4639 4 : ABI_FREE(tmpval)
4640 4 : ABI_FREE(rfpert)
4641 :
4642 75 : else if (ddb%typ(iblok) == BLKTYP_d3E_lw) then
4643 :
4644 9 : nsize=3*mpert*3*mpert*3*mpert
4645 63 : ABI_MALLOC(tmpflg,(3,mpert,3,mpert,3,mpert))
4646 63 : ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,3,mpert))
4647 :
4648 63 : tmpflg(:,:,:,:,:,:) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4649 2012931 : tmpval(1,:,:,:,:,:,:) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4650 2012931 : tmpval(2,:,:,:,:,:,:) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/))
4651 :
4652 36 : ABI_MALLOC(d3cart,(2,3,mpert,3,mpert,3,mpert))
4653 36 : ABI_MALLOC(car3flg,(3,mpert,3,mpert,3,mpert))
4654 :
4655 9 : call lwcart(tmpflg,car3flg,tmpval,d3cart,gprimd,mpert,natom,rprimd)
4656 :
4657 1483047 : ddb%flg(1:nsize,iblok) = reshape(car3flg, shape = (/3*mpert*3*mpert*3*mpert/))
4658 1483047 : ddb%val(1,1:nsize,iblok) = reshape(d3cart(1,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/))
4659 1483047 : ddb%val(2,1:nsize,iblok) = reshape(d3cart(2,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/))
4660 :
4661 9 : ABI_FREE(d3cart)
4662 9 : ABI_FREE(car3flg)
4663 9 : ABI_FREE(tmpflg)
4664 9 : ABI_FREE(tmpval)
4665 : end if
4666 :
4667 1960 : ABI_FREE(symq)
4668 :
4669 1960 : end subroutine ddb_symmetrize_and_transform
4670 : !!***
4671 :
4672 : !----------------------------------------------------------------------
4673 :
4674 : !!****f* m_ddb/ddb_diagoq
4675 : !! NAME
4676 : !! ddb_diagoq
4677 : !!
4678 : !! FUNCTION
4679 : !! Compute the phonon frequencies at the specified q-point by performing
4680 : !! a direct diagonalization of the dynamical matrix. The q-point **MUST** be
4681 : !! one the points stored in the DDB file.
4682 : !!
4683 : !! INPUTS
4684 : !! ddb<type(ddb_type)>=Object storing the DDB results.
4685 : !! crystal<type(crystal_t)> = Information on the crystalline structure.
4686 : !! asrq0<asrq0_t>=Object for the treatment of the ASR based on the q=0 block found in the DDB file.
4687 : !! symdynmat=If equal to 1, the dynamical matrix is symmetrized in dfpt_phfrq before the diagonalization.
4688 : !! rftyp = 1 if non-stationary block
4689 : !! 2 if stationary block
4690 : !! 3 if third order derivatives
4691 : !! qpt(3)=q-point in reduced coordinates.
4692 : !!
4693 : !! OUTPUT
4694 : !! phfrq(3*crystal%natom)=Phonon frequencies in Hartree
4695 : !! displ_cart(2,3*%natom,3*%natom)=Phonon displacement in Cartesian coordinates
4696 : !! [out_eigvec(2*3*natom*3*natom) = The igenvectors of the dynamical matrix.
4697 : !! [out_displ_red(2*3*natom*3*natom) = The displacement in reduced coordinates.
4698 : !!
4699 : !! SOURCE
4700 :
4701 0 : subroutine ddb_diagoq(ddb, crystal, qpt, asrq0, symdynmat, rftyp, phfrq, displ_cart, &
4702 0 : out_eigvec,out_displ_red) ! Optional [out]
4703 :
4704 : !Arguments -------------------------------
4705 : !scalars
4706 : integer,intent(in) :: symdynmat
4707 : integer,intent(in) :: rftyp
4708 : class(ddb_type),intent(in) :: ddb
4709 : type(asrq0_t),intent(inout) :: asrq0
4710 : type(crystal_t),intent(in) :: crystal
4711 : !arrays
4712 : real(dp),intent(in) :: qpt(3)
4713 : real(dp),intent(out) :: displ_cart(2,3,crystal%natom,3,crystal%natom)
4714 : real(dp),intent(out) :: phfrq(3*crystal%natom)
4715 : !real(dp),optional,intent(out) :: out_d2cart(2,3*crystal%natom,3*crystal%natom)
4716 : real(dp),optional,intent(out) :: out_eigvec(2,3,crystal%natom,3*crystal%natom)
4717 : real(dp),optional,intent(out) :: out_displ_red(2,3,crystal%natom,3*crystal%natom)
4718 :
4719 : !Local variables-------------------------------
4720 : integer :: iblok,natom
4721 : !arrays
4722 : integer :: rfphon(4),rfelfd(4),rfstrs(4)
4723 0 : real(dp) :: qphnrm(3), qphon_padded(3,3),d2cart(2,ddb%msize),my_qpt(3)
4724 0 : real(dp) :: eigvec(2,3,crystal%natom,3*crystal%natom),eigval(3*crystal%natom)
4725 : ! ************************************************************************
4726 :
4727 : ! Use my_qpt because dfpt_phfrq can change the q-point (very bad design)
4728 0 : qphnrm = one; my_qpt = qpt
4729 :
4730 : ! Look for the information in the DDB (no interpolation here!)
4731 0 : rfphon(1:2)=1; rfelfd(1:2)=0; rfstrs(1:2)=0
4732 0 : qphon_padded = zero; qphon_padded(:,1) = qpt
4733 0 : natom = crystal%natom
4734 :
4735 0 : call ddb%get_block(iblok, qphon_padded, qphnrm, rfphon, rfelfd, rfstrs, rftyp)
4736 0 : ABI_CHECK(iblok /= 0, sjoin("Cannot find q-point ", ktoa(qpt)," in DDB file"))
4737 :
4738 : ! Copy the dynamical matrix in d2cart
4739 0 : d2cart(:,1:ddb%msize) = ddb%val(:,:,iblok)
4740 :
4741 : ! Eventually impose the acoustic sum rule based on previously calculated d2asr
4742 0 : call asrq0%apply(natom, ddb%mpert, ddb%msize, qphon_padded, crystal, d2cart)
4743 :
4744 : ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
4745 : call dfpt_phfrq(ddb%amu,displ_cart,d2cart,eigval,eigvec,crystal%indsym,&
4746 : ddb%mpert,crystal%nsym,natom,crystal%nsym,crystal%ntypat,phfrq,qphnrm(1),my_qpt,&
4747 0 : crystal%rprimd,symdynmat,crystal%symrel,crystal%symafm,crystal%typat,crystal%ucvol)
4748 :
4749 : ! Return the dynamical matrix and the eigenvector for this q-point
4750 : !if (present(out_d2cart)) out_d2cart = d2cart(:,:3*natom,:3*natom)
4751 0 : if (present(out_eigvec)) out_eigvec = eigvec
4752 :
4753 : ! Return phonon displacement in reduced coordinates.
4754 0 : if (present(out_displ_red)) call phdispl_cart2red(natom, crystal%gprimd, displ_cart, out_displ_red)
4755 :
4756 0 : end subroutine ddb_diagoq
4757 : !!***
4758 :
4759 : !----------------------------------------------------------------------
4760 :
4761 : !!****f* m_ddb/asrq0_apply
4762 : !! NAME
4763 : !! asrq0_apply
4764 : !!
4765 : !! FUNCTION
4766 : !! Impose the acoustic sum rule based on the q=0 block found in the DDB file.
4767 : !!
4768 : !! INPUTS
4769 : !! asrq0<asrq0_t>=Object for the treatment of the ASR based on the q=0 block found in the DDB file.
4770 : !! natom=Number of atoms per unit cell.
4771 : !! mpert=Maximum number of perturbation (reported in ddb%mpert)
4772 : !! msize=Maximum size of array ddb%val
4773 : !! qphon(3,3)=wavevectors for the three possible phonons
4774 : !! crystal<type(crystal_t)> = Information on the crystalline structure.
4775 : !! dcdq=Moment of IFCs from Fourier transform
4776 : !! d2cdq=Second Moment of IFCs from Fourier transform
4777 : !! phi1=First Moment of IFCs from LW driver, if available
4778 : !! phi2=Second Moment of IFCs from LW driver summed of kappa', if available
4779 : !!
4780 : !! SIDE EFFECTS
4781 : !! d2cart=matrix of second derivatives of total energy, in cartesian coordinates
4782 : !! Input: Values stored in ddb%
4783 : !! Output: Changed to enforce ASR.
4784 : !!
4785 : !! SOURCE
4786 :
4787 222 : subroutine asrq0_apply(asrq0, natom, mpert, msize, qphon, crystal, d2cart)
4788 :
4789 : !Arguments -------------------------------
4790 : !scalars
4791 : class(asrq0_t),intent(inout) :: asrq0
4792 : type(crystal_t),intent(in) :: crystal
4793 : integer, intent(in) :: natom, mpert, msize
4794 : !arrays
4795 : real(dp),intent(in) :: qphon(3,3)
4796 : real(dp),intent(inout) :: d2cart(2,msize)
4797 : ! ************************************************************************
4798 :
4799 : ! TODO: Remove msize, since it can be inferred from mpert.
4800 :
4801 222 : if (asrq0%asr /= 0 .and. asrq0%iblok == 0) then
4802 0 : ABI_WARNING("asr != 0 but DDB file does not contain q=Gamma. D(q) cannot be corrected")
4803 0 : return
4804 : end if
4805 :
4806 : select case (asrq0%asr)
4807 : case (0)
4808 34 : return
4809 : case (1,2,5)
4810 34 : call asria_corr(asrq0%asr, asrq0%d2asr, d2cart, mpert, natom)
4811 : case (3,4)
4812 : ! Impose acoustic sum rule plus rotational symmetry for 0D and 1D systems
4813 22 : call asrprs(asrq0%asr,2,3,asrq0%uinvers,asrq0%vtinvers,asrq0%singular,d2cart,mpert,natom,crystal%xcart)
4814 : case (6)
4815 162 : call msria_apply(asrq0%asr,asrq0%d2asr,asrq0%d2dqmsr,d2cart,mpert,natom,qphon,crystal)
4816 : case default
4817 222 : ABI_ERROR(sjoin("Wrong value for asr:", itoa(asrq0%asr)))
4818 : end select
4819 : end subroutine asrq0_apply
4820 : !!***
4821 :
4822 : !----------------------------------------------------------------------
4823 :
4824 : !!****f* m_ddb/asrq0_free
4825 : !! NAME
4826 : !! asrq0_free
4827 : !!
4828 : !! FUNCTION
4829 : !! Free dynamic memory
4830 : !!
4831 : !! SOURCE
4832 :
4833 110 : subroutine asrq0_free(asrq0)
4834 :
4835 : !Arguments -------------------------------
4836 : class(asrq0_t),intent(inout) :: asrq0
4837 : ! ************************************************************************
4838 :
4839 : ! real
4840 110 : ABI_SFREE(asrq0%d2asr)
4841 110 : ABI_SFREE(asrq0%d2dqmsr)
4842 110 : ABI_SFREE(asrq0%d2dqdqmsr)
4843 110 : ABI_SFREE(asrq0%singular)
4844 110 : ABI_SFREE(asrq0%uinvers)
4845 110 : ABI_SFREE(asrq0%vtinvers)
4846 :
4847 110 : end subroutine asrq0_free
4848 : !!***
4849 :
4850 : !----------------------------------------------------------------------
4851 :
4852 : !!****f* m_ddb/ddb_write_block_txt
4853 : !!
4854 : !! NAME
4855 : !! ddb_write_block_txt
4856 : !!
4857 : !! FUNCTION
4858 : !! This routine writes blocks of data in the DDB in text format.
4859 : !!
4860 : !! INPUTS
4861 : !! choice= (2 => write), (3 => write minimal info )
4862 : !! mpert =maximum number of ipert
4863 : !! msize=maximum size of the arrays flags and values
4864 : !! nunit=unit number for the data block file
4865 : !!
4866 : !! OUTPUT
4867 : !! (see side effects)
4868 : !!
4869 : !! SIDE EFFECTS
4870 : !! Input/Output
4871 : !! ddb = ddb block datastructure
4872 : !! ddb%typ=type of the block:
4873 : !! 0 => total energy
4874 : !! 1 => second-order energy derivatives, non-stationary block
4875 : !! 2 => second-order energy derivatives, stationary block
4876 : !! 3 => third-order energy derivatives
4877 : !! 4 => first-order energy derivatives: forces, stresses and polarization
4878 : !! 5 => second-order eigenvalue derivatives
4879 : !! ddb%flg(msize)=flag for every matrix element (0=> the element is
4880 : !! not in the data block), (1=> the element is in the data blok)
4881 : !! ddb%qpt(9)=wavevector of the perturbation(s). The elements from
4882 : !! 1 to 3 are used if we are dealing with the 2nd derivative of
4883 : !! total energy (only one wavevector), while all elements are
4884 : !! used in case of a third order derivative of total energy
4885 : !! (three wavevector could be present)
4886 : !! ddb%nrm(3)=normalization factors for the three allowed wavevectors.
4887 : !! ddb%val(2,msize)=real(dp), complex, value of the
4888 : !! matrix elements that are present in the data block
4889 : !! blkval2(2,msize,mband,nkpt) = value of the matrix elements
4890 : !! that are present in a block of EIGR2D/EIGI2D
4891 : !!
4892 : !! NOTES
4893 : !! only executed by one processor.
4894 : !!
4895 : !! SOURCE
4896 :
4897 2645 : subroutine ddb_write_block_txt(ddb,iblok,choice,mband,mpert,msize,nkpt,nunit, &
4898 20 : blkval2,kpt) !optional
4899 :
4900 : !Arguments -------------------------------
4901 : !scalars
4902 : integer,intent(in) :: choice,mband,mpert,msize,nkpt,nunit
4903 : integer,intent(in) :: iblok
4904 : class(ddb_type),intent(in) :: ddb
4905 : !arrays
4906 : real(dp),intent(in),optional :: kpt(3,nkpt)
4907 : real(dp),intent(in),optional :: blkval2(2,msize,mband,nkpt)
4908 :
4909 : !Local variables -------------------------
4910 : !scalars
4911 : integer,parameter :: cvrsio9_new=20240201
4912 : integer :: iband,idir1,idir2,idir3,ii,ikpt,ipert1,ipert2,ipert3
4913 : integer :: nelmts
4914 : logical :: eig2d_
4915 : ! *********************************************************************
4916 :
4917 : ! GA: Remove choice option.
4918 : ! choice=3 is used to write summary info at the end of the DDB.
4919 : ! With MG and MV, we agreed that it could be removed.
4920 :
4921 : ! GA: Remove arguments: mband, blkval2, kpt
4922 : ! This feature of writing eigenvalues 2nd deriv is no longer used
4923 : ! (see 80_tdep/m_tdep_abitypes.F90)
4924 : ! With FB, we agreed that it could be removed.
4925 :
4926 2645 : eig2d_ = .false.
4927 2645 : if(present(blkval2).and.present(kpt)) eig2d_ = .true.
4928 :
4929 :
4930 : ! Count the number of elements
4931 2645 : nelmts=0
4932 7296329 : do ii=1,msize
4933 7296329 : if(ddb%flg(ii,iblok)==1)nelmts=nelmts+1
4934 : end do
4935 :
4936 : ! Write the block type and number of elements
4937 2645 : write(nunit,*)' '
4938 2645 : if (ddb%typ(iblok) == BLKTYP_d0E_xx) then
4939 48 : write(nunit, '(a,i12)' )' Total energy - # elements :',nelmts
4940 : else if (ddb%typ(iblok)==BLKTYP_d2E_ns) then
4941 2502 : write(nunit, '(a,i12)' )' 2nd derivatives (non-stat.) - # elements :',nelmts
4942 : else if(ddb%typ(iblok)==BLKTYP_d2E_st) then
4943 2 : write(nunit, '(a,i12)' )' 2nd derivatives (stationary) - # elements :',nelmts
4944 : else if(ddb%typ(iblok)==BLKTYP_d2E_mbc) then
4945 0 : write(nunit, '(a,i12)' )' 2nd derivatives (MBC) - # elements :',nelmts
4946 : else if(ddb%typ(iblok)==BLKTYP_d3E_xx) then
4947 3 : write(nunit, '(a,i12)' )' 3rd derivatives - # elements :',nelmts
4948 : else if (ddb%typ(iblok) == BLKTYP_d1E_xx) then
4949 48 : write(nunit, '(a,i12)' )' 1st derivatives - # elements :',nelmts
4950 : else if (ddb%typ(iblok) == BLKTYP_d2eig_re) then
4951 20 : write(nunit, '(a,i12)' )' 2nd eigenvalue derivatives - # elements :',nelmts
4952 : else if(ddb%typ(iblok)==BLKTYP_d3E_lw) then
4953 22 : write(nunit, '(a,i12)' )' 3rd derivatives (long wave) - # elements :',nelmts
4954 : end if
4955 :
4956 : ! Write the 2nd derivative block
4957 2645 : if (is_type_d2E(ddb%typ(iblok))) then
4958 :
4959 : ! Write the phonon wavevector
4960 10016 : write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
4961 :
4962 : ! Write the perturbation frequency
4963 2504 : write(nunit, '(a,1es16.8)' )' frequency',ddb%omega(1,iblok)
4964 :
4965 : ! Write the matrix elements
4966 2504 : if(choice==2)then
4967 2504 : ii=0
4968 26334 : do ipert2=1,mpert
4969 97824 : do idir2=1,3
4970 895474 : do ipert1=1,mpert
4971 3272106 : do idir1=1,3
4972 2400462 : ii=ii+1
4973 3200616 : if(ddb%flg(ii,iblok)==1)then
4974 564810 : write(nunit,'(4i4,2d22.14)') idir1, ipert1, idir2, ipert2, &
4975 1129620 : ddb%val(1,ii,iblok),ddb%val(2,ii,iblok)
4976 : end if
4977 : end do
4978 : end do
4979 : end do
4980 : end do
4981 : end if
4982 :
4983 :
4984 141 : else if (is_type_d3E(ddb%typ(iblok))) then
4985 : ! Write the 3rd derivative block
4986 :
4987 : ! Write the phonon wavevectors
4988 100 : write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
4989 100 : write(nunit, '(a,3es16.8,f6.1)' )' ',(ddb%qpt(ii,iblok),ii=4,6),ddb%nrm(2,iblok)
4990 100 : write(nunit, '(a,3es16.8,f6.1)' )' ',(ddb%qpt(ii,iblok),ii=7,9),ddb%nrm(3,iblok)
4991 :
4992 : ! Write the perturbation frequency
4993 25 : write(nunit, '(a,1es16.8)' )' frequency',ddb%omega(1,iblok)
4994 25 : write(nunit, '(a,1es16.8)' )' ',ddb%omega(2,iblok)
4995 25 : write(nunit, '(a,1es16.8)' )' ',ddb%omega(3,iblok)
4996 :
4997 : ! Write the matrix elements
4998 25 : if(choice==2)then
4999 25 : ii=0
5000 385 : do ipert3=1,mpert
5001 1465 : do idir3=1,3
5002 19140 : do ipert2=1,mpert
5003 71880 : do idir2=1,3
5004 1044366 : do ipert1=1,mpert
5005 3947364 : do idir1=1,3
5006 2920698 : ii=ii+1
5007 3894264 : if(ddb%flg(ii,iblok)==1)then
5008 : write(nunit, '(6i6,2d22.14)' )&
5009 3941 : idir1,ipert1,idir2,ipert2,idir3,ipert3,ddb%val(1,ii,iblok),ddb%val(2,ii,iblok)
5010 : end if
5011 : end do
5012 : end do
5013 : end do
5014 : end do
5015 : end do
5016 : end do
5017 : end if
5018 :
5019 :
5020 116 : else if (is_type_d0E(ddb%typ(iblok))) then
5021 : ! Write total energy
5022 48 : if (choice == 2) write(nunit,'(2d22.14)')ddb%val(1,1,iblok),ddb%val(2,1,iblok)
5023 :
5024 68 : else if (is_type_d1E(ddb%typ(iblok))) then
5025 : ! Write the 1st derivative blok
5026 48 : if (choice == 2) then
5027 48 : ii = 0
5028 459 : do ipert1 = 1, mpert
5029 1692 : do idir1 = 1, 3
5030 1233 : ii = ii + 1
5031 1644 : if (ddb%flg(ii,iblok) == 1) then
5032 603 : write(nunit,'(2i6,2d22.14)')idir1,ipert1,ddb%val(1,ii,iblok),ddb%val(2,ii,iblok)
5033 : end if
5034 : end do
5035 : end do
5036 : end if
5037 :
5038 20 : else if (is_type_d2eig(ddb%typ(iblok))) then
5039 : ! Write the phonon wavevector
5040 80 : write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok)
5041 : ! Write the matrix elements
5042 : ! GA: Note that isppol is invisible here. It is simply marked as more bands.
5043 : ! To be changed in a future version of text format.
5044 20 : if(choice==2)then
5045 20 : if (eig2d_) then
5046 212 : do ikpt=1,nkpt
5047 192 : write(nunit,'(a,3es16.8)')' K-point:',(kpt(ii,ikpt),ii=1,3)
5048 1332 : do iband=1,mband
5049 1120 : write(nunit,'(a,i3)')' Band:',iband
5050 1120 : ii=0
5051 3296 : do ipert2=1,mpert
5052 9056 : do idir2=1,3
5053 19072 : do ipert1=1,mpert
5054 50496 : do idir1=1,3
5055 33408 : ii=ii+1
5056 44544 : if(ddb%flg(ii,iblok)==1)then
5057 33408 : write(nunit,'(4i4,2d22.14)')idir1,ipert1,idir2,ipert2,blkval2(1,ii,iband,ikpt),blkval2(2,ii,iband,ikpt)
5058 : end if
5059 : end do !idir1
5060 : end do !ipert1
5061 : end do !idir2
5062 : end do !ipert2
5063 : end do !iband
5064 : end do !ikpt
5065 : end if !eig2d_
5066 : end if !choice
5067 : end if !ddb%typ(iblok)
5068 :
5069 2645 : end subroutine ddb_write_block_txt
5070 : !!***
5071 :
5072 : !----------------------------------------------------------------------
5073 :
5074 : !!****f* m_ddb/ddb_write
5075 : !! NAME
5076 : !! ddb_write
5077 : !!
5078 : !! FUNCTION
5079 : !! Write the DDB file in either txt or netcdf format.
5080 : !!
5081 : !! INPUTS
5082 : !! ddb_hdr=ddb header object.
5083 : !! filename=name of the file being written (abo_DS*_DDB)
5084 : !! with_psps
5085 : !! 1-> include information on pseudopotentials
5086 : !! 0-> do not include information on pseudopotentials
5087 : !! comm=MPI communicator
5088 : !!
5089 : !! SOURCE
5090 :
5091 3287 : subroutine ddb_write(ddb, ddb_hdr, filename, with_psps, comm)
5092 :
5093 : !Arguments -------------------------------
5094 : class(ddb_type),intent(inout) :: ddb
5095 : type(ddb_hdr_type),intent(inout) :: ddb_hdr
5096 : character(len=fnlen),intent(in) :: filename
5097 : integer,intent(in),optional :: with_psps
5098 : integer,intent(in),optional :: comm
5099 :
5100 : !Local variables-------------------------------
5101 : character(len=fnlen) :: filename_
5102 : integer :: iomode
5103 : ! ************************************************************************
5104 :
5105 3287 : call ddb_hdr%get_iomode(filename, 2, iomode, filename_)
5106 :
5107 3287 : if (iomode==IO_MODE_ETSF) then
5108 3161 : call ddb%write_nc(ddb_hdr, filename_, comm=comm, with_psps=with_psps)
5109 126 : else if (iomode==IO_MODE_FORTRAN) then
5110 126 : call ddb%write_txt(ddb_hdr, filename_, with_psps=with_psps, comm=comm)
5111 126 : ddb_hdr%mpert = ddb%mpert ! Text format doesnt know about mpert.
5112 : end if
5113 :
5114 3287 : end subroutine ddb_write
5115 : !!***
5116 :
5117 : !----------------------------------------------------------------------
5118 :
5119 : !!****f* m_ddb/ddb_write_txt
5120 : !! NAME
5121 : !! ddb_write_txt
5122 : !!
5123 : !! FUNCTION
5124 : !! Write the DDB file in text format.
5125 : !!
5126 : !! INPUTS
5127 : !! ddb_hdr=ddb header object.
5128 : !! filename=name of the file being written (abo_DS*_DDB)
5129 : !! with_psps
5130 : !! 1-> include information on pseudopoentials
5131 : !! 0-> do not include information on pseudopoentials
5132 : !!
5133 : !! SOURCE
5134 :
5135 144 : subroutine ddb_write_txt(ddb, ddb_hdr, filename, with_psps, comm)
5136 :
5137 : !Arguments -------------------------------
5138 : class(ddb_type),intent(inout) :: ddb
5139 : type(ddb_hdr_type),intent(inout) :: ddb_hdr
5140 : character(len=*),intent(in) :: filename
5141 : integer,intent(in),optional :: with_psps
5142 : integer,intent(in),optional :: comm
5143 :
5144 : !Local variables -------------------------
5145 : !scalars
5146 : integer :: iblok
5147 : integer,parameter :: master=0, choice=2
5148 : ! ************************************************************************
5149 :
5150 144 : if (present(comm)) then
5151 0 : if (xmpi_comm_rank(comm) /= master) return
5152 : end if
5153 :
5154 144 : call ddb_hdr%open_write_txt(filename, with_psps)
5155 :
5156 2769 : do iblok=1,ddb%nblok
5157 2769 : call ddb%write_block_txt(iblok,choice,1,ddb%mpert,ddb%msize,ddb_hdr%nkpt,ddb_hdr%unddb)
5158 : end do
5159 :
5160 144 : call ddb_hdr%close()
5161 :
5162 : end subroutine ddb_write_txt
5163 : !!***
5164 :
5165 : !----------------------------------------------------------------------
5166 :
5167 : !!****f* m_ddb/ddb_write_d2eig
5168 : !! NAME
5169 : !! ddb_write_d2eig
5170 : !!
5171 : !! FUNCTION
5172 : !! Write the current eig2d data as the next block in the ddb file.
5173 : !!
5174 : !! INPUTS
5175 : !! ddb_hdr=ddb header object.
5176 : !! unddb=unit of the open ddb file in text format or netcdf identifier.
5177 : !!
5178 : !!
5179 : !! SOURCE
5180 :
5181 157 : subroutine ddb_write_d2eig(ddb, ddb_hdr, iblok, comm)
5182 : !Arguments -------------------------------
5183 : class(ddb_type),intent(inout) :: ddb
5184 : type(ddb_hdr_type),intent(inout) :: ddb_hdr
5185 : integer,intent(in) :: iblok
5186 : integer,intent(in),optional :: comm
5187 :
5188 : !Local variables -------------------------
5189 : !scalars
5190 : integer,parameter :: master=0
5191 : character(len=500) :: msg
5192 : ! ************************************************************************
5193 :
5194 157 : if (present(comm)) then
5195 112 : if (xmpi_comm_rank(comm) /= master) return
5196 : end if
5197 :
5198 137 : if (ddb_hdr%has_open_file_nc) then
5199 :
5200 117 : call ddb%write_d2eig_nc(ddb_hdr%ncid, iblok)
5201 :
5202 20 : else if (ddb_hdr%has_open_file_txt) then
5203 :
5204 20 : call ddb%write_d2eig_txt(ddb_hdr%unddb, iblok)
5205 :
5206 : else
5207 : write(msg, '(3a)' )&
5208 : ! File has not been opened by ddb_hdr
5209 0 : 'Attempting to write into unopen DDB file.',ch10,&
5210 0 : 'Action: contact Abinit group.'
5211 0 : ABI_ERROR(msg)
5212 : end if
5213 :
5214 : end subroutine ddb_write_d2eig
5215 : !!***
5216 :
5217 : !----------------------------------------------------------------------
5218 :
5219 : !!****f* m_ddb/ddb_write_d2eig_nc
5220 : !! NAME
5221 : !! ddb_write_d2eig_nc
5222 : !!
5223 : !! FUNCTION
5224 : !! Write the current d2eig data in the ddb netcdf file.
5225 : !!
5226 : !! INPUTS
5227 : !! iblok=index of the eig2d block within the d2eig subgroup.
5228 : !! ncid=netcdf identifier of a file open in writing mode.
5229 : !! comm=MPI communicator.
5230 : !!
5231 : !! SOURCE
5232 :
5233 117 : subroutine ddb_write_d2eig_nc(ddb, ncid, iblok, comm)
5234 : !Arguments -------------------------------
5235 : class(ddb_type),intent(inout) :: ddb
5236 : integer,intent(in) :: ncid
5237 : integer,intent(in) :: iblok
5238 : integer,intent(in),optional :: comm
5239 :
5240 : !Local variables -------------------------
5241 : !scalars
5242 : integer,parameter :: master=0
5243 : integer :: iband, jband, bandshift, isppol, mband
5244 : integer :: ikpt, ipert1, idir1, ipert2, idir2, ii
5245 : integer :: ncid_d2eig, ncerr
5246 : real(dp) :: qpt(3)
5247 117 : real(dp), allocatable :: matrix_d2eig(:,:,:,:,:,:,:)
5248 117 : real(dp), allocatable :: matrix_d2eig_isppol(:,:,:,:,:,:,:)
5249 117 : integer, allocatable :: flg_d2eig(:,:,:,:)
5250 : ! ************************************************************************
5251 :
5252 :
5253 117 : if (present(comm)) then
5254 0 : if (xmpi_comm_rank(comm) /= master) return
5255 : end if
5256 :
5257 117 : ncid_d2eig = nctk_idgroup(ncid, 'd2eig')
5258 :
5259 468 : qpt(1:3) = ddb%qpt(1:3,iblok)
5260 : ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5261 : 'reduced_coordinates_of_qpoints'),&
5262 : qpt,&
5263 351 : start=[1,iblok])
5264 117 : NCF_CHECK(ncerr)
5265 : ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5266 : 'qpoints_normalization'),&
5267 : ddb%nrm(1,iblok),&
5268 234 : start=[iblok])
5269 117 : NCF_CHECK(ncerr)
5270 :
5271 : ! GA: Here we assume that all blocks are d2eig blocks.
5272 : ! Otherwise, iblok is only the 'local' iblok index
5273 : ! and we would need to figure out the corresponding 'global' index
5274 117 : call ddb%get_d2eig(matrix_d2eig, flg_d2eig, iblok)
5275 :
5276 117 : mband = ddb%nband / ddb%nsppol
5277 819 : ABI_MALLOC(matrix_d2eig_isppol, (2,3,ddb%mpert,3,ddb%mpert,mband,ddb%nkpt))
5278 :
5279 : ! Loop over spin index
5280 235 : do isppol=1,ddb%nsppol
5281 :
5282 118 : bandshift = (isppol - 1) * mband
5283 :
5284 1214 : do iband=1,mband
5285 1096 : jband = bandshift + iband
5286 :
5287 18064 : do ikpt=1,ddb%nkpt
5288 51518 : do ipert1=1,ddb%mpert
5289 151138 : do idir1=1,3
5290 343400 : do ipert2=1,ddb%mpert
5291 937164 : do idir2=1,3
5292 2091120 : do ii=1,2
5293 : matrix_d2eig_isppol(ii,idir2,ipert2,idir1,ipert1,iband,ikpt)=&
5294 1882008 : matrix_d2eig(ii,idir2,ipert2,idir1,ipert1,jband,ikpt)
5295 : end do
5296 : end do
5297 : end do
5298 : end do
5299 : end do
5300 : end do
5301 :
5302 :
5303 : end do ! iband
5304 :
5305 : ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5306 : 'matrix_values'),&
5307 : matrix_d2eig_isppol,&
5308 1180 : start=[1,1,1,1,1,1,1,isppol,iblok])
5309 : !count=[2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt,1,1])
5310 : !count=[2,3,ddb%mpert,3,ddb%mpert,ddb%nkpt,ddb%nband,1,1])
5311 235 : NCF_CHECK(ncerr)
5312 :
5313 : end do ! isppol
5314 :
5315 : ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5316 : 'matrix_mask'),&
5317 : flg_d2eig,&
5318 702 : start=[1,1,1,1,iblok])
5319 117 : NCF_CHECK(ncerr)
5320 :
5321 117 : ABI_SFREE(matrix_d2eig_isppol)
5322 117 : ABI_SFREE(matrix_d2eig)
5323 117 : ABI_SFREE(flg_d2eig)
5324 :
5325 117 : end subroutine ddb_write_d2eig_nc
5326 : !!***
5327 :
5328 : !----------------------------------------------------------------------
5329 :
5330 :
5331 : !!****f* m_ddb/ddb_write_d2eig_txt
5332 : !! NAME
5333 : !! ddb_write_d2eig_txt
5334 : !!
5335 : !! FUNCTION
5336 : !! Write the eig2d data as the next block in text file format.
5337 : !!
5338 : !! INPUTS
5339 : !! ddb_hdr=ddb header object.
5340 : !! unddb=unit of the open ddb file in text format.
5341 : !!
5342 : !!
5343 : !! SOURCE
5344 :
5345 20 : subroutine ddb_write_d2eig_txt(ddb, unddb, iblok)
5346 : !Arguments -------------------------------
5347 : class(ddb_type),intent(in) :: ddb
5348 : integer,intent(in) :: unddb
5349 : integer,intent(in) :: iblok
5350 :
5351 : !Local variables -------------------------
5352 : !scalars
5353 : integer,parameter :: iblok_eig2d=1
5354 : integer,parameter :: choice=2
5355 : ! ************************************************************************
5356 :
5357 : ! GA: This routine is redundant with outbsd.
5358 : ! The present implementation should replace outbsd.
5359 :
5360 : call ddb%write_block_txt(iblok,choice,ddb%nband,ddb%mpert,ddb%msize,ddb%nkpt,unddb, &
5361 20 : ddb%eig2dval(:,:,:,:), ddb%kpt(:,:))
5362 :
5363 20 : end subroutine ddb_write_d2eig_txt
5364 : !!***
5365 :
5366 : !----------------------------------------------------------------------
5367 :
5368 : !!****f* m_ddb/ddb_write_nc
5369 : !! NAME
5370 : !! ddb_write_nc
5371 : !!
5372 : !! FUNCTION
5373 : !! Write the netndf file DDB.nc in the format of version 20230219.
5374 : !!
5375 : !! INPUTS
5376 : !! ddb_hdr=ddb header object with open file.
5377 : !! filename=DDB filename.
5378 : !! comm=MPI communicator.
5379 : !! with_psps
5380 : !! 1-> include information on pseudopoentials
5381 : !! 0-> do not include information on pseudopoentials
5382 : !!
5383 : !! SOURCE
5384 :
5385 3162 : subroutine ddb_write_nc(ddb, ddb_hdr, filename, comm, with_psps)
5386 :
5387 : !Arguments -------------------------------
5388 : class(ddb_type),intent(inout) :: ddb
5389 : type(ddb_hdr_type),intent(inout) :: ddb_hdr
5390 : character(len=*),intent(in) :: filename
5391 : integer,intent(in),optional :: comm
5392 : integer,intent(in),optional :: with_psps
5393 :
5394 : !Local variables -------------------------
5395 : !scalars
5396 : integer,parameter :: master=0
5397 : integer :: ncid, ncerr, ncid_d0E, ncid_d1E, ncid_d2E, ncid_d3E, ncid_d2eig
5398 : integer :: ii,iblok,iblok_d0E,iblok_d1E,iblok_d2E,iblok_d3E,iblok_d2eig
5399 : !arrays
5400 3162 : integer,allocatable :: flg_d1E(:,:)
5401 3162 : integer,allocatable :: flg_d2E(:,:,:,:)
5402 3162 : integer,allocatable :: flg_d3E(:,:,:,:,:,:)
5403 : real(dp) :: qpt(3), qpts(3,3), nrms(3)
5404 : real(dp) :: omega, omegas(3)
5405 3162 : real(dp),allocatable :: matrix_d1E(:,:,:)
5406 3162 : real(dp),allocatable :: matrix_d2E(:,:,:,:,:)
5407 3162 : real(dp),allocatable :: matrix_d3E(:,:,:,:,:,:,:)
5408 : ! ************************************************************************
5409 :
5410 3162 : if (present(comm)) then
5411 0 : if (xmpi_comm_rank(comm) /= master) return
5412 : end if
5413 :
5414 : ! =====================
5415 : ! Header and dimensions
5416 : ! =====================
5417 : ! Copy types and dimensions into the header
5418 3162 : ddb_hdr%mpert = ddb%mpert
5419 3162 : call ddb_hdr%set_typ(ddb%nblok, ddb%typ)
5420 :
5421 3162 : call ddb_hdr%open_write_nc(filename, with_psps=with_psps)
5422 3162 : ncid = ddb_hdr%ncid
5423 :
5424 : ! Get all group id
5425 3162 : ncid_d0E = nctk_idgroup(ncid, 'd0E')
5426 3162 : ncid_d1E = nctk_idgroup(ncid, 'd1E')
5427 3162 : ncid_d2E = nctk_idgroup(ncid, 'd2E')
5428 3162 : ncid_d3E = nctk_idgroup(ncid, 'd3E')
5429 3162 : ncid_d2eig = nctk_idgroup(ncid, 'd2eig')
5430 :
5431 : ! =============================
5432 : ! Loop over block to be written
5433 : ! =============================
5434 :
5435 3162 : iblok_d0E = 0; iblok_d1E = 0; iblok_d2E = 0; iblok_d3E = 0; iblok_d2eig = 0
5436 :
5437 9053 : do iblok=1,ddb%nblok
5438 :
5439 : ! ------------------------
5440 : ! Zeroth-order derivatives
5441 : ! ------------------------
5442 9053 : if (is_type_d0E(ddb%typ(iblok))) then
5443 :
5444 2712 : iblok_d0E = iblok_d0E + 1
5445 :
5446 : ncerr = nf90_put_var(ncid_d0E, nctk_idname(ncid_d0E,&
5447 : 'matrix_values'),&
5448 : ddb%val(1,1,iblok),&
5449 5424 : start=[iblok_d0E])
5450 2712 : NCF_CHECK(ncerr)
5451 :
5452 : ncerr = nf90_put_var(ncid_d0E, nctk_idname(ncid_d0E,&
5453 : 'matrix_mask'),&
5454 : ddb%flg(1,iblok),&
5455 5424 : start=[iblok_d0E])
5456 2712 : NCF_CHECK(ncerr)
5457 :
5458 : ! -----------------------
5459 : ! First-order derivatives
5460 : ! -----------------------
5461 3179 : else if (is_type_d1E(ddb%typ(iblok))) then
5462 :
5463 2719 : iblok_d1E = iblok_d1E + 1
5464 :
5465 2719 : call ddb%get_d1matr(iblok, matrix_d1E, flg_d1E)
5466 :
5467 : ncerr = nf90_put_var(ncid_d1E, nctk_idname(ncid_d1E,&
5468 : 'matrix_values'),&
5469 : matrix_d1E,&
5470 13595 : start=[1,1,1,iblok_d1E])
5471 2719 : NCF_CHECK(ncerr)
5472 :
5473 : ncerr = nf90_put_var(ncid_d1E, nctk_idname(ncid_d1E,&
5474 : 'matrix_mask'),&
5475 : flg_d1E,&
5476 10876 : start=[1,1,iblok_d1E])
5477 2719 : NCF_CHECK(ncerr)
5478 2719 : ABI_SFREE(matrix_d1E)
5479 2719 : ABI_SFREE(flg_d1E)
5480 :
5481 : ! ------------------------
5482 : ! Second-order derivatives
5483 : ! ------------------------
5484 460 : else if (is_type_d2E(ddb%typ(iblok))) then
5485 :
5486 436 : iblok_d2E = iblok_d2E + 1
5487 :
5488 1744 : do ii=1,3
5489 1744 : qpt(ii) = ddb%qpt(ii,iblok)
5490 : end do
5491 : ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,&
5492 : 'reduced_coordinates_of_qpoints'),&
5493 : qpt,&
5494 1308 : start=[1,iblok_d2E])
5495 436 : NCF_CHECK(ncerr)
5496 :
5497 : ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,&
5498 : 'qpoints_normalization'),&
5499 : (ddb%nrm(1,iblok)),&
5500 872 : start=[iblok_d2E])
5501 436 : NCF_CHECK(ncerr)
5502 :
5503 436 : omega = ddb%omega(1,iblok)
5504 : ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,&
5505 : 'frequency'),&
5506 : omega,&
5507 872 : start=[iblok_d2E])
5508 436 : NCF_CHECK(ncerr)
5509 :
5510 436 : call ddb%get_d2matr(iblok, matrix_d2E, flg_d2E)
5511 :
5512 : ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,&
5513 : 'matrix_values'),&
5514 : matrix_d2E,&
5515 3052 : start=[1,1,1,1,1,iblok_d2E])
5516 436 : NCF_CHECK(ncerr)
5517 :
5518 : ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,&
5519 : 'matrix_mask'),&
5520 : flg_d2E,&
5521 2616 : start=[1,1,1,1,iblok_d2E])
5522 436 : NCF_CHECK(ncerr)
5523 436 : ABI_SFREE(matrix_d2E)
5524 436 : ABI_SFREE(flg_d2E)
5525 :
5526 : ! -----------------------
5527 : ! Third-order derivatives
5528 : ! -----------------------
5529 24 : else if (is_type_d3E(ddb%typ(iblok))) then
5530 :
5531 24 : iblok_d3E = iblok_d3E + 1
5532 :
5533 96 : do ii=1,3
5534 72 : nrms(ii) = ddb%nrm(ii,iblok)
5535 72 : qpts(1,ii) = ddb%qpt(ii,iblok)
5536 72 : qpts(2,ii) = ddb%qpt(ii+3,iblok)
5537 96 : qpts(3,ii) = ddb%qpt(ii+6,iblok)
5538 : end do
5539 :
5540 : ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,&
5541 : 'reduced_coordinates_of_qpoints'),&
5542 : qpts,&
5543 96 : start=[1,1,iblok_d3E])
5544 24 : NCF_CHECK(ncerr)
5545 :
5546 : ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,&
5547 : 'qpoints_normalization'),&
5548 : nrms,&
5549 72 : start=[1,iblok_d3E])
5550 24 : NCF_CHECK(ncerr)
5551 :
5552 24 : omegas(1) = ddb%omega(1,iblok)
5553 24 : omegas(2) = ddb%omega(2,iblok)
5554 24 : omegas(3) = ddb%omega(3,iblok)
5555 :
5556 :
5557 : ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,&
5558 : 'frequency'),&
5559 : omegas,&
5560 72 : start=[1,iblok_d3E])
5561 24 : NCF_CHECK(ncerr)
5562 :
5563 24 : call ddb%get_d3matr(iblok, matrix_d3E, flg_d3E)
5564 :
5565 : ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,&
5566 : 'matrix_values'),&
5567 : matrix_d3E,&
5568 216 : start=[1,1,1,1,1,1,1,iblok_d3E])
5569 24 : NCF_CHECK(ncerr)
5570 :
5571 : ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,&
5572 : 'matrix_mask'),&
5573 : flg_d3E,&
5574 192 : start=[1,1,1,1,1,1,iblok_d3E])
5575 24 : NCF_CHECK(ncerr)
5576 :
5577 24 : ABI_SFREE(matrix_d3E)
5578 24 : ABI_SFREE(flg_d3E)
5579 :
5580 : ! ---------------------------------------
5581 : ! Second-order derivatives of eigenvalues
5582 : ! ---------------------------------------
5583 0 : else if (is_type_d2eig(ddb%typ(iblok))) then
5584 :
5585 0 : iblok_d2eig = iblok_d2eig + 1
5586 :
5587 0 : call ddb%write_d2eig_nc(ncid_d2eig, iblok_d2eig)
5588 :
5589 : end if
5590 : end do
5591 :
5592 3162 : end subroutine ddb_write_nc
5593 : !!***
5594 :
5595 : !----------------------------------------------------------------------
5596 :
5597 : !!****f* m_ddb/ddb_read_d0E_nc
5598 : !! NAME
5599 : !! ddb_read_d0E_nc
5600 : !!
5601 : !! FUNCTION
5602 : !! Read a DDB block containing 0th order derivatives of energy.
5603 : !!
5604 : !!
5605 : !! INPUTS
5606 : !! ncid=netcdf identifier of a file open in reading mode.
5607 : !! iblok=index of the block we are setting.
5608 : !! iblok_d0E=index of the block we are reading in the d0E group.
5609 : !!
5610 : !! OUTPUT
5611 : !!
5612 : !! SOURCE
5613 :
5614 6 : subroutine ddb_read_d0E_nc(ddb, ncid, iblok, iblok_d0E)
5615 :
5616 : !Arguments -------------------------------
5617 : !scalars
5618 : class(ddb_type),intent(inout) :: ddb
5619 : integer,intent(in) :: ncid,iblok,iblok_d0E
5620 :
5621 : !Local variables -------------------------
5622 : !scalars
5623 : integer :: ncid_d0E
5624 : integer :: ncerr
5625 : !arrays
5626 : integer :: flg(1)
5627 : real(dp) :: val(1)
5628 : ! ************************************************************************
5629 :
5630 6 : ncid_d0E = nctk_idgroup(ncid, 'd0E')
5631 :
5632 : ! Allocate temporary arrays
5633 24 : ncerr = nf90_get_var(ncid_d0E, nctk_idname(ncid_d0E, 'matrix_values'), val, start=[1,1,iblok_d0E], count=[1,1,1])
5634 6 : NCF_CHECK(ncerr)
5635 6 : ddb%val(1,1,iblok) = val(1)
5636 6 : ddb%val(2,1,iblok) = zero
5637 18 : ncerr = nf90_get_var(ncid_d0E, nctk_idname(ncid_d0E, 'matrix_mask'), flg, start=[1,iblok_d0E], count=[1,1])
5638 6 : NCF_CHECK(ncerr)
5639 6 : ddb%flg(1,iblok) = flg(1)
5640 :
5641 6 : end subroutine ddb_read_d0E_nc
5642 : !!***
5643 :
5644 : !----------------------------------------------------------------------
5645 :
5646 : !!****f* m_ddb/ddb_read_d1E_nc
5647 : !! NAME
5648 : !! ddb_read_d1E_nc
5649 : !!
5650 : !! FUNCTION
5651 : !! Read a DDB block containing 1st order derivatives of energy.
5652 : !!
5653 : !!
5654 : !! INPUTS
5655 : !! ncid=netcdf identifier of a file open in reading mode.
5656 : !! iblok=index of the block we are setting.
5657 : !! iblok_d1E=index of the block we are reading in the d1E group.
5658 : !!
5659 : !! OUTPUT
5660 : !!
5661 : !! SOURCE
5662 :
5663 10 : subroutine ddb_read_d1E_nc(ddb, ncid, iblok, iblok_d1E)
5664 :
5665 : !Arguments -------------------------------
5666 : !scalars
5667 : class(ddb_type),intent(inout) :: ddb
5668 : integer,intent(in) :: ncid,iblok,iblok_d1E
5669 :
5670 : !Local variables -------------------------
5671 : !scalars
5672 : integer :: ncid_d1E
5673 : integer :: ncerr
5674 : !arrays
5675 : integer,allocatable :: flg_d1E(:,:)
5676 : real(dp),allocatable :: matrix_d1E(:,:,:)
5677 : ! ************************************************************************
5678 :
5679 10 : ncid_d1E = nctk_idgroup(ncid, 'd1E')
5680 :
5681 : ! Allocate temporary arrays
5682 30 : ABI_MALLOC(matrix_d1E, (2,3,ddb%mpert))
5683 30 : ABI_MALLOC(flg_d1E, (3,ddb%mpert))
5684 :
5685 50 : ncerr = nf90_get_var(ncid_d1E, nctk_idname(ncid_d1E, 'matrix_values'), matrix_d1E, start=[1,1,1,iblok_d1E])
5686 10 : NCF_CHECK(ncerr)
5687 40 : ncerr = nf90_get_var(ncid_d1E, nctk_idname(ncid_d1E, 'matrix_mask'), flg_d1E, start=[1,1,iblok_d1E])
5688 10 : NCF_CHECK(ncerr)
5689 :
5690 : ! Reshape
5691 10 : call ddb%set_d1matr(iblok, matrix_d1E, flg_d1E)
5692 :
5693 : ! Free memory
5694 10 : ABI_FREE(matrix_d1E)
5695 10 : ABI_FREE(flg_d1E)
5696 :
5697 10 : end subroutine ddb_read_d1E_nc
5698 : !!***
5699 :
5700 : !----------------------------------------------------------------------
5701 :
5702 : !!****f* m_ddb/ddb_read_d2E_nc
5703 : !! NAME
5704 : !! ddb_read_d2E_nc
5705 : !!
5706 : !! FUNCTION
5707 : !! Read a DDB block containing 2nd order derivatives of energy.
5708 : !!
5709 : !! INPUTS
5710 : !! ncid=netcdf identifier of a file open in reading mode.
5711 : !! iblok=index of the block we are setting.
5712 : !! iblok_d2E=index of the block we are reading in the d2E group.
5713 : !!
5714 : !! OUTPUT
5715 : !!
5716 : !! SOURCE
5717 :
5718 148 : subroutine ddb_read_d2E_nc(ddb, ncid, iblok, iblok_d2E, ddb_version)
5719 :
5720 : !Arguments -------------------------------
5721 : !scalars
5722 : class(ddb_type),intent(inout) :: ddb
5723 : integer,intent(in) :: ncid,iblok,iblok_d2E
5724 : integer,intent(in) :: ddb_version
5725 :
5726 : !Local variables -------------------------
5727 : !scalars
5728 : integer :: ncid_d2E
5729 : integer :: ncerr
5730 : integer, parameter :: cvrsio9_new=20240201
5731 : !arrays
5732 : real(dp) :: qpt(3)
5733 : integer,allocatable :: flg_d2E(:,:,:,:)
5734 : real(dp),allocatable :: matrix_d2E(:,:,:,:,:)
5735 : ! ************************************************************************
5736 :
5737 148 : ncid_d2E = nctk_idgroup(ncid, 'd2E')
5738 :
5739 : ! Allocate temporary arrays
5740 740 : ABI_MALLOC(matrix_d2E, (2,3,ddb%mpert,3,ddb%mpert))
5741 740 : ABI_MALLOC(flg_d2E, (3,ddb%mpert,3,ddb%mpert))
5742 :
5743 444 : ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'reduced_coordinates_of_qpoints'), qpt, start=[1,iblok_d2E])
5744 148 : NCF_CHECK(ncerr)
5745 592 : ddb%qpt(1:3,iblok) = qpt(:)
5746 296 : ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'qpoints_normalization'), ddb%nrm(1,iblok), start=[iblok_d2E])
5747 148 : NCF_CHECK(ncerr)
5748 : ! Read the perturbation frequency
5749 148 : if (ddb_version>=cvrsio9_new) then
5750 296 : ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'frequency'), ddb%omega(1,iblok), start=[iblok_d2E])
5751 148 : NCF_CHECK(ncerr)
5752 : else
5753 0 : ddb%omega(1,iblok)=0.d0
5754 : end if
5755 444 : ddb%omega(2:3,iblok)=0.d0
5756 :
5757 1036 : ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'matrix_values'), matrix_d2E, start=[1,1,1,1,1,iblok_d2E])
5758 148 : NCF_CHECK(ncerr)
5759 888 : ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'matrix_mask'), flg_d2E, start=[1,1,1,1,iblok_d2E])
5760 148 : NCF_CHECK(ncerr)
5761 :
5762 : ! Reshape
5763 148 : call ddb%set_d2matr(iblok, matrix_d2E, flg_d2E)
5764 :
5765 : ! Free memory
5766 148 : ABI_FREE(matrix_d2E)
5767 148 : ABI_FREE(flg_d2E)
5768 :
5769 148 : end subroutine ddb_read_d2E_nc
5770 : !!***
5771 :
5772 : !----------------------------------------------------------------------
5773 :
5774 : !!****f* m_ddb/ddb_read_d3E_nc
5775 : !! NAME
5776 : !! ddb_read_d3E_nc
5777 : !!
5778 : !! FUNCTION
5779 : !! Read a DDB block containing 3rd order derivatives of energy.
5780 : !!
5781 : !! INPUTS
5782 : !! ncid=netcdf identifier of a file open in reading mode.
5783 : !! iblok=index of the block we are setting.
5784 : !! iblok_d3E=index of the block we are reading in the d3E group.
5785 : !!
5786 : !! OUTPUT
5787 : !!
5788 : !! SOURCE
5789 :
5790 3 : subroutine ddb_read_d3E_nc(ddb, ncid, iblok, iblok_d3E, ddb_version)
5791 :
5792 : !Arguments -------------------------------
5793 : !scalars
5794 : class(ddb_type),intent(inout) :: ddb
5795 : integer,intent(in) :: ncid,iblok,iblok_d3E
5796 : integer,intent(in) :: ddb_version
5797 :
5798 : !Local variables -------------------------
5799 : !scalars
5800 : integer :: blktyp
5801 : integer :: ncid_d3E
5802 : integer :: ncerr
5803 : integer, parameter :: cvrsio9_new=20240201
5804 : !arrays
5805 : real(dp) :: qpt(3), nrm(3), omega(3)
5806 : real(dp),allocatable :: matrix_d3E(:,:,:,:,:,:,:)
5807 : integer,allocatable :: flg_d3E(:,:,:,:,:,:)
5808 : ! ************************************************************************
5809 :
5810 3 : ncid_d3E = nctk_idgroup(ncid, 'd3E')
5811 :
5812 : ! Allocate temporary arrays
5813 21 : ABI_MALLOC(matrix_d3E, (2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert))
5814 21 : ABI_MALLOC(flg_d3E, (3,ddb%mpert,3,ddb%mpert,3,ddb%mpert))
5815 :
5816 12 : ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[1,1,iblok_d3E],count=[1,3,1])
5817 3 : NCF_CHECK(ncerr)
5818 12 : ddb%qpt(1:3,iblok) = qpt(:)
5819 :
5820 12 : ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[2,1,iblok_d3E],count=[1,3,1])
5821 3 : NCF_CHECK(ncerr)
5822 12 : ddb%qpt(4:6,iblok) = qpt(:)
5823 :
5824 12 : ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[3,1,iblok_d3E],count=[1,3,1])
5825 3 : NCF_CHECK(ncerr)
5826 12 : ddb%qpt(7:9,iblok) = qpt(:)
5827 :
5828 9 : ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'qpoints_normalization'), nrm, start=[1,iblok_d3E],count=[3,1])
5829 3 : NCF_CHECK(ncerr)
5830 12 : ddb%nrm(:,iblok) = nrm(:)
5831 3 : if (ddb_version>=cvrsio9_new) then
5832 9 : ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'frequency'),omega,start=[1,iblok_d3E],count=[3,1])
5833 3 : NCF_CHECK(ncerr)
5834 12 : ddb%omega(1:3,iblok)=omega(:)
5835 : else
5836 0 : ddb%omega(:,iblok)=0.d0
5837 : end if
5838 :
5839 27 : NCF_CHECK(nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'matrix_values'), matrix_d3E, start=[1,1,1,1,1,1,1,iblok_d3E]))
5840 24 : NCF_CHECK(nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'matrix_mask'), flg_d3E, start=[1,1,1,1,1,1,iblok_d3E]))
5841 :
5842 :
5843 3 : blktyp = ddb%typ(iblok) ! Save block type so it doesnt get overwritten.
5844 :
5845 3 : call ddb%set_d3matr(iblok, matrix_d3E, flg_d3E)
5846 :
5847 3 : ddb%typ(iblok) = blktyp
5848 :
5849 : ! Free memory
5850 3 : ABI_FREE(matrix_d3E)
5851 3 : ABI_FREE(flg_d3E)
5852 :
5853 3 : end subroutine ddb_read_d3E_nc
5854 : !!***
5855 :
5856 : !----------------------------------------------------------------------
5857 :
5858 : !!****f* m_ddb/ddb_read_d2eig_nc
5859 : !! NAME
5860 : !! ddb_read_d2eig_nc
5861 : !!
5862 : !! FUNCTION
5863 : !! Read a DDB block containing 2nd order derivatives of eigenvalues.
5864 : !!
5865 : !! INPUTS
5866 : !! ncid=netcdf identifier of a file open in reading mode.
5867 : !! iblok=index of the block we are setting.
5868 : !! iblok_d2eig=index of the block we are reading in the d2eig group.
5869 : !!
5870 : !! OUTPUT
5871 : !!
5872 : !! SOURCE
5873 :
5874 44 : subroutine ddb_read_d2eig_nc(ddb, ncid, iblok, iblok_d2eig)
5875 :
5876 : !Arguments -------------------------------
5877 : !scalars
5878 : class(ddb_type),intent(inout) :: ddb
5879 : integer,intent(in) :: ncid,iblok
5880 : integer,intent(in),optional :: iblok_d2eig
5881 :
5882 : !Local variables -------------------------
5883 : !scalars
5884 : integer :: ncid_d2eig,ncerr
5885 : integer :: nkpt_file
5886 : integer :: nblok_d2eig
5887 : integer :: iblok_, iblok_d2eig_
5888 : integer :: iband, jband, bandshift, isppol, mband
5889 : integer :: ikpt,ipert1,idir1,ipert2,idir2,ii
5890 : character(len=500) :: msg
5891 : !arrays
5892 44 : integer,allocatable :: flg_d2eig(:,:,:,:)
5893 : real(dp) :: qpt(3)
5894 44 : real(dp),allocatable :: nrm(:)
5895 44 : real(dp),allocatable :: matrix_d2eig(:,:,:,:,:,:,:)
5896 44 : real(dp),allocatable :: matrix_d2eig_isppol(:,:,:,:,:,:,:)
5897 : ! ************************************************************************
5898 :
5899 44 : ncid_d2eig = nctk_idgroup(ncid, 'd2eig')
5900 :
5901 44 : if (present(iblok_d2eig)) then
5902 44 : iblok_d2eig_= iblok_d2eig
5903 : else
5904 : ! Recount the blok index
5905 0 : iblok_d2eig_ = 0
5906 0 : do iblok_=1,iblok
5907 0 : if (is_type_d2eig(ddb%typ(iblok_))) then
5908 0 : iblok_d2eig_ = iblok_d2eig_ + 1
5909 : end if
5910 : end do
5911 : end if
5912 :
5913 : ! Sanity check on dimensions
5914 44 : if (MOD(ddb%nband, ddb%nsppol)/=0) then
5915 0 : write(msg,'(a,i5,a,i5)') 'ddb was allocated with nband=',ddb%nband,&
5916 0 : ' but nsppol=',ddb%nsppol
5917 0 : ABI_ERROR(msg)
5918 : end if
5919 :
5920 : ! Read kpoints
5921 44 : NCF_CHECK(nctk_get_dim(ncid, "number_of_kpoints", nkpt_file))
5922 132 : ncerr = nf90_get_var(ncid, nctk_idname(ncid, 'reduced_coordinates_of_kpoints'), ddb%kpt, count=[3,nkpt_file])
5923 44 : NCF_CHECK(ncerr)
5924 :
5925 44 : mband = ddb%nband / ddb%nsppol
5926 :
5927 : ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5928 : 'reduced_coordinates_of_qpoints'),&
5929 : qpt,&
5930 132 : start=[1,iblok_d2eig_])
5931 44 : NCF_CHECK(ncerr)
5932 :
5933 440 : ddb%qpt(:,iblok) = zero
5934 176 : ddb%qpt(1:3,iblok) = qpt
5935 :
5936 : !ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5937 : ! 'qpoints_normalization'),&
5938 : ! nrm(1,iblok),&
5939 : ! start=[iblok_d2eig_])
5940 44 : NCF_CHECK(nctk_get_dim(ncid_d2eig, "number_of_d2eig_blocks", nblok_d2eig))
5941 132 : ABI_MALLOC(nrm, (nblok_d2eig))
5942 : ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5943 : 'qpoints_normalization'),&
5944 44 : nrm)
5945 44 : NCF_CHECK(ncerr)
5946 176 : ddb%nrm(:,iblok) = zero
5947 44 : ddb%nrm(1,iblok) = nrm(iblok_d2eig_)
5948 44 : ABI_FREE(nrm)
5949 :
5950 :
5951 308 : ABI_MALLOC(matrix_d2eig, (2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt))
5952 264 : ABI_MALLOC(matrix_d2eig_isppol, (2,3,ddb%mpert,3,ddb%mpert,mband,ddb%nkpt))
5953 220 : ABI_MALLOC(flg_d2eig, (3,ddb%mpert,3,ddb%mpert))
5954 :
5955 88 : do isppol=1,ddb%nsppol
5956 :
5957 : ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5958 : 'matrix_values'),&
5959 : matrix_d2eig_isppol,&
5960 440 : start=[1,1,1,1,1,1,1,isppol,iblok_d2eig_])
5961 44 : NCF_CHECK(ncerr)
5962 :
5963 88 : if (ddb%nsppol==1) then
5964 366772 : matrix_d2eig(:,:,:,:,:,:,:) = matrix_d2eig_isppol(:,:,:,:,:,:,:)
5965 : else
5966 0 : bandshift = (isppol - 1) * mband
5967 0 : do ikpt=1,ddb%nkpt
5968 0 : do iband=1,ddb%nband
5969 0 : jband = bandshift + iband
5970 0 : do ipert1=1,ddb%mpert
5971 0 : do idir1=1,3
5972 0 : do ipert2=1,ddb%mpert
5973 0 : do idir2=1,3
5974 0 : do ii=1,2
5975 : matrix_d2eig(ii,idir2,ipert2,idir1,ipert1,jband,ikpt)=&
5976 0 : matrix_d2eig_isppol(ii,idir2,ipert2,idir1,ipert1,iband,ikpt)
5977 : end do
5978 : end do
5979 : end do
5980 : end do
5981 : end do
5982 : end do
5983 : end do
5984 : end if
5985 : end do
5986 :
5987 : ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,&
5988 : 'matrix_mask'),&
5989 : flg_d2eig,&
5990 264 : start=[1,1,1,1,iblok_d2eig_])
5991 44 : NCF_CHECK(ncerr)
5992 :
5993 : ! Store values
5994 44 : call ddb%set_d2eig(iblok, matrix_d2eig, flg_d2eig)
5995 :
5996 : ! Free memory
5997 44 : ABI_FREE(matrix_d2eig)
5998 44 : ABI_FREE(matrix_d2eig_isppol)
5999 44 : ABI_FREE(flg_d2eig)
6000 :
6001 44 : end subroutine ddb_read_d2eig_nc
6002 : !!***
6003 :
6004 : !----------------------------------------------------------------------
6005 :
6006 : !!****f* m_ddb/ddb_set_d3matr
6007 : !! NAME
6008 : !! ddb_set_d3matr
6009 : !!
6010 : !! FUNCTION
6011 : !! Set values for the third-order derivative matrix.
6012 : !!
6013 : !! INPUTS
6014 : !! iblok=index of the block we are setting.
6015 : !! d2matr=the third-order derivative matrix.
6016 : !! flg=flag to indicate presence of a given element.
6017 : !! lw=whether this type of perturbation correspond to longwave derivatives
6018 : !!
6019 : !! OUTPUT
6020 : !!
6021 : !! SOURCE
6022 :
6023 44 : subroutine ddb_set_d3matr(ddb, iblok, d3matr, flg, lw)
6024 :
6025 : !Arguments -------------------------------
6026 : !array
6027 : class(ddb_type),intent(inout) :: ddb
6028 : real(dp),intent(in) :: d3matr(2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)
6029 : integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)
6030 : !scalars
6031 : integer,intent(in) :: iblok
6032 : logical,intent(in),optional :: lw
6033 :
6034 : !Local variables -------------------------
6035 : !scalars
6036 : integer :: idir1,idir2,idir3,ipert1,ipert2,ipert3,index,mpert
6037 : ! ************************************************************************
6038 :
6039 44 : mpert = ddb%mpert
6040 :
6041 : ! GA: Should be consistent among all ddb_set_dxmatr routines
6042 : ! and alway have options to specify block type...
6043 44 : ddb%typ(iblok) = BLKTYP_d3E_xx
6044 44 : if (present(lw)) then
6045 17 : if (lw) then
6046 17 : ddb%typ(iblok) = BLKTYP_d3E_lw
6047 : end if
6048 : end if
6049 :
6050 502 : do ipert1=1,mpert
6051 1876 : do idir1=1,3
6052 18788 : do ipert2=1,mpert
6053 69198 : do idir2=1,3
6054 835992 : do ipert3=1,mpert
6055 3123540 : do idir3=1,3
6056 :
6057 : index = idir1 + 3*((ipert1-1)+mpert*((idir2-1) + &
6058 2304504 : & 3*((ipert2-1)+mpert*((idir3-1) + 3*(ipert3-1)))))
6059 :
6060 2304504 : ddb%flg(index,iblok) = flg(idir1,ipert1,idir2,ipert2,idir3,ipert3)
6061 7681680 : ddb%val(:,index,iblok)= d3matr(:,idir1,ipert1,idir2,ipert2,idir3,ipert3)
6062 :
6063 : end do
6064 : end do
6065 : end do
6066 : end do
6067 : end do
6068 : end do
6069 :
6070 :
6071 44 : end subroutine ddb_set_d3matr
6072 : !!***
6073 :
6074 : !----------------------------------------------------------------------
6075 :
6076 : !!****f* m_ddb/ddb_get_d3matr
6077 : !! NAME
6078 : !! ddb_get_d3matr
6079 : !!
6080 : !! FUNCTION
6081 : !! Transform the third-order derivative matrix
6082 : !! from flat indices to real tensor d3matr(cplex,ncart,natom,ncart,natom,ncart,natom)
6083 : !!
6084 : !! INPUTS
6085 : !! iblok=index of the block to get.
6086 : !!
6087 : !! OUTPUT
6088 : !! d3matr=the third-order derivative matrix.
6089 : !! flg=flag to indicate presence of a given element.
6090 : !!
6091 : !! SOURCE
6092 :
6093 36 : subroutine ddb_get_d3matr(ddb, iblok, d3matr, flg)
6094 :
6095 : !Arguments -------------------------------
6096 : !array
6097 : class(ddb_type),intent(inout) :: ddb
6098 : integer,intent(in) :: iblok
6099 : real(dp), allocatable, intent(out) :: d3matr(:,:,:,:,:,:,:)
6100 : integer, allocatable, intent(out) :: flg(:,:,:,:,:,:)
6101 : !scalars
6102 :
6103 : !Local variables -------------------------
6104 : !scalars
6105 : integer :: ii,idir1,idir2,idir3,ipert1,ipert2,ipert3
6106 : ! ************************************************************************
6107 :
6108 252 : ABI_MALLOC(d3matr, (2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert))
6109 252 : ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert,3,ddb%mpert))
6110 :
6111 8794146 : d3matr = zero
6112 :
6113 : ii=0
6114 435 : do ipert3=1,ddb%mpert
6115 1632 : do idir3=1,3
6116 18327 : do ipert2=1,ddb%mpert
6117 68121 : do idir2=1,3
6118 939483 : do ipert1=1,ddb%mpert
6119 3540429 : do idir1=1,3
6120 2617677 : ii=ii+1
6121 2617677 : flg(idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%flg(ii,iblok)
6122 3490236 : if (ddb%flg(ii,iblok) > 0) then
6123 4433 : d3matr(1,idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%val(1,ii,iblok)
6124 4433 : d3matr(2,idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%val(2,ii,iblok)
6125 : end if
6126 : end do
6127 : end do
6128 : end do
6129 : end do
6130 : end do
6131 : end do
6132 :
6133 36 : end subroutine ddb_get_d3matr
6134 : !!***
6135 :
6136 : !----------------------------------------------------------------------
6137 :
6138 : !!****f* m_ddb/ddb_get_d2eig
6139 : !! NAME
6140 : !! ddb_get_d2eig
6141 : !!
6142 : !! FUNCTION
6143 : !! Transform the second-order derivative matrix of eigenvalues
6144 : !! from flat indices to real tensor d2eig(cplex,ncart,natom,ncart,natom,nband,nkpt)
6145 : !!
6146 : !! INPUTS
6147 : !! iblok=index of the block to get.
6148 : !!
6149 : !! OUTPUTS
6150 : !! d2eig(cplex,ncart,natom,ncart,natom,nband,nkpt) =
6151 : !! the second-order derivative matrix of eigenvalues
6152 : !! with the isppol index wrapped in nband.
6153 : !! flg(ncart,natom,ncart,natom)=flag to indicate presence of a given element.
6154 : !!
6155 : !! SOURCE
6156 :
6157 117 : subroutine ddb_get_d2eig(ddb, d2eig, flg, iblok)
6158 :
6159 : !Arguments -------------------------------
6160 : !array
6161 : class(ddb_type),intent(inout) :: ddb
6162 : real(dp), allocatable, intent(out) :: d2eig(:,:,:,:,:,:,:)
6163 : integer,intent(in) :: iblok
6164 : integer, allocatable, intent(out) :: flg(:,:,:,:)
6165 : !scalars
6166 :
6167 : !Local variables -------------------------
6168 : !scalars
6169 : integer :: ii,idir1,idir2,ipert1,ipert2,iband,ikpt
6170 : ! ************************************************************************
6171 :
6172 819 : ABI_MALLOC(d2eig, (2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt))
6173 585 : ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert))
6174 :
6175 2244086 : d2eig = zero
6176 :
6177 1828 : do ikpt=1,ddb%nkpt
6178 18678 : do iband=1,ddb%nband
6179 16850 : ii=0
6180 52133 : do ipert2=1,ddb%mpert
6181 151138 : do idir2=1,3
6182 343400 : do ipert1=1,ddb%mpert
6183 937164 : do idir1=1,3
6184 627336 : ii=ii+1
6185 627336 : flg(idir1,ipert1,idir2,ipert2) = ddb%flg(ii,iblok)
6186 836448 : if (ddb%flg(ii,iblok) > 0) then
6187 627336 : d2eig(1,idir1,ipert1,idir2,ipert2,iband,ikpt) = ddb%eig2dval(1,ii,iband,ikpt)
6188 627336 : d2eig(2,idir1,ipert1,idir2,ipert2,iband,ikpt) = ddb%eig2dval(2,ii,iband,ikpt)
6189 : end if
6190 : end do
6191 : end do
6192 : end do
6193 : end do
6194 : end do
6195 : end do
6196 :
6197 117 : end subroutine ddb_get_d2eig
6198 : !!***
6199 :
6200 : !----------------------------------------------------------------------
6201 :
6202 : !!****f* m_ddb/ddb_set_d2eig
6203 : !! NAME
6204 : !! ddb_set_d2eig
6205 : !!
6206 : !! FUNCTION
6207 : !! Set values for the second-order derivatives of eigenvalues.
6208 : !!
6209 : !! INPUTS
6210 : !! iblok=index of the block we are setting.
6211 : !! d2eig=the second-order derivative of eigenvalues.
6212 : !! flg=flag to indicate presence of a given element.
6213 : !!
6214 : !! OUTPUT
6215 : !!
6216 : !! NOTE
6217 : !! Does not handle spin index. Also, sometimes, d2eig is available with flat index
6218 : !! SOURCE
6219 :
6220 44 : subroutine ddb_set_d2eig(ddb, iblok, d2eig, flg)
6221 :
6222 : !Arguments -------------------------------
6223 : !array
6224 : class(ddb_type),intent(inout) :: ddb
6225 : real(dp),intent(in) :: d2eig(2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt)
6226 : integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert)
6227 : !scalars
6228 : integer,intent(in) :: iblok
6229 :
6230 : !Local variables -------------------------
6231 : !scalars
6232 : integer :: idir1,idir2,ipert1,ipert2,index,iband,ikpt,ii
6233 : ! ************************************************************************
6234 :
6235 432 : do ikpt=1,ddb%nkpt
6236 2740 : do iband=1,ddb%nband
6237 2308 : ii = 0
6238 7184 : do ipert2=1,ddb%mpert
6239 20260 : do idir2=1,3
6240 52560 : do ipert1=1,ddb%mpert
6241 151896 : do idir1=1,3
6242 103824 : index=idir1+3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1)))
6243 103824 : ddb%eig2dval(1,index,iband,ikpt)=d2eig(1,idir1,ipert1,idir2,ipert2,iband,ikpt)
6244 103824 : ddb%eig2dval(2,index,iband,ikpt)=d2eig(2,idir1,ipert1,idir2,ipert2,iband,ikpt)
6245 138432 : ddb%flg(index,iblok)=flg(idir1,ipert1,idir2,ipert2)
6246 : end do !idir1
6247 : end do !pert1
6248 : end do !idir2
6249 : end do !pert2
6250 : end do !band
6251 : end do !kpt
6252 :
6253 44 : end subroutine ddb_set_d2eig
6254 : !!***
6255 :
6256 : !----------------------------------------------------------------------
6257 :
6258 : !!****f* m_ddb/ddb_set_d2eig_reshape
6259 : !! NAME
6260 : !! ddb_set_d2eig_reshape
6261 : !!
6262 : !! FUNCTION
6263 : !! Set values for the second-order derivatives of eigenvalues
6264 : !! and reshape the array received.
6265 : !!
6266 : !! INPUTS
6267 : !! iblok=index of the block we are setting.
6268 : !! d2eig=the second-order derivative of eigenvalues.
6269 : !! flg=flag to indicate presence of a given element.
6270 : !! blktyp=block type
6271 : !! 5->real part
6272 : !! 6->imaginary part (broadening)
6273 : !!
6274 : !! OUTPUT
6275 : !!
6276 : !! SOURCE
6277 :
6278 137 : subroutine ddb_set_d2eig_reshape(ddb, iblok, d2eig, flg, blktyp)
6279 :
6280 : !Arguments -------------------------------
6281 : !array
6282 : class(ddb_type),intent(inout) :: ddb
6283 : real(dp),intent(in) :: d2eig(2,ddb%nband*ddb%nsppol,ddb%nkpt,3,ddb%mpert,3,ddb%mpert)
6284 : integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert)
6285 : !scalars
6286 : integer,intent(in) :: iblok
6287 : integer,intent(in),optional :: blktyp
6288 :
6289 : !Local variables -------------------------
6290 : !scalars
6291 : integer :: idir1,idir2,ipert1,ipert2,index,iband,ikpt,ii,mband
6292 : ! ************************************************************************
6293 :
6294 137 : ddb%typ(iblok) = BLKTYP_d2eig_re
6295 137 : if (present(blktyp)) ddb%typ(iblok) = blktyp
6296 :
6297 : ! Spin polarization is wrapped in band number
6298 137 : mband = ddb%nband * ddb%nsppol
6299 :
6300 2200 : do ikpt=1,ddb%nkpt
6301 22068 : do iband=1,mband
6302 19868 : ii = 0
6303 61539 : do ipert2=1,ddb%mpert
6304 178300 : do idir2=1,3
6305 403760 : do ipert1=1,ddb%mpert
6306 1100136 : do idir1=1,3
6307 735984 : index=idir1+3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1)))
6308 735984 : ddb%flg(index,iblok)=flg(idir1,ipert1,idir2,ipert2)
6309 981312 : if (ddb%flg(index,iblok) > 0) then
6310 735984 : ddb%eig2dval(1,index,iband,ikpt)=d2eig(1,iband,ikpt,idir1,ipert1,idir2,ipert2)
6311 735984 : ddb%eig2dval(2,index,iband,ikpt)=d2eig(2,iband,ikpt,idir1,ipert1,idir2,ipert2)
6312 : end if
6313 : end do !idir1
6314 : end do !pert1
6315 : end do !idir2
6316 : end do !pert2
6317 : end do !band
6318 : end do !kpt
6319 :
6320 137 : end subroutine ddb_set_d2eig_reshape
6321 : !!***
6322 :
6323 : !----------------------------------------------------------------------
6324 :
6325 : !!****f* m_ddb/ddb_to_dtset
6326 : !! NAME
6327 : !! ddb_to_dtset
6328 : !!
6329 : !! FUNCTION
6330 : !! Initialize a dataset object from ddb.
6331 : !!
6332 : !! FIXME: I don't understand the goal of this routine.
6333 : !! The dtset constructed from the DDB won't be equal to the one used to generate the DDB
6334 : !! There's only one safe way to init dtset i.e. from file by calling the parser
6335 : !!
6336 : !! INPUTS
6337 : !!
6338 : !! OUTPUT
6339 : !!
6340 : !! SOURCE
6341 :
6342 :
6343 0 : subroutine ddb_to_dtset(comm, dtset, filename, psps)
6344 :
6345 : !Arguments -------------------------------
6346 : integer,intent(in) :: comm
6347 : type(dataset_type),intent(inout) :: dtset
6348 : type(pseudopotential_type),intent(inout) :: psps
6349 : ! type(pawtab_type),intent(inout) :: pawtab(psps%ntypat*psps%usepaw)
6350 : character(len=*),intent(in) :: filename
6351 : !Local variables -------------------------
6352 : integer :: mxnimage,unddb
6353 : !integer :: ii, nn
6354 0 : type(ddb_hdr_type) :: ddb_hdr
6355 : ! ************************************************************************
6356 :
6357 : ABI_UNUSED(psps%usepaw)
6358 :
6359 : !Set variables
6360 0 : mxnimage = 1 ! Only 1 image in the DDB
6361 :
6362 : ! Must read natom from the DDB before being able to allocate some arrays needed for invars9
6363 0 : unddb = get_unit()
6364 0 : call ddb_hdr%open_read(filename,comm=comm)
6365 0 : call ddb_hdr%close()
6366 : !close ddb file, just want to read the headers
6367 0 : dtset%ngfft = ddb_hdr%ngfft
6368 :
6369 : ! Copy scalars from ddb
6370 0 : dtset%natom = ddb_hdr%natom
6371 0 : dtset%mband = ddb_hdr%mband
6372 0 : dtset%nkpt = ddb_hdr%nkpt
6373 0 : dtset%nsym = ddb_hdr%msym
6374 0 : dtset%ntypat = ddb_hdr%ntypat
6375 0 : dtset%nspden = ddb_hdr%nspden
6376 0 : dtset%nspinor = ddb_hdr%nspinor
6377 0 : dtset%nsppol = ddb_hdr%nsppol
6378 0 : dtset%occopt = ddb_hdr%occopt
6379 0 : dtset%usepaw = ddb_hdr%usepaw
6380 0 : dtset%intxc = ddb_hdr%intxc
6381 0 : dtset%ixc = ddb_hdr%ixc
6382 0 : dtset%iscf = ddb_hdr%iscf
6383 0 : dtset%dilatmx = ddb_hdr%dilatmx
6384 0 : dtset%ecut = ddb_hdr%ecut
6385 0 : dtset%ecutsm = ddb_hdr%ecutsm
6386 0 : dtset%pawecutdg = ddb_hdr%pawecutdg
6387 0 : dtset%kptnrm = ddb_hdr%kptnrm
6388 0 : dtset%dfpt_sciss = ddb_hdr%dfpt_sciss
6389 0 : dtset%tolwfr = 1.0_dp ! dummy
6390 0 : dtset%tphysel = ddb_hdr%tphysel
6391 0 : dtset%tsmear = ddb_hdr%tsmear
6392 :
6393 : ! Copy arrays from ddb
6394 0 : ABI_REMALLOC(dtset%acell_orig, (3,mxnimage))
6395 0 : dtset%acell_orig(1:3,1) = ddb_hdr%acell(:)
6396 :
6397 0 : ABI_REMALLOC(dtset%rprim_orig, (3,3,mxnimage))
6398 0 : dtset%rprim_orig(1:3,1:3,1) = ddb_hdr%rprim(:,:)
6399 :
6400 0 : ABI_REMALLOC(dtset%rprimd_orig, (3,3,mxnimage))
6401 0 : dtset%rprimd_orig(:,1,1) = ddb_hdr%rprim(:,1) * dtset%acell_orig(1,1)
6402 0 : dtset%rprimd_orig(:,2,1) = ddb_hdr%rprim(:,2) * dtset%acell_orig(2,1)
6403 0 : dtset%rprimd_orig(:,3,1) = ddb_hdr%rprim(:,3) * dtset%acell_orig(3,1)
6404 :
6405 0 : ABI_REMALLOC(dtset%amu_orig,(dtset%ntypat,mxnimage))
6406 0 : dtset%amu_orig(:,1) = ddb_hdr%amu(:)
6407 :
6408 0 : ABI_REMALLOC(dtset%typat, (dtset%natom))
6409 0 : dtset%typat(:) = ddb_hdr%typat(1:ddb_hdr%matom)
6410 :
6411 0 : ABI_REMALLOC(dtset%spinat, (3,dtset%natom))
6412 0 : dtset%spinat(:,:) = ddb_hdr%spinat(1:3,1:ddb_hdr%matom)
6413 :
6414 : #ifdef FC_LLVM
6415 : ! LLVM 16 doesn't recognize this macro here
6416 : ABI_REMALLOC(dtset%xred_orig, (3,dtset%natom,mxnimage) )
6417 : #else
6418 0 : ABI_REMALLOC(dtset%xred_orig, (3,dtset%natom,mxnimage))
6419 : #endif
6420 0 : dtset%xred_orig(:,:,1) = ddb_hdr%xred(1:3,1:ddb_hdr%matom)
6421 :
6422 0 : ABI_REMALLOC(dtset%ziontypat, (dtset%ntypat))
6423 0 : dtset%ziontypat(1:ddb_hdr%mtypat) = ddb_hdr%zion(1:ddb_hdr%mtypat)
6424 :
6425 0 : ABI_REMALLOC(dtset%znucl,(dtset%ntypat))
6426 0 : dtset%znucl(:) = ddb_hdr%znucl(1:ddb_hdr%mtypat)
6427 :
6428 0 : ABI_REMALLOC(dtset%nband,(dtset%nkpt))
6429 0 : dtset%nband(:) = ddb_hdr%nband(1:ddb_hdr%mkpt*ddb_hdr%nsppol)
6430 :
6431 0 : ABI_REMALLOC(dtset%symafm,(dtset%nsym))
6432 0 : dtset%symafm(:) = ddb_hdr%symafm(1:ddb_hdr%msym)
6433 :
6434 0 : ABI_REMALLOC(dtset%symrel, (3,3,dtset%nsym) )
6435 0 : dtset%symrel(:,:,:) = ddb_hdr%symrel(1:3,1:3,1:ddb_hdr%msym)
6436 :
6437 0 : ABI_REMALLOC(dtset%tnons,(3,dtset%nsym))
6438 0 : dtset%tnons(:,:) = ddb_hdr%tnons(1:3,1:ddb_hdr%msym)
6439 :
6440 0 : ABI_REMALLOC(dtset%kpt,(3,dtset%nkpt))
6441 0 : dtset%kpt(:,:) = ddb_hdr%kpt(1:3,1:ddb_hdr%mkpt)
6442 :
6443 0 : ABI_REMALLOC(dtset%wtk,(dtset%nkpt))
6444 0 : dtset%wtk(:) = ddb_hdr%wtk(1:ddb_hdr%mkpt)
6445 :
6446 : ! GA: I had way too much problems implementing pawtab_copy.
6447 : ! The script check-libpaw would report all sorts of errors.
6448 : ! Therefore, I do a cheap copy here, copying only the relevant info.
6449 : !call pawtab_copy(pawtab, ddb_hdr%pawtab)
6450 : ! nn=size(pawtab)
6451 : ! if (nn.gt.0) then
6452 : ! do ii=1,nn
6453 : ! pawtab(ii)%basis_size =ddb_hdr%pawtab(ii)%basis_size
6454 : ! pawtab(ii)%lmn_size =ddb_hdr%pawtab(ii)%lmn_size
6455 : ! pawtab(ii)%lmn2_size =ddb_hdr%pawtab(ii)%lmn2_size
6456 : ! pawtab(ii)%rpaw =ddb_hdr%pawtab(ii)%rpaw
6457 : ! pawtab(ii)%rshp =ddb_hdr%pawtab(ii)%rshp
6458 : ! pawtab(ii)%shape_type =ddb_hdr%pawtab(ii)%shape_type
6459 : ! if (allocated(pawtab(ii)%dij0)) then
6460 : ! call alloc_copy(ddb_hdr%pawtab(ii)%dij0, pawtab(ii)%dij0)
6461 : ! end if
6462 : ! end do
6463 : ! end if
6464 :
6465 0 : call ddb_hdr%free()
6466 :
6467 0 : end subroutine ddb_to_dtset
6468 : !!***
6469 :
6470 : !----------------------------------------------------------------------
6471 :
6472 : !!****f* m_ddb/merge_ddb
6473 : !! NAME
6474 : !! merge_ddb
6475 : !!
6476 : !! FUNCTION
6477 : !! Read a list of ddb files and merge them into a single ddb object.
6478 : !!
6479 : !! INPUTS
6480 : !! nddb=number of DDBs to merge
6481 : !! filenames=names of input DDB files
6482 : !! outfile=name of the merged DDB file to be written
6483 : !! dscrpt=string description of the final ddb.
6484 : !! chkopt=option for consistency checks between DDB files
6485 : !! (0 --> do not check header consistency between files)
6486 : !! (1 --> check header consistency between files)
6487 : !!
6488 : !! OUTPUT
6489 : !!
6490 : !! SOURCE
6491 :
6492 47 : subroutine merge_ddb(nddb, filenames, outfile, dscrpt, chkopt)
6493 :
6494 : !Arguments -------------------------------
6495 : !scalars
6496 : integer,intent(in) :: nddb
6497 : integer,intent(in) :: chkopt
6498 : !arrays
6499 : character(len=fnlen),intent(in) :: filenames(nddb)
6500 : character(len=fnlen),intent(in) :: outfile, dscrpt
6501 :
6502 : !Local variables -------------------------
6503 : !scalars
6504 : integer,parameter :: master=0
6505 : integer :: iddb, ddbvsn
6506 : ! integer :: ddbun
6507 : integer :: iddb_mkpt, iddb_psps
6508 : integer :: dimekb, matom, mband, mblok, mkpt, nsppol
6509 : integer :: msize, msize_, mtypat, lmnmax, usepaw, msym, mpert
6510 : integer :: nblok, iblok, iblok1, iblok2
6511 : ! integer :: tmerge, nq, nw
6512 : integer :: comm
6513 : logical :: eig2d, can_merge
6514 : integer,parameter :: prtvol=-1, brav=1
6515 : real(dp),parameter :: qtol=2.0d-8, wtol=2.0d-8
6516 : ! real(dp) :: diff,sdiff
6517 : character(len=500) :: msg
6518 47 : type(ddb_type) :: ddb, ddb2
6519 4841 : type(ddb_hdr_type) :: ddb_hdr, ddb_hdr2
6520 2444 : type(crystal_t) :: crystal
6521 : ! ************************************************************************
6522 :
6523 47 : comm = xmpi_world
6524 :
6525 : ! -----------------------------------------------
6526 : ! Read all headers and evaluate arrays dimensions
6527 : ! -----------------------------------------------
6528 47 : if (xmpi_comm_rank(comm) == master) then
6529 47 : call wrtout(std_out, sjoin(ch10, " merge_ddb: Reading all headers."))
6530 : end if
6531 :
6532 47 : dimekb=0 ; matom=0 ; mband=0 ; mblok=0 ; mkpt=0 ; mpert=0
6533 47 : msize=0 ; mtypat=0 ; lmnmax=0 ; usepaw=0
6534 47 : iddb_mkpt = 1 ; iddb_psps = nddb
6535 47 : msym=192
6536 :
6537 47 : eig2d = .False.
6538 290 : do iddb=1,nddb
6539 :
6540 243 : call ddb_hdr%open_read(filenames(iddb), comm, dimonly=1)
6541 :
6542 243 : matom=max(matom,ddb_hdr%matom)
6543 :
6544 : ! GA: Should get mkpt from the ddb containing d2eig, if any.
6545 : ! In facts, since I removed comparison on the k-points
6546 : ! in ddb_hdr_compare, I should add a check to make sure
6547 : ! k-points are consistent when merging d2eig data.
6548 243 : if (ddb_hdr%mkpt > mkpt) then
6549 59 : mkpt = ddb_hdr%mkpt
6550 59 : iddb_mkpt = iddb
6551 : end if
6552 : !mkpt=max(mkpt,ddb_hdr%mkpt)
6553 243 : mtypat=max(mtypat,ddb_hdr%mtypat)
6554 243 : msym=max(msym,ddb_hdr%msym)
6555 243 : mband=max(mband,ddb_hdr%mband)
6556 243 : dimekb=max(dimekb,ddb_hdr%psps%dimekb)
6557 243 : lmnmax=max(lmnmax,ddb_hdr%psps%lmnmax)
6558 243 : usepaw=max(usepaw,ddb_hdr%usepaw)
6559 243 : nsppol = ddb_hdr%nsppol
6560 :
6561 : ! Count the blocks
6562 243 : mblok=mblok+ddb_hdr%nblok
6563 :
6564 : ! Figure out if we are merging eig2d files
6565 243 : eig2d = ddb_hdr%has_d2eig
6566 :
6567 : ! Figure out if we are merging d3E blocks and compute msize accordingly
6568 243 : mpert = max(mpert,ddb_hdr%mpert)
6569 243 : msize_ = 3 * mpert * 3 * mpert
6570 243 : if (ddb_hdr%has_d3E_xx) msize_ = msize_ * 3 * mpert
6571 243 : msize = max(msize, msize_)
6572 :
6573 290 : if (ddb_hdr%with_psps>0 .or. ddb_hdr%psps%usepaw > 0) then
6574 161 : iddb_psps = iddb
6575 : end if
6576 : end do
6577 :
6578 47 : ddb%nsppol = nsppol
6579 :
6580 : ! ---------------
6581 : ! Allocate arrays
6582 : ! ---------------
6583 47 : if (eig2d) then
6584 : ! GA: We need to multiply mband by nsppol (to keep array rank below 8)
6585 6 : call ddb%malloc(msize, mblok, matom, mtypat, mpert, mkpt, mband * nsppol)
6586 : else
6587 41 : call ddb%malloc(msize, mblok, matom, mtypat, mpert)
6588 : end if
6589 :
6590 : ! -------------------------------------------------------
6591 : ! Initialize the output ddb_hdr using the first input ddb
6592 : ! -------------------------------------------------------
6593 :
6594 : ! GA: The last ddb is usually the one that contains the most info on pseudos
6595 : ! however, we should check them all and figure out which one has
6596 : ! the most info.
6597 :
6598 47 : call ddb_hdr%free() ! GA: why do I need this? Try to remove
6599 : call ddb_hdr%open_read(filenames(1), comm, &
6600 : matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,&
6601 47 : msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw)
6602 47 : call ddb_hdr%close()
6603 47 : ddb_hdr%mpert = mpert
6604 47 : ddb_hdr%msize = msize
6605 :
6606 : ! GA: We are setting mkpt at initialization,
6607 : ! but netcdf file declares dimension with nkpt.
6608 : ! TODO: Should check consistency of nkpt
6609 : ! among of all blocks containing eig2d data.
6610 :
6611 : ! ==================
6612 : ! Read all databases
6613 : ! ==================
6614 :
6615 47 : nblok = 0
6616 :
6617 290 : do iddb=1,nddb
6618 :
6619 : ! Open the corresponding input DDB, and read the database file information
6620 243 : write(msg, '(a,a,i6)' )ch10,' read the input derivative database number',iddb
6621 243 : call wrtout(std_out,msg)
6622 :
6623 : ! Note: it is necessary to specify mkpt, otherwise the comparison will crash
6624 : call ddb_hdr2%open_read(filenames(iddb), comm, &
6625 : matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,&
6626 243 : msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw)
6627 243 : ddbvsn=ddb_hdr2%ddb_version
6628 243 : call ddb_hdr2%close()
6629 :
6630 243 : if (chkopt==1)then
6631 :
6632 : ! Compare the current DDB and input DDB information.
6633 : ! In case of an inconsistency, halt the execution.
6634 243 : call wrtout(std_out, ' compare the current and input DDB information')
6635 243 : call ddb_hdr%compare(ddb_hdr2)
6636 :
6637 : else
6638 : ! No comparison between the current DDB and input DDB information.
6639 0 : call wrtout(std_out,msg)
6640 : write(msg, '(3a)' )&
6641 0 : 'No comparison/check is performed for the current and input DDB information ',ch10,&
6642 0 : 'because argument --nostrict was passed to the command line. '
6643 0 : ABI_COMMENT(msg)
6644 : end if
6645 :
6646 243 : if (chkopt==1 .or. usepaw==1) then
6647 243 : call ddb_hdr%copy_missing_variables(ddb_hdr2)
6648 : end if
6649 :
6650 : ! GA: In principle, this could be done only once,
6651 : ! but I could not managed to do that without failing test v8[07].
6652 243 : if (iddb == iddb_psps) then
6653 47 : call ddb_hdr%copy_psps_from(ddb_hdr2)
6654 : end if
6655 :
6656 243 : call ddb_hdr2%free()
6657 :
6658 : ! Now read the whole DDB
6659 243 : call ddb2%from_file(filenames(iddb), ddb_hdr2, crystal, comm, prtvol, raw=1)
6660 243 : call crystal%free()
6661 243 : call ddb_hdr2%free()
6662 :
6663 : ! --------------------------------------------------------------
6664 : ! Double loop over the blocks of the last ddb and the output ddb
6665 : ! --------------------------------------------------------------
6666 :
6667 527 : do iblok2=1,ddb2%nblok
6668 :
6669 284 : can_merge = .false.
6670 985 : do iblok1=1, nblok
6671 :
6672 784 : can_merge = ddb%can_merge_blocks(ddb2, iblok1, iblok2, ddbvsn)
6673 :
6674 985 : if (can_merge) then
6675 83 : write(msg, '(a,i5,a,a)' )' merge block #',iblok2,' from file ', filenames(iddb)
6676 83 : call wrtout(std_out,msg)
6677 83 : iblok = iblok1 ! Merge with previous block
6678 83 : exit
6679 : end if
6680 : end do
6681 :
6682 284 : if (.not. can_merge) then
6683 201 : write(msg, '(a,i5,a,a)' )' add block #',iblok2,' from file ', filenames(iddb)
6684 201 : call wrtout(std_out,msg)
6685 201 : nblok = nblok + 1
6686 201 : iblok = nblok
6687 : end if
6688 :
6689 527 : call ddb%merge_blocks(ddb2, iblok, iblok2, ddbvsn)
6690 :
6691 : end do ! iblok2
6692 :
6693 : ! Free memory
6694 290 : call ddb2%free()
6695 :
6696 : end do ! iddb
6697 :
6698 :
6699 :
6700 47 : ddb_hdr%nblok = nblok
6701 47 : ddb%nblok = nblok
6702 47 : ddb_hdr%dscrpt = dscrpt
6703 :
6704 47 : call ddb_hdr%set_typ(ddb%nblok, ddb%typ)
6705 :
6706 47 : ddb_hdr%mpert = mpert ! This is done anyway at writing
6707 :
6708 : ! Summarize the merging phase
6709 47 : write(msg, '(a,i6,a)' )' Final DDB has ',nblok,' blocks.'
6710 47 : call wrtout(std_out,msg)
6711 :
6712 : ! Always use format specified with output filename.
6713 : ! GA: Might need an extra variable to enforce a different iomode
6714 47 : ddb_hdr%iomode = iomode_from_fname(outfile)
6715 :
6716 : ! GA: This is because netcdf format has more info than txt
6717 : ! and psps might be initialized even if with_psps==0
6718 : ! Very weird that I have to do this.
6719 : ! TODO Do not enforce with_psps=1. Change the test reference instead.
6720 47 : if (ddb_hdr%iomode/=IO_MODE_ETSF) then
6721 46 : if (ddb_hdr%with_psps==0) then
6722 1 : ddb_hdr%psps%dimekb = 0
6723 1 : ddb_hdr%psps%lmnmax = 0
6724 1 : ABI_SFREE(ddb_hdr%psps%ekb)
6725 1 : ABI_SFREE(ddb_hdr%psps%indlmn)
6726 4 : ABI_MALLOC(ddb_hdr%psps%ekb,(ddb_hdr%psps%dimekb,ddb_hdr%mtypat))
6727 4 : ABI_MALLOC(ddb_hdr%psps%indlmn,(6,ddb_hdr%psps%lmnmax,ddb_hdr%mtypat))
6728 3 : ddb_hdr%psps%ekb = zero
6729 3 : ddb_hdr%psps%indlmn = zero
6730 : end if
6731 : end if
6732 :
6733 : ! Enforce full initialization, regardless of DDB content
6734 47 : ddb_hdr%with_psps=1
6735 47 : ddb_hdr%with_dfpt_vars=1
6736 :
6737 : ! Write the final ddb to file.
6738 47 : if (.not. eig2d) then
6739 41 : call ddb%write(ddb_hdr, outfile)
6740 : end if
6741 :
6742 : ! =================================
6743 : ! Second derivatives of eigenvalues
6744 : ! =================================
6745 : if (eig2d) then
6746 :
6747 : ! GA: Here we assume that the blocks are complete wrt perturbations.
6748 : ! No merging of blocks occurs.
6749 : ! TODO: Implement merging of partial d2eig blocks
6750 :
6751 278 : ddb%kpt(:,:) = ddb_hdr%kpt(:,:)
6752 :
6753 : ! Open the output DDB and write the header
6754 6 : call ddb_hdr%open_write(outfile, with_psps=1, comm=comm)
6755 :
6756 6 : iblok = 0
6757 26 : do iddb=1,nddb
6758 :
6759 : call ddb_hdr2%open_read(filenames(iddb), comm, &
6760 : matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,&
6761 20 : msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw)
6762 :
6763 40 : do iblok2=1,ddb_hdr2%nblok
6764 :
6765 : ! Handle one block at a time
6766 20 : iblok = iblok + 1
6767 20 : call ddb%read_d2eig(ddb_hdr2, iblok, iblok2)
6768 40 : call ddb%write_d2eig(ddb_hdr, iblok)
6769 :
6770 : end do
6771 :
6772 20 : call ddb_hdr2%close() ! Close the file
6773 26 : call ddb_hdr2%free() ! Free memory
6774 :
6775 : end do
6776 :
6777 6 : call ddb_hdr%close()
6778 :
6779 : end if
6780 :
6781 : ! -----------
6782 : ! Free memory
6783 : ! -----------
6784 47 : call ddb_hdr%free()
6785 47 : call ddb%free()
6786 :
6787 47 : end subroutine merge_ddb
6788 : !!***
6789 :
6790 : !----------------------------------------------------------------------
6791 :
6792 : !!****f* m_ddb/lwcart
6793 : !! NAME
6794 : !! lwcart
6795 : !!
6796 : !! FUNCTION
6797 : !! Transform the 3rd-order energy derivative read from the ddb file generated by a long wave
6798 : !! calculation into cartesian coordinates, and also...
6799 : !!
6800 : !! INPUTS
6801 : !! blkflg(3,mpert,3,mpert,3,mpert)= ( 1 if the element of the 3dte
6802 : !! has been calculated ; 0 otherwise )
6803 : !! d3(2,3,mpert,3,mpert,3,mpert)= matrix of the 3DTE
6804 : !! gprimd(3,3)=dimensional primitive translations for reciprocal space(bohr^-1)
6805 : !! mpert =maximum number of ipert
6806 : !! natom= number of atoms
6807 : !! rprimd(3,3)=dimensional primitive translations (bohr)
6808 : !!
6809 : !! OUTPUT
6810 : !! carflg(3,mpert,3,mpert,3,mpert)=1 if the element of d3cart has been calculated, 0 otherwise
6811 : !! d3cart(2,3,mpert,3,mpert,3,mpert)=matrix of third-order energy derivatives in cartesian coordinates
6812 : !!
6813 : !! SOURCE
6814 :
6815 26 : subroutine lwcart(blkflg,carflg,d3,d3cart,gprimd,mpert,natom,rprimd)
6816 :
6817 : !Arguments -------------------------------
6818 : !scalars
6819 : integer,intent(in) :: mpert,natom
6820 : !arrays
6821 : integer,intent(in) :: blkflg(3,mpert,3,mpert,3,mpert)
6822 : integer,intent(out) :: carflg(3,mpert,3,mpert,3,mpert)
6823 : real(dp),intent(in) :: d3(2,3,mpert,3,mpert,3,mpert),gprimd(3,3),rprimd(3,3)
6824 : real(dp),intent(out) :: d3cart(2,3,mpert,3,mpert,3,mpert)
6825 :
6826 : !Local variables -------------------------
6827 : !scalars
6828 : integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert
6829 : integer :: ii
6830 : !arrays
6831 : integer :: flg1(3),flg2(3)
6832 : real(dp) :: vec1(3),vec2(3)
6833 :
6834 : ! *******************************************************************
6835 :
6836 : !Transform to cartesian coordinates
6837 11464528 : d3cart(:,:,:,:,:,:,:) = d3(:,:,:,:,:,:,:)
6838 4635958 : carflg(:,:,:,:,:,:) = 0
6839 :
6840 427 : do i1pert = 1, mpert
6841 7256 : do i2pert = 1, mpert
6842 133685 : do i3pert = 1, mpert
6843 :
6844 505820 : do i2dir = 1, 3
6845 1643915 : do i3dir = 1, 3
6846 3793650 : do ii= 1, 2
6847 9104760 : vec1(:) = d3cart(ii,:,i1pert,i2dir,i2pert,i3dir,i3pert)
6848 9104760 : flg1(:) = blkflg(:,i1pert,i2dir,i2pert,i3dir,i3pert)
6849 2276190 : call cart39(flg1,flg2,gprimd,i1pert,natom,rprimd,vec1,vec2)
6850 9104760 : d3cart(ii,:,i1pert,i2dir,i2pert,i3dir,i3pert) = vec2(:)
6851 10242855 : carflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) = flg2(:)
6852 : end do
6853 : end do
6854 : end do
6855 :
6856 505820 : do i1dir = 1, 3
6857 1643915 : do i3dir = 1, 3
6858 3793650 : do ii= 1, 2
6859 9104760 : vec1(:) = d3cart(ii,i1dir,i1pert,:,i2pert,i3dir,i3pert)
6860 9104760 : flg1(:) = blkflg(i1dir,i1pert,:,i2pert,i3dir,i3pert)
6861 2276190 : call cart39(flg1,flg2,gprimd,i2pert,natom,rprimd,vec1,vec2)
6862 9104760 : d3cart(ii,i1dir,i1pert,:,i2pert,i3dir,i3pert) = vec2(:)
6863 10242855 : carflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) = flg2(:)
6864 : end do
6865 : end do
6866 : end do
6867 :
6868 512649 : do i1dir = 1, 3
6869 1643915 : do i2dir = 1, 3
6870 3793650 : do ii= 1, 2
6871 9104760 : vec1(:) = d3cart(ii,i1dir,i1pert,i2dir,i2pert,:,i3pert)
6872 9104760 : flg1(:) = blkflg(i1dir,i1pert,i2dir,i2pert,:,i3pert)
6873 2276190 : call cart39(flg1,flg2,gprimd,i3pert,natom,rprimd,vec1,vec2)
6874 9104760 : d3cart(ii,i1dir,i1pert,i2dir,i2pert,:,i3pert) = vec2(:)
6875 10242855 : carflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) = flg2(:)
6876 : end do
6877 : end do
6878 : end do
6879 :
6880 : end do
6881 : end do
6882 : end do
6883 :
6884 26 : end subroutine lwcart
6885 : !!***
6886 :
6887 : !----------------------------------------------------------------------
6888 :
6889 : !!****f* m_ddb/dtqdrp
6890 : !! NAME
6891 : !! dtqdrp
6892 : !!
6893 : !! FUNCTION
6894 : !! Reads the Dynamical Quadrupole or the P^(1) Tensor
6895 : !! in the Gamma Block coming from the Derivative Data Base
6896 : !! (long wave third-order derivatives).
6897 : !!
6898 : !! INPUTS
6899 : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies
6900 : !! ddb_version = 8 digit integer giving date. To mantain compatibility with olderDDB files.
6901 : !! lwsym = 0 do not symmetrize the tensor wrt efield and qvec derivative
6902 : !! |-> 1st gradient of polarization response to atomic displacement
6903 : !! = 1 symmetrize the tensor wrt efield and qvec derivative
6904 : !! |-> dynamic quadrupoles
6905 : !! natom= number of atoms in unit cell
6906 : !! mpert =maximum number of ipert
6907 : !!
6908 : !! OUTPUT
6909 : !! lwtens(3,3,3,natom) = Dynamical Quadrupoles or P^(1) tensor
6910 : !!
6911 : !! SOURCE
6912 :
6913 9 : subroutine dtqdrp(blkval,ddb_version,lwsym,mpert,natom,lwtens)
6914 :
6915 : !Arguments -------------------------------
6916 : !scalars
6917 : integer,intent(in) :: ddb_version,lwsym,mpert,natom
6918 : !arrays
6919 : real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
6920 : real(dp),intent(out) :: lwtens(3,3,3,natom)
6921 :
6922 : !Local variables -------------------------
6923 : !scalars
6924 : integer,parameter :: cvrsio8=20100401
6925 : integer :: elfd,iatd,iatom,qvecd
6926 : real(dp) :: fac
6927 : logical :: iwrite
6928 : character(len=500) :: msg
6929 : !arrays
6930 18 : real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
6931 :
6932 : ! *********************************************************************
6933 :
6934 1499619 : d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
6935 1499619 : d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
6936 :
6937 : !Define a factor to apply if DDB file has been created with the old version of
6938 : !the longwave driver.
6939 9 : if (ddb_version <= cvrsio8) then
6940 : fac=-two
6941 : else
6942 5 : fac=one
6943 : end if
6944 :
6945 : !Extraction of quadrupoles (need symmetrization wrt qvecd and elfd)
6946 33 : do iatom = 1,natom
6947 105 : do iatd = 1,3
6948 312 : do elfd = 1,3
6949 432 : do qvecd = 1,elfd-1
6950 432 : if (lwsym==1) then
6951 : lwtens(elfd,qvecd,iatd,iatom) = fac * &
6952 162 : (d3cart(2,elfd,natom+2,iatd,iatom,qvecd,natom+8)+d3cart(2,qvecd,natom+2,iatd,iatom,elfd,natom+8))
6953 162 : lwtens(qvecd,elfd,iatd,iatom) = lwtens(elfd,qvecd,iatd,iatom)
6954 54 : else if (lwsym==0) then
6955 54 : lwtens(elfd,qvecd,iatd,iatom) = fac * d3cart(2,elfd,natom+2,iatd,iatom,qvecd,natom+8)
6956 54 : lwtens(qvecd,elfd,iatd,iatom) = fac * d3cart(2,qvecd,natom+2,iatd,iatom,elfd,natom+8)
6957 : end if
6958 : end do
6959 288 : if (lwsym==1) then
6960 162 : lwtens(elfd,elfd,iatd,iatom) = fac * two*d3cart(2,elfd,natom+2,iatd,iatom,elfd,natom+8)
6961 54 : else if (lwsym==0) then
6962 54 : lwtens(elfd,elfd,iatd,iatom) = fac * d3cart(2,elfd,natom+2,iatd,iatom,elfd,natom+8)
6963 : end if
6964 : end do
6965 : end do
6966 : end do
6967 :
6968 9 : iwrite = ab_out > 0
6969 :
6970 9 : if (iwrite) then
6971 9 : if (lwsym==1) then
6972 7 : write(msg,*)' atom dir Qxx Qyy Qzz Qyz Qxz Qxy'
6973 21 : call wrtout([ab_out,std_out],msg)
6974 25 : do iatom= 1, natom
6975 18 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'x',lwtens(1,1,1,iatom),lwtens(2,2,1,iatom),lwtens(3,3,1,iatom), &
6976 36 : & lwtens(2,3,1,iatom),lwtens(1,3,1,iatom),lwtens(1,2,1,iatom)
6977 54 : call wrtout([ab_out,std_out],msg)
6978 18 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'y',lwtens(1,1,2,iatom),lwtens(2,2,2,iatom),lwtens(3,3,2,iatom), &
6979 36 : & lwtens(2,3,2,iatom),lwtens(1,3,2,iatom),lwtens(1,2,2,iatom)
6980 54 : call wrtout([ab_out,std_out],msg)
6981 18 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'z',lwtens(1,1,3,iatom),lwtens(2,2,3,iatom),lwtens(3,3,3,iatom), &
6982 36 : & lwtens(2,3,3,iatom),lwtens(1,3,3,iatom),lwtens(1,2,3,iatom)
6983 61 : call wrtout([ab_out,std_out],msg)
6984 : end do
6985 2 : else if (lwsym==0) then
6986 : write(msg,*) &
6987 2 : & ' atom dir Pxx Pyy Pzz Pyz Pxz Pxy Pzy Pzx Pyx'
6988 6 : call wrtout([ab_out,std_out],msg)
6989 8 : do iatom= 1, natom
6990 6 : write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'x',lwtens(1,1,1,iatom),lwtens(2,2,1,iatom),lwtens(3,3,1,iatom), &
6991 6 : & lwtens(2,3,1,iatom),lwtens(1,3,1,iatom),lwtens(1,2,1,iatom), &
6992 12 : & lwtens(3,2,1,iatom),lwtens(3,1,1,iatom),lwtens(2,1,1,iatom)
6993 18 : call wrtout([ab_out,std_out],msg)
6994 6 : write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'y',lwtens(1,1,2,iatom),lwtens(2,2,2,iatom),lwtens(3,3,2,iatom), &
6995 6 : & lwtens(2,3,2,iatom),lwtens(1,3,2,iatom),lwtens(1,2,2,iatom), &
6996 12 : & lwtens(3,2,2,iatom),lwtens(3,1,2,iatom),lwtens(2,1,2,iatom)
6997 18 : call wrtout([ab_out,std_out],msg)
6998 6 : write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'z',lwtens(1,1,3,iatom),lwtens(2,2,3,iatom),lwtens(3,3,3,iatom), &
6999 6 : & lwtens(2,3,3,iatom),lwtens(1,3,3,iatom),lwtens(1,2,3,iatom), &
7000 12 : & lwtens(3,2,3,iatom),lwtens(3,1,3,iatom),lwtens(2,1,3,iatom)
7001 20 : call wrtout([ab_out,std_out],msg)
7002 : end do
7003 : endif
7004 : end if
7005 :
7006 9 : end subroutine dtqdrp
7007 : !!***
7008 :
7009 : !----------------------------------------------------------------------
7010 :
7011 : !!****f* m_ddb/ddb_lw_copy
7012 : !! NAME
7013 : !! ddb_lw_copy
7014 : !!
7015 : !! FUNCTION
7016 : !! Copy the ddb object after reading the long wave 3rd order derivatives
7017 : !! into a new ddb_lw and resizes ddb as for 2nd order derivatives
7018 : !!
7019 : !! INPUTS
7020 : !! ddb (INOUT) = ddb block datastructure
7021 : !! mpert =maximum number of ipert
7022 : !! natom= number of atoms in unit cell
7023 : !! ntypat= number of atom types
7024 : !!
7025 : !! OUTPUT
7026 : !! ddb_lw= ddb block datastructure
7027 : !!
7028 : !! NOTE
7029 : !! A new ddb is necessary for the longwave quantities in anaddb
7030 : !! due to incompability of it with automatic reshapes that ddb%val and ddb%flg
7031 : !! experience when passed as arguments of some routines.
7032 : !!
7033 : !! SOURCE
7034 :
7035 9 : subroutine ddb_lw_copy(ddb, ddb_lw, ddb_hdr)
7036 :
7037 : !Arguments -------------------------------
7038 : !scalars
7039 : class(ddb_type),intent(inout) :: ddb
7040 : class(ddb_type),intent(out) :: ddb_lw
7041 : type(ddb_hdr_type),intent(in) :: ddb_hdr
7042 : !arrays
7043 :
7044 : !Local variables -------------------------
7045 : !scalars
7046 : integer :: ii,nblok,nsize,cnt
7047 : integer :: mpert,natom,ntypat
7048 : ! *********************************************************************
7049 :
7050 9 : mpert = ddb_hdr%mpert
7051 9 : natom = ddb_hdr%natom
7052 9 : ntypat = ddb_hdr%ntypat
7053 :
7054 9 : call ddb%copy(ddb_lw)
7055 9 : call ddb%free()
7056 9 : nsize=3*mpert*3*mpert
7057 219 : nblok=ddb_lw%nblok-count(ddb_lw%typ(:)==BLKTYP_d3E_lw)
7058 9 : call ddb%malloc(nsize, nblok, natom, ntypat, mpert)
7059 :
7060 : ! Copy dimensions and static variables.
7061 9 : ddb%msize = nsize
7062 9 : ddb%mpert = ddb_lw%mpert
7063 9 : ddb%nblok = nblok
7064 9 : ddb%natom = ddb_lw%natom
7065 9 : ddb%ntypat = ddb_lw%ntypat
7066 9 : ddb%occopt = ddb_lw%occopt
7067 9 : ddb%prtvol = ddb_lw%prtvol
7068 :
7069 117 : ddb%rprim = ddb_lw%rprim
7070 117 : ddb%gprim = ddb_lw%gprim
7071 36 : ddb%acell = ddb_lw%acell
7072 :
7073 : ! Copy the allocatable arrays.
7074 22 : ddb%amu(:) = ddb_lw%amu(:)
7075 9 : cnt = 0
7076 219 : do ii=1,ddb_lw%nblok
7077 219 : if (ddb_lw%typ(ii)/=BLKTYP_d3E_lw) then
7078 201 : cnt = cnt + 1
7079 615882 : ddb%flg(:,cnt) = ddb_lw%flg(1:nsize,ii)
7080 1847244 : ddb%val(:,:,cnt) = ddb_lw%val(:,1:nsize,ii)
7081 201 : ddb%typ(cnt) = ddb_lw%typ(ii)
7082 804 : ddb%nrm(:,cnt) = ddb_lw%nrm(:,ii)
7083 2010 : ddb%qpt(:,cnt) = ddb_lw%qpt(:,ii)
7084 804 : ddb%omega(:,cnt) = ddb_lw%omega(:,ii)
7085 : end if
7086 : end do
7087 :
7088 9 : end subroutine ddb_lw_copy
7089 : !!***
7090 :
7091 : !----------------------------------------------------------------------
7092 : !!****f* m_ddb/symdm9
7093 : !! NAME
7094 : !! symdm9
7095 : !!
7096 : !! FUNCTION
7097 : !! Use the set of special k points calculated by the Monkhorst & Pack Technique.
7098 : !! Check if all the information for the k points are present in
7099 : !! the DDB to determine their dynamical matrices.
7100 : !! Generate the dynamical matrices of the set of k points which
7101 : !! samples homogeneously the entire Brillouin zone.
7102 : !!
7103 : !! INPUTS
7104 : !! %flg(nsize,nblok)= flag of existence for each element of the DDB
7105 : !! %nrm(1,nblok)=norm of qpt providing normalization
7106 : !! %qpt(1<ii<9,nblok)=q vector of a phonon mode (ii=1,2,3)
7107 : !! %typ(nblok)=1 or 2 depending on non-stationary or stationary block 3 for third order derivatives
7108 : !! %val(2,3*mpert*3*mpert,nblok)= all the dynamical matrices
7109 : !! gprimd(3,3)=dimensionlal primitive translations in reciprocal space
7110 : !! indsym = mapping of atoms under symops
7111 : !! mpert =maximum number of ipert
7112 : !! natom=number of atoms in unit cell
7113 : !! %nblok=number of blocks in the DDB
7114 : !! nqpt=number of special q points
7115 : !! nsym=number of space group symmetries
7116 : !! rfmeth =
7117 : !! 1 or -1 if non-stationary block
7118 : !! 2 or -2 if stationary block
7119 : !! 3 or -3 if third order derivatives
7120 : !! 85 if molecular Berry curvature
7121 : !! positive if symmetries are used to set elements to zero whenever possible, negative to prevent this to happen.
7122 : !! rprimd(3,3)=dimensional primitive translations in real space
7123 : !! spqpt(3,nqpt)=set of special q points generated by the Monkhorst & Pack Method
7124 : !! symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space)
7125 : !! symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
7126 : !! comm=MPI communicator.
7127 : !!
7128 : !! OUTPUT
7129 : !! dynmat(2,3,natom,3,natom,nqpt)=dynamical matrices relative to the q points of the B.Z. sampling
7130 : !! [qmissing]=Allocatable array with the indices of the q-points in the BZ that could not be obtained
7131 : !! by symmetry. If qmissing is present, the routine does not stop if the full BZ cannot be reconstructed.
7132 : !! The caller is responsible for filling the missing entries.
7133 : !!
7134 : !! TODO
7135 : !! * A full description of the inputs should be included
7136 : !!
7137 : !! NOTES
7138 : !! Time-reversal symmetry is always assumed
7139 : !! The time-reversal is correctly used for the MBC (Molecular Berry
7140 : !! curvature): G(-k)=G^*(k)
7141 : !!
7142 : !! SOURCE
7143 :
7144 242 : subroutine symdm9(ddb, dynmat, gprimd, indsym, mpert, natom, nqpt, nsym, rfmeth,&
7145 242 : rprimd, spqpt, symrec, symrel, comm, qmissing)
7146 :
7147 : !Arguments -------------------------------
7148 : !scalars
7149 : class(ddb_type),intent(in) :: ddb
7150 : integer,intent(in) :: mpert,natom,nqpt,nsym,rfmeth,comm
7151 : !arrays
7152 : integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym),symrel(3,3,nsym)
7153 : integer,allocatable,optional,intent(out) :: qmissing(:)
7154 : real(dp),intent(in) :: gprimd(3,3),rprimd(3,3)
7155 : real(dp),intent(in) :: spqpt(3,nqpt)
7156 : real(dp),intent(out) :: dynmat(2,3,natom,3,natom,nqpt)
7157 :
7158 : !Local variables -------------------------
7159 : !scalars
7160 : integer :: ia,ib,iblok,idir1,idir2,ii,ipert1,ipert2,iqpt,isym,jj,kk,ll
7161 : integer :: mu,nu,q1,q2,nqmiss,nprocs,my_rank,ierr,index
7162 : real(dp),parameter :: tol=2.d-8
7163 : real(dp) :: sign1, sign2
7164 : !tolerance for equality of q points between those of the DDB and those of the sampling grid
7165 : real(dp) :: arg1,arg2,im,re,sumi,sumr
7166 : logical :: allow_qmiss
7167 : character(len=500) :: msg
7168 : !arrays
7169 242 : integer,allocatable :: qtest(:,:)
7170 484 : integer :: qmiss_(nqpt)
7171 : real(dp) :: qq(3),qsym(6),ss(3,3)
7172 242 : real(dp),allocatable :: ddd(:,:,:,:,:)
7173 : ! *********************************************************************
7174 :
7175 242 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
7176 :
7177 : ! Initialize output (some q-points might not be reconstructed if qmissing is present)
7178 12537516 : dynmat = zero
7179 242 : allow_qmiss = (present(qmissing))
7180 :
7181 1210 : ABI_MALLOC(ddd,(2,3,natom,3,natom))
7182 : ! Check if the blkqpt points and their symmetrics are sufficient
7183 : ! in the DDB to retrieve all the q points of the B.Z. sampling
7184 :
7185 : !Initialization of a test variable
7186 : ! qtest(iqpt,1)=iblok
7187 : ! qtest(iqpt,2)=isym
7188 : ! qtest(iqpt,3)=time_reversal
7189 726 : ABI_MALLOC(qtest,(nqpt,3))
7190 26542 : do iqpt=1,nqpt
7191 26542 : qtest(iqpt,1)=0
7192 : end do
7193 :
7194 : !Q points coming from the DDB
7195 : !write(std_out,*)' Nbr. of Blocks -> ',nblok
7196 : ! TODO: This part scales badly with nblock/nqpt
7197 : ! One could use listkk or rearrange the loop so that iqpt comes first and then MPI-parallelize.
7198 :
7199 16500 : do iblok=1,ddb%nblok
7200 :
7201 16500 : if (abs(ddb%typ(iblok)) == abs(rfmeth)) then
7202 16178 : qq(1)=ddb%qpt(1,iblok)/ddb%nrm(1,iblok)
7203 16178 : qq(2)=ddb%qpt(2,iblok)/ddb%nrm(1,iblok)
7204 16178 : qq(3)=ddb%qpt(3,iblok)/ddb%nrm(1,iblok)
7205 :
7206 : ! Calculation of the symmetric points (including Time Reversal)
7207 551682 : do isym=1,nsym
7208 535504 : qsym(1)=qq(1)*symrec(1,1,isym)+qq(2)*symrec(1,2,isym)+qq(3)*symrec(1,3,isym)
7209 535504 : qsym(2)=qq(1)*symrec(2,1,isym)+qq(2)*symrec(2,2,isym)+qq(3)*symrec(2,3,isym)
7210 535504 : qsym(3)=qq(1)*symrec(3,1,isym)+qq(2)*symrec(3,2,isym)+qq(3)*symrec(3,3,isym)
7211 :
7212 : ! Dont forget the Time Reversal symmetry
7213 535504 : qsym(4)=-qq(1)*symrec(1,1,isym)-qq(2)*symrec(1,2,isym)-qq(3)*symrec(1,3,isym)
7214 535504 : qsym(5)=-qq(1)*symrec(2,1,isym)-qq(2)*symrec(2,2,isym)-qq(3)*symrec(2,3,isym)
7215 535504 : qsym(6)=-qq(1)*symrec(3,1,isym)-qq(2)*symrec(3,2,isym)-qq(3)*symrec(3,3,isym)
7216 :
7217 : ! Comparison between the q points and their symmetric points
7218 : ! and the set of q points which samples the entire Brillouin zone
7219 187521464 : do iqpt=1,nqpt
7220 :
7221 186969782 : if (mod(abs(spqpt(1,iqpt)-qsym(1))+tol,1._dp)<2*tol)then
7222 23298506 : if (mod(abs(spqpt(2,iqpt)-qsym(2))+tol,1._dp)<2*tol)then
7223 3030084 : if (mod(abs(spqpt(3,iqpt)-qsym(3))+tol,1._dp)<2*tol)then
7224 :
7225 : ! write(std_out,*)' q point from the DDB ! '
7226 : ! write(std_out,*)' block -> ',iblok
7227 : ! write(std_out,*)' sym. -> ',isym
7228 : ! write(std_out,*)' No Time Reversal '
7229 : ! write(std_out,*)'(',qsym(1),',',qsym(2),',',qsym(3),')'
7230 : ! write(std_out,*)' '
7231 507328 : qtest(iqpt,1)=iblok
7232 507328 : qtest(iqpt,2)=isym
7233 507328 : qtest(iqpt,3)=0
7234 : end if
7235 : end if
7236 : end if
7237 :
7238 187505286 : if (mod(abs(spqpt(1,iqpt)-qsym(4))+tol,1._dp)<2*tol)then
7239 23298506 : if (mod(abs(spqpt(2,iqpt)-qsym(5))+tol,1._dp)<2*tol)then
7240 3030084 : if (mod(abs(spqpt(3,iqpt)-qsym(6))+tol,1._dp)<2*tol)then
7241 :
7242 : ! write(std_out,*)' q point from the DDB ! '
7243 : ! write(std_out,*)' block -> ',iblok
7244 : ! write(std_out,*)' sym. -> ',isym
7245 : ! write(std_out,*)' Time Reversal '
7246 : ! write(std_out,*)'(',qsym(4),',',qsym(5),',',qsym(6),')'
7247 : ! write(std_out,*)' '
7248 :
7249 507328 : qtest(iqpt,1)=iblok
7250 507328 : qtest(iqpt,2)=isym
7251 507328 : qtest(iqpt,3)=1
7252 : end if
7253 : end if
7254 : end if
7255 :
7256 : end do ! iqpt
7257 : end do ! isym
7258 :
7259 : end if
7260 : end do ! iblok
7261 :
7262 : ! Check if all the information relatives to the q points sampling are found in the DDB if not => stop message
7263 242 : nqmiss = 0
7264 26542 : do iqpt=1,nqpt
7265 26542 : if (qtest(iqpt,1)==0) then
7266 96 : nqmiss = nqmiss + 1
7267 96 : qmiss_(nqmiss) = iqpt
7268 96 : write(msg, '(3a)' )' symdm9: the bloks found in the DDB are characterized',ch10,' by the following wavevectors :'
7269 96 : call wrtout(std_out,msg)
7270 672 : do iblok=1,ddb%nblok
7271 576 : write(msg, '(a,4d20.12)')' ',ddb%qpt(1,iblok),ddb%qpt(2,iblok),ddb%qpt(3,iblok),ddb%nrm(1,iblok)
7272 672 : call wrtout(std_out,msg)
7273 : end do
7274 : write(msg, '(3a,i0,3a,3es16.6,3a)' )&
7275 96 : 'Information is missing in the DDB file.',ch10,&
7276 96 : 'The dynamical matrix with iqpt= ',iqpt,' cannot be built,',ch10,&
7277 96 : 'since no block with qpt: ',spqpt(1:3,iqpt), ' has been found.',ch10,&
7278 192 : 'Action: add the required block in the DDB, or modify the q-mesh your input file.'
7279 96 : if (.not. allow_qmiss) then
7280 0 : ABI_ERROR(msg)
7281 : else
7282 96 : ABI_COMMENT(msg)
7283 : end if
7284 : end if
7285 : end do
7286 :
7287 : ! Will return a list with the index of the q-points that could not be symmetrized.
7288 242 : if (allow_qmiss) then
7289 3 : ABI_MALLOC(qmissing, (nqmiss))
7290 98 : if (nqmiss > 0) qmissing = qmiss_(1:nqmiss)
7291 : end if
7292 :
7293 : ! Generation of the dynamical matrices relative to the q points
7294 : ! of the set which samples the entire Brillouin zone
7295 26542 : do iqpt=1,nqpt
7296 26300 : if (mod(iqpt, nprocs) /= my_rank) cycle ! mpi-parallelism
7297 :
7298 26292 : q1=qtest(iqpt,1) ! iblok
7299 26292 : q2=qtest(iqpt,2) ! isym
7300 : ! Skip this q-point if don't have enough info and allow_qmiss
7301 26292 : if (allow_qmiss .and. q1==0) cycle
7302 :
7303 : ! Check if the symmetry accompagnied with time reversal : q <- -q
7304 104784 : do ii=1,3
7305 104784 : qq(ii)=ddb%qpt(ii,q1)/ddb%nrm(1,q1)
7306 : end do
7307 67347 : if (qtest(iqpt,3)/=0) qq(:) = -qq(:)
7308 : !
7309 104784 : do ii=1,3
7310 340548 : do jj=1,3
7311 235764 : ss(ii,jj)=zero
7312 1021644 : do kk=1,3
7313 3064932 : do ll=1,3
7314 2829168 : ss(ii,jj) = ss(ii,jj) + rprimd(ii,kk) * symrel(kk,ll,q2) * gprimd(jj,ll)
7315 : end do
7316 : end do
7317 : end do
7318 : end do
7319 :
7320 : ! Check whether all the information is contained in the DDB
7321 106655 : do ipert2=1,natom
7322 348032 : do idir2=1,3
7323 1539917 : do ipert1=1,natom
7324 5113701 : do idir1=1,3
7325 3654243 : index = idir1+ 3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1)))
7326 : !if(ddb%flg(idir1,ipert1,idir2,ipert2,q1)/=1)then
7327 4872324 : if(ddb%flg(index,q1)/=1)then
7328 : write(msg, '(a,a,a,i0,a,a,a,4(i0,1x),a,a,a,a)' )&
7329 0 : 'Elements are missing in the DDB.',ch10,&
7330 0 : 'In block iq1: ',q1,' the following element is missing: ',ch10,&
7331 0 : '(idir1, ipert1, idir2, ipert2): ',idir1,ipert1,idir2,ipert2,ch10,&
7332 0 : 'Action: add the required information in the DDB with mrgddb,',ch10,&
7333 0 : 'and/or check that all irreducible perturbations have been computed.'
7334 0 : ABI_ERROR(msg)
7335 : end if
7336 : end do
7337 : end do
7338 : end do
7339 : end do
7340 :
7341 : ! Read the dynamical matrices in the DDB
7342 106655 : do ipert2=1,natom
7343 348032 : do idir2=1,3
7344 1539917 : do ipert1=1,natom
7345 5113701 : do idir1=1,3
7346 12180810 : ddd(:,idir1,ipert1,idir2,ipert2)=ddb%val(:,idir1+3*(ipert1-1+mpert*(idir2-1+3*(ipert2-1))),q1)
7347 : end do
7348 : end do
7349 : end do
7350 : end do
7351 :
7352 : ! determine sign of complex conjugation
7353 : ! If there is Time Reversal : D.M. <- Complex Conjugate D.M.
7354 : ! MBC <- Complex Conjugate MBC
7355 26196 : if (qtest(iqpt,3)==0) then
7356 : sign1 = one
7357 : sign2 = one
7358 : else ! if timrev -> complex conjugate
7359 13717 : sign1 = one
7360 13717 : sign2 = -one
7361 : end if
7362 :
7363 : ! Calculation of the dynamical matrix of a symmetrical q point
7364 106897 : do ia=1,natom
7365 512786 : do ib=1,natom
7366 : ! write(std_out,*)'atom-> ',ia,indsym(4,q2,ia); write(std_out,*)'atom-> ',ib,indsym(4,q2,ib)
7367 406027 : arg1=two_pi*(qq(1)*indsym(1,q2,ia)+qq(2)*indsym(2,q2,ia)+qq(3)*indsym(3,q2,ia))
7368 406027 : arg2=two_pi*(qq(1)*indsym(1,q2,ib)+qq(2)*indsym(2,q2,ib)+qq(3)*indsym(3,q2,ib))
7369 406027 : re=cos(arg1)*cos(arg2)+sin(arg1)*sin(arg2)
7370 406027 : im=cos(arg2)*sin(arg1)-cos(arg1)*sin(arg2)
7371 1704567 : do mu=1,3
7372 5278351 : do nu=1,3
7373 : sumr=zero
7374 : sumi=zero
7375 14616972 : do ii=1,3
7376 47505159 : do jj=1,3
7377 32888187 : sumr=sumr+ss(mu,ii)*ss(nu,jj)*ddd(1,ii,indsym(4,q2,ia),jj,indsym(4,q2,ib))
7378 43850916 : sumi=sumi+ss(mu,ii)*ss(nu,jj)*ddd(2,ii,indsym(4,q2,ia),jj,indsym(4,q2,ib))
7379 : end do
7380 : end do
7381 :
7382 : ! Dynmat -> Dynamical Matrix for the q point of the sampling
7383 : ! write(std_out,*)' Sumr -> ',mu,nu,sumr; write(std_out,*)' Sumi -> ',mu,nu,sumi
7384 3654243 : dynmat(1,mu,ia,nu,ib,iqpt) = sign1*re*sumr - sign2*im*sumi
7385 4872324 : dynmat(2,mu,ia,nu,ib,iqpt) = sign2*re*sumi + sign1*im*sumr
7386 : end do ! coordinates
7387 : end do
7388 :
7389 : end do ! ia atoms
7390 : end do ! ib atoms
7391 : end do ! q points of the sampling
7392 :
7393 242 : ABI_FREE(ddd)
7394 242 : ABI_FREE(qtest)
7395 :
7396 242 : call xmpi_sum(dynmat, comm, ierr)
7397 :
7398 242 : end subroutine symdm9
7399 : !!***
7400 :
7401 : !----------------------------------------------------------------------
7402 :
7403 384 : end module m_ddb
7404 : !!***
|