From c6ffb7f6a32f2657b3fde229ab70a7d1456934f8 Mon Sep 17 00:00:00 2001 From: Fausto Tomei Date: Sun, 26 Nov 2023 19:22:11 +0100 Subject: [PATCH] update 3D --- crop/crop.cpp | 60 +++++++++++++-------------------- crop/crop.h | 2 +- crop/cropDbTools.cpp | 6 +++- interpolation/interpolation.cpp | 9 ++--- snow/snow.cpp | 3 +- utilities/utilities.cpp | 7 ++++ utilities/utilities.h | 1 + 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/crop/crop.cpp b/crop/crop.cpp index 8b030d153..385e3c19a 100644 --- a/crop/crop.cpp +++ b/crop/crop.cpp @@ -51,14 +51,9 @@ void Crit3DCrop::clear() idCrop = ""; type = HERBACEOUS_ANNUAL; - /*! - * \brief roots - */ roots.clear(); - /*! - * \brief crop cycle - */ + // crop cycle sowingDoy = NODATA; currentSowingDoy = NODATA; doyStartSenescence = NODATA; @@ -74,17 +69,13 @@ void Crit3DCrop::clear() degreeDaysDecrease = NODATA; degreeDaysEmergence = NODATA; - /*! - * \brief water need - */ + // water need kcMax = NODATA; psiLeaf = NODATA; stressTolerance = NODATA; fRAW = NODATA; - /*! - * \brief irrigation - */ + // irrigation irrigationShift = NODATA; irrigationVolume = NODATA; degreeDaysStartIrrigation = NODATA; @@ -93,9 +84,7 @@ void Crit3DCrop::clear() doyEndIrrigation = NODATA; maxSurfacePuddle = NODATA; - /*! - * \brief variables - */ + // variables isLiving = false; isEmerged = false; LAIstartSenescence = NODATA; @@ -330,7 +319,7 @@ bool Crit3DCrop::isRootStatic() const /*! * \brief getSurfaceWaterPonding - * \return maximum height of water ponding [mm] + * \return maximum height of water pond [mm] */ double Crit3DCrop::getSurfaceWaterPonding() const { @@ -406,7 +395,7 @@ bool Crit3DCrop::needReset(Crit3DDate myDate, double latitude, double waterTable // reset of (already initialized) crop -// TODO: smart start (using sowing doy and cycle) +// TODO: smart start (using meteo settings) void Crit3DCrop::resetCrop(unsigned int nrLayers) { // roots @@ -452,7 +441,7 @@ bool Crit3DCrop::dailyUpdate(const Crit3DDate &myDate, double latitude, const st unsigned int nrLayers = unsigned(soilLayers.size()); - // check start/end crop cycle (update isLiving) + // check start/end crop cycle if (needReset(myDate, latitude, waterTableDepth)) { resetCrop(nrLayers); @@ -520,29 +509,26 @@ bool Crit3DCrop::restore(const Crit3DDate &myDate, double latitude, const std::v } -// Liangxia Zhang, Zhongmin Hu, Jiangwen Fan, Decheng Zhou & Fengpei Tang, 2014 -// A meta-analysis of the canopy light extinction coefficient in terrestrial ecosystems -// "Cropland had the highest value of K (0.62), followed by broadleaf forest (0.59), -// shrubland (0.56), grassland (0.50), and needleleaf forest (0.45)" -double Crit3DCrop::getSurfaceCoverFraction() +/*! \brief getCoveredSurfaceFraction + * \ref Liangxia Zhang, Zhongmin Hu, Jiangwen Fan, Decheng Zhou & Fengpei Tang, 2014 + * A meta-analysis of the canopy light extinction coefficient in terrestrial ecosystems + * "Cropland had the highest value of K (0.62), followed by broadleaf forest (0.59) + * shrubland (0.56), grassland (0.50), and needleleaf forest (0.45)" + * \return covered surface fraction [-] + */ +double Crit3DCrop::getCoveredSurfaceFraction() { - double k = 0.6; // [-] light extinction coefficient + if (idCrop == "" || ! isLiving || LAI < EPSILON) return 0; - if (idCrop == "" || ! isLiving || LAI < EPSILON) - { - return 0; - } - else - { - return 1 - exp(-k * LAI); - } + double k = 0.6; // [-] light extinction coefficient + return 1 - exp(-k * LAI); } double Crit3DCrop::getMaxEvaporation(double ET0) { - double evapMax = ET0 * (1.0 - getSurfaceCoverFraction()); - // TODO check + double evapMax = ET0 * (1.0 - getCoveredSurfaceFraction()); + // TODO check evaporation on free water return evapMax * 0.66; } @@ -552,9 +538,9 @@ double Crit3DCrop::getMaxTranspiration(double ET0) if (idCrop == "" || ! isLiving || LAI < EPSILON) return 0; - double SCF = this->getSurfaceCoverFraction(); - double kcmaxFactor = 1 + (kcMax - 1) * SCF; - return ET0 * (SCF * kcmaxFactor); + double coverSurfFraction = getCoveredSurfaceFraction(); + double kcFactor = 1 + (kcMax - 1) * coverSurfFraction; + return ET0 * coverSurfFraction * kcFactor; } diff --git a/crop/crop.h b/crop/crop.h index 35766f176..55a9b4aff 100644 --- a/crop/crop.h +++ b/crop/crop.h @@ -95,7 +95,7 @@ bool restore(const Crit3DDate &myDate, double latitude, const std::vector &soilLayers, double currentWaterTable, std::string &myError); - double getSurfaceCoverFraction(); + double getCoveredSurfaceFraction(); double getMaxEvaporation(double ET0); double getMaxTranspiration(double ET0); double getSurfaceWaterPonding() const; diff --git a/crop/cropDbTools.cpp b/crop/cropDbTools.cpp index c7358a32e..6904172b7 100644 --- a/crop/cropDbTools.cpp +++ b/crop/cropDbTools.cpp @@ -67,7 +67,11 @@ bool loadCropParameters(const QSqlDatabase &dbCrop, QString idCrop, Crit3DCrop & myCrop.roots.rootDepthMax = query.value("root_depth_max").toDouble(); myCrop.roots.actualRootDepthMax = myCrop.roots.rootDepthMax; - if (! getValue(query.value("roots_additional_cohesion"), &(myCrop.roots.rootsAdditionalCohesion))) + if (fieldExists(query, "roots_additional_cohesion")) + { + getValue(query.value("roots_additional_cohesion"), &(myCrop.roots.rootsAdditionalCohesion)); + } + else { // default: no mechanical effect of roots myCrop.roots.rootsAdditionalCohesion = 0; diff --git a/interpolation/interpolation.cpp b/interpolation/interpolation.cpp index 74262544e..d76526227 100644 --- a/interpolation/interpolation.cpp +++ b/interpolation/interpolation.cpp @@ -23,7 +23,6 @@ ftomei@arpae.it */ -#include #include #include #include @@ -1172,7 +1171,7 @@ float retrend(meteoVariable myVar, vector myProxyValues, Crit3DInterpola if (! getUseDetrendingVar(myVar)) return 0.; - float retrendValue = 0.; + double retrendValue = 0.; double myProxyValue; Crit3DProxy* myProxy = nullptr; Crit3DProxyCombination myCombination = mySettings->getCurrentCombination(); @@ -1223,7 +1222,7 @@ float retrend(meteoVariable myVar, vector myProxyValues, Crit3DInterpola } } - return retrendValue; + return float(retrendValue); } @@ -1395,6 +1394,7 @@ std::vector getfittingParameters(Crit3DProxyCombination myCombination, return myParam; } + bool multipleDetrending(std::vector &myPoints, Crit3DInterpolationSettings* mySettings, meteoVariable myVar) { if (! getUseDetrendingVar(myVar)) return false; @@ -1519,7 +1519,7 @@ bool multipleDetrending(std::vector &myPoints, Cr setFittingParameters(myCombination, mySettings, myFunc, parametersMin, parametersMax, parametersDelta, parameters); // multiple non linear fitting - int nSteps = interpolation::bestFittingMarquardt_nDimension(&functionSum, myFunc, 10000, 5, parametersMin, parametersMax, parameters, parametersDelta, + interpolation::bestFittingMarquardt_nDimension(&functionSum, myFunc, 10000, 5, parametersMin, parametersMax, parameters, parametersDelta, 100, EPSILON, 0.01, predictors, predictands, false, weights); mySettings->setFittingFunction(myFunc); @@ -1547,6 +1547,7 @@ bool multipleDetrending(std::vector &myPoints, Cr return true; } + void topographicDistanceOptimize(meteoVariable myVar, Crit3DMeteoPoint* &myMeteoPoints, int nrMeteoPoints, diff --git a/snow/snow.cpp b/snow/snow.cpp index eb5d46301..85e050705 100644 --- a/snow/snow.cpp +++ b/snow/snow.cpp @@ -392,7 +392,8 @@ void Crit3DSnow::computeSnowBrooksModel() double freeze_melt = 0; // [mm] freeze (positive) or melt (negative) // pag.53 (3.25) - /*! net amount of liquid water that freezes (heat added to the snow pack) and ice that melts (heat removed from the snow pack) */ + /*! net amount of liquid water that freezes (heat added to the snow pack) + * and ice that melts (heat removed from the snow pack) */ double w = (prevInternalEnergy + QTotal) / (LATENT_HEAT_FUSION * WATER_DENSITY); // [m] if (w < 0) { diff --git a/utilities/utilities.cpp b/utilities/utilities.cpp index 3f100d208..78b82876b 100644 --- a/utilities/utilities.cpp +++ b/utilities/utilities.cpp @@ -46,6 +46,13 @@ QList getFieldsUpperCase(const QSqlQuery& query) } +bool fieldExists(const QSqlQuery &query, const QString fieldName) +{ + QList fieldList = getFieldsUpperCase(query); + return fieldList.contains(fieldName.toUpper()); +} + + // return boolean (false if recordset is not valid) bool getValue(QVariant myRs) { diff --git a/utilities/utilities.h b/utilities/utilities.h index 134fa0042..47a5c88f0 100644 --- a/utilities/utilities.h +++ b/utilities/utilities.h @@ -30,6 +30,7 @@ QList getFields(QSqlDatabase* db_, QString tableName); QList getFields(const QSqlQuery& query); QList getFieldsUpperCase(const QSqlQuery &query); + bool fieldExists(const QSqlQuery &query, const QString fieldName); bool getValue(QVariant myRs); bool getValue(QVariant myRs, int* myValue);