\section{River Mode 2}
\label{subsubsec:river_mode1}

While the Household Emission model introduced the very basic concepts of the
model implementation in the GREAT-ER II Model Suite, the River model mode 2
presents further items like results or estimate functions. 

This section 
focus on the most important parts, the complete implementation can be found in
the GREAT-ER Model source codes under 
\filename{GreaterModel/Worker/rivermodels.py}

\subsection{General}

{\scriptsize
\begin{verbatim}
class RiverModel2( RiverModel1 ):
    """Implements GREAT-ER River Model Mode 2."""
       
    _required_parameters = [('MOD','MODE_RIVER','2'), 
        ('STRETCH','Q_VAL'), ('STRETCH','Q_DIST'),
        ('STRETCH','V_VAL'), ('STRETCH','V_DIST'),
        ('STRETCH','L'), ('STRETCH','STRETCH_CLASS_ID'),
        ('STRETCH_CLASS','SS_VAL'),('STRETCH_CLASS','SS_DIST'),
        ('ENV', 'SS_CORR'),
        ('STRETCH_CLASS','F_OC'),
        ('SUBST','K_DEG'), ('SUBST','K_SED'), ('SUBST','K_VOL'),
        ('SUBST','KD_RIVER'), ('SUBST','K_OC')
        ]

    _correlated_parameters = [(('STRETCH','V_VAL'), ('STRETCH','Q_VAL'), 1.0),
                              (('STRETCH_CLASS','SS_VAL'), 
                                    ('STRETCH','Q_VAL'), ('ENV', 'SS_CORR'))]

    name = 'River Model, Mode 2'
\end{verbatim}
}

\begin{itemize}
	\item The \classobj{RiverModel2} inherits from the 
		\classobj{RiverModel1}.
	\item The mode tuple identifies the parameter and the value on which 
		the application of the River model mode 2 is decided.
	\item The \varname{\_correlated\_parameters} lists the correlation 
		of flow velocity with the volumne flow (fixed) and the 
		suspended solids concentration with the flow (specified by 
		correlation factor as an environmental parameter)
\end{itemize}

\subsection{Missing Parameters}

The River model mode 2 provides an estimation function for the $K_d$: 
$K_d = K_{OC} \cdot f_{OC}$, if $K_d$ is not present. Therefore the 
\method{MissingParameter} method has to be extended to take this into account.

{\scriptsize
\begin{verbatim}
    def MissingParameters(self, parameter_list = None):
        """Implement River Model, Mode 2 specific Missing Parameter Check."""

        parameters = []
        
        if parameter_list is None:
            parameter_list = self._required_parameters

        # First perform the default analysis
        parameters = RiverModel1.MissingParameters(self, parameter_list)

        # Second check the specifics, if the model is currently selected:
        if (eval_parameter(data, ('MOD','MODE_RIVER','value')) == '2':
            # We have an estimate function for Kd_river = f_oc * K_ow
            # I.e. if K_ow is well defined, don't force KD_RIVER.
            # f_oc as a river class parameter must be present by definition.
            if eval_parameter(self.session.data, ('SUBST', 'K_OC', 'value')):
                remove_parameter(parameters, ('SUBST','KD_RIVER'))
            # In any other case, KD_RIVER is well defined or already in the
            # list of missing parameters, so we don't need do force K_OC.
            else:
                remove_parameter(parameters, ('SUBST','K_OC'))

        return parameters

\end{verbatim}
}

\begin{itemize}
	\item The method header and preparatory steps have to be equal 
		with the basic method.
	\item First perform the default analysis by calling the parent class 
		\method{MissingParameters} method with the current classes
		\varname{\_required\_parameters} list.
	\item Second perform the analysis on the parameters affected by the 
		estimate function:
		\begin{itemize}
			\item Ensure we are in the correct River model mode.
			\item If the $K_{OC}$ is well defined in the data,
				the $K_d$ can be estimated so try to delete
				it from the list of missing parameters
				(\method{remove\_parameter}, 
				\ref{subsubsec:remove_parameter}).
			\item If the $K_{OC}$ is not present, the $K_d$
				must be defined for a complete parameter set.
				Either it is or it is already in the list 
				of missing parameters. In any case, the 
				$K_{OC}$ is not mandatory and can be removed
				from the list of missing parameters.
		\end{itemize}
	\item Finally the derived list has to be returned.
\end{itemize}

\subsection{Setup}

{\scriptsize
\begin{verbatim}
    def setup(self, segmentID):
        """Set up River Model, Mode 2."""
        
        # Instantiate the Results
        self.Results['CSIMSTART']  = StochasticResult()
        self.Results['CSIMEND']    = StochasticResult()
        self.Results['CSIMINTERN'] = StochasticResult()

[...]
        
        # Some parameters which only have to be processed once
        self.L = atof(data['STRETCH'][ID].l)
        
        if eval_parameter(data, ('SUBST', 'KD_RIVER', value):
            self.kd   = atof(data['SUBST']['KD_RIVER'].value)
        else:
            f_oc = atof(data['STRETCH_CLASS'][self.ClassID].f_oc)
            k_oc = atof(data['SUBST']['K_OC'].value)
            self.kd = f_oc * k_oc

[...]

\end{verbatim}
}

\begin{itemize}
	\item The River model calculates three different results, the according 
		\classobj{StochasticResult} objects are instantiated during 
		model setup and stored in the \varname{Results} dictionary.
	\item Object specific data (like the stretch length) are accessible
		within the data by table name, record identifier and field
		name.
	\item If the $K_d$ is present, make use of it. Else $f_{OC}$ and 
		$K_{OC}$ are present\footnote{Before actually starting a
		simulation a final analysis on parameter completeness is 
		performed. Hence we can be sure that $K_{OC}$ is defined if 
		$K_d$ is not.} so apply the estimate function. 
	\item The rest of the setup is similar to the Household Emission
		model.
\end{itemize}

\subsection{Compute}

{\scriptsize
\begin{verbatim}
    def compute( self, segment, shot_num ):
        """Compute GREAT-ER River Model Mode 2 for segment."""

        data = self.session.data
        # Get the flux input
        PHI = segment.PHIin()
        
        # Get the parameters from the data
        Q = self.Q.get(shot_num)
        v = self.v.get(shot_num)
        L = self.L
        SS = self.SS.get(shot_num)
 
        k_deg = self.k_deg.get(shot_num)
        k_sed = self.k_deg.get(shot_num)
        k_vol = self.k_deg.get(shot_num)
        
        f_d = 1.0 / (1.0 + 1.0e-6 * self.kd *SS)
        f_s = 1.0 - f_d

        # Avoid division by zero
        if v > 0.0 and Q > 0.0 and L > 0.0:
            # Hydralic Residence time in stretch [h]
            if segment.type == model.RiverSegmentType['LAKE']:
                V = L           # In case of a lake the length stores the 
                HRT=L/(Q*3600)  # volume by definition.
            else:    
                V = Q * L / v
                HRT = L/(v*3600.0)

            # 1st order river elimination process
            k = k_deg + f_s * k_sed + f_d * k_vol
            exp_term = exp( - k * HRT )
            PHIout = self.first_order_elimination(PHI, Q, v, HRT, L, 
                                                  k, exp_term)

        else:
            # flux output
            PHIout = PHI

            # Collect different concentrations
            self.Results['CSIMSTART'].add( 0.0 )
            self.Results['CSIMEND'].add( 0.0 )
            self.Results['CSIMINTERN'].add( 0.0 )

        return PHIout
\end{verbatim}
}

\begin{itemize}
	\item The mass flux into the segment is provided by the segments 
	method \method{PHIin}. The model implementation itself has not to take
	care about the graph structure.
	\item For better transparency a couple of shortcuts are used for
	the Parameter objects values.
	\item Fractioning values are depending on potentially distributed
	parameters and therewith have to be computed per Monte Carlo shot.
	\item Check all values used as quotient to avoid a division by zero.
	If a division by zero would coccur, consider the stretch segment 
	as virtual, store invalid results and hand through the mass flux
	income. 
	\item Else, calculate the hydraulic residence time, the first order
	elimination rate and perform the first order elimination
\end{itemize}

\subsection{First order elimination}

For completeness we show in addition to the River model mode 2 the
first order elimination as implemented as method of the River model mode 1.

{\scriptsize
\begin{verbatim}
    def first_order_elimination(self, PHI, Q, v, HRT, L, k, exp_term):
        """Generic first order elimination for rivers.""" 

        PHIout = exp_term * PHI

        if k != 0.0:
            self.Results['CSIMINTERN'].add( PHI * (1.0 - exp_term) 
                                            / ( Q * k * HRT ) )
        else:
            self.Results['CSIMINTERN'].add( PHI / Q )

        # Collect start and end concentrations
        self.Results['CSIMSTART'].add( PHI / Q )
        self.Results['CSIMEND'].add( PHIout / Q )

        return PHIout
\end{verbatim}
} 

The first order model ($\Phi_{out} = \Phi_{in} \cdot e^{-k HRT})$ is 
straight forward, mainly the calculation of the $C_{sim, internal}$
is of some complexity. Note, that the checks in the river models 
\method{compute} method in combination with checks on the elimination rate here
ensures to prevent a division by zero.

