GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_fixed_lno_layer.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 362 391 92.6%
Functions: 0 0 -%
Branches: 978 1950 50.2%

Line Branch Exec Source
1 module athena__fixed_lno_layer
2 !! Module containing implementation of a Laplace Neural Operator layer
3 !!
4 !! This module implements a Laplace Neural Operator (LNO) layer that
5 !! approximates an integral kernel operator in the Laplace-transform domain.
6 !! It combines a spectral pathway (encode → spectral mixing → decode)
7 !! with a local affine bypass:
8 !!
9 !! \[ \mathbf{v} = \sigma\!\bigl(
10 !! \underbrace{\mathbf{D}\,\mathbf{R}\,\mathbf{E}\,\mathbf{u}}_{\text{spectral}}
11 !! + \underbrace{\mathbf{W}\,\mathbf{u}}_{\text{local}}
12 !! + \mathbf{b}\bigr) \]
13 !!
14 !! where:
15 !! - \(\mathbf{u} \in \mathbb{R}^{n_{in}}\) is the discretised input
16 !! - \(\mathbf{E} \in \mathbb{R}^{M \times n_{in}}\) is the Laplace
17 !! encoder basis: \(E_{k,j}=\exp(-s_k\,t_j)\),
18 !! \(s_k = k\pi\), \(t_j = (j{-}1)/(n_{in}{-}1)\)
19 !! - \(\mathbf{R} \in \mathbb{R}^{M \times M}\) are learnable spectral
20 !! mixing weights
21 !! - \(\mathbf{D} \in \mathbb{R}^{n_{out} \times M}\) is the Laplace
22 !! decoder basis: \(D_{i,k}=\exp(-s_k\,\tau_i)\),
23 !! \(\tau_i = (i{-}1)/(n_{out}{-}1)\)
24 !! - \(\mathbf{W} \in \mathbb{R}^{n_{out} \times n_{in}}\) are the
25 !! local (bypass) weights
26 !! - \(\mathbf{b} \in \mathbb{R}^{n_{out}}\) is the bias
27 !! - \(\sigma\) is the activation function
28 !! - \(M\) = num_modes, the number of Laplace spectral modes
29 !!
30 !! Number of parameters (learnable):
31 !! \(M^2 + n_{out}\,n_{in}\) without bias,
32 !! \(M^2 + n_{out}\,n_{in} + n_{out}\) with bias.
33 use coreutils, only: real32, stop_program, pi
34 use athena__base_layer, only: learnable_layer_type, base_layer_type
35 use athena__misc_types, only: base_actv_type, base_init_type, &
36 onnx_attribute_type, &
37 onnx_node_type, onnx_initialiser_type, onnx_tensor_type
38 use athena__onnx_nop_utils, only: emit_nop_input_transpose, &
39 emit_nop_output_tail, emit_float_initialiser, emit_matrix_initialiser
40 use diffstruc, only: array_type, matmul, operator(+)
41 implicit none
42
43
44 private
45
46 public :: fixed_lno_layer_type
47 public :: read_fixed_lno_layer
48
49
50 type, extends(learnable_layer_type) :: fixed_lno_layer_type
51 !! Type for a fixed-basis Laplace Neural Operator layer
52 integer :: num_inputs
53 !! Number of inputs (discretisation points)
54 integer :: num_outputs
55 !! Number of outputs (discretisation points)
56 integer :: num_modes
57 !! Number of Laplace spectral modes
58 type(array_type) :: encoder_basis
59 !! Fixed Laplace encoder basis E [num_modes x num_inputs]
60 type(array_type) :: decoder_basis
61 !! Fixed Laplace decoder basis D [num_outputs x num_modes]
62 type(array_type), dimension(1) :: z
63 !! Temporary array for pre-activation values
64 contains
65 procedure, pass(this) :: get_num_params => get_num_params_fixed_lno
66 procedure, pass(this) :: set_hyperparams => set_hyperparams_fixed_lno
67 procedure, pass(this) :: init => init_fixed_lno
68 procedure, pass(this) :: print_to_unit => print_to_unit_fixed_lno
69 procedure, pass(this) :: read => read_fixed_lno
70
71 procedure, pass(this) :: forward => forward_fixed_lno
72 procedure, pass(this) :: get_attributes => get_attributes_fixed_lno
73 procedure, pass(this) :: emit_onnx_nodes => emit_onnx_nodes_fixed_lno
74
75 final :: finalise_fixed_lno
76 end type fixed_lno_layer_type
77
78 interface fixed_lno_layer_type
79 module function layer_setup( &
80 num_outputs, num_modes, num_inputs, use_bias, &
81 activation, &
82 kernel_initialiser, bias_initialiser, verbose &
83 ) result(layer)
84 integer, intent(in) :: num_outputs
85 integer, intent(in) :: num_modes
86 integer, optional, intent(in) :: num_inputs
87 logical, optional, intent(in) :: use_bias
88 class(*), optional, intent(in) :: activation
89 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
90 integer, optional, intent(in) :: verbose
91 type(fixed_lno_layer_type) :: layer
92 end function layer_setup
93 end interface fixed_lno_layer_type
94
95
96
97 contains
98
99 !###############################################################################
100 26 subroutine finalise_fixed_lno(this)
101 !! Finalise the fixed-basis Laplace neural operator layer
102 implicit none
103
104 ! Arguments
105 type(fixed_lno_layer_type), intent(inout) :: this
106 !! Layer instance to release
107
108
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
26 if(allocated(this%input_shape)) deallocate(this%input_shape)
109
4/6
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
26 if(allocated(this%output)) deallocate(this%output)
110
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 23 times.
26 if(this%z(1)%allocated) call this%z(1)%deallocate()
111
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 if(this%encoder_basis%allocated) call this%encoder_basis%deallocate()
112
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 if(this%decoder_basis%allocated) call this%decoder_basis%deallocate()
113
114 26 end subroutine finalise_fixed_lno
115 !###############################################################################
116
117
118 !###############################################################################
119 12 pure function get_num_params_fixed_lno(this) result(num_params)
120 !! Return the number of learnable parameters for the layer
121 implicit none
122
123 ! Arguments
124 class(fixed_lno_layer_type), intent(in) :: this
125 !! Layer instance
126 integer :: num_params
127 !! Total number of learnable parameters
128
129 ! R: num_modes^2, W: n_out * n_in, b: n_out (optional)
130 num_params = this%num_modes * this%num_modes + &
131 12 this%num_outputs * this%num_inputs
132
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(this%use_bias) num_params = num_params + this%num_outputs
133
134 12 end function get_num_params_fixed_lno
135 !###############################################################################
136
137
138 !###############################################################################
139 12 module function layer_setup( &
140 num_outputs, num_modes, num_inputs, &
141 use_bias, &
142 activation, &
143 kernel_initialiser, bias_initialiser, verbose &
144
9/16
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
24 ) result(layer)
145 use athena__activation, only: activation_setup
146 use athena__initialiser, only: initialiser_setup
147 implicit none
148
149 ! Arguments
150 integer, intent(in) :: num_outputs
151 !! Number of output features
152 integer, intent(in) :: num_modes
153 !! Number of Laplace spectral modes
154 integer, optional, intent(in) :: num_inputs
155 !! Number of input features when known at construction time
156 logical, optional, intent(in) :: use_bias
157 !! Whether to allocate a bias term
158 class(*), optional, intent(in) :: activation
159 !! Activation function specification
160 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
161 !! Kernel and bias initialiser specifications
162 integer, optional, intent(in) :: verbose
163 !! Verbosity level
164
165 type(fixed_lno_layer_type) :: layer
166 !! Constructed fixed LNO layer
167
168 ! Local variables
169 integer :: verbose_ = 0
170 !! Effective verbosity level
171 logical :: use_bias_ = .true.
172 !! Effective bias flag
173 36 class(base_actv_type), allocatable :: activation_
174 !! Materialised activation object
175 12 class(base_init_type), allocatable :: kernel_initialiser_, bias_initialiser_
176 !! Materialised kernel and bias initialisers
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(present(verbose)) verbose_ = verbose
179
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if(present(use_bias)) use_bias_ = use_bias
180
181
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
12 if(present(activation))then
182
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 activation_ = activation_setup(activation)
183 else
184
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 activation_ = activation_setup("none")
185 end if
186
187
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if(present(kernel_initialiser))then
188 kernel_initialiser_ = initialiser_setup(kernel_initialiser)
189 end if
190
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if(present(bias_initialiser))then
191 bias_initialiser_ = initialiser_setup(bias_initialiser)
192 end if
193
194 call layer%set_hyperparams( &
195 num_outputs = num_outputs, &
196 num_modes = num_modes, &
197 use_bias = use_bias_, &
198 activation = activation_, &
199 kernel_initialiser = kernel_initialiser_, &
200 bias_initialiser = bias_initialiser_, &
201 verbose = verbose_ &
202 12 )
203
204
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
22 if(present(num_inputs)) call layer%init(input_shape=[num_inputs])
205
206
13/28
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 12 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 26 taken 12 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 12 times.
36 end function layer_setup
207 !###############################################################################
208
209
210 !###############################################################################
211 13 subroutine set_hyperparams_fixed_lno( &
212 this, num_outputs, num_modes, &
213 use_bias, &
214 activation, &
215 kernel_initialiser, bias_initialiser, &
216 verbose &
217 )
218 use athena__activation, only: activation_setup
219 use athena__initialiser, only: get_default_initialiser, initialiser_setup
220 implicit none
221
222 ! Arguments
223 class(fixed_lno_layer_type), intent(inout) :: this
224 !! Layer instance to configure
225 integer, intent(in) :: num_outputs
226 !! Number of output features
227 integer, intent(in) :: num_modes
228 !! Number of Laplace spectral modes
229 logical, intent(in) :: use_bias
230 !! Whether to use a bias term
231 class(base_actv_type), allocatable, intent(in) :: activation
232 !! Activation function object
233 class(base_init_type), allocatable, intent(in) :: &
234 kernel_initialiser, bias_initialiser
235 !! Kernel and bias initialiser objects
236 integer, optional, intent(in) :: verbose
237 !! Verbosity level
238
239 ! Local variables
240 character(len=256) :: buffer
241 !! Buffer for default initialiser lookup
242
243
5/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
13 this%name = "fixed_lno"
244 13 this%type = "nop"
245 13 this%input_rank = 1
246 13 this%output_rank = 1
247 13 this%use_bias = use_bias
248 13 this%num_outputs = num_outputs
249 13 this%num_modes = num_modes
250
251
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
13 if(allocated(this%activation)) deallocate(this%activation)
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(.not.allocated(activation))then
253 this%activation = activation_setup("none")
254 else
255
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 allocate(this%activation, source=activation)
256 end if
257
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
13 if(allocated(this%kernel_init)) deallocate(this%kernel_init)
258
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
13 if(.not.allocated(kernel_initialiser))then
259
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 buffer = get_default_initialiser(this%activation%name)
260
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✓ Branch 17 taken 12 times.
✗ Branch 18 not taken.
12 this%kernel_init = initialiser_setup(buffer)
261 else
262
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 allocate(this%kernel_init, source=kernel_initialiser)
263 end if
264
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
13 if(allocated(this%bias_init)) deallocate(this%bias_init)
265
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
13 if(.not.allocated(bias_initialiser))then
266 buffer = get_default_initialiser( &
267 this%activation%name, &
268 is_bias=.true. &
269
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 )
270
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✓ Branch 17 taken 12 times.
✗ Branch 18 not taken.
12 this%bias_init = initialiser_setup(buffer)
271 else
272
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1 if(allocated(this%bias_init)) deallocate(this%bias_init)
273
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 allocate(this%bias_init, source=bias_initialiser)
274 end if
275
276
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if(present(verbose))then
277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(abs(verbose).gt.0)then
278 write(*,'("fixed_lno activation: ",A)') &
279 trim(this%activation%name)
280 end if
281 end if
282
283 13 end subroutine set_hyperparams_fixed_lno
284 !###############################################################################
285
286
287 !###############################################################################
288
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 subroutine init_fixed_lno(this, input_shape, verbose)
289 !! Initialise parameter storage, fixed bases and output buffers
290 implicit none
291
292 ! Arguments
293 class(fixed_lno_layer_type), intent(inout) :: this
294 !! Layer instance to initialise
295 integer, dimension(:), intent(in) :: input_shape
296 !! Input shape used to infer num_inputs
297 integer, optional, intent(in) :: verbose
298 !! Verbosity level
299
300 ! Local variables
301 integer :: num_inputs, j, k, i, idx
302 !! Effective fan-in size and basis-construction indices
303 integer :: verbose_ = 0
304 !! Effective verbosity level
305 real(real32) :: s, t
306 !! Spectral pole value and normalised coordinate
307
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(present(verbose)) verbose_ = verbose
309
310 !---------------------------------------------------------------------------
311 ! Set shapes
312 !---------------------------------------------------------------------------
313
4/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
12 if(.not.allocated(this%input_shape)) call this%set_shape(input_shape)
314
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%num_inputs = this%input_shape(1)
315
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 12 times.
24 this%output_shape = [this%num_outputs]
316 12 this%num_params = this%get_num_params()
317
318
319 !---------------------------------------------------------------------------
320 ! Allocate learnable parameters
321 !
322 ! params(1): R spectral mixing weights [num_modes x num_modes]
323 ! params(2): W local bypass weights [num_outputs x num_inputs]
324 ! params(3): b bias [num_outputs] (optional)
325 !---------------------------------------------------------------------------
326
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
12 allocate(this%weight_shape(2,2))
327
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✓ Branch 21 taken 24 times.
✓ Branch 22 taken 12 times.
36 this%weight_shape(:,1) = [ this%num_modes, this%num_modes ]
328
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✓ Branch 21 taken 24 times.
✓ Branch 22 taken 12 times.
36 this%weight_shape(:,2) = [ this%num_outputs, this%num_inputs ]
329
330
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(this%use_bias)then
331
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 10 times.
20 this%bias_shape = [ this%num_outputs ]
332
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 10 times.
✓ Branch 21 taken 30 times.
✓ Branch 22 taken 10 times.
✓ Branch 23 taken 30 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 30 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 30 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 30 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 30 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 30 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 30 times.
40 allocate(this%params(3))
333 else
334
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✓ Branch 21 taken 4 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 4 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 4 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 4 times.
6 allocate(this%params(2))
335 end if
336
337 ! R: spectral mixing weights
338
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 36 times.
✓ Branch 7 taken 12 times.
48 call this%params(1)%allocate([this%num_modes, this%num_modes, 1])
339
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 call this%params(1)%set_requires_grad(.true.)
340
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(1)%fix_pointer = .true.
341
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(1)%is_sample_dependent = .false.
342
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(1)%is_temporary = .false.
343
344 ! W: local bypass weights
345
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 36 times.
✓ Branch 7 taken 12 times.
48 call this%params(2)%allocate([this%num_outputs, this%num_inputs, 1])
346
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 call this%params(2)%set_requires_grad(.true.)
347
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(2)%fix_pointer = .true.
348
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(2)%is_sample_dependent = .false.
349
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 this%params(2)%is_temporary = .false.
350
351 12 num_inputs = this%num_inputs
352
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(this%use_bias)then
353 10 num_inputs = this%num_inputs + 1
354
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 10 times.
✓ Branch 21 taken 10 times.
✓ Branch 22 taken 10 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 10 times.
✓ Branch 25 taken 20 times.
✓ Branch 26 taken 10 times.
40 call this%params(3)%allocate([this%bias_shape, 1])
355
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 call this%params(3)%set_requires_grad(.true.)
356
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 this%params(3)%fix_pointer = .true.
357
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 this%params(3)%is_sample_dependent = .false.
358
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 this%params(3)%is_temporary = .false.
359 end if
360
361
362 !---------------------------------------------------------------------------
363 ! Initialise learnable parameters
364 !---------------------------------------------------------------------------
365 call this%kernel_init%initialise( &
366 120 this%params(1)%val(:,1), &
367 fan_in = this%num_modes, fan_out = this%num_modes, &
368 spacing = [ this%num_modes ] &
369
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 12 times.
✓ Branch 30 taken 12 times.
✓ Branch 31 taken 12 times.
24 )
370 call this%kernel_init%initialise( &
371 120 this%params(2)%val(:,1), &
372 fan_in = num_inputs, fan_out = this%num_outputs, &
373 spacing = [ this%num_outputs ] &
374
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 12 times.
✓ Branch 30 taken 12 times.
✓ Branch 31 taken 12 times.
24 )
375
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(this%use_bias)then
376 call this%bias_init%initialise( &
377 100 this%params(3)%val(:,1), &
378 fan_in = num_inputs, fan_out = this%num_outputs &
379
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 10 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 10 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 10 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 10 times.
10 )
380 end if
381
382
383 !---------------------------------------------------------------------------
384 ! Build fixed encoder basis E [num_modes x num_inputs]
385 ! E(k,j) = exp(-s_k * t_j)
386 ! s_k = k * pi, t_j = (j-1)/(n_in-1)
387 !---------------------------------------------------------------------------
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(this%encoder_basis%allocated) call this%encoder_basis%deallocate()
389 call this%encoder_basis%allocate( &
390
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 12 times.
48 [this%num_modes, this%num_inputs, 1])
391 12 this%encoder_basis%is_sample_dependent = .false.
392 12 this%encoder_basis%requires_grad = .false.
393 12 this%encoder_basis%fix_pointer = .true.
394 12 this%encoder_basis%is_temporary = .false.
395
396
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 12 times.
121 do j = 1, this%num_inputs
397
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 if(this%num_inputs .gt. 1)then
398 109 t = real(j-1, real32) / real(this%num_inputs-1, real32)
399 else
400 t = 0.0_real32
401 end if
402
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 109 times.
487 do k = 1, this%num_modes
403 366 s = real(k, real32) * pi
404 366 idx = k + (j-1) * this%num_modes
405
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 366 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 366 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 366 times.
475 this%encoder_basis%val(idx, 1) = exp(-s * t)
406 end do
407 end do
408
409
410 !---------------------------------------------------------------------------
411 ! Build fixed decoder basis D [num_outputs x num_modes]
412 ! D(i,k) = exp(-s_k * tau_i)
413 ! s_k = k * pi, tau_i = (i-1)/(n_out-1)
414 !---------------------------------------------------------------------------
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(this%decoder_basis%allocated) call this%decoder_basis%deallocate()
416 call this%decoder_basis%allocate( &
417
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 12 times.
48 [this%num_outputs, this%num_modes, 1])
418 12 this%decoder_basis%is_sample_dependent = .false.
419 12 this%decoder_basis%requires_grad = .false.
420 12 this%decoder_basis%fix_pointer = .true.
421 12 this%decoder_basis%is_temporary = .false.
422
423
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 12 times.
43 do k = 1, this%num_modes
424 31 s = real(k, real32) * pi
425
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 31 times.
275 do i = 1, this%num_outputs
426
1/2
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
232 if(this%num_outputs .gt. 1)then
427 232 t = real(i-1, real32) / real(this%num_outputs-1, real32)
428 else
429 t = 0.0_real32
430 end if
431 232 idx = i + (k-1) * this%num_outputs
432
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 232 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 232 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 232 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 232 times.
263 this%decoder_basis%val(idx, 1) = exp(-s * t)
433 end do
434 end do
435
436
437 !---------------------------------------------------------------------------
438 ! Allocate output arrays
439 !---------------------------------------------------------------------------
440
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
12 if(allocated(this%output)) deallocate(this%output)
441
15/26
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 12 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 12 times.
✓ Branch 33 taken 12 times.
✓ Branch 34 taken 12 times.
✓ Branch 35 taken 12 times.
✓ Branch 36 taken 12 times.
36 allocate(this%output(1,1))
442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(this%z(1)%allocated) call this%z(1)%deallocate()
443
444 12 end subroutine init_fixed_lno
445 !###############################################################################
446
447
448 !###############################################################################
449 1 subroutine print_to_unit_fixed_lno(this, unit)
450 !! Print fixed LNO settings and parameters to a unit
451 use coreutils, only: to_upper
452 implicit none
453
454 ! Arguments
455 class(fixed_lno_layer_type), intent(in) :: this
456 !! Layer instance to print
457 integer, intent(in) :: unit
458 !! Output unit number
459
460 1 write(unit,'(3X,"NUM_INPUTS = ",I0)') this%num_inputs
461 1 write(unit,'(3X,"NUM_OUTPUTS = ",I0)') this%num_outputs
462 1 write(unit,'(3X,"NUM_MODES = ",I0)') this%num_modes
463 1 write(unit,'(3X,"USE_BIAS = ",L1)') this%use_bias
464
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%activation%name .ne. 'none')then
465 1 call this%activation%print_to_unit(unit)
466 end if
467
468 1 write(unit,'("WEIGHTS")')
469
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 1 times.
5 write(unit,'(5(E16.8E2))') this%params(1)%val(:,1) ! R
470
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 12 times.
✓ Branch 26 taken 1 times.
13 write(unit,'(5(E16.8E2))') this%params(2)%val(:,1) ! W
471
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
472
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 1 times.
5 write(unit,'(5(E16.8E2))') this%params(3)%val(:,1) ! b
473 end if
474 1 write(unit,'("END WEIGHTS")')
475
476 1 end subroutine print_to_unit_fixed_lno
477 !###############################################################################
478
479
480 !###############################################################################
481 1 subroutine read_fixed_lno(this, unit, verbose)
482 use athena__tools_infile, only: assign_val, assign_vec, move
483 use coreutils, only: to_lower, to_upper, icount
484 use athena__activation, only: read_activation
485 use athena__initialiser, only: initialiser_setup
486 implicit none
487
488 ! Arguments
489 class(fixed_lno_layer_type), intent(inout) :: this
490 !! Layer instance to populate from file data
491 integer, intent(in) :: unit
492 !! Input unit number
493 integer, optional, intent(in) :: verbose
494 !! Verbosity level
495
496 ! Local variables
497 integer :: stat, verbose_ = 0
498 !! I/O status and effective verbosity level
499 integer :: j, k, c, itmp1, iline
500 !! Loop counters and parser scratch integers
501 integer :: num_inputs, num_outputs, num_modes
502 !! Parsed layer dimensions
503 logical :: use_bias = .true.
504 !! Parsed bias flag
505 character(14) :: kernel_initialiser_name='', bias_initialiser_name=''
506 !! Parsed initialiser names
507 3 class(base_actv_type), allocatable :: activation
508 !! Parsed activation object
509 5 class(base_init_type), allocatable :: kernel_initialiser, bias_initialiser
510 !! Parsed initialiser objects
511 character(256) :: buffer, tag, err_msg
512 !! Input buffer, parsed tag and formatted error message
513 1 real(real32), allocatable, dimension(:) :: data_list
514 !! Temporary storage for flattened parameter blocks
515 integer :: param_line, final_line, num_vals
516 !! Weights-section line markers and current block size
517
518
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(verbose)) verbose_ = verbose
519
520 1 iline = 0
521 1 param_line = 0
522 1 final_line = 0
523 12 tag_loop: do
524 13 read(unit,'(A)',iostat=stat) buffer
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(stat.ne.0)then
526 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
527 to_upper(this%name)
528 call stop_program(err_msg)
529 return
530 end if
531
2/4
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
13 if(trim(adjustl(buffer)).eq."") cycle tag_loop
532
533
4/6
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 12 times.
26 if(trim(adjustl(buffer)).eq."END "//to_upper(trim(this%name)))then
534 1 final_line = iline
535 1 backspace(unit)
536 13 exit tag_loop
537 end if
538 12 iline = iline + 1
539
540
2/4
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
12 tag=trim(adjustl(buffer))
541
6/10
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
12 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
542
543 24 select case(trim(tag))
544 case("NUM_INPUTS")
545 2 call assign_val(buffer, num_inputs, itmp1)
546 case("NUM_OUTPUTS")
547 2 call assign_val(buffer, num_outputs, itmp1)
548 case("NUM_MODES")
549 2 call assign_val(buffer, num_modes, itmp1)
550 case("USE_BIAS")
551 2 call assign_val(buffer, use_bias, itmp1)
552 case("ACTIVATION")
553 1 iline = iline - 1
554 1 backspace(unit)
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 activation = read_activation(unit, iline)
556 case("KERNEL_INITIALISER", "KERNEL_INIT", "KERNEL_INITIALIZER")
557 call assign_val(buffer, kernel_initialiser_name, itmp1)
558 case("BIAS_INITIALISER", "BIAS_INIT", "BIAS_INITIALIZER")
559 call assign_val(buffer, bias_initialiser_name, itmp1)
560 case("WEIGHTS")
561 1 kernel_initialiser_name = 'zeros'
562 1 bias_initialiser_name = 'zeros'
563 1 param_line = iline
564 case default
565
3/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
12 if(scan(to_lower(trim(adjustl(buffer))),&
566 'abcdfghijklmnopqrstuvwxyz').eq.0)then
567 6 cycle tag_loop
568
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(tag(:3).eq.'END')then
569 6 cycle tag_loop
570 end if
571 write(err_msg,'("Unrecognised line in input file: ",A)') &
572 trim(adjustl(buffer))
573 call stop_program(err_msg)
574
8/11
✓ Branch 0 taken 12 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 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 6 times.
24 return
575 end select
576 end do tag_loop
577
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)
578
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)
579
580 call this%set_hyperparams( &
581 num_outputs = num_outputs, &
582 num_modes = num_modes, &
583 use_bias = use_bias, &
584 activation = activation, &
585 kernel_initialiser = kernel_initialiser, &
586 bias_initialiser = bias_initialiser, &
587 verbose = verbose_ &
588 1 )
589
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 call this%init(input_shape=[num_inputs])
590
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(param_line.eq.0)then
592 write(0,*) "WARNING: WEIGHTS card in " // trim(this%name) // " not found"
593 else
594 1 call move(unit, param_line - iline, iostat=stat)
595
596 ! Read R (num_modes^2 values)
597 1 num_vals = num_modes * num_modes
598
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_vals), source=0._real32)
599 1 c = 1
600 1 k = 1
601
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 do while(c.le.num_vals)
602 1 read(unit,'(A)',iostat=stat) buffer
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0) exit
604 1 k = icount(buffer)
605
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
5 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
606 1 c = c + k
607 end do
608
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 4 times.
✓ Branch 40 taken 1 times.
5 this%params(1)%val(:,1) = data_list
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
610
611 ! Read W (num_outputs * num_inputs values)
612 1 num_vals = num_outputs * num_inputs
613
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_vals), source=0._real32)
614 1 c = 1
615 1 k = 1
616
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 do while(c.le.num_vals)
617 3 read(unit,'(A)',iostat=stat) buffer
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(stat.ne.0) exit
619 3 k = icount(buffer)
620
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
15 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
621 3 c = c + k
622 end do
623
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 12 times.
✓ Branch 40 taken 1 times.
13 this%params(2)%val(:,1) = data_list
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
625
626 ! Read b if use_bias
627
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(use_bias)then
628
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_outputs), source=0._real32)
629 1 c = 1
630 1 k = 1
631
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 do while(c.le.num_outputs)
632 1 read(unit,'(A)',iostat=stat) buffer
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0) exit
634 1 k = icount(buffer)
635
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
5 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
636 1 c = c + k
637 end do
638
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 4 times.
✓ Branch 40 taken 1 times.
5 this%params(3)%val(:,1) = data_list(1:num_outputs)
639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
640 end if
641
642 1 read(unit,'(A)') buffer
643
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
644 call stop_program("END WEIGHTS not where expected")
645 return
646 end if
647 end if
648
649 1 call move(unit, final_line - iline, iostat=stat)
650 1 read(unit,'(A)') buffer
651
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
652 write(err_msg,'("END ",A," not where expected")') to_upper(this%name)
653 call stop_program(err_msg)
654 1 return
655 end if
656
657
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_fixed_lno
658 !###############################################################################
659
660
661 !###############################################################################
662 1 function read_fixed_lno_layer(unit, verbose) result(layer)
663 !! Read a fixed LNO layer from file and return it
664 implicit none
665
666 ! Arguments
667 integer, intent(in) :: unit
668 !! Input unit number
669 integer, optional, intent(in) :: verbose
670 !! Verbosity level
671 class(base_layer_type), allocatable :: layer
672 !! Allocated base-layer instance containing the result
673
674 ! Local variables
675 integer :: verbose_ = 0
676 !! Effective verbosity level
677
678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(present(verbose)) verbose_ = verbose
679 allocate(layer, source=fixed_lno_layer_type( &
680
33/102
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 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 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 50 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 62 not taken.
✓ Branch 63 taken 1 times.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✓ Branch 69 taken 1 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 1 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✓ Branch 74 taken 1 times.
✓ Branch 76 taken 1 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 1 times.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 81 taken 1 times.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✓ Branch 89 taken 1 times.
✗ Branch 90 not taken.
✓ Branch 91 taken 1 times.
✗ Branch 92 not taken.
✓ Branch 93 taken 1 times.
✗ Branch 94 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✓ Branch 97 taken 1 times.
✗ Branch 99 not taken.
✓ Branch 100 taken 1 times.
✗ Branch 101 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 1 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 1 times.
✗ Branch 107 not taken.
✓ Branch 108 taken 1 times.
✗ Branch 109 not taken.
✓ Branch 110 taken 1 times.
2 num_outputs=0, num_modes=1))
681 1 call layer%read(unit, verbose=verbose_)
682
683 2 end function read_fixed_lno_layer
684 !###############################################################################
685
686
687 !###############################################################################
688
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 subroutine forward_fixed_lno(this, input)
689 !! Forward propagation for the Laplace Neural Operator layer
690 !!
691 !! Computes:
692 !! v = sigma( D @ R @ E @ u + W @ u + b )
693 implicit none
694
695 ! Arguments
696 class(fixed_lno_layer_type), intent(inout) :: this
697 !! Layer instance to execute
698 class(array_type), dimension(:,:), intent(in) :: input
699 !! Input batch tensor collection
700
701 ! Local variables
702 type(array_type), pointer :: ptr, ptr_spec, ptr_local
703 !! Combined output, spectral-path output and local-path output
704
705
706 ! Spectral pathway: D @ R @ E @ u
707 !---------------------------------------------------------------------------
708
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 ptr_spec => matmul(this%encoder_basis, input(1,1)) ! [M, batch]
709
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 ptr_spec => matmul(this%params(1), ptr_spec) ! [M, batch]
710 4 ptr_spec => matmul(this%decoder_basis, ptr_spec) ! [n_out, batch]
711
712 ! Local bypass: W @ u
713 !---------------------------------------------------------------------------
714
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
4 ptr_local => matmul(this%params(2), input(1,1)) ! [n_out, batch]
715
716 ! Combine
717 !---------------------------------------------------------------------------
718 4 ptr => ptr_spec + ptr_local
719
720 ! Add bias
721 !---------------------------------------------------------------------------
722
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(this%use_bias)then
723
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 ptr => ptr + this%params(3)
724 end if
725
726 ! Apply activation
727 !---------------------------------------------------------------------------
728
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
4 call this%output(1,1)%zero_grad()
729
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
4 if(trim(this%activation%name) .eq. "none")then
730
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)
731 else
732 3 call this%z(1)%zero_grad()
733 3 call this%z(1)%assign_and_deallocate_source(ptr)
734 3 this%z(1)%is_temporary = .false.
735 3 ptr => this%activation%apply(this%z(1))
736
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 call this%output(1,1)%assign_and_deallocate_source(ptr)
737 end if
738
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
4 this%output(1,1)%is_temporary = .false.
739
740 4 end subroutine forward_fixed_lno
741 !###############################################################################
742
743
744 !###############################################################################
745 2 function get_attributes_fixed_lno(this) result(attributes)
746 !! Return list of fixed LNO attributes for ONNX export
747 implicit none
748
749 ! Arguments
750 class(fixed_lno_layer_type), intent(in) :: this
751 !! Instance of the fixed LNO layer
752 type(onnx_attribute_type), allocatable, dimension(:) :: attributes
753 !! List of attributes for ONNX export
754
755 ! Local variables
756 character(32) :: buffer
757 !! Buffer for integer-to-string conversion
758
759
13/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✓ Branch 21 taken 10 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 10 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 10 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 10 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 10 times.
12 allocate(attributes(5))
760
761 2 write(buffer, '(I0)') this%num_inputs
762 attributes(1) = onnx_attribute_type( &
763
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_inputs', type='int', val=trim(buffer))
764 2 write(buffer, '(I0)') this%num_outputs
765 attributes(2) = onnx_attribute_type( &
766
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_outputs', type='int', val=trim(buffer))
767 2 write(buffer, '(I0)') this%num_modes
768 attributes(3) = onnx_attribute_type( &
769
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_modes', type='int', val=trim(buffer))
770
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(this%use_bias)then
771 2 buffer = '1'
772 else
773 buffer = '0'
774 end if
775 attributes(4) = onnx_attribute_type( &
776
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='use_bias', type='int', val=trim(buffer))
777 attributes(5) = onnx_attribute_type( &
778
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='activation', type='string', val=trim(this%activation%name))
779
780 2 end function get_attributes_fixed_lno
781 !###############################################################################
782
783
784 !###############################################################################
785 1 subroutine emit_onnx_nodes_fixed_lno( &
786
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 this, prefix, nodes, num_nodes, max_nodes, inits, num_inits, &
787 max_inits, input_name, is_last_layer, format)
788 !! Emit decomposed standard ONNX nodes for a Fixed LNO layer.
789 !!
790 !! Forward: v = sigma(D * R * E * u + W * u + b)
791 !! where E and D are fixed Laplace bases, R is a learnable mixing matrix.
792 use coreutils, only: pi
793 implicit none
794
795 ! Arguments
796 class(fixed_lno_layer_type), intent(in) :: this
797 !! Fixed LNO layer instance
798 character(*), intent(in) :: prefix
799 !! Layer name prefix (e.g. "layer1")
800 type(onnx_node_type), intent(inout), dimension(:) :: nodes
801 !! Node accumulator
802 integer, intent(inout) :: num_nodes
803 !! Node counter
804 integer, intent(in) :: max_nodes
805 !! Node limit
806 type(onnx_initialiser_type), intent(inout), dimension(:) :: inits
807 !! Initialiser accumulator
808 integer, intent(inout) :: num_inits
809 !! Initialiser counter
810 integer, intent(in) :: max_inits
811 !! Initialiser limit
812 character(*), optional, intent(in) :: input_name
813 !! Name of the input tensor
814 logical, optional, intent(in) :: is_last_layer
815 !! Whether this is the last layer
816 integer, optional, intent(in) :: format
817 !! Export format selector
818
819 ! Local variables
820 integer :: j, k, idx, n
821 real(real32) :: s, t
822 1 real(real32), allocatable :: e_data(:), d_data(:)
823 character(128) :: e_name, d_name, r_name, w_name, b_name
824 character(128) :: trans_in_out, mm_e_out, mm_r_out, mm_d_out
825 character(128) :: mm_w_out, add_out, add_b_out, final_output, &
826 output_source
827 integer :: format_
828
829 1 format_ = 1
830
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(format)) format_ = format
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(format_ .ne. 2) return
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(.not.present(input_name)) return
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(.not.present(is_last_layer)) return
834
835 !--------------------------------------------------------------------------
836 ! Build names
837 !--------------------------------------------------------------------------
838
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(e_name, '(A,".E")') trim(prefix)
839
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(d_name, '(A,".D")') trim(prefix)
840
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(r_name, '(A,".R")') trim(prefix)
841
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(w_name, '(A,".W")') trim(prefix)
842
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(b_name, '(A,".b")') trim(prefix)
843
844
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(trans_in_out, '("/",A,"/Transpose_output_0")') trim(prefix)
845
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(mm_e_out, '("/",A,"/MatMul_output_0")') trim(prefix)
846
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(mm_r_out, '("/",A,"/MatMul_1_output_0")') trim(prefix)
847
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(mm_d_out, '("/",A,"/MatMul_2_output_0")') trim(prefix)
848
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(mm_w_out, '("/",A,"/MatMul_3_output_0")') trim(prefix)
849
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(add_out, '("/",A,"/Add_output_0")') trim(prefix)
850
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(add_b_out, '("/",A,"/Add_1_output_0")') trim(prefix)
851
852 !--------------------------------------------------------------------------
853 ! Emit nodes
854 !--------------------------------------------------------------------------
855 ! 1. Transpose(input)
856 call emit_nop_input_transpose(trim(prefix), trim(input_name), nodes, &
857
6/12
✗ 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 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 num_nodes, trim(trans_in_out))
858
859 ! 2. MatMul(E, x_t)
860 1 num_nodes = num_nodes + 1
861
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/MatMul")') trim(prefix)
862
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'MatMul'
863
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
864
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(e_name)
865
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(trans_in_out)
866
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
867
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(mm_e_out)
868
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
869
870 ! 3. MatMul(R, encoded)
871 1 num_nodes = num_nodes + 1
872
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/MatMul_1")') trim(prefix)
873
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'MatMul'
874
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
875
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(r_name)
876
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(mm_e_out)
877
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
878
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(mm_r_out)
879
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
880
881 ! 4. MatMul(D, mixed)
882 1 num_nodes = num_nodes + 1
883
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/MatMul_2")') trim(prefix)
884
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'MatMul'
885
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
886
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(d_name)
887
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(mm_r_out)
888
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
889
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(mm_d_out)
890
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
891
892 ! 5. MatMul(W, x_t)
893 1 num_nodes = num_nodes + 1
894
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/MatMul_3")') trim(prefix)
895
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'MatMul'
896
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
897
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(w_name)
898
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(trans_in_out)
899
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
900
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(mm_w_out)
901
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
902
903 ! 6. Add(spectral, local)
904 1 num_nodes = num_nodes + 1
905
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/Add")') trim(prefix)
906
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'Add'
907
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
908
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(mm_d_out)
909
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(mm_w_out)
910
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
911
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(add_out)
912
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
913
914 ! 7. Add(combined, bias)
915
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
916 1 num_nodes = num_nodes + 1
917
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 write(nodes(num_nodes)%name, '("/",A,"/Add_1")') trim(prefix)
918
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%op_type = 'Add'
919
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%inputs(2))
920
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(1) = trim(add_out)
921
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%inputs(2) = trim(b_name)
922
5/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 not taken.
✓ Branch 13 taken 1 times.
1 allocate(nodes(num_nodes)%outputs(1))
923
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 nodes(num_nodes)%outputs(1) = trim(add_b_out)
924
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 nodes(num_nodes)%attributes_json = ''
925 end if
926
927
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
928 1 output_source = add_b_out
929 else
930 output_source = add_out
931 end if
932 call emit_nop_output_tail(trim(prefix), trim(this%activation%name), &
933
6/12
✗ 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 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 is_last_layer, trim(output_source), nodes, num_nodes, final_output)
934
935 !--------------------------------------------------------------------------
936 ! Emit initialisers
937 !--------------------------------------------------------------------------
938 ! E: fixed encoder basis [M, n_in] in row-major
939 1 n = this%num_modes * this%num_inputs
940
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(e_data(n))
941
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 do j = 1, this%num_inputs
942
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if(this%num_inputs .gt. 1)then
943 24 t = real(j - 1, real32) / real(this%num_inputs - 1, real32)
944 else
945 t = 0.0_real32
946 end if
947
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 24 times.
121 do k = 1, this%num_modes
948 96 s = real(k, real32) * pi
949 96 idx = (k - 1) * this%num_inputs + j
950
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96 times.
120 e_data(idx) = exp(-s * t)
951 end do
952 end do
953 call emit_float_initialiser(trim(e_name), e_data, &
954
6/10
✓ Branch 1 taken 2 times.
✓ Branch 2 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 13 taken 1 times.
✗ Branch 14 not taken.
3 [this%num_modes, this%num_inputs], inits, num_inits)
955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(e_data)
956
957 ! D: fixed decoder basis [n_out, M] in row-major
958 1 n = this%num_outputs * this%num_modes
959
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(d_data(n))
960
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 do k = 1, this%num_modes
961 4 s = real(k, real32) * pi
962
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
53 do j = 1, this%num_outputs
963
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if(this%num_outputs .gt. 1)then
964 48 t = real(j - 1, real32) / real(this%num_outputs - 1, real32)
965 else
966 t = 0.0_real32
967 end if
968 48 idx = (j - 1) * this%num_modes + k
969
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
52 d_data(idx) = exp(-s * t)
970 end do
971 end do
972 call emit_float_initialiser(trim(d_name), d_data, &
973
6/10
✓ Branch 1 taken 2 times.
✓ Branch 2 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 13 taken 1 times.
✗ Branch 14 not taken.
3 [this%num_outputs, this%num_modes], inits, num_inits)
974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(d_data)
975
976 ! R: spectral mixing [M, M] in row-major
977 10 call emit_matrix_initialiser(trim(r_name), this%params(1)%val(:,1), &
978
14/28
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
1 this%num_modes, this%num_modes, inits, num_inits)
979
980 ! W: bypass weights [n_out, n_in] in row-major
981 10 call emit_matrix_initialiser(trim(w_name), this%params(2)%val(:,1), &
982
14/28
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
1 this%num_outputs, this%num_inputs, inits, num_inits)
983
984 ! b: bias [n_out, 1]
985
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
986 10 call emit_float_initialiser(trim(b_name), this%params(3)%val(:,1), &
987
16/30
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✓ Branch 31 taken 2 times.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
3 [this%num_outputs, 1], inits, num_inits)
988 end if
989
990
3/6
✓ 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.
2 end subroutine emit_onnx_nodes_fixed_lno
991 !###############################################################################
992
993
58/115
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 22 times.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 22 times.
✓ Branch 40 taken 26 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 22 times.
✓ Branch 43 taken 26 times.
✓ Branch 44 taken 22 times.
✓ Branch 45 taken 48 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 22 times.
✓ Branch 48 taken 28 times.
✓ Branch 49 taken 48 times.
✓ Branch 50 taken 2 times.
✓ Branch 51 taken 48 times.
✓ Branch 52 taken 2 times.
✓ Branch 53 taken 20 times.
✓ Branch 54 taken 4 times.
✓ Branch 55 taken 22 times.
✓ Branch 56 taken 2 times.
✓ Branch 57 taken 64 times.
✓ Branch 58 taken 22 times.
✓ Branch 59 taken 64 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 64 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 64 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 64 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 64 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 64 times.
✓ Branch 71 taken 24 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 24 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 24 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 22 times.
✓ Branch 81 taken 2 times.
✓ Branch 82 taken 22 times.
✓ Branch 83 taken 2 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 24 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 24 times.
✗ Branch 88 not taken.
✓ Branch 89 taken 24 times.
✗ Branch 90 not taken.
✓ Branch 91 taken 24 times.
✓ Branch 92 taken 22 times.
✓ Branch 93 taken 2 times.
✓ Branch 94 taken 22 times.
✓ Branch 95 taken 2 times.
✗ Branch 96 not taken.
✓ Branch 97 taken 24 times.
✗ Branch 98 not taken.
✓ Branch 99 taken 24 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 24 times.
✗ Branch 102 not taken.
✓ Branch 103 taken 24 times.
✓ Branch 104 taken 24 times.
✓ Branch 105 taken 24 times.
✗ Branch 106 not taken.
✓ Branch 107 taken 24 times.
✗ Branch 108 not taken.
✓ Branch 109 taken 24 times.
✗ Branch 110 not taken.
✓ Branch 111 taken 24 times.
✗ Branch 112 not taken.
✓ Branch 113 taken 24 times.
✗ Branch 114 not taken.
✓ Branch 115 taken 24 times.
✗ Branch 116 not taken.
✓ Branch 117 taken 24 times.
460 end module athena__fixed_lno_layer
994