MicroModelicaCCompiler  4.5.3
equation_printer.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  This file is part of QSS Solver.
4 
5  QSS Solver is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  QSS Solver is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QSS Solver. If not, see <http://www.gnu.org/licenses/>.
17 
18  ******************************************************************************/
19 
20 #include "equation_printer.hpp"
21 
22 #include <boost/optional/optional_io.hpp>
23 #include <sstream>
24 
25 #include <ast/ast_builder.hpp>
26 #include <ast/equation.hpp>
27 #include <ast/expression.hpp>
28 #include <ast/parser/parse.hpp>
29 #include <ir/annotation.hpp>
30 #include <ir/alg_usage.hpp>
31 #include <ir/derivative.hpp>
32 #include <ir/equation.hpp>
33 #include <ir/helpers.hpp>
34 #include <util/error.hpp>
35 #include <util/model_config.hpp>
36 #include <util/util.hpp>
37 #include <util/visitors/get_index_variables.hpp>
38 #include <util/visitors/is_recursive_def.hpp>
39 #include <util/visitors/replace_der.hpp>
40 #include <util/visitors/revert_index.hpp>
41 
42 namespace MicroModelica {
43 using namespace Util;
44 using namespace Deps;
45 namespace IR {
46 
47 EquationPrinter* getPrinter(Equation eq)
48 {
49  switch (eq.type()) {
51  return new ClassicPrinter(eq);
52  case EQUATION::Output:
53  return new OutputPrinter(eq);
55  return new AlgebraicPrinter(eq);
57  return new DependencyPrinter(eq);
59  return new ZeroCrossingPrinter(eq);
60  default:
61  return new DerivativePrinter(eq);
62  }
63 }
64 
65 EquationPrinter::EquationPrinter(Equation eq) : _identifier(), _id(eq.id()), _type(eq.type()), _lhs(eq.lhs()), _alg_code(eq.algCode())
66 {
67  setup(eq);
68 }
69 
71 {
72  stringstream buffer;
73  if (eq.hasRange()) {
74  Option<Variable> var = eq.LHSVariable();
75  if (var) {
76  buffer << *var;
77  }
78  _identifier = buffer.str();
79  } else {
80  buffer << "_eval" << eq.lhs();
81  _identifier = buffer.str();
82  }
83  const bool QSS_EQS = eq.type() == EQUATION::QSSDerivative || eq.type() == EQUATION::ZeroCrossing;
86 }
87 
89 
90 std::multimap<std::string, int> EquationPrinter::usedVariables() const { return _used_variables; }
91 
92 string EquationPrinter::equationId() const
93 {
94  stringstream buffer;
95  buffer << "_eq_" << _id;
96  return buffer.str();
97 }
98 
99 string EquationPrinter::lhs(int order) const
100 {
101  stringstream buffer;
102  switch (_type) {
103  case EQUATION::Algebraic:
108  buffer << exp;
109  break;
110  }
112  Expression exp = Expression(_lhs.expression(), 1);
113  buffer << exp;
114  break;
115  }
117  if (ModelConfig::instance().isQss()) {
118  buffer << "(" << order << ")";
119  }
120  break;
121  }
122  default:
123  return "";
124  }
125  return buffer.str();
126 }
127 
128 string EquationPrinter::prefix() const
129 {
130  switch (_type) {
133  return "_der";
135  return "_zc";
136  case EQUATION::Output:
137  return "_out";
140  return "_eval_dep";
141  default:
142  return "";
143  }
144  return "";
145 }
146 
148  : EquationPrinter(eq), _fact_init(2), _id(eq.id()), _range(eq.range()), _lhs(eq.lhs()), _rhs(eq.rhs())
149 {
150  initializeDerivatives();
151 }
152 
153 string DerivativePrinter::macro() const
154 {
155  stringstream buffer;
156  if (_range) {
157  stringstream apply_buffer;
158  GetIndexVariables index_usage;
159  FunctionPrinter function_printer;
160  RangeDefinitionTable range_def = _range->definition();
161  apply_buffer << "#define _apply_usage" << equationId();
162  apply_buffer << "(" << _lhs.dimVariables() << ") \\" << endl;
163  multimap<string, int> usage = index_usage.apply(_lhs.expression());
164  int i = 1, size = usage.size();
165  for (auto index : usage) {
166  apply_buffer << TAB << index.first << " = " << _range->getDimensionVar(index.second) << ";";
167  apply_buffer << ((i + 1 <= size) ? "\\" : "");
168  apply_buffer << endl;
169  i++;
170  }
171  buffer << apply_buffer.str();
172  buffer << function_printer.equationVariableMacros(_range, _lhs, equationId());
173  }
174  return buffer.str();
175 }
176 
178 {
180  ExpressionDerivator ed;
181  ReplaceDer replace_der;
182  AST_Expression exp1 = ed.derivate(_rhs.expression(), _rhs);
183  _derivatives[0] = Expression(exp1);
184  AST_Expression exp2 = ed.derivate(exp1, _rhs);
185  _derivatives[1] = Expression(replace_der.apply(exp2));
186  AST_Expression exp3 = ed.derivate(exp2, _rhs);
187  _derivatives[2] = Expression(replace_der.apply(exp3));
188  }
189 }
190 
191 string DerivativePrinter::generateDerivatives(string tabs, int init) const
192 {
193  ModelConfig config = ModelConfig::instance();
194  if (config.generateDerivatives()) {
195  stringstream buffer;
196  int order = config.order() - 1;
197  int fact = _fact_init;
198  const bool POLY_COEFF = _fact_init > 0;
199  for (int i = 0; i < order; i++) {
200  buffer << tabs << prefix() << lhs(init + i) << " = ";
201  if (POLY_COEFF) {
202  buffer << "(";
203  }
204  buffer << _derivatives[i];
205  if (POLY_COEFF) {
206  buffer << ")/" << fact;
207  }
208  buffer << ";";
209  if (i + 1 < order) {
210  buffer << endl;
211  fact *= fact + 1;
212  }
213  }
214  return buffer.str();
215  }
216  return "";
217 }
218 
219 string DerivativePrinter::print() const
220 {
221  stringstream buffer;
222  string tabs = "";
223  FunctionPrinter printer;
224  string arguments;
225  tabs += TAB;
226  if (_range) {
227  tabs = _range->block();
228  arguments = _lhs.dimVariables();
229  }
230  tabs += TAB;
231  buffer << printer.beginExpression(identifier(), _range);
232  buffer << algCode();
233  buffer << printer.beginDimGuards(equationId(), arguments, _range, usedVariables());
234  buffer << tabs << prefix() << lhs() << " = " << _rhs << ";" << endl;
235  buffer << generateDerivatives(tabs) << endl;
236  buffer << endl << TAB << printer.endDimGuards(_range);
237  buffer << TAB << printer.endExpression(_range, returnStm());
238  return buffer.str();
239 }
240 
241 ClassicPrinter::ClassicPrinter(Equation eq) : DerivativePrinter(eq), _range(eq.range()), _rhs(eq.rhs()) {}
242 
243 string ClassicPrinter::print() const
244 {
245  stringstream buffer;
246  string block = "";
247  if (_range) {
248  buffer << _range.get();
249  block = _range->block();
250  }
251  buffer << block << prefix() << lhs() << " = " << _rhs << ";";
252  if (_range) {
253  buffer << endl << _range.get().end();
254  }
255  return buffer.str();
256 }
257 
258 OutputPrinter::OutputPrinter(Equation eq) : DerivativePrinter(eq), _id(eq.id()), _range(eq.range()), _rhs(eq.rhs()){};
259 
261 {
262  stringstream buffer;
263  buffer << "_out_exp_" << _id;
264  return buffer.str();
265 }
266 
267 string OutputPrinter::print() const
268 {
269  stringstream buffer;
270  string block = "";
271  FunctionPrinter fp;
272  string arguments;
273  block += TAB;
274  if (_range) {
275  block = _range->block();
276  arguments = _range->getDimensionVarsString();
277  }
278  block += TAB;
279  buffer << fp.beginExpression(identifier(), _range);
280  buffer << fp.beginDimGuards(equationId(), arguments, _range, usedVariables());
281  buffer << algCode();
282  buffer << block << prefix() << lhs() << " = " << _rhs << ";";
283  buffer << endl << TAB << fp.endDimGuards(_range);
284  buffer << TAB << fp.endExpression(_range);
285  return buffer.str();
286 }
287 
288 AlgebraicPrinter::AlgebraicPrinter(Equation eq) : DerivativePrinter(eq), _range(eq.range()), _rhs(eq.rhs()), _lhs(eq.lhs()), _id(eq.id())
289 {
290  factorialInit(0);
291 };
292 
293 string AlgebraicPrinter::print() const
294 {
295  stringstream buffer;
296  string tabs = "";
297  tabs += TAB;
298  const bool CLASSIC_MODEL = !ModelConfig::instance().isQss();
299  if (_range) {
300  tabs = _range->block();
301  if (CLASSIC_MODEL) {
302  buffer << _range.get();
303  }
304  }
305  buffer << tabs << prefix() << _lhs << " = " << _rhs << ";" << endl;
306  if (!_range) {
307  tabs += TAB;
308  }
309  buffer << generateDerivatives(tabs) << endl;
310  if (_range && CLASSIC_MODEL) {
311  buffer << _range->end();
312  }
313  return buffer.str();
314 }
315 
316 string AlgebraicPrinter::equationId() const
317 {
318  stringstream buffer;
319  buffer << "_alg_eq_" << _id;
320  return buffer.str();
321 }
322 
324  : DerivativePrinter(eq),
325  _usage(eq.usage()),
326  _range(eq.range()),
327  _rhs(eq.rhs()),
328  _var_idx(Index(eq.lhs())),
329  _parallel(ModelConfig::instance().modelAnnotations().parallel()){};
330 
331 string DependencyPrinter::beginParallelMap(string& tabs) const
332 {
333  if (_parallel) {
334  stringstream buffer;
335  buffer << tabs << "if (map[" << _var_idx << "] > NOT_ASSIGNED) {" << endl;
336  tabs += TAB;
337  return buffer.str();
338  }
339  return "";
340 }
341 
343 {
344  if (_parallel) {
345  stringstream buffer;
346  buffer << TAB << TAB << "}" << endl;
347  return buffer.str();
348  }
349  return "";
350 }
351 
352 string DependencyPrinter::print() const
353 {
354  stringstream buffer;
355  string tabs = TAB;
356  static constexpr int FIRST_ORDER = 1;
357  static constexpr int SECOND_ORDER = 2;
358  FunctionPrinter printer;
359  string arguments;
360  // Case 1 -> N
361  const bool PRINT_EQ_RANGE = _usage.isConstant() && _range;
362  if (_range) {
363  tabs = _range->block();
364  if (PRINT_EQ_RANGE) {
365  buffer << _range.get();
366  arguments = _range.get().indexes();
367  } else {
368  Index revert = _usage.revert().replace();
369  arguments = revert.usageExp();
370  }
371  }
372  tabs += TAB;
373  buffer << printer.beginDimGuards(equationId(), arguments, _range, usedVariables());
374  buffer << beginParallelMap(tabs);
375  buffer << tabs << prefix() << lhs(FIRST_ORDER) << " = " << _rhs << ";" << endl;
376  buffer << generateDerivatives(tabs, SECOND_ORDER) << endl;
377  buffer << endParallelMap();
378  buffer << TAB << printer.endDimGuards(_range);
379  if (PRINT_EQ_RANGE) {
380  buffer << _range.get().end();
381  }
382  return buffer.str();
383 }
384 
385 ZeroCrossingPrinter::ZeroCrossingPrinter(Equation eq) : DerivativePrinter(eq), _id(eq.id()) { factorialInit(1); };
386 
387 string ZeroCrossingPrinter::equationId() const
388 {
389  stringstream buffer;
390  buffer << "_event_" << _id;
391  return buffer.str();
392 }
393 
394 } // namespace IR
395 } // namespace MicroModelica
MicroModelica::IR::AlgebraicPrinter::_rhs
Expression _rhs
Definition: equation_printer.hpp:137
MicroModelica::IR::DerivativePrinter::_fact_init
int _fact_init
Definition: equation_printer.hpp:96
equation.hpp
MicroModelica::IR::FunctionPrinter
Definition: helpers.hpp:147
ModelTable< std::string, RangeDefinition >
MicroModelica::IR::DerivativePrinter::_lhs
Expression _lhs
Definition: equation_printer.hpp:99
MicroModelica::IR::OutputPrinter::_rhs
Expression _rhs
Definition: equation_printer.hpp:125
MicroModelica::IR::EquationPrinter::_used_variables
std::multimap< std::string, int > _used_variables
Definition: equation_printer.hpp:77
ast_builder.hpp
usage
void usage()
Definition: main.cpp:48
MicroModelica::IR::DerivativePrinter::generateDerivatives
std::string generateDerivatives(std::string tabs, int init=1) const
Definition: equation_printer.cpp:208
MicroModelica::IR::DerivativePrinter::factorialInit
void factorialInit(int fact_init)
Definition: equation_printer.hpp:88
MicroModelica::IR::AlgebraicPrinter::AlgebraicPrinter
AlgebraicPrinter(Equation eq)
Definition: equation_printer.cpp:305
MicroModelica::IR::EQUATION::ClassicDerivative
@ ClassicDerivative
Definition: equation.hpp:50
MicroModelica::IR::AlgebraicPrinter::equationId
std::string equationId() const override
Definition: equation_printer.cpp:333
MicroModelica::IR::EquationPrinter::_return_stm
FUNCTION_PRINTER::ReturnStatementType _return_stm
Definition: equation_printer.hpp:76
MicroModelica::IR::DerivativePrinter
Definition: equation_printer.hpp:82
MicroModelica::IR::ClassicPrinter::ClassicPrinter
ClassicPrinter(Equation eq)
Definition: equation_printer.cpp:258
MicroModelica::IR::DependencyPrinter::endParallelMap
std::string endParallelMap() const
Definition: equation_printer.cpp:359
MicroModelica::IR::ZeroCrossingPrinter::equationId
std::string equationId() const override
Definition: equation_printer.cpp:404
MicroModelica::IR::FunctionPrinter::endExpression
std::string endExpression(Option< Range > range, FUNCTION_PRINTER::ReturnStatementType ret=FUNCTION_PRINTER::ReturnStatementType::Return) const
Definition: helpers.cpp:232
MicroModelica::IR::AlgebraicPrinter::_lhs
Expression _lhs
Definition: equation_printer.hpp:138
MicroModelica::IR::DerivativePrinter::_range
Option< Range > _range
Definition: equation_printer.hpp:98
MicroModelica::IR::AlgebraicPrinter::_id
int _id
Definition: equation_printer.hpp:139
MicroModelica::IR::Equation::LHSVariable
Option< Util::Variable > LHSVariable() const
Definition: equation.cpp:165
MicroModelica::IR::Expression::expression
AST_Expression expression() const
Definition: expression.hpp:87
MicroModelica::IR::EquationPrinter::lhs
std::string lhs(int order=0) const
Definition: equation_printer.cpp:116
MicroModelica::IR::getPrinter
EquationPrinter * getPrinter(Equation eq)
Definition: equation_printer.cpp:64
MicroModelica::IR::AlgebraicPrinter::_range
Option< Range > _range
Definition: equation_printer.hpp:136
MicroModelica::IR::DependencyPrinter::_range
Option< Range > _range
Definition: equation_printer.hpp:154
MicroModelica::IR::OutputPrinter::equationId
std::string equationId() const override
Definition: equation_printer.cpp:277
helpers.hpp
Option
Definition: util_types.hpp:32
MicroModelica::IR::EQUATION::Output
@ Output
Definition: equation.hpp:50
MicroModelica::IR::EquationPrinter::_identifier
std::string _identifier
Definition: equation_printer.hpp:71
MicroModelica::IR::FunctionPrinter::endDimGuards
std::string endDimGuards(Option< Range > range) const
Definition: helpers.cpp:256
MicroModelica::IR::Index::revert
Index revert() const
Definition: index.cpp:169
MicroModelica::IR::EquationPrinter::returnStm
FUNCTION_PRINTER::ReturnStatementType returnStm() const
Definition: equation_printer.cpp:105
model_config.hpp
MicroModelica::IR::DependencyPrinter::print
std::string print() const override
Definition: equation_printer.cpp:369
MicroModelica::IR::DependencyPrinter::_usage
Index _usage
Definition: equation_printer.hpp:153
MicroModelica::IR::OutputPrinter::_range
Option< Range > _range
Definition: equation_printer.hpp:124
MicroModelica::IR::FUNCTION_PRINTER::Return
@ Return
Definition: helpers.hpp:144
MicroModelica::IR::DerivativePrinter::print
std::string print() const override
Definition: equation_printer.cpp:236
MicroModelica::IR::Expression
Definition: expression.hpp:64
MicroModelica::IR::DerivativePrinter::_derivatives
Expression _derivatives[3]
Definition: equation_printer.hpp:95
MicroModelica::IR::Equation::lhs
Expression lhs() const
Definition: equation.hpp:78
MicroModelica::IR::ZeroCrossingPrinter::_id
int _id
Definition: equation_printer.hpp:167
MicroModelica::IR::EquationPrinter::EquationPrinter
EquationPrinter(Equation eq)
Definition: equation_printer.cpp:82
MicroModelica::IR::OutputPrinter::_id
int _id
Definition: equation_printer.hpp:123
MicroModelica::IR::OutputPrinter::print
std::string print() const override
Definition: equation_printer.cpp:284
MicroModelica::IR::ZeroCrossingPrinter::ZeroCrossingPrinter
ZeroCrossingPrinter(Equation eq)
Definition: equation_printer.cpp:402
MicroModelica::IR::EquationPrinter::_lhs
Expression _lhs
Definition: equation_printer.hpp:74
MicroModelica::IR::Equation
Definition: equation.hpp:67
MicroModelica::IR::EquationPrinter::setup
void setup(Equation eq)
Definition: equation_printer.cpp:87
alg_usage.hpp
MicroModelica::IR::ClassicPrinter::print
std::string print() const override
Definition: equation_printer.cpp:260
equation.hpp
MicroModelica::IR::Index::isConstant
bool isConstant() const
Definition: index.cpp:134
MicroModelica::IR::DerivativePrinter::_rhs
Expression _rhs
Definition: equation_printer.hpp:100
MicroModelica::IR::DependencyPrinter::_rhs
Expression _rhs
Definition: equation_printer.hpp:155
MicroModelica::IR::EquationPrinter::equationId
virtual std::string equationId() const
Definition: equation_printer.cpp:109
MicroModelica::IR::DerivativePrinter::initializeDerivatives
void initializeDerivatives()
Definition: equation_printer.cpp:194
MicroModelica::Util::ModelConfig::isQss
bool isQss()
Definition: model_config.hpp:107
TAB
#define TAB
Definition: util.hpp:79
MicroModelica::Util::ModelConfig::instance
static ModelConfig & instance()
Definition: model_config.hpp:87
MicroModelica::Generator::WRITER::Output
@ Output
Definition: writer.hpp:98
MicroModelica::IR::ClassicPrinter::_range
Option< Range > _range
Definition: equation_printer.hpp:110
MicroModelica::IR::ClassicPrinter::_rhs
Expression _rhs
Definition: equation_printer.hpp:111
MicroModelica::IR::Expression::dimVariables
std::string dimVariables(bool range_idxs=false) const
Definition: expression.cpp:114
MicroModelica::IR::Index::usageExp
std::string usageExp() const
Definition: index.cpp:188
MicroModelica::IR::EquationPrinter::identifier
std::string identifier() const
Definition: equation_printer.hpp:59
MicroModelica::IR::EQUATION::QSSDerivative
@ QSSDerivative
Definition: equation.hpp:50
MicroModelica::IR::Index
Definition: index.hpp:92
MicroModelica::IR::EQUATION::Dependency
@ Dependency
Definition: equation.hpp:50
derivative.hpp
MicroModelica::Generator::MODEL_INSTANCE::Component::Deps
@ Deps
MicroModelica::IR::Index::replace
Index replace(bool range_idx=false) const
Definition: index.cpp:175
block
int block
Definition: ast_builder.cpp:41
MicroModelica
Definition: files.cpp:45
MicroModelica::IR::EquationPrinter::_type
int _type
Definition: equation_printer.hpp:73
MicroModelica::IR::DependencyPrinter::DependencyPrinter
DependencyPrinter(Equation eq)
Definition: equation_printer.cpp:340
MicroModelica::IR::DependencyPrinter::_parallel
bool _parallel
Definition: equation_printer.hpp:157
MicroModelica::IR::EquationPrinter::_id
int _id
Definition: equation_printer.hpp:72
equation_printer.hpp
MicroModelica::IR::EquationPrinter
Definition: equation_printer.hpp:53
MicroModelica::IR::Equation::hasRange
bool hasRange() const
Definition: equation.hpp:77
MicroModelica::IR::DependencyPrinter::beginParallelMap
std::string beginParallelMap(std::string &tabs) const
Definition: equation_printer.cpp:348
MicroModelica::IR::EQUATION::ZeroCrossing
@ ZeroCrossing
Definition: equation.hpp:50
MicroModelica::IR::FunctionPrinter::beginDimGuards
std::string beginDimGuards(std::string token, string args, Option< Range > range, std::multimap< std::string, int > used_variables) const
Definition: helpers.cpp:266
MicroModelica::IR::FunctionPrinter::beginExpression
std::string beginExpression(std::string token, Option< Range > range) const
Definition: helpers.cpp:219
MicroModelica::IR::Equation::usedVariables
std::multimap< std::string, int > usedVariables() const
Definition: equation.cpp:250
MicroModelica::IR::AlgebraicPrinter::print
std::string print() const override
Definition: equation_printer.cpp:310
MicroModelica::IR::FunctionPrinter::equationVariableMacros
std::string equationVariableMacros(Option< Range > range, Expression lhs, std::string id) const
Definition: helpers.cpp:421
MicroModelica::IR::DerivativePrinter::macro
std::string macro() const override
Definition: equation_printer.cpp:170
MicroModelica::IR::EQUATION::Algebraic
@ Algebraic
Definition: equation.hpp:50
MicroModelica::IR::DependencyPrinter::_var_idx
Index _var_idx
Definition: equation_printer.hpp:156
MicroModelica::IR::EQUATION::QSSBDFDerivative
@ QSSBDFDerivative
Definition: equation.hpp:50
annotation.hpp
MicroModelica::IR::FUNCTION_PRINTER::Continue
@ Continue
Definition: helpers.hpp:144
MicroModelica::IR::DerivativePrinter::DerivativePrinter
DerivativePrinter(Equation eq)
Definition: equation_printer.cpp:164
MicroModelica::IR::OutputPrinter::OutputPrinter
OutputPrinter(Equation eq)
Definition: equation_printer.cpp:275
MicroModelica::IR::EquationPrinter::prefix
std::string prefix() const
Definition: equation_printer.cpp:145
MicroModelica::IR::Equation::type
EQUATION::Type type() const
Definition: equation.hpp:89
MicroModelica::IR::EquationPrinter::usedVariables
std::multimap< std::string, int > usedVariables() const
Definition: equation_printer.cpp:107
util.hpp
error.hpp
MicroModelica::IR::EquationPrinter::algCode
std::string algCode() const
Definition: equation_printer.hpp:60
expression.hpp
MicroModelica::IR::FUNCTION_PRINTER::ReturnStatementType
ReturnStatementType
Definition: helpers.hpp:144