1 /*! 2 * \file src/Math/DifferentiatedFunctionExpr.cxx 3 * \brief 4 * 5 * \author Thomas Helfer 6 * \date 02 oct 2007 7 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 8 * reserved. 9 * This project is publicly released under either the GNU GPL Licence 10 * or the CECILL-A licence. A copy of thoses licences are delivered 11 * with the sources of TFEL. CEA or EDF may also distribute this 12 * project under specific licensing conditions. 13 */ 14 15 #include <sstream> 16 #include <stdexcept> 17 18 #include "TFEL/Raise.hxx" 19 #include "TFEL/Math/Parser/Number.hxx" 20 #include "TFEL/Math/Parser/Variable.hxx" 21 #include "TFEL/Math/Parser/BinaryOperator.hxx" 22 #include "TFEL/Math/Parser/ExternalFunctionExpr2.hxx" 23 #include "TFEL/Math/Parser/DifferentiatedFunctionExpr.hxx" 24 25 namespace tfel { 26 27 namespace math { 28 29 namespace parser { 30 DifferentiatedFunctionExpr(std::shared_ptr<ExternalFunction> ff,std::vector<std::shared_ptr<Expr>> & fargs,const std::vector<std::vector<double>::size_type> & fpvar)31 DifferentiatedFunctionExpr::DifferentiatedFunctionExpr( 32 std::shared_ptr<ExternalFunction> ff, 33 std::vector<std::shared_ptr<Expr>>& fargs, 34 const std::vector<std::vector<double>::size_type>& fpvar) 35 : f(std::move(ff)), args(fargs), pvar(fpvar) { 36 raise_if(f->getNumberOfVariables() != args.size(), 37 "DifferentiatedFunctionExpr::DifferentiatedFunctionExpr: " 38 "invalid number of arguments for function " 39 "(" + 40 std::to_string(this->args.size()) + " given, " + 41 std::to_string(f->getNumberOfVariables()) + " required)"); 42 } // end of DifferentiatedFunctionExpr::DifferentiatedFunctionExpr 43 44 std::shared_ptr<ExternalFunction> getDerivative() const45 DifferentiatedFunctionExpr::getDerivative() const { 46 auto df = this->f; 47 for (const auto& p : this->pvar) { 48 df = df->differentiate(p); 49 } 50 return df; 51 } // end of DifferentiatedFunctionExpr::getDerivative 52 getValue() const53 double DifferentiatedFunctionExpr::getValue() const { 54 auto df = this->getDerivative(); 55 decltype(this->args.size()) i = 0u; 56 for (const auto& a : this->args) { 57 const auto val = a->getValue(); 58 df->setVariableValue(i, val); 59 ++i; 60 } 61 return df->getValue(); 62 } // end of DifferentiatedFunctionExpr::getValue 63 getCxxFormula(const std::vector<std::string> &) const64 std::string DifferentiatedFunctionExpr::getCxxFormula( 65 const std::vector<std::string>&) const { 66 tfel::raise( 67 "DifferentiatedFunctionExpr::getCxxFormula: " 68 "unimplemented feature"); 69 } // end of DifferentiatedFunctionExpr::getCxxFormula 70 checkCyclicDependency(std::vector<std::string> & names) const71 void DifferentiatedFunctionExpr::checkCyclicDependency( 72 std::vector<std::string>& names) const { 73 std::vector<std::string> v(names); 74 this->f->checkCyclicDependency(names); 75 for (const auto& a : this->args) { 76 std::vector<std::string> n(v); 77 a->checkCyclicDependency(n); 78 mergeVariablesNames(names, n); 79 } 80 } // end of DifferentiatedFunctionExpr::checkCyclicDependency 81 differentiate(const std::vector<double>::size_type pos,const std::vector<double> & v) const82 std::shared_ptr<Expr> DifferentiatedFunctionExpr::differentiate( 83 const std::vector<double>::size_type pos, 84 const std::vector<double>& v) const { 85 std::vector<std::shared_ptr<Expr>> nargs(this->args.size()); 86 auto p = this->args.begin(); 87 unsigned short i = 0; 88 if (args.empty()) { 89 return std::make_shared<Number>("0", 0.); 90 } 91 auto p4 = nargs.begin(); 92 for (const auto& a : this->args) { 93 *p4 = a->clone(v); 94 ++p4; 95 } 96 auto ndf = this->getDerivative(); 97 auto df_ = std::make_shared<ExternalFunctionExpr2>( 98 ndf->differentiate(i), nargs); 99 std::shared_ptr<Expr> df = std::make_shared<BinaryOperation<OpMult>>( 100 df_, (*p)->differentiate(pos, v)); 101 ++p; 102 ++i; 103 while (p != this->args.end()) { 104 df_ = std::make_shared<ExternalFunctionExpr2>(ndf->differentiate(i), 105 nargs); 106 std::shared_ptr<Expr> df2 = std::make_shared<BinaryOperation<OpMult>>( 107 df_, (*p)->differentiate(pos, v)); 108 df = std::make_shared<BinaryOperation<OpPlus>>(df, df2); 109 ++p; 110 ++i; 111 } 112 return df; 113 } // end of DifferentiatedFunctionExpr::differentiate 114 clone(const std::vector<double> & v) const115 std::shared_ptr<Expr> DifferentiatedFunctionExpr::clone( 116 const std::vector<double>& v) const { 117 std::vector<std::shared_ptr<Expr>> nargs(this->args.size()); 118 auto p = nargs.begin(); 119 for (const auto& a : this->args) { 120 *p = a->clone(v); 121 } 122 return std::make_shared<DifferentiatedFunctionExpr>(this->f, nargs, 123 this->pvar); 124 } // end of DifferentiatedFunctionExpr::clone 125 126 std::shared_ptr<Expr> DifferentiatedFunctionExpr:: createFunctionByChangingParametersIntoVariables(const std::vector<double> & v,const std::vector<std::string> & params,const std::map<std::string,std::vector<double>::size_type> & pos) const127 createFunctionByChangingParametersIntoVariables( 128 const std::vector<double>& v, 129 const std::vector<std::string>& params, 130 const std::map<std::string, std::vector<double>::size_type>& pos) 131 const { 132 using namespace std; 133 vector<shared_ptr<Expr>> nargs; 134 vector<string> vnames; 135 shared_ptr<ExternalFunction> nf; 136 vector<shared_ptr<Expr>>::const_iterator p; 137 vector<shared_ptr<Expr>>::iterator p2; 138 map<string, vector<double>::size_type>::const_iterator p3; 139 vector<string>::size_type i; 140 nf = this->f->createFunctionByChangingParametersIntoVariables( 141 vnames, v, params, pos); 142 raise_if(nf->getNumberOfVariables() <= this->args.size(), 143 "ExternalFunctionExpr::getValue: " 144 "internal error (function has less variable after " 145 "'createFunctionByChangingParametersIntoVariables' " 146 "than before"); 147 nargs.resize(nf->getNumberOfVariables()); 148 for (p = this->args.begin(), p2 = nargs.begin(); p != this->args.end(); 149 ++p, ++p2) { 150 *p2 = (*p)->createFunctionByChangingParametersIntoVariables(v, params, 151 pos); 152 } 153 for (i = 0; i != vnames.size(); ++i) { 154 p3 = pos.find(vnames[i]); 155 raise_if(p3 == pos.end(), 156 "ExternalFunctionExpr::" 157 "createFunctionByChangingParametersIntoVariables: " 158 "internal error (no position found for " 159 "parameter '" + 160 vnames[i] + "')"); 161 nargs[args.size() + i] = 162 shared_ptr<Expr>(new Variable(v, p3->second)); 163 } 164 return shared_ptr<Expr>( 165 new DifferentiatedFunctionExpr(nf, nargs, this->pvar)); 166 } // end of 167 // DifferentiatedFunctionExpr::createFunctionByChangingParametersIntoVariables 168 getParametersNames(std::set<std::string> & p) const169 void DifferentiatedFunctionExpr::getParametersNames( 170 std::set<std::string>& p) const { 171 this->f->getParametersNames(p); 172 for (const auto& a : this->args) { 173 a->getParametersNames(p); 174 } 175 } // end of DifferentiatedFunctionExpr::getParametersNames 176 resolveDependencies(const std::vector<double> & v) const177 std::shared_ptr<Expr> DifferentiatedFunctionExpr::resolveDependencies( 178 const std::vector<double>& v) const { 179 using namespace std; 180 vector<shared_ptr<Expr>> nargs(this->args.size()); 181 vector<shared_ptr<Expr>>::const_iterator p; 182 vector<shared_ptr<Expr>>::iterator p2; 183 for (p = this->args.begin(), p2 = nargs.begin(); p != this->args.end(); 184 ++p, ++p2) { 185 *p2 = (*p)->resolveDependencies(v); 186 } 187 return std::make_shared<ExternalFunctionExpr2>(this->getDerivative(), 188 nargs); 189 } // end of DifferentiatedFunctionExpr::resolveDependencies 190 191 DifferentiatedFunctionExpr::~DifferentiatedFunctionExpr() = default; 192 193 } // end of namespace parser 194 195 } // end of namespace math 196 197 } // end of namespace tfel 198