(git:1f285aa)
negf_control_types.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Input control types for NEGF based quantum transport calculations
10 ! **************************************************************************************************
11 
13  USE cp_subsys_types, ONLY: cp_subsys_get,&
14  cp_subsys_type
15  USE input_constants, ONLY: negf_run
18  section_vals_type,&
20  USE kinds, ONLY: default_string_length,&
21  dp
22  USE mathconstants, ONLY: pi
24  molecule_kind_type
25  USE molecule_types, ONLY: get_molecule,&
26  molecule_type
27  USE negf_alloc_types, ONLY: negf_allocatable_ivector
28  USE particle_types, ONLY: particle_type
29  USE physcon, ONLY: kelvin
31  USE util, ONLY: sort
32 #include "./base/base_uses.f90"
33 
34  IMPLICIT NONE
35  PRIVATE
36 
37  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'negf_control_types'
38  LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .true.
39 
40  PUBLIC :: negf_control_type, negf_control_contact_type
42 
43 ! **************************************************************************************************
44 !> \brief Input parameters related to a single contact.
45 !> \author Sergey Chulkov
46 ! **************************************************************************************************
47  TYPE negf_control_contact_type
48  !> atoms belonging to bulk and screening regions
49  INTEGER, ALLOCATABLE, DIMENSION(:) :: atomlist_bulk, atomlist_screening
50  !> atom belonging to the primary and secondary bulk unit cells
51  TYPE(negf_allocatable_ivector), ALLOCATABLE, &
52  DIMENSION(:) :: atomlist_cell
53  !> index of the sub_force_env which should be used for bulk calculation
54  INTEGER :: force_env_index
55  !> contact Fermi level needs to be computed prior NEGF run
56  LOGICAL :: compute_fermi_level
57  !> when computing contact Fermi level, use the energy given in 'fermi_level' (instead of HOMO)
58  !> (instead of the HOMO energy) as a starting point
59  LOGICAL :: refine_fermi_level
60  !> Fermi level
61  REAL(kind=dp) :: fermi_level
62  !> temperature [in a.u.]
63  REAL(kind=dp) :: temperature
64  !> applied electric potential
65  REAL(kind=dp) :: v_external
66  END TYPE negf_control_contact_type
67 
68 ! **************************************************************************************************
69 !> \brief Input parameters related to the NEGF run.
70 !> \author Sergey Chulkov
71 ! **************************************************************************************************
72  TYPE negf_control_type
73  !> input options for every contact
74  TYPE(negf_control_contact_type), ALLOCATABLE, &
75  DIMENSION(:) :: contacts
76  !> atoms belonging to the scattering region
77  INTEGER, ALLOCATABLE, DIMENSION(:) :: atomlist_S
78  !> atoms belonging to the scattering region as well as atoms belonging to
79  !> screening regions of all the contacts
80  INTEGER, ALLOCATABLE, DIMENSION(:) :: atomlist_S_screening
81  !> do not keep contact self-energy matrices
82  LOGICAL :: disable_cache
83  !> convergence criteria for adaptive integration methods
84  REAL(kind=dp) :: conv_density
85  !> convergence criteria for iterative Lopez-Sancho algorithm
86  REAL(kind=dp) :: conv_green
87  !> convergence criteria for self-consistent iterations
88  REAL(kind=dp) :: conv_scf
89  !> accuracy in mapping atoms between different force environments
90  REAL(kind=dp) :: eps_geometry
91  !> applied bias [in a.u.]
92  REAL(kind=dp) :: v_bias
93  !> integration lower bound [in a.u.]
94  REAL(kind=dp) :: energy_lbound
95  !> infinitesimal offset along the imaginary axis [in a.u.]
96  REAL(kind=dp) :: eta
97  !> initial guess to determine the actual Fermi level of bulk contacts [in a.u.]
98  REAL(kind=dp) :: homo_lumo_gap
99  !> number of residuals (poles of the Fermi function)
100  INTEGER :: delta_npoles
101  !> offset along the x-axis away from the poles of the Fermi function [in units of kT]
102  INTEGER :: gamma_kT
103  !> integration method
104  INTEGER :: integr_method
105  !> minimal number of grid points along the closed contour
106  INTEGER :: integr_min_points
107  !> maximal number of grid points along the closed contour
108  INTEGER :: integr_max_points
109  !> maximal number of SCF iterations
110  INTEGER :: max_scf
111  !> minimal number of MPI processes to be used to compute Green's function per energy point
112  INTEGER :: nprocs
113  !> shift in Hartree potential [in a.u.]
114  REAL(kind=dp) :: v_shift
115  !> initial offset to determine the correct shift in Hartree potential [in a.u.]
116  REAL(kind=dp) :: v_shift_offset
117  !> maximal number of iteration to determine the shift in Hartree potential
118  INTEGER :: v_shift_maxiters
119  END TYPE negf_control_type
120 
121  PRIVATE :: read_negf_atomlist
122 
123 CONTAINS
124 
125 ! **************************************************************************************************
126 !> \brief allocate control options for Non-equilibrium Green's Function calculation
127 !> \param negf_control an object to create
128 !> \par History
129 !> * 02.2017 created [Sergey Chulkov]
130 ! **************************************************************************************************
131  SUBROUTINE negf_control_create(negf_control)
132  TYPE(negf_control_type), POINTER :: negf_control
133 
134  CHARACTER(len=*), PARAMETER :: routinen = 'negf_control_create'
135 
136  INTEGER :: handle
137 
138  cpassert(.NOT. ASSOCIATED(negf_control))
139  CALL timeset(routinen, handle)
140 
141  ALLOCATE (negf_control)
142 
143  CALL timestop(handle)
144  END SUBROUTINE negf_control_create
145 
146 ! **************************************************************************************************
147 !> \brief release memory allocated for NEGF control options
148 !> \param negf_control an object to release
149 !> \par History
150 !> * 02.2017 created [Sergey Chulkov]
151 ! **************************************************************************************************
152  SUBROUTINE negf_control_release(negf_control)
153  TYPE(negf_control_type), POINTER :: negf_control
154 
155  CHARACTER(len=*), PARAMETER :: routinen = 'negf_control_release'
156 
157  INTEGER :: handle, i, j
158 
159  CALL timeset(routinen, handle)
160 
161  IF (ASSOCIATED(negf_control)) THEN
162  IF (ALLOCATED(negf_control%atomlist_S)) DEALLOCATE (negf_control%atomlist_S)
163  IF (ALLOCATED(negf_control%atomlist_S_screening)) DEALLOCATE (negf_control%atomlist_S_screening)
164 
165  IF (ALLOCATED(negf_control%contacts)) THEN
166  DO i = SIZE(negf_control%contacts), 1, -1
167  IF (ALLOCATED(negf_control%contacts(i)%atomlist_bulk)) &
168  DEALLOCATE (negf_control%contacts(i)%atomlist_bulk)
169 
170  IF (ALLOCATED(negf_control%contacts(i)%atomlist_screening)) &
171  DEALLOCATE (negf_control%contacts(i)%atomlist_screening)
172 
173  IF (ALLOCATED(negf_control%contacts(i)%atomlist_cell)) THEN
174  DO j = SIZE(negf_control%contacts(i)%atomlist_cell), 1, -1
175  IF (ALLOCATED(negf_control%contacts(i)%atomlist_cell(j)%vector)) &
176  DEALLOCATE (negf_control%contacts(i)%atomlist_cell(j)%vector)
177  END DO
178  DEALLOCATE (negf_control%contacts(i)%atomlist_cell)
179  END IF
180  END DO
181 
182  DEALLOCATE (negf_control%contacts)
183  END IF
184 
185  DEALLOCATE (negf_control)
186  END IF
187 
188  CALL timestop(handle)
189  END SUBROUTINE negf_control_release
190 
191 ! **************************************************************************************************
192 !> \brief Read NEGF input parameters.
193 !> \param negf_control NEGF control parameters
194 !> \param input root input section
195 !> \param subsys subsystem environment
196 ! **************************************************************************************************
197  SUBROUTINE read_negf_control(negf_control, input, subsys)
198  TYPE(negf_control_type), POINTER :: negf_control
199  TYPE(section_vals_type), POINTER :: input
200  TYPE(cp_subsys_type), POINTER :: subsys
201 
202  CHARACTER(len=*), PARAMETER :: routinen = 'read_negf_control'
203 
204  CHARACTER(len=default_string_length) :: contact_id_str, eta_current_str, eta_max_str, &
205  npoles_current_str, npoles_min_str, temp_current_str, temp_min_str
206  INTEGER :: delta_npoles_min, handle, i2_rep, i_rep, &
207  n2_rep, n_rep, natoms_current, &
208  natoms_total, run_type
209  INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
210  LOGICAL :: do_negf, is_explicit
211  REAL(kind=dp) :: eta_max, temp_current, temp_min
212  TYPE(section_vals_type), POINTER :: cell_section, contact_section, &
213  negf_section, region_section
214 
215  CALL timeset(routinen, handle)
216 
217  CALL section_vals_val_get(input, "GLOBAL%RUN_TYPE", i_val=run_type)
218  do_negf = run_type == negf_run
219 
220  negf_section => section_vals_get_subs_vals(input, "NEGF")
221 
222  contact_section => section_vals_get_subs_vals(negf_section, "CONTACT")
223  CALL section_vals_get(contact_section, n_repetition=n_rep, explicit=is_explicit)
224  IF ((.NOT. is_explicit) .AND. do_negf) THEN
225  CALL cp_abort(__location__, &
226  "At least one contact is needed for NEGF calculation.")
227  END IF
228 
229  ALLOCATE (negf_control%contacts(n_rep))
230  DO i_rep = 1, n_rep
231  region_section => section_vals_get_subs_vals(contact_section, "SCREENING_REGION", i_rep_section=i_rep)
232  CALL section_vals_get(region_section, explicit=is_explicit)
233 
234  IF ((.NOT. is_explicit) .AND. do_negf) THEN
235  WRITE (contact_id_str, '(I11)') i_rep
236  CALL cp_abort(__location__, &
237  "The screening region must be defined for the contact "//trim(adjustl(contact_id_str))//".")
238  END IF
239 
240  IF (is_explicit) THEN
241  CALL read_negf_atomlist(negf_control%contacts(i_rep)%atomlist_screening, region_section, 1, subsys)
242  END IF
243 
244  region_section => section_vals_get_subs_vals(contact_section, "BULK_REGION", i_rep_section=i_rep)
245 
246  CALL section_vals_get(region_section, explicit=is_explicit)
247 
248  IF ((.NOT. is_explicit) .AND. do_negf) THEN
249  WRITE (contact_id_str, '(I11)') i_rep
250  CALL cp_abort(__location__, &
251  "The bulk region must be defined for the contact "//trim(adjustl(contact_id_str))//".")
252  END IF
253 
254  IF (is_explicit) THEN
255  CALL read_negf_atomlist(negf_control%contacts(i_rep)%atomlist_bulk, region_section, 1, subsys)
256  END IF
257 
258  CALL section_vals_val_get(contact_section, "FORCE_EVAL_SECTION", &
259  i_val=negf_control%contacts(i_rep)%force_env_index, &
260  i_rep_section=i_rep)
261 
262  cell_section => section_vals_get_subs_vals(region_section, "CELL")
263  CALL section_vals_get(cell_section, n_repetition=n2_rep, explicit=is_explicit)
264 
265  IF (((.NOT. is_explicit) .OR. n2_rep /= 2) .AND. negf_control%contacts(i_rep)%force_env_index <= 0 .AND. do_negf) THEN
266  WRITE (contact_id_str, '(I11)') i_rep
267  CALL cp_abort(__location__, &
268  "You must either provide indices of atoms belonging to two adjacent bulk unit cells "// &
269  "(BULK_REGION/CELL) for the contact, or the index of the FORCE_EVAL section (FORCE_EVAL_SECTION) "// &
270  "which will be used to construct Kohn-Sham matrix for the bulk contact "// &
271  trim(adjustl(contact_id_str))//".")
272  END IF
273 
274  IF (is_explicit .AND. n2_rep > 0) THEN
275  ALLOCATE (negf_control%contacts(i_rep)%atomlist_cell(n2_rep))
276 
277  DO i2_rep = 1, n2_rep
278  CALL read_negf_atomlist(negf_control%contacts(i_rep)%atomlist_cell(i2_rep)%vector, cell_section, i2_rep, subsys)
279  END DO
280  END IF
281 
282  CALL section_vals_val_get(contact_section, "REFINE_FERMI_LEVEL", &
283  l_val=negf_control%contacts(i_rep)%refine_fermi_level, &
284  i_rep_section=i_rep)
285 
286  CALL section_vals_val_get(contact_section, "FERMI_LEVEL", &
287  r_val=negf_control%contacts(i_rep)%fermi_level, &
288  i_rep_section=i_rep, explicit=is_explicit)
289  negf_control%contacts(i_rep)%compute_fermi_level = (.NOT. is_explicit) .OR. &
290  negf_control%contacts(i_rep)%refine_fermi_level
291 
292  IF (do_negf .AND. negf_control%contacts(i_rep)%force_env_index <= 0 .AND. &
293  (.NOT. (is_explicit .OR. negf_control%contacts(i_rep)%refine_fermi_level))) THEN
294  WRITE (contact_id_str, '(I11)') i_rep
295  CALL cp_warn(__location__, &
296  "There is no way to reasonably guess the Fermi level for the bulk contact "// &
297  trim(adjustl(contact_id_str))//" without running a separate bulk DFT calculation first. "// &
298  "Therefore, 0.0 Hartree will be used as an initial guess. It is strongly advised to enable "// &
299  "the REFINE_FERMI_LEVEL switch and to provide an initial guess using the FERMI_LEVEL keyword. "// &
300  "Alternatively, a bulk FORCE_EVAL_SECTION can be set up.")
301  END IF
302 
303  CALL section_vals_val_get(contact_section, "TEMPERATURE", &
304  r_val=negf_control%contacts(i_rep)%temperature, &
305  i_rep_section=i_rep)
306  IF (negf_control%contacts(i_rep)%temperature <= 0.0_dp) THEN
307  CALL cp_abort(__location__, "Electronic temperature must be > 0")
308  END IF
309 
310  CALL section_vals_val_get(contact_section, "ELECTRIC_POTENTIAL", &
311  r_val=negf_control%contacts(i_rep)%v_external, &
312  i_rep_section=i_rep)
313  END DO
314 
315  region_section => section_vals_get_subs_vals(negf_section, "SCATTERING_REGION")
316  CALL section_vals_get(region_section, explicit=is_explicit)
317  IF (is_explicit) THEN
318  CALL read_negf_atomlist(negf_control%atomlist_S, region_section, 1, subsys)
319  END IF
320 
321  CALL section_vals_val_get(negf_section, "DISABLE_CACHE", l_val=negf_control%disable_cache)
322 
323  CALL section_vals_val_get(negf_section, "EPS_DENSITY", r_val=negf_control%conv_density)
324  CALL section_vals_val_get(negf_section, "EPS_GREEN", r_val=negf_control%conv_green)
325  CALL section_vals_val_get(negf_section, "EPS_SCF", r_val=negf_control%conv_scf)
326 
327  CALL section_vals_val_get(negf_section, "EPS_GEO", r_val=negf_control%eps_geometry)
328 
329  CALL section_vals_val_get(negf_section, "ENERGY_LBOUND", r_val=negf_control%energy_lbound)
330  CALL section_vals_val_get(negf_section, "ETA", r_val=negf_control%eta)
331  CALL section_vals_val_get(negf_section, "HOMO_LUMO_GAP", r_val=negf_control%homo_lumo_gap)
332  CALL section_vals_val_get(negf_section, "DELTA_NPOLES", i_val=negf_control%delta_npoles)
333  CALL section_vals_val_get(negf_section, "GAMMA_KT", i_val=negf_control%gamma_kT)
334 
335  CALL section_vals_val_get(negf_section, "INTEGRATION_METHOD", i_val=negf_control%integr_method)
336  CALL section_vals_val_get(negf_section, "INTEGRATION_MIN_POINTS", i_val=negf_control%integr_min_points)
337  CALL section_vals_val_get(negf_section, "INTEGRATION_MAX_POINTS", i_val=negf_control%integr_max_points)
338 
339  IF (negf_control%integr_max_points < negf_control%integr_min_points) &
340  negf_control%integr_max_points = negf_control%integr_min_points
341 
342  CALL section_vals_val_get(negf_section, "MAX_SCF", i_val=negf_control%max_scf)
343 
344  CALL section_vals_val_get(negf_section, "NPROC_POINT", i_val=negf_control%nprocs)
345 
346  CALL section_vals_val_get(negf_section, "V_SHIFT", r_val=negf_control%v_shift)
347  CALL section_vals_val_get(negf_section, "V_SHIFT_OFFSET", r_val=negf_control%v_shift_offset)
348  CALL section_vals_val_get(negf_section, "V_SHIFT_MAX_ITERS", i_val=negf_control%v_shift_maxiters)
349 
350  ! check consistency
351  IF (negf_control%eta < 0.0_dp) THEN
352  CALL cp_abort(__location__, "ETA must be >= 0")
353  END IF
354 
355  IF (n_rep > 0) THEN
356  delta_npoles_min = nint(0.5_dp*(negf_control%eta/(pi*maxval(negf_control%contacts(:)%temperature)) + 1.0_dp))
357  ELSE
358  delta_npoles_min = 1
359  END IF
360 
361  IF (negf_control%delta_npoles < delta_npoles_min) THEN
362  IF (n_rep > 0) THEN
363  eta_max = real(2*negf_control%delta_npoles - 1, kind=dp)*pi*maxval(negf_control%contacts(:)%temperature)
364  temp_current = maxval(negf_control%contacts(:)%temperature)*kelvin
365  temp_min = negf_control%eta/(pi*real(2*negf_control%delta_npoles - 1, kind=dp))*kelvin
366 
367  WRITE (eta_current_str, '(ES11.4E2)') negf_control%eta
368  WRITE (eta_max_str, '(ES11.4E2)') eta_max
369  WRITE (npoles_current_str, '(I11)') negf_control%delta_npoles
370  WRITE (npoles_min_str, '(I11)') delta_npoles_min
371  WRITE (temp_current_str, '(F11.3)') temp_current
372  WRITE (temp_min_str, '(F11.3)') temp_min
373 
374  CALL cp_abort(__location__, &
375  "Parameter DELTA_NPOLES must be at least "//trim(adjustl(npoles_min_str))// &
376  " (instead of "//trim(adjustl(npoles_current_str))// &
377  ") for given TEMPERATURE ("//trim(adjustl(temp_current_str))// &
378  " K) and ETA ("//trim(adjustl(eta_current_str))// &
379  "). Alternatively you can increase TEMPERATURE above "//trim(adjustl(temp_min_str))// &
380  " K, or decrease ETA below "//trim(adjustl(eta_max_str))// &
381  ". Please keep in mind that very tight ETA may result in dramatical precision loss"// &
382  " due to inversion of ill-conditioned matrices.")
383  ELSE
384  ! no leads have been defined, so calculation will abort anyway
385  negf_control%delta_npoles = delta_npoles_min
386  END IF
387  END IF
388 
389  ! expand scattering region by adding atoms from contact screening regions
390  n_rep = SIZE(negf_control%contacts)
391  IF (ALLOCATED(negf_control%atomlist_S)) THEN
392  natoms_total = SIZE(negf_control%atomlist_S)
393  ELSE
394  natoms_total = 0
395  END IF
396 
397  DO i_rep = 1, n_rep
398  IF (ALLOCATED(negf_control%contacts(i_rep)%atomlist_screening)) THEN
399  IF (ALLOCATED(negf_control%contacts(i_rep)%atomlist_screening)) &
400  natoms_total = natoms_total + SIZE(negf_control%contacts(i_rep)%atomlist_screening)
401  END IF
402  END DO
403 
404  IF (natoms_total > 0) THEN
405  ALLOCATE (negf_control%atomlist_S_screening(natoms_total))
406  IF (ALLOCATED(negf_control%atomlist_S)) THEN
407  natoms_total = SIZE(negf_control%atomlist_S)
408  negf_control%atomlist_S_screening(1:natoms_total) = negf_control%atomlist_S(1:natoms_total)
409  ELSE
410  natoms_total = 0
411  END IF
412 
413  DO i_rep = 1, n_rep
414  IF (ALLOCATED(negf_control%contacts(i_rep)%atomlist_screening)) THEN
415  natoms_current = SIZE(negf_control%contacts(i_rep)%atomlist_screening)
416 
417  negf_control%atomlist_S_screening(natoms_total + 1:natoms_total + natoms_current) = &
418  negf_control%contacts(i_rep)%atomlist_screening(1:natoms_current)
419 
420  natoms_total = natoms_total + natoms_current
421  END IF
422  END DO
423 
424  ! sort and remove duplicated atoms
425  ALLOCATE (inds(natoms_total))
426  CALL sort(negf_control%atomlist_S_screening, natoms_total, inds)
427  DEALLOCATE (inds)
428 
429  natoms_current = 1
430  DO i_rep = natoms_current + 1, natoms_total
431  IF (negf_control%atomlist_S_screening(i_rep) /= negf_control%atomlist_S_screening(natoms_current)) THEN
432  natoms_current = natoms_current + 1
433  negf_control%atomlist_S_screening(natoms_current) = negf_control%atomlist_S_screening(i_rep)
434  END IF
435  END DO
436 
437  IF (natoms_current < natoms_total) THEN
438  CALL move_alloc(negf_control%atomlist_S_screening, inds)
439 
440  ALLOCATE (negf_control%atomlist_S_screening(natoms_current))
441  negf_control%atomlist_S_screening(1:natoms_current) = inds(1:natoms_current)
442  DEALLOCATE (inds)
443  END IF
444  END IF
445 
446  IF (do_negf .AND. SIZE(negf_control%contacts) > 2) THEN
447  CALL cp_abort(__location__, &
448  "General case (> 2 contacts) has not been implemented yet")
449  END IF
450 
451  CALL timestop(handle)
452  END SUBROUTINE read_negf_control
453 
454 ! **************************************************************************************************
455 !> \brief Read region-specific list of atoms.
456 !> \param atomlist list of atoms
457 !> \param input_section input section which contains 'LIST' and 'MOLNAME' keywords
458 !> \param i_rep_section repetition index of the input_section
459 !> \param subsys subsystem environment
460 ! **************************************************************************************************
461  SUBROUTINE read_negf_atomlist(atomlist, input_section, i_rep_section, subsys)
462  INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(out) :: atomlist
463  TYPE(section_vals_type), POINTER :: input_section
464  INTEGER, INTENT(in) :: i_rep_section
465  TYPE(cp_subsys_type), POINTER :: subsys
466 
467  CHARACTER(len=*), PARAMETER :: routinen = 'read_negf_atomlist'
468 
469  CHARACTER(len=default_string_length) :: index_str, natoms_str
470  CHARACTER(len=default_string_length), &
471  DIMENSION(:), POINTER :: cptr
472  INTEGER :: first_atom, handle, iatom, ikind, imol, iname, irep, last_atom, natoms_current, &
473  natoms_max, natoms_total, nkinds, nmols, nnames, nrep_list, nrep_molname
474  INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
475  INTEGER, DIMENSION(:), POINTER :: iptr
476  LOGICAL :: is_list, is_molname
477  TYPE(molecule_kind_type), DIMENSION(:), POINTER :: molecule_kind_set
478  TYPE(molecule_kind_type), POINTER :: molecule_kind
479  TYPE(molecule_type), DIMENSION(:), POINTER :: molecule_set
480  TYPE(molecule_type), POINTER :: molecule
481  TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
482 
483  CALL timeset(routinen, handle)
484 
485  CALL cp_subsys_get(subsys, particle_set=particle_set, &
486  molecule_set=molecule_set, &
487  molecule_kind_set=molecule_kind_set)
488  natoms_max = SIZE(particle_set)
489  nkinds = SIZE(molecule_kind_set)
490 
491  CALL section_vals_val_get(input_section, "LIST", i_rep_section=i_rep_section, &
492  n_rep_val=nrep_list, explicit=is_list)
493  CALL section_vals_val_get(input_section, "MOLNAME", i_rep_section=i_rep_section, &
494  n_rep_val=nrep_molname, explicit=is_molname)
495 
496  ! compute the number of atoms in the NEGF region, and check the validity of giben atomic indices
497  natoms_total = 0
498  IF (is_list .AND. nrep_list > 0) THEN
499  DO irep = 1, nrep_list
500  CALL section_vals_val_get(input_section, "LIST", i_rep_section=i_rep_section, i_rep_val=irep, i_vals=iptr)
501 
502  natoms_current = SIZE(iptr)
503  DO iatom = 1, natoms_current
504  IF (iptr(iatom) > natoms_max) THEN
505  CALL integer_to_string(iptr(iatom), index_str)
506  CALL integer_to_string(natoms_max, natoms_str)
507  CALL cp_abort(__location__, &
508  "NEGF: Atomic index "//trim(index_str)//" given in section "// &
509  trim(input_section%section%name)//" exceeds the maximum number of atoms ("// &
510  trim(natoms_str)//").")
511  END IF
512  END DO
513 
514  natoms_total = natoms_total + natoms_current
515  END DO
516  END IF
517 
518  IF (is_molname .AND. nrep_molname > 0) THEN
519  DO irep = 1, nrep_molname
520  CALL section_vals_val_get(input_section, "MOLNAME", i_rep_section=i_rep_section, i_rep_val=irep, c_vals=cptr)
521  nnames = SIZE(cptr)
522 
523  DO iname = 1, nnames
524  DO ikind = 1, nkinds
525  IF (molecule_kind_set(ikind)%name .EQ. cptr(iname)) EXIT
526  END DO
527 
528  IF (ikind <= nkinds) THEN
529  molecule_kind => molecule_kind_set(ikind)
530  CALL get_molecule_kind(molecule_kind, nmolecule=nmols, molecule_list=iptr)
531 
532  DO imol = 1, nmols
533  molecule => molecule_set(iptr(imol))
534  CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
535  natoms_current = last_atom - first_atom + 1
536  natoms_total = natoms_total + natoms_current
537  END DO
538  ELSE
539  CALL cp_abort(__location__, &
540  "NEGF: A molecule with the name '"//trim(cptr(iname))//"' mentioned in section "// &
541  trim(input_section%section%name)//" has not been defined. Note that names are case sensitive.")
542  END IF
543  END DO
544  END DO
545  END IF
546 
547  ! create a list of atomic indices
548  IF (natoms_total > 0) THEN
549  ALLOCATE (atomlist(natoms_total))
550 
551  natoms_total = 0
552 
553  IF (is_list .AND. nrep_list > 0) THEN
554  DO irep = 1, nrep_list
555  CALL section_vals_val_get(input_section, "LIST", i_rep_section=i_rep_section, i_rep_val=irep, i_vals=iptr)
556 
557  natoms_current = SIZE(iptr)
558  atomlist(natoms_total + 1:natoms_total + natoms_current) = iptr(1:natoms_current)
559  natoms_total = natoms_total + natoms_current
560  END DO
561  END IF
562 
563  IF (is_molname .AND. nrep_molname > 0) THEN
564  DO irep = 1, nrep_molname
565  CALL section_vals_val_get(input_section, "MOLNAME", i_rep_section=i_rep_section, i_rep_val=irep, c_vals=cptr)
566  nnames = SIZE(cptr)
567 
568  DO iname = 1, nnames
569  DO ikind = 1, nkinds
570  IF (molecule_kind_set(ikind)%name .EQ. cptr(iname)) EXIT
571  END DO
572 
573  IF (ikind <= nkinds) THEN
574  molecule_kind => molecule_kind_set(ikind)
575  CALL get_molecule_kind(molecule_kind, nmolecule=nmols, molecule_list=iptr)
576 
577  DO imol = 1, nmols
578  molecule => molecule_set(iptr(imol))
579  CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
580 
581  DO natoms_current = first_atom, last_atom
582  natoms_total = natoms_total + 1
583  atomlist(natoms_total) = natoms_current
584  END DO
585  END DO
586  END IF
587  END DO
588  END DO
589  END IF
590 
591  ! remove duplicated atoms
592  ALLOCATE (inds(natoms_total))
593  CALL sort(atomlist, natoms_total, inds)
594  DEALLOCATE (inds)
595 
596  natoms_current = 1
597  DO iatom = natoms_current + 1, natoms_total
598  IF (atomlist(iatom) /= atomlist(natoms_current)) THEN
599  natoms_current = natoms_current + 1
600  atomlist(natoms_current) = atomlist(iatom)
601  END IF
602  END DO
603 
604  IF (natoms_current < natoms_total) THEN
605  CALL move_alloc(atomlist, inds)
606 
607  ALLOCATE (atomlist(natoms_current))
608  atomlist(1:natoms_current) = inds(1:natoms_current)
609  DEALLOCATE (inds)
610  END IF
611  END IF
612 
613  CALL timestop(handle)
614  END SUBROUTINE read_negf_atomlist
615 END MODULE negf_control_types
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell)
returns information about various attributes of the given subsys
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public negf_run
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
integer, parameter, public default_string_length
Definition: kinds.F:57
Definition of mathematical constants and functions.
Definition: mathconstants.F:16
real(kind=dp), parameter, public pi
Define the molecule kind structure types and the corresponding functionality.
subroutine, public get_molecule_kind(molecule_kind, atom_list, bond_list, bend_list, ub_list, impr_list, opbend_list, colv_list, fixd_list, g3x3_list, g4x6_list, vsite_list, torsion_list, shell_list, name, mass, charge, kind_number, natom, nbend, nbond, nub, nimpr, nopbend, nconstraint, nconstraint_fixd, nfixd, ncolv, ng3x3, ng4x6, nvsite, nfixd_restraint, ng3x3_restraint, ng4x6_restraint, nvsite_restraint, nrestraints, nmolecule, nsgf, nshell, ntorsion, molecule_list, nelectron, nelectron_alpha, nelectron_beta, bond_kind_set, bend_kind_set, ub_kind_set, impr_kind_set, opbend_kind_set, torsion_kind_set, molname_generated)
Get informations about a molecule kind.
Define the data structure for the molecule information.
subroutine, public get_molecule(molecule, molecule_kind, lmi, lci, lg3x3, lg4x6, lcolv, first_atom, last_atom, first_shell, last_shell)
Get components from a molecule data set.
Allocatable vectors for NEGF based quantum transport calculations.
Input control types for NEGF based quantum transport calculations.
subroutine, public negf_control_create(negf_control)
allocate control options for Non-equilibrium Green's Function calculation
subroutine, public read_negf_control(negf_control, input, subsys)
Read NEGF input parameters.
subroutine, public negf_control_release(negf_control)
release memory allocated for NEGF control options
Define the data structure for the particle information.
Definition of physical constants:
Definition: physcon.F:68
real(kind=dp), parameter, public kelvin
Definition: physcon.F:165
Utilities for string manipulations.
subroutine, public integer_to_string(inumber, string)
Converts an integer number to a string. The WRITE statement will return an error message,...
All kind of helpful little routines.
Definition: util.F:14