(git:b195825)
nnp_model.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Methods dealing with core routines for artificial neural networks
10 !> \author Christoph Schran (christoph.schran@rub.de)
11 !> \date 2020-10-10
12 ! **************************************************************************************************
13 MODULE nnp_model
14 
17  cp_logger_type
18  USE kinds, ONLY: default_string_length,&
19  dp
20  USE message_passing, ONLY: mp_para_env_type
21  USE nnp_environment_types, ONLY: &
24  nnp_type
25 #include "./base/base_uses.f90"
26 
27  IMPLICIT NONE
28 
29  PRIVATE
30 
31  LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .true.
32  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nnp_model'
33 
34  PUBLIC :: nnp_write_arc, &
35  nnp_predict, &
37 
38 CONTAINS
39 
40 ! **************************************************************************************************
41 !> \brief Write neural network architecture information
42 !> \param nnp ...
43 !> \param para_env ...
44 !> \param printtag ...
45 ! **************************************************************************************************
46  SUBROUTINE nnp_write_arc(nnp, para_env, printtag)
47  TYPE(nnp_type), INTENT(IN) :: nnp
48  TYPE(mp_para_env_type), INTENT(IN) :: para_env
49  CHARACTER(LEN=*), INTENT(IN) :: printtag
50 
51  CHARACTER(len=default_string_length) :: my_label
52  INTEGER :: i, j, unit_nr
53  TYPE(cp_logger_type), POINTER :: logger
54 
55  NULLIFY (logger)
56  logger => cp_get_default_logger()
57 
58  my_label = trim(printtag)//"| "
59  IF (para_env%is_source()) THEN
60  unit_nr = cp_logger_get_default_unit_nr(logger)
61  DO i = 1, nnp%n_ele
62  WRITE (unit_nr, *) trim(my_label)//" Neural network specification for element "// &
63  nnp%ele(i)//":"
64  DO j = 1, nnp%n_layer
65  WRITE (unit_nr, '(1X,A,1X,I3,1X,A,1X,I2)') trim(my_label), &
66  nnp%arc(i)%n_nodes(j), "nodes in layer", j
67  END DO
68  END DO
69  END IF
70 
71  RETURN
72 
73  END SUBROUTINE nnp_write_arc
74 
75 ! **************************************************************************************************
76 !> \brief Predict energy by evaluating neural network
77 !> \param arc ...
78 !> \param nnp ...
79 !> \param i_com ...
80 ! **************************************************************************************************
81  SUBROUTINE nnp_predict(arc, nnp, i_com)
82  TYPE(nnp_arc_type), INTENT(INOUT) :: arc
83  TYPE(nnp_type), INTENT(INOUT) :: nnp
84  INTEGER, INTENT(IN) :: i_com
85 
86  CHARACTER(len=*), PARAMETER :: routinen = 'nnp_predict'
87 
88  INTEGER :: handle, i, j
89  REAL(kind=dp) :: norm
90 
91  CALL timeset(routinen, handle)
92 
93  DO i = 2, nnp%n_layer
94  ! Calculate node(i)
95  arc%layer(i)%node(:) = 0.0_dp
96  !Perform matrix-vector product
97  !y := alpha*A*x + beta*y
98  !with A = layer(i)*weights
99  !and x = layer(i-1)%node
100  !and y = layer(i)%node
101  CALL dgemv('T', & !transpose matrix A
102  arc%n_nodes(i - 1), & !number of rows of A
103  arc%n_nodes(i), & !number of columns of A
104  1.0_dp, & ! alpha
105  arc%layer(i)%weights(:, :, i_com), & !matrix A
106  arc%n_nodes(i - 1), & !leading dimension of A
107  arc%layer(i - 1)%node, & !vector x
108  1, & !increment for the elements of x
109  1.0_dp, & !beta
110  arc%layer(i)%node, & !vector y
111  1) !increment for the elements of y
112 
113  ! Add bias weight
114  DO j = 1, arc%n_nodes(i)
115  arc%layer(i)%node(j) = arc%layer(i)%node(j) + arc%layer(i)%bweights(j, i_com)
116  END DO
117 
118  ! Normalize by number of nodes in previous layer if requested
119  IF (nnp%normnodes) THEN
120  norm = 1.0_dp/real(arc%n_nodes(i - 1), dp)
121  DO j = 1, arc%n_nodes(i)
122  arc%layer(i)%node(j) = arc%layer(i)%node(j)*norm
123  END DO
124  END IF
125 
126  ! Store node values before application of activation function
127  ! (needed for derivatives)
128  DO j = 1, arc%n_nodes(i)
129  arc%layer(i)%node_grad(j) = arc%layer(i)%node(j)
130  END DO
131 
132  ! Apply activation function:
133  SELECT CASE (nnp%actfnct(i - 1))
134  CASE (nnp_actfnct_tanh)
135  arc%layer(i)%node(:) = tanh(arc%layer(i)%node(:))
136  CASE (nnp_actfnct_gaus)
137  arc%layer(i)%node(:) = exp(-0.5_dp*arc%layer(i)%node(:)**2)
138  CASE (nnp_actfnct_lin)
139  CONTINUE
140  CASE (nnp_actfnct_cos)
141  arc%layer(i)%node(:) = cos(arc%layer(i)%node(:))
142  CASE (nnp_actfnct_sig)
143  arc%layer(i)%node(:) = 1.0_dp/(1.0_dp + exp(-1.0_dp*arc%layer(i)%node(:)))
144  CASE (nnp_actfnct_invsig)
145  arc%layer(i)%node(:) = 1.0_dp - 1.0_dp/(1.0_dp + exp(-1.0_dp*arc%layer(i)%node(:)))
146  CASE (nnp_actfnct_exp)
147  arc%layer(i)%node(:) = exp(-1.0_dp*arc%layer(i)%node(:))
148  CASE (nnp_actfnct_softplus)
149  arc%layer(i)%node(:) = log(exp(arc%layer(i)%node(:)) + 1.0_dp)
150  CASE (nnp_actfnct_quad)
151  arc%layer(i)%node(:) = arc%layer(i)%node(:)**2
152  CASE DEFAULT
153  cpabort("NNP| Error: Unknown activation function")
154  END SELECT
155  END DO
156 
157  CALL timestop(handle)
158 
159  END SUBROUTINE nnp_predict
160 
161 ! **************************************************************************************************
162 !> \brief Calculate gradients of neural network
163 !> \param arc ...
164 !> \param nnp ...
165 !> \param i_com ...
166 !> \param denergydsym ...
167 ! **************************************************************************************************
168  SUBROUTINE nnp_gradients(arc, nnp, i_com, denergydsym)
169  TYPE(nnp_arc_type), INTENT(INOUT) :: arc
170  TYPE(nnp_type), INTENT(INOUT) :: nnp
171  INTEGER, INTENT(IN) :: i_com
172  REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: denergydsym
173 
174  CHARACTER(len=*), PARAMETER :: routinen = 'nnp_gradients'
175 
176  INTEGER :: handle, i, j, k
177  REAL(kind=dp) :: norm
178 
179  CALL timeset(routinen, handle)
180 
181  norm = 1.0_dp
182 
183  DO i = 2, nnp%n_layer
184 
185  ! Apply activation function:
186  SELECT CASE (nnp%actfnct(i - 1))
187  CASE (nnp_actfnct_tanh)
188  arc%layer(i)%node_grad(:) = 1.0_dp - arc%layer(i)%node(:)**2 !tanh(x)'=1-tanh(x)**2
189  CASE (nnp_actfnct_gaus)
190  arc%layer(i)%node_grad(:) = -1.0_dp*arc%layer(i)%node(:)*arc%layer(i)%node_grad(:)
191  CASE (nnp_actfnct_lin)
192  arc%layer(i)%node_grad(:) = 1.0_dp
193  CASE (nnp_actfnct_cos)
194  arc%layer(i)%node_grad(:) = -sin(arc%layer(i)%node_grad(:))
195  CASE (nnp_actfnct_sig)
196  arc%layer(i)%node_grad(:) = exp(-arc%layer(i)%node_grad(:))/ &
197  (1.0_dp + exp(-1.0_dp*arc%layer(i)%node_grad(:)))**2
198  CASE (nnp_actfnct_invsig)
199  arc%layer(i)%node_grad(:) = -1.0_dp*exp(-1.0_dp*arc%layer(i)%node_grad(:))/ &
200  (1.0_dp + exp(-1.0_dp*arc%layer(i)%node_grad(:)))**2
201  CASE (nnp_actfnct_exp)
202  arc%layer(i)%node_grad(:) = -1.0_dp*arc%layer(i)%node(:)
203  CASE (nnp_actfnct_softplus)
204  arc%layer(i)%node_grad(:) = (exp(arc%layer(i)%node(:)) + 1.0_dp)/ &
205  exp(arc%layer(i)%node(:))
206  CASE (nnp_actfnct_quad)
207  arc%layer(i)%node_grad(:) = 2.0_dp*arc%layer(i)%node_grad(:)
208  CASE DEFAULT
209  cpabort("NNP| Error: Unknown activation function")
210  END SELECT
211  ! Normalize by number of nodes in previous layer if requested
212  IF (nnp%normnodes) THEN
213  norm = 1.0_dp/real(arc%n_nodes(i - 1), dp)
214  arc%layer(i)%node_grad(:) = norm*arc%layer(i)%node_grad(:)
215  END IF
216 
217  END DO
218 
219  ! calculate \frac{\partial f^1(x_j^1)}{\partial G_i}*a_{ij}^{01}
220  DO j = 1, arc%n_nodes(2)
221  DO i = 1, arc%n_nodes(1)
222  arc%layer(2)%tmp_der(i, j) = arc%layer(2)%node_grad(j)*arc%layer(2)%weights(i, j, i_com)
223  END DO
224  END DO
225 
226  DO k = 3, nnp%n_layer
227  ! Reset tmp_der:
228  arc%layer(k)%tmp_der(:, :) = 0.0_dp
229  !Perform matrix-matrix product
230  !C := alpha*A*B + beta*C
231  !with A = layer(k-1)%tmp_der
232  !and B = layer(k)%weights
233  !and C = tmp
234  CALL dgemm('N', & !don't transpose matrix A
235  'N', & !don't transpose matrix B
236  arc%n_nodes(1), & !number of rows of A
237  arc%n_nodes(k), & !number of columns of B
238  arc%n_nodes(k - 1), & !number of col of A and nb of rows of B
239  1.0_dp, & !alpha
240  arc%layer(k - 1)%tmp_der, & !matrix A
241  arc%n_nodes(1), & !leading dimension of A
242  arc%layer(k)%weights(:, :, i_com), & !matrix B
243  arc%n_nodes(k - 1), & !leading dimension of B
244  1.0_dp, & !beta
245  arc%layer(k)%tmp_der, & !matrix C
246  arc%n_nodes(1)) !leading dimension of C
247 
248  ! sum over all nodes in the target layer
249  DO j = 1, arc%n_nodes(k)
250  ! sum over input layer
251  DO i = 1, arc%n_nodes(1)
252  arc%layer(k)%tmp_der(i, j) = arc%layer(k)%node_grad(j)* &
253  arc%layer(k)%tmp_der(i, j)
254  END DO
255  END DO
256  END DO
257 
258  DO i = 1, arc%n_nodes(1)
259  denergydsym(i) = arc%layer(nnp%n_layer)%tmp_der(i, 1)
260  END DO
261 
262  CALL timestop(handle)
263 
264  END SUBROUTINE nnp_gradients
265 
266 END MODULE nnp_model
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
integer, parameter, public default_string_length
Definition: kinds.F:57
Interface to the message passing library MPI.
Data types for neural network potentials.
integer, parameter, public nnp_actfnct_lin
integer, parameter, public nnp_actfnct_cos
integer, parameter, public nnp_actfnct_invsig
integer, parameter, public nnp_actfnct_sig
integer, parameter, public nnp_actfnct_exp
integer, parameter, public nnp_actfnct_softplus
integer, parameter, public nnp_actfnct_quad
integer, parameter, public nnp_actfnct_gaus
integer, parameter, public nnp_actfnct_tanh
Methods dealing with core routines for artificial neural networks.
Definition: nnp_model.F:13
subroutine, public nnp_predict(arc, nnp, i_com)
Predict energy by evaluating neural network.
Definition: nnp_model.F:82
subroutine, public nnp_gradients(arc, nnp, i_com, denergydsym)
Calculate gradients of neural network.
Definition: nnp_model.F:169
subroutine, public nnp_write_arc(nnp, para_env, printtag)
Write neural network architecture information.
Definition: nnp_model.F:47