mbsim  4.0.0
MBSim Kernel
piecewise_defined_function.h
1/* Copyright (C) 2004-2014 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@gmail.com
18 */
19
20#ifndef _PIECEWISE_DEFINED_FUNCTIONS_H_
21#define _PIECEWISE_DEFINED_FUNCTIONS_H_
22
23#include "mbsim/functions/function.h"
24#include "mbsim/utils/utils.h"
25
26namespace MBSim {
27
28 template<typename Sig> class LimitedFunction;
29
30 template <typename Ret, typename Arg>
31 struct LimitedFunction<Ret(Arg)> {
32 LimitedFunction(Function<Ret(Arg)> *function_, double limit_) : function(function_), limit(limit_) { }
33 Function<Ret(Arg)> *function;
34 double limit;
35 };
36
37 template<typename Sig> class PiecewiseDefinedFunction;
38
39 template<typename Ret, typename Arg>
40 class PiecewiseDefinedFunction<Ret(Arg)> : public Function<Ret(Arg)> {
41 using B = fmatvec::Function<Ret(Arg)>;
42 public:
43 PiecewiseDefinedFunction() { a.push_back(0); }
44 ~PiecewiseDefinedFunction() override {
45 for(unsigned int i=0; i<function.size(); i++)
46 delete function[i];
47 }
48 void addLimitedFunction(const LimitedFunction<Ret(Arg)> &limitedFunction) {
49 function.push_back(limitedFunction.function);
50 limitedFunction.function->setParent(this);
51 a.push_back(limitedFunction.limit);
52 }
53 int getArgSize() const override { return 1; }
54 std::pair<int, int> getRetSize() const override { return function.size()?function[0]->getRetSize():std::make_pair(0,1); }
55 Ret operator()(const Arg &x) override {
56 if(firstCall) {
57 firstCall = false;
58 y0.resize(a.size(),0.0*(*function[0])(Arg(1)));
59 if(shiftOrdinate) {
60 for(unsigned int i=1; i<a.size(); i++)
61 y0[i] = (*this)(FromDouble<Arg>::cast(a[i]));
62 }
63 }
64 for(unsigned int i=0; i<function.size(); i++) {
65 if(ToDouble<Arg>::cast(x)<=a[i+1])
66 return y0[i] + (*function[i])(x-FromDouble<Arg>::cast(x0[i]));
67 }
68 this->throwError("(PiecewiseDefinedFunction::operator()): x out of range! x= "+fmatvec::toString(x)+", upper bound= "+fmatvec::toString(a[function.size()]));
69 }
70 typename B::DRetDArg parDer(const Arg &x) override {
71 for(unsigned int i=0; i<function.size(); i++)
72 if(ToDouble<Arg>::cast(x)<=a[i+1])
73 return function[i]->parDer(x-FromDouble<Arg>::cast(x0[i]));
74 this->throwError("(PiecewiseDefinedFunction::parDer): x out of range! x= "+fmatvec::toString(x)+", upper bound= "+fmatvec::toString(a[function.size()]));
75 }
76 typename B::DRetDArg parDerDirDer(const Arg &xDir, const Arg &x) override {
77 for(unsigned int i=0; i<function.size(); i++)
78 if(ToDouble<Arg>::cast(x)<=a[i+1])
79 return function[i]->parDerDirDer(xDir,x-FromDouble<Arg>::cast(x0[i]));
80 this->throwError("(PiecewiseDefinedFunction::parDerDirDer): x out of range! x= "+fmatvec::toString(x)+", upper bound= "+fmatvec::toString(a[function.size()]));
81 }
82
83 void initializeUsingXML(xercesc::DOMElement *element) override {
84 xercesc::DOMElement *e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"limitedFunctions");
85 xercesc::DOMElement *ee=e->getFirstElementChild();
86 while(ee && MBXMLUtils::E(ee)->getTagName()==MBSIM%"LimitedFunction") {
87 addLimitedFunction(LimitedFunction<Ret(Arg)>(ObjectFactory::createAndInit<Function<Ret(Arg)>>(MBXMLUtils::E(ee)->getFirstElementChildNamed(MBSIM%"function")->getFirstElementChild()),MBXMLUtils::E(MBXMLUtils::E(ee)->getFirstElementChildNamed(MBSIM%"limit"))->getText<double>()));
88 ee=ee->getNextElementSibling();
89 }
90 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"shiftAbscissa");
91 if(e) shiftAbscissa=MBXMLUtils::E(e)->getText<bool>();
92 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"shiftOrdinate");
93 if(e) shiftOrdinate=MBXMLUtils::E(e)->getText<bool>();
94 }
95 void init(Element::InitStage stage, const InitConfigSet &config) override {
96 Function<Ret(Arg)>::init(stage, config);
97 for(auto it=function.begin(); it!=function.end(); it++)
98 (*it)->init(stage, config);
99 if(stage==Element::preInit) {
100 if(shiftAbscissa) {
101 for(unsigned int i=1; i<a.size(); i++)
102 a[i] += a[i-1];
103 x0 = a;
104 }
105 else
106 x0.resize(a.size());
107 }
108 }
109 private:
110 std::vector<Function<Ret(Arg)> *> function;
111 std::vector<double> a, x0;
112 std::vector<Ret> y0;
113 bool shiftAbscissa{false}, shiftOrdinate{false}, firstCall{true};
114 };
115
116}
117
118#endif
InitStage
The stages of the initialization.
Definition: element.h:62
@ preInit
Definition: element.h:64
Definition: utils.h:89
Definition: function.h:53
Definition: piecewise_defined_function.h:28
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:103
void init(Element::InitStage stage, const InitConfigSet &config) override
plots time series header
Definition: piecewise_defined_function.h:95
Definition: piecewise_defined_function.h:37
Definition: utils.h:61
namespace MBSim
Definition: bilateral_constraint.cc:30