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/0 X/Q/0 -
60 // CONTINUOUS - - U X/Q/W/Z/0 X/Q/W/Z/0 X/Q/T/0
61 
62 // Variable categories
63 enum class Category {T, C, P, D, W, U, X, Z, Q, CALCULATED,
64  ODE, ALG, QUAD, ZERO, DDEF, WDEF, Y, NUMEL};
65 
68 
69 // Attributes
71 
72 // Permitted dependenciesKind values
74 
81 struct CASADI_EXPORT Variable {
82  friend class DaeBuilderInternal;
83 
84  private:
86  Variable(casadi_int index, const std::string& name,
87  const std::vector<casadi_int>& dimension, const MX& expr);
88 
89  public:
91  casadi_int index;
92 
94  std::string name;
95 
97  std::vector<casadi_int> dimension;
98 
100  casadi_int numel;
101 
104  unsigned int value_reference;
105  std::string description;
110 
113 
116  // std::string declared_type;
117  std::string unit;
118  std::string display_unit;
120  // std::string quantity;
121  // bool relative_quantity;
122  // bool unbounded;
123  double min;
124  double max;
125  double nominal;
126  std::vector<double> start;
127  casadi_int der_of; // 'derivative' in FMI specification
128  casadi_int parent;
130 
131  // corresponding derivative variable, if any
132  casadi_int der;
133 
134  // corresponding binding expression, if any
135  casadi_int bind;
136 
137  // Does it appear in any right-hand-side?
138  bool in_rhs;
139 
141  std::vector<double> value;
142 
144  std::string stringvalue;
145 
148 
150  mutable std::vector<casadi_int> dependencies;
151 
153  mutable std::vector<DependenciesKind> dependenciesKind;
154 
156  MX v;
157 
160 
162  casadi_int size(Attribute a) const;
163 
166  void get_attribute(Attribute a, double* val) const;
167  void get_attribute(Attribute a, std::vector<double>* val) const;
168  void get_attribute(Attribute a, std::string* val) const;
170 
173  void set_attribute(Attribute a, double val);
174  void set_attribute(Attribute a, const std::vector<double>& val);
175  void set_attribute(Attribute a, const std::string& val);
177 
178  // Export as XML
179  XmlNode export_xml(const DaeBuilderInternal& self) const;
180 
181  // Is the variable real?
182  bool is_real() const {return type == Type::FLOAT32 || type == Type::FLOAT64;}
183 
184  // Does the variable need a start attribute?
185  bool has_start() const;
186 
187  // Unused derivative variable?
188  bool has_der() const {
189  return der != size_t(-1) || causality == Causality::INDEPENDENT;
190  }
191 
192  // Permitted categories for the variable
193  std::vector<Category> categories() const;
194 
195  // Is a category permitted for the variable?
196  bool permitted(Category cat) const;
197 
198  // Has the variable been set
199  bool is_set() const {
200  return !(type==Type::STRING ? stringvalue.empty() : std::isnan(value.front()));
201  }
202 
203  // Does the variable have a binding equation
204  bool has_beq() const {return bind >= 0;}
205 
206  // Does the variable need a derivative variable?
207  bool needs_der() const;
208 
209  // Derivative of the expression, create at first encounter
210  MX get_der(DaeBuilderInternal& self, bool may_allocate = true);
211 
212  // Derivative of the expression, never create
213  MX get_der(const DaeBuilderInternal& self) const;
214 };
215 
218 class CASADI_EXPORT DaeBuilderInternal : public SharedObjectInternal {
219  friend class DaeBuilder;
220  friend class FmuInternal;
221  friend class FmuFunction;
222  friend class Variable;
223 
224  public:
225 
227  explicit DaeBuilderInternal(const std::string& name, const std::string& path, const Dict& opts);
228 
230  ~DaeBuilderInternal() override;
231 
233  std::string class_name() const override {return "DaeBuilderInternal";}
234 
236  void sanity_check() const;
237 
242 
244  void eliminate(Category cat);
245 
247  void sort(Category cat);
248 
250  void lift(bool lift_shared, bool lift_calls);
251 
253  void sort_z(const std::vector<std::string>& z_order);
254 
256  std::vector<size_t>& indices(Category cat);
257 
259  const std::vector<size_t>& indices(Category cat) const;
260 
262  size_t size(Category cat) const {return indices(cat).size();}
263 
265  void reorder(Category cat, const std::vector<size_t>& v);
266 
268  void reorder(const std::string& n, std::vector<size_t>& ind,
269  const std::vector<size_t>& v) const;
270 
272  void prune(bool prune_p, bool prune_u);
273 
275  void tearing_variables(std::vector<std::string>* res, std::vector<std::string>* iv,
276  std::vector<std::string>* iv_on_hold) const;
277 
279  void tear();
281 
286  void load_fmi_description(const std::string& filename);
287 
289  static std::string iso_8601_time();
290 
291  // Generate a random 32 digit hexadecimal number
292  static std::string generate_guid();
293 
295  Dict export_fmu(const Dict& opts) const;
296 
298  Dict compile_fmu(const Dict& files, const Dict& opts) const;
299 
301  std::string pack_fmu(const Dict& files, const Dict& opts) const;
302 
304  std::string generate_wrapper(const std::string& guid, const CodeGenerator& gen) const;
305 
307  std::string generate_build_description(const std::vector<std::string>& cfiles) const;
308 
310  std::string generate_model_description(const std::string& guid) const;
311 
313  XmlNode generate_model_variables() const;
314 
316  XmlNode generate_model_structure(bool dae = false) const;
317 
319  void update_dependencies() const;
320 
323  static std::string generate(const std::vector<size_t>& v);
324  static std::string generate(const std::vector<double>& v);
326 
327  // Get input expressions, given enum
328  std::vector<MX> inputs(Category ind) const;
329 
330  // Get output expressions, given enum
331  std::vector<MX> outputs(Category ind) const;
332 
333  // Get input expressions, given enum
334  std::vector<MX> inputs(const std::vector<Category>& ind) const;
335 
336  // Get output expressions, given enum
337  std::vector<MX> outputs(const std::vector<Category>& ind) const;
338 
340  void add_lc(const std::string& name, const std::vector<std::string>& f_out);
341 
343  Function create(const std::string& fname,
344  const std::vector<std::string>& name_in,
345  const std::vector<std::string>& name_out,
346  const Dict& opts, bool sx, bool lifted_calls) const;
347 
349  Function fmu_fun(const std::string& fname,
350  const std::vector<std::string>& name_in,
351  const std::vector<std::string>& name_out,
352  const Dict& opts) const;
353 
355  Function dependent_fun(const std::string& fname,
356  const std::vector<std::string>& s_in,
357  const std::vector<std::string>& s_out) const;
358 
360  Function transition(const std::string& fname, casadi_int index,
361  bool dummy_index_input = false) const;
362 
364  Function transition(const std::string& fname) const;
365 
367  Function gather_eq() const;
368 
370  const MX& var(const std::string& name) const;
371 
373  MX get_der(size_t ind) const {return variable(ind).get_der(*this);}
374 
376  MX get_der(size_t ind, bool may_allocate = true) {
377  return variable(ind).get_der(*this, may_allocate);
378  }
379 
381  MX der(const MX& var) const;
382 
384  MX der(const MX& var, bool may_allocate = true);
385 
387  std::string unique_name(const std::string& prefix, bool allow_no_prefix = false) const;
388 
390  std::string type_name() const {return "DaeBuilderInternal";}
391 
393  void disp(std::ostream& stream, bool more) const override;
394 
396  std::string get_str(bool more=false) const {
397  std::stringstream ss;
398  disp(ss, more);
399  return ss.str();
400  }
401 
403  Variable& new_variable(const std::string& name,
404  const std::vector<casadi_int>& dimension = {1},
405  const MX& expr = MX());
406 
408  bool has(const std::string& name) const;
409 
411  std::vector<std::string> all() const;
412 
414  std::vector<std::string> all(Category cat) const;
415 
417  size_t n_variables() const {return variables_.size();}
418 
420  size_t n_mem() const;
421 
423  std::vector<double> start_all() const;
424 
427  Variable& variable(size_t ind) {return *variables_.at(ind);}
428  const Variable& variable(size_t ind) const {return *variables_.at(ind);}
430 
433  Variable& variable(Category cat, size_t ind) {return variable(indices(cat).at(ind));}
434  const Variable& variable(Category cat, size_t ind) const {
435  return variable(indices(cat).at(ind));
436  }
438 
441  Variable& variable(const std::string& name) {return variable(find(name));}
442  const Variable& variable(const std::string& name) const {return variable(find(name));}
444 
447  Variable& variable(const MX& v) {return variable(find(v));}
448  const Variable& variable(const MX& v) const {return variable(find(v));}
450 
452  const MX& var(size_t ind) const;
453 
455  const MX& var(Category cat, size_t ind) const {return var(indices(cat).at(ind));}
456 
458  std::vector<MX> var(const std::vector<size_t>& ind) const;
459 
461  std::vector<MX> var(Category cat) const {return var(indices(cat));}
462 
464  size_t find(const std::string& name) const;
465 
467  size_t find(const MX& v) const;
468 
470  std::vector<size_t> find(const std::vector<std::string>& name) const;
471 
473  std::vector<size_t> find(const std::vector<MX>& v) const;
474 
478  const std::string& name(size_t ind) const;
479 
483  std::vector<std::string> name(const std::vector<size_t>& ind) const;
484 
486  const Function& oracle(bool sx = false, bool elim_w = false, bool lifted_calls = false) const;
487 
489  Sparsity jac_sparsity(const std::vector<size_t>& oind, const std::vector<size_t>& iind) const;
490 
492  Sparsity hess_sparsity(const std::vector<size_t>& oind, const std::vector<size_t>& iind) const;
493 
494  // Internal methods
495 protected:
496 
498  static std::string qualified_name(const XmlNode& nn, Attribute* att = nullptr);
499 
500  // User-set options
501  bool debug_;
502  double fmutol_;
503  bool ignore_time_;
504  bool enable_ls_dae_, enable_ls_serialization_;
505 
506  // FMI attributes
507  std::string fmi_version_;
508  std::string model_name_;
509  std::string instantiation_token_; // In FMI 2: guid
510  std::string description_;
511  std::string author_;
512  std::string copyright_;
513  std::string license_;
514  std::string generation_tool_;
515  std::string generation_date_and_time_;
516  std::string variable_naming_convention_;
517  casadi_int nzero_;
518 
519  // Default experiment
520  double start_time_, stop_time_, tolerance_, step_size_;
521 
522  // Model Exchange
523  std::string model_identifier_;
524  bool provides_directional_derivatives_;
525  bool provides_adjoint_derivatives_;
526  bool can_be_instantiated_only_once_per_process_;
527  std::vector<std::string> source_files_;
528 
530  std::string name_;
531 
532  // Path to FMU, if any
533  Resource resource_;
534 
535  // Symbolic representation of the model equations?
536  bool symbolic_;
537 
538  // Original index of the independent variable, if any
539  casadi_int orig_time_index_;
540 
541  // Detect quadrature states
542  bool detect_quad_;
543 
544  // FMI major version
545  casadi_int fmi_major_;
546 
548  std::vector<Variable*> variables_;
549 
550  // Model structure
551  std::vector<size_t> der_, initial_unknowns_;
552 
554  std::unordered_map<std::string, size_t> varind_;
555 
557  std::unordered_map<unsigned int, size_t> vrmap_;
558 
560  std::vector<std::vector<size_t>> indices_;
561 
562  // Initial equations
563  std::vector<size_t> init_;
564 
565  // Event conditions and transition equations
566  std::vector<std::pair<size_t, std::vector<size_t>>> when_;
567 
568  // Convert XML model variable index to DaeBuilder index
569  casadi_int convert_index(casadi_int index) const;
570 
574  bool has_t() const;
575 
576  // Time variable
577  const MX& time() const;
578 
582  std::vector<MX> cdef() const;
583 
587  std::vector<MX> init_lhs() const;
588 
592  std::vector<MX> init_rhs() const;
593 
595  static Variability default_variability(Causality causality, Type type);
596 
597  // Default initial attribute, per the FMI specification
598  static Initial default_initial(Causality causality, Variability variability);
599 
601  Variable& add(const std::string& name, Causality causality, Variability variability,
602  const Dict& opts);
603 
605  Variable& add(const std::string& name, Causality causality, Variability variability,
606  const MX& expr, const Dict& opts);
607 
609  Variable& add(const std::string& name, Causality causality, const Dict& opts);
610 
612  Variable& add(const std::string& name, const Dict& opts) {
613  // Per FMI 3.0.2 specification, section 2.4.7.4: Default causality is LOCAL
614  return add(name, Causality::LOCAL, opts);
615  }
616 
618  void categorize(size_t ind, Category cat);
619 
621  void insert(std::vector<size_t>& v, size_t ind) const;
622 
624  void remove(std::vector<size_t>& v, size_t ind) const;
625 
627  Causality causality(size_t ind) const;
628 
630  void set_causality(size_t ind, Causality causality);
631 
633  Variability variability(size_t ind) const;
634 
636  void set_variability(size_t ind, Variability variability);
637 
639  Category category(size_t ind) const;
640 
642  void set_category(size_t ind, Category cat);
643 
645  void eq(const MX& lhs, const MX& rhs, const Dict& opts);
646 
648  void when(const MX& cond, const std::vector<std::string>& eqs, const Dict& opts);
649 
651  Variable& assign(const std::string& name, const MX& val);
652 
654  Variable& reinit(const std::string& name, const MX& val);
655 
657  void set_init(const std::string& name, const MX& init_rhs);
658 
660  Function::AuxOut lc_;
661 
665  std::vector<Function> fun_;
666 
670  mutable Function oracle_[2][2][2];
671 
673  mutable bool clear_cache_;
674 
676  MX read_expr(const XmlNode& node);
677 
679  MX read_identifier(const XmlNode& node);
680 
682  Variable& read_variable(const XmlNode& node, Attribute* att = nullptr);
683 
684  // Read DefaultExperiment
685  void import_default_experiment(const XmlNode& n);
686 
687  // Read dependencies node
688  std::vector<casadi_int> read_dependencies(const XmlNode& n);
689 
690  // Read dependenciesKind node
691  std::vector<DependenciesKind> read_dependencies_kind(const XmlNode& n, size_t ndep);
692 
693  // Read ModelExchange
694  void import_model_exchange(const XmlNode& n);
695 
699  void import_model_variables(const XmlNode& modvars);
700 
701  // Read ModelStructure
702  void import_model_structure(const XmlNode& n);
703 
704  // Read LS-DAE manifest, if any
705  XmlNode import_ls_dae(const std::string& lsdae);
706 
707  // Read symbolic binding equations
708  void import_binding_equations(const XmlNode& eqs);
709 
710  // Read symbolic dynamic equations
711  void import_dynamic_equations(const XmlNode& eqs);
712 
713  // Read symbolic initial equations
714  void import_initial_equations(const XmlNode& eqs);
715 
717  void clear_cache() const;
718 
720  Function add_fun(const std::string& name,
721  const std::vector<std::string>& arg,
722  const std::vector<std::string>& res, const Dict& opts=Dict());
723 
725  Function add_fun(const Function& f);
726 
728  bool has_fun(const std::string& name) const;
729 
731  Function fun(const std::string& name) const;
732 
733  // Reset value attributes
734  void reset();
735 
738  double attribute(Attribute a, const std::string& name) const;
739  std::vector<double> attribute(Attribute a, const std::vector<std::string>& name) const;
741 
744  void set_attribute(Attribute a, const std::string& name, double val);
745  void set_attribute(Attribute a, const std::vector<std::string>& name,
746  const std::vector<double>& val);
748 
751  std::string string_attribute(Attribute a, const std::string& name) const;
752  std::vector<std::string> string_attribute(Attribute a,
753  const std::vector<std::string>& name) const;
755 
758  void set_string_attribute(Attribute a, const std::string& name, const std::string& val);
759  void set_string_attribute(Attribute a, const std::vector<std::string>& name,
760  const std::vector<std::string>& val);
762 
764  casadi_int size(Attribute a, const std::vector<std::string>& name) const;
765 
767  struct CallIO {
768  // Function instances
769  Function f, adj1_f, J, H;
770  // Index in v and vdef
771  std::vector<size_t> v, vdef;
772  // Nondifferentiated inputs
773  std::vector<MX> arg;
774  // Nondifferentiated inputs
775  std::vector<MX> res;
776  // Jacobian outputs
777  std::vector<MX> jac_res;
778  // Adjoint seeds
779  std::vector<MX> adj1_arg;
780  // Adjoint sensitivities
781  std::vector<MX> adj1_res;
782  // Hessian outputs
783  std::vector<MX> hess_res;
784  // Calculate Jacobian blocks
785  void calc_jac();
786  // Calculate gradient of Lagrangian
787  void calc_grad();
788  // Calculate Hessian of Lagrangian
789  void calc_hess();
790  // Access a specific Jacobian block
791  const MX& jac(casadi_int oind, casadi_int iind) const;
792  // Access a specific Hessian block
793  const MX& hess(casadi_int iind1, casadi_int iind2) const;
794  };
795 
797  MX jac_vdef_v_from_calls(std::map<MXNode*, CallIO>& call_nodes,
798  const std::vector<casadi_int>& h_offsets) const;
799 
801  MX hess_v_v_from_calls(std::map<MXNode*, CallIO>& call_nodes,
802  const std::vector<casadi_int>& h_offsets) const;
803 
804  // Sort dependent variables/parameters
805  static void sort_dependent(std::vector<MX>& v, std::vector<MX>& vdef);
806 };
807 
810 CASADI_EXPORT Type from_fmi2(TypeFmi2 v);
811 CASADI_EXPORT TypeFmi2 to_fmi2(Type v);
813 
816 CASADI_EXPORT std::string to_string(TypeFmi2 v);
817 CASADI_EXPORT std::string to_string(Type v);
818 CASADI_EXPORT std::string to_string(Causality v);
819 CASADI_EXPORT std::string to_string(Variability v);
820 CASADI_EXPORT std::string to_string(Initial v);
821 CASADI_EXPORT std::string to_string(Attribute v);
822 CASADI_EXPORT std::string to_string(DependenciesKind v);
823 CASADI_EXPORT std::string to_string(Category v);
825 
828 CASADI_EXPORT std::string description(Category v);
830 
831 // Check if input category
832 CASADI_EXPORT bool is_input_category(Category cat);
833 
834 // Check if output category
835 CASADI_EXPORT bool is_output_category(Category cat);
836 
837 // Check if acyclic dependency category
838 CASADI_EXPORT bool is_acyclic(Category cat);
839 
840 // Definition for acyclyc dependency categories
841 CASADI_EXPORT Category dependent_definition(Category cat);
842 
843 // Get all input categories
844 CASADI_EXPORT std::vector<Category> input_categories();
845 
846 // Get all output categories
847 CASADI_EXPORT std::vector<Category> output_categories();
848 
849 // Get the input category for a particular output category
850 CASADI_EXPORT Category input_category(Category cat);
851 
853 
854 } // namespace casadi
855 
856 #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:447
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.
bool permitted(Category cat) const
std::vector< Category > categories() const
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)