Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief NEGF based quantum transport calculations
10 : ! **************************************************************************************************
11 : MODULE negf_methods
12 : USE bibliography, ONLY: Bailey2006,&
13 : Papior2017,&
14 : cite_reference
15 : USE cp_blacs_env, ONLY: cp_blacs_env_type
16 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_scale,&
17 : cp_cfm_scale_and_add,&
18 : cp_cfm_trace
19 : USE cp_cfm_types, ONLY: &
20 : copy_cfm_info_type, cp_cfm_cleanup_copy_general, cp_cfm_create, &
21 : cp_cfm_finish_copy_general, cp_cfm_get_info, cp_cfm_get_submatrix, cp_cfm_release, &
22 : cp_cfm_set_submatrix, cp_cfm_start_copy_general, cp_cfm_to_fm, cp_cfm_type
23 : USE cp_control_types, ONLY: dft_control_type
24 : USE cp_dbcsr_api, ONLY: dbcsr_copy,&
25 : dbcsr_deallocate_matrix,&
26 : dbcsr_init_p,&
27 : dbcsr_p_type
28 : USE cp_dbcsr_contrib, ONLY: dbcsr_dot
29 : USE cp_dbcsr_operations, ONLY: dbcsr_allocate_matrix_set
30 : USE cp_fm_basic_linalg, ONLY: cp_fm_scale,&
31 : cp_fm_scale_and_add,&
32 : cp_fm_trace
33 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
34 : cp_fm_struct_release,&
35 : cp_fm_struct_type
36 : USE cp_fm_types, ONLY: &
37 : cp_fm_add_to_element, cp_fm_copy_general, cp_fm_create, cp_fm_get_info, &
38 : cp_fm_get_submatrix, cp_fm_release, cp_fm_set_all, cp_fm_to_fm, cp_fm_type
39 : USE cp_log_handling, ONLY: cp_get_default_logger,&
40 : cp_logger_get_default_io_unit,&
41 : cp_logger_type
42 : USE cp_output_handling, ONLY: cp_p_file,&
43 : cp_print_key_finished_output,&
44 : cp_print_key_should_output,&
45 : cp_print_key_unit_nr,&
46 : debug_print_level,&
47 : high_print_level
48 : USE cp_subsys_types, ONLY: cp_subsys_type
49 : USE force_env_types, ONLY: force_env_get,&
50 : force_env_p_type,&
51 : force_env_type
52 : USE global_types, ONLY: global_environment_type
53 : USE input_constants, ONLY: negfint_method_cc,&
54 : negfint_method_simpson
55 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
56 : section_vals_type,&
57 : section_vals_val_get
58 : USE kinds, ONLY: default_string_length,&
59 : dp
60 : USE kpoint_types, ONLY: get_kpoint_info,&
61 : kpoint_type
62 : USE machine, ONLY: m_walltime
63 : USE mathconstants, ONLY: pi,&
64 : twopi,&
65 : z_one,&
66 : z_zero
67 : USE message_passing, ONLY: mp_para_env_type
68 : USE negf_control_types, ONLY: negf_control_create,&
69 : negf_control_release,&
70 : negf_control_type,&
71 : read_negf_control
72 : USE negf_env_types, ONLY: negf_env_create,&
73 : negf_env_release,&
74 : negf_env_type
75 : USE negf_green_cache, ONLY: green_functions_cache_expand,&
76 : green_functions_cache_release,&
77 : green_functions_cache_reorder,&
78 : green_functions_cache_type
79 : USE negf_green_methods, ONLY: do_sancho,&
80 : negf_contact_broadening_matrix,&
81 : negf_contact_self_energy,&
82 : negf_retarded_green_function,&
83 : sancho_work_matrices_create,&
84 : sancho_work_matrices_release,&
85 : sancho_work_matrices_type
86 : USE negf_integr_cc, ONLY: &
87 : cc_interval_full, cc_interval_half, cc_shape_arc, cc_shape_linear, &
88 : ccquad_double_number_of_points, ccquad_init, ccquad_reduce_and_append_zdata, &
89 : ccquad_refine_integral, ccquad_release, ccquad_type
90 : USE negf_integr_simpson, ONLY: simpsonrule_get_next_nodes,&
91 : simpsonrule_init,&
92 : simpsonrule_refine_integral,&
93 : simpsonrule_release,&
94 : simpsonrule_type,&
95 : sr_shape_arc,&
96 : sr_shape_linear
97 : USE negf_matrix_utils, ONLY: invert_cell_to_index,&
98 : negf_copy_fm_submat_to_dbcsr,&
99 : negf_copy_sym_dbcsr_to_fm_submat
100 : USE negf_subgroup_types, ONLY: negf_sub_env_create,&
101 : negf_sub_env_release,&
102 : negf_subgroup_env_type
103 : USE parallel_gemm_api, ONLY: parallel_gemm
104 : USE physcon, ONLY: e_charge,&
105 : evolt,&
106 : kelvin,&
107 : seconds
108 : USE qs_density_mixing_types, ONLY: direct_mixing_nr,&
109 : gspace_mixing_nr
110 : USE qs_energy_types, ONLY: qs_energy_type
111 : USE qs_environment_types, ONLY: get_qs_env,&
112 : qs_environment_type
113 : USE qs_gspace_mixing, ONLY: gspace_mixing
114 : USE qs_ks_methods, ONLY: qs_ks_build_kohn_sham_matrix
115 : USE qs_mixing_utils, ONLY: mixing_allocate,&
116 : mixing_init
117 : USE qs_rho_methods, ONLY: qs_rho_update_rho
118 : USE qs_rho_types, ONLY: qs_rho_get,&
119 : qs_rho_type
120 : USE qs_scf_methods, ONLY: scf_env_density_mixing
121 : USE qs_subsys_types, ONLY: qs_subsys_type
122 : USE string_utilities, ONLY: integer_to_string
123 : #include "./base/base_uses.f90"
124 :
125 : IMPLICIT NONE
126 : PRIVATE
127 :
128 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'negf_methods'
129 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .TRUE.
130 :
131 : PUBLIC :: do_negf
132 :
133 : ! **************************************************************************************************
134 : !> \brief Type to accumulate the total number of points used in integration as well as
135 : !> the final error estimate
136 : !> \author Sergey Chulkov
137 : ! **************************************************************************************************
138 : TYPE integration_status_type
139 : INTEGER :: npoints = -1
140 : REAL(kind=dp) :: error = -1.0_dp
141 : END TYPE integration_status_type
142 :
143 : CONTAINS
144 :
145 : ! **************************************************************************************************
146 : !> \brief Perform NEGF calculation.
147 : !> \param force_env Force environment
148 : !> \par History
149 : !> * 01.2017 created [Sergey Chulkov]
150 : !> * 11.2025 modified [Dmitry Ryndyk]
151 : ! **************************************************************************************************
152 4 : SUBROUTINE do_negf(force_env)
153 : TYPE(force_env_type), POINTER :: force_env
154 :
155 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_negf'
156 :
157 : CHARACTER(len=default_string_length) :: contact_id_str
158 : INTEGER :: handle, icontact, ispin, log_unit, &
159 : ncontacts, npoints, nspins, &
160 : print_level, print_unit
161 : LOGICAL :: debug_output, should_output, &
162 : verbose_output
163 : REAL(kind=dp) :: energy_max, energy_min
164 : REAL(kind=dp), DIMENSION(2) :: current
165 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
166 : TYPE(cp_logger_type), POINTER :: logger
167 : TYPE(cp_subsys_type), POINTER :: cp_subsys
168 : TYPE(dft_control_type), POINTER :: dft_control
169 4 : TYPE(force_env_p_type), DIMENSION(:), POINTER :: sub_force_env
170 : TYPE(global_environment_type), POINTER :: global_env
171 : TYPE(mp_para_env_type), POINTER :: para_env_global
172 : TYPE(negf_control_type), POINTER :: negf_control
173 4 : TYPE(negf_env_type) :: negf_env
174 4 : TYPE(negf_subgroup_env_type) :: sub_env
175 : TYPE(qs_environment_type), POINTER :: qs_env
176 : TYPE(section_vals_type), POINTER :: negf_contact_section, &
177 : negf_mixing_section, negf_section, &
178 : print_section, root_section
179 :
180 4 : CALL timeset(routineN, handle)
181 4 : logger => cp_get_default_logger()
182 4 : log_unit = cp_logger_get_default_io_unit()
183 :
184 4 : CALL cite_reference(Bailey2006)
185 4 : CALL cite_reference(Papior2017)
186 :
187 4 : NULLIFY (blacs_env, cp_subsys, global_env, qs_env, root_section, sub_force_env)
188 : CALL force_env_get(force_env, globenv=global_env, qs_env=qs_env, root_section=root_section, &
189 4 : sub_force_env=sub_force_env, subsys=cp_subsys)
190 :
191 4 : CALL get_qs_env(qs_env, blacs_env=blacs_env, para_env=para_env_global)
192 :
193 4 : negf_section => section_vals_get_subs_vals(root_section, "NEGF")
194 4 : negf_contact_section => section_vals_get_subs_vals(negf_section, "CONTACT")
195 4 : negf_mixing_section => section_vals_get_subs_vals(negf_section, "MIXING")
196 :
197 4 : NULLIFY (negf_control)
198 4 : CALL negf_control_create(negf_control)
199 4 : CALL read_negf_control(negf_control, root_section, cp_subsys)
200 4 : CALL get_qs_env(qs_env, dft_control=dft_control)
201 :
202 : ! print unit, if log_unit > 0, otherwise no output
203 4 : log_unit = cp_print_key_unit_nr(logger, negf_section, "PRINT%PROGRAM_RUN_INFO", extension=".Log")
204 :
205 4 : IF (log_unit > 0) THEN
206 2 : WRITE (log_unit, '(/,T2,79("-"))')
207 2 : WRITE (log_unit, '(T27,A,T62)') "NEGF calculation is started"
208 2 : WRITE (log_unit, '(T2,79("-"))')
209 : END IF
210 :
211 : ! print levels, are used if log_unit > 0
212 : ! defined for all parallel MPI processes
213 4 : CALL section_vals_val_get(negf_section, "PRINT%PROGRAM_RUN_INFO%PRINT_LEVEL", i_val=print_level)
214 0 : SELECT CASE (print_level)
215 : CASE (high_print_level)
216 0 : verbose_output = .TRUE.
217 : CASE (debug_print_level)
218 4 : verbose_output = .TRUE.
219 4 : debug_output = .TRUE.
220 : CASE DEFAULT
221 0 : verbose_output = .FALSE.
222 4 : debug_output = .FALSE.
223 : END SELECT
224 :
225 4 : IF (log_unit > 0) THEN
226 2 : WRITE (log_unit, "(/,' THE RELEVANT HAMILTONIAN AND OVERLAP MATRICES FROM DFT')")
227 2 : WRITE (log_unit, "( ' ------------------------------------------------------')")
228 : END IF
229 :
230 4 : CALL negf_sub_env_create(sub_env, negf_control, blacs_env, global_env%blacs_grid_layout, global_env%blacs_repeatable)
231 4 : CALL negf_env_create(negf_env, sub_env, negf_control, force_env, negf_mixing_section, log_unit)
232 :
233 4 : IF (log_unit > 0) THEN
234 2 : WRITE (log_unit, "(/,' NEGF| The initial Hamiltonian and Overlap matrices are calculated.')")
235 : END IF
236 :
237 4 : CALL negf_output_initial(log_unit, negf_env, sub_env, negf_control, dft_control, verbose_output, debug_output)
238 :
239 : ! NEGF procedure
240 : ! --------------
241 :
242 : ! Compute contact Fermi levels as well as requested properties
243 : ! ------------------------------------------------------------
244 4 : ncontacts = SIZE(negf_control%contacts)
245 12 : DO icontact = 1, ncontacts
246 8 : NULLIFY (qs_env)
247 8 : IF (negf_control%contacts(icontact)%force_env_index > 0) THEN
248 4 : CALL force_env_get(sub_force_env(negf_control%contacts(icontact)%force_env_index)%force_env, qs_env=qs_env)
249 : ELSE
250 4 : CALL force_env_get(force_env, qs_env=qs_env)
251 : END IF
252 :
253 8 : CALL guess_fermi_level(icontact, negf_env, negf_control, sub_env, qs_env, log_unit)
254 :
255 8 : print_section => section_vals_get_subs_vals(negf_contact_section, "PRINT", i_rep_section=icontact)
256 8 : should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "DOS"), cp_p_file)
257 :
258 12 : IF (should_output) THEN
259 0 : CALL section_vals_val_get(print_section, "DOS%FROM_ENERGY", r_val=energy_min)
260 0 : CALL section_vals_val_get(print_section, "DOS%TILL_ENERGY", r_val=energy_max)
261 0 : CALL section_vals_val_get(print_section, "DOS%N_GRIDPOINTS", i_val=npoints)
262 :
263 0 : CALL integer_to_string(icontact, contact_id_str)
264 : print_unit = cp_print_key_unit_nr(logger, print_section, "DOS", &
265 : extension=".dos", &
266 : middle_name=TRIM(ADJUSTL(contact_id_str)), &
267 0 : file_status="REPLACE")
268 : CALL negf_print_dos(print_unit, energy_min, energy_max, npoints, &
269 : v_shift=0.0_dp, negf_env=negf_env, negf_control=negf_control, &
270 0 : sub_env=sub_env, base_contact=icontact, just_contact=icontact)
271 0 : CALL cp_print_key_finished_output(print_unit, logger, print_section, "DOS")
272 : END IF
273 :
274 : END DO
275 :
276 : ! Compute multi-terminal systems
277 : ! ------------------------------
278 4 : IF (ncontacts > 1) THEN
279 4 : CALL force_env_get(force_env, qs_env=qs_env)
280 :
281 : ! shift potential
282 : ! ---------------
283 4 : CALL shift_potential(negf_env, negf_control, sub_env, qs_env, base_contact=1, log_unit=log_unit)
284 :
285 : ! self-consistent density
286 : ! -----------------------
287 4 : CALL converge_density(negf_env, negf_control, sub_env, qs_env, negf_control%v_shift, base_contact=1, log_unit=log_unit)
288 :
289 : ! current
290 : ! -------
291 4 : CALL get_qs_env(qs_env, dft_control=dft_control)
292 :
293 4 : nspins = dft_control%nspins
294 :
295 4 : CPASSERT(nspins <= 2)
296 8 : DO ispin = 1, nspins
297 : ! compute the electric current flown through a pair of electrodes
298 : ! contact_id1 -> extended molecule -> contact_id2.
299 : ! Only extended systems with two electrodes are supported at the moment,
300 : ! so for the time being the contacts' indices are hardcoded.
301 : current(ispin) = negf_compute_current(contact_id1=1, contact_id2=2, &
302 : v_shift=negf_control%v_shift, &
303 : negf_env=negf_env, &
304 : negf_control=negf_control, &
305 : sub_env=sub_env, &
306 : ispin=ispin, &
307 8 : blacs_env_global=blacs_env)
308 : END DO
309 :
310 4 : IF (log_unit > 0) THEN
311 2 : IF (nspins > 1) THEN
312 0 : WRITE (log_unit, '(/,T2,A,T60,ES20.7E2)') "NEGF| Alpha-spin electric current (A)", current(1)
313 0 : WRITE (log_unit, '(T2,A,T60,ES20.7E2)') "NEGF| Beta-spin electric current (A)", current(2)
314 : ELSE
315 2 : WRITE (log_unit, '(/,T2,A,T60,ES20.7E2)') "NEGF| Electric current (A)", 2.0_dp*current(1)
316 : END IF
317 : END IF
318 :
319 : ! density of states
320 : ! -----------------
321 4 : print_section => section_vals_get_subs_vals(negf_section, "PRINT")
322 4 : should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "DOS"), cp_p_file)
323 :
324 4 : IF (should_output) THEN
325 4 : CALL section_vals_val_get(print_section, "DOS%FROM_ENERGY", r_val=energy_min)
326 4 : CALL section_vals_val_get(print_section, "DOS%TILL_ENERGY", r_val=energy_max)
327 4 : CALL section_vals_val_get(print_section, "DOS%N_GRIDPOINTS", i_val=npoints)
328 :
329 4 : CALL integer_to_string(0, contact_id_str)
330 : print_unit = cp_print_key_unit_nr(logger, print_section, "DOS", &
331 : extension=".dos", &
332 : middle_name=TRIM(ADJUSTL(contact_id_str)), &
333 4 : file_status="REPLACE")
334 :
335 : CALL negf_print_dos(print_unit, energy_min, energy_max, npoints, negf_control%v_shift, &
336 : negf_env=negf_env, negf_control=negf_control, &
337 4 : sub_env=sub_env, base_contact=1)
338 :
339 4 : CALL cp_print_key_finished_output(print_unit, logger, print_section, "DOS")
340 : END IF
341 :
342 : ! transmission coefficient
343 : ! ------------------------
344 4 : should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "TRANSMISSION"), cp_p_file)
345 :
346 4 : IF (should_output) THEN
347 4 : CALL section_vals_val_get(print_section, "TRANSMISSION%FROM_ENERGY", r_val=energy_min)
348 4 : CALL section_vals_val_get(print_section, "TRANSMISSION%TILL_ENERGY", r_val=energy_max)
349 4 : CALL section_vals_val_get(print_section, "TRANSMISSION%N_GRIDPOINTS", i_val=npoints)
350 :
351 4 : CALL integer_to_string(0, contact_id_str)
352 : print_unit = cp_print_key_unit_nr(logger, print_section, "TRANSMISSION", &
353 : extension=".transm", &
354 : middle_name=TRIM(ADJUSTL(contact_id_str)), &
355 4 : file_status="REPLACE")
356 :
357 : CALL negf_print_transmission(print_unit, energy_min, energy_max, npoints, negf_control%v_shift, &
358 : negf_env=negf_env, negf_control=negf_control, &
359 4 : sub_env=sub_env, contact_id1=1, contact_id2=2)
360 :
361 4 : CALL cp_print_key_finished_output(print_unit, logger, print_section, "TRANSMISSION")
362 : END IF
363 :
364 : END IF
365 :
366 4 : IF (log_unit > 0) THEN
367 2 : WRITE (log_unit, '(/,T2,79("-"))')
368 2 : WRITE (log_unit, '(T27,A,T62)') "NEGF calculation is finished"
369 2 : WRITE (log_unit, '(T2,79("-"))')
370 : END IF
371 :
372 4 : CALL negf_env_release(negf_env)
373 4 : CALL negf_sub_env_release(sub_env)
374 4 : CALL negf_control_release(negf_control)
375 4 : CALL timestop(handle)
376 8 : END SUBROUTINE do_negf
377 :
378 : ! **************************************************************************************************
379 : !> \brief Compute the contact's Fermi level.
380 : !> \param contact_id index of the contact
381 : !> \param negf_env NEGF environment
382 : !> \param negf_control NEGF control
383 : !> \param sub_env NEGF parallel (sub)group environment
384 : !> \param qs_env QuickStep environment
385 : !> \param log_unit output unit
386 : !> \par History
387 : !> * 10.2017 created [Sergey Chulkov]
388 : !> * 11.2025 modified [Dmitry Ryndyk]
389 : ! **************************************************************************************************
390 8 : SUBROUTINE guess_fermi_level(contact_id, negf_env, negf_control, sub_env, qs_env, log_unit)
391 : INTEGER, INTENT(in) :: contact_id
392 : TYPE(negf_env_type), INTENT(inout) :: negf_env
393 : TYPE(negf_control_type), POINTER :: negf_control
394 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
395 : TYPE(qs_environment_type), POINTER :: qs_env
396 : INTEGER, INTENT(in) :: log_unit
397 :
398 : CHARACTER(LEN=*), PARAMETER :: routineN = 'guess_fermi_level'
399 : TYPE(cp_fm_type), PARAMETER :: fm_dummy = cp_fm_type()
400 :
401 : CHARACTER(len=default_string_length) :: temperature_str
402 : COMPLEX(kind=dp) :: lbound_cpath, lbound_lpath, ubound_lpath
403 : INTEGER :: direction_axis_abs, handle, image, &
404 : ispin, nao, nimages, nspins, step
405 8 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: index_to_cell
406 8 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
407 : LOGICAL :: do_kpoints
408 : REAL(kind=dp) :: delta_au, delta_Ef, energy_ubound_minus_fermi, fermi_level_guess, &
409 : fermi_level_max, fermi_level_min, nelectrons_guess, nelectrons_max, nelectrons_min, &
410 : nelectrons_qs_cell0, nelectrons_qs_cell1, offset_au, rscale, t1, t2, trace
411 : TYPE(cp_blacs_env_type), POINTER :: blacs_env_global
412 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
413 : TYPE(cp_fm_type) :: rho_ao_fm
414 : TYPE(cp_fm_type), POINTER :: matrix_s_fm
415 8 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s_kp, rho_ao_qs_kp
416 : TYPE(dft_control_type), POINTER :: dft_control
417 8 : TYPE(green_functions_cache_type) :: g_surf_cache
418 : TYPE(integration_status_type) :: stats
419 : TYPE(kpoint_type), POINTER :: kpoints
420 : TYPE(mp_para_env_type), POINTER :: para_env_global
421 : TYPE(qs_energy_type), POINTER :: energy
422 : TYPE(qs_rho_type), POINTER :: rho_struct
423 : TYPE(qs_subsys_type), POINTER :: subsys
424 :
425 8 : CALL timeset(routineN, handle)
426 :
427 8 : IF (log_unit > 0) THEN
428 4 : WRITE (temperature_str, '(F11.3)') negf_control%contacts(contact_id)%temperature*kelvin
429 4 : WRITE (log_unit, '(/,T2,A,I3)') "FERMI LEVEL OF CONTACT ", contact_id
430 4 : WRITE (log_unit, "( ' --------------------------')")
431 4 : WRITE (log_unit, '(A)') " Temperature "//TRIM(ADJUSTL(temperature_str))//" Kelvin"
432 : END IF
433 :
434 8 : IF (negf_control%contacts(contact_id)%compute_fermi_level) THEN
435 :
436 : CALL get_qs_env(qs_env, &
437 : blacs_env=blacs_env_global, &
438 : dft_control=dft_control, &
439 : do_kpoints=do_kpoints, &
440 : kpoints=kpoints, &
441 : matrix_s_kp=matrix_s_kp, &
442 : para_env=para_env_global, &
443 4 : rho=rho_struct, subsys=subsys)
444 4 : CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
445 :
446 4 : nimages = dft_control%nimages
447 4 : nspins = dft_control%nspins
448 4 : direction_axis_abs = ABS(negf_env%contacts(contact_id)%direction_axis)
449 :
450 4 : CPASSERT(SIZE(negf_env%contacts(contact_id)%h_00) == nspins)
451 :
452 4 : IF (sub_env%ngroups > 1) THEN
453 4 : NULLIFY (matrix_s_fm, fm_struct)
454 :
455 4 : CALL cp_fm_get_info(negf_env%contacts(contact_id)%s_00, nrow_global=nao)
456 4 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env_global)
457 4 : CALL cp_fm_create(rho_ao_fm, fm_struct)
458 :
459 4 : ALLOCATE (matrix_s_fm)
460 4 : CALL cp_fm_create(matrix_s_fm, fm_struct)
461 4 : CALL cp_fm_struct_release(fm_struct)
462 :
463 4 : IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
464 2 : CALL cp_fm_copy_general(negf_env%contacts(contact_id)%s_00, matrix_s_fm, para_env_global)
465 : ELSE
466 2 : CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env_global)
467 : END IF
468 : ELSE
469 0 : matrix_s_fm => negf_env%contacts(contact_id)%s_00
470 0 : CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
471 0 : CALL cp_fm_create(rho_ao_fm, fm_struct)
472 : END IF
473 :
474 4 : IF (do_kpoints) THEN
475 0 : CALL get_kpoint_info(kpoints, cell_to_index=cell_to_index)
476 : ELSE
477 4 : ALLOCATE (cell_to_index(0:0, 0:0, 0:0))
478 4 : cell_to_index(0, 0, 0) = 1
479 : END IF
480 :
481 12 : ALLOCATE (index_to_cell(3, nimages))
482 4 : CALL invert_cell_to_index(cell_to_index, nimages, index_to_cell)
483 4 : IF (.NOT. do_kpoints) DEALLOCATE (cell_to_index)
484 :
485 4 : IF (nspins == 1) THEN
486 : ! spin-restricted calculation: number of electrons must be doubled
487 : rscale = 2.0_dp
488 : ELSE
489 0 : rscale = 1.0_dp
490 : END IF
491 :
492 : ! compute the refence number of electrons using the electron density
493 4 : nelectrons_qs_cell0 = 0.0_dp
494 4 : nelectrons_qs_cell1 = 0.0_dp
495 4 : IF (negf_control%contacts(contact_id)%force_env_index > 0) THEN
496 0 : DO image = 1, nimages
497 0 : IF (index_to_cell(direction_axis_abs, image) == 0) THEN
498 0 : DO ispin = 1, nspins
499 0 : CALL dbcsr_dot(rho_ao_qs_kp(ispin, image)%matrix, matrix_s_kp(1, image)%matrix, trace)
500 0 : nelectrons_qs_cell0 = nelectrons_qs_cell0 + trace
501 : END DO
502 0 : ELSE IF (ABS(index_to_cell(direction_axis_abs, image)) == 1) THEN
503 0 : DO ispin = 1, nspins
504 0 : CALL dbcsr_dot(rho_ao_qs_kp(ispin, image)%matrix, matrix_s_kp(1, image)%matrix, trace)
505 0 : nelectrons_qs_cell1 = nelectrons_qs_cell1 + trace
506 : END DO
507 : END IF
508 : END DO
509 : ELSE
510 8 : DO ispin = 1, nspins
511 : CALL cp_fm_trace(negf_env%contacts(contact_id)%rho_00(ispin), &
512 4 : negf_env%contacts(contact_id)%s_00, trace)
513 4 : nelectrons_qs_cell0 = nelectrons_qs_cell0 + trace
514 : CALL cp_fm_trace(negf_env%contacts(contact_id)%rho_01(ispin), &
515 4 : negf_env%contacts(contact_id)%s_01, trace)
516 8 : nelectrons_qs_cell1 = nelectrons_qs_cell1 + 2.0_dp*trace
517 : END DO
518 : END IF
519 :
520 4 : DEALLOCATE (index_to_cell)
521 :
522 4 : IF (log_unit > 0) THEN
523 2 : WRITE (log_unit, '(A)') " Computing the Fermi level of bulk electrode"
524 2 : WRITE (log_unit, '(T2,A,T60,F20.10,/)') "Electronic density of the electrode unit cell:", &
525 4 : -1.0_dp*(nelectrons_qs_cell0 + nelectrons_qs_cell1)
526 2 : WRITE (log_unit, '(T3,A)') "Step Integration method Time Fermi level Convergence (density)"
527 2 : WRITE (log_unit, '(T3,78("-"))')
528 : END IF
529 :
530 : ! Use the Fermi level given in the input file or the Fermi level of bulk electrodes as a reference point
531 : ! and then refine the Fermi level by using a simple linear interpolation technique
532 4 : CALL get_qs_env(qs_env, energy=energy)
533 4 : IF (negf_control%homo_lumo_gap > 0.0_dp) THEN
534 4 : IF (negf_control%contacts(contact_id)%refine_fermi_level) THEN
535 4 : fermi_level_min = negf_control%contacts(contact_id)%fermi_level
536 : ELSE
537 0 : fermi_level_min = energy%efermi
538 : END IF
539 4 : fermi_level_max = fermi_level_min + negf_control%homo_lumo_gap
540 : ELSE
541 0 : IF (negf_control%contacts(contact_id)%refine_fermi_level) THEN
542 0 : fermi_level_max = negf_control%contacts(contact_id)%fermi_level
543 : ELSE
544 0 : fermi_level_max = energy%efermi
545 : END IF
546 0 : fermi_level_min = fermi_level_max + negf_control%homo_lumo_gap
547 : END IF
548 :
549 4 : step = 0
550 4 : lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
551 4 : delta_au = REAL(negf_control%delta_npoles, kind=dp)*twopi*negf_control%contacts(contact_id)%temperature
552 4 : offset_au = REAL(negf_control%gamma_kT, kind=dp)*negf_control%contacts(contact_id)%temperature
553 4 : energy_ubound_minus_fermi = -2.0_dp*LOG(negf_control%conv_density)*negf_control%contacts(contact_id)%temperature
554 4 : t1 = m_walltime()
555 :
556 : DO
557 4 : step = step + 1
558 :
559 4 : SELECT CASE (step)
560 : CASE (1)
561 4 : fermi_level_guess = fermi_level_min
562 : CASE (2)
563 0 : fermi_level_guess = fermi_level_max
564 : CASE DEFAULT
565 : fermi_level_guess = fermi_level_min - (nelectrons_min - nelectrons_qs_cell0)* &
566 4 : (fermi_level_max - fermi_level_min)/(nelectrons_max - nelectrons_min)
567 : END SELECT
568 :
569 4 : negf_control%contacts(contact_id)%fermi_level = fermi_level_guess
570 4 : nelectrons_guess = 0.0_dp
571 :
572 4 : lbound_lpath = CMPLX(fermi_level_guess - offset_au, delta_au, kind=dp)
573 4 : ubound_lpath = CMPLX(fermi_level_guess + energy_ubound_minus_fermi, delta_au, kind=dp)
574 :
575 4 : CALL integration_status_reset(stats)
576 :
577 8 : DO ispin = 1, nspins
578 : CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_fm, &
579 : v_shift=0.0_dp, &
580 : ignore_bias=.TRUE., &
581 : negf_env=negf_env, &
582 : negf_control=negf_control, &
583 : sub_env=sub_env, &
584 : ispin=ispin, &
585 : base_contact=contact_id, &
586 4 : just_contact=contact_id)
587 :
588 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm, &
589 : stats=stats, &
590 : v_shift=0.0_dp, &
591 : ignore_bias=.TRUE., &
592 : negf_env=negf_env, &
593 : negf_control=negf_control, &
594 : sub_env=sub_env, &
595 : ispin=ispin, &
596 : base_contact=contact_id, &
597 : integr_lbound=lbound_cpath, &
598 : integr_ubound=lbound_lpath, &
599 : matrix_s_global=matrix_s_fm, &
600 : is_circular=.TRUE., &
601 : g_surf_cache=g_surf_cache, &
602 4 : just_contact=contact_id)
603 4 : CALL green_functions_cache_release(g_surf_cache)
604 :
605 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm, &
606 : stats=stats, &
607 : v_shift=0.0_dp, &
608 : ignore_bias=.TRUE., &
609 : negf_env=negf_env, &
610 : negf_control=negf_control, &
611 : sub_env=sub_env, &
612 : ispin=ispin, &
613 : base_contact=contact_id, &
614 : integr_lbound=lbound_lpath, &
615 : integr_ubound=ubound_lpath, &
616 : matrix_s_global=matrix_s_fm, &
617 : is_circular=.FALSE., &
618 : g_surf_cache=g_surf_cache, &
619 4 : just_contact=contact_id)
620 4 : CALL green_functions_cache_release(g_surf_cache)
621 :
622 4 : CALL cp_fm_trace(rho_ao_fm, matrix_s_fm, trace)
623 8 : nelectrons_guess = nelectrons_guess + trace
624 : END DO
625 4 : nelectrons_guess = nelectrons_guess*rscale
626 :
627 4 : t2 = m_walltime()
628 :
629 4 : IF (log_unit > 0) THEN
630 : WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T42,F15.8,T60,ES20.5E2)') &
631 2 : step, get_method_description_string(stats, negf_control%integr_method), &
632 4 : t2 - t1, fermi_level_guess, nelectrons_guess - nelectrons_qs_cell0
633 : END IF
634 :
635 4 : IF (ABS(nelectrons_qs_cell0 - nelectrons_guess) < negf_control%conv_density) EXIT
636 :
637 : SELECT CASE (step)
638 : CASE (1)
639 0 : nelectrons_min = nelectrons_guess
640 : CASE (2)
641 0 : nelectrons_max = nelectrons_guess
642 : CASE DEFAULT
643 0 : IF (fermi_level_guess < fermi_level_min) THEN
644 : fermi_level_max = fermi_level_min
645 : nelectrons_max = nelectrons_min
646 : fermi_level_min = fermi_level_guess
647 : nelectrons_min = nelectrons_guess
648 0 : ELSE IF (fermi_level_guess > fermi_level_max) THEN
649 : fermi_level_min = fermi_level_max
650 : nelectrons_min = nelectrons_max
651 : fermi_level_max = fermi_level_guess
652 : nelectrons_max = nelectrons_guess
653 0 : ELSE IF (fermi_level_max - fermi_level_guess < fermi_level_guess - fermi_level_min) THEN
654 : fermi_level_max = fermi_level_guess
655 : nelectrons_max = nelectrons_guess
656 : ELSE
657 0 : fermi_level_min = fermi_level_guess
658 0 : nelectrons_min = nelectrons_guess
659 : END IF
660 : END SELECT
661 :
662 4 : t1 = t2
663 : END DO
664 :
665 4 : negf_control%contacts(contact_id)%fermi_level = fermi_level_guess
666 :
667 4 : IF (sub_env%ngroups > 1) THEN
668 4 : CALL cp_fm_release(matrix_s_fm)
669 4 : DEALLOCATE (matrix_s_fm)
670 : END IF
671 4 : CALL cp_fm_release(rho_ao_fm)
672 : END IF
673 :
674 8 : IF (negf_control%contacts(contact_id)%shift_fermi_level) THEN
675 0 : delta_Ef = negf_control%contacts(contact_id)%fermi_level_shifted - negf_control%contacts(contact_id)%fermi_level
676 0 : IF (log_unit > 0) WRITE (log_unit, "(/,' The energies are shifted by (a.u.):',F18.8)") delta_Ef
677 0 : IF (log_unit > 0) WRITE (log_unit, "(' (eV):',F18.8)") delta_Ef*evolt
678 0 : negf_control%contacts(contact_id)%fermi_level = negf_control%contacts(contact_id)%fermi_level_shifted
679 0 : CALL get_qs_env(qs_env, dft_control=dft_control)
680 0 : nspins = dft_control%nspins
681 0 : CALL cp_fm_get_info(negf_env%contacts(contact_id)%s_00, nrow_global=nao)
682 0 : DO ispin = 1, nspins
683 0 : DO step = 1, nao
684 0 : CALL cp_fm_add_to_element(negf_env%contacts(contact_id)%h_00(ispin), step, step, delta_Ef)
685 : END DO
686 : END DO
687 : END IF
688 :
689 8 : IF (log_unit > 0) THEN
690 4 : WRITE (temperature_str, '(F11.3)') negf_control%contacts(contact_id)%temperature*kelvin
691 4 : WRITE (log_unit, '(/,T2,A,I0)') "NEGF| Contact No. ", contact_id
692 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| Fermi level at "//TRIM(ADJUSTL(temperature_str))// &
693 4 : " Kelvin (a.u.):", negf_control%contacts(contact_id)%fermi_level
694 4 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| (eV):", &
695 8 : negf_control%contacts(contact_id)%fermi_level*evolt
696 4 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| Electric potential (a.u.):", &
697 8 : negf_control%contacts(contact_id)%v_external
698 4 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| (Volt):", &
699 8 : negf_control%contacts(contact_id)%v_external*evolt
700 4 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| Electro-chemical potential Ef-|e|V (a.u.):", &
701 8 : (negf_control%contacts(contact_id)%fermi_level - negf_control%contacts(contact_id)%v_external)
702 4 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| (eV):", &
703 8 : (negf_control%contacts(contact_id)%fermi_level - negf_control%contacts(contact_id)%v_external)*evolt
704 : END IF
705 :
706 8 : CALL timestop(handle)
707 16 : END SUBROUTINE guess_fermi_level
708 :
709 : ! **************************************************************************************************
710 : !> \brief Compute shift in Hartree potential
711 : !> \param negf_env NEGF environment
712 : !> \param negf_control NEGF control
713 : !> \param sub_env NEGF parallel (sub)group environment
714 : !> \param qs_env QuickStep environment
715 : !> \param base_contact index of the reference contact
716 : !> \param log_unit output unit
717 : !> * 09.2017 created [Sergey Chulkov]
718 : !> * 11.2025 modified [Dmitry Ryndyk]
719 : ! **************************************************************************************************
720 4 : SUBROUTINE shift_potential(negf_env, negf_control, sub_env, qs_env, base_contact, log_unit)
721 : TYPE(negf_env_type), INTENT(in) :: negf_env
722 : TYPE(negf_control_type), POINTER :: negf_control
723 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
724 : TYPE(qs_environment_type), POINTER :: qs_env
725 : INTEGER, INTENT(in) :: base_contact, log_unit
726 :
727 : CHARACTER(LEN=*), PARAMETER :: routineN = 'shift_potential'
728 : TYPE(cp_fm_type), PARAMETER :: fm_dummy = cp_fm_type()
729 :
730 : COMPLEX(kind=dp) :: lbound_cpath, ubound_cpath, ubound_lpath
731 : INTEGER :: handle, ispin, iter_count, nao, &
732 : ncontacts, nspins
733 : LOGICAL :: do_kpoints
734 : REAL(kind=dp) :: mu_base, nelectrons_guess, nelectrons_max, nelectrons_min, nelectrons_ref, &
735 : t1, t2, temperature, trace, v_shift_guess, v_shift_max, v_shift_min
736 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
737 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
738 4 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: rho_ao_fm
739 : TYPE(cp_fm_type), POINTER :: matrix_s_fm
740 4 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_qs_kp
741 : TYPE(dft_control_type), POINTER :: dft_control
742 : TYPE(green_functions_cache_type), ALLOCATABLE, &
743 4 : DIMENSION(:) :: g_surf_circular, g_surf_linear
744 : TYPE(integration_status_type) :: stats
745 : TYPE(mp_para_env_type), POINTER :: para_env
746 : TYPE(qs_rho_type), POINTER :: rho_struct
747 : TYPE(qs_subsys_type), POINTER :: subsys
748 :
749 4 : ncontacts = SIZE(negf_control%contacts)
750 : ! nothing to do
751 4 : IF (.NOT. (ALLOCATED(negf_env%h_s) .AND. ALLOCATED(negf_env%h_sc) .AND. &
752 : ASSOCIATED(negf_env%s_s) .AND. ALLOCATED(negf_env%s_sc))) RETURN
753 4 : IF (ncontacts < 2) RETURN
754 4 : IF (negf_control%v_shift_maxiters == 0) RETURN
755 :
756 4 : CALL timeset(routineN, handle)
757 :
758 : CALL get_qs_env(qs_env, blacs_env=blacs_env, do_kpoints=do_kpoints, dft_control=dft_control, &
759 4 : para_env=para_env, rho=rho_struct, subsys=subsys)
760 4 : CPASSERT(.NOT. do_kpoints)
761 :
762 : ! apply external NEGF potential
763 4 : t1 = m_walltime()
764 :
765 : ! need a globally distributed overlap matrix in order to compute integration errors
766 4 : IF (sub_env%ngroups > 1) THEN
767 4 : NULLIFY (matrix_s_fm, fm_struct)
768 :
769 4 : CALL cp_fm_get_info(negf_env%s_s, nrow_global=nao)
770 4 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
771 :
772 4 : ALLOCATE (matrix_s_fm)
773 4 : CALL cp_fm_create(matrix_s_fm, fm_struct)
774 4 : CALL cp_fm_struct_release(fm_struct)
775 :
776 4 : IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
777 2 : CALL cp_fm_copy_general(negf_env%s_s, matrix_s_fm, para_env)
778 : ELSE
779 2 : CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env)
780 : END IF
781 : ELSE
782 0 : matrix_s_fm => negf_env%s_s
783 : END IF
784 :
785 4 : CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
786 :
787 4 : nspins = SIZE(negf_env%h_s)
788 :
789 4 : mu_base = negf_control%contacts(base_contact)%fermi_level
790 :
791 : ! keep the initial charge density matrix and Kohn-Sham matrix
792 4 : CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
793 :
794 : ! extract the reference density matrix blocks
795 4 : nelectrons_ref = 0.0_dp
796 16 : ALLOCATE (rho_ao_fm(nspins))
797 8 : DO ispin = 1, nspins
798 4 : CALL cp_fm_create(rho_ao_fm(ispin), fm_struct)
799 :
800 : CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
801 : fm=rho_ao_fm(ispin), &
802 : atomlist_row=negf_control%atomlist_S_screening, &
803 : atomlist_col=negf_control%atomlist_S_screening, &
804 : subsys=subsys, mpi_comm_global=para_env, &
805 4 : do_upper_diag=.TRUE., do_lower=.TRUE.)
806 :
807 4 : CALL cp_fm_trace(rho_ao_fm(ispin), matrix_s_fm, trace)
808 8 : nelectrons_ref = nelectrons_ref + trace
809 : END DO
810 :
811 4 : IF (log_unit > 0) THEN
812 2 : WRITE (log_unit, '(/,T2,A)') "COMPUTE SHIFT IN HARTREE POTENTIAL"
813 2 : WRITE (log_unit, "( ' ----------------------------------')")
814 2 : WRITE (log_unit, '(/,T2,A,T55,F25.14,/)') "Initial electronic density of the scattering region:", -1.0_dp*nelectrons_ref
815 2 : WRITE (log_unit, '(T3,A)') "Step Integration method Time V shift Convergence (density)"
816 2 : WRITE (log_unit, '(T3,78("-"))')
817 : END IF
818 :
819 4 : temperature = negf_control%contacts(base_contact)%temperature
820 :
821 : ! integration limits: C-path (arch)
822 4 : lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
823 : ubound_cpath = CMPLX(mu_base - REAL(negf_control%gamma_kT, kind=dp)*temperature, &
824 4 : REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
825 :
826 : ! integration limits: L-path (linear)
827 : ubound_lpath = CMPLX(mu_base - LOG(negf_control%conv_density)*temperature, &
828 4 : REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
829 :
830 4 : v_shift_min = negf_control%v_shift
831 4 : v_shift_max = negf_control%v_shift + negf_control%v_shift_offset
832 :
833 24 : ALLOCATE (g_surf_circular(nspins), g_surf_linear(nspins))
834 :
835 10 : DO iter_count = 1, negf_control%v_shift_maxiters
836 4 : SELECT CASE (iter_count)
837 : CASE (1)
838 4 : v_shift_guess = v_shift_min
839 : CASE (2)
840 2 : v_shift_guess = v_shift_max
841 : CASE DEFAULT
842 : v_shift_guess = v_shift_min - (nelectrons_min - nelectrons_ref)* &
843 10 : (v_shift_max - v_shift_min)/(nelectrons_max - nelectrons_min)
844 : END SELECT
845 :
846 : ! compute an updated density matrix
847 10 : CALL integration_status_reset(stats)
848 :
849 20 : DO ispin = 1, nspins
850 : ! closed contour: residuals
851 : CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_fm(ispin), &
852 : v_shift=v_shift_guess, &
853 : ignore_bias=.TRUE., &
854 : negf_env=negf_env, &
855 : negf_control=negf_control, &
856 : sub_env=sub_env, &
857 : ispin=ispin, &
858 10 : base_contact=base_contact)
859 :
860 : ! closed contour: C-path
861 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm(ispin), &
862 : stats=stats, &
863 : v_shift=v_shift_guess, &
864 : ignore_bias=.TRUE., &
865 : negf_env=negf_env, &
866 : negf_control=negf_control, &
867 : sub_env=sub_env, &
868 : ispin=ispin, &
869 : base_contact=base_contact, &
870 : integr_lbound=lbound_cpath, &
871 : integr_ubound=ubound_cpath, &
872 : matrix_s_global=matrix_s_fm, &
873 : is_circular=.TRUE., &
874 10 : g_surf_cache=g_surf_circular(ispin))
875 10 : IF (negf_control%disable_cache) &
876 0 : CALL green_functions_cache_release(g_surf_circular(ispin))
877 :
878 : ! closed contour: L-path
879 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm(ispin), &
880 : stats=stats, &
881 : v_shift=v_shift_guess, &
882 : ignore_bias=.TRUE., &
883 : negf_env=negf_env, &
884 : negf_control=negf_control, &
885 : sub_env=sub_env, &
886 : ispin=ispin, &
887 : base_contact=base_contact, &
888 : integr_lbound=ubound_cpath, &
889 : integr_ubound=ubound_lpath, &
890 : matrix_s_global=matrix_s_fm, &
891 : is_circular=.FALSE., &
892 10 : g_surf_cache=g_surf_linear(ispin))
893 10 : IF (negf_control%disable_cache) &
894 10 : CALL green_functions_cache_release(g_surf_linear(ispin))
895 : END DO
896 :
897 10 : IF (nspins > 1) THEN
898 0 : DO ispin = 2, nspins
899 0 : CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm(1), 1.0_dp, rho_ao_fm(ispin))
900 : END DO
901 : ELSE
902 10 : CALL cp_fm_scale(2.0_dp, rho_ao_fm(1))
903 : END IF
904 :
905 10 : CALL cp_fm_trace(rho_ao_fm(1), matrix_s_fm, nelectrons_guess)
906 :
907 10 : t2 = m_walltime()
908 :
909 10 : IF (log_unit > 0) THEN
910 : WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T42,F15.8,T60,ES20.5E2)') &
911 5 : iter_count, get_method_description_string(stats, negf_control%integr_method), &
912 10 : t2 - t1, v_shift_guess, nelectrons_guess - nelectrons_ref
913 : END IF
914 :
915 10 : IF (ABS(nelectrons_guess - nelectrons_ref) < negf_control%conv_scf) EXIT
916 :
917 : ! compute correction
918 : SELECT CASE (iter_count)
919 : CASE (1)
920 2 : nelectrons_min = nelectrons_guess
921 : CASE (2)
922 2 : nelectrons_max = nelectrons_guess
923 : CASE DEFAULT
924 6 : IF (v_shift_guess < v_shift_min) THEN
925 : v_shift_max = v_shift_min
926 : nelectrons_max = nelectrons_min
927 : v_shift_min = v_shift_guess
928 : nelectrons_min = nelectrons_guess
929 0 : ELSE IF (v_shift_guess > v_shift_max) THEN
930 : v_shift_min = v_shift_max
931 : nelectrons_min = nelectrons_max
932 : v_shift_max = v_shift_guess
933 : nelectrons_max = nelectrons_guess
934 0 : ELSE IF (v_shift_max - v_shift_guess < v_shift_guess - v_shift_min) THEN
935 : v_shift_max = v_shift_guess
936 : nelectrons_max = nelectrons_guess
937 : ELSE
938 0 : v_shift_min = v_shift_guess
939 0 : nelectrons_min = nelectrons_guess
940 : END IF
941 : END SELECT
942 :
943 20 : t1 = t2
944 : END DO
945 :
946 4 : negf_control%v_shift = v_shift_guess
947 :
948 4 : IF (log_unit > 0) THEN
949 2 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| Shift in Hartree potential (a.u.):", negf_control%v_shift
950 2 : WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF| (eV):", negf_control%v_shift*evolt
951 : END IF
952 :
953 8 : DO ispin = nspins, 1, -1
954 4 : CALL green_functions_cache_release(g_surf_circular(ispin))
955 8 : CALL green_functions_cache_release(g_surf_linear(ispin))
956 : END DO
957 12 : DEALLOCATE (g_surf_circular, g_surf_linear)
958 :
959 4 : CALL cp_fm_release(rho_ao_fm)
960 :
961 4 : IF (sub_env%ngroups > 1 .AND. ASSOCIATED(matrix_s_fm)) THEN
962 4 : CALL cp_fm_release(matrix_s_fm)
963 4 : DEALLOCATE (matrix_s_fm)
964 : END IF
965 :
966 4 : CALL timestop(handle)
967 12 : END SUBROUTINE shift_potential
968 :
969 : ! **************************************************************************************************
970 : !> \brief Converge electronic density of the scattering region.
971 : !> \param negf_env NEGF environment
972 : !> \param negf_control NEGF control
973 : !> \param sub_env NEGF parallel (sub)group environment
974 : !> \param qs_env QuickStep environment
975 : !> \param v_shift shift in Hartree potential
976 : !> \param base_contact index of the reference contact
977 : !> \param log_unit output unit
978 : !> \par History
979 : !> * 06.2017 created [Sergey Chulkov]
980 : !> * 11.2025 modified [Dmitry Ryndyk]
981 : ! **************************************************************************************************
982 4 : SUBROUTINE converge_density(negf_env, negf_control, sub_env, qs_env, v_shift, base_contact, log_unit)
983 : TYPE(negf_env_type), INTENT(in) :: negf_env
984 : TYPE(negf_control_type), POINTER :: negf_control
985 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
986 : TYPE(qs_environment_type), POINTER :: qs_env
987 : REAL(kind=dp), INTENT(in) :: v_shift
988 : INTEGER, INTENT(in) :: base_contact, log_unit
989 :
990 : CHARACTER(LEN=*), PARAMETER :: routineN = 'converge_density'
991 : REAL(kind=dp), PARAMETER :: threshold = 16.0_dp*EPSILON(0.0_dp)
992 : TYPE(cp_fm_type), PARAMETER :: fm_dummy = cp_fm_type()
993 :
994 : COMPLEX(kind=dp) :: lbound_cpath, ubound_cpath, ubound_lpath
995 : INTEGER :: handle, icontact, image, ispin, &
996 : iter_count, nao, ncontacts, nimages, &
997 : nspins
998 : LOGICAL :: do_kpoints
999 : REAL(kind=dp) :: delta, iter_delta, mu_base, nelectrons, &
1000 : nelectrons_diff, t1, t2, temperature, &
1001 : trace, v_base
1002 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1003 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1004 4 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: rho_ao_delta_fm, rho_ao_new_fm
1005 : TYPE(cp_fm_type), POINTER :: matrix_s_fm
1006 4 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_initial_kp, matrix_ks_qs_kp, &
1007 4 : rho_ao_initial_kp, rho_ao_new_kp, &
1008 4 : rho_ao_qs_kp
1009 : TYPE(dft_control_type), POINTER :: dft_control
1010 : TYPE(green_functions_cache_type), ALLOCATABLE, &
1011 4 : DIMENSION(:) :: g_surf_circular, g_surf_linear, &
1012 4 : g_surf_nonequiv
1013 : TYPE(integration_status_type) :: stats
1014 : TYPE(mp_para_env_type), POINTER :: para_env
1015 : TYPE(qs_rho_type), POINTER :: rho_struct
1016 : TYPE(qs_subsys_type), POINTER :: subsys
1017 :
1018 4 : ncontacts = SIZE(negf_control%contacts)
1019 : ! the current subroutine works for the general case as well, but the Poisson solver does not
1020 4 : IF (ncontacts > 2) THEN
1021 0 : CPABORT("Poisson solver does not support the general NEGF setup (>2 contacts).")
1022 : END IF
1023 : ! nothing to do
1024 4 : IF (.NOT. (ALLOCATED(negf_env%h_s) .AND. ALLOCATED(negf_env%h_sc) .AND. &
1025 : ASSOCIATED(negf_env%s_s) .AND. ALLOCATED(negf_env%s_sc))) RETURN
1026 4 : IF (ncontacts < 2) RETURN
1027 4 : IF (negf_control%max_scf == 0) RETURN
1028 :
1029 4 : CALL timeset(routineN, handle)
1030 :
1031 : CALL get_qs_env(qs_env, blacs_env=blacs_env, do_kpoints=do_kpoints, dft_control=dft_control, &
1032 4 : matrix_ks_kp=matrix_ks_qs_kp, para_env=para_env, rho=rho_struct, subsys=subsys)
1033 4 : CPASSERT(.NOT. do_kpoints)
1034 :
1035 : ! apply external NEGF potential
1036 4 : t1 = m_walltime()
1037 :
1038 : ! need a globally distributed overlap matrix in order to compute integration errors
1039 4 : IF (sub_env%ngroups > 1) THEN
1040 4 : NULLIFY (matrix_s_fm, fm_struct)
1041 :
1042 4 : CALL cp_fm_get_info(negf_env%s_s, nrow_global=nao)
1043 4 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
1044 :
1045 4 : ALLOCATE (matrix_s_fm)
1046 4 : CALL cp_fm_create(matrix_s_fm, fm_struct)
1047 4 : CALL cp_fm_struct_release(fm_struct)
1048 :
1049 4 : IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
1050 2 : CALL cp_fm_copy_general(negf_env%s_s, matrix_s_fm, para_env)
1051 : ELSE
1052 2 : CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env)
1053 : END IF
1054 : ELSE
1055 0 : matrix_s_fm => negf_env%s_s
1056 : END IF
1057 :
1058 4 : CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
1059 :
1060 4 : nspins = SIZE(negf_env%h_s)
1061 4 : nimages = dft_control%nimages
1062 :
1063 4 : v_base = negf_control%contacts(base_contact)%v_external
1064 4 : mu_base = negf_control%contacts(base_contact)%fermi_level - v_base
1065 :
1066 : ! keep the initial charge density matrix and Kohn-Sham matrix
1067 4 : CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
1068 :
1069 4 : NULLIFY (matrix_ks_initial_kp, rho_ao_initial_kp, rho_ao_new_kp)
1070 4 : CALL dbcsr_allocate_matrix_set(matrix_ks_initial_kp, nspins, nimages)
1071 4 : CALL dbcsr_allocate_matrix_set(rho_ao_initial_kp, nspins, nimages)
1072 4 : CALL dbcsr_allocate_matrix_set(rho_ao_new_kp, nspins, nimages)
1073 :
1074 8 : DO image = 1, nimages
1075 12 : DO ispin = 1, nspins
1076 4 : CALL dbcsr_init_p(matrix_ks_initial_kp(ispin, image)%matrix)
1077 4 : CALL dbcsr_copy(matrix_b=matrix_ks_initial_kp(ispin, image)%matrix, matrix_a=matrix_ks_qs_kp(ispin, image)%matrix)
1078 :
1079 4 : CALL dbcsr_init_p(rho_ao_initial_kp(ispin, image)%matrix)
1080 4 : CALL dbcsr_copy(matrix_b=rho_ao_initial_kp(ispin, image)%matrix, matrix_a=rho_ao_qs_kp(ispin, image)%matrix)
1081 :
1082 4 : CALL dbcsr_init_p(rho_ao_new_kp(ispin, image)%matrix)
1083 8 : CALL dbcsr_copy(matrix_b=rho_ao_new_kp(ispin, image)%matrix, matrix_a=rho_ao_qs_kp(ispin, image)%matrix)
1084 : END DO
1085 : END DO
1086 :
1087 : ! extract the reference density matrix blocks
1088 4 : nelectrons = 0.0_dp
1089 24 : ALLOCATE (rho_ao_delta_fm(nspins), rho_ao_new_fm(nspins))
1090 8 : DO ispin = 1, nspins
1091 4 : CALL cp_fm_create(rho_ao_delta_fm(ispin), fm_struct)
1092 4 : CALL cp_fm_create(rho_ao_new_fm(ispin), fm_struct)
1093 :
1094 : CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
1095 : fm=rho_ao_delta_fm(ispin), &
1096 : atomlist_row=negf_control%atomlist_S_screening, &
1097 : atomlist_col=negf_control%atomlist_S_screening, &
1098 : subsys=subsys, mpi_comm_global=para_env, &
1099 4 : do_upper_diag=.TRUE., do_lower=.TRUE.)
1100 :
1101 4 : CALL cp_fm_trace(rho_ao_delta_fm(ispin), matrix_s_fm, trace)
1102 8 : nelectrons = nelectrons + trace
1103 : END DO
1104 :
1105 : ! mixing storage allocation
1106 4 : IF (negf_env%mixing_method >= gspace_mixing_nr) THEN
1107 4 : CALL mixing_allocate(qs_env, negf_env%mixing_method, nspins=nspins, mixing_store=negf_env%mixing_storage)
1108 4 : IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
1109 0 : CPABORT('TB Code not available')
1110 4 : ELSE IF (dft_control%qs_control%semi_empirical) THEN
1111 0 : CPABORT('SE Code not possible')
1112 : ELSE
1113 4 : CALL mixing_init(negf_env%mixing_method, rho_struct, negf_env%mixing_storage, para_env)
1114 : END IF
1115 : END IF
1116 :
1117 4 : IF (log_unit > 0) THEN
1118 2 : WRITE (log_unit, '(/,T2,A)') "NEGF SELF-CONSISTENT PROCEDURE"
1119 2 : WRITE (log_unit, "( ' ------------------------------')")
1120 2 : WRITE (log_unit, '(/,T2,A,T55,F25.14,/)') "Initial electronic density of the scattering region:", -1.0_dp*nelectrons
1121 2 : WRITE (log_unit, '(T3,A)') "Step Integration method Time Electronic density Convergence"
1122 2 : WRITE (log_unit, '(T3,78("-"))')
1123 : END IF
1124 :
1125 4 : temperature = negf_control%contacts(base_contact)%temperature
1126 :
1127 : ! integration limits: C-path (arch)
1128 4 : lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
1129 : ubound_cpath = CMPLX(mu_base - REAL(negf_control%gamma_kT, kind=dp)*temperature, &
1130 4 : REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
1131 :
1132 : ! integration limits: L-path (linear)
1133 : ubound_lpath = CMPLX(mu_base - LOG(negf_control%conv_density)*temperature, &
1134 4 : REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
1135 :
1136 32 : ALLOCATE (g_surf_circular(nspins), g_surf_linear(nspins), g_surf_nonequiv(nspins))
1137 :
1138 : !--- main SCF cycle -------------------------------------------------------------------!
1139 4 : DO iter_count = 1, negf_control%max_scf
1140 : ! compute an updated density matrix
1141 4 : CALL integration_status_reset(stats)
1142 :
1143 8 : DO ispin = 1, nspins
1144 : ! closed contour: residuals
1145 : CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_new_fm(ispin), &
1146 : v_shift=v_shift, &
1147 : ignore_bias=.FALSE., &
1148 : negf_env=negf_env, &
1149 : negf_control=negf_control, &
1150 : sub_env=sub_env, &
1151 : ispin=ispin, &
1152 4 : base_contact=base_contact)
1153 :
1154 : ! closed contour: C-path
1155 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_new_fm(ispin), &
1156 : stats=stats, &
1157 : v_shift=v_shift, &
1158 : ignore_bias=.FALSE., &
1159 : negf_env=negf_env, &
1160 : negf_control=negf_control, &
1161 : sub_env=sub_env, &
1162 : ispin=ispin, &
1163 : base_contact=base_contact, &
1164 : integr_lbound=lbound_cpath, &
1165 : integr_ubound=ubound_cpath, &
1166 : matrix_s_global=matrix_s_fm, &
1167 : is_circular=.TRUE., &
1168 4 : g_surf_cache=g_surf_circular(ispin))
1169 4 : IF (negf_control%disable_cache) &
1170 0 : CALL green_functions_cache_release(g_surf_circular(ispin))
1171 :
1172 : ! closed contour: L-path
1173 : CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_new_fm(ispin), &
1174 : stats=stats, &
1175 : v_shift=v_shift, &
1176 : ignore_bias=.FALSE., &
1177 : negf_env=negf_env, &
1178 : negf_control=negf_control, &
1179 : sub_env=sub_env, &
1180 : ispin=ispin, &
1181 : base_contact=base_contact, &
1182 : integr_lbound=ubound_cpath, &
1183 : integr_ubound=ubound_lpath, &
1184 : matrix_s_global=matrix_s_fm, &
1185 : is_circular=.FALSE., &
1186 4 : g_surf_cache=g_surf_linear(ispin))
1187 4 : IF (negf_control%disable_cache) &
1188 0 : CALL green_functions_cache_release(g_surf_linear(ispin))
1189 :
1190 : ! non-equilibrium part
1191 4 : delta = 0.0_dp
1192 12 : DO icontact = 1, ncontacts
1193 12 : IF (icontact /= base_contact) THEN
1194 : delta = delta + ABS(negf_control%contacts(icontact)%v_external - &
1195 : negf_control%contacts(base_contact)%v_external) + &
1196 : ABS(negf_control%contacts(icontact)%fermi_level - &
1197 : negf_control%contacts(base_contact)%fermi_level) + &
1198 : ABS(negf_control%contacts(icontact)%temperature - &
1199 4 : negf_control%contacts(base_contact)%temperature)
1200 : END IF
1201 : END DO
1202 8 : IF (delta >= threshold) THEN
1203 : CALL negf_add_rho_nonequiv(rho_ao_fm=rho_ao_new_fm(ispin), &
1204 : stats=stats, &
1205 : v_shift=v_shift, &
1206 : negf_env=negf_env, &
1207 : negf_control=negf_control, &
1208 : sub_env=sub_env, &
1209 : ispin=ispin, &
1210 : base_contact=base_contact, &
1211 : matrix_s_global=matrix_s_fm, &
1212 0 : g_surf_cache=g_surf_nonequiv(ispin))
1213 0 : IF (negf_control%disable_cache) &
1214 0 : CALL green_functions_cache_release(g_surf_nonequiv(ispin))
1215 : END IF
1216 : END DO
1217 :
1218 4 : IF (nspins == 1) CALL cp_fm_scale(2.0_dp, rho_ao_new_fm(1))
1219 :
1220 4 : nelectrons = 0.0_dp
1221 4 : nelectrons_diff = 0.0_dp
1222 8 : DO ispin = 1, nspins
1223 4 : CALL cp_fm_trace(rho_ao_new_fm(ispin), matrix_s_fm, trace)
1224 4 : nelectrons = nelectrons + trace
1225 :
1226 : ! rho_ao_delta_fm contains the original (non-mixed) density matrix from the previous iteration
1227 4 : CALL cp_fm_scale_and_add(1.0_dp, rho_ao_delta_fm(ispin), -1.0_dp, rho_ao_new_fm(ispin))
1228 4 : CALL cp_fm_trace(rho_ao_delta_fm(ispin), matrix_s_fm, trace)
1229 4 : nelectrons_diff = nelectrons_diff + trace
1230 :
1231 : ! rho_ao_new_fm -> rho_ao_delta_fm
1232 12 : CALL cp_fm_to_fm(rho_ao_new_fm(ispin), rho_ao_delta_fm(ispin))
1233 : END DO
1234 :
1235 4 : t2 = m_walltime()
1236 :
1237 4 : IF (log_unit > 0) THEN
1238 : WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T43,F20.8,T65,ES15.5E2)') &
1239 2 : iter_count, get_method_description_string(stats, negf_control%integr_method), &
1240 4 : t2 - t1, -1.0_dp*nelectrons, nelectrons_diff
1241 : END IF
1242 :
1243 4 : IF (ABS(nelectrons_diff) < negf_control%conv_scf) EXIT
1244 :
1245 0 : t1 = t2
1246 :
1247 : ! mix density matrices
1248 0 : IF (negf_env%mixing_method == direct_mixing_nr) THEN
1249 0 : DO image = 1, nimages
1250 0 : DO ispin = 1, nspins
1251 : CALL dbcsr_copy(matrix_b=rho_ao_new_kp(ispin, image)%matrix, &
1252 0 : matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
1253 : END DO
1254 : END DO
1255 :
1256 0 : DO ispin = 1, nspins
1257 : CALL negf_copy_fm_submat_to_dbcsr(fm=rho_ao_new_fm(ispin), &
1258 : matrix=rho_ao_new_kp(ispin, 1)%matrix, &
1259 : atomlist_row=negf_control%atomlist_S_screening, &
1260 : atomlist_col=negf_control%atomlist_S_screening, &
1261 0 : subsys=subsys)
1262 : END DO
1263 :
1264 : CALL scf_env_density_mixing(rho_ao_new_kp, negf_env%mixing_storage, rho_ao_qs_kp, &
1265 0 : para_env, iter_delta, iter_count)
1266 :
1267 0 : DO image = 1, nimages
1268 0 : DO ispin = 1, nspins
1269 0 : CALL dbcsr_copy(rho_ao_qs_kp(ispin, image)%matrix, rho_ao_new_kp(ispin, image)%matrix)
1270 : END DO
1271 : END DO
1272 : ELSE
1273 : ! store the updated density matrix directly into the variable 'rho_ao_qs_kp'
1274 : ! (which is qs_env%rho%rho_ao_kp); density mixing will be done on an inverse-space grid
1275 0 : DO image = 1, nimages
1276 0 : DO ispin = 1, nspins
1277 : CALL dbcsr_copy(matrix_b=rho_ao_qs_kp(ispin, image)%matrix, &
1278 0 : matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
1279 : END DO
1280 : END DO
1281 :
1282 0 : DO ispin = 1, nspins
1283 : CALL negf_copy_fm_submat_to_dbcsr(fm=rho_ao_new_fm(ispin), &
1284 : matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
1285 : atomlist_row=negf_control%atomlist_S_screening, &
1286 : atomlist_col=negf_control%atomlist_S_screening, &
1287 0 : subsys=subsys)
1288 : END DO
1289 : END IF
1290 :
1291 0 : CALL qs_rho_update_rho(rho_struct, qs_env=qs_env)
1292 :
1293 0 : IF (negf_env%mixing_method >= gspace_mixing_nr) THEN
1294 : CALL gspace_mixing(qs_env, negf_env%mixing_method, negf_env%mixing_storage, &
1295 0 : rho_struct, para_env, iter_count)
1296 : END IF
1297 :
1298 : ! update KS-matrix
1299 0 : CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.FALSE., just_energy=.FALSE.)
1300 :
1301 : ! extract blocks from the updated Kohn-Sham matrix
1302 4 : DO ispin = 1, nspins
1303 : CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=matrix_ks_qs_kp(ispin, 1)%matrix, &
1304 : fm=negf_env%h_s(ispin), &
1305 : atomlist_row=negf_control%atomlist_S_screening, &
1306 : atomlist_col=negf_control%atomlist_S_screening, &
1307 : subsys=subsys, mpi_comm_global=para_env, &
1308 0 : do_upper_diag=.TRUE., do_lower=.TRUE.)
1309 :
1310 : END DO
1311 : END DO
1312 :
1313 : !--------------------------------------------------------------------------------------!
1314 :
1315 4 : IF (log_unit > 0) THEN
1316 2 : IF (iter_count <= negf_control%max_scf) THEN
1317 2 : WRITE (log_unit, '(/,T11,1X,A,I0,A)') "*** NEGF run converged in ", iter_count, " iteration(s) ***"
1318 : ELSE
1319 0 : WRITE (log_unit, '(/,T11,1X,A,I0,A)') "*** NEGF run did NOT converge after ", iter_count - 1, " iteration(s) ***"
1320 : END IF
1321 : END IF
1322 :
1323 8 : DO ispin = nspins, 1, -1
1324 4 : CALL green_functions_cache_release(g_surf_circular(ispin))
1325 4 : CALL green_functions_cache_release(g_surf_linear(ispin))
1326 8 : CALL green_functions_cache_release(g_surf_nonequiv(ispin))
1327 : END DO
1328 16 : DEALLOCATE (g_surf_circular, g_surf_linear, g_surf_nonequiv)
1329 :
1330 4 : CALL cp_fm_release(rho_ao_new_fm)
1331 4 : CALL cp_fm_release(rho_ao_delta_fm)
1332 :
1333 8 : DO image = 1, nimages
1334 12 : DO ispin = 1, nspins
1335 4 : CALL dbcsr_copy(matrix_b=matrix_ks_qs_kp(ispin, image)%matrix, matrix_a=matrix_ks_initial_kp(ispin, image)%matrix)
1336 4 : CALL dbcsr_copy(matrix_b=rho_ao_qs_kp(ispin, image)%matrix, matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
1337 :
1338 4 : CALL dbcsr_deallocate_matrix(matrix_ks_initial_kp(ispin, image)%matrix)
1339 4 : CALL dbcsr_deallocate_matrix(rho_ao_initial_kp(ispin, image)%matrix)
1340 8 : CALL dbcsr_deallocate_matrix(rho_ao_new_kp(ispin, image)%matrix)
1341 : END DO
1342 : END DO
1343 4 : DEALLOCATE (matrix_ks_initial_kp, rho_ao_new_kp, rho_ao_initial_kp)
1344 :
1345 4 : IF (sub_env%ngroups > 1 .AND. ASSOCIATED(matrix_s_fm)) THEN
1346 4 : CALL cp_fm_release(matrix_s_fm)
1347 4 : DEALLOCATE (matrix_s_fm)
1348 : END IF
1349 :
1350 4 : CALL timestop(handle)
1351 12 : END SUBROUTINE converge_density
1352 :
1353 : ! **************************************************************************************************
1354 : !> \brief Compute the surface retarded Green's function at a set of points in parallel.
1355 : !> \param g_surf set of surface Green's functions computed within the given parallel group
1356 : !> \param omega list of energy points where the surface Green's function need to be computed
1357 : !> \param h0 diagonal block of the Kohn-Sham matrix (must be Hermitian)
1358 : !> \param s0 diagonal block of the overlap matrix (must be Hermitian)
1359 : !> \param h1 off-fiagonal block of the Kohn-Sham matrix
1360 : !> \param s1 off-fiagonal block of the overlap matrix
1361 : !> \param sub_env NEGF parallel (sub)group environment
1362 : !> \param v_external applied electric potential
1363 : !> \param conv convergence threshold
1364 : !> \param transp flag which indicates that the matrices h1 and s1 should be transposed
1365 : !> \par History
1366 : !> * 07.2017 created [Sergey Chulkov]
1367 : ! **************************************************************************************************
1368 1088 : SUBROUTINE negf_surface_green_function_batch(g_surf, omega, h0, s0, h1, s1, sub_env, v_external, conv, transp)
1369 : TYPE(cp_cfm_type), DIMENSION(:), INTENT(inout) :: g_surf
1370 : COMPLEX(kind=dp), DIMENSION(:), INTENT(in) :: omega
1371 : TYPE(cp_fm_type), INTENT(IN) :: h0, s0, h1, s1
1372 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
1373 : REAL(kind=dp), INTENT(in) :: v_external, conv
1374 : LOGICAL, INTENT(in) :: transp
1375 :
1376 : CHARACTER(len=*), PARAMETER :: routineN = 'negf_surface_green_function_batch'
1377 : TYPE(cp_cfm_type), PARAMETER :: cfm_null = cp_cfm_type()
1378 :
1379 : INTEGER :: handle, igroup, ipoint, npoints
1380 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1381 : TYPE(sancho_work_matrices_type) :: work
1382 :
1383 1088 : CALL timeset(routineN, handle)
1384 1088 : npoints = SIZE(omega)
1385 :
1386 1088 : CALL cp_fm_get_info(s0, matrix_struct=fm_struct)
1387 1088 : CALL sancho_work_matrices_create(work, fm_struct)
1388 :
1389 1088 : igroup = sub_env%group_distribution(sub_env%mepos_global)
1390 :
1391 10848 : g_surf(1:npoints) = cfm_null
1392 :
1393 5968 : DO ipoint = igroup + 1, npoints, sub_env%ngroups
1394 : IF (debug_this_module) THEN
1395 4880 : CPASSERT(.NOT. ASSOCIATED(g_surf(ipoint)%matrix_struct))
1396 : END IF
1397 4880 : CALL cp_cfm_create(g_surf(ipoint), fm_struct)
1398 :
1399 : CALL do_sancho(g_surf(ipoint), omega(ipoint) + v_external, &
1400 5968 : h0, s0, h1, s1, conv, transp, work)
1401 : END DO
1402 :
1403 1088 : CALL sancho_work_matrices_release(work)
1404 1088 : CALL timestop(handle)
1405 1088 : END SUBROUTINE negf_surface_green_function_batch
1406 :
1407 : ! **************************************************************************************************
1408 : !> \brief Compute the retarded Green's function and related properties at a set of points in parallel.
1409 : !> \param omega list of energy points
1410 : !> \param v_shift shift in Hartree potential
1411 : !> \param ignore_bias ignore v_external from negf_control
1412 : !> \param negf_env NEGF environment
1413 : !> \param negf_control NEGF control
1414 : !> \param sub_env (sub)group environment
1415 : !> \param ispin spin component to compute
1416 : !> \param g_surf_contacts set of surface Green's functions for every contact that computed
1417 : !> within the given parallel group
1418 : !> \param g_ret_s globally distributed matrices to store retarded Green's functions
1419 : !> \param g_ret_scale scale factor for retarded Green's functions
1420 : !> \param gamma_contacts 2-D array of globally distributed matrices to store broadening matrices
1421 : !> for every contact ([n_contacts, npoints])
1422 : !> \param gret_gamma_gadv 2-D array of globally distributed matrices to store the spectral function:
1423 : !> g_ret_s * gamma * g_ret_s^C for every contact ([n_contacts, n_points])
1424 : !> \param dos density of states at 'omega' ([n_points])
1425 : !> \param transm_coeff transmission coefficients between two contacts 'transm_contact1'
1426 : !> and 'transm_contact2' computed at points 'omega' ([n_points])
1427 : !> \param transm_contact1 index of the first contact
1428 : !> \param transm_contact2 index of the second contact
1429 : !> \param just_contact if present, compute the retarded Green's function of the system
1430 : !> lead1 -- device -- lead2. All 3 regions have the same Kohn-Sham
1431 : !> matrices which are taken from 'negf_env%contacts(just_contact)%h'.
1432 : !> Useful to apply NEGF procedure a single contact in order to compute
1433 : !> its Fermi level
1434 : !> \par History
1435 : !> * 07.2017 created [Sergey Chulkov]
1436 : ! **************************************************************************************************
1437 556 : SUBROUTINE negf_retarded_green_function_batch(omega, v_shift, ignore_bias, negf_env, negf_control, sub_env, ispin, &
1438 556 : g_surf_contacts, &
1439 1112 : g_ret_s, g_ret_scale, gamma_contacts, gret_gamma_gadv, dos, &
1440 556 : transm_coeff, transm_contact1, transm_contact2, just_contact)
1441 : COMPLEX(kind=dp), DIMENSION(:), INTENT(in) :: omega
1442 : REAL(kind=dp), INTENT(in) :: v_shift
1443 : LOGICAL, INTENT(in) :: ignore_bias
1444 : TYPE(negf_env_type), INTENT(in) :: negf_env
1445 : TYPE(negf_control_type), POINTER :: negf_control
1446 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
1447 : INTEGER, INTENT(in) :: ispin
1448 : TYPE(cp_cfm_type), DIMENSION(:, :), INTENT(in) :: g_surf_contacts
1449 : TYPE(cp_cfm_type), DIMENSION(:), INTENT(in), &
1450 : OPTIONAL :: g_ret_s
1451 : COMPLEX(kind=dp), DIMENSION(:), INTENT(in), &
1452 : OPTIONAL :: g_ret_scale
1453 : TYPE(cp_cfm_type), DIMENSION(:, :), INTENT(in), &
1454 : OPTIONAL :: gamma_contacts, gret_gamma_gadv
1455 : REAL(kind=dp), DIMENSION(:), INTENT(out), OPTIONAL :: dos
1456 : COMPLEX(kind=dp), DIMENSION(:), INTENT(out), &
1457 : OPTIONAL :: transm_coeff
1458 : INTEGER, INTENT(in), OPTIONAL :: transm_contact1, transm_contact2, &
1459 : just_contact
1460 :
1461 : CHARACTER(len=*), PARAMETER :: routineN = 'negf_retarded_green_function_batch'
1462 :
1463 : INTEGER :: handle, icontact, igroup, ipoint, &
1464 : ncontacts, npoints, nrows
1465 : REAL(kind=dp) :: v_external
1466 : TYPE(copy_cfm_info_type), ALLOCATABLE, &
1467 556 : DIMENSION(:) :: info1
1468 : TYPE(copy_cfm_info_type), ALLOCATABLE, &
1469 556 : DIMENSION(:, :) :: info2
1470 556 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: g_ret_s_group, self_energy_contacts, &
1471 556 : zwork1_contacts, zwork2_contacts
1472 556 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:, :) :: gamma_contacts_group, &
1473 556 : gret_gamma_gadv_group
1474 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1475 : TYPE(cp_fm_type) :: g_ret_imag
1476 : TYPE(cp_fm_type), POINTER :: matrix_s
1477 : TYPE(mp_para_env_type), POINTER :: para_env
1478 :
1479 556 : CALL timeset(routineN, handle)
1480 556 : npoints = SIZE(omega)
1481 556 : ncontacts = SIZE(negf_env%contacts)
1482 556 : CPASSERT(SIZE(negf_control%contacts) == ncontacts)
1483 :
1484 556 : IF (PRESENT(just_contact)) THEN
1485 36 : CPASSERT(just_contact <= ncontacts)
1486 : ncontacts = 2
1487 : END IF
1488 :
1489 520 : CPASSERT(ncontacts >= 2)
1490 :
1491 : IF (ignore_bias) v_external = 0.0_dp
1492 :
1493 556 : IF (PRESENT(transm_coeff) .OR. PRESENT(transm_contact1) .OR. PRESENT(transm_contact2)) THEN
1494 204 : CPASSERT(PRESENT(transm_coeff))
1495 204 : CPASSERT(PRESENT(transm_contact1))
1496 204 : CPASSERT(PRESENT(transm_contact2))
1497 204 : CPASSERT(.NOT. PRESENT(just_contact))
1498 : END IF
1499 :
1500 6116 : ALLOCATE (self_energy_contacts(ncontacts), zwork1_contacts(ncontacts), zwork2_contacts(ncontacts))
1501 :
1502 556 : IF (PRESENT(just_contact)) THEN
1503 36 : CALL cp_fm_get_info(negf_env%contacts(just_contact)%s_01, matrix_struct=fm_struct)
1504 108 : DO icontact = 1, ncontacts
1505 72 : CALL cp_cfm_create(zwork1_contacts(icontact), fm_struct)
1506 108 : CALL cp_cfm_create(zwork2_contacts(icontact), fm_struct)
1507 : END DO
1508 :
1509 36 : CALL cp_fm_get_info(negf_env%contacts(just_contact)%s_00, nrow_global=nrows, matrix_struct=fm_struct)
1510 108 : DO icontact = 1, ncontacts
1511 108 : CALL cp_cfm_create(self_energy_contacts(icontact), fm_struct)
1512 : END DO
1513 : ELSE
1514 1560 : DO icontact = 1, ncontacts
1515 1040 : CALL cp_fm_get_info(negf_env%s_sc(icontact), matrix_struct=fm_struct)
1516 1040 : CALL cp_cfm_create(zwork1_contacts(icontact), fm_struct)
1517 1560 : CALL cp_cfm_create(zwork2_contacts(icontact), fm_struct)
1518 : END DO
1519 :
1520 520 : CALL cp_fm_get_info(negf_env%s_s, nrow_global=nrows, matrix_struct=fm_struct)
1521 1560 : DO icontact = 1, ncontacts
1522 1560 : CALL cp_cfm_create(self_energy_contacts(icontact), fm_struct)
1523 : END DO
1524 : END IF
1525 :
1526 : IF (PRESENT(g_ret_s) .OR. PRESENT(gret_gamma_gadv) .OR. &
1527 556 : PRESENT(dos) .OR. PRESENT(transm_coeff)) THEN
1528 7624 : ALLOCATE (g_ret_s_group(npoints))
1529 :
1530 556 : IF (sub_env%ngroups <= 1 .AND. PRESENT(g_ret_s)) THEN
1531 0 : g_ret_s_group(1:npoints) = g_ret_s(1:npoints)
1532 : END IF
1533 : END IF
1534 :
1535 556 : IF (PRESENT(gamma_contacts) .OR. PRESENT(gret_gamma_gadv) .OR. PRESENT(transm_coeff)) THEN
1536 204 : IF (debug_this_module .AND. PRESENT(gamma_contacts)) THEN
1537 0 : CPASSERT(SIZE(gamma_contacts, 1) == ncontacts)
1538 : END IF
1539 :
1540 5628 : ALLOCATE (gamma_contacts_group(ncontacts, npoints))
1541 204 : IF (sub_env%ngroups <= 1 .AND. PRESENT(gamma_contacts)) THEN
1542 0 : gamma_contacts_group(1:ncontacts, 1:npoints) = gamma_contacts(1:ncontacts, 1:npoints)
1543 : END IF
1544 : END IF
1545 :
1546 556 : IF (PRESENT(gret_gamma_gadv)) THEN
1547 : IF (debug_this_module .AND. PRESENT(gret_gamma_gadv)) THEN
1548 0 : CPASSERT(SIZE(gret_gamma_gadv, 1) == ncontacts)
1549 : END IF
1550 :
1551 0 : ALLOCATE (gret_gamma_gadv_group(ncontacts, npoints))
1552 0 : IF (sub_env%ngroups <= 1) THEN
1553 0 : gret_gamma_gadv_group(1:ncontacts, 1:npoints) = gret_gamma_gadv(1:ncontacts, 1:npoints)
1554 : END IF
1555 : END IF
1556 :
1557 556 : igroup = sub_env%group_distribution(sub_env%mepos_global)
1558 :
1559 6512 : DO ipoint = 1, npoints
1560 6512 : IF (ASSOCIATED(g_surf_contacts(1, ipoint)%matrix_struct)) THEN
1561 2978 : IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(g_ret_s)) THEN
1562 : ! create a group-specific matrix to store retarded Green's function if there are
1563 : ! at least two parallel groups; otherwise pointers to group-specific matrices have
1564 : ! already been initialised and they point to globally distributed matrices
1565 2978 : IF (ALLOCATED(g_ret_s_group)) THEN
1566 2978 : CALL cp_cfm_create(g_ret_s_group(ipoint), fm_struct)
1567 : END IF
1568 : END IF
1569 :
1570 2978 : IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(gamma_contacts)) THEN
1571 2978 : IF (ALLOCATED(gamma_contacts_group)) THEN
1572 2406 : DO icontact = 1, ncontacts
1573 2406 : CALL cp_cfm_create(gamma_contacts_group(icontact, ipoint), fm_struct)
1574 : END DO
1575 : END IF
1576 : END IF
1577 :
1578 2978 : IF (sub_env%ngroups > 1) THEN
1579 2978 : IF (ALLOCATED(gret_gamma_gadv_group)) THEN
1580 0 : DO icontact = 1, ncontacts
1581 0 : IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
1582 0 : CALL cp_cfm_create(gret_gamma_gadv_group(icontact, ipoint), fm_struct)
1583 : END IF
1584 : END DO
1585 : END IF
1586 : END IF
1587 :
1588 2978 : IF (PRESENT(just_contact)) THEN
1589 : ! self energy of the "left" (1) and "right" contacts
1590 612 : DO icontact = 1, ncontacts
1591 : CALL negf_contact_self_energy(self_energy_c=self_energy_contacts(icontact), &
1592 : omega=omega(ipoint), &
1593 : g_surf_c=g_surf_contacts(icontact, ipoint), &
1594 : h_sc0=negf_env%contacts(just_contact)%h_01(ispin), &
1595 : s_sc0=negf_env%contacts(just_contact)%s_01, &
1596 : zwork1=zwork1_contacts(icontact), &
1597 : zwork2=zwork2_contacts(icontact), &
1598 612 : transp=(icontact == 1))
1599 : END DO
1600 : ELSE
1601 : ! contact self energies
1602 8322 : DO icontact = 1, ncontacts
1603 5548 : IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
1604 :
1605 : CALL negf_contact_self_energy(self_energy_c=self_energy_contacts(icontact), &
1606 : omega=omega(ipoint) + v_external, &
1607 : g_surf_c=g_surf_contacts(icontact, ipoint), &
1608 : h_sc0=negf_env%h_sc(ispin, icontact), &
1609 : s_sc0=negf_env%s_sc(icontact), &
1610 : zwork1=zwork1_contacts(icontact), &
1611 : zwork2=zwork2_contacts(icontact), &
1612 8322 : transp=.FALSE.)
1613 : END DO
1614 : END IF
1615 :
1616 : ! broadening matrices
1617 2978 : IF (ALLOCATED(gamma_contacts_group)) THEN
1618 2406 : DO icontact = 1, ncontacts
1619 : CALL negf_contact_broadening_matrix(gamma_c=gamma_contacts_group(icontact, ipoint), &
1620 2406 : self_energy_c=self_energy_contacts(icontact))
1621 : END DO
1622 : END IF
1623 :
1624 2978 : IF (ALLOCATED(g_ret_s_group)) THEN
1625 : ! sum up self energies for all contacts
1626 5956 : DO icontact = 2, ncontacts
1627 5956 : CALL cp_cfm_scale_and_add(z_one, self_energy_contacts(1), z_one, self_energy_contacts(icontact))
1628 : END DO
1629 :
1630 : ! retarded Green's function for the scattering region
1631 2978 : IF (PRESENT(just_contact)) THEN
1632 : CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
1633 : omega=omega(ipoint) - v_shift, &
1634 : self_energy_ret_sum=self_energy_contacts(1), &
1635 : h_s=negf_env%contacts(just_contact)%h_00(ispin), &
1636 204 : s_s=negf_env%contacts(just_contact)%s_00)
1637 2774 : ELSE IF (ignore_bias) THEN
1638 : CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
1639 : omega=omega(ipoint) - v_shift, &
1640 : self_energy_ret_sum=self_energy_contacts(1), &
1641 : h_s=negf_env%h_s(ispin), &
1642 894 : s_s=negf_env%s_s)
1643 : ELSE
1644 : CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
1645 : omega=omega(ipoint) - v_shift, &
1646 : self_energy_ret_sum=self_energy_contacts(1), &
1647 : h_s=negf_env%h_s(ispin), &
1648 : s_s=negf_env%s_s, &
1649 1880 : v_hartree_s=negf_env%v_hartree_s)
1650 : END IF
1651 :
1652 2978 : IF (PRESENT(g_ret_scale)) THEN
1653 1338 : IF (g_ret_scale(ipoint) /= z_one) CALL cp_cfm_scale(g_ret_scale(ipoint), g_ret_s_group(ipoint))
1654 : END IF
1655 : END IF
1656 :
1657 2978 : IF (ALLOCATED(gret_gamma_gadv_group)) THEN
1658 : ! we do not need contact self energies any longer, so we can use
1659 : ! the array 'self_energy_contacts' as a set of work matrices
1660 0 : DO icontact = 1, ncontacts
1661 0 : IF (ASSOCIATED(gret_gamma_gadv_group(icontact, ipoint)%matrix_struct)) THEN
1662 : CALL parallel_gemm('N', 'C', nrows, nrows, nrows, &
1663 : z_one, gamma_contacts_group(icontact, ipoint), &
1664 : g_ret_s_group(ipoint), &
1665 0 : z_zero, self_energy_contacts(icontact))
1666 : CALL parallel_gemm('N', 'N', nrows, nrows, nrows, &
1667 : z_one, g_ret_s_group(ipoint), &
1668 : self_energy_contacts(icontact), &
1669 0 : z_zero, gret_gamma_gadv_group(icontact, ipoint))
1670 : END IF
1671 : END DO
1672 : END IF
1673 : END IF
1674 : END DO
1675 :
1676 : ! redistribute locally stored matrices
1677 556 : IF (PRESENT(g_ret_s)) THEN
1678 148 : IF (sub_env%ngroups > 1) THEN
1679 148 : NULLIFY (para_env)
1680 148 : DO ipoint = 1, npoints
1681 148 : IF (ASSOCIATED(g_ret_s(ipoint)%matrix_struct)) THEN
1682 148 : CALL cp_cfm_get_info(g_ret_s(ipoint), para_env=para_env)
1683 148 : EXIT
1684 : END IF
1685 : END DO
1686 :
1687 148 : IF (ASSOCIATED(para_env)) THEN
1688 4376 : ALLOCATE (info1(npoints))
1689 :
1690 2896 : DO ipoint = 1, npoints
1691 : CALL cp_cfm_start_copy_general(g_ret_s_group(ipoint), &
1692 : g_ret_s(ipoint), &
1693 2896 : para_env, info1(ipoint))
1694 : END DO
1695 :
1696 2896 : DO ipoint = 1, npoints
1697 2896 : IF (ASSOCIATED(g_ret_s(ipoint)%matrix_struct)) THEN
1698 2748 : CALL cp_cfm_finish_copy_general(g_ret_s(ipoint), info1(ipoint))
1699 2748 : IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) &
1700 1374 : CALL cp_cfm_cleanup_copy_general(info1(ipoint))
1701 : END IF
1702 : END DO
1703 :
1704 2896 : DEALLOCATE (info1)
1705 : END IF
1706 : END IF
1707 : END IF
1708 :
1709 556 : IF (PRESENT(gamma_contacts)) THEN
1710 0 : IF (sub_env%ngroups > 1) THEN
1711 0 : NULLIFY (para_env)
1712 0 : pnt1: DO ipoint = 1, npoints
1713 0 : DO icontact = 1, ncontacts
1714 0 : IF (ASSOCIATED(gamma_contacts(icontact, ipoint)%matrix_struct)) THEN
1715 0 : CALL cp_cfm_get_info(gamma_contacts(icontact, ipoint), para_env=para_env)
1716 0 : EXIT pnt1
1717 : END IF
1718 : END DO
1719 : END DO pnt1
1720 :
1721 0 : IF (ASSOCIATED(para_env)) THEN
1722 0 : ALLOCATE (info2(ncontacts, npoints))
1723 :
1724 0 : DO ipoint = 1, npoints
1725 0 : DO icontact = 1, ncontacts
1726 : CALL cp_cfm_start_copy_general(gamma_contacts_group(icontact, ipoint), &
1727 : gamma_contacts(icontact, ipoint), &
1728 0 : para_env, info2(icontact, ipoint))
1729 : END DO
1730 : END DO
1731 :
1732 0 : DO ipoint = 1, npoints
1733 0 : DO icontact = 1, ncontacts
1734 0 : IF (ASSOCIATED(gamma_contacts(icontact, ipoint)%matrix_struct)) THEN
1735 0 : CALL cp_cfm_finish_copy_general(gamma_contacts(icontact, ipoint), info2(icontact, ipoint))
1736 0 : IF (ASSOCIATED(gamma_contacts_group(icontact, ipoint)%matrix_struct)) THEN
1737 0 : CALL cp_cfm_cleanup_copy_general(info2(icontact, ipoint))
1738 : END IF
1739 : END IF
1740 : END DO
1741 : END DO
1742 :
1743 0 : DEALLOCATE (info2)
1744 : END IF
1745 : END IF
1746 : END IF
1747 :
1748 556 : IF (PRESENT(gret_gamma_gadv)) THEN
1749 0 : IF (sub_env%ngroups > 1) THEN
1750 0 : NULLIFY (para_env)
1751 0 : pnt2: DO ipoint = 1, npoints
1752 0 : DO icontact = 1, ncontacts
1753 0 : IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
1754 0 : CALL cp_cfm_get_info(gret_gamma_gadv(icontact, ipoint), para_env=para_env)
1755 0 : EXIT pnt2
1756 : END IF
1757 : END DO
1758 : END DO pnt2
1759 :
1760 0 : IF (ASSOCIATED(para_env)) THEN
1761 0 : ALLOCATE (info2(ncontacts, npoints))
1762 :
1763 0 : DO ipoint = 1, npoints
1764 0 : DO icontact = 1, ncontacts
1765 : CALL cp_cfm_start_copy_general(gret_gamma_gadv_group(icontact, ipoint), &
1766 : gret_gamma_gadv(icontact, ipoint), &
1767 0 : para_env, info2(icontact, ipoint))
1768 : END DO
1769 : END DO
1770 :
1771 0 : DO ipoint = 1, npoints
1772 0 : DO icontact = 1, ncontacts
1773 0 : IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
1774 0 : CALL cp_cfm_finish_copy_general(gret_gamma_gadv(icontact, ipoint), info2(icontact, ipoint))
1775 0 : IF (ASSOCIATED(gret_gamma_gadv_group(icontact, ipoint)%matrix_struct)) THEN
1776 0 : CALL cp_cfm_cleanup_copy_general(info2(icontact, ipoint))
1777 : END IF
1778 : END IF
1779 : END DO
1780 : END DO
1781 :
1782 0 : DEALLOCATE (info2)
1783 : END IF
1784 : END IF
1785 : END IF
1786 :
1787 556 : IF (PRESENT(dos)) THEN
1788 1808 : dos(:) = 0.0_dp
1789 :
1790 204 : IF (PRESENT(just_contact)) THEN
1791 0 : matrix_s => negf_env%contacts(just_contact)%s_00
1792 : ELSE
1793 204 : matrix_s => negf_env%s_s
1794 : END IF
1795 :
1796 204 : CALL cp_fm_get_info(matrix_s, matrix_struct=fm_struct)
1797 204 : CALL cp_fm_create(g_ret_imag, fm_struct)
1798 :
1799 1808 : DO ipoint = 1, npoints
1800 1808 : IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) THEN
1801 802 : CALL cp_cfm_to_fm(g_ret_s_group(ipoint), mtargeti=g_ret_imag)
1802 802 : CALL cp_fm_trace(g_ret_imag, matrix_s, dos(ipoint))
1803 802 : IF (sub_env%para_env%mepos /= 0) dos(ipoint) = 0.0_dp
1804 : END IF
1805 : END DO
1806 :
1807 204 : CALL cp_fm_release(g_ret_imag)
1808 :
1809 3412 : CALL sub_env%mpi_comm_global%sum(dos)
1810 1808 : dos(:) = -1.0_dp/pi*dos(:)
1811 : END IF
1812 :
1813 556 : IF (PRESENT(transm_coeff)) THEN
1814 1808 : transm_coeff(:) = z_zero
1815 :
1816 1808 : DO ipoint = 1, npoints
1817 1808 : IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) THEN
1818 : ! gamma_1 * g_adv_s * gamma_2
1819 : CALL parallel_gemm('N', 'C', nrows, nrows, nrows, &
1820 : z_one, gamma_contacts_group(transm_contact1, ipoint), &
1821 : g_ret_s_group(ipoint), &
1822 802 : z_zero, self_energy_contacts(transm_contact1))
1823 : CALL parallel_gemm('N', 'N', nrows, nrows, nrows, &
1824 : z_one, self_energy_contacts(transm_contact1), &
1825 : gamma_contacts_group(transm_contact2, ipoint), &
1826 802 : z_zero, self_energy_contacts(transm_contact2))
1827 :
1828 : ! Trace[ g_ret_s * gamma_1 * g_adv_s * gamma_2 ]
1829 : CALL cp_cfm_trace(g_ret_s_group(ipoint), &
1830 : self_energy_contacts(transm_contact2), &
1831 802 : transm_coeff(ipoint))
1832 802 : IF (sub_env%para_env%mepos /= 0) transm_coeff(ipoint) = 0.0_dp
1833 : END IF
1834 : END DO
1835 :
1836 : ! transmission coefficients are scaled by 2/pi
1837 3412 : CALL sub_env%mpi_comm_global%sum(transm_coeff)
1838 : !transm_coeff(:) = 0.5_dp/pi*transm_coeff(:)
1839 : END IF
1840 :
1841 : ! -- deallocate temporary matrices
1842 556 : IF (ALLOCATED(g_ret_s_group)) THEN
1843 6512 : DO ipoint = npoints, 1, -1
1844 6512 : IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(g_ret_s)) THEN
1845 5956 : CALL cp_cfm_release(g_ret_s_group(ipoint))
1846 : END IF
1847 : END DO
1848 556 : DEALLOCATE (g_ret_s_group)
1849 : END IF
1850 :
1851 556 : IF (ALLOCATED(gamma_contacts_group)) THEN
1852 1808 : DO ipoint = npoints, 1, -1
1853 5016 : DO icontact = ncontacts, 1, -1
1854 4812 : IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(gamma_contacts)) THEN
1855 3208 : CALL cp_cfm_release(gamma_contacts_group(icontact, ipoint))
1856 : END IF
1857 : END DO
1858 : END DO
1859 204 : DEALLOCATE (gamma_contacts_group)
1860 : END IF
1861 :
1862 556 : IF (ALLOCATED(gret_gamma_gadv_group)) THEN
1863 0 : DO ipoint = npoints, 1, -1
1864 0 : DO icontact = ncontacts, 1, -1
1865 0 : IF (sub_env%ngroups > 1) THEN
1866 0 : CALL cp_cfm_release(gret_gamma_gadv_group(icontact, ipoint))
1867 : END IF
1868 : END DO
1869 : END DO
1870 0 : DEALLOCATE (gret_gamma_gadv_group)
1871 : END IF
1872 :
1873 556 : IF (ALLOCATED(self_energy_contacts)) THEN
1874 1668 : DO icontact = ncontacts, 1, -1
1875 1668 : CALL cp_cfm_release(self_energy_contacts(icontact))
1876 : END DO
1877 556 : DEALLOCATE (self_energy_contacts)
1878 : END IF
1879 :
1880 556 : IF (ALLOCATED(zwork1_contacts)) THEN
1881 1668 : DO icontact = ncontacts, 1, -1
1882 1668 : CALL cp_cfm_release(zwork1_contacts(icontact))
1883 : END DO
1884 556 : DEALLOCATE (zwork1_contacts)
1885 : END IF
1886 :
1887 556 : IF (ALLOCATED(zwork2_contacts)) THEN
1888 1668 : DO icontact = ncontacts, 1, -1
1889 1668 : CALL cp_cfm_release(zwork2_contacts(icontact))
1890 : END DO
1891 556 : DEALLOCATE (zwork2_contacts)
1892 : END IF
1893 :
1894 556 : CALL timestop(handle)
1895 1112 : END SUBROUTINE negf_retarded_green_function_batch
1896 :
1897 : ! **************************************************************************************************
1898 : !> \brief Fermi function (exp(E/(kT)) + 1) ^ {-1} .
1899 : !> \param omega 'energy' point on the complex plane
1900 : !> \param temperature temperature in atomic units
1901 : !> \return value
1902 : !> \par History
1903 : !> * 05.2017 created [Sergey Chulkov]
1904 : ! **************************************************************************************************
1905 2676 : PURE FUNCTION fermi_function(omega, temperature) RESULT(val)
1906 : COMPLEX(kind=dp), INTENT(in) :: omega
1907 : REAL(kind=dp), INTENT(in) :: temperature
1908 : COMPLEX(kind=dp) :: val
1909 :
1910 : REAL(kind=dp), PARAMETER :: max_ln_omega_over_T = LOG(HUGE(0.0_dp))/16.0_dp
1911 :
1912 2676 : IF (REAL(omega, kind=dp) <= temperature*max_ln_omega_over_T) THEN
1913 : ! exp(omega / T) < huge(0), so EXP() should not return infinity
1914 2676 : val = z_one/(EXP(omega/temperature) + z_one)
1915 : ELSE
1916 : val = z_zero
1917 : END IF
1918 2676 : END FUNCTION fermi_function
1919 :
1920 : ! **************************************************************************************************
1921 : !> \brief Compute contribution to the density matrix from the poles of the Fermi function.
1922 : !> \param rho_ao_fm density matrix (initialised on exit)
1923 : !> \param v_shift shift in Hartree potential
1924 : !> \param ignore_bias ignore v_external from negf_control
1925 : !> \param negf_env NEGF environment
1926 : !> \param negf_control NEGF control
1927 : !> \param sub_env NEGF parallel (sub)group environment
1928 : !> \param ispin spin conponent to proceed
1929 : !> \param base_contact index of the reference contact
1930 : !> \param just_contact ...
1931 : !> \author Sergey Chulkov
1932 : ! **************************************************************************************************
1933 18 : SUBROUTINE negf_init_rho_equiv_residuals(rho_ao_fm, v_shift, ignore_bias, negf_env, &
1934 : negf_control, sub_env, ispin, base_contact, just_contact)
1935 : TYPE(cp_fm_type), INTENT(IN) :: rho_ao_fm
1936 : REAL(kind=dp), INTENT(in) :: v_shift
1937 : LOGICAL, INTENT(in) :: ignore_bias
1938 : TYPE(negf_env_type), INTENT(in) :: negf_env
1939 : TYPE(negf_control_type), POINTER :: negf_control
1940 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
1941 : INTEGER, INTENT(in) :: ispin, base_contact
1942 : INTEGER, INTENT(in), OPTIONAL :: just_contact
1943 :
1944 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_init_rho_equiv_residuals'
1945 :
1946 18 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: omega
1947 : INTEGER :: handle, icontact, ipole, ncontacts, &
1948 : npoles
1949 : REAL(kind=dp) :: mu_base, pi_temperature, temperature, &
1950 : v_external
1951 18 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: g_ret_s
1952 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1953 18 : TYPE(green_functions_cache_type) :: g_surf_cache
1954 : TYPE(mp_para_env_type), POINTER :: para_env
1955 :
1956 18 : CALL timeset(routineN, handle)
1957 :
1958 18 : temperature = negf_control%contacts(base_contact)%temperature
1959 18 : IF (ignore_bias) THEN
1960 14 : mu_base = negf_control%contacts(base_contact)%fermi_level
1961 14 : v_external = 0.0_dp
1962 : ELSE
1963 4 : mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
1964 : END IF
1965 :
1966 18 : pi_temperature = pi*temperature
1967 18 : npoles = negf_control%delta_npoles
1968 :
1969 18 : ncontacts = SIZE(negf_env%contacts)
1970 18 : CPASSERT(base_contact <= ncontacts)
1971 18 : IF (PRESENT(just_contact)) THEN
1972 4 : ncontacts = 2
1973 4 : CPASSERT(just_contact == base_contact)
1974 : END IF
1975 :
1976 18 : IF (npoles > 0) THEN
1977 18 : CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
1978 :
1979 162 : ALLOCATE (omega(npoles), g_ret_s(npoles))
1980 :
1981 90 : DO ipole = 1, npoles
1982 72 : CALL cp_cfm_create(g_ret_s(ipole), fm_struct)
1983 :
1984 90 : omega(ipole) = CMPLX(mu_base, REAL(2*ipole - 1, kind=dp)*pi_temperature, kind=dp)
1985 : END DO
1986 :
1987 18 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoles)
1988 :
1989 18 : IF (PRESENT(just_contact)) THEN
1990 : ! do not apply the external potential when computing the Fermi level of a bulk contact.
1991 : ! We are using a fictitious electronic device, which identical to the bulk contact in question;
1992 : ! icontact == 1 corresponds to the "left" contact, so the matrices h_01 and s_01 needs to be transposed,
1993 : ! while icontact == 2 correspond to the "right" contact and we should use the matrices h_01 and s_01 as is.
1994 12 : DO icontact = 1, ncontacts
1995 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
1996 : omega=omega(:), &
1997 : h0=negf_env%contacts(just_contact)%h_00(ispin), &
1998 : s0=negf_env%contacts(just_contact)%s_00, &
1999 : h1=negf_env%contacts(just_contact)%h_01(ispin), &
2000 : s1=negf_env%contacts(just_contact)%s_01, &
2001 : sub_env=sub_env, v_external=0.0_dp, &
2002 12 : conv=negf_control%conv_green, transp=(icontact == 1))
2003 : END DO
2004 : ELSE
2005 42 : DO icontact = 1, ncontacts
2006 28 : IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
2007 :
2008 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
2009 : omega=omega(:), &
2010 : h0=negf_env%contacts(icontact)%h_00(ispin), &
2011 : s0=negf_env%contacts(icontact)%s_00, &
2012 : h1=negf_env%contacts(icontact)%h_01(ispin), &
2013 : s1=negf_env%contacts(icontact)%s_01, &
2014 : sub_env=sub_env, &
2015 : v_external=v_external, &
2016 42 : conv=negf_control%conv_green, transp=.FALSE.)
2017 : END DO
2018 : END IF
2019 :
2020 : CALL negf_retarded_green_function_batch(omega=omega(:), &
2021 : v_shift=v_shift, &
2022 : ignore_bias=ignore_bias, &
2023 : negf_env=negf_env, &
2024 : negf_control=negf_control, &
2025 : sub_env=sub_env, &
2026 : ispin=ispin, &
2027 : g_surf_contacts=g_surf_cache%g_surf_contacts, &
2028 : g_ret_s=g_ret_s, &
2029 18 : just_contact=just_contact)
2030 :
2031 18 : CALL green_functions_cache_release(g_surf_cache)
2032 :
2033 72 : DO ipole = 2, npoles
2034 72 : CALL cp_cfm_scale_and_add(z_one, g_ret_s(1), z_one, g_ret_s(ipole))
2035 : END DO
2036 :
2037 : !Re(-i * (-2*pi*i*kB*T/(-pi) * [Re(G)+i*Im(G)]) == 2*kB*T * Re(G)
2038 18 : CALL cp_cfm_to_fm(g_ret_s(1), mtargetr=rho_ao_fm)
2039 18 : CALL cp_fm_scale(2.0_dp*temperature, rho_ao_fm)
2040 :
2041 90 : DO ipole = npoles, 1, -1
2042 90 : CALL cp_cfm_release(g_ret_s(ipole))
2043 : END DO
2044 18 : DEALLOCATE (g_ret_s, omega)
2045 : END IF
2046 :
2047 18 : CALL timestop(handle)
2048 18 : END SUBROUTINE negf_init_rho_equiv_residuals
2049 :
2050 : ! **************************************************************************************************
2051 : !> \brief Compute equilibrium contribution to the density matrix.
2052 : !> \param rho_ao_fm density matrix (initialised on exit)
2053 : !> \param stats integration statistics (updated on exit)
2054 : !> \param v_shift shift in Hartree potential
2055 : !> \param ignore_bias ignore v_external from negf_control
2056 : !> \param negf_env NEGF environment
2057 : !> \param negf_control NEGF control
2058 : !> \param sub_env NEGF parallel (sub)group environment
2059 : !> \param ispin spin conponent to proceed
2060 : !> \param base_contact index of the reference contact
2061 : !> \param integr_lbound integration lower bound
2062 : !> \param integr_ubound integration upper bound
2063 : !> \param matrix_s_global globally distributed overlap matrix
2064 : !> \param is_circular compute the integral along the circular path
2065 : !> \param g_surf_cache set of precomputed surface Green's functions (updated on exit)
2066 : !> \param just_contact ...
2067 : !> \author Sergey Chulkov
2068 : ! **************************************************************************************************
2069 36 : SUBROUTINE negf_add_rho_equiv_low(rho_ao_fm, stats, v_shift, ignore_bias, negf_env, negf_control, sub_env, &
2070 : ispin, base_contact, integr_lbound, integr_ubound, matrix_s_global, &
2071 : is_circular, g_surf_cache, just_contact)
2072 : TYPE(cp_fm_type), INTENT(IN) :: rho_ao_fm
2073 : TYPE(integration_status_type), INTENT(inout) :: stats
2074 : REAL(kind=dp), INTENT(in) :: v_shift
2075 : LOGICAL, INTENT(in) :: ignore_bias
2076 : TYPE(negf_env_type), INTENT(in) :: negf_env
2077 : TYPE(negf_control_type), POINTER :: negf_control
2078 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
2079 : INTEGER, INTENT(in) :: ispin, base_contact
2080 : COMPLEX(kind=dp), INTENT(in) :: integr_lbound, integr_ubound
2081 : TYPE(cp_fm_type), INTENT(IN) :: matrix_s_global
2082 : LOGICAL, INTENT(in) :: is_circular
2083 : TYPE(green_functions_cache_type), INTENT(inout) :: g_surf_cache
2084 : INTEGER, INTENT(in), OPTIONAL :: just_contact
2085 :
2086 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_add_rho_equiv_low'
2087 :
2088 36 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: xnodes, zscale
2089 : INTEGER :: handle, icontact, interval_id, ipoint, max_points, min_points, ncontacts, &
2090 : npoints, npoints_exist, npoints_tmp, npoints_total, shape_id
2091 : LOGICAL :: do_surface_green
2092 : REAL(kind=dp) :: conv_integr, mu_base, temperature, &
2093 : v_external
2094 36 : TYPE(ccquad_type) :: cc_env
2095 36 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: zdata, zdata_tmp
2096 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2097 : TYPE(cp_fm_type) :: integral_imag
2098 : TYPE(mp_para_env_type), POINTER :: para_env
2099 36 : TYPE(simpsonrule_type) :: sr_env
2100 :
2101 36 : CALL timeset(routineN, handle)
2102 :
2103 : ! convergence criteria for the integral of the retarded Green's function. This integral needs to be
2104 : ! computed for both spin-components and needs to be scaled by -1/pi to obtain the electron density.
2105 36 : conv_integr = 0.5_dp*negf_control%conv_density*pi
2106 :
2107 36 : IF (ignore_bias) THEN
2108 28 : mu_base = negf_control%contacts(base_contact)%fermi_level
2109 28 : v_external = 0.0_dp
2110 : ELSE
2111 8 : mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
2112 : END IF
2113 :
2114 36 : min_points = negf_control%integr_min_points
2115 36 : max_points = negf_control%integr_max_points
2116 36 : temperature = negf_control%contacts(base_contact)%temperature
2117 :
2118 36 : ncontacts = SIZE(negf_env%contacts)
2119 36 : CPASSERT(base_contact <= ncontacts)
2120 36 : IF (PRESENT(just_contact)) THEN
2121 8 : ncontacts = 2
2122 8 : CPASSERT(just_contact == base_contact)
2123 : END IF
2124 :
2125 36 : do_surface_green = .NOT. ALLOCATED(g_surf_cache%tnodes)
2126 :
2127 36 : IF (do_surface_green) THEN
2128 24 : npoints = min_points
2129 : ELSE
2130 12 : npoints = SIZE(g_surf_cache%tnodes)
2131 : END IF
2132 36 : npoints_total = 0
2133 :
2134 36 : CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
2135 36 : CALL cp_fm_create(integral_imag, fm_struct)
2136 :
2137 36 : SELECT CASE (negf_control%integr_method)
2138 : CASE (negfint_method_cc)
2139 : ! Adaptive Clenshaw-Curtis method
2140 0 : ALLOCATE (xnodes(npoints))
2141 :
2142 0 : IF (is_circular) THEN
2143 0 : shape_id = cc_shape_arc
2144 0 : interval_id = cc_interval_full
2145 : ELSE
2146 0 : shape_id = cc_shape_linear
2147 0 : interval_id = cc_interval_half
2148 : END IF
2149 :
2150 0 : IF (do_surface_green) THEN
2151 : CALL ccquad_init(cc_env, xnodes, npoints, integr_lbound, integr_ubound, &
2152 0 : interval_id, shape_id, matrix_s_global)
2153 : ELSE
2154 : CALL ccquad_init(cc_env, xnodes, npoints, integr_lbound, integr_ubound, &
2155 0 : interval_id, shape_id, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
2156 : END IF
2157 :
2158 0 : ALLOCATE (zdata(npoints))
2159 0 : DO ipoint = 1, npoints
2160 0 : CALL cp_cfm_create(zdata(ipoint), fm_struct)
2161 : END DO
2162 :
2163 : DO
2164 0 : IF (do_surface_green) THEN
2165 0 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
2166 :
2167 0 : IF (PRESENT(just_contact)) THEN
2168 : ! do not apply the external potential when computing the Fermi level of a bulk contact.
2169 0 : DO icontact = 1, ncontacts
2170 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
2171 : omega=xnodes(1:npoints), &
2172 : h0=negf_env%contacts(just_contact)%h_00(ispin), &
2173 : s0=negf_env%contacts(just_contact)%s_00, &
2174 : h1=negf_env%contacts(just_contact)%h_01(ispin), &
2175 : s1=negf_env%contacts(just_contact)%s_01, &
2176 : sub_env=sub_env, v_external=0.0_dp, &
2177 0 : conv=negf_control%conv_green, transp=(icontact == 1))
2178 : END DO
2179 : ELSE
2180 0 : DO icontact = 1, ncontacts
2181 0 : IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
2182 :
2183 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
2184 : omega=xnodes(1:npoints), &
2185 : h0=negf_env%contacts(icontact)%h_00(ispin), &
2186 : s0=negf_env%contacts(icontact)%s_00, &
2187 : h1=negf_env%contacts(icontact)%h_01(ispin), &
2188 : s1=negf_env%contacts(icontact)%s_01, &
2189 : sub_env=sub_env, &
2190 : v_external=v_external, &
2191 0 : conv=negf_control%conv_green, transp=.FALSE.)
2192 : END DO
2193 : END IF
2194 : END IF
2195 :
2196 0 : ALLOCATE (zscale(npoints))
2197 :
2198 0 : IF (temperature >= 0.0_dp) THEN
2199 0 : DO ipoint = 1, npoints
2200 0 : zscale(ipoint) = fermi_function(xnodes(ipoint) - mu_base, temperature)
2201 : END DO
2202 : ELSE
2203 0 : zscale(:) = z_one
2204 : END IF
2205 :
2206 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
2207 : v_shift=v_shift, &
2208 : ignore_bias=ignore_bias, &
2209 : negf_env=negf_env, &
2210 : negf_control=negf_control, &
2211 : sub_env=sub_env, &
2212 : ispin=ispin, &
2213 : g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
2214 : g_ret_s=zdata(1:npoints), &
2215 : g_ret_scale=zscale(1:npoints), &
2216 0 : just_contact=just_contact)
2217 :
2218 0 : DEALLOCATE (xnodes, zscale)
2219 0 : npoints_total = npoints_total + npoints
2220 :
2221 0 : CALL ccquad_reduce_and_append_zdata(cc_env, zdata)
2222 0 : CALL MOVE_ALLOC(zdata, zdata_tmp)
2223 :
2224 0 : CALL ccquad_refine_integral(cc_env)
2225 :
2226 0 : IF (cc_env%error <= conv_integr) EXIT
2227 0 : IF (2*(npoints_total - 1) + 1 > max_points) EXIT
2228 :
2229 : ! all cached points have been reused at the first iteration;
2230 : ! we need to compute surface Green's function at extra points if the integral has not been converged
2231 0 : do_surface_green = .TRUE.
2232 :
2233 0 : npoints_tmp = npoints
2234 0 : CALL ccquad_double_number_of_points(cc_env, xnodes)
2235 0 : npoints = SIZE(xnodes)
2236 :
2237 0 : ALLOCATE (zdata(npoints))
2238 :
2239 0 : npoints_exist = 0
2240 0 : DO ipoint = 1, npoints_tmp
2241 0 : IF (ASSOCIATED(zdata_tmp(ipoint)%matrix_struct)) THEN
2242 0 : npoints_exist = npoints_exist + 1
2243 0 : zdata(npoints_exist) = zdata_tmp(ipoint)
2244 : END IF
2245 : END DO
2246 0 : DEALLOCATE (zdata_tmp)
2247 :
2248 0 : DO ipoint = npoints_exist + 1, npoints
2249 0 : CALL cp_cfm_create(zdata(ipoint), fm_struct)
2250 : END DO
2251 : END DO
2252 :
2253 : ! the obtained integral will be scaled by -1/pi, so scale the error extimate as well
2254 0 : stats%error = stats%error + cc_env%error/pi
2255 :
2256 0 : DO ipoint = SIZE(zdata_tmp), 1, -1
2257 0 : CALL cp_cfm_release(zdata_tmp(ipoint))
2258 : END DO
2259 0 : DEALLOCATE (zdata_tmp)
2260 :
2261 0 : CALL cp_cfm_to_fm(cc_env%integral, mtargeti=integral_imag)
2262 :
2263 : ! keep the cache
2264 0 : IF (do_surface_green) THEN
2265 0 : CALL green_functions_cache_reorder(g_surf_cache, cc_env%tnodes)
2266 : END IF
2267 0 : CALL ccquad_release(cc_env)
2268 :
2269 : CASE (negfint_method_simpson)
2270 : ! Adaptive Simpson's rule method
2271 1676 : ALLOCATE (xnodes(npoints), zdata(npoints), zscale(npoints))
2272 :
2273 36 : IF (is_circular) THEN
2274 18 : shape_id = sr_shape_arc
2275 : ELSE
2276 18 : shape_id = sr_shape_linear
2277 : END IF
2278 :
2279 36 : IF (do_surface_green) THEN
2280 : CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
2281 24 : shape_id, conv_integr, matrix_s_global)
2282 : ELSE
2283 : CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
2284 12 : shape_id, conv_integr, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
2285 : END IF
2286 :
2287 130 : DO WHILE (npoints > 0 .AND. npoints_total < max_points)
2288 2806 : DO ipoint = 1, npoints
2289 2806 : CALL cp_cfm_create(zdata(ipoint), fm_struct)
2290 : END DO
2291 :
2292 130 : IF (do_surface_green) THEN
2293 118 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
2294 :
2295 118 : IF (PRESENT(just_contact)) THEN
2296 : ! do not apply the external potential when computing the Fermi level of a bulk contact.
2297 96 : DO icontact = 1, ncontacts
2298 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
2299 : omega=xnodes(1:npoints), &
2300 : h0=negf_env%contacts(just_contact)%h_00(ispin), &
2301 : s0=negf_env%contacts(just_contact)%s_00, &
2302 : h1=negf_env%contacts(just_contact)%h_01(ispin), &
2303 : s1=negf_env%contacts(just_contact)%s_01, &
2304 : sub_env=sub_env, v_external=0.0_dp, &
2305 96 : conv=negf_control%conv_green, transp=(icontact == 1))
2306 : END DO
2307 : ELSE
2308 258 : DO icontact = 1, ncontacts
2309 172 : IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
2310 :
2311 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
2312 : omega=xnodes(1:npoints), &
2313 : h0=negf_env%contacts(icontact)%h_00(ispin), &
2314 : s0=negf_env%contacts(icontact)%s_00, &
2315 : h1=negf_env%contacts(icontact)%h_01(ispin), &
2316 : s1=negf_env%contacts(icontact)%s_01, &
2317 : sub_env=sub_env, &
2318 : v_external=v_external, &
2319 258 : conv=negf_control%conv_green, transp=.FALSE.)
2320 : END DO
2321 : END IF
2322 : END IF
2323 :
2324 130 : IF (temperature >= 0.0_dp) THEN
2325 2806 : DO ipoint = 1, npoints
2326 2806 : zscale(ipoint) = fermi_function(xnodes(ipoint) - mu_base, temperature)
2327 : END DO
2328 : ELSE
2329 0 : zscale(:) = z_one
2330 : END IF
2331 :
2332 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
2333 : v_shift=v_shift, &
2334 : ignore_bias=ignore_bias, &
2335 : negf_env=negf_env, &
2336 : negf_control=negf_control, &
2337 : sub_env=sub_env, &
2338 : ispin=ispin, &
2339 : g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
2340 : g_ret_s=zdata(1:npoints), &
2341 : g_ret_scale=zscale(1:npoints), &
2342 130 : just_contact=just_contact)
2343 :
2344 130 : npoints_total = npoints_total + npoints
2345 :
2346 130 : CALL simpsonrule_refine_integral(sr_env, zdata(1:npoints))
2347 :
2348 130 : IF (sr_env%error <= conv_integr) EXIT
2349 :
2350 : ! all cached points have been reused at the first iteration;
2351 : ! if the integral has not been converged, turn on the 'do_surface_green' flag
2352 : ! in order to add more points
2353 94 : do_surface_green = .TRUE.
2354 :
2355 94 : npoints = max_points - npoints_total
2356 94 : IF (npoints <= 0) EXIT
2357 94 : IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
2358 :
2359 130 : CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
2360 : END DO
2361 :
2362 : ! the obtained integral will be scaled by -1/pi, so scale the error extimate as well
2363 36 : stats%error = stats%error + sr_env%error/pi
2364 :
2365 36 : CALL cp_cfm_to_fm(sr_env%integral, mtargeti=integral_imag)
2366 :
2367 : ! keep the cache
2368 36 : IF (do_surface_green) THEN
2369 26 : CALL green_functions_cache_reorder(g_surf_cache, sr_env%tnodes)
2370 : END IF
2371 :
2372 36 : CALL simpsonrule_release(sr_env)
2373 36 : DEALLOCATE (xnodes, zdata, zscale)
2374 :
2375 : CASE DEFAULT
2376 36 : CPABORT("Unimplemented integration method")
2377 : END SELECT
2378 :
2379 36 : stats%npoints = stats%npoints + npoints_total
2380 :
2381 36 : CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm, -1.0_dp/pi, integral_imag)
2382 36 : CALL cp_fm_release(integral_imag)
2383 :
2384 36 : CALL timestop(handle)
2385 72 : END SUBROUTINE negf_add_rho_equiv_low
2386 :
2387 : ! **************************************************************************************************
2388 : !> \brief Compute non-equilibrium contribution to the density matrix.
2389 : !> \param rho_ao_fm density matrix (initialised on exit)
2390 : !> \param stats integration statistics (updated on exit)
2391 : !> \param v_shift shift in Hartree potential
2392 : !> \param negf_env NEGF environment
2393 : !> \param negf_control NEGF control
2394 : !> \param sub_env NEGF parallel (sub)group environment
2395 : !> \param ispin spin conponent to proceed
2396 : !> \param base_contact index of the reference contact
2397 : !> \param matrix_s_global globally distributed overlap matrix
2398 : !> \param g_surf_cache set of precomputed surface Green's functions (updated on exit)
2399 : !> \author Sergey Chulkov
2400 : ! **************************************************************************************************
2401 0 : SUBROUTINE negf_add_rho_nonequiv(rho_ao_fm, stats, v_shift, negf_env, negf_control, sub_env, &
2402 : ispin, base_contact, matrix_s_global, g_surf_cache)
2403 : TYPE(cp_fm_type), INTENT(IN) :: rho_ao_fm
2404 : TYPE(integration_status_type), INTENT(inout) :: stats
2405 : REAL(kind=dp), INTENT(in) :: v_shift
2406 : TYPE(negf_env_type), INTENT(in) :: negf_env
2407 : TYPE(negf_control_type), POINTER :: negf_control
2408 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
2409 : INTEGER, INTENT(in) :: ispin, base_contact
2410 : TYPE(cp_fm_type), INTENT(IN) :: matrix_s_global
2411 : TYPE(green_functions_cache_type), INTENT(inout) :: g_surf_cache
2412 :
2413 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_add_rho_nonequiv'
2414 :
2415 : COMPLEX(kind=dp) :: fermi_base, fermi_contact, &
2416 : integr_lbound, integr_ubound
2417 0 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: xnodes
2418 : INTEGER :: handle, icontact, ipoint, jcontact, &
2419 : max_points, min_points, ncontacts, &
2420 : npoints, npoints_total
2421 : LOGICAL :: do_surface_green
2422 : REAL(kind=dp) :: conv_density, conv_integr, eta, &
2423 : ln_conv_density, mu_base, mu_contact, &
2424 : temperature_base, temperature_contact
2425 0 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:, :) :: zdata
2426 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2427 : TYPE(cp_fm_type) :: integral_real
2428 : TYPE(mp_para_env_type), POINTER :: para_env
2429 0 : TYPE(simpsonrule_type) :: sr_env
2430 :
2431 0 : CALL timeset(routineN, handle)
2432 :
2433 0 : ncontacts = SIZE(negf_env%contacts)
2434 0 : CPASSERT(base_contact <= ncontacts)
2435 :
2436 : ! the current subroutine works for the general case as well, but the Poisson solver does not
2437 0 : IF (ncontacts > 2) THEN
2438 0 : CPABORT("Poisson solver does not support the general NEGF setup (>2 contacts).")
2439 : END IF
2440 :
2441 0 : mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
2442 0 : min_points = negf_control%integr_min_points
2443 0 : max_points = negf_control%integr_max_points
2444 0 : temperature_base = negf_control%contacts(base_contact)%temperature
2445 0 : eta = negf_control%eta
2446 0 : conv_density = negf_control%conv_density
2447 0 : ln_conv_density = LOG(conv_density)
2448 :
2449 : ! convergence criteria for the integral. This integral needs to be computed for both
2450 : ! spin-components and needs to be scaled by -1/pi to obtain the electron density.
2451 0 : conv_integr = 0.5_dp*conv_density*pi
2452 :
2453 0 : DO icontact = 1, ncontacts
2454 0 : IF (icontact /= base_contact) THEN
2455 0 : mu_contact = negf_control%contacts(icontact)%fermi_level - negf_control%contacts(icontact)%v_external
2456 0 : temperature_contact = negf_control%contacts(icontact)%temperature
2457 :
2458 : integr_lbound = CMPLX(MIN(mu_base + ln_conv_density*temperature_base, &
2459 0 : mu_contact + ln_conv_density*temperature_contact), eta, kind=dp)
2460 : integr_ubound = CMPLX(MAX(mu_base - ln_conv_density*temperature_base, &
2461 0 : mu_contact - ln_conv_density*temperature_contact), eta, kind=dp)
2462 :
2463 0 : do_surface_green = .NOT. ALLOCATED(g_surf_cache%tnodes)
2464 :
2465 0 : IF (do_surface_green) THEN
2466 0 : npoints = min_points
2467 : ELSE
2468 0 : npoints = SIZE(g_surf_cache%tnodes)
2469 : END IF
2470 0 : npoints_total = 0
2471 :
2472 0 : ALLOCATE (xnodes(npoints))
2473 0 : CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
2474 :
2475 0 : IF (do_surface_green) THEN
2476 : CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
2477 0 : sr_shape_linear, conv_integr, matrix_s_global)
2478 : ELSE
2479 : CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
2480 0 : sr_shape_linear, conv_integr, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
2481 : END IF
2482 :
2483 0 : DO WHILE (npoints > 0 .AND. npoints_total < max_points)
2484 :
2485 0 : IF (do_surface_green) THEN
2486 0 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
2487 :
2488 0 : DO jcontact = 1, ncontacts
2489 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(jcontact, npoints_total + 1:), &
2490 : omega=xnodes(1:npoints), &
2491 : h0=negf_env%contacts(jcontact)%h_00(ispin), &
2492 : s0=negf_env%contacts(jcontact)%s_00, &
2493 : h1=negf_env%contacts(jcontact)%h_01(ispin), &
2494 : s1=negf_env%contacts(jcontact)%s_01, &
2495 : sub_env=sub_env, &
2496 : v_external=negf_control%contacts(jcontact)%v_external, &
2497 0 : conv=negf_control%conv_green, transp=.FALSE.)
2498 : END DO
2499 : END IF
2500 :
2501 0 : ALLOCATE (zdata(ncontacts, npoints))
2502 :
2503 0 : DO ipoint = 1, npoints
2504 0 : CALL cp_cfm_create(zdata(base_contact, ipoint), fm_struct)
2505 0 : CALL cp_cfm_create(zdata(icontact, ipoint), fm_struct)
2506 : END DO
2507 :
2508 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
2509 : v_shift=v_shift, &
2510 : ignore_bias=.FALSE., &
2511 : negf_env=negf_env, &
2512 : negf_control=negf_control, &
2513 : sub_env=sub_env, &
2514 : ispin=ispin, &
2515 : g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
2516 0 : gret_gamma_gadv=zdata(:, 1:npoints))
2517 :
2518 0 : DO ipoint = 1, npoints
2519 : fermi_base = fermi_function(CMPLX(REAL(xnodes(ipoint), kind=dp) - mu_base, 0.0_dp, kind=dp), &
2520 0 : temperature_base)
2521 : fermi_contact = fermi_function(CMPLX(REAL(xnodes(ipoint), kind=dp) - mu_contact, 0.0_dp, kind=dp), &
2522 0 : temperature_contact)
2523 0 : CALL cp_cfm_scale(fermi_contact - fermi_base, zdata(icontact, ipoint))
2524 : END DO
2525 :
2526 0 : npoints_total = npoints_total + npoints
2527 :
2528 0 : CALL simpsonrule_refine_integral(sr_env, zdata(icontact, 1:npoints))
2529 :
2530 0 : DO ipoint = 1, npoints
2531 0 : CALL cp_cfm_release(zdata(base_contact, ipoint))
2532 0 : CALL cp_cfm_release(zdata(icontact, ipoint))
2533 : END DO
2534 0 : DEALLOCATE (zdata)
2535 :
2536 0 : IF (sr_env%error <= conv_integr) EXIT
2537 :
2538 : ! not enought cached points to achieve target accuracy
2539 0 : do_surface_green = .TRUE.
2540 :
2541 0 : npoints = max_points - npoints_total
2542 0 : IF (npoints <= 0) EXIT
2543 0 : IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
2544 :
2545 0 : CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
2546 :
2547 : END DO
2548 :
2549 0 : CALL cp_fm_create(integral_real, fm_struct)
2550 :
2551 0 : CALL cp_cfm_to_fm(sr_env%integral, mtargetr=integral_real)
2552 0 : CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm, 0.5_dp/pi, integral_real)
2553 :
2554 0 : CALL cp_fm_release(integral_real)
2555 :
2556 0 : DEALLOCATE (xnodes)
2557 :
2558 0 : stats%error = stats%error + sr_env%error*0.5_dp/pi
2559 0 : stats%npoints = stats%npoints + npoints_total
2560 :
2561 : ! keep the cache
2562 0 : IF (do_surface_green) THEN
2563 0 : CALL green_functions_cache_reorder(g_surf_cache, sr_env%tnodes)
2564 : END IF
2565 :
2566 0 : CALL simpsonrule_release(sr_env)
2567 : END IF
2568 : END DO
2569 :
2570 0 : CALL timestop(handle)
2571 0 : END SUBROUTINE negf_add_rho_nonequiv
2572 :
2573 : ! **************************************************************************************************
2574 : !> \brief Reset integration statistics.
2575 : !> \param stats integration statistics
2576 : !> \author Sergey Chulkov
2577 : ! **************************************************************************************************
2578 18 : ELEMENTAL SUBROUTINE integration_status_reset(stats)
2579 : TYPE(integration_status_type), INTENT(out) :: stats
2580 :
2581 18 : stats%npoints = 0
2582 18 : stats%error = 0.0_dp
2583 18 : END SUBROUTINE integration_status_reset
2584 :
2585 : ! **************************************************************************************************
2586 : !> \brief Generate an integration method description string.
2587 : !> \param stats integration statistics
2588 : !> \param integration_method integration method used
2589 : !> \return description string
2590 : !> \author Sergey Chulkov
2591 : ! **************************************************************************************************
2592 9 : ELEMENTAL FUNCTION get_method_description_string(stats, integration_method) RESULT(method_descr)
2593 : TYPE(integration_status_type), INTENT(in) :: stats
2594 : INTEGER, INTENT(in) :: integration_method
2595 : CHARACTER(len=18) :: method_descr
2596 :
2597 : CHARACTER(len=2) :: method_abbr
2598 : CHARACTER(len=6) :: npoints_str
2599 :
2600 9 : SELECT CASE (integration_method)
2601 : CASE (negfint_method_cc)
2602 : ! Adaptive Clenshaw-Curtis method
2603 0 : method_abbr = "CC"
2604 : CASE (negfint_method_simpson)
2605 : ! Adaptive Simpson's rule method
2606 9 : method_abbr = "SR"
2607 : CASE DEFAULT
2608 9 : method_abbr = "??"
2609 : END SELECT
2610 :
2611 9 : WRITE (npoints_str, '(I6)') stats%npoints
2612 9 : WRITE (method_descr, '(A2,T4,A,T11,ES8.2E2)') method_abbr, TRIM(ADJUSTL(npoints_str)), stats%error
2613 9 : END FUNCTION get_method_description_string
2614 :
2615 : ! **************************************************************************************************
2616 : !> \brief Compute electric current for one spin-channel through the scattering region.
2617 : !> \param contact_id1 reference contact
2618 : !> \param contact_id2 another contact
2619 : !> \param v_shift shift in Hartree potential
2620 : !> \param negf_env NEFG environment
2621 : !> \param negf_control NEGF control
2622 : !> \param sub_env NEGF parallel (sub)group environment
2623 : !> \param ispin spin conponent to proceed
2624 : !> \param blacs_env_global global BLACS environment
2625 : !> \return electric current in Amper
2626 : !> \author Sergey Chulkov
2627 : ! **************************************************************************************************
2628 4 : FUNCTION negf_compute_current(contact_id1, contact_id2, v_shift, negf_env, negf_control, sub_env, ispin, &
2629 : blacs_env_global) RESULT(current)
2630 : INTEGER, INTENT(in) :: contact_id1, contact_id2
2631 : REAL(kind=dp), INTENT(in) :: v_shift
2632 : TYPE(negf_env_type), INTENT(in) :: negf_env
2633 : TYPE(negf_control_type), POINTER :: negf_control
2634 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
2635 : INTEGER, INTENT(in) :: ispin
2636 : TYPE(cp_blacs_env_type), POINTER :: blacs_env_global
2637 : REAL(kind=dp) :: current
2638 :
2639 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_compute_current'
2640 : REAL(kind=dp), PARAMETER :: threshold = 16.0_dp*EPSILON(0.0_dp)
2641 :
2642 : COMPLEX(kind=dp) :: fermi_contact1, fermi_contact2, &
2643 : integr_lbound, integr_ubound
2644 4 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: transm_coeff, xnodes
2645 : COMPLEX(kind=dp), DIMENSION(1, 1) :: transmission
2646 : INTEGER :: handle, icontact, ipoint, max_points, &
2647 : min_points, ncontacts, npoints, &
2648 : npoints_total
2649 : REAL(kind=dp) :: conv_density, energy, eta, ln_conv_density, mu_contact1, mu_contact2, &
2650 : temperature_contact1, temperature_contact2, v_contact1, v_contact2
2651 4 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: zdata
2652 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_single
2653 : TYPE(cp_fm_type) :: weights
2654 4 : TYPE(green_functions_cache_type) :: g_surf_cache
2655 4 : TYPE(simpsonrule_type) :: sr_env
2656 :
2657 4 : current = 0.0_dp
2658 : ! nothing to do
2659 4 : IF (.NOT. ASSOCIATED(negf_env%s_s)) RETURN
2660 :
2661 4 : CALL timeset(routineN, handle)
2662 :
2663 4 : ncontacts = SIZE(negf_env%contacts)
2664 4 : CPASSERT(contact_id1 <= ncontacts)
2665 4 : CPASSERT(contact_id2 <= ncontacts)
2666 4 : CPASSERT(contact_id1 /= contact_id2)
2667 :
2668 4 : v_contact1 = negf_control%contacts(contact_id1)%v_external
2669 4 : mu_contact1 = negf_control%contacts(contact_id1)%fermi_level - v_contact1
2670 4 : v_contact2 = negf_control%contacts(contact_id2)%v_external
2671 4 : mu_contact2 = negf_control%contacts(contact_id2)%fermi_level - v_contact2
2672 :
2673 4 : IF (ABS(mu_contact1 - mu_contact2) < threshold) THEN
2674 4 : CALL timestop(handle)
2675 4 : RETURN
2676 : END IF
2677 :
2678 0 : min_points = negf_control%integr_min_points
2679 0 : max_points = negf_control%integr_max_points
2680 0 : temperature_contact1 = negf_control%contacts(contact_id1)%temperature
2681 0 : temperature_contact2 = negf_control%contacts(contact_id2)%temperature
2682 0 : eta = negf_control%eta
2683 0 : conv_density = negf_control%conv_density
2684 0 : ln_conv_density = LOG(conv_density)
2685 :
2686 : integr_lbound = CMPLX(MIN(mu_contact1 + ln_conv_density*temperature_contact1, &
2687 0 : mu_contact2 + ln_conv_density*temperature_contact2), eta, kind=dp)
2688 : integr_ubound = CMPLX(MAX(mu_contact1 - ln_conv_density*temperature_contact1, &
2689 0 : mu_contact2 - ln_conv_density*temperature_contact2), eta, kind=dp)
2690 :
2691 0 : npoints_total = 0
2692 0 : npoints = min_points
2693 :
2694 0 : NULLIFY (fm_struct_single)
2695 0 : CALL cp_fm_struct_create(fm_struct_single, nrow_global=1, ncol_global=1, context=blacs_env_global)
2696 0 : CALL cp_fm_create(weights, fm_struct_single)
2697 0 : CALL cp_fm_set_all(weights, 1.0_dp)
2698 :
2699 0 : ALLOCATE (transm_coeff(npoints), xnodes(npoints), zdata(npoints))
2700 :
2701 : CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
2702 0 : sr_shape_linear, negf_control%conv_density, weights)
2703 :
2704 0 : DO WHILE (npoints > 0 .AND. npoints_total < max_points)
2705 0 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
2706 :
2707 0 : DO icontact = 1, ncontacts
2708 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, 1:npoints), &
2709 : omega=xnodes(1:npoints), &
2710 : h0=negf_env%contacts(icontact)%h_00(ispin), &
2711 : s0=negf_env%contacts(icontact)%s_00, &
2712 : h1=negf_env%contacts(icontact)%h_01(ispin), &
2713 : s1=negf_env%contacts(icontact)%s_01, &
2714 : sub_env=sub_env, &
2715 : v_external=negf_control%contacts(icontact)%v_external, &
2716 0 : conv=negf_control%conv_green, transp=.FALSE.)
2717 : END DO
2718 :
2719 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
2720 : v_shift=v_shift, &
2721 : ignore_bias=.FALSE., &
2722 : negf_env=negf_env, &
2723 : negf_control=negf_control, &
2724 : sub_env=sub_env, &
2725 : ispin=ispin, &
2726 : g_surf_contacts=g_surf_cache%g_surf_contacts(:, 1:npoints), &
2727 : transm_coeff=transm_coeff(1:npoints), &
2728 : transm_contact1=contact_id1, &
2729 0 : transm_contact2=contact_id2)
2730 :
2731 0 : DO ipoint = 1, npoints
2732 0 : CALL cp_cfm_create(zdata(ipoint), fm_struct_single)
2733 :
2734 0 : energy = REAL(xnodes(ipoint), kind=dp)
2735 0 : fermi_contact1 = fermi_function(CMPLX(energy - mu_contact1, 0.0_dp, kind=dp), temperature_contact1)
2736 0 : fermi_contact2 = fermi_function(CMPLX(energy - mu_contact2, 0.0_dp, kind=dp), temperature_contact2)
2737 :
2738 0 : transmission(1, 1) = transm_coeff(ipoint)*(fermi_contact1 - fermi_contact2)
2739 0 : CALL cp_cfm_set_submatrix(zdata(ipoint), transmission)
2740 : END DO
2741 :
2742 0 : CALL green_functions_cache_release(g_surf_cache)
2743 :
2744 0 : npoints_total = npoints_total + npoints
2745 :
2746 0 : CALL simpsonrule_refine_integral(sr_env, zdata(1:npoints))
2747 :
2748 0 : IF (sr_env%error <= negf_control%conv_density) EXIT
2749 :
2750 0 : npoints = max_points - npoints_total
2751 0 : IF (npoints <= 0) EXIT
2752 0 : IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
2753 :
2754 0 : CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
2755 : END DO
2756 :
2757 0 : CALL cp_cfm_get_submatrix(sr_env%integral, transmission)
2758 :
2759 0 : current = -0.5_dp/pi*REAL(transmission(1, 1), kind=dp)*e_charge/seconds
2760 :
2761 0 : CALL cp_fm_release(weights)
2762 0 : CALL cp_fm_struct_release(fm_struct_single)
2763 :
2764 0 : CALL simpsonrule_release(sr_env)
2765 0 : DEALLOCATE (transm_coeff, xnodes, zdata)
2766 :
2767 0 : CALL timestop(handle)
2768 8 : END FUNCTION negf_compute_current
2769 :
2770 : ! **************************************************************************************************
2771 : !> \brief Print the Density of States.
2772 : !> \param log_unit output unit
2773 : !> \param energy_min energy point to start with
2774 : !> \param energy_max energy point to end with
2775 : !> \param npoints number of points to compute
2776 : !> \param v_shift shift in Hartree potential
2777 : !> \param negf_env NEFG environment
2778 : !> \param negf_control NEGF control
2779 : !> \param sub_env NEGF parallel (sub)group environment
2780 : !> \param base_contact index of the reference contact
2781 : !> \param just_contact compute DOS for the given contact rather than for a scattering region
2782 : !> \param volume unit cell volume
2783 : !> \author Sergey Chulkov
2784 : ! **************************************************************************************************
2785 4 : SUBROUTINE negf_print_dos(log_unit, energy_min, energy_max, npoints, v_shift, negf_env, &
2786 : negf_control, sub_env, base_contact, just_contact, volume)
2787 : INTEGER, INTENT(in) :: log_unit
2788 : REAL(kind=dp), INTENT(in) :: energy_min, energy_max
2789 : INTEGER, INTENT(in) :: npoints
2790 : REAL(kind=dp), INTENT(in) :: v_shift
2791 : TYPE(negf_env_type), INTENT(in) :: negf_env
2792 : TYPE(negf_control_type), POINTER :: negf_control
2793 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
2794 : INTEGER, INTENT(in) :: base_contact
2795 : INTEGER, INTENT(in), OPTIONAL :: just_contact
2796 : REAL(kind=dp), INTENT(in), OPTIONAL :: volume
2797 :
2798 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_print_dos'
2799 :
2800 : CHARACTER :: uks_str
2801 : CHARACTER(len=15) :: units_str
2802 4 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: xnodes
2803 : INTEGER :: handle, icontact, ipoint, ispin, &
2804 : ncontacts, npoints_bundle, &
2805 : npoints_remain, nspins
2806 4 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: dos
2807 4 : TYPE(green_functions_cache_type) :: g_surf_cache
2808 :
2809 4 : CALL timeset(routineN, handle)
2810 :
2811 4 : IF (PRESENT(just_contact)) THEN
2812 0 : nspins = SIZE(negf_env%contacts(just_contact)%h_00)
2813 : ELSE
2814 4 : nspins = SIZE(negf_env%h_s)
2815 : END IF
2816 :
2817 4 : IF (log_unit > 0) THEN
2818 2 : IF (PRESENT(volume)) THEN
2819 0 : units_str = ' (angstroms^-3)'
2820 : ELSE
2821 2 : units_str = ''
2822 : END IF
2823 :
2824 2 : IF (nspins > 1) THEN
2825 : ! [alpha , beta]
2826 0 : uks_str = ','
2827 : ELSE
2828 : ! [alpha + beta]
2829 2 : uks_str = '+'
2830 : END IF
2831 :
2832 2 : IF (PRESENT(just_contact)) THEN
2833 0 : WRITE (log_unit, '(3A,T70,I11)') "# Density of states", TRIM(units_str), " for the contact No. ", just_contact
2834 : ELSE
2835 2 : WRITE (log_unit, '(3A)') "# Density of states", TRIM(units_str), " for the scattering region"
2836 : END IF
2837 :
2838 2 : WRITE (log_unit, '(A,T10,A,T43,3A)') "#", "Energy (a.u.)", "Number of states [alpha ", uks_str, " beta]"
2839 :
2840 2 : WRITE (log_unit, '("#", T3,78("-"))')
2841 : END IF
2842 :
2843 4 : ncontacts = SIZE(negf_env%contacts)
2844 4 : CPASSERT(base_contact <= ncontacts)
2845 4 : IF (PRESENT(just_contact)) THEN
2846 0 : ncontacts = 2
2847 0 : CPASSERT(just_contact == base_contact)
2848 : END IF
2849 : MARK_USED(base_contact)
2850 :
2851 4 : npoints_bundle = 4*sub_env%ngroups
2852 4 : IF (npoints_bundle > npoints) npoints_bundle = npoints
2853 :
2854 24 : ALLOCATE (dos(npoints_bundle, nspins), xnodes(npoints_bundle))
2855 :
2856 208 : npoints_remain = npoints
2857 208 : DO WHILE (npoints_remain > 0)
2858 204 : IF (npoints_bundle > npoints_remain) npoints_bundle = npoints_remain
2859 :
2860 204 : IF (npoints > 1) THEN
2861 1808 : DO ipoint = 1, npoints_bundle
2862 : xnodes(ipoint) = CMPLX(energy_min + REAL(npoints - npoints_remain + ipoint - 1, kind=dp)/ &
2863 1808 : REAL(npoints - 1, kind=dp)*(energy_max - energy_min), negf_control%eta, kind=dp)
2864 : END DO
2865 : ELSE
2866 0 : xnodes(ipoint) = CMPLX(energy_min, negf_control%eta, kind=dp)
2867 : END IF
2868 :
2869 408 : DO ispin = 1, nspins
2870 204 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints_bundle)
2871 :
2872 204 : IF (PRESENT(just_contact)) THEN
2873 0 : DO icontact = 1, ncontacts
2874 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
2875 : omega=xnodes(1:npoints_bundle), &
2876 : h0=negf_env%contacts(just_contact)%h_00(ispin), &
2877 : s0=negf_env%contacts(just_contact)%s_00, &
2878 : h1=negf_env%contacts(just_contact)%h_01(ispin), &
2879 : s1=negf_env%contacts(just_contact)%s_01, &
2880 : sub_env=sub_env, v_external=0.0_dp, &
2881 0 : conv=negf_control%conv_green, transp=(icontact == 1))
2882 : END DO
2883 : ELSE
2884 612 : DO icontact = 1, ncontacts
2885 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
2886 : omega=xnodes(1:npoints_bundle), &
2887 : h0=negf_env%contacts(icontact)%h_00(ispin), &
2888 : s0=negf_env%contacts(icontact)%s_00, &
2889 : h1=negf_env%contacts(icontact)%h_01(ispin), &
2890 : s1=negf_env%contacts(icontact)%s_01, &
2891 : sub_env=sub_env, &
2892 : v_external=negf_control%contacts(icontact)%v_external, &
2893 612 : conv=negf_control%conv_green, transp=.FALSE.)
2894 : END DO
2895 : END IF
2896 :
2897 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints_bundle), &
2898 : v_shift=v_shift, &
2899 : ignore_bias=.FALSE., &
2900 : negf_env=negf_env, &
2901 : negf_control=negf_control, &
2902 : sub_env=sub_env, &
2903 : ispin=ispin, &
2904 : g_surf_contacts=g_surf_cache%g_surf_contacts, &
2905 : dos=dos(1:npoints_bundle, ispin), &
2906 204 : just_contact=just_contact)
2907 :
2908 408 : CALL green_functions_cache_release(g_surf_cache)
2909 : END DO
2910 :
2911 204 : IF (log_unit > 0) THEN
2912 904 : DO ipoint = 1, npoints_bundle
2913 904 : IF (nspins > 1) THEN
2914 : ! spin-polarised calculations: print alpha- and beta-spin components separately
2915 0 : WRITE (log_unit, '(T2,F20.8,T30,2ES25.11E3)') REAL(xnodes(ipoint), kind=dp), dos(ipoint, 1), dos(ipoint, 2)
2916 : ELSE
2917 : ! spin-restricted calculations: print alpha- and beta-spin components together
2918 802 : WRITE (log_unit, '(T2,F20.8,T43,ES25.11E3)') REAL(xnodes(ipoint), kind=dp), 2.0_dp*dos(ipoint, 1)
2919 : END IF
2920 : END DO
2921 : END IF
2922 :
2923 204 : npoints_remain = npoints_remain - npoints_bundle
2924 : END DO
2925 :
2926 4 : DEALLOCATE (dos, xnodes)
2927 4 : CALL timestop(handle)
2928 8 : END SUBROUTINE negf_print_dos
2929 :
2930 : ! **************************************************************************************************
2931 : !> \brief Print the transmission coefficient.
2932 : !> \param log_unit output unit
2933 : !> \param energy_min energy point to start with
2934 : !> \param energy_max energy point to end with
2935 : !> \param npoints number of points to compute
2936 : !> \param v_shift shift in Hartree potential
2937 : !> \param negf_env NEFG environment
2938 : !> \param negf_control NEGF control
2939 : !> \param sub_env NEGF parallel (sub)group environment
2940 : !> \param contact_id1 index of a reference contact
2941 : !> \param contact_id2 index of another contact
2942 : !> \author Sergey Chulkov
2943 : ! **************************************************************************************************
2944 4 : SUBROUTINE negf_print_transmission(log_unit, energy_min, energy_max, npoints, v_shift, negf_env, &
2945 : negf_control, sub_env, contact_id1, contact_id2)
2946 : INTEGER, INTENT(in) :: log_unit
2947 : REAL(kind=dp), INTENT(in) :: energy_min, energy_max
2948 : INTEGER, INTENT(in) :: npoints
2949 : REAL(kind=dp), INTENT(in) :: v_shift
2950 : TYPE(negf_env_type), INTENT(in) :: negf_env
2951 : TYPE(negf_control_type), POINTER :: negf_control
2952 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
2953 : INTEGER, INTENT(in) :: contact_id1, contact_id2
2954 :
2955 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_print_transmission'
2956 :
2957 : CHARACTER :: uks_str
2958 4 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:) :: xnodes
2959 4 : COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: transm_coeff
2960 : INTEGER :: handle, icontact, ipoint, ispin, &
2961 : ncontacts, npoints_bundle, &
2962 : npoints_remain, nspins
2963 : REAL(kind=dp) :: rscale
2964 4 : TYPE(green_functions_cache_type) :: g_surf_cache
2965 :
2966 4 : CALL timeset(routineN, handle)
2967 :
2968 4 : nspins = SIZE(negf_env%h_s)
2969 :
2970 4 : IF (nspins > 1) THEN
2971 : ! [alpha , beta]
2972 0 : uks_str = ','
2973 : ELSE
2974 : ! [alpha + beta]
2975 4 : uks_str = '+'
2976 : END IF
2977 :
2978 4 : IF (log_unit > 0) THEN
2979 2 : WRITE (log_unit, '(A)') "# Transmission coefficient (G0 = 2 e^2/h) for the scattering region"
2980 :
2981 2 : WRITE (log_unit, '(A,T10,A,T39,3A)') "#", "Energy (a.u.)", "Transmission coefficient [alpha ", uks_str, " beta]"
2982 2 : WRITE (log_unit, '("#", T3,78("-"))')
2983 : END IF
2984 :
2985 4 : ncontacts = SIZE(negf_env%contacts)
2986 4 : CPASSERT(contact_id1 <= ncontacts)
2987 4 : CPASSERT(contact_id2 <= ncontacts)
2988 :
2989 4 : IF (nspins == 1) THEN
2990 : rscale = 2.0_dp
2991 : ELSE
2992 0 : rscale = 1.0_dp
2993 : END IF
2994 :
2995 : ! print transmission coefficients in terms of G0 = 2 * e^2 / h = 1 / pi ;
2996 : ! transmission coefficients returned by negf_retarded_green_function_batch() are already multiplied by 2 / pi
2997 4 : rscale = 0.5_dp*rscale
2998 :
2999 4 : npoints_bundle = 4*sub_env%ngroups
3000 4 : IF (npoints_bundle > npoints) npoints_bundle = npoints
3001 :
3002 24 : ALLOCATE (transm_coeff(npoints_bundle, nspins), xnodes(npoints_bundle))
3003 :
3004 208 : npoints_remain = npoints
3005 208 : DO WHILE (npoints_remain > 0)
3006 204 : IF (npoints_bundle > npoints_remain) npoints_bundle = npoints_remain
3007 :
3008 204 : IF (npoints > 1) THEN
3009 1808 : DO ipoint = 1, npoints_bundle
3010 : xnodes(ipoint) = CMPLX(energy_min + REAL(npoints - npoints_remain + ipoint - 1, kind=dp)/ &
3011 1808 : REAL(npoints - 1, kind=dp)*(energy_max - energy_min), negf_control%eta, kind=dp)
3012 : END DO
3013 : ELSE
3014 0 : xnodes(ipoint) = CMPLX(energy_min, negf_control%eta, kind=dp)
3015 : END IF
3016 :
3017 408 : DO ispin = 1, nspins
3018 204 : CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints_bundle)
3019 :
3020 612 : DO icontact = 1, ncontacts
3021 : CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
3022 : omega=xnodes(1:npoints_bundle), &
3023 : h0=negf_env%contacts(icontact)%h_00(ispin), &
3024 : s0=negf_env%contacts(icontact)%s_00, &
3025 : h1=negf_env%contacts(icontact)%h_01(ispin), &
3026 : s1=negf_env%contacts(icontact)%s_01, &
3027 : sub_env=sub_env, &
3028 : v_external=negf_control%contacts(icontact)%v_external, &
3029 612 : conv=negf_control%conv_green, transp=.FALSE.)
3030 : END DO
3031 :
3032 : CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints_bundle), &
3033 : v_shift=v_shift, &
3034 : ignore_bias=.FALSE., &
3035 : negf_env=negf_env, &
3036 : negf_control=negf_control, &
3037 : sub_env=sub_env, &
3038 : ispin=ispin, &
3039 : g_surf_contacts=g_surf_cache%g_surf_contacts, &
3040 : transm_coeff=transm_coeff(1:npoints_bundle, ispin), &
3041 : transm_contact1=contact_id1, &
3042 204 : transm_contact2=contact_id2)
3043 :
3044 408 : CALL green_functions_cache_release(g_surf_cache)
3045 : END DO
3046 :
3047 204 : IF (log_unit > 0) THEN
3048 904 : DO ipoint = 1, npoints_bundle
3049 904 : IF (nspins > 1) THEN
3050 : ! spin-polarised calculations: print alpha- and beta-spin components separately
3051 : WRITE (log_unit, '(T2,F20.8,T30,2ES25.11E3)') &
3052 0 : REAL(xnodes(ipoint), kind=dp), rscale*REAL(transm_coeff(ipoint, 1:2), kind=dp)
3053 : ELSE
3054 : ! spin-restricted calculations: print alpha- and beta-spin components together
3055 : WRITE (log_unit, '(T2,F20.8,T43,ES25.11E3)') &
3056 802 : REAL(xnodes(ipoint), kind=dp), rscale*REAL(transm_coeff(ipoint, 1), kind=dp)
3057 : END IF
3058 : END DO
3059 : END IF
3060 :
3061 204 : npoints_remain = npoints_remain - npoints_bundle
3062 : END DO
3063 :
3064 4 : DEALLOCATE (transm_coeff, xnodes)
3065 4 : CALL timestop(handle)
3066 8 : END SUBROUTINE negf_print_transmission
3067 :
3068 : ! **************************************************************************************************
3069 : !> \brief Print the initial info and Hamiltonian / overlap matrices.
3070 : !> \param log_unit ...
3071 : !> \param negf_env ...
3072 : !> \param sub_env ...
3073 : !> \param negf_control ...
3074 : !> \param dft_control ...
3075 : !> \param verbose_output ...
3076 : !> \param debug_output ...
3077 : !> \par History
3078 : !> * 11.2025 created [Dmitry Ryndyk]
3079 : ! **************************************************************************************************
3080 4 : SUBROUTINE negf_output_initial(log_unit, negf_env, sub_env, negf_control, dft_control, verbose_output, &
3081 : debug_output)
3082 : INTEGER, INTENT(in) :: log_unit
3083 : TYPE(negf_env_type), INTENT(in) :: negf_env
3084 : TYPE(negf_subgroup_env_type), INTENT(in) :: sub_env
3085 : TYPE(negf_control_type), POINTER :: negf_control
3086 : TYPE(dft_control_type), POINTER :: dft_control
3087 : LOGICAL, INTENT(in) :: verbose_output, debug_output
3088 :
3089 : CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_output_initial'
3090 :
3091 : CHARACTER(len=100) :: sfmt
3092 : INTEGER :: handle, i, icontact, j, k, n, nrow
3093 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: target_m
3094 :
3095 4 : CALL timeset(routineN, handle)
3096 :
3097 : ! Electrodes
3098 12 : DO icontact = 1, SIZE(negf_control%contacts)
3099 8 : IF (log_unit > 0) THEN
3100 4 : WRITE (log_unit, "(/,' The electrode',I5)") icontact
3101 4 : WRITE (log_unit, "( ' ------------------')")
3102 4 : WRITE (log_unit, "(' From the force environment:',I16)") negf_control%contacts(icontact)%force_env_index
3103 4 : WRITE (log_unit, "(' Number of atoms:',I27)") SIZE(negf_control%contacts(icontact)%atomlist_bulk)
3104 4 : IF (verbose_output) WRITE (log_unit, "(' Atoms belonging to a contact (from the entire system):')")
3105 36 : IF (verbose_output) WRITE (log_unit, "(16I5)") negf_control%contacts(icontact)%atomlist_bulk
3106 : WRITE (log_unit, "(' Number of atoms in a primary unit cell:',I4)") &
3107 4 : SIZE(negf_env%contacts(icontact)%atomlist_cell0)
3108 : END IF
3109 8 : IF (log_unit > 0 .AND. verbose_output) THEN
3110 4 : WRITE (log_unit, "(' Atoms belonging to a primary unit cell (from the entire system):')")
3111 20 : WRITE (log_unit, "(16I5)") negf_env%contacts(icontact)%atomlist_cell0
3112 4 : WRITE (log_unit, "(' Direction of an electrode: ',I16)") negf_env%contacts(icontact)%direction_axis
3113 : END IF
3114 : ! print the electrode Hamiltonians for check and debuging
3115 12 : IF (debug_output) THEN
3116 8 : CALL cp_fm_get_info(negf_env%contacts(icontact)%s_00, nrow_global=nrow)
3117 32 : ALLOCATE (target_m(nrow, nrow))
3118 8 : IF (log_unit > 0) WRITE (log_unit, "(' The number of atomic orbitals:',I13)") nrow
3119 16 : DO k = 1, dft_control%nspins
3120 8 : CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%h_00(k), target_m)
3121 8 : IF (log_unit > 0) THEN
3122 4 : WRITE (sfmt, "('(',i0,'(E15.5))')") nrow
3123 4 : WRITE (log_unit, "(' The H_00 electrode Hamiltonian for spin',I2)") k
3124 20 : DO i = 1, nrow
3125 20 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3126 : END DO
3127 : END IF
3128 8 : CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%h_01(k), target_m)
3129 16 : IF (log_unit > 0) THEN
3130 4 : WRITE (log_unit, "(' The H_01 electrode Hamiltonian for spin',I2)") k
3131 20 : DO i = 1, nrow
3132 20 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3133 : END DO
3134 : END IF
3135 : END DO
3136 8 : CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%s_00, target_m)
3137 8 : IF (log_unit > 0) THEN
3138 4 : WRITE (log_unit, "(' The S_00 overlap matrix')")
3139 20 : DO i = 1, nrow
3140 20 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3141 : END DO
3142 : END IF
3143 8 : CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%s_01, target_m)
3144 8 : IF (log_unit > 0) THEN
3145 4 : WRITE (log_unit, "(' The S_01 overlap matrix')")
3146 20 : DO i = 1, nrow
3147 20 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3148 : END DO
3149 : END IF
3150 16 : DEALLOCATE (target_m)
3151 : END IF
3152 : END DO
3153 :
3154 : ! Scattering region and contacts
3155 4 : IF (log_unit > 0) THEN
3156 2 : WRITE (log_unit, "(/,' The full scattering region')")
3157 2 : WRITE (log_unit, "( ' --------------------------')")
3158 2 : WRITE (log_unit, "(' Number of atoms:',I27)") SIZE(negf_control%atomlist_S_screening)
3159 2 : IF (verbose_output) WRITE (log_unit, "(' Atoms belonging to a full scattering region:')")
3160 2 : IF (verbose_output) WRITE (log_unit, "(16I5)") negf_control%atomlist_S_screening
3161 : END IF
3162 : ! print the full scattering region Hamiltonians for check and debuging
3163 4 : IF (debug_output) THEN
3164 4 : CALL cp_fm_get_info(negf_env%s_s, nrow_global=n)
3165 16 : ALLOCATE (target_m(n, n))
3166 4 : WRITE (sfmt, "('(',i0,'(E15.5))')") n
3167 4 : IF (log_unit > 0) WRITE (log_unit, "(' The number of atomic orbitals:',I14)") n
3168 8 : DO k = 1, dft_control%nspins
3169 4 : IF (log_unit > 0) WRITE (log_unit, "(' The H_s Hamiltonian for spin',I2)") k
3170 4 : CALL cp_fm_get_submatrix(negf_env%h_s(k), target_m)
3171 56 : DO i = 1, n
3172 52 : IF (log_unit > 0) WRITE (log_unit, sfmt) (target_m(i, j), j=1, n)
3173 : END DO
3174 : END DO
3175 4 : IF (log_unit > 0) WRITE (log_unit, "(' The S_s overlap matrix')")
3176 4 : CALL cp_fm_get_submatrix(negf_env%s_s, target_m)
3177 52 : DO i = 1, n
3178 52 : IF (log_unit > 0) WRITE (log_unit, sfmt) (target_m(i, j), j=1, n)
3179 : END DO
3180 4 : DEALLOCATE (target_m)
3181 4 : IF (log_unit > 0) WRITE (log_unit, "(/,' Scattering region - electrode contacts')")
3182 4 : IF (log_unit > 0) WRITE (log_unit, "( ' ---------------------------------------')")
3183 16 : ALLOCATE (target_m(n, nrow))
3184 12 : DO icontact = 1, SIZE(negf_control%contacts)
3185 8 : IF (log_unit > 0) WRITE (log_unit, "(/,' The contact',I5)") icontact
3186 8 : IF (log_unit > 0) WRITE (log_unit, "( ' ----------------')")
3187 16 : DO k = 1, dft_control%nspins
3188 8 : CALL cp_fm_get_submatrix(negf_env%h_sc(k, icontact), target_m)
3189 16 : IF (log_unit > 0) THEN
3190 4 : WRITE (log_unit, "(' The H_sc Hamiltonian for spin',I2)") k
3191 52 : DO i = 1, n
3192 52 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3193 : END DO
3194 : END IF
3195 : END DO
3196 8 : CALL cp_fm_get_submatrix(negf_env%s_sc(icontact), target_m)
3197 12 : IF (log_unit > 0) THEN
3198 4 : WRITE (log_unit, "(' The S_sc overlap matrix')")
3199 52 : DO i = 1, n
3200 52 : WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
3201 : END DO
3202 : END IF
3203 : END DO
3204 8 : DEALLOCATE (target_m)
3205 : END IF
3206 :
3207 4 : IF (log_unit > 0) THEN
3208 2 : WRITE (log_unit, "(/,' NEGF| Number of MPI processes: ',I5)") sub_env%mpi_comm_global%num_pe
3209 2 : WRITE (log_unit, "(' NEGF| Maximal number of processes per energy point:',I5)") negf_control%nprocs
3210 2 : WRITE (log_unit, "(' NEGF| Number of parallel MPI (energy) groups: ',I5)") sub_env%ngroups
3211 : END IF
3212 :
3213 4 : CALL timestop(handle)
3214 4 : END SUBROUTINE negf_output_initial
3215 :
3216 0 : END MODULE negf_methods
|