\section{\src{dyn_vi_rhow_solver}}

\subsection{Description}

Kernel \src{dyn_vi_rhow_solver} is taken from the original subroutine
\src{vi_rhow_solver} in \NICAM.
%
This subrouine is originally defined in \src{mod_vi}.
%
Subroutine \src{vi_rhow_solver} is to solve the tridiagonal matrix
equations related to the vertical implicit scheme. See
\autoref{s:vert_coord} for the detail of this calculation.

\subsection{Discretization and code}

Argument lists and local variables definition part of this subroutine is
as follows.

\begin{LstF90}[name=vi_rhow_solver]
!-----------------------------------------------------------------------------
!> Tridiagonal matrix solver
subroutine vi_rhow_solver( &
     rhogw,  rhogw_pl,  &
     rhogw0, rhogw0_pl, &
     preg0,  preg0_pl,  &
     rhog0,  rhog0_pl,  &
     Srho,   Srho_pl,   &
     Sw,     Sw_pl,     &
     Spre,   Spre_pl,   &
     dt                 )
  !$ use omp_lib
  implicit none

  real(RP), intent(inout) :: rhogw    (ADM_gall   ,ADM_kall,ADM_lall   ) ! rho*w          ( G^1/2 x gam2 ), n+1
  real(RP), intent(inout) :: rhogw_pl (ADM_gall_pl,ADM_kall,ADM_lall_pl)

  real(RP), intent(in)    :: rhogw0   (ADM_gall   ,ADM_kall,ADM_lall   ) ! rho*w          ( G^1/2 x gam2 )
  real(RP), intent(in)    :: rhogw0_pl(ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: preg0    (ADM_gall   ,ADM_kall,ADM_lall   ) ! pressure prime ( G^1/2 x gam2 )
  real(RP), intent(in)    :: preg0_pl (ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: rhog0    (ADM_gall   ,ADM_kall,ADM_lall   ) ! rho            ( G^1/2 x gam2 )
  real(RP), intent(in)    :: rhog0_pl (ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: Srho     (ADM_gall   ,ADM_kall,ADM_lall   ) ! source term for rho  at the full level
  real(RP), intent(in)    :: Srho_pl  (ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: Sw       (ADM_gall   ,ADM_kall,ADM_lall   ) ! source term for rhow at the half level
  real(RP), intent(in)    :: Sw_pl    (ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: Spre     (ADM_gall   ,ADM_kall,ADM_lall   ) ! source term for pres at the full level
  real(RP), intent(in)    :: Spre_pl  (ADM_gall_pl,ADM_kall,ADM_lall_pl)
  real(RP), intent(in)    :: dt

  real(RP) :: Sall    (ADM_gall,   ADM_kall)
  real(RP) :: Sall_pl (ADM_gall_pl,ADM_kall)
  real(RP) :: beta    (ADM_gall   )
  real(RP) :: beta_pl (ADM_gall_pl)
  real(RP) :: gamma   (ADM_gall,   ADM_kall)
  real(RP) :: gamma_pl(ADM_gall_pl,ADM_kall)

  integer  :: gall, kmin, kmax, lall
  real(RP) :: grav
  real(RP) :: CVovRt2 ! Cv / R / dt**2
  real(RP) :: alpha

  integer  :: g, k, l
  integer  :: gstr, gend
  !$ integer  :: n_per_thread
  !$ integer  :: n_thread
  !---------------------------------------------------------------------------

\end{LstF90}

Here \src{rhogw} is $\rho \times w$ with metric $G^{1/2} \gamma^2$
multiplied at new time step $n+1$.
%
\src{rhogw0}, \src{preg0}, \src{rhog0}, are
$\rho \times w$, pressure, $\rho$
with metric multiplied at time step $n$, respectively.
%
\src{Srho}, \src{Sw}, \src{Spre} are
source term for $\rho$ at the full level,
source term for $\rho \times w$ at the half level,
source term for pressure at the full level, respectively.
%
Other arguments with suffix \src{_pl} are for the pole region.
%
\src{dt} is a time step for fast-mode.

Among local variables,
\src{alpha} is the flag for non-hydrostatic/hydrostatic.
In this kernel, set to $1$ in \src{problem_size.inc}.

Main part of this subroutine is as follows.

\begin{LstF90}[name=vi_rhow_solver,firstnumber=last]
  call DEBUG_rapstart('____vi_rhow_solver')

  gall = ADM_gall
  kmin = ADM_kmin
  kmax = ADM_kmax
  lall = ADM_lall

  grav    = CONST_GRAV
  CVovRt2 = CONST_CVdry / CONST_Rdry / (dt*dt)
  alpha   = real(NON_HYDRO_ALPHA,kind=RP)

  !$omp parallel default(none),private(g,k,l), &
  !$omp private(gstr,gend,n_thread,n_per_thread) &
  !$omp shared(gall,kmin,kmax,lall,rhogw,rhogw0,preg0,rhog0,Srho,Sw,Spre,dt,Sall,beta,gamma,Mu,Mc,Ml, &
  !$omp        GRD_afact,GRD_bfact,GRD_rdgzh,VMTR_GSGAM2H,VMTR_RGAM,VMTR_RGAMH,VMTR_RGSGAM2,VMTR_RGSGAM2H,grav,alpha,CVovRt2)
  gstr = 1
  gend = gall
  !$ n_thread     = omp_get_num_threads()
  !$ n_per_thread = gall / n_thread + int( 0.5_RP + sign(0.5_RP,mod(gall,n_thread)-0.5_RP) )
  !$ gstr         = n_per_thread * omp_get_thread_num() + 1
  !$ gend         = min( gstr+n_per_thread-1, gall )

  do l = 1, lall
     ! calc Sall
     do k = kmin+1, kmax
     do g = gstr, gend
        Sall(g,k) = (   ( rhogw0(g,k,  l)*alpha + dt * Sw  (g,k,  l) ) * VMTR_RGAMH  (g,k,  l)**2             &
                    - ( ( preg0 (g,k,  l)       + dt * Spre(g,k,  l) ) * VMTR_RGSGAM2(g,k,  l)                &
                      - ( preg0 (g,k-1,l)       + dt * Spre(g,k-1,l) ) * VMTR_RGSGAM2(g,k-1,l)                &
                      ) * dt * GRD_rdgzh(k)                                                                   &
                    - ( ( rhog0 (g,k,  l)       + dt * Srho(g,k,  l) ) * VMTR_RGAM(g,k,  l)**2 * GRD_afact(k) &
                      + ( rhog0 (g,k-1,l)       + dt * Srho(g,k-1,l) ) * VMTR_RGAM(g,k-1,l)**2 * GRD_bfact(k) &
                      ) * dt * grav                                                                           &
                    ) * CVovRt2
     enddo
     enddo

     ! boundary conditions
     do g = gstr, gend
        rhogw(g,kmin,  l) = rhogw(g,kmin,  l) * VMTR_RGSGAM2H(g,kmin,  l)
        rhogw(g,kmax+1,l) = rhogw(g,kmax+1,l) * VMTR_RGSGAM2H(g,kmax+1,l)
        Sall (g,kmin+1)   = Sall (g,kmin+1) - Ml(g,kmin+1,l) * rhogw(g,kmin,  l)
        Sall (g,kmax  )   = Sall (g,kmax  ) - Mu(g,kmax,  l) * rhogw(g,kmax+1,l)
     enddo

     !---< solve tri-daigonal matrix >

     ! condition at kmin+1
     k = kmin+1
     do g = gstr, gend
        beta (g)     = Mc(g,k,l)
        rhogw(g,k,l) = Sall(g,k) / beta(g)
     enddo

     ! forward
     do k = kmin+2, kmax
     do g = gstr, gend
        gamma(g,k)   = Mu(g,k-1,l) / beta(g)
        beta (g)     = Mc(g,k,l) - Ml(g,k,l) * gamma(g,k) ! update beta
        rhogw(g,k,l) = ( Sall(g,k) - Ml(g,k,l) * rhogw(g,k-1,l) ) / beta(g)
     enddo
     enddo

     ! backward
     do k = kmax-1, kmin+1, -1
     do g = gstr, gend
        rhogw(g,k  ,l) = rhogw(g,k  ,l) - gamma(g,k+1) * rhogw(g,k+1,l)
        rhogw(g,k+1,l) = rhogw(g,k+1,l) * VMTR_GSGAM2H(g,k+1,l) ! return value ( G^1/2 x gam2 )
     enddo
     enddo

     ! boundary treatment
     do g = gstr, gend
        rhogw(g,kmin  ,l) = rhogw(g,kmin  ,l) * VMTR_GSGAM2H(g,kmin  ,l)
        rhogw(g,kmin+1,l) = rhogw(g,kmin+1,l) * VMTR_GSGAM2H(g,kmin+1,l)
        rhogw(g,kmax+1,l) = rhogw(g,kmax+1,l) * VMTR_GSGAM2H(g,kmax+1,l)
     enddo
  enddo
  !$omp end parallel
\end{LstF90}

Inside of the long $l$-loop(l.72), the first $k$-loop(l.73) calcurates total source
term \src{Sall}.
%
The section after setting the boundary condition at \src{kmin} and \src{kmax}
solves tri-diagonal matrix.
%
Its first part(l.97 to l.111) is for forward elimination and the second
part(l.114 to l.119) is for backward substitution.

Note that elements of the tridiagonal matrix \src{Mc}, \src{Mu} and
\src{Ml} are calculated in advance by other subroutine in the original
module, and they are read from input data file in this kernel program.

The last part of this subroutine is for the pole region, doing almost
the same process as the normal region.

\begin{LstF90}[name=vi_rhow_solver,firstnumber=last,breaklines=false]
  if ( ADM_have_pl ) then
     do l = 1, ADM_lall_pl
        do k  = ADM_kmin+1, ADM_kmax
        do g = 1, ADM_gall_pl
           Sall_pl(g,k) = (   ( rhogw0_pl(g,k,  l)*alpha + dt * Sw_pl  (g,k,  l) ) * VMTR_RGAMH_pl  (g,k,  l)**2             &
                          - ( ( preg0_pl (g,k,  l)       + dt * Spre_pl(g,k,  l) ) * VMTR_RGSGAM2_pl(g,k,  l)                &
                            - ( preg0_pl (g,k-1,l)       + dt * Spre_pl(g,k-1,l) ) * VMTR_RGSGAM2_pl(g,k-1,l)                &
                            ) * dt * GRD_rdgzh(k)                                                                            &
                          - ( ( rhog0_pl (g,k,  l)       + dt * Srho_pl(g,k,  l) ) * VMTR_RGAM_pl(g,k,  l)**2 * GRD_afact(k) &
                            + ( rhog0_pl (g,k-1,l)       + dt * Srho_pl(g,k-1,l) ) * VMTR_RGAM_pl(g,k-1,l)**2 * GRD_bfact(k) &
                            ) * dt * grav                                                                                &
                          ) * CVovRt2
        enddo
        enddo

        do g = 1, ADM_gall_pl
           rhogw_pl(g,ADM_kmin,  l) = rhogw_pl(g,ADM_kmin,  l) * VMTR_RGSGAM2H_pl(g,ADM_kmin,  l)
           rhogw_pl(g,ADM_kmax+1,l) = rhogw_pl(g,ADM_kmax+1,l) * VMTR_RGSGAM2H_pl(g,ADM_kmax+1,l)
           Sall_pl (g,ADM_kmin+1)   = Sall_pl (g,ADM_kmin+1) - Ml_pl(g,ADM_kmin+1,l) * rhogw_pl(g,ADM_kmin,  l)
           Sall_pl (g,ADM_kmax  )   = Sall_pl (g,ADM_kmax  ) - Mu_pl(g,ADM_kmax,  l) * rhogw_pl(g,ADM_kmax+1,l)
        enddo

        k = ADM_kmin+1
        do g = 1, ADM_gall_pl
           beta_pl (g)     = Mc_pl(g,k,l)
           rhogw_pl(g,k,l) = Sall_pl(g,k) / beta_pl(g)
        enddo

        do k = ADM_kmin+2, ADM_kmax
        do g = 1, ADM_gall_pl
           gamma_pl(g,k)   = Mu_pl(g,k-1,l) / beta_pl(g)
           beta_pl (g)     = Mc_pl(g,k,l) - Ml_pl(g,k,l) * gamma_pl(g,k) ! update beta
           rhogw_pl(g,k,l) = ( Sall_pl(g,k) - Ml_pl(g,k,l) * rhogw_pl(g,k-1,l) ) / beta_pl(g)
        enddo
        enddo

        ! backward
        do k = ADM_kmax-1, ADM_kmin+1, -1
        do g = 1, ADM_gall_pl
           rhogw_pl(g,k  ,l) = rhogw_pl(g,k  ,l) - gamma_pl(g,k+1) * rhogw_pl(g,k+1,l)
           rhogw_pl(g,k+1,l) = rhogw_pl(g,k+1,l) * VMTR_GSGAM2H_pl(g,k+1,l) ! return value ( G^1/2 x gam2 )
        enddo
        enddo

        ! boundary treatment
        do g = 1, ADM_gall_pl
           rhogw_pl(g,ADM_kmin  ,l) = rhogw_pl(g,ADM_kmin  ,l) * VMTR_GSGAM2H_pl(g,ADM_kmin  ,l)
           rhogw_pl(g,ADM_kmin+1,l) = rhogw_pl(g,ADM_kmin+1,l) * VMTR_GSGAM2H_pl(g,ADM_kmin+1,l)
           rhogw_pl(g,ADM_kmax+1,l) = rhogw_pl(g,ADM_kmax+1,l) * VMTR_GSGAM2H_pl(g,ADM_kmax+1,l)
        enddo
     enddo
  endif

  call DEBUG_rapend('____vi_rhow_solver')

  return
end subroutine vi_rhow_solver
\end{LstF90}

\subsection{Input data and result}

Max/min/sum of input/output data of the kernel subroutine are output as
a log.
%
Below is an example of \src{$IAB_SYS=Ubuntu-gnu-ompi} case.

\begin{LstLog}
 ### Input ###
 +check[rhogw_prev      ] max=  1.0733675425174699E-14,min= -2.5212277839542070E-18,sum=  2.1443525022460023E-14
 +check[rhogw_prev_pl   ] max=  1.0733675425174699E-14,min= -3.0929371635479732E-15,sum=  7.6415689931329447E-15
 +check[check_rhogw     ] max=  6.3321830580406713E-01,min= -5.5759247708875415E-01,sum=  3.9071354372140144E+02
 +check[check_rhogw_pl  ] max=  9.9023353298473032E-02,min= -7.4852014128754477E-03,sum=  2.1725659627743767E+00
 +check[rhogw0          ] max=  1.2675708942695349E-03,min= -4.2678569215437437E-03,sum= -2.6525715444058587E-02
 +check[rhogw0_pl       ] max=  9.9481836269239257E-04,min= -4.2678569215437437E-03,sum= -8.3801034534239580E-02
 +check[preg0           ] max=  1.4047194007847271E+01,min= -2.6115802085359952E+01,sum= -1.0687083035942905E+05
 +check[preg0_pl        ] max=  1.3572400586711277E+01,min= -2.6115802085359952E+01,sum=  3.4640462790019097E+02
 +check[Srho            ] max=  3.3317357550311205E-04,min= -3.9691441465327759E-04,sum= -2.7468694177252501E-01
 +check[Srho_pl         ] max=  4.3441154740222974E-05,min= -2.2770470374092324E-05,sum= -3.8685936849254728E-05
 +check[Sw              ] max=  2.4651449651180712E-04,min= -3.2516247664737818E-04,sum= -1.6092196259156019E-01
 +check[Sw_pl           ] max=  2.8812604579719903E-04,min= -5.5442162236740700E-04,sum= -1.1046915056782920E-02
 +check[Spre            ] max=  3.6234075910381584E+01,min= -3.7498614557267203E+01,sum= -2.4763893276893483E+04
 +check[Spre_pl         ] max=  4.4863109100507081E+00,min= -2.0915571645010926E+00,sum=  1.0496606720811164E+00
 +check[Mc              ] max=  1.7037935104756485E+00,min=  0.0000000000000000E+00,sum=  8.2325595392291399E+05
 +check[Mc_pl           ] max=  1.4569727548844720E+00,min=  2.3177911966477871-310,sum=  6.0165678214473996E+02
 +check[Ml              ] max=  0.0000000000000000E+00,min= -8.3019108752152282E-01,sum= -3.9659607793632336E+05
 +check[Ml_pl           ] max=  3.2282782818256430E+02,min= -6.9953788050738130E-01,sum=  3.4604237063825449E+03
 +check[Mu              ] max=  0.0000000000000000E+00,min= -8.6888851023079583E-01,sum= -4.2616616191494197E+05
 +check[Mu_pl           ] max=  9.7233873292775215E+01,min= -7.5264063505825385E-01,sum=  8.5169724995286754E+02
 ### Output ###
 +check[rhogw           ] max=  6.3321830580406713E-01,min= -5.5759247708875415E-01,sum=  3.9071354372140144E+02
 +check[rhogw_pl        ] max=  9.9023353298473032E-02,min= -7.4852014128754477E-03,sum=  2.1725659627743767E+00
 ### Validation : point-by-point diff ###
 +check[check_rhogw     ] max=  0.0000000000000000E+00,min=  0.0000000000000000E+00,sum=  0.0000000000000000E+00
 +check[check_rhogw_pl  ] max=  0.0000000000000000E+00,min=  0.0000000000000000E+00,sum=  0.0000000000000000E+00
 *** Finish kernel
\end{LstLog}

Check the lines below \src{``Validation : point-by-point diff''} line,
that shows difference between calculated output array and
pre-calculated reference array.
These should be zero or enough small to be acceptable.

There are sample output log files in \file{reference/}
in each kernel program directory, for reference purpose.

\subsection{Sample of perfomance result}

Here's an example of the performance result part of the log output.
Below is an example executed with the machine environment described in \autoref{s:measuring_env}.
%
Note that in this program kernel part is iterated one time.

\begin{LstLog}
 *** Computational Time Report
 *** ID=001 : MAIN_dyn_vi_rhow_solver          T=     0.016 N=      1
 *** ID=002 : ____vi_rhow_solver               T=     0.016 N=      1
\end{LstLog}


\section{Cryptographic primitives}
\label{sec:crypto-primitives-shelley}

Figure~\ref{fig:crypto-defs-shelley} introduces the cryptographic abstractions used in
this document. We begin by listing the abstract types, which are meant to
represent the corresponding concepts in cryptography.
Their exact
implementation remains open to interpretation and we do not rely on
any additional properties of public key cryptography that are not explicitly stated
in this document. The types and rules we give here are needed in
order to guarantee certain security properties of the delegation process, which
we discuss later.

The cryptographic concepts required for the formal definition of witnessing
include public-private key pairs, one-way functions, signatures and
multi-signature scripts. The constraint we introduce states that a signature of
some data signed with a (private) key is only correct whenever we can verify it
using the corresponding public key.

Abstract data types in this paper are essentially placeholders with names
indicating the data types they are meant to represent in an implementation.
Derived types are made up of data structures (i.e.~products, lists, finite
maps, etc.) built from abstract types. The underlying structure of a data type
is implementation-dependent and furthermore, the way the data is stored on
physical storage can vary as well.

Serialization is a physical manifestation of data on a given storage device.
In this document, the properties and rules we state involving serialization are
assumed to hold true independently of the storage medium and style of data
organization chosen for an implementation.
The type $\Ser$ denotes the serialized representation of a term of any serializable
type.

\begin{figure}[htb]
  \emph{Abstract types}
  %
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      \var{sk} & \SKey & \text{private signing key}\\
      \var{vk} & \VKey & \text{public verifying key}\\
      \var{hk} & \KeyHash & \text{hash of a key}\\
      \sigma & \Sig  & \text{signature}\\
      \var{d} & \Ser  & \text{data}\\
      \var{script} & \Script & \text{multi-signature script} \\
      \var{hs} & \HashScr & \text{hash of a script}
    \end{array}
  \end{equation*}
  \emph{Derived types}
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      (sk, vk) & \KeyPair & \text{signing-verifying key pairs}
    \end{array}
  \end{equation*}
  \emph{Abstract functions}
  %
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      \hashKey{} & \VKey \to \KeyHash
                 & \text{hash a verification key} \\
                 %
      \fun{verify} & \powerset{\left(\VKey \times \Ser \times \Sig\right)}
                   & \text{verification relation}\\
                   %
      \fun{sign} & \SKey \to \Ser \to \Sig
                 & \text{signing function}\\
      \fun{hashScript} & \Script \to \HashScr & \text{hash a serialized script}
    \end{array}
  \end{equation*}
  \emph{Constraints}
  \begin{align*}
    & \forall (sk, vk) \in \KeyPair,~ d \in \Ser,~ \sigma \in \Sig \cdot
    \sign{sk}{d} = \sigma \implies (vk, d, \sigma) \in \fun{verify}
  \end{align*}
  \emph{Notation for serialized and verified data}
  \begin{align*}
    & \serialised{x} ~\in \Ser & \text{serialised representation of } x\\
    & \mathcal{V}_{\var{vk}}{\serialised{d}}_{\sigma} = \verify{vk}{d}{\sigma}
    & \text{shorthand notation for } \fun{verify}
  \end{align*}
  \caption{Cryptographic definitions}
  \label{fig:crypto-defs-shelley}
\end{figure}

When we get to the blockchain layer validation, we will use
key evolving signatures (KES) according to the MMM scheme \cite{cryptoeprint:2001:034}.
This is another asymmetric key cryptographic scheme, also relying on
the use of public and private key pairs.
These signature schemes provide forward cryptographic security, meaning that a
compromised key does not make it easier for an adversary to forge a signature that
allegedly had been signed in the past.
Figure~\ref{fig:kes-defs-shelley} introduces the additional cryptographic abstractions
needed for KES.

In KES, the public verification key stays constant, but the
corresponding private key evolves incrementally. For this reason, KES
signing keys are indexed by integers representing the step in the key's
evolution. This evolution step parameter is also an additional parameter needed
for the signing (denoted by $\fun{sign_{ev}}$) and verification
(denoted by $\fun{verify_{ev}}$) functions.

Since the private key evolves incrementally in a KES scheme, the ledger rules
require the pool operators to evolve their keys every time a certain number of
slots have passed, as determined by the global constant $\SlotsPerKESPeriod$.

\begin{figure}[htb]
  \emph{Abstract types}
  %
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      \var{sk} & \N \to \SKeyEv & \text{private signing keys}\\
      \var{vk} & \VKeyEv & \text{public verifying key}\\
    \end{array}
  \end{equation*}
  \emph{Notation for evolved signing key}
  \begin{align*}
    & \var{sk_n} = \var{sk}~n & n\text{-th evolution of }sk
  \end{align*}
  \emph{Derived types}
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      (sk_n, vk) & \KeyPairEv & \text{signing-verifying key pairs}
    \end{array}
  \end{equation*}
  \emph{Abstract functions}
  %
  \begin{equation*}
    \begin{array}{r@{~\in~}lr}
      \fun{verify_{ev}} & \powerset{\left(\VKey \times \N \times \Ser \times \Sig\right)}
                        & \text{verification relation}\\
                        %
      \fun{sign_{ev}} & (\N \to \SKeyEv) \to \N \to \Ser \to \Sig
                      & \text{signing function}\\
    \end{array}
  \end{equation*}
  \emph{Constraints}
  \begin{align*}
    & \forall n\in\N, (sk_n, vk) \in \KeyPairEv, ~ d \in \Ser,~ \sigma \in \Sig \cdot \\
    & ~~~~~~~~\fun{sign_{ev}}~{sk}~{n}~{d} = \sigma \implies \verifyEv{vk}{n}{d}{\sigma}
  \end{align*}
  \emph{Notation for verified KES data}
  \begin{align*}
    & \mathcal{V}^{\mathsf{KES}}_{\var{vk}}{\serialised{d}}_{\sigma}^n
        = \verifyEv{vk}{n}{d}{\sigma}
    & \text{shorthand notation for } \fun{verify_{ev}}
  \end{align*}
  \caption{KES Cryptographic definitions}
  \label{fig:kes-defs-shelley}
\end{figure}

Figure~\ref{fig:types-msig} shows the types for multi-signature
schemes. Multi-signatures effectively specify one or more combinations of
cryptographic signatures which are considered valid. This is realized in a
native way via a script-like DSL which allows for defining terms that can be
evaluated. Multi-signature scripts is the only type of script (for any
purpose, including output-locking) that exist in Shelley.

The terms form a tree like structure and are evaluated via the
\fun{evalMultiSigScript} function. The parameters are a script and a set of key
hashes. The function returns $\mathsf{True}$ when the supplied key hashes are
a valid combination for the script, otherwise it returns $\mathsf{False}$.
The following are the four constructors that make up the multisignature script
scheme:

\begin{itemize}
\item[$\type{RequireSig}$] ~:~ the signature of a key with a specific
hash is required;
\item[$\type{RequireAllOf}$] ~:~signatures of all of the keys that hash to the
values specified in the given list are required;
\item[$\type{RequireAnyOf}$] ~:~a single signature is required, by a key hashing
to one of the given values in the list (this constructor is redundant and can
be expressed using $\type{RequireMOf}$);
\item[$\type{RequireMOf}$]~:~ $m$ of the keys with the hashes specified in the list
are required to sign
\end{itemize}

\begin{figure*}[hbt]
  \emph{MultiSig Type}

  \begin{equation*}
    \begin{array}{rll}
      \MSig & \subseteq & \Script \\
      \\~\\
      \var{msig}\in\MSig & = & \type{RequireSig}~\KeyHash\\
      & \uniondistinct &
         \type{RequireAllOf}~[\Script] \\
      & \uniondistinct&
         \type{RequireAnyOf}~[\Script] \\
      & \uniondistinct&
        \type{RequireMOf}~\N~[\Script]
    \end{array}
  \end{equation*}

  \emph{Functions}

  \begin{align*}
    \fun{evalMultiSigScript} & \in\MSig\to\powerset\KeyHash\to\Bool & \\
    \fun{evalMultiSigScript} & ~(\type{RequireSig}~hk)~\var{vhks} =  hk \in vhks \\
    \fun{evalMultiSigScript} & ~(\type{RequireAllOf}~ts)~\var{vhks} =
                              \forall t \in ts: \fun{evalMultiSigScript}~t~vhks\\
    \fun{evalMultiSigScript} & ~(\type{RequireAnyOf}~ts)~\var{vhks} =
                              \exists t \in ts: \fun{evalMultiSigScript}~t~vhks\\
    \fun{evalMultiSigScript} & ~(\type{RequireMOf}~m~ts)~\var{vhks} = \\
                             & m \leq \Sigma
                               \left(
                               [\textrm{if}~(\fun{evalMultiSigScript}~\var{t}~\var{vhks})~
                               \textrm{then}~1~\textrm{else}~0\vert t \leftarrow ts]
                               \right)
  \end{align*}

  \caption{Multi-signature via Native Scripts}
  \label{fig:types-msig}
\end{figure*}

\clearpage


% Created 2021-10-08 Fri 08:57
% Intended LaTeX compiler: pdflatex
\documentclass[presentation,aspectratio=169, usenames, dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{grffile}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{textcomp}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usepackage{khpreamble}
\usepackage{amssymb}
\usepgfplotslibrary{groupplots}
\newcommand*{\shift}{\operatorname{q}}
\definecolor{ppc}{rgb}{0.1,0.1,0.6}
\definecolor{iic}{rgb}{0.6,0.1,0.1}
\definecolor{ddc}{rgb}{0.1,0.6,0.1}
\def\ucolor{blue!80!black}
\def\ycolor{green!60!black}
\newcommand*{\incolor}[1]{\textcolor{\ucolor}{#1}}
\newcommand*{\outcolor}[1]{\textcolor{\ycolor}{#1}}
\usetheme{default}
\author{Kjartan Halvorsen}
\date{\today}
\title{PID for industrial control}
\hypersetup{
 pdfauthor={Kjartan Halvorsen},
 pdftitle={PID for industrial control},
 pdfkeywords={},
 pdfsubject={},
 pdfcreator={Emacs 26.3 (Org mode 9.4.6)},
 pdflang={English}}
\begin{document}

\maketitle

\section{PID tuning - (Smith and Corripio) Ziegler Nichols}
\label{sec:org7d5d788}
\begin{frame}[label={sec:orgb4c1428}]{The PID - practical form}
\definecolor{ppc}{rgb}{0.1,0.1,0.6}
\definecolor{iic}{rgb}{0.6,0.1,0.1}
\definecolor{ddc}{rgb}{0.1,0.5,0.1}

\begin{center}
  \begin{tikzpicture}[node distance=22mm, block/.style={rectangle, draw, minimum width=15mm}, sumnode/.style={circle, draw, inner sep=2pt}]

    \node[coordinate] (input) {};
    \node[sumnode, right of=input, node distance=16mm] (sum) {\tiny $\Sigma$};
    \node[color=iic,block, right of=sum, node distance=28mm] (ii)  {$\frac{1}{\tau_is}$};
    \node[color=ppc, coordinate, above of=ii, node distance=10mm] (pp)  {};
    \node[color=ddc,block, below of=ii, node distance=13mm] (dd)  {$\frac{-\tau_ds}{\frac{\tau_d}{N}s + 1}$};
    \node[sumnode, right of=ii, node distance=20mm] (sum2) {\tiny $\Sigma$};
    \node[block, right of=sum2, node distance=20mm] (gain)  {$k_c$};
    \node[coordinate, below of=sum, node distance=18mm] (feedback) {};
    \node[coordinate, right of=gain, node distance=20mm] (output) {};

    \draw[->] (input) -- node[above, pos=0.3] {$r(t)$} (sum);
    \draw[->] (sum) -- node[above, pos=0.2] {$e(t)$} node[coordinate] (mm) {}  (ii);
    \draw[->] (gain) -- node[above, near end] {$u(t)$} (output);
    \draw[->] (feedback) -- node[left, near start] {$y(t)$} node[right, pos=0.95] {-} (sum);
    \draw[->, color=ppc] (mm) |- (pp) -| node[right,] {$u_P(t)$} (sum2);
    \draw[->, color=ddc] (feedback |- dd) -- node[above, pos=0.95] {} (dd);
    \draw[->, color=ddc] (dd) -| node[right,] {$u_D(t)$} (sum2)  ;
    \draw[->, color=iic] (ii)  -- node[above,] {$u_I(t)$} (sum2);
    \draw[->] (sum2) -- node[above, near end] {} (gain);

  \end{tikzpicture}
\end{center}

\alert{Activity} What are the modifications and why are they introduced, comparing to the controller \(F(s) = k_c\left(1 + \frac{1}{\tau_i s} + \tau_d s\right)\)?
\end{frame}

\begin{frame}[label={sec:org168e46f}]{PID tuning}
\end{frame}
\begin{frame}[label={sec:org974319e}]{Method by Smith \& Corripio using table by Ziegler-Nichols}
\small

Given process model (fitted to response of the system) \[ G(s) = K \frac{\mathrm{e}^{-s\theta}}{\tau s + 1} \] and PID controller
   \[ F(s) = k_c\left( 1 + \frac{1}{\tau_i s} + \tau_d s\right) \]
   Choose the PID parameters according to the following table (Ziegler-Nichols, 1943)
   \begin{center}
   \setlength{\tabcolsep}{20pt}
   \renewcommand{\arraystretch}{1.5}
   \begin{tabular}{llll}
   Controller & \(k_c\) & \(\tau_i\) & \(\tau_d\)\\
  \hline\hline
  P & \(\frac{\tau}{\theta K}\) &  & \\
  PI & \(\frac{0.9\tau}{\theta K}\) & \(\frac{\theta}{0.3}\) & \\
  PID & \(\frac{1.2\tau}{\theta K}\) & \(2\theta\) & \(\frac{\theta}{2}\)\\
  \hline
\end{tabular}
\end{center}

Gives good control for \[0.1 < \frac{\theta}{\tau} < 0.6.\]
\end{frame}

\section{The delay transfer function}
\label{sec:org13c8ece}

\begin{frame}[label={sec:org4fe7098}]{The delay}
\begin{center}
  \begin{tikzpicture}[scale = 0.8, node distance=20mm, block/.style={rectangle, draw, minimum width=15mm}, sumnode/.style={circle, draw, inner sep=2pt}]

  \node[coordinate] (refinput) {};
  \node[block, right of=refinput] (motor) {$G(s)$};
  \node[coordinate, right of=motor, node distance=20mm] (output) {};

  \draw[\ucolor, ->] (refinput) -- node[above, pos=0.3] (voltsignal) {$u$} (motor);
  \draw[\ycolor, ->] (motor) -- node[above, pos=0.5] (velsignal) {$y$} (output);
  \end{tikzpicture}
\end{center}

Let \(\incolor{u(t) = \sin\omega_1 t}\). Then, after transients have died out,
\[ \outcolor{y(t)}= \outcolor{|G(\omega_1)| \sin \big( \omega_1 t + \arg G(i\omega_1)\big)}. \]

\pause
\alert{If ouput is simply a delayed input} \(\outcolor{y(t)}= \outcolor{ \sin \big( \omega_1 (t - \theta) \big)}\)

\pause
\alert{Activity}
Identify \(|G(i\omega)|\) and \(\arg G(i\omega)\) for the pure delay.
\end{frame}

\begin{frame}[label={sec:org3ad6758}]{The Bode-plot of the delay}
\begin{columns}
\begin{column}{0.7\columnwidth}
\begin{center}
  \includegraphics[width=.8\linewidth]{../../figures/bode-delay}
\end{center}
\end{column}

\begin{column}{0.6\columnwidth}
\pause

\alert{Review of Excercises for Session 3}

What is the time-delay \(\theta\)?
\end{column}
\end{columns}
\end{frame}

\section{Analytical PID design}
\label{sec:org90ed2bc}

\begin{frame}[label={sec:org5b54ab8}]{Analytical PID design}
\end{frame}
\begin{frame}[label={sec:org3701623}]{Analytical PID design}
   \begin{center}
   \begin{tikzpicture}[node distance=22mm, block/.style={rectangle, draw, minimum width=15mm}, sumnode/.style={circle, draw, inner sep=2pt}]
  {
  \node[coordinate] (input) {};
  \node[sumnode, right of=input] (sum) {\tiny $\sum$};
  \node[block, right of=sum, node distance=2.6cm] (reg) {$F(s)$};
  \node[block, right of=reg, node distance=2.6cm] (plant) {$G(s)$};
  \node[coordinate, right of=plant, node distance=2cm] (output) {};
  \node[coordinate, below of=plant, node distance=12mm] (feedback) {};

  \draw[->] (plant) -- node[coordinate, inner sep=0pt] (meas) {} node[near end, above] {$y(t)$} (output);
  \draw[->] (meas) |- (feedback) -| node[very near end, left] {$-$} (sum);
  \draw[->] (input) -- node[very near start, above] {$r(t)$} (sum);
  \draw[->] (sum) -- node[above] {$e(t)$} (reg);
  \draw[->] (reg) -- node[above] {$u(t)$}(plant);
}
\end{tikzpicture}
\end{center}

\alert{Activity}  Solve for \(F(s)\) in the closed-loop transfer function \[G_c(s) = \frac{G(s)F(s)}{1 + G(s)F(s)}\]
\end{frame}

\begin{frame}[label={sec:orga5c28fe}]{Analytical PID design - Solution}
\end{frame}
\begin{frame}[label={sec:org99ec3bb}]{Analytical PID design - Solution}
Solving for \(F(s)\) in the closed-loop transfer function \(G_c(s) = \frac{G(s)F(s)}{1 + G(s)F(s)}\)

\[ \big(1 + G(s)F(s)\big) G_c(s) = G(s)F(s)\]
\[ G_c(s) = \big( 1 - G_c(s)\big) G(s)F(s)\]
\[F(s) = \frac{\frac{G_c(s)}{G(s)}}{1 - G_c(s)}\]
\end{frame}

\begin{frame}[label={sec:orgb8e67b6}]{Analytic PID tuning - first-order with delay}
   \begin{center}
   \begin{tikzpicture}[scale=0.7, transform shape, node distance=22mm, block/.style={rectangle, draw, minimum width=15mm}, sumnode/.style={circle, draw, inner sep=2pt}]
  {
  \node[coordinate] (input) {};
  \node[sumnode, right of=input] (sum) {\tiny $\sum$};
  \node[block, right of=sum, node distance=2.6cm] (reg) {$F(s)$};
  \node[block, right of=reg, node distance=2.6cm] (plant) {$G(s)$};
  \node[coordinate, right of=plant, node distance=2cm] (output) {};
  \node[coordinate, below of=plant, node distance=12mm] (feedback) {};

  \draw[->] (plant) -- node[coordinate, inner sep=0pt] (meas) {} node[near end, above] {$y(t)$} (output);
  \draw[->] (meas) |- (feedback) -| node[very near end, left] {$-$} (sum);
  \draw[->] (input) -- node[very near start, above] {$r(t)$} (sum);
  \draw[->] (sum) -- node[above] {$e(t)$} (reg);
  \draw[->] (reg) -- node[above] {$u(t)$}(plant);
}
\end{tikzpicture}
\end{center}

Given model \(G(s) = K \frac{\mathrm{e}^{-s\theta}}{\tau s + 1}\) of the process and desired closed-loop transfer function \(G_c(s) = \frac{\mathrm{e}^{-s\theta}}{\tau_c s + 1}\)

\begin{align*}
F(s) &=  \frac{ \frac{G_c(s)}{G(s)}}{1 - G_c(s)} = \frac{ \frac{\mathrm{e}^{-s\theta}}{\tau_cs + 1} \frac{\tau s + 1}{K \mathrm{e}^{-s\theta}} }{1 - \frac{\mathrm{e}^{-s\theta}}{\tau_cs + 1}} = \frac{1}{K} \left( \frac{\tau s + 1}{\tau_c s + 1 - \mathrm{e}^{-s\theta}} \right) \\
&\approx \frac{1}{K} \left( \frac{\tau s + 1}{(\tau_c+\theta) s}\right)
%  = \underbrace{\frac{\tau}{K(\tau_c+\theta)}}_{k_c} \left( 1 + \frac{1}{\underbrace{\tau}_{\tau_i} s} \right).
\end{align*}

\pause
\alert{Activity}  A PI-controller can be written \(F(s) = k_c\frac{\tau_is + 1}{\tau_i s}\). Determine \(k_c\) and \(\tau_i\) in terms of the parameters \(K\), \(\theta\), \(\tau\) and \(\tau_c\).
\end{frame}

\begin{frame}[label={sec:org9f32e07}]{Example}
   \begin{center}
   \begin{tikzpicture}[node distance=22mm, block/.style={rectangle, draw, minimum width=15mm}, sumnode/.style={circle, draw, inner sep=2pt}]
  {
  \node[coordinate] (input) {};
  \node[sumnode, right of=input] (sum) {\tiny $\sum$};
  \node[block, right of=sum, node distance=2.6cm] (reg) {$k_c\frac{\tau_i s + 1}{\tau_i s}$};
  \node[block, right of=reg, node distance=2.6cm] (plant) {$\frac{200 \mathrm{e}^{-0.1s}}{0.1s + 1}$};
  \node[coordinate, right of=plant, node distance=2cm] (output) {};
  \node[coordinate, below of=plant, node distance=12mm] (feedback) {};

  \draw[->] (plant) -- node[coordinate, inner sep=0pt] (meas) {} node[near end, above] {$y(t)$} (output);
  \draw[->] (meas) |- (feedback) -| node[very near end, left] {$-$} (sum);
  \draw[->] (input) -- node[very near start, above] {$r(t)$} (sum);
  \draw[->] (sum) -- node[above] {$e(t)$} (reg);
  \draw[->] (reg) -- node[above] {$u(t)$}(plant);
}
\end{tikzpicture}
\end{center}

\(k_c = \frac{\tau}{K(\tau_c+\theta)}\) and \(\tau_i = \tau\).

\alert{Activity} Determine the controller for the choice \(\tau_c = \tau\)
\end{frame}

\begin{frame}[label={sec:org7cb52e1}]{The PID - practical aspects}
{\footnotesize Åström \& Hägglund (1988) \emph{PID controllers: Theory, design and tuning, 2nd ed} Instrument Society of America.}

\begin{block}{Approximating nonlinear systems with linear models}
\begin{itemize}
\item Model is accurate only in neighborhood of operating point for which the system is approximated.
\item Solution: Divide operating range into many regions, with separate PID parameters for each region
\end{itemize}
\end{block}

\begin{block}{Approximating high-order systems with low-order models}
\begin{itemize}
\item Only accurate for low frequencies
\item Beware of behavior for high-frequency input to the closed-loop system
\end{itemize}
\end{block}
\end{frame}

\begin{frame}[label={sec:org348d7d8}]{The PID - practical aspects, contd}
\begin{block}{When do PID controllers work well?}
\begin{itemize}
\item The plant dynamics can be well approximated with low-order model
\item Demands on performance not too high
\end{itemize}
\end{block}
\begin{block}{More sophisticated control needed when}
\begin{itemize}
\item Higher order dynamics
\item Oscillatory modes
\item Long deadtime
\end{itemize}
\end{block}
\end{frame}

\begin{frame}[label={sec:org8734794}]{The PID - practical aspects, contd}
\begin{block}{Choice of controller}
\begin{enumerate}
\item P-controller if damping and steady-state error satisfied
\item PI-controller if steady-state error must be zero (often 1st order dynamics)
\item PID-controller if PI does not give sufficient damping (often 2nd order dynamics)
\item Tuning parameter \(\tau_c\) for SIMC tuning method:
\begin{itemize}
\item Smaller (=faster) than \(\tau\) if sufficiently damped and limitations on input signal not violated.
\item larger (=slower) than \(\tau\) if more damping required or smaller input signal required.
\end{itemize}
\end{enumerate}
\end{block}
\end{frame}

\section{Windup}
\label{sec:orgcbf51b3}

\begin{frame}[label={sec:org74f2e63}]{Integral windup}
\end{frame}

\section{Anti-windup}
\label{sec:orgc2e60f9}

\begin{frame}[label={sec:org9814f48}]{Anti-windup using back-calculation}
\begin{center}
\includegraphics[width=.7\linewidth]{/home/kjartan/tec/mr2025/figures/Simulink-backtracking.png}
\end{center}
\end{frame}

\begin{frame}[label={sec:org251c356}]{Anti-windup using back-calculation}
   \begin{center}
 	  \begin{tikzpicture}[every node/.append style={transform shape}, scale = 0.7, font=\footnotesize,
	block/.style={rectangle, draw, minimum width=12mm, minimum height=10mm, inner sep=4pt},
	amp/.style = {regular polygon, regular polygon sides=3,
              draw, fill=white, text width=1em,
              inner sep=1pt, outer sep=0mm,
              shape border rotate=-90},
	      summ/.style = {circle, draw, inner sep = 1pt},]
	 \node[block, align=center] (motor) at (0,0) {Plant};
	 \node[coordinate, right of=motor, node distance = 26mm,] (output) {};
	 \node[block, left of=motor, node distance=26mm] (saturation) {};

	 \node[block, left of=saturation, node distance=26mm] (gain)  {$k_{c}$};

	 \node[summ, left of=gain, node distance=16mm] (sum2) {};
	 \node[color=iic,block, left of=sum2, node distance=18mm] (int)  {$\frac{1}{s}$};
	 \node[summ, left of=int, node distance=16mm] (sumint) {};
	 \node[color=iic,block, left of=sumint, node distance=18mm] (ii)  {$\frac{1}{\tau_{i}}$};
	 \node[color=ppc, coordinate, above of=ii, node distance=10mm] (pp)  {};
	 \node[summ, left of=ii, node distance=16mm] (sumsp) {};
	 \node[coordinate, left of=sumsp, node distance = 10mm,] (setpoint) {};

       \draw[->] (sumsp) -- node[above, pos=0.2] {$e(t)$} node[coordinate] (mm) {}  (ii);
       \draw[->] (gain) -- node[coordinate] (idmeas) {} node[above, ] {$u(t)$} (saturation);
       \draw[->, color=ppc] (mm) |- (pp) -| node[right,] {$u_P(t)$} (sum2);
       \draw[->, color=iic] (int)  -- node[above,] {$u_I(t)$} (sum2);
       \draw[->] (sum2) -- node[above, near end] {} (gain);

	 \draw[->] (setpoint) -- node[above, very near start ] {$y_{ref}$} (sumsp);
	 \draw[->] (saturation) -- node[coordinate, ] (satmeas) {} node[above,] {$u_s(t)$} (motor);
	 \draw[->] (motor) -- node[coordinate] (meas) {} node[above, very near end] {$y$} (output);
	 \draw[->] (meas) -- node[right] {} ++(0,-28mm) -| node[pos=0.95, left] {$-$} (sumsp);

	 % Anti-windup
	 \draw ($ (saturation.south west) + (2mm, 2mm) $) -- ++(3mm, 0) -- ++(3mm, 5mm) -- ++(3mm, 0);
	 \node[block, below of=sumint, node distance=16mm] (back) {$\frac{1}{k_{c}\tau_t}$};
	 \node[summ, below of=saturation, node distance=12mm] (sumsat) {};
	 \draw[->] (satmeas) |- node[above, pos=0.8] {} (sumsat);
	 \draw[->] (idmeas) |- node[above, pos=0.8] {$-$} (sumsat);
	 \draw[->] (sumsat) |- (back);
	 \draw[->] (back) -- (sumint);
	 \draw[->] (ii) -- (sumint);
	 \draw[->] (sumint) -- (int);

	 \node[coordinate, right of=back, node distance=2cm] (sat) {};

\end{tikzpicture}
\end{center}

\alert{Activity} Assume that the actuator is saturated. determine the transfer function from \(u_s(t)\) to \(u(t)\).
\end{frame}
\end{document}