dae_builder_internal.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_DAE_BUILDER_INTERNAL_HPP
27 #define CASADI_DAE_BUILDER_INTERNAL_HPP
28 
29 #include <unordered_map>
30 
31 #include "dae_builder.hpp"
32 #include "shared_object.hpp"
33 #include "casadi_enum.hpp"
34 #include "resource.hpp"
35 
36 namespace casadi {
37 
38 // Forward declarations
39 struct XmlNode;
40 
43 
47 
50 
53 
54 // CasADi classification of model variables, cf. Table 18 in FMI specification, 3.0.2
55 // PARAMETER CALCULATED_PARAMETER INPUT OUTPUT LOCAL INDEPENDENT
56 // CONSTANT - - - C C -
57 // FIXED C D - - D -
58 // TUNABLE P D - - D -
59 // DISCRETE - - U X/Q X/Q -
60 // CONTINUOUS - - U X/Q/W/Z X/Q/W/Z T
61 
62 // Variable categories
63 enum class Category {T, C, P, D, W, U, X, Z, Q, CALCULATED, NUMEL};
64 
65 // Output categories for generated functions
66 enum class OutputCategory {ODE, ALG, QUAD, ZERO, DDEF, WDEF, Y, NUMEL};
67 
70 
71 // Attributes
73 
74 // Permitted dependenciesKind values
76 
83 struct CASADI_EXPORT Variable {
84  friend class DaeBuilderInternal;
85 
86  private:
88  Variable(casadi_int index, const std::string& name,
89  const std::vector<casadi_int>& dimension, const MX& expr);
90 
91  public:
93  casadi_int index;
94 
96  std::string name;
97 
99  std::vector<casadi_int> dimension;
100 
102  casadi_int numel;
103 
106  unsigned int value_reference;
107  std::string description;
112 
115 
118  // std::string declared_type;
119  std::string unit;
120  std::string display_unit;
122  // std::string quantity;
123  // bool relative_quantity;
124  // bool unbounded;
125  double min;
126  double max;
127  double nominal;
128  std::vector<double> start;
129  casadi_int der_of; // 'derivative' in FMI specification
130  casadi_int parent;
132 
133  // corresponding derivative variable, if any
134  casadi_int der;
135 
136  // corresponding binding expression, if any
137  casadi_int bind;
138 
139  // Does it appear in any right-hand-side?
140  bool in_rhs;
141 
143  std::vector<double> value;
144 
146  std::string stringvalue;
147 
150 
152  mutable std::vector<casadi_int> dependencies;
153 
155  mutable std::vector<DependenciesKind> dependenciesKind;
156 
158  MX v;
159 
162 
164  casadi_int size(Attribute a) const;
165 
168  void get_attribute(Attribute a, double* val) const;
169  void get_attribute(Attribute a, std::vector<double>* val) const;
170  void get_attribute(Attribute a, std::string* val) const;
172 
175  void set_attribute(Attribute a, double val);
176  void set_attribute(Attribute a, const std::vector<double>& val);
177  void set_attribute(Attribute a, const std::string& val);
179 
180  // Export as XML
181  XmlNode export_xml(const DaeBuilderInternal& self) const;
182 
183  // Is the variable real?
184  bool is_real() const {return type == Type::FLOAT32 || type == Type::FLOAT64;}
185 
186  // Does the variable need a start attribute?
187  bool has_start() const;
188 
189  // Has the variable been set
190  bool is_set() const {
191  return !(type==Type::STRING ? stringvalue.empty() : std::isnan(value.front()));
192  }
193 
194  // Does the variable have a binding equation
195  bool has_beq() const {return bind >= 0;}
196 
197  // Does the variable need a derivative variable?
198  bool needs_der() const;
199 
200  // Derivative of the expression, create at first encounter
201  MX get_der(DaeBuilderInternal& self, bool may_allocate = true);
202 
203  // Derivative of the expression, never create
204  MX get_der(const DaeBuilderInternal& self) const;
205 };
206 
209 class CASADI_EXPORT DaeBuilderInternal : public SharedObjectInternal {
210  friend class DaeBuilder;
211  friend class FmuInternal;
212  friend class FmuFunction;
213  friend class Variable;
214 
215  public:
216 
218  explicit DaeBuilderInternal(const std::string& name, const std::string& path, const Dict& opts);
219 
221  ~DaeBuilderInternal() override;
222 
224  std::string class_name() const override {return "DaeBuilderInternal";}
225 
227  void sanity_check() const;
228 
233 
235  void eliminate(Category cat);
236 
238  void sort(Category cat);
239 
241  void lift(bool lift_shared, bool lift_calls);
242 
244  void sort_z(const std::vector<std::string>& z_order);
245 
247  std::vector<size_t>& indices(Category cat);
248 
250  const std::vector<size_t>& indices(Category cat) const;
251 
253  size_t size(Category cat) const {return indices(cat).size();}
254 
256  void reorder(Category cat, const std::vector<size_t>& v);
257 
259  void reorder(const std::string& n, std::vector<size_t>& ind,
260  const std::vector<size_t>& v) const;
261 
263  void prune(bool prune_p, bool prune_u);
264 
266  void tearing_variables(std::vector<std::string>* res, std::vector<std::string>* iv,
267  std::vector<std::string>* iv_on_hold) const;
268 
270  void tear();
272 
277  void load_fmi_description(const std::string& filename);
278 
280  static std::string iso_8601_time();
281 
282  // Generate a random 32 digit hexadecimal number
283  static std::string generate_guid();
284 
286  std::vector<std::string> export_fmu(const Dict& opts) const;
287 
289  std::string generate_wrapper(const std::string& guid, const CodeGenerator& gen) const;
290 
292  std::string generate_build_description(const std::vector<std::string>& cfiles) const;
293 
295  std::string generate_model_description(const std::string& guid) const;
296 
298  XmlNode generate_model_variables() const;
299 
301  XmlNode generate_model_structure() const;
302 
304  void update_dependencies() const;
305 
308  static std::string generate(const std::vector<size_t>& v);
309  static std::string generate(const std::vector<double>& v);
311 
312  // Get input expression, given enum
313  std::vector<MX> input(Category ind) const;
314 
315  // Get output expression, given enum
316  std::vector<MX> output(OutputCategory ind) const;
317 
318  // Get input expression, given enum
319  std::vector<MX> input(const std::vector<Category>& ind) const;
320 
321  // Get output expression, given enum
322  std::vector<MX> output(const std::vector<OutputCategory>& ind) const;
323 
325  void add_lc(const std::string& name, const std::vector<std::string>& f_out);
326 
328  Function create(const std::string& fname,
329  const std::vector<std::string>& name_in,
330  const std::vector<std::string>& name_out,
331  const Dict& opts, bool sx, bool lifted_calls) const;
332 
334  Function fmu_fun(const std::string& fname,
335  const std::vector<std::string>& name_in,
336  const std::vector<std::string>& name_out,
337  const Dict& opts) const;
338 
340  Function dependent_fun(const std::string& fname,
341  const std::vector<std::string>& s_in,
342  const std::vector<std::string>& s_out) const;
343 
345  Function transition(const std::string& fname, casadi_int index,
346  bool dummy_index_input = false) const;
347 
349  Function transition(const std::string& fname) const;
350 
352  Function gather_eq() const;
353 
355  const MX& var(const std::string& name) const;
356 
358  MX get_der(size_t ind) const {return variable(ind).get_der(*this);}
359 
361  MX get_der(size_t ind, bool may_allocate = true) {
362  return variable(ind).get_der(*this, may_allocate);
363  }
364 
366  MX der(const MX& var) const;
367 
369  MX der(const MX& var, bool may_allocate = true);
370 
372  std::string unique_name(const std::string& prefix, bool allow_no_prefix = true) const;
373 
375  std::string type_name() const {return "DaeBuilderInternal";}
376 
378  void disp(std::ostream& stream, bool more) const override;
379 
381  std::string get_str(bool more=false) const {
382  std::stringstream ss;
383  disp(ss, more);
384  return ss.str();
385  }
386 
388  Variable& new_variable(const std::string& name,
389  const std::vector<casadi_int>& dimension = {1},
390  const MX& expr = MX());
391 
393  bool has(const std::string& name) const;
394 
396  std::vector<std::string> all() const;
397 
399  std::vector<std::string> all(Category cat) const;
400 
402  size_t n_variables() const {return variables_.size();}
403 
405  size_t n_mem() const;
406 
408  std::vector<double> start_all() const;
409 
412  Variable& variable(size_t ind) {return *variables_.at(ind);}
413  const Variable& variable(size_t ind) const {return *variables_.at(ind);}
415 
418  Variable& variable(Category cat, size_t ind) {return variable(indices(cat).at(ind));}
419  const Variable& variable(Category cat, size_t ind) const {
420  return variable(indices(cat).at(ind));
421  }
423 
426  Variable& variable(const std::string& name) {return variable(find(name));}
427  const Variable& variable(const std::string& name) const {return variable(find(name));}
429 
432  Variable& variable(const MX& v) {return variable(find(v));}
433  const Variable& variable(const MX& v) const {return variable(find(v));}
435 
437  const MX& var(size_t ind) const;
438 
440  const MX& var(Category cat, size_t ind) const {return var(indices(cat).at(ind));}
441 
443  std::vector<MX> var(const std::vector<size_t>& ind) const;
444 
446  std::vector<MX> var(Category cat) const {return var(indices(cat));}
447 
449  size_t find(const std::string& name) const;
450 
452  size_t find(const MX& v) const;
453 
455  std::vector<size_t> find(const std::vector<std::string>& name) const;
456 
458  std::vector<size_t> find(const std::vector<MX>& v) const;
459 
463  const std::string& name(size_t ind) const;
464 
468  std::vector<std::string> name(const std::vector<size_t>& ind) const;
469 
471  const Function& oracle(bool sx = false, bool elim_w = false, bool lifted_calls = false) const;
472 
474  Sparsity jac_sparsity(const std::vector<size_t>& oind, const std::vector<size_t>& iind) const;
475 
477  Sparsity hess_sparsity(const std::vector<size_t>& oind, const std::vector<size_t>& iind) const;
478 
479  // Internal methods
480 protected:
481 
483  static std::string qualified_name(const XmlNode& nn, Attribute* att = 0);
484 
485  // User-set options
486  bool debug_;
487  double fmutol_;
488  bool ignore_time_;
489 
490  // FMI attributes
491  std::string fmi_version_;
492  std::string model_name_;
493  std::string instantiation_token_; // In FMI 2: guid
494  std::string description_;
495  std::string author_;
496  std::string copyright_;
497  std::string license_;
498  std::string generation_tool_;
499  std::string generation_date_and_time_;
500  std::string variable_naming_convention_;
501  casadi_int number_of_event_indicators_;
502 
503  // Default experiment
504  double start_time_, stop_time_, tolerance_, step_size_;
505 
506  // Model Exchange
507  std::string model_identifier_;
508  bool provides_directional_derivatives_;
509  bool provides_adjoint_derivatives_;
510  bool can_be_instantiated_only_once_per_process_;
511  std::vector<std::string> source_files_;
512 
514  std::string name_;
515 
516  // Path to FMU, if any
517  Resource resource_;
518 
519  // Symbolic representation of the model equations?
520  bool symbolic_;
521 
522  // Detect quadrature states
523  bool detect_quad_;
524 
525  // FMI major version
526  casadi_int fmi_major_;
527 
529  std::vector<Variable*> variables_;
530 
531  // Model structure
532  std::vector<size_t> outputs_, derivatives_, initial_unknowns_, event_indicators_, residuals_;
533 
535  std::unordered_map<std::string, size_t> varind_;
536 
538  std::unordered_map<unsigned int, size_t> vrmap_;
539 
541  std::vector<std::vector<size_t>> indices_;
542 
543  // Initial equations
544  std::vector<size_t> init_;
545 
546  // Event conditions and transition equations
547  std::vector<std::pair<size_t, std::vector<size_t>>> when_;
548 
552  bool has_t() const;
553 
554  // Time variable
555  const MX& time() const;
556 
560  std::vector<MX> cdef() const;
561 
565  std::vector<MX> quad() const;
566 
570  std::vector<MX> init_lhs() const;
571 
575  std::vector<MX> init_rhs() const;
576 
578  static Variability default_variability(Causality causality, Type type);
579 
580  // Default initial attribute, per the FMI specification
581  static Initial default_initial(Causality causality, Variability variability);
582 
584  Variable& add(const std::string& name, Causality causality, Variability variability,
585  const Dict& opts);
586 
588  Variable& add(const std::string& name, Causality causality, Variability variability,
589  const MX& expr, const Dict& opts);
590 
592  Variable& add(const std::string& name, Causality causality, const Dict& opts);
593 
595  Variable& add(const std::string& name, const Dict& opts) {
596  // Per FMI 3.0.2 specification, section 2.4.7.4: Default causality is LOCAL
597  return add(name, Causality::LOCAL, opts);
598  }
599 
601  void categorize(size_t ind, Category cat);
602 
604  void insert(std::vector<size_t>& v, size_t ind) const;
605 
607  void remove(std::vector<size_t>& v, size_t ind) const;
608 
610  Causality causality(size_t ind) const;
611 
613  void set_causality(size_t ind, Causality causality);
614 
616  Variability variability(size_t ind) const;
617 
619  void set_variability(size_t ind, Variability variability);
620 
622  Category category(size_t ind) const;
623 
625  void set_category(size_t ind, Category cat);
626 
628  void eq(const MX& lhs, const MX& rhs, const Dict& opts);
629 
631  void when(const MX& cond, const std::vector<std::string>& eqs, const Dict& opts);
632 
634  Variable& assign(const std::string& name, const MX& val);
635 
637  Variable& reinit(const std::string& name, const MX& val);
638 
640  void set_init(const std::string& name, const MX& init_rhs);
641 
643  Function::AuxOut lc_;
644 
648  std::vector<Function> fun_;
649 
653  mutable Function oracle_[2][2][2];
654 
656  mutable bool clear_cache_;
657 
659  MX read_expr(const XmlNode& node);
660 
662  MX read_identifier(const XmlNode& node);
663 
665  Variable& read_variable(const XmlNode& node, Attribute* att = 0);
666 
667  // Read DefaultExperiment
668  void import_default_experiment(const XmlNode& n);
669 
670  // Read dependencies node
671  std::vector<casadi_int> read_dependencies(const XmlNode& n);
672 
673  // Read dependenciesKind node
674  std::vector<DependenciesKind> read_dependencies_kind(const XmlNode& n, size_t ndep);
675 
676  // Read ModelExchange
677  void import_model_exchange(const XmlNode& n);
678 
679  // Read ModelVariables
680  void import_model_variables(const XmlNode& modvars);
681 
682  // Read ModelStructure
683  void import_model_structure(const XmlNode& n);
684 
685  // Read symbolic binding equations
686  void import_binding_equations(const XmlNode& eqs);
687 
688  // Read symbolic dynamic equations
689  void import_dynamic_equations(const XmlNode& eqs);
690 
691  // Read symbolic initial equations
692  void import_initial_equations(const XmlNode& eqs);
693 
695  void clear_cache() const;
696 
698  Function add_fun(const std::string& name,
699  const std::vector<std::string>& arg,
700  const std::vector<std::string>& res, const Dict& opts=Dict());
701 
703  Function add_fun(const Function& f);
704 
706  bool has_fun(const std::string& name) const;
707 
709  Function fun(const std::string& name) const;
710 
711  // Reset value attributes
712  void reset();
713 
716  double attribute(Attribute a, const std::string& name) const;
717  std::vector<double> attribute(Attribute a, const std::vector<std::string>& name) const;
719 
722  void set_attribute(Attribute a, const std::string& name, double val);
723  void set_attribute(Attribute a, const std::vector<std::string>& name,
724  const std::vector<double>& val);
726 
729  std::string string_attribute(Attribute a, const std::string& name) const;
730  std::vector<std::string> string_attribute(Attribute a,
731  const std::vector<std::string>& name) const;
733 
736  void set_string_attribute(Attribute a, const std::string& name, const std::string& val);
737  void set_string_attribute(Attribute a, const std::vector<std::string>& name,
738  const std::vector<std::string>& val);
740 
742  casadi_int size(Attribute a, const std::vector<std::string>& name) const;
743 
745  struct CallIO {
746  // Function instances
747  Function f, adj1_f, J, H;
748  // Index in v and vdef
749  std::vector<size_t> v, vdef;
750  // Nondifferentiated inputs
751  std::vector<MX> arg;
752  // Nondifferentiated inputs
753  std::vector<MX> res;
754  // Jacobian outputs
755  std::vector<MX> jac_res;
756  // Adjoint seeds
757  std::vector<MX> adj1_arg;
758  // Adjoint sensitivities
759  std::vector<MX> adj1_res;
760  // Hessian outputs
761  std::vector<MX> hess_res;
762  // Calculate Jacobian blocks
763  void calc_jac();
764  // Calculate gradient of Lagrangian
765  void calc_grad();
766  // Calculate Hessian of Lagrangian
767  void calc_hess();
768  // Access a specific Jacobian block
769  const MX& jac(casadi_int oind, casadi_int iind) const;
770  // Access a specific Hessian block
771  const MX& hess(casadi_int iind1, casadi_int iind2) const;
772  };
773 
775  MX jac_vdef_v_from_calls(std::map<MXNode*, CallIO>& call_nodes,
776  const std::vector<casadi_int>& h_offsets) const;
777 
779  MX hess_v_v_from_calls(std::map<MXNode*, CallIO>& call_nodes,
780  const std::vector<casadi_int>& h_offsets) const;
781 
782  // Sort dependent variables/parameters
783  static void sort_dependent(std::vector<MX>& v, std::vector<MX>& vdef);
784 };
785 
788 CASADI_EXPORT Type from_fmi2(TypeFmi2 v);
789 CASADI_EXPORT TypeFmi2 to_fmi2(Type v);
791 
794 CASADI_EXPORT std::string to_string(TypeFmi2 v);
795 CASADI_EXPORT std::string to_string(Type v);
796 CASADI_EXPORT std::string to_string(Causality v);
797 CASADI_EXPORT std::string to_string(Variability v);
798 CASADI_EXPORT std::string to_string(Initial v);
799 CASADI_EXPORT std::string to_string(Attribute v);
800 CASADI_EXPORT std::string to_string(DependenciesKind v);
801 CASADI_EXPORT std::string to_string(Category v);
802 CASADI_EXPORT std::string to_string(OutputCategory v);
804 
807 CASADI_EXPORT std::string description(Category v);
809 
810 // Check if input category
811 CASADI_EXPORT bool is_input_category(Category cat);
812 
813 // Check if acyclic dependency category
814 CASADI_EXPORT bool is_acyclic(Category cat);
815 
816 // Definition for acyclyc dependency categories
817 CASADI_EXPORT OutputCategory dependent_definition(Category cat);
818 
819 // Get all input categories
820 CASADI_EXPORT std::vector<Category> input_categories();
821 
822 // Get all output categories
823 CASADI_EXPORT std::vector<OutputCategory> output_categories();
824 
825 // Get the input category for a particular output category
826 CASADI_EXPORT Category input_category(OutputCategory cat);
827 
829 
830 } // namespace casadi
831 
832 #endif // CASADI_DAE_BUILDER_INTERNAL_HPP
A symbolic representation of a differential-algebraic equations model.
Definition: dae_builder.hpp:70
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:404
MX - Matrix expression.
Definition: mx.hpp:92
The casadi namespace.
Definition: archiver.hpp:32
Variability
Variability: FMI 2.0 specification, section 2.2.7 or FMI 3.0 specification, section 2....
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Initial
Initial: FMI 2.0 specification, section 2.2.7 or FMI 3.0 specification, section 2....
Causality
Causality: FMI 2.0 specification, section 2.2.7 or FMI 3.0 specification, section 2....
Type
Variable type (FMI 3)
TypeFmi2
Variable type (FMI 2)
Holds expressions and meta-data corresponding to a physical quantity evolving in time.
Category category
CasADi's classification of the variable.
bool dependency
Do other expressions depend on this variable.
void set_attribute(Attribute a, const std::vector< double > &val)
void set_attribute(Attribute a, double val)
std::vector< double > value
Numerical value (also for booleans, integers, enums)
MX get_der(DaeBuilderInternal &self, bool may_allocate=true)
void set_attribute(Attribute a, const std::string &val)
bool needs_der() const
bool has_start() const
casadi_int size(Attribute a) const
Total number of elements for a particular attribute.
void get_attribute(Attribute a, std::string *val) const
void get_attribute(Attribute a, double *val) const
std::vector< double > start
casadi_int index
Location in variable vector.
MX get_der(const DaeBuilderInternal &self) const
std::string stringvalue
String value (if string-valued)
casadi_int numel
Number of elements - product of all dimensions.
std::string name
Name of the variable.
void get_attribute(Attribute a, std::vector< double > *val) const
MX v
Variable expression (always a vector)
XmlNode export_xml(const DaeBuilderInternal &self) const
std::vector< casadi_int > dependencies
Dependencies.
std::vector< DependenciesKind > dependenciesKind
Dependencies.
std::vector< casadi_int > dimension
Dimensions.
MX ieq
Initial equation (to be removed and moved to a separate dependent variable)