Source code for hestia_earth.calculation.emissions.noxToAirFertilizerAndExcretaStehfestBouwman2006

import numpy as np
from hestia_earth.calculation.abstract_model import Model
from hestia_earth.calculation.utils import most_relevant_measurement, residue_nitrogen, summation, primary_product
from hestia_earth.calculation.data.constants.nox import NOX_FACTORS_BY_CLIMATE_ZONE, DRY_MATTER_FACTOR_TO_NOX
from hestia_earth.calculation.data.constants.generic import ATOMIC_WEIGHT_CONVERSIONS
from hestia_earth.utils.api import download_hestia

MODEL_KEY = 'noxToAirFertilizerAndExcretaStehfestBouwman2006'


[docs]class NOXToAirFertilizerAndExcretaStehfestBouwman2006(Model): def __init__(self): # Define model tier self.tier = 2 self.term = download_hestia(MODEL_KEY) # Define model requirements self.nitrogenContent = None self.eco_ClimateZone = None self.crop_name = None self.inorgN_total = None self.orgN_total = None self.excretaN_total = None self.res_nitrogen = None self.N_total = None # Instantiate variables self.noxToAirInorganicFertilizer = None self.noxToAirOrganicFertilizer = None self.noxToAirExcreta = None self.noxToAirCropResidueDecomposition = None self.noxToAirAllOrigins = None # Define model coefficients self.crop_nox_n = NOX_FACTORS_BY_CLIMATE_ZONE self.conv_non_no = ATOMIC_WEIGHT_CONVERSIONS['Conv_Mol_NON_NO'] self.drymatter_to_nox = DRY_MATTER_FACTOR_TO_NOX def calculate_noxToAirInorganicFertilizer(self): self.noxToAirInorganicFertilizer = \ self.calculate_noxToAirAllOrigins() * self.inorgN_total / self.N_total return self.noxToAirInorganicFertilizer def calculate_noxToAirOrganicFertilizer(self): self.noxToAirOrganicFertilizer = self.calculate_noxToAirAllOrigins() * self.orgN_total / self.N_total return self.noxToAirOrganicFertilizer def calculate_noxToAirExcreta(self): self.noxToAirExcreta = self.calculate_noxToAirAllOrigins() * self.excretaN_total / self.N_total return self.noxToAirExcreta def calculate_noxToAirCropResidueDecomposition(self): self.noxToAirCropResidueDecomposition = \ self.calculate_noxToAirAllOrigins() * self.res_nitrogen / self.N_total return self.noxToAirCropResidueDecomposition def calculate_noxToAirAllOrigins(self): self.noxToAirAllOrigins = min( 0.025 * self.N_total, np.exp(-0.451 + 0.0061 * self.N_total + (0 if self.nitrogenContent / 1000000 < 0.0005 else -1.0211 if self.nitrogenContent / 1000000 <= 0.002 else 0.7892) + self.crop_nox_n[str(self.eco_ClimateZone)]) - np.exp(-0.451 + (0 if self.nitrogenContent / 1000000 < 0.0005 else -1.0211 if self.nitrogenContent / 1000000 <= 0.002 else 0.7892) + self.crop_nox_n[str(self.eco_ClimateZone)])) * self.conv_non_no return self.noxToAirAllOrigins def get_total_n(self, cycle): inputs = cycle["inputs"].evalues() N_total = summation([sum(input["value"]) if "units" in input["term"] and input["term"]["units"] == "kg N" else {} for input in inputs]) return [N_total] def complete(self, completeness): self.inorgN_total = 0 if self.inorgN_total == {} and completeness['fertilizer'] else self.inorgN_total self.orgN_total = 0 if self.orgN_total == {} and completeness['fertilizer'] else self.orgN_total self.excretaN_total = 0 if self.excretaN_total == {} and completeness['products'] else self.excretaN_total self.res_nitrogen = 0 if self.res_nitrogen == {} and completeness['cropResidue'] else self.res_nitrogen self.N_total = 0 if self.N_total == {} and completeness['fertilizer'] and completeness['products'] and\ completeness['cropResidue'] else self.N_total def check_noxToAirInorganicFertilizer(self, cycle): inputs = cycle['inputs'].evalues() self.inorgN_total = summation([sum(input['value']) if 'units' in input['term'] and input['term']['units'] == 'kg N' and input['term']['termType'] == 'inorganicFertilizer' else {} for input in inputs]) self.complete(cycle['dataCompleteness']) return self.inorgN_total != {} and self.check_noxToAirAllOrigins(cycle) and self.N_total != 0 def check_noxToAirOrganicFertilizer(self, cycle): inputs = cycle['inputs'].evalues() self.orgN_total = summation([sum(input['value']) if 'units' in input['term'] and input['term']['units'] == 'kg N' and input['term']['termType'] == 'organicFertilizer' else {} for input in inputs]) self.complete(cycle['dataCompleteness']) return self.orgN_total != {} and self.check_noxToAirAllOrigins(cycle) and self.N_total != 0 def check_noxToAirCropResidueDecomposition(self, cycle): self.res_nitrogen = residue_nitrogen(cycle['products']) self.complete(cycle['dataCompleteness']) return self.res_nitrogen != {} and self.check_noxToAirAllOrigins(cycle) and self.N_total != 0 def check_noxToAirExcreta(self, cycle): products = cycle["products"].evalues() self.excretaN_total = summation([sum(product["value"]) if "units" in product["term"] and product["term"]["units"] == "kg N" and product["term"]["termType"] == "animalProduct" else {} for product in products]) self.complete(cycle['dataCompleteness']) return self.excretaN_total != {} and self.check_noxToAirAllOrigins(cycle) and self.N_total != 0 def check_noxToAirAllOrigins(self, cycle): self.eco_ClimateZone = most_relevant_measurement(cycle['site']['measurements']['eco-ClimateZone'], cycle['endDate']) self.nitrogenContent = most_relevant_measurement(cycle['site']['measurements']['soilTotalNitrogenContent'], cycle['endDate']) product = primary_product(cycle['products']) if cycle['products'] != {} else {} self.crop_name = product['term']['name'] if product != {} else {} self.N_total = summation(self.get_total_n(cycle) + [residue_nitrogen(cycle['products'])]) self.complete(cycle['dataCompleteness']) return self.N_total != {} and self.nitrogenContent != {} and self.eco_ClimateZone != {} and self.crop_name != {}