Spaces:
Sleeping
Sleeping
| """Biological, physical, and economic constants for the Fish Farm simulation. | |
| ALL values sourced from the knowledge base: | |
| - 01-BIOLOGY-AND-SCIENCE.md (species data, water quality thresholds) | |
| - 02-REAL-WORLD-OPERATIONS.md (operational parameters, economics) | |
| - 03-MATHEMATICAL-MODELS.md (equation parameters, MDP spec) | |
| References inline as KB-XX-Section. | |
| """ | |
| import math | |
| from dataclasses import dataclass | |
| class TilapiaParams: | |
| """Nile Tilapia (Oreochromis niloticus) biological parameters. | |
| Source: FAO Annex 3 Fish Growth Model + KB-03 Section 15.6 | |
| """ | |
| # Growth model (bioenergetic: dW/dt = H*W^m - k*W^n) | |
| h: float = 0.4768 # consumption coefficient (KB-03 Sec 1.1) | |
| m: float = 0.6277 # anabolism exponent (KB-03 Sec 1.1) | |
| n: float = 0.8373 # catabolism exponent (KB-03 Sec 1.1) | |
| b: float = 0.7108 # assimilation efficiency (KB-03 Sec 1.1) | |
| a: float = 0.0559 # feeding catabolism fraction (KB-03 Sec 1.1) | |
| k_min: float = 0.0104 # catabolism base rate g^(1-n)/d (KB-03 Sec 1.1) | |
| s: float = 0.0288 # catabolism temp sensitivity 1/C (KB-03 Sec 1.1) | |
| # Temperature (KB-01 Sec 6.2, KB-03 Sec 1.1) | |
| T_min: float = 18.7 # minimum survivable temp (C) | |
| T_opt: float = 32.4 # optimal growth temp (C) | |
| T_max: float = 39.7 # maximum survivable temp (C) | |
| T_lethal_low: float = 11.0 # lethal low (KB-01 Sec 16) | |
| T_lethal_high: float = 42.0 # lethal high (KB-01 Sec 16) | |
| # Stocking / lifecycle | |
| w_initial: float = 5.0 # initial fingerling weight (g) | |
| w_market: float = 500.0 # target market weight (g) | |
| N_initial: int = 10000 # default stocking count | |
| base_mortality: float = 0.0005 # natural daily mortality rate (KB-03 Sec 15.6) | |
| # Feeding | |
| fcr_target: float = 1.6 # target FCR (KB-02 Sec 3) | |
| max_feeding_pct: float = 5.0 # max % body weight/day for fingerlings (KB-01 Sec 5.2) | |
| protein_fraction: float = 0.40 # feed protein content (KB-02 Sec 3) | |
| n_wasted_fraction: float = 0.50 # fraction of consumed N not retained (KB-03 Sec 2.2) | |
| # DO requirements (KB-01 Sec 2.2) | |
| DO_optimal: float = 5.0 # mg/L, growth reduction begins below | |
| DO_stress: float = 3.0 # mg/L, significant stress | |
| DO_lethal: float = 1.0 # mg/L, fish die | |
| # Allometric: W = a_wl * L^b_wl | |
| a_wl: float = 0.0282 # weight-length coefficient | |
| b_wl: float = 3.0 # isometric growth | |
| class WaterParams: | |
| """Water quality parameters and thresholds. | |
| Source: KB-01 Sec 2-4, KB-03 Sec 2, KB-01 Sec 16 | |
| """ | |
| # Dissolved Oxygen thresholds (mg/L) — tilapia-specific | |
| DO_optimal: float = 5.0 # above this = no growth reduction | |
| DO_crit: float = 5.0 # growth reduction begins (KB-03 Sec 1.2) | |
| DO_min: float = 3.0 # growth ceases (KB-03 Sec 1.2) | |
| DO_lethal: float = 1.0 # fish die (KB-01 Sec 2.2) | |
| DO_saturation_30C: float = 7.54 # mg/L at 30C (KB-01 Sec 2.1) | |
| # Unionized Ammonia thresholds (mg/L) — KB-01 Sec 3.3, KB-03 Sec 1.2 | |
| UIA_safe: float = 0.02 # safe zone | |
| UIA_crit: float = 0.05 # chronic stress begins | |
| UIA_lethal: float = 0.6 # lethal (KB-03 Sec 15.6) | |
| # TAN (mg/L) | |
| TAN_max: float = 5.0 # maximum before emergency (KB-03 Sec 15.6) | |
| # Nitrite (mg/L) — KB-01 Sec 3.4 | |
| NO2_safe: float = 0.1 | |
| NO2_stress: float = 0.5 | |
| NO2_lethal: float = 5.0 | |
| # pH — KB-01 Sec 4.1 | |
| pH_min: float = 6.5 | |
| pH_max: float = 8.5 | |
| pH_lethal_low: float = 4.0 | |
| pH_lethal_high: float = 11.0 | |
| pH_default: float = 7.5 | |
| # Nitrification — KB-01 Sec 3.1 | |
| O2_per_TAN: float = 4.57 # g O2 per g TAN oxidized (KB-01 Sec 3.1) | |
| alkalinity_per_TAN: float = 7.14 # g CaCO3 per g TAN oxidized | |
| # Reaeration coefficient (1/h) — KB-03 Sec 2.1 | |
| K_a_base: float = 0.04 # base reaeration at moderate wind | |
| # Biofilter removal efficiency (fraction) — KB-03 Sec 2.2 | |
| biofilter_efficiency: float = 0.6 | |
| class DiseaseParams: | |
| """SEIR disease model parameters. | |
| Source: KB-03 Sec 4, KB-01 Sec 7 | |
| """ | |
| # SEIR rates (per day) — KB-03 Sec 4.1-4.2 | |
| beta: float = 0.4 # transmission coefficient | |
| sigma: float = 0.2 # 1/latent_period (5 day latent) | |
| gamma: float = 0.1 # recovery rate (10 day infectious) | |
| alpha: float = 0.05 # disease-induced mortality | |
| mu: float = 0.0005 # natural mortality (background) | |
| # Environmental triggers — KB-01 Sec 7 | |
| stress_DO_threshold: float = 3.5 # DO below this increases disease risk | |
| stress_ammonia_threshold: float = 0.04 # UIA above this increases disease risk | |
| stress_temp_deviation: float = 5.0 # degrees from optimal that increases risk | |
| stress_density_threshold: float = 80.0 # fish/m3 that increases disease risk | |
| # Disease probability per hour when stressed | |
| outbreak_prob_per_hour: float = 0.0005 # ~1.2% chance per day under stress | |
| # Treatment effectiveness | |
| treatment_recovery_boost: float = 2.0 # multiplier on gamma during treatment | |
| treatment_cost_per_day: float = 50.0 # $/day | |
| treatment_duration_days: int = 5 | |
| class EconomicsParams: | |
| """Economic parameters. | |
| Source: KB-02 Sec 7, KB-03 Sec 6 | |
| """ | |
| feed_price_per_kg: float = 0.50 # $/kg feed (KB-03 Sec 15.6) | |
| market_price_per_kg: float = 3.00 # $/kg fish (KB-03 Sec 15.6) | |
| fixed_cost_per_day: float = 10.0 # $/day operating (KB-03 Sec 15.6) | |
| harvest_cost_per_kg: float = 0.30 # $/kg harvested | |
| fingerling_cost: float = 0.05 # $/fingerling | |
| electricity_cost_per_kwh: float = 0.12 | |
| aeration_power_kw: float = 2.0 # aerator power consumption | |
| heater_power_kw: float = 5.0 | |
| water_cost_per_m3: float = 0.50 | |
| class SystemParams: | |
| """Physical system parameters. | |
| Source: KB-02 Sec 14, KB-03 Sec 15.6 | |
| """ | |
| dt_hours: float = 1.0 # agent decision interval (hours) | |
| sub_steps: int = 10 # water quality sub-steps per hour (6 min each) | |
| tank_volume_m3: float = 100.0 # RAS tank volume | |
| tank_depth_m: float = 1.5 # tank depth | |
| initial_stocking_density: float = 50.0 # fish/m3 | |
| # Aeration | |
| # Real RAS: 2kW aerator × 1.8 SAE = 3.6 kg O2/h ÷ 100m³ tank = 36 mg/L/h | |
| # We cap at 20 to represent a well-sized but not over-engineered system | |
| max_aeration_rate: float = 20.0 # mg O2/L/h at full power (KB-02 Sec 4) | |
| aerator_SAE: float = 1.8 # kg O2/kWh standard aeration efficiency | |
| # Water exchange | |
| max_exchange_rate: float = 0.10 # fraction of volume per hour | |
| incoming_water_DO: float = 7.0 # mg/L (fresh water supply) | |
| incoming_water_temp: float = 28.0 | |
| incoming_water_TAN: float = 0.0 | |
| # Biofilter | |
| biofilter_volume_m3: float = 5.0 | |
| biofilter_VTR: float = 350.0 # g TAN/m3/d moving-bed reactor (KB-03 Sec 2.2) | |
| # Latitude for photoperiod (tropical) | |
| latitude: float = 10.0 # degrees N (tropical fish farm) | |
| # ---- Singleton instances ---- | |
| TILAPIA = TilapiaParams() | |
| WATER = WaterParams() | |
| DISEASE = DiseaseParams() | |
| ECONOMICS = EconomicsParams() | |
| SYSTEM = SystemParams() | |
| # ---- Utility functions ---- | |
| def uia_fraction(pH: float, temp_c: float) -> float: | |
| """Calculate fraction of TAN that is toxic unionized ammonia (NH3). | |
| Source: KB-01 Sec 3.2 | |
| Fraction NH3 = 1 / (1 + 10^(pKa - pH)) | |
| pKa = 0.09018 + 2729.92 / T_kelvin | |
| """ | |
| T_kelvin = temp_c + 273.15 | |
| pKa = 0.09018 + 2729.92 / T_kelvin | |
| fraction = 1.0 / (1.0 + 10.0 ** (pKa - pH)) | |
| return fraction | |
| def do_saturation(temp_c: float) -> float: | |
| """DO saturation concentration at given temperature (freshwater, sea level). | |
| Source: KB-03 Sec 2.1 | |
| DO_sat(T) = 468 / (31.6 + T) [approximate, mg/L] | |
| """ | |
| return 468.0 / (31.6 + temp_c) | |
| def photoperiod_hours(day_of_year: int, latitude: float = 10.0) -> float: | |
| """Calculate daylight hours from day of year and latitude. | |
| Source: KB-03 Sec 15.3 (photoperiod scalar pi = P_h / 12) | |
| """ | |
| declination = 23.45 * math.sin(math.radians(360 / 365 * (day_of_year - 81))) | |
| lat_rad = math.radians(latitude) | |
| dec_rad = math.radians(declination) | |
| cos_hour_angle = -math.tan(lat_rad) * math.tan(dec_rad) | |
| cos_hour_angle = max(-1.0, min(1.0, cos_hour_angle)) | |
| hour_angle = math.degrees(math.acos(cos_hour_angle)) | |
| return 2.0 * hour_angle / 15.0 | |
| def temperature_factor(T: float, T_min: float = TILAPIA.T_min, | |
| T_opt: float = TILAPIA.T_opt, | |
| T_max: float = TILAPIA.T_max) -> float: | |
| """Bell-shaped temperature response function tau(T). | |
| Source: KB-03 Sec 1.2 | |
| tau(T) = exp{-4.6 * ((T_opt - T) / (T_opt - T_min))^4} if T < T_opt | |
| tau(T) = exp{-4.6 * ((T - T_opt) / (T_max - T_opt))^4} if T >= T_opt | |
| """ | |
| if T <= T_min or T >= T_max: | |
| return 0.0 | |
| if T < T_opt: | |
| x = (T_opt - T) / (T_opt - T_min) | |
| else: | |
| x = (T - T_opt) / (T_max - T_opt) | |
| return math.exp(-4.6 * x ** 4) | |
| def do_factor(DO: float, DO_crit: float = WATER.DO_crit, | |
| DO_min: float = WATER.DO_min) -> float: | |
| """Piecewise linear DO response function sigma(DO). | |
| Source: KB-03 Sec 1.2 | |
| """ | |
| if DO >= DO_crit: | |
| return 1.0 | |
| elif DO >= DO_min: | |
| return (DO - DO_min) / (DO_crit - DO_min) | |
| else: | |
| return 0.0 | |
| def uia_factor(UIA: float, UIA_crit: float = WATER.UIA_crit, | |
| UIA_max: float = WATER.UIA_lethal) -> float: | |
| """Piecewise linear UIA response function v(UIA). | |
| Source: KB-03 Sec 1.2 | |
| """ | |
| if UIA <= UIA_crit: | |
| return 1.0 | |
| elif UIA <= UIA_max: | |
| return (UIA_max - UIA) / (UIA_max - UIA_crit) | |
| else: | |
| return 0.0 | |