Source code for pcse.crop.nutrients.npk_demand_uptake

# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Alterra, Wageningen-UR
# Allard de Wit and Iwan Supit (allard.dewit@wur.nl), July 2015
# Approach based on LINTUL N/P/K made by Joost Wolf
from collections import namedtuple

from ...base import StatesTemplate, ParamTemplate, SimulationObject, RatesTemplate
from ...decorators import prepare_rates, prepare_states
from ...traitlets import HasTraits, Float, Int, Instance
from ...util import AfgenTrait

MaxNutrientConcentrations = namedtuple("MaxNutrientConcentrations",
                                       ["NMAXLV", "PMAXLV", "KMAXLV",
                                        "NMAXST", "PMAXST", "KMAXST",
                                        "NMAXRT", "PMAXRT", "KMAXRT",
                                        "NMAXSO", "PMAXSO", "KMAXSO"])

[docs]class NPK_Demand_Uptake(SimulationObject): """Calculates the crop N/P/K demand and its uptake from the soil. Crop N/P/K demand is calculated as the difference between the actual N/P/K concentration (kg N/P/K per kg biomass) in the vegetative plant organs (leaves, stems and roots) and the maximum N/P/K concentration for each organ. N/P/K uptake is then estimated as the minimum of supply from the soil and demand from the crop. Nitrogen fixation (leguminous plants) is calculated by assuming that a fixed fraction of the daily N demand is supplied by nitrogen fixation. The remaining part has to be supplied by the soil. The N/P/K demand of the storage organs is calculated in a somewhat different way because it is assumed that the demand from the storage organs is fulfilled by translocation of N/P/K from the leaves, stems and roots. So Therefore the uptake of the storage organs is calculated as the minimum of the translocatable N/P/K (supply) and the demand from the storage organs. Moreover, there is time coefficient for translocation which takes into account that there is a delay in the availability of translocatable N/P/K **Simulation parameters** ============ ============================================= ====================== Name Description Unit ============ ============================================= ====================== NMAXLV_TB Maximum N concentration in leaves as kg N kg-1 dry biomass function of DVS PMAXLV_TB As for P kg P kg-1 dry biomass KMAXLV_TB As for K kg K kg-1 dry biomass NMAXRT_FR Maximum N concentration in roots as fraction - of maximum N concentration in leaves PMAXRT_FR As for P - KMAXRT_FR As for K - NMAXST_FR Maximum N concentration in stems as fraction - of maximum N concentration in leaves PMAXST_FR As for P - KMAXST_FR As for K - NMAXSO Maximum N concentration in storage organs kg N kg-1 dry biomass PMAXSO As for P kg P kg-1 dry biomass KMAXSO As for K kg K kg-1 dry biomass NCRIT_FR Critical N concentration as fraction of - maximum N concentration for vegetative plant organs as a whole (leaves + stems) PCRIT_FR As for P - KCRIT_FR As for K - TCNT Time coefficient for N translation to days storage organs TCPT As for P days TCKT As for K days NFIX_FR fraction of crop nitrogen uptake by kg N kg-1 dry biomass biological fixation RNUPTAKEMAX Maximum rate of N uptake |kg N ha-1 d-1| RPUPTAKEMAX Maximum rate of P uptake |kg N ha-1 d-1| RKUPTAKEMAX Maximum rate of K uptake |kg N ha-1 d-1| ============ ============================================= ====================== **State variables** ============= ================================================= ==== ============ Name Description Pbl Unit ============= ================================================= ==== ============ NuptakeTotal Total N uptake by the crop N |kg N ha-1| PuptakeTotal Total P uptake by the crop N |kg N ha-1| KuptakeTotal Total K uptake by the crop N |kg N ha-1| NfixTotal Total N fixated by the crop N |kg N ha-1| NdemandST N Demand in living stems N |kg N ha-1| NdemandRT N Demand in living roots N |kg N ha-1| NdemandSO N Demand in storage organs N |kg N ha-1| PdemandLV P Demand in living leaves N |kg P ha-1| PdemandST P Demand in living stems N |kg P ha-1| PdemandRT P Demand in living roots N |kg P ha-1| PdemandSO P Demand in storage organs N |kg P ha-1| KdemandLV K Demand in living leaves N |kg K ha-1| KdemandST K Demand in living stems N |kg K ha-1| KdemandRT K Demand in living roots N |kg K ha-1| KdemandSO K Demand in storage organs N |kg K ha-1| ========== ================================================= ==== ============ **Rate variables** =========== ================================================= ==== ================ Name Description Pbl Unit =========== ================================================= ==== ================ RNuptakeLV Rate of N uptake in leaves Y |kg N ha-1 d-1| RNuptakeST Rate of N uptake in stems Y |kg N ha-1 d-1| RNuptakeRT Rate of N uptake in roots Y |kg N ha-1 d-1| RNuptakeSO Rate of N uptake in storage organs Y |kg N ha-1 d-1| RPuptakeLV Rate of P uptake in leaves Y |kg P ha-1 d-1| RPuptakeST Rate of P uptake in stems Y |kg P ha-1 d-1| RPuptakeRT Rate of P uptake in roots Y |kg P ha-1 d-1| RPuptakeSO Rate of P uptake in storage organs Y |kg P ha-1 d-1| RKuptakeLV Rate of K uptake in leaves Y |kg K ha-1 d-1| RKuptakeST Rate of K uptake in stems Y |kg K ha-1 d-1| RKuptakeRT Rate of K uptake in roots Y |kg K ha-1 d-1| RKuptakeSO Rate of K uptake in storage organs Y |kg K ha-1 d-1| RNuptake Total rate of N uptake Y |kg N ha-1 d-1| RPuptake Total rate of P uptake Y |kg P ha-1 d-1| RKuptake Total rate of K uptake Y |kg K ha-1 d-1| RNfixation Rate of N fixation Y |kg N ha-1 d-1| NdemandLV N Demand in living leaves N |kg N ha-1| NdemandST N Demand in living stems N |kg N ha-1| NdemandRT N Demand in living roots N |kg N ha-1| NdemandSO N Demand in storage organs N |kg N ha-1| PdemandLV P Demand in living leaves N |kg P ha-1| PdemandST P Demand in living stems N |kg P ha-1| PdemandRT P Demand in living roots N |kg P ha-1| PdemandSO P Demand in storage organs N |kg P ha-1| KdemandLV K Demand in living leaves N |kg K ha-1| KdemandST K Demand in living stems N |kg K ha-1| KdemandRT K Demand in living roots N |kg K ha-1| KdemandSO K Demand in storage organs N |kg K ha-1| Ndemand Total crop N demand N |kg N ha-1 d-1| Pdemand Total crop P demand N |kg P ha-1 d-1| Kdemand Total crop K demand N |kg K ha-1 d-1| =========== ================================================= ==== ================ **Signals send or handled** None **External dependencies** ================ =================================== ==================== =========== Name Description Provided by Unit ================ =================================== ==================== =========== DVS Crop development stage DVS_Phenology - TRA Crop transpiration Evapotranspiration |cm d-1| TRAMX Potential crop transpiration Evapotranspiration |cm d-1| NAVAIL Total available N from soil NPK_Soil_Dynamics |kg ha-1| PAVAIL Total available P from soil NPK_Soil_Dynamics |kg ha-1| KAVAIL Total available K from soil NPK_Soil_Dynamics |kg ha-1| Ntranslocatable Translocatable amount of N from NPK_Translocation |kg ha-1| stems, Leaves and roots Ptranslocatable As for P NPK_Translocation |kg ha-1| Ktranslocatable As for K NPK_Translocation |kg ha-1| ================ =================================== ==================== =========== """ class Parameters(ParamTemplate): NMAXLV_TB = AfgenTrait() # maximum N concentration in leaves as function of dvs PMAXLV_TB = AfgenTrait() # maximum P concentration in leaves as function of dvs KMAXLV_TB = AfgenTrait() # maximum P concentration in leaves as function of dvs NMAXRT_FR = Float(-99.) # maximum N concentration in roots as fraction of maximum N concentration in leaves PMAXRT_FR = Float(-99.) # maximum P concentration in roots as fraction of maximum P concentration in leaves KMAXRT_FR = Float(-99.) # maximum K concentration in roots as fraction of maximum K concentration in leaves NMAXST_FR = Float(-99.) # maximum N concentration in stems as fraction of maximum N concentration in leaves PMAXST_FR = Float(-99.) # maximum P concentration in stems as fraction of maximum P concentration in leaves KMAXST_FR = Float(-99.) # maximum K concentration in stems as fraction of maximum K concentration in leaves NMAXSO = Float(-99.) # maximum P concentration in storage organs [kg N kg-1 dry biomass] PMAXSO = Float(-99.) # maximum P concentration in storage organs [kg P kg-1 dry biomass] KMAXSO = Float(-99.) # maximum K concentration in storage organs [kg K kg-1 dry biomass] TCNT = Float(-99.) # time coefficient for N translocation to storage organs [days] TCPT = Float(-99.) # time coefficient for P translocation to storage organs [days] TCKT = Float(-99.) # time coefficient for K translocation to storage organs [days] NFIX_FR = Float(-99.) # fraction of crop nitrogen uptake by biological fixation RNUPTAKEMAX = Float() # Maximum N uptake rate RPUPTAKEMAX = Float() # Maximum P uptake rate RKUPTAKEMAX = Float() # Maximum K uptake rate class RateVariables(RatesTemplate): RNuptakeLV = Float(-99.) # N uptake rates in organs [kg ha-1 d -1] RNuptakeST = Float(-99.) RNuptakeRT = Float(-99.) RNuptakeSO = Float(-99.) RPuptakeLV = Float(-99.) # P uptake rates in organs [kg ha-1 d -1] RPuptakeST = Float(-99.) RPuptakeRT = Float(-99.) RPuptakeSO = Float(-99.) RKuptakeLV = Float(-99.) # K uptake rates in organs [kg ha-1 d -1] RKuptakeST = Float(-99.) RKuptakeRT = Float(-99.) RKuptakeSO = Float(-99.) RNuptake = Float(-99.) # Total N uptake rates [kg ha-1 d -1] RPuptake = Float(-99.) # For P RKuptake = Float(-99.) # For K RNfixation = Float(-99.) # Total N fixated NdemandLV = Float(-99.) # N demand in organs [kg ha-1] NdemandST = Float(-99.) NdemandRT = Float(-99.) NdemandSO = Float(-99.) PdemandLV = Float(-99.) # P demand in organs [kg ha-1] PdemandST = Float(-99.) PdemandRT = Float(-99.) PdemandSO = Float(-99.) KdemandLV = Float(-99.) # K demand in organs [kg ha-1] KdemandST = Float(-99.) KdemandRT = Float(-99.) KdemandSO = Float(-99.) Ndemand = Float() # Total N/P/K demand of the crop Pdemand = Float() Kdemand = Float() def initialize(self, day, kiosk, parvalues): """ :param day: start date of the simulation :param kiosk: variable kiosk of this PCSE instance :param parvalues: a ParameterProvider with parameter key/value pairs """ self.params = self.Parameters(parvalues) self.kiosk = kiosk self.rates = self.RateVariables(kiosk, publish=["RNuptakeLV", "RNuptakeST", "RNuptakeRT", "RNuptakeSO", "RPuptakeLV", "RPuptakeST", "RPuptakeRT", "RPuptakeSO", "RKuptakeLV", "RKuptakeST", "RKuptakeRT", "RKuptakeSO", "RNuptake", "RPuptake", "RKuptake", "RNfixation"]) @prepare_rates def calc_rates(self, day, drv): r = self.rates p = self.params k = self.kiosk delt = 1.0 mc = self._compute_NPK_max_concentrations() # Total NPK demand of leaves, stems, roots and storage organs # Demand consists of a demand carried over from previous timesteps plus a demand from new growth # Note that we are pre-integrating here, so a multiplication with time-step delt is required # N demand [kg ha-1] r.NdemandLV = max(mc.NMAXLV * k.WLV - k.NamountLV, 0.) + max(k.GRLV * mc.NMAXLV, 0) * delt r.NdemandST = max(mc.NMAXST * k.WST - k.NamountST, 0.) + max(k.GRST * mc.NMAXST, 0) * delt r.NdemandRT = max(mc.NMAXRT * k.WRT - k.NamountRT, 0.) + max(k.GRRT * mc.NMAXRT, 0) * delt r.NdemandSO = max(mc.NMAXSO * k.WSO - k.NamountSO, 0.) # P demand [kg ha-1] r.PdemandLV = max(mc.PMAXLV * k.WLV - k.PamountLV, 0.) + max(k.GRLV * mc.PMAXLV, 0) * delt r.PdemandST = max(mc.PMAXST * k.WST - k.PamountST, 0.) + max(k.GRST * mc.PMAXST, 0) * delt r.PdemandRT = max(mc.PMAXRT * k.WRT - k.PamountRT, 0.) + max(k.GRRT * mc.PMAXRT, 0) * delt r.PdemandSO = max(mc.PMAXSO * k.WSO - k.PamountSO, 0.) # K demand [kg ha-1] r.KdemandLV = max(mc.KMAXLV * k.WLV - k.KamountLV, 0.) + max(k.GRLV * mc.KMAXLV, 0) * delt r.KdemandST = max(mc.KMAXST * k.WST - k.KamountST, 0.) + max(k.GRST * mc.KMAXST, 0) * delt r.KdemandRT = max(mc.KMAXRT * k.WRT - k.KamountRT, 0.) + max(k.GRRT * mc.KMAXRT, 0) * delt r.KdemandSO = max(mc.KMAXSO * k.WSO - k.KamountSO, 0.) r.Ndemand = r.NdemandLV + r.NdemandST + r.NdemandRT r.Pdemand = r.PdemandLV + r.PdemandST + r.PdemandRT r.Kdemand = r.KdemandLV + r.KdemandST + r.KdemandRT # NPK uptake rate in storage organs (kg N ha-1 d-1) is the mimimum of supply and # demand divided by the time coefficient for N/P/K translocation r.RNuptakeSO = min(r.NdemandSO, k.Ntranslocatable)/p.TCNT r.RPuptakeSO = min(r.PdemandSO, k.Ptranslocatable)/p.TCPT r.RKuptakeSO = min(r.KdemandSO, k.Ktranslocatable)/p.TCKT # No nutrients are absorbed when severe water shortage occurs i.e. RFTRA <= 0.01 if k.RFTRA > 0.01: NutrientLIMIT = 1.0 else: NutrientLIMIT = 0. # biological nitrogen fixation r.RNfixation = (max(0., p.NFIX_FR * r.Ndemand) * NutrientLIMIT) # NPK uptake rate from soil r.RNuptake = (max(0., min(r.Ndemand - r.RNfixation, k.NAVAIL, p.RNUPTAKEMAX)) * NutrientLIMIT) r.RPuptake = (max(0., min(r.Pdemand, k.PAVAIL, p.RPUPTAKEMAX)) * NutrientLIMIT) r.RKuptake = (max(0., min(r.Kdemand, k.KAVAIL, p.RKUPTAKEMAX)) * NutrientLIMIT) # NPK uptake rate for different organs weighted as fraction of total demand # if no demand then uptake rate = 0. if r.Ndemand == 0.: r.RNuptakeLV = r.RNuptakeST = r.RNuptakeRT = 0. else: r.RNuptakeLV = (r.NdemandLV / r.Ndemand) * (r.RNuptake + r.RNfixation) r.RNuptakeST = (r.NdemandST / r.Ndemand) * (r.RNuptake + r.RNfixation) r.RNuptakeRT = (r.NdemandRT / r.Ndemand) * (r.RNuptake + r.RNfixation) if r.Pdemand == 0.: r.RPuptakeLV = r.RPuptakeST = r.RPuptakeRT = 0. else: r.RPuptakeLV = (r.PdemandLV / r.Pdemand) * r.RPuptake r.RPuptakeST = (r.PdemandST / r.Pdemand) * r.RPuptake r.RPuptakeRT = (r.PdemandRT / r.Pdemand) * r.RPuptake if r.Kdemand == 0.: r.RKuptakeLV = r.RKuptakeST = r.RKuptakeRT = 0. else: r.RKuptakeLV = (r.KdemandLV / r.Kdemand) * r.RKuptake r.RKuptakeST = (r.KdemandST / r.Kdemand) * r.RKuptake r.RKuptakeRT = (r.KdemandRT / r.Kdemand) * r.RKuptake @prepare_states def integrate(self, day, delt=1.0): pass def _compute_NPK_max_concentrations(self): """Computes the maximum N/P/K concentrations in leaves, stems, roots and storage organs. Note that max concentrations are first derived from the dilution curve for leaves. Maximum concentrations for stems and roots are computed as a fraction of the concentration for leaves. Maximum concentration for storage organs is directly taken from the parameters N/P/KMAXSO. """ p = self.params k = self.kiosk NMAXLV = p.NMAXLV_TB(k.DVS) PMAXLV = p.PMAXLV_TB(k.DVS) KMAXLV = p.KMAXLV_TB(k.DVS) max_NPK_conc = MaxNutrientConcentrations( # Maximum NPK concentrations in leaves [kg N kg-1 DM] NMAXLV=NMAXLV, PMAXLV=PMAXLV, KMAXLV=KMAXLV, # Maximum NPK concentrations in stems and roots [kg N kg-1 DM] NMAXST=(p.NMAXST_FR * NMAXLV), NMAXRT=p.NMAXRT_FR * NMAXLV, NMAXSO=p.NMAXSO, PMAXST=p.PMAXST_FR * PMAXLV, PMAXRT=p.PMAXRT_FR * PMAXLV, PMAXSO=p.PMAXSO, KMAXST=p.KMAXST_FR * KMAXLV, KMAXRT=p.KMAXRT_FR * KMAXLV, KMAXSO=p.KMAXSO ) return max_NPK_conc