GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_conv2d_layer.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 218 267 81.6%
Functions: 0 0 -%
Branches: 564 1367 41.3%

Line Branch Exec Source
1 module athena__conv2d_layer
2 !! Module containing implementation of a 2D convolutional layer
3 !!
4 !! This module implements 2D convolution for processing image-like data.
5 !! Applies learnable filters to extract spatial features.
6 !!
7 !! Mathematical operation:
8 !! \[ y_{i,j,k} =
9 !! \sigma\left(
10 !! \sum_{c=1}^{C_{in}}
11 !! \sum_{m=0}^{K_h-1}
12 !! \sum_{n=0}^{K_w-1}
13 !! x_{i+m,j+n,c} \cdot w_{m,n,c,k} + b_k
14 !! \right)
15 !! \]
16 !!
17 !! where:
18 !! - \((i,j)\) are spatial coordinates in the output
19 !! - \(k\) is the output channel (filter) index
20 !! - \((m,n)\) are kernel offsets
21 !! - \(c\) is the input channel index
22 !! - \(K_h, K_w\) are kernel dimensions
23 !! - \(\sigma\) is the activation function
24 !!
25 !! Shape: \((W, H, C_{in}) \rightarrow (W', H', C_{out})\)
26 use coreutils, only: real32, stop_program
27 use athena__base_layer, only: conv_layer_type, base_layer_type
28 use athena__pad2d_layer, only: pad2d_layer_type
29 use athena__misc_types, only: base_init_type, &
30 onnx_node_type, onnx_initialiser_type, onnx_tensor_type
31 use athena__misc_types, only: base_actv_type, base_init_type
32 use diffstruc, only: array_type
33 use athena__diffstruc_extd, only: conv2d, add_bias
34 use athena__initialiser_data, only: data_init_type
35 implicit none
36
37
38 private
39
40 public :: conv2d_layer_type
41 public :: read_conv2d_layer
42
43
44 type, extends(conv_layer_type) :: conv2d_layer_type
45 !! Type for 2D convolutional layer with overloaded procedures
46 contains
47 procedure, pass(this) :: set_hyperparams => set_hyperparams_conv2d
48 !! Set hyperparameters for 2D convolutional layer
49 procedure, pass(this) :: read => read_conv2d
50 !! Read 2D convolutional layer from file
51 procedure, pass(this) :: build_from_onnx => build_from_onnx_conv2d
52 !! Build 2D convolutional layer from ONNX node and initialiser
53
54 procedure, pass(this) :: forward => forward_conv2d
55 !! Forward propagation derived type handler
56
57 final :: finalise_conv2d
58 !! Finalise 2D convolutional layer
59 end type conv2d_layer_type
60
61 interface conv2d_layer_type
62 !! Interface for setting up the 2D convolutional layer
63 module function layer_setup( &
64 input_shape, &
65 num_filters, kernel_size, stride, dilation, padding, &
66 use_bias, &
67 activation, &
68 kernel_initialiser, bias_initialiser, &
69 verbose ) result(layer)
70 !! Set up the 2D convolutional layer
71 integer, dimension(:), optional, intent(in) :: input_shape
72 !! Input shape
73 integer, optional, intent(in) :: num_filters
74 !! Number of filters
75 integer, dimension(..), optional, intent(in) :: kernel_size
76 !! Kernel size
77 integer, dimension(..), optional, intent(in) :: stride
78 !! Stride
79 integer, dimension(..), optional, intent(in) :: dilation
80 !! Dilation
81 logical, optional, intent(in) :: use_bias
82 !! Use bias
83 class(*), optional, intent(in) :: activation, &
84 kernel_initialiser, bias_initialiser
85 !! Activation function, kernel initialiser, bias initialiser
86 character(*), optional, intent(in) :: padding
87 !! Padding method
88 integer, optional, intent(in) :: verbose
89 !! Verbosity level
90 type(conv2d_layer_type) :: layer
91 !! Instance of the 2D convolutional layer
92 end function layer_setup
93 end interface conv2d_layer_type
94
95
96
97 contains
98
99 !###############################################################################
100 !!! finalise layer
101 !###############################################################################
102 48 subroutine finalise_conv2d(this)
103 !! Finalise 2D convolutional layer
104 implicit none
105
106 ! Arguments
107 type(conv2d_layer_type), intent(inout) :: this
108 !! Instance of the 2D convolutional layer
109
110
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if(allocated(this%dil)) deallocate(this%dil)
111
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if(allocated(this%knl)) deallocate(this%knl)
112
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if(allocated(this%stp)) deallocate(this%stp)
113
114
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
48 if(allocated(this%input_shape)) deallocate(this%input_shape)
115
4/6
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
48 if(allocated(this%output)) deallocate(this%output)
116
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
48 if(allocated(this%pad_layer)) deallocate(this%pad_layer)
117
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 38 times.
48 if(this%z(1)%allocated) call this%z(1)%deallocate()
118
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 39 times.
48 if(this%z(2)%allocated) call this%z(2)%deallocate()
119
120 48 end subroutine finalise_conv2d
121 !###############################################################################
122
123
124 !##############################################################################!
125 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
126 !##############################################################################!
127
128
129 !###############################################################################
130 34 module function layer_setup( &
131
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
34 input_shape, &
132 num_filters, kernel_size, stride, dilation, padding, &
133 use_bias, &
134 activation, &
135 kernel_initialiser, bias_initialiser, &
136
9/16
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 68 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 68 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 68 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 68 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 68 times.
102 verbose ) result(layer)
137 !! Set up the 2D convolutional layer
138 use athena__activation, only: activation_setup
139 use athena__initialiser, only: initialiser_setup
140 implicit none
141
142 ! Arguments
143 integer, dimension(:), optional, intent(in) :: input_shape
144 !! Input shape
145 integer, optional, intent(in) :: num_filters
146 !! Number of filters
147 integer, dimension(..), optional, intent(in) :: kernel_size
148 !! Kernel size
149 integer, dimension(..), optional, intent(in) :: stride
150 !! Stride
151 integer, dimension(..), optional, intent(in) :: dilation
152 !! Dilation
153 logical, optional, intent(in) :: use_bias
154 !! Use bias
155 class(*), optional, intent(in) :: activation
156 !! Activation function
157 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
158 !! Activation function, kernel initialiser, and bias initialiser
159 character(*), optional, intent(in) :: padding
160 !! Padding method
161 integer, optional, intent(in) :: verbose
162 !! Verbosity level
163
164 type(conv2d_layer_type) :: layer
165 !! Instance of the 2D convolutional layer
166
167 ! Local variables
168 integer :: verbose_ = 0
169 !! Verbosity level
170 integer :: num_filters_
171 !! Number of filters
172 logical :: use_bias_ = .true.
173 !! Use bias
174 character(len=20) :: padding_
175 !! Padding
176 integer, dimension(2) :: kernel_size_, stride_, dilation_
177 !! Kernel size and stride
178 102 class(base_actv_type), allocatable :: activation_
179 !! Activation function
180 34 class(base_init_type), allocatable :: kernel_initialiser_, bias_initialiser_
181 !! Kernel and bias initialisers
182
183
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 23 times.
34 if(present(verbose)) verbose_ = verbose
184
185
186 !---------------------------------------------------------------------------
187 ! Set use_bias
188 !---------------------------------------------------------------------------
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if(present(use_bias)) use_bias_ = use_bias
190
191
192 !---------------------------------------------------------------------------
193 ! Set activation functions based on input name
194 !---------------------------------------------------------------------------
195
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
34 if(present(activation))then
196
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 16 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 16 times.
✓ Branch 17 taken 16 times.
✗ Branch 18 not taken.
16 activation_ = activation_setup(activation)
197 else
198
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 18 times.
✓ Branch 17 taken 18 times.
✗ Branch 18 not taken.
18 activation_ = activation_setup("none")
199 end if
200
201
202 !---------------------------------------------------------------------------
203 ! Define weights (kernels) and biases initialisers
204 !---------------------------------------------------------------------------
205
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
34 if(present(kernel_initialiser))then
206
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 23 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 23 times.
✓ Branch 17 taken 23 times.
✗ Branch 18 not taken.
23 kernel_initialiser_ = initialiser_setup(kernel_initialiser)
207 end if
208
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
34 if(present(bias_initialiser))then
209
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 10 times.
✓ Branch 17 taken 10 times.
✗ Branch 18 not taken.
10 bias_initialiser_ = initialiser_setup(bias_initialiser)
210 end if
211
212
213 !---------------------------------------------------------------------------
214 ! Set up number of filters
215 !---------------------------------------------------------------------------
216
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if(present(num_filters))then
217 17 num_filters_ = num_filters
218 else
219 17 num_filters_ = 32
220 end if
221
222
223 !---------------------------------------------------------------------------
224 ! Set up kernel size
225 !---------------------------------------------------------------------------
226
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
34 if(present(kernel_size))then
227 19 select rank(kernel_size)
228 rank(0)
229
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 kernel_size_ = kernel_size
230 rank(1)
231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 kernel_size_(1) = kernel_size(1)
232
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
6 if(size(kernel_size,dim=1).eq.1)then
233
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 kernel_size_(2) = kernel_size(1)
234
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 elseif(size(kernel_size,dim=1).eq.2)then
235
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 kernel_size_(2) = kernel_size(2)
236 end if
237 end select
238 else
239
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 15 times.
45 kernel_size_ = 3
240 end if
241
242
243 !---------------------------------------------------------------------------
244 ! Set up padding name
245 !---------------------------------------------------------------------------
246
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
34 if(present(padding))then
247
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 padding_ = padding
248 else
249 24 padding_ = "valid"
250 end if
251
252
253 !---------------------------------------------------------------------------
254 ! Set up stride
255 !---------------------------------------------------------------------------
256
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
34 if(present(stride))then
257 12 select rank(stride)
258 rank(0)
259
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 stride_ = stride
260 rank(1)
261
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 stride_(1) = stride(1)
262
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
4 if(size(stride,dim=1).eq.1)then
263
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 stride_(2) = stride(1)
264
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(size(stride,dim=1).eq.2)then
265
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 stride_(2) = stride(2)
266 end if
267 end select
268 else
269
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 22 times.
66 stride_ = 1
270 end if
271
272
273 !---------------------------------------------------------------------------
274 ! Set up dilation
275 !---------------------------------------------------------------------------
276
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
34 if(present(dilation))then
277 select rank(dilation)
278 rank(0)
279 dilation_ = dilation
280 rank(1)
281 dilation_(1) = dilation(1)
282 if(size(dilation,dim=1).eq.1)then
283 dilation_(2) = dilation(1)
284 elseif(size(dilation,dim=1).eq.2)then
285 dilation_(2) = dilation(2)
286 end if
287 end select
288 else
289
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 34 times.
102 dilation_ = 1
290 end if
291
292
293 !---------------------------------------------------------------------------
294 ! Set hyperparameters
295 !---------------------------------------------------------------------------
296 call layer%set_hyperparams( &
297 num_filters = num_filters_, &
298 kernel_size = kernel_size_, stride = stride_, dilation = dilation_, &
299 padding = padding_, &
300 use_bias = use_bias_, &
301 activation = activation_, &
302 kernel_initialiser = kernel_initialiser_, &
303 bias_initialiser = bias_initialiser_, &
304 verbose = verbose_ &
305 34 )
306
307
308 !---------------------------------------------------------------------------
309 ! Initialise layer shape
310 !---------------------------------------------------------------------------
311
6/10
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 24 times.
34 if(present(input_shape)) call layer%init(input_shape=input_shape)
312
313
19/30
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 68 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 68 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 68 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 68 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 68 times.
✓ Branch 16 taken 24 times.
✓ Branch 17 taken 10 times.
✓ Branch 18 taken 23 times.
✓ Branch 19 taken 11 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 23 times.
✓ Branch 23 taken 10 times.
✓ Branch 24 taken 24 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 10 times.
✓ Branch 28 taken 34 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 34 times.
136 end function layer_setup
314 !###############################################################################
315
316
317 !###############################################################################
318 36 subroutine set_hyperparams_conv2d( &
319 this, &
320 num_filters, &
321 kernel_size, stride, dilation, &
322 padding, &
323 use_bias, &
324 activation, &
325 kernel_initialiser, bias_initialiser, &
326 verbose &
327 )
328 !! Set hyperparameters for 2D convolutional layer
329 use athena__activation, only: activation_setup
330 use athena__initialiser, only: get_default_initialiser, initialiser_setup
331 use coreutils, only: to_lower
332 implicit none
333
334 ! Arguments
335 class(conv2d_layer_type), intent(inout) :: this
336 !! Instance of the 2D convolutional layer
337 integer, intent(in) :: num_filters
338 !! Number of filters
339 integer, dimension(2), intent(in) :: kernel_size, stride, dilation
340 !! Kernel size, stride, dilation
341 character(*), intent(in) :: padding
342 !! Padding
343 logical, intent(in) :: use_bias
344 !! Use bias
345 class(base_actv_type), allocatable, intent(in) :: activation
346 !! Activation function
347 class(base_init_type), allocatable, intent(in) :: &
348 kernel_initialiser, bias_initialiser
349 !! Kernel and bias initialisers
350 integer, optional, intent(in) :: verbose
351 !! Verbosity level
352
353 ! Local variables
354 character(len=20) :: padding_
355 character(len=256) :: buffer
356
357
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
36 this%name = "conv2d"
358 36 this%type = "conv"
359 36 this%input_rank = 3
360 36 this%output_rank = 3
361 36 this%use_bias = use_bias
362
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
36 if(allocated(this%dil)) deallocate(this%dil)
363
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
36 if(allocated(this%knl)) deallocate(this%knl)
364
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
36 if(allocated(this%stp)) deallocate(this%stp)
365 allocate( &
366 this%dil(this%input_rank-1), &
367 this%knl(this%input_rank-1), &
368 this%stp(this%input_rank-1) &
369
24/48
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 36 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 36 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 36 times.
✓ Branch 18 taken 36 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 36 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 36 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 36 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 36 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 36 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 36 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 36 times.
✓ Branch 36 taken 36 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 36 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✓ Branch 41 taken 36 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 36 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 36 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 36 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 36 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 36 times.
36 )
370
4/8
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 36 times.
144 this%dil = dilation
371
4/8
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 36 times.
144 this%knl = kernel_size
372
4/8
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 36 times.
144 this%stp = stride
373 36 this%num_filters = num_filters
374
3/4
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 1 times.
36 padding_ = trim(adjustl(padding))
375
376 107 select case(trim(adjustl(to_lower(padding_))))
377 case("valid", "none", "")
378 case default
379 this%pad_layer = pad2d_layer_type( &
380 padding = [ (this%knl-1)/2 ], &
381 method = padding_ &
382
3/96
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 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 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 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 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 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.
107 )
383 end select
384
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
36 if(allocated(this%activation)) deallocate(this%activation)
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if(.not.allocated(activation))then
386 this%activation = activation_setup("none")
387 else
388
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
36 allocate(this%activation, source=activation)
389 end if
390
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
36 if(allocated(this%kernel_init)) deallocate(this%kernel_init)
391
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 25 times.
36 if(.not.allocated(kernel_initialiser))then
392
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 buffer = get_default_initialiser(this%activation%name)
393
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✓ Branch 17 taken 11 times.
✗ Branch 18 not taken.
11 this%kernel_init = initialiser_setup(buffer)
394 else
395
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
25 allocate(this%kernel_init, source=kernel_initialiser)
396 end if
397
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
36 if(allocated(this%bias_init)) deallocate(this%bias_init)
398
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 if(.not.allocated(bias_initialiser))then
399 buffer = get_default_initialiser( &
400 this%activation%name, &
401 is_bias=.true. &
402
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 )
403
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 24 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 24 times.
✓ Branch 17 taken 24 times.
✗ Branch 18 not taken.
24 this%bias_init = initialiser_setup(buffer)
404 else
405
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 allocate(this%bias_init, source=bias_initialiser)
406 end if
407
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if(present(verbose))then
408
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 25 times.
36 if(abs(verbose).gt.0)then
409 write(*,'("CONV2D activation function: ",A)') &
410
1/2
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
11 trim(this%activation%name)
411 write(*,'("CONV2D kernel initialiser: ",A)') &
412
1/2
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
11 trim(this%kernel_init%name)
413 write(*,'("CONV2D bias initialiser: ",A)') &
414
1/2
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
11 trim(this%bias_init%name)
415 end if
416 end if
417
418
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
36 end subroutine set_hyperparams_conv2d
419 !###############################################################################
420
421
422 !##############################################################################!
423 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
424 !##############################################################################!
425
426
427 !###############################################################################
428 1 subroutine read_conv2d(this, unit, verbose)
429 !! Read 2D convolutional layer from file
430 use athena__tools_infile, only: assign_val, assign_vec, move
431 use coreutils, only: to_lower, to_upper, icount
432 use athena__activation, only: read_activation
433 use athena__initialiser, only: initialiser_setup
434 implicit none
435
436 ! Arguments
437 class(conv2d_layer_type), intent(inout) :: this
438 !! Instance of the 2D convolutional layer
439 integer, intent(in) :: unit
440 !! Unit number
441 integer, optional, intent(in) :: verbose
442 !! Verbosity level
443
444 ! Local variables
445 integer :: stat
446 !! Status of read
447 integer :: verbose_ = 0
448 !! Verbosity level
449 integer :: j, k, l, c, itmp1, iline, num_params
450 !! Loop variables and temporary integer
451 integer :: num_filters
452 !! Number of filters
453 logical :: use_bias = .true.
454 !! Whether to use bias
455 character(14) :: kernel_initialiser_name='', bias_initialiser_name=''
456 !! Kernel and bias initialisers
457 character(20) :: padding='', activation_name=''
458 !! Padding and activation function
459 3 class(base_actv_type), allocatable :: activation
460 !! Activation function
461 5 class(base_init_type), allocatable :: kernel_initialiser, bias_initialiser
462 !! Initialisers
463 character(256) :: buffer, tag, err_msg
464 !! Buffer, tag, and error message
465 integer, dimension(2) :: kernel_size, stride, dilation
466 !! Kernel size and stride
467 integer, dimension(3) :: input_shape
468 !! Input shape
469 1 real(real32), allocatable, dimension(:) :: data_list
470 !! Data list
471 integer :: param_line, final_line
472 !! Parameter line number
473
474
475 ! Initialise optional arguments
476 !---------------------------------------------------------------------------
477
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(verbose)) verbose_ = verbose
478
479
480 ! Loop over tags in layer card
481 !---------------------------------------------------------------------------
482 1 iline = 0
483 1 param_line = 0
484 1 final_line = 0
485 16 tag_loop: do
486
487 ! Check for end of file
488 !------------------------------------------------------------------------
489 17 read(unit,'(A)',iostat=stat) buffer
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if(stat.ne.0)then
491 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
492 to_upper(this%name)
493 call stop_program(err_msg)
494 return
495 end if
496
2/4
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 if(trim(adjustl(buffer)).eq."") cycle tag_loop
497
498 ! Check for end of layer card
499 !------------------------------------------------------------------------
500
4/6
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 16 times.
34 if(trim(adjustl(buffer)).eq."END "//to_upper(trim(this%name)))then
501 1 final_line = iline
502 1 backspace(unit)
503 17 exit tag_loop
504 end if
505 16 iline = iline + 1
506
507
2/4
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 tag=trim(adjustl(buffer))
508
6/10
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
16 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
509
510 ! Read parameters from save file
511 !------------------------------------------------------------------------
512 32 select case(trim(tag))
513 case("INPUT_SHAPE")
514 1 call assign_vec(buffer, input_shape, itmp1)
515 case("NUM_FILTERS")
516 2 call assign_val(buffer, num_filters, itmp1)
517 case("KERNEL_SIZE")
518 1 call assign_vec(buffer, kernel_size, itmp1)
519 case("STRIDE")
520 1 call assign_vec(buffer, stride, itmp1)
521 case("DILATION")
522 1 call assign_vec(buffer, dilation, itmp1)
523 case("USE_BIAS")
524 1 call assign_val(buffer, use_bias, itmp1)
525 case("PADDING")
526 call assign_val(buffer, padding, itmp1)
527 padding = to_lower(padding)
528 case("ACTIVATION")
529 1 iline = iline - 1
530 1 backspace(unit)
531
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)
532 case("KERNEL_INITIALISER", "KERNEL_INIT", "KERNEL_INITIALIZER")
533 call assign_val(buffer, kernel_initialiser_name, itmp1)
534 case("BIAS_INITIALISER", "BIAS_INIT", "BIAS_INITIALIZER")
535 call assign_val(buffer, bias_initialiser_name, itmp1)
536 case("WEIGHTS")
537 1 kernel_initialiser_name = 'zeros'
538 1 bias_initialiser_name = 'zeros'
539 1 param_line = iline
540 case default
541 ! Don't look for "e" due to scientific notation of numbers
542 ! ... i.e. exponent (E+00)
543
3/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
16 if(scan(to_lower(trim(adjustl(buffer))),&
544 'abcdfghijklmnopqrstuvwxyz').eq.0)then
545 8 cycle tag_loop
546
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(tag(:3).eq.'END')then
547 8 cycle tag_loop
548 end if
549 write(err_msg,'("Unrecognised line in input file: ",A)') &
550 trim(adjustl(buffer))
551 call stop_program(err_msg)
552
10/14
✓ Branch 0 taken 16 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 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 8 times.
32 return
553 end select
554 end do tag_loop
555
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)
556
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)
557
558
559 ! Set hyperparameters and initialise layer
560 !---------------------------------------------------------------------------
561 call this%set_hyperparams( &
562 num_filters = num_filters, &
563 kernel_size = kernel_size, stride = stride, dilation = dilation, &
564 padding = padding, &
565 use_bias = use_bias, &
566 activation = activation, &
567 kernel_initialiser = kernel_initialiser, &
568 bias_initialiser = bias_initialiser, &
569 verbose = verbose_ &
570 1 )
571 1 call this%init(input_shape = input_shape)
572
573
574 ! Check if WEIGHTS card was found
575 !---------------------------------------------------------------------------
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(param_line.eq.0)then
577 write(0,*) "WARNING: WEIGHTS card in "//to_upper(trim(this%name))//" not found"
578 else
579 1 call move(unit, param_line - iline, iostat=stat)
580
6/10
✗ 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 taken 2 times.
✓ Branch 13 taken 1 times.
3 num_params = product(this%knl) * input_shape(3) * num_filters
581
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)
582 1 c = 1
583 1 k = 1
584
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 data_concat_loop: do while(c.le.num_params)
585 6 read(unit,'(A)',iostat=stat) buffer
586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(stat.ne.0) exit data_concat_loop
587 6 k = icount(buffer)
588
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
33 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
589 6 c = c + k
590 end do data_concat_loop
591
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 27 times.
✓ Branch 40 taken 1 times.
28 this%params(1)%val(:,1) = data_list
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
593
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_filters), source=0._real32)
594 1 c = 1
595 1 k = 1
596
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 data_concat_loop2: do while(c.le.num_filters)
597 1 read(unit,'(A)',iostat=stat) buffer
598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0) exit data_concat_loop2
599 1 k = icount(buffer)
600
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
2 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
601 1 c = c + k
602 end do data_concat_loop2
603
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 1 times.
✓ Branch 40 taken 1 times.
2 this%params(2)%val(:,1) = data_list
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
605
606 ! Check for end of weights card
607 !------------------------------------------------------------------------
608 1 read(unit,'(A)') buffer
609
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
610 write(0,*) trim(adjustl(buffer))
611 call stop_program("END WEIGHTS not where expected")
612 return
613 end if
614 end if
615
616
617 ! Check for end of layer card
618 !---------------------------------------------------------------------------
619 1 call move(unit, final_line - iline, iostat=stat)
620 1 read(unit,'(A)') buffer
621
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
622 write(0,*) trim(adjustl(buffer))
623 write(err_msg,'("END ",A," not where expected")') to_upper(this%name)
624 call stop_program(err_msg)
625 1 return
626 end if
627
628
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_conv2d
629 !###############################################################################
630
631
632 !###############################################################################
633 1 function read_conv2d_layer(unit, verbose) result(layer)
634 !! Read 2D convolutional layer from file and return layer
635 implicit none
636
637 ! Arguments
638 integer, intent(in) :: unit
639 !! Unit number
640 integer, optional, intent(in) :: verbose
641 !! Verbosity level
642 class(base_layer_type), allocatable :: layer
643 !! Instance of the 2D convolutional layer
644
645 ! Local variables
646 integer :: verbose_ = 0
647 !! Verbosity level
648
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(present(verbose)) verbose_ = verbose
650
25/172
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ 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 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 1 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 1 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 1 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 1 times.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✓ Branch 79 taken 1 times.
✗ Branch 80 not taken.
✓ Branch 81 taken 1 times.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✓ Branch 86 taken 1 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 1 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 1 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 1 times.
✗ Branch 93 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 98 not taken.
✓ Branch 99 taken 1 times.
✗ 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 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✓ Branch 168 taken 1 times.
✗ Branch 170 not taken.
✓ Branch 171 taken 1 times.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
2 allocate(layer, source=conv2d_layer_type())
651 1 call layer%read(unit, verbose=verbose_)
652
653 2 end function read_conv2d_layer
654 !###############################################################################
655
656
657 !###############################################################################
658 1 subroutine build_from_onnx_conv2d( &
659
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 this, node, initialisers, value_info, verbose &
660 )
661 !! Read ONNX attributes for 2D convolutional layer
662 use athena__activation, only: activation_setup
663 implicit none
664
665 ! Arguments
666 class(conv2d_layer_type), intent(inout) :: this
667 !! Instance of the 2D convolutional layer
668 type(onnx_node_type), intent(in) :: node
669 !! ONNX node information
670 type(onnx_initialiser_type), dimension(:), intent(in) :: initialisers
671 !! ONNX initialiser information
672 type(onnx_tensor_type), dimension(:), intent(in) :: value_info
673 !! ONNX value info information
674 integer, intent(in) :: verbose
675 !! Verbosity level
676
677 ! Local variables
678 integer :: i, weight_idx, bias_idx
679 !! Loop index and temporary integer
680 integer :: num_filters
681 !! Number of filters
682 logical :: use_bias = .true.
683 !! Whether to use bias
684 integer, dimension(2) :: padding, stride, kernel_size, dilation
685 !! Padding, stride, kernel size, and dilation
686 1 integer, dimension(:), allocatable :: dims
687 !! Dimensions
688 character(256) :: val
689 !! Attribute value
690 3 class(base_actv_type), allocatable :: activation
691 !! Activation function
692 5 class(base_init_type), allocatable :: kernel_initialiser, bias_initialiser
693
694
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do i = 1, size(node%attributes)
695
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
3 val = node%attributes(i)%val
696
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
7 select case(trim(adjustl(node%attributes(i)%name)))
697 case("pads")
698 read(val,*) padding
699 case("strides")
700 1 read(val,*) stride
701 case("kernel_shape")
702 1 read(val,*) kernel_size
703 case("dilations")
704 1 read(val,*) dilation
705 case default
706 ! Do nothing
707 write(0,*) "WARNING: Unrecognised attribute in ONNX CONV2D layer: ", &
708
4/13
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
6 trim(adjustl(node%attributes(i)%name))
709 end select
710 end do
711
712 1 weight_idx = -1
713 1 bias_idx = -1
714
3/6
✗ 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.
1 allocate(dims(0))
715
4/8
✗ 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.
1 if(size(initialisers).lt.1)then
716 call stop_program("ONNX CONV2D layer requires at least 1 initialiser")
717 return
718 else
719 ! check which initialiser has weights and which has biases,
720 ! look for dimensions
721
5/8
✗ 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 taken 2 times.
✓ Branch 10 taken 1 times.
3 do i = 1, size(initialisers)
722
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
3 if(allocated(initialisers(i)%dims))then
723
23/38
✗ 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 taken 1 times.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 2 times.
✓ Branch 35 taken 5 times.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2 times.
✓ Branch 39 taken 3 times.
✓ Branch 40 taken 2 times.
✓ Branch 41 taken 2 times.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 2 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 2 times.
✓ Branch 47 taken 3 times.
✓ Branch 48 taken 2 times.
14 dims = [ dims, product(initialisers(i)%dims) ]
724 end if
725 end do
726 end if
727 ! if both weight and bias have dimension 1, check which is larger and that
728 ! the division of it by the kernel size is equal to the length of the other
729 1 select case(size(dims))
730 case(1)
731 ! check if the division of dims by the kernel size is integer
732 if(mod(dims(1), product(kernel_size)).eq.0)then
733 weight_idx = 1
734 else
735 call stop_program("ONNX CONV2D layer initialiser dimensions do not &
736 &match kernel size")
737 return
738 end if
739 use_bias = .false.
740 case(2)
741 ! check which is weight and which is bias
742
7/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
7 if(mod(dims(1), product(kernel_size)).eq.0 .and. &
743
4/8
✗ 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.
3 dims(1)/product(kernel_size).eq.dims(2))then
744 1 weight_idx = 1
745 1 bias_idx = 2
746 elseif(mod(dims(2), product(kernel_size)).eq.0 .and. &
747 dims(2)/product(kernel_size).eq.dims(1))then
748 weight_idx = 2
749 bias_idx = 1
750 else
751 call stop_program("ONNX CONV2D layer initialiser dimensions do not &
752 &match kernel size")
753 return
754 end if
755 case default
756 call stop_program("ONNX CONV2D layer number of initialisers not supported")
757
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return
758 end select
759
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 num_filters = dims(weight_idx) / product(kernel_size)
760
4/8
✗ 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.
1 if(num_filters .ne. value_info(1)%dims(2))then
761 call stop_program("ONNX CONV2D layer number of filters does not match &
762 &value info")
763 return
764 end if
765
766
12/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 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.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
1 kernel_initialiser = data_init_type( data = initialisers(weight_idx)%data )
767
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(use_bias)then
768
12/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 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.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
1 bias_initialiser = data_init_type( data = initialisers(bias_idx)%data )
769 end if
770
771
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 = activation_setup("none")
772 call this%set_hyperparams( &
773 num_filters = num_filters, &
774 kernel_size = kernel_size, stride = stride, &
775 dilation = dilation, &
776 padding = "valid", &
777 use_bias = .true., &
778 activation = activation, &
779 verbose = verbose, &
780 kernel_initialiser = kernel_initialiser, &
781 bias_initialiser = bias_initialiser &
782 1 )
783
784
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 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 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
3 end subroutine build_from_onnx_conv2d
785 !###############################################################################
786
787
788 !##############################################################################!
789 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
790 !##############################################################################!
791
792
793 !###############################################################################
794
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 subroutine forward_conv2d(this, input)
795 !! Forward propagation
796 implicit none
797
798 ! Arguments
799 class(conv2d_layer_type), intent(inout) :: this
800 !! Instance of the 2D convolutional layer
801 class(array_type), dimension(:,:), intent(in) :: input
802 !! Input values
803
804 ! Local variables
805 type(array_type), pointer :: ptr
806 !! Pointer array
807
808
809 ! Generate outputs from weights, biases, and inputs
810 !---------------------------------------------------------------------------
811 17 select case(allocated(this%pad_layer))
812 case(.true.)
813 call this%pad_layer%forward(input)
814 ptr => conv2d(this%pad_layer%output(1,1), this%params(1), &
815 this%stp, this%dil &
816 )
817 case default
818
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 17 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 17 times.
17 ptr => conv2d(input(1,1), this%params(1), this%stp, this%dil)
819 end select
820 17 call this%z(1)%zero_grad()
821 17 call this%z(1)%assign_and_deallocate_source(ptr)
822 17 this%z(1)%is_temporary = .false.
823
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
17 ptr => add_bias(this%z(1), this%params(2), dim=3, dim_act_on_shape=.true.)
824
825 ! Apply activation function to activation
826 !---------------------------------------------------------------------------
827
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
17 call this%output(1,1)%zero_grad()
828
3/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 15 times.
17 if(trim(this%activation%name) .eq. "none")then
829
4/8
✗ 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.
2 call this%output(1,1)%assign_and_deallocate_source(ptr)
830 else
831 15 call this%z(2)%zero_grad()
832 15 call this%z(2)%assign_and_deallocate_source(ptr)
833 15 this%z(2)%is_temporary = .false.
834 15 ptr => this%activation%apply(this%z(2))
835
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
15 call this%output(1,1)%assign_and_deallocate_source(ptr)
836 end if
837
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
17 this%output(1,1)%is_temporary = .false.
838
839 17 end subroutine forward_conv2d
840 !###############################################################################
841
842
54/101
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 62 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 62 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 10 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ 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 37 times.
✓ Branch 37 taken 22 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 37 times.
✓ Branch 40 taken 48 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 37 times.
✓ Branch 43 taken 48 times.
✓ Branch 44 taken 37 times.
✓ Branch 45 taken 85 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 37 times.
✓ Branch 48 taken 22 times.
✓ Branch 49 taken 37 times.
✓ Branch 50 taken 22 times.
✓ Branch 51 taken 37 times.
✓ Branch 52 taken 22 times.
✓ Branch 53 taken 37 times.
✓ Branch 54 taken 22 times.
✓ Branch 55 taken 37 times.
✓ Branch 56 taken 22 times.
✓ Branch 57 taken 74 times.
✓ Branch 58 taken 37 times.
✓ Branch 59 taken 74 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 74 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 74 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 74 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 74 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 74 times.
✓ Branch 71 taken 59 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 59 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 59 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 59 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 59 times.
✗ Branch 83 not taken.
✓ Branch 84 taken 59 times.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✓ Branch 87 taken 59 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 59 times.
✓ Branch 92 taken 118 times.
✓ Branch 93 taken 59 times.
✗ Branch 94 not taken.
✓ Branch 95 taken 118 times.
✗ Branch 96 not taken.
✓ Branch 97 taken 118 times.
✗ Branch 98 not taken.
✓ Branch 99 taken 118 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 118 times.
✗ Branch 102 not taken.
✓ Branch 103 taken 118 times.
✗ Branch 104 not taken.
✓ Branch 105 taken 118 times.
851 end module athena__conv2d_layer
843