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 : #ifdef __GAUXC
9 : #include "gauxc/gauxc_config.f"
10 : #endif
11 :
12 : #define GAUXC_RETURN_IF_ERROR(status) IF (status%status%code /= 0) RETURN
13 :
14 : MODULE xc_gauxc_interface
15 :
16 : USE iso_c_binding, ONLY: &
17 : c_associated, &
18 : c_bool, &
19 : c_char, &
20 : c_double, &
21 : c_f_pointer, &
22 : c_int, &
23 : c_int32_t, &
24 : c_int64_t, &
25 : c_null_char, &
26 : c_null_ptr, &
27 : c_ptr, &
28 : c_size_t
29 : USE particle_types, ONLY: &
30 : particle_type
31 : USE qs_kind_types, ONLY: &
32 : get_qs_kind, &
33 : qs_kind_type
34 : USE cp_dbcsr_api, ONLY: &
35 : dbcsr_p_type
36 :
37 : #ifdef __GAUXC
38 :
39 : USE kinds, ONLY: &
40 : default_path_length, &
41 : default_string_length, &
42 : dp
43 : USE physcon, ONLY: &
44 : bohr
45 : USE atomic_kind_types, ONLY: &
46 : atomic_kind_type, &
47 : get_atomic_kind, &
48 : get_atomic_kind_set
49 : USE qs_integral_utils, ONLY: &
50 : basis_set_list_setup
51 : USE basis_set_types, ONLY: &
52 : gto_basis_set_p_type, &
53 : gto_basis_set_type, &
54 : write_gto_basis_set
55 : USE periodic_table, ONLY: &
56 : get_ptable_info
57 : USE gauxc_status, ONLY: &
58 : gauxc_status_message, &
59 : gauxc_status_type
60 : USE gauxc_enums, ONLY: &
61 : gauxc_atomicgridsizedefault, &
62 : gauxc_executionspace, &
63 : gauxc_pruningscheme, &
64 : gauxc_radialquad
65 : USE gauxc_runtime_environment, ONLY: &
66 : gauxc_runtime_environment_delete, &
67 : gauxc_runtime_environment_new, &
68 : gauxc_runtime_environment_type
69 : USE gauxc_molecule, ONLY: &
70 : gauxc_delete, &
71 : gauxc_molecule_new_from_atoms, &
72 : gauxc_molecule_type
73 : USE gauxc_atom, ONLY: &
74 : gauxc_atom_type
75 : USE gauxc_basisset, ONLY: &
76 : gauxc_basisset_new, &
77 : gauxc_basisset_new_from_shells, &
78 : gauxc_basisset_type, &
79 : gauxc_delete
80 : USE gauxc_shell, ONLY: &
81 : gauxc_shell_type
82 : USE gauxc_molgrid, ONLY: &
83 : gauxc_delete, &
84 : gauxc_molgrid_new_default, &
85 : gauxc_molgrid_type
86 : USE gauxc_load_balancer, ONLY: &
87 : gauxc_delete, &
88 : gauxc_load_balancer_factory_get_instance, &
89 : gauxc_load_balancer_factory_new, &
90 : gauxc_load_balancer_factory_type, &
91 : gauxc_load_balancer_type
92 : USE gauxc_molecular_weights, ONLY: &
93 : gauxc_delete, &
94 : gauxc_get_instance, &
95 : gauxc_molecular_weights_factory_new, &
96 : gauxc_molecular_weights_factory_type, &
97 : gauxc_molecular_weights_modify_weights, &
98 : gauxc_molecular_weights_settings, &
99 : gauxc_molecular_weights_type
100 : USE gauxc_xc_functional, ONLY: &
101 : gauxc_delete, &
102 : gauxc_functional_from_string, &
103 : gauxc_functional_type
104 : USE gauxc_integrator, ONLY: &
105 : gauxc_delete, &
106 : gauxc_integrator_eval_exc_grad_rks, &
107 : gauxc_integrator_eval_exc_grad_uks, &
108 : gauxc_integrator_eval_exc_vxc_rks, &
109 : gauxc_integrator_eval_exc_vxc_uks, &
110 : gauxc_integrator_new, &
111 : gauxc_integrator_type
112 : #ifdef GAUXC_HAS_ONEDFT
113 : USE gauxc_integrator, ONLY: &
114 : gauxc_integrator_eval_exc_grad_onedft_uks, &
115 : gauxc_integrator_eval_exc_vxc_onedft_uks
116 : USE OMP_LIB, ONLY: &
117 : omp_get_max_threads, &
118 : omp_set_num_threads
119 : #endif
120 : #ifdef GAUXC_HAS_HDF5
121 : USE gauxc_external_hdf5_write, ONLY: &
122 : gauxc_write_hdf5_record
123 : #endif
124 : USE string_utilities, ONLY: &
125 : uppercase
126 : #endif
127 :
128 : #include "../base/base_uses.f90"
129 :
130 : IMPLICIT NONE
131 : PRIVATE
132 :
133 : #ifndef __GAUXC
134 :
135 : ! The module still exists as an empty shell when compiling without GauXC.
136 :
137 : TYPE cp_gauxc_molecule_type
138 : END TYPE cp_gauxc_molecule_type
139 :
140 : TYPE cp_gauxc_basisset_type
141 : INTEGER :: max_l = -1
142 : END TYPE cp_gauxc_basisset_type
143 :
144 : TYPE cp_gauxc_grid_type
145 : END TYPE cp_gauxc_grid_type
146 :
147 : TYPE cp_gauxc_integrator_type
148 : END TYPE cp_gauxc_integrator_type
149 :
150 : TYPE cp_gauxc_status_type
151 : END TYPE cp_gauxc_status_type
152 :
153 : #else
154 :
155 : ! TODO can we make the single fields private somehow?
156 :
157 : TYPE cp_gauxc_molecule_type
158 : TYPE(gauxc_molecule_type) :: molecule
159 : END TYPE cp_gauxc_molecule_type
160 :
161 : TYPE cp_gauxc_basisset_type
162 : TYPE(gauxc_basisset_type) :: basis
163 : INTEGER :: max_l = -1
164 : END TYPE cp_gauxc_basisset_type
165 :
166 : TYPE cp_gauxc_grid_type
167 : TYPE(gauxc_molgrid_type) :: grid
168 : TYPE(gauxc_load_balancer_type) :: lb
169 : TYPE(gauxc_load_balancer_factory_type) :: lbf
170 : TYPE(gauxc_molecular_weights_type) :: mw
171 : TYPE(gauxc_molecular_weights_factory_type) :: mwf
172 : TYPE(gauxc_runtime_environment_type) :: rt
173 : LOGICAL :: owns_rt = .FALSE.
174 : END TYPE cp_gauxc_grid_type
175 :
176 : TYPE cp_gauxc_integrator_type
177 : TYPE(gauxc_functional_type) :: func
178 : TYPE(gauxc_integrator_type) :: integrator
179 : END TYPE cp_gauxc_integrator_type
180 :
181 : TYPE cp_gauxc_status_type
182 : TYPE(gauxc_status_type) :: status
183 : END TYPE cp_gauxc_status_type
184 :
185 : TYPE(gauxc_runtime_environment_type) :: rt
186 : INTEGER :: rt_mpi_comm = -1
187 : LOGICAL :: rt_has_mpi_comm = .FALSE.
188 :
189 : #endif
190 :
191 : TYPE cp_gauxc_xc_type
192 : REAL(c_double) :: exc
193 : REAL(c_double), DIMENSION(:, :), ALLOCATABLE :: vxc_scalar, vxc_zeta
194 : END TYPE cp_gauxc_xc_type
195 :
196 : TYPE cp_gauxc_xc_gradient_type
197 : REAL(c_double), ALLOCATABLE, DIMENSION(:) :: exc_grad
198 : END TYPE cp_gauxc_xc_gradient_type
199 :
200 : CHARACTER(len=*), PARAMETER :: no_gauxc_message = "Compile CP2K with GauXC to use this functionality!"
201 :
202 : PUBLIC :: &
203 : cp_gauxc_basisset_type, &
204 : cp_gauxc_grid_type, &
205 : cp_gauxc_integrator_type, &
206 : cp_gauxc_molecule_type, &
207 : cp_gauxc_status_type, &
208 : cp_gauxc_xc_gradient_type, &
209 : cp_gauxc_xc_type, &
210 : gauxc_check_status, &
211 : gauxc_compute_xc_gradient, &
212 : gauxc_compute_xc, &
213 : gauxc_create_basisset, &
214 : gauxc_create_grid, &
215 : gauxc_create_integrator, &
216 : gauxc_create_molecule, &
217 : gauxc_destroy_basisset, &
218 : gauxc_destroy_grid, &
219 : gauxc_destroy_integrator, &
220 : gauxc_destroy_molecule, &
221 : gauxc_finalize, &
222 : gauxc_init, &
223 : gauxc_write_basisset_hdf5, &
224 : gauxc_write_molecule_hdf5
225 : CONTAINS
226 :
227 : ! **************************************************************************************************
228 : !> \brief ...
229 : !> \param status ...
230 : ! **************************************************************************************************
231 0 : SUBROUTINE print_gauxc_status_message(status)
232 : ! IMPORT :: c_ptr
233 : TYPE(cp_gauxc_status_type) :: status
234 :
235 : #ifdef __GAUXC
236 0 : CHARACTER(kind=c_char), POINTER :: s(:)
237 : INTEGER :: i
238 :
239 0 : WRITE (0, '(a,1x,i0)') "GauXC returned with status code", status%status%code
240 0 : IF (c_associated(status%status%message)) THEN
241 0 : WRITE (0, '(a)', ADVANCE='no') "GauXC status message: ["
242 :
243 0 : CALL c_f_pointer(status%status%message, s, [default_string_length])
244 0 : DO i = 1, SIZE(s)
245 0 : IF (s(i) == c_null_char) EXIT
246 0 : WRITE (0, '(A)', advance='no') s(i)
247 : END DO
248 :
249 0 : WRITE (0, '(a)') "]"
250 : ELSE
251 0 : WRITE (0, '(a)') "GauXC status message: [null]"
252 : END IF
253 : #else
254 : MARK_USED(status)
255 : #endif
256 0 : END SUBROUTINE print_gauxc_status_message
257 :
258 : ! **************************************************************************************************
259 : !> \brief ...
260 : !> \param mpi_comm ...
261 : !> \param status ...
262 : ! **************************************************************************************************
263 10112 : SUBROUTINE gauxc_init(mpi_comm, status)
264 : INTEGER, INTENT(IN), OPTIONAL :: mpi_comm
265 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
266 :
267 : #ifdef __GAUXC
268 : #if defined(GAUXC_HAS_MPI) && defined(__parallel)
269 10112 : IF (PRESENT(mpi_comm)) THEN
270 10112 : rt = gauxc_runtime_environment_new(status%status, mpi_comm)
271 10112 : rt_mpi_comm = mpi_comm
272 10112 : rt_has_mpi_comm = .TRUE.
273 : ELSE
274 0 : rt = gauxc_runtime_environment_new(status%status)
275 0 : rt_mpi_comm = -1
276 0 : rt_has_mpi_comm = .FALSE.
277 : END IF
278 : #else
279 : MARK_USED(mpi_comm)
280 : rt = gauxc_runtime_environment_new(status%status)
281 : rt_mpi_comm = -1
282 : rt_has_mpi_comm = .FALSE.
283 : #endif
284 10112 : GAUXC_RETURN_IF_ERROR(status)
285 : #else
286 : MARK_USED(mpi_comm)
287 : MARK_USED(status)
288 : #endif
289 : END SUBROUTINE gauxc_init
290 :
291 : ! **************************************************************************************************
292 : !> \brief ...
293 : !> \param status ...
294 : ! **************************************************************************************************
295 10112 : SUBROUTINE gauxc_finalize(status)
296 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
297 :
298 : #ifdef __GAUXC
299 10112 : CALL gauxc_runtime_environment_delete(status%status, rt)
300 10112 : GAUXC_RETURN_IF_ERROR(status)
301 10112 : rt_mpi_comm = -1
302 10112 : rt_has_mpi_comm = .FALSE.
303 : #else
304 : MARK_USED(status)
305 : #endif
306 : END SUBROUTINE gauxc_finalize
307 :
308 : ! **************************************************************************************************
309 : !> \brief ...
310 : !> \param particle_set ...
311 : !> \param status ...
312 : !> \return ...
313 : ! **************************************************************************************************
314 1020 : FUNCTION gauxc_create_molecule(particle_set, status) RESULT(res)
315 : TYPE(particle_type), DIMENSION(:), INTENT(IN) :: particle_set
316 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
317 : TYPE(cp_gauxc_molecule_type) :: res
318 :
319 : #ifdef __GAUXC
320 : CHARACTER(LEN=2) :: element_symbol
321 : INTEGER :: atomic_number, i, natoms
322 : TYPE(atomic_kind_type), POINTER :: atomic_kind
323 510 : TYPE(gauxc_atom_type), ALLOCATABLE, DIMENSION(:) :: atoms
324 :
325 510 : natoms = SIZE(particle_set)
326 1530 : ALLOCATE (atoms(natoms))
327 :
328 1726 : DO i = 1, natoms
329 1216 : atomic_kind => particle_set(i)%atomic_kind
330 1216 : CALL get_atomic_kind(atomic_kind, element_symbol=element_symbol)
331 1216 : CALL get_ptable_info(element_symbol, number=atomic_number)
332 1216 : atoms(i)%atomic_number = INT(atomic_number, c_int64_t)
333 1216 : atoms(i)%x = REAL(particle_set(i)%r(1), c_double)
334 1216 : atoms(i)%y = REAL(particle_set(i)%r(2), c_double)
335 1726 : atoms(i)%z = REAL(particle_set(i)%r(3), c_double)
336 : END DO
337 :
338 510 : res%molecule = gauxc_molecule_new_from_atoms(status%status, atoms, INT(natoms, c_size_t))
339 510 : GAUXC_RETURN_IF_ERROR(status)
340 :
341 510 : DEALLOCATE (atoms)
342 : #else
343 : MARK_USED(particle_set)
344 : MARK_USED(res)
345 : MARK_USED(status)
346 : CPABORT(no_gauxc_message)
347 : #endif
348 1020 : END FUNCTION gauxc_create_molecule
349 :
350 : ! **************************************************************************************************
351 : !> \brief ...
352 : !> \param qs_kind_set ...
353 : !> \param particle_set ...
354 : !> \param status ...
355 : !> \return ...
356 : ! **************************************************************************************************
357 1020 : FUNCTION gauxc_create_basisset(qs_kind_set, particle_set, status) RESULT(res)
358 : TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
359 : POINTER :: qs_kind_set
360 : TYPE(particle_type), DIMENSION(:), INTENT(IN) :: particle_set
361 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
362 : TYPE(cp_gauxc_basisset_type) :: res
363 :
364 : #ifdef __GAUXC
365 : INTEGER :: iatom, ikind, iprim, iset, ishell, lval, &
366 : nkind, npgf, nset, nshell, &
367 : nshell_total, shell_index, natoms
368 : REAL(c_double), DIMENSION(3) :: shell_origin
369 : TYPE(atomic_kind_type), POINTER :: atomic_kind
370 510 : TYPE(gauxc_shell_type), ALLOCATABLE, DIMENSION(:) :: shells
371 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
372 : TYPE(gto_basis_set_type), POINTER :: gto_basis
373 :
374 510 : nkind = SIZE(qs_kind_set)
375 510 : natoms = SIZE(particle_set)
376 :
377 2142 : ALLOCATE (basis_set_list(nkind))
378 510 : CALL basis_set_list_setup(basis_set_list, "ORB", qs_kind_set)
379 :
380 510 : nshell_total = 0
381 1726 : DO iatom = 1, natoms
382 1216 : atomic_kind => particle_set(iatom)%atomic_kind
383 1216 : CALL get_atomic_kind(atomic_kind, kind_number=ikind)
384 1216 : gto_basis => basis_set_list(ikind)%gto_basis_set
385 1216 : CPASSERT(ASSOCIATED(gto_basis))
386 : ! CALL write_gto_basis_set(gto_basis, 6, "–––––GAUXC-CREATE-BASISSET–––––")
387 5234 : nshell_total = nshell_total + SUM(gto_basis%nshell)
388 : END DO
389 :
390 5386 : ALLOCATE (shells(nshell_total))
391 :
392 1726 : shell_index = 0
393 1726 : res%max_l = -1
394 1726 : DO iatom = 1, natoms ! for each atom
395 1216 : atomic_kind => particle_set(iatom)%atomic_kind
396 1216 : CALL get_atomic_kind(atomic_kind, kind_number=ikind)
397 1216 : gto_basis => basis_set_list(ikind)%gto_basis_set
398 1216 : CPASSERT(ASSOCIATED(gto_basis))
399 :
400 1216 : shell_origin(1) = REAL(particle_set(iatom)%r(1), c_double)
401 1216 : shell_origin(2) = REAL(particle_set(iatom)%r(2), c_double)
402 1216 : shell_origin(3) = REAL(particle_set(iatom)%r(3), c_double)
403 :
404 1216 : nset = gto_basis%nset
405 1216 : CPASSERT(nset == SIZE(gto_basis%nshell))
406 5234 : DO iset = 1, nset ! for each shell group
407 2292 : nshell = gto_basis%nshell(iset)
408 2292 : npgf = gto_basis%npgf(iset) ! corresponds with nprim of gauxc
409 :
410 7364 : DO ishell = 1, gto_basis%nshell(iset) ! for each shell within the shell group
411 3856 : shell_index = shell_index + 1 ! global shell index, flattened over atoms and groups
412 3856 : lval = gto_basis%l(ishell, iset)
413 3856 : res%max_l = MAX(res%max_l, lval)
414 3856 : shells(shell_index)%l = INT(lval, c_int32_t)
415 : ! FIXME hardcoded true param
416 : ! pure=1: spherical Gaussians; pure=0: cartesian Gaussians
417 3856 : shells(shell_index)%pure = .TRUE._c_bool
418 3856 : shells(shell_index)%nprim = INT(npgf, c_int32_t)
419 15424 : shells(shell_index)%origin = shell_origin
420 :
421 19092 : DO iprim = 1, npgf
422 : shells(shell_index)%exponents(iprim) = &
423 12944 : REAL(gto_basis%zet(iprim, iset), c_double)
424 : shells(shell_index)%coefficients(iprim) = &
425 : REAL(gto_basis%norm_cgf(gto_basis%first_cgf(ishell, iset))* &
426 16800 : gto_basis%gcc(iprim, ishell, iset), c_double)
427 : END DO
428 : END DO
429 : END DO
430 : END DO
431 :
432 : res%basis = gauxc_basisset_new_from_shells( &
433 : status%status, &
434 : shells, &
435 510 : normalize=.FALSE.)
436 510 : GAUXC_RETURN_IF_ERROR(status)
437 :
438 510 : DEALLOCATE (shells)
439 510 : DEALLOCATE (basis_set_list)
440 :
441 : #else
442 : MARK_USED(particle_set)
443 : MARK_USED(qs_kind_set)
444 : MARK_USED(res)
445 : MARK_USED(status)
446 : CPABORT(no_gauxc_message)
447 : #endif
448 1020 : END FUNCTION gauxc_create_basisset
449 :
450 : ! **************************************************************************************************
451 : !> \brief ...
452 : !> \param molecule ...
453 : !> \param basis ...
454 : !> \param grid_type ...
455 : !> \param radial_quadrature ...
456 : !> \param pruning_scheme ...
457 : !> \param lb_exec_space ...
458 : !> \param batch_size ...
459 : !> \param status ...
460 : !> \param mpi_comm optional communicator for a grid-local GauXC runtime
461 : !> \return ...
462 : ! **************************************************************************************************
463 514 : FUNCTION gauxc_create_grid( &
464 : molecule, &
465 : basis, &
466 : grid_type, &
467 : radial_quadrature, &
468 : pruning_scheme, &
469 : lb_exec_space, &
470 : batch_size, &
471 : status, &
472 514 : mpi_comm) RESULT(res)
473 :
474 : TYPE(cp_gauxc_molecule_type), INTENT(IN) :: molecule
475 : TYPE(cp_gauxc_basisset_type), INTENT(in) :: basis
476 : CHARACTER(len=*) :: grid_type, lb_exec_space, &
477 : pruning_scheme, radial_quadrature
478 : INTEGER :: batch_size
479 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
480 : INTEGER, INTENT(IN), OPTIONAL :: mpi_comm
481 : TYPE(cp_gauxc_grid_type) :: res
482 :
483 : #ifdef __GAUXC
484 : INTEGER(c_int) :: grid_type_local, int_exec_space_local, &
485 : lb_exec_space_local, &
486 : pruning_scheme_local, radial_quad_local
487 :
488 514 : grid_type_local = read_atomic_grid_size(grid_type)
489 514 : radial_quad_local = read_radial_quad(radial_quadrature)
490 514 : pruning_scheme_local = read_pruning_scheme(pruning_scheme)
491 514 : lb_exec_space_local = read_execution_space(lb_exec_space)
492 514 : int_exec_space_local = read_execution_space("host")
493 514 : res%owns_rt = .FALSE.
494 :
495 : #if defined(GAUXC_HAS_MPI) && defined(__parallel)
496 514 : IF (PRESENT(mpi_comm)) THEN
497 : ! Reuse the global runtime when the requested communicator matches
498 : ! the communicator used during gauxc_init.
499 514 : IF (.NOT. rt_has_mpi_comm .OR. mpi_comm /= rt_mpi_comm) THEN
500 228 : res%rt = gauxc_runtime_environment_new(status%status, mpi_comm)
501 228 : GAUXC_RETURN_IF_ERROR(status)
502 : res%owns_rt = .TRUE.
503 : END IF
504 : END IF
505 : #else
506 : MARK_USED(mpi_comm)
507 : #endif
508 :
509 : res%grid = gauxc_molgrid_new_default( &
510 : status%status, &
511 : molecule%molecule, &
512 : pruning_scheme_local, &
513 : INT(batch_size, c_int64_t), &
514 : radial_quad_local, &
515 514 : grid_type_local)
516 514 : GAUXC_RETURN_IF_ERROR(status)
517 :
518 : res%lbf = gauxc_load_balancer_factory_new( &
519 : status%status, &
520 514 : lb_exec_space_local)
521 514 : GAUXC_RETURN_IF_ERROR(status)
522 :
523 514 : IF (res%owns_rt) THEN
524 : res%lb = gauxc_load_balancer_factory_get_instance( &
525 : status%status, &
526 : res%lbf, &
527 : res%rt, &
528 : molecule%molecule, &
529 : res%grid, &
530 228 : basis%basis)
531 : ELSE
532 : res%lb = gauxc_load_balancer_factory_get_instance( &
533 : status%status, &
534 : res%lbf, &
535 : rt, &
536 : molecule%molecule, &
537 : res%grid, &
538 286 : basis%basis)
539 : END IF
540 514 : GAUXC_RETURN_IF_ERROR(status)
541 :
542 : res%mwf = gauxc_molecular_weights_factory_new( &
543 : status%status, &
544 514 : int_exec_space_local)
545 514 : GAUXC_RETURN_IF_ERROR(status)
546 :
547 : res%mw = gauxc_get_instance( &
548 : status%status, &
549 514 : res%mwf)
550 514 : GAUXC_RETURN_IF_ERROR(status)
551 :
552 : CALL gauxc_molecular_weights_modify_weights( &
553 : status%status, &
554 : res%mw, &
555 514 : res%lb)
556 514 : GAUXC_RETURN_IF_ERROR(status)
557 :
558 : #else
559 : MARK_USED(basis)
560 : MARK_USED(batch_size)
561 : MARK_USED(grid_type)
562 : MARK_USED(lb_exec_space)
563 : MARK_USED(mpi_comm)
564 : MARK_USED(molecule)
565 : MARK_USED(pruning_scheme)
566 : MARK_USED(radial_quadrature)
567 : MARK_USED(res)
568 : MARK_USED(status)
569 : CPABORT(no_gauxc_message)
570 : #endif
571 1028 : END FUNCTION gauxc_create_grid
572 :
573 : ! **************************************************************************************************
574 : !> \brief ...
575 : !> \param xc_functional_name ...
576 : !> \param grid ...
577 : !> \param int_exec_space ...
578 : !> \param nspins ...
579 : !> \param status ...
580 : !> \return ...
581 : ! **************************************************************************************************
582 514 : FUNCTION gauxc_create_integrator( &
583 : xc_functional_name, &
584 : grid, &
585 : int_exec_space, &
586 : nspins, &
587 514 : status) RESULT(res)
588 :
589 : CHARACTER(len=*), INTENT(IN) :: xc_functional_name, int_exec_space
590 : TYPE(cp_gauxc_grid_type), INTENT(IN) :: grid
591 : INTEGER, INTENT(IN) :: nspins
592 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
593 : TYPE(cp_gauxc_integrator_type) :: res
594 :
595 : #ifdef __GAUXC
596 : INTEGER(c_int) :: int_exec_space_local
597 : LOGICAL(c_bool) :: polarized
598 :
599 514 : polarized = (nspins == 2)
600 : res%func = gauxc_functional_from_string( &
601 : status%status, &
602 : xc_functional_name, &
603 1028 : polarized)
604 514 : GAUXC_RETURN_IF_ERROR(status)
605 :
606 514 : int_exec_space_local = read_execution_space(int_exec_space)
607 : res%integrator = gauxc_integrator_new( &
608 : status%status, &
609 : res%func, &
610 : grid%lb, &
611 514 : int_exec_space_local)
612 514 : GAUXC_RETURN_IF_ERROR(status)
613 :
614 : #else
615 : MARK_USED(grid)
616 : MARK_USED(int_exec_space)
617 : MARK_USED(nspins)
618 : MARK_USED(res)
619 : MARK_USED(status)
620 : MARK_USED(xc_functional_name)
621 : CPABORT(no_gauxc_message)
622 : #endif
623 1028 : END FUNCTION gauxc_create_integrator
624 :
625 : ! **************************************************************************************************
626 : !> \brief ...
627 : !> \param integrator ...
628 : !> \param density_scalar ...
629 : !> \param density_zeta ...
630 : !> \param nspins ...
631 : !> \param status ...
632 : !> \param model ...
633 : !> \return ...
634 : ! **************************************************************************************************
635 1020 : FUNCTION gauxc_compute_xc( &
636 : integrator, &
637 1020 : density_scalar, &
638 510 : density_zeta, &
639 : nspins, &
640 : status, &
641 510 : model) RESULT(res)
642 :
643 : TYPE(cp_gauxc_integrator_type), INTENT(IN) :: integrator
644 : ! Must be inout since we need to modify the matrix for some code paths
645 : REAL(c_double), DIMENSION(:, :) :: density_scalar
646 : REAL(c_double), DIMENSION(:, :), INTENT(IN), &
647 : OPTIONAL :: density_zeta
648 : INTEGER, INTENT(IN) :: nspins
649 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
650 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: model
651 : TYPE(cp_gauxc_xc_type) :: res
652 :
653 : #ifdef __GAUXC
654 : CHARACTER(len=default_path_length) :: model_key
655 : LOGICAL :: use_onedft
656 : #ifdef GAUXC_HAS_ONEDFT
657 510 : REAL(c_double), ALLOCATABLE, DIMENSION(:, :) :: density_zeta_zero
658 : INTEGER :: omp_max_threads_restore
659 : #endif
660 :
661 510 : use_onedft = .FALSE.
662 510 : IF (PRESENT(model)) THEN
663 510 : model_key = ADJUSTL(model)
664 510 : CALL uppercase(model_key)
665 510 : use_onedft = (TRIM(model_key) /= "" .AND. TRIM(model_key) /= "NONE")
666 : END IF
667 :
668 510 : IF (.NOT. ALLOCATED(res%vxc_scalar)) THEN
669 2040 : ALLOCATE (res%vxc_scalar, mold=density_scalar)
670 : ELSE
671 0 : CPASSERT(ALL(SHAPE(res%vxc_scalar) == SHAPE(density_scalar)))
672 : END IF
673 140722 : res%vxc_scalar = 0._dp
674 :
675 510 : IF (use_onedft) THEN
676 : #ifndef GAUXC_HAS_ONEDFT
677 : CPABORT("GauXC lacks OneDFT support")
678 : #else
679 : ! OneDFT may change the OpenMP team size for later parallel regions.
680 : ! Restore max threads only; omp_get_num_threads() is 1 here.
681 486 : omp_max_threads_restore = omp_get_max_threads()
682 486 : IF (.NOT. ALLOCATED(res%vxc_zeta)) THEN
683 1944 : ALLOCATE (res%vxc_zeta, mold=density_scalar)
684 : ELSE
685 0 : CPASSERT(ALL(SHAPE(res%vxc_zeta) == SHAPE(density_scalar)))
686 : END IF
687 134666 : res%vxc_zeta = 0._dp
688 :
689 486 : IF (nspins == 1) THEN
690 1440 : ALLOCATE (density_zeta_zero, mold=density_scalar)
691 360 : density_zeta_zero = 0._dp
692 : CALL gauxc_integrator_eval_exc_vxc_onedft_uks( &
693 : status%status, &
694 : integrator%integrator, &
695 : density_scalar, &
696 : density_zeta_zero, &
697 : TRIM(model), &
698 : res%exc, &
699 : res%vxc_scalar, &
700 108000 : res%vxc_zeta)
701 360 : DEALLOCATE (density_zeta_zero)
702 : ELSE
703 126 : CPASSERT(PRESENT(density_zeta))
704 : CALL gauxc_integrator_eval_exc_vxc_onedft_uks( &
705 : status%status, &
706 : integrator%integrator, &
707 : density_scalar, &
708 : density_zeta, &
709 : TRIM(model), &
710 : res%exc, &
711 : res%vxc_scalar, &
712 53206 : res%vxc_zeta)
713 : END IF
714 486 : CALL omp_set_num_threads(omp_max_threads_restore)
715 486 : GAUXC_RETURN_IF_ERROR(status)
716 486 : RETURN
717 : #endif
718 : END IF
719 :
720 24 : IF (nspins == 1) THEN
721 : ! xmat factor 2 is applied by both CP2K and GauXC
722 : ! "unapply" it here to even things back out
723 : ! This is NOT necessary in the OneDFT branch
724 6056 : density_scalar = 0.5_dp*density_scalar
725 : CALL gauxc_integrator_eval_exc_vxc_rks( &
726 : status%status, &
727 : integrator%integrator, &
728 : density_scalar, &
729 : res%exc, &
730 6056 : res%vxc_scalar)
731 : ELSE
732 0 : CPASSERT(PRESENT(density_zeta))
733 :
734 0 : IF (.NOT. ALLOCATED(res%vxc_zeta)) THEN
735 0 : ALLOCATE (res%vxc_zeta, mold=density_zeta)
736 : ELSE
737 0 : CPASSERT(ALL(SHAPE(res%vxc_zeta) == SHAPE(density_scalar)))
738 : END IF
739 0 : res%vxc_zeta = 0._dp
740 :
741 : CALL gauxc_integrator_eval_exc_vxc_uks( &
742 : status%status, &
743 : integrator%integrator, &
744 : density_scalar, &
745 : density_zeta, &
746 : res%exc, &
747 : res%vxc_scalar, &
748 0 : res%vxc_zeta)
749 : END IF
750 24 : GAUXC_RETURN_IF_ERROR(status)
751 :
752 : #else
753 : MARK_USED(integrator)
754 : MARK_USED(density_scalar)
755 : MARK_USED(density_zeta)
756 : MARK_USED(nspins)
757 : MARK_USED(status)
758 : MARK_USED(model)
759 : CPABORT(no_gauxc_message)
760 : #endif
761 1020 : END FUNCTION gauxc_compute_xc
762 :
763 : ! **************************************************************************************************
764 : !> \brief ...
765 : !> \param integrator ...
766 : !> \param density_scalar ...
767 : !> \param density_zeta ...
768 : !> \param nspins ...
769 : !> \param natom ...
770 : !> \param status ...
771 : !> \param model ...
772 : !> \return ...
773 : ! **************************************************************************************************
774 8 : FUNCTION gauxc_compute_xc_gradient( &
775 : integrator, &
776 8 : density_scalar, &
777 4 : density_zeta, &
778 : nspins, &
779 : natom, &
780 : status, &
781 4 : model) RESULT(res)
782 :
783 : TYPE(cp_gauxc_integrator_type), INTENT(IN) :: integrator
784 : REAL(c_double), DIMENSION(:, :), INTENT(IN) :: density_scalar
785 : REAL(c_double), DIMENSION(:, :), INTENT(IN), &
786 : OPTIONAL :: density_zeta
787 : INTEGER, INTENT(IN) :: nspins, natom
788 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
789 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: model
790 : TYPE(cp_gauxc_xc_gradient_type) :: res
791 :
792 : #ifdef __GAUXC
793 : CHARACTER(len=default_path_length) :: model_key
794 : LOGICAL :: use_onedft
795 : #ifdef GAUXC_HAS_ONEDFT
796 4 : REAL(c_double), ALLOCATABLE, DIMENSION(:, :) :: density_zeta_zero
797 : INTEGER :: omp_max_threads_restore
798 : #endif
799 :
800 12 : ALLOCATE (res%exc_grad(3*natom))
801 40 : res%exc_grad = 0._dp
802 :
803 4 : use_onedft = .FALSE.
804 4 : IF (PRESENT(model)) THEN
805 4 : model_key = ADJUSTL(model)
806 4 : CALL uppercase(model_key)
807 4 : use_onedft = (TRIM(model_key) /= "" .AND. TRIM(model_key) /= "NONE")
808 : END IF
809 :
810 : IF (use_onedft) THEN
811 : #ifndef GAUXC_HAS_ONEDFT
812 : CPABORT("GauXC lacks OneDFT support")
813 : #else
814 : ! OneDFT may change the OpenMP team size for later parallel regions.
815 : ! Restore max threads only; omp_get_num_threads() is 1 here.
816 4 : omp_max_threads_restore = omp_get_max_threads()
817 4 : IF (nspins == 1) THEN
818 16 : ALLOCATE (density_zeta_zero, mold=density_scalar)
819 4 : density_zeta_zero = 0._dp
820 : CALL gauxc_integrator_eval_exc_grad_onedft_uks( &
821 : status%status, &
822 : integrator%integrator, &
823 : density_scalar, &
824 : density_zeta_zero, &
825 : TRIM(model), &
826 1848 : res%exc_grad)
827 4 : DEALLOCATE (density_zeta_zero)
828 : ELSE
829 0 : CPASSERT(PRESENT(density_zeta))
830 : CALL gauxc_integrator_eval_exc_grad_onedft_uks( &
831 : status%status, &
832 : integrator%integrator, &
833 : density_scalar, &
834 : density_zeta, &
835 : TRIM(model), &
836 0 : res%exc_grad)
837 : END IF
838 4 : CALL omp_set_num_threads(omp_max_threads_restore)
839 4 : GAUXC_RETURN_IF_ERROR(status)
840 4 : RETURN
841 : #endif
842 : END IF
843 :
844 0 : IF (nspins == 1) THEN
845 : CALL gauxc_integrator_eval_exc_grad_rks( &
846 : status%status, &
847 : integrator%integrator, &
848 : density_scalar, &
849 0 : res%exc_grad)
850 : ELSE
851 0 : CPASSERT(PRESENT(density_zeta))
852 : CALL gauxc_integrator_eval_exc_grad_uks( &
853 : status%status, &
854 : integrator%integrator, &
855 : density_scalar, &
856 : density_zeta, &
857 0 : res%exc_grad)
858 : END IF
859 0 : GAUXC_RETURN_IF_ERROR(status)
860 :
861 : #else
862 : MARK_USED(density_scalar)
863 : MARK_USED(density_zeta)
864 : MARK_USED(res)
865 : MARK_USED(integrator)
866 : MARK_USED(model)
867 : MARK_USED(natom)
868 : MARK_USED(nspins)
869 : MARK_USED(status)
870 : CPABORT(no_gauxc_message)
871 : #endif
872 8 : END FUNCTION gauxc_compute_xc_gradient
873 :
874 : ! **************************************************************************************************
875 : !> \brief ...
876 : !> \param molecule ...
877 : !> \param status ...
878 : ! **************************************************************************************************
879 510 : SUBROUTINE gauxc_destroy_molecule(molecule, status)
880 : TYPE(cp_gauxc_molecule_type), INTENT(INOUT) :: molecule
881 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
882 :
883 : #ifdef __GAUXC
884 510 : CALL gauxc_delete(status%status, molecule%molecule)
885 510 : GAUXC_RETURN_IF_ERROR(status)
886 : #else
887 : MARK_USED(molecule)
888 : MARK_USED(status)
889 : CPABORT(no_gauxc_message)
890 : #endif
891 : END SUBROUTINE gauxc_destroy_molecule
892 :
893 : ! **************************************************************************************************
894 : !> \brief ...
895 : !> \param basis ...
896 : !> \param status ...
897 : ! **************************************************************************************************
898 510 : SUBROUTINE gauxc_destroy_basisset(basis, status)
899 : TYPE(cp_gauxc_basisset_type), INTENT(INOUT) :: basis
900 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
901 :
902 : #ifdef __GAUXC
903 510 : CALL gauxc_delete(status%status, basis%basis)
904 510 : GAUXC_RETURN_IF_ERROR(status)
905 : #else
906 : MARK_USED(basis)
907 : MARK_USED(status)
908 : CPABORT(no_gauxc_message)
909 : #endif
910 : END SUBROUTINE gauxc_destroy_basisset
911 :
912 : ! **************************************************************************************************
913 : !> \brief ...
914 : !> \param grid_result ...
915 : !> \param status ...
916 : ! **************************************************************************************************
917 514 : SUBROUTINE gauxc_destroy_grid(grid_result, status)
918 : TYPE(cp_gauxc_grid_type), INTENT(INOUT) :: grid_result
919 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
920 :
921 : #ifdef __GAUXC
922 514 : CALL gauxc_delete(status%status, grid_result%mw)
923 514 : GAUXC_RETURN_IF_ERROR(status)
924 514 : CALL gauxc_delete(status%status, grid_result%mwf)
925 514 : GAUXC_RETURN_IF_ERROR(status)
926 514 : CALL gauxc_delete(status%status, grid_result%lb)
927 514 : GAUXC_RETURN_IF_ERROR(status)
928 514 : CALL gauxc_delete(status%status, grid_result%lbf)
929 514 : GAUXC_RETURN_IF_ERROR(status)
930 514 : CALL gauxc_delete(status%status, grid_result%grid)
931 514 : GAUXC_RETURN_IF_ERROR(status)
932 514 : IF (grid_result%owns_rt) THEN
933 228 : CALL gauxc_runtime_environment_delete(status%status, grid_result%rt)
934 228 : GAUXC_RETURN_IF_ERROR(status)
935 228 : grid_result%owns_rt = .FALSE.
936 : END IF
937 : #else
938 : MARK_USED(grid_result)
939 : MARK_USED(status)
940 : CPABORT(no_gauxc_message)
941 : #endif
942 : END SUBROUTINE gauxc_destroy_grid
943 :
944 : ! **************************************************************************************************
945 : !> \brief ...
946 : !> \param integrator_result ...
947 : !> \param status ...
948 : ! **************************************************************************************************
949 514 : SUBROUTINE gauxc_destroy_integrator(integrator_result, status)
950 : TYPE(cp_gauxc_integrator_type), INTENT(INOUT) :: integrator_result
951 : TYPE(cp_gauxc_status_type), INTENT(OUT) :: status
952 :
953 : #ifdef __GAUXC
954 514 : CALL gauxc_delete(status%status, integrator_result%integrator)
955 514 : GAUXC_RETURN_IF_ERROR(status)
956 514 : CALL gauxc_delete(status%status, integrator_result%func)
957 514 : GAUXC_RETURN_IF_ERROR(status)
958 : #else
959 : MARK_USED(integrator_result)
960 : MARK_USED(status)
961 : CPABORT(no_gauxc_message)
962 : #endif
963 : END SUBROUTINE gauxc_destroy_integrator
964 :
965 : ! **************************************************************************************************
966 : !> \brief Checks gauxc status and prints error message before aborting
967 : !> \param status the gauxc status to check
968 : ! **************************************************************************************************
969 24834 : SUBROUTINE gauxc_check_status(status)
970 : TYPE(cp_gauxc_status_type), INTENT(IN) :: status
971 :
972 : #ifdef __GAUXC
973 24834 : IF (status%status%code /= 0) THEN
974 0 : CALL print_gauxc_status_message(status)
975 0 : CPABORT("GauXC returned with non-zero status code")
976 : END IF
977 : #else
978 : MARK_USED(status)
979 : #endif
980 24834 : END SUBROUTINE gauxc_check_status
981 :
982 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
983 : ! From here on, it's private helpers !
984 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
985 :
986 : #ifdef __GAUXC
987 :
988 : ! **************************************************************************************************
989 : !> \brief ...
990 : !> \param spec ...
991 : !> \return ...
992 : ! **************************************************************************************************
993 1542 : PURE FUNCTION read_execution_space(spec) RESULT(val)
994 : CHARACTER(len=*), INTENT(IN) :: spec
995 : INTEGER(c_int) :: val
996 :
997 1542 : CHARACTER(len=LEN(spec)) :: spec_upper
998 :
999 1542 : spec_upper = spec
1000 1542 : CALL uppercase(spec_upper)
1001 :
1002 : SELECT CASE (spec_upper)
1003 : CASE ("HOST")
1004 0 : val = gauxc_executionspace%host
1005 : CASE ("DEVICE")
1006 0 : val = gauxc_executionspace%device
1007 : CASE DEFAULT
1008 1542 : val = gauxc_executionspace%host
1009 : END SELECT
1010 1542 : END FUNCTION read_execution_space
1011 :
1012 : ! **************************************************************************************************
1013 : !> \brief ...
1014 : !> \param spec ...
1015 : !> \return ...
1016 : ! **************************************************************************************************
1017 514 : PURE FUNCTION read_atomic_grid_size(spec) RESULT(val)
1018 : CHARACTER(len=*), INTENT(IN) :: spec
1019 : INTEGER(c_int) :: val
1020 :
1021 514 : CHARACTER(len=LEN(spec)) :: spec_upper
1022 :
1023 514 : spec_upper = spec
1024 514 : CALL uppercase(spec_upper)
1025 :
1026 : SELECT CASE (spec_upper)
1027 : CASE ("FINE")
1028 0 : val = gauxc_atomicgridsizedefault%finegrid
1029 : CASE ("ULTRAFINE")
1030 0 : val = gauxc_atomicgridsizedefault%ultrafinegrid
1031 : CASE ("SUPERFINE")
1032 42 : val = gauxc_atomicgridsizedefault%superfinegrid
1033 : CASE ("GM3")
1034 0 : val = gauxc_atomicgridsizedefault%gm3
1035 : CASE ("GM5")
1036 0 : val = gauxc_atomicgridsizedefault%gm5
1037 : CASE DEFAULT
1038 514 : val = gauxc_atomicgridsizedefault%finegrid
1039 : END SELECT
1040 514 : END FUNCTION read_atomic_grid_size
1041 :
1042 : ! **************************************************************************************************
1043 : !> \brief ...
1044 : !> \param spec ...
1045 : !> \return ...
1046 : ! **************************************************************************************************
1047 514 : PURE FUNCTION read_radial_quad(spec) RESULT(val)
1048 : CHARACTER(len=*), INTENT(IN) :: spec
1049 : INTEGER(c_int) :: val
1050 :
1051 514 : CHARACTER(len=LEN(spec)) :: spec_upper
1052 :
1053 514 : spec_upper = spec
1054 514 : CALL uppercase(spec_upper)
1055 :
1056 : SELECT CASE (spec_upper)
1057 : CASE ("BECKE")
1058 514 : val = gauxc_radialquad%becke
1059 : CASE ("MURAKNOWLES")
1060 514 : val = gauxc_radialquad%mura_knowles
1061 : CASE ("TREUTLERAHLRICHS")
1062 0 : val = gauxc_radialquad%treutler_ahlrichs
1063 : CASE ("MURRAYHANDYLAMING")
1064 0 : val = gauxc_radialquad%murray_handy_laming
1065 : CASE DEFAULT
1066 514 : val = gauxc_radialquad%mura_knowles
1067 : END SELECT
1068 514 : END FUNCTION read_radial_quad
1069 :
1070 : ! **************************************************************************************************
1071 : !> \brief ...
1072 : !> \param spec ...
1073 : !> \return ...
1074 : ! **************************************************************************************************
1075 514 : PURE FUNCTION read_pruning_scheme(spec) RESULT(val)
1076 : CHARACTER(len=*), INTENT(IN) :: spec
1077 : INTEGER(c_int) :: val
1078 :
1079 514 : CHARACTER(len=LEN(spec)) :: spec_upper
1080 :
1081 514 : spec_upper = spec
1082 514 : CALL uppercase(spec_upper)
1083 :
1084 : SELECT CASE (spec_upper)
1085 : CASE ("UNPRUNED")
1086 472 : val = gauxc_pruningscheme%unpruned
1087 : CASE ("ROBUST")
1088 472 : val = gauxc_pruningscheme%robust
1089 : CASE ("TREUTLER")
1090 0 : val = gauxc_pruningscheme%treutler
1091 : CASE DEFAULT
1092 514 : val = gauxc_pruningscheme%robust
1093 : END SELECT
1094 514 : END FUNCTION read_pruning_scheme
1095 :
1096 : #endif
1097 :
1098 : ! **************************************************************************************************
1099 : !> \brief Write molecule data to HDF5 file for debugging
1100 : !> \param molecule ...
1101 : !> \param output_path ...
1102 : !> \param filename ...
1103 : !> \param dataset ...
1104 : !> \param status ...
1105 : ! **************************************************************************************************
1106 0 : SUBROUTINE gauxc_write_molecule_hdf5(molecule, output_path, filename, dataset, status)
1107 : TYPE(cp_gauxc_molecule_type), INTENT(IN) :: molecule
1108 : CHARACTER(len=*), INTENT(IN) :: output_path, filename, dataset
1109 : TYPE(cp_gauxc_status_type), INTENT(INOUT) :: status
1110 :
1111 : #if defined(__GAUXC) && defined(GAUXC_HAS_HDF5)
1112 : CHARACTER(len=default_path_length) :: full_path
1113 :
1114 : full_path = TRIM(output_path)//"/"//TRIM(filename)
1115 : CALL gauxc_write_hdf5_record(status%status, molecule%molecule, full_path, dataset)
1116 : #else
1117 : MARK_USED(molecule)
1118 : MARK_USED(output_path)
1119 : MARK_USED(filename)
1120 : MARK_USED(dataset)
1121 : MARK_USED(status)
1122 0 : CPABORT("GauXC HDF5 output requires GauXC to be built with HDF5 support.")
1123 : #endif
1124 0 : END SUBROUTINE gauxc_write_molecule_hdf5
1125 :
1126 : ! **************************************************************************************************
1127 : !> \brief Write basis set data to HDF5 file for debugging
1128 : !> \param basis ...
1129 : !> \param output_path ...
1130 : !> \param filename ...
1131 : !> \param dataset ...
1132 : !> \param status ...
1133 : ! **************************************************************************************************
1134 0 : SUBROUTINE gauxc_write_basisset_hdf5(basis, output_path, filename, dataset, status)
1135 : TYPE(cp_gauxc_basisset_type), INTENT(IN) :: basis
1136 : CHARACTER(len=*), INTENT(IN) :: output_path, filename, dataset
1137 : TYPE(cp_gauxc_status_type), INTENT(INOUT) :: status
1138 :
1139 : #if defined(__GAUXC) && defined(GAUXC_HAS_HDF5)
1140 : CHARACTER(len=default_path_length) :: full_path
1141 :
1142 : full_path = TRIM(output_path)//"/"//TRIM(filename)
1143 : CALL gauxc_write_hdf5_record(status%status, basis%basis, full_path, dataset)
1144 : #else
1145 : MARK_USED(basis)
1146 : MARK_USED(output_path)
1147 : MARK_USED(filename)
1148 : MARK_USED(dataset)
1149 : MARK_USED(status)
1150 0 : CPABORT("GauXC HDF5 output requires GauXC to be built with HDF5 support.")
1151 : #endif
1152 0 : END SUBROUTINE gauxc_write_basisset_hdf5
1153 :
1154 0 : END MODULE xc_gauxc_interface
|