MicroModelicaCCompiler  4.5.3
jacobian.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 "jacobian.hpp"
21 
22 #include <sstream>
23 
24 #include <ast/parser/parse.hpp>
25 #include <deps/builders/eq_graph_builder.hpp>
26 #include <deps/sbg_graph/build_from_exps.hpp>
27 #include <deps/sb_dependencies.hpp>
28 #include <ir/derivative.hpp>
29 #include <ir/helpers.hpp>
30 #include <ir/index.hpp>
31 #include <util/model_config.hpp>
32 #include <util/util.hpp>
33 #include <util/symbol_table.hpp>
34 
35 namespace MicroModelica {
36 using namespace Deps;
37 using namespace SB;
38 using namespace Util;
39 namespace IR {
40 
41 JacGenerator::JacGenerator() : _jac_def(), _tabs(0) {}
42 
43 void JacGenerator::postProcess(SB::Deps::SetVertex vertex)
44 {
45  int size = vertex.range().size();
46  int id = vertex.index() - 1;
47  stringstream code;
48  string tab = Utils::instance().tabs(_tabs);
49  code << "// Assign Jacobian Matrix values for equation: " << id << endl;
50  code << tab << "for (row = 0; row < " << size << "; row++) {" << endl;
51  code << tab << " for (col = 0; col < dvdx->df_dx[" << id << "]->size[row]; col++) {" << endl;
52  code << tab << " row_t = dvdx->df_dx[" << id << "]->index[row][col];" << endl;
53  code << tab << " _assign_jac(row_t, dvdx->df_dx[" << id << "]->value[row][col]);" << endl;
54  code << tab << " }" << endl;
55  code << tab << "}" << endl;
56  _jac_def.code.append(code.str());
57 }
58 
59 void JacGenerator::init(SB::Deps::SetVertex vertex)
60 {
61  stringstream code;
62  FunctionPrinter function_printer;
63  Equation eq = getEquation(vertex);
64  code << "for(row = 1; row <= " << vertex.range().size() << "; row++) {" << endl;
65  code << TAB << "c_row = _c_index(row);" << endl;
66  code << function_printer.jacMacrosAccess(eq);
67  _tabs++;
68  _jac_def.code.append(code.str());
69 }
70 
71 void JacGenerator::end()
72 {
73  _jac_def.code.append("}\n");
74  _tabs--;
75 }
76 
77 std::string JacGenerator::guard(SB::Set dom, int offset, std::string var_name, SB::Deps::LMapExp map, Equation v_eq)
78 {
79  if (map.constantExp()) {
80  return "";
81  }
82  Range range(dom, offset);
83  stringstream code;
84  vector<string> exps = map.apply(range.getDimensionVars());
85  Expression map_exp = Expression::generate(var_name, exps);
86  range.applyUsage(Index(map_exp));
87  if (v_eq.hasRange()) {
88  range.update(v_eq.range().get());
89  }
90  return range.in(exps);
91 }
92 
93 void JacGenerator::dependencyPrologue(Equation eq, SB::Deps::VariableDep var_dep, std::string guard)
94 {
95  stringstream code;
96  string tabs = Utils::instance().tabs(_tabs);
97  SB::Deps::LMapExp map = var_dep.nMap();
98  Range range(var_dep.variables(), var_dep.varOffset());
99  if (var_dep.isRecursive() && eq.hasRange()) {
100  FunctionPrinter printer;
101  code << tabs << eq.range().get();
102  _tabs++;
103  tabs = Utils::instance().tabs(_tabs);
104  vector<string> exps = eq.range()->getIndexes();
105  Expression a_exp = Expression::generate(eq.LHSVariable()->name(), exps);
106  Index a_ind(a_exp);
107  code << TAB << printer.jacMacrosAccess(eq, a_ind.print());
108  }
109  vector<string> exps = map.apply(range.getDimensionVars());
110  if (!map.constantExp()) {
111  code << tabs << "if(" << range.in(exps);
112  if (!guard.empty()) {
113  code << " && " << guard;
114  }
115  code << ") {" << endl;
116  } else if (!guard.empty()) {
117  code << tabs << " if(" << guard << ") {" << endl;
118  }
119  Expression i_exp = Expression::generate(var_dep.var().name(), exps);
120  Index x_ind(i_exp);
121  if (!map.constantExp() || !guard.empty()) {
122  _tabs++;
123  tabs = tabs + TAB;
124  }
125  code << tabs << "x_ind = " << x_ind << ";" << endl;
126  _jac_def.code.append(code.str());
127 }
128 
129 void JacGenerator::dependencyEpilogue(Equation eq, SB::Deps::VariableDep var_dep)
130 {
131  stringstream code;
132  if (!var_dep.nMap().constantExp() || !var_dep.mMap().constantExp()) {
133  _tabs--;
134  code << Utils::instance().tabs(_tabs) + "}\n";
135  }
136  if (var_dep.isRecursive() && eq.hasRange()) {
137  code << eq.range()->end();
138  }
139  _jac_def.code.append(code.str());
140 }
141 
142 void JacGenerator::generatePos(int id, EQUATION::Type type, string row, string col)
143 {
144  stringstream code;
145  string tab = Utils::instance().tabs(_tabs);
146  string type_str = "df_dx";
147  code << tab << col << " = pos(dvdx->";
148  if (type == EQUATION::Algebraic) {
149  type_str = "dg_dx";
150  }
151  code << type_str << "[" << id << "]->index[" << row << "], ";
152  code << "dvdx->" << type_str << "[" << id << "]->size[" << row << "], x_ind);" << endl;
153  _jac_def.code.append(code.str());
154 }
155 
157 {
158  stringstream code;
159  string tab = Utils::instance().tabs(_tabs);
160  string mat = (type == EQUATION::Algebraic) ? "dg_dx" : "df_dx";
161  code << tab << "dvdx->" << mat << "[" << id << "]->value[c_row][col] += aux;" << endl;
162  _jac_def.code.append(code.str());
163 }
164 
165 void JacGenerator::generateEquation(int v_id, int g_id, EQUATION::Type type)
166 {
167  stringstream code;
168  string tab = Utils::instance().tabs(_tabs);
169  string mat = (type == EQUATION::Algebraic) ? "dg_dx" : "df_dx";
170  code << tab << "dvdx->" << mat << "[" << v_id << "]->value[c_row][col] += ";
171  code << "aux * dvdx->dg_dx[" << g_id << "]->value[c_row_g][col_g];" << endl;
172  _jac_def.code.append(code.str());
173 }
174 
176 {
177  stringstream code;
178  if (eq.hasRange()) {
179  string tab = Utils::instance().tabs(_tabs);
180  string args = Index(eq.lhs()).replace().usageExp();
181  code << tab << "_apply_usage" << eq.applyId() << "(" << args << ");" << endl;
182  eq.range()->addLocalVariables();
183  }
184  return code.str();
185 }
186 
187 void JacGenerator::visitF(SB::Deps::SetVertex vertex, SB::Deps::VariableDep var_dep)
188 {
189  Equation eq = getEquation(vertex);
190  Fvisitor(vertex, var_dep, eq.arrayId());
191 }
192 
193 void JacGenerator::visitF(SB::Deps::SetVertex vertex, SB::Deps::VariableDep var_dep, SB::Deps::SetVertex gen_vertex)
194 {
195  Equation eq = getEquation(gen_vertex);
196  Fvisitor(vertex, var_dep, eq.arrayId());
197 }
198 
199 void JacGenerator::Fvisitor(SB::Deps::SetVertex vertex, SB::Deps::VariableDep var_dep, int eq_id)
200 {
201  stringstream code;
203  Equation eq = getEquation(vertex);
204  dependencyPrologue(eq, var_dep);
205  string tab = Utils::instance().tabs(_tabs);
206  generatePos(eq_id, eq.type());
207  code << getVariableIndexes(eq);
208  code << tab << "aux = " << ExpressionDerivator::partialDerivative(eq, Index(var_dep.exp())) << ";" << endl;
209  _jac_def.code.append(code.str());
210  generateEquation(eq_id, eq.type());
211  dependencyEpilogue(eq, var_dep);
212 }
213 
214 void JacGenerator::visitG(SB::Deps::SetVertex v_vertex, SB::Deps::SetVertex g_vertex, SB::Deps::VariableDep var_dep, int index_shift)
215 {
216  stringstream code;
217  const bool REC_DEPS = var_dep.isRecursive();
218  Equation v_eq = getEquation(v_vertex);
219  Equation g_eq = getEquation(g_vertex);
220  // Generate composed expression for guards
221  SB::Deps::LMapExp map_m = var_dep.mMap();
222  SB::Deps::LMapExp n_map = var_dep.nMap();
223  string dom_guard = guard(var_dep.equations(), var_dep.eqOffset(), var_dep.var().name(), map_m, v_eq);
224  dependencyPrologue(g_eq, var_dep, dom_guard);
225  generatePos(v_eq.arrayId(), v_eq.type());
226  vector<string> variables;
227  string tab = Utils::instance().tabs(_tabs);
228  static const bool USE_RANGE_IDXS = true;
229  vector<string> exps;
230  if (v_eq.hasRange()) {
231  exps = map_m.apply(v_eq.range()->getDimensionVars(USE_RANGE_IDXS));
232  } else {
233  Option<Variable> v_lhs = v_eq.LHSVariable();
234  Option<Variable> g_lhs = g_eq.LHSVariable();
235  if (REC_DEPS || g_lhs->isArray()) {
236  Range range(var_dep.variables(), var_dep.varOffset());
237  exps = n_map.apply(range.getDimensionVars(USE_RANGE_IDXS));
238  } else if (v_lhs->isArray()) {
239  // Is this condition possible?
240  for (Expression exp : v_eq.lhs().indexes()) {
241  exps.push_back(exp.print());
242  }
243  }
244  }
245  Expression a_exp = Expression::generate(g_eq.LHSVariable()->name(), exps);
246  Index a_ind(a_exp);
247  code << tab << "c_row_g = " << a_ind << " - ";
248  int eq_shift = g_eq.LHSVariable()->offset();
249  if (g_eq.hasRange()) {
250  eq_shift += index_shift;
251  }
252  code << eq_shift << ";" << endl;
253  _jac_def.code.append(code.str());
254  int g_eq_id = g_eq.arrayId();
255  generatePos(g_eq_id, g_eq.type(), "c_row_g", "col_g");
256  generateEquation(v_eq.arrayId(), g_eq_id, v_eq.type());
257  dependencyEpilogue(g_eq, var_dep);
258 }
259 
260 void JacGenerator::visitG(SB::Deps::SetVertex v_vertex, SB::Deps::SetVertex g_vertex, SB::PWLMap use_map, SB::Deps::LMapExp use_map_exp,
261  Expression use_exp, SB::PWLMap def_map, SB::Deps::LMapExp def_map_exp, SB::Set intersection)
262 {
263 }
264 
265 void JacGenerator::initG(SB::Deps::SetVertex vertex, SB::Deps::SetEdge edge)
266 {
267  stringstream code;
268  string tab = Utils::instance().tabs(_tabs);
269  Equation eq = getEquation(vertex);
270  code << getVariableIndexes(eq);
271  code << tab << "aux = " << ExpressionDerivator::partialDerivative(eq, Index(edge.desc().exp())) << ";" << endl;
272  _jac_def.code.append(code.str());
273 }
274 
275 JacDef JacGenerator::def() { return _jac_def; }
276 
278 
279 void Jacobian::build()
280 {
284  JacobianBuilder jac;
285  IndexShiftBuilder index_shifts(algebraics);
286  jac.setup(algebraics);
287  SDSBGraphBuilder SDSBGraph = SDSBGraphBuilder(derivatives, algebraics);
288  SDSBGraph.setOrigEquations(ModelConfig::instance().derivatives());
289  jac.compute(SDSBGraph.build(), index_shifts.build());
290  _jac_def = jac.def();
291 }
292 
293 string Jacobian::code() { return _jac_def.code; }
294 
295 } // namespace IR
296 } // namespace MicroModelica
MicroModelica::IR::FunctionPrinter
Definition: helpers.hpp:147
MicroModelica::IR::Range
Definition: index.hpp:164
MicroModelica::IR::ExpressionDerivator::partialDerivative
static Expression partialDerivative(Equation eq, Index variable)
Definition: derivative.cpp:89
MicroModelica::IR::Expression::indexes
list< Expression > indexes() const
Definition: expression.cpp:145
ModelTable< int, Equation >
MicroModelica::Util::VarSymbolTable
Definition: symbol_table.hpp:184
MicroModelica::Util::ModelConfig::symbols
VarSymbolTable & symbols()
Definition: model_config.hpp:122
MicroModelica::IR::JacGenerator::generateEquation
void generateEquation(int id, EQUATION::Type type)
Definition: jacobian.cpp:173
index.hpp
MicroModelica::IR::JacGenerator::init
void init(SB::Deps::SetVertex vertex)
Definition: jacobian.cpp:76
MicroModelica::IR::JacGenerator::JacGenerator
JacGenerator()
Definition: jacobian.cpp:58
MicroModelica::IR::Index::print
std::string print() const
Definition: index.cpp:201
MicroModelica::IR::Range::applyUsage
void applyUsage(Index usage)
Definition: index.cpp:694
MicroModelica::IR::Equation::LHSVariable
Option< Util::Variable > LHSVariable() const
Definition: equation.cpp:165
symbol_table.hpp
MicroModelica::IR::JacGenerator::end
void end()
Definition: jacobian.cpp:88
MicroModelica::IR::Jacobian::build
void build()
Definition: jacobian.cpp:296
helpers.hpp
Option
Definition: util_types.hpp:32
MicroModelica::IR::Jacobian::_jac_def
JacDef _jac_def
Definition: jacobian.hpp:115
MicroModelica::IR::EQUATION::Type
Type
Definition: equation.hpp:50
MicroModelica::IR::JacDef::code
std::string code
Definition: jacobian.hpp:85
MicroModelica::IR::FunctionPrinter::jacMacrosAccess
std::string jacMacrosAccess(Equation eq, std::string index="row", std::string tab=TAB) const
Definition: helpers.cpp:455
model_config.hpp
MicroModelica::IR::JacGenerator::guard
std::string guard(SB::Set dom, int offset, std::string var_name, SB::Deps::LMapExp map, Equation v_eq)
Definition: jacobian.cpp:94
MicroModelica::IR::JacGenerator::Fvisitor
void Fvisitor(SB::Deps::SetVertex vertex, SB::Deps::VariableDep var_dep, int eq_id)
Definition: jacobian.cpp:216
MicroModelica::IR::JacGenerator::dependencyPrologue
void dependencyPrologue(Equation eq, SB::Deps::VariableDep var_dep, std::string guard="")
Definition: jacobian.cpp:110
MicroModelica::IR::Expression
Definition: expression.hpp:64
MicroModelica::IR::Expression::generate
static Expression generate(std::string var_name, std::vector< std::string > indices)
Definition: expression.cpp:162
MicroModelica::Util::ModelConfig::algebraics
IR::EquationTable algebraics()
Definition: model_config.hpp:96
MicroModelica::IR::Equation::lhs
Expression lhs() const
Definition: equation.hpp:78
MicroModelica::IR::Jacobian::Jacobian
Jacobian()
Definition: jacobian.cpp:294
MicroModelica::IR::JacGenerator::visitF
void visitF(SB::Deps::SetVertex vertex, SB::Deps::VariableDep var_dep)
Definition: jacobian.cpp:204
MicroModelica::IR::Equation
Definition: equation.hpp:67
MicroModelica::IR::JacGenerator::_jac_def
JacDef _jac_def
Definition: jacobian.hpp:100
MicroModelica::Util::ModelConfig::orderedDerivatives
IR::EquationTable orderedDerivatives()
Definition: model_config.hpp:111
MicroModelica::IR::Range::getDimensionVars
std::vector< std::string > getDimensionVars(bool range=false) const
Definition: index.cpp:536
MicroModelica::IR::Equation::range
Option< Range > range() const
Definition: equation.hpp:86
MicroModelica::IR::Equation::arrayId
int arrayId() const
Definition: equation.cpp:244
TAB
#define TAB
Definition: util.hpp:79
MicroModelica::Util::ModelConfig::instance
static ModelConfig & instance()
Definition: model_config.hpp:87
MicroModelica::IR::Index::usageExp
std::string usageExp() const
Definition: index.cpp:188
MicroModelica::IR::Range::in
std::string in(ExpressionList exps)
Definition: index.cpp:765
MicroModelica::IR::Jacobian::code
std::string code()
Definition: jacobian.cpp:310
MicroModelica::IR::Index
Definition: index.hpp:92
derivative.hpp
MicroModelica::Generator::MODEL_INSTANCE::Component::Deps
@ Deps
MicroModelica::IR::Index::replace
Index replace(bool range_idx=false) const
Definition: index.cpp:175
MicroModelica::IR::JacGenerator::dependencyEpilogue
void dependencyEpilogue(Equation eq, SB::Deps::VariableDep var_dep)
Definition: jacobian.cpp:146
MicroModelica
Definition: files.cpp:45
MicroModelica::IR::Equation::applyId
std::string applyId() const
Definition: equation.cpp:163
MicroModelica::IR::JacGenerator::getVariableIndexes
std::string getVariableIndexes(Equation eq)
Definition: jacobian.cpp:192
MicroModelica::IR::JacGenerator::visitG
void visitG(SB::Deps::SetVertex v_vertex, SB::Deps::SetVertex g_vertex, SB::Deps::VariableDep var_dep, int index_shift)
Definition: jacobian.cpp:231
MicroModelica::IR::JacGenerator::generatePos
void generatePos(int id, EQUATION::Type type, std::string row="c_row", std::string col="col")
Definition: jacobian.cpp:159
MicroModelica::Util::Utils::instance
static Utils & instance()
Definition: util.hpp:83
MicroModelica::IR::Equation::hasRange
bool hasRange() const
Definition: equation.hpp:77
MicroModelica::IR::JacGenerator::def
JacDef def()
Definition: jacobian.cpp:292
MicroModelica::IR::JacGenerator::initG
void initG(SB::Deps::SetVertex vertex, SB::Deps::SetEdge edge)
Definition: jacobian.cpp:282
MicroModelica::IR::Range::update
void update(int offset)
Definition: index.cpp:710
MicroModelica::IR::EQUATION::Algebraic
@ Algebraic
Definition: equation.hpp:50
jacobian.hpp
MicroModelica::IR::JacGenerator::_tabs
int _tabs
Definition: jacobian.hpp:101
MicroModelica::IR::JacGenerator::postProcess
void postProcess(SB::Deps::SetVertex vertex)
Definition: jacobian.cpp:60
MicroModelica::Util::Utils::tabs
std::string tabs(int t)
Definition: util.cpp:401
MicroModelica::IR::Equation::type
EQUATION::Type type() const
Definition: equation.hpp:89
util.hpp