Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 : MODULE torch_api
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 :
21 : USE kinds, ONLY: sp, int_4, int_8, dp, default_string_length
22 :
23 : #include "./base/base_uses.f90"
24 :
25 : IMPLICIT NONE
26 :
27 : PRIVATE
28 :
29 : TYPE torch_tensor_type
30 : PRIVATE
31 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
32 : END TYPE torch_tensor_type
33 :
34 : TYPE torch_dict_type
35 : PRIVATE
36 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
37 : END TYPE torch_dict_type
38 :
39 : TYPE torch_model_type
40 : PRIVATE
41 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
42 : END TYPE torch_model_type
43 :
44 : #:set max_dim = 3
45 : INTERFACE torch_tensor_from_array
46 : #:for ndims in range(1, max_dim+1)
47 : MODULE PROCEDURE torch_tensor_from_array_int32_${ndims}$d
48 : MODULE PROCEDURE torch_tensor_from_array_float_${ndims}$d
49 : MODULE PROCEDURE torch_tensor_from_array_int64_${ndims}$d
50 : MODULE PROCEDURE torch_tensor_from_array_double_${ndims}$d
51 : #:endfor
52 : END INTERFACE torch_tensor_from_array
53 :
54 : INTERFACE torch_tensor_reset_from_array
55 : #:for ndims in range(1, max_dim+1)
56 : MODULE PROCEDURE torch_tensor_reset_from_array_double_${ndims}$d
57 : #:endfor
58 : END INTERFACE torch_tensor_reset_from_array
59 :
60 : INTERFACE torch_tensor_data_ptr
61 : #:for ndims in range(1, max_dim+1)
62 : MODULE PROCEDURE torch_tensor_data_ptr_int32_${ndims}$d
63 : MODULE PROCEDURE torch_tensor_data_ptr_float_${ndims}$d
64 : MODULE PROCEDURE torch_tensor_data_ptr_int64_${ndims}$d
65 : MODULE PROCEDURE torch_tensor_data_ptr_double_${ndims}$d
66 : #:endfor
67 : END INTERFACE torch_tensor_data_ptr
68 :
69 : INTERFACE torch_model_get_attr
70 : MODULE PROCEDURE torch_model_get_attr_string
71 : MODULE PROCEDURE torch_model_get_attr_double
72 : MODULE PROCEDURE torch_model_get_attr_int64
73 : MODULE PROCEDURE torch_model_get_attr_int32
74 : MODULE PROCEDURE torch_model_get_attr_strlist
75 : END INTERFACE torch_model_get_attr
76 :
77 : PUBLIC :: torch_tensor_type, torch_tensor_expand_dim, torch_tensor_from_array, &
78 : torch_tensor_narrow, torch_tensor_release
79 : PUBLIC :: torch_tensor_reset_from_array
80 : PUBLIC :: torch_tensor_data_ptr, torch_tensor_backward, torch_tensor_backward_scalar
81 : PUBLIC :: torch_tensor_grad, torch_tensor_grad_batch3
82 : PUBLIC :: torch_tensor_to_device_leaf
83 : PUBLIC :: torch_tensor_item_double, torch_tensor_weighted_sum
84 : PUBLIC :: torch_dict_type, torch_dict_clone, torch_dict_create, torch_dict_insert
85 : PUBLIC :: torch_dict_get, torch_dict_release
86 : PUBLIC :: torch_model_type, torch_model_load, torch_model_load_with_metadata, &
87 : torch_model_forward, torch_model_release
88 : PUBLIC :: torch_model_disable_parameter_gradients, torch_model_forward_mol_tensor, &
89 : torch_model_remap_device_constants
90 : PUBLIC :: torch_model_promote_float32
91 : PUBLIC :: torch_model_get_attr, torch_model_read_metadata
92 : PUBLIC :: torch_cuda_device_count, torch_cuda_is_available
93 : PUBLIC :: torch_allow_tf32, torch_model_freeze, torch_model_freeze_preserving_method, &
94 : torch_use_cuda
95 :
96 : CONTAINS
97 :
98 : #:set typenames = ['int32', 'float', 'int64', 'double']
99 : #:set types_f = ['INTEGER(kind=int_4)', 'REAL(sp)', 'INTEGER(kind=int_8)', 'REAL(dp)']
100 : #:set types_c = ['INTEGER(kind=C_INT32_T)', 'REAL(kind=C_FLOAT)', 'INTEGER(kind=C_INT64_T)', 'REAL(kind=C_DOUBLE)']
101 :
102 : #:for ndims in range(1, max_dim+1)
103 : #:for typename, type_f, type_c in zip(typenames, types_f, types_c)
104 :
105 : ! **************************************************************************************************
106 : !> \brief Creates a Torch tensor from an array. The passed array has to outlive the tensor!
107 : !> The source must be an ALLOCATABLE to prevent passing a temporary array.
108 : !> \author Ole Schuett
109 : ! **************************************************************************************************
110 2682 : SUBROUTINE torch_tensor_from_array_${typename}$_${ndims}$d(tensor, source, requires_grad)
111 : TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
112 : #:set arraydims = ", ".join(":" for i in range(ndims))
113 : ${type_f}$, DIMENSION(${arraydims}$), ALLOCATABLE, INTENT(IN) :: source
114 : LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
115 :
116 : #if defined(__LIBTORCH)
117 : INTEGER(kind=int_8), DIMENSION(${ndims}$) :: sizes_c
118 : LOGICAL :: my_req_grad
119 :
120 : INTERFACE
121 : SUBROUTINE torch_c_tensor_from_array_${typename}$ (tensor, req_grad, ndims, sizes, source) &
122 : BIND(C, name="torch_c_tensor_from_array_${typename}$")
123 : IMPORT :: C_PTR, C_INT, C_INT32_T, C_INT64_T, C_FLOAT, C_DOUBLE, C_BOOL
124 : TYPE(C_PTR) :: tensor
125 : LOGICAL(kind=C_BOOL), VALUE :: req_grad
126 : INTEGER(kind=C_INT), VALUE :: ndims
127 : INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
128 : ${type_c}$, DIMENSION(*) :: source
129 : END SUBROUTINE torch_c_tensor_from_array_${typename}$
130 : END INTERFACE
131 :
132 2682 : my_req_grad = .FALSE.
133 2682 : IF (PRESENT(requires_grad)) my_req_grad = requires_grad
134 :
135 : #:for axis in range(ndims)
136 2682 : sizes_c(${axis + 1}$) = SIZE(source, ${ndims - axis}$) ! C arrays are stored row-major.
137 : #:endfor
138 :
139 2682 : CPASSERT(.NOT. C_ASSOCIATED(tensor%c_ptr))
140 : CALL torch_c_tensor_from_array_${typename}$ (tensor=tensor%c_ptr, &
141 : req_grad=LOGICAL(my_req_grad, C_BOOL), &
142 : ndims=${ndims}$, &
143 : sizes=sizes_c, &
144 2682 : source=source)
145 2682 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
146 : #else
147 : CPABORT("CP2K compiled without the Torch library.")
148 : MARK_USED(tensor)
149 : MARK_USED(source)
150 : MARK_USED(requires_grad)
151 : #endif
152 2682 : END SUBROUTINE torch_tensor_from_array_${typename}$_${ndims}$d
153 :
154 : ! **************************************************************************************************
155 : !> \brief Copies data from a Torch tensor to an array.
156 : !> The returned pointer is only valide during the tensor's lifetime!
157 : !> \author Ole Schuett
158 : ! **************************************************************************************************
159 1180 : SUBROUTINE torch_tensor_data_ptr_${typename}$_${ndims}$d(tensor, data_ptr)
160 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
161 : #:set arraydims = ", ".join(":" for i in range(ndims))
162 : ${type_f}$, DIMENSION(${arraydims}$), POINTER :: data_ptr
163 :
164 : #if defined(__LIBTORCH)
165 : INTEGER(kind=int_8), DIMENSION(${ndims}$) :: sizes_f, sizes_c
166 : TYPE(C_PTR) :: data_ptr_c
167 :
168 : INTERFACE
169 : SUBROUTINE torch_c_tensor_data_ptr_${typename}$ (tensor, ndims, sizes, data_ptr) &
170 : BIND(C, name="torch_c_tensor_data_ptr_${typename}$")
171 : IMPORT :: C_CHAR, C_PTR, C_INT, C_INT32_T, C_INT64_T
172 : TYPE(C_PTR), VALUE :: tensor
173 : INTEGER(kind=C_INT), VALUE :: ndims
174 : INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
175 : TYPE(C_PTR) :: data_ptr
176 : END SUBROUTINE torch_c_tensor_data_ptr_${typename}$
177 : END INTERFACE
178 :
179 3746 : sizes_c(:) = -1
180 1180 : data_ptr_c = C_NULL_PTR
181 1180 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
182 1180 : CPASSERT(.NOT. ASSOCIATED(data_ptr))
183 : CALL torch_c_tensor_data_ptr_${typename}$ (tensor=tensor%c_ptr, &
184 : ndims=${ndims}$, &
185 : sizes=sizes_c, &
186 1180 : data_ptr=data_ptr_c)
187 :
188 : #:for axis in range(ndims)
189 1180 : sizes_f(${axis + 1}$) = sizes_c(${ndims - axis}$) ! C arrays are stored row-major.
190 : #:endfor
191 :
192 3746 : IF (ALL(sizes_f /= 0)) THEN ! Torch returns null pointer for zero-sized tensors.
193 1180 : CPASSERT(C_ASSOCIATED(data_ptr_c))
194 3746 : CALL C_F_POINTER(data_ptr_c, data_ptr, shape=sizes_f)
195 : END IF
196 : #else
197 : CPABORT("CP2K compiled without the Torch library.")
198 : MARK_USED(tensor)
199 : MARK_USED(data_ptr)
200 : #endif
201 1180 : END SUBROUTINE torch_tensor_data_ptr_${typename}$_${ndims}$d
202 :
203 : #:endfor
204 : #:endfor
205 :
206 : #:for ndims in range(1, max_dim+1)
207 :
208 : ! **************************************************************************************************
209 : !> \brief Reuses or creates a device leaf tensor and copies data into it.
210 : !> The source must be an ALLOCATABLE to prevent passing a temporary array.
211 : ! **************************************************************************************************
212 144 : SUBROUTINE torch_tensor_reset_from_array_double_${ndims}$d(tensor, source, requires_grad)
213 : TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
214 : #:set arraydims = ", ".join(":" for i in range(ndims))
215 : REAL(dp), DIMENSION(${arraydims}$), ALLOCATABLE, INTENT(IN) :: source
216 : LOGICAL, OPTIONAL, INTENT(IN) :: requires_grad
217 :
218 : #if defined(__LIBTORCH)
219 : INTEGER(kind=int_8), DIMENSION(${ndims}$) :: sizes_c
220 : LOGICAL :: my_req_grad
221 :
222 : INTERFACE
223 : SUBROUTINE torch_c_tensor_reset_from_array_double(tensor, req_grad, ndims, sizes, source) &
224 : BIND(C, name="torch_c_tensor_reset_from_array_double")
225 : IMPORT :: C_PTR, C_INT, C_INT64_T, C_DOUBLE, C_BOOL
226 : TYPE(C_PTR) :: tensor
227 : LOGICAL(kind=C_BOOL), VALUE :: req_grad
228 : INTEGER(kind=C_INT), VALUE :: ndims
229 : INTEGER(kind=C_INT64_T), DIMENSION(*) :: sizes
230 : REAL(kind=C_DOUBLE), DIMENSION(*) :: source
231 : END SUBROUTINE torch_c_tensor_reset_from_array_double
232 : END INTERFACE
233 :
234 144 : my_req_grad = .FALSE.
235 144 : IF (PRESENT(requires_grad)) my_req_grad = requires_grad
236 :
237 : #:for axis in range(ndims)
238 144 : sizes_c(${axis + 1}$) = SIZE(source, ${ndims - axis}$) ! C arrays are stored row-major.
239 : #:endfor
240 :
241 : CALL torch_c_tensor_reset_from_array_double(tensor=tensor%c_ptr, &
242 : req_grad=LOGICAL(my_req_grad, C_BOOL), &
243 : ndims=${ndims}$, &
244 : sizes=sizes_c, &
245 144 : source=source)
246 144 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
247 : #else
248 : CPABORT("CP2K compiled without the Torch library.")
249 : MARK_USED(tensor)
250 : MARK_USED(source)
251 : MARK_USED(requires_grad)
252 : #endif
253 144 : END SUBROUTINE torch_tensor_reset_from_array_double_${ndims}$d
254 :
255 : #:endfor
256 :
257 : ! **************************************************************************************************
258 : !> \brief Creates an expanded tensor view along one singleton dimension.
259 : ! **************************************************************************************************
260 96 : SUBROUTINE torch_tensor_expand_dim(tensor, dim, extent, result)
261 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
262 : INTEGER, INTENT(IN) :: dim, extent
263 : TYPE(torch_tensor_type), INTENT(INOUT) :: result
264 :
265 : #if defined(__LIBTORCH)
266 : INTERFACE
267 : SUBROUTINE torch_c_tensor_expand_dim(tensor, dim, extent, result) &
268 : BIND(C, name="torch_c_tensor_expand_dim")
269 : IMPORT :: C_INT64_T, C_PTR
270 : TYPE(C_PTR), VALUE :: tensor
271 : INTEGER(kind=C_INT64_T), VALUE :: dim, extent
272 : TYPE(C_PTR) :: result
273 : END SUBROUTINE torch_c_tensor_expand_dim
274 : END INTERFACE
275 :
276 96 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
277 96 : CPASSERT(.NOT. C_ASSOCIATED(result%c_ptr))
278 96 : CPASSERT(dim >= 0)
279 96 : CPASSERT(extent >= 0)
280 : CALL torch_c_tensor_expand_dim(tensor=tensor%c_ptr, &
281 : dim=INT(dim, C_INT64_T), &
282 : extent=INT(extent, C_INT64_T), &
283 96 : result=result%c_ptr)
284 96 : CPASSERT(C_ASSOCIATED(result%c_ptr))
285 : #else
286 : CPABORT("CP2K compiled without the Torch library.")
287 : MARK_USED(tensor)
288 : MARK_USED(dim)
289 : MARK_USED(extent)
290 : MARK_USED(result)
291 : #endif
292 96 : END SUBROUTINE torch_tensor_expand_dim
293 :
294 : ! **************************************************************************************************
295 : !> \brief Creates a view of a contiguous tensor slice.
296 : ! **************************************************************************************************
297 1872 : SUBROUTINE torch_tensor_narrow(tensor, dim, start_index, length, result)
298 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
299 : INTEGER, INTENT(IN) :: dim, start_index, length
300 : TYPE(torch_tensor_type), INTENT(INOUT) :: result
301 :
302 : #if defined(__LIBTORCH)
303 : INTERFACE
304 : SUBROUTINE torch_c_tensor_narrow(tensor, dim, start_index, length, result) &
305 : BIND(C, name="torch_c_tensor_narrow")
306 : IMPORT :: C_INT64_T, C_PTR
307 : TYPE(C_PTR), VALUE :: tensor
308 : INTEGER(kind=C_INT64_T), VALUE :: dim, start_index, length
309 : TYPE(C_PTR) :: result
310 : END SUBROUTINE torch_c_tensor_narrow
311 : END INTERFACE
312 :
313 1872 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
314 1872 : CPASSERT(.NOT. C_ASSOCIATED(result%c_ptr))
315 1872 : CPASSERT(dim >= 0)
316 1872 : CPASSERT(start_index >= 0)
317 1872 : CPASSERT(length >= 0)
318 : CALL torch_c_tensor_narrow(tensor=tensor%c_ptr, &
319 : dim=INT(dim, C_INT64_T), &
320 : start_index=INT(start_index, C_INT64_T), &
321 : length=INT(length, C_INT64_T), &
322 1872 : result=result%c_ptr)
323 1872 : CPASSERT(C_ASSOCIATED(result%c_ptr))
324 : #else
325 : CPABORT("CP2K compiled without the Torch library.")
326 : MARK_USED(tensor)
327 : MARK_USED(dim)
328 : MARK_USED(start_index)
329 : MARK_USED(length)
330 : MARK_USED(result)
331 : #endif
332 1872 : END SUBROUTINE torch_tensor_narrow
333 :
334 : ! **************************************************************************************************
335 : !> \brief Runs autograd on a Torch tensor.
336 : !> \author Ole Schuett
337 : ! **************************************************************************************************
338 6 : SUBROUTINE torch_tensor_backward(tensor, outer_grad)
339 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
340 : TYPE(torch_tensor_type), INTENT(IN) :: outer_grad
341 :
342 : #if defined(__LIBTORCH)
343 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_tensor_backward'
344 : INTEGER :: handle
345 :
346 : INTERFACE
347 : SUBROUTINE torch_c_tensor_backward(tensor, outer_grad) &
348 : BIND(C, name="torch_c_tensor_backward")
349 : IMPORT :: C_CHAR, C_PTR
350 : TYPE(C_PTR), VALUE :: tensor
351 : TYPE(C_PTR), VALUE :: outer_grad
352 : END SUBROUTINE torch_c_tensor_backward
353 : END INTERFACE
354 :
355 6 : CALL timeset(routineN, handle)
356 6 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
357 6 : CPASSERT(C_ASSOCIATED(outer_grad%c_ptr))
358 6 : CALL torch_c_tensor_backward(tensor=tensor%c_ptr, outer_grad=outer_grad%c_ptr)
359 6 : CALL timestop(handle)
360 : #else
361 : CPABORT("CP2K compiled without the Torch library.")
362 : MARK_USED(tensor)
363 : MARK_USED(outer_grad)
364 : #endif
365 6 : END SUBROUTINE torch_tensor_backward
366 :
367 : ! **************************************************************************************************
368 : !> \brief Runs autograd on a scalar Torch tensor.
369 : ! **************************************************************************************************
370 284 : SUBROUTINE torch_tensor_backward_scalar(tensor)
371 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
372 :
373 : #if defined(__LIBTORCH)
374 : INTERFACE
375 : SUBROUTINE torch_c_tensor_backward_scalar(tensor) &
376 : BIND(C, name="torch_c_tensor_backward_scalar")
377 : IMPORT :: C_PTR
378 : TYPE(C_PTR), VALUE :: tensor
379 : END SUBROUTINE torch_c_tensor_backward_scalar
380 : END INTERFACE
381 :
382 284 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
383 284 : CALL torch_c_tensor_backward_scalar(tensor=tensor%c_ptr)
384 : #else
385 : CPABORT("CP2K compiled without the Torch library.")
386 : MARK_USED(tensor)
387 : #endif
388 284 : END SUBROUTINE torch_tensor_backward_scalar
389 :
390 : ! **************************************************************************************************
391 : !> \brief Moves a tensor to the active Torch device and makes it an autograd leaf.
392 : ! **************************************************************************************************
393 2420 : SUBROUTINE torch_tensor_to_device_leaf(tensor, requires_grad)
394 : TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
395 : LOGICAL, INTENT(IN) :: requires_grad
396 :
397 : #if defined(__LIBTORCH)
398 : INTERFACE
399 : SUBROUTINE torch_c_tensor_to_device_leaf(tensor, req_grad) &
400 : BIND(C, name="torch_c_tensor_to_device_leaf")
401 : IMPORT :: C_BOOL, C_PTR
402 : TYPE(C_PTR) :: tensor
403 : LOGICAL(kind=C_BOOL), VALUE :: req_grad
404 : END SUBROUTINE torch_c_tensor_to_device_leaf
405 : END INTERFACE
406 :
407 2420 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
408 : CALL torch_c_tensor_to_device_leaf(tensor=tensor%c_ptr, &
409 2420 : req_grad=LOGICAL(requires_grad, C_BOOL))
410 2420 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
411 : #else
412 : CPABORT("CP2K compiled without the Torch library.")
413 : MARK_USED(tensor)
414 : MARK_USED(requires_grad)
415 : #endif
416 2420 : END SUBROUTINE torch_tensor_to_device_leaf
417 :
418 : ! **************************************************************************************************
419 : !> \brief Select whether Torch wrappers should use CUDA when available.
420 : ! **************************************************************************************************
421 608 : SUBROUTINE torch_use_cuda(use_cuda)
422 : LOGICAL, INTENT(IN) :: use_cuda
423 :
424 : #if defined(__LIBTORCH)
425 : INTERFACE
426 : SUBROUTINE torch_c_use_cuda(use_cuda) BIND(C, name="torch_c_use_cuda")
427 : IMPORT :: C_BOOL
428 : LOGICAL(kind=C_BOOL), VALUE :: use_cuda
429 : END SUBROUTINE torch_c_use_cuda
430 : END INTERFACE
431 :
432 608 : CALL torch_c_use_cuda(use_cuda=LOGICAL(use_cuda, C_BOOL))
433 : #else
434 : MARK_USED(use_cuda)
435 : #endif
436 608 : END SUBROUTINE torch_use_cuda
437 :
438 : ! **************************************************************************************************
439 : !> \brief Returns the gradient of a Torch tensor which was computed by autograd.
440 : !> \author Ole Schuett
441 : ! **************************************************************************************************
442 256 : SUBROUTINE torch_tensor_grad(tensor, grad)
443 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
444 : TYPE(torch_tensor_type), INTENT(INOUT) :: grad
445 :
446 : #if defined(__LIBTORCH)
447 : INTERFACE
448 : SUBROUTINE torch_c_tensor_grad(tensor, grad) &
449 : BIND(C, name="torch_c_tensor_grad")
450 : IMPORT :: C_PTR
451 : TYPE(C_PTR), VALUE :: tensor
452 : TYPE(C_PTR) :: grad
453 : END SUBROUTINE torch_c_tensor_grad
454 : END INTERFACE
455 :
456 256 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
457 256 : CPASSERT(.NOT. C_ASSOCIATED(grad%c_ptr))
458 256 : CALL torch_c_tensor_grad(tensor=tensor%c_ptr, grad=grad%c_ptr)
459 256 : CPASSERT(C_ASSOCIATED(grad%c_ptr))
460 : #else
461 : CPABORT("CP2K compiled without the Torch library.")
462 : MARK_USED(tensor)
463 : MARK_USED(grad)
464 : #endif
465 256 : END SUBROUTINE torch_tensor_grad
466 :
467 : ! **************************************************************************************************
468 : !> \brief Copies three autograd gradients to CPU memory.
469 : ! **************************************************************************************************
470 282 : SUBROUTINE torch_tensor_grad_batch3(tensor1, tensor2, tensor3, grad1, grad2, grad3)
471 : TYPE(torch_tensor_type), INTENT(IN) :: tensor1, tensor2, tensor3
472 : TYPE(torch_tensor_type), INTENT(INOUT) :: grad1, grad2, grad3
473 :
474 : #if defined(__LIBTORCH)
475 : INTERFACE
476 : SUBROUTINE torch_c_tensor_grad_batch3(tensor1, tensor2, tensor3, grad1, grad2, grad3) &
477 : BIND(C, name="torch_c_tensor_grad_batch3")
478 : IMPORT :: C_PTR
479 : TYPE(C_PTR), VALUE :: tensor1, tensor2, tensor3
480 : TYPE(C_PTR) :: grad1, grad2, grad3
481 : END SUBROUTINE torch_c_tensor_grad_batch3
482 : END INTERFACE
483 :
484 282 : CPASSERT(C_ASSOCIATED(tensor1%c_ptr))
485 282 : CPASSERT(C_ASSOCIATED(tensor2%c_ptr))
486 282 : CPASSERT(C_ASSOCIATED(tensor3%c_ptr))
487 282 : CPASSERT(.NOT. C_ASSOCIATED(grad1%c_ptr))
488 282 : CPASSERT(.NOT. C_ASSOCIATED(grad2%c_ptr))
489 282 : CPASSERT(.NOT. C_ASSOCIATED(grad3%c_ptr))
490 : CALL torch_c_tensor_grad_batch3(tensor1=tensor1%c_ptr, tensor2=tensor2%c_ptr, &
491 : tensor3=tensor3%c_ptr, grad1=grad1%c_ptr, &
492 282 : grad2=grad2%c_ptr, grad3=grad3%c_ptr)
493 282 : CPASSERT(C_ASSOCIATED(grad1%c_ptr))
494 282 : CPASSERT(C_ASSOCIATED(grad2%c_ptr))
495 282 : CPASSERT(C_ASSOCIATED(grad3%c_ptr))
496 : #else
497 : CPABORT("CP2K compiled without the Torch library.")
498 : MARK_USED(tensor1)
499 : MARK_USED(tensor2)
500 : MARK_USED(tensor3)
501 : MARK_USED(grad1)
502 : MARK_USED(grad2)
503 : MARK_USED(grad3)
504 : #endif
505 282 : END SUBROUTINE torch_tensor_grad_batch3
506 :
507 : ! **************************************************************************************************
508 : !> \brief Returns the weighted sum of two Torch tensors.
509 : ! **************************************************************************************************
510 284 : SUBROUTINE torch_tensor_weighted_sum(values, weights, result)
511 : TYPE(torch_tensor_type), INTENT(IN) :: values, weights
512 : TYPE(torch_tensor_type), INTENT(INOUT) :: result
513 :
514 : #if defined(__LIBTORCH)
515 : INTERFACE
516 : SUBROUTINE torch_c_tensor_weighted_sum(values, weights, result) &
517 : BIND(C, name="torch_c_tensor_weighted_sum")
518 : IMPORT :: C_PTR
519 : TYPE(C_PTR), VALUE :: values
520 : TYPE(C_PTR), VALUE :: weights
521 : TYPE(C_PTR) :: result
522 : END SUBROUTINE torch_c_tensor_weighted_sum
523 : END INTERFACE
524 :
525 284 : CPASSERT(C_ASSOCIATED(values%c_ptr))
526 284 : CPASSERT(C_ASSOCIATED(weights%c_ptr))
527 284 : CPASSERT(.NOT. C_ASSOCIATED(result%c_ptr))
528 284 : CALL torch_c_tensor_weighted_sum(values=values%c_ptr, weights=weights%c_ptr, result=result%c_ptr)
529 284 : CPASSERT(C_ASSOCIATED(result%c_ptr))
530 : #else
531 : CPABORT("CP2K compiled without the Torch library.")
532 : MARK_USED(values)
533 : MARK_USED(weights)
534 : MARK_USED(result)
535 : #endif
536 284 : END SUBROUTINE torch_tensor_weighted_sum
537 :
538 : ! **************************************************************************************************
539 : !> \brief Returns a scalar double value from a Torch tensor.
540 : ! **************************************************************************************************
541 284 : FUNCTION torch_tensor_item_double(tensor) RESULT(value)
542 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
543 : REAL(KIND=dp) :: value
544 :
545 : #if defined(__LIBTORCH)
546 : INTERFACE
547 : FUNCTION torch_c_tensor_item_double(tensor) RESULT(value) &
548 : BIND(C, name="torch_c_tensor_item_double")
549 : IMPORT :: C_DOUBLE, C_PTR
550 : TYPE(C_PTR), VALUE :: tensor
551 : REAL(KIND=C_DOUBLE) :: value
552 : END FUNCTION torch_c_tensor_item_double
553 : END INTERFACE
554 :
555 284 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
556 284 : value = torch_c_tensor_item_double(tensor=tensor%c_ptr)
557 : #else
558 : value = 0.0_dp
559 : CPABORT("CP2K compiled without the Torch library.")
560 : MARK_USED(tensor)
561 : #endif
562 284 : END FUNCTION torch_tensor_item_double
563 :
564 : ! **************************************************************************************************
565 : !> \brief Releases a Torch tensor and all its ressources.
566 : !> \author Ole Schuett
567 : ! **************************************************************************************************
568 6378 : SUBROUTINE torch_tensor_release(tensor)
569 : TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
570 :
571 : #if defined(__LIBTORCH)
572 : INTERFACE
573 : SUBROUTINE torch_c_tensor_release(tensor) BIND(C, name="torch_c_tensor_release")
574 : IMPORT :: C_PTR
575 : TYPE(C_PTR), VALUE :: tensor
576 : END SUBROUTINE torch_c_tensor_release
577 : END INTERFACE
578 :
579 6378 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
580 6378 : CALL torch_c_tensor_release(tensor=tensor%c_ptr)
581 6378 : tensor%c_ptr = C_NULL_PTR
582 : #else
583 : CPABORT("CP2K was compiled without Torch library.")
584 : MARK_USED(tensor)
585 : #endif
586 6378 : END SUBROUTINE torch_tensor_release
587 :
588 : ! **************************************************************************************************
589 : !> \brief Creates an empty Torch dictionary.
590 : !> \author Ole Schuett
591 : ! **************************************************************************************************
592 410 : SUBROUTINE torch_dict_create(dict)
593 : TYPE(torch_dict_type), INTENT(INOUT) :: dict
594 :
595 : #if defined(__LIBTORCH)
596 : INTERFACE
597 : SUBROUTINE torch_c_dict_create(dict) BIND(C, name="torch_c_dict_create")
598 : IMPORT :: C_PTR
599 : TYPE(C_PTR) :: dict
600 : END SUBROUTINE torch_c_dict_create
601 : END INTERFACE
602 :
603 410 : CPASSERT(.NOT. C_ASSOCIATED(dict%c_ptr))
604 410 : CALL torch_c_dict_create(dict=dict%c_ptr)
605 410 : CPASSERT(C_ASSOCIATED(dict%c_ptr))
606 : #else
607 : CPABORT("CP2K was compiled without Torch library.")
608 : MARK_USED(dict)
609 : #endif
610 410 : END SUBROUTINE torch_dict_create
611 :
612 : ! **************************************************************************************************
613 : !> \brief Clones a Torch dictionary.
614 : ! **************************************************************************************************
615 34 : SUBROUTINE torch_dict_clone(source, target)
616 : TYPE(torch_dict_type), INTENT(IN) :: source
617 : TYPE(torch_dict_type), INTENT(INOUT) :: target
618 :
619 : #if defined(__LIBTORCH)
620 : INTERFACE
621 : SUBROUTINE torch_c_dict_clone(source, target) BIND(C, name="torch_c_dict_clone")
622 : IMPORT :: C_PTR
623 : TYPE(C_PTR), VALUE :: source
624 : TYPE(C_PTR) :: target
625 : END SUBROUTINE torch_c_dict_clone
626 : END INTERFACE
627 :
628 34 : CPASSERT(C_ASSOCIATED(source%c_ptr))
629 34 : CPASSERT(.NOT. C_ASSOCIATED(target%c_ptr))
630 34 : CALL torch_c_dict_clone(source=source%c_ptr, target=target%c_ptr)
631 34 : CPASSERT(C_ASSOCIATED(target%c_ptr))
632 : #else
633 : CPABORT("CP2K was compiled without Torch library.")
634 : MARK_USED(source)
635 : MARK_USED(target)
636 : #endif
637 34 : END SUBROUTINE torch_dict_clone
638 :
639 : ! **************************************************************************************************
640 : !> \brief Inserts a Torch tensor into a Torch dictionary.
641 : !> \author Ole Schuett
642 : ! **************************************************************************************************
643 2806 : SUBROUTINE torch_dict_insert(dict, key, tensor)
644 : TYPE(torch_dict_type), INTENT(INOUT) :: dict
645 : CHARACTER(len=*), INTENT(IN) :: key
646 : TYPE(torch_tensor_type), INTENT(IN) :: tensor
647 :
648 : #if defined(__LIBTORCH)
649 :
650 : INTERFACE
651 : SUBROUTINE torch_c_dict_insert(dict, key, tensor) &
652 : BIND(C, name="torch_c_dict_insert")
653 : IMPORT :: C_CHAR, C_PTR
654 : TYPE(C_PTR), VALUE :: dict
655 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
656 : TYPE(C_PTR), VALUE :: tensor
657 : END SUBROUTINE torch_c_dict_insert
658 : END INTERFACE
659 :
660 2806 : CPASSERT(C_ASSOCIATED(dict%c_ptr))
661 2806 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
662 2806 : CALL torch_c_dict_insert(dict=dict%c_ptr, key=TRIM(key)//C_NULL_CHAR, tensor=tensor%c_ptr)
663 : #else
664 : CPABORT("CP2K compiled without the Torch library.")
665 : MARK_USED(dict)
666 : MARK_USED(key)
667 : MARK_USED(tensor)
668 : #endif
669 2806 : END SUBROUTINE torch_dict_insert
670 :
671 : ! **************************************************************************************************
672 : !> \brief Retrieves a Torch tensor from a Torch dictionary.
673 : !> \author Ole Schuett
674 : ! **************************************************************************************************
675 76 : SUBROUTINE torch_dict_get(dict, key, tensor)
676 : TYPE(torch_dict_type), INTENT(IN) :: dict
677 : CHARACTER(len=*), INTENT(IN) :: key
678 : TYPE(torch_tensor_type), INTENT(INOUT) :: tensor
679 :
680 : #if defined(__LIBTORCH)
681 :
682 : INTERFACE
683 : SUBROUTINE torch_c_dict_get(dict, key, tensor) &
684 : BIND(C, name="torch_c_dict_get")
685 : IMPORT :: C_CHAR, C_PTR
686 : TYPE(C_PTR), VALUE :: dict
687 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
688 : TYPE(C_PTR) :: tensor
689 : END SUBROUTINE torch_c_dict_get
690 : END INTERFACE
691 :
692 76 : CPASSERT(C_ASSOCIATED(dict%c_ptr))
693 76 : CPASSERT(.NOT. C_ASSOCIATED(tensor%c_ptr))
694 76 : CALL torch_c_dict_get(dict=dict%c_ptr, key=TRIM(key)//C_NULL_CHAR, tensor=tensor%c_ptr)
695 76 : CPASSERT(C_ASSOCIATED(tensor%c_ptr))
696 :
697 : #else
698 : CPABORT("CP2K compiled without the Torch library.")
699 : MARK_USED(dict)
700 : MARK_USED(key)
701 : MARK_USED(tensor)
702 : #endif
703 76 : END SUBROUTINE torch_dict_get
704 :
705 : ! **************************************************************************************************
706 : !> \brief Releases a Torch dictionary and all its ressources.
707 : !> \author Ole Schuett
708 : ! **************************************************************************************************
709 422 : SUBROUTINE torch_dict_release(dict)
710 : TYPE(torch_dict_type), INTENT(INOUT) :: dict
711 :
712 : #if defined(__LIBTORCH)
713 : INTERFACE
714 : SUBROUTINE torch_c_dict_release(dict) BIND(C, name="torch_c_dict_release")
715 : IMPORT :: C_PTR
716 : TYPE(C_PTR), VALUE :: dict
717 : END SUBROUTINE torch_c_dict_release
718 : END INTERFACE
719 :
720 422 : CPASSERT(C_ASSOCIATED(dict%c_ptr))
721 422 : CALL torch_c_dict_release(dict=dict%c_ptr)
722 422 : dict%c_ptr = C_NULL_PTR
723 : #else
724 : CPABORT("CP2K was compiled without Torch library.")
725 : MARK_USED(dict)
726 : #endif
727 422 : END SUBROUTINE torch_dict_release
728 :
729 : ! **************************************************************************************************
730 : !> \brief Loads a Torch model from given "*.pth" file. (In Torch lingo models are called modules)
731 : !> \author Ole Schuett
732 : ! **************************************************************************************************
733 16 : SUBROUTINE torch_model_load(model, filename)
734 : TYPE(torch_model_type), INTENT(INOUT) :: model
735 : CHARACTER(len=*), INTENT(IN) :: filename
736 :
737 : #if defined(__LIBTORCH)
738 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_load'
739 : INTEGER :: handle
740 :
741 : INTERFACE
742 : SUBROUTINE torch_c_model_load(model, filename) BIND(C, name="torch_c_model_load")
743 : IMPORT :: C_PTR, C_CHAR
744 : TYPE(C_PTR) :: model
745 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename
746 : END SUBROUTINE torch_c_model_load
747 : END INTERFACE
748 :
749 16 : CALL timeset(routineN, handle)
750 16 : CPASSERT(.NOT. C_ASSOCIATED(model%c_ptr))
751 16 : CALL torch_c_model_load(model=model%c_ptr, filename=TRIM(filename)//C_NULL_CHAR)
752 16 : CPASSERT(C_ASSOCIATED(model%c_ptr))
753 16 : CALL timestop(handle)
754 : #else
755 : CPABORT("CP2K was compiled without Torch library.")
756 : MARK_USED(model)
757 : MARK_USED(filename)
758 : #endif
759 16 : END SUBROUTINE torch_model_load
760 :
761 : ! **************************************************************************************************
762 : !> \brief Loads a Torch model and reads two metadata entries in the same archive pass.
763 : ! **************************************************************************************************
764 17 : SUBROUTINE torch_model_load_with_metadata(model, filename, key1, value1, key2, value2)
765 : TYPE(torch_model_type), INTENT(INOUT) :: model
766 : CHARACTER(len=*), INTENT(IN) :: filename, key1, key2
767 : CHARACTER(:), ALLOCATABLE, INTENT(OUT) :: value1, value2
768 :
769 : #if defined(__LIBTORCH)
770 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_load_with_metadata'
771 : INTEGER :: handle, length1, length2
772 : TYPE(C_PTR) :: content1_c, content2_c
773 :
774 : INTERFACE
775 : SUBROUTINE torch_c_model_load_with_metadata(model, filename, key1, key2, &
776 : content1, length1, content2, length2) &
777 : BIND(C, name="torch_c_model_load_with_metadata")
778 : IMPORT :: C_CHAR, C_INT, C_PTR
779 : TYPE(C_PTR) :: model
780 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename, key1, key2
781 : TYPE(C_PTR) :: content1, content2
782 : INTEGER(kind=C_INT) :: length1, length2
783 : END SUBROUTINE torch_c_model_load_with_metadata
784 : END INTERFACE
785 :
786 17 : CALL timeset(routineN, handle)
787 17 : CPASSERT(.NOT. C_ASSOCIATED(model%c_ptr))
788 17 : content1_c = C_NULL_PTR
789 17 : content2_c = C_NULL_PTR
790 17 : length1 = -1
791 17 : length2 = -1
792 : CALL torch_c_model_load_with_metadata(model=model%c_ptr, &
793 : filename=TRIM(filename)//C_NULL_CHAR, &
794 : key1=TRIM(key1)//C_NULL_CHAR, &
795 : key2=TRIM(key2)//C_NULL_CHAR, &
796 : content1=content1_c, length1=length1, &
797 17 : content2=content2_c, length2=length2)
798 17 : CPASSERT(C_ASSOCIATED(model%c_ptr))
799 17 : CALL c_string_to_allocatable(content1_c, length1, value1)
800 17 : CALL c_string_to_allocatable(content2_c, length2, value2)
801 17 : CALL timestop(handle)
802 : #else
803 : CPABORT("CP2K was compiled without Torch library.")
804 : MARK_USED(model)
805 : MARK_USED(filename)
806 : MARK_USED(key1)
807 : MARK_USED(value1)
808 : MARK_USED(key2)
809 : MARK_USED(value2)
810 : #endif
811 17 : END SUBROUTINE torch_model_load_with_metadata
812 :
813 : ! **************************************************************************************************
814 : !> \brief Maps serialized TorchScript device constants to the active Torch device.
815 : ! **************************************************************************************************
816 25 : SUBROUTINE torch_model_remap_device_constants(model)
817 : TYPE(torch_model_type), INTENT(INOUT) :: model
818 :
819 : #if defined(__LIBTORCH)
820 : INTERFACE
821 : SUBROUTINE torch_c_model_remap_device_constants(model) &
822 : BIND(C, name="torch_c_model_remap_device_constants")
823 : IMPORT :: C_PTR
824 : TYPE(C_PTR), VALUE :: model
825 : END SUBROUTINE torch_c_model_remap_device_constants
826 : END INTERFACE
827 :
828 25 : CPASSERT(C_ASSOCIATED(model%c_ptr))
829 25 : CALL torch_c_model_remap_device_constants(model=model%c_ptr)
830 : #else
831 : CPABORT("CP2K was compiled without Torch library.")
832 : MARK_USED(model)
833 : #endif
834 25 : END SUBROUTINE torch_model_remap_device_constants
835 :
836 : ! **************************************************************************************************
837 : !> \brief Promote float32 model state and explicit floating-point casts to double precision.
838 : ! **************************************************************************************************
839 17 : SUBROUTINE torch_model_promote_float32(model)
840 : TYPE(torch_model_type), INTENT(INOUT) :: model
841 :
842 : #if defined(__LIBTORCH)
843 : INTERFACE
844 : SUBROUTINE torch_c_model_promote_float32(model) BIND(C, name="torch_c_model_promote_float32")
845 : IMPORT :: C_PTR
846 : TYPE(C_PTR), VALUE :: model
847 : END SUBROUTINE torch_c_model_promote_float32
848 : END INTERFACE
849 :
850 17 : CPASSERT(C_ASSOCIATED(model%c_ptr))
851 17 : CALL torch_c_model_promote_float32(model%c_ptr)
852 : #else
853 : CPABORT("CP2K was compiled without Torch library.")
854 : MARK_USED(model)
855 : #endif
856 17 : END SUBROUTINE torch_model_promote_float32
857 :
858 : ! **************************************************************************************************
859 : !> \brief Disable gradients for inference-only model parameters.
860 : ! **************************************************************************************************
861 17 : SUBROUTINE torch_model_disable_parameter_gradients(model)
862 : TYPE(torch_model_type), INTENT(INOUT) :: model
863 :
864 : #if defined(__LIBTORCH)
865 : INTERFACE
866 : SUBROUTINE torch_c_model_disable_parameter_gradients(model) &
867 : BIND(C, name="torch_c_model_disable_parameter_gradients")
868 : IMPORT :: C_PTR
869 : TYPE(C_PTR), VALUE :: model
870 : END SUBROUTINE torch_c_model_disable_parameter_gradients
871 : END INTERFACE
872 :
873 17 : CPASSERT(C_ASSOCIATED(model%c_ptr))
874 17 : CALL torch_c_model_disable_parameter_gradients(model=model%c_ptr)
875 : #else
876 : CPABORT("CP2K was compiled without Torch library.")
877 : MARK_USED(model)
878 : #endif
879 17 : END SUBROUTINE torch_model_disable_parameter_gradients
880 :
881 : ! **************************************************************************************************
882 : !> \brief Evaluates the given Torch model.
883 : !> \author Ole Schuett
884 : ! **************************************************************************************************
885 62 : SUBROUTINE torch_model_forward(model, inputs, outputs)
886 : TYPE(torch_model_type), INTENT(INOUT) :: model
887 : TYPE(torch_dict_type), INTENT(IN) :: inputs
888 : TYPE(torch_dict_type), INTENT(INOUT) :: outputs
889 :
890 : #if defined(__LIBTORCH)
891 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_forward'
892 : INTEGER :: handle
893 :
894 : INTERFACE
895 : SUBROUTINE torch_c_model_forward(model, inputs, outputs) BIND(C, name="torch_c_model_forward")
896 : IMPORT :: C_PTR
897 : TYPE(C_PTR), VALUE :: model
898 : TYPE(C_PTR), VALUE :: inputs
899 : TYPE(C_PTR), VALUE :: outputs
900 : END SUBROUTINE torch_c_model_forward
901 : END INTERFACE
902 :
903 62 : CALL timeset(routineN, handle)
904 62 : CPASSERT(C_ASSOCIATED(model%c_ptr))
905 62 : CPASSERT(C_ASSOCIATED(inputs%c_ptr))
906 62 : CPASSERT(C_ASSOCIATED(outputs%c_ptr))
907 62 : CALL torch_c_model_forward(model=model%c_ptr, inputs=inputs%c_ptr, outputs=outputs%c_ptr)
908 62 : CALL timestop(handle)
909 : #else
910 : CPABORT("CP2K was compiled without Torch library.")
911 : MARK_USED(model)
912 : MARK_USED(inputs)
913 : MARK_USED(outputs)
914 : #endif
915 62 : END SUBROUTINE torch_model_forward
916 :
917 : ! **************************************************************************************************
918 : !> \brief Evaluates a TorchScript model method expecting keyword argument "mol".
919 : ! **************************************************************************************************
920 284 : SUBROUTINE torch_model_forward_mol_tensor(model, method_name, inputs, output)
921 : TYPE(torch_model_type), INTENT(INOUT) :: model
922 : CHARACTER(len=*), INTENT(IN) :: method_name
923 : TYPE(torch_dict_type), INTENT(IN) :: inputs
924 : TYPE(torch_tensor_type), INTENT(INOUT) :: output
925 :
926 : #if defined(__LIBTORCH)
927 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_forward_mol_tensor'
928 : INTEGER :: handle
929 :
930 : INTERFACE
931 : SUBROUTINE torch_c_model_forward_mol_tensor(model, method_name, inputs, output) &
932 : BIND(C, name="torch_c_model_forward_mol_tensor")
933 : IMPORT :: C_CHAR, C_PTR
934 : TYPE(C_PTR), VALUE :: model
935 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: method_name
936 : TYPE(C_PTR), VALUE :: inputs
937 : TYPE(C_PTR) :: output
938 : END SUBROUTINE torch_c_model_forward_mol_tensor
939 : END INTERFACE
940 :
941 284 : CALL timeset(routineN, handle)
942 284 : CPASSERT(C_ASSOCIATED(model%c_ptr))
943 284 : CPASSERT(C_ASSOCIATED(inputs%c_ptr))
944 284 : CPASSERT(.NOT. C_ASSOCIATED(output%c_ptr))
945 : CALL torch_c_model_forward_mol_tensor(model=model%c_ptr, &
946 : method_name=TRIM(method_name)//C_NULL_CHAR, &
947 : inputs=inputs%c_ptr, &
948 284 : output=output%c_ptr)
949 284 : CPASSERT(C_ASSOCIATED(output%c_ptr))
950 284 : CALL timestop(handle)
951 : #else
952 : CPABORT("CP2K was compiled without Torch library.")
953 : MARK_USED(model)
954 : MARK_USED(method_name)
955 : MARK_USED(inputs)
956 : MARK_USED(output)
957 : #endif
958 284 : END SUBROUTINE torch_model_forward_mol_tensor
959 :
960 : ! **************************************************************************************************
961 : !> \brief Releases a Torch model and all its ressources.
962 : !> \author Ole Schuett
963 : ! **************************************************************************************************
964 16 : SUBROUTINE torch_model_release(model)
965 : TYPE(torch_model_type), INTENT(INOUT) :: model
966 :
967 : #if defined(__LIBTORCH)
968 : INTERFACE
969 : SUBROUTINE torch_c_model_release(model) BIND(C, name="torch_c_model_release")
970 : IMPORT :: C_PTR
971 : TYPE(C_PTR), VALUE :: model
972 : END SUBROUTINE torch_c_model_release
973 : END INTERFACE
974 :
975 16 : CPASSERT(C_ASSOCIATED(model%c_ptr))
976 16 : CALL torch_c_model_release(model=model%c_ptr)
977 16 : model%c_ptr = C_NULL_PTR
978 : #else
979 : CPABORT("CP2K was compiled without Torch library.")
980 : MARK_USED(model)
981 : #endif
982 16 : END SUBROUTINE torch_model_release
983 :
984 : ! **************************************************************************************************
985 : !> \brief Reads metadata entry from given "*.pth" file. (In Torch lingo they are called extra files)
986 : !> \author Ole Schuett
987 : ! **************************************************************************************************
988 40 : FUNCTION torch_model_read_metadata(filename, key) RESULT(res)
989 : CHARACTER(len=*), INTENT(IN) :: filename, key
990 : CHARACTER(:), ALLOCATABLE :: res
991 :
992 : #if defined(__LIBTORCH)
993 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_read_metadata'
994 : INTEGER :: handle
995 :
996 : INTEGER :: length
997 : TYPE(C_PTR) :: content_c
998 :
999 : INTERFACE
1000 : SUBROUTINE torch_c_model_read_metadata(filename, key, content, length) &
1001 : BIND(C, name="torch_c_model_read_metadata")
1002 : IMPORT :: C_CHAR, C_PTR, C_INT
1003 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: filename, key
1004 : TYPE(C_PTR) :: content
1005 : INTEGER(kind=C_INT) :: length
1006 : END SUBROUTINE torch_c_model_read_metadata
1007 : END INTERFACE
1008 :
1009 40 : CALL timeset(routineN, handle)
1010 40 : content_c = C_NULL_PTR
1011 40 : length = -1
1012 : CALL torch_c_model_read_metadata(filename=TRIM(filename)//C_NULL_CHAR, &
1013 : key=TRIM(key)//C_NULL_CHAR, &
1014 : content=content_c, &
1015 40 : length=length)
1016 40 : CALL c_string_to_allocatable(content_c, length, res)
1017 40 : CALL timestop(handle)
1018 : #else
1019 : res = ""
1020 : MARK_USED(filename)
1021 : MARK_USED(key)
1022 : CPABORT("CP2K was compiled without Torch library.")
1023 : #endif
1024 40 : END FUNCTION torch_model_read_metadata
1025 :
1026 : ! **************************************************************************************************
1027 : !> \brief Move a C-allocated null-terminated string into an allocatable Fortran string.
1028 : ! **************************************************************************************************
1029 74 : SUBROUTINE c_string_to_allocatable(content_c, length, res)
1030 : TYPE(C_PTR), INTENT(INOUT) :: content_c
1031 : INTEGER, INTENT(IN) :: length
1032 : CHARACTER(:), ALLOCATABLE, INTENT(OUT) :: res
1033 :
1034 : #if defined(__LIBTORCH)
1035 : CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(:), &
1036 74 : POINTER :: content_f
1037 : INTEGER :: i
1038 :
1039 : INTERFACE
1040 : SUBROUTINE torch_c_free_string(content) BIND(C, name="torch_c_free_string")
1041 : IMPORT :: C_PTR
1042 : TYPE(C_PTR), VALUE :: content
1043 : END SUBROUTINE torch_c_free_string
1044 : END INTERFACE
1045 :
1046 0 : CPASSERT(C_ASSOCIATED(content_c))
1047 74 : CPASSERT(length >= 0)
1048 :
1049 148 : CALL C_F_POINTER(content_c, content_f, shape=[length + 1])
1050 74 : CPASSERT(content_f(length + 1) == C_NULL_CHAR)
1051 :
1052 74 : ALLOCATE (CHARACTER(LEN=length) :: res)
1053 2954 : DO i = 1, length
1054 2880 : CPASSERT(content_f(i) /= C_NULL_CHAR)
1055 2954 : res(i:i) = content_f(i)
1056 : END DO
1057 :
1058 74 : NULLIFY (content_f)
1059 74 : CALL torch_c_free_string(content_c)
1060 74 : content_c = C_NULL_PTR
1061 :
1062 : #else
1063 : res = ""
1064 : MARK_USED(content_c)
1065 : MARK_USED(length)
1066 : CPABORT("CP2K was compiled without Torch library.")
1067 : #endif
1068 74 : END SUBROUTINE c_string_to_allocatable
1069 :
1070 : ! **************************************************************************************************
1071 : !> \brief Returns true iff the Torch CUDA backend is available.
1072 : !> \author Ole Schuett
1073 : ! **************************************************************************************************
1074 2 : FUNCTION torch_cuda_is_available() RESULT(res)
1075 : LOGICAL :: res
1076 :
1077 : #if defined(__LIBTORCH)
1078 : INTERFACE
1079 : FUNCTION torch_c_cuda_is_available() BIND(C, name="torch_c_cuda_is_available")
1080 : IMPORT :: C_BOOL
1081 : LOGICAL(C_BOOL) :: torch_c_cuda_is_available
1082 : END FUNCTION torch_c_cuda_is_available
1083 : END INTERFACE
1084 :
1085 2 : res = torch_c_cuda_is_available()
1086 : #else
1087 : CPABORT("CP2K was compiled without Torch library.")
1088 : res = .FALSE.
1089 : #endif
1090 2 : END FUNCTION torch_cuda_is_available
1091 :
1092 : ! **************************************************************************************************
1093 : !> \brief Return the number of CUDA devices visible to Torch.
1094 : ! **************************************************************************************************
1095 0 : FUNCTION torch_cuda_device_count() RESULT(count)
1096 : INTEGER :: count
1097 :
1098 : #if defined(__LIBTORCH)
1099 : INTERFACE
1100 : FUNCTION torch_c_cuda_device_count() BIND(C, name="torch_c_cuda_device_count")
1101 : IMPORT :: C_INT
1102 : INTEGER(C_INT) :: torch_c_cuda_device_count
1103 : END FUNCTION torch_c_cuda_device_count
1104 : END INTERFACE
1105 :
1106 0 : count = torch_c_cuda_device_count()
1107 : #else
1108 : CPABORT("CP2K was compiled without Torch library.")
1109 : count = 0
1110 : #endif
1111 0 : END FUNCTION torch_cuda_device_count
1112 :
1113 : ! **************************************************************************************************
1114 : !> \brief Set whether to allow the use of TF32.
1115 : !> Needed due to changes in defaults from pytorch 1.7 to 1.11 to >=1.12
1116 : !> See https://pytorch.org/docs/stable/notes/cuda.html
1117 : !> \author Gabriele Tocci
1118 : ! **************************************************************************************************
1119 6 : SUBROUTINE torch_allow_tf32(allow_tf32)
1120 : LOGICAL, INTENT(IN) :: allow_tf32
1121 :
1122 : #if defined(__LIBTORCH)
1123 : INTERFACE
1124 : SUBROUTINE torch_c_allow_tf32(allow_tf32) BIND(C, name="torch_c_allow_tf32")
1125 : IMPORT :: C_BOOL
1126 : LOGICAL(C_BOOL), VALUE :: allow_tf32
1127 : END SUBROUTINE torch_c_allow_tf32
1128 : END INTERFACE
1129 :
1130 6 : CALL torch_c_allow_tf32(allow_tf32=LOGICAL(allow_tf32, C_BOOL))
1131 : #else
1132 : CPABORT("CP2K was compiled without Torch library.")
1133 : MARK_USED(allow_tf32)
1134 : #endif
1135 6 : END SUBROUTINE torch_allow_tf32
1136 :
1137 : ! **************************************************************************************************
1138 : !> \brief Freeze the given Torch model: applies generic optimization that speed up model.
1139 : !> See https://pytorch.org/docs/stable/generated/torch.jit.freeze.html
1140 : !> \author Gabriele Tocci
1141 : ! **************************************************************************************************
1142 6 : SUBROUTINE torch_model_freeze(model)
1143 : TYPE(torch_model_type), INTENT(INOUT) :: model
1144 :
1145 : #if defined(__LIBTORCH)
1146 : CHARACTER(len=*), PARAMETER :: routineN = 'torch_model_freeze'
1147 : INTEGER :: handle
1148 :
1149 : INTERFACE
1150 : SUBROUTINE torch_c_model_freeze(model) BIND(C, name="torch_c_model_freeze")
1151 : IMPORT :: C_PTR
1152 : TYPE(C_PTR), VALUE :: model
1153 : END SUBROUTINE torch_c_model_freeze
1154 : END INTERFACE
1155 :
1156 6 : CALL timeset(routineN, handle)
1157 6 : CPASSERT(C_ASSOCIATED(model%c_ptr))
1158 6 : CALL torch_c_model_freeze(model=model%c_ptr)
1159 6 : CALL timestop(handle)
1160 : #else
1161 : CPABORT("CP2K was compiled without Torch library.")
1162 : MARK_USED(model)
1163 : #endif
1164 6 : END SUBROUTINE torch_model_freeze
1165 :
1166 : ! **************************************************************************************************
1167 : !> \brief Freeze a Torch model while preserving one exported method.
1168 : !> \param model ...
1169 : !> \param method_name ...
1170 : ! **************************************************************************************************
1171 17 : SUBROUTINE torch_model_freeze_preserving_method(model, method_name)
1172 : TYPE(torch_model_type), INTENT(INOUT) :: model
1173 : CHARACTER(len=*), INTENT(IN) :: method_name
1174 :
1175 : #if defined(__LIBTORCH)
1176 : CHARACTER(len=*), PARAMETER :: routineN = &
1177 : 'torch_model_freeze_preserving_method'
1178 : INTEGER :: handle
1179 :
1180 : INTERFACE
1181 : SUBROUTINE torch_c_model_freeze_preserving_method(model, method_name) &
1182 : BIND(C, name="torch_c_model_freeze_preserving_method")
1183 : IMPORT :: C_CHAR, C_PTR
1184 : TYPE(C_PTR), VALUE :: model
1185 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: method_name
1186 : END SUBROUTINE torch_c_model_freeze_preserving_method
1187 : END INTERFACE
1188 :
1189 17 : CALL timeset(routineN, handle)
1190 17 : CPASSERT(C_ASSOCIATED(model%c_ptr))
1191 : CALL torch_c_model_freeze_preserving_method( &
1192 17 : model=model%c_ptr, method_name=TRIM(method_name)//C_NULL_CHAR)
1193 17 : CALL timestop(handle)
1194 : #else
1195 : CPABORT("CP2K was compiled without Torch library.")
1196 : MARK_USED(method_name)
1197 : MARK_USED(model)
1198 : #endif
1199 17 : END SUBROUTINE torch_model_freeze_preserving_method
1200 :
1201 : #:set typenames = ['int64', 'double', 'string']
1202 : #:set types_f = ['INTEGER(kind=int_8)', 'REAL(dp)', 'CHARACTER(LEN=default_string_length)']
1203 : #:set types_c = ['INTEGER(kind=C_INT64_T)', 'REAL(kind=C_DOUBLE)', 'CHARACTER(kind=C_CHAR), DIMENSION(*)']
1204 : #:set zeros_f = ['0', '0.0_dp', '""']
1205 :
1206 : #:for typename, type_f, type_c, zero_f in zip(typenames, types_f, types_c, zeros_f)
1207 : ! **************************************************************************************************
1208 : !> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
1209 : !> \author Ole Schuett
1210 : ! **************************************************************************************************
1211 64 : SUBROUTINE torch_model_get_attr_${typename}$ (model, key, dest)
1212 : TYPE(torch_model_type), INTENT(IN) :: model
1213 : CHARACTER(len=*), INTENT(IN) :: key
1214 : ${type_f}$, INTENT(OUT) :: dest
1215 :
1216 : #if defined(__LIBTORCH)
1217 :
1218 : INTERFACE
1219 : SUBROUTINE torch_c_model_get_attr_${typename}$ (model, key, dest) &
1220 : BIND(C, name="torch_c_model_get_attr_${typename}$")
1221 : IMPORT :: C_PTR, C_CHAR, C_INT64_T, C_DOUBLE
1222 : TYPE(C_PTR), VALUE :: model
1223 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
1224 : ${type_c}$ :: dest
1225 : END SUBROUTINE torch_c_model_get_attr_${typename}$
1226 : END INTERFACE
1227 :
1228 : CALL torch_c_model_get_attr_${typename}$ (model=model%c_ptr, &
1229 : key=TRIM(key)//C_NULL_CHAR, &
1230 64 : dest=dest)
1231 : #else
1232 : dest = ${zero_f}$
1233 : MARK_USED(model)
1234 : MARK_USED(key)
1235 : CPABORT("CP2K compiled without the Torch library.")
1236 : #endif
1237 64 : END SUBROUTINE torch_model_get_attr_${typename}$
1238 : #:endfor
1239 :
1240 : ! **************************************************************************************************
1241 : !> \brief Retrieves an attribute from a Torch model. Must be called before torch_model_freeze.
1242 : !> \author Ole Schuett
1243 : ! **************************************************************************************************
1244 40 : SUBROUTINE torch_model_get_attr_int32(model, key, dest)
1245 : TYPE(torch_model_type), INTENT(IN) :: model
1246 : CHARACTER(len=*), INTENT(IN) :: key
1247 : INTEGER, INTENT(OUT) :: dest
1248 :
1249 : INTEGER(kind=int_8) :: temp
1250 40 : CALL torch_model_get_attr_int64(model, key, temp)
1251 40 : CPASSERT(ABS(temp) < HUGE(dest))
1252 40 : dest = INT(temp)
1253 40 : END SUBROUTINE torch_model_get_attr_int32
1254 :
1255 : ! **************************************************************************************************
1256 : !> \brief Retrieves a list attribute from a Torch model. Must be called before torch_model_freeze.
1257 : !> \author Ole Schuett
1258 : ! **************************************************************************************************
1259 8 : SUBROUTINE torch_model_get_attr_strlist(model, key, dest)
1260 : TYPE(torch_model_type), INTENT(IN) :: model
1261 : CHARACTER(len=*), INTENT(IN) :: key
1262 : CHARACTER(LEN=default_string_length), &
1263 : ALLOCATABLE, DIMENSION(:) :: dest
1264 :
1265 : #if defined(__LIBTORCH)
1266 :
1267 : INTEGER :: num_items, i
1268 :
1269 : INTERFACE
1270 : SUBROUTINE torch_c_model_get_attr_list_size(model, key, size) &
1271 : BIND(C, name="torch_c_model_get_attr_list_size")
1272 : IMPORT :: C_PTR, C_CHAR, C_INT
1273 : TYPE(C_PTR), VALUE :: model
1274 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
1275 : INTEGER(kind=C_INT) :: size
1276 : END SUBROUTINE torch_c_model_get_attr_list_size
1277 : END INTERFACE
1278 :
1279 : INTERFACE
1280 : SUBROUTINE torch_c_model_get_attr_strlist(model, key, index, dest) &
1281 : BIND(C, name="torch_c_model_get_attr_strlist")
1282 : IMPORT :: C_PTR, C_CHAR, C_INT
1283 : TYPE(C_PTR), VALUE :: model
1284 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: key
1285 : INTEGER(kind=C_INT), VALUE :: index
1286 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: dest
1287 : END SUBROUTINE torch_c_model_get_attr_strlist
1288 : END INTERFACE
1289 :
1290 : CALL torch_c_model_get_attr_list_size(model=model%c_ptr, &
1291 : key=TRIM(key)//C_NULL_CHAR, &
1292 8 : size=num_items)
1293 24 : ALLOCATE (dest(num_items))
1294 24 : dest(:) = ""
1295 :
1296 24 : DO i = 1, num_items
1297 : CALL torch_c_model_get_attr_strlist(model=model%c_ptr, &
1298 : key=TRIM(key)//C_NULL_CHAR, &
1299 : index=i - 1, &
1300 24 : dest=dest(i))
1301 :
1302 : END DO
1303 : #else
1304 : CPABORT("CP2K compiled without the Torch library.")
1305 : MARK_USED(model)
1306 : MARK_USED(key)
1307 : MARK_USED(dest)
1308 : #endif
1309 :
1310 8 : END SUBROUTINE torch_model_get_attr_strlist
1311 :
1312 0 : END MODULE torch_api
|