mbsim  4.0.0
MBSim Kernel
piecewise_polynom_function.h
1/* Copyright (C) 2004-2009 MBSim Development Team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * Contact: martin.o.foerg@googlemail.com
18 */
19
20#ifndef PIECEWISE_POLYNOM
21#define PIECEWISE_POLYNOM
22
23#include "fmatvec/fmatvec.h"
24#include "mbsim/functions/function.h"
25#include "mbsim/utils/utils.h"
26#include "mbsim/utils/eps.h"
27#include "mbsim/mbsim_event.h"
28
29namespace MBSim {
30
31 template<typename Sig> class PiecewisePolynomFunction;
32
62 template<typename Ret, typename Arg>
63 class PiecewisePolynomFunction<Ret(Arg)> : public MBSim::Function<Ret(Arg)> {
64 protected:
65 using B = fmatvec::Function<Ret(Arg)>;
66
67 public:
68 enum InterpolationMethod {
69 cSplinePeriodic,
70 cSplineNatural,
71 piecewiseLinear,
72 useBreaksAndCoefs
73 };
74
75 enum ExtrapolationMethod {
76 error,
77 continuePolynom,
78 linear,
79 };
80
81 PiecewisePolynomFunction() : index(0), interpolationMethod(cSplineNatural), extrapolationMethod(error), f(this), fd(this), fdd(this) { }
82 virtual ~PiecewisePolynomFunction() = default;
83
84 int getArgSize() const { return 1; }
85
86 std::pair<int, int> getRetSize() const { return std::make_pair(coefs[0].cols(),1); }
87
88 void init(Element::InitStage stage, const InitConfigSet &config=InitConfigSet()) {
89 Function<Ret(Arg)>::init(stage, config);
90 if(stage==Element::preInit) {
91 if(interpolationMethod!=useBreaksAndCoefs) {
92 if(y.rows() != x.size())
93 this->throwError("Dimension missmatch in size of x");
94 for(int i=1; i<x.size(); i++)
95 if(x(i) <= x(i-1))
96 this->throwError("Values of x must be strictly monotonic increasing!");
97 calculateSpline();
98 }
99 else {
100 for(int i=1; i<breaks.size(); i++)
101 if(breaks(i) < breaks(i-1))
102 this->throwError("Values of breaks must be monotonic increasing!");
103 for(int j=0; j<static_cast<int>(coefs.size()); j++) {
104 if(coefs[j].rows()!=breaks.size()-1)
105 this->throwError("Dimension missmatch in size of breaks and rows of coefficients!");
106 if(coefs[0].cols()!=coefs[j].cols())
107 this->throwError("Dimension missmatch in columns of coefficients!");
108 }
109
110 // remove duplicate entries from breaks
111 std::set<int> removeIdx;
112 for(int i=0; i<breaks.size()-1; ++i)
113 if(breaks(i)==breaks(i+1))
114 removeIdx.emplace(i);
115 if(!removeIdx.empty()) {
116 auto breaksOld(std::move(breaks));
117 auto coefsOld(std::move(coefs));
118 breaks.resize(breaksOld.size()-removeIdx.size());
119 coefs.resize(coefsOld.size());
120 for(auto &c : coefs)
121 c.resize(coefsOld[0].rows()-removeIdx.size(),coefsOld[0].cols());
122 int ii=0, i=0;
123 for(i=0; i<breaksOld.size()-1; ++i) {
124 if(removeIdx.find(i)!=removeIdx.end())
125 continue;
126 breaks(ii)=breaksOld(i);
127 for(int o=0; o<static_cast<int>(coefs.size()); o++)
128 coefs[o].set(ii,coefsOld[o].row(i));
129 ++ii;
130 }
131 breaks(ii)=breaksOld(i);
132 }
133
134 }
135 nPoly = (coefs[0]).rows();
136 order = coefs.size()-1;
137 }
138 }
139
140 void calculateSpline() {
141 if(interpolationMethod == cSplinePeriodic) calculateSplinePeriodic();
142 else if(interpolationMethod == cSplineNatural) calculateSplineNatural();
143 else if(interpolationMethod == piecewiseLinear) calculatePLinear();
144 else this->throwError("(PiecewisePolynomFunction::init): No valid method to calculate pp-form");
145 }
146
147 void reset() {
148 index = 0;
149 f.reset();
150 fd.reset();
151 fdd.reset();
152 coefs.clear();
153 }
154
155 Ret operator()(const Arg &x) { return f(ToDouble<Arg>::cast(x)); }
156
157 // we do not use B::DRetDArg as return type here since SWIG cannot wrap the propably
158 // -> hence we resolve B::DRetDArg manually here to fmatvec::Der<Ret, Arg>::type
159 typename fmatvec::Der<Ret, Arg>::type parDer(const Arg &x) { return fd(ToDouble<Arg>::cast(x)); }
160 typename fmatvec::Der<Ret, Arg>::type parDerDirDer(const Arg &argDir, const Arg &arg) { return fdd(ToDouble<Arg>::cast(arg))*ToDouble<Arg>::cast(argDir); }
161
165 fmatvec::VecV getBreaks() { return breaks; }
166
177 void setInterpolationMethod(InterpolationMethod method_) { interpolationMethod = method_; }
178
179 void setExtrapolationMethod(ExtrapolationMethod method_) { extrapolationMethod = method_; }
180
181 void setx(const fmatvec::VecV &x_) { x <<= x_; }
182 void sety(const fmatvec::MatV &y_) { y <<= y_; }
183 void setxy(const fmatvec::MatV &xy) {
184 if(xy.cols() <= 1)
185 this->throwError("Dimension missmatch in size of xy");
186 x <<= xy.col(0);
187 y <<= xy(fmatvec::RangeV(0, xy.rows() - 1), fmatvec::RangeV(1, xy.cols() - 1));
188 }
189
194 void setCoefficientsArray(const std::vector<fmatvec::MatV> &allCoefs);
195
196 void addCoefficients(const fmatvec::MatV &coef);
197
202 void setBreaks(const fmatvec::VecV &breaks_u) {
203 interpolationMethod=useBreaksAndCoefs;
204 breaks <<= breaks_u;
205 }
206
211 virtual void initializeUsingXML(xercesc::DOMElement *element);
212
213 protected:
217 std::vector<fmatvec::MatV> coefs;
218
222 fmatvec::VecV breaks;
223
227 int nPoly;
228
232 int order;
233
237 int index;
238
239 fmatvec::VecV x;
240 fmatvec::MatV y;
241
245 InterpolationMethod interpolationMethod;
246
247 ExtrapolationMethod extrapolationMethod;
248
255
262
263 /*
264 * \brief calculation of piecewise linear interpolation
265 * \param interpolated arguments
266 * \param interpolated function values
267 *
268 * the first derivative is weak and the second derivative is zero elsewhere although it should be distributionally at the corners
269 */
270 void calculatePLinear();
271
272#ifndef SWIG
276 class ZerothDerivative {
277 public:
278 ZerothDerivative(PiecewisePolynomFunction<Ret(Arg)> *polynom) : parent(polynom), xSave(0), ySave(), firstCall(true) {}
279
280 void reset() { firstCall = true; }
281
282 Ret operator()(const double &x);
283
284 private:
285 PiecewisePolynomFunction<Ret(Arg)> *parent;
286 double xSave;
287 fmatvec::VecV ySave;
288 bool firstCall;
289 };
290
294 class FirstDerivative {
295 public:
296 FirstDerivative(PiecewisePolynomFunction<Ret(Arg)> *polynom) : parent(polynom), xSave(0), ySave(), firstCall(true) {}
297
298 void reset() { firstCall = true; }
299
300 Ret operator()(const double& x);
301
302 private:
303 PiecewisePolynomFunction<Ret(Arg)> *parent;
304 double xSave;
305 fmatvec::VecV ySave;
306 bool firstCall;
307 };
308
312 class SecondDerivative {
313 public:
314 SecondDerivative(PiecewisePolynomFunction<Ret(Arg)> *polynom) : parent(polynom), xSave(0), ySave(), firstCall(true) {}
315
316 void reset() { firstCall = true; }
317
318 Ret operator()(const double& x);
319
320 private:
321 PiecewisePolynomFunction<Ret(Arg)> *parent;
322 double xSave;
323 fmatvec::VecV ySave;
324 bool firstCall;
325 };
326#endif
327
328 private:
329 ZerothDerivative f;
330 FirstDerivative fd;
331 SecondDerivative fdd;
332 };
333
334 // the code is moved to piecewise_polynom_function_impl to avoid SWIG parsing errors
335 #include "piecewise_polynom_function_impl.h"
336
337}
338
339#endif /* PPOLYNOM */
InitStage
The stages of the initialization.
Definition: element.h:62
@ preInit
Definition: element.h:64
Definition: function.h:53
void setBreaks(const fmatvec::VecV &breaks_u)
set interval boundaries
Definition: piecewise_polynom_function.h:202
void calculateSplinePeriodic()
calculation of periodic spline by interpolation
fmatvec::VecV getBreaks()
Definition: piecewise_polynom_function.h:165
fmatvec::VecV breaks
vector of breaks (interval boundaries)
Definition: piecewise_polynom_function.h:222
std::vector< fmatvec::MatV > coefs
vector of polynomial coefficents
Definition: piecewise_polynom_function.h:217
void calculateSplineNatural()
calculation of natural spline by interpolation
void setCoefficientsArray(const std::vector< fmatvec::MatV > &allCoefs)
set polynomial coefficients
int nPoly
number of defined piecewise polynomials
Definition: piecewise_polynom_function.h:227
int index
for internal use in ppeval functions
Definition: piecewise_polynom_function.h:237
int order
order of polynomial (3 for cubic polynomials)
Definition: piecewise_polynom_function.h:232
void init(Element::InitStage stage, const InitConfigSet &config=InitConfigSet())
plots time series header
Definition: piecewise_polynom_function.h:88
InterpolationMethod interpolationMethod
interpolation interpolationMethod
Definition: piecewise_polynom_function.h:245
void setInterpolationMethod(InterpolationMethod method_)
set interpolation
Definition: piecewise_polynom_function.h:177
virtual void initializeUsingXML(xercesc::DOMElement *element)
initialize function with XML code
Definition: piecewise_polynom_function.h:31
namespace MBSim
Definition: bilateral_constraint.cc:30