1 // -*- C++ -*-
2 /**
3 * @brief This is a nD function build as a product of n 1D function
4 *
5 * Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6 *
7 * This library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21 #include "openturns/ProductUniVariateFunctionGradient.hxx"
22 #include "openturns/OSS.hxx"
23 #include "openturns/PersistentObjectFactory.hxx"
24
25 BEGIN_NAMESPACE_OPENTURNS
26
27
28
29 CLASSNAMEINIT(ProductUniVariateFunctionGradient)
30
31 static const Factory<ProductUniVariateFunctionGradient> Factory_ProductUniVariateFunctionGradient;
32
33
34 /* Default constructor */
ProductUniVariateFunctionGradient()35 ProductUniVariateFunctionGradient::ProductUniVariateFunctionGradient()
36 : GradientImplementation()
37 {
38 // Nothing to do
39 }
40
41
42 /* Constructor */
ProductUniVariateFunctionGradient(const Pointer<ProductUniVariateFunctionEvaluation> & p_evaluation)43 ProductUniVariateFunctionGradient::ProductUniVariateFunctionGradient(const Pointer<ProductUniVariateFunctionEvaluation> & p_evaluation)
44 : GradientImplementation()
45 , p_evaluation_(p_evaluation)
46 {
47 // Nothing to do
48 }
49
50
51 /* Virtual constructor */
clone() const52 ProductUniVariateFunctionGradient * ProductUniVariateFunctionGradient::clone() const
53 {
54 return new ProductUniVariateFunctionGradient(*this);
55 }
56
57
58 /* String converter */
__repr__() const59 String ProductUniVariateFunctionGradient::__repr__() const
60 {
61 return OSS() << "class=" << GetClassName();
62 }
63
64
65 /* Compute the gradient of a product of univariate polynomials */
gradient(const Point & inP) const66 Matrix ProductUniVariateFunctionGradient::gradient (const Point & inP) const
67 {
68 const UnsignedInteger inDimension = inP.getDimension();
69 if (inDimension != getInputDimension()) throw InvalidArgumentException(HERE) << "Error: trying to evaluate a ProductPolynomialFunction with an argument of invalid dimension";
70 Scalar productEvaluation = 1.0;
71 Point evaluations(inDimension);
72 Point derivatives(inDimension);
73 for (UnsignedInteger i = 0; i < inDimension; ++i)
74 {
75 const Scalar x = inP[i];
76 const Scalar y = p_evaluation_->functions_[i](x);
77 const Scalar dy = p_evaluation_->functions_[i].gradient(x);
78 evaluations[i] = y;
79 derivatives[i] = dy;
80 productEvaluation *= y;
81 }
82 Matrix grad(inDimension, 1);
83 // Usual case: productEvaluation <> 0
84 if (productEvaluation != 0.0)
85 {
86 for (UnsignedInteger i = 0; i < inDimension; ++i)
87 {
88 grad(i, 0) = derivatives[i] * (productEvaluation / evaluations[i]);
89 }
90 }
91 // Must compute the gradient in a more expensive way
92 else
93 {
94 for (UnsignedInteger i = 0; i < inDimension; ++i)
95 {
96 grad(i, 0) = derivatives[i];
97 for (UnsignedInteger j = 0; j < i; ++j) grad(i, 0) *= evaluations[j];
98 for (UnsignedInteger j = i + 1; j < inDimension; ++j) grad(i, 0) *= evaluations[j];
99 }
100 }
101 return grad;
102 }
103
104
105 /* Accessor for input point dimension */
getInputDimension() const106 UnsignedInteger ProductUniVariateFunctionGradient::getInputDimension() const
107 {
108 return p_evaluation_->functions_.getSize();
109 }
110
111 /* Accessor for output point dimension */
getOutputDimension() const112 UnsignedInteger ProductUniVariateFunctionGradient::getOutputDimension() const
113 {
114 return 1;
115 }
116
117
118 /* Method save() stores the object through the StorageManager */
save(Advocate & adv) const119 void ProductUniVariateFunctionGradient::save(Advocate & adv) const
120 {
121 GradientImplementation::save(adv);
122 adv.saveAttribute("evaluation_", *p_evaluation_);
123 }
124
125 /* Method load() reloads the object from the StorageManager */
load(Advocate & adv)126 void ProductUniVariateFunctionGradient::load(Advocate & adv)
127 {
128 GradientImplementation::load(adv);
129 TypedInterfaceObject<ProductUniVariateFunctionEvaluation> evaluation;
130 adv.loadAttribute("evaluation_", evaluation);
131 p_evaluation_ = evaluation.getImplementation();
132 }
133
134
135 END_NAMESPACE_OPENTURNS
136