LCOV - code coverage report
Current view: top level - src - torch_api.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 97.8 % 226 221
Test Date: 2026-08-14 07:04:57 Functions: 73.4 % 64 47

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

Generated by: LCOV version 2.0-1