Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Calculate the KS reference potentials
10 : !> \par History
11 : !> 07.2022 created
12 : !> \author JGH
13 : ! **************************************************************************************************
14 : MODULE qs_ks_reference
15 : USE admm_types, ONLY: admm_type,&
16 : get_admm_env
17 : USE atomic_kind_types, ONLY: atomic_kind_type
18 : USE cp_control_types, ONLY: dft_control_type
19 : USE cp_dbcsr_api, ONLY: dbcsr_p_type
20 : USE hartree_local_methods, ONLY: Vh_1c_gg_integrals,&
21 : init_coulomb_local
22 : USE hartree_local_types, ONLY: hartree_local_create,&
23 : hartree_local_release,&
24 : hartree_local_type
25 : USE input_constants, ONLY: do_admm_aux_exch_func_none
26 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
27 : section_vals_type
28 : USE kinds, ONLY: dp
29 : USE message_passing, ONLY: mp_para_env_type
30 : USE pw_env_types, ONLY: pw_env_get,&
31 : pw_env_type
32 : USE pw_grid_types, ONLY: pw_grid_type
33 : USE pw_methods, ONLY: pw_scale,&
34 : pw_transfer,&
35 : pw_zero
36 : USE pw_poisson_methods, ONLY: pw_poisson_solve
37 : USE pw_poisson_types, ONLY: pw_poisson_type
38 : USE pw_pool_types, ONLY: pw_pool_type
39 : USE pw_types, ONLY: pw_c1d_gs_type,&
40 : pw_r3d_rs_type
41 : USE qs_core_energies, ONLY: calculate_ecore_overlap,&
42 : calculate_ecore_self
43 : USE qs_environment_types, ONLY: get_qs_env,&
44 : qs_environment_type
45 : USE qs_gapw_densities, ONLY: prepare_gapw_den
46 : USE qs_kind_types, ONLY: qs_kind_type
47 : USE qs_ks_methods, ONLY: calc_rho_tot_gspace
48 : USE qs_ks_types, ONLY: qs_ks_env_type
49 : USE qs_local_rho_types, ONLY: local_rho_set_create,&
50 : local_rho_type
51 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
52 : USE qs_oce_types, ONLY: oce_matrix_type
53 : USE qs_rho0_ggrid, ONLY: integrate_vhg0_rspace,&
54 : rho0_s_grid_create
55 : USE qs_rho0_methods, ONLY: init_rho0
56 : USE qs_rho_atom_methods, ONLY: allocate_rho_atom_internals,&
57 : calculate_rho_atom_coeff
58 : USE qs_rho_types, ONLY: qs_rho_get,&
59 : qs_rho_type
60 : USE qs_vxc, ONLY: qs_vxc_create
61 : USE qs_vxc_atom, ONLY: calculate_vxc_atom
62 : USE virial_types, ONLY: virial_type
63 : #include "./base/base_uses.f90"
64 :
65 : IMPLICIT NONE
66 :
67 : PRIVATE
68 :
69 : ! *** Global parameters ***
70 :
71 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_ks_reference'
72 :
73 : PUBLIC :: ks_ref_potential, ks_ref_potential_atom
74 :
75 : ! **************************************************************************************************
76 :
77 : CONTAINS
78 :
79 : ! **************************************************************************************************
80 : !> \brief calculate the Kohn-Sham reference potential
81 : !> \param qs_env ...
82 : !> \param vh_rspace ...
83 : !> \param vxc_rspace ...
84 : !> \param vtau_rspace ...
85 : !> \param vadmm_rspace ...
86 : !> \param ehartree ...
87 : !> \param exc ...
88 : !> \param h_stress container for the stress tensor of the Hartree term
89 : !> \param vadmm_tau_rspace ADMM auxiliary tau potential
90 : !> \par History
91 : !> 10.2019 created [JGH]
92 : !> \author JGH
93 : ! **************************************************************************************************
94 6054 : SUBROUTINE ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, &
95 : ehartree, exc, h_stress, vadmm_tau_rspace)
96 : TYPE(qs_environment_type), POINTER :: qs_env
97 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: vh_rspace
98 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: vxc_rspace, vtau_rspace, vadmm_rspace
99 : REAL(KIND=dp), INTENT(OUT) :: ehartree, exc
100 : REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
101 : OPTIONAL :: h_stress
102 : TYPE(pw_r3d_rs_type), DIMENSION(:), OPTIONAL, &
103 : POINTER :: vadmm_tau_rspace
104 :
105 : CHARACTER(LEN=*), PARAMETER :: routineN = 'ks_ref_potential'
106 :
107 : INTEGER :: handle, iab, ispin, nspins
108 : REAL(dp) :: eadmm, edisp, eovrl, eself
109 : REAL(KIND=dp), DIMENSION(3, 3) :: virial_xc
110 : TYPE(admm_type), POINTER :: admm_env
111 : TYPE(dft_control_type), POINTER :: dft_control
112 : TYPE(mp_para_env_type), POINTER :: para_env
113 : TYPE(pw_c1d_gs_type) :: rho_tot_gspace, v_hartree_gspace
114 : TYPE(pw_c1d_gs_type), POINTER :: rho_core
115 : TYPE(pw_env_type), POINTER :: pw_env
116 : TYPE(pw_grid_type), POINTER :: pw_grid
117 : TYPE(pw_poisson_type), POINTER :: poisson_env
118 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
119 : TYPE(pw_r3d_rs_type) :: v_hartree_rspace
120 2018 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_admm_rspace, v_admm_tau_rspace, &
121 2018 : v_rspace, v_tau_rspace
122 : TYPE(qs_ks_env_type), POINTER :: ks_env
123 : TYPE(qs_rho_type), POINTER :: rho, rho_xc
124 : TYPE(section_vals_type), POINTER :: xc_section
125 : TYPE(virial_type), POINTER :: virial
126 :
127 2018 : CALL timeset(routineN, handle)
128 :
129 : ! get all information on the electronic density
130 2018 : NULLIFY (rho, ks_env)
131 : CALL get_qs_env(qs_env=qs_env, rho=rho, dft_control=dft_control, &
132 2018 : para_env=para_env, ks_env=ks_env, rho_core=rho_core)
133 :
134 2018 : nspins = dft_control%nspins
135 :
136 2018 : NULLIFY (pw_env)
137 2018 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
138 2018 : CPASSERT(ASSOCIATED(pw_env))
139 :
140 2018 : NULLIFY (auxbas_pw_pool, poisson_env)
141 : ! gets the tmp grids
142 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
143 2018 : poisson_env=poisson_env)
144 :
145 : ! Calculate the Hartree potential
146 2018 : CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
147 2018 : CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
148 2018 : CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
149 :
150 : ! Get the total density in g-space [ions + electrons]
151 2018 : CALL calc_rho_tot_gspace(rho_tot_gspace, qs_env, rho)
152 :
153 : CALL pw_poisson_solve(poisson_env, rho_tot_gspace, ehartree, &
154 2018 : v_hartree_gspace, h_stress=h_stress, rho_core=rho_core)
155 2018 : CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
156 2018 : CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
157 :
158 2018 : CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
159 2018 : CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
160 : !
161 2018 : CALL calculate_ecore_self(qs_env, E_self_core=eself)
162 2018 : CALL calculate_ecore_overlap(qs_env, para_env, PRESENT(h_stress), E_overlap_core=eovrl)
163 2018 : ehartree = ehartree + eovrl + eself
164 :
165 : ! v_rspace and v_tau_rspace are generated from the auxbas pool
166 2018 : IF (dft_control%do_admm) THEN
167 420 : CALL get_qs_env(qs_env, admm_env=admm_env)
168 420 : xc_section => admm_env%xc_section_primary
169 : ELSE
170 1598 : xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
171 : END IF
172 2018 : NULLIFY (v_rspace, v_tau_rspace)
173 2018 : IF (dft_control%qs_control%gapw_xc) THEN
174 92 : CALL get_qs_env(qs_env=qs_env, rho_xc=rho_xc)
175 : CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho_xc, xc_section=xc_section, &
176 : vxc_rho=v_rspace, vxc_tau=v_tau_rspace, exc=exc, &
177 92 : edisp=edisp, dispersion_env=qs_env%dispersion_env, just_energy=.FALSE.)
178 : ELSE
179 : CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho, xc_section=xc_section, &
180 : vxc_rho=v_rspace, vxc_tau=v_tau_rspace, exc=exc, &
181 1926 : edisp=edisp, dispersion_env=qs_env%dispersion_env, just_energy=.FALSE.)
182 : END IF
183 :
184 2018 : NULLIFY (v_admm_rspace, v_admm_tau_rspace)
185 2018 : IF (dft_control%do_admm) THEN
186 420 : IF (dft_control%admm_control%aux_exch_func /= do_admm_aux_exch_func_none) THEN
187 : ! For the virial, we have to save the pv_xc component because it will be reset in qs_vxc_create
188 248 : IF (PRESENT(h_stress)) THEN
189 12 : CALL get_qs_env(qs_env, virial=virial)
190 156 : virial_xc = virial%pv_xc
191 : END IF
192 248 : CALL get_admm_env(admm_env, rho_aux_fit=rho)
193 248 : xc_section => admm_env%xc_section_aux
194 : CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho, xc_section=xc_section, &
195 248 : vxc_rho=v_admm_rspace, vxc_tau=v_admm_tau_rspace, exc=eadmm, just_energy=.FALSE.)
196 392 : IF (PRESENT(h_stress)) virial%pv_xc = virial%pv_xc + virial_xc
197 : END IF
198 : END IF
199 :
200 : ! allocate potentials
201 2018 : IF (ASSOCIATED(vh_rspace%pw_grid)) THEN
202 0 : CALL vh_rspace%release()
203 : END IF
204 2018 : IF (ASSOCIATED(vxc_rspace)) THEN
205 0 : DO iab = 1, SIZE(vxc_rspace)
206 0 : CALL vxc_rspace(iab)%release()
207 : END DO
208 : ELSE
209 8310 : ALLOCATE (vxc_rspace(nspins))
210 : END IF
211 2018 : IF (ASSOCIATED(v_tau_rspace)) THEN
212 106 : IF (ASSOCIATED(vtau_rspace)) THEN
213 0 : DO iab = 1, SIZE(vtau_rspace)
214 0 : CALL vtau_rspace(iab)%release()
215 : END DO
216 : ELSE
217 448 : ALLOCATE (vtau_rspace(nspins))
218 : END IF
219 : ELSE
220 1912 : NULLIFY (vtau_rspace)
221 : END IF
222 2018 : IF (ASSOCIATED(v_admm_rspace)) THEN
223 240 : IF (ASSOCIATED(vadmm_rspace)) THEN
224 0 : DO iab = 1, SIZE(vadmm_rspace)
225 0 : CALL vadmm_rspace(iab)%release()
226 : END DO
227 : ELSE
228 988 : ALLOCATE (vadmm_rspace(nspins))
229 : END IF
230 : ELSE
231 1778 : NULLIFY (vadmm_rspace)
232 : END IF
233 2018 : IF (PRESENT(vadmm_tau_rspace)) THEN
234 1390 : IF (ASSOCIATED(vadmm_tau_rspace)) THEN
235 0 : DO iab = 1, SIZE(vadmm_tau_rspace)
236 0 : CALL vadmm_tau_rspace(iab)%release()
237 : END DO
238 : END IF
239 1390 : IF (ASSOCIATED(v_admm_tau_rspace)) THEN
240 0 : IF (.NOT. ASSOCIATED(vadmm_tau_rspace)) ALLOCATE (vadmm_tau_rspace(nspins))
241 : ELSE
242 1390 : IF (ASSOCIATED(vadmm_tau_rspace)) DEALLOCATE (vadmm_tau_rspace)
243 1390 : NULLIFY (vadmm_tau_rspace)
244 : END IF
245 : END IF
246 :
247 2018 : pw_grid => v_hartree_rspace%pw_grid
248 2018 : CALL vh_rspace%create(pw_grid)
249 4274 : DO ispin = 1, nspins
250 2256 : CALL vxc_rspace(ispin)%create(pw_grid)
251 2256 : IF (ASSOCIATED(vtau_rspace)) THEN
252 130 : CALL vtau_rspace(ispin)%create(pw_grid)
253 : END IF
254 2256 : IF (ASSOCIATED(vadmm_rspace)) THEN
255 268 : CALL vadmm_rspace(ispin)%create(pw_grid)
256 : END IF
257 4274 : IF (PRESENT(vadmm_tau_rspace)) THEN
258 1520 : IF (ASSOCIATED(vadmm_tau_rspace)) CALL vadmm_tau_rspace(ispin)%create(pw_grid)
259 : END IF
260 : END DO
261 : !
262 2018 : CALL pw_transfer(v_hartree_rspace, vh_rspace)
263 2018 : IF (ASSOCIATED(v_rspace)) THEN
264 3376 : DO ispin = 1, nspins
265 1782 : CALL pw_transfer(v_rspace(ispin), vxc_rspace(ispin))
266 1782 : CALL pw_scale(vxc_rspace(ispin), v_rspace(ispin)%pw_grid%dvol)
267 3376 : IF (ASSOCIATED(v_tau_rspace)) THEN
268 130 : CALL pw_transfer(v_tau_rspace(ispin), vtau_rspace(ispin))
269 130 : CALL pw_scale(vtau_rspace(ispin), v_tau_rspace(ispin)%pw_grid%dvol)
270 : END IF
271 : END DO
272 : ELSE
273 898 : DO ispin = 1, nspins
274 898 : CALL pw_zero(vxc_rspace(ispin))
275 : END DO
276 : END IF
277 2018 : IF (ASSOCIATED(v_admm_rspace)) THEN
278 508 : DO ispin = 1, nspins
279 268 : CALL pw_transfer(v_admm_rspace(ispin), vadmm_rspace(ispin))
280 508 : CALL pw_scale(vadmm_rspace(ispin), vadmm_rspace(ispin)%pw_grid%dvol)
281 : END DO
282 : END IF
283 2018 : IF (PRESENT(vadmm_tau_rspace)) THEN
284 1390 : IF (ASSOCIATED(v_admm_tau_rspace)) THEN
285 0 : DO ispin = 1, nspins
286 0 : CALL pw_transfer(v_admm_tau_rspace(ispin), vadmm_tau_rspace(ispin))
287 0 : CALL pw_scale(vadmm_tau_rspace(ispin), vadmm_tau_rspace(ispin)%pw_grid%dvol)
288 : END DO
289 : END IF
290 : END IF
291 :
292 : ! return pw grids
293 2018 : CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
294 2018 : IF (ASSOCIATED(v_rspace)) THEN
295 3376 : DO ispin = 1, nspins
296 1782 : CALL auxbas_pw_pool%give_back_pw(v_rspace(ispin))
297 3376 : IF (ASSOCIATED(v_tau_rspace)) THEN
298 130 : CALL auxbas_pw_pool%give_back_pw(v_tau_rspace(ispin))
299 : END IF
300 : END DO
301 1594 : DEALLOCATE (v_rspace)
302 : END IF
303 2018 : IF (ASSOCIATED(v_tau_rspace)) DEALLOCATE (v_tau_rspace)
304 2018 : IF (ASSOCIATED(v_admm_rspace)) THEN
305 508 : DO ispin = 1, nspins
306 508 : CALL auxbas_pw_pool%give_back_pw(v_admm_rspace(ispin))
307 : END DO
308 240 : DEALLOCATE (v_admm_rspace)
309 : END IF
310 2018 : IF (ASSOCIATED(v_admm_tau_rspace)) THEN
311 0 : DO ispin = 1, nspins
312 0 : CALL auxbas_pw_pool%give_back_pw(v_admm_tau_rspace(ispin))
313 : END DO
314 0 : DEALLOCATE (v_admm_tau_rspace)
315 : END IF
316 :
317 2018 : CALL timestop(handle)
318 :
319 2018 : END SUBROUTINE ks_ref_potential
320 :
321 : ! **************************************************************************************************
322 : !> \brief calculate the Kohn-Sham GAPW reference potentials
323 : !> \param qs_env ...
324 : !> \param local_rho_set ...
325 : !> \param local_rho_set_admm ...
326 : !> \param v_hartree_rspace ...
327 : !> \par History
328 : !> 07.2022 created [JGH]
329 : !> \author JGH
330 : ! **************************************************************************************************
331 1390 : SUBROUTINE ks_ref_potential_atom(qs_env, local_rho_set, local_rho_set_admm, v_hartree_rspace)
332 : TYPE(qs_environment_type), POINTER :: qs_env
333 : TYPE(local_rho_type), POINTER :: local_rho_set, local_rho_set_admm
334 : TYPE(pw_r3d_rs_type), INTENT(IN) :: v_hartree_rspace
335 :
336 : CHARACTER(LEN=*), PARAMETER :: routineN = 'ks_ref_potential_atom'
337 :
338 : INTEGER :: handle, natom, nspins
339 : LOGICAL :: gapw, gapw_xc
340 : REAL(KIND=dp) :: eh1c, exc1, exc1_admm
341 : TYPE(admm_type), POINTER :: admm_env
342 1390 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
343 1390 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_aux, rho_ao_kp
344 : TYPE(dft_control_type), POINTER :: dft_control
345 : TYPE(hartree_local_type), POINTER :: hartree_local
346 : TYPE(mp_para_env_type), POINTER :: para_env
347 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
348 1390 : POINTER :: sab
349 : TYPE(oce_matrix_type), POINTER :: oce
350 : TYPE(pw_env_type), POINTER :: pw_env
351 1390 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
352 : TYPE(qs_rho_type), POINTER :: rho, rho_aux_fit
353 : TYPE(section_vals_type), POINTER :: xc_section
354 :
355 1390 : CALL timeset(routineN, handle)
356 :
357 : ! get all information on the electronic density
358 : CALL get_qs_env(qs_env=qs_env, rho=rho, pw_env=pw_env, &
359 1390 : dft_control=dft_control, para_env=para_env)
360 :
361 1390 : nspins = dft_control%nspins
362 1390 : gapw = dft_control%qs_control%gapw
363 1390 : gapw_xc = dft_control%qs_control%gapw_xc
364 :
365 1390 : IF (gapw .OR. gapw_xc) THEN
366 300 : NULLIFY (hartree_local, local_rho_set, local_rho_set_admm)
367 : CALL get_qs_env(qs_env, &
368 : atomic_kind_set=atomic_kind_set, &
369 300 : qs_kind_set=qs_kind_set)
370 300 : CALL local_rho_set_create(local_rho_set)
371 : CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
372 300 : qs_kind_set, dft_control, para_env)
373 300 : IF (gapw) THEN
374 232 : CALL get_qs_env(qs_env, natom=natom)
375 232 : CALL init_rho0(local_rho_set, qs_env, dft_control%qs_control%gapw_control)
376 232 : CALL rho0_s_grid_create(pw_env, local_rho_set%rho0_mpole)
377 232 : CALL hartree_local_create(hartree_local)
378 232 : CALL init_coulomb_local(hartree_local, natom)
379 : END IF
380 :
381 300 : CALL get_qs_env(qs_env=qs_env, oce=oce, sab_orb=sab)
382 300 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
383 : CALL calculate_rho_atom_coeff(qs_env, rho_ao_kp, local_rho_set%rho_atom_set, &
384 300 : qs_kind_set, oce, sab, para_env)
385 300 : CALL prepare_gapw_den(qs_env, local_rho_set, do_rho0=gapw)
386 :
387 300 : IF (dft_control%do_admm) THEN
388 54 : CALL get_qs_env(qs_env, admm_env=admm_env)
389 54 : xc_section => admm_env%xc_section_primary
390 : ELSE
391 246 : xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
392 : END IF
393 : CALL calculate_vxc_atom(qs_env, .FALSE., exc1=exc1, xc_section_external=xc_section, &
394 300 : rho_atom_set_external=local_rho_set%rho_atom_set)
395 :
396 300 : IF (gapw) THEN
397 232 : CALL Vh_1c_gg_integrals(qs_env, eh1c, hartree_local%ecoul_1c, local_rho_set, para_env, .FALSE.)
398 : CALL integrate_vhg0_rspace(qs_env, v_hartree_rspace, para_env, calculate_forces=.FALSE., &
399 232 : local_rho_set=local_rho_set)
400 : END IF
401 :
402 300 : IF (dft_control%do_admm) THEN
403 54 : IF (admm_env%do_gapw) THEN
404 54 : CALL local_rho_set_create(local_rho_set_admm)
405 : CALL allocate_rho_atom_internals(local_rho_set_admm%rho_atom_set, atomic_kind_set, &
406 54 : admm_env%admm_gapw_env%admm_kind_set, dft_control, para_env)
407 54 : oce => admm_env%admm_gapw_env%oce
408 54 : sab => admm_env%sab_aux_fit
409 54 : CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit)
410 54 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_aux)
411 : CALL calculate_rho_atom_coeff(qs_env, rho_ao_aux, local_rho_set_admm%rho_atom_set, &
412 54 : admm_env%admm_gapw_env%admm_kind_set, oce, sab, para_env)
413 : CALL prepare_gapw_den(qs_env, local_rho_set=local_rho_set_admm, &
414 54 : do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
415 : !compute the potential due to atomic densities
416 54 : xc_section => admm_env%xc_section_aux
417 : CALL calculate_vxc_atom(qs_env, energy_only=.FALSE., exc1=exc1_admm, &
418 : kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
419 : xc_section_external=xc_section, &
420 54 : rho_atom_set_external=local_rho_set_admm%rho_atom_set)
421 : END IF
422 : END IF
423 :
424 : ! clean up
425 300 : CALL hartree_local_release(hartree_local)
426 :
427 : ELSE
428 :
429 1090 : NULLIFY (local_rho_set, local_rho_set_admm)
430 :
431 : END IF
432 :
433 1390 : CALL timestop(handle)
434 :
435 1390 : END SUBROUTINE ks_ref_potential_atom
436 :
437 : ! **************************************************************************************************
438 :
439 : END MODULE qs_ks_reference
|