(git:26ffdda)
Loading...
Searching...
No Matches
torch_api.F
Go to the documentation of this file.
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!--------------------------------------------------------------------------------------------------!
8 USE iso_c_binding, ONLY: c_associated, &
9 c_bool, &
10 c_char, &
11 c_float, &
12 c_double, &
13 c_f_pointer, &
14 c_int, &
15 c_null_char, &
16 c_null_ptr, &
17 c_ptr, &
18 c_int32_t, &
19 c_int64_t
20
22
23#include "./base/base_uses.f90"
24
25 IMPLICIT NONE
26
27 PRIVATE
28
30 PRIVATE
31 TYPE(C_PTR) :: c_ptr = c_null_ptr
32 END TYPE torch_tensor_type
33
35 PRIVATE
36 TYPE(C_PTR) :: c_ptr = c_null_ptr
37 END TYPE torch_dict_type
38
40 PRIVATE
41 TYPE(C_PTR) :: c_ptr = c_null_ptr
42 END TYPE torch_model_type
43
45 MODULE PROCEDURE torch_tensor_from_array_int32_1d
46 MODULE PROCEDURE torch_tensor_from_array_float_1d
47 MODULE PROCEDURE torch_tensor_from_array_int64_1d
48 MODULE PROCEDURE torch_tensor_from_array_double_1d
49 MODULE PROCEDURE torch_tensor_from_array_int32_2d
50 MODULE PROCEDURE torch_tensor_from_array_float_2d
51 MODULE PROCEDURE torch_tensor_from_array_int64_2d
52 MODULE PROCEDURE torch_tensor_from_array_double_2d
53 MODULE PROCEDURE torch_tensor_from_array_int32_3d
54 MODULE PROCEDURE torch_tensor_from_array_float_3d
55 MODULE PROCEDURE torch_tensor_from_array_int64_3d
56 MODULE PROCEDURE torch_tensor_from_array_double_3d
57 END INTERFACE torch_tensor_from_array
58
60 MODULE PROCEDURE torch_tensor_reset_from_array_double_1d
61 MODULE PROCEDURE torch_tensor_reset_from_array_double_2d
62 MODULE PROCEDURE torch_tensor_reset_from_array_double_3d
64
66 MODULE PROCEDURE torch_tensor_data_ptr_int32_1d
67 MODULE PROCEDURE torch_tensor_data_ptr_float_1d
68 MODULE PROCEDURE torch_tensor_data_ptr_int64_1d
69 MODULE PROCEDURE torch_tensor_data_ptr_double_1d
70 MODULE PROCEDURE torch_tensor_data_ptr_int32_2d
71 MODULE PROCEDURE torch_tensor_data_ptr_float_2d
72 MODULE PROCEDURE torch_tensor_data_ptr_int64_2d
73 MODULE PROCEDURE torch_tensor_data_ptr_double_2d
74 MODULE PROCEDURE torch_tensor_data_ptr_int32_3d
75 MODULE PROCEDURE torch_tensor_data_ptr_float_3d
76 MODULE PROCEDURE torch_tensor_data_ptr_int64_3d
77 MODULE PROCEDURE torch_tensor_data_ptr_double_3d
78 END INTERFACE torch_tensor_data_ptr
79
81 MODULE PROCEDURE torch_model_get_attr_string
82 MODULE PROCEDURE torch_model_get_attr_double
83 MODULE PROCEDURE torch_model_get_attr_int64
84 MODULE PROCEDURE torch_model_get_attr_int32
85 MODULE PROCEDURE torch_model_get_attr_strlist
86 END INTERFACE torch_model_get_attr
87
105
106CONTAINS
107
108
109
110! **************************************************************************************************
111!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
112!> The source must be an ALLOCATABLE to prevent passing a temporary array.
113!> \author Ole Schuett
114! **************************************************************************************************
115 SUBROUTINE torch_tensor_from_array_int32_1d(tensor, source, requires_grad)
116 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
117 INTEGER(kind=int_4), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: source
118 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
119
120#if defined(__LIBTORCH)
121 INTEGER(kind=int_8), DIMENSION(1) :: sizes_c
122 LOGICAL :: my_req_grad
123
124 INTERFACE
125 SUBROUTINE torch_c_tensor_from_array_int32 (tensor, req_grad, ndims, sizes, source) &
126 BIND(C, name="torch_c_tensor_from_array_int32")
127 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
128 TYPE(c_ptr) :: tensor
129 LOGICAL(kind=C_BOOL), VALUE :: req_grad
130 INTEGER(kind=C_INT), VALUE :: ndims
131 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
132 INTEGER(kind=C_INT32_T), DIMENSION(*) :: source
133 END SUBROUTINE torch_c_tensor_from_array_int32
134 END INTERFACE
135
136 my_req_grad = .false.
137 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
138
139 sizes_c(1) = SIZE(source, 1) ! C arrays are stored row-major.
140
141 cpassert(.NOT. c_associated(tensor%c_ptr))
142 CALL torch_c_tensor_from_array_int32 (tensor=tensor%c_ptr, &
143 req_grad=LOGICAL(my_req_grad, C_BOOL), &
144 ndims=1, &
145 sizes=sizes_c, &
146 source=source)
147 cpassert(c_associated(tensor%c_ptr))
148#else
149 cpabort("CP2K compiled without the Torch library.")
150 mark_used(tensor)
151 mark_used(source)
152 mark_used(requires_grad)
153#endif
154 END SUBROUTINE torch_tensor_from_array_int32_1d
155
156! **************************************************************************************************
157!> \brief Copies data from a Torch tensor to an array.
158!> The returned pointer is only valide during the tensor's lifetime!
159!> \author Ole Schuett
160! **************************************************************************************************
161 SUBROUTINE torch_tensor_data_ptr_int32_1d(tensor, data_ptr)
162 TYPE(torch_tensor_type), INTENT(IN) :: tensor
163 INTEGER(kind=int_4), DIMENSION(:), POINTER :: data_ptr
164
165#if defined(__LIBTORCH)
166 INTEGER(kind=int_8), DIMENSION(1) :: sizes_f, sizes_c
167 TYPE(c_ptr) :: data_ptr_c
168
169 INTERFACE
170 SUBROUTINE torch_c_tensor_data_ptr_int32 (tensor, ndims, sizes, data_ptr) &
171 BIND(C, name="torch_c_tensor_data_ptr_int32")
172 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
173 TYPE(c_ptr), VALUE :: tensor
174 INTEGER(kind=C_INT), VALUE :: ndims
175 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
176 TYPE(c_ptr) :: data_ptr
177 END SUBROUTINE torch_c_tensor_data_ptr_int32
178 END INTERFACE
179
180 sizes_c(:) = -1
181 data_ptr_c = c_null_ptr
182 cpassert(c_associated(tensor%c_ptr))
183 cpassert(.NOT. ASSOCIATED(data_ptr))
184 CALL torch_c_tensor_data_ptr_int32 (tensor=tensor%c_ptr, &
185 ndims=1, &
186 sizes=sizes_c, &
187 data_ptr=data_ptr_c)
188
189 sizes_f(1) = sizes_c(1) ! C arrays are stored row-major.
190
191 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
192 cpassert(c_associated(data_ptr_c))
193 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
194 END IF
195#else
196 cpabort("CP2K compiled without the Torch library.")
197 mark_used(tensor)
198 mark_used(data_ptr)
199#endif
200 END SUBROUTINE torch_tensor_data_ptr_int32_1d
201
202
203! **************************************************************************************************
204!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
205!> The source must be an ALLOCATABLE to prevent passing a temporary array.
206!> \author Ole Schuett
207! **************************************************************************************************
208 SUBROUTINE torch_tensor_from_array_float_1d(tensor, source, requires_grad)
209 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
210 REAL(sp), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: source
211 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
212
213#if defined(__LIBTORCH)
214 INTEGER(kind=int_8), DIMENSION(1) :: sizes_c
215 LOGICAL :: my_req_grad
216
217 INTERFACE
218 SUBROUTINE torch_c_tensor_from_array_float (tensor, req_grad, ndims, sizes, source) &
219 BIND(C, name="torch_c_tensor_from_array_float")
220 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
221 TYPE(c_ptr) :: tensor
222 LOGICAL(kind=C_BOOL), VALUE :: req_grad
223 INTEGER(kind=C_INT), VALUE :: ndims
224 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
225 REAL(kind=c_float), DIMENSION(*) :: source
226 END SUBROUTINE torch_c_tensor_from_array_float
227 END INTERFACE
228
229 my_req_grad = .false.
230 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
231
232 sizes_c(1) = SIZE(source, 1) ! C arrays are stored row-major.
233
234 cpassert(.NOT. c_associated(tensor%c_ptr))
235 CALL torch_c_tensor_from_array_float (tensor=tensor%c_ptr, &
236 req_grad=LOGICAL(my_req_grad, C_BOOL), &
237 ndims=1, &
238 sizes=sizes_c, &
239 source=source)
240 cpassert(c_associated(tensor%c_ptr))
241#else
242 cpabort("CP2K compiled without the Torch library.")
243 mark_used(tensor)
244 mark_used(source)
245 mark_used(requires_grad)
246#endif
247 END SUBROUTINE torch_tensor_from_array_float_1d
248
249! **************************************************************************************************
250!> \brief Copies data from a Torch tensor to an array.
251!> The returned pointer is only valide during the tensor's lifetime!
252!> \author Ole Schuett
253! **************************************************************************************************
254 SUBROUTINE torch_tensor_data_ptr_float_1d(tensor, data_ptr)
255 TYPE(torch_tensor_type), INTENT(IN) :: tensor
256 REAL(sp), DIMENSION(:), POINTER :: data_ptr
257
258#if defined(__LIBTORCH)
259 INTEGER(kind=int_8), DIMENSION(1) :: sizes_f, sizes_c
260 TYPE(c_ptr) :: data_ptr_c
261
262 INTERFACE
263 SUBROUTINE torch_c_tensor_data_ptr_float (tensor, ndims, sizes, data_ptr) &
264 BIND(C, name="torch_c_tensor_data_ptr_float")
265 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
266 TYPE(c_ptr), VALUE :: tensor
267 INTEGER(kind=C_INT), VALUE :: ndims
268 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
269 TYPE(c_ptr) :: data_ptr
270 END SUBROUTINE torch_c_tensor_data_ptr_float
271 END INTERFACE
272
273 sizes_c(:) = -1
274 data_ptr_c = c_null_ptr
275 cpassert(c_associated(tensor%c_ptr))
276 cpassert(.NOT. ASSOCIATED(data_ptr))
277 CALL torch_c_tensor_data_ptr_float (tensor=tensor%c_ptr, &
278 ndims=1, &
279 sizes=sizes_c, &
280 data_ptr=data_ptr_c)
281
282 sizes_f(1) = sizes_c(1) ! C arrays are stored row-major.
283
284 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
285 cpassert(c_associated(data_ptr_c))
286 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
287 END IF
288#else
289 cpabort("CP2K compiled without the Torch library.")
290 mark_used(tensor)
291 mark_used(data_ptr)
292#endif
293 END SUBROUTINE torch_tensor_data_ptr_float_1d
294
295
296! **************************************************************************************************
297!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
298!> The source must be an ALLOCATABLE to prevent passing a temporary array.
299!> \author Ole Schuett
300! **************************************************************************************************
301 SUBROUTINE torch_tensor_from_array_int64_1d(tensor, source, requires_grad)
302 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
303 INTEGER(kind=int_8), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: source
304 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
305
306#if defined(__LIBTORCH)
307 INTEGER(kind=int_8), DIMENSION(1) :: sizes_c
308 LOGICAL :: my_req_grad
309
310 INTERFACE
311 SUBROUTINE torch_c_tensor_from_array_int64 (tensor, req_grad, ndims, sizes, source) &
312 BIND(C, name="torch_c_tensor_from_array_int64")
313 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
314 TYPE(c_ptr) :: tensor
315 LOGICAL(kind=C_BOOL), VALUE :: req_grad
316 INTEGER(kind=C_INT), VALUE :: ndims
317 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
318 INTEGER(kind=C_INT64_T), DIMENSION(*) :: source
319 END SUBROUTINE torch_c_tensor_from_array_int64
320 END INTERFACE
321
322 my_req_grad = .false.
323 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
324
325 sizes_c(1) = SIZE(source, 1) ! C arrays are stored row-major.
326
327 cpassert(.NOT. c_associated(tensor%c_ptr))
328 CALL torch_c_tensor_from_array_int64 (tensor=tensor%c_ptr, &
329 req_grad=LOGICAL(my_req_grad, C_BOOL), &
330 ndims=1, &
331 sizes=sizes_c, &
332 source=source)
333 cpassert(c_associated(tensor%c_ptr))
334#else
335 cpabort("CP2K compiled without the Torch library.")
336 mark_used(tensor)
337 mark_used(source)
338 mark_used(requires_grad)
339#endif
340 END SUBROUTINE torch_tensor_from_array_int64_1d
341
342! **************************************************************************************************
343!> \brief Copies data from a Torch tensor to an array.
344!> The returned pointer is only valide during the tensor's lifetime!
345!> \author Ole Schuett
346! **************************************************************************************************
347 SUBROUTINE torch_tensor_data_ptr_int64_1d(tensor, data_ptr)
348 TYPE(torch_tensor_type), INTENT(IN) :: tensor
349 INTEGER(kind=int_8), DIMENSION(:), POINTER :: data_ptr
350
351#if defined(__LIBTORCH)
352 INTEGER(kind=int_8), DIMENSION(1) :: sizes_f, sizes_c
353 TYPE(c_ptr) :: data_ptr_c
354
355 INTERFACE
356 SUBROUTINE torch_c_tensor_data_ptr_int64 (tensor, ndims, sizes, data_ptr) &
357 BIND(C, name="torch_c_tensor_data_ptr_int64")
358 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
359 TYPE(c_ptr), VALUE :: tensor
360 INTEGER(kind=C_INT), VALUE :: ndims
361 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
362 TYPE(c_ptr) :: data_ptr
363 END SUBROUTINE torch_c_tensor_data_ptr_int64
364 END INTERFACE
365
366 sizes_c(:) = -1
367 data_ptr_c = c_null_ptr
368 cpassert(c_associated(tensor%c_ptr))
369 cpassert(.NOT. ASSOCIATED(data_ptr))
370 CALL torch_c_tensor_data_ptr_int64 (tensor=tensor%c_ptr, &
371 ndims=1, &
372 sizes=sizes_c, &
373 data_ptr=data_ptr_c)
374
375 sizes_f(1) = sizes_c(1) ! C arrays are stored row-major.
376
377 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
378 cpassert(c_associated(data_ptr_c))
379 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
380 END IF
381#else
382 cpabort("CP2K compiled without the Torch library.")
383 mark_used(tensor)
384 mark_used(data_ptr)
385#endif
386 END SUBROUTINE torch_tensor_data_ptr_int64_1d
387
388
389! **************************************************************************************************
390!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
391!> The source must be an ALLOCATABLE to prevent passing a temporary array.
392!> \author Ole Schuett
393! **************************************************************************************************
394 SUBROUTINE torch_tensor_from_array_double_1d(tensor, source, requires_grad)
395 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
396 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: source
397 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
398
399#if defined(__LIBTORCH)
400 INTEGER(kind=int_8), DIMENSION(1) :: sizes_c
401 LOGICAL :: my_req_grad
402
403 INTERFACE
404 SUBROUTINE torch_c_tensor_from_array_double (tensor, req_grad, ndims, sizes, source) &
405 BIND(C, name="torch_c_tensor_from_array_double")
406 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
407 TYPE(c_ptr) :: tensor
408 LOGICAL(kind=C_BOOL), VALUE :: req_grad
409 INTEGER(kind=C_INT), VALUE :: ndims
410 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
411 REAL(kind=c_double), DIMENSION(*) :: source
412 END SUBROUTINE torch_c_tensor_from_array_double
413 END INTERFACE
414
415 my_req_grad = .false.
416 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
417
418 sizes_c(1) = SIZE(source, 1) ! C arrays are stored row-major.
419
420 cpassert(.NOT. c_associated(tensor%c_ptr))
421 CALL torch_c_tensor_from_array_double (tensor=tensor%c_ptr, &
422 req_grad=LOGICAL(my_req_grad, C_BOOL), &
423 ndims=1, &
424 sizes=sizes_c, &
425 source=source)
426 cpassert(c_associated(tensor%c_ptr))
427#else
428 cpabort("CP2K compiled without the Torch library.")
429 mark_used(tensor)
430 mark_used(source)
431 mark_used(requires_grad)
432#endif
433 END SUBROUTINE torch_tensor_from_array_double_1d
434
435! **************************************************************************************************
436!> \brief Copies data from a Torch tensor to an array.
437!> The returned pointer is only valide during the tensor's lifetime!
438!> \author Ole Schuett
439! **************************************************************************************************
440 SUBROUTINE torch_tensor_data_ptr_double_1d(tensor, data_ptr)
441 TYPE(torch_tensor_type), INTENT(IN) :: tensor
442 REAL(dp), DIMENSION(:), POINTER :: data_ptr
443
444#if defined(__LIBTORCH)
445 INTEGER(kind=int_8), DIMENSION(1) :: sizes_f, sizes_c
446 TYPE(c_ptr) :: data_ptr_c
447
448 INTERFACE
449 SUBROUTINE torch_c_tensor_data_ptr_double (tensor, ndims, sizes, data_ptr) &
450 BIND(C, name="torch_c_tensor_data_ptr_double")
451 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
452 TYPE(c_ptr), VALUE :: tensor
453 INTEGER(kind=C_INT), VALUE :: ndims
454 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
455 TYPE(c_ptr) :: data_ptr
456 END SUBROUTINE torch_c_tensor_data_ptr_double
457 END INTERFACE
458
459 sizes_c(:) = -1
460 data_ptr_c = c_null_ptr
461 cpassert(c_associated(tensor%c_ptr))
462 cpassert(.NOT. ASSOCIATED(data_ptr))
463 CALL torch_c_tensor_data_ptr_double (tensor=tensor%c_ptr, &
464 ndims=1, &
465 sizes=sizes_c, &
466 data_ptr=data_ptr_c)
467
468 sizes_f(1) = sizes_c(1) ! C arrays are stored row-major.
469
470 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
471 cpassert(c_associated(data_ptr_c))
472 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
473 END IF
474#else
475 cpabort("CP2K compiled without the Torch library.")
476 mark_used(tensor)
477 mark_used(data_ptr)
478#endif
479 END SUBROUTINE torch_tensor_data_ptr_double_1d
480
481
482! **************************************************************************************************
483!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
484!> The source must be an ALLOCATABLE to prevent passing a temporary array.
485!> \author Ole Schuett
486! **************************************************************************************************
487 SUBROUTINE torch_tensor_from_array_int32_2d(tensor, source, requires_grad)
488 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
489 INTEGER(kind=int_4), DIMENSION(:, :), ALLOCATABLE, INTENT(IN) :: source
490 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
491
492#if defined(__LIBTORCH)
493 INTEGER(kind=int_8), DIMENSION(2) :: sizes_c
494 LOGICAL :: my_req_grad
495
496 INTERFACE
497 SUBROUTINE torch_c_tensor_from_array_int32 (tensor, req_grad, ndims, sizes, source) &
498 BIND(C, name="torch_c_tensor_from_array_int32")
499 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
500 TYPE(c_ptr) :: tensor
501 LOGICAL(kind=C_BOOL), VALUE :: req_grad
502 INTEGER(kind=C_INT), VALUE :: ndims
503 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
504 INTEGER(kind=C_INT32_T), DIMENSION(*) :: source
505 END SUBROUTINE torch_c_tensor_from_array_int32
506 END INTERFACE
507
508 my_req_grad = .false.
509 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
510
511 sizes_c(1) = SIZE(source, 2) ! C arrays are stored row-major.
512 sizes_c(2) = SIZE(source, 1) ! C arrays are stored row-major.
513
514 cpassert(.NOT. c_associated(tensor%c_ptr))
515 CALL torch_c_tensor_from_array_int32 (tensor=tensor%c_ptr, &
516 req_grad=LOGICAL(my_req_grad, C_BOOL), &
517 ndims=2, &
518 sizes=sizes_c, &
519 source=source)
520 cpassert(c_associated(tensor%c_ptr))
521#else
522 cpabort("CP2K compiled without the Torch library.")
523 mark_used(tensor)
524 mark_used(source)
525 mark_used(requires_grad)
526#endif
527 END SUBROUTINE torch_tensor_from_array_int32_2d
528
529! **************************************************************************************************
530!> \brief Copies data from a Torch tensor to an array.
531!> The returned pointer is only valide during the tensor's lifetime!
532!> \author Ole Schuett
533! **************************************************************************************************
534 SUBROUTINE torch_tensor_data_ptr_int32_2d(tensor, data_ptr)
535 TYPE(torch_tensor_type), INTENT(IN) :: tensor
536 INTEGER(kind=int_4), DIMENSION(:, :), POINTER :: data_ptr
537
538#if defined(__LIBTORCH)
539 INTEGER(kind=int_8), DIMENSION(2) :: sizes_f, sizes_c
540 TYPE(c_ptr) :: data_ptr_c
541
542 INTERFACE
543 SUBROUTINE torch_c_tensor_data_ptr_int32 (tensor, ndims, sizes, data_ptr) &
544 BIND(C, name="torch_c_tensor_data_ptr_int32")
545 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
546 TYPE(c_ptr), VALUE :: tensor
547 INTEGER(kind=C_INT), VALUE :: ndims
548 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
549 TYPE(c_ptr) :: data_ptr
550 END SUBROUTINE torch_c_tensor_data_ptr_int32
551 END INTERFACE
552
553 sizes_c(:) = -1
554 data_ptr_c = c_null_ptr
555 cpassert(c_associated(tensor%c_ptr))
556 cpassert(.NOT. ASSOCIATED(data_ptr))
557 CALL torch_c_tensor_data_ptr_int32 (tensor=tensor%c_ptr, &
558 ndims=2, &
559 sizes=sizes_c, &
560 data_ptr=data_ptr_c)
561
562 sizes_f(1) = sizes_c(2) ! C arrays are stored row-major.
563 sizes_f(2) = sizes_c(1) ! C arrays are stored row-major.
564
565 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
566 cpassert(c_associated(data_ptr_c))
567 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
568 END IF
569#else
570 cpabort("CP2K compiled without the Torch library.")
571 mark_used(tensor)
572 mark_used(data_ptr)
573#endif
574 END SUBROUTINE torch_tensor_data_ptr_int32_2d
575
576
577! **************************************************************************************************
578!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
579!> The source must be an ALLOCATABLE to prevent passing a temporary array.
580!> \author Ole Schuett
581! **************************************************************************************************
582 SUBROUTINE torch_tensor_from_array_float_2d(tensor, source, requires_grad)
583 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
584 REAL(sp), DIMENSION(:, :), ALLOCATABLE, INTENT(IN) :: source
585 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
586
587#if defined(__LIBTORCH)
588 INTEGER(kind=int_8), DIMENSION(2) :: sizes_c
589 LOGICAL :: my_req_grad
590
591 INTERFACE
592 SUBROUTINE torch_c_tensor_from_array_float (tensor, req_grad, ndims, sizes, source) &
593 BIND(C, name="torch_c_tensor_from_array_float")
594 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
595 TYPE(c_ptr) :: tensor
596 LOGICAL(kind=C_BOOL), VALUE :: req_grad
597 INTEGER(kind=C_INT), VALUE :: ndims
598 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
599 REAL(kind=c_float), DIMENSION(*) :: source
600 END SUBROUTINE torch_c_tensor_from_array_float
601 END INTERFACE
602
603 my_req_grad = .false.
604 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
605
606 sizes_c(1) = SIZE(source, 2) ! C arrays are stored row-major.
607 sizes_c(2) = SIZE(source, 1) ! C arrays are stored row-major.
608
609 cpassert(.NOT. c_associated(tensor%c_ptr))
610 CALL torch_c_tensor_from_array_float (tensor=tensor%c_ptr, &
611 req_grad=LOGICAL(my_req_grad, C_BOOL), &
612 ndims=2, &
613 sizes=sizes_c, &
614 source=source)
615 cpassert(c_associated(tensor%c_ptr))
616#else
617 cpabort("CP2K compiled without the Torch library.")
618 mark_used(tensor)
619 mark_used(source)
620 mark_used(requires_grad)
621#endif
622 END SUBROUTINE torch_tensor_from_array_float_2d
623
624! **************************************************************************************************
625!> \brief Copies data from a Torch tensor to an array.
626!> The returned pointer is only valide during the tensor's lifetime!
627!> \author Ole Schuett
628! **************************************************************************************************
629 SUBROUTINE torch_tensor_data_ptr_float_2d(tensor, data_ptr)
630 TYPE(torch_tensor_type), INTENT(IN) :: tensor
631 REAL(sp), DIMENSION(:, :), POINTER :: data_ptr
632
633#if defined(__LIBTORCH)
634 INTEGER(kind=int_8), DIMENSION(2) :: sizes_f, sizes_c
635 TYPE(c_ptr) :: data_ptr_c
636
637 INTERFACE
638 SUBROUTINE torch_c_tensor_data_ptr_float (tensor, ndims, sizes, data_ptr) &
639 BIND(C, name="torch_c_tensor_data_ptr_float")
640 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
641 TYPE(c_ptr), VALUE :: tensor
642 INTEGER(kind=C_INT), VALUE :: ndims
643 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
644 TYPE(c_ptr) :: data_ptr
645 END SUBROUTINE torch_c_tensor_data_ptr_float
646 END INTERFACE
647
648 sizes_c(:) = -1
649 data_ptr_c = c_null_ptr
650 cpassert(c_associated(tensor%c_ptr))
651 cpassert(.NOT. ASSOCIATED(data_ptr))
652 CALL torch_c_tensor_data_ptr_float (tensor=tensor%c_ptr, &
653 ndims=2, &
654 sizes=sizes_c, &
655 data_ptr=data_ptr_c)
656
657 sizes_f(1) = sizes_c(2) ! C arrays are stored row-major.
658 sizes_f(2) = sizes_c(1) ! C arrays are stored row-major.
659
660 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
661 cpassert(c_associated(data_ptr_c))
662 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
663 END IF
664#else
665 cpabort("CP2K compiled without the Torch library.")
666 mark_used(tensor)
667 mark_used(data_ptr)
668#endif
669 END SUBROUTINE torch_tensor_data_ptr_float_2d
670
671
672! **************************************************************************************************
673!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
674!> The source must be an ALLOCATABLE to prevent passing a temporary array.
675!> \author Ole Schuett
676! **************************************************************************************************
677 SUBROUTINE torch_tensor_from_array_int64_2d(tensor, source, requires_grad)
678 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
679 INTEGER(kind=int_8), DIMENSION(:, :), ALLOCATABLE, INTENT(IN) :: source
680 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
681
682#if defined(__LIBTORCH)
683 INTEGER(kind=int_8), DIMENSION(2) :: sizes_c
684 LOGICAL :: my_req_grad
685
686 INTERFACE
687 SUBROUTINE torch_c_tensor_from_array_int64 (tensor, req_grad, ndims, sizes, source) &
688 BIND(C, name="torch_c_tensor_from_array_int64")
689 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
690 TYPE(c_ptr) :: tensor
691 LOGICAL(kind=C_BOOL), VALUE :: req_grad
692 INTEGER(kind=C_INT), VALUE :: ndims
693 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
694 INTEGER(kind=C_INT64_T), DIMENSION(*) :: source
695 END SUBROUTINE torch_c_tensor_from_array_int64
696 END INTERFACE
697
698 my_req_grad = .false.
699 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
700
701 sizes_c(1) = SIZE(source, 2) ! C arrays are stored row-major.
702 sizes_c(2) = SIZE(source, 1) ! C arrays are stored row-major.
703
704 cpassert(.NOT. c_associated(tensor%c_ptr))
705 CALL torch_c_tensor_from_array_int64 (tensor=tensor%c_ptr, &
706 req_grad=LOGICAL(my_req_grad, C_BOOL), &
707 ndims=2, &
708 sizes=sizes_c, &
709 source=source)
710 cpassert(c_associated(tensor%c_ptr))
711#else
712 cpabort("CP2K compiled without the Torch library.")
713 mark_used(tensor)
714 mark_used(source)
715 mark_used(requires_grad)
716#endif
717 END SUBROUTINE torch_tensor_from_array_int64_2d
718
719! **************************************************************************************************
720!> \brief Copies data from a Torch tensor to an array.
721!> The returned pointer is only valide during the tensor's lifetime!
722!> \author Ole Schuett
723! **************************************************************************************************
724 SUBROUTINE torch_tensor_data_ptr_int64_2d(tensor, data_ptr)
725 TYPE(torch_tensor_type), INTENT(IN) :: tensor
726 INTEGER(kind=int_8), DIMENSION(:, :), POINTER :: data_ptr
727
728#if defined(__LIBTORCH)
729 INTEGER(kind=int_8), DIMENSION(2) :: sizes_f, sizes_c
730 TYPE(c_ptr) :: data_ptr_c
731
732 INTERFACE
733 SUBROUTINE torch_c_tensor_data_ptr_int64 (tensor, ndims, sizes, data_ptr) &
734 BIND(C, name="torch_c_tensor_data_ptr_int64")
735 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
736 TYPE(c_ptr), VALUE :: tensor
737 INTEGER(kind=C_INT), VALUE :: ndims
738 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
739 TYPE(c_ptr) :: data_ptr
740 END SUBROUTINE torch_c_tensor_data_ptr_int64
741 END INTERFACE
742
743 sizes_c(:) = -1
744 data_ptr_c = c_null_ptr
745 cpassert(c_associated(tensor%c_ptr))
746 cpassert(.NOT. ASSOCIATED(data_ptr))
747 CALL torch_c_tensor_data_ptr_int64 (tensor=tensor%c_ptr, &
748 ndims=2, &
749 sizes=sizes_c, &
750 data_ptr=data_ptr_c)
751
752 sizes_f(1) = sizes_c(2) ! C arrays are stored row-major.
753 sizes_f(2) = sizes_c(1) ! C arrays are stored row-major.
754
755 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
756 cpassert(c_associated(data_ptr_c))
757 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
758 END IF
759#else
760 cpabort("CP2K compiled without the Torch library.")
761 mark_used(tensor)
762 mark_used(data_ptr)
763#endif
764 END SUBROUTINE torch_tensor_data_ptr_int64_2d
765
766
767! **************************************************************************************************
768!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
769!> The source must be an ALLOCATABLE to prevent passing a temporary array.
770!> \author Ole Schuett
771! **************************************************************************************************
772 SUBROUTINE torch_tensor_from_array_double_2d(tensor, source, requires_grad)
773 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
774 REAL(dp), DIMENSION(:, :), ALLOCATABLE, INTENT(IN) :: source
775 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
776
777#if defined(__LIBTORCH)
778 INTEGER(kind=int_8), DIMENSION(2) :: sizes_c
779 LOGICAL :: my_req_grad
780
781 INTERFACE
782 SUBROUTINE torch_c_tensor_from_array_double (tensor, req_grad, ndims, sizes, source) &
783 BIND(C, name="torch_c_tensor_from_array_double")
784 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
785 TYPE(c_ptr) :: tensor
786 LOGICAL(kind=C_BOOL), VALUE :: req_grad
787 INTEGER(kind=C_INT), VALUE :: ndims
788 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
789 REAL(kind=c_double), DIMENSION(*) :: source
790 END SUBROUTINE torch_c_tensor_from_array_double
791 END INTERFACE
792
793 my_req_grad = .false.
794 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
795
796 sizes_c(1) = SIZE(source, 2) ! C arrays are stored row-major.
797 sizes_c(2) = SIZE(source, 1) ! C arrays are stored row-major.
798
799 cpassert(.NOT. c_associated(tensor%c_ptr))
800 CALL torch_c_tensor_from_array_double (tensor=tensor%c_ptr, &
801 req_grad=LOGICAL(my_req_grad, C_BOOL), &
802 ndims=2, &
803 sizes=sizes_c, &
804 source=source)
805 cpassert(c_associated(tensor%c_ptr))
806#else
807 cpabort("CP2K compiled without the Torch library.")
808 mark_used(tensor)
809 mark_used(source)
810 mark_used(requires_grad)
811#endif
812 END SUBROUTINE torch_tensor_from_array_double_2d
813
814! **************************************************************************************************
815!> \brief Copies data from a Torch tensor to an array.
816!> The returned pointer is only valide during the tensor's lifetime!
817!> \author Ole Schuett
818! **************************************************************************************************
819 SUBROUTINE torch_tensor_data_ptr_double_2d(tensor, data_ptr)
820 TYPE(torch_tensor_type), INTENT(IN) :: tensor
821 REAL(dp), DIMENSION(:, :), POINTER :: data_ptr
822
823#if defined(__LIBTORCH)
824 INTEGER(kind=int_8), DIMENSION(2) :: sizes_f, sizes_c
825 TYPE(c_ptr) :: data_ptr_c
826
827 INTERFACE
828 SUBROUTINE torch_c_tensor_data_ptr_double (tensor, ndims, sizes, data_ptr) &
829 BIND(C, name="torch_c_tensor_data_ptr_double")
830 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
831 TYPE(c_ptr), VALUE :: tensor
832 INTEGER(kind=C_INT), VALUE :: ndims
833 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
834 TYPE(c_ptr) :: data_ptr
835 END SUBROUTINE torch_c_tensor_data_ptr_double
836 END INTERFACE
837
838 sizes_c(:) = -1
839 data_ptr_c = c_null_ptr
840 cpassert(c_associated(tensor%c_ptr))
841 cpassert(.NOT. ASSOCIATED(data_ptr))
842 CALL torch_c_tensor_data_ptr_double (tensor=tensor%c_ptr, &
843 ndims=2, &
844 sizes=sizes_c, &
845 data_ptr=data_ptr_c)
846
847 sizes_f(1) = sizes_c(2) ! C arrays are stored row-major.
848 sizes_f(2) = sizes_c(1) ! C arrays are stored row-major.
849
850 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
851 cpassert(c_associated(data_ptr_c))
852 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
853 END IF
854#else
855 cpabort("CP2K compiled without the Torch library.")
856 mark_used(tensor)
857 mark_used(data_ptr)
858#endif
859 END SUBROUTINE torch_tensor_data_ptr_double_2d
860
861
862! **************************************************************************************************
863!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
864!> The source must be an ALLOCATABLE to prevent passing a temporary array.
865!> \author Ole Schuett
866! **************************************************************************************************
867 SUBROUTINE torch_tensor_from_array_int32_3d(tensor, source, requires_grad)
868 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
869 INTEGER(kind=int_4), DIMENSION(:, :, :), ALLOCATABLE, INTENT(IN) :: source
870 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
871
872#if defined(__LIBTORCH)
873 INTEGER(kind=int_8), DIMENSION(3) :: sizes_c
874 LOGICAL :: my_req_grad
875
876 INTERFACE
877 SUBROUTINE torch_c_tensor_from_array_int32 (tensor, req_grad, ndims, sizes, source) &
878 BIND(C, name="torch_c_tensor_from_array_int32")
879 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
880 TYPE(c_ptr) :: tensor
881 LOGICAL(kind=C_BOOL), VALUE :: req_grad
882 INTEGER(kind=C_INT), VALUE :: ndims
883 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
884 INTEGER(kind=C_INT32_T), DIMENSION(*) :: source
885 END SUBROUTINE torch_c_tensor_from_array_int32
886 END INTERFACE
887
888 my_req_grad = .false.
889 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
890
891 sizes_c(1) = SIZE(source, 3) ! C arrays are stored row-major.
892 sizes_c(2) = SIZE(source, 2) ! C arrays are stored row-major.
893 sizes_c(3) = SIZE(source, 1) ! C arrays are stored row-major.
894
895 cpassert(.NOT. c_associated(tensor%c_ptr))
896 CALL torch_c_tensor_from_array_int32 (tensor=tensor%c_ptr, &
897 req_grad=LOGICAL(my_req_grad, C_BOOL), &
898 ndims=3, &
899 sizes=sizes_c, &
900 source=source)
901 cpassert(c_associated(tensor%c_ptr))
902#else
903 cpabort("CP2K compiled without the Torch library.")
904 mark_used(tensor)
905 mark_used(source)
906 mark_used(requires_grad)
907#endif
908 END SUBROUTINE torch_tensor_from_array_int32_3d
909
910! **************************************************************************************************
911!> \brief Copies data from a Torch tensor to an array.
912!> The returned pointer is only valide during the tensor's lifetime!
913!> \author Ole Schuett
914! **************************************************************************************************
915 SUBROUTINE torch_tensor_data_ptr_int32_3d(tensor, data_ptr)
916 TYPE(torch_tensor_type), INTENT(IN) :: tensor
917 INTEGER(kind=int_4), DIMENSION(:, :, :), POINTER :: data_ptr
918
919#if defined(__LIBTORCH)
920 INTEGER(kind=int_8), DIMENSION(3) :: sizes_f, sizes_c
921 TYPE(c_ptr) :: data_ptr_c
922
923 INTERFACE
924 SUBROUTINE torch_c_tensor_data_ptr_int32 (tensor, ndims, sizes, data_ptr) &
925 BIND(C, name="torch_c_tensor_data_ptr_int32")
926 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
927 TYPE(c_ptr), VALUE :: tensor
928 INTEGER(kind=C_INT), VALUE :: ndims
929 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
930 TYPE(c_ptr) :: data_ptr
931 END SUBROUTINE torch_c_tensor_data_ptr_int32
932 END INTERFACE
933
934 sizes_c(:) = -1
935 data_ptr_c = c_null_ptr
936 cpassert(c_associated(tensor%c_ptr))
937 cpassert(.NOT. ASSOCIATED(data_ptr))
938 CALL torch_c_tensor_data_ptr_int32 (tensor=tensor%c_ptr, &
939 ndims=3, &
940 sizes=sizes_c, &
941 data_ptr=data_ptr_c)
942
943 sizes_f(1) = sizes_c(3) ! C arrays are stored row-major.
944 sizes_f(2) = sizes_c(2) ! C arrays are stored row-major.
945 sizes_f(3) = sizes_c(1) ! C arrays are stored row-major.
946
947 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
948 cpassert(c_associated(data_ptr_c))
949 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
950 END IF
951#else
952 cpabort("CP2K compiled without the Torch library.")
953 mark_used(tensor)
954 mark_used(data_ptr)
955#endif
956 END SUBROUTINE torch_tensor_data_ptr_int32_3d
957
958
959! **************************************************************************************************
960!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
961!> The source must be an ALLOCATABLE to prevent passing a temporary array.
962!> \author Ole Schuett
963! **************************************************************************************************
964 SUBROUTINE torch_tensor_from_array_float_3d(tensor, source, requires_grad)
965 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
966 REAL(sp), DIMENSION(:, :, :), ALLOCATABLE, INTENT(IN) :: source
967 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
968
969#if defined(__LIBTORCH)
970 INTEGER(kind=int_8), DIMENSION(3) :: sizes_c
971 LOGICAL :: my_req_grad
972
973 INTERFACE
974 SUBROUTINE torch_c_tensor_from_array_float (tensor, req_grad, ndims, sizes, source) &
975 BIND(C, name="torch_c_tensor_from_array_float")
976 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
977 TYPE(c_ptr) :: tensor
978 LOGICAL(kind=C_BOOL), VALUE :: req_grad
979 INTEGER(kind=C_INT), VALUE :: ndims
980 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
981 REAL(kind=c_float), DIMENSION(*) :: source
982 END SUBROUTINE torch_c_tensor_from_array_float
983 END INTERFACE
984
985 my_req_grad = .false.
986 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
987
988 sizes_c(1) = SIZE(source, 3) ! C arrays are stored row-major.
989 sizes_c(2) = SIZE(source, 2) ! C arrays are stored row-major.
990 sizes_c(3) = SIZE(source, 1) ! C arrays are stored row-major.
991
992 cpassert(.NOT. c_associated(tensor%c_ptr))
993 CALL torch_c_tensor_from_array_float (tensor=tensor%c_ptr, &
994 req_grad=LOGICAL(my_req_grad, C_BOOL), &
995 ndims=3, &
996 sizes=sizes_c, &
997 source=source)
998 cpassert(c_associated(tensor%c_ptr))
999#else
1000 cpabort("CP2K compiled without the Torch library.")
1001 mark_used(tensor)
1002 mark_used(source)
1003 mark_used(requires_grad)
1004#endif
1005 END SUBROUTINE torch_tensor_from_array_float_3d
1006
1007! **************************************************************************************************
1008!> \brief Copies data from a Torch tensor to an array.
1009!> The returned pointer is only valide during the tensor's lifetime!
1010!> \author Ole Schuett
1011! **************************************************************************************************
1012 SUBROUTINE torch_tensor_data_ptr_float_3d(tensor, data_ptr)
1013 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1014 REAL(sp), DIMENSION(:, :, :), POINTER :: data_ptr
1015
1016#if defined(__LIBTORCH)
1017 INTEGER(kind=int_8), DIMENSION(3) :: sizes_f, sizes_c
1018 TYPE(c_ptr) :: data_ptr_c
1019
1020 INTERFACE
1021 SUBROUTINE torch_c_tensor_data_ptr_float (tensor, ndims, sizes, data_ptr) &
1022 BIND(C, name="torch_c_tensor_data_ptr_float")
1023 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
1024 TYPE(c_ptr), VALUE :: tensor
1025 INTEGER(kind=C_INT), VALUE :: ndims
1026 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1027 TYPE(c_ptr) :: data_ptr
1028 END SUBROUTINE torch_c_tensor_data_ptr_float
1029 END INTERFACE
1030
1031 sizes_c(:) = -1
1032 data_ptr_c = c_null_ptr
1033 cpassert(c_associated(tensor%c_ptr))
1034 cpassert(.NOT. ASSOCIATED(data_ptr))
1035 CALL torch_c_tensor_data_ptr_float (tensor=tensor%c_ptr, &
1036 ndims=3, &
1037 sizes=sizes_c, &
1038 data_ptr=data_ptr_c)
1039
1040 sizes_f(1) = sizes_c(3) ! C arrays are stored row-major.
1041 sizes_f(2) = sizes_c(2) ! C arrays are stored row-major.
1042 sizes_f(3) = sizes_c(1) ! C arrays are stored row-major.
1043
1044 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
1045 cpassert(c_associated(data_ptr_c))
1046 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
1047 END IF
1048#else
1049 cpabort("CP2K compiled without the Torch library.")
1050 mark_used(tensor)
1051 mark_used(data_ptr)
1052#endif
1053 END SUBROUTINE torch_tensor_data_ptr_float_3d
1054
1055
1056! **************************************************************************************************
1057!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
1058!> The source must be an ALLOCATABLE to prevent passing a temporary array.
1059!> \author Ole Schuett
1060! **************************************************************************************************
1061 SUBROUTINE torch_tensor_from_array_int64_3d(tensor, source, requires_grad)
1062 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1063 INTEGER(kind=int_8), DIMENSION(:, :, :), ALLOCATABLE, INTENT(IN) :: source
1064 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
1065
1066#if defined(__LIBTORCH)
1067 INTEGER(kind=int_8), DIMENSION(3) :: sizes_c
1068 LOGICAL :: my_req_grad
1069
1070 INTERFACE
1071 SUBROUTINE torch_c_tensor_from_array_int64 (tensor, req_grad, ndims, sizes, source) &
1072 BIND(C, name="torch_c_tensor_from_array_int64")
1073 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
1074 TYPE(c_ptr) :: tensor
1075 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1076 INTEGER(kind=C_INT), VALUE :: ndims
1077 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1078 INTEGER(kind=C_INT64_T), DIMENSION(*) :: source
1079 END SUBROUTINE torch_c_tensor_from_array_int64
1080 END INTERFACE
1081
1082 my_req_grad = .false.
1083 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
1084
1085 sizes_c(1) = SIZE(source, 3) ! C arrays are stored row-major.
1086 sizes_c(2) = SIZE(source, 2) ! C arrays are stored row-major.
1087 sizes_c(3) = SIZE(source, 1) ! C arrays are stored row-major.
1088
1089 cpassert(.NOT. c_associated(tensor%c_ptr))
1090 CALL torch_c_tensor_from_array_int64 (tensor=tensor%c_ptr, &
1091 req_grad=LOGICAL(my_req_grad, C_BOOL), &
1092 ndims=3, &
1093 sizes=sizes_c, &
1094 source=source)
1095 cpassert(c_associated(tensor%c_ptr))
1096#else
1097 cpabort("CP2K compiled without the Torch library.")
1098 mark_used(tensor)
1099 mark_used(source)
1100 mark_used(requires_grad)
1101#endif
1102 END SUBROUTINE torch_tensor_from_array_int64_3d
1103
1104! **************************************************************************************************
1105!> \brief Copies data from a Torch tensor to an array.
1106!> The returned pointer is only valide during the tensor's lifetime!
1107!> \author Ole Schuett
1108! **************************************************************************************************
1109 SUBROUTINE torch_tensor_data_ptr_int64_3d(tensor, data_ptr)
1110 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1111 INTEGER(kind=int_8), DIMENSION(:, :, :), POINTER :: data_ptr
1112
1113#if defined(__LIBTORCH)
1114 INTEGER(kind=int_8), DIMENSION(3) :: sizes_f, sizes_c
1115 TYPE(c_ptr) :: data_ptr_c
1116
1117 INTERFACE
1118 SUBROUTINE torch_c_tensor_data_ptr_int64 (tensor, ndims, sizes, data_ptr) &
1119 BIND(C, name="torch_c_tensor_data_ptr_int64")
1120 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
1121 TYPE(c_ptr), VALUE :: tensor
1122 INTEGER(kind=C_INT), VALUE :: ndims
1123 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1124 TYPE(c_ptr) :: data_ptr
1125 END SUBROUTINE torch_c_tensor_data_ptr_int64
1126 END INTERFACE
1127
1128 sizes_c(:) = -1
1129 data_ptr_c = c_null_ptr
1130 cpassert(c_associated(tensor%c_ptr))
1131 cpassert(.NOT. ASSOCIATED(data_ptr))
1132 CALL torch_c_tensor_data_ptr_int64 (tensor=tensor%c_ptr, &
1133 ndims=3, &
1134 sizes=sizes_c, &
1135 data_ptr=data_ptr_c)
1136
1137 sizes_f(1) = sizes_c(3) ! C arrays are stored row-major.
1138 sizes_f(2) = sizes_c(2) ! C arrays are stored row-major.
1139 sizes_f(3) = sizes_c(1) ! C arrays are stored row-major.
1140
1141 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
1142 cpassert(c_associated(data_ptr_c))
1143 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
1144 END IF
1145#else
1146 cpabort("CP2K compiled without the Torch library.")
1147 mark_used(tensor)
1148 mark_used(data_ptr)
1149#endif
1150 END SUBROUTINE torch_tensor_data_ptr_int64_3d
1151
1152
1153! **************************************************************************************************
1154!> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
1155!> The source must be an ALLOCATABLE to prevent passing a temporary array.
1156!> \author Ole Schuett
1157! **************************************************************************************************
1158 SUBROUTINE torch_tensor_from_array_double_3d(tensor, source, requires_grad)
1159 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1160 REAL(dp), DIMENSION(:, :, :), ALLOCATABLE, INTENT(IN) :: source
1161 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
1162
1163#if defined(__LIBTORCH)
1164 INTEGER(kind=int_8), DIMENSION(3) :: sizes_c
1165 LOGICAL :: my_req_grad
1166
1167 INTERFACE
1168 SUBROUTINE torch_c_tensor_from_array_double (tensor, req_grad, ndims, sizes, source) &
1169 BIND(C, name="torch_c_tensor_from_array_double")
1170 IMPORT :: c_ptr, c_int, c_int32_t, c_int64_t, c_float, c_double, c_bool
1171 TYPE(c_ptr) :: tensor
1172 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1173 INTEGER(kind=C_INT), VALUE :: ndims
1174 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1175 REAL(kind=c_double), DIMENSION(*) :: source
1176 END SUBROUTINE torch_c_tensor_from_array_double
1177 END INTERFACE
1178
1179 my_req_grad = .false.
1180 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
1181
1182 sizes_c(1) = SIZE(source, 3) ! C arrays are stored row-major.
1183 sizes_c(2) = SIZE(source, 2) ! C arrays are stored row-major.
1184 sizes_c(3) = SIZE(source, 1) ! C arrays are stored row-major.
1185
1186 cpassert(.NOT. c_associated(tensor%c_ptr))
1187 CALL torch_c_tensor_from_array_double (tensor=tensor%c_ptr, &
1188 req_grad=LOGICAL(my_req_grad, C_BOOL), &
1189 ndims=3, &
1190 sizes=sizes_c, &
1191 source=source)
1192 cpassert(c_associated(tensor%c_ptr))
1193#else
1194 cpabort("CP2K compiled without the Torch library.")
1195 mark_used(tensor)
1196 mark_used(source)
1197 mark_used(requires_grad)
1198#endif
1199 END SUBROUTINE torch_tensor_from_array_double_3d
1200
1201! **************************************************************************************************
1202!> \brief Copies data from a Torch tensor to an array.
1203!> The returned pointer is only valide during the tensor's lifetime!
1204!> \author Ole Schuett
1205! **************************************************************************************************
1206 SUBROUTINE torch_tensor_data_ptr_double_3d(tensor, data_ptr)
1207 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1208 REAL(dp), DIMENSION(:, :, :), POINTER :: data_ptr
1209
1210#if defined(__LIBTORCH)
1211 INTEGER(kind=int_8), DIMENSION(3) :: sizes_f, sizes_c
1212 TYPE(c_ptr) :: data_ptr_c
1213
1214 INTERFACE
1215 SUBROUTINE torch_c_tensor_data_ptr_double (tensor, ndims, sizes, data_ptr) &
1216 BIND(C, name="torch_c_tensor_data_ptr_double")
1217 IMPORT :: c_char, c_ptr, c_int, c_int32_t, c_int64_t
1218 TYPE(c_ptr), VALUE :: tensor
1219 INTEGER(kind=C_INT), VALUE :: ndims
1220 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1221 TYPE(c_ptr) :: data_ptr
1222 END SUBROUTINE torch_c_tensor_data_ptr_double
1223 END INTERFACE
1224
1225 sizes_c(:) = -1
1226 data_ptr_c = c_null_ptr
1227 cpassert(c_associated(tensor%c_ptr))
1228 cpassert(.NOT. ASSOCIATED(data_ptr))
1229 CALL torch_c_tensor_data_ptr_double (tensor=tensor%c_ptr, &
1230 ndims=3, &
1231 sizes=sizes_c, &
1232 data_ptr=data_ptr_c)
1233
1234 sizes_f(1) = sizes_c(3) ! C arrays are stored row-major.
1235 sizes_f(2) = sizes_c(2) ! C arrays are stored row-major.
1236 sizes_f(3) = sizes_c(1) ! C arrays are stored row-major.
1237
1238 IF (all(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
1239 cpassert(c_associated(data_ptr_c))
1240 CALL c_f_pointer(data_ptr_c, data_ptr, shape=sizes_f)
1241 END IF
1242#else
1243 cpabort("CP2K compiled without the Torch library.")
1244 mark_used(tensor)
1245 mark_used(data_ptr)
1246#endif
1247 END SUBROUTINE torch_tensor_data_ptr_double_3d
1248
1249
1250
1251! **************************************************************************************************
1252!> \brief Reuses or creates a device leaf tensor and copies data into it.
1253!> The source must be an ALLOCATABLE to prevent passing a temporary array.
1254! **************************************************************************************************
1255 SUBROUTINE torch_tensor_reset_from_array_double_1d(tensor, source, requires_grad)
1256 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1257 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: source
1258 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
1259
1260#if defined(__LIBTORCH)
1261 INTEGER(kind=int_8), DIMENSION(1) :: sizes_c
1262 LOGICAL :: my_req_grad
1263
1264 INTERFACE
1265 SUBROUTINE torch_c_tensor_reset_from_array_double(tensor, req_grad, ndims, sizes, source) &
1266 BIND(C, name="torch_c_tensor_reset_from_array_double")
1267 IMPORT :: c_ptr, c_int, c_int64_t, c_double, c_bool
1268 TYPE(c_ptr) :: tensor
1269 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1270 INTEGER(kind=C_INT), VALUE :: ndims
1271 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1272 REAL(kind=c_double), DIMENSION(*) :: source
1273 END SUBROUTINE torch_c_tensor_reset_from_array_double
1274 END INTERFACE
1275
1276 my_req_grad = .false.
1277 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
1278
1279 sizes_c(1) = SIZE(source, 1) ! C arrays are stored row-major.
1280
1281 CALL torch_c_tensor_reset_from_array_double(tensor=tensor%c_ptr, &
1282 req_grad=LOGICAL(my_req_grad, C_BOOL), &
1283 ndims=1, &
1284 sizes=sizes_c, &
1285 source=source)
1286 cpassert(c_associated(tensor%c_ptr))
1287#else
1288 cpabort("CP2K compiled without the Torch library.")
1289 mark_used(tensor)
1290 mark_used(source)
1291 mark_used(requires_grad)
1292#endif
1293 END SUBROUTINE torch_tensor_reset_from_array_double_1d
1294
1295
1296! **************************************************************************************************
1297!> \brief Reuses or creates a device leaf tensor and copies data into it.
1298!> The source must be an ALLOCATABLE to prevent passing a temporary array.
1299! **************************************************************************************************
1300 SUBROUTINE torch_tensor_reset_from_array_double_2d(tensor, source, requires_grad)
1301 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1302 REAL(dp), DIMENSION(:, :), ALLOCATABLE, INTENT(IN) :: source
1303 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
1304
1305#if defined(__LIBTORCH)
1306 INTEGER(kind=int_8), DIMENSION(2) :: sizes_c
1307 LOGICAL :: my_req_grad
1308
1309 INTERFACE
1310 SUBROUTINE torch_c_tensor_reset_from_array_double(tensor, req_grad, ndims, sizes, source) &
1311 BIND(C, name="torch_c_tensor_reset_from_array_double")
1312 IMPORT :: c_ptr, c_int, c_int64_t, c_double, c_bool
1313 TYPE(c_ptr) :: tensor
1314 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1315 INTEGER(kind=C_INT), VALUE :: ndims
1316 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1317 REAL(kind=c_double), DIMENSION(*) :: source
1318 END SUBROUTINE torch_c_tensor_reset_from_array_double
1319 END INTERFACE
1320
1321 my_req_grad = .false.
1322 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
1323
1324 sizes_c(1) = SIZE(source, 2) ! C arrays are stored row-major.
1325 sizes_c(2) = SIZE(source, 1) ! C arrays are stored row-major.
1326
1327 CALL torch_c_tensor_reset_from_array_double(tensor=tensor%c_ptr, &
1328 req_grad=LOGICAL(my_req_grad, C_BOOL), &
1329 ndims=2, &
1330 sizes=sizes_c, &
1331 source=source)
1332 cpassert(c_associated(tensor%c_ptr))
1333#else
1334 cpabort("CP2K compiled without the Torch library.")
1335 mark_used(tensor)
1336 mark_used(source)
1337 mark_used(requires_grad)
1338#endif
1339 END SUBROUTINE torch_tensor_reset_from_array_double_2d
1340
1341
1342! **************************************************************************************************
1343!> \brief Reuses or creates a device leaf tensor and copies data into it.
1344!> The source must be an ALLOCATABLE to prevent passing a temporary array.
1345! **************************************************************************************************
1346 SUBROUTINE torch_tensor_reset_from_array_double_3d(tensor, source, requires_grad)
1347 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1348 REAL(dp), DIMENSION(:, :, :), ALLOCATABLE, INTENT(IN) :: source
1349 LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
1350
1351#if defined(__LIBTORCH)
1352 INTEGER(kind=int_8), DIMENSION(3) :: sizes_c
1353 LOGICAL :: my_req_grad
1354
1355 INTERFACE
1356 SUBROUTINE torch_c_tensor_reset_from_array_double(tensor, req_grad, ndims, sizes, source) &
1357 BIND(C, name="torch_c_tensor_reset_from_array_double")
1358 IMPORT :: c_ptr, c_int, c_int64_t, c_double, c_bool
1359 TYPE(c_ptr) :: tensor
1360 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1361 INTEGER(kind=C_INT), VALUE :: ndims
1362 INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
1363 REAL(kind=c_double), DIMENSION(*) :: source
1364 END SUBROUTINE torch_c_tensor_reset_from_array_double
1365 END INTERFACE
1366
1367 my_req_grad = .false.
1368 IF (PRESENT(requires_grad)) my_req_grad = requires_grad
1369
1370 sizes_c(1) = SIZE(source, 3) ! C arrays are stored row-major.
1371 sizes_c(2) = SIZE(source, 2) ! C arrays are stored row-major.
1372 sizes_c(3) = SIZE(source, 1) ! C arrays are stored row-major.
1373
1374 CALL torch_c_tensor_reset_from_array_double(tensor=tensor%c_ptr, &
1375 req_grad=LOGICAL(my_req_grad, C_BOOL), &
1376 ndims=3, &
1377 sizes=sizes_c, &
1378 source=source)
1379 cpassert(c_associated(tensor%c_ptr))
1380#else
1381 cpabort("CP2K compiled without the Torch library.")
1382 mark_used(tensor)
1383 mark_used(source)
1384 mark_used(requires_grad)
1385#endif
1386 END SUBROUTINE torch_tensor_reset_from_array_double_3d
1387
1388
1389! **************************************************************************************************
1390!> \brief Creates an expanded tensor view along one singleton dimension.
1391! **************************************************************************************************
1392 SUBROUTINE torch_tensor_expand_dim(tensor, dim, extent, result)
1393 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1394 INTEGER, INTENT(IN) :: dim, extent
1395 TYPE(torch_tensor_type), INTENT(INOUT) :: result
1396
1397#if defined(__LIBTORCH)
1398 INTERFACE
1399 SUBROUTINE torch_c_tensor_expand_dim(tensor, dim, extent, result) &
1400 BIND(C, name="torch_c_tensor_expand_dim")
1401 IMPORT :: c_int64_t, c_ptr
1402 TYPE(c_ptr), VALUE :: tensor
1403 INTEGER(kind=C_INT64_T), VALUE :: dim, extent
1404 TYPE(c_ptr) :: result
1405 END SUBROUTINE torch_c_tensor_expand_dim
1406 END INTERFACE
1407
1408 cpassert(c_associated(tensor%c_ptr))
1409 cpassert(.NOT. c_associated(result%c_ptr))
1410 cpassert(dim >= 0)
1411 cpassert(extent >= 0)
1412 CALL torch_c_tensor_expand_dim(tensor=tensor%c_ptr, &
1413 dim=int(dim, c_int64_t), &
1414 extent=int(extent, c_int64_t), &
1415 result=result%c_ptr)
1416 cpassert(c_associated(result%c_ptr))
1417#else
1418 cpabort("CP2K compiled without the Torch library.")
1419 mark_used(tensor)
1420 mark_used(dim)
1421 mark_used(extent)
1422 mark_used(result)
1423#endif
1424 END SUBROUTINE torch_tensor_expand_dim
1425
1426! **************************************************************************************************
1427!> \brief Creates a view of a contiguous tensor slice.
1428! **************************************************************************************************
1429 SUBROUTINE torch_tensor_narrow(tensor, dim, start_index, length, result)
1430 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1431 INTEGER, INTENT(IN) :: dim, start_index, length
1432 TYPE(torch_tensor_type), INTENT(INOUT) :: result
1433
1434#if defined(__LIBTORCH)
1435 INTERFACE
1436 SUBROUTINE torch_c_tensor_narrow(tensor, dim, start_index, length, result) &
1437 BIND(C, name="torch_c_tensor_narrow")
1438 IMPORT :: c_int64_t, c_ptr
1439 TYPE(c_ptr), VALUE :: tensor
1440 INTEGER(kind=C_INT64_T), VALUE :: dim, start_index, length
1441 TYPE(c_ptr) :: result
1442 END SUBROUTINE torch_c_tensor_narrow
1443 END INTERFACE
1444
1445 cpassert(c_associated(tensor%c_ptr))
1446 cpassert(.NOT. c_associated(result%c_ptr))
1447 cpassert(dim >= 0)
1448 cpassert(start_index >= 0)
1449 cpassert(length >= 0)
1450 CALL torch_c_tensor_narrow(tensor=tensor%c_ptr, &
1451 dim=int(dim, c_int64_t), &
1452 start_index=int(start_index, c_int64_t), &
1453 length=int(length, c_int64_t), &
1454 result=result%c_ptr)
1455 cpassert(c_associated(result%c_ptr))
1456#else
1457 cpabort("CP2K compiled without the Torch library.")
1458 mark_used(tensor)
1459 mark_used(dim)
1460 mark_used(start_index)
1461 mark_used(length)
1462 mark_used(result)
1463#endif
1464 END SUBROUTINE torch_tensor_narrow
1465
1466! **************************************************************************************************
1467!> \brief Runs autograd on a Torch tensor.
1468!> \author Ole Schuett
1469! **************************************************************************************************
1470 SUBROUTINE torch_tensor_backward(tensor, outer_grad)
1471 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1472 TYPE(torch_tensor_type), INTENT(IN) :: outer_grad
1473
1474#if defined(__LIBTORCH)
1475 CHARACTER(len=*), PARAMETER :: routinen = 'torch_tensor_backward'
1476 INTEGER :: handle
1477
1478 INTERFACE
1479 SUBROUTINE torch_c_tensor_backward(tensor, outer_grad) &
1480 BIND(C, name="torch_c_tensor_backward")
1481 IMPORT :: c_char, c_ptr
1482 TYPE(c_ptr), VALUE :: tensor
1483 TYPE(c_ptr), VALUE :: outer_grad
1484 END SUBROUTINE torch_c_tensor_backward
1485 END INTERFACE
1486
1487 CALL timeset(routinen, handle)
1488 cpassert(c_associated(tensor%c_ptr))
1489 cpassert(c_associated(outer_grad%c_ptr))
1490 CALL torch_c_tensor_backward(tensor=tensor%c_ptr, outer_grad=outer_grad%c_ptr)
1491 CALL timestop(handle)
1492#else
1493 cpabort("CP2K compiled without the Torch library.")
1494 mark_used(tensor)
1495 mark_used(outer_grad)
1496#endif
1497 END SUBROUTINE torch_tensor_backward
1498
1499! **************************************************************************************************
1500!> \brief Runs autograd on a scalar Torch tensor.
1501! **************************************************************************************************
1503 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1504
1505#if defined(__LIBTORCH)
1506 INTERFACE
1507 SUBROUTINE torch_c_tensor_backward_scalar(tensor) &
1508 BIND(C, name="torch_c_tensor_backward_scalar")
1509 IMPORT :: c_ptr
1510 TYPE(c_ptr), VALUE :: tensor
1511 END SUBROUTINE torch_c_tensor_backward_scalar
1512 END INTERFACE
1513
1514 cpassert(c_associated(tensor%c_ptr))
1515 CALL torch_c_tensor_backward_scalar(tensor=tensor%c_ptr)
1516#else
1517 cpabort("CP2K compiled without the Torch library.")
1518 mark_used(tensor)
1519#endif
1520 END SUBROUTINE torch_tensor_backward_scalar
1521
1522! **************************************************************************************************
1523!> \brief Moves a tensor to the active Torch device and makes it an autograd leaf.
1524! **************************************************************************************************
1525 SUBROUTINE torch_tensor_to_device_leaf(tensor, requires_grad)
1526 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1527 LOGICAL, INTENT(IN) :: requires_grad
1528
1529#if defined(__LIBTORCH)
1530 INTERFACE
1531 SUBROUTINE torch_c_tensor_to_device_leaf(tensor, req_grad) &
1532 BIND(C, name="torch_c_tensor_to_device_leaf")
1533 IMPORT :: c_bool, c_ptr
1534 TYPE(c_ptr) :: tensor
1535 LOGICAL(kind=C_BOOL), VALUE :: req_grad
1536 END SUBROUTINE torch_c_tensor_to_device_leaf
1537 END INTERFACE
1538
1539 cpassert(c_associated(tensor%c_ptr))
1540 CALL torch_c_tensor_to_device_leaf(tensor=tensor%c_ptr, &
1541 req_grad=LOGICAL(requires_grad, c_bool))
1542 cpassert(c_associated(tensor%c_ptr))
1543#else
1544 cpabort("CP2K compiled without the Torch library.")
1545 mark_used(tensor)
1546 mark_used(requires_grad)
1547#endif
1548 END SUBROUTINE torch_tensor_to_device_leaf
1549
1550! **************************************************************************************************
1551!> \brief Select whether Torch wrappers should use CUDA when available.
1552! **************************************************************************************************
1553 SUBROUTINE torch_use_cuda(use_cuda)
1554 LOGICAL, INTENT(IN) :: use_cuda
1555
1556#if defined(__LIBTORCH)
1557 INTERFACE
1558 SUBROUTINE torch_c_use_cuda(use_cuda) BIND(C, name="torch_c_use_cuda")
1559 IMPORT :: c_bool
1560 LOGICAL(kind=C_BOOL), VALUE :: use_cuda
1561 END SUBROUTINE torch_c_use_cuda
1562 END INTERFACE
1563
1564 CALL torch_c_use_cuda(use_cuda=LOGICAL(use_cuda, c_bool))
1565#else
1566 mark_used(use_cuda)
1567#endif
1568 END SUBROUTINE torch_use_cuda
1569
1570! **************************************************************************************************
1571!> \brief Returns the gradient of a Torch tensor which was computed by autograd.
1572!> \author Ole Schuett
1573! **************************************************************************************************
1574 SUBROUTINE torch_tensor_grad(tensor, grad)
1575 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1576 TYPE(torch_tensor_type), INTENT(INOUT) :: grad
1577
1578#if defined(__LIBTORCH)
1579 INTERFACE
1580 SUBROUTINE torch_c_tensor_grad(tensor, grad) &
1581 BIND(C, name="torch_c_tensor_grad")
1582 IMPORT :: c_ptr
1583 TYPE(c_ptr), VALUE :: tensor
1584 TYPE(c_ptr) :: grad
1585 END SUBROUTINE torch_c_tensor_grad
1586 END INTERFACE
1587
1588 cpassert(c_associated(tensor%c_ptr))
1589 cpassert(.NOT. c_associated(grad%c_ptr))
1590 CALL torch_c_tensor_grad(tensor=tensor%c_ptr, grad=grad%c_ptr)
1591 cpassert(c_associated(grad%c_ptr))
1592#else
1593 cpabort("CP2K compiled without the Torch library.")
1594 mark_used(tensor)
1595 mark_used(grad)
1596#endif
1597 END SUBROUTINE torch_tensor_grad
1598
1599! **************************************************************************************************
1600!> \brief Copies three autograd gradients to CPU memory.
1601! **************************************************************************************************
1602 SUBROUTINE torch_tensor_grad_batch3(tensor1, tensor2, tensor3, grad1, grad2, grad3)
1603 TYPE(torch_tensor_type), INTENT(IN) :: tensor1, tensor2, tensor3
1604 TYPE(torch_tensor_type), INTENT(INOUT) :: grad1, grad2, grad3
1605
1606#if defined(__LIBTORCH)
1607 INTERFACE
1608 SUBROUTINE torch_c_tensor_grad_batch3(tensor1, tensor2, tensor3, grad1, grad2, grad3) &
1609 BIND(C, name="torch_c_tensor_grad_batch3")
1610 IMPORT :: c_ptr
1611 TYPE(c_ptr), VALUE :: tensor1, tensor2, tensor3
1612 TYPE(c_ptr) :: grad1, grad2, grad3
1613 END SUBROUTINE torch_c_tensor_grad_batch3
1614 END INTERFACE
1615
1616 cpassert(c_associated(tensor1%c_ptr))
1617 cpassert(c_associated(tensor2%c_ptr))
1618 cpassert(c_associated(tensor3%c_ptr))
1619 cpassert(.NOT. c_associated(grad1%c_ptr))
1620 cpassert(.NOT. c_associated(grad2%c_ptr))
1621 cpassert(.NOT. c_associated(grad3%c_ptr))
1622 CALL torch_c_tensor_grad_batch3(tensor1=tensor1%c_ptr, tensor2=tensor2%c_ptr, &
1623 tensor3=tensor3%c_ptr, grad1=grad1%c_ptr, &
1624 grad2=grad2%c_ptr, grad3=grad3%c_ptr)
1625 cpassert(c_associated(grad1%c_ptr))
1626 cpassert(c_associated(grad2%c_ptr))
1627 cpassert(c_associated(grad3%c_ptr))
1628#else
1629 cpabort("CP2K compiled without the Torch library.")
1630 mark_used(tensor1)
1631 mark_used(tensor2)
1632 mark_used(tensor3)
1633 mark_used(grad1)
1634 mark_used(grad2)
1635 mark_used(grad3)
1636#endif
1637 END SUBROUTINE torch_tensor_grad_batch3
1638
1639! **************************************************************************************************
1640!> \brief Returns the weighted sum of two Torch tensors.
1641! **************************************************************************************************
1642 SUBROUTINE torch_tensor_weighted_sum(values, weights, result)
1643 TYPE(torch_tensor_type), INTENT(IN) :: values, weights
1644 TYPE(torch_tensor_type), INTENT(INOUT) :: result
1645
1646#if defined(__LIBTORCH)
1647 INTERFACE
1648 SUBROUTINE torch_c_tensor_weighted_sum(values, weights, result) &
1649 BIND(C, name="torch_c_tensor_weighted_sum")
1650 IMPORT :: c_ptr
1651 TYPE(c_ptr), VALUE :: values
1652 TYPE(c_ptr), VALUE :: weights
1653 TYPE(c_ptr) :: result
1654 END SUBROUTINE torch_c_tensor_weighted_sum
1655 END INTERFACE
1656
1657 cpassert(c_associated(values%c_ptr))
1658 cpassert(c_associated(weights%c_ptr))
1659 cpassert(.NOT. c_associated(result%c_ptr))
1660 CALL torch_c_tensor_weighted_sum(values=values%c_ptr, weights=weights%c_ptr, result=result%c_ptr)
1661 cpassert(c_associated(result%c_ptr))
1662#else
1663 cpabort("CP2K compiled without the Torch library.")
1664 mark_used(values)
1665 mark_used(weights)
1666 mark_used(result)
1667#endif
1668 END SUBROUTINE torch_tensor_weighted_sum
1669
1670! **************************************************************************************************
1671!> \brief Returns a scalar double value from a Torch tensor.
1672! **************************************************************************************************
1673 FUNCTION torch_tensor_item_double(tensor) RESULT(value)
1674 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1675 REAL(kind=dp) :: value
1676
1677#if defined(__LIBTORCH)
1678 INTERFACE
1679 FUNCTION torch_c_tensor_item_double(tensor) RESULT(value) &
1680 BIND(C, name="torch_c_tensor_item_double")
1681 IMPORT :: c_double, c_ptr
1682 TYPE(c_ptr), VALUE :: tensor
1683 REAL(kind=c_double) :: value
1684 END FUNCTION torch_c_tensor_item_double
1685 END INTERFACE
1686
1687 cpassert(c_associated(tensor%c_ptr))
1688 value = torch_c_tensor_item_double(tensor=tensor%c_ptr)
1689#else
1690 value = 0.0_dp
1691 cpabort("CP2K compiled without the Torch library.")
1692 mark_used(tensor)
1693#endif
1694 END FUNCTION torch_tensor_item_double
1695
1696! **************************************************************************************************
1697!> \brief Releases a Torch tensor and all its ressources.
1698!> \author Ole Schuett
1699! **************************************************************************************************
1700 SUBROUTINE torch_tensor_release(tensor)
1701 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1702
1703#if defined(__LIBTORCH)
1704 INTERFACE
1705 SUBROUTINE torch_c_tensor_release(tensor) BIND(C, name="torch_c_tensor_release")
1706 IMPORT :: c_ptr
1707 TYPE(c_ptr), VALUE :: tensor
1708 END SUBROUTINE torch_c_tensor_release
1709 END INTERFACE
1710
1711 cpassert(c_associated(tensor%c_ptr))
1712 CALL torch_c_tensor_release(tensor=tensor%c_ptr)
1713 tensor%c_ptr = c_null_ptr
1714#else
1715 cpabort("CP2K was compiled without Torch library.")
1716 mark_used(tensor)
1717#endif
1718 END SUBROUTINE torch_tensor_release
1719
1720! **************************************************************************************************
1721!> \brief Creates an empty Torch dictionary.
1722!> \author Ole Schuett
1723! **************************************************************************************************
1724 SUBROUTINE torch_dict_create(dict)
1725 TYPE(torch_dict_type), INTENT(INOUT) :: dict
1726
1727#if defined(__LIBTORCH)
1728 INTERFACE
1729 SUBROUTINE torch_c_dict_create(dict) BIND(C, name="torch_c_dict_create")
1730 IMPORT :: c_ptr
1731 TYPE(c_ptr) :: dict
1732 END SUBROUTINE torch_c_dict_create
1733 END INTERFACE
1734
1735 cpassert(.NOT. c_associated(dict%c_ptr))
1736 CALL torch_c_dict_create(dict=dict%c_ptr)
1737 cpassert(c_associated(dict%c_ptr))
1738#else
1739 cpabort("CP2K was compiled without Torch library.")
1740 mark_used(dict)
1741#endif
1742 END SUBROUTINE torch_dict_create
1743
1744! **************************************************************************************************
1745!> \brief Clones a Torch dictionary.
1746! **************************************************************************************************
1747 SUBROUTINE torch_dict_clone(source, target)
1748 TYPE(torch_dict_type), INTENT(IN) :: source
1749 TYPE(torch_dict_type), INTENT(INOUT) :: target
1750
1751#if defined(__LIBTORCH)
1752 INTERFACE
1753 SUBROUTINE torch_c_dict_clone(source, target) BIND(C, name="torch_c_dict_clone")
1754 IMPORT :: c_ptr
1755 TYPE(c_ptr), VALUE :: source
1756 TYPE(c_ptr) :: target
1757 END SUBROUTINE torch_c_dict_clone
1758 END INTERFACE
1759
1760 cpassert(c_associated(source%c_ptr))
1761 cpassert(.NOT. c_associated(target%c_ptr))
1762 CALL torch_c_dict_clone(source=source%c_ptr, target=target%c_ptr)
1763 cpassert(c_associated(target%c_ptr))
1764#else
1765 cpabort("CP2K was compiled without Torch library.")
1766 mark_used(source)
1767 mark_used(target)
1768#endif
1769 END SUBROUTINE torch_dict_clone
1770
1771! **************************************************************************************************
1772!> \brief Inserts a Torch tensor into a Torch dictionary.
1773!> \author Ole Schuett
1774! **************************************************************************************************
1775 SUBROUTINE torch_dict_insert(dict, key, tensor)
1776 TYPE(torch_dict_type), INTENT(INOUT) :: dict
1777 CHARACTER(len=*), INTENT(IN) :: key
1778 TYPE(torch_tensor_type), INTENT(IN) :: tensor
1779
1780#if defined(__LIBTORCH)
1781
1782 INTERFACE
1783 SUBROUTINE torch_c_dict_insert(dict, key, tensor) &
1784 BIND(C, name="torch_c_dict_insert")
1785 IMPORT :: c_char, c_ptr
1786 TYPE(c_ptr), VALUE :: dict
1787 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
1788 TYPE(c_ptr), VALUE :: tensor
1789 END SUBROUTINE torch_c_dict_insert
1790 END INTERFACE
1791
1792 cpassert(c_associated(dict%c_ptr))
1793 cpassert(c_associated(tensor%c_ptr))
1794 CALL torch_c_dict_insert(dict=dict%c_ptr, key=trim(key)//c_null_char, tensor=tensor%c_ptr)
1795#else
1796 cpabort("CP2K compiled without the Torch library.")
1797 mark_used(dict)
1798 mark_used(key)
1799 mark_used(tensor)
1800#endif
1801 END SUBROUTINE torch_dict_insert
1802
1803! **************************************************************************************************
1804!> \brief Retrieves a Torch tensor from a Torch dictionary.
1805!> \author Ole Schuett
1806! **************************************************************************************************
1807 SUBROUTINE torch_dict_get(dict, key, tensor)
1808 TYPE(torch_dict_type), INTENT(IN) :: dict
1809 CHARACTER(len=*), INTENT(IN) :: key
1810 TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
1811
1812#if defined(__LIBTORCH)
1813
1814 INTERFACE
1815 SUBROUTINE torch_c_dict_get(dict, key, tensor) &
1816 BIND(C, name="torch_c_dict_get")
1817 IMPORT :: c_char, c_ptr
1818 TYPE(c_ptr), VALUE :: dict
1819 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
1820 TYPE(c_ptr) :: tensor
1821 END SUBROUTINE torch_c_dict_get
1822 END INTERFACE
1823
1824 cpassert(c_associated(dict%c_ptr))
1825 cpassert(.NOT. c_associated(tensor%c_ptr))
1826 CALL torch_c_dict_get(dict=dict%c_ptr, key=trim(key)//c_null_char, tensor=tensor%c_ptr)
1827 cpassert(c_associated(tensor%c_ptr))
1828
1829#else
1830 cpabort("CP2K compiled without the Torch library.")
1831 mark_used(dict)
1832 mark_used(key)
1833 mark_used(tensor)
1834#endif
1835 END SUBROUTINE torch_dict_get
1836
1837! **************************************************************************************************
1838!> \brief Releases a Torch dictionary and all its ressources.
1839!> \author Ole Schuett
1840! **************************************************************************************************
1841 SUBROUTINE torch_dict_release(dict)
1842 TYPE(torch_dict_type), INTENT(INOUT) :: dict
1843
1844#if defined(__LIBTORCH)
1845 INTERFACE
1846 SUBROUTINE torch_c_dict_release(dict) BIND(C, name="torch_c_dict_release")
1847 IMPORT :: c_ptr
1848 TYPE(c_ptr), VALUE :: dict
1849 END SUBROUTINE torch_c_dict_release
1850 END INTERFACE
1851
1852 cpassert(c_associated(dict%c_ptr))
1853 CALL torch_c_dict_release(dict=dict%c_ptr)
1854 dict%c_ptr = c_null_ptr
1855#else
1856 cpabort("CP2K was compiled without Torch library.")
1857 mark_used(dict)
1858#endif
1859 END SUBROUTINE torch_dict_release
1860
1861! **************************************************************************************************
1862!> \brief Loads a Torch model from given "*.pth" file. (In Torch lingo models are called modules)
1863!> \author Ole Schuett
1864! **************************************************************************************************
1865 SUBROUTINE torch_model_load(model, filename)
1866 TYPE(torch_model_type), INTENT(INOUT) :: model
1867 CHARACTER(len=*), INTENT(IN) :: filename
1868
1869#if defined(__LIBTORCH)
1870 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_load'
1871 INTEGER :: handle
1872
1873 INTERFACE
1874 SUBROUTINE torch_c_model_load(model, filename) BIND(C, name="torch_c_model_load")
1875 IMPORT :: c_ptr, c_char
1876 TYPE(c_ptr) :: model
1877 CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename
1878 END SUBROUTINE torch_c_model_load
1879 END INTERFACE
1880
1881 CALL timeset(routinen, handle)
1882 cpassert(.NOT. c_associated(model%c_ptr))
1883 CALL torch_c_model_load(model=model%c_ptr, filename=trim(filename)//c_null_char)
1884 cpassert(c_associated(model%c_ptr))
1885 CALL timestop(handle)
1886#else
1887 cpabort("CP2K was compiled without Torch library.")
1888 mark_used(model)
1889 mark_used(filename)
1890#endif
1891 END SUBROUTINE torch_model_load
1892
1893! **************************************************************************************************
1894!> \brief Loads a Torch model and reads two metadata entries in the same archive pass.
1895! **************************************************************************************************
1896 SUBROUTINE torch_model_load_with_metadata(model, filename, key1, value1, key2, value2)
1897 TYPE(torch_model_type), INTENT(INOUT) :: model
1898 CHARACTER(len=*), INTENT(IN) :: filename, key1, key2
1899 CHARACTER(:), ALLOCATABLE, INTENT(OUT) :: value1, value2
1900
1901#if defined(__LIBTORCH)
1902 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_load_with_metadata'
1903 INTEGER :: handle, length1, length2
1904 TYPE(c_ptr) :: content1_c, content2_c
1905
1906 INTERFACE
1907 SUBROUTINE torch_c_model_load_with_metadata(model, filename, key1, key2, &
1908 content1, length1, content2, length2) &
1909 BIND(C, name="torch_c_model_load_with_metadata")
1910 IMPORT :: c_char, c_int, c_ptr
1911 TYPE(c_ptr) :: model
1912 CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename, key1, key2
1913 TYPE(c_ptr) :: content1, content2
1914 INTEGER(kind=C_INT) :: length1, length2
1915 END SUBROUTINE torch_c_model_load_with_metadata
1916 END INTERFACE
1917
1918 CALL timeset(routinen, handle)
1919 cpassert(.NOT. c_associated(model%c_ptr))
1920 content1_c = c_null_ptr
1921 content2_c = c_null_ptr
1922 length1 = -1
1923 length2 = -1
1924 CALL torch_c_model_load_with_metadata(model=model%c_ptr, &
1925 filename=trim(filename)//c_null_char, &
1926 key1=trim(key1)//c_null_char, &
1927 key2=trim(key2)//c_null_char, &
1928 content1=content1_c, length1=length1, &
1929 content2=content2_c, length2=length2)
1930 cpassert(c_associated(model%c_ptr))
1931 CALL c_string_to_allocatable(content1_c, length1, value1)
1932 CALL c_string_to_allocatable(content2_c, length2, value2)
1933 CALL timestop(handle)
1934#else
1935 cpabort("CP2K was compiled without Torch library.")
1936 mark_used(model)
1937 mark_used(filename)
1938 mark_used(key1)
1939 mark_used(value1)
1940 mark_used(key2)
1941 mark_used(value2)
1942#endif
1943 END SUBROUTINE torch_model_load_with_metadata
1944
1945! **************************************************************************************************
1946!> \brief Maps serialized TorchScript device constants to the active Torch device.
1947! **************************************************************************************************
1949 TYPE(torch_model_type), INTENT(INOUT) :: model
1950
1951#if defined(__LIBTORCH)
1952 INTERFACE
1953 SUBROUTINE torch_c_model_remap_device_constants(model) &
1954 BIND(C, name="torch_c_model_remap_device_constants")
1955 IMPORT :: c_ptr
1956 TYPE(c_ptr), VALUE :: model
1957 END SUBROUTINE torch_c_model_remap_device_constants
1958 END INTERFACE
1959
1960 cpassert(c_associated(model%c_ptr))
1961 CALL torch_c_model_remap_device_constants(model=model%c_ptr)
1962#else
1963 cpabort("CP2K was compiled without Torch library.")
1964 mark_used(model)
1965#endif
1967
1968! **************************************************************************************************
1969!> \brief Disable gradients for inference-only model parameters.
1970! **************************************************************************************************
1972 TYPE(torch_model_type), INTENT(INOUT) :: model
1973
1974#if defined(__LIBTORCH)
1975 INTERFACE
1976 SUBROUTINE torch_c_model_disable_parameter_gradients(model) &
1977 BIND(C, name="torch_c_model_disable_parameter_gradients")
1978 IMPORT :: c_ptr
1979 TYPE(c_ptr), VALUE :: model
1980 END SUBROUTINE torch_c_model_disable_parameter_gradients
1981 END INTERFACE
1982
1983 cpassert(c_associated(model%c_ptr))
1984 CALL torch_c_model_disable_parameter_gradients(model=model%c_ptr)
1985#else
1986 cpabort("CP2K was compiled without Torch library.")
1987 mark_used(model)
1988#endif
1990
1991! **************************************************************************************************
1992!> \brief Evaluates the given Torch model.
1993!> \author Ole Schuett
1994! **************************************************************************************************
1995 SUBROUTINE torch_model_forward(model, inputs, outputs)
1996 TYPE(torch_model_type), INTENT(INOUT) :: model
1997 TYPE(torch_dict_type), INTENT(IN) :: inputs
1998 TYPE(torch_dict_type), INTENT(INOUT) :: outputs
1999
2000#if defined(__LIBTORCH)
2001 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_forward'
2002 INTEGER :: handle
2003
2004 INTERFACE
2005 SUBROUTINE torch_c_model_forward(model, inputs, outputs) BIND(C, name="torch_c_model_forward")
2006 IMPORT :: c_ptr
2007 TYPE(c_ptr), VALUE :: model
2008 TYPE(c_ptr), VALUE :: inputs
2009 TYPE(c_ptr), VALUE :: outputs
2010 END SUBROUTINE torch_c_model_forward
2011 END INTERFACE
2012
2013 CALL timeset(routinen, handle)
2014 cpassert(c_associated(model%c_ptr))
2015 cpassert(c_associated(inputs%c_ptr))
2016 cpassert(c_associated(outputs%c_ptr))
2017 CALL torch_c_model_forward(model=model%c_ptr, inputs=inputs%c_ptr, outputs=outputs%c_ptr)
2018 CALL timestop(handle)
2019#else
2020 cpabort("CP2K was compiled without Torch library.")
2021 mark_used(model)
2022 mark_used(inputs)
2023 mark_used(outputs)
2024#endif
2025 END SUBROUTINE torch_model_forward
2026
2027! **************************************************************************************************
2028!> \brief Evaluates a TorchScript model method expecting keyword argument "mol".
2029! **************************************************************************************************
2030 SUBROUTINE torch_model_forward_mol_tensor(model, method_name, inputs, output)
2031 TYPE(torch_model_type), INTENT(INOUT) :: model
2032 CHARACTER(len=*), INTENT(IN) :: method_name
2033 TYPE(torch_dict_type), INTENT(IN) :: inputs
2034 TYPE(torch_tensor_type), INTENT(INOUT) :: output
2035
2036#if defined(__LIBTORCH)
2037 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_forward_mol_tensor'
2038 INTEGER :: handle
2039
2040 INTERFACE
2041 SUBROUTINE torch_c_model_forward_mol_tensor(model, method_name, inputs, output) &
2042 BIND(C, name="torch_c_model_forward_mol_tensor")
2043 IMPORT :: c_char, c_ptr
2044 TYPE(c_ptr), VALUE :: model
2045 CHARACTER(kind=C_CHAR), DIMENSION(*) :: method_name
2046 TYPE(c_ptr), VALUE :: inputs
2047 TYPE(c_ptr) :: output
2048 END SUBROUTINE torch_c_model_forward_mol_tensor
2049 END INTERFACE
2050
2051 CALL timeset(routinen, handle)
2052 cpassert(c_associated(model%c_ptr))
2053 cpassert(c_associated(inputs%c_ptr))
2054 cpassert(.NOT. c_associated(output%c_ptr))
2055 CALL torch_c_model_forward_mol_tensor(model=model%c_ptr, &
2056 method_name=trim(method_name)//c_null_char, &
2057 inputs=inputs%c_ptr, &
2058 output=output%c_ptr)
2059 cpassert(c_associated(output%c_ptr))
2060 CALL timestop(handle)
2061#else
2062 cpabort("CP2K was compiled without Torch library.")
2063 mark_used(model)
2064 mark_used(method_name)
2065 mark_used(inputs)
2066 mark_used(output)
2067#endif
2068 END SUBROUTINE torch_model_forward_mol_tensor
2069
2070! **************************************************************************************************
2071!> \brief Releases a Torch model and all its ressources.
2072!> \author Ole Schuett
2073! **************************************************************************************************
2074 SUBROUTINE torch_model_release(model)
2075 TYPE(torch_model_type), INTENT(INOUT) :: model
2076
2077#if defined(__LIBTORCH)
2078 INTERFACE
2079 SUBROUTINE torch_c_model_release(model) BIND(C, name="torch_c_model_release")
2080 IMPORT :: c_ptr
2081 TYPE(c_ptr), VALUE :: model
2082 END SUBROUTINE torch_c_model_release
2083 END INTERFACE
2084
2085 cpassert(c_associated(model%c_ptr))
2086 CALL torch_c_model_release(model=model%c_ptr)
2087 model%c_ptr = c_null_ptr
2088#else
2089 cpabort("CP2K was compiled without Torch library.")
2090 mark_used(model)
2091#endif
2092 END SUBROUTINE torch_model_release
2093
2094! **************************************************************************************************
2095!> \brief Reads metadata entry from given "*.pth" file. (In Torch lingo they are called extra files)
2096!> \author Ole Schuett
2097! **************************************************************************************************
2098 FUNCTION torch_model_read_metadata(filename, key) RESULT(res)
2099 CHARACTER(len=*), INTENT(IN) :: filename, key
2100 CHARACTER(:), ALLOCATABLE :: res
2101
2102#if defined(__LIBTORCH)
2103 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_read_metadata'
2104 INTEGER :: handle
2105
2106 INTEGER :: length
2107 TYPE(c_ptr) :: content_c
2108
2109 INTERFACE
2110 SUBROUTINE torch_c_model_read_metadata(filename, key, content, length) &
2111 BIND(C, name="torch_c_model_read_metadata")
2112 IMPORT :: c_char, c_ptr, c_int
2113 CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename, key
2114 TYPE(c_ptr) :: content
2115 INTEGER(kind=C_INT) :: length
2116 END SUBROUTINE torch_c_model_read_metadata
2117 END INTERFACE
2118
2119 CALL timeset(routinen, handle)
2120 content_c = c_null_ptr
2121 length = -1
2122 CALL torch_c_model_read_metadata(filename=trim(filename)//c_null_char, &
2123 key=trim(key)//c_null_char, &
2124 content=content_c, &
2125 length=length)
2126 CALL c_string_to_allocatable(content_c, length, res)
2127 CALL timestop(handle)
2128#else
2129 res = ""
2130 mark_used(filename)
2131 mark_used(key)
2132 cpabort("CP2K was compiled without Torch library.")
2133#endif
2134 END FUNCTION torch_model_read_metadata
2135
2136! **************************************************************************************************
2137!> \brief Move a C-allocated null-terminated string into an allocatable Fortran string.
2138! **************************************************************************************************
2139 SUBROUTINE c_string_to_allocatable(content_c, length, res)
2140 TYPE(c_ptr), INTENT(INOUT) :: content_c
2141 INTEGER, INTENT(IN) :: length
2142 CHARACTER(:), ALLOCATABLE, INTENT(OUT) :: res
2143
2144#if defined(__LIBTORCH)
2145 CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(:), &
2146 POINTER :: content_f
2147 INTEGER :: i
2148
2149 INTERFACE
2150 SUBROUTINE torch_c_free_string(content) BIND(C, name="torch_c_free_string")
2151 IMPORT :: c_ptr
2152 TYPE(c_ptr), VALUE :: content
2153 END SUBROUTINE torch_c_free_string
2154 END INTERFACE
2155
2156 cpassert(c_associated(content_c))
2157 cpassert(length >= 0)
2158
2159 CALL c_f_pointer(content_c, content_f, shape=[length + 1])
2160 cpassert(content_f(length + 1) == c_null_char)
2161
2162 ALLOCATE (CHARACTER(LEN=length) :: res)
2163 DO i = 1, length
2164 cpassert(content_f(i) /= c_null_char)
2165 res(i:i) = content_f(i)
2166 END DO
2167
2168 NULLIFY (content_f)
2169 CALL torch_c_free_string(content_c)
2170 content_c = c_null_ptr
2171
2172#else
2173 res = ""
2174 mark_used(content_c)
2175 mark_used(length)
2176 cpabort("CP2K was compiled without Torch library.")
2177#endif
2178 END SUBROUTINE c_string_to_allocatable
2179
2180! **************************************************************************************************
2181!> \brief Returns true iff the Torch CUDA backend is available.
2182!> \author Ole Schuett
2183! **************************************************************************************************
2184 FUNCTION torch_cuda_is_available() RESULT(res)
2185 LOGICAL :: res
2186
2187#if defined(__LIBTORCH)
2188 INTERFACE
2189 FUNCTION torch_c_cuda_is_available() BIND(C, name="torch_c_cuda_is_available")
2190 IMPORT :: c_bool
2191 LOGICAL(C_BOOL) :: torch_c_cuda_is_available
2192 END FUNCTION torch_c_cuda_is_available
2193 END INTERFACE
2194
2195 res = torch_c_cuda_is_available()
2196#else
2197 cpabort("CP2K was compiled without Torch library.")
2198 res = .false.
2199#endif
2200 END FUNCTION torch_cuda_is_available
2201
2202! **************************************************************************************************
2203!> \brief Return the number of CUDA devices visible to Torch.
2204! **************************************************************************************************
2205 FUNCTION torch_cuda_device_count() RESULT(count)
2206 INTEGER :: count
2207
2208#if defined(__LIBTORCH)
2209 INTERFACE
2210 FUNCTION torch_c_cuda_device_count() BIND(C, name="torch_c_cuda_device_count")
2211 IMPORT :: c_int
2212 INTEGER(C_INT) :: torch_c_cuda_device_count
2213 END FUNCTION torch_c_cuda_device_count
2214 END INTERFACE
2215
2216 count = torch_c_cuda_device_count()
2217#else
2218 cpabort("CP2K was compiled without Torch library.")
2219 count = 0
2220#endif
2221 END FUNCTION torch_cuda_device_count
2222
2223! **************************************************************************************************
2224!> \brief Set whether to allow the use of TF32.
2225!> Needed due to changes in defaults from pytorch 1.7 to 1.11 to >=1.12
2226!> See https://pytorch.org/docs/stable/notes/cuda.html
2227!> \author Gabriele Tocci
2228! **************************************************************************************************
2229 SUBROUTINE torch_allow_tf32(allow_tf32)
2230 LOGICAL, INTENT(IN) :: allow_tf32
2231
2232#if defined(__LIBTORCH)
2233 INTERFACE
2234 SUBROUTINE torch_c_allow_tf32(allow_tf32) BIND(C, name="torch_c_allow_tf32")
2235 IMPORT :: c_bool
2236 LOGICAL(C_BOOL), VALUE :: allow_tf32
2237 END SUBROUTINE torch_c_allow_tf32
2238 END INTERFACE
2239
2240 CALL torch_c_allow_tf32(allow_tf32=LOGICAL(allow_tf32, c_bool))
2241#else
2242 cpabort("CP2K was compiled without Torch library.")
2243 mark_used(allow_tf32)
2244#endif
2245 END SUBROUTINE torch_allow_tf32
2246
2247! **************************************************************************************************
2248!> \brief Freeze the given Torch model: applies generic optimization that speed up model.
2249!> See https://pytorch.org/docs/stable/generated/torch.jit.freeze.html
2250!> \author Gabriele Tocci
2251! **************************************************************************************************
2252 SUBROUTINE torch_model_freeze(model)
2253 TYPE(torch_model_type), INTENT(INOUT) :: model
2254
2255#if defined(__LIBTORCH)
2256 CHARACTER(len=*), PARAMETER :: routinen = 'torch_model_freeze'
2257 INTEGER :: handle
2258
2259 INTERFACE
2260 SUBROUTINE torch_c_model_freeze(model) BIND(C, name="torch_c_model_freeze")
2261 IMPORT :: c_ptr
2262 TYPE(c_ptr), VALUE :: model
2263 END SUBROUTINE torch_c_model_freeze
2264 END INTERFACE
2265
2266 CALL timeset(routinen, handle)
2267 cpassert(c_associated(model%c_ptr))
2268 CALL torch_c_model_freeze(model=model%c_ptr)
2269 CALL timestop(handle)
2270#else
2271 cpabort("CP2K was compiled without Torch library.")
2272 mark_used(model)
2273#endif
2274 END SUBROUTINE torch_model_freeze
2275
2276! **************************************************************************************************
2277!> \brief Freeze a Torch model while preserving one exported method.
2278!> \param model ...
2279!> \param method_name ...
2280! **************************************************************************************************
2281 SUBROUTINE torch_model_freeze_preserving_method(model, method_name)
2282 TYPE(torch_model_type), INTENT(INOUT) :: model
2283 CHARACTER(len=*), INTENT(IN) :: method_name
2284
2285#if defined(__LIBTORCH)
2286 CHARACTER(len=*), PARAMETER :: routinen = &
2287 'torch_model_freeze_preserving_method'
2288 INTEGER :: handle
2289
2290 INTERFACE
2291 SUBROUTINE torch_c_model_freeze_preserving_method(model, method_name) &
2292 BIND(C, name="torch_c_model_freeze_preserving_method")
2293 IMPORT :: c_char, c_ptr
2294 TYPE(c_ptr), VALUE :: model
2295 CHARACTER(kind=C_CHAR), DIMENSION(*) :: method_name
2296 END SUBROUTINE torch_c_model_freeze_preserving_method
2297 END INTERFACE
2298
2299 CALL timeset(routinen, handle)
2300 cpassert(c_associated(model%c_ptr))
2301 CALL torch_c_model_freeze_preserving_method( &
2302 model=model%c_ptr, method_name=trim(method_name)//c_null_char)
2303 CALL timestop(handle)
2304#else
2305 cpabort("CP2K was compiled without Torch library.")
2306 mark_used(method_name)
2307 mark_used(model)
2308#endif
2310
2311
2312! **************************************************************************************************
2313!> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
2314!> \author Ole Schuett
2315! **************************************************************************************************
2316 SUBROUTINE torch_model_get_attr_int64 (model, key, dest)
2317 TYPE(torch_model_type), INTENT(IN) :: model
2318 CHARACTER(len=*), INTENT(IN) :: key
2319 INTEGER(kind=int_8), INTENT(OUT) :: dest
2320
2321#if defined(__LIBTORCH)
2322
2323 INTERFACE
2324 SUBROUTINE torch_c_model_get_attr_int64 (model, key, dest) &
2325 BIND(C, name="torch_c_model_get_attr_int64")
2326 IMPORT :: c_ptr, c_char, c_int64_t, c_double
2327 TYPE(c_ptr), VALUE :: model
2328 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
2329 INTEGER(kind=C_INT64_T) :: dest
2330 END SUBROUTINE torch_c_model_get_attr_int64
2331 END INTERFACE
2332
2333 CALL torch_c_model_get_attr_int64 (model=model%c_ptr, &
2334 key=trim(key)//c_null_char, &
2335 dest=dest)
2336#else
2337 dest = 0
2338 mark_used(model)
2339 mark_used(key)
2340 cpabort("CP2K compiled without the Torch library.")
2341#endif
2342 END SUBROUTINE torch_model_get_attr_int64
2343! **************************************************************************************************
2344!> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
2345!> \author Ole Schuett
2346! **************************************************************************************************
2347 SUBROUTINE torch_model_get_attr_double (model, key, dest)
2348 TYPE(torch_model_type), INTENT(IN) :: model
2349 CHARACTER(len=*), INTENT(IN) :: key
2350 REAL(dp), INTENT(OUT) :: dest
2351
2352#if defined(__LIBTORCH)
2353
2354 INTERFACE
2355 SUBROUTINE torch_c_model_get_attr_double (model, key, dest) &
2356 BIND(C, name="torch_c_model_get_attr_double")
2357 IMPORT :: c_ptr, c_char, c_int64_t, c_double
2358 TYPE(c_ptr), VALUE :: model
2359 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
2360 REAL(kind=c_double) :: dest
2361 END SUBROUTINE torch_c_model_get_attr_double
2362 END INTERFACE
2363
2364 CALL torch_c_model_get_attr_double (model=model%c_ptr, &
2365 key=trim(key)//c_null_char, &
2366 dest=dest)
2367#else
2368 dest = 0.0_dp
2369 mark_used(model)
2370 mark_used(key)
2371 cpabort("CP2K compiled without the Torch library.")
2372#endif
2373 END SUBROUTINE torch_model_get_attr_double
2374! **************************************************************************************************
2375!> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
2376!> \author Ole Schuett
2377! **************************************************************************************************
2378 SUBROUTINE torch_model_get_attr_string (model, key, dest)
2379 TYPE(torch_model_type), INTENT(IN) :: model
2380 CHARACTER(len=*), INTENT(IN) :: key
2381 CHARACTER(LEN=default_string_length), INTENT(OUT) :: dest
2382
2383#if defined(__LIBTORCH)
2384
2385 INTERFACE
2386 SUBROUTINE torch_c_model_get_attr_string (model, key, dest) &
2387 BIND(C, name="torch_c_model_get_attr_string")
2388 IMPORT :: c_ptr, c_char, c_int64_t, c_double
2389 TYPE(c_ptr), VALUE :: model
2390 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
2391 CHARACTER(kind=C_CHAR), DIMENSION(*) :: dest
2392 END SUBROUTINE torch_c_model_get_attr_string
2393 END INTERFACE
2394
2395 CALL torch_c_model_get_attr_string (model=model%c_ptr, &
2396 key=trim(key)//c_null_char, &
2397 dest=dest)
2398#else
2399 dest = ""
2400 mark_used(model)
2401 mark_used(key)
2402 cpabort("CP2K compiled without the Torch library.")
2403#endif
2404 END SUBROUTINE torch_model_get_attr_string
2405
2406! **************************************************************************************************
2407!> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
2408!> \author Ole Schuett
2409! **************************************************************************************************
2410 SUBROUTINE torch_model_get_attr_int32(model, key, dest)
2411 TYPE(torch_model_type), INTENT(IN) :: model
2412 CHARACTER(len=*), INTENT(IN) :: key
2413 INTEGER, INTENT(OUT) :: dest
2414
2415 INTEGER(kind=int_8) :: temp
2416 CALL torch_model_get_attr_int64(model, key, temp)
2417 cpassert(abs(temp) < huge(dest))
2418 dest = int(temp)
2419 END SUBROUTINE torch_model_get_attr_int32
2420
2421! **************************************************************************************************
2422!> \brief Retrieves a list attribute from a Torch model. Must be called before torch_model_freeze.
2423!> \author Ole Schuett
2424! **************************************************************************************************
2425 SUBROUTINE torch_model_get_attr_strlist(model, key, dest)
2426 TYPE(torch_model_type), INTENT(IN) :: model
2427 CHARACTER(len=*), INTENT(IN) :: key
2428 CHARACTER(LEN=default_string_length), &
2429 ALLOCATABLE, DIMENSION(:) :: dest
2430
2431#if defined(__LIBTORCH)
2432
2433 INTEGER :: num_items, i
2434
2435 INTERFACE
2436 SUBROUTINE torch_c_model_get_attr_list_size(model, key, size) &
2437 BIND(C, name="torch_c_model_get_attr_list_size")
2438 IMPORT :: c_ptr, c_char, c_int
2439 TYPE(c_ptr), VALUE :: model
2440 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
2441 INTEGER(kind=C_INT) :: size
2442 END SUBROUTINE torch_c_model_get_attr_list_size
2443 END INTERFACE
2444
2445 INTERFACE
2446 SUBROUTINE torch_c_model_get_attr_strlist(model, key, index, dest) &
2447 BIND(C, name="torch_c_model_get_attr_strlist")
2448 IMPORT :: c_ptr, c_char, c_int
2449 TYPE(c_ptr), VALUE :: model
2450 CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
2451 INTEGER(kind=C_INT), VALUE :: index
2452 CHARACTER(kind=C_CHAR), DIMENSION(*) :: dest
2453 END SUBROUTINE torch_c_model_get_attr_strlist
2454 END INTERFACE
2455
2456 CALL torch_c_model_get_attr_list_size(model=model%c_ptr, &
2457 key=trim(key)//c_null_char, &
2458 size=num_items)
2459 ALLOCATE (dest(num_items))
2460 dest(:) = ""
2461
2462 DO i = 1, num_items
2463 CALL torch_c_model_get_attr_strlist(model=model%c_ptr, &
2464 key=trim(key)//c_null_char, &
2465 index=i - 1, &
2466 dest=dest(i))
2467
2468 END DO
2469#else
2470 cpabort("CP2K compiled without the Torch library.")
2471 mark_used(model)
2472 mark_used(key)
2473 mark_used(dest)
2474#endif
2475
2476 END SUBROUTINE torch_model_get_attr_strlist
2477
2478END MODULE torch_api
struct tensor_ tensor
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public sp
Definition kinds.F:33
integer, parameter, public int_4
Definition kinds.F:51
subroutine, public torch_dict_release(dict)
Releases a Torch dictionary and all its ressources.
Definition torch_api.F:1842
subroutine, public torch_tensor_backward(tensor, outer_grad)
Runs autograd on a Torch tensor.
Definition torch_api.F:1471
subroutine, public torch_use_cuda(use_cuda)
Select whether Torch wrappers should use CUDA when available.
Definition torch_api.F:1554
subroutine, public torch_dict_get(dict, key, tensor)
Retrieves a Torch tensor from a Torch dictionary.
Definition torch_api.F:1808
subroutine, public torch_model_freeze_preserving_method(model, method_name)
Freeze a Torch model while preserving one exported method.
Definition torch_api.F:2282
real(kind=dp) function, public torch_tensor_item_double(tensor)
Returns a scalar double value from a Torch tensor.
Definition torch_api.F:1674
subroutine, public torch_tensor_backward_scalar(tensor)
Runs autograd on a scalar Torch tensor.
Definition torch_api.F:1503
subroutine, public torch_model_load_with_metadata(model, filename, key1, value1, key2, value2)
Loads a Torch model and reads two metadata entries in the same archive pass.
Definition torch_api.F:1897
subroutine, public torch_model_load(model, filename)
Loads a Torch model from given "*.pth" file. (In Torch lingo models are called modules).
Definition torch_api.F:1866
subroutine, public torch_tensor_narrow(tensor, dim, start_index, length, result)
Creates a view of a contiguous tensor slice.
Definition torch_api.F:1430
subroutine, public torch_model_remap_device_constants(model)
Maps serialized TorchScript device constants to the active Torch device.
Definition torch_api.F:1949
subroutine, public torch_tensor_to_device_leaf(tensor, requires_grad)
Moves a tensor to the active Torch device and makes it an autograd leaf.
Definition torch_api.F:1526
subroutine, public torch_dict_create(dict)
Creates an empty Torch dictionary.
Definition torch_api.F:1725
subroutine, public torch_model_forward_mol_tensor(model, method_name, inputs, output)
Evaluates a TorchScript model method expecting keyword argument "mol".
Definition torch_api.F:2031
subroutine, public torch_model_disable_parameter_gradients(model)
Disable gradients for inference-only model parameters.
Definition torch_api.F:1972
subroutine, public torch_model_release(model)
Releases a Torch model and all its ressources.
Definition torch_api.F:2075
subroutine, public torch_tensor_grad(tensor, grad)
Returns the gradient of a Torch tensor which was computed by autograd.
Definition torch_api.F:1575
subroutine, public torch_allow_tf32(allow_tf32)
Set whether to allow the use of TF32. Needed due to changes in defaults from pytorch 1....
Definition torch_api.F:2230
subroutine, public torch_tensor_weighted_sum(values, weights, result)
Returns the weighted sum of two Torch tensors.
Definition torch_api.F:1643
subroutine, public torch_tensor_grad_batch3(tensor1, tensor2, tensor3, grad1, grad2, grad3)
Copies three autograd gradients to CPU memory.
Definition torch_api.F:1603
subroutine, public torch_model_freeze(model)
Freeze the given Torch model: applies generic optimization that speed up model. See https://pytorch....
Definition torch_api.F:2253
integer function, public torch_cuda_device_count()
Return the number of CUDA devices visible to Torch.
Definition torch_api.F:2206
character(:) function, allocatable, public torch_model_read_metadata(filename, key)
Reads metadata entry from given "*.pth" file. (In Torch lingo they are called extra files).
Definition torch_api.F:2099
subroutine, public torch_tensor_expand_dim(tensor, dim, extent, result)
Creates an expanded tensor view along one singleton dimension.
Definition torch_api.F:1393
subroutine, public torch_dict_insert(dict, key, tensor)
Inserts a Torch tensor into a Torch dictionary.
Definition torch_api.F:1776
logical function, public torch_cuda_is_available()
Returns true iff the Torch CUDA backend is available.
Definition torch_api.F:2185
subroutine, public torch_dict_clone(source, target)
Clones a Torch dictionary.
Definition torch_api.F:1748
subroutine, public torch_tensor_release(tensor)
Releases a Torch tensor and all its ressources.
Definition torch_api.F:1701
subroutine, public torch_model_forward(model, inputs, outputs)
Evaluates the given Torch model.
Definition torch_api.F:1996