├── images ├── Balance.PNG └── Greenhouse.PNG ├── MATLAB ├── sat_conc.m ├── climterp_linear.m ├── lamorturb.m ├── GESModel.m ├── PlotResults.m ├── parameters.m └── derivatives.m ├── LICENSE ├── README.md └── python ├── GES_Example.py ├── parameters.py └── functions.py /images/Balance.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EECi/GES/HEAD/images/Balance.PNG -------------------------------------------------------------------------------- /images/Greenhouse.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EECi/GES/HEAD/images/Greenhouse.PNG -------------------------------------------------------------------------------- /MATLAB/sat_conc.m: -------------------------------------------------------------------------------- 1 | function a = sat_conc(T) 2 | 3 | T = T - 273.15; 4 | 5 | spec_hum = exp(11.56 - 4030./(T + 235)); % Ratio of mass of water vapour to mass of dry air (ref?) 6 | air_dens = -0.0046*T + 1.2978; % Density of air [kg/m^3] 7 | a = spec_hum.*air_dens; % Density of water vapour [kg/m^3] 8 | 9 | end -------------------------------------------------------------------------------- /MATLAB/climterp_linear.m: -------------------------------------------------------------------------------- 1 | function climate=climterp_linear(deltaT) 2 | 3 | climate=zeros(2200000,25); 4 | 5 | %weather/radiation data 6 | climdat=csvread('SampleWeather.csv'); 7 | 8 | [l,w]=size(climdat); 9 | mult=linspace(1,l,(1+(l-1)*3600)/deltaT); 10 | 11 | for col=2:w 12 | new=interp1(climdat(:,1),climdat(:,col),mult); 13 | if (col==2) 14 | climate=new'; 15 | else 16 | climate=[climate new']; 17 | end 18 | end 19 | 20 | check_nonneg=climate(:,3:20)>=0; 21 | climate(:,3:20)=check_nonneg.*climate(:,3:20); 22 | 23 | save('climate.mat','climate'); 24 | 25 | end -------------------------------------------------------------------------------- /MATLAB/lamorturb.m: -------------------------------------------------------------------------------- 1 | function [Nu, varargout] = lamorturb(Gr, Re, varargin) 2 | 3 | % This function calculates the Nusselt number due to free and forced 4 | % convection, and then chooses the larger of the two. In each case the 5 | % convection may be laminar or turbulent, and this depends on the magnitude 6 | % of the Grashof and Reynolds number respectively. 7 | % 8 | % The dimensionless number Sh, used in computing the heat exchange due to 9 | % evaporation and condensastion of water, depends on the Lewis number of 10 | % air in a manner that depends on whether convection is free or forced. It 11 | % is treated as an optional argument. 12 | 13 | % Free convection, laminar or turbulent 14 | free = Gr < 1e5; 15 | Nu_G = 0.5*free.*Gr.^0.25 + 0.13*(1 - free).*Gr.^0.33; 16 | 17 | % Forced convection, laminar or turbulent 18 | forced = Re < 2e4; 19 | Nu_R = 0.6*forced.*Re.^0.5 + 0.032*(1 - forced).*Re.^0.8; 20 | 21 | % Calculating the larger of the two, and Sh 22 | x = Nu_G > Nu_R; 23 | Nu = x.*Nu_G + (1 - x).*Nu_R; 24 | 25 | if nargin == 3 26 | Le = varargin{1}; 27 | Sh = x.*Nu*Le^0.25 + (1 - x).*Nu*Le^0.33; 28 | varargout{1} = Sh; 29 | end 30 | 31 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Energy Efficient Cities Initiative, University of Cambridge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MATLAB/GESModel.m: -------------------------------------------------------------------------------- 1 | 2 | % ----------------------------------------------------------------------- 3 | % Greenhouse Energy Simulation model 4 | % Single zone greenhouse, unheated 5 | % ----------------------------------------------------------------------- 6 | 7 | clear; close all; 8 | 9 | parameters; % Read in all parameters for model from parameters.m 10 | 11 | global climate; 12 | 13 | % Interpolate weather data 14 | 15 | climate=climterp_linear(deltaT); % interpolates climate data 16 | 17 | tf = 86400*sim_days; 18 | tspan = [0, tf]; 19 | 20 | % Initialise data 21 | 22 | st = [20 + T_k % Temperature of cover 23 | 12 + T_k % Temperature of air 24 | 12 + T_k % Temperature of vegetation (instantaneous) 25 | 12 + T_k % Temperature of mat 26 | 12 + T_k % Temperature of tray 27 | 12 + T_k % Temperature of floor 28 | 12 + T_k % Temperature of soil Layer 1 29 | 12 + T_k % Temperature of soil Layer 2 30 | 12 + T_k % Temperature of soil Layer 3 31 | 11 + T_k % Temperature of soil Layer 4 32 | 12 + T_k % 24 hour mean temperature of vegetation 33 | 0 % Temperature sum 34 | climate(1,4)/100*sat_conc(climate(1,1) + T_k) % Density of water vapour 35 | (4e-4)*M_c*atm/(R*(climate(1,1) + T_k)) % Density of CO2 36 | 0.01 % Mass of carbohydrate per unit area of cultivated floor for buffer 37 | 0.001 % Mass of carbohydrate per unit area of cultivated floor for fruit 38 | 0.01 % Mass of carbohydrate per unit area of cultivated floor for leaves 39 | 0.01 % Mass of carbohydrate per unit area of cultivated floor for stem 40 | 0 % Relative growth rate 41 | 0 % Relative growth rate 42 | 0]; % Relative growth rate 43 | 44 | [t, T] = ode15s(@derivatives, tspan, st); 45 | out = [t, T]; 46 | save('out.mat', 'out'); 47 | 48 | x = 'complete'; 49 | 50 | -------------------------------------------------------------------------------- /MATLAB/PlotResults.m: -------------------------------------------------------------------------------- 1 | %% Plot Results 2 | 3 | clear; close all; 4 | 5 | parameters; 6 | load out; 7 | load climate; 8 | 9 | % Temperature 10 | figure('WindowStyle','docked'); 11 | dT=1/(24*60*60/deltaT); 12 | tplot=dT:dT:sim_days; 13 | [~,lenc]=size(tplot); 14 | 15 | subplot(3,1,1); 16 | plot(out(:,1)/(24*3600),(out(:,3)-273.15),'b'); 17 | hold on; 18 | plot(out(:,1)/(24*3600),(out(:,4)-273.15),'g--'); 19 | plot(tplot,climate(1:lenc,1),'k:') 20 | legend on; 21 | legend('Air','Plants','External'); 22 | title('Temperatures'); 23 | 24 | 25 | subplot(3,1,2) 26 | plot(out(:,1)/(24*3600),(out(:,2)-273.15),'b'); 27 | hold on; 28 | plot(out(:,1)/(24*3600),(out(:,7)-273.15),'c'); 29 | plot(out(:,1)/(24*3600),(out(:,8)-273.15),'r'); 30 | plot(out(:,1)/(24*3600),(out(:,9)-273.15),'r--'); 31 | plot(out(:,1)/(24*3600),(out(:,10)-273.15),'r-.'); 32 | plot(out(:,1)/(24*3600),(out(:,11)-273.15),'r:'); 33 | plot(tplot,climate(1:lenc,1),'k:') 34 | 35 | legend on; 36 | legend('Cover','Floor','Soil (1)','Soil(2)','Soil(3)','Soil(4)','External'); 37 | ylabel('Temperature(^oC)'); 38 | 39 | 40 | subplot(3,1,3) 41 | plot(out(:,1)/(24*3600),(out(:,5)-273.15),'m'); 42 | hold on; 43 | plot(out(:,1)/(24*3600),(out(:,6)-273.15),'b--'); 44 | plot(tplot,climate(1:lenc,1),'k:') 45 | legend on; 46 | legend('Mat','Tray','External'); 47 | xlabel('Day'); 48 | 49 | 50 | % Moisture content 51 | figure('WindowStyle','docked'); 52 | [len2,~]=size(climate); 53 | 54 | for ii=1:len2 55 | C_we(ii)=(climate(ii,4)/100)*sat_conc(climate(ii,1)+273.15); 56 | end 57 | 58 | plot(out(:,1)/(24*3600),out(:,14),'c'); 59 | hold on; 60 | 61 | plot(tplot,C_we(1:lenc),'k:'); 62 | 63 | legend('Simulation','External'); 64 | grid on; 65 | title('Air Moisture Content'); 66 | xlabel('Day'); 67 | ylabel('Air Moisture Content (kg/m^3)'); 68 | 69 | % RH 70 | figure('WindowStyle','docked'); 71 | 72 | for ii=1:len2 73 | RH(ii)=(climate(ii,4)/100); 74 | end 75 | 76 | plot(out(:,1)/(24*3600),(out(:,14)./sat_conc(out(:,3))),'c'); 77 | hold on; 78 | 79 | plot(tplot,RH(1:lenc),'k:'); 80 | 81 | legend('Simulation','External'); 82 | grid on; 83 | title('Relative Humidity'); 84 | xlabel('Day'); 85 | ylabel('Relative Humidity'); 86 | 87 | 88 | % CO2 89 | figure('WindowStyle','docked'); 90 | 91 | C_c=out(:,15).*out(:,3)*8.314/(0.044*1.013e5)*1e6; 92 | plot(out(:,1)/(24*3600),C_c,'c'); 93 | title('CO_2 concentration'); 94 | xlabel('Day'); 95 | ylabel('CO_2 concentration (ppm)'); 96 | 97 | % LAI 98 | figure('WindowStyle','docked'); 99 | 100 | C_leaf = out(:,18); 101 | C_fruit = out(:,17); 102 | C_stem = out(:,19); 103 | 104 | LAI = C_leaf*SLA; 105 | 106 | plot(out(:,1)/(24*3600),LAI,'g'); 107 | title('Leaf Area Index'); 108 | xlabel('Day'); 109 | ylabel('Leaf Area Index'); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GES 2 | Greenhouse Energy Simulation 3 | 4 | ## Introduction 5 | This code simulates heat, mass and CO2 exchange in an unheated, ventilated single-zone greenhouse for a simple test case. The heat transfer processes simulated include convection, conduction and radiation, together with plant transpiration for simulation of heat and mass exchange due to evaporation of water from the leaf surface. Simple models of photosynthesis and crop growth for tomatoes are included in order to simulate CO2 exchange. The model is based on the GDGCM (Pieters, J. and Deltour, J., 'The Gembloux Dynamic Greenhouse Climate Model - GDGCM', 2000 ) and on the thesis by Vanthoor (Vanthoor, B.H.,'A model-based greenhouse design method', PhD Thesis, Wageningen University, 2011). 6 | 7 | ## How to run model 8 | There are two versions included here, written in MATLAB and python3. 9 | 10 | For the MATLAB version, the files included here are as follows: 11 | 12 | * `GESModel.m` 13 | 14 | This is the main MATLAB file which initialises and calls the differential equation solver ode15s with derivatives.m. Using parameters.m and the weather data in SampleWeather.csv, running GESModel.m provides time histories of temperature, air moisture content and CO2 concentration. 15 | 16 | * `derivatives.m` 17 | 18 | Contains the governing heat, mass and CO2 balance equations for solution at each timestep 19 | 20 | * `parameters.m` 21 | 22 | Contains parameters for greenhouse and plant geometry and material properties 23 | 24 | * `climterp_linear.m` 25 | 26 | Sub-routine called by GESModel.m to interpolate weather data according to the timestep specified in parameters.m 27 | 28 | * `lamorturb.m` 29 | 30 | Sub-routine called by derivatives.m in order to calculate whether flow is laminar or turbulent for convection calculation 31 | 32 | * `sat_conc.m` 33 | 34 | Sub-routine which converts relative humidity into air moisture content. 35 | 36 | * `PlotResults.m` 37 | 38 | Routine for plotting time histories of temperature, moisture content, relative humidity and CO2 concentration output by GESModel.m 39 | 40 | * `SampleWeather.csv` 41 | 42 | Hourly input weather data, in the format 'Hour, Ambient Temperature (oC), Sky Temperature (oC), Windspeed (m/s), Relative Humidity (%), Direct Solar Radiation (order NE wall, NE Roof, SE Wall, SE Roof, SW Wall, SW Roof, NW Wall, NW Roof) (W/m2), Diffuse Solar Radiation (order as for Direct)(W/m2) 43 | 44 | The model has been run with MATLAB R2018a https://uk.mathworks.com/products/matlab.html 45 | 46 | The python version is similar except that the functions are all contained within the file `functions.py`, with parameter values in `parameters.py` which is called by the main file, `GES_Example.py`. 47 | 48 | ## Sample data 49 | The example given is a single zone unheated greenhouse, dimensions 10 x 25 x 5m with no artificial lighting or supplemental CO2, as illustrated. 50 | 51 | 52 | 53 | The heat, mass and CO2 exchanges are modelled as indicated. 54 | 55 | 56 | 57 | 58 | ## Project status 59 | 60 | This code is under development and has been modified for use in multi-zone, rooftop and underground greenhouses. More information can be found under the University of Cambridge Engineering Department Energy Efficient Cities initative website here: https://www.eeci.cam.ac.uk/research/greenhouse-energy-simulation 61 | 62 | ## Citation 63 | If using this code for development or research please cite as: 64 | 65 | [![DOI](https://zenodo.org/badge/171309394.svg)](https://zenodo.org/badge/latestdoi/171309394) 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /MATLAB/parameters.m: -------------------------------------------------------------------------------- 1 | %-------------------- 2 | %------ INPUTS ------ 3 | %-------------------- 4 | 5 | % CALCULATION CONTROL 6 | % =================== 7 | deltaT = 60; % time step size [s] 8 | sim_days = 364; % number of days to simulate [-] NB 2016 Leap Year 9 | Nz = 1; % number of zones [-] 10 | 11 | % CONSTANTS 12 | % ========= 13 | sigm = 5.67e-8; % Stefan-Boltzmann constant [W/m^2/K^4] 14 | T_k = 273.15; % zero celsius [K] 15 | g = 9.81; % acceleration due to gravity [m/s^2] 16 | atm = 1.013e5; % standard atmospheric pressure [Pa] 17 | latitude = 53.193583; % latitude of greenhouse 18 | longitude = -2.434920; % longitude of greenhouse 19 | N_A = 6.02214e+23; % Avogadro's number 20 | M_a = 0.029; % molar mass of dry air [kg/mol] 21 | lambda = 0.025; % thermal conductivity of air [W/m/K] 22 | c_i = 1003.2; % heat capacity of humid air [J/kg/K] 23 | H_fg = 2437000; % latent heat of condensation of water [J/kg] 24 | Le = 0.819; % Lewis number [-] 25 | R = 8.314; % gas constant [J/mol/K] 26 | M_w = 0.018; % molar mass of water [kg/mol] 27 | M_c = 0.044; % molar mass of CO2 [kg/mol] 28 | M_carb = 0.03; % molar mass of CH2O [kg/mol] 29 | nu = 15.1e-6; % kinematic viscosity [m^2/s] 30 | rho_w = 1000; % density of water [kg/m^3] 31 | 32 | % GEOMETRY 33 | % ======== 34 | A_f = 250; % greenhouse floor area [m^2] 35 | V = 1000; % greenhouse volume [m^3] 36 | % surface areas NE Wall NE Roof SE Wall SE Roof SW Wall SW Roof NW Wall NW Roof [m^2] 37 | SurfaceArea = [40 0 75 135 40 0 75 135]; 38 | A_c = sum(SurfaceArea, 2); % cover areas [m^2] 39 | a_obs = 0.05; % fraction of solar radiation hitting obstructions [-] 40 | H = 5; % Height of greenhouse 41 | 42 | % AIR CHARACTERISTICS 43 | % =================== 44 | int_air_speed = 0.5; % internal air speed [m/s] 45 | R_a_max = 30/3600; % ventilation air change rate [1/s] 46 | T_sp_vent = 25 + T_k; % Ventilation set-point 47 | 48 | % COVER 49 | % ===================== 50 | % Glass 51 | eps_ce = 0.85; % far-IR emissivity, outer surface [-] 52 | eps_ci = 0.85; % far-IR emissivity, inner surface [-] 53 | tau_c = 0.0; % far-IR transmissivity (0.0) [-] 54 | rho_ci = 0.15; % far-IR reflectivity, inner surface (0.1) [-] 55 | alph_c = 0.04; % solar absorptivity, taking 'perpendicular' values [-] 56 | tau_c_NIR = 0.85; % near-IR transmissivity of cover (0.84) [-] 57 | tau_c_VIS = 0.85; % visible transmissivity of cover [-] 58 | d_c = 1.5; % characteristic length of cover [m] 59 | cd_c = 8736; % cover heat capacity per unit area [J/m^2/K] 60 | 61 | % FLOOR 62 | % ===================== 63 | lam_s=[1.7 0.85 0.85 0.85 0.85]; %thermal conductivity of soil layers [W/mK] Concrete, Soil, Clay 64 | c_s=[880 1081 1081 1081 1081]; %specific heat of soil layers [J/kgK] 65 | l_s=[0.02 0.05 0.1 0.25 1.0]; %thickness of soil layers [m] 66 | rhod_s=[2300 1500 1600 1600 1600]; %density of soil layers [kg/m^3] 67 | rho_s=0.85; %far-IR reflectance of floor [-] 68 | eps_s=0.95; %far-IR emmittance of floor [-] 69 | rhoS_s=0.5; %solar reflectance of floor [-] 70 | alphS_s=0.5; %solar absorptance of floor [-] 71 | d_f=0.5; %characteristic floor length [m] 72 | T_ss = 14.0 + T_k; %deep soil temperature [K] 73 | 74 | % VEGETATION CHARACTERISTICS 75 | % ========================== 76 | c_v = 4180; % heat capacity of vegetation [J/kgK] 77 | k_l = 0.94; % long-wave extinction coefficient [-] 78 | rho_v = 0.22; % far-IR reflectivity of vegetation [-] 79 | eps_v = 0.95; % far-IR emissivity of vegetation [-] 80 | rhoS_v=0.35; %solar reflectance of vegetation [-] 81 | d_v = 0.1; % characteristic leaf length [m] 82 | p_v = 0.75; % cultivated fraction of floor 83 | msd_v = 1.326; % surface density [kg/m^2] 84 | 85 | % TRAY/MAT CHARACTERISTICS 86 | % ======================== 87 | A_p = p_v*A_f; % Area of cultivated floor [m^2] 88 | A_v = A_p; % Area of plants [m^2] 89 | A_m = A_p; % Area of mat for conduction to tray [m^2] 90 | d_p = 1; % characteristic dimension of tray (width) 91 | d_m = 0.1; % characteristic dimension of mat (width) 92 | lam_m = 0.5; % thermal conductivity of mat [W/mK] 93 | lam_p = 0.2; % thermal conductivity of plastic tray [W/mK] 94 | c_m = 45050; % specific heat of mat assumed 25% saturated [J/m^2K] 95 | c_p = 10020; % specific heat of tray [J/m^2K] 96 | l_m = 0.03; % thickness of mat [m] 97 | l_p = 0.005; % thickness of tray [m] 98 | rhod_m = 720; % density of mat [kg/m^3] 99 | rhod_p = 1200; % density of tray [kg/m^3] 100 | rho_m = 0.05; % far-IR reflectivity of mat [-] 101 | rho_p = 0.05; % far-IR reflectivity of tray 102 | eps_m = 0.95; % far-IR emissivity of mat [-] 103 | eps_p = 0.95; % far-IR emissivity of tray 104 | 105 | % PHOTOSYNTHESIS MODEL - VANTHOOR 106 | % =============================== 107 | c_Gamma = 1.7e-6; % effect of canopy temperature on CO2 compensation point [mol{CO2}/mol{air}/K] 108 | J_max_25 = 210e-6; % maximum rate of electron transport at 25 C [mol{e}/m^2{leaf}/s] 109 | alph = 0.385; % conversion factor from photons to electrons [mol{e}/mol{phot}] 110 | C_buf_max = 0.02; % maximum buffer capacity per unit area of cultivated floor [kg{CH2O}/m^2/s] 111 | theta = 0.7; % degree of curvature of the electron transport rate [-] 112 | S = 710; % entropy term for J_pot calculation [J/mol/K] 113 | HH = 22e4; % deactivation energy for J_pot calculation [J/mol] 114 | E_j = 37e3; % activation energy for J_pot calculation [J/mol] 115 | heat_phot = 3.6368e-19; % conversion rate from incident energy to number of photons [num{photons}/J] 116 | eta = 0.67; % conversion factor from CO2 in the air to CO2 in the stomata [-] 117 | s_airbuf_buf = 5e2; % differential switch function slope for maximum buffer capacity [m^2/kg] 118 | s_buforg_buf = -5e3; % differential switch function slope for minimum buffer capacity [m^2/kg] 119 | s_min_T = -0.8690; % differential switch function slope for minimum photosynthesis instantaneous temperature [1/degC] 120 | s_max_T = 0.5793; % differential switch function slope for maximum photosynthesis instantaneous temperature [1/degC] 121 | s_min_T24 = -1.1587; % differential switch function slope for minimum photosynthesis mean 24 hour temperature [1/degC] 122 | s_max_T24 = 1.3904; % differential switch function slope for maximum photosynthesis mean 24 hour temperature [1/degC] 123 | s_prune = -50; % differential switch function slope for leaf pruning [m^2/kg] 124 | 125 | % CROP GROWTH MODEL 126 | % =================== 127 | added_CO2 = 0; % mass of CO2 pumped in per hour [kg/h] (100) 128 | SLA = 26.6; % specific leaf area index [m^2{leaf}/kg{CH2O}] 129 | LAI_max = 5; % the maximum allowed leaf area index [m^2{leaf}/m^2{floor}] 130 | Q_10 = 2; % see parameters for de Zwart model above [-] 131 | rg_fruit = 0.328e-6; % potential fruit growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 132 | rg_leaf = 0.095e-6; % potential leaf growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 133 | rg_stem = 0.074e-6; % potential stem growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 134 | c_fruit_g = 0.27; % fruit growth respiration coefficient [-] 135 | c_fruit_m = 1.16e-7; % fruit maintenance respiration coefficient [1/s] 136 | c_leaf_g = 0.28; % leaf growth respiration coefficient [-] 137 | c_leaf_m = 3.47e-7; % leaf maintenance respiration coefficient [1/s] 138 | c_stem_g = 0.30; % stem growth respiration coefficient [-] 139 | c_stem_m = 1.47e-7; % stem maintenance respiration coefficient [1/s] 140 | c_RGR = 2.85e6; % regression coefficient in maintenance respiration function [s] 141 | T_min_v24 = 12 ; % between base temperature and first optimal temperature for 24 hour mean [oC] 142 | T_max_v24 = 27 ; % between second optimal temperature and maximum temperature for 24 hour mean [oC] 143 | T_min_v = 6 ; % between base temperature and first optimal temperature [oC] 144 | T_max_v = 40 ; % between second optimal temperature and maximum temperature [oC] 145 | T_sum_end = 1035; % the temperature sum at which point the fruit growth rate is maximal [oC] 146 | 147 | 148 | % PARAMETERS FOR INFILTRATION CALCULATION 149 | % ======================================= 150 | c = 0.35; % terrain factor, see Awbi, Chapter 3, Table 3.2 151 | a = 0.25; % terrain factor, see Awbi, Chapter 3, Table 3.2 152 | Cp = 0.62; % static pressure coefficient - for wind perpendicular to gap 153 | Cd = 0.61; % sharp edge orifice, see Awbi 154 | crack_length = 1; % typical estimate 155 | crack_width = 0.001; % typical estimate 156 | crack_area = crack_length*crack_width; 157 | crack_length_total = 350; % -------------------------------------------------------------------------------- /python/GES_Example.py: -------------------------------------------------------------------------------- 1 | ####################################################################################################################################### 2 | ## GES: Greenhouse Energy Simulation 3 | 4 | # This python3 code simulates heat, mass and CO$_2$ exchange in an unheated, ventilated single-zone greenhouse for a simple test case. 5 | # The heat transfer processes simulated include convection, conduction and radiation, together with plant transpiration for simulation 6 | # of heat and mass exchange due to evaporation of water from the leaf surface. 7 | # Simple models of photosynthesis and crop growth for tomatoes are included in order to simulate CO_2 exchange. 8 | # The model is based on the GDGCM (Pieters, J. and Deltour, J., 'The Gembloux Dynamic Greenhouse Climate Model - GDGCM', 2000) 9 | # and on the thesis by Vanthoor (Vanthoor, B.H.,'A model-based greenhouse design method', PhD Thesis, Wageningen University, 2011). 10 | 11 | # The original code was written in MATLAB and can be found on GitHub at https://github.com/EECi/GES. 12 | 13 | # The files required include: 14 | 15 | # functions.py 16 | # contains generic functions for convection, radiation and conduction calculations, climate data interpolation and calculation of 17 | # relative humidity 18 | # parameters.py 19 | # contains parameter values for fundamental constants, greenhouse construction and operation and plant geometry and growth. 20 | # SampleWeather.csv 21 | # Hourly input weather data, in the format 'Hour, Ambient Temperature ($^o$C), Sky Temperature ($^o$C), Windspeed (m/s), 22 | # Relative Humidity (%), Direct Solar Radiation (order NE wall, NE Roof, SE Wall, SE Roof, SW Wall, SW Roof, NW Wall, NW Roof) 23 | # (W/m$^2$), Diffuse Solar Radiation (order as for Direct)(W/m$^2$) 24 | 25 | ####################################################################################################################################### 26 | 27 | ## Initialise 28 | 29 | import numpy as np 30 | import matplotlib.pyplot as plt 31 | from functions import sat_conc, model 32 | from scipy.integrate import solve_ivp 33 | from scipy.interpolate import interp1d 34 | import time 35 | 36 | from parameters import * 37 | 38 | ## Specify initial conditions** 39 | 40 | # Temperatures 41 | T_c_0 = 20. + T_k # Cover temperature [K] 42 | T_i_0 = 12. + T_k # Internal air temperature [K] 43 | T_v_0 = 12. + T_k # Vegetation temperature [K] 44 | T_m_0 = 12. + T_k # Growing medium temperature [K] 45 | T_p_0 = 12. + T_k # Tray temperature [K] 46 | T_f_0 = 12. + T_k # Floor temperature [K] 47 | T_s1_0 = 12. + T_k # Temperature of soil layer 1 [K] 48 | T_s2_0 = 12. + T_k # Temperature of soil layer 2 [K] 49 | T_s3_0 = 12. + T_k # Temperature of soil layer 3 [K] 50 | T_s4_0 = 11. + T_k # Temperature of soil layer 4 [K] 51 | # 52 | T_vmean_0 = 12. + T_k; # 24 hour mean vegetation temperature [K] 53 | T_vsum_0 = 0; # Vegetation temperature sum [degC] 54 | # 55 | C_w_0 = 0.0085 # Density of water vapour [kg/m^3] 56 | C_c_0 = 7.5869e-4 # CO_2 density 57 | # 58 | C_buf_0 = 0.01 # Mass of carbohydrate in buffer per unit per unit area of cultivated floor [kg/m^2] 59 | C_fruit_0 = 0.001 # Mass of carbohydrate in fruit per unit per unit area of cultivated floor [kg/m^2] 60 | C_leaf_0 = 0.01 # Mass of carbohydrate in leaves per unit per unit area of cultivated floor [kg/m^2] 61 | C_stem_0 = 0.01 # Mass of carbohydrate in stem per unit per unit area of cultivated floor [kg/m^2] 62 | R_fruit_0 = 0. # Relative growth rate of fruit averaged over 5 days [1/s] 63 | R_leaf_0 = 0. # Relative growth rate of leaf averaged over 5 days [1/s] 64 | R_stem_0 = 0. # Relative growth rate of stem averaged over 5 days [1/s] 65 | 66 | z = [T_c_0, T_i_0, T_v_0, T_m_0, T_p_0, T_f_0, T_s1_0, T_s2_0, T_s3_0, T_s4_0, T_vmean_0, T_vsum_0, 67 | C_w_0, C_c_0, C_buf_0, C_fruit_0, C_leaf_0, C_stem_0, R_fruit_0, R_leaf_0, R_stem_0] 68 | 69 | daynum = [0] 70 | 71 | ## Interpolate weather data 72 | 73 | climdat = np.genfromtxt('SampleWeather.csv', delimiter=',') # Hourly data 74 | 75 | l=len(climdat) 76 | mult=np.linspace(1,l,int((l-1)*3600/deltaT)) 77 | y_interp = interp1d(climdat[:,0], climdat[:,1:21],axis=0) 78 | 79 | climate = y_interp(mult) 80 | 81 | ## Simulate over time 82 | 83 | tic = time.time() 84 | 85 | sim_days = 364 # Number of days of simulation 86 | tf = 86400*sim_days # Time in seconds 87 | t = [0,tf] 88 | tval = np.linspace(0,tf,tf+1) 89 | 90 | # Use solve_ivp with 'BDF' stiff solver to solve the ODEs 91 | params = [climate, daynum] 92 | 93 | output = solve_ivp(model, t, z, method='BDF', t_eval=tval, rtol = 1e-5, args=params) 94 | 95 | # Time simulation and print time taken 96 | toc = time.time() 97 | 98 | xt = toc-tic 99 | 100 | print('Runtime(s) = ', f"{xt:.3}") 101 | 102 | ####################################################################################################################################### 103 | ## Plot results 104 | 105 | print('Plotting results ...') 106 | 107 | Tout_c = np.transpose(output.y[0,:]-T_k) 108 | Tout_i = np.transpose(output.y[1,:]-T_k) 109 | Tout_v = np.transpose(output.y[2,:]-T_k) 110 | Tout_m = np.transpose(output.y[3,:]-T_k) 111 | Tout_p = np.transpose(output.y[4,:]-T_k) 112 | Tout_f = np.transpose(output.y[5,:]-T_k) 113 | Tout_s1 = np.transpose(output.y[6,:]-T_k) 114 | Tout_s2 = np.transpose(output.y[7,:]-T_k) 115 | Tout_s3 = np.transpose(output.y[8,:]-T_k) 116 | Tout_s4 = np.transpose(output.y[9,:]-T_k) 117 | 118 | Tvmeanout = np.transpose(output.y[10,:]) 119 | Tvsumout = np.transpose(output.y[11,:]) 120 | 121 | Cwout = np.transpose(output.y[12,:]) 122 | Ccout = np.transpose(output.y[13,:]) 123 | 124 | C_buf = np.transpose(output.y[14,:]) 125 | C_fruit = np.transpose(output.y[15,:]) 126 | C_leaf = np.transpose(output.y[16,:]) 127 | C_stem = np.transpose(output.y[17,:]) 128 | 129 | Rfruitout = np.transpose(output.y[18,:]) 130 | Rleafout = np.transpose(output.y[19,:]) 131 | Rstemout = np.transpose(output.y[20,:]) 132 | 133 | #Temperatures 134 | 135 | time = output.t/(3600*24) # Time in days 136 | resolution_value = 1200 137 | 138 | # Internal air, vegetation 139 | 140 | fig1, ax = plt.subplots() 141 | 142 | ax.plot(time,Tout_i, color='b', label = 'Internal air') 143 | ax.plot(time,Tout_v, color='g', linestyle = ':', label = 'Vegetation') 144 | ax.set_title('Internal air and vegetation temperatures') 145 | ax.legend(loc='upper right', fontsize=8) 146 | 147 | ax.set_xlabel('Day') 148 | ax.set_ylabel('Temperature ($^o$C)') 149 | 150 | plt.savefig('Temperature1.png', format="png", dpi=resolution_value) 151 | 152 | # Mat, tray, vegetation 153 | 154 | fig2, ax2 = plt.subplots() 155 | 156 | ax2.plot(time,Tout_m, color='brown', linestyle = '-', label = 'Mat') 157 | ax2.plot(time,Tout_p, color='k', linestyle = '--', label = 'Tray') 158 | ax2.plot(time,Tout_v, color='g', linestyle = ':', label = 'Vegetation') 159 | 160 | 161 | ax2.set_title('Vegetation, mat and tray temperatures') 162 | ax2.legend(loc='upper right', fontsize=8) 163 | 164 | ax2.set_xlabel('Day') 165 | ax2.set_ylabel('Temperature ($^o$C)') 166 | 167 | plt.savefig('Temperature2.png', format="png", dpi=resolution_value) 168 | 169 | # Cover, floor, Soil layer 1, soil layer 4 170 | 171 | fig3, ax1 = plt.subplots() 172 | 173 | ax1.plot(time,Tout_c, color='b', label = 'Cover') 174 | ax1.plot(time,Tout_f, color='g', linestyle = '--', label = 'Floor') 175 | ax1.plot(time,Tout_s1, color='brown', linestyle = ':', label = 'Soil layer 1') 176 | ax1.plot(time,Tout_s4,color='k',linestyle='-.', label = 'Soil layer 4') 177 | 178 | ax1.set_title('Cover, floor and soil temperatures') 179 | ax1.legend(loc='upper right', fontsize=8) 180 | 181 | ax1.set_xlabel('Day') 182 | ax1.set_ylabel('Temperature ($^o$C)') 183 | 184 | plt.savefig('Temperature3.png', format="png", dpi=resolution_value) 185 | 186 | # LAI 187 | 188 | fig4, ax3 = plt.subplots() 189 | 190 | LAI = C_leaf * SLA 191 | 192 | ax3.plot(time,LAI, color='g') 193 | ax3.set_title('Leaf Area Index') 194 | ax3.set_xlabel('Day') 195 | ax3.set_ylabel('LAI') 196 | 197 | plt.savefig('LAI.png', format="png", dpi=resolution_value) 198 | 199 | # Relative Humidity 200 | 201 | RHout = 100*Cwout/sat_conc(Tout_i+T_k) 202 | 203 | fig5, ax5 = plt.subplots() 204 | ax5.plot(time,RHout, color='b') 205 | ax5.set_title('Relative Humidity') 206 | ax5.set_xlabel('Day') 207 | ax5.set_ylabel('Relativce Humidity (%)') 208 | 209 | plt.savefig('RH.png', format="png", dpi=resolution_value) 210 | 211 | # CO_2 212 | 213 | Ccout_ppm = Ccout*R*(Tout_i+T_k)/(M_c*atm)*1.e6 214 | 215 | fig6, ax4 = plt.subplots() 216 | ax4.plot(time,Ccout_ppm, color='b') 217 | ax4.set_title('CO$_2$') 218 | ax4.set_xlabel('Day') 219 | ax4.set_ylabel('CO$_2$ (ppm)') 220 | 221 | plt.savefig('CO2.png', format="png", dpi=resolution_value) 222 | 223 | # Show plots before code completion 224 | 225 | #plt.show() 226 | 227 | 228 | -------------------------------------------------------------------------------- /python/parameters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Feb 16 10:35:04 2021 4 | 5 | @author: rmw61 6 | """ 7 | 8 | import numpy as np 9 | 10 | Nz = 1. 11 | deltaT = 60 # s 12 | 13 | # Constants 14 | sigm = 5.67e-8 # Stefan-Boltzmann constant [W/m^2/K^4] 15 | T_k = 273.15 # zero celsius [K] 16 | g = 9.81 # acceleration due to gravity [m/s^2] 17 | atm = 1.013e5 # standard atmospheric pressure [Pa] 18 | latitude = 53.193583 # latitude of greenhouse 19 | longitude = -2.434920 # longitude of greenhouse 20 | N_A = 6.02214e+23 # Avogadro's number 21 | M_a = 0.029 # molar mass of dry air [kg/mol] 22 | lam = 0.025 # thermal conductivity of air [W/m/K] 23 | c_i = 1003.2 # heat capacity of humid air [J/kg/K] 24 | H_fg = 2437000. # latent heat of condensation of water [J/kg] 25 | Le = 0.819 # Lewis number [-] 26 | R = 8.314 # gas constant [J/mol/K] 27 | M_w = 0.018 # molar mass of water [kg/mol] 28 | M_c = 0.044 # molar mass of CO2 [kg/mol] 29 | M_carb = 0.03 # molar mass of CH2O [kg/mol] 30 | nu = 15.1e-6 # kinematic viscosity [m^2/s] 31 | rho_w = 1000. # density of water [kg/m^3] 32 | 33 | # Geometry 34 | A_f = 250. # greenhouse floor area [m^2] 35 | V = 1000. # greenhouse volume [m^3] 36 | # surface areas NE Wall NE Roof SE Wall SE Roof SW Wall SW Roof NW Wall NW Roof [m^2] 37 | SurfaceArea = np.array([40., 0., 75., 135., 40., 0., 75., 135.]) 38 | A_c = np.sum(SurfaceArea) 39 | a_obs = 0.05 # fraction of solar radiation hitting obstructions [-] 40 | H = 5. # Height of greenhouse [m] 41 | A_c_roof = 271. # Area of roof 42 | 43 | # Air characteristics 44 | ias = 0.5 # internal air speed [m/s] 45 | R_a_max = 30./3600. # ventilation air change rate [1/s] 46 | T_sp_vent = 25. + T_k # Ventilation set-point 47 | 48 | # Cover 49 | # Glass 50 | eps_ce = 0.85 # far-IR emissivity, outer surface [-] 51 | eps_ci = 0.85 # far-IR emissivity, inner surface [-] 52 | tau_c = 0.0 # far-IR transmissivity (0.0) [-] 53 | rho_ci = 0.15 # far-IR reflectivity, inner surface (0.1) [-] 54 | alph_c = 0.04 # solar absorptivity, taking 'perpendicular' values [-] 55 | tau_c_NIR = 0.85 # near-IR transmissivity of cover (0.84) [-] 56 | tau_c_VIS = 0.85 # visible transmissivity of cover [-] 57 | d_c = 1.5 # characteristic length of cover [m] 58 | cd_c = 8736. # cover heat capacity per unit area [J/m^2/K] 59 | 60 | # Floor 61 | lam_s = [1.7, 0.85, 0.85, 0.85, 0.85] # thermal conductivity of soil layers [W/mK] Concrete, Soil, Clay 62 | c_s = [880., 1081., 1081., 1081., 1081.] # specific heat of soil layers [J/kgK] 63 | l_s = [0.02, 0.05, 0.1, 0.25, 1.0] # thickness of soil layers [m] 64 | rhod_s = [2300., 1500., 1600., 1600., 1600.] # density of soil layers [kg/m^3] 65 | rho_s = 0.85 # far-IR reflectance of floor [-] 66 | eps_s = 0.95 # far-IR emmittance of floor [-] 67 | rhoS_s = 0.5 # solar reflectance of floor [-] 68 | alphS_s = 0.5 # solar absorptance of floor [-] 69 | d_f = 0.5 # characteristic floor length [m] 70 | T_ss = 14.0 + T_k # deep soil temperature [K] 71 | 72 | # Vegetation 73 | c_v = 4180. # heat capacity of vegetation [J/kgK] 74 | k_l = 0.94 # long-wave extinction coefficient [-] 75 | rho_v = 0.22 # far-IR reflectivity of vegetation [-] 76 | eps_v = 0.95 # far-IR emissivity of vegetation [-] 77 | rhoS_v=0.35 # solar reflectance of vegetation [-] 78 | d_v = 0.1 # characteristic leaf length [m] 79 | p_v = 0.75 # cultivated fraction of floor 80 | msd_v = 1.326 # surface density [kg/m^2] 81 | 82 | # Tray/mat 83 | A_p = p_v*A_f # Area of cultivated floor [m^2] 84 | A_v = A_p # Area of plants [m^2] 85 | A_m = A_p # Area of mat for conduction to tray [m^2] 86 | d_p = 1. # characteristic dimension of tray (width) 87 | d_m = 0.1 # characteristic dimension of mat (width) 88 | lam_m = 0.5 # thermal conductivity of mat [W/mK] 89 | lam_p = 0.2 # thermal conductivity of plastic tray [W/mK] 90 | c_m = 45050. # specific heat of mat assumed 25% saturated [J/m^2K] 91 | c_p = 10020. # specific heat of tray [J/m^2K] 92 | l_m = 0.03 # thickness of mat [m] 93 | l_p = 0.005 # thickness of tray [m] 94 | rhod_m = 720. # density of mat [kg/m^3] 95 | rhod_p = 1200. # density of tray [kg/m^3] 96 | rho_m = 0.05 # far-IR reflectivity of mat [-] 97 | rho_p = 0.05 # far-IR reflectivity of tray 98 | eps_m = 0.95 # far-IR emissivity of mat [-] 99 | eps_p = 0.95 # far-IR emissivity of tray 100 | 101 | # Photosynthesis model - Vanthoor 102 | c_Gamma = 1.7e-6 # effect of canopy temperature on CO2 compensation point [mol{CO2}/mol{air}/K] 103 | J_max_25 = 210e-6 # maximum rate of electron transport at 25 C [mol{e}/m^2{leaf}/s] 104 | alph = 0.385 # conversion factor from photons to electrons [mol{e}/mol{phot}] 105 | C_buf_max = 0.02 # maximum buffer capacity per unit area of cultivated floor [kg{CH2O}/m^2/s] 106 | theta = 0.7 # degree of curvature of the electron transport rate [-] 107 | S = 710. # entropy term for J_pot calculation [J/mol/K] 108 | HH = 22.e4# deactivation energy for J_pot calculation [J/mol] 109 | E_j = 37.e3 # activation energy for J_pot calculation [J/mol] 110 | heat_phot = 3.6368e-19 # conversion rate from incident energy to number of photons [num{photons}/J] 111 | eta = 0.67 # conversion factor from CO2 in the air to CO2 in the stomata [-] 112 | s_airbuf_buf = 5.e2 # differential switch function slope for maximum buffer capacity [m^2/kg] 113 | s_buforg_buf = -5.e3 # differential switch function slope for minimum buffer capacity [m^2/kg] 114 | s_min_T = -0.8690 # differential switch function slope for minimum photosynthesis instantaneous temperature [1/degC] 115 | s_max_T = 0.5793 # differential switch function slope for maximum photosynthesis instantaneous temperature [1/degC] 116 | s_min_T24 = -1.1587 # differential switch function slope for minimum photosynthesis mean 24 hour temperature [1/degC] 117 | s_max_T24 = 1.3904 # differential switch function slope for maximum photosynthesis mean 24 hour temperature [1/degC] 118 | s_prune = -50. # differential switch function slope for leaf pruning [m^2/kg] 119 | 120 | # Crop Growth Model 121 | added_CO2 = 0. # mass of CO2 pumped in per hour [kg/h] (100) 122 | SLA = 26.6 # specific leaf area index [m^2{leaf}/kg{CH2O}] 123 | LAI_max = 5. # the maximum allowed leaf area index [m^2{leaf}/m^2{floor}] 124 | Q_10 = 2. # see parameters for de Zwart model above [-] 125 | rg_fruit = 0.328e-6 # potential fruit growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 126 | rg_leaf = 0.095e-6 # potential leaf growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 127 | rg_stem = 0.074e-6 # potential stem growth rate coefficient at 20 deg C [kg{CH2O}/m^2/s] 128 | c_fruit_g = 0.27 # fruit growth respiration coefficient [-] 129 | c_fruit_m = 1.16e-7 # fruit maintenance respiration coefficient [1/s] 130 | c_leaf_g = 0.28 # leaf growth respiration coefficient [-] 131 | c_leaf_m = 3.47e-7 # leaf maintenance respiration coefficient [1/s] 132 | c_stem_g = 0.30 # stem growth respiration coefficient [-] 133 | c_stem_m = 1.47e-7 # stem maintenance respiration coefficient [1/s] 134 | c_RGR = 2.85e6 # regression coefficient in maintenance respiration function [s] 135 | T_min_v24 = 12. # between base temperature and first optimal temperature for 24 hour mean [oC] 136 | T_max_v24 = 27. # between second optimal temperature and maximum temperature for 24 hour mean [oC] 137 | T_min_v = 6. # between base temperature and first optimal temperature [oC] 138 | T_max_v = 40. # between second optimal temperature and maximum temperature [oC] 139 | T_sum_end = 1035. # the temperature sum at which point the fruit growth rate is maximal [oC] 140 | 141 | 142 | # Infiltration 143 | c = 0.35 # terrain factor, see Awbi, Chapter 3, Table 3.2 144 | a = 0.25 # terrain factor, see Awbi, Chapter 3, Table 3.2 145 | Cp = 0.62 # static pressure coefficient - for wind perpendicular to gap 146 | Cd = 0.61 # sharp edge orifice, see Awbi 147 | crack_length = 1. # typical estimate 148 | crack_width = 0.001 # typical estimate 149 | crack_area = crack_length*crack_width 150 | crack_length_total = 350. 151 | 152 | # View Factors 153 | F_f_c = 1-p_v # Floor to cover 154 | F_f_p = p_v # Floor to tray 155 | F_c_f = A_f/A_c_roof*F_f_c # Cover to floor 156 | #F_c_v = min((1-F_c_f)*LAI,(1-F_c_f)) # Cover to vegetation 157 | #F_c_m = max((1-F_c_f)*(1-LAI),0) # Cover to mat 158 | F_v_c = 0.5 # Vegetation to cover 159 | F_v_m = 0.5 # Vegetation to mat 160 | F_v_p = 0. # Vegetation to tray 161 | #F_m_c = max((1-LAI),0.0) # Mat to cover 162 | #F_m_v = 1-F_m_c # Mat to vegetation 163 | F_m_p = 0. # Mat to tray 164 | F_p_v = 0. # Tray to vegetation 165 | F_p_m = 0. # Tray to mat 166 | F_p_f = 1.0 # Tray to floor 167 | 168 | dict = {'g':g, 'd_c':d_c, 'd_f':d_f, 'nu':nu, 'ias':ias, 'A_c':A_c, 'A_f':A_f, 'V':V, 'lam':lam, 169 | 'cd_c':cd_c, 'R':R, 'atm':atm, 'M_w':M_w, 'M_a':M_a, 'H_fg':H_fg, 'c_i':c_i} 170 | 171 | np.save('parameters.npy',dict) 172 | -------------------------------------------------------------------------------- /python/functions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Feb 16 09:18:07 2021 4 | 5 | @author: rmw61 6 | """ 7 | import numpy as np 8 | from parameters import * 9 | 10 | def lamorturb(Gr, Re): 11 | 12 | free = Gr < 1e5 13 | Nu_G = 0.5 * free * Gr**0.25 + 0.13*(1-free)*Gr**0.33 14 | 15 | forced = Re < 2e4 16 | Nu_R = 0.6*forced*Re**0.5 + 0.032*(1-forced)*Re**0.8 17 | 18 | x = Nu_G > Nu_R 19 | 20 | Nu = x*Nu_G + (1-x)*Nu_R 21 | 22 | Sh = x*Nu*Le**0.25 + (1-x)*Nu*Le**0.33 23 | 24 | return(Nu, Sh) 25 | 26 | def convection(d, A, T1, T2, ias, rho, c, C): 27 | 28 | g = 9.81 29 | nu = 15.1e-6 30 | lam = 0.025 31 | 32 | Gr = (g*d**3)/(T1*nu**2)*abs(T1 - T2) 33 | Re = ias*d/nu 34 | (Nu, Sh) = lamorturb(Gr,Re) 35 | 36 | QV_1_2 = A*Nu*lam*(T1-T2)/d 37 | QP_1_2 = A*H_fg/(rho*c)*Sh/Le*lam/d*(C - sat_conc(T2)) 38 | #QP_1_2 = 0 39 | 40 | return(QV_1_2, QP_1_2, Nu) 41 | 42 | def radiation(eps_1, eps_2, rho_1, rho_2, F_1_2, F_2_1, A_1, T_1, T_2): 43 | 44 | sigm = 5.67e-8 45 | 46 | k = eps_1*eps_2/(1-rho_1*rho_2*F_1_2*F_2_1) 47 | QR_1_2 = k*sigm*A_1*F_1_2*(T_1**4 - T_2**4) 48 | 49 | return(QR_1_2) 50 | 51 | def conduction(A, lam, l, T1, T2): 52 | QD_12 = (A*lam/l)*(T1-T2) 53 | 54 | return(QD_12) 55 | 56 | def T_ext(t): 57 | # Weather data 58 | 59 | climate = np.genfromtxt('climate.txt', delimiter=',') 60 | 61 | deltaT = 600 62 | n = int(np.ceil(t/deltaT)) 63 | T_e = climate[n, 0] + T_k 64 | 65 | return(T_e) 66 | 67 | def sat_conc(T): 68 | 69 | TC = T - T_k 70 | spec_hum = np.exp(11.56 - 4030/(TC + 235)) 71 | air_dens = -0.0046*TC + 1.2978 72 | a = spec_hum*air_dens 73 | 74 | return a 75 | 76 | def Cw_ext(t): 77 | # Weather data 78 | 79 | climate = np.genfromtxt('climate.txt', delimiter=',') 80 | 81 | deltaT = 600 82 | n = int(np.ceil(t/deltaT)) 83 | RH_e = climate[n, 1]/100; 84 | 85 | Cw_e = RH_e * sat_conc(T_ext(t)) 86 | 87 | return(Cw_e) 88 | 89 | def day(t): 90 | ## Day 91 | day_new = np.ceil(t/86400) 92 | return(day_new) 93 | 94 | def model(t,z, climate, daynum): 95 | 96 | # Values being calculated 97 | 98 | T_c = z[0] 99 | T_i = z[1] 100 | T_v = z[2] 101 | T_m = z[3] 102 | T_p = z[4] 103 | T_f = z[5] 104 | T_s1 = z[6] 105 | T_s2 = z[7] 106 | T_s3 = z[8] 107 | T_s4 = z[9] 108 | T_vmean = z[10] 109 | T_vsum = z[11] 110 | C_w = z[12] 111 | C_c = z[13] 112 | C_buf = z[14] 113 | C_fruit = z[15] 114 | C_leaf = z[16] 115 | C_stem = z[17] 116 | R_fruit = z[18] 117 | R_leaf = z[19] 118 | R_stem = z[20] 119 | 120 | # External weather and dependent internal parameter values 121 | n = int(np.ceil(t/deltaT)) # count 122 | T_ext = climate[n, 0] + T_k # External air temperature (K) 123 | T_sk = climate[n, 1] + T_k # External sky temperature (K) 124 | wind_speed = climate[n, 2] # External wind speed (m/s) 125 | RH_e = climate[n, 3]/100 # External relative humidity 126 | Cw_ext = RH_e * sat_conc(T_ext) # External air moisture content 127 | p_w = C_w*R*T_i/M_w # Partial pressure of water [Pa] 128 | rho_i = ((atm - p_w)*M_a + p_w*M_w)/(R*T_i) # Internal density of air [kg/m^3] 129 | LAI = SLA*C_leaf # Leaf area index 130 | C_ce = 4.0e-4*M_c*atm/(R*T_ext) # External carbon dioxide concentration [kg/m^3] 131 | C_c_ppm = C_c*R*T_i/(M_c*atm)*1.e6 # External carbon dioxide concentration [ppm] 132 | 133 | daynum.append(day(t)) # Day number 134 | 135 | # Option for printing progress of run in days - uncomment out if needed 136 | if daynum[(len(daynum)-1)] > daynum[(len(daynum)-2)]: 137 | print('Day', daynum[len(daynum)-1]) 138 | 139 | hour = np.floor(t/3600) + 1 140 | # Option for printing progress in hours - uncomment if needed 141 | #print('Hour', hour) 142 | 143 | day_hour=(hour/24-np.floor(hour/24))*24 144 | 145 | ## Lights 146 | L_on = 0 # No additional lighting included 147 | AL_on = 0 # No ambient lighting included 148 | 149 | ## Convection 150 | # Convection external air -> cover 151 | 152 | (QV_e_c, QP_e_c, Nu_e_c ) = convection(d_c, A_c, T_ext, T_c, wind_speed, rho_i, c_i, C_w) 153 | QP_e_c = 0 # Assumed no external condensation/evaporation 154 | 155 | # Convection internal air -> cover 156 | 157 | (QV_i_c, QP_i_c, Nu_i_c) = convection(d_c, A_c, T_i, T_c, ias, rho_i, c_i, C_w) 158 | QP_i_c = max(QP_i_c,0) # assumed no evaporation from the cover, only condensation 159 | 160 | # Convection internal air -> floor 161 | 162 | (QV_i_f, QP_i_f, Nu_i_f) = convection(d_f, A_f, T_i, T_f, ias, rho_i, c_i, C_w) 163 | QP_i_f = max(QP_i_f,0) # assumed no evaporation from the floor, only condensation 164 | 165 | # Convection internal air -> vegetation 166 | A_v_exp = LAI*A_v 167 | (QV_i_v, QP_i_v, Nu_i_v) = convection(d_v, A_v_exp, T_i, T_v, ias, rho_i, c_i, C_w) 168 | QP_i_v = 0 # No condensation/evaporation - transpiration considered separately 169 | HV = Nu_i_v*lam/d_v 170 | 171 | # Convection internal air -> mat 172 | A_m_wool = 0.75*A_m # Area of mat exposed 173 | A_m_water = 0.25*A_m # assumed 25% saturated 174 | 175 | (QV_i_m, QP_i_m, Nu_i_m) = convection(d_m, A_m_wool, T_i, T_m, ias, rho_i, c_i, C_w) 176 | 177 | QP_i_m = A_m_water/A_m_wool * QP_i_m # Factored down 178 | 179 | # Convection internal air -> tray 180 | (QV_i_p, QP_i_p, Nu_i_p) = convection(d_p, A_p, T_i, T_p, ias, rho_i, c_i, C_w) 181 | QP_i_p = 0 # Assumed no condensation/evaporation from tray 182 | 183 | ## Far-IR Radiation 184 | 185 | A_vvf=min(LAI*p_v*A_f,p_v*A_f) 186 | F_c_v = min((1-F_c_f)*LAI,(1-F_c_f)) # Cover to vegetation 187 | F_c_m = max((1-F_c_f)*(1-LAI),0) # Cover to mat 188 | F_m_c = max((1-LAI),0.0) # Mat to cover 189 | F_m_v = 1-F_m_c # Mat to vegetation 190 | 191 | # Cover to sky 192 | QR_c_sk = radiation(eps_ce, 1, 0, 0, 1, 0, A_c, T_c, T_sk) 193 | 194 | # Radiation cover to floor 195 | QR_c_f = radiation(eps_ci, eps_s, rho_ci, rho_s, F_c_f, F_f_c, A_c_roof, T_c, T_f) 196 | 197 | # Radiation cover to vegetation 198 | QR_c_v = radiation(eps_ci, eps_v, rho_ci, rho_v, F_c_v, F_v_c, A_c_roof, T_c, T_v) 199 | 200 | # Radiation cover to mat 201 | QR_c_m = radiation(eps_ci, eps_m, rho_ci, rho_m, F_c_m, F_m_c, A_c_roof, T_c, T_m) 202 | 203 | # Radiation vegetation to cover 204 | QR_v_c = radiation(eps_v, eps_ci, rho_v, rho_ci, F_v_c, F_c_v, A_vvf, T_v, T_c) 205 | 206 | # Radiation vegetation to mat 207 | QR_v_m = radiation(eps_v, eps_m, rho_v, rho_m, F_v_m, F_m_v, A_vvf, T_v, T_m) 208 | 209 | # Radiation vegetation to tray 210 | QR_v_p = radiation(eps_v, eps_p, rho_v, rho_p, F_v_p, F_p_v, A_vvf, T_v, T_p) 211 | 212 | # Radiation mat to cover 213 | QR_m_c = radiation(eps_m, eps_ci, rho_m, rho_ci, F_m_c, F_c_m, A_m, T_m, T_c) 214 | 215 | # Radiation mat to vegetation 216 | QR_m_v = radiation(eps_m, eps_v, rho_m, rho_v, F_m_v, F_v_m, A_m, T_m, T_v) 217 | 218 | # Radiation mat to tray 219 | QR_m_p = radiation(eps_m, eps_p, rho_m, rho_p, F_m_p, F_p_m, A_m, T_m, T_p) 220 | 221 | # Radiation tray to vegetation 222 | QR_p_v = radiation(eps_p, eps_v, rho_p, rho_v, F_p_v, F_v_p, A_p, T_p, T_v) 223 | 224 | # Radiation tray to mat 225 | QR_p_m = radiation(eps_p, eps_m, rho_p, rho_m, F_p_m, F_m_p, A_p, T_p, T_m) 226 | 227 | # Radiation tray to floor 228 | QR_p_f = radiation(eps_p, eps_s, rho_p, rho_s, F_p_f, F_f_p, A_p, T_p, T_f) 229 | 230 | # Radiation floor to cover 231 | QR_f_c = radiation(eps_s, eps_ci, rho_s, rho_ci, F_f_c, F_c_f, A_f, T_f, T_c) 232 | 233 | # Radiation floor to tray 234 | QR_f_p = radiation(eps_s, eps_p, rho_s, rho_p, F_f_p, F_p_f, A_f, T_f, T_p) 235 | 236 | 237 | ## Conduction 238 | # Conduction through floor 239 | QD_sf1 = conduction(A_f, lam_s[0], l_s[0], T_f, T_s1) 240 | QD_s12 = conduction(A_f, lam_s[1], l_s[1], T_s1, T_s2) 241 | QD_s23 = conduction(A_f, lam_s[2], l_s[2], T_s2, T_s3) 242 | QD_s34 = conduction(A_f, lam_s[3], l_s[3], T_s3, T_s4) 243 | QD_s45 = conduction(A_f, lam_s[4], l_s[4], T_s4, T_ss) 244 | 245 | # Conduction mat to tray 246 | QD_m_p = (A_m*lam_p/l_m)*(T_m-T_p) 247 | 248 | ## Ventilation 249 | # Leakage (equations for orifice flow from Awbi, Ventilation of Buildings, Chapter 3) 250 | wind_speed_H = wind_speed*c*H**a # Wind speed at height H 251 | wind_pressure = Cp*0.5*rho_i*wind_speed_H**2 # Equals DeltaP for wind pressure 252 | stack_pressure_diff = rho_i*g*H*(T_i - T_ext)/T_i # DeltaP for stack pressure 253 | 254 | Qw = Cd*crack_area*(2*wind_pressure/rho_i)**0.5 # Flow rate due to wind pressure 255 | Qs = Cd*crack_area*(2*abs(stack_pressure_diff)/rho_i)**0.5 # Flow rate due to stack pressure 256 | Qt = (Qw**2 + Qs**2)**0.5 # Total flow rate 257 | 258 | total_air_flow = Qt*crack_length_total/crack_length 259 | R_a_min = total_air_flow/V 260 | 261 | # Ventilation 262 | DeltaT_vent = T_i - T_sp_vent 263 | comp_dtv_low = DeltaT_vent > 0 and DeltaT_vent < 4 264 | comp_dtv_high = DeltaT_vent >= 4 265 | R_a = R_a_min + comp_dtv_low*(R_a_max - R_a_min)/4*DeltaT_vent + comp_dtv_high*(R_a_max-R_a_min) 266 | 267 | QV_i_e = R_a*V*rho_i*c_i*(T_i - T_ext) # Internal air to outside air [J/s] 268 | QP_i_e = R_a*V*H_fg*(C_w - Cw_ext) # Latent heat loss due to leakiness 269 | 270 | MW_i_e = R_a*(C_w - Cw_ext) 271 | 272 | ## Solar radiation 273 | # We first define the solar elevation angle that determines that absorption of solar radiation. Notation: r is direct radiation, f is diffuse radiation, whilst VIS and NIR stand for visible and near infra-red respectively. 274 | 275 | gamma = np.deg2rad(360.*(day(t) - 80.)/365.) # Year angle [rad] --- day counts from January 1st 276 | eqn_time = -7.13*np.cos(gamma) - 1.84*np.sin(gamma) - 0.69*np.cos(2.* gamma) + 9.92*np.sin(2.*gamma) # Equation of time [min] 277 | az = np.deg2rad(360.*((t/(3600.)%24.) + eqn_time/60. - 12.)/24.) # Azimuth [rad] 278 | delta = np.deg2rad(0.38 - 0.77*np.cos(gamma) + 23.27*np.cos(gamma)) # Declination angle [rad] 279 | lat = np.deg2rad(latitude) 280 | angler = np.arcsin(np.sin(lat)*np.sin(delta) + np.cos(lat)*np.cos(delta)*np.cos(az)) # Angle of elevation [rad] 281 | angle = np.rad2deg(angler) 282 | 283 | # Radiation from artifical lighting 284 | QS_al_NIR = 0. # no artificial lighting 285 | QS_al_VIS = 0. 286 | 287 | # Solar radiation incident on the cover 288 | QS_tot_rNIR = 0.5*SurfaceArea@climate[n, 4:12] # Direct 289 | QS_tot_rVIS = 0.5*SurfaceArea@climate[n, 4:12] 290 | QS_tot_fNIR = 0.5*SurfaceArea@climate[n, 12:20] # Diffuse 291 | QS_tot_fVIS = 0.5*SurfaceArea@climate[n, 12:20] 292 | 293 | # Transmitted solar radiation 294 | QS_int_rNIR = tau_c_NIR*QS_tot_rNIR # J/s total inside greenhouse 295 | QS_int_rVIS = tau_c_VIS*QS_tot_rVIS 296 | QS_int_fNIR = tau_c_NIR*QS_tot_fNIR 297 | QS_int_fVIS = tau_c_VIS*QS_tot_fVIS 298 | 299 | # Solar radiation absorbed by the cover and the obstructions 300 | QS_c = alph_c*(QS_tot_rNIR + QS_tot_rVIS + QS_tot_fNIR + QS_tot_fVIS) # J/s 301 | QS_i = a_obs*(QS_int_rNIR + QS_int_rVIS + QS_int_fNIR + QS_int_fVIS) 302 | 303 | # Solar radiation absorbed by the vegetation 304 | # Area = A_v i.e. planted area 305 | # factor QS by A_v/A_f 306 | 307 | k_fNIR = 0.27 # Near-IR diffuse extinction coefficient [-] 308 | a_v_fNIR = 0.65 - 0.65*np.exp(-k_fNIR*LAI) # Near-IR diffuse absorption coefficient [-] 309 | 310 | k_fVIS = 0.85 # Visible diffuse extinction coefficient [-] 311 | a_v_fVIS = 0.95 - 0.9*np.exp(-k_fVIS*LAI) # Visible diffuse absorption coefficient [-] 312 | 313 | k_rNIR = 0.25 + 0.38*np.exp(-0.12*angle) # Near-IR direct extinction coefficient [-] 314 | a_v_rNIR = 0.67 - 0.06*np.exp(-0.08*angle) - (0.68 - 0.5*np.exp(-0.11*angle))*np.exp(-k_rNIR*LAI) # Near-IR direct absorption coefficient [-] 315 | 316 | k_rVIS = 0.88 + 2.6*np.exp(-0.18*angle) # Visible direct extinction coefficient [-] 317 | a_v_rVIS = 0.94 - 0.95*np.exp(-k_rVIS*LAI) # Visible direct absorption coefficient [-] 318 | 319 | QS_v_rNIR = (QS_int_rNIR*(1 - a_obs) + QS_al_NIR)*a_v_rNIR*A_v/A_f 320 | QS_v_fNIR = (QS_int_fNIR*(1 - a_obs))*a_v_fNIR*A_v/A_f 321 | QS_v_NIR = (QS_v_rNIR + QS_v_fNIR) # factor as planted area not entire floor 322 | 323 | QS_v_rVIS = (QS_int_rVIS*(1 - a_obs) + QS_al_VIS)*a_v_rVIS*A_v/A_f 324 | QS_v_fVIS = (QS_int_fVIS*(1 - a_obs))*a_v_fVIS*A_v/A_f 325 | QS_v_VIS = (QS_v_rVIS + QS_v_fVIS) # Used for photosynthesis calc 326 | 327 | # Solar radiation absorbed by the mat 328 | a_m_fNIR = 0.05 + 0.91*np.exp(-0.5*LAI) # Near-IR diffuse absorption coefficient [-] 329 | a_m_fVIS = np.exp(-0.92*LAI) # Visible diffuse absorption coefficient [-] 330 | a_m_rNIR = 0.05 + 0.06*np.exp(-0.08*angle) + (0.92 - 0.53*np.exp(-0.18*angle))*np.exp(-(0.48 + 0.54*np.exp(-0.13*angle))*LAI) # Near-IR direct absorption coefficient [-] 331 | a_m_rVIS = np.exp(-(0.9 + 0.83*np.exp(-0.12*angle))*LAI) # Visible direct absorption coefficient [-] 332 | 333 | QS_m_rNIR = (QS_int_rNIR*(1 - a_obs) + QS_al_NIR)*a_m_rNIR*A_v/A_f 334 | QS_m_fNIR = QS_int_fNIR*(1 - a_obs)*a_m_fNIR*A_v/A_f # W 335 | QS_m_NIR = (QS_m_rNIR + QS_m_fNIR) 336 | 337 | QS_m_rVIS = (QS_int_rVIS*(1 - a_obs) + QS_al_VIS)*a_m_rVIS*A_v/A_f 338 | QS_m_fVIS = QS_int_fVIS*(1 - a_obs)*a_m_fVIS*A_v/A_f 339 | QS_m_VIS = (QS_m_rVIS + QS_m_fVIS) 340 | 341 | # Solar radiation absorbed by the floor 342 | # factor by (A_f-A_v)/A_f 343 | 344 | QS_s_rNIR = QS_int_rNIR*(1-a_obs)*alphS_s*(A_f-A_v)/A_f 345 | QS_s_fNIR = QS_int_fNIR*(1-a_obs)*alphS_s*(A_f-A_v)/A_f 346 | QS_s_NIR = QS_s_rNIR + QS_s_fNIR 347 | 348 | QS_s_rVIS = QS_int_rVIS*(1-a_obs)*alphS_s*(A_f-A_v)/A_f 349 | QS_s_fVIS = QS_int_fVIS*(1-a_obs)*alphS_s*(A_f-A_v)/A_f 350 | QS_s_VIS = QS_s_rVIS + QS_s_fVIS 351 | 352 | ## Transpiration 353 | QS_int = (QS_int_rNIR + QS_int_rVIS + QS_int_fNIR + QS_int_fVIS)*(1-a_obs)*A_v/A_f # J/s 354 | 355 | # Vapour pressure deficit at leaf surface 356 | xa = C_w/rho_i #[-] 357 | xv = sat_conc(T_v)/rho_i #[-] 358 | vpd = atm*(xv/(xv + 0.622) - xa/(xa + 0.622)) # [Pa] 359 | 360 | # Stomatal resistance according to Stanghellini 361 | x = np.exp(-0.24*LAI) # [-] 362 | a_v_short = 0.83*(1 - 0.70*x)*(1 + 0.58*x**2)*(0.88 - x**2 + 0.12*x**(8/3)) # [-]Absorption for shortwave radiation 363 | I_s_bar = QS_int*a_v_short/(2*LAI) # [J/s] Mean radiation interacting with leaf surface 364 | 365 | Heavy_CO2 = I_s_bar > 0. 366 | r_i_CO2 = 1 + Heavy_CO2*6.1e-7*(C_c_ppm - 200)**2 367 | Heavy_vpd = vpd/1000 < 0.8 368 | r_i_vpd = Heavy_vpd*(1 + 4.3*(vpd/1000)**2) + (1 - Heavy_vpd)*3.8 369 | r_st = 82*((QS_int + 4.3)/(QS_int + 0.54))*(1 + 0.023*(T_v - T_k - 24.5)**2)*r_i_CO2*r_i_vpd #[s/m] 370 | 371 | hL_v_i = 2*LAI*H_fg/(rho_i*c_i)*(Le**(2/3)/HV + r_st/(rho_i*c_i))**(-1) 372 | 373 | QT_St = A_v*hL_v_i*(sat_conc(T_v) - C_w) # J/s 374 | 375 | QT_v_i = max(QT_St,0) 376 | 377 | ## Dehumidification 378 | MW_cc_i = 0 # No dehumidification included 379 | 380 | # CO2 exchange with outside 381 | MC_i_e = (R_a*(C_c - C_ce)) # [kg/m^3/s] 382 | 383 | day_hour_c=(hour/24-np.floor(hour/24))*24 384 | track=day_hour_c>6 and day_hour_c<20 385 | Value=added_CO2/Nz/3600./V 386 | 387 | MC_cc_i=Value*track 388 | 389 | ## Photosynthesis model - Vanthoor 390 | 391 | # Consider photosynthetically active radiation to be visible radiation 392 | 393 | T_25 = T_k + 25. # K 394 | 395 | I_VIS=QS_v_VIS # J/s incident on planted area 396 | 397 | PAR = I_VIS/heat_phot/N_A/A_v 398 | 399 | # The number of moles of photosynthetically active photons per unit area of planted floor [mol{phot}/m^2/s] 400 | #J/s/(J/photon)/(photons/mol)/m^2 cf Vanthoor 2.3mumol(photons)/J 401 | 402 | Gamma = max((c_Gamma*(T_v - T_k)/LAI + 20*c_Gamma*(1 - 1/LAI)),0) # The CO2 compensation point [mol{CO2}/mol{air}] 403 | k_switch = C_buf_max # kg/m^2/s 404 | h_airbuf_buf = 1/(1 + np.exp(s_airbuf_buf*(C_buf - k_switch))) 405 | 406 | C_c_molar=(C_c/rho_i)*(M_a/M_c) 407 | C_stom = eta*C_c_molar # Stomatal CO2 concentration [mol{CO2}/mol{air}] 408 | 409 | J_pot = LAI*J_max_25*np.exp(E_j*(T_v - T_25)/(R*T_v*T_25))*(1 + np.exp((S*T_25 - HH)/(R*T_25)))/(1 + np.exp((S*T_v - HH)/(R*T_v))) # [mol{e}/m^2{floor}s] 410 | J = (J_pot + alph*PAR - ((J_pot + alph*PAR)**2 - 4*theta*J_pot*alph*PAR)**0.5)/(2*theta) 411 | P = J*(C_stom - Gamma)/(4*(C_stom + 2*Gamma)) # Photosynthesis rate [mol{CO2}/s] 412 | Resp = P*Gamma/C_stom # Photorespiration rate 413 | 414 | MC_i_buf = (M_carb*h_airbuf_buf*(P - Resp)) # The net photosynthesis rate [kg{CH2O}/m^2/s] 415 | 416 | ## Crop growth model 417 | 418 | # Flow of carbohydrates from buffer to fruit, leaves and stem 419 | C_buf_min = 0.05*C_buf_max 420 | h_buforg_buf =1/(1 + np.exp(s_buforg_buf*(C_buf - C_buf_min))) 421 | 422 | # inhibition terms need temperatures in oC 423 | h_T_v = 1/(1 + np.exp(s_min_T*((T_v-T_k) - T_min_v)))/(1 + np.exp(s_max_T*((T_v-T_k) - T_max_v))) 424 | h_T_v24 = 1/(1 + np.exp(s_min_T24*((T_vmean-T_k) - T_min_v24)))/(1 + np.exp(s_max_T24*((T_vmean-T_k) - T_max_v24))) 425 | 426 | h_T_vsum = 0.5*(T_vsum/T_sum_end + ((T_vsum/T_sum_end)**2 + 1e-4)**0.5) - 0.5*(((T_vsum - T_sum_end)/T_sum_end)+(((T_vsum - T_sum_end)/T_sum_end)**2 + 1e-4)**0.5) 427 | 428 | g_T_v24 = 0.047*(T_vmean - T_k) + 0.06 429 | 430 | MC_buf_fruit = (h_buforg_buf*h_T_v*h_T_v24*h_T_vsum*g_T_v24*rg_fruit) 431 | MC_buf_leaf = (h_buforg_buf*h_T_v24*g_T_v24*rg_leaf) 432 | MC_buf_stem = (h_buforg_buf*h_T_v24*g_T_v24*rg_stem) 433 | 434 | # Growth respiration, which is CO2 leaving the buffer 435 | MC_buf_i = c_fruit_g*MC_buf_fruit + c_leaf_g*MC_buf_leaf + c_stem_g*MC_buf_stem 436 | #MC_buf_i = 0 437 | 438 | # Maintenance respiration 439 | MC_fruit_i = (c_fruit_m*Q_10**(0.1*(T_vmean - T_25))*C_fruit*(1 - np.exp(-c_RGR*R_fruit))) 440 | MC_leaf_i = (c_leaf_m*Q_10**(0.1*(T_vmean - T_25))*C_leaf*(1 - np.exp(-c_RGR*R_leaf))) 441 | MC_stem_i = (c_stem_m*Q_10**(0.1*(T_vmean - T_25))*C_stem*(1 - np.exp(-c_RGR*R_stem))) 442 | 443 | C_max_leaf = LAI_max/SLA 444 | MC_leaf_prune = max(C_leaf - C_max_leaf, 0) 445 | 446 | ## ODE equations 447 | 448 | # Temperature components 449 | dT_c_dt = (1/(A_c*cd_c))*(QV_i_c + QP_i_c - QR_c_f - QR_c_v - QR_c_m + QV_e_c - QR_c_sk + QS_c) 450 | 451 | dT_i_dt = (1/(V*rho_i*c_i))*(-QV_i_m - QV_i_v - QV_i_f - QV_i_c - QV_i_e - QV_i_p + QS_i) 452 | 453 | dT_v_dt = (1/(c_v*A_v*msd_v))*(QV_i_v - QR_v_c - QR_v_m - QR_v_p + QS_v_NIR - QT_v_i) 454 | 455 | dT_m_dt = (1/(A_m*c_m))*(QV_i_m + QP_i_m - QR_m_v - QR_m_c - QR_m_p - QD_m_p + QS_m_NIR) 456 | dT_p_dt = (1/(A_p*c_p))*(QD_m_p + QV_i_p + QP_i_p - QR_p_f - QR_p_v - QR_p_m) 457 | dT_f_dt = (1/(rhod_s[0]*A_f*c_s[0]*l_s[0]))*(QV_i_f + QP_i_f - QR_f_c - QR_f_p - QD_sf1 + QS_s_NIR) 458 | dT_s1_dt = (1/(rhod_s[1]*c_s[1]*l_s[1]*A_f))*(QD_sf1-QD_s12) 459 | dT_s2_dt = (1/(rhod_s[2]*c_s[2]*l_s[2]*A_f))*(QD_s12-QD_s23) 460 | dT_s3_dt = (1/(rhod_s[3]*c_s[3]*l_s[3]*A_f))*(QD_s23-QD_s34) 461 | dT_s4_dt = (1/(rhod_s[4]*c_s[4]*l_s[4]*A_f))*(QD_s34-QD_s45) 462 | 463 | # Water vapour 464 | dC_w_dt = (1/(V*H_fg))*(QT_v_i-QP_i_c-QP_i_f-QP_i_m-QP_i_p) - MW_i_e + MW_cc_i 465 | #dC_wdt = -MW_i_e 466 | 467 | # Carbon Dioxide 468 | dC_c_dt = MC_cc_i - MC_i_e + (M_c/M_carb)*(A_v/V)*(MC_buf_i + MC_fruit_i + MC_leaf_i + MC_stem_i - MC_i_buf) 469 | 470 | # Plant growth control 471 | dT_vmean_dt = 1/86400*(T_v - T_vmean) 472 | dT_vsum_dt = 1/86400*(T_v - T_k) 473 | 474 | # Plant carbon exchange 475 | dC_buf_dt = MC_i_buf - MC_buf_fruit - MC_buf_leaf - MC_buf_stem - MC_buf_i 476 | dC_fruit_dt = MC_buf_fruit - MC_fruit_i 477 | dC_leaf_dt = MC_buf_leaf - MC_leaf_i - MC_leaf_prune 478 | dC_stem_dt = MC_buf_stem - MC_stem_i 479 | 480 | # Plant growth 481 | dR_fruit_dt = (dC_fruit_dt/C_fruit - R_fruit) 482 | dR_leaf_dt = ((dC_leaf_dt + MC_leaf_prune)/C_leaf - R_leaf) 483 | dR_stem_dt = (dC_stem_dt/C_stem - R_stem) 484 | 485 | return np.array([dT_c_dt,dT_i_dt,dT_v_dt,dT_m_dt,dT_p_dt,dT_f_dt,dT_s1_dt, 486 | dT_s2_dt,dT_s3_dt,dT_s4_dt,dT_vmean_dt,dT_vsum_dt,dC_w_dt, 487 | dC_c_dt,dC_buf_dt,dC_fruit_dt,dC_leaf_dt,dC_stem_dt, 488 | dR_fruit_dt,dR_leaf_dt,dR_stem_dt]) 489 | -------------------------------------------------------------------------------- /MATLAB/derivatives.m: -------------------------------------------------------------------------------- 1 | function dT = derivatives(t, T) 2 | %% IMPORT DATA, OUTPUT DAY NUMBER 3 | 4 | global climate; 5 | persistent day; 6 | 7 | %% Read in and initialise parameters for model 8 | 9 | parameters; 10 | 11 | % Time control parameters 12 | n = ceil(t/deltaT); 13 | if t == 0 14 | n = 1; 15 | day = 1; 16 | end 17 | 18 | day_new = ceil(t/(86400)); % Day number 19 | if day_new == day + 1 20 | disp(strcat(num2str(day_new), '/', num2str(sim_days))); 21 | end 22 | day = day_new; 23 | 24 | hour = floor(t/3600) + 1; 25 | 26 | 27 | 28 | % Initial Values 29 | T_c = T(1, 1); % Cover temperature [K] 30 | T_i = T(2, 1); % Internal temperature [K] 31 | T_v = T(3, 1); % Vegetation temperature [K] 32 | T_m = T(4, 1); % Temperature of mat [K] 33 | T_p = T(5, 1); %Temperature of tray [K] 34 | T_f = T(6, 1); % Temperature of floor [K] 35 | T_s1 = T(7, 1); % Temperature of first layer of soil [K] 36 | T_s2 = T(8, 1); % Temperature of second layer of soil [K] 37 | T_s3 = T(9, 1); % Temperature of third layer of soil [K] 38 | T_s4 = T(10, 1); % Temperature of fourth layer of soil [K] 39 | % 40 | T_vmean = T(11, 1); % 24 hour mean vegetation temperature [K] 41 | T_vsum = T(12, 1); % Vegetation temperature sum [degC] 42 | % 43 | C_w = T(13, 1); % Density of water vapour [kg/m^3] 44 | C_c = T(14, 1); % Density of carbon dioxide [kg/m^3] 45 | C_buf = T(15, 1); % Mass of carbohydrate in buffer per unit per unit area of cultivated floor [kg/m^2] 46 | C_fruit = T(16, 1); % Mass of carbohydrate in fruit per unit per unit area of cultivated floor [kg/m^2] 47 | C_leaf = T(17, 1); % Mass of carbohydrate in leaves per unit per unit area of cultivated floor [kg/m^2] 48 | C_stem = T(18, 1); % Mass of carbohydrate in stem per unit per unit area of cultivated floor [kg/m^2] 49 | R_fruit = T(19, 1); % Relative growth rate of fruit averaged over 5 days [1/s] 50 | R_leaf = T(20, 1); % Relative growth rate of leaf averaged over 5 days [1/s] 51 | R_stem = T(21, 1); % Relative growth rate of stem averaged over 5 days [1/s] 52 | % 53 | T_e = climate(n, 1) + T_k; % External temperature [K] 54 | T_sk = climate(n, 2) + T_k; % Sky temperature [K] 55 | wind_speed = climate(n, 3)*ones(Nz, 1); % External wind speed [m/s] 56 | rel_humid = climate(n, 4)/100; % External relative humidity [-] 57 | C_we = rel_humid.*sat_conc(T_e); % External density of water vapour [kg/m^3] 58 | p_w = C_w*R.*T_i/M_w; % Partial pressure of water [Pa] 59 | rho_i = ((atm - p_w)*M_a + p_w*M_w)./(R*T_i); % Density of air [kg/m^3] 60 | LAI = SLA.*C_leaf; % Leaf area index 61 | C_ce = 4.0e-4*M_c*atm/(R*T_e); % External carbon dioxide concentration [kg/m^3] 62 | C_c_ppm = C_c*R.*T_i/(M_c*atm)*1e6; % CO2 concentration in ppm 63 | 64 | %% HEAT EXCHANGE TERMS 65 | 66 | % Convection including evaporation/condensation 67 | % Radiation 68 | % Conduction 69 | % Transpiration 70 | 71 | %% Convection 72 | 73 | % The Grashof and Reynolds numbers are calculated, and then the Nusselt 74 | % number calculated as the larger of the 'free' Nusselt number, based on 75 | % the Grashof number, and the 'forced' Nusselt number, based on the 76 | % Reynolds number. The heat transferred per unit time is then calculated 77 | % based on this. The first subscript is where heat is transferred from, and 78 | % the second subscript where heat is transferred to. 79 | 80 | % Cover to external air 81 | Gr = g*d_c^3/(T_e*nu^2)*abs(T_c - T_e); 82 | Re = wind_speed*d_c/nu; 83 | Nu = lamorturb(Gr, Re); 84 | QV_c_e = A_c.*Nu*lambda.*(T_c - T_e)/d_c; 85 | 86 | % Internal air to cover 87 | Gr = g*d_c^3./(T_i*nu^2).*abs(T_i - T_c); 88 | Re = int_air_speed*d_c/nu; 89 | [Nu, Sh] = lamorturb(Gr, Re, Le); 90 | QV_i_c = A_c.*Nu*lambda.*(T_i - T_c)/d_c; 91 | QP_i_c = A_c*H_fg./(rho_i*c_i).*Sh/Le*lambda/d_c.*(C_w - sat_conc(T_c)); 92 | QP_i_c = max(QP_i_c,0); % assumed no evaporation from the cover, only condensation 93 | 94 | %Internal air to floor 95 | Gr = g*d_f^3./(T_i*nu^2).*abs(T_i - T_f); 96 | Re = int_air_speed*d_f/nu; 97 | [Nu, Sh] = lamorturb(Gr, Re, Le); 98 | QV_i_f = A_f.*Nu*lambda.*(T_i - T_f)/d_f; 99 | QP_i_f = A_f*H_fg./(rho_i*c_i).*Sh/Le*lambda/d_f.*(C_w - sat_conc(T_f)); 100 | QP_i_f = max(QP_i_f,0); % assumed no evaporation from the floor, only condensation 101 | 102 | % Mat to internal air 103 | Gr = g*d_m^3./(T_i*nu^2).*abs(T_m - T_i); 104 | Re = int_air_speed*d_m/nu; 105 | [Nu, Sh] = lamorturb(Gr, Re, Le); 106 | A_m_wool = 0.75*A_m; % Area of mat exposed 107 | A_m_water = 0.25*A_m; % assumed 25% saturated 108 | QV_m_i = A_m_wool.*Nu*lambda.*(T_m - T_i)/d_m; 109 | QP_m_i = A_m_water*H_fg./(rho_i*c_i).*Sh/Le*lambda/d_m.*(sat_conc(T_m) - C_w); 110 | 111 | % Tray to internal air 112 | Gr = g*d_p^3./(T_i*nu^2).*abs(T_p - T_i); 113 | Re = int_air_speed*d_p/nu; 114 | [Nu, ~] = lamorturb(Gr, Re, Le); 115 | QV_p_i = A_p.*Nu*lambda.*(T_p - T_i)/d_p; 116 | QP_p_i = 0; % assumed no condensation/evaporation from tray 117 | 118 | % Vegetation to internal air 119 | Gr = g*d_v^3./(T_i*nu^2).*abs(T_v - T_i); 120 | Re = int_air_speed*d_v/nu; 121 | Nu = lamorturb(Gr, Re); 122 | A_v_exp = LAI*A_v; % Area vegetation exposed 123 | QV_v_i = A_v_exp.*Nu*lambda.*(T_v - T_i)/d_v; 124 | HV = Nu*lambda/d_v; % Used in the transpiration term 125 | 126 | %% Far-IR radiation 127 | 128 | % In the following equations the emissivity is used at times when the 129 | % relevant quantity is the absorptivity, since these are equal according to 130 | % Kirchoff's law. The constant k is the pre-factor that takes into account 131 | % emission, reflection, transmission and absorption. The F's are view 132 | % factors --- in the case of the cover they are calculated using 133 | % reciprocity since the precise geometry of the cover is not known. Once 134 | % again, the first subscript is the element that is radiating, whilst the 135 | % second subscript is the element that is absorbing. 136 | 137 | % View factors 138 | A_vvf=min(LAI*p_v*A_f,p_v*A_f); 139 | A_c_roof = 271; 140 | 141 | F_f_c = 1-p_v; % Floor to cover 142 | F_f_p = p_v; % Floor to tray 143 | F_c_f = A_f/A_c_roof*F_f_c; % Cover to floor 144 | F_c_v = min((1-F_c_f)*LAI,(1-F_c_f)); % Cover to vegetation 145 | F_c_m = max((1-F_c_f)*(1-LAI),0); % Cover to mat 146 | F_v_c = 0.5; % Vegetation to cover 147 | F_v_m = 0.5; % Vegetation to mat 148 | F_v_p = 0; % Vegetation to tray 149 | F_m_c = max((1-LAI),0.0); % Mat to cover 150 | F_m_v = 1-F_m_c; % Mat to vegetation 151 | F_m_p = 0; % Mat to tray 152 | F_p_v = 0; % Tray to vegetation 153 | F_p_m = 0; % Tray to mat 154 | F_p_f = 1.0; % Tray to floor 155 | 156 | % Cover to sky 157 | k = eps_ce; 158 | QR_c_sk = k*sigm*A_c.*(T_c.^4 - T_sk^4); % J/s 159 | 160 | % Cover to vegetation 161 | k = eps_ci*eps_v./(1 - rho_ci*rho_v*F_c_v.*F_v_c); 162 | QR_c_v = k*sigm.*A_c_roof.*F_c_v.*(T_c.^4 - T_v.^4); 163 | 164 | % Cover to mat 165 | k = eps_ci*eps_m./(1 - rho_ci*rho_m*F_c_m.*F_m_c); 166 | QR_c_m = k*sigm.*A_c_roof.*F_c_m.*(T_c.^4 - T_m.^4); 167 | 168 | % Cover to floor 169 | k = eps_ci*eps_s./(1 - rho_ci*rho_s*F_c_f.*F_f_c); 170 | QR_c_f = k*sigm.*A_c_roof.*F_c_f.*(T_c.^4 - T_f.^4); 171 | 172 | % Vegetation to cover 173 | k = eps_v*eps_ci./(1 - rho_v*rho_ci*F_v_c.*F_c_v); 174 | QR_v_c = k*sigm.*A_vvf*2.*F_v_c.*(T_v.^4 - T_c.^4); 175 | 176 | % Vegetation to mat 177 | k = eps_v*eps_m./(1 - rho_v*rho_m*F_v_m.*F_m_v); 178 | QR_v_m = k*sigm.*A_vvf*2.*F_v_m.*(T_v.^4 - T_m.^4); 179 | 180 | % Vegetation to tray 181 | k = eps_v*eps_p./(1 - rho_v*rho_p*F_v_p.*F_p_v); 182 | QR_v_p = k*sigm.*A_vvf*2.*F_v_p.*(T_v.^4 - T_p.^4); 183 | 184 | % Mat to cover 185 | k = eps_m*eps_ci./(1 - rho_m*rho_ci*F_m_c.*F_c_m); 186 | QR_m_c = k*sigm.*A_m.*F_m_c.*(T_m.^4 - T_c.^4); 187 | 188 | % Mat to vegetation 189 | k = eps_m*eps_v./(1 - rho_m*rho_v*F_m_v.*F_v_m); 190 | QR_m_v = k*sigm.*A_m.*F_m_v.*(T_m.^4 - T_v.^4); 191 | 192 | % Mat to tray 193 | k = eps_m*eps_p./(1 - rho_m*rho_p*F_m_p.*F_p_m); 194 | QR_m_p = k*sigm.*A_m.*F_m_p.*(T_m.^4 - T_p.^4); 195 | 196 | % Tray to vegetation 197 | k = eps_p*eps_v./(1 - rho_p*rho_v*F_p_v.*F_v_p); 198 | QR_p_v = k*sigm.*A_p.*F_p_v.*(T_p.^4 - T_v.^4); 199 | 200 | % Tray to mat 201 | k = eps_p*eps_m./(1 - rho_p*rho_m*F_p_m.*F_m_p); 202 | QR_p_m = k*sigm.*A_p.*F_p_m.*(T_p.^4 - T_m.^4); 203 | 204 | % Tray to floor 205 | k = eps_p*eps_s./(1 - rho_p*rho_s*F_p_f.*F_f_p); 206 | QR_p_f = k*sigm.*A_p.*F_p_f.*(T_p.^4 - T_f.^4); 207 | 208 | % Floor to cover 209 | k = eps_s*eps_ci./(1 - rho_s*rho_ci*F_c_f.*F_f_c); 210 | QR_f_c = k*sigm.*A_f.*F_f_c.*(T_f.^4 - T_c.^4); 211 | 212 | % Floor to tray 213 | k = eps_s*eps_p./(1 - rho_s*rho_p*F_f_p.*F_p_f); 214 | QR_f_p = k*sigm.*A_f.*F_f_p.*(T_f.^4 - T_p.^4); 215 | 216 | 217 | %% Solar radiation 218 | 219 | % We first define the solar elevation angle that determines that absorption 220 | % of solar radiation. Notation: r is direct radiation, f is diffuse 221 | % radiation, whilst VIS and NIR stand for visible and near infra-red 222 | % respectively. 223 | 224 | gamma = 360*(day - 80)/365; % Year angle [deg] --- day counts from January 1st 225 | eqn_time = -7.13*cosd(gamma) - 1.84*sind(gamma) - ... 226 | 0.69*cosd(2*gamma) + 9.92*sind(2*gamma); % Equation of time [min] 227 | az = 360*(rem(t/(3600), 24) + eqn_time/60 - 12)/24; % Azimuth [deg] 228 | delta = 0.38 - 0.77*cosd(gamma) + 23.27*cosd(gamma); % Declination angle [deg] 229 | angle = asind(sind(latitude)*sind(delta) + ... 230 | cosd(latitude)*cosd(delta)*cosd(az)); % Angle of elevation [deg] 231 | 232 | % Radiation from artifical lighting 233 | QS_al_NIR = 0; % no artificial lighting 234 | QS_al_VIS = 0; 235 | 236 | % Solar radiation incident on the cover 237 | QS_tot_rNIR = 0.5*SurfaceArea*climate(n, 5:12)'; % Direct (J/s) 238 | QS_tot_rVIS = 0.5*SurfaceArea*climate(n, 5:12)'; 239 | QS_tot_fNIR = 0.5*SurfaceArea*climate(n, 13:20)'; % Diffuse 240 | QS_tot_fVIS = 0.5*SurfaceArea*climate(n, 13:20)'; 241 | 242 | % Transmitted solar radiation 243 | QS_int_rNIR = tau_c_NIR*QS_tot_rNIR; % J/s total inside greenhouse 244 | QS_int_rVIS = tau_c_VIS*QS_tot_rVIS; 245 | QS_int_fNIR = tau_c_NIR*QS_tot_fNIR; 246 | QS_int_fVIS = tau_c_VIS*QS_tot_fVIS; % 247 | 248 | % Solar radiation absorbed by the cover and the obstructions 249 | QS_c = alph_c*(QS_tot_rNIR + QS_tot_rVIS + QS_tot_fNIR + QS_tot_fVIS); % J/s 250 | QS_i = a_obs*(QS_int_rNIR + QS_int_rVIS + QS_int_fNIR + QS_int_fVIS); 251 | 252 | % Solar radiation absorbed by the vegetation 253 | % Area = A_v i.e. planted area 254 | % factor QS by A_v/A_f 255 | 256 | k_fNIR = 0.27; % Near-IR diffuse extinction coefficient [-] 257 | a_v_fNIR = 0.65 - 0.65*exp(-k_fNIR*LAI); % Near-IR diffuse absorption coefficient [-] 258 | % 259 | k_fVIS = 0.85; % Visible diffuse extinction coefficient [-] 260 | a_v_fVIS = 0.95 - 0.9*exp(-k_fVIS*LAI); % Visible diffuse absorption coefficient [-] 261 | % 262 | k_rNIR = 0.25 + 0.38*exp(-0.12*angle); % Near-IR direct extinction coefficient [-] 263 | a_v_rNIR = 0.67 - 0.06*exp(-0.08*angle) - (0.68 - 0.5*exp(-0.11*angle))* ... 264 | exp(-k_rNIR*LAI); % Near-IR direct absorption coefficient [-] 265 | % 266 | k_rVIS = 0.88 + 2.6*exp(-0.18*angle); % Visible direct extinction coefficient [-] 267 | a_v_rVIS = 0.94 - 0.95*exp(-k_rVIS*LAI); % Visible direct absorption coefficient [-] 268 | 269 | QS_v_rNIR = (QS_int_rNIR.*(1 - a_obs) + QS_al_NIR)*a_v_rNIR*A_v/A_f; 270 | QS_v_fNIR = (QS_int_fNIR.*(1 - a_obs))*a_v_fNIR*A_v/A_f; 271 | QS_v_NIR = (QS_v_rNIR + QS_v_fNIR); % factor as planted area not entire floor 272 | 273 | QS_v_rVIS = (QS_int_rVIS.*(1 - a_obs) + QS_al_VIS)*a_v_rVIS*A_v/A_f; 274 | QS_v_fVIS = (QS_int_fVIS.*(1 - a_obs))*a_v_fVIS*A_v/A_f; 275 | QS_v_VIS = (QS_v_rVIS + QS_v_fVIS); % Used for photosynthesis calc 276 | 277 | % Solar radiation absorbed by the mat 278 | a_m_fNIR = 0.05 + 0.91*exp(-0.5*LAI); % Near-IR diffuse absorption coefficient [-] 279 | a_m_fVIS = exp(-0.92*LAI); % Visible diffuse absorption coefficient [-] 280 | a_m_rNIR = 0.05 + 0.06*exp(-0.08*angle) + (0.92 - 0.53*exp(-0.18*angle))* ... 281 | exp(-(0.48 + 0.54*exp(-0.13*angle))*LAI); % Near-IR direct absorption coefficient [-] 282 | a_m_rVIS = exp(-(0.9 + 0.83*exp(-0.12*angle))*LAI); % Visible direct absorption coefficient [-] 283 | 284 | QS_m_rNIR = (QS_int_rNIR.*(1 - a_obs) + QS_al_NIR).*a_m_rNIR*A_v/A_f; 285 | QS_m_fNIR = QS_int_fNIR.*(1 - a_obs).*a_m_fNIR*A_v/A_f; % W 286 | QS_m_NIR = (QS_m_rNIR + QS_m_fNIR); 287 | 288 | QS_m_rVIS = (QS_int_rVIS.*(1 - a_obs) + QS_al_VIS).*a_m_rVIS*A_v/A_f; 289 | QS_m_fVIS = QS_int_fVIS.*(1 - a_obs).*a_m_fVIS*A_v/A_f; 290 | QS_m_VIS = (QS_m_rVIS + QS_m_fVIS); 291 | 292 | % Solar radiation absorbed by the floor 293 | % factor by (A_f-A_v)/A_f 294 | 295 | QS_s_rNIR = QS_int_rNIR*(1-a_obs)*alphS_s*(A_f-A_v)/A_f; 296 | QS_s_fNIR = QS_int_fNIR*(1-a_obs)*alphS_s*(A_f-A_v)/A_f; 297 | QS_s_NIR = QS_s_rNIR + QS_s_fNIR; 298 | 299 | QS_s_rVIS = QS_int_rVIS*(1-a_obs)*alphS_s*(A_f-A_v)/A_f ; 300 | QS_s_fVIS = QS_int_fVIS*(1-a_obs)*alphS_s*(A_f-A_v)/A_f; 301 | QS_s_VIS = QS_s_rVIS + QS_s_fVIS; 302 | % 303 | 304 | %% Transpiration 305 | 306 | % Radiation 307 | QS_int = (QS_int_rNIR + QS_int_rVIS + QS_int_fNIR + QS_int_fVIS)*(1-a_obs)*A_v/A_f; % J/s 308 | 309 | % Vapour pressure deficit at leaf surface 310 | xa = C_w./rho_i; %[-] 311 | xv = sat_conc(T_v)./rho_i; %[-] 312 | vpd = atm*(xv./(xv + 0.622) - xa./(xa + 0.622)); % [Pa] 313 | 314 | % Stomatal resistance according to Stanghellini 315 | x = exp(-0.24*LAI); % [-] 316 | a_v_short = 0.83*(1 - 0.70*x).*(1 + 0.58*x.^2).*(0.88 - x.^2 + 0.12*x.^(8/3)); % [-]Absorption for shortwave radiation 317 | I_s_bar = QS_int.*a_v_short./(2*LAI); % [J/s] Mean radiation interacting with leaf surface 318 | 319 | Heavy_CO2 = I_s_bar > 0; 320 | r_i_CO2 = 1 + Heavy_CO2*6.1e-7.*(C_c_ppm - 200).^2; 321 | Heavy_vpd = vpd/1000 < 0.8; 322 | r_i_vpd = Heavy_vpd.*(1 + 4.3*(vpd/1000).^2) + (1 - Heavy_vpd)*3.8; 323 | r_st = 82*((QS_int + 4.3)./(QS_int + 0.54)).*(1 + 0.023*(T_v - T_k - 24.5).^2).*r_i_CO2.*r_i_vpd; %[s/m] 324 | 325 | hL_v_i = 2*LAI*H_fg./(rho_i*c_i).*(Le^(2/3)./HV + r_st./(rho_i*c_i)).^(-1); % 326 | 327 | QT_St = A_v.*hL_v_i.*(sat_conc(T_v) - C_w); % J/s 328 | 329 | QT_v_i = max(QT_St,0); 330 | 331 | %% Conduction 332 | % Floor layers 333 | % 334 | QD_sf1 = A_f*lam_s(1)/l_s(1).*(T_f - T_s1); 335 | QD_s12 = A_f*lam_s(2)/l_s(2).*(T_s1 - T_s2); 336 | QD_s23 = A_f*lam_s(3)/l_s(3).*(T_s2 - T_s3); 337 | QD_s34 = A_f*lam_s(4)/l_s(4).*(T_s3 - T_s4); 338 | QD_s45 = A_f*lam_s(5)/l_s(5).*(T_s4 - T_ss); 339 | 340 | % Mat to tray 341 | QD_m_p = A_m*lam_p/l_m.*(T_m-T_p); 342 | 343 | %% Ventilation 344 | 345 | % Leakage (equations for orifice flow from Awbi, Ventilation of Buildings, Chapter 3) 346 | wind_speed_H = wind_speed*c*H^a; % Wind speed at height H 347 | wind_pressure = Cp*0.5*rho_i.*wind_speed_H.^2; % Equals DeltaP for wind pressure 348 | stack_pressure_diff = rho_i*g*H.*(T_i - T_e)./T_i; % DeltaP for stack pressure 349 | % 350 | Qw = Cd*crack_area*(2*wind_pressure./rho_i).^0.5; % Flow rate due to wind pressure 351 | Qs = Cd*crack_area*(2*abs(stack_pressure_diff)./rho_i).^0.5; % Flow rate due to stack pressure 352 | Qt = (Qw.^2 + Qs.^2).^0.5; % Total flow rate 353 | % 354 | total_air_flow = Qt.*crack_length_total/crack_length; % 355 | R_a_min = total_air_flow./V; % 356 | 357 | % Ventilation 358 | DeltaT_vent = T_i - T_sp_vent; 359 | comp_dtv_low = DeltaT_vent > 0 & DeltaT_vent < 4; 360 | comp_dtv_high = DeltaT_vent >= 4; 361 | R_a = R_a_min + comp_dtv_low.*(R_a_max - R_a_min)/4.*DeltaT_vent + comp_dtv_high.*(R_a_max-R_a_min); 362 | 363 | QV_i_e = R_a.*V.*rho_i*c_i.*(T_i - T_e); % Internal air to outside air [J/s] 364 | QP_i_e = R_a.*V*H_fg.*(C_w - C_we); % Latent heat loss due to leakiness 365 | 366 | 367 | %% WATER VAPOUR EXCHANGE TERMS 368 | 369 | MW_i_e = R_a.*(C_w - C_we); 370 | MW_cc_i = 0; % Climate controller 371 | 372 | %% CARBON DIOXIDE EXCHANGE TERMS 373 | 374 | MC_i_e = (R_a.*(C_c - C_ce)); % [kg/m^3/s] 375 | 376 | day_hour_c=(hour/24-floor(hour/24))*24; 377 | track=day_hour_c>6 && day_hour_c<20; 378 | Value=added_CO2/Nz/3600./V; 379 | 380 | MC_cc_i=Value*track; 381 | 382 | 383 | %% PHOTOSYNTHESIS MODEL - VANTHOOR 384 | 385 | % Consider photosynthetically active radiation to be visible radiation 386 | 387 | T_25 = T_k + 25; % K 388 | 389 | I_VIS=QS_v_VIS; % J/s incident on planted area 390 | 391 | PAR = I_VIS/heat_phot/N_A./A_v; 392 | % The number of moles of photosynthetically active photons per unit area of planted floor [mol{phot}/m^2/s] 393 | %J/s/(J/photon)/(photons/mol)/m^2 cf Vanthoor 2.3mumol(photons)/J 394 | 395 | Gamma = max((c_Gamma*(T_v - T_k)./LAI + 20*c_Gamma*(1 - 1./LAI)),0); % The CO2 compensation point [mol{CO2}/mol{air}] 396 | k_switch = C_buf_max;% kg/m^2/s 397 | h_airbuf_buf = 1./(1 + exp(s_airbuf_buf*(C_buf - k_switch))); 398 | 399 | C_c_molar=(C_c./rho_i).*(M_a/M_c); 400 | C_stom = eta*C_c_molar; % Stomatal CO2 concentration [mol{CO2}/mol{air}] 401 | 402 | J_pot = LAI*J_max_25.*exp(E_j*(T_v - T_25)./(R*T_v*T_25)).*... 403 | (1 + exp((S*T_25 - HH)/(R*T_25)))./(1 + exp((S*T_v - HH)./(R*T_v))); % [mol{e}/m^2{floor}s] 404 | J = (J_pot + alph*PAR - sqrt((J_pot + alph*PAR).^2 - 4*theta*J_pot*alph.*PAR))/(2*theta); 405 | P = J.*(C_stom - Gamma)./(4*(C_stom + 2*Gamma)); % Photosynthesis rate [mol{CO2}/s] 406 | Resp = P.*Gamma./C_stom; % Photorespiration rate 407 | 408 | MC_i_buf = (M_carb*h_airbuf_buf.*(P - Resp)); % The net photosynthesis rate [kg{CH2O}/m^2/s] 409 | 410 | 411 | %% CROP GROWTH MODEL 412 | 413 | % Flow of carbohydrates from buffer to fruit, leaves and stem 414 | C_buf_min = 0.05*C_buf_max; 415 | h_buforg_buf =1./(1 + exp(s_buforg_buf*(C_buf - C_buf_min))); 416 | 417 | % inhibition terms need temperatures in oC 418 | h_T_v = 1./(1 + exp(s_min_T*((T_v-T_k) - T_min_v)))./(1 + exp(s_max_T*((T_v-T_k) - T_max_v))); 419 | h_T_v24 = 1./(1 + exp(s_min_T24*((T_vmean-T_k) - T_min_v24)))./(1 + exp(s_max_T24*((T_vmean-T_k) - T_max_v24))); 420 | 421 | h_T_vsum = 0.5*(T_vsum./T_sum_end + sqrt((T_vsum./T_sum_end).^2 + 1e-4)) ... 422 | - 0.5*(((T_vsum - T_sum_end)/T_sum_end)+sqrt(((T_vsum - T_sum_end)/T_sum_end).^2 + 1e-4)); 423 | 424 | g_T_v24 = 0.047*(T_vmean - T_k) + 0.06; 425 | 426 | MC_buf_fruit = (h_buforg_buf.*h_T_v.*h_T_v24.*h_T_vsum.*g_T_v24.*rg_fruit); 427 | MC_buf_leaf = (h_buforg_buf.*h_T_v24.*g_T_v24.*rg_leaf); 428 | MC_buf_stem = (h_buforg_buf.*h_T_v24.*g_T_v24.*rg_stem); 429 | 430 | % Growth respiration, which is CO2 leaving the buffer 431 | MC_buf_i = c_fruit_g*MC_buf_fruit + c_leaf_g*MC_buf_leaf + c_stem_g*MC_buf_stem; 432 | 433 | % Maintenance respiration 434 | MC_fruit_i = (c_fruit_m*Q_10.^(0.1*(T_vmean - T_25)).*C_fruit.*(1 - exp(-c_RGR*R_fruit))); 435 | MC_leaf_i = (c_leaf_m*Q_10.^(0.1*(T_vmean - T_25)).*C_leaf.*(1 - exp(-c_RGR*R_leaf))); 436 | MC_stem_i = (c_stem_m*Q_10.^(0.1*(T_vmean - T_25)).*C_stem.*(1 - exp(-c_RGR*R_stem))); 437 | 438 | C_max_leaf = LAI_max/SLA; 439 | MC_leaf_prune = max(C_leaf - C_max_leaf, 0); 440 | 441 | %% CALCULATING DERIVATIVES 442 | 443 | % Temperature components 444 | dT_c_dt = 1./(A_c*cd_c).*(QV_i_c + QP_i_c - QR_c_f - QR_c_v ... 445 | - QR_c_m - QV_c_e - QR_c_sk + QS_c); 446 | dT_i_dt = 1./(V.*rho_i*c_i).*(QV_m_i + QV_v_i - QV_i_f - QV_i_c - QV_i_e ... 447 | + QV_p_i + QS_i); 448 | dT_v_dt = 1./(c_v*A_v.*msd_v).*(-QV_v_i - QR_v_c - QR_v_m ... 449 | - QR_v_p - QT_v_i + QS_v_NIR); 450 | dT_m_dt = 1./(A_m*c_m).*(-QV_m_i - QP_m_i - QR_m_v - QR_m_c ... 451 | - QR_m_p - QD_m_p + QS_m_NIR); 452 | dT_p_dt = 1./(A_p*c_p).*(QD_m_p - QV_p_i - QP_p_i - QR_p_f ... 453 | - QR_p_v - QR_p_m); 454 | dT_f_dt = 1./(rhod_s(1)*A_f*c_s(1)*l_s(1)).*(QV_i_f + QP_i_f - ... 455 | QR_f_c - QR_f_p - QD_sf1 + QS_s_NIR); 456 | dT_s1_dt = 1./(rhod_s(2)*c_s(2)*l_s(2)*A_f).*(QD_sf1 - QD_s12); 457 | dT_s2_dt = 1./(rhod_s(3)*c_s(3)*l_s(3)*A_f).*(QD_s12 - QD_s23); 458 | dT_s3_dt = 1./(rhod_s(4)*c_s(4)*l_s(4)*A_f).*(QD_s23 - QD_s34); 459 | dT_s4_dt = 1./(rhod_s(5)*c_s(5)*l_s(5)*A_f).*(QD_s34 - QD_s45); 460 | 461 | % Water Vapour 462 | dC_w_dt = 1./(V*H_fg).*(QP_m_i + QP_p_i - QP_i_c - QP_i_f + QT_v_i) + ... 463 | MW_cc_i - MW_i_e; 464 | 465 | % Carbon Dioxide 466 | dC_c_dt = MC_cc_i - MC_i_e + (M_c/M_carb)*(A_v/V)*(MC_buf_i + MC_fruit_i + ... 467 | MC_leaf_i + MC_stem_i - MC_i_buf); 468 | 469 | % Plant growth control 470 | dT_vmean_dt = 1/86400*(T_v - T_vmean); 471 | dT_vsum_dt = 1/86400*(T_v - T_k); 472 | 473 | % Plant carbon exchange 474 | dC_buf_dt = MC_i_buf - MC_buf_fruit - MC_buf_leaf - MC_buf_stem - MC_buf_i; 475 | dC_fruit_dt = MC_buf_fruit - MC_fruit_i; 476 | dC_leaf_dt = MC_buf_leaf - MC_leaf_i - MC_leaf_prune; 477 | dC_stem_dt = MC_buf_stem - MC_stem_i; 478 | 479 | % Plant growth 480 | dR_fruit_dt = (dC_fruit_dt./C_fruit - R_fruit); 481 | dR_leaf_dt = ((dC_leaf_dt + MC_leaf_prune)./C_leaf - R_leaf); 482 | dR_stem_dt = (dC_stem_dt./C_stem - R_stem); 483 | 484 | % Return all temperature derivatives 485 | dT = cat(1, dT_c_dt, dT_i_dt, dT_v_dt, dT_m_dt, dT_p_dt, dT_f_dt, ... 486 | dT_s1_dt, dT_s2_dt, dT_s3_dt, dT_s4_dt, ... 487 | dT_vmean_dt, dT_vsum_dt, ... 488 | dC_w_dt, dC_c_dt, dC_buf_dt, dC_fruit_dt, dC_leaf_dt, dC_stem_dt, ... 489 | dR_fruit_dt, dR_leaf_dt, dR_stem_dt); 490 | 491 | end --------------------------------------------------------------------------------