GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_recurrent_layer.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 219 243 90.1%
Functions: 0 0 -%
Branches: 596 1255 47.5%

Line Branch Exec Source
1 module athena__recurrent_layer
2 !! Module containing implementation of recurrent neural network layers
3 !!
4 !! This module implements the simple recurrent neural network (RNN) layer,
5 !! which is designed to handle sequential data by maintaining a hidden state.
6 !!
7 !! **Simple RNN layer (equivalent to RNNCell of PyTorch):**
8 !! \[
9 !! \begin{align}
10 !! \mathbf{h}_t &= \sigma(\mathbf{W}_{ih}\mathbf{x}_t + \mathbf{W}_{hh}\mathbf{h}_{t-1} + \mathbf{b}_h) \\
11 !! \mathbf{y}_t &= \mathbf{W}_{ho}\mathbf{h}_t + \mathbf{b}_o
12 !! \end{align}
13 !! \]
14 !!
15 !! where:
16 !! - \(\mathbf{x}_t\) is input at time t
17 !! - \(\mathbf{h}_t\) is hidden state at time t
18 !! - \(\sigma\) is the activation function (e.g., tanh, relu)
19 !! - \(\mathbf{W}\) matrices are learnable weights
20 !! - \(\mathbf{b}\) vectors are learnable biases
21 !!
22 !! Properties:
23 !! - Processes sequential data with temporal dependencies
24 !! - Maintains hidden state across time steps
25 use coreutils, only: real32, stop_program
26 use athena__base_layer, only: learnable_layer_type, base_layer_type
27 use athena__misc_types, only: base_actv_type, base_init_type, &
28 onnx_node_type, onnx_initialiser_type
29 use diffstruc, only: array_type, matmul, operator(+), operator(*)
30 implicit none
31
32
33 private
34
35 public :: recurrent_layer_type
36 public :: read_recurrent_layer
37
38
39 type, extends(learnable_layer_type) :: recurrent_layer_type
40 !! Type for simple RNN layer
41 integer :: hidden_size
42 !! Size of hidden state
43 integer :: input_size
44 !! Size of input
45 integer :: time_step
46 !! Current time step
47 type(array_type), pointer :: hidden_state => null()
48 !! Hidden state
49 contains
50 procedure, pass(this) :: get_num_params => get_num_params_recurrent
51 procedure, pass(this) :: set_hyperparams => set_hyperparams_recurrent
52 procedure, pass(this) :: init => init_recurrent
53 procedure, pass(this) :: print_to_unit => print_to_unit_recurrent
54 procedure, pass(this) :: read => read_recurrent
55 procedure, pass(this) :: forward => forward_recurrent
56 procedure, pass(this) :: reset_state => reset_state_recurrent
57 end type recurrent_layer_type
58
59 interface recurrent_layer_type
60 module function layer_setup( &
61 hidden_size, input_size, use_bias, &
62 activation, &
63 kernel_initialiser, bias_initialiser, verbose &
64 ) result(layer)
65 integer, intent(in) :: hidden_size
66 integer, optional, intent(in) :: input_size
67 logical, optional, intent(in) :: use_bias
68 class(*), optional, intent(in) :: activation
69 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
70 integer, optional, intent(in) :: verbose
71 type(recurrent_layer_type) :: layer
72 end function layer_setup
73 end interface recurrent_layer_type
74
75
76
77 contains
78
79 !###############################################################################
80 8 pure function get_num_params_recurrent(this) result(num_params)
81 implicit none
82 class(recurrent_layer_type), intent(in) :: this
83 integer :: num_params
84
85 num_params = &
86 this%hidden_size * this%input_size + & ! W_ih
87 8 this%hidden_size * this%hidden_size ! W_hh
88
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if(this%use_bias)then
89 5 num_params = num_params + 2 * this%hidden_size ! b_h + b_o
90 end if
91
92 8 end function get_num_params_recurrent
93 !###############################################################################
94
95
96 !###############################################################################
97 1 subroutine reset_state_recurrent(this)
98 !! Reset the hidden state of the recurrent layer
99 implicit none
100
101 ! Arguments
102 class(recurrent_layer_type), intent(inout) :: this
103 !! Instance of the recurrent layer
104
105 1 this%time_step = 0
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(associated(this%hidden_state))then
107 call this%hidden_state%deallocate()
108 nullify(this%hidden_state)
109 end if
110
111 1 end subroutine reset_state_recurrent
112 !###############################################################################
113
114
115 !##############################################################################!
116 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
117 !##############################################################################!
118
119
120 !###############################################################################
121 8 module function layer_setup( &
122 hidden_size, input_size, use_bias, &
123 activation, &
124 kernel_initialiser, bias_initialiser, verbose &
125 8 ) result(layer)
126 !! Setup a recurrent layer
127 use athena__activation, only: activation_setup
128 use athena__initialiser, only: initialiser_setup
129 implicit none
130
131 ! Arguments
132 integer, intent(in) :: hidden_size
133 !! Size of hidden state
134 integer, optional, intent(in) :: input_size
135 !! Size of input
136 logical, optional, intent(in) :: use_bias
137 !! Whether to use bias
138 class(*), optional, intent(in) :: activation
139 !! Activation function
140 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
141 !! Activation function, kernel initialiser, and bias initialiser
142 integer, optional, intent(in) :: verbose
143 !! Verbosity level
144
145 type(recurrent_layer_type) :: layer
146 !! Instance of the recurrent layer
147
148 ! Local variables
149 integer :: verbose_ = 0
150 !! Verbosity level
151 logical :: use_bias_ = .true.
152 !! Whether to use bias
153 24 class(base_actv_type), allocatable :: activation_
154 !! Activation function
155 25 class(base_init_type), allocatable :: kernel_initialiser_, bias_initialiser_
156 !! Kernel and bias initialisers
157
158 if(present(verbose)) verbose_ = verbose
159
160
161 !---------------------------------------------------------------------------
162 ! Set use_bias
163 !---------------------------------------------------------------------------
164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if(present(use_bias)) use_bias_ = use_bias
165
166
167 !---------------------------------------------------------------------------
168 ! Set activation functions based on input name
169 !---------------------------------------------------------------------------
170
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 if(present(activation))then
171
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 activation_ = activation_setup(activation)
172 else
173
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 activation_ = activation_setup("tanh")
174 end if
175
176
177 !---------------------------------------------------------------------------
178 ! Define weights (kernels) and biases initialisers
179 !---------------------------------------------------------------------------
180
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
8 if(present(kernel_initialiser))then
181
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 kernel_initialiser_ = initialiser_setup(kernel_initialiser)
182 end if
183
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if(present(bias_initialiser))then
184 bias_initialiser_ = initialiser_setup(bias_initialiser)
185 end if
186
187
188 !---------------------------------------------------------------------------
189 ! Set hyperparameters
190 !---------------------------------------------------------------------------
191 call layer%set_hyperparams( &
192 hidden_size = hidden_size, &
193 use_bias = use_bias_, &
194 activation = activation_, &
195 kernel_initialiser = kernel_initialiser_, &
196 bias_initialiser = bias_initialiser_, &
197 verbose = verbose_ &
198 8 )
199
200
201 !---------------------------------------------------------------------------
202 ! Initialise layer shape
203 !---------------------------------------------------------------------------
204
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
14 if(present(input_size)) call layer%init(input_shape=[input_size])
205
206
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
16 end function layer_setup
207 !###############################################################################
208
209
210 !###############################################################################
211 9 subroutine set_hyperparams_recurrent( &
212 this, hidden_size, &
213 use_bias, &
214 activation, &
215 kernel_initialiser, bias_initialiser, &
216 verbose &
217 )
218 !! Set the hyperparameters for fully connected layer
219 use athena__activation, only: activation_setup
220 use athena__initialiser, only: get_default_initialiser, initialiser_setup
221 implicit none
222
223 ! Arguments
224 class(recurrent_layer_type), intent(inout) :: this
225 !! Instance of the recurrent layer
226 integer, intent(in) :: hidden_size
227 !! Number of hidden units
228 logical, intent(in) :: use_bias
229 !! Whether to use bias
230 class(base_actv_type), allocatable, intent(in) :: activation
231 !! Activation function
232 class(base_init_type), allocatable, intent(in) :: &
233 kernel_initialiser, bias_initialiser
234 !! Kernel and bias initialisers
235 integer, optional, intent(in) :: verbose
236 !! Verbosity level
237
238 ! Local variables
239 character(len=256) :: buffer
240
241
242
5/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
9 this%name = "recu"
243 9 this%type = "recurrent"
244 9 this%input_rank = 1
245 9 this%output_rank = 1
246 9 this%use_bias = use_bias
247 9 this%hidden_size = hidden_size
248
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
9 if(allocated(this%activation)) deallocate(this%activation)
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(.not.allocated(activation))then
250 this%activation = activation_setup("none")
251 else
252
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 allocate(this%activation, source=activation)
253 end if
254
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
9 if(allocated(this%kernel_init)) deallocate(this%kernel_init)
255
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if(.not.allocated(kernel_initialiser))then
256
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 buffer = get_default_initialiser(this%activation%name)
257
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 7 times.
✓ Branch 17 taken 7 times.
✗ Branch 18 not taken.
7 this%kernel_init = initialiser_setup(buffer)
258 else
259
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 allocate(this%kernel_init, source=kernel_initialiser)
260 end if
261
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
9 if(allocated(this%bias_init)) deallocate(this%bias_init)
262
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if(.not.allocated(bias_initialiser))then
263 buffer = get_default_initialiser( &
264 this%activation%name, &
265 is_bias=.true. &
266
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 )
267
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
8 this%bias_init = initialiser_setup(buffer)
268 else
269
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 allocate(this%bias_init, source=bias_initialiser)
270 end if
271
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(present(verbose))then
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(abs(verbose).gt.0)then
273 write(*,'("RECU activation function: ",A)') &
274 trim(this%activation%name)
275 write(*,'("RECU kernel initialiser: ",A)') &
276 trim(this%kernel_init%name)
277 write(*,'("RECU bias initialiser: ",A)') &
278 trim(this%bias_init%name)
279 end if
280 end if
281
282 9 end subroutine set_hyperparams_recurrent
283 !###############################################################################
284
285
286 !###############################################################################
287
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 subroutine init_recurrent(this, input_shape, verbose)
288 !! Initialise the recurrent layer
289 implicit none
290
291 ! Arguments
292 class(recurrent_layer_type), intent(inout) :: this
293 !! Instance of the recurrent layer
294 integer, dimension(:), intent(in) :: input_shape
295 !! Shape of the input
296 integer, optional, intent(in) :: verbose
297 !! Verbosity level
298
299 ! Local variables
300 integer :: num_inputs
301 !! Temporary variable
302 integer :: verbose_ = 0
303
304
305 !---------------------------------------------------------------------------
306 ! Initialise optional arguments
307 !---------------------------------------------------------------------------
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if(present(verbose)) verbose_ = verbose
309
310
311 !---------------------------------------------------------------------------
312 ! Initialise number of inputs
313 !---------------------------------------------------------------------------
314
4/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
8 if(.not.allocated(this%input_shape)) call this%set_shape(input_shape)
315
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%input_size = this%input_shape(1)
316
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 8 times.
16 this%output_shape = [this%hidden_size]
317 8 this%num_params = this%get_num_params()
318
319
320 !---------------------------------------------------------------------------
321 ! Allocate weight, weight steps (velocities), output, and activation
322 !---------------------------------------------------------------------------
323
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 allocate(this%weight_shape(2,2))
324
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 8 times.
24 this%weight_shape(:,1) = [ this%hidden_size, this%input_size ]
325
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 8 times.
24 this%weight_shape(:,2) = [ this%hidden_size, this%hidden_size ]
326
327
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if(this%use_bias)then
328
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 5 times.
15 this%bias_shape = [ this%hidden_size, this%hidden_size ]
329
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✓ Branch 21 taken 20 times.
✓ Branch 22 taken 5 times.
✓ Branch 23 taken 20 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 20 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 20 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 20 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 20 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 20 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 20 times.
25 allocate(this%params(4))
330 else
331
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✓ Branch 21 taken 6 times.
✓ Branch 22 taken 3 times.
✓ Branch 23 taken 6 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 6 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 6 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 6 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 6 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 6 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 6 times.
9 allocate(this%params(2))
332 end if
333
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
✓ Branch 27 taken 16 times.
✓ Branch 28 taken 8 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 8 times.
✓ Branch 31 taken 24 times.
✓ Branch 32 taken 8 times.
48 call this%params(1)%allocate([this%weight_shape(:,1), 1])
334
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 call this%params(1)%set_requires_grad(.true.)
335
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(1)%fix_pointer = .true.
336
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(1)%is_sample_dependent = .false.
337
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(1)%is_temporary = .false.
338
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
✓ Branch 27 taken 16 times.
✓ Branch 28 taken 8 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 8 times.
✓ Branch 31 taken 24 times.
✓ Branch 32 taken 8 times.
48 call this%params(2)%allocate([this%weight_shape(:,2), 1])
339
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 call this%params(2)%set_requires_grad(.true.)
340
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(2)%fix_pointer = .true.
341
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(2)%is_sample_dependent = .false.
342
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 this%params(2)%is_temporary = .false.
343
344 8 num_inputs = this%input_size + this%hidden_size
345
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if(this%use_bias)then
346 5 num_inputs = num_inputs + 2 * this%hidden_size
347
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 10 times.
✓ Branch 13 taken 5 times.
15 call this%params(3)%allocate([this%bias_shape(1), 1])
348
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 call this%params(3)%set_requires_grad(.true.)
349
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(3)%fix_pointer = .true.
350
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(3)%is_sample_dependent = .false.
351
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(3)%is_temporary = .false.
352
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 10 times.
✓ Branch 13 taken 5 times.
15 call this%params(4)%allocate([this%bias_shape(2), 1])
353
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 call this%params(4)%set_requires_grad(.true.)
354
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(4)%fix_pointer = .true.
355
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(4)%is_sample_dependent = .false.
356
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%params(4)%is_temporary = .false.
357 end if
358
359
360 !---------------------------------------------------------------------------
361 ! Initialise weights (kernels)
362 !---------------------------------------------------------------------------
363 call this%kernel_init%initialise( &
364 80 this%params(1)%val(:,1), &
365 fan_in = num_inputs, fan_out = this%hidden_size, &
366 spacing = [ this%hidden_size ] &
367
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 8 times.
✓ Branch 30 taken 8 times.
✓ Branch 31 taken 8 times.
16 )
368 call this%kernel_init%initialise( &
369 80 this%params(2)%val(:,1), &
370 fan_in = num_inputs, fan_out = this%hidden_size, &
371 spacing = [ this%hidden_size ] &
372
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 8 times.
✓ Branch 30 taken 8 times.
✓ Branch 31 taken 8 times.
16 )
373
374 ! Initialise biases
375 !---------------------------------------------------------------------------
376
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if(this%use_bias)then
377 call this%bias_init%initialise( &
378 50 this%params(3)%val(:,1), &
379 fan_in = num_inputs, fan_out = this%hidden_size &
380
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 5 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 5 times.
5 )
381 call this%bias_init%initialise( &
382 50 this%params(4)%val(:,1), &
383 fan_in = num_inputs, fan_out = this%hidden_size &
384
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 5 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 5 times.
5 )
385 end if
386
387
388 !---------------------------------------------------------------------------
389 ! Allocate arrays and initialise time_step
390 !---------------------------------------------------------------------------
391
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8 if(allocated(this%output)) deallocate(this%output)
392
15/26
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 8 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 8 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 8 times.
✓ Branch 33 taken 8 times.
✓ Branch 34 taken 8 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 8 times.
24 allocate(this%output(1,1))
393 8 this%time_step = 0
394
395 8 end subroutine init_recurrent
396 !###############################################################################
397
398
399 !##############################################################################!
400 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
401 !##############################################################################!
402
403
404 !###############################################################################
405 1 subroutine print_to_unit_recurrent(this, unit)
406 !! Print recurrent layer to unit
407 use coreutils, only: to_upper
408 implicit none
409
410 ! Arguments
411 class(recurrent_layer_type), intent(in) :: this
412 !! Instance of the fully connected layer
413 integer, intent(in) :: unit
414 !! File unit
415
416
417 ! Write initial parameters
418 !---------------------------------------------------------------------------
419 1 write(unit,'(3X,"INPUT_SIZE = ",I0)') this%input_size
420 1 write(unit,'(3X,"HIDDEN_SIZE = ",I0)') this%hidden_size
421
422 1 write(unit,'(3X,"USE_BIAS = ",L1)') this%use_bias
423
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%activation%name .ne. 'none')then
424 1 call this%activation%print_to_unit(unit)
425 end if
426
427
428 ! Write fully connected weights and biases
429 !---------------------------------------------------------------------------
430 1 write(unit,'("WEIGHTS")')
431
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 21 times.
✓ Branch 26 taken 1 times.
22 write(unit,'(5(E16.8E2))') this%params(1)%val(:,1)
432
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 49 times.
✓ Branch 26 taken 1 times.
50 write(unit,'(5(E16.8E2))') this%params(2)%val(:,1)
433
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
434
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 7 times.
✓ Branch 26 taken 1 times.
8 write(unit,'(5(E16.8E2))') this%params(3)%val(:,1)
435
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 7 times.
✓ Branch 26 taken 1 times.
8 write(unit,'(5(E16.8E2))') this%params(4)%val(:,1)
436 end if
437 1 write(unit,'("END WEIGHTS")')
438
439 1 end subroutine print_to_unit_recurrent
440 !###############################################################################
441
442
443 !###############################################################################
444 1 subroutine read_recurrent(this, unit, verbose)
445 !! Read recurrent layer from file
446 use athena__tools_infile, only: assign_val, assign_vec, move
447 use coreutils, only: to_lower, to_upper, icount
448 use athena__activation, only: read_activation
449 use athena__initialiser, only: initialiser_setup
450 implicit none
451
452 ! Arguments
453 class(recurrent_layer_type), intent(inout) :: this
454 !! Instance of the recurrent layer
455 integer, intent(in) :: unit
456 !! Unit number
457 integer, optional, intent(in) :: verbose
458 !! Verbosity level
459
460 ! Local variables
461 integer :: stat
462 !! Status of read
463 integer :: verbose_ = 0
464 !! Verbosity level
465 integer :: i, j, k, c, itmp1, iline, num_params
466 !! Loop variables and temporary integer
467 integer :: input_size, hidden_size
468 !! Input and hidden sizes
469 logical :: use_bias = .true.
470 !! Whether to use bias
471 character(14) :: kernel_initialiser_name='', bias_initialiser_name=''
472 !! Initialisers
473 character(20) :: activation_name=''
474 !! Activation function
475 3 class(base_actv_type), allocatable :: activation
476 !! Activation function
477 5 class(base_init_type), allocatable :: kernel_initialiser, bias_initialiser
478 !! Initialisers
479 character(256) :: buffer, tag, err_msg
480 !! Buffer, tag, and error message
481 integer, dimension(2) :: input_shape
482 !! Input shape
483 1 real(real32), allocatable, dimension(:) :: data_list
484 !! Data list
485 integer :: param_line, final_line
486 !! Parameter line number
487
488
489 ! Initialise optional arguments
490 !---------------------------------------------------------------------------
491
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(verbose)) verbose_ = verbose
492
493
494 ! Loop over tags in layer card
495 !---------------------------------------------------------------------------
496 1 iline = 0
497 1 param_line = 0
498 1 final_line = 0
499 25 tag_loop: do
500
501 ! Check for end of file
502 !------------------------------------------------------------------------
503 26 read(unit,'(A)',iostat=stat) buffer
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if(stat.ne.0)then
505 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
506 to_upper(this%name)
507 call stop_program(err_msg)
508 return
509 end if
510
2/4
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
26 if(trim(adjustl(buffer)).eq."") cycle tag_loop
511
512 ! Check for end of layer card
513 !------------------------------------------------------------------------
514
4/6
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 25 times.
52 if(trim(adjustl(buffer)).eq."END "//to_upper(trim(this%name)))then
515 1 final_line = iline
516 1 backspace(unit)
517 26 exit tag_loop
518 end if
519 25 iline = iline + 1
520
521
2/4
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
25 tag=trim(adjustl(buffer))
522
6/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
25 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
523
524 ! Read parameters from file
525 !------------------------------------------------------------------------
526 50 select case(trim(tag))
527 case("INPUT_SIZE", "NUM_INPUTS")
528 2 call assign_val(buffer, input_size, itmp1)
529 case("HIDDEN_SIZE", "NUM_OUTPUTS")
530 2 call assign_val(buffer, hidden_size, itmp1)
531 case("USE_BIAS")
532 2 call assign_val(buffer, use_bias, itmp1)
533 case("ACTIVATION")
534 1 iline = iline - 1
535 1 backspace(unit)
536
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 activation = read_activation(unit, iline)
537 case("KERNEL_INITIALISER", "KERNEL_INIT", "KERNEL_INITIALIZER")
538 call assign_val(buffer, kernel_initialiser_name, itmp1)
539 case("BIAS_INITIALISER", "BIAS_INIT", "BIAS_INITIALIZER")
540 call assign_val(buffer, bias_initialiser_name, itmp1)
541 case("WEIGHTS")
542 1 kernel_initialiser_name = 'zeros'
543 1 bias_initialiser_name = 'zeros'
544 1 param_line = iline
545 case default
546 ! Don't look for "e" due to scientific notation of numbers
547 ! ... i.e. exponent (E+00)
548
3/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 1 times.
40 if(scan(to_lower(trim(adjustl(buffer))),&
549 'abcdfghijklmnopqrstuvwxyz').eq.0)then
550 20 cycle tag_loop
551
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(tag(:3).eq.'END')then
552 20 cycle tag_loop
553 end if
554 write(err_msg,'("Unrecognised line in input file: ",A)') &
555 trim(adjustl(buffer))
556 call stop_program(err_msg)
557
7/10
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 20 times.
50 return
558 end select
559 end do tag_loop
560
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 kernel_initialiser = initialiser_setup(kernel_initialiser_name)
561
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 bias_initialiser = initialiser_setup(bias_initialiser_name)
562
563
564 ! Set hyperparameters and initialise layer
565 !---------------------------------------------------------------------------
566 call this%set_hyperparams( &
567 hidden_size = hidden_size, &
568 use_bias = use_bias, &
569 activation = activation, &
570 kernel_initialiser = kernel_initialiser, &
571 bias_initialiser = bias_initialiser, &
572 verbose = verbose_ &
573 1 )
574
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 call this%init(input_shape=[input_size])
575
576
577 ! Check if WEIGHTS card was found
578 !---------------------------------------------------------------------------
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(param_line.eq.0)then
580 write(0,*) "WARNING: WEIGHTS card in "//to_upper(trim(this%name))//" not found"
581 else
582 1 call move(unit, param_line - iline, iostat=stat)
583 1 num_params = this%input_size * this%hidden_size
584
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_params), source=0._real32)
585 1 c = 1
586 1 k = 1
587
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 data_concat_loop: do while(c.le.num_params)
588 5 read(unit,'(A)',iostat=stat) buffer
589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(stat.ne.0) exit data_concat_loop
590 5 k = icount(buffer)
591
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 21 times.
26 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
592 5 c = c + k
593 end do data_concat_loop
594
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 21 times.
✓ Branch 40 taken 1 times.
22 this%params(1)%val(:,1) = data_list
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
596 1 num_params = this%hidden_size * this%hidden_size
597
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_params), source=0._real32)
598 1 c = 1
599 1 k = 1
600
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 data_concat_loop1: do while(c.le.num_params)
601 10 read(unit,'(A)',iostat=stat) buffer
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if(stat.ne.0) exit data_concat_loop1
603 10 k = icount(buffer)
604
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 49 times.
59 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
605 10 c = c + k
606 end do data_concat_loop1
607
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 49 times.
✓ Branch 40 taken 1 times.
50 this%params(2)%val(:,1) = data_list
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
609
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(use_bias)then
610
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 do i = 1, 2
611 2 hidden_size = this%hidden_size
612
7/14
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
2 allocate(data_list(hidden_size), source=0._real32)
613 2 c = 1
614 2 k = 1
615
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 data_concat_loop_bias: do while(c.le.hidden_size)
616 4 read(unit,'(A)',iostat=stat) buffer
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(stat.ne.0) exit data_concat_loop_bias
618 4 k = icount(buffer)
619
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 14 times.
18 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
620 4 c = c + k
621 end do data_concat_loop_bias
622
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 2 times.
✓ Branch 39 taken 14 times.
✓ Branch 40 taken 2 times.
16 this%params(i+2)%val(:,1) = data_list(1:hidden_size)
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
3 deallocate(data_list)
624 end do
625 end if
626
627 ! Check for end of weights card
628 !------------------------------------------------------------------------
629 1 read(unit,'(A)') buffer
630
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if(trim(adjustl(buffer)).ne."END WEIGHTS")then
631 write(0,*) trim(adjustl(buffer))
632 call stop_program("END WEIGHTS not where expected")
633 return
634 end if
635 end if
636
637
638 !---------------------------------------------------------------------------
639 ! Check for end of layer card
640 !---------------------------------------------------------------------------
641 1 call move(unit, final_line - iline, iostat=stat)
642 1 read(unit,'(A)') buffer
643
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
2 if(trim(adjustl(buffer)).ne."END "//to_upper(trim(this%name)))then
644 write(0,*) trim(adjustl(buffer))
645 write(err_msg,'("END ",A," not where expected")') to_upper(this%name)
646 call stop_program(err_msg)
647 1 return
648 end if
649
650
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 end subroutine read_recurrent
651 !###############################################################################
652
653
654 !###############################################################################
655 1 function read_recurrent_layer(unit, verbose) result(layer)
656 !! Read recurrent layer from file and return layer
657 implicit none
658
659 ! Arguments
660 integer, intent(in) :: unit
661 !! Unit number
662 integer, optional, intent(in) :: verbose
663 !! Verbosity level
664 class(base_layer_type), allocatable :: layer
665 !! Instance of the fully connected layer
666
667 ! Local variables
668 integer :: verbose_ = 0
669 !! Verbosity level
670
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(present(verbose)) verbose_ = verbose
672
21/78
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 1 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 1 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 1 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1 times.
✓ Branch 65 taken 1 times.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 1 times.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✓ Branch 75 taken 1 times.
✓ Branch 77 taken 1 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1 times.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✓ Branch 82 taken 1 times.
✓ Branch 84 taken 1 times.
✗ Branch 85 not taken.
2 allocate(layer, source=recurrent_layer_type(hidden_size=0))
673 1 call layer%read(unit, verbose=verbose_)
674
675 2 end function read_recurrent_layer
676 !###############################################################################
677
678
679 !##############################################################################!
680 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
681 !##############################################################################!
682
683
684 !###############################################################################
685
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 subroutine forward_recurrent(this, input)
686 !! Forward propagation
687 implicit none
688
689 ! Arguments
690 class(recurrent_layer_type), intent(inout) :: this
691 !! Instance of the recurrent layer
692 class(array_type), dimension(:,:), intent(in) :: input
693 !! Input values
694
695 type(array_type), pointer :: ptr1, ptr2, ptr
696
697
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(.not.associated(this%hidden_state))then
698 1 call this%reset_state()
699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 allocate(this%hidden_state)
700 call this%hidden_state%allocate( &
701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 [this%hidden_size, size(input(1,1)%val,2)], &
702 source = 0._real32 &
703
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
4 )
704 1 this%hidden_state%is_temporary = .false.
705 end if
706
707
708 ! Generate outputs from weights, biases, and inputs
709 !---------------------------------------------------------------------------
710
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(this%use_bias)then
711
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 3 times.
3 ptr1 => matmul(this%params(1), input(1,1) ) + this%params(3)
712
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
3 ptr2 => matmul(this%params(2), this%hidden_state ) + this%params(4)
713 else
714 ptr1 => matmul(this%params(1), input(1,1) )
715 ptr2 => matmul(this%params(2), this%hidden_state )
716 end if
717 3 ptr => ptr1 + ptr2
718
719 ! Apply activation function to activation
720 !---------------------------------------------------------------------------
721
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 call this%output(1,1)%zero_grad()
722
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 if(trim(this%activation%name) .ne. "none")then
723 3 ptr => this%activation%apply(ptr)
724 end if
725 3 this%hidden_state => ptr
726
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 call this%output(1,1)%assign_shallow(ptr)
727
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 this%output(1,1)%is_temporary = .false.
728 3 this%time_step = this%time_step + 1
729
730 3 end subroutine forward_recurrent
731 !###############################################################################
732
733
59/155
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 2 times.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 2 times.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✓ Branch 43 taken 1 times.
✓ Branch 44 taken 2 times.
✓ Branch 45 taken 3 times.
✓ Branch 46 taken 1 times.
✓ Branch 47 taken 2 times.
✓ Branch 48 taken 3 times.
✓ Branch 49 taken 2 times.
✓ Branch 50 taken 2 times.
✓ Branch 51 taken 2 times.
✓ Branch 52 taken 2 times.
✓ Branch 53 taken 2 times.
✓ Branch 54 taken 2 times.
✓ Branch 55 taken 2 times.
✓ Branch 56 taken 2 times.
✓ Branch 57 taken 8 times.
✓ Branch 58 taken 2 times.
✓ Branch 59 taken 8 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 8 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 8 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 8 times.
✓ Branch 67 taken 1 times.
✓ Branch 68 taken 8 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 9 times.
✓ Branch 71 taken 5 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✓ Branch 74 taken 5 times.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✓ Branch 77 taken 4 times.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✓ Branch 109 taken 1 times.
✗ Branch 110 not taken.
✓ Branch 111 taken 1 times.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✓ Branch 114 taken 1 times.
✓ Branch 115 taken 1 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 1 times.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✓ Branch 121 taken 1 times.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✓ Branch 125 taken 1 times.
✓ Branch 126 taken 1 times.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✓ Branch 129 taken 1 times.
✓ Branch 130 taken 1 times.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✓ Branch 133 taken 1 times.
✓ Branch 134 taken 1 times.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✓ Branch 137 taken 1 times.
✓ Branch 139 taken 1 times.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✓ Branch 142 taken 1 times.
✗ Branch 143 not taken.
✓ Branch 144 taken 1 times.
✓ Branch 146 taken 1 times.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✓ Branch 149 taken 1 times.
✗ Branch 150 not taken.
✓ Branch 151 taken 1 times.
✓ Branch 153 taken 1 times.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✓ Branch 156 taken 1 times.
✗ Branch 157 not taken.
✓ Branch 158 taken 1 times.
40 end module athena__recurrent_layer
734