(git:374b731)
Loading...
Searching...
No Matches
transport.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief routines for DFT+NEGF calculations (coupling with the quantum transport code OMEN)
10!> \par History
11!> 12.2012 created external_scf_method [Hossein Bani-Hashemian]
12!> 05.2013 created rotines to work with C-interoperable matrices [Hossein Bani-Hashemian]
13!> 07.2013 created transport_env routines [Hossein Bani-Hashemian]
14!> 11.2014 switch to CSR matrices [Hossein Bani-Hashemian]
15!> 12.2014 merged [Hossein Bani-Hashemian]
16!> 04.2016 added imaginary DM and current density cube [Hossein Bani-Hashemian]
17!> \author Mohammad Hossein Bani-Hashemian
18! **************************************************************************************************
20 USE iso_c_binding, ONLY: c_associated,&
21 c_bool,&
22 c_double,&
23 c_f_procpointer,&
24 c_int,&
25 c_loc,&
26 c_null_ptr,&
27 c_ptr
30 USE bibliography, ONLY: bruck2014,&
31 cite_reference
37 USE cp_output_handling, ONLY: cp_p_file,&
42 USE dbcsr_api, ONLY: &
43 dbcsr_convert_csr_to_dbcsr, dbcsr_convert_dbcsr_to_csr, dbcsr_copy, &
44 dbcsr_copy_into_existing, dbcsr_create, dbcsr_csr_create, dbcsr_csr_create_from_dbcsr, &
45 dbcsr_csr_dbcsr_blkrow_dist, dbcsr_csr_print_sparsity, dbcsr_csr_type, &
46 dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_has_symmetry, dbcsr_set, dbcsr_type, &
47 dbcsr_type_no_symmetry, dbcsr_type_real_8
53 USE kinds, ONLY: dp
57 USE physcon, ONLY: boltzmann,&
58 e_charge,&
59 evolt,&
60 h_bar
61 USE pw_env_types, ONLY: pw_env_get,&
63 USE pw_methods, ONLY: pw_zero
65 USE pw_types, ONLY: pw_c1d_gs_type,&
70 USE qs_kind_types, ONLY: get_qs_kind,&
75 USE qs_rho_types, ONLY: qs_rho_get,&
84#include "./base/base_uses.f90"
85
86 IMPLICIT NONE
87
88 PRIVATE
89
90 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'transport'
91
93 PUBLIC :: qs_scf_post_transport
94
95!> interface between C/C++ and FORTRAN
96 INTERFACE c_func_interface
97! **************************************************************************************************
98!> \brief C routine that takes the S and H matrices as input and outputs a P matrix
99!> \param cp2k_transport_params transport parameters read form a CP2K input file
100!> \param s_mat C-interoperable overlap matrix
101!> \param ks_mat C-interoperable Kohn-Sham matrix
102!> \param p_mat C-interoperable density matrix
103!> \param imagp_mat C-interoperable imaginary density matrix
104!> \author Mohammad Hossein Bani-Hashemian
105! **************************************************************************************************
106 SUBROUTINE c_scf_routine(cp2k_transport_params, s_mat, ks_mat, p_mat, imagp_mat) BIND(C)
107 IMPORT :: c_int, c_ptr, cp2k_csr_interop_type, cp2k_transport_parameters
108 IMPLICIT NONE
109 TYPE(cp2k_transport_parameters), VALUE, INTENT(IN) :: cp2k_transport_params
110 TYPE(cp2k_csr_interop_type), VALUE, INTENT(IN) :: s_mat
111 TYPE(cp2k_csr_interop_type), VALUE, INTENT(IN) :: ks_mat
112 TYPE(cp2k_csr_interop_type), INTENT(INOUT) :: p_mat
113 TYPE(cp2k_csr_interop_type), INTENT(INOUT) :: imagp_mat
114 END SUBROUTINE c_scf_routine
115 END INTERFACE c_func_interface
116
117CONTAINS
118
119! **************************************************************************************************
120!> \brief creates the transport environment
121!> \param[inout] qs_env the qs_env containing the transport_env
122!> \author Mohammad Hossein Bani-Hashemian
123! **************************************************************************************************
124 SUBROUTINE transport_env_create(qs_env)
125 TYPE(qs_environment_type), POINTER :: qs_env
126
127 CHARACTER(LEN=*), PARAMETER :: routinen = 'transport_env_create'
128
129 INTEGER :: handle
130 TYPE(dft_control_type), POINTER :: dft_control
131 TYPE(section_vals_type), POINTER :: input
132 TYPE(transport_env_type), POINTER :: transport_env
133
134 CALL timeset(routinen, handle)
135
136 CALL get_qs_env(qs_env, &
137 transport_env=transport_env, &
138 dft_control=dft_control, &
139 input=input)
140
141 cpassert(.NOT. ASSOCIATED(transport_env))
142
143 ALLOCATE (transport_env)
144
145 CALL transport_init_read_input(input, transport_env)
146 CALL transport_set_contact_params(qs_env, transport_env)
147
148 CALL set_qs_env(qs_env, transport_env=transport_env)
149
150 CALL timestop(handle)
151
152 END SUBROUTINE transport_env_create
153
154! **************************************************************************************************
155!> \brief intitializes all fields of transport_env using the parameters read from
156!> the corresponding input section
157!> \param[inout] input the input file
158!> \param[inout] transport_env the transport_env to be initialized
159!> \author Mohammad Hossein Bani-Hashemian
160! **************************************************************************************************
161 SUBROUTINE transport_init_read_input(input, transport_env)
162 TYPE(section_vals_type), POINTER :: input
163 TYPE(transport_env_type), INTENT(INOUT) :: transport_env
164
165 CHARACTER(len=*), PARAMETER :: routinen = 'transport_init_read_input'
166
167 INTEGER :: contact_bandwidth, contact_injsign, &
168 contact_natoms, contact_start, handle, &
169 i, n_contacts, stride_contacts
170 INTEGER, DIMENSION(:), POINTER :: i_vals
171 LOGICAL :: contact_explicit, injecting_contact, &
172 obc_equilibrium, one_circle
173 TYPE(section_vals_type), POINTER :: beyn_section, contact_section, &
174 pexsi_section, transport_section
175
176 CALL timeset(routinen, handle)
177
178 transport_section => section_vals_get_subs_vals(input, "DFT%TRANSPORT")
179 contact_section => section_vals_get_subs_vals(transport_section, "CONTACT")
180 beyn_section => section_vals_get_subs_vals(transport_section, "BEYN")
181 pexsi_section => section_vals_get_subs_vals(transport_section, "PEXSI")
182 CALL section_vals_get(contact_section, explicit=contact_explicit, n_repetition=n_contacts)
183
184 NULLIFY (i_vals)
185! read from input
186 CALL section_vals_val_get(transport_section, "TRANSPORT_METHOD", i_val=transport_env%params%method)
187 CALL section_vals_val_get(transport_section, "INJECTION_METHOD", i_val=transport_env%params%injection_method)
188 CALL section_vals_val_get(transport_section, "REAL_AXIS_INTEGRATION_METHOD", &
189 i_val=transport_env%params%rlaxis_integration_method)
190 CALL section_vals_val_get(transport_section, "QT_FORMALISM", i_val=transport_env%params%qt_formalism)
191 CALL section_vals_val_get(transport_section, "LINEAR_SOLVER", i_val=transport_env%params%linear_solver)
192 CALL section_vals_val_get(transport_section, "MATRIX_INVERSION_METHOD", &
193 i_val=transport_env%params%matrixinv_method)
194 CALL section_vals_val_get(transport_section, "CONTACT_FILLING", i_val=transport_env%params%transport_neutral)
195 CALL section_vals_val_get(transport_section, "N_KPOINTS", i_val=transport_env%params%n_kpoint)
196 CALL section_vals_val_get(transport_section, "NUM_INTERVAL", i_val=transport_env%params%num_interval)
197 CALL section_vals_val_get(transport_section, "TASKS_PER_ENERGY_POINT", &
198 i_val=transport_env%params%tasks_per_energy_point)
199 CALL section_vals_val_get(transport_section, "TASKS_PER_POLE", i_val=transport_env%params%tasks_per_pole)
200 CALL section_vals_val_get(transport_section, "NUM_POLE", i_val=transport_env%params%num_pole)
201 CALL section_vals_val_get(transport_section, "GPUS_PER_POINT", i_val=transport_env%params%gpus_per_point)
202 CALL section_vals_val_get(transport_section, "N_POINTS_INV", i_val=transport_env%params%n_points_inv)
203 CALL section_vals_val_get(transport_section, "COLZERO_THRESHOLD", r_val=transport_env%params%colzero_threshold)
204 CALL section_vals_val_get(transport_section, "EPS_LIMIT", r_val=transport_env%params%eps_limit)
205 CALL section_vals_val_get(transport_section, "EPS_LIMIT_CC", r_val=transport_env%params%eps_limit_cc)
206 CALL section_vals_val_get(transport_section, "EPS_DECAY", r_val=transport_env%params%eps_decay)
207 CALL section_vals_val_get(transport_section, "EPS_SINGULARITY_CURVATURES", &
208 r_val=transport_env%params%eps_singularity_curvatures)
209 CALL section_vals_val_get(transport_section, "EPS_MU", r_val=transport_env%params%eps_mu)
210 CALL section_vals_val_get(transport_section, "EPS_EIGVAL_DEGEN", r_val=transport_env%params%eps_eigval_degen)
211 CALL section_vals_val_get(transport_section, "EPS_FERMI", r_val=transport_env%params%eps_fermi)
212 CALL section_vals_val_get(transport_section, "ENERGY_INTERVAL", r_val=transport_env%params%energy_interval)
213 CALL section_vals_val_get(transport_section, "MIN_INTERVAL", r_val=transport_env%params%min_interval)
214 CALL section_vals_val_get(transport_section, "TEMPERATURE", r_val=transport_env%params%temperature)
215 CALL section_vals_val_get(transport_section, "DENSITY_MIXING", r_val=transport_env%params%dens_mixing)
216 CALL section_vals_val_get(transport_section, "CSR_SCREENING", l_val=transport_env%csr_screening)
217
218 ! logical*1 to logical*4 , l_val is logical*1 and c_bool is equivalent to logical*4
219 CALL section_vals_val_get(transport_section, "OBC_EQUILIBRIUM", l_val=obc_equilibrium)
220 IF (obc_equilibrium) THEN
221 transport_env%params%obc_equilibrium = .true.
222 ELSE
223 transport_env%params%obc_equilibrium = .false.
224 END IF
225
226 CALL section_vals_val_get(transport_section, "CUTOUT", i_vals=i_vals)
227 transport_env%params%cutout = i_vals
228
229 CALL section_vals_val_get(beyn_section, "TASKS_PER_INTEGRATION_POINT", &
230 i_val=transport_env%params%tasks_per_integration_point)
231 CALL section_vals_val_get(beyn_section, "N_POINTS_BEYN", i_val=transport_env%params%n_points_beyn)
232 CALL section_vals_val_get(beyn_section, "N_RAND", r_val=transport_env%params%n_rand_beyn)
233 CALL section_vals_val_get(beyn_section, "N_RAND_CC", r_val=transport_env%params%n_rand_cc_beyn)
234 CALL section_vals_val_get(beyn_section, "SVD_CUTOFF", r_val=transport_env%params%svd_cutoff)
235 CALL section_vals_val_get(beyn_section, "ONE_CIRCLE", l_val=one_circle)
236 IF (one_circle) THEN
237 transport_env%params%ncrc_beyn = 1
238 ELSE
239 transport_env%params%ncrc_beyn = 2
240 END IF
241
242 CALL section_vals_val_get(pexsi_section, "ORDERING", i_val=transport_env%params%ordering)
243 CALL section_vals_val_get(pexsi_section, "ROW_ORDERING", i_val=transport_env%params%row_ordering)
244 CALL section_vals_val_get(pexsi_section, "VERBOSITY", i_val=transport_env%params%verbosity)
245 CALL section_vals_val_get(pexsi_section, "NP_SYMB_FACT", i_val=transport_env%params%pexsi_np_symb_fact)
246
247 IF (contact_explicit) THEN
248 transport_env%params%num_contacts = n_contacts
249 stride_contacts = 5
250 transport_env%params%stride_contacts = stride_contacts
251 ALLOCATE (transport_env%contacts_data(stride_contacts*n_contacts))
252
253 DO i = 1, n_contacts
254 CALL section_vals_val_get(contact_section, "BANDWIDTH", i_rep_section=i, i_val=contact_bandwidth)
255 CALL section_vals_val_get(contact_section, "START", i_rep_section=i, i_val=contact_start)
256 CALL section_vals_val_get(contact_section, "N_ATOMS", i_rep_section=i, i_val=contact_natoms)
257 CALL section_vals_val_get(contact_section, "INJECTION_SIGN", i_rep_section=i, i_val=contact_injsign)
258 CALL section_vals_val_get(contact_section, "INJECTING_CONTACT", i_rep_section=i, l_val=injecting_contact)
259
260 IF (contact_natoms .LE. 0) cpabort("Number of atoms in contact region needs to be defined.")
261
262 transport_env%contacts_data((i - 1)*stride_contacts + 1) = contact_bandwidth
263 transport_env%contacts_data((i - 1)*stride_contacts + 2) = contact_start - 1 ! C indexing
264 transport_env%contacts_data((i - 1)*stride_contacts + 3) = contact_natoms
265 transport_env%contacts_data((i - 1)*stride_contacts + 4) = contact_injsign
266
267 IF (injecting_contact) THEN
268 transport_env%contacts_data((i - 1)*stride_contacts + 5) = 1
269 ELSE
270 transport_env%contacts_data((i - 1)*stride_contacts + 5) = 0
271 END IF
272 END DO
273 transport_env%params%contacts_data = c_loc(transport_env%contacts_data(1))
274 ELSE
275 cpabort("No contact region is defined.")
276 END IF
277
278 CALL timestop(handle)
279
280 END SUBROUTINE transport_init_read_input
281
282! **************************************************************************************************
283!> \brief initializes the transport environment
284!> \param ks_env ...
285!> \param[inout] transport_env the transport env to be initialized
286!> \param[in] template_matrix template matrix to keep the sparsity of matrices fixed
287!> \author Mohammad Hossein Bani-Hashemian
288! **************************************************************************************************
289 SUBROUTINE transport_initialize(ks_env, transport_env, template_matrix)
290 TYPE(qs_ks_env_type), POINTER :: ks_env
291 TYPE(transport_env_type), INTENT(INOUT) :: transport_env
292 TYPE(dbcsr_type), INTENT(IN) :: template_matrix
293
294 CHARACTER(len=*), PARAMETER :: routinen = 'transport_initialize'
295
296 INTEGER :: handle, numnodes, unit_nr
297 TYPE(cp_logger_type), POINTER :: logger
298
299 CALL timeset(routinen, handle)
300
301 CALL cite_reference(bruck2014)
302
303 logger => cp_get_default_logger()
304 IF (logger%para_env%is_source()) THEN
305 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
306 ELSE
307 unit_nr = -1
308 END IF
309
310 numnodes = logger%para_env%num_pe
311
312 IF (dbcsr_has_symmetry(template_matrix)) THEN
313 CALL dbcsr_copy(transport_env%template_matrix_sym, template_matrix)
314 CALL dbcsr_desymmetrize(transport_env%template_matrix_sym, transport_env%template_matrix_nosym)
315 ELSE
316 CALL dbcsr_copy(transport_env%template_matrix_nosym, template_matrix)
317 CALL dbcsr_copy(transport_env%template_matrix_sym, template_matrix)
318 END IF
319
320 ALLOCATE (transport_env%dm_imag)
321 CALL dbcsr_create(transport_env%dm_imag, "imaginary DM", &
322 template=template_matrix, matrix_type=dbcsr_type_no_symmetry)
323 CALL dbcsr_set(transport_env%dm_imag, 0.0_dp)
324
325 CALL dbcsr_create(transport_env%csr_sparsity, "CSR sparsity", &
326 template=transport_env%template_matrix_sym, &
327 data_type=dbcsr_type_real_8)
328 CALL dbcsr_copy(transport_env%csr_sparsity, transport_env%template_matrix_sym)
329
330 CALL cp_dbcsr_to_csr_screening(ks_env, transport_env%csr_sparsity)
331
332 IF (.NOT. transport_env%csr_screening) CALL dbcsr_set(transport_env%csr_sparsity, 1.0)
333 CALL dbcsr_csr_create_from_dbcsr(transport_env%template_matrix_nosym, &
334 transport_env%s_matrix, &
335 dbcsr_csr_dbcsr_blkrow_dist, &
336 csr_sparsity=transport_env%csr_sparsity, &
337 numnodes=numnodes)
338
339 CALL dbcsr_csr_print_sparsity(transport_env%s_matrix, unit_nr)
340
341 CALL dbcsr_convert_dbcsr_to_csr(transport_env%template_matrix_nosym, transport_env%s_matrix)
342
343 CALL dbcsr_csr_create(transport_env%ks_matrix, transport_env%s_matrix)
344 CALL dbcsr_csr_create(transport_env%p_matrix, transport_env%s_matrix)
345 CALL dbcsr_csr_create(transport_env%imagp_matrix, transport_env%s_matrix)
346
347 CALL timestop(handle)
348
349 END SUBROUTINE transport_initialize
350
351! **************************************************************************************************
352!> \brief SCF calcualtion with an externally evaluated density matrix
353!> \param[inout] transport_env transport environment
354!> \param[in] matrix_s DBCSR overlap matrix
355!> \param[in] matrix_ks DBCSR Kohn-Sham matrix
356!> \param[inout] matrix_p DBCSR density matrix
357!> \param[in] nelectron_spin number of electrons
358!> \param[in] natoms number of atoms
359!> \param[in] energy_diff scf energy difference
360!> \param[in] iscf the current scf iteration
361!> \param[in] extra_scf whether or not an extra scf step will be performed
362!> \par History
363!> 12.2012 created [Hossein Bani-Hashemian]
364!> 12.2014 revised [Hossein Bani-Hashemian]
365!> \author Mohammad Hossein Bani-Hashemian
366! **************************************************************************************************
367 SUBROUTINE external_scf_method(transport_env, matrix_s, matrix_ks, matrix_p, &
368 nelectron_spin, natoms, energy_diff, iscf, extra_scf)
369
370 TYPE(transport_env_type), INTENT(INOUT) :: transport_env
371 TYPE(dbcsr_type), INTENT(IN) :: matrix_s, matrix_ks
372 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
373 INTEGER, INTENT(IN) :: nelectron_spin, natoms
374 REAL(dp), INTENT(IN) :: energy_diff
375 INTEGER, INTENT(IN) :: iscf
376 LOGICAL, INTENT(IN) :: extra_scf
377
378 CHARACTER(len=*), PARAMETER :: routinen = 'external_scf_method'
379
380 TYPE(cp2k_csr_interop_type) :: imagp_mat, ks_mat, p_mat, s_mat
381
382 PROCEDURE(c_scf_routine), POINTER :: c_method
383 INTEGER :: handle
384
385 CALL timeset(routinen, handle)
386
387 CALL c_f_procpointer(transport_env%ext_c_method_ptr, c_method)
388 IF (.NOT. c_associated(transport_env%ext_c_method_ptr)) &
389 CALL cp_abort(__location__, &
390 "MISSING C/C++ ROUTINE: The TRANSPORT section is meant to be used together with an external "// &
391 "program, e.g. the quantum transport code OMEN, that provides CP2K with a density matrix.")
392
393 transport_env%params%n_occ = nelectron_spin
394 transport_env%params%n_atoms = natoms
395 transport_env%params%energy_diff = energy_diff
396 transport_env%params%evoltfactor = evolt
397 transport_env%params%e_charge = e_charge
398 transport_env%params%boltzmann = boltzmann
399 transport_env%params%h_bar = h_bar
400 transport_env%params%iscf = iscf
401 transport_env%params%extra_scf = LOGICAL(extra_scf, C_BOOL) ! C_BOOL and Fortran logical don't have the same size
402
403 CALL csr_interop_nullify(s_mat)
404 CALL csr_interop_nullify(ks_mat)
405 CALL csr_interop_nullify(p_mat)
406 CALL csr_interop_nullify(imagp_mat)
407
408 CALL dbcsr_copy_into_existing(transport_env%template_matrix_sym, matrix_s)
409 CALL convert_dbcsr_to_csr_interop(transport_env%template_matrix_sym, transport_env%s_matrix, s_mat)
410
411 CALL dbcsr_copy_into_existing(transport_env%template_matrix_sym, matrix_ks)
412 CALL convert_dbcsr_to_csr_interop(transport_env%template_matrix_sym, transport_env%ks_matrix, ks_mat)
413
414 CALL dbcsr_copy_into_existing(transport_env%template_matrix_sym, matrix_p)
415 CALL convert_dbcsr_to_csr_interop(transport_env%template_matrix_sym, transport_env%p_matrix, p_mat)
416
417 CALL dbcsr_copy_into_existing(transport_env%template_matrix_sym, matrix_s)
418 CALL convert_dbcsr_to_csr_interop(transport_env%template_matrix_sym, transport_env%imagp_matrix, imagp_mat)
419
420 CALL c_method(transport_env%params, s_mat, ks_mat, p_mat, imagp_mat)
421
422 CALL convert_csr_interop_to_dbcsr(p_mat, transport_env%p_matrix, transport_env%template_matrix_nosym)
423 CALL dbcsr_copy(matrix_p, transport_env%template_matrix_nosym)
424
425 CALL convert_csr_interop_to_dbcsr(imagp_mat, transport_env%imagp_matrix, transport_env%template_matrix_nosym)
426 CALL dbcsr_copy(transport_env%dm_imag, transport_env%template_matrix_nosym)
427
428 CALL timestop(handle)
429
430 END SUBROUTINE external_scf_method
431
432! **************************************************************************************************
433!> \brief converts a DBCSR matrix to a C-interoperable CSR matrix
434!> \param[in] dbcsr_mat DBCSR matrix to be converted
435!> \param[inout] csr_mat auxiliary CSR matrix
436!> \param[inout] csr_interop_mat C-interoperable CSR matrix
437!> \author Mohammad Hossein Bani-Hashemian
438! **************************************************************************************************
439 SUBROUTINE convert_dbcsr_to_csr_interop(dbcsr_mat, csr_mat, csr_interop_mat)
440
441 TYPE(dbcsr_type), INTENT(IN) :: dbcsr_mat
442 TYPE(dbcsr_csr_type), INTENT(INOUT) :: csr_mat
443 TYPE(cp2k_csr_interop_type), INTENT(INOUT) :: csr_interop_mat
444
445 CHARACTER(LEN=*), PARAMETER :: routinen = 'convert_dbcsr_to_csr_interop'
446
447 INTEGER :: handle
448 INTEGER, ALLOCATABLE, DIMENSION(:) :: nrows_local_all, first_row_all
449 INTEGER(C_INT), DIMENSION(:), POINTER :: colind_local, rowptr_local, nzerow_local
450 REAL(c_double), DIMENSION(:), POINTER :: nzvals_local
451 TYPE(cp_logger_type), POINTER :: logger
452
453 CALL timeset(routinen, handle)
454
455 logger => cp_get_default_logger()
456
457! dbcsr to csr
458 CALL dbcsr_convert_dbcsr_to_csr(dbcsr_mat, csr_mat)
459
460! csr to csr_interop
461 rowptr_local => csr_mat%rowptr_local
462 colind_local => csr_mat%colind_local
463 nzerow_local => csr_mat%nzerow_local
464 nzvals_local => csr_mat%nzval_local%r_dp ! support real double percision for now
465
466 IF (SIZE(rowptr_local) .EQ. 0) THEN
467 csr_interop_mat%rowptr_local = c_null_ptr
468 ELSE
469 csr_interop_mat%rowptr_local = c_loc(rowptr_local(1))
470 END IF
471
472 IF (SIZE(colind_local) .EQ. 0) THEN
473 csr_interop_mat%colind_local = c_null_ptr
474 ELSE
475 csr_interop_mat%colind_local = c_loc(colind_local(1))
476 END IF
477
478 IF (SIZE(nzerow_local) .EQ. 0) THEN
479 csr_interop_mat%nzerow_local = c_null_ptr
480 ELSE
481 csr_interop_mat%nzerow_local = c_loc(nzerow_local(1))
482 END IF
483
484 IF (SIZE(nzvals_local) .EQ. 0) THEN
485 csr_interop_mat%nzvals_local = c_null_ptr
486 ELSE
487 csr_interop_mat%nzvals_local = c_loc(nzvals_local(1))
488 END IF
489
490 associate(mp_group => logger%para_env, mepos => logger%para_env%mepos, num_pe => logger%para_env%num_pe)
491 ALLOCATE (nrows_local_all(0:num_pe - 1), first_row_all(0:num_pe - 1))
492 CALL mp_group%allgather(csr_mat%nrows_local, nrows_local_all)
493 CALL cumsum_i(nrows_local_all, first_row_all)
494
495 IF (mepos .EQ. 0) THEN
496 csr_interop_mat%first_row = 0
497 ELSE
498 csr_interop_mat%first_row = first_row_all(mepos - 1)
499 END IF
500 END associate
501 csr_interop_mat%nrows_total = csr_mat%nrows_total
502 csr_interop_mat%ncols_total = csr_mat%ncols_total
503 csr_interop_mat%nze_local = csr_mat%nze_local
504 IF (csr_mat%nze_total > huge(csr_interop_mat%nze_total)) THEN
505 cpabort("overflow in nze")
506 END IF
507 csr_interop_mat%nze_total = int(csr_mat%nze_total, kind=kind(csr_interop_mat%nze_total))
508 csr_interop_mat%nrows_local = csr_mat%nrows_local
509 csr_interop_mat%data_type = csr_mat%nzval_local%data_type
510
511 CALL timestop(handle)
512
513 CONTAINS
514! **************************************************************************************************
515!> \brief cumulative sum of a 1d array of integers
516!> \param[in] arr input array
517!> \param[out] cumsum cumulative sum of the input array
518! **************************************************************************************************
519 SUBROUTINE cumsum_i(arr, cumsum)
520 INTEGER, DIMENSION(:), INTENT(IN) :: arr
521 INTEGER, DIMENSION(SIZE(arr)), INTENT(OUT) :: cumsum
522
523 INTEGER :: i
524
525 cumsum(1) = arr(1)
526 DO i = 2, SIZE(arr)
527 cumsum(i) = cumsum(i - 1) + arr(i)
528 END DO
529 END SUBROUTINE cumsum_i
530
531 END SUBROUTINE convert_dbcsr_to_csr_interop
532
533! **************************************************************************************************
534!> \brief converts a C-interoperable CSR matrix to a DBCSR matrix
535!> \param[in] csr_interop_mat C-interoperable CSR matrix
536!> \param[inout] csr_mat auxiliary CSR matrix
537!> \param[inout] dbcsr_mat DBCSR matrix
538!> \author Mohammad Hossein Bani-Hashemian
539! **************************************************************************************************
540 SUBROUTINE convert_csr_interop_to_dbcsr(csr_interop_mat, csr_mat, dbcsr_mat)
541
542 TYPE(cp2k_csr_interop_type), INTENT(IN) :: csr_interop_mat
543 TYPE(dbcsr_csr_type), INTENT(INOUT) :: csr_mat
544 TYPE(dbcsr_type), INTENT(INOUT) :: dbcsr_mat
545
546 CHARACTER(LEN=*), PARAMETER :: routinen = 'convert_csr_interop_to_dbcsr'
547
548 INTEGER :: data_type, handle, ncols_total, &
549 nrows_local, nrows_total, nze_local, &
550 nze_total
551 INTEGER, DIMENSION(:), POINTER :: colind_local, nzerow_local, rowptr_local
552 REAL(dp), DIMENSION(:), POINTER :: nzvals_local
553
554 CALL timeset(routinen, handle)
555
556! csr_interop to csr
557 CALL csr_interop_matrix_get_info(csr_interop_mat, &
558 nrows_total=nrows_total, ncols_total=ncols_total, nze_local=nze_local, &
559 nze_total=nze_total, nrows_local=nrows_local, data_type=data_type, &
560 rowptr_local=rowptr_local, colind_local=colind_local, &
561 nzerow_local=nzerow_local, nzvals_local=nzvals_local)
562
563 csr_mat%nrows_total = nrows_total
564 csr_mat%ncols_total = ncols_total
565 csr_mat%nze_local = nze_local
566 csr_mat%nze_total = nze_total
567 csr_mat%nrows_local = nrows_local
568 csr_mat%nzval_local%data_type = data_type
569
570 csr_mat%rowptr_local = rowptr_local
571 csr_mat%colind_local = colind_local
572 csr_mat%nzerow_local = nzerow_local
573 csr_mat%nzval_local%r_dp = nzvals_local
574
575! csr to dbcsr
576 CALL dbcsr_convert_csr_to_dbcsr(dbcsr_mat, csr_mat)
577
578 CALL timestop(handle)
579
580 END SUBROUTINE convert_csr_interop_to_dbcsr
581
582! **************************************************************************************************
583!> \brief extraxts zeff (effective nuclear charges per atom) and nsgf (the size
584!> of spherical Gaussian basis functions per atom) from qs_env and initializes
585!> the corresponding arrays in transport_env%params
586!> \param[in] qs_env qs environment
587!> \param[inout] transport_env transport environment
588!> \author Mohammad Hossein Bani-Hashemian
589! **************************************************************************************************
590 SUBROUTINE transport_set_contact_params(qs_env, transport_env)
591 TYPE(qs_environment_type), POINTER :: qs_env
592 TYPE(transport_env_type), INTENT(INOUT) :: transport_env
593
594 INTEGER :: i, iat, ikind, natom, nkind
595 INTEGER, DIMENSION(:), POINTER :: atom_list
596 REAL(kind=dp) :: zeff
597 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
598 TYPE(atomic_kind_type), POINTER :: atomic_kind
599 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
600 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
601
602 CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
603 CALL get_qs_env(qs_env, particle_set=particle_set, &
604 qs_kind_set=qs_kind_set, &
605 atomic_kind_set=atomic_kind_set)
606
607 ALLOCATE (transport_env%nsgf(natom))
608 ALLOCATE (transport_env%zeff(natom))
609 CALL get_particle_set(particle_set, qs_kind_set, nsgf=transport_env%nsgf)
610
611 ! reference charges
612 DO ikind = 1, nkind
613 CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
614 atomic_kind => atomic_kind_set(ikind)
615 CALL get_atomic_kind(atomic_kind, atom_list=atom_list)
616 DO iat = 1, SIZE(atom_list)
617 i = atom_list(iat)
618 transport_env%zeff(i) = zeff
619 END DO
620 END DO
621
622 IF (natom .EQ. 0) THEN
623 transport_env%params%nsgf = c_null_ptr
624 transport_env%params%zeff = c_null_ptr
625 ELSE
626 transport_env%params%nsgf = c_loc(transport_env%nsgf(1))
627 transport_env%params%zeff = c_loc(transport_env%zeff(1))
628 END IF
629
630 END SUBROUTINE transport_set_contact_params
631
632!**************************************************************************************************
633!> \brief evaluates current density using the imaginary part of the density matrix and prints it
634!> into cube files
635!> \param[in] input the input
636!> \param[in] qs_env qs environment
637!> \author Mohammad Hossein Bani-Hashemian
638! **************************************************************************************************
639 SUBROUTINE transport_current(input, qs_env)
640 TYPE(section_vals_type), POINTER :: input
641 TYPE(qs_environment_type), POINTER :: qs_env
642
643 CHARACTER(len=*), PARAMETER :: routinen = 'transport_current'
644
645 CHARACTER(len=14) :: ext
646 CHARACTER(len=2) :: sdir
647 INTEGER :: dir, handle, unit_nr
648 LOGICAL :: do_current_cube, do_transport, mpi_io
649 TYPE(cp_logger_type), POINTER :: logger
650 TYPE(current_env_type) :: current_env
651 TYPE(dbcsr_type), POINTER :: zero
652 TYPE(dft_control_type), POINTER :: dft_control
653 TYPE(particle_list_type), POINTER :: particles
654 TYPE(pw_c1d_gs_type) :: gs
655 TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
656 TYPE(pw_env_type), POINTER :: pw_env
657 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
658 TYPE(pw_r3d_rs_type) :: rs
659 TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
660 TYPE(qs_rho_type), POINTER :: rho
661 TYPE(qs_subsys_type), POINTER :: subsys
662 TYPE(section_vals_type), POINTER :: dft_section
663 TYPE(transport_env_type), POINTER :: transport_env
664
665 CALL timeset(routinen, handle)
666
667 logger => cp_get_default_logger()
668 dft_section => section_vals_get_subs_vals(input, "DFT")
669 CALL get_qs_env(qs_env=qs_env, &
670 subsys=subsys, &
671 pw_env=pw_env, &
672 transport_env=transport_env, &
673 do_transport=do_transport, &
674 dft_control=dft_control, &
675 rho=rho)
676 CALL qs_subsys_get(subsys, particles=particles)
677 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
678 CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
679
680 do_current_cube = btest(cp_print_key_should_output(logger%iter_info, input, &
681 "DFT%TRANSPORT%PRINT%CURRENT"), cp_p_file)
682
683 ! check if transport is active i.e. the imaginary dm has been actually passed to cp2k by the external code
684 IF (do_transport) THEN
685 IF (c_associated(transport_env%ext_c_method_ptr)) THEN
686
687 ! calculate_jrho_resp uses sab_all which is not associated in DFTB environment
688 IF (dft_control%qs_control%dftb) cpabort("Current is not available for DFTB.")
689 IF (dft_control%qs_control%xtb) cpabort("Current is not available for xTB.")
690
691 ! now do the current
692 IF (do_current_cube) THEN
693 current_env%gauge = -1
694 current_env%gauge_init = .false.
695
696 CALL auxbas_pw_pool%create_pw(rs)
697 CALL auxbas_pw_pool%create_pw(gs)
698
699 NULLIFY (zero)
700 ALLOCATE (zero)
701 CALL dbcsr_create(zero, template=transport_env%dm_imag)
702 CALL dbcsr_copy(zero, transport_env%dm_imag)
703 CALL dbcsr_set(zero, 0.0_dp)
704
705 DO dir = 1, 3
706 CALL pw_zero(rs)
707 CALL pw_zero(gs)
708 CALL calculate_jrho_resp(zero, transport_env%dm_imag, &
709 zero, zero, dir, dir, rs, gs, qs_env, current_env, &
710 retain_rsgrid=.true.)
711 SELECT CASE (dir)
712 CASE (1)
713 sdir = "-x"
714 CASE (2)
715 sdir = "-y"
716 CASE (3)
717 sdir = "-z"
718 END SELECT
719 ext = sdir//".cube"
720 mpi_io = .true.
721 unit_nr = cp_print_key_unit_nr(logger, dft_section, "TRANSPORT%PRINT%CURRENT", &
722 extension=ext, file_status="REPLACE", file_action="WRITE", &
723 log_filename=.false., mpi_io=mpi_io)
724 CALL cp_pw_to_cube(rs, unit_nr, "Transport current", particles=particles, &
725 stride=section_get_ivals(dft_section, "TRANSPORT%PRINT%CURRENT%STRIDE"), &
726 mpi_io=mpi_io)
727 CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "TRANSPORT%PRINT%CURRENT", &
728 mpi_io=mpi_io)
729 END DO
730
731 CALL dbcsr_deallocate_matrix(zero)
732 CALL auxbas_pw_pool%give_back_pw(rs)
733 CALL auxbas_pw_pool%give_back_pw(gs)
734 END IF
735 END IF
736
737 END IF
738
739 CALL timestop(handle)
740
741 END SUBROUTINE transport_current
742
743!**************************************************************************************************
744!> \brief post scf calculations for transport
745!> \param[in] qs_env qs environment
746!> \author Mohammad Hossein Bani-Hashemian
747! **************************************************************************************************
748 SUBROUTINE qs_scf_post_transport(qs_env)
749 TYPE(qs_environment_type), POINTER :: qs_env
750
751 CHARACTER(len=*), PARAMETER :: routinen = 'qs_scf_post_transport'
752
753 INTEGER :: handle
754 TYPE(section_vals_type), POINTER :: input
755
756 CALL timeset(routinen, handle)
757
758 NULLIFY (input)
759
760 CALL get_qs_env(qs_env=qs_env, &
761 input=input)
762
763 CALL transport_current(input, qs_env)
764
765 CALL timestop(handle)
766
767 END SUBROUTINE qs_scf_post_transport
768
769END MODULE transport
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public bruck2014
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
A wrapper around pw_to_cube() which accepts particle_list_type.
subroutine, public cp_pw_to_cube(pw, unit_nr, title, particles, stride, zero_tails, silent, mpi_io)
...
objects that represent the structure of input sections and the data contained in an input section
integer function, dimension(:), pointer, public section_get_ivals(section_vals, keyword_name)
...
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
represent a simple array based list of the given type
Define methods related to particle_type.
subroutine, public get_particle_set(particle_set, qs_kind_set, first_sgf, last_sgf, nsgf, nmao, basis)
Get the components of a particle set.
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public boltzmann
Definition physcon.F:129
real(kind=dp), parameter, public e_charge
Definition physcon.F:106
real(kind=dp), parameter, public h_bar
Definition physcon.F:103
real(kind=dp), parameter, public evolt
Definition physcon.F:183
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
subroutine, public set_qs_env(qs_env, super_cell, mos, qmmm, qmmm_periodic, ewald_env, ewald_pw, mpools, rho_external, external_vxc, mask, scf_control, rel_control, qs_charges, ks_env, ks_qmmm_env, wf_history, scf_env, active_space, input, oce, rho_atom_set, rho0_atom_set, rho0_mpole, run_rtp, rtp, rhoz_set, rhoz_tot, ecoul_1c, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, efield, linres_control, xas_env, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, ls_scf_env, do_transport, transport_env, lri_env, lri_density, exstate_env, ec_env, dispersion_env, gcp_env, mp2_env, bs_env, kg_env, force, kpoints, wanniercentres, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, rhs)
Set the QUICKSTEP environment.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, rhs)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_r3d_rs_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, init_u_ramping_each_scf, reltmat, ghost, floating, name, element_symbol, pao_basis_size, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
given the response wavefunctions obtained by the application of the (rxp), p, and ((dk-dl)xp) operato...
subroutine, public calculate_jrho_resp(mat_d0, mat_jp, mat_jp_rii, mat_jp_riii, ib, idir, current_rs, current_gs, qs_env, current_env, soft_valid, retain_rsgrid)
Calculation of the idir component of the response current density in the presence of a constant magne...
Type definitiona for linear response calculations.
superstucture that hold various representations of the density and keeps track of which ones are vali...
subroutine, public qs_rho_get(rho_struct, rho_ao, rho_ao_im, rho_ao_kp, rho_ao_im_kp, rho_r, drho_r, rho_g, drho_g, tau_r, tau_g, rho_r_valid, drho_r_valid, rho_g_valid, drho_g_valid, tau_r_valid, tau_g_valid, tot_rho_r, tot_rho_g, rho_r_sccs, soft_valid, complex_rho_ao)
returns info about the density described by this object. If some representation is not available an e...
types that represent a quickstep subsys
subroutine, public qs_subsys_get(subsys, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell, energy, force, qs_kind_set, cp_subsys, nelectron_total, nelectron_spin)
...
CP2K transport environment and related C-interoperable types.
subroutine, public csr_interop_nullify(csr_interop_mat)
nullifies (and zeroizes) a C-interoperable CSR matrix
subroutine, public csr_interop_matrix_get_info(csr_interop_mat, nrows_total, ncols_total, nze_local, nze_total, nrows_local, data_type, first_row, rowptr_local, colind_local, nzerow_local, nzvals_local)
gets the fields of a C-interoperable CSR matrix
routines for DFT+NEGF calculations (coupling with the quantum transport code OMEN)
Definition transport.F:19
subroutine, public transport_env_create(qs_env)
creates the transport environment
Definition transport.F:125
subroutine, public external_scf_method(transport_env, matrix_s, matrix_ks, matrix_p, nelectron_spin, natoms, energy_diff, iscf, extra_scf)
SCF calcualtion with an externally evaluated density matrix.
Definition transport.F:369
subroutine, public transport_initialize(ks_env, transport_env, template_matrix)
initializes the transport environment
Definition transport.F:290
subroutine, public qs_scf_post_transport(qs_env)
post scf calculations for transport
Definition transport.F:749
Provides all information about an atomic kind.
CP2K's C-interoperable CSR matrix This definition matches the respective type definition in the trans...
Definition libcp2k.h:268
Transport parameters read from a CP2K input file. This definition matches the respective type definit...
Definition libcp2k.h:208
type of a logger, at the moment it contains just a print level starting at which level it should be l...
contained for different pw related things
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Provides all information about a quickstep kind.
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...
keeps the density in various representations, keeping track of which ones are valid.