GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_conv3d_layer.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 185 271 68.3%
Functions: 0 0 -%
Branches: 470 1403 33.5%

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