mbsim  4.0.0
MBSim Kernel
demuxing_argument_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 _NESTED_FUNCTION_H_
21#define _NESTED_FUNCTION_H_
22
23#include "mbsim/functions/function.h"
24
25namespace MBSim {
26
27 template<typename Sig> class DemuxingArgumentFunction;
28
35 template<typename Ret, typename Arg>
36 class DemuxingArgumentFunction<Ret(Arg)> : public Function<Ret(Arg)> {
37 using B = Function<Ret(Arg)>;
38 public:
39 DemuxingArgumentFunction() = default;
40 DemuxingArgumentFunction(Function<Ret(double)> *f1_, Function<Ret(double,double)> *f2_) {
41 set1ArgFunction(f1_);
42 set2ArgFunction(f2_);
43 }
44 ~DemuxingArgumentFunction() override {
45 delete fo1;
46 delete fo2;
47 }
48 int getArgSize() const override { return argDim; }
49 std::pair<int, int> getRetSize() const override {
50 return fo1?fo1->getRetSize():fo2->getRetSize();
51 }
52 Ret operator()(const Arg &arg) override {
53 const double& a1 = arg(argIdx1);
54 if( fo1 )
55 return (*fo1)(a1);
56 const double& a2 = arg(argIdx2);
57 return (*fo2)(a1,a2);
58 }
59 typename B::DRetDArg parDer(const Arg &arg) override {
60 // we might need that return value for dimensioning
61 const auto& v1 = fo1 ? fo1->parDer(arg(argIdx1)) : fo2->parDer1(arg(argIdx1),arg(argIdx2));
62
63 initTmp(v1, arg);
64
65 if( fo1 )
66 {
67 if constexpr (std::is_same_v<Ret, double>)
68 tmp(argIdx1) = v1;
69 else
70 tmp.set(argIdx1, v1);
71 }
72 else
73 {
74 const auto& v2 = fo2->parDer2(arg(argIdx1),arg(argIdx2));
75 if constexpr (std::is_same_v<Ret, double>)
76 {
77 tmp(argIdx1) = v1;
78 tmp(argIdx2) = v2;
79 }
80 else
81 {
82 tmp.set(argIdx1, v1);
83 tmp.set(argIdx2, v2);
84 }
85 }
86 return tmp;
87 }
88 typename B::DRetDArg parDerDirDer(const Arg &argDir, const Arg &arg) override {
89 const auto& v11 = fo1 ? fo1->parDerDirDer(argDir(argIdx1), arg(argIdx1)) :
90 fo2->parDer1DirDer1(argDir(argIdx1), arg(argIdx1),arg(argIdx2));
91
92 initTmp(v11, arg);
93
94 if( fo1 )
95 {
96 if constexpr (std::is_same_v<Ret, double>)
97 tmp(argIdx1) = v11;
98 else
99 tmp.set(argIdx1, v11);
100 }
101 else
102 {
103 const auto& v22 = fo2->parDer2DirDer2(argDir(argIdx2), arg(argIdx1),arg(argIdx2));
104 const auto& v12 = fo2->parDer1DirDer2(argDir(argIdx2), arg(argIdx1),arg(argIdx2));
105 const auto& v21 = fo2->parDer2DirDer1(argDir(argIdx1), arg(argIdx1),arg(argIdx2));
106 if constexpr (std::is_same_v<Ret, double>)
107 {
108 tmp(argIdx1) = v11 + v12;
109 tmp(argIdx2) = v21 + v22;
110 }
111 else
112 {
113 tmp.set(argIdx1, v11 + v12);
114 tmp.set(argIdx2, v21 + v22);
115 }
116 }
117 return tmp;
118 }
119 void setArgumentIndex1(size_t argIdx1_) { argIdx1 = argIdx1_; }
120 void setArgumentIndex2(size_t argIdx2_) { argIdx2 = argIdx2_; }
121 void set1ArgFunction(Function<Ret(double)> *fo_) {
122 fo1 = fo_;
123 fo1->setParent(this);
124 fo1->setName("OneArgumentFunction");
125 }
126 void set2ArgFunction(Function<Ret(double,double)> *fo_) {
127 fo2 = fo_;
128 fo2->setParent(this);
129 fo2->setName("TwoArgumentFunction");
130 }
131 void setArgDim(size_t d) {
132 argDim = d;
133 }
134 void initializeUsingXML(xercesc::DOMElement *element) override {
135 if(MBXMLUtils::E(element)->hasAttribute("argDim"))
136 setArgDim(boost::lexical_cast<size_t>(MBXMLUtils::E(element)->getAttribute("argDim")));
137 xercesc::DOMElement *e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"oneArgumentFunction");
138 if(e)
139 set1ArgFunction(ObjectFactory::createAndInit<Function<Ret(double)>>(e->getFirstElementChild()));
140 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"twoArgumentFunction");
141 if(e)
142 set2ArgFunction(ObjectFactory::createAndInit<Function<Ret(double,double)>>(e->getFirstElementChild()));
143 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"argumentIndex1");
144 if(e)
145 setArgumentIndex1(MBXMLUtils::E(e)->getText<size_t>()-1);// flatxml is 1-based
146 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"argumentIndex2");
147 if(e)
148 setArgumentIndex2(MBXMLUtils::E(e)->getText<size_t>()-1);// flatxml is 1-based
149 }
150 void init(Element::InitStage stage, const InitConfigSet &config) override {
151 Function<Ret(Arg)>::init(stage, config);
152 if(fo1) fo1->init(stage, config);
153 if(fo2) fo2->init(stage, config);
154 }
155 private:
156 Function<Ret(double)> *fo1{nullptr};
157 Function<Ret(double,double)> *fo2{nullptr};
158 size_t argDim { 0 };
159 size_t argIdx1 { 0 };
160 size_t argIdx2 { 0 };
161 typename B::DRetDArg tmp;
162 void initTmp(const typename std::remove_pointer_t<decltype(fo1)>::DRetDArg &s1, const Arg &s2) {
163 // resize and initialize class member tmp
164 if(tmp.rows() == 0 || tmp.cols() == 0)
165 {
166 if constexpr (std::is_same_v<Ret, double>)
167 tmp.resize(/*1 ,*/ s2.rows());
168 else
169 tmp.resize(s1.rows() , s2.rows());
170 tmp.init(0.0);
171 }
172 }
173 };
174}
175
176#endif
void init(Element::InitStage stage, const InitConfigSet &config) override
plots time series header
Definition: demuxing_argument_function.h:150
Definition: demuxing_argument_function.h:27
InitStage
The stages of the initialization.
Definition: element.h:63
Definition: function.h:53
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:103
namespace MBSim
Definition: bilateral_constraint.cc:30