Loading OpenSimRoot/InputFiles/templates/plantTemplate.IncludeLeafSenescence.xml +15 −10 Original line number Diff line number Diff line Loading @@ -29,24 +29,29 @@ note that this requires historical information on leave area, so the garbage col name="senescedLeafDryWeight" unit="g" function="leafSenescence" /> <!-- these are optional and can be renamed, the code does not use them --> <SimulaDerivative name="leafArea_green" function="useFormula"> <SimulaConstant name="formula" type="string"> leafArea - senescedLeafArea </SimulaConstant> </SimulaDerivative> <SimulaDerivative name="leafDryWeight_green" function="useFormula"> <SimulaConstant name="formula" type="string"> leafDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaDerivative name="greenLeafArea" unit="cm2" function="useFormula"> <SimulaConstant name="formula" type="string"> leafArea - senescedLeafArea </SimulaConstant> </SimulaDerivative> </SimulaDirective> <SimulaDirective path="/plants"> <SimulaVariable name="senescedLeafArea" function="sumOverAllPlantShoots" unit="cm2" /> </SimulaDirective> <SimulaDirective path="/plantTemplate"> <SimulaDerivative name="shootDryWeight_green" function="useFormula"> <SimulaDerivative name="greenShootDryWeight" function="useFormula"> <SimulaConstant name="formula" type="string"> shootDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaBase name="variablePaths"> <SimulaConstant name="senescedLeafDryWeight" type="string"> plantPosition/shoot/senescedLeafDryWeight </SimulaConstant> </SimulaBase> </SimulaDerivative> <SimulaDerivative name="plantDryWeight_green" function="useFormula"> <SimulaDerivative name="greenPlantDryWeight" function="useFormula"> <SimulaConstant name="formula" type="string"> plantDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaBase name="variablePaths"> <SimulaConstant name="senescedLeafDryWeight" type="string"> plantPosition/shoot/senescedLeafDryWeight </SimulaConstant> Loading OpenSimRoot/src/engine/SimulaBase.cpp +70 −39 Original line number Diff line number Diff line Loading @@ -412,42 +412,21 @@ SimulaBase* SimulaBase::existingSibling(const std::string& name,const Unit& u){ SimulaBase* SimulaBase::getPath(const std::string &name, const Time &t){ SimulaBase *probe(getPath(name)); if(!probe->evaluateTime(t)) msg::error("SimulaBase::getPath: path "+getPath()+'/'+name+" found but life time is not correct."); SimulaBase *probe(existingPath(name,t)); if(!probe) msg::error("SimulaBase::getPath: path "+getPath()+name+" not found"); return probe; } SimulaBase* SimulaBase::getPath(const std::string &name, const Unit &u){ SimulaBase *probe(getPath(name)); probe->checkUnit(u); SimulaBase *probe(existingPath(name,u)); if(!probe) { std::string p(name[0]=='/'?"":getPath()); msg::error("SimulaBase::getPath: path "+p+name+" not found"); } return probe; } SimulaBase* SimulaBase::getPath(const std::string &name){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->get(*it); }else{ msg::error("SimulaBase::getPath: path "+getPath()+'/'+name+" not found. "+probe->getPath()+" has no children."); } } } SimulaBase *probe(existingPath(name)); if(!probe) msg::error("SimulaBase::getPath: path "+getPath()+name+" not found"); return probe; } Loading Loading @@ -475,7 +454,9 @@ SimulaBase* SimulaBase::getOneOfThesePathsIfExisting(const std::string &name0, return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name){ SimulaBase* SimulaBase::existingPath(const std::string &name, const Time &t){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); Loading @@ -496,7 +477,7 @@ SimulaBase* SimulaBase::existingPath(const std::string &name){ }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); probe=l->existing(*it,t); }else{ probe=nullptr; } Loading @@ -504,14 +485,33 @@ SimulaBase* SimulaBase::existingPath(const std::string &name){ } return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name, const Time &t){ SimulaBase* probe = existingPath(name); if(probe && ! probe->evaluateTime(t)) probe=nullptr; return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name, const Unit &u){ SimulaBase* probe = existingPath(name); //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); }else{ probe=nullptr; } } } if(probe) probe->checkUnit(u); return probe; } Loading Loading @@ -628,6 +628,37 @@ void SimulaBase::stopUpdatefunction(){ if(attributes) attributes->stopUpdatefunction(); } SimulaBase* SimulaBase::existingPath(const std::string &name){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); }else{ probe=nullptr; } } } return probe; } ///@todo getNext, getFirst and getPrevious are expensive code, which could be done more elegantly? SimulaBase* SimulaBase::getNextSibling(const Time &t){ Database *a=getParent()->getChildren(); Loading OpenSimRoot/src/modules/PlantNutrients/OptimalNutrientContent.cpp +43 −11 Original line number Diff line number Diff line Loading @@ -42,13 +42,26 @@ DerivativeBase * newInstantiationUseRootClassAndNutrientSpecificTable(SimulaDyna bool OptimalNutrientContent::issueMessage(true); OptimalNutrientContent::OptimalNutrientContent(SimulaDynamic* pSD) : TotalBaseLabeled(pSD) { TotalBaseLabeled(pSD), current(nullptr), dw(nullptr), rca(nullptr), paramConc(nullptr) { std::string l(pSD->getName().substr(11, 7)); if (l[0] == 'O') l[0] = 'o'; if (l[0] == 'M') l[0] = 'm'; current = pSD->getSibling(l + "NutrientConcentration"); current = pSD->existingSibling(l + "NutrientConcentration"); if(!current){ //use parameter section to get target concentrations //plant type and root type std::string plantType; PLANTTYPE(plantType,pSD); //get the root type std::string rootType; pSD->getParent(4)->getChild("rootType")->get(rootType); SimulaBase *param=GETROOTPARAMETERS(plantType,rootType); paramConc=param->getChild(pSD->getParent()->getName())->getChild(l + "NutrientConcentration"); } //dryweight dw = pSD->getParent(2)->getChild("rootSegmentDryWeight"); Loading Loading @@ -92,15 +105,23 @@ void OptimalNutrientContent::calculate(const Time &t, double &result) { l[0] = 'o'; if (l[0] == 'M') l[0] = 'm'; SimulaBase *next = getNext(t)->getSibling(l + "NutrientConcentration"); SimulaBase *next = getNext(t); //get optimal concentrations at these datapoints double concD0(0); double concD0(0), concD1(0); if(current){ current->get(t, concD0); double concD1(concD0); next=next->getSibling(l + "NutrientConcentration"); if(next!=current && next->evaluateTime(t)){ next->get(t, concD1); } }else{ const double t0=pSD->getStartTime(); const double t1=next->getStartTime(); paramConc->get(t-t0,concD0); paramConc->get(t-t1,concD1); } //get dryweight double d; Loading @@ -124,6 +145,7 @@ void OptimalNutrientContent::calculate(const Time &t, double &result) { scale_ = result; } bool OptimalNutrientContent::postIntegrationCorrection(SimulaVariable::Table & data) { //only for old input files that expect integration, rather than a simply algabreic solution. bool r(false); //iterators SimulaVariable::Table::iterator eit(data.end()); Loading @@ -148,7 +170,7 @@ DerivativeBase * newInstantiationOptimalNutrientContent(SimulaDynamic* const pSD } ShootOptimalNutrientContent::ShootOptimalNutrientContent(SimulaDynamic* pSD) : DerivativeBase(pSD), dws(nullptr) { //leafs or stem DerivativeBase(pSD), conc(nullptr), dw(nullptr), dws(nullptr), refTime(0) { //leafs or stem std::string s(pSD->getName()); std::size_t n(s.size() - 22); std::string sp(s.substr(0, n)); Loading @@ -157,7 +179,17 @@ ShootOptimalNutrientContent::ShootOptimalNutrientContent(SimulaDynamic* pSD) : dw = pSD->getParent(2)->getChild(sp + "DryWeight", "g"); if(sp=="leaf") dws = pSD->getParent(2)->existingChild("senescedLeafDryWeight", "g"); //concentration conc = pSD->getSibling(som + "NutrientConcentration", pSD->getUnit() / "g"); conc = pSD->existingSibling(som + "NutrientConcentration", pSD->getUnit() / "g"); if(!conc){ refTime=pSD->getStartTime(); //use parameter section to get target concentrations //plant type and root type std::string plantType; PLANTTYPE(plantType,pSD); //get the root type SimulaBase *param=GETSHOOTPARAMETERS(plantType); conc = param->getChild(pSD->getParent()->getName())->getChild(som + "NutrientConcentration", pSD->getUnit() / "g"); } } void ShootOptimalNutrientContent::calculate(const Time &t, double &result) { dw->get(t, result); Loading @@ -167,7 +199,7 @@ void ShootOptimalNutrientContent::calculate(const Time &t, double &result) { result-=senescence; } double c; conc->get(t, c); conc->get(t-refTime, c); result *= c; } std::string ShootOptimalNutrientContent::getName() const { Loading OpenSimRoot/src/modules/PlantNutrients/OptimalNutrientContent.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: std::string getName() const; protected: void calculate(const Time &t, double &var); SimulaBase *current, *dw, *rca; SimulaBase *current, *dw, *rca, *paramConc; static bool issueMessage; double scale_; }; Loading @@ -50,6 +50,7 @@ public: protected: void calculate(const Time &t, double &var); SimulaBase *conc, *dw, *dws; Time refTime; }; class ActualNutrientContent: public TotalBaseLabeled { public: Loading Loading
OpenSimRoot/InputFiles/templates/plantTemplate.IncludeLeafSenescence.xml +15 −10 Original line number Diff line number Diff line Loading @@ -29,24 +29,29 @@ note that this requires historical information on leave area, so the garbage col name="senescedLeafDryWeight" unit="g" function="leafSenescence" /> <!-- these are optional and can be renamed, the code does not use them --> <SimulaDerivative name="leafArea_green" function="useFormula"> <SimulaConstant name="formula" type="string"> leafArea - senescedLeafArea </SimulaConstant> </SimulaDerivative> <SimulaDerivative name="leafDryWeight_green" function="useFormula"> <SimulaConstant name="formula" type="string"> leafDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaDerivative name="greenLeafArea" unit="cm2" function="useFormula"> <SimulaConstant name="formula" type="string"> leafArea - senescedLeafArea </SimulaConstant> </SimulaDerivative> </SimulaDirective> <SimulaDirective path="/plants"> <SimulaVariable name="senescedLeafArea" function="sumOverAllPlantShoots" unit="cm2" /> </SimulaDirective> <SimulaDirective path="/plantTemplate"> <SimulaDerivative name="shootDryWeight_green" function="useFormula"> <SimulaDerivative name="greenShootDryWeight" function="useFormula"> <SimulaConstant name="formula" type="string"> shootDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaBase name="variablePaths"> <SimulaConstant name="senescedLeafDryWeight" type="string"> plantPosition/shoot/senescedLeafDryWeight </SimulaConstant> </SimulaBase> </SimulaDerivative> <SimulaDerivative name="plantDryWeight_green" function="useFormula"> <SimulaDerivative name="greenPlantDryWeight" function="useFormula"> <SimulaConstant name="formula" type="string"> plantDryWeight - senescedLeafDryWeight </SimulaConstant> <SimulaBase name="variablePaths"> <SimulaConstant name="senescedLeafDryWeight" type="string"> plantPosition/shoot/senescedLeafDryWeight </SimulaConstant> Loading
OpenSimRoot/src/engine/SimulaBase.cpp +70 −39 Original line number Diff line number Diff line Loading @@ -412,42 +412,21 @@ SimulaBase* SimulaBase::existingSibling(const std::string& name,const Unit& u){ SimulaBase* SimulaBase::getPath(const std::string &name, const Time &t){ SimulaBase *probe(getPath(name)); if(!probe->evaluateTime(t)) msg::error("SimulaBase::getPath: path "+getPath()+'/'+name+" found but life time is not correct."); SimulaBase *probe(existingPath(name,t)); if(!probe) msg::error("SimulaBase::getPath: path "+getPath()+name+" not found"); return probe; } SimulaBase* SimulaBase::getPath(const std::string &name, const Unit &u){ SimulaBase *probe(getPath(name)); probe->checkUnit(u); SimulaBase *probe(existingPath(name,u)); if(!probe) { std::string p(name[0]=='/'?"":getPath()); msg::error("SimulaBase::getPath: path "+p+name+" not found"); } return probe; } SimulaBase* SimulaBase::getPath(const std::string &name){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->get(*it); }else{ msg::error("SimulaBase::getPath: path "+getPath()+'/'+name+" not found. "+probe->getPath()+" has no children."); } } } SimulaBase *probe(existingPath(name)); if(!probe) msg::error("SimulaBase::getPath: path "+getPath()+name+" not found"); return probe; } Loading Loading @@ -475,7 +454,9 @@ SimulaBase* SimulaBase::getOneOfThesePathsIfExisting(const std::string &name0, return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name){ SimulaBase* SimulaBase::existingPath(const std::string &name, const Time &t){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); Loading @@ -496,7 +477,7 @@ SimulaBase* SimulaBase::existingPath(const std::string &name){ }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); probe=l->existing(*it,t); }else{ probe=nullptr; } Loading @@ -504,14 +485,33 @@ SimulaBase* SimulaBase::existingPath(const std::string &name){ } return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name, const Time &t){ SimulaBase* probe = existingPath(name); if(probe && ! probe->evaluateTime(t)) probe=nullptr; return probe; } SimulaBase* SimulaBase::existingPath(const std::string &name, const Unit &u){ SimulaBase* probe = existingPath(name); //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); }else{ probe=nullptr; } } } if(probe) probe->checkUnit(u); return probe; } Loading Loading @@ -628,6 +628,37 @@ void SimulaBase::stopUpdatefunction(){ if(attributes) attributes->stopUpdatefunction(); } SimulaBase* SimulaBase::existingPath(const std::string &name){ //Separate path into list names std::list<std::string> list; std::string::size_type pos(0); //loop through the list SimulaBase* probe; Database* l; if(name[pos]=='/'){ ++pos; while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=ORIGIN; }else{ while (pos<name.size()) list.push_back(nextWord(name,pos,'/')); probe=this; } for(std::list<std::string>::iterator it(list.begin());it!=list.end() && probe!=nullptr ;++it){ if(*it==".."){ probe=probe->getParent(); }else{ l=probe->hasChildren(); if(l){ probe=l->existing(*it); }else{ probe=nullptr; } } } return probe; } ///@todo getNext, getFirst and getPrevious are expensive code, which could be done more elegantly? SimulaBase* SimulaBase::getNextSibling(const Time &t){ Database *a=getParent()->getChildren(); Loading
OpenSimRoot/src/modules/PlantNutrients/OptimalNutrientContent.cpp +43 −11 Original line number Diff line number Diff line Loading @@ -42,13 +42,26 @@ DerivativeBase * newInstantiationUseRootClassAndNutrientSpecificTable(SimulaDyna bool OptimalNutrientContent::issueMessage(true); OptimalNutrientContent::OptimalNutrientContent(SimulaDynamic* pSD) : TotalBaseLabeled(pSD) { TotalBaseLabeled(pSD), current(nullptr), dw(nullptr), rca(nullptr), paramConc(nullptr) { std::string l(pSD->getName().substr(11, 7)); if (l[0] == 'O') l[0] = 'o'; if (l[0] == 'M') l[0] = 'm'; current = pSD->getSibling(l + "NutrientConcentration"); current = pSD->existingSibling(l + "NutrientConcentration"); if(!current){ //use parameter section to get target concentrations //plant type and root type std::string plantType; PLANTTYPE(plantType,pSD); //get the root type std::string rootType; pSD->getParent(4)->getChild("rootType")->get(rootType); SimulaBase *param=GETROOTPARAMETERS(plantType,rootType); paramConc=param->getChild(pSD->getParent()->getName())->getChild(l + "NutrientConcentration"); } //dryweight dw = pSD->getParent(2)->getChild("rootSegmentDryWeight"); Loading Loading @@ -92,15 +105,23 @@ void OptimalNutrientContent::calculate(const Time &t, double &result) { l[0] = 'o'; if (l[0] == 'M') l[0] = 'm'; SimulaBase *next = getNext(t)->getSibling(l + "NutrientConcentration"); SimulaBase *next = getNext(t); //get optimal concentrations at these datapoints double concD0(0); double concD0(0), concD1(0); if(current){ current->get(t, concD0); double concD1(concD0); next=next->getSibling(l + "NutrientConcentration"); if(next!=current && next->evaluateTime(t)){ next->get(t, concD1); } }else{ const double t0=pSD->getStartTime(); const double t1=next->getStartTime(); paramConc->get(t-t0,concD0); paramConc->get(t-t1,concD1); } //get dryweight double d; Loading @@ -124,6 +145,7 @@ void OptimalNutrientContent::calculate(const Time &t, double &result) { scale_ = result; } bool OptimalNutrientContent::postIntegrationCorrection(SimulaVariable::Table & data) { //only for old input files that expect integration, rather than a simply algabreic solution. bool r(false); //iterators SimulaVariable::Table::iterator eit(data.end()); Loading @@ -148,7 +170,7 @@ DerivativeBase * newInstantiationOptimalNutrientContent(SimulaDynamic* const pSD } ShootOptimalNutrientContent::ShootOptimalNutrientContent(SimulaDynamic* pSD) : DerivativeBase(pSD), dws(nullptr) { //leafs or stem DerivativeBase(pSD), conc(nullptr), dw(nullptr), dws(nullptr), refTime(0) { //leafs or stem std::string s(pSD->getName()); std::size_t n(s.size() - 22); std::string sp(s.substr(0, n)); Loading @@ -157,7 +179,17 @@ ShootOptimalNutrientContent::ShootOptimalNutrientContent(SimulaDynamic* pSD) : dw = pSD->getParent(2)->getChild(sp + "DryWeight", "g"); if(sp=="leaf") dws = pSD->getParent(2)->existingChild("senescedLeafDryWeight", "g"); //concentration conc = pSD->getSibling(som + "NutrientConcentration", pSD->getUnit() / "g"); conc = pSD->existingSibling(som + "NutrientConcentration", pSD->getUnit() / "g"); if(!conc){ refTime=pSD->getStartTime(); //use parameter section to get target concentrations //plant type and root type std::string plantType; PLANTTYPE(plantType,pSD); //get the root type SimulaBase *param=GETSHOOTPARAMETERS(plantType); conc = param->getChild(pSD->getParent()->getName())->getChild(som + "NutrientConcentration", pSD->getUnit() / "g"); } } void ShootOptimalNutrientContent::calculate(const Time &t, double &result) { dw->get(t, result); Loading @@ -167,7 +199,7 @@ void ShootOptimalNutrientContent::calculate(const Time &t, double &result) { result-=senescence; } double c; conc->get(t, c); conc->get(t-refTime, c); result *= c; } std::string ShootOptimalNutrientContent::getName() const { Loading
OpenSimRoot/src/modules/PlantNutrients/OptimalNutrientContent.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: std::string getName() const; protected: void calculate(const Time &t, double &var); SimulaBase *current, *dw, *rca; SimulaBase *current, *dw, *rca, *paramConc; static bool issueMessage; double scale_; }; Loading @@ -50,6 +50,7 @@ public: protected: void calculate(const Time &t, double &var); SimulaBase *conc, *dw, *dws; Time refTime; }; class ActualNutrientContent: public TotalBaseLabeled { public: Loading