Rev 191 | Rev 210 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 191 | Rev 209 | ||
---|---|---|---|
Line 62... | Line 62... | ||
62 | } // while query.next() |
62 | } // while query.next() |
63 | qDebug() << "loaded" << mSpecies.count() << "active species:"; |
63 | qDebug() << "loaded" << mSpecies.count() << "active species:"; |
64 | qDebug() << mSpecies.keys(); |
64 | qDebug() << mSpecies.keys(); |
65 | 65 | ||
66 | mSetupQuery = 0; |
66 | mSetupQuery = 0; |
- | 67 | ||
- | 68 | // setup nitrogen response
|
|
- | 69 | XmlHelper resp(xml.node("model.species.nitrogenResponseClasses")); |
|
- | 70 | if (!resp.isValid()) |
|
- | 71 | throw IException("model.species.nitrogenResponseClasses not present!"); |
|
- | 72 | mNitrogen_1a = resp.valueDouble("class_1_a"); |
|
- | 73 | mNitrogen_1b = resp.valueDouble("class_1_b"); |
|
- | 74 | mNitrogen_2a = resp.valueDouble("class_2_a"); |
|
- | 75 | mNitrogen_2b = resp.valueDouble("class_2_b"); |
|
- | 76 | mNitrogen_3a = resp.valueDouble("class_3_a"); |
|
- | 77 | mNitrogen_3b = resp.valueDouble("class_3_b"); |
|
- | 78 | if (mNitrogen_1a*mNitrogen_1b*mNitrogen_2a*mNitrogen_2b*mNitrogen_3a*mNitrogen_3b == 0) |
|
- | 79 | throw IException("at least one parameter of model.species.nitrogenResponseClasses is not valid (value=0)!"); |
|
- | 80 | ||
- | 81 | // setup CO2 response
|
|
- | 82 | XmlHelper co2(xml.node("model.species.CO2Response")); |
|
- | 83 | mCO2base = co2.valueDouble("baseConcentration"); |
|
- | 84 | mCO2comp = co2.valueDouble("compensationPoint"); |
|
- | 85 | mCO2beta0 = co2.valueDouble("beta0"); |
|
- | 86 | mCO2p0 = co2.valueDouble("p0"); |
|
- | 87 | if (mCO2base*mCO2comp*(mCO2base-mCO2comp)*mCO2beta0*mCO2p0==0) |
|
- | 88 | throw IException("at least one parameter of model.species.CO2Response is not valid!"); |
|
- | 89 | ||
67 | return mSpecies.count(); |
90 | return mSpecies.count(); |
68 | 91 | ||
69 | }
|
92 | }
|
70 | /** retrieves variables from the datasource available during the setup of species.
|
93 | /** retrieves variables from the datasource available during the setup of species.
|
71 | */
|
94 | */
|
Line 79... | Line 102... | ||
79 | throw IException(QString("SpeciesSet: variable not set: %1").arg(varName)); |
102 | throw IException(QString("SpeciesSet: variable not set: %1").arg(varName)); |
80 | //throw IException(QString("load species parameter: field %1 not found!").arg(varName));
|
103 | //throw IException(QString("load species parameter: field %1 not found!").arg(varName));
|
81 | // lookup in defaults
|
104 | // lookup in defaults
|
82 | //qDebug() << "variable" << varName << "not found - using default.";
|
105 | //qDebug() << "variable" << varName << "not found - using default.";
|
83 | //return GlobalSettings::instance()->settingDefaultValue(varName);
|
106 | //return GlobalSettings::instance()->settingDefaultValue(varName);
|
- | 107 | }
|
|
- | 108 | ||
- | 109 | inline double SpeciesSet::nitrogenResponse(const double &availableNitrogen, const double &NA, const double &NB) const |
|
- | 110 | {
|
|
- | 111 | if (availableNitrogen<=NB) |
|
- | 112 | return 0; |
|
- | 113 | double x = 1. - exp(NA * (availableNitrogen-NB)); |
|
- | 114 | return x; |
|
- | 115 | }
|
|
- | 116 | ||
- | 117 | /// calculate nitrogen response for a given amount of available nitrogen and a respone class
|
|
- | 118 | /// for fractional values, the response value is interpolated between the fixedly defined classes (1,2,3)
|
|
- | 119 | double SpeciesSet::nitrogenResponse(const double availableNitrogen, const double &responseClass) const |
|
- | 120 | {
|
|
- | 121 | double value1, value2, value3; |
|
- | 122 | if (responseClass>2.) { |
|
- | 123 | if (responseClass==3.) |
|
- | 124 | return nitrogenResponse(availableNitrogen, mNitrogen_3a, mNitrogen_3b); |
|
- | 125 | else { |
|
- | 126 | // interpolate between 2 and 3
|
|
- | 127 | value2 = nitrogenResponse(availableNitrogen, mNitrogen_2a, mNitrogen_2b); |
|
- | 128 | value3 = nitrogenResponse(availableNitrogen, mNitrogen_3a, mNitrogen_3b); |
|
- | 129 | return value2 + (responseClass-2)*(value3-value2); |
|
- | 130 | }
|
|
- | 131 | }
|
|
- | 132 | if (responseClass==2) |
|
- | 133 | return nitrogenResponse(availableNitrogen, mNitrogen_2a, mNitrogen_2b); |
|
- | 134 | if (responseClass==1) |
|
- | 135 | return nitrogenResponse(availableNitrogen, mNitrogen_1a, mNitrogen_1b); |
|
- | 136 | // last ressort: interpolate between 1 and 2
|
|
- | 137 | value1 = nitrogenResponse(availableNitrogen, mNitrogen_1a, mNitrogen_1b); |
|
- | 138 | value2 = nitrogenResponse(availableNitrogen, mNitrogen_2a, mNitrogen_2b); |
|
- | 139 | return value1 + (responseClass-1)*(value2-value1); |
|
- | 140 | }
|
|
- | 141 | ||
- | 142 | /** calculation for the CO2 response for the ambientCO2 for the water- and nitrogen responses given.
|
|
- | 143 | The calculation follows Friedlingsstein 1995 (see also links to equations in code)
|
|
- | 144 | */
|
|
- | 145 | double SpeciesSet::co2Response(const double ambientCO2, const double nitrogenResponse, const double soilWaterResponse) const |
|
- | 146 | {
|
|
- | 147 | double co2_water = 2. - soilWaterResponse; |
|
- | 148 | double beta = mCO2beta0 * co2_water * nitrogenResponse; |
|
- | 149 | ||
- | 150 | double r =1. + M_LN2 * beta; // NPP increase for a doubling of atmospheric CO2 (Eq. 17) |
|
- | 151 | ||
- | 152 | // fertilization function (cf. Farquhar, 1980) based on Michaelis-Menten expressions
|
|
- | 153 | double deltaC = mCO2base - mCO2comp; |
|
- | 154 | double K2 = ((2*mCO2base - mCO2comp) - r*deltaC ) / ((r-1.)*deltaC*(2*mCO2base - mCO2comp)); // Eq. 16 |
|
- | 155 | double K1 = (1. + K2*deltaC) / deltaC; |
|
- | 156 | ||
- | 157 | double response = mCO2p0 * K1*(ambientCO2 - mCO2comp) / (1 + K2*(ambientCO2-mCO2comp)); // Eq. 16 |
|
- | 158 | return response; |
|
- | 159 | ||
84 | }
|
160 | }
|