\chapter{Hay and feed}\label{ch:feed}
\section{Hay preparation}
\subsection*{Physics}
Hay concentration is calculated from grass produced over two preparation
windows, with a configurable weight for the first window. The running
weighted mean of fresh-grass concentration is multiplied by a drying factor
to express activity per kilogram of hay. This represents seasonal variation
in grass contamination and the change in mass basis during drying.

During preparation, only grass produced up to the query date enters the
average. Pre-event production contributes zero activity but remains in the
denominator. After preparation ends, the completed
stock is held and loses activity by radioactive decay. When it becomes a
stored feed, the feed graph applies its own specified delay and radioactive
survival exactly once; that delay is distinct from hay preparation and does
not repeat the dry-mass conversion (\cref{eq:hay,eq:edge}).
\subsection*{Equations}
With start $s$, split $h$, end $e$, query $q$, and dimensionless first-window
multiplier $w$ and drying factor $d_h$, define $q'=\min(q,e)$ and
$W(q)=w[\min(q',h)-s]+\max(0,q'-h)$ for $q\geq s$. With grass concentration
$C_g(x)$ in \si{\becquerel\per\kilogram},
\begin{equation}\label{eq:hay}
C_{h}(q)=d_h\frac{w\int_s^{\min(q',h)} C_g(x)\,dx+
\int_h^{\max(h,q')}C_g(x)\,dx}{W(q)}
e^{-\lambda_{\phys}\max(0,q-e)}\quad(W(q)>0).
\end{equation}
Empty integral spans contribute zero. At $q=s$, the kernel uses grass at
$s$. $W$ has units days and the numerator
\si{\becquerel\day\per\kilogram}, so the result is
\si{\becquerel\per\kilogram}. For $q<s$, it is zero.
\subsection*{Parameters}
\begin{center}\footnotesize\begin{tabular}{@{}p{.10\linewidth}@{\hspace{3pt}}p{.14\linewidth}@{\hspace{3pt}}p{.35\linewidth}@{\hspace{3pt}}p{.35\linewidth}@{}}\toprule Symbol & Unit & SQLite table.column & Compiled field\\\midrule
$s,h,e$ & seasonal day & scenario.hay\_preparation\_start\_day, hay\_first\_interval\_end\_day, hay\_preparation\_end\_day & hay\_preparation\_start\_day, hay\_first\_interval\_end\_day, hay\_preparation\_end\_day\\
$w$ & 1 & scenario.hay\_weighting\_factor & hay\_weighting\_factor\\
$d_h$ & 1 & plant.drying\_factor\_hay & drying\_factor\_hay\\\bottomrule\end{tabular}\end{center}
Loader \coderef{ecosys/data/loader.py}{282}{290} and
\coderef{ecosys/data/loader.py}{438}{477}; compiler
\coderef{ecosys/data/compile.py}{403}{449}.
\subsection*{Implementation}
\coderef{ecosys/kernels/processing.py}{160}{204}; Gregorian windows and
daily grass sources \coderef{ecosys/engine.py}{818}{1004}; report and delayed
source queries are handled in \coderef{ecosys/engine.py}{1007}{1128}.
\subsection*{Numerical treatment}
The source grid contains deterministic daily positions plus in-window query
positions; each subwindow uses piecewise-linear trapezoids, including
interpolated bounds. These source evaluations leave the animal-state
support unchanged.
\relation{The original formulation uses a 70/30 split over the completed
season \cite{mueller1993}. The configurable multiplier follows
\cite{excelmanual}; running weighted duration is specified by \sd{09}.
Implementation comparisons are in Appendix~\ref{sec:history-processing}.}
\evidence{\codefn{tests/kernels/test_hay.py::test_running_hay_weights_elapsed_production_without_future_grass},
\codefn{tests/integration/test_event_feed.py}.}

\section{Feed processing graph}
\subsection*{Physics}
Feed preparation and storage are represented by a directed graph. Each edge
specifies a source material, a product, a concentration factor and a storage
duration. Product concentration is obtained from the source at the delayed
time, multiplied by the processing factor and radioactive survival during
storage (\cref{eq:edge}). Factors greater than one can represent concentration
of activity into a smaller product mass.

Prepared hay and primary crops can supply these arrows. Some feed also
comes from an animal product---milk replacer is an example---so the animal
that supplies the milk must be calculated before the animal that eats that
feed. The graph makes this ordering explicit. A material-to-itself arrow
means a \emph{stored copy} of its primary source, rather than a physical
feedback loop. If another product uses that primary material, its processing
edge uses the primary source without the self-edge's delay.
\subsection*{Equations}
For edge $e: r\to m$ and storage $\tau_e$ in days, factor $f_e$ unitless,
\begin{equation}\label{eq:edge}
C_m(t)=f_e C_r(t-\tau_e)e^{-\lambda_{\phys}\tau_e},
\end{equation}
all concentrations in \si{\becquerel\per\kilogram}. A stored-copy source
for an edge is the primary $C_r$ at the shifted time, even if an $r\to r$
self-edge also exists.
\subsection*{Parameters}
\begin{center}\footnotesize\begin{tabular}{@{}p{.10\linewidth}@{\hspace{3pt}}p{.14\linewidth}@{\hspace{3pt}}p{.35\linewidth}@{\hspace{3pt}}p{.35\linewidth}@{}}\toprule Symbol & Unit & SQLite table.column & Compiled field\\\midrule
$f_e$ & 1 & processing\_factor.factor,raw\_material\_id,final\_material\_id,domain & ProcessingGraph.factors, raw\_material\_positions, final\_material\_positions\\
$\tau_e$ & d & storage\_duration.duration\_days & ProcessingGraph.storage\_durations\_days\\
$T_{\phys}$ & yr & nuclide.half\_life\_years & CompiledEventAxis.physical\_half\_life\_years\\\bottomrule\end{tabular}\end{center}
Loader \coderef{ecosys/data/loader.py}{295}{301},
\coderef{ecosys/data/loader.py}{522}{543}; graph compiler
\coderef{ecosys/foodchain.py}{87}{208}.
\subsection*{Implementation}
\coderef{ecosys/kernels/processing.py}{207}{274} handles an edge; the exact
delayed-time evaluator \coderef{ecosys/foodchain.py}{329}{442} handles graph
dependencies and the stored-copy rule; feed orchestration is
\coderef{ecosys/engine.py}{1007}{1075} and staged animal/feeds are in
\coderef{ecosys/engine.py}{1309}{1364}.
\subsection*{Numerical treatment}
Plant/hay evaluator callbacks are queried at exact cumulative shifted times;
simple sparse material sources can be linearly interpolated. A missing
reachable source or a genuine graph cycle raises an error. Pre-source values
are zero; no report-grid nearest-node lookup is performed.
\relation{Storage follows the model described in \cite{excelmanual}.
The source-selection convention and historical delay approximations are
documented in Appendix~\ref{sec:history-processing}.}
\evidence{\codefn{tests/kernels/test_processing_edges.py},
\codefn{tests/kernels/test_processing_graph.py::test_product_of_a_stored_material_uses_the_source_not_its_stored_copy},
\codefn{tests/integration/test_event_feed.py}.}
