forward_dynamic_lno Subroutine

private subroutine forward_dynamic_lno(this, input)

Forward propagation for the Laplace Neural Operator layer

Computes via pole-residue spectral decomposition: v = sigma( D(mu) @ diag(beta) @ E(mu) @ u + W @ u + b )

Bases E(mu) and D(mu) are rebuilt from current poles at each call. The element-wise residue scaling uses the diffstruc * broadcast: beta [M,1] * encoded [M,batch] -> [M,batch]

Type Bound

dynamic_lno_layer_type

Arguments

Type IntentOptional Attributes Name
class(dynamic_lno_layer_type), intent(inout) :: this

Layer instance to execute

class(array_type), intent(in), dimension(:,:) :: input

Input batch tensor collection


Source Code

  subroutine forward_dynamic_lno(this, input)
    !! Forward propagation for the Laplace Neural Operator layer
    !!
    !! Computes via pole-residue spectral decomposition:
    !!   v = sigma( D(mu) @ diag(beta) @ E(mu) @ u  +  W @ u  +  b )
    !!
    !! Bases E(mu) and D(mu) are rebuilt from current poles at each call.
    !! The element-wise residue scaling uses the diffstruc * broadcast:
    !!   beta [M,1] * encoded [M,batch] -> [M,batch]
    implicit none

    ! Arguments
    class(dynamic_lno_layer_type), intent(inout) :: this
    !! Layer instance to execute
    class(array_type), dimension(:,:), intent(in) :: input
    !! Input batch tensor collection

    ! Local variables
    type(array_type), pointer :: ptr, ptr_spec, ptr_local
    !! Combined output, spectral-path output and local-path output


    ! Spectral pathway:  D(mu) @ diag(beta) @ E(mu) @ u
    ! Uses autodiff-tracked lno_encode/lno_decode for pole gradients
    !---------------------------------------------------------------------------
    ptr_spec => lno_encode(input(1,1), this%params(1), &
         this%num_inputs, this%num_modes)                ! [M, batch]
    ptr_spec => elem_scale(ptr_spec, this%params(2))
    ! [M, batch] residue scaling
    ptr_spec => lno_decode(ptr_spec, this%params(1), &
         this%num_outputs, this%num_modes)               ! [n_out, batch]

    ! Local bypass:  W @ u
    !---------------------------------------------------------------------------
    ptr_local => matmul(this%params(3), input(1,1))     ! [n_out, batch]

    ! Combine
    !---------------------------------------------------------------------------
    ptr => ptr_spec + ptr_local

    ! Add bias
    !---------------------------------------------------------------------------
    if(this%use_bias)then
       ptr => ptr + this%params(4)
    end if

    ! Apply activation
    !---------------------------------------------------------------------------
    call this%output(1,1)%zero_grad()
    if(trim(this%activation%name) .eq. "none")then
       call this%output(1,1)%assign_and_deallocate_source(ptr)
    else
       call this%z(1)%zero_grad()
       call this%z(1)%assign_and_deallocate_source(ptr)
       this%z(1)%is_temporary = .false.
       ptr => this%activation%apply(this%z(1))
       call this%output(1,1)%assign_and_deallocate_source(ptr)
    end if
    this%output(1,1)%is_temporary = .false.

  end subroutine forward_dynamic_lno