/*! * \brief Constructor to load external csv-File as plant database. * * \param plantDbFileStream A file stream to read csv data from. * * \code{.unparsed} * 'create filestream for csv data file * Dim fs As System.IO.FileStream = New IO.FileStream("C:\DHI\MIKE-Basin_PlantData.csv", IO.FileMode.Open) * 'create new plantDb * Dim plantDb As atbApi.data.PlantDb = New atbApi.data.PlantDb(fs) * 'important: close fileStream after PlantDb is created * fs.Close() * 'create new plant and provide your own plantDb to constructor * Dim myPlant As atbApi.data.Plant = New atbApi.data.Plant("CROPWAT_80_Crop_data_CITRUS_70p_ca_bare", plantDb) * \endcode */ public PlantDb(Stream plantDbFileStream, CultureInfo cultureInfo = null) { this.plantDbFileStream = plantDbFileStream; CsvReader csvReader = new CsvReader(plantDbFileStream); while (!csvReader.EndOfStream()) { IDictionary <String, String> fields; fields = csvReader.readLine(); //Debug.WriteLine(fields["dataObjName"] + " day: " + fields["_iterator.day"]); if (fields == null || !fields.ContainsKey("dataObjName") || String.IsNullOrEmpty(fields["dataObjName"])) { continue; } String name = fields["dataObjName"]; if (!plantData.ContainsKey(name)) { plantData.Add(name, new Dictionary <int, PlantValues>()); plantStagesLength.Add(name, 0); initialEnd.Add(name, 0); } IDictionary <int, PlantValues> plantValues = plantData[name]; PlantValues values = new PlantValues(); values.parseData(fields, cultureInfo != null ? cultureInfo : CultureInfo.InvariantCulture); int _iterator = Int32.Parse(fields["_iterator.day"], cultureInfo != null ? cultureInfo : CultureInfo.InvariantCulture); plantValues.Add(_iterator, values); plantStagesLength[name] = Math.Max(plantStagesLength[name], _iterator); if (values.stage.Equals(PlantStage.initial)) { if (!initialEnd.ContainsKey(name)) { initialEnd[name] = 0; } initialEnd[name] = Math.Max(initialEnd[name], _iterator); } if (values.stage.Equals(PlantStage.development)) { if (!developmentEnd.ContainsKey(name)) { developmentEnd[name] = 0; } developmentEnd[name] = Math.Max(developmentEnd[name], _iterator); } } }
/*! * \brief calculate evaporation. * * \param [in,out] lastConditions The last soil conditions. * \param plantSet Set the plant values. * \param climateSet Set the climate values. * \param irrigationType Type of the irrigation. * \param et0 The reference evapotranspiration. * \param eFactor The factor e is reduced by. May be used to consider mulching etc. * \param tew The totally evaporable water. * \param irrigationFw The fraction of wetted surface depending on irrigation type. * \param autoIrrigationFw The fraction of wetted surface depending on automatic irrigation type. * \param netIrrigation The netto irrigation. * \param autoNetIrrigation The automatic netto irrigation. * \param interception The interception. * \param interceptionIrr The interception of the irrigated water. * \param interceptionAutoIrr The interception of the automatic irrigated water. * \param [in,out] eResult The result of the calculation. * * \return true if it succeeds, false if it fails. */ public static bool ECalculation( ref SoilConditions lastConditions, PlantValues plantSet, ClimateValues climateSet, String irrigationType, double et0, double eFactor, double tew, double irrigationFw, double autoIrrigationFw, double netIrrigation, double autoNetIrrigation, double interception, double interceptionIrr, double interceptionAutoIrr, ref EvaporationResult eResult ) { if (eResult == null) { eResult = new EvaporationResult(); } var rewFactor = 2.2926; var kcMax = 1.2; var kcMin = 0.0; var kcb = 0.0; var fc = 0.0; if (!(plantSet.isFallow == true)) { kcb = (double)plantSet.Kcb; kcMax = 1.2 + (0.04 * ((double)climateSet.windspeed - 2) - 0.004 * ((double)climateSet.humidity - 45)) * Math.Pow(((double)plantSet.height / 3), 0.3); kcMax = Math.Max(kcMax, kcb + 0.05); kcMax = Math.Min(kcMax, 1.3); kcMax = Math.Max(kcMax, 1.05); kcMin = 0.175; fc = Math.Pow(Math.Max((kcb - kcMin), 0.01) / (kcMax - kcMin), 1 + 0.5 * (double)plantSet.height); fc = Math.Min(0.99, fc); } eResult.kcMin = kcMin; eResult.kcMax = kcMax; eResult.kcb = kcb; eResult.fc = fc; var few = Math.Min(1 - fc, Math.Min(irrigationFw, autoIrrigationFw)); if ((netIrrigation > 0 || autoNetIrrigation > 0) && (irrigationType == "drip")) { few = Math.Min(1 - fc, (1 - (2 / 3) * fc) * Math.Min(irrigationFw, autoIrrigationFw)); } eResult.few = few; eResult.tew = tew; var rew = tew / rewFactor; eResult.rew = rew; var kr = 1.0; if (lastConditions.de > rew) { kr = (tew - lastConditions.de) / (tew - rew); kr = Math.Max(0, kr); } if (rew == 0) { kr = 0; } eResult.kr = kr; var ke = Math.Min(kr * (kcMax - kcb), few * kcMax); eResult.ke = ke; var e = ke * et0; e = e * eFactor; eResult.e = e; var rpPrecipitation = climateSet.rpPrecipitation != null ? (double)climateSet.rpPrecipitation : (double)climateSet.precipitation; var netPrecititationTc = rpPrecipitation - interception + netIrrigation - interceptionIrr + autoNetIrrigation - interceptionAutoIrr; var dpe = netPrecititationTc - lastConditions.de; dpe = Math.Max(0, dpe); var de = lastConditions.de - netPrecititationTc + e / few + dpe; de = Math.Max(0, de); de = Math.Min(tew, de); lastConditions.de = de; lastConditions.dpe = dpe; eResult.de = de; eResult.dpe = dpe; return(true); }