List of all members | Classes | Public Types | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Friends
casadi::DaeBuilderInternal Class Reference

#include <dae_builder_internal.hpp>

Detailed Description

Internal class for DaeBuilder, see comments on the public class.

Definition at line 209 of file dae_builder_internal.hpp.

Inheritance diagram for casadi::DaeBuilderInternal:
Inheritance graph
[legend]
Collaboration diagram for casadi::DaeBuilderInternal:
Collaboration graph
[legend]

Classes

struct  CallIO
 Helper class, represents inputs and outputs for a function call node. More...
 

Public Types

using weak_ref_type = WeakRefInternal
 

Public Member Functions

 DaeBuilderInternal (const std::string &name, const std::string &path, const Dict &opts)
 Constructor. More...
 
 ~DaeBuilderInternal () override
 Destructor. More...
 
std::string class_name () const override
 Readable name of the internal class. More...
 
void sanity_check () const
 Check if dimensions match. More...
 
std::vector< MXinput (Category ind) const
 
std::vector< MXoutput (OutputCategory ind) const
 
std::vector< MXinput (const std::vector< Category > &ind) const
 
std::vector< MXoutput (const std::vector< OutputCategory > &ind) const
 
void add_lc (const std::string &name, const std::vector< std::string > &f_out)
 Add a named linear combination of output expressions. More...
 
Function create (const std::string &fname, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts, bool sx, bool lifted_calls) const
 Construct a function object. More...
 
Function fmu_fun (const std::string &fname, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts) const
 Construct function from an FMU DLL. More...
 
Function dependent_fun (const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out) const
 Construct a function for evaluating dependent parameters. More...
 
Function transition (const std::string &fname, casadi_int index, bool dummy_index_input=false) const
 Construct a function describing transition at a specific event. More...
 
Function transition (const std::string &fname) const
 Construct a function describing transition at all events. More...
 
Function gather_eq () const
 Function corresponding to all equations. More...
 
const MXvar (const std::string &name) const
 Get variable expression by name. More...
 
MX get_der (size_t ind) const
 Get a derivative expression by variable index (const, never create) More...
 
MX get_der (size_t ind, bool may_allocate=true)
 Get a derivative expression by variable index (non-const, may create) More...
 
MX der (const MX &var) const
 Get a derivative expression by non-differentiated expression (const, never create) More...
 
MX der (const MX &var, bool may_allocate=true)
 Get a derivative expression by non-differentiated expression (non-const, may create) More...
 
std::string unique_name (const std::string &prefix, bool allow_no_prefix=true) const
 Find a unique name, with a specific prefix. More...
 
std::string type_name () const
 Readable name of the class. More...
 
void disp (std::ostream &stream, bool more) const override
 Print description. More...
 
std::string get_str (bool more=false) const
 Get string representation. More...
 
Variablenew_variable (const std::string &name, const std::vector< casadi_int > &dimension={1}, const MX &expr=MX())
 Create a new variable. More...
 
bool has (const std::string &name) const
 Check if a particular variable exists. More...
 
std::vector< std::string > all () const
 Get a list of all variables. More...
 
std::vector< std::string > all (Category cat) const
 Get a list of all variables of a particular category. More...
 
size_t n_variables () const
 Length of variables array. More...
 
size_t n_mem () const
 Length of memory for all variables. More...
 
std::vector< double > start_all () const
 Start values for all variables. More...
 
const MXvar (size_t ind) const
 Get variable expression by index. More...
 
const MXvar (Category cat, size_t ind) const
 Get variable expression by category and index. More...
 
std::vector< MXvar (const std::vector< size_t > &ind) const
 Get variable expressions by index. More...
 
std::vector< MXvar (Category cat) const
 Get variable expressions by category. More...
 
size_t find (const std::string &name) const
 Get index of variable, given name. More...
 
size_t find (const MX &v) const
 Get index of variable, given expression. More...
 
std::vector< size_t > find (const std::vector< std::string > &name) const
 Get indices of variable, given multiple names. More...
 
std::vector< size_t > find (const std::vector< MX > &v) const
 Get indices of variable, given multiple expressions. More...
 
const std::string & name (size_t ind) const
 Get variable name by index. More...
 
std::vector< std::string > name (const std::vector< size_t > &ind) const
 Get variable names by indices. More...
 
const Functionoracle (bool sx=false, bool elim_w=false, bool lifted_calls=false) const
 Get the (cached) oracle, SX or MX. More...
 
Sparsity jac_sparsity (const std::vector< size_t > &oind, const std::vector< size_t > &iind) const
 Get Jacobian sparsity. More...
 
Sparsity hess_sparsity (const std::vector< size_t > &oind, const std::vector< size_t > &iind) const
 Get what is known of the Hessian sparsity. More...
 
casadi_int getCount () const
 Get the reference count. More...
 
std::string debug_repr (const SharedObjectInternal *) const
 
GenericWeakRef< SharedObject, SharedObjectInternal > * weak ()
 Get a weak reference to the object. More...
 
Manipulation

Reformulate the dynamic optimization problem.

void eliminate (Category cat)
 Eliminate all variables of a category. More...
 
void sort (Category cat)
 Sort all variables of a category. More...
 
void lift (bool lift_shared, bool lift_calls)
 Lift problem formulation by extracting shared subexpressions. More...
 
void sort_z (const std::vector< std::string > &z_order)
 Sort algebraic variables. More...
 
std::vector< size_t > & indices (Category cat)
 Classified variable indices (mutable) More...
 
const std::vector< size_t > & indices (Category cat) const
 Classified variable indices (immutable) More...
 
size_t size (Category cat) const
 Number of indices with a particular category. More...
 
void reorder (Category cat, const std::vector< size_t > &v)
 Reorder variables in a category. More...
 
void reorder (const std::string &n, std::vector< size_t > &ind, const std::vector< size_t > &v) const
 Reorder any index vector. More...
 
void prune (bool prune_p, bool prune_u)
 Prune unused controls. More...
 
void tearing_variables (std::vector< std::string > *res, std::vector< std::string > *iv, std::vector< std::string > *iv_on_hold) const
 Identify free variables and residual equations. More...
 
void tear ()
 Identify free variables and residual equations. More...
 
Variablevariable (size_t ind)
 
const Variablevariable (size_t ind) const
 
Variablevariable (Category cat, size_t ind)
 
const Variablevariable (Category cat, size_t ind) const
 
Variablevariable (const std::string &name)
 
const Variablevariable (const std::string &name) const
 
Variablevariable (const MX &v)
 
const Variablevariable (const MX &v) const
 

Protected Member Functions

bool has_t () const
 Is there a time variable? More...
 
const MXtime () const
 
std::vector< MXcdef () const
 Definitions of dependent constants. More...
 
std::vector< MXinit_lhs () const
 Initial conditions, left-hand-side. More...
 
std::vector< MXinit_rhs () const
 Initial conditions, right-hand-side. More...
 
Variableadd (const std::string &name, Causality causality, Variability variability, const Dict &opts)
 Add a new variable. More...
 
Variableadd (const std::string &name, Causality causality, Variability variability, const MX &expr, const Dict &opts)
 Add a new variable, expression provided. More...
 
Variableadd (const std::string &name, Causality causality, const Dict &opts)
 Add a new variable, default variability. More...
 
Variableadd (const std::string &name, const Dict &opts)
 Add a new variable, default variability and causality. More...
 
void categorize (size_t ind, Category cat)
 Set or change the category for a variable. More...
 
void insert (std::vector< size_t > &v, size_t ind) const
 Insert into list of variables, keeping it ordered. More...
 
void remove (std::vector< size_t > &v, size_t ind) const
 Remove from list of variables. More...
 
Causality causality (size_t ind) const
 Get causality. More...
 
void set_causality (size_t ind, Causality causality)
 Set causality. More...
 
Variability variability (size_t ind) const
 Get variability. More...
 
void set_variability (size_t ind, Variability variability)
 Set variability. More...
 
Category category (size_t ind) const
 Get category. More...
 
void set_category (size_t ind, Category cat)
 Set category. More...
 
void eq (const MX &lhs, const MX &rhs, const Dict &opts)
 Add a simple equation. More...
 
void when (const MX &cond, const std::vector< std::string > &eqs, const Dict &opts)
 Add when equations. More...
 
Variableassign (const std::string &name, const MX &val)
 Assignment inside when-equations or if-else equations. More...
 
Variablereinit (const std::string &name, const MX &val)
 Reinitialize a state inside when-equations. More...
 
void set_init (const std::string &name, const MX &init_rhs)
 Set a initial equation. More...
 
MX read_expr (const XmlNode &node)
 Read an equation. More...
 
MX read_identifier (const XmlNode &node)
 Read an identifier expression. More...
 
Variableread_variable (const XmlNode &node, Attribute *att=0)
 Read a variable. More...
 
void import_default_experiment (const XmlNode &n)
 
std::vector< casadi_int > read_dependencies (const XmlNode &n)
 
std::vector< DependenciesKindread_dependencies_kind (const XmlNode &n, size_t ndep)
 
void import_model_exchange (const XmlNode &n)
 
void import_model_variables (const XmlNode &modvars)
 
void import_model_structure (const XmlNode &n)
 
void import_binding_equations (const XmlNode &eqs)
 
void import_dynamic_equations (const XmlNode &eqs)
 
void import_initial_equations (const XmlNode &eqs)
 
void clear_cache () const
 Problem structure has changed: Clear cache. More...
 
Function add_fun (const std::string &name, const std::vector< std::string > &arg, const std::vector< std::string > &res, const Dict &opts=Dict())
 Add a function from loaded expressions. More...
 
Function add_fun (const Function &f)
 Add an already existing function. More...
 
bool has_fun (const std::string &name) const
 Does a particular function already exist? More...
 
Function fun (const std::string &name) const
 Get function by name. More...
 
void reset ()
 
casadi_int size (Attribute a, const std::vector< std::string > &name) const
 Total number of elements for a particular attribute. More...
 
MX jac_vdef_v_from_calls (std::map< MXNode *, CallIO > &call_nodes, const std::vector< casadi_int > &h_offsets) const
 Calculate contribution to jac_vdef_v from lifted calls. More...
 
MX hess_v_v_from_calls (std::map< MXNode *, CallIO > &call_nodes, const std::vector< casadi_int > &h_offsets) const
 Calculate contribution to hess_?_v_v from lifted calls. More...
 
void initSingleton ()
 
void destroySingleton ()
 
shared_from_this ()
 Get a shared object from the current internal object. More...
 
const B shared_from_this () const
 Get a shared object from the current internal object. More...
 
double attribute (Attribute a, const std::string &name) const
 
std::vector< double > attribute (Attribute a, const std::vector< std::string > &name) const
 
void set_attribute (Attribute a, const std::string &name, double val)
 
void set_attribute (Attribute a, const std::vector< std::string > &name, const std::vector< double > &val)
 
std::string string_attribute (Attribute a, const std::string &name) const
 
std::vector< std::string > string_attribute (Attribute a, const std::vector< std::string > &name) const
 
void set_string_attribute (Attribute a, const std::string &name, const std::string &val)
 
void set_string_attribute (Attribute a, const std::vector< std::string > &name, const std::vector< std::string > &val)
 

Static Protected Member Functions

static std::string qualified_name (const XmlNode &nn, Attribute *att=0)
 Get the qualified name. More...
 
static Variability default_variability (Causality causality, Type type)
 Default variability attribute, per the FMI specification. More...
 
static Initial default_initial (Causality causality, Variability variability)
 
static void sort_dependent (std::vector< MX > &v, std::vector< MX > &vdef)
 

Protected Attributes

bool debug_
 
double fmutol_
 
bool ignore_time_
 
std::string fmi_version_
 
std::string model_name_
 
std::string instantiation_token_
 
std::string description_
 
std::string author_
 
std::string copyright_
 
std::string license_
 
std::string generation_tool_
 
std::string generation_date_and_time_
 
std::string variable_naming_convention_
 
casadi_int number_of_event_indicators_
 
double start_time_
 
double stop_time_
 
double tolerance_
 
double step_size_
 
std::string model_identifier_
 
bool provides_directional_derivatives_
 
bool provides_adjoint_derivatives_
 
bool can_be_instantiated_only_once_per_process_
 
std::vector< std::string > source_files_
 
std::string name_
 Name of instance. More...
 
Resource resource_
 
bool symbolic_
 
bool detect_quad_
 
casadi_int fmi_major_
 
std::vector< Variable * > variables_
 All variables. More...
 
std::vector< size_t > outputs_
 
std::vector< size_t > derivatives_
 
std::vector< size_t > initial_unknowns_
 
std::vector< size_t > event_indicators_
 
std::vector< size_t > residuals_
 
std::vector< size_t > rate_
 
std::unordered_map< std::string, size_t > varind_
 Find of variable by name. More...
 
std::unordered_map< unsigned int, size_t > vrmap_
 Find of variable by value reference. More...
 
std::vector< std::vector< size_t > > indices_
 Ordered variables. More...
 
std::vector< size_t > init_
 
std::vector< std::pair< size_t, std::vector< size_t > > > when_
 
Function::AuxOut lc_
 Linear combinations of output expressions. More...
 
std::vector< Functionfun_
 Functions. More...
 
Function oracle_ [2][2][2]
 Function oracles (cached) More...
 
bool clear_cache_
 Should the cache be cleared? More...
 

Friends

class DaeBuilder
 
class FmuInternal
 
class FmuFunction
 
class Variable
 

Import and export

void load_fmi_description (const std::string &filename)
 
std::vector< std::string > export_fmu (const Dict &opts) const
 Export instance into an FMU (experimental) More...
 
std::string generate_wrapper (const std::string &guid, const CodeGenerator &gen) const
 Generate FMU wrapper file (fmi3Functions.c) More...
 
std::string generate_build_description (const std::vector< std::string > &cfiles) const
 Generate buildDescription.xml. More...
 
std::string generate_model_description (const std::string &guid) const
 Generate modelDescription.xml. More...
 
XmlNode generate_model_variables () const
 Generate FMU ModelVariables. More...
 
XmlNode generate_model_structure () const
 Generate FMU ModelStructure. More...
 
void update_dependencies () const
 Update model variable dependencies. More...
 
static std::string iso_8601_time ()
 Get current date and time in the ISO 8601 format. More...
 
static std::string generate_guid ()
 
static std::string generate (const std::vector< size_t > &v)
 
static std::string generate (const std::vector< double > &v)
 

Member Typedef Documentation

◆ weak_ref_type

Definition at line 152 of file shared_object.hpp.

Constructor & Destructor Documentation

◆ DaeBuilderInternal()

casadi::DaeBuilderInternal::DaeBuilderInternal ( const std::string &  name,
const std::string &  path,
const Dict opts 
)
explicit

Definition at line 565 of file dae_builder_internal.cpp.

566  : name_(name), resource_(path) {
567  clear_cache_ = false;
572  symbolic_ = true;
573  detect_quad_ = false;
574  start_time_ = nan;
575  stop_time_ = nan;
576  tolerance_ = nan;
577  step_size_ = nan;
578  // Default options
579  debug_ = false;
580  fmutol_ = 0;
581  ignore_time_ = false;
582  std::string resource_serialize = "link";
583  // Read options
584  for (auto&& op : opts) {
585  if (op.first=="debug") {
586  debug_ = op.second;
587  } else if (op.first=="fmutol") {
588  fmutol_ = op.second;
589  } else if (op.first=="ignore_time") {
590  ignore_time_ = op.second;
591  } else if (op.first=="detect_quad") {
592  detect_quad_ = op.second;
593  } else if (op.first=="resource_serialize_mode") {
594  resource_.change_option("serialize_mode", op.second);
595  } else {
596  casadi_error("No such option: " + op.first);
597  }
598  }
600 }
bool clear_cache_
Should the cache be cleared?
std::vector< std::vector< size_t > > indices_
Ordered variables.
const std::string & name(size_t ind) const
Get variable name by index.
std::string name_
Name of instance.
void change_option(const std::string &option_name, const GenericType &option_value)
Change option after object creation for debugging.
Definition: resource.cpp:74
const double nan
Not a number.
Definition: calculus.hpp:53
std::vector< casadi_int > path(const std::vector< casadi_int > &map, casadi_int i_start)
static const size_t n_enum
Definition: casadi_enum.hpp:42

References can_be_instantiated_only_once_per_process_, casadi::Resource::change_option(), clear_cache_, debug_, detect_quad_, fmutol_, ignore_time_, indices_, casadi::nan, number_of_event_indicators_, provides_adjoint_derivatives_, provides_directional_derivatives_, resource_, start_time_, step_size_, stop_time_, symbolic_, and tolerance_.

◆ ~DaeBuilderInternal()

casadi::DaeBuilderInternal::~DaeBuilderInternal ( )
override

Definition at line 559 of file dae_builder_internal.cpp.

559  {
560  for (Variable* v : variables_) {
561  if (v) delete v;
562  }
563 }
std::vector< Variable * > variables_
All variables.

References variables_.

Member Function Documentation

◆ add() [1/4]

Variable & casadi::DaeBuilderInternal::add ( const std::string &  name,
Causality  causality,
const Dict opts 
)
protected

Definition at line 2886 of file dae_builder_internal.cpp.

2886  {
2887  // Get type
2888  Type type = Type::FLOAT64;
2889  if (opts.find("type") != opts.end()) {
2890  type = to_enum<Type>(opts.at("type").to_string());
2891  }
2892 
2893  // Default variability per FMI 3.0.2, section 2.4.7.4
2894  return add(name, causality, default_variability(causality, type), opts);
2895 }
Causality causality(size_t ind) const
Get causality.
static Variability default_variability(Causality causality, Type type)
Default variability attribute, per the FMI specification.
Variable & add(const std::string &name, Causality causality, Variability variability, const Dict &opts)
Add a new variable.
Type
Variable type (FMI 3)

References add(), causality(), default_variability(), casadi::FLOAT64, and name().

◆ add() [2/4]

Variable & casadi::DaeBuilderInternal::add ( const std::string &  name,
Causality  causality,
Variability  variability,
const Dict opts 
)
protected

Definition at line 2755 of file dae_builder_internal.cpp.

2756  {
2757  // No expression provided
2758  return add(name, causality, variability, MX(), opts);
2759 }
Variability variability(size_t ind) const
Get variability.

References causality(), name(), and variability().

Referenced by add(), assign(), eq(), import_model_variables(), reinit(), and when().

◆ add() [3/4]

Variable & casadi::DaeBuilderInternal::add ( const std::string &  name,
Causality  causality,
Variability  variability,
const MX expr,
const Dict opts 
)
protected

Definition at line 2761 of file dae_builder_internal.cpp.

2762  {
2763  // Default options
2764  std::string description, type, initial, unit, display_unit;
2765  std::vector<casadi_int> dimension = {1};
2766  double min = -casadi::inf, max = casadi::inf, nominal = 1;
2767  std::vector<double> start;
2768  // Read options
2769  for (auto&& op : opts) {
2770  if (op.first=="dimension") {
2771  dimension = op.second.to_int_vector();
2772  } else if (op.first=="description") {
2773  description = op.second.to_string();
2774  } else if (op.first=="unit") {
2775  unit = op.second.to_string();
2776  } else if (op.first=="display_unit") {
2777  display_unit = op.second.to_string();
2778  } else if (op.first=="min") {
2779  min = op.second.to_double();
2780  } else if (op.first=="max") {
2781  max = op.second.to_double();
2782  } else if (op.first=="nominal") {
2783  nominal = op.second.to_double();
2784  } else if (op.first=="start") {
2785  if (op.second.can_cast_to(OT_DOUBLE)) {
2786  start.resize(1, op.second.to_double());
2787  } else {
2788  start = op.second.to_double_vector();
2789  }
2790  } else if (op.first=="type") {
2791  type = op.second.to_string();
2792  } else if (op.first=="initial") {
2793  initial = op.second.to_string();
2794  } else {
2795  casadi_error("No such option: " + op.first);
2796  }
2797  }
2798  // Create a new variable
2799  Variable& v = new_variable(name, dimension, expr);
2800  v.description = description;
2801  if (!type.empty()) v.type = to_enum<Type>(type);
2802  v.causality = causality;
2803  v.variability = variability;
2804  if (!start.empty()) v.start = start;
2805  if (!initial.empty()) v.initial = to_enum<Initial>(initial);
2806  if (!unit.empty()) v.unit = unit;
2807  if (!display_unit.empty()) v.display_unit = display_unit;
2808  if (min != -casadi::inf) v.min = min;
2809  if (max != casadi::inf) v.max = max;
2810  v.nominal = nominal;
2811  // Handle different categories
2812  switch (causality) {
2813  case Causality::PARAMETER:
2814  // Parameter
2816  categorize(v.index, Category::P);
2817  } else if (variability == Variability::FIXED) {
2818  categorize(v.index, Category::C);
2819  } else {
2820  casadi_error("'parameter' causality requires 'fixed' or 'tunable' variability");
2821  }
2822  break;
2825  "'calculatedParameter' causality requires 'fixed' or 'tunable' variability");
2826  categorize(v.index, Category::D);
2827  break;
2828  case Causality::INPUT:
2829  // Control
2830  casadi_assert(variability == Variability::CONTINUOUS
2832  "'input' causality requires 'continuous' or 'discrete' variability");
2833  categorize(v.index, Category::U);
2834  break;
2835  case Causality::OUTPUT:
2836  // Type determined by providing equation, unless discrete variability
2838  // Constant output
2839  categorize(v.index, Category::C);
2840  } else if (variability == Variability::DISCRETE) {
2841  // Discrete variables are considered states with zero derivatives
2843  } else if (variability == Variability::CONTINUOUS) {
2844  // Continuous variables are considered algebraic variables until given a defining equation
2845  categorize(v.index, Category::Z);
2846  } else {
2847  casadi_error("'output' causality requires 'constant', 'continuous' or "
2848  "'discrete' variability");
2849  }
2850  break;
2851  case Causality::LOCAL:
2852  // Type determined by providing equation, unless discrete variability
2854  // Constant local
2855  categorize(v.index, Category::C);
2856  } else if (variability == Variability::DISCRETE) {
2857  // Discrete variables are considered states with zero derivatives
2859  } else if (variability == Variability::CONTINUOUS) {
2860  // Continuous variables are considered algebraic variables until given a defining equation
2861  categorize(v.index, Category::Z);
2863  // Fixed or tunable local
2864  categorize(v.index, Category::D);
2865  } else {
2866  casadi_error("'output' causality requires 'constant', 'fixed', 'tunable', 'discrete' or "
2867  "'continuous' variability");
2868  }
2869  break;
2871  // Independent variable
2872  casadi_assert(!has_t(), "'t' already defined");
2873  casadi_assert(variability == Variability::CONTINUOUS,
2874  "Independent variable must be continuous");
2875  categorize(v.index, Category::T);
2876  break;
2877  default:
2878  casadi_error("Unknown causality: " + to_string(causality));
2879  }
2880  // If an output, add to list of outputs
2881  if (causality == Causality::OUTPUT) outputs_.push_back(v.index);
2882  // Return variable reference
2883  return v;
2884 }
bool has_t() const
Is there a time variable?
Variable & new_variable(const std::string &name, const std::vector< casadi_int > &dimension={1}, const MX &expr=MX())
Create a new variable.
void categorize(size_t ind, Category cat)
Set or change the category for a variable.
std::string description(Category v)
const double inf
infinity
Definition: calculus.hpp:50
std::string to_string(TypeFmi2 v)

References casadi::C, casadi::CALCULATED_PARAMETER, categorize(), casadi::Variable::causality, causality(), casadi::CONSTANT, casadi::CONTINUOUS, casadi::D, casadi::description(), casadi::Variable::description, detect_quad_, casadi::DISCRETE, casadi::Variable::display_unit, casadi::FIXED, has_t(), casadi::INDEPENDENT, casadi::Variable::index, casadi::inf, casadi::Variable::initial, casadi::INPUT, casadi::LOCAL, casadi::Variable::max, casadi::Variable::min, name(), new_variable(), casadi::Variable::nominal, casadi::OT_DOUBLE, casadi::OUTPUT, outputs_, casadi::P, casadi::PARAMETER, casadi::Q, casadi::Variable::start, casadi::T, casadi::to_string(), casadi::TUNABLE, casadi::Variable::type, casadi::U, casadi::Variable::unit, casadi::Variable::variability, variability(), casadi::X, and casadi::Z.

◆ add() [4/4]

Variable& casadi::DaeBuilderInternal::add ( const std::string &  name,
const Dict opts 
)
inlineprotected

Definition at line 591 of file dae_builder_internal.hpp.

591  {
592  // Per FMI 3.0.2 specification, section 2.4.7.4: Default causality is LOCAL
593  return add(name, Causality::LOCAL, opts);
594  }

References casadi::LOCAL.

◆ add_fun() [1/2]

Function casadi::DaeBuilderInternal::add_fun ( const Function f)
protected

Definition at line 4003 of file dae_builder_internal.cpp.

4003  {
4004  casadi_assert(!has_fun(f.name()), "Function '" + f.name() + "' already exists");
4005  fun_.push_back(f);
4006  return f;
4007 }
bool has_fun(const std::string &name) const
Does a particular function already exist?
std::vector< Function > fun_
Functions.

References fun_, has_fun(), and casadi::Function::name().

◆ add_fun() [2/2]

Function casadi::DaeBuilderInternal::add_fun ( const std::string &  name,
const std::vector< std::string > &  arg,
const std::vector< std::string > &  res,
const Dict opts = Dict() 
)
protected

Definition at line 4009 of file dae_builder_internal.cpp.

4011  {
4012  casadi_assert(!has_fun(name), "Function '" + name + "' already exists");
4013 
4014  // Dependent variable definitions
4015  std::vector<MX> wdef = output(OutputCategory::WDEF);
4016  // Get inputs
4017  std::vector<MX> arg_ex, res_ex;
4018  for (auto&& s : arg) arg_ex.push_back(var(s));
4019  for (auto&& s : res) {
4020  // Find the binding expression FIXME(@jaeandersson)
4021  casadi_int v_ind;
4022  for (v_ind = 0; v_ind < size(Category::W); ++v_ind) {
4023  if (s == variable(indices(Category::W).at(v_ind)).name) {
4024  res_ex.push_back(wdef.at(v_ind));
4025  break;
4026  }
4027  }
4028  casadi_assert(v_ind < size(Category::W), "Cannot find dependent '" + s + "'");
4029  }
4030  Function ret(name, arg_ex, res_ex, arg, res, opts);
4031  return add_fun(ret);
4032 }
std::vector< size_t > & indices(Category cat)
Classified variable indices (mutable)
std::vector< MX > output(OutputCategory ind) const
Variable & variable(size_t ind)
Function add_fun(const std::string &name, const std::vector< std::string > &arg, const std::vector< std::string > &res, const Dict &opts=Dict())
Add a function from loaded expressions.
size_t size(Category cat) const
Number of indices with a particular category.
const MX & var(const std::string &name) const
Get variable expression by name.
std::string name
Name of the variable.

References has_fun(), indices(), casadi::Variable::name, name(), output(), size(), var(), variable(), casadi::W, and casadi::WDEF.

◆ add_lc()

void casadi::DaeBuilderInternal::add_lc ( const std::string &  name,
const std::vector< std::string > &  f_out 
)

Definition at line 1903 of file dae_builder_internal.cpp.

1903  {
1904  // Make sure object valid
1905  sanity_check();
1906 
1907  // Make sure name is valid
1908  casadi_assert(!name.empty(), "DaeBuilderInternal::add_lc: \"name\" is empty");
1909  for (std::string::const_iterator i=name.begin(); i!=name.end(); ++i) {
1910  casadi_assert(isalnum(*i),
1911  "DaeBuilderInternal::add_lc: \"name\" must be alphanumeric");
1912  }
1913 
1914  // Consistency checks
1915  casadi_assert(!f_out.empty(), "DaeBuilderInternal::add_lc: Linear combination is empty");
1916  std::vector<bool> in_use(enum_traits<OutputCategory>::n_enum, false);
1917  for (casadi_int i=0; i < f_out.size(); ++i) {
1918  auto oind = static_cast<size_t>(to_enum<OutputCategory>(f_out[i]));
1919  casadi_assert(!in_use[oind], "DaeBuilderInternal::add_lc: Duplicate expression " + f_out[i]);
1920  in_use[oind] = true;
1921  }
1922 
1923  std::vector<std::string>& ret1 = lc_[name];
1924  if (!ret1.empty()) casadi_warning("DaeBuilderInternal::add_lc: Overwriting " << name);
1925  ret1 = f_out;
1926 }
void sanity_check() const
Check if dimensions match.
Function::AuxOut lc_
Linear combinations of output expressions.

References lc_, name(), and sanity_check().

◆ all() [1/2]

std::vector< std::string > casadi::DaeBuilderInternal::all ( ) const

Definition at line 1605 of file dae_builder_internal.cpp.

1605  {
1606  std::vector<std::string> r;
1607  r.reserve(n_variables());
1608  for (const Variable* v : variables_) r.push_back(v->name);
1609  return r;
1610 }
size_t n_variables() const
Length of variables array.

References n_variables(), and variables_.

◆ all() [2/2]

std::vector< std::string > casadi::DaeBuilderInternal::all ( Category  cat) const

Definition at line 1612 of file dae_builder_internal.cpp.

1612  {
1613  return name(indices(cat));
1614 }

References indices(), and name().

◆ assign()

Variable & casadi::DaeBuilderInternal::assign ( const std::string &  name,
const MX val 
)
protected

Definition at line 3234 of file dae_builder_internal.cpp.

3234  {
3235  // Create a unique name for the reinit variable
3236  std::string assign_name = unique_name("__assign__" + name + "__");
3237  // Add a new dependent variable defined by val
3239  val, Dict());
3240  // Classify as assign variable
3241  categorize(v.index, Category::CALCULATED);
3242  v.parent = variable(name).index;
3243  // Return the variable name
3244  return v;
3245 }
std::string unique_name(const std::string &prefix, bool allow_no_prefix=true) const
Find a unique name, with a specific prefix.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
casadi_int index
Location in variable vector.

References add(), casadi::CALCULATED, categorize(), casadi::CONTINUOUS, casadi::Variable::index, casadi::LOCAL, name(), casadi::Variable::parent, unique_name(), and variable().

Referenced by import_binding_equations(), import_dynamic_equations(), lift(), and read_expr().

◆ attribute() [1/2]

double casadi::DaeBuilderInternal::attribute ( Attribute  a,
const std::string &  name 
) const
protected

Get by attribute name

Definition at line 4056 of file dae_builder_internal.cpp.

4056  {
4057  double ret;
4058  variable(name).get_attribute(a, &ret);
4059  return ret;
4060 }
void get_attribute(Attribute a, double *val) const

References casadi::Variable::get_attribute(), name(), and variable().

◆ attribute() [2/2]

std::vector< double > casadi::DaeBuilderInternal::attribute ( Attribute  a,
const std::vector< std::string > &  name 
) const
protected

Get by attribute name

Definition at line 4062 of file dae_builder_internal.cpp.

4063  {
4064  // Allocate return
4065  std::vector<double> r;
4066  r.reserve(size(a, name));
4067  // Get contribution from each variable
4068  std::vector<double> r1;
4069  for (auto& n : name) {
4070  variable(n).get_attribute(a, &r1);
4071  r.insert(r.end(), r1.begin(), r1.end());
4072  }
4073  return r;
4074 }

References casadi::Variable::get_attribute(), name(), size(), and variable().

◆ categorize()

void casadi::DaeBuilderInternal::categorize ( size_t  ind,
Category  cat 
)
protected

Definition at line 2897 of file dae_builder_internal.cpp.

2897  {
2898  // Get variable reference
2899  Variable& v = variable(ind);
2900  // If same category, quick return
2901  if (v.category == cat) return;
2902  // Remove from current category, if any
2903  if (v.category != Category::NUMEL) {
2904  remove(indices(v.category), ind);
2905  v.category = Category::NUMEL;
2906  }
2907  // Add to new category, if any
2908  if (cat != Category::NUMEL) {
2909  std::vector<size_t>& indices = this->indices(cat);
2910  if (is_acyclic(cat)) {
2911  indices.push_back(ind);
2912  } else {
2913  insert(indices, ind);
2914  }
2915  v.category = cat;
2916  }
2917 }
void insert(std::vector< size_t > &v, size_t ind) const
Insert into list of variables, keeping it ordered.
void remove(std::vector< size_t > &v, size_t ind) const
Remove from list of variables.
bool is_acyclic(Category cat)

References casadi::Variable::category, indices(), insert(), casadi::is_acyclic(), casadi::NUMEL, remove(), and variable().

Referenced by add(), assign(), eliminate(), import_dynamic_equations(), import_model_structure(), import_model_variables(), reinit(), set_category(), set_variability(), and when().

◆ category()

Category casadi::DaeBuilderInternal::category ( size_t  ind) const
protected

Definition at line 3034 of file dae_builder_internal.cpp.

3034  {
3035  return variable(ind).category;
3036 }
Category category
CasADi's classification of the variable.

References casadi::Variable::category, and variable().

◆ causality()

Causality casadi::DaeBuilderInternal::causality ( size_t  ind) const
protected

Definition at line 2941 of file dae_builder_internal.cpp.

2941  {
2942  return variable(ind).causality;
2943 }

References casadi::Variable::causality, and variable().

Referenced by add(), default_initial(), default_variability(), import_model_variables(), and set_causality().

◆ cdef()

std::vector< MX > casadi::DaeBuilderInternal::cdef ( ) const
protected

Extra doc: https://github.com/casadi/casadi/wiki/L_2c7

Definition at line 2687 of file dae_builder_internal.cpp.

2687  {
2688  std::vector<MX> ret;
2689  ret.reserve(size(Category::C));
2690  for (size_t c : indices(Category::C)) ret.push_back(variable(variable(c).bind).v);
2691  return ret;
2692 }

References casadi::C, indices(), size(), and variable().

◆ class_name()

std::string casadi::DaeBuilderInternal::class_name ( ) const
inlineoverridevirtual

Implements casadi::SharedObjectInternal.

Definition at line 224 of file dae_builder_internal.hpp.

224 {return "DaeBuilderInternal";}

◆ clear_cache()

void casadi::DaeBuilderInternal::clear_cache ( ) const
protected

Definition at line 2238 of file dae_builder_internal.cpp.

2238  {
2239  for (bool sx : {false, true}) {
2240  for (bool elim_w : {false, true}) {
2241  for (bool lifted_calls : {false, true}) {
2242  Function& fref = oracle_[sx][elim_w][lifted_calls];
2243  if (!fref.is_null()) fref = Function();
2244  }
2245  }
2246  }
2247  clear_cache_ = false;
2248 }
Function oracle_[2][2][2]
Function oracles (cached)

References clear_cache_, casadi::GenericShared< Shared, Internal >::is_null(), and oracle_.

Referenced by oracle().

◆ create()

Function casadi::DaeBuilderInternal::create ( const std::string &  fname,
const std::vector< std::string > &  name_in,
const std::vector< std::string > &  name_out,
const Dict opts,
bool  sx,
bool  lifted_calls 
) const

Definition at line 1928 of file dae_builder_internal.cpp.

1930  {
1931  // Are there any '_' in the names?
1932  bool with_underscore = false;
1933  for (auto s_io : {&s_in, &s_out}) {
1934  for (const std::string& s : *s_io) {
1935  with_underscore = with_underscore || std::count(s.begin(), s.end(), '_');
1936  }
1937  }
1938  // Model equations in DLL
1939  if (!symbolic_) {
1940  // Cannot lift calls in an FMU
1941  casadi_assert(!lifted_calls, "Lifting requires a symbolic representation");
1942  // Cannot convert to SX
1943  casadi_assert(!sx, "SX expansion requires a symbolic representation");
1944  // Redirect to FmuFunction creation
1945  return fmu_fun(fname, s_in, s_out, opts);
1946  }
1947  // Replace '_' with ':', if needed
1948  if (with_underscore) {
1949  std::vector<std::string> s_in_mod(s_in), s_out_mod(s_out);
1950  for (auto s_io : {&s_in_mod, &s_out_mod}) {
1951  for (std::string& s : *s_io) std::replace(s.begin(), s.end(), '_', ':');
1952  }
1953  // Recursive call
1954  return create(fname, s_in_mod, s_out_mod, opts, sx, lifted_calls);
1955  }
1956  // Check if dependent variables are given and needed
1957  bool elim_w = false;
1958  if (size(Category::W) > 0) {
1959  // Dependent variables exists, eliminate unless v is given
1960  elim_w = true;
1961  for (const std::string& s : s_in) {
1962  if (s == "w") {
1963  // Dependent variables are given
1964  elim_w = false;
1965  break;
1966  }
1967  }
1968  }
1969  // Are lifted calls really needed?
1970  if (lifted_calls) {
1971  // Consistency check
1972  casadi_assert(!elim_w, "Lifted calls cannot be used if dependent variables are eliminated");
1973  // Only lift calls if really needed
1974  lifted_calls = false;
1975  for (const MX& vdef_comp : output(OutputCategory::WDEF)) {
1976  if (vdef_comp.is_output()) {
1977  // There are indeed function calls present
1978  lifted_calls = true;
1979  break;
1980  }
1981  }
1982  }
1983  // Call factory without lifted calls
1984  std::string fname_nocalls = lifted_calls ? fname + "_nocalls" : fname;
1985  Function ret = oracle(sx, elim_w, lifted_calls).factory(fname_nocalls, s_in, s_out, lc_);
1986  // If no lifted calls, done
1987  if (!lifted_calls) return ret;
1988  // MX expressions for ret without lifted calls
1989  std::vector<MX> ret_in = ret.mx_in();
1990  std::vector<MX> ret_out = ret(ret_in);
1991  // Offsets in v
1992  std::vector<casadi_int> h_offsets = offset(var(indices(Category::W)));
1993  // Split "w", "lam_wdef" into components
1994  std::vector<MX> v_in, lam_vdef_in;
1995  for (size_t i = 0; i < s_in.size(); ++i) {
1996  if (ret.name_in(i) == "w") {
1997  v_in = vertsplit(ret_in[i], h_offsets);
1998  } else if (ret.name_in(i) == "lam_wdef") {
1999  lam_vdef_in = vertsplit(ret_in[i], h_offsets);
2000  }
2001  }
2002  // Map dependent variables into index in vector
2003  std::map<MXNode*, size_t> v_map;
2004  for (size_t i = 0; i < size(Category::W); ++i) {
2005  v_map[var(Category::W, i).get()] = i;
2006  }
2007  // Definitions of w
2008  std::vector<MX> wdef = output(OutputCategory::WDEF);
2009  // Collect all the call nodes
2010  std::map<MXNode*, CallIO> call_nodes;
2011  for (size_t vdefind = 0; vdefind < wdef.size(); ++vdefind) {
2012  // Current element handled
2013  const MX& vdefref = wdef.at(vdefind);
2014  // Handle function call nodes
2015  if (vdefref.is_output()) {
2016  // Get function call node
2017  MX c = vdefref.dep(0);
2018  // Find the corresponding call node in the map
2019  auto call_it = call_nodes.find(c.get());
2020  // If first time this call node is encountered
2021  if (call_it == call_nodes.end()) {
2022  // Create new CallIO struct
2023  CallIO cio;
2024  // Save function instance
2025  cio.f = c.which_function();
2026  // Expressions for function call inputs
2027  cio.v.resize(c.n_dep(), -1);
2028  cio.arg.resize(cio.v.size());
2029  for (casadi_int i = 0; i < cio.v.size(); ++i) {
2030  if (c.dep(i).is_constant()) {
2031  cio.arg.at(i) = c.dep(i);
2032  } else {
2033  size_t v_ind = v_map.at(c.dep(i).get());
2034  cio.v.at(i) = v_ind;
2035  cio.arg.at(i) = v_in.at(v_ind);
2036  }
2037  }
2038  // Allocate memory for function call outputs
2039  cio.vdef.resize(c.n_out(), -1);
2040  cio.res.resize(cio.vdef.size());
2041  // Allocate memory for adjoint seeds, if any
2042  if (!lam_vdef_in.empty()) cio.adj1_arg.resize(c.n_out());
2043  // Save to map and update iterator
2044  call_it = call_nodes.insert(std::make_pair(c.get(), cio)).first;
2045  }
2046  // Which output of the function are we calculating?
2047  casadi_int oind = vdefref.which_output();
2048  // Save output expression to structure
2049  call_it->second.vdef.at(oind) = vdefind;
2050  call_it->second.res.at(oind) = v_in.at(vdefind);
2051  // Save adjoint seed to structure, if any
2052  if (!lam_vdef_in.empty()) call_it->second.adj1_arg.at(oind) = lam_vdef_in.at(vdefind);
2053  }
2054  }
2055  // Additional term in jac_vdef_v
2056  for (size_t i = 0; i < ret_out.size(); ++i) {
2057  if (ret.name_out(i) == "jac_wdef_w") {
2058  ret_out.at(i) += jac_vdef_v_from_calls(call_nodes, h_offsets);
2059  }
2060  }
2061  // Additional term in hess_?_v_v where ? is any linear combination containing vdef
2062  MX extra_hess_v_v; // same for all linear combinations, if multiple
2063  for (auto&& e : lc_) {
2064  // Find out of vdef is part of the linear combination
2065  bool has_vdef = false;
2066  for (const std::string& r : e.second) {
2067  if (r == "wdef") {
2068  has_vdef = true;
2069  break;
2070  }
2071  }
2072  // Skip if linear combination does not depend on vdef
2073  if (!has_vdef) continue;
2074  // Search for matching function outputs
2075  for (size_t i = 0; i < ret_out.size(); ++i) {
2076  if (ret.name_out(i) == "hess_" + e.first + "_w_w") {
2077  // Calculate contribution to hess_?_v_v
2078  if (extra_hess_v_v.is_empty())
2079  extra_hess_v_v = hess_v_v_from_calls(call_nodes, h_offsets);
2080  // Add contribution to output
2081  ret_out.at(i) += extra_hess_v_v;
2082  }
2083  }
2084  }
2085  // Assemble modified return function and return
2086  ret = Function(fname, ret_in, ret_out, ret.name_in(), ret.name_out());
2087  return ret;
2088 }
Function create(const std::string &fname, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts, bool sx, bool lifted_calls) const
Construct a function object.
const Function & oracle(bool sx=false, bool elim_w=false, bool lifted_calls=false) const
Get the (cached) oracle, SX or MX.
MX hess_v_v_from_calls(std::map< MXNode *, CallIO > &call_nodes, const std::vector< casadi_int > &h_offsets) const
Calculate contribution to hess_?_v_v from lifted calls.
Function fmu_fun(const std::string &fname, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts) const
Construct function from an FMU DLL.
MX jac_vdef_v_from_calls(std::map< MXNode *, CallIO > &call_nodes, const std::vector< casadi_int > &h_offsets) const
Calculate contribution to jac_vdef_v from lifted calls.
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1592
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
Definition: function.cpp:1820
MXNode * get() const
Get a const pointer to the node.
Definition: mx.cpp:544

References casadi::DaeBuilderInternal::CallIO::adj1_arg, casadi::DaeBuilderInternal::CallIO::arg, casadi::MX::dep(), casadi::DaeBuilderInternal::CallIO::f, casadi::Function::factory(), casadi::MX::find(), fmu_fun(), casadi::MX::get(), hess_v_v_from_calls(), indices(), casadi::MX::is_constant(), casadi::GenericMatrix< MatType >::is_empty(), casadi::MX::is_output(), jac_vdef_v_from_calls(), lc_, casadi::Function::mx_in(), casadi::MX::n_dep(), casadi::MX::n_out(), casadi::Function::name_in(), casadi::Function::name_out(), oracle(), output(), casadi::DaeBuilderInternal::CallIO::res, size(), symbolic_, casadi::DaeBuilderInternal::CallIO::v, var(), casadi::DaeBuilderInternal::CallIO::vdef, casadi::W, casadi::WDEF, casadi::MX::which_function(), and casadi::MX::which_output().

◆ debug_repr()

std::string casadi::GenericSharedInternal< SharedObject , SharedObjectInternal >::debug_repr ( const Internal *  i) const
inherited

Definition at line 62 of file generic_shared_internal.hpp.

162  {
163  // Note: i != this because of something something multiple inheritance
164  return str( (casadi_int)(i)) + "/" + static_cast<const Internal*>(this)->class_name();
165  }
std::string str(const T &v)
String representation, any type.

◆ default_initial()

Initial casadi::DaeBuilderInternal::default_initial ( Causality  causality,
Variability  variability 
)
staticprotected

Definition at line 2728 of file dae_builder_internal.cpp.

2728  {
2729  // According to table in FMI 2.0.2 specification, section 2.2.7
2730  switch (variability) {
2731  case Variability::CONSTANT:
2733  return Initial::EXACT;
2734  break;
2735  case Variability::FIXED:
2736  // Fall-through
2737  case Variability::TUNABLE:
2739  return Initial::EXACT;
2741  return Initial::CALCULATED;
2742  break;
2743  case Variability::DISCRETE:
2744  // Fall-through
2747  return Initial::CALCULATED;
2748  break;
2749  default: break;
2750  }
2751  // Initial value not available
2752  return Initial::NA;
2753 }

References casadi::CALCULATED, casadi::CALCULATED_PARAMETER, causality(), casadi::CONSTANT, casadi::CONTINUOUS, casadi::DISCRETE, casadi::EXACT, casadi::FIXED, casadi::LOCAL, casadi::NA, casadi::OUTPUT, casadi::PARAMETER, casadi::TUNABLE, and variability().

Referenced by import_model_variables().

◆ default_variability()

Variability casadi::DaeBuilderInternal::default_variability ( Causality  causality,
Type  type 
)
staticprotected

Definition at line 2712 of file dae_builder_internal.cpp.

2712  {
2713  // Default variability per FMI 3.0.2, section 2.4.7.4
2714  // "The default for variables of causality parameter, structural parameter or
2715  // calculated parameter is fixed."
2717  return Variability::FIXED;
2718  }
2719  // "The default for variables of type Float32 and Float64 and causality other
2720  // than parameter, structuralParameter or calculatedParameter is continuous"
2721  if (type == Type::FLOAT32 || type == Type::FLOAT64) {
2722  return Variability::CONTINUOUS;
2723  } else {
2724  return Variability::DISCRETE;
2725  }
2726 }

References casadi::CALCULATED_PARAMETER, causality(), casadi::CONTINUOUS, casadi::DISCRETE, casadi::FIXED, casadi::FLOAT32, casadi::FLOAT64, and casadi::PARAMETER.

Referenced by add(), and import_model_variables().

◆ dependent_fun()

Function casadi::DaeBuilderInternal::dependent_fun ( const std::string &  fname,
const std::vector< std::string > &  s_in,
const std::vector< std::string > &  s_out 
) const

Definition at line 2450 of file dae_builder_internal.cpp.

2452  {
2453  // Are we calculating d and/or w
2454  bool calc_d = false, calc_w = false;
2455  // Convert outputs to enums
2456  std::vector<Category> v_out;
2457  v_out.reserve(v_out.size());
2458  for (const std::string& s : s_out) {
2459  Category e = to_enum<Category>(s);
2460  if (e == Category::D) {
2461  calc_d = true;
2462  } else if (e == Category::W) {
2463  calc_w = true;
2464  } else {
2465  casadi_error("Can only calculate d and/or w");
2466  }
2467  v_out.push_back(e);
2468  }
2469  // Consistency check
2470  casadi_assert(calc_d || calc_w, "Nothing to calculate");
2471  // Convert inputs to enums
2472  std::vector<Category> v_in;
2473  v_in.reserve(v_in.size());
2474  for (const std::string& s : s_in) {
2475  Category e = to_enum<Category>(s);
2476  if (calc_d && e == Category::D) casadi_error("'d' cannot be both input and output");
2477  if (calc_w && e == Category::W) casadi_error("'w' cannot be both input and output");
2478  v_in.push_back(e);
2479  }
2480  // Collect input expressions
2481  std::vector<MX> f_in;
2482  f_in.reserve(s_in.size());
2483  for (Category v : v_in) f_in.push_back(vertcat(input(v)));
2484  // Collect output expressions
2485  std::vector<MX> f_out;
2486  f_out.reserve(s_out.size());
2487  for (Category v : v_out) f_out.push_back(vertcat(input(v)));
2488  // Variables to be substituted
2489  std::vector<MX> dw, dwdef;
2490  if (calc_d) {
2491  std::vector<MX> d = var(indices(Category::D));
2492  dw.insert(dw.end(), d.begin(), d.end());
2493  std::vector<MX> ddef = output(OutputCategory::DDEF);
2494  dwdef.insert(dwdef.end(), ddef.begin(), ddef.end());
2495  }
2496  if (calc_w) {
2497  std::vector<MX> w = var(indices(Category::W));
2498  dw.insert(dw.end(), w.begin(), w.end());
2499  std::vector<MX> wdef = output(OutputCategory::WDEF);
2500  dwdef.insert(dwdef.end(), wdef.begin(), wdef.end());
2501  }
2502  // Perform elimination
2503  substitute_inplace(dw, dwdef, f_out);
2504  // Assemble return function
2505  return Function(fname, f_in, f_out, s_in, s_out);
2506 }
std::vector< MX > input(Category ind) const

References casadi::D, casadi::DDEF, indices(), input(), output(), var(), casadi::W, and casadi::WDEF.

◆ der() [1/2]

MX casadi::DaeBuilderInternal::der ( const MX var) const

Definition at line 1694 of file dae_builder_internal.cpp.

1694  {
1695  return const_cast<DaeBuilderInternal*>(this)->der(var, false);
1696 }
MX der(const MX &var) const
Get a derivative expression by non-differentiated expression (const, never create)
DaeBuilderInternal(const std::string &name, const std::string &path, const Dict &opts)
Constructor.

References var().

Referenced by der(), disp(), generate_model_structure(), generate_wrapper(), import_dynamic_equations(), lift(), and update_dependencies().

◆ der() [2/2]

MX casadi::DaeBuilderInternal::der ( const MX var,
bool  may_allocate = true 
)

Definition at line 1698 of file dae_builder_internal.cpp.

1698  {
1699  // Must be a vector
1700  casadi_assert(var.is_column(), "Input expression must be a vector");
1701  // Quick return if symbolic variable
1702  if (var.is_symbolic()) return get_der(find(var), may_allocate);
1703  // If a vertical concatenation
1704  if (var.is_valid_input()) {
1705  // Differentiate each primitive
1706  auto var_split = var.primitives();
1707  for (MX& s : var_split) s = der(s, may_allocate);
1708  // Return the concatenation
1709  return var.join_primitives(var_split);
1710  }
1711  // Handle general case: Get dependent symbolic primitives
1712  std::vector<MX> dep = symvar(var);
1713  // Get derivatives of dependent symbolic primitives
1714  std::vector<MX> dep_der;
1715  for (size_t ind : find(dep)) dep_der.push_back(get_der(ind, may_allocate));
1716  // Forward directional derivative to get time derivative:
1717  // dot(var) = d_var/d_dep * dot(dep)
1718  std::vector<std::vector<MX>> r = {dep_der};
1719  r = forward(std::vector<MX>{var}, dep, r);
1720  casadi_assert_dev(r.size() == 1);
1721  return vertcat(r.at(0));
1722 }
MX get_der(size_t ind) const
Get a derivative expression by variable index (const, never create)
size_t find(const std::string &name) const
Get index of variable, given name.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
bool is_valid_input() const
Check if matrix can be used to define function inputs.
Definition: mx.cpp:925
std::vector< MX > primitives() const
Get primitives.
Definition: mx.cpp:933
MX join_primitives(const std::vector< MX > &v) const
Join an expression along symbolic primitives.
Definition: mx.cpp:965
bool is_symbolic() const
Check if symbolic.
Definition: mx.cpp:766

References der(), find(), get_der(), casadi::GenericMatrix< MatType >::is_column(), casadi::MX::is_symbolic(), casadi::MX::is_valid_input(), casadi::MX::join_primitives(), casadi::MX::primitives(), and var().

◆ destroySingleton()

void casadi::GenericSharedInternal< SharedObject , SharedObjectInternal >::destroySingleton ( )
inlineprotectedinherited

Called in the destructor of singletons

Definition at line 77 of file generic_shared_internal.hpp.

77  {
78  static_cast<Internal*>(this)->count--;
79  }

◆ disp()

void casadi::DaeBuilderInternal::disp ( std::ostream &  stream,
bool  more 
) const
overridevirtual

Implements casadi::SharedObjectInternal.

Definition at line 1238 of file dae_builder_internal.cpp.

1238  {
1239  // Assert correctness
1240  if (more) sanity_check();
1241 
1242  // Print dimensions
1243  stream << "nx = " << size(Category::X) << ", "
1244  << "nz = " << size(Category::Z) << ", "
1245  << "nq = " << size(Category::Q) << ", "
1246  << "ny = " << outputs_.size() << ", "
1247  << "np = " << size(Category::P) << ", "
1248  << "nc = " << size(Category::C) << ", "
1249  << "nd = " << size(Category::D) << ", "
1250  << "nw = " << size(Category::W) << ", "
1251  << "nu = " << size(Category::U);
1252 
1253  // Quick return?
1254  if (!more) return;
1255  stream << std::endl;
1256 
1257  // Print the functions
1258  if (!fun_.empty()) {
1259  stream << "Functions:" << std::endl;
1260  for (const Function& f : fun_) {
1261  stream << " " << f << std::endl;
1262  }
1263  }
1264 
1265  // Print the variables, including outputs
1266  stream << "Model variables:" << std::endl;
1269  if (size(cat) > 0) {
1270  stream << " " << to_string(cat) << " = " << var(indices(cat)) << std::endl;
1271  }
1272  }
1273 
1274  // All variables that can have dependent variables
1275  for (Category cat : {Category::C, Category::D, Category::W}) {
1276  if (size(cat) > 0) {
1277  stream << "List of " << description(cat) << "s (" << to_string(cat) << "):" << std::endl;
1278  for (size_t c : indices(cat)) {
1279  const Variable& v = variable(c);
1280  stream << " " << v.name;
1281  if (v.bind >= 0) stream << " := " << variable(v.bind).v;
1282  stream << std::endl;
1283  }
1284  }
1285  }
1286 
1287  // Print derivatives
1288  for (Category cat : {Category::X, Category::Q}) {
1289  if (size(cat) > 0) {
1290  stream << "Time derivatives of " << description(cat) << "s (" << to_string(cat) << "):"
1291  << std::endl;
1292  for (size_t k : indices(cat)) {
1293  const Variable& v = variable(k);
1294  stream << " " << v.name << ": " << der(v.v) << std::endl;
1295  }
1296  }
1297  }
1298 
1299  // Outputs
1300  if (!outputs_.empty()) {
1301  stream << "Outputs (y):" << std::endl;
1302  for (size_t k : outputs_) {
1303  const Variable& v = variable(k);
1304  stream << " " << v.name << ": " << v.v << std::endl;
1305  }
1306  }
1307 
1308  if (!residuals_.empty()) {
1309  stream << "Algebraic equations:" << std::endl;
1310  for (size_t k : residuals_) {
1311  stream << " 0 == " << variable(k).v << std::endl;
1312  }
1313  }
1314 
1315  if (!init_.empty()) {
1316  stream << "Initial equations:" << std::endl;
1317  for (size_t k : init_) {
1318  const Variable& v = variable(k);
1319  stream << " " << v.name;
1320  if (!v.ieq.is_empty()) stream << " := " << v.ieq;
1321  stream << std::endl;
1322  }
1323  }
1324 
1325  if (!when_.empty()) {
1326  stream << "When equations:" << std::endl;
1327  for (auto weq : when_) {
1328  stream << " when " << variable(weq.first).v << " < 0 : " << std::endl;
1329  for (size_t eq : weq.second) {
1330  auto v = variable(eq).parent;
1331  stream << " " << variable(v).name << " := " << variable(eq).v << std::endl;
1332  }
1333  }
1334  }
1335 }
std::vector< std::pair< size_t, std::vector< size_t > > > when_
std::vector< size_t > residuals_
void eq(const MX &lhs, const MX &rhs, const Dict &opts)
Add a simple equation.
MX v
Variable expression (always a vector)

References casadi::Variable::bind, casadi::C, casadi::D, der(), casadi::description(), eq(), fun_, casadi::Variable::ieq, indices(), init_, casadi::GenericMatrix< MatType >::is_empty(), casadi::Variable::name, outputs_, casadi::P, casadi::Variable::parent, casadi::Q, residuals_, sanity_check(), size(), casadi::T, casadi::to_string(), casadi::U, casadi::Variable::v, var(), variable(), casadi::W, when_, casadi::X, and casadi::Z.

Referenced by import_binding_equations(), import_dynamic_equations(), and import_initial_equations().

◆ eliminate()

void casadi::DaeBuilderInternal::eliminate ( Category  cat)

Definition at line 1735 of file dae_builder_internal.cpp.

1735  {
1736  // Eliminate quadratures
1737  if (cat == Category::Q) {
1738  for (size_t q : indices(cat)) set_category(q, Category::X);
1739  return;
1740  }
1741 
1742  // Assume dependent variable (c, d, w)
1743  casadi_assert(is_acyclic(cat), "Elimination not supported for category " + to_string(cat));
1744 
1745  // Quick return if no dependent variables
1746  if (size(cat) == 0) return;
1747  // Clear cache after this
1748  clear_cache_ = true;
1749  // Ensure variables are sorted
1750  sort(cat);
1751  // Expressions where the variables are also being used
1752  std::vector<MX> ex;
1753  for (const Variable* v : variables_) {
1754  if (!v->v.is_constant()) ex.push_back(v->v);
1755  }
1756  // Perform elimination
1757  std::vector<size_t> ind = indices(cat);
1758  std::vector<MX> v = var(ind);
1759  std::vector<MX> vdef = output(dependent_definition(cat));
1760  substitute_inplace(v, vdef, ex);
1761  // Replace binding equations
1762  auto it = ex.begin();
1763  for (Variable* v : variables_) {
1764  if (!v->v.is_constant()) v->v = *it++;
1765  }
1766  // Consistency check
1767  casadi_assert_dev(it == ex.end());
1768  // Reclassify as calculated variables
1769  for (size_t k : ind) {
1771  }
1772 }
void sort(Category cat)
Sort all variables of a category.
void set_category(size_t ind, Category cat)
Set category.
OutputCategory dependent_definition(Category cat)

References casadi::CALCULATED, categorize(), clear_cache_, casadi::dependent_definition(), indices(), casadi::is_acyclic(), output(), casadi::Q, set_category(), size(), sort(), casadi::to_string(), var(), variable(), variables_, and casadi::X.

◆ eq()

void casadi::DaeBuilderInternal::eq ( const MX lhs,
const MX rhs,
const Dict opts 
)
protected

Definition at line 3078 of file dae_builder_internal.cpp.

3078  {
3079  // Read options
3080  for (auto&& op : opts) {
3081  casadi_error("No such option: " + op.first);
3082  }
3083  // Make sure vectors
3084  casadi_assert(lhs.is_column(), "Left-hand-side must be a column vector");
3085  casadi_assert(rhs.is_column(), "Right-hand-side must be a column vector");
3086  // Make sure dense
3087  if (!lhs.is_dense()) return eq(densify(lhs), rhs, opts);
3088  if (!rhs.is_dense()) return eq(lhs, densify(rhs), opts);
3089  // Make sure dimensions agree
3090  if (lhs.size1() != rhs.size1()) {
3091  // Handle mismatching dimnensions by recursion
3092  if (lhs.size1() == 1 && rhs.size1() > 1) {
3093  return eq(repmat(lhs, rhs.size1()), rhs, opts);
3094  } else if (lhs.size1() > 1 && rhs.size1() == 1) {
3095  return eq(lhs, repmat(rhs, lhs.size1()), opts);
3096  } else {
3097  casadi_error("Mismatched dimensions: " + str(lhs.size1()) + " vs " + str(rhs.size1()));
3098  }
3099  }
3100  // Make sure right-hand-side only depends on known model variables
3101  std::vector<size_t> rhs_vars = find(symvar(rhs));
3102  // If right-hand-side contains a time derivative that hasn't been defined yet,
3103  // add a new algebraic variable der_x and the ODE "der(x) = der_x"
3104  // This ensures that the DAE stays in semi-explicit form
3105  for (size_t rhs : rhs_vars) {
3106  Variable& v = variable(rhs);
3107  if (v.category == Category::Z && v.parent >= 0) {
3108  // Find the corresponding state variable
3109  Variable& x = variable(v.parent);
3110  // The "parent" attribute is used in some other cases, like assignments
3111  casadi_assert(x.der == v.index, "Cannot handle right-hand-side variable: " + v.name);
3112  // Create a new algebraic variable der_{name}, to distinguish from der({name})
3113  Variable& der_x = add(unique_name("der_" + x.name, true),
3115  {{"dimension", {x.dimension}}});
3116  // Add the trivial ODE
3117  eq(x.get_der(*this), der_x.v, Dict());
3118  }
3119  }
3120  // Try to honor a == b as an explicit equation
3121  if (lhs.is_valid_input()) {
3122  // Explicit equation
3123  if (lhs.is_symbolic()) {
3124  // Regular symbolic: Find the variable
3125  Variable& v = variable(lhs);
3126  // Set the binding equation
3127  if (v.has_beq()) {
3128  // Treat as implicit equation via recursion
3129  return eq(MX::zeros(lhs.sparsity()), lhs - rhs, opts);
3130  } else {
3131  // Set the binding equation
3132  Variable& beq = assign(v.name, rhs);
3133  v.bind = beq.index;
3134  }
3135  // (Re)classify variables
3136  if (v.parent >= 0) {
3137  // Derivative variable is being set - find the corresponding state variable
3138  Variable& x = variable(v.parent);
3139  // The "parent" attribute is used in some other cases, like assignments
3140  casadi_assert(x.der == v.index, "Cannot handle left-hand-side: " + str(lhs));
3141  // Reclassify as a differential state and derivative as a dependent variable
3142  if (x.category == Category::Z) {
3143  // Not previously used: Reclassify as differential state
3144  categorize(x.index, detect_quad_ && !x.in_rhs ? Category::Q : Category::X);
3145  categorize(v.index, Category::W);
3146  } else if (x.category == Category::W) {
3147  // Already given a defining equation: Create a new dependent variable and use this
3148  // for the previous definition
3149  Variable& def_x = add(unique_name("def_" + x.name, true),
3151  {{"dimension", {x.dimension}}});
3152  categorize(def_x.index, Category::W);
3153  def_x.bind = x.bind;
3154  // We can now reclassify x as a differential state
3155  x.bind = -1;
3156  categorize(x.index, Category::X);
3157  categorize(v.index, Category::W);
3158  // Add a new implicit equation: 0 == x - def_x
3160  x.v - def_x.v, {{"dimension", x.dimension}});
3161  categorize(alg.index, Category::CALCULATED);
3162  residuals_.push_back(alg.index);
3163  } else {
3164  casadi_error("Unexpected category for " + x.name + ": " + to_string(x.category));
3165  }
3166  } else if (v.category == Category::Z) {
3167  // Reclassify as dependent variable
3168  categorize(v.index, Category::W);
3169  } else {
3170  casadi_error("Cannot handle left-hand-side: " + str(lhs) + " of category '"
3171  + to_string(v.category) + "'");
3172  }
3173  } else {
3174  // Concatenation: Split into primitives
3175  auto lhs_split = lhs.primitives();
3176  std::vector<MX> rhs_split = lhs.split_primitives(rhs);
3177  // Call recursively
3178  for (size_t k = 0; k < lhs_split.size(); ++k) {
3179  eq(lhs_split.at(k), rhs_split.at(k), opts);
3180  }
3181  return;
3182  }
3183  } else {
3184  // Implicit equation: Create residual variable
3186  lhs - rhs, {{"dimension", std::vector<casadi_int>{lhs.size1()}}});
3187  categorize(alg.index, Category::CALCULATED);
3188  residuals_.push_back(alg.index);
3189  }
3190  // Do not allow any quadrature states in the right-hand-sides
3191  for (size_t rhs : rhs_vars) {
3192  Variable& v = variable(rhs);
3193  if (!v.in_rhs) {
3194  v.in_rhs = true;
3195  if (v.category == Category::Q) categorize(v.index, Category::X);
3196  }
3197  }
3198 }
Variable & assign(const std::string &name, const MX &val)
Assignment inside when-equations or if-else equations.
static MX zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.

References add(), casadi::Variable::category, casadi::CONTINUOUS, casadi::Variable::der, find(), casadi::Variable::index, casadi::GenericMatrix< MatType >::is_column(), casadi::GenericMatrix< MatType >::is_dense(), casadi::LOCAL, casadi::Variable::name, casadi::Variable::parent, casadi::GenericMatrix< MatType >::size1(), casadi::str(), unique_name(), variable(), and casadi::Z.

Referenced by disp(), import_binding_equations(), import_dynamic_equations(), import_initial_equations(), transition(), and when().

◆ export_fmu()

std::vector< std::string > casadi::DaeBuilderInternal::export_fmu ( const Dict opts) const

Definition at line 902 of file dae_builder_internal.cpp.

902  {
903  // Default options
904  bool no_warning = false;
905  for (auto&& op : opts) {
906  if (op.first == "no_warning") {
907  no_warning = op.second;
908  }
909  }
910  // Feature incomplete
911  if (!no_warning) casadi_warning("FMU generation is experimental and incomplete")
912  // Return object
913  std::vector<std::string> ret;
914  // GUID
915  std::string guid = generate_guid();
916  // Generate model function
917  std::string dae_filename = name_;
918  casadi_assert(size(Category::Q) == 0, "Not implemented");
919  Function dae = shared_from_this<DaeBuilder>().create(dae_filename,
920  {"t", "x", "p", "u"}, {"ode", "y", "zero"});
921  // Event transition function, if needed
922  Function tfun;
923  if (!event_indicators_.empty()) tfun = transition("transition_" + name_);
924  // Generate C code for model equations
925  Dict codegen_opts;
926  codegen_opts["with_header"] = true;
927  CodeGenerator gen(dae_filename, codegen_opts);
928  gen.add(dae);
929  gen.add(dae.forward(1));
930  gen.add(dae.reverse(1));
931  if (!tfun.is_null()) gen.add(tfun);
932  ret.push_back(gen.generate());
933  ret.push_back(dae_filename + ".h");
934  // Make sure dependencies are up-to-date
936  // Generate FMU wrapper file
937  std::string wrapper_filename = generate_wrapper(guid, gen);
938  ret.push_back(wrapper_filename);
939  // Generate build description
940  ret.push_back(generate_build_description(ret));
941  // Generate modelDescription file
942  ret.push_back(generate_model_description(guid));
943  // Return list of files
944  return ret;
945 }
Function transition(const std::string &fname, casadi_int index, bool dummy_index_input=false) const
Construct a function describing transition at a specific event.
void update_dependencies() const
Update model variable dependencies.
std::string generate_wrapper(const std::string &guid, const CodeGenerator &gen) const
Generate FMU wrapper file (fmi3Functions.c)
std::vector< size_t > event_indicators_
std::string generate_build_description(const std::vector< std::string > &cfiles) const
Generate buildDescription.xml.
std::string generate_model_description(const std::string &guid) const
Generate modelDescription.xml.
B shared_from_this()
Get a shared object from the current internal object.

References casadi::CodeGenerator::add(), casadi::Function::create(), event_indicators_, casadi::Function::forward(), casadi::CodeGenerator::generate(), generate_build_description(), generate_guid(), generate_model_description(), generate_wrapper(), casadi::GenericShared< Shared, Internal >::is_null(), name_, casadi::Q, casadi::Function::reverse(), size(), transition(), and update_dependencies().

◆ find() [1/4]

size_t casadi::DaeBuilderInternal::find ( const MX v) const

Definition at line 3969 of file dae_builder_internal.cpp.

3969  {
3970  // Make sure it is a valid input
3971  casadi_assert(v.is_symbolic(), "Variable must be symbolic");
3972  // Find the prospective variable
3973  size_t ind = find(v.name());
3974  // Make sure that the expression (not just the name) is correct
3975  casadi_assert(is_equal(v, variables_.at(ind)->v),
3976  "Variable \"" + v.name() + "\" has mismatching symbolic expression");
3977  // Return index
3978  return ind;
3979 }
bool is_equal(double x, double y, casadi_int depth=0)
Definition: calculus.hpp:281

References find(), casadi::is_equal(), casadi::MX::is_symbolic(), casadi::MX::name(), and variables_.

◆ find() [2/4]

size_t casadi::DaeBuilderInternal::find ( const std::string &  name) const

Definition at line 3963 of file dae_builder_internal.cpp.

3963  {
3964  auto it = varind_.find(name);
3965  casadi_assert(it != varind_.end(), "No such variable: \"" + name + "\".");
3966  return it->second;
3967 }
std::unordered_map< std::string, size_t > varind_
Find of variable by name.

References name(), and varind_.

Referenced by der(), eq(), find(), fmu_fun(), sort(), sort_z(), and tear().

◆ find() [3/4]

std::vector< size_t > casadi::DaeBuilderInternal::find ( const std::vector< MX > &  v) const

Definition at line 3987 of file dae_builder_internal.cpp.

3987  {
3988  std::vector<size_t> r(v.size());
3989  for (size_t i = 0; i < r.size(); ++i) r[i] = find(v[i]);
3990  return r;
3991 }

References find().

◆ find() [4/4]

std::vector< size_t > casadi::DaeBuilderInternal::find ( const std::vector< std::string > &  name) const

Definition at line 3981 of file dae_builder_internal.cpp.

3981  {
3982  std::vector<size_t> r(name.size());
3983  for (size_t i = 0; i < r.size(); ++i) r[i] = find(name[i]);
3984  return r;
3985 }

References find(), and name().

◆ fmu_fun()

Function casadi::DaeBuilderInternal::fmu_fun ( const std::string &  fname,
const std::vector< std::string > &  name_in,
const std::vector< std::string > &  name_out,
const Dict opts 
) const

Definition at line 2578 of file dae_builder_internal.cpp.

2581  {
2582  // Iterator for options lookup
2583  Dict::const_iterator it;
2584  // Scheme inputs
2585  std::vector<std::string> scheme_in;
2586  bool has_in = false;
2587  if ((it = opts.find("scheme_in")) != opts.end()) {
2588  try {
2589  scheme_in = it->second;
2590  } catch (std::exception& e) {
2591  casadi_error(std::string("Cannot read 'scheme_in': ") + e.what());
2592  }
2593  has_in = true;
2594  }
2595 
2596  // Scheme outputs
2597  std::vector<std::string> scheme_out;
2598  bool has_out = false;
2599  if ((it = opts.find("scheme_out")) != opts.end()) {
2600  try {
2601  scheme_out = it->second;
2602  has_out = true;
2603  } catch (std::exception& e) {
2604  casadi_error(std::string("Cannot read 'scheme_out': ") + e.what());
2605  }
2606  }
2607  // If scheme_in and/or scheme_out not provided, identify from name_in, name_out
2608  if (!has_in || !has_out) {
2609  FmuFunction::identify_io(has_in ? 0 : &scheme_in, has_out ? 0 : &scheme_out, name_in, name_out);
2610  }
2611  // IO scheme
2612  std::map<std::string, std::vector<size_t>> scheme;
2613  if ((it = opts.find("scheme")) != opts.end()) {
2614  try {
2615  // Argument is a Dict
2616  Dict scheme_dict = it->second;
2617  // Convert indices
2618  for (auto&& e : scheme_dict) {
2619  std::vector<std::string> v = e.second;
2620  scheme[e.first] = find(v);
2621  }
2622  } catch (std::exception& e) {
2623  casadi_error(std::string("Cannot read 'scheme': ") + e.what());
2624  }
2625  } else {
2626  // Initialize all scheme entries
2627  for (auto&& s : dyn_in()) scheme[s] = std::vector<size_t>();
2628  for (auto&& s : dyn_out()) scheme[s] = std::vector<size_t>();
2629  // Default IO scheme
2630  scheme["t"] = indices(Category::T);
2631  scheme["x"] = indices(Category::X);
2632  scheme["u"] = indices(Category::U);
2633  scheme["z"] = indices(Category::Z);
2634  scheme["p"] = indices(Category::P);
2635  scheme["ode"] = indices(Category::X);
2636  for (size_t& i : scheme["ode"]) i = variable(i).der;
2637  scheme["quad"] = indices(Category::Q);
2638  for (size_t& i : scheme["quad"]) i = variable(i).der;
2639  scheme["alg"] = indices(Category::Z);
2640  casadi_assert(size(Category::Z) == 0, "Not implemented)");
2641  scheme["y"] = outputs_;
2642  scheme["rate"] = rate_;
2643  }
2644  // Auxilliary variables, if any
2645  std::vector<std::string> aux;
2646  if ((it = opts.find("aux")) != opts.end()) {
2647  try {
2648  aux = it->second;
2649  } catch (std::exception& e) {
2650  casadi_error(std::string("Cannot read 'aux': ") + e.what());
2651  }
2652  }
2653  // New FMU instance (to be shared between derivative functions)
2654  Fmu fmu(name, fmi_major_ >= 3 ? FmuApi::FMI3 : FmuApi::FMI2, this,
2655  scheme_in, scheme_out, scheme, aux);
2656 
2657  // Crete new function
2658  return Function::create(new FmuFunction(name, fmu, name_in, name_out), opts);
2659 }
static void identify_io(std::vector< std::string > *scheme_in, std::vector< std::string > *scheme_out, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out)
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:336
std::vector< std::string > dyn_out()
Get output scheme of a DAE function.
Definition: integrator.cpp:236
std::vector< std::string > dyn_in()
Get input scheme of a DAE function.
Definition: integrator.cpp:232

References casadi::Function::create(), casadi::Variable::der, casadi::dyn_in(), casadi::dyn_out(), find(), casadi::FMI2, casadi::FMI3, fmi_major_, FmuFunction, casadi::FmuFunction::identify_io(), indices(), name(), outputs_, casadi::P, casadi::Q, rate_, size(), casadi::T, casadi::U, variable(), casadi::X, and casadi::Z.

Referenced by create().

◆ fun()

Function casadi::DaeBuilderInternal::fun ( const std::string &  name) const
protected

Definition at line 4041 of file dae_builder_internal.cpp.

4041  {
4042  casadi_assert(has_fun(name), "No such function: '" + name + "'");
4043  for (const Function& f : fun_) {
4044  if (f.name()==name) return f;
4045  }
4046  return Function();
4047 }

References fun_, has_fun(), and name().

◆ gather_eq()

Function casadi::DaeBuilderInternal::gather_eq ( ) const

Definition at line 2661 of file dae_builder_internal.cpp.

2661  {
2662  // Output expressions
2663  std::vector<MX> f_out;
2664  // Names of outputs
2665  std::vector<std::string> f_out_name;
2666  // Get all expressions
2667  for (OutputCategory cat : output_categories()) {
2668  std::vector<MX> v = output(cat);
2669  if (!v.empty()) {
2670  f_out.push_back(vertcat(v));
2671  f_out_name.push_back(to_string(cat));
2672  }
2673  }
2674  // Construct function
2675  return Function("all_eq", {}, f_out, {}, f_out_name, {{"allow_free", true}});
2676 }
std::vector< OutputCategory > output_categories()

References output(), casadi::output_categories(), and casadi::to_string().

◆ generate() [1/2]

std::string casadi::DaeBuilderInternal::generate ( const std::vector< double > &  v)
static

Import existing problem from FMI/XML

Definition at line 962 of file dae_builder_internal.cpp.

962  {
963  std::stringstream ss;
964  ss << "{";
965  bool first = true;
966  for (double e : v) {
967  // Separator
968  if (!first) ss << ", ";
969  first = false;
970  // Print element
971  ss << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << e;
972  }
973  ss << "}";
974  return ss.str();
975 }

◆ generate() [2/2]

std::string casadi::DaeBuilderInternal::generate ( const std::vector< size_t > &  v)
static

Helper function: generate constants

Definition at line 947 of file dae_builder_internal.cpp.

947  {
948  std::stringstream ss;
949  ss << "{";
950  bool first = true;
951  for (double e : v) {
952  // Separator
953  if (!first) ss << ", ";
954  first = false;
955  // Print element
956  ss << e;
957  }
958  ss << "}";
959  return ss.str();
960 }

Referenced by generate_wrapper().

◆ generate_build_description()

std::string casadi::DaeBuilderInternal::generate_build_description ( const std::vector< std::string > &  cfiles) const

Definition at line 702 of file dae_builder_internal.cpp.

703  {
704  // Default arguments
705  int fmi_major = 3;
706  int fmi_minor = 0;
707  std::string model_name = name_;
708  // Construct XML file
709  XmlNode r;
710  // Preamble
711  r.name = "fmiBuildDescription";
712  r.set_attribute("fmiVersion", std::to_string(fmi_major) + "." + std::to_string(fmi_minor));
713  // Set of source files
714  XmlNode source_file_set;
715  source_file_set.name = "SourceFileSet";
716  for (auto&& f : cfiles) {
717  XmlNode source_file;
718  source_file.name = "SourceFile";
719  source_file.set_attribute("name", f);
720  source_file_set.children.push_back(source_file);
721  }
722  // Build configurations
723  XmlNode bc;
724  bc.name = "BuildConfiguration";
725  bc.set_attribute("modelIdentifier", model_name);
726  bc.children.push_back(source_file_set);
727  r.children.push_back(bc);
728  // XML file name
729  std::string xml_filename = "buildDescription.xml";
730  // Construct ModelDescription
731  XmlNode build_description;
732  build_description.children.push_back(r);
733  // Export to file
734  XmlFile xml_file("tinyxml");
735  xml_file.dump(xml_filename, build_description);
736  return xml_filename;
737 }

References casadi::XmlNode::children, casadi::XmlFile::dump(), casadi::XmlNode::name, name_, and casadi::XmlNode::set_attribute().

Referenced by export_fmu().

◆ generate_guid()

std::string casadi::DaeBuilderInternal::generate_guid ( )
static

Import existing problem from FMI/XML

Definition at line 4223 of file dae_builder_internal.cpp.

4223  {
4224  // Initialize random seed
4225  static bool initialized = false;
4226  if (!initialized) {
4227  srand(::time(nullptr)); // NOLINT(runtime/threadsafe_fn)
4228  initialized = true;
4229  }
4230  // Possible characters
4231  const char h[] = "0123456789abcdef";
4232  // Length of GUID
4233  const size_t len = 32;
4234  // Generate random hex string
4235  std::vector<char> buf(len);
4236  for (size_t i = 0; i < len; ++i)
4237  buf[i] = h[rand() % 16]; // NOLINT(runtime/threadsafe_fn)
4238  return std::string(&buf.front(), len);
4239 }

References time().

Referenced by export_fmu().

◆ generate_model_description()

std::string casadi::DaeBuilderInternal::generate_model_description ( const std::string &  guid) const

Definition at line 739 of file dae_builder_internal.cpp.

739  {
740  // Default arguments
741  int fmi_major = 3;
742  int fmi_minor = 0;
743  std::string model_name = name_;
744  std::string description; // none
745  std::string author; // none
746  std::string version; // none
747  std::string copyright; // none
748  std::string license; // none
749  // Construct XML file
750  XmlNode r;
751  // Preamble
752  r.name = "fmiModelDescription";
753  r.set_attribute("fmiVersion", std::to_string(fmi_major) + "." + std::to_string(fmi_minor));
754  r.set_attribute("modelName", model_name);
755  r.set_attribute(fmi_major >= 3 ? "instantiationToken" : "guid", guid);
756  if (!description.empty()) r.set_attribute("description", description);
757  if (!author.empty()) r.set_attribute("author", author);
758  if (!version.empty()) r.set_attribute("version", version);
759  if (!copyright.empty()) r.set_attribute("copyright", copyright);
760  if (!license.empty()) r.set_attribute("license", license);
761  r.set_attribute("generationTool", "CasADi");
762  r.set_attribute("generationDateAndTime", iso_8601_time());
763  r.set_attribute("variableNamingConvention", "structured"); // flat better?
764  if (fmi_major < 3) r.set_attribute("numberOfEventIndicators", "0");
765  // Model exchange marker
766  XmlNode me;
767  me.name = "ModelExchange";
768  me.set_attribute("modelIdentifier", model_name); // sanitize name?
769  r.children.push_back(me);
770 
771  // Default experiment
772  XmlNode def_exp;
773  def_exp.name = "DefaultExperiment";
774  if (!std::isnan(start_time_)) def_exp.set_attribute("startTime", start_time_);
775  if (!std::isnan(stop_time_)) def_exp.set_attribute("stopTime", stop_time_);
776  if (!std::isnan(tolerance_)) def_exp.set_attribute("tolerance", tolerance_);
777  if (!std::isnan(step_size_)) def_exp.set_attribute("stepSize", step_size_);
778  if (!def_exp.attributes.empty()) r.children.push_back(def_exp);
779 
780  // Model variables
781  r.children.push_back(generate_model_variables());
782  // Model structure
783  r.children.push_back(generate_model_structure());
784  // XML file name
785  std::string xml_filename = "modelDescription.xml";
786  // Construct ModelDescription
787  XmlNode model_description;
788  model_description.children.push_back(r);
789  // Export to file
790  XmlFile xml_file("tinyxml");
791  xml_file.dump(xml_filename, model_description);
792  return xml_filename;
793 }
XmlNode generate_model_variables() const
Generate FMU ModelVariables.
XmlNode generate_model_structure() const
Generate FMU ModelStructure.
static std::string iso_8601_time()
Get current date and time in the ISO 8601 format.

References casadi::XmlNode::attributes, casadi::XmlNode::children, casadi::description(), casadi::XmlFile::dump(), generate_model_structure(), generate_model_variables(), iso_8601_time(), casadi::XmlNode::name, name_, casadi::XmlNode::set_attribute(), start_time_, step_size_, stop_time_, and tolerance_.

Referenced by export_fmu().

◆ generate_model_structure()

XmlNode casadi::DaeBuilderInternal::generate_model_structure ( ) const

Definition at line 805 of file dae_builder_internal.cpp.

805  {
806  XmlNode r;
807  r.name = "ModelStructure";
808  // Add outputs
809  for (size_t i : outputs_) {
810  const Variable& y = variable(i);
811  XmlNode c;
812  c.name = "Output";
813  c.set_attribute("valueReference", static_cast<casadi_int>(y.value_reference));
814  c.set_attribute("dependencies", y.dependencies);
815  r.children.push_back(c);
816  }
817  // Add state derivatives
818  for (size_t i : indices(Category::X)) {
819  const Variable& xdot = variable(variable(i).der);
820  XmlNode c;
821  c.name = "ContinuousStateDerivative";
822  c.set_attribute("valueReference", static_cast<casadi_int>(xdot.value_reference));
823  c.set_attribute("dependencies", xdot.dependencies);
824  r.children.push_back(c);
825  }
826  // Add initial unknowns: Outputs
827  for (size_t i : outputs_) {
828  const Variable& y = variable(i);
829  XmlNode c;
830  c.name = "InitialUnknown";
831  c.set_attribute("valueReference", static_cast<casadi_int>(y.value_reference));
832  c.set_attribute("dependencies", y.dependencies);
833  r.children.push_back(c);
834  }
835  // Add initial unknowns: State derivative
836  for (size_t i : indices(Category::X)) {
837  const Variable& xdot = variable(variable(i).der);
838  XmlNode c;
839  c.name = "InitialUnknown";
840  c.set_attribute("valueReference", static_cast<casadi_int>(xdot.value_reference));
841  c.set_attribute("dependencies", xdot.dependencies);
842  r.children.push_back(c);
843  }
844  // Add event indicators
845  for (size_t i : event_indicators_) {
846  const Variable& zero = variable(i);
847  XmlNode c;
848  c.name = "EventIndicator";
849  c.set_attribute("valueReference", static_cast<casadi_int>(zero.value_reference));
850  c.set_attribute("dependencies", zero.dependencies);
851  r.children.push_back(c);
852  }
853  return r;
854 }

References casadi::XmlNode::children, casadi::Variable::dependencies, der(), event_indicators_, indices(), casadi::XmlNode::name, outputs_, casadi::XmlNode::set_attribute(), casadi::Variable::value_reference, variable(), and casadi::X.

Referenced by generate_model_description().

◆ generate_model_variables()

XmlNode casadi::DaeBuilderInternal::generate_model_variables ( ) const

Definition at line 796 of file dae_builder_internal.cpp.

796  {
797  XmlNode r;
798  r.name = "ModelVariables";
799  for (auto&& v : variables_) {
800  r.children.push_back(v->export_xml(*this));
801  }
802  return r;
803 }

References casadi::XmlNode::children, casadi::XmlNode::name, and variables_.

Referenced by generate_model_description().

◆ generate_wrapper()

std::string casadi::DaeBuilderInternal::generate_wrapper ( const std::string &  guid,
const CodeGenerator gen 
) const

Definition at line 985 of file dae_builder_internal.cpp.

986  {
987  // Create file
988  std::string wrapper_filename = name_ + "_wrap.c";
989 
990  auto f_ptr = Filesystem::ofstream_ptr(wrapper_filename);
991  std::ostream& f = *f_ptr;
992  CodeGenerator::stream_open(f, false);
993 
994  // Add includes
995  f << "#include <fmi3Functions.h>\n"
996  << "#include \"" << name_ << ".h\"\n"
997  << "\n";
998 
999  // Total number of variables
1000  f << "#define N_VAR " << n_variables() << "\n";
1001 
1002  // Memory size
1003  f << "#define SZ_MEM " << n_mem() << "\n";
1004 
1005  // Work vectors sizes
1006  size_t sz_arg, sz_res, sz_iw, sz_w;
1007  gen.sz_work(sz_arg, sz_res, sz_iw, sz_w);
1008  f << "#define SZ_ARG " << sz_arg << "\n"
1009  << "#define SZ_RES " << sz_res << "\n"
1010  << "#define SZ_IW " << sz_iw << "\n"
1011  << "#define SZ_W " << sz_w << "\n";
1012 
1013  // Memory offsets
1014  f << "const size_t var_offset[N_VAR + 1] = {0";
1015  size_t mem_ind = 0;
1016  for (const Variable* v : variables_) {
1017  mem_ind += v->numel;
1018  f << ", " << mem_ind;
1019  }
1020  f << "};\n\n";
1021 
1022  // Start attributes
1023  f << "casadi_real start[SZ_MEM] = " << generate(start_all()) << ";\n\n";
1024 
1025  // States
1026  f << "#define N_X " << size(Category::X) << "\n"
1027  << "fmi3ValueReference x_vr[N_X] = " << generate(indices(Category::X)) << ";\n"
1028  << "\n";
1029 
1030  // Controls
1031  f << "#define N_U " << size(Category::U) << "\n"
1032  << "fmi3ValueReference u_vr[N_U] = " << generate(indices(Category::U)) << ";\n"
1033  << "\n";
1034 
1035  // Parameters
1036  f << "#define N_P " << size(Category::P) << "\n"
1037  << "fmi3ValueReference p_vr[N_P] = " << generate(indices(Category::P)) << ";\n"
1038  << "\n";
1039 
1040  // State derivatives
1041  std::vector<size_t> xdot;
1042  for (size_t v : indices(Category::X)) xdot.push_back(variable(v).der);
1043  f << "fmi3ValueReference xdot_vr[N_X] = " << generate(xdot) << ";\n"
1044  << "\n";
1045 
1046  // Outputs
1047  f << "#define N_Y " << outputs_.size() << "\n"
1048  << "fmi3ValueReference y_vr[N_Y] = " << generate(outputs_) << ";\n"
1049  << "\n";
1050 
1051  // Event indicators
1052  f << "#define N_ZERO " << event_indicators_.size() << "\n"
1053  << "fmi3ValueReference zero_vr[N_ZERO] = " << generate(event_indicators_) << ";\n"
1054  << "\n";
1055 
1056  // Memory structure
1058 
1059  // Finalize file
1060  CodeGenerator::stream_close(f, false);
1061  return wrapper_filename;
1062 }
static std::string fmu_helpers(const std::string &modelname)
FMU helper functions.
static void stream_open(std::ostream &f, bool cpp)
Print file header.
static void stream_close(std::ostream &f, bool cpp)
Print file header.
size_t n_mem() const
Length of memory for all variables.
static std::string generate(const std::vector< size_t > &v)
std::vector< double > start_all() const
Start values for all variables.
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.cpp:115

References der(), event_indicators_, casadi::CodeGenerator::fmu_helpers(), generate(), indices(), n_mem(), n_variables(), name_, casadi::Filesystem::ofstream_ptr(), outputs_, casadi::P, size(), start_all(), casadi::CodeGenerator::stream_close(), casadi::CodeGenerator::stream_open(), casadi::CodeGenerator::sz_work(), casadi::U, variable(), variables_, and casadi::X.

Referenced by export_fmu().

◆ get_der() [1/2]

MX casadi::DaeBuilderInternal::get_der ( size_t  ind) const
inline

Definition at line 358 of file dae_builder_internal.hpp.

358 {return variable(ind).get_der(*this);}
MX get_der(DaeBuilderInternal &self, bool may_allocate=true)

Referenced by der().

◆ get_der() [2/2]

MX casadi::DaeBuilderInternal::get_der ( size_t  ind,
bool  may_allocate = true 
)
inline

Definition at line 361 of file dae_builder_internal.hpp.

361  {
362  return variable(ind).get_der(*this, may_allocate);
363  }

◆ get_str()

std::string casadi::DaeBuilderInternal::get_str ( bool  more = false) const
inline

Definition at line 381 of file dae_builder_internal.hpp.

381  {
382  std::stringstream ss;
383  disp(ss, more);
384  return ss.str();
385  }
void disp(std::ostream &stream, bool more) const override
Print description.

◆ getCount()

Definition at line 60 of file generic_shared_internal.hpp.

186  {
187  return static_cast<const Internal*>(this)->count;
188  }

◆ has()

bool casadi::DaeBuilderInternal::has ( const std::string &  name) const

Definition at line 1601 of file dae_builder_internal.cpp.

1601  {
1602  return varind_.find(name) != varind_.end();
1603 }

References name(), and varind_.

Referenced by new_variable(), tearing_variables(), and unique_name().

◆ has_fun()

bool casadi::DaeBuilderInternal::has_fun ( const std::string &  name) const
protected

Definition at line 4034 of file dae_builder_internal.cpp.

4034  {
4035  for (const Function& f : fun_) {
4036  if (f.name()==name) return true;
4037  }
4038  return false;
4039 }

References fun_, and name().

Referenced by add_fun(), and fun().

◆ has_t()

bool casadi::DaeBuilderInternal::has_t ( ) const
protected

Extra doc: https://github.com/casadi/casadi/wiki/L_2bx

Definition at line 2683 of file dae_builder_internal.cpp.

2683  {
2684  return size(Category::T) > 0;
2685 }

References size(), and casadi::T.

Referenced by add(), and time().

◆ hess_sparsity()

Sparsity casadi::DaeBuilderInternal::hess_sparsity ( const std::vector< size_t > &  oind,
const std::vector< size_t > &  iind 
) const

Definition at line 4161 of file dae_builder_internal.cpp.

4162  {
4163  // Mark inputs
4164  std::vector<casadi_int> lookup(n_variables(), -1);
4165  for (size_t i = 0; i < iind.size(); ++i) lookup.at(iind[i]) = i;
4166  // Which variables enter as a nonlinear dependency in any variable in oind
4167  std::vector<bool> nonlin(iind.size(), false);
4168  // List of nonlinearly entering variables for the specific output
4169  std::vector<casadi_int> nonlin_list;
4170  // Rows and columns of the Hessian
4171  std::vector<casadi_int> row, col;
4172  // Loop over output variables
4173  for (casadi_int j = 0; j < oind.size(); ++j) {
4174  const Variable& v = variable(oind[j]);
4175  // Loop over dependencies
4176  for (size_t k = 0; k < v.dependencies.size(); ++k) {
4177  if (v.dependenciesKind.empty() || v.dependenciesKind.at(k) == DependenciesKind::DEPENDENT) {
4178  casadi_int i = lookup.at(v.dependencies[k]);
4179  if (i >= 0 && !nonlin.at(i)) {
4180  // Add to list
4181  nonlin_list.push_back(i);
4182  nonlin.at(i) = true;
4183  }
4184  }
4185  }
4186  // Add all combinations to sparsity pattern
4187  for (casadi_int k1 : nonlin_list) {
4188  for (casadi_int k2 : nonlin_list) {
4189  row.push_back(k1);
4190  col.push_back(k2);
4191  }
4192  }
4193  // If row/col vectors grow too large, remove duplicates
4194  if (col.size() > 2 * iind.size() * iind.size()) {
4195  Sparsity r = Sparsity::triplet(iind.size(), iind.size(), row, col);
4196  row = r.get_row();
4197  col = r.get_col();
4198  }
4199  // Reset nonlin, nonlin_list for next iteration
4200  for (casadi_int k : nonlin_list) nonlin[k] = false;
4201  nonlin_list.clear();
4202  }
4203  // Create sparsity pattern
4204  return Sparsity::triplet(iind.size(), iind.size(), row, col);
4205 }
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
Definition: sparsity.cpp:1127

References casadi::Variable::dependencies, casadi::Variable::dependenciesKind, casadi::DEPENDENT, casadi::Sparsity::get_col(), casadi::Sparsity::get_row(), n_variables(), casadi::Sparsity::triplet(), and variable().

Referenced by casadi::FmuInternal::init().

◆ hess_v_v_from_calls()

MX casadi::DaeBuilderInternal::hess_v_v_from_calls ( std::map< MXNode *, CallIO > &  call_nodes,
const std::vector< casadi_int > &  h_offsets 
) const
protected

Definition at line 2161 of file dae_builder_internal.cpp.

2162  {
2163  // Calculate all Hessian expressions
2164  for (auto&& call_ref : call_nodes) call_ref.second.calc_hess();
2165  // Row offsets in hess_v_v
2166  casadi_int voffset_begin = 0, voffset_end = 0, voffset_last = 0;
2167  // Vertical and horizontal slices of hess_v_v
2168  std::vector<MX> vblocks, hblocks;
2169  // All blocks for a block row
2170  std::map<size_t, MX> hess_brow;
2171  // Loop over block rows
2172  for (size_t vind1 = 0; vind1 < size(Category::W); ++vind1) {
2173  // Current element handled
2174  const MX& vref = var(Category::W, vind1);
2175  // Update vertical offset
2176  voffset_begin = voffset_end;
2177  voffset_end += vref.numel();
2178  // Collect all blocks for this block row
2179  hess_brow.clear();
2180  for (auto&& call_ref : call_nodes) {
2181  // Locate the specific index
2182  for (size_t iind1 = 0; iind1 < call_ref.second.v.size(); ++iind1) {
2183  if (call_ref.second.v.at(iind1) == vind1) {
2184  // Add contribution to block row
2185  for (size_t iind2 = 0; iind2 < call_ref.second.v.size(); ++iind2) {
2186  // Corresponding index in v
2187  size_t vind2 = call_ref.second.v[iind2];
2188  if (vind2 == size_t(-1)) continue;
2189  // Hessian contribution
2190  MX H_contr = call_ref.second.hess(iind1, iind2);
2191  // Insert new block or add to existing one
2192  auto it = hess_brow.find(vind2);
2193  if (it != hess_brow.end()) {
2194  it->second += H_contr;
2195  } else {
2196  hess_brow[vind2] = H_contr;
2197  }
2198  }
2199  // An index can only appear once
2200  break;
2201  }
2202  }
2203  }
2204  // If no blocks, skip row
2205  if (hess_brow.empty()) continue;
2206  // Add empty rows to vblocks, if any
2207  if (voffset_last != voffset_begin) {
2208  vblocks.push_back(MX(voffset_begin - voffset_last, h_offsets.back()));
2209  }
2210  // Collect horizontal blocks
2211  hblocks.clear();
2212  casadi_int hoffset = 0;
2213  for (auto e : hess_brow) {
2214  // Add empty block before Jacobian block, if needed
2215  if (hoffset < h_offsets.at(e.first))
2216  hblocks.push_back(MX(vref.numel(), h_offsets.at(e.first) - hoffset));
2217  // Add Jacobian block
2218  hblocks.push_back(e.second);
2219  // Update offsets
2220  hoffset = h_offsets.at(e.first + 1);
2221  }
2222  // Add trailing empty block, if needed
2223  if (hoffset < h_offsets.back())
2224  hblocks.push_back(MX(vref.numel(), h_offsets.back() - hoffset));
2225  // Add new block row to vblocks
2226  vblocks.push_back(horzcat(hblocks));
2227  // Keep track of the offset handled in jac_brow
2228  voffset_last = voffset_end;
2229  }
2230  // Add empty trailing row to vblocks, if any
2231  if (voffset_last != voffset_end) {
2232  vblocks.push_back(MX(voffset_end - voffset_last, h_offsets.back()));
2233  }
2234  // Return additional term in jac_vdef_v
2235  return vertcat(vblocks);
2236 }

References casadi::MX::find(), casadi::GenericMatrix< MatType >::numel(), size(), var(), and casadi::W.

Referenced by create().

◆ import_binding_equations()

void casadi::DaeBuilderInternal::import_binding_equations ( const XmlNode eqs)
protected

Definition at line 3760 of file dae_builder_internal.cpp.

3760  {
3761  if (debug_) {
3762  uout() << "== Structure before importing binding equations ==" << std::endl;
3763  disp(uout(), true);
3764  }
3765 
3766  // Loop over binding equations
3767  for (casadi_int i = 0; i < eqs.size(); ++i) {
3768  const XmlNode& eq = eqs[i];
3769  std::string eq_name = "beq_" + str(i);
3770  // Try to read the node
3771  try {
3772  // Get the variable and binding expression
3773  Variable& var = read_variable(eq[0]);
3774  if (eq[1].size() == 1) {
3775  // Set the binding equation
3776  var.bind = assign(var.name, read_expr(eq[1][0])).index;
3777  } else {
3778  // OpenModelica 1.17 occationally generates integer values without type specifier (bug?)
3779  casadi_assert(eq[1].size() == 0, "Not implemented");
3780  casadi_int val;
3781  eq[1].get(&val);
3782  casadi_warning(var.name + " has binding equation without type specifier: " + str(val));
3783  // Set the binding equation
3784  var.bind = assign(var.name, val).index;
3785  }
3786  // Add to list of dependent parameters
3787  indices(Category::D).push_back(var.index);
3788  } catch (std::exception& e) {
3789  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
3790  }
3791  }
3792 }
Variable & read_variable(const XmlNode &node, Attribute *att=0)
Read a variable.
MX read_expr(const XmlNode &node)
Read an equation.
std::string name() const
Get the name.
Definition: mx.cpp:762
std::ostream & uout()

References assign(), casadi::D, debug_, disp(), eq(), casadi::Variable::index, indices(), casadi::MX::name(), read_expr(), read_variable(), casadi::XmlNode::size(), size(), casadi::str(), casadi::uout(), and var().

Referenced by load_fmi_description().

◆ import_default_experiment()

void casadi::DaeBuilderInternal::import_default_experiment ( const XmlNode n)
protected

Definition at line 3295 of file dae_builder_internal.cpp.

3295  {
3296  start_time_ = n.attribute<double>("startTime", nan);
3297  stop_time_ = n.attribute<double>("stopTime", nan);
3298  tolerance_ = n.attribute<double>("tolerance", nan);
3299  step_size_ = n.attribute<double>("stepSize", nan);
3300 }

References casadi::XmlNode::attribute(), casadi::nan, start_time_, step_size_, stop_time_, and tolerance_.

Referenced by load_fmi_description().

◆ import_dynamic_equations()

void casadi::DaeBuilderInternal::import_dynamic_equations ( const XmlNode eqs)
protected

Definition at line 3794 of file dae_builder_internal.cpp.

3794  {
3795  if (debug_) {
3796  uout() << "== Structure before importing dynamic equations ==" << std::endl;
3797  disp(uout(), true);
3798  }
3799  // Add discrete states to x_
3800  // Note: Make generic, should also apply to regular FMUs
3801  for (Variable* v : variables_) {
3802  if (v->variability == Variability::DISCRETE) {
3803  categorize(v->index, Category::X);
3804  }
3805  }
3806  // Add equations
3807  for (casadi_int i = 0; i < eqs.size(); ++i) {
3808  const XmlNode& eq = eqs[i];
3809  std::string eq_name = "dyneq_" + str(i);
3810  // Try to read the node
3811  try {
3812  if (eq.name == "equ:When") { // When equation
3813  // Nodes for condition, equations
3814  const XmlNode& n_cond = eq["equ:Condition"];
3815  const XmlNode& n_equ = eq["equ:Equation"];
3816  // Consistency checks - only working for very simple expressions
3817  casadi_assert(n_cond.size() == 1, "Only one condition in when equation supported");
3818  casadi_assert(n_equ.size() == 1, "Only one equation in when equation supported");
3819  // Get expression for condition
3820  std::string cond_name = n_cond[0][0].attribute<std::string>("name");
3821  std::string when_prefix = "$whenCondition";
3822  cond_name = cond_name.substr(when_prefix.size());
3823  casadi_int ind = std::stoi(cond_name) - 1;
3824  // Left-hand-side and right-hand-side
3825  MX lhs, rhs;
3826  // Handle different types of equations
3827  if (n_equ[0].name == "exp:Sub") {
3828  // Assume equation is an assignment
3829  lhs = read_identifier(n_equ[0][0]);
3830  rhs = read_expr(n_equ[0][1]);
3831  when_.at(ind).second.push_back(assign(lhs.name(), rhs).index);
3832  } else if (n_equ[0].name == "exp:Reinit") {
3833  // Reinitialization
3834  lhs = read_identifier(n_equ[0][0]);
3835  rhs = read_expr(n_equ[0][1]);
3836  when_.at(ind).second.push_back(reinit(lhs.name(), rhs).index);
3837  } else {
3838  // Not implemented
3839  casadi_error(n_equ[0].name + " in when equation not supported");
3840  }
3841  } else if (eq.name == "equ:Equation") { // Residual equation
3842  // Consistency checks
3843  casadi_assert_dev(eq.size() == 1 && eq[0].name == "exp:Sub");
3844  // Skip if empty
3845  if (eq[0].size() == 0) {
3846  casadi_warning(eq_name + " is empty, ignored.");
3847  continue;
3848  }
3849  // Get the left-hand-sides and right-hand-sides
3850  const XmlNode& lhs = eq[0][0];
3851  const XmlNode& rhs = eq[0][1];
3852  // Right-hand-side is the binding equation
3853  MX beq = read_expr(rhs);
3854  // Left-hand-side is a variable or derivative
3855  std::string when_prefix = "$whenCondition";
3856  if (lhs.name == "exp:Der") {
3857  // Differential equation
3858  Variable& v = read_variable(lhs[0]);
3859  this->eq(der(v.v), beq, Dict());
3860  } else if (lhs.size() > 0
3861  && lhs[0].attribute<std::string>("name").rfind(when_prefix, 0) == 0) {
3862  // Get the index
3863  std::string cond_name = lhs[0].attribute<std::string>("name");
3864  if (debug_) {
3865  uout() << "Reading event indicator: " << cond_name << " := " << beq << std::endl;
3866  }
3867  cond_name = cond_name.substr(when_prefix.size());
3868  casadi_int ind = std::stoi(cond_name) - 1;
3869  // Ensure consequitive for now
3870  casadi_assert(ind == when_.size(), "Non-consequitive when conditions");
3871  // Create a when equation with no equations
3872  when(beq, {}, Dict());
3873  } else {
3874  // Regular equation
3875  Variable& v = read_variable(lhs);
3876  if (debug_) uout() << "Reading equation: " << v.name << " == " << beq << std::endl;
3877  this->eq(v.v, beq, Dict());
3878  }
3879  } else {
3880  casadi_error("Unknown dynamic equation type, got:" + eq.name);
3881  }
3882  } catch (std::exception& e) {
3883  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
3884  }
3885  }
3886 }
void when(const MX &cond, const std::vector< std::string > &eqs, const Dict &opts)
Add when equations.
MX read_identifier(const XmlNode &node)
Read an identifier expression.
Variable & reinit(const std::string &name, const MX &val)
Reinitialize a state inside when-equations.

References assign(), casadi::XmlNode::attribute(), categorize(), debug_, der(), casadi::DISCRETE, disp(), eq(), casadi::Variable::index, casadi::Variable::name, casadi::MX::name(), name(), casadi::XmlNode::name, read_expr(), read_identifier(), read_variable(), reinit(), casadi::XmlNode::size(), size(), casadi::str(), casadi::uout(), casadi::Variable::v, variables_, when(), when_, and casadi::X.

Referenced by load_fmi_description().

◆ import_initial_equations()

void casadi::DaeBuilderInternal::import_initial_equations ( const XmlNode eqs)
protected

Definition at line 3888 of file dae_builder_internal.cpp.

3888  {
3889  if (debug_) {
3890  uout() << "== Structure before importing initial equations ==" << std::endl;
3891  disp(uout(), true);
3892  }
3893 
3894  // Hack: OpenModelica XML may contain duplicate expressions, ignore these
3895  std::set<std::string> already_added;
3896  // Add equations
3897  for (casadi_int i = 0; i < eqs.size(); ++i) {
3898  const XmlNode& eq = eqs[i];
3899  // Try to read the node
3900  std::string eq_name = "initeq_" + str(i);
3901  try {
3902  if (eq.name == "equ:Equation") { // Residual equation
3903  // Consistency checks
3904  casadi_assert_dev(eq.size() == 1 && eq[0].name == "exp:Sub");
3905  // Ensure not empty
3906  if (eq[0].size() == 0) {
3907  casadi_warning(eq_name + " is empty, ignored.");
3908  continue;
3909  }
3910  // Get the left-hand-sides and right-hand-sides
3911  const XmlNode& lhs = eq[0][0];
3912  const XmlNode& rhs = eq[0][1];
3913 
3914  // Ignore initalizations of when equation indicators
3915  if (lhs.size() > 0
3916  && lhs[0].attribute<std::string>("name").rfind("$whenCondition", 0) == 0) {
3917  continue;
3918  }
3919 
3920  // Hack: Ignore expressions that just set a $PRE variable
3921  if (lhs.size() > 0 && lhs[0].attribute<std::string>("name") == "$PRE") {
3922  casadi_warning(eq_name + " defines a pre-variable, ignored");
3923  continue;
3924  }
3925  // Right-hand-side is the binding equation
3926  MX beq = read_expr(rhs);
3927  // Left-hand-side is a variable
3928  Variable& v = read_variable(lhs);
3929  // Hack: ignore initial equations for tunable parameters
3930  if (v.variability == Variability::TUNABLE) {
3931  casadi_warning(eq_name + " defines a tunable parameter, ignored")
3932  continue;
3933  }
3934  // Hack: avoid duplicate equations
3935  std::string eq_str = str(v.v) + " == " + str(beq);
3936  auto it = already_added.insert(eq_str);
3937  if (!it.second) {
3938  casadi_warning(eq_name + " duplicate of previous equation " + eq_str + ", ignored")
3939  continue;
3940  }
3941  // Set initial condition
3942  set_init(v.name, beq);
3943  } else {
3944  casadi_error("Unknown initial equation type, got:" + eq.name);
3945  }
3946  } catch (std::exception& e) {
3947  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
3948  }
3949  }
3950 }
void set_init(const std::string &name, const MX &init_rhs)
Set a initial equation.

References casadi::XmlNode::attribute(), debug_, disp(), eq(), casadi::Variable::name, read_expr(), read_variable(), set_init(), casadi::XmlNode::size(), size(), casadi::str(), casadi::TUNABLE, casadi::uout(), casadi::Variable::v, and casadi::Variable::variability.

Referenced by load_fmi_description().

◆ import_model_exchange()

void casadi::DaeBuilderInternal::import_model_exchange ( const XmlNode n)
protected

Definition at line 3302 of file dae_builder_internal.cpp.

3302  {
3303  // Read attributes
3304  provides_directional_derivatives_ = n.attribute<bool>(
3305  fmi_major_ >= 3 ? "providesDirectionalDerivatives" : "providesDirectionalDerivative", false);
3307  = n.attribute<bool>("providesAdjointDerivatives", false);
3308  model_identifier_ = n.attribute<std::string>("modelIdentifier");
3310  n.attribute<bool>("canBeInstantiatedOnlyOncePerProcess", false);
3311  // Get list of source files
3312  if (n.has_child("SourceFiles")) {
3313  for (const XmlNode& sf : n["SourceFiles"].children) {
3314  source_files_.push_back(sf.attribute<std::string>("name"));
3315  }
3316  }
3317 }
std::vector< std::string > source_files_

References casadi::XmlNode::attribute(), can_be_instantiated_only_once_per_process_, fmi_major_, casadi::XmlNode::has_child(), model_identifier_, provides_adjoint_derivatives_, provides_directional_derivatives_, and source_files_.

Referenced by load_fmi_description().

◆ import_model_structure()

void casadi::DaeBuilderInternal::import_model_structure ( const XmlNode n)
protected

Definition at line 3559 of file dae_builder_internal.cpp.

3559  {
3560  // Do not use the automatic selection of outputs based on output causality
3561  outputs_.clear();
3562 
3563  // Algebraic variables are handled internally in the FMU
3564  for (size_t i = 0; i < n_variables(); ++i) {
3565  Variable& v = variable(i);
3566  if (v.category == Category::Z) {
3567  // Mark as dependent variable, no need for an algebraic equation anymore
3568  categorize(v.index, Category::W);
3569  }
3570  }
3571 
3572  // Read structure
3573  if (fmi_major_ >= 3) {
3574  // Loop over ModelStructure elements
3575  for (casadi_int i = 0; i < n.size(); ++i) {
3576  const XmlNode& e = n[i];
3577  // Get a reference to the variable
3578  if (e.name == "Output") {
3579  // Get index
3580  outputs_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
3581  // Corresponding variable
3582  Variable& v = variable(outputs_.back());
3583  // Get dependencies
3584  v.dependencies = read_dependencies(e);
3585  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
3586  // Mark interdependencies
3587  for (casadi_int d : v.dependencies) variable(d).dependency = true;
3588  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
3589  } else if (e.name == "ContinuousStateDerivative") {
3590  // Get index
3591  derivatives_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
3592  // Corresponding variable
3593  Variable& v = variable(derivatives_.back());
3594  // Add to list of states and derivative to list of dependent variables
3595  casadi_assert(v.parent >= 0, "Error processing derivative info for " + v.name);
3596  categorize(v.index, Category::W);
3597  categorize(v.parent, Category::X);
3598  // Map der field to derivative variable
3599  variable(v.parent).der = derivatives_.back();
3600  // Get dependencies
3601  v.dependencies = read_dependencies(e);
3602  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
3603  // Mark interdependencies
3604  for (casadi_int d : v.dependencies) variable(d).dependency = true;
3605  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
3606  } else if (e.name == "ClockedState") {
3607  // Clocked state
3608  casadi_message("ClockedState not implemented, ignoring");
3609  } else if (e.name == "InitialUnknown") {
3610  // Get index
3611  initial_unknowns_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
3612  // Get dependencies
3613  for (casadi_int d : read_dependencies(e)) variable(d).dependency = true;
3614  } else if (e.name == "EventIndicator") {
3615  // Event indicator
3616  event_indicators_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
3618  } else {
3619  // Unknown
3620  casadi_error("Unknown ModelStructure element: " + e.name);
3621  }
3622  }
3623  } else {
3624  // Derivatives
3625  if (n.has_child("Derivatives")) {
3626  for (auto& e : n["Derivatives"].children) {
3627  // Get index
3628  derivatives_.push_back(e.attribute<casadi_int>("index", 0) - 1);
3629  // Corresponding variable
3630  Variable& v = variable(derivatives_.back());
3631  // Add to list of states and derivative to list of dependent variables
3632  casadi_assert(v.parent >= 0, "Error processing derivative info for " + v.name);
3633  categorize(v.index, Category::W);
3634  categorize(v.parent, Category::X);
3635  // Map der field to derivative variable
3636  variable(v.parent).der = derivatives_.back();
3637  }
3638  }
3639 
3640  // What if dependencies attributed is missing from Outputs,Derivatives?
3641  // Depends on x_ having been populated
3642  std::vector<casadi_int> default_dependencies;
3643  default_dependencies.insert(default_dependencies.begin(),
3644  indices(Category::T).begin(), indices(Category::T).end());
3645  default_dependencies.insert(default_dependencies.begin(),
3646  indices(Category::X).begin(), indices(Category::X).end());
3647  default_dependencies.insert(default_dependencies.begin(),
3648  indices(Category::U).begin(), indices(Category::U).end());
3649  std::sort(default_dependencies.begin(), default_dependencies.end());
3650 
3651  // FMI2 standard does not allow parameters to be included in dependencies attribute
3652  // (Table in section 2.2.8)
3653  // FMI3 standard does (Table in section 2.4.8)
3654  //
3655  // A uniform treatment is unconditionally add dense dependencies to all parameters
3656  // when loading FMI2
3657 
3658  std::vector<casadi_int> additional_dependencies;
3659  additional_dependencies.insert(additional_dependencies.begin(),
3660  indices(Category::P).begin(), indices(Category::P).end());
3661  std::vector<DependenciesKind> additional_dependencies_kind(size(Category::P),
3663 
3664  // Derivatives
3665  if (n.has_child("Derivatives")) {
3666  // Separate pass for dependencies
3667  for (auto& e : n["Derivatives"].children) {
3668  casadi_int index = e.attribute<casadi_int>("index", 0)-1;
3669 
3670  // Corresponding variable
3671  Variable& v = variable(index);
3672 
3673  // Get dependencies
3674  if (e.has_attribute("dependencies")) {
3675  v.dependencies = read_dependencies(e);
3676  } else {
3677  v.dependencies = default_dependencies;
3678  }
3679  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
3680 
3681  v.dependencies.insert(v.dependencies.end(),
3682  additional_dependencies.begin(), additional_dependencies.end());
3683  v.dependenciesKind.insert(v.dependenciesKind.end(),
3684  additional_dependencies_kind.begin(), additional_dependencies_kind.end());
3685 
3686  // Mark interdependencies
3687  for (casadi_int d : v.dependencies) variable(d).dependency = true;
3688  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
3689  }
3690  }
3691  // Outputs
3692  if (n.has_child("Outputs")) {
3693  for (auto& e : n["Outputs"].children) {
3694  // Get index
3695  outputs_.push_back(e.attribute<casadi_int>("index", 0) - 1);
3696  // Corresponding variable
3697  Variable& v = variable(outputs_.back());
3698  // Get dependencies
3699  if (e.has_attribute("dependencies")) {
3700  v.dependencies = read_dependencies(e);
3701  } else {
3702  v.dependencies = default_dependencies;
3703  }
3704  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
3705 
3706  v.dependencies.insert(v.dependencies.end(),
3707  additional_dependencies.begin(), additional_dependencies.end());
3708  v.dependenciesKind.insert(v.dependenciesKind.end(),
3709  additional_dependencies_kind.begin(), additional_dependencies_kind.end());
3710 
3711  // Mark interdependencies
3712  for (casadi_int d : v.dependencies) variable(d).dependency = true;
3713  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
3714  }
3715  }
3716  // What if dependencies is missing from InitialUnknowns?
3717  // Depends on x_ having been populated
3718  default_dependencies.clear();
3719  default_dependencies.insert(default_dependencies.begin(),
3720  indices(Category::T).begin(), indices(Category::T).end());
3721  for (const Variable* v : variables_) {
3722  if (v->initial == Initial::EXACT) default_dependencies.push_back(v->index);
3723  }
3724  default_dependencies.insert(default_dependencies.begin(),
3725  indices(Category::U).begin(), indices(Category::U).end());
3726  std::sort(default_dependencies.begin(), default_dependencies.end());
3727 
3728  // Initial unknowns
3729  if (n.has_child("InitialUnknowns")) {
3730  for (auto& e : n["InitialUnknowns"].children) {
3731  // Get index
3732  initial_unknowns_.push_back(e.attribute<casadi_int>("index", 0) - 1);
3733 
3734  std::vector<casadi_int> dependencies;
3735  // Get dependencies
3736  if (e.has_attribute("dependencies")) {
3737  dependencies = read_dependencies(e);
3738  } else {
3739  dependencies = default_dependencies;
3740  }
3741 
3742  dependencies.insert(dependencies.end(),
3743  additional_dependencies.begin(), additional_dependencies.end());
3744 
3745  // Get dependencies
3746  for (casadi_int d : dependencies) variable(d).dependency = true;
3747  }
3748  }
3749  }
3750 
3751  // Reclassify some states as quadratures
3752  if (detect_quad_ && fmi_major_ >= 2) {
3753  for (size_t i : derivatives_) {
3754  size_t x = variable(i).parent;
3755  if (!variable(x).in_rhs) categorize(x, Category::Q);
3756  }
3757  }
3758 }
std::vector< size_t > derivatives_
std::vector< size_t > initial_unknowns_
std::unordered_map< unsigned int, size_t > vrmap_
Find of variable by value reference.
std::vector< DependenciesKind > read_dependencies_kind(const XmlNode &n, size_t ndep)
std::vector< casadi_int > read_dependencies(const XmlNode &n)
bool dependency
Do other expressions depend on this variable.

References casadi::XmlNode::attribute(), categorize(), casadi::Variable::category, casadi::Variable::dependencies, casadi::Variable::dependenciesKind, casadi::Variable::dependency, casadi::DEPENDENT, casadi::Variable::der, derivatives_, detect_quad_, event_indicators_, casadi::EXACT, fmi_major_, casadi::XmlNode::has_child(), casadi::Variable::in_rhs, casadi::Variable::index, indices(), initial_unknowns_, n_variables(), casadi::Variable::name, casadi::XmlNode::name, number_of_event_indicators_, outputs_, casadi::P, casadi::Variable::parent, casadi::Q, read_dependencies(), read_dependencies_kind(), casadi::XmlNode::size(), size(), casadi::T, casadi::U, variable(), variables_, vrmap_, casadi::W, casadi::X, and casadi::Z.

Referenced by load_fmi_description().

◆ import_model_variables()

void casadi::DaeBuilderInternal::import_model_variables ( const XmlNode modvars)
protected

Definition at line 3319 of file dae_builder_internal.cpp.

3319  {
3320  // Mapping from derivative variables to corresponding state variables, FMUX only
3321  std::vector<std::pair<std::string, std::string>> fmi1_der;
3322 
3323  // Force any independent variable to appear first
3324  std::vector<const XmlNode*> modvars_children;
3325 
3326  for (casadi_int i = 0; i < modvars.size(); ++i) {
3327  // Get a reference to the variable
3328  const XmlNode& vnode = modvars[i];
3329  std::string causality_str = vnode.attribute<std::string>("causality", "local");
3330  if (causality_str=="independent") {
3331  modvars_children.push_back(&vnode);
3332  }
3333  }
3334 
3335  for (casadi_int i = 0; i < modvars.size(); ++i) {
3336  // Get a reference to the variable
3337  const XmlNode& vnode = modvars[i];
3338  std::string causality_str = vnode.attribute<std::string>("causality", "local");
3339  if (causality_str!="independent") {
3340  modvars_children.push_back(&vnode);
3341  }
3342  }
3343 
3344  // Add variables
3345  for (const XmlNode* & vnode_ptr : modvars_children) {
3346  // Get a reference to the variable
3347  const XmlNode& vnode = *vnode_ptr;
3348 
3349  // Name of variable
3350  std::string name = vnode.attribute<std::string>("name");
3351 
3352  // Handle variable categories (FMUX)
3353  if (fmi_major_ == 1 && vnode.has_child("VariableCategory")) {
3354  std::string variable_category = vnode["VariableCategory"].text;
3355  if (variable_category == "derivative") {
3356  // Create a new derivative variable
3357  std::string x_name = vnode["QualifiedName"][0].attribute<std::string>("name");
3358  fmi1_der.push_back(std::make_pair(x_name, name));
3359  }
3360  }
3361 
3362  // When conditions are reformulated into continuous zero-crossing functions
3363  if (fmi_major_ == 1 && name.rfind("$whenCondition", 0) == 0) continue;
3364 
3365  // Ignore duplicate variables
3366  if (varind_.find(name) != varind_.end()) {
3367  casadi_warning("Duplicate variable '" + name + "' ignored");
3368  continue;
3369  }
3370 
3371  // Type specific properties
3372  Dict opts;
3373  Type type = Type::NUMEL;
3374  casadi_int derivative = -1;
3375  if (fmi_major_ >= 3) {
3376  // FMI 3.0: Type information in the same node
3377  type = to_enum<Type>(vnode.name);
3378  switch (type) {
3379  case Type::FLOAT32: // fall-through
3380  case Type::FLOAT64:
3381  // Floating point valued variables
3382  opts["unit"] = vnode.attribute<std::string>("unit", "");
3383  opts["display_unit"] = vnode.attribute<std::string>("displayUnit", "");
3384  opts["min"] = vnode.attribute<double>("min", -inf);
3385  opts["max"] = vnode.attribute<double>("max", inf);
3386  opts["nominal"] = vnode.attribute<double>("nominal", 1.);
3387  opts["start"] = vnode.attribute<double>("start", 0.);
3388  derivative = vnode.attribute<casadi_int>("derivative", -1);
3389  break;
3390  case Type::INT8: // fall-through
3391  case Type::UINT8: // fall-through
3392  case Type::INT16: // fall-through
3393  case Type::UINT16: // fall-through
3394  case Type::INT32: // fall-through
3395  case Type::UINT32: // fall-through
3396  case Type::INT64: // fall-through
3397  case Type::UINT64: // fall-through
3398  // Integer valued variables
3399  opts["min"] = vnode.attribute<double>("min", -inf);
3400  opts["max"] = vnode.attribute<double>("max", inf);
3401  break;
3402  default:
3403  break;
3404  }
3405  } else {
3406  // FMI 1.0 / 2.0: Type information in a separate node
3407  if (vnode.has_child("Real")) {
3408  type = Type::FLOAT64;
3409  const XmlNode& props = vnode["Real"];
3410  opts["unit"] = props.attribute<std::string>("unit", "");
3411  opts["display_unit"] = props.attribute<std::string>("displayUnit", "");
3412  opts["min"] = props.attribute<double>("min", -inf);
3413  opts["max"] = props.attribute<double>("max", inf);
3414  opts["nominal"] = props.attribute<double>("nominal", 1.);
3415  opts["start"] = props.attribute<double>("start", 0.);
3416  derivative = props.attribute<casadi_int>("derivative", -1);
3417  } else if (vnode.has_child("Integer")) {
3418  type = Type::INT32;
3419  const XmlNode& props = vnode["Integer"];
3420  opts["min"] = props.attribute<double>("min", -inf);
3421  opts["max"] = props.attribute<double>("max", inf);
3422  } else if (vnode.has_child("Boolean")) {
3423  type = Type::BOOLEAN;
3424  } else if (vnode.has_child("String")) {
3425  type = Type::STRING;
3426  } else if (vnode.has_child("Enumeration")) {
3427  type = Type::ENUMERATION;
3428  } else {
3429  casadi_warning("Unknown type for " + name);
3430  }
3431  }
3432 
3433  // Description
3434  std::string description = vnode.attribute<std::string>("description", "");
3435 
3436  // Causality (FMI 1.0 -> FMI 2.0+)
3437  std::string causality_str = vnode.attribute<std::string>("causality", "local");
3438  if (fmi_major_ == 1 && causality_str == "internal") causality_str = "local";
3439  Causality causality = to_enum<Causality>(causality_str);
3440 
3441  // Variability (FMI 1.0 -> FMI 2.0+)
3442  std::string variability_str = vnode.attribute<std::string>("variability",
3444  if (fmi_major_ == 1 && variability_str == "parameter") variability_str = "fixed";
3445  Variability variability = to_enum<Variability>(variability_str);
3446 
3447  // Initial property
3449  std::string initial_str = vnode.attribute<std::string>("initial", "");
3450  if (!initial_str.empty()) {
3451  // Consistency check
3453  "The combination causality = '" + to_string(causality) + "', "
3454  "initial = '" + initial_str + "' is not allowed per the FMI specification.");
3455  initial = to_enum<Initial>(initial_str);
3456  }
3457 
3458  // If an input has a description that starts with "PARAMETER:",
3459  // treat it as a tunable parameter
3460  if (causality == Causality::INPUT && description.rfind("PARAMETER:", 0) == 0) {
3461  // Make tunable parameter
3464  }
3465 
3466  // Create the new variable
3467  opts["type"] = to_string(type);
3468  opts["initial"] = to_string(initial);
3469  opts["description"] = description;
3470  Variable& var = add(name, causality, variability, opts);
3471  if (debug_) uout() << "Added variable: " << var.name << std::endl;
3472 
3473  // Ignore time variable?
3475  categorize(var.index, Category::NUMEL);
3476  }
3477 
3478  // Do not permit discrete variables in x, for now
3480  categorize(var.index, Category::NUMEL);
3481  }
3482 
3483  // Unless detect_quad has been set, assume all variables in the right-hand-sides
3484  // Prevents changing X to Q
3485  var.in_rhs = !detect_quad_ && fmi_major_ >= 2;
3486  var.value_reference = static_cast<unsigned int>(vnode.attribute<casadi_int>("valueReference"));
3487  vrmap_[var.value_reference] = var.index;
3488  var.der_of = derivative;
3489  }
3490 
3491  // Set "parent" property using "derivative" attribute
3492  for (size_t i = 0; i < n_variables(); ++i) {
3493  Variable& v = variable(i);
3494  if (v.der_of >= 0) {
3495  if (fmi_major_ >= 3) {
3496  // Value reference is given: Find corresponding variable
3497  v.parent = vrmap_.at(static_cast<unsigned int>(v.der_of));
3498  } else if (fmi_major_ > 1) {
3499  // Variable given with index-1, make index 0
3500  v.parent = v.der_of - 1;
3501  }
3502  // TODO(@jaeandersson): Remove this redefinition of der_of
3503  v.der_of = v.parent;
3504  }
3505  }
3506 
3507  // Map derivative variables to corresponding state variables, FMUX only
3508  for (auto& p : fmi1_der) {
3509  // Add to list of derivatives
3510  Variable& v = variable(p.first);
3511  Variable& der_v = variable(p.second);
3512  categorize(der_v.index, Category::Z);
3513  der_v.der_of = der_v.parent = v.index;
3514  v.der = der_v.index;
3515  derivatives_.push_back(der_v.index);
3516  }
3517 }
static Initial default_initial(Causality causality, Variability variability)
Variability
Variability: FMI 2.0 specification, section 2.2.7 or FMI 3.0 specification, section 2....
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....

References add(), casadi::XmlNode::attribute(), casadi::BOOLEAN, categorize(), causality(), debug_, default_initial(), default_variability(), casadi::Variable::der, casadi::Variable::der_of, derivatives_, casadi::description(), detect_quad_, casadi::DISCRETE, casadi::ENUMERATION, casadi::FLOAT32, casadi::FLOAT64, fmi_major_, casadi::XmlNode::has_child(), ignore_time_, casadi::INDEPENDENT, casadi::Variable::index, casadi::inf, casadi::INPUT, casadi::INT16, casadi::INT32, casadi::INT64, casadi::INT8, n_variables(), casadi::MX::name(), name(), casadi::XmlNode::name, casadi::NUMEL, casadi::PARAMETER, casadi::Variable::parent, casadi::XmlNode::size(), casadi::STRING, casadi::XmlNode::text, casadi::to_string(), casadi::TUNABLE, casadi::UINT16, casadi::UINT32, casadi::UINT64, casadi::UINT8, casadi::uout(), var(), variability(), variable(), varind_, vrmap_, and casadi::Z.

Referenced by load_fmi_description().

◆ indices() [1/2]

std::vector< size_t > & casadi::DaeBuilderInternal::indices ( Category  cat)

◆ indices() [2/2]

const std::vector< size_t > & casadi::DaeBuilderInternal::indices ( Category  cat) const

Definition at line 1370 of file dae_builder_internal.cpp.

1370  {
1371  return const_cast<DaeBuilderInternal*>(this)->indices(cat);
1372 }

References indices().

◆ init_lhs()

std::vector< MX > casadi::DaeBuilderInternal::init_lhs ( ) const
protected

Extra doc: https://github.com/casadi/casadi/wiki/L_2a7

Definition at line 2694 of file dae_builder_internal.cpp.

2694  {
2695  std::vector<MX> ret;
2696  ret.reserve(init_.size());
2697  for (size_t ind : init_) {
2698  ret.push_back(variable(ind).v);
2699  }
2700  return ret;
2701 }

References init_, and variable().

◆ init_rhs()

std::vector< MX > casadi::DaeBuilderInternal::init_rhs ( ) const
protected

Extra doc: https://github.com/casadi/casadi/wiki/L_2a8

Definition at line 2703 of file dae_builder_internal.cpp.

2703  {
2704  std::vector<MX> ret;
2705  ret.reserve(init_.size());
2706  for (size_t ind : init_) {
2707  ret.push_back(variable(ind).ieq);
2708  }
2709  return ret;
2710 }

References init_, and variable().

Referenced by set_init().

◆ initSingleton()

void casadi::GenericSharedInternal< SharedObject , SharedObjectInternal >::initSingleton ( )
inlineprotectedinherited

Called in the constructor of singletons to avoid that the counter reaches zero

Definition at line 71 of file generic_shared_internal.hpp.

71  {
72  casadi_assert_dev(static_cast<Internal*>(this)->count==0);
73  static_cast<Internal*>(this)->count++;
74  }

◆ input() [1/2]

std::vector< MX > casadi::DaeBuilderInternal::input ( Category  ind) const

Definition at line 1831 of file dae_builder_internal.cpp.

1831  {
1832  // Operation only permitted for input categories
1833  casadi_assert(is_input_category(ind),
1834  to_string(ind) + " is not an input category");
1835  // Get the expressions
1836  return var(indices(ind));
1837 }
bool is_input_category(Category cat)

References indices(), casadi::is_input_category(), casadi::to_string(), and var().

Referenced by dependent_fun(), input(), oracle(), and prune().

◆ input() [2/2]

std::vector< MX > casadi::DaeBuilderInternal::input ( const std::vector< Category > &  ind) const

Definition at line 1839 of file dae_builder_internal.cpp.

1839  {
1840  std::vector<MX> ret(ind.size());
1841  for (casadi_int i=0; i<ind.size(); ++i) {
1842  ret[i] = vertcat(input(ind[i]));
1843  }
1844  return ret;
1845 }

References input().

◆ insert()

void casadi::DaeBuilderInternal::insert ( std::vector< size_t > &  v,
size_t  ind 
) const
protected

Definition at line 2919 of file dae_builder_internal.cpp.

2919  {
2920  // Keep list ordered: Insert at location corresponding to model variable index
2921  size_t loc = v.size();
2922  for (size_t i = 0; i < v.size(); ++i) {
2923  if (variable(v[i]).index >= ind) {
2924  loc = i;
2925  break;
2926  }
2927  }
2928  v.insert(v.begin() + loc, ind);
2929 }

References variable().

Referenced by categorize(), and set_causality().

◆ iso_8601_time()

std::string casadi::DaeBuilderInternal::iso_8601_time ( )
static

Definition at line 4207 of file dae_builder_internal.cpp.

4207  {
4208  // Get current time
4209  auto now = std::chrono::system_clock::now();
4210  std::time_t tt = std::chrono::system_clock::to_time_t(now);
4211  auto local_tm = *std::localtime(&tt); // NOLINT(runtime/threadsafe_fn)
4212  // Convert to ISO 8601 (YYYY-MM-DDThh:mm:ssZ) format and return
4213  std::stringstream ss;
4214  ss << local_tm.tm_year + 1900 << '-'; // YYYY-
4215  ss << std::setfill('0') << std::setw(2) << local_tm.tm_mon + 1 << '-'; // MM-
4216  ss << std::setfill('0') << std::setw(2) << local_tm.tm_mday << 'T'; // DDT
4217  ss << std::setfill('0') << std::setw(2) << local_tm.tm_hour << ':'; // hh:
4218  ss << std::setfill('0') << std::setw(2) << local_tm.tm_min << ':'; // mm:
4219  ss << std::setfill('0') << std::setw(2) << local_tm.tm_sec << 'Z'; // ssZ
4220  return ss.str();
4221 }

Referenced by generate_model_description().

◆ jac_sparsity()

Sparsity casadi::DaeBuilderInternal::jac_sparsity ( const std::vector< size_t > &  oind,
const std::vector< size_t > &  iind 
) const

Definition at line 4139 of file dae_builder_internal.cpp.

4140  {
4141  // Mark inputs
4142  std::vector<casadi_int> lookup(n_variables(), -1);
4143  for (size_t i = 0; i < iind.size(); ++i)
4144  lookup.at(iind[i]) = i;
4145  // Sparsity pattern for the Jacobian block
4146  std::vector<casadi_int> row, col;
4147  // Loop over output nonzeros
4148  for (casadi_int j = 0; j < oind.size(); ++j) {
4149  for (casadi_int d : variable(oind[j]).dependencies) {
4150  casadi_int i = lookup.at(d);
4151  if (i >= 0) {
4152  row.push_back(j); // Note: May not be sorted in ascending order
4153  col.push_back(i);
4154  }
4155  }
4156  }
4157  // Assemble sparsity in triplet format
4158  return Sparsity::triplet(oind.size(), iind.size(), row, col);
4159 }

References n_variables(), casadi::Sparsity::triplet(), and variable().

Referenced by casadi::FmuInternal::init().

◆ jac_vdef_v_from_calls()

MX casadi::DaeBuilderInternal::jac_vdef_v_from_calls ( std::map< MXNode *, CallIO > &  call_nodes,
const std::vector< casadi_int > &  h_offsets 
) const
protected

Definition at line 2090 of file dae_builder_internal.cpp.

2091  {
2092  // Calculate all Jacobian expressions
2093  for (auto call_it = call_nodes.begin(); call_it != call_nodes.end(); ++call_it) {
2094  call_it->second.calc_jac();
2095  }
2096  // Row offsets in jac_vdef_v
2097  casadi_int voffset_begin = 0, voffset_end = 0, voffset_last = 0;
2098  // Vertical and horizontal slices of jac_vdef_v
2099  std::vector<MX> vblocks, hblocks;
2100  // All blocks for this block row
2101  std::map<size_t, MX> jac_brow;
2102  // Definitions of w
2103  std::vector<MX> wdef = output(OutputCategory::WDEF);
2104  // Collect all Jacobian blocks
2105  for (size_t vdefind = 0; vdefind < wdef.size(); ++vdefind) {
2106  // Current element handled
2107  const MX& vdefref = wdef.at(vdefind);
2108  // Update vertical offset
2109  voffset_begin = voffset_end;
2110  voffset_end += vdefref.numel();
2111  // Handle function call nodes
2112  if (vdefref.is_output()) {
2113  // Which output of the function are we calculating?
2114  casadi_int oind = vdefref.which_output();
2115  // Get function call node
2116  MX c = vdefref.dep(0);
2117  // Find data about inputs and outputs
2118  auto call_it = call_nodes.find(c.get());
2119  casadi_assert_dev(call_it != call_nodes.end());
2120  // Collect all blocks for this block row
2121  jac_brow.clear();
2122  for (casadi_int iind = 0; iind < call_it->second.arg.size(); ++iind) {
2123  size_t vind = call_it->second.v.at(iind);
2124  if (vind != size_t(-1)) {
2125  jac_brow[vind] = call_it->second.jac(oind, iind);
2126  }
2127  }
2128  // Add empty rows to vblocks, if any
2129  if (voffset_last != voffset_begin) {
2130  vblocks.push_back(MX(voffset_begin - voffset_last, h_offsets.back()));
2131  }
2132  // Collect horizontal blocks
2133  hblocks.clear();
2134  casadi_int hoffset = 0;
2135  for (auto e : jac_brow) {
2136  // Add empty block before Jacobian block, if needed
2137  if (hoffset < h_offsets.at(e.first))
2138  hblocks.push_back(MX(vdefref.numel(), h_offsets.at(e.first) - hoffset));
2139  // Add Jacobian block
2140  hblocks.push_back(e.second);
2141  // Update offsets
2142  hoffset = h_offsets.at(e.first + 1);
2143  }
2144  // Add trailing empty block, if needed
2145  if (hoffset < h_offsets.back())
2146  hblocks.push_back(MX(vdefref.numel(), h_offsets.back() - hoffset));
2147  // Add new block row to vblocks
2148  vblocks.push_back(horzcat(hblocks));
2149  // Keep track of the offset handled in jac_brow
2150  voffset_last = voffset_end;
2151  }
2152  }
2153  // Add empty trailing row to vblocks, if any
2154  if (voffset_last != voffset_end) {
2155  vblocks.push_back(MX(voffset_end - voffset_last, h_offsets.back()));
2156  }
2157  // Return additional term in jac_vdef_v
2158  return vertcat(vblocks);
2159 }

References casadi::MX::dep(), casadi::MX::find(), casadi::MX::get(), casadi::MX::is_output(), casadi::GenericMatrix< MatType >::numel(), output(), casadi::WDEF, and casadi::MX::which_output().

Referenced by create().

◆ lift()

void casadi::DaeBuilderInternal::lift ( bool  lift_shared,
bool  lift_calls 
)

Definition at line 1774 of file dae_builder_internal.cpp.

1774  {
1775  // Not tested if w is non-empty before
1776  if (size(Category::W) > 0) casadi_warning("'w' already has entries");
1777  // Expressions where the variables are also being used
1778  std::vector<MX> ex;
1779  for (size_t v : indices(Category::X)) ex.push_back(variable(variable(variable(v).der).bind).v);
1780  for (size_t v : indices(Category::Q)) ex.push_back(variable(variable(variable(v).der).bind).v);
1781  for (size_t v : residuals_) ex.push_back(variable(v).v);
1782  // Lift expressions
1783  std::vector<MX> new_w, new_wdef;
1784  Dict opts{{"lift_shared", lift_shared}, {"lift_calls", lift_calls},
1785  {"prefix", "w_"}, {"suffix", ""}, {"offset", static_cast<casadi_int>(size(Category::W))}};
1786  extract(ex, new_w, new_wdef, opts);
1787  // Register as dependent variables
1788  for (size_t i = 0; i < new_w.size(); ++i) {
1789  Variable& v = new_variable(new_w.at(i).name());
1790  v.v = new_w.at(i);
1791  Variable& v_beq = assign(v.name, new_wdef.at(i));
1792  v.bind = v_beq.index;
1793  indices(Category::W).push_back(v.index);
1794  }
1795  // Get expressions
1796  auto it = ex.begin();
1797  for (size_t v : indices(Category::X)) variable(variable(variable(v).der).bind).v = *it++;
1798  for (size_t v : indices(Category::Q)) variable(variable(variable(v).der).bind).v = *it++;
1799  for (size_t v : residuals_) variable(v).v = *it++;
1800  // Consistency check
1801  casadi_assert_dev(it == ex.end());
1802 }

References assign(), casadi::Variable::bind, der(), casadi::Variable::index, indices(), casadi::Variable::name, new_variable(), casadi::Q, residuals_, size(), casadi::Variable::v, variable(), casadi::W, and casadi::X.

◆ load_fmi_description()

void casadi::DaeBuilderInternal::load_fmi_description ( const std::string &  filename)

Import existing problem from FMI/XML

Definition at line 602 of file dae_builder_internal.cpp.

602  {
603  // Check if file exists
605  if (Filesystem::is_enabled()) {
606  casadi_error("Could not open file '" + filename + "'.");
607  } else {
608  casadi_error("Could not open file '" + filename + "'. "
609  "Note that, since CasADi was compiled without WITH_GHC_FILESYSTEM=ON, "
610  "passing fmu files to DaeBuilder is unsupported. "
611  "You could manually unzip the FMU file and "
612  "pass the path to the unzipped directory instead.");
613  }
614  }
615 
616  // Ensure no variables already
617  casadi_assert(n_variables() == 0, "Instance already has variables");
618 
619  // Parse XML file
620  XmlFile xml_file("tinyxml");
621  XmlNode fmi_desc = xml_file.parse(filename)[0]; // One child; fmiModelDescription
622 
623  // Read FMU version
624  fmi_version_ = fmi_desc.attribute<std::string>("fmiVersion", "");
625  if (fmi_version_.rfind("1.", 0) == 0) {
626  // FMI 1.0: Only for symbolic FMUs
627  fmi_major_ = 1;
628  } else if (fmi_version_.rfind("2.", 0) == 0) {
629  // FMI 2.0
630  fmi_major_ = 2;
631  } else if (fmi_version_.rfind("3.", 0) == 0) {
632  // FMI 3
633  fmi_major_ = 3;
634  } else {
635  casadi_error("Unknown FMI version: " + fmi_version_);
636  }
637 
638  // Read attributes
639  model_name_ = fmi_desc.attribute<std::string>("modelName", "");
640  instantiation_token_ = fmi_desc.attribute<std::string>(
641  fmi_major_ >= 3 ? "instantiationToken" : "guid");
642  description_ = fmi_desc.attribute<std::string>("description", "");
643  author_ = fmi_desc.attribute<std::string>("author", "");
644  copyright_ = fmi_desc.attribute<std::string>("copyright", "");
645  license_ = fmi_desc.attribute<std::string>("license", "");
646  generation_tool_ = fmi_desc.attribute<std::string>("generationTool", "");
647  generation_date_and_time_ = fmi_desc.attribute<std::string>("generationDateAndTime", "");
648  variable_naming_convention_ = fmi_desc.attribute<std::string>("variableNamingConvention", "");
649  if (fmi_major_ >= 3) {
650  number_of_event_indicators_ = 0; // In FMI 3: Obtain from binary
651  } else {
652  number_of_event_indicators_ = fmi_desc.attribute<casadi_int>("numberOfEventIndicators", 0);
653  }
654 
655  // Process DefaultExperiment
656  if (fmi_desc.has_child("DefaultExperiment")) {
657  import_default_experiment(fmi_desc["DefaultExperiment"]);
658  }
659 
660  // Process ModelExchange
661  bool has_model_exchange = false;
662  if (fmi_desc.has_child("ModelExchange")) {
663  has_model_exchange = true;
664  import_model_exchange(fmi_desc["ModelExchange"]);
665  }
666 
667  // Process ModelVariables
668  casadi_assert(fmi_desc.has_child("ModelVariables"), "Missing 'ModelVariables'");
669  import_model_variables(fmi_desc["ModelVariables"]);
670 
671  // Process model structure
672  if (fmi_desc.has_child("ModelStructure")) {
673  import_model_structure(fmi_desc["ModelStructure"]);
674  }
675 
676  // Is a symbolic representation available?
677  symbolic_ = false; // use DLL by default
678 
679  // Add symbolic binding equations
680  if (fmi_desc.has_child("equ:BindingEquations")) {
681  symbolic_ = true;
682  import_binding_equations(fmi_desc["equ:BindingEquations"]);
683  }
684 
685  // Add symbolic initial equations
686  if (fmi_desc.has_child("equ:InitialEquations")) {
687  symbolic_ = true;
688  import_initial_equations(fmi_desc["equ:InitialEquations"]);
689  }
690 
691  // Add symbolic dynamic equations
692  if (fmi_desc.has_child("equ:DynamicEquations")) {
693  symbolic_ = true;
694  import_dynamic_equations(fmi_desc["equ:DynamicEquations"]);
695  }
696 
697  // Ensure model equations are available, binary or symbolic
698  casadi_assert(symbolic_ || has_model_exchange,
699  "FMU must be of ModelExchange type or be symbolic (FMUX)");
700 }
void import_model_structure(const XmlNode &n)
void import_dynamic_equations(const XmlNode &eqs)
void import_model_variables(const XmlNode &modvars)
void import_model_exchange(const XmlNode &n)
void import_initial_equations(const XmlNode &eqs)
void import_default_experiment(const XmlNode &n)
void import_binding_equations(const XmlNode &eqs)
static bool is_enabled()
Definition: filesystem.cpp:83
static bool exists(const std::string &path)
Definition: filesystem.cpp:144
std::string filename(const std::string &path)
Definition: ghc.cpp:55

References casadi::XmlNode::attribute(), author_, copyright_, description_, casadi::Filesystem::exists(), casadi::filename(), fmi_major_, fmi_version_, generation_date_and_time_, generation_tool_, casadi::XmlNode::has_child(), import_binding_equations(), import_default_experiment(), import_dynamic_equations(), import_initial_equations(), import_model_exchange(), import_model_structure(), import_model_variables(), instantiation_token_, casadi::Filesystem::is_enabled(), license_, model_name_, n_variables(), number_of_event_indicators_, casadi::XmlFile::parse(), symbolic_, and variable_naming_convention_.

◆ n_mem()

size_t casadi::DaeBuilderInternal::n_mem ( ) const

Definition at line 1616 of file dae_builder_internal.cpp.

1616  {
1617  size_t n = 0;
1618  for (const Variable* v : variables_) n += v->numel;
1619  return n;
1620 }

References variables_.

Referenced by generate_wrapper().

◆ n_variables()

size_t casadi::DaeBuilderInternal::n_variables ( ) const
inline

◆ name() [1/2]

std::vector< std::string > casadi::DaeBuilderInternal::name ( const std::vector< size_t > &  ind) const

Extra doc: https://github.com/casadi/casadi/wiki/L_2bw

Definition at line 3997 of file dae_builder_internal.cpp.

3997  {
3998  std::vector<std::string> r(ind.size());
3999  for (size_t i = 0; i < r.size(); ++i) r[i] = name(ind[i]);
4000  return r;
4001 }

References name().

◆ name() [2/2]

const std::string & casadi::DaeBuilderInternal::name ( size_t  ind) const

◆ new_variable()

Variable & casadi::DaeBuilderInternal::new_variable ( const std::string &  name,
const std::vector< casadi_int > &  dimension = {1},
const MX expr = MX() 
)

Definition at line 1622 of file dae_builder_internal.cpp.

1623  {
1624  // Name check
1625  casadi_assert(!name.empty(), "Name is empty string");
1626  // Try to find the component
1627  casadi_assert(!has(name), "Variable \"" + name + "\" already exists.");
1628  // Index of the variable
1629  size_t ind = n_variables();
1630  // Add to the map of all variables
1631  varind_[name] = ind;
1632  variables_.push_back(new Variable(ind, name, dimension, expr));
1633  // Clear cache
1634  clear_cache_ = true;
1635  // Return reference to new variable
1636  return *variables_.back();
1637 }
bool has(const std::string &name) const
Check if a particular variable exists.

References clear_cache_, has(), n_variables(), name(), Variable, variables_, and varind_.

Referenced by add(), lift(), and read_expr().

◆ oracle()

const Function & casadi::DaeBuilderInternal::oracle ( bool  sx = false,
bool  elim_w = false,
bool  lifted_calls = false 
) const

Definition at line 2250 of file dae_builder_internal.cpp.

2250  {
2251  casadi_assert(symbolic_, "DaeBuilder oracle only available if symbolic representation");
2252 
2253  // Clear cache now, if necessary
2254  if (clear_cache_) clear_cache();
2255  // Create an MX oracle, if needed
2256  if (oracle_[false][elim_w][lifted_calls].is_null()) {
2257  // Oracle function inputs and outputs
2258  std::vector<MX> f_in, f_out, v;
2259  std::vector<std::string> f_in_name, f_out_name;
2260  // Index for wdef
2261  casadi_int wdef_ind = -1;
2262  // Options consistency check
2263  casadi_assert(!(elim_w && lifted_calls), "Incompatible options");
2264  // Do we need to substitute out v
2265  bool subst_v = false;
2266  // Collect all DAE input variables
2267  for (Category cat : input_categories()) {
2268  v = input(cat);
2269  if (elim_w && cat == Category::W) {
2270  if (!v.empty()) subst_v = true;
2271  } else {
2272  if (v.empty()) {
2273  f_in.push_back(MX(0, 1));
2274  } else {
2275  f_in.push_back(vertcat(v));
2276  }
2277  f_in_name.push_back(to_string(cat));
2278  }
2279  }
2280 
2281  // Collect all DAE output variables
2282  for (OutputCategory cat : output_categories()) {
2283  f_out_name.push_back(to_string(cat));
2284  v = output(cat);
2285  if (v.empty()) {
2286  f_out.push_back(MX(0, 1));
2287  } else {
2288  if (cat == OutputCategory::WDEF) wdef_ind = f_out.size();
2289  f_out.push_back(vertcat(v));
2290  }
2291  }
2292  // Eliminate v from inputs
2293  if (subst_v) {
2294  // Dependent variable definitions
2295  std::vector<MX> wdef = output(OutputCategory::WDEF);
2296  // Perform in-place substitution
2297  substitute_inplace(var(Category::W), wdef, f_out, false);
2298  } else if (lifted_calls && wdef_ind >= 0) {
2299  // Dependent variable definitions
2300  std::vector<MX> wdef = output(OutputCategory::WDEF);
2301  // Remove references to call nodes
2302  for (MX& wdefref : wdef) {
2303  if (wdefref.is_output()) wdefref = MX::zeros(wdefref.sparsity());
2304  }
2305  // Save to oracle outputs
2306  f_out.at(wdef_ind) = vertcat(wdef);
2307  }
2308  // Create oracle
2309  oracle_[false][elim_w][lifted_calls]
2310  = Function("mx_oracle", f_in, f_out, f_in_name, f_out_name);
2311  }
2312  // Return MX oracle, if requested
2313  if (!sx) return oracle_[false][elim_w][lifted_calls];
2314  // Create SX oracle, if needed
2315  Function& sx_oracle = oracle_[true][elim_w][lifted_calls];
2316  if (sx_oracle.is_null()) sx_oracle = oracle_[false][elim_w][lifted_calls].expand("sx_oracle");
2317  // Return SX oracle reference
2318  return sx_oracle;
2319 }
void clear_cache() const
Problem structure has changed: Clear cache.
Function expand() const
Expand a function to SX.
Definition: function.cpp:308
std::vector< Category > input_categories()

References clear_cache(), clear_cache_, casadi::Function::expand(), input(), casadi::input_categories(), casadi::GenericShared< Shared, Internal >::is_null(), oracle_, output(), casadi::output_categories(), symbolic_, casadi::to_string(), var(), casadi::W, casadi::WDEF, and casadi::GenericMatrix< MX >::zeros().

Referenced by create(), transition(), and update_dependencies().

◆ output() [1/2]

std::vector< MX > casadi::DaeBuilderInternal::output ( const std::vector< OutputCategory > &  ind) const

Definition at line 1895 of file dae_builder_internal.cpp.

1895  {
1896  std::vector<MX> ret(ind.size());
1897  for (casadi_int i=0; i<ind.size(); ++i) {
1898  ret[i] = vertcat(output(ind[i]));
1899  }
1900  return ret;
1901 }

References output().

◆ output() [2/2]

std::vector< MX > casadi::DaeBuilderInternal::output ( OutputCategory  ind) const

Definition at line 1847 of file dae_builder_internal.cpp.

1847  {
1848  // If defined by index set
1849  switch (ind) {
1850  case OutputCategory::Y:
1851  return var(outputs_);
1852  case OutputCategory::ZERO:
1853  return var(event_indicators_);
1854  case OutputCategory::ALG:
1855  return var(residuals_);
1856  case OutputCategory::RATE:
1857  return var(rate_);
1858  default: break;
1859  }
1860  // Otherwise: Defined by corresponding input category
1861  Category cat = input_category(ind);
1862 
1863  // Return object
1864  std::vector<MX> ret;
1865  ret.reserve(size(cat));
1866  // Handle different categories
1867  switch (ind) {
1868  case OutputCategory::ODE: // fall-through
1869  case OutputCategory::QUAD:
1870  // Differential state
1871  for (size_t v : indices(cat)) {
1872  const Variable& x = variable(v);
1873  if (x.der >= 0) {
1874  // Derivative variable
1875  ret.push_back(variable(variable(x.der).bind).v);
1876  } else if (x.variability == Variability::DISCRETE) {
1877  // Discrete variable - derivative is zero
1878  ret.push_back(MX::zeros(x.v.sparsity()));
1879  } else {
1880  // Missing ODE?
1881  casadi_error("Missing derivative for " + str(x.name));
1882  }
1883  }
1884  break;
1885  case OutputCategory::DDEF: // fall-through
1886  case OutputCategory::WDEF:
1887  // Defined by binding expression
1888  for (size_t d : indices(cat)) ret.push_back(variable(variable(d).bind).v);
1889  break;
1890  default: break;
1891  }
1892  return ret;
1893 }
Category input_category(OutputCategory cat)

References casadi::ALG, casadi::Variable::bind, casadi::DDEF, casadi::Variable::der, casadi::DISCRETE, event_indicators_, indices(), casadi::input_category(), casadi::Variable::name, casadi::ODE, outputs_, casadi::QUAD, casadi::RATE, rate_, residuals_, size(), casadi::MX::sparsity(), casadi::str(), casadi::Variable::v, var(), casadi::Variable::variability, variable(), casadi::WDEF, casadi::Y, casadi::ZERO, and casadi::GenericMatrix< MX >::zeros().

Referenced by add_fun(), create(), dependent_fun(), eliminate(), gather_eq(), jac_vdef_v_from_calls(), oracle(), output(), prune(), sort(), and transition().

◆ prune()

void casadi::DaeBuilderInternal::prune ( bool  prune_p,
bool  prune_u 
)

Definition at line 1393 of file dae_builder_internal.cpp.

1393  {
1394  // Function inputs and outputs
1395  std::vector<MX> f_in, f_out, v;
1396  std::vector<std::string> f_in_name, f_out_name;
1397  // Collect all DAE input variables with at least one entry, skip u
1398  for (Category cat : input_categories()) {
1399  if (prune_p && cat == Category::P) continue;
1400  if (prune_u && cat == Category::U) continue;
1401  v = input(cat);
1402  if (!v.empty()) {
1403  f_in.push_back(vertcat(v));
1404  f_in_name.push_back(to_string(cat));
1405  }
1406  }
1407  // Collect all DAE output variables with at least one entry
1408  for (OutputCategory cat : output_categories()) {
1409  v = output(cat);
1410  if (!v.empty()) {
1411  f_out.push_back(vertcat(v));
1412  f_out_name.push_back(to_string(cat));
1413  }
1414  }
1415  // Create a function
1416  Function f("prune_fcn", f_in, f_out, f_in_name, f_out_name);
1417  // Mark which variables are free
1418  std::vector<bool> free_variables(n_variables(), false);
1419  for (const std::string& s : f.get_free()) {
1420  auto it = varind_.find(s);
1421  casadi_assert(it != varind_.end(), "No such variable: \"" + s + "\".");
1422  free_variables.at(it->second) = true;
1423  }
1424  // Prune p
1425  if (prune_p) {
1426  size_t np = 0;
1427  for (size_t i = 0; i < size(Category::P); ++i) {
1428  if (!free_variables.at(indices(Category::P).at(i))) {
1429  indices(Category::P).at(np++) = indices(Category::P).at(i);
1430  }
1431  }
1432  indices(Category::P).resize(np);
1433  }
1434  // Prune u
1435  if (prune_u) {
1436  size_t nu = 0;
1437  std::vector<size_t>& u = indices(Category::U);
1438  for (size_t i = 0; i < u.size(); ++i) {
1439  if (!free_variables.at(u.at(i))) u.at(nu++) = u.at(i);
1440  }
1441  u.resize(nu);
1442  }
1443 }

References casadi::Function::get_free(), indices(), input(), casadi::input_categories(), n_variables(), output(), casadi::output_categories(), casadi::P, size(), casadi::to_string(), casadi::U, and varind_.

◆ qualified_name()

std::string casadi::DaeBuilderInternal::qualified_name ( const XmlNode nn,
Attribute att = 0 
)
staticprotected

Definition at line 1647 of file dae_builder_internal.cpp.

1647  {
1648  // std::stringstream to assemble name
1649  std::stringstream qn;
1650  bool first_part = true;
1651  if (att) *att = Attribute::VALUE; // value attribute by default
1652 
1653  // Loop over name parts
1654  for (casadi_int i=0; i<nn.size(); ++i) {
1655  // Get the name part
1656  std::string np = nn[i].attribute<std::string>("name");
1657 
1658  // Check if an attribute
1659  if (np == "$START") {
1660  if (att) {
1661  *att = Attribute::START;
1662  } else {
1663  casadi_error("Ignoring attribute " + np);
1664  }
1665  continue;
1666  } else if (np == "$PRE") {
1667  casadi_warning("$PRE attribute has not been implemented, ignoring");
1668  continue;
1669  }
1670 
1671  // Add the name part to the variable name
1672  if (!first_part) qn << ".";
1673  qn << np;
1674 
1675  // Get the index, if any
1676  if (nn[i].size()>0) {
1677  casadi_int ind;
1678  nn[i]["exp:ArraySubscripts"]["exp:IndexExpression"]["exp:IntegerLiteral"].get(&ind);
1679  qn << "[" << ind << "]";
1680  }
1681 
1682  // Dot prefix if a additional parts
1683  first_part = false;
1684  }
1685 
1686  // Return the name
1687  return qn.str();
1688 }

References casadi::XmlNode::attribute(), casadi::XmlNode::get(), casadi::XmlNode::size(), size(), casadi::START, and casadi::VALUE.

Referenced by read_expr(), and read_variable().

◆ read_dependencies()

std::vector< casadi_int > casadi::DaeBuilderInternal::read_dependencies ( const XmlNode n)
protected

Definition at line 3519 of file dae_builder_internal.cpp.

3519  {
3520  // Default behaviour should be no known structure
3521  casadi_assert(n.has_attribute("dependencies"),
3522  "Default 'dependencies' not implemented");
3523  // Read list of dependencies
3524  std::vector<casadi_int> r = n.attribute<std::vector<casadi_int>>("dependencies", {});
3525  // Get corresponding variable index
3526  for (casadi_int& e : r) {
3527  if (fmi_major_ >= 3) {
3528  // Value reference is given
3529  e = vrmap_.at(static_cast<unsigned int>(e));
3530  } else {
3531  // Index-1 is given
3532  e--;
3533  }
3534  }
3535  // Return list of dependencies
3536  return r;
3537 }

References casadi::XmlNode::attribute(), fmi_major_, casadi::XmlNode::has_attribute(), and vrmap_.

Referenced by import_model_structure().

◆ read_dependencies_kind()

std::vector< DependenciesKind > casadi::DaeBuilderInternal::read_dependencies_kind ( const XmlNode n,
size_t  ndep 
)
protected

Definition at line 3539 of file dae_builder_internal.cpp.

3540  {
3541  // Quick return if node not provided
3542  if (!n.has_attribute("dependenciesKind")) {
3543  // No structure known, assume general dependency
3544  return std::vector<DependenciesKind>(ndep, DependenciesKind::DEPENDENT);
3545  } else {
3546  // Read list of strings
3547  auto dk_str = n.attribute<std::vector<std::string>>("dependenciesKind");
3548  // Make sure expected length
3549  casadi_assert(dk_str.size() == ndep, "Mismatching 'dependenciesKind'");
3550  // Convert to enums
3551  std::vector<DependenciesKind> r(ndep);
3552  for (size_t i = 0; i < ndep; ++i) {
3553  r[i] = to_enum<DependenciesKind>(dk_str[i]);
3554  }
3555  return r;
3556  }
3557 }

References casadi::XmlNode::attribute(), casadi::DEPENDENT, and casadi::XmlNode::has_attribute().

Referenced by import_model_structure().

◆ read_expr()

MX casadi::DaeBuilderInternal::read_expr ( const XmlNode node)
protected

Definition at line 1089 of file dae_builder_internal.cpp.

1089  {
1090  try {
1091  const std::string& fullname = node.name;
1092 
1093  if (fullname == "fun:If") {
1094  // Expression for condition, if and else
1095  const XmlNode& cond = node["fun:Condition"];
1096  const XmlNode& then_stmt = node["fun:Statements"];
1097  const XmlNode& else_stmt = node["fun:Else"];
1098  // Only scalar expression implemented
1099  casadi_assert(cond.size() == 1, "Only one condition in if expression supported");
1100  casadi_assert(then_stmt.size() == 1, "Only one then statement in if expression supported");
1101  casadi_assert(else_stmt.size() == 1, "Only one else statement in if expression supported");
1102  return if_else(read_expr(cond[0]), read_expr(then_stmt[0]), read_expr(else_stmt[0]));
1103  }
1104 
1105  if (fullname.find("exp:")== std::string::npos) {
1106  casadi_error("DaeBuilderInternal::read_expr: unknown - expression is supposed to "
1107  "start with 'exp:' , got " + fullname);
1108  }
1109 
1110  // Chop the 'exp:'
1111  std::string name = fullname.substr(4);
1112 
1113  // The switch below is alphabetical, and can be thus made more efficient,
1114  // for example by using a switch statement of the first three letters,
1115  // if it would ever become a bottleneck
1116  if (name=="Add") {
1117  return read_expr(node[0]) + read_expr(node[1]);
1118  } else if (name=="Acos") {
1119  return acos(read_expr(node[0]));
1120  } else if (name=="Asin") {
1121  return asin(read_expr(node[0]));
1122  } else if (name=="Atan") {
1123  return atan(read_expr(node[0]));
1124  } else if (name=="Cos") {
1125  return cos(read_expr(node[0]));
1126  } else if (name=="Der") {
1127  return variable(read_variable(node[0]).der_of).v;
1128  } else if (name=="Div") {
1129  return read_expr(node[0]) / read_expr(node[1]);
1130  } else if (name=="Exp") {
1131  return exp(read_expr(node[0]));
1132  } else if (name=="Identifier") {
1133  return read_identifier(node);
1134  } else if (name=="IntegerLiteral" || name=="BooleanLiteral") {
1135  casadi_int val;
1136  node.get(&val);
1137  return val;
1138  } else if (name=="Instant") {
1139  double val;
1140  node.get(&val);
1141  return val;
1142  } else if (name=="Log") {
1143  return log(read_expr(node[0]));
1144  } else if (name=="Not") { // Logical not
1145  return !read_expr(node[0]);
1146  } else if (name=="LogLeq") { // Logical less than equal
1147  return read_expr(node[0]) <= read_expr(node[1]);
1148  } else if (name=="LogGeq") { // Logical greater than equal
1149  return read_expr(node[0]) >= read_expr(node[1]);
1150  } else if (name=="LogLt") { // Logical less than
1151  return read_expr(node[0]) < read_expr(node[1]);
1152  } else if (name=="LogGt") { // Logical greater than
1153  return read_expr(node[0]) > read_expr(node[1]);
1154  } else if (name=="Max") {
1155  return fmax(read_expr(node[0]), read_expr(node[1]));
1156  } else if (name=="Min") {
1157  return fmin(read_expr(node[0]), read_expr(node[1]));
1158  } else if (name=="Mul") { // Multiplication
1159  return read_expr(node[0]) * read_expr(node[1]);
1160  } else if (name=="Neg") {
1161  return -read_expr(node[0]);
1162  } else if (name=="NoEvent") {
1163  // NOTE: This is a workaround, we assume that whenever NoEvent occurs,
1164  // what is meant is a switch
1165  casadi_int n = node.size();
1166 
1167  // Default-expression
1168  MX ex = read_expr(node[n-1]);
1169 
1170  // Evaluate ifs
1171  for (casadi_int i=n-3; i>=0; i -= 2) {
1172  ex = if_else(read_expr(node[i]), read_expr(node[i+1]), ex);
1173  }
1174 
1175  return ex;
1176  } else if (name=="Pow") {
1177  return pow(read_expr(node[0]), read_expr(node[1]));
1178  } else if (name=="Pre") {
1179  casadi_warning("Ignoring pre attribute");
1180  return read_expr(node[0]);
1181  } else if (name=="RealLiteral") {
1182  double val;
1183  node.get(&val);
1184  return val;
1185  } else if (name=="Sin") {
1186  return sin(read_expr(node[0]));
1187  } else if (name=="Sqrt") {
1188  return sqrt(read_expr(node[0]));
1189  } else if (name=="StringLiteral") {
1190  casadi_error(node.text);
1191  } else if (name=="Sub") {
1192  return read_expr(node[0]) - read_expr(node[1]);
1193  } else if (name=="Tan") {
1194  return tan(read_expr(node[0]));
1195  } else if (name=="Time") {
1196  return var(indices(Category::T).at(0));
1197  } else if (name=="TimedVariable") {
1198  return read_variable(node[0]).v;
1199  } else if (name=="FunctionCall") {
1200  // Get the name of the function
1201  std::string fname = qualified_name(node["exp:Name"]);
1202  casadi_warning("Function call to '" + fname + "' incomplete");
1203  // Collect the arguments
1204  const XmlNode& args = node["exp:Arguments"];
1205  std::vector<MX> farg(args.size());
1206  for (casadi_int i = 0; i < args.size(); ++i) {
1207  // Lift input arguments
1208  Variable& v = new_variable("w_" + str(size(Category::W)));
1209  // Add to list of variables
1210  indices(Category::W).push_back(v.index);
1211  // Set binding expression
1212  Variable& v_beq = assign(v.name, read_expr(args[i]));
1213  v.bind = v_beq.index;
1214  // Add to list of function arguments
1215  farg[i] = v.v;
1216  }
1217  // Return argument (scalar for now)
1218  Variable& r = new_variable("w_" + str(size(Category::W)));
1219  // Add to list of variables
1220  indices(Category::W).push_back(r.index);
1221  // Return output variable
1222  return r.v;
1223  } else if (name=="Array") {
1224  // Array of arguments
1225  std::vector<MX> v(node.size());
1226  for (casadi_int i = 0; i < v.size(); ++i) v[i] = read_expr(node[i]);
1227  return vertcat(v);
1228  }
1229 
1230  // throw error if reached this point
1231  casadi_error("Unknown node: " + name);
1232  } catch (std::exception& e) {
1233  THROW_ERROR_NODE("read_expr", node, e.what());
1234  return {};
1235  }
1236 }
static std::string qualified_name(const XmlNode &nn, Attribute *att=0)
Get the qualified name.
double if_else(double x, double y, double z)
Definition: calculus.hpp:290

References assign(), casadi::Variable::bind, casadi::XmlNode::get(), casadi::if_else(), casadi::Variable::index, indices(), casadi::Variable::name, name(), casadi::XmlNode::name, new_variable(), qualified_name(), read_identifier(), read_variable(), casadi::XmlNode::size(), size(), casadi::str(), casadi::T, casadi::XmlNode::text, casadi::Variable::v, var(), variable(), and casadi::W.

Referenced by import_binding_equations(), import_dynamic_equations(), and import_initial_equations().

◆ read_identifier()

MX casadi::DaeBuilderInternal::read_identifier ( const XmlNode node)
protected

Definition at line 1076 of file dae_builder_internal.cpp.

1076  {
1077  Attribute att; // attribute
1078  Variable& v = read_variable(node, &att);
1079  if (att == Attribute::VALUE) {
1080  return v.v;
1081  } else if (att == Attribute::START) {
1082  return v.start;
1083  } else {
1084  casadi_error("Cannot read attribute " + to_string(att));
1085  return MX();
1086  }
1087 }

References read_variable(), casadi::START, casadi::Variable::start, casadi::to_string(), casadi::Variable::v, and casadi::VALUE.

Referenced by import_dynamic_equations(), and read_expr().

◆ read_variable()

Variable & casadi::DaeBuilderInternal::read_variable ( const XmlNode node,
Attribute att = 0 
)
protected

Definition at line 1064 of file dae_builder_internal.cpp.

1064  {
1065  try {
1066  // Qualified name
1067  std::string qn = qualified_name(node, att);
1068 
1069  return variable(qn);
1070  } catch (std::exception& e) {
1071  THROW_ERROR_NODE("read_variable", node, e.what());
1072  //return {};
1073  }
1074 }

References qualified_name(), and variable().

Referenced by import_binding_equations(), import_dynamic_equations(), import_initial_equations(), read_expr(), and read_identifier().

◆ reinit()

Variable & casadi::DaeBuilderInternal::reinit ( const std::string &  name,
const MX val 
)
protected

Definition at line 3247 of file dae_builder_internal.cpp.

3247  {
3248  // Create a unique name for the reinit variable
3249  std::string reinit_name = unique_name("__reinit__" + name + "__");
3250  // Add a new dependent variable defined by val
3251  Variable& v = add(reinit_name, Causality::LOCAL, Variability::CONTINUOUS, val, Dict());
3252  // Classify as a defined variable
3253  categorize(v.index, Category::CALCULATED);
3254  v.parent = variable(name).index;
3255  // Return the variable name
3256  return v;
3257 }

References add(), casadi::CALCULATED, categorize(), casadi::CONTINUOUS, casadi::Variable::index, casadi::LOCAL, name(), casadi::Variable::parent, unique_name(), and variable().

Referenced by import_dynamic_equations().

◆ remove()

void casadi::DaeBuilderInternal::remove ( std::vector< size_t > &  v,
size_t  ind 
) const
protected

Definition at line 2931 of file dae_builder_internal.cpp.

2931  {
2932  for (auto it = v.begin(); it != v.end(); ++it) {
2933  if (*it == ind) {
2934  v.erase(it);
2935  return;
2936  }
2937  }
2938  casadi_error("Variable not found");
2939 }

Referenced by categorize(), and set_causality().

◆ reorder() [1/2]

void casadi::DaeBuilderInternal::reorder ( Category  cat,
const std::vector< size_t > &  v 
)

Definition at line 1374 of file dae_builder_internal.cpp.

1374  {
1375  return reorder(to_string(cat), indices(cat), v);
1376 }
void reorder(Category cat, const std::vector< size_t > &v)
Reorder variables in a category.

References indices(), and casadi::to_string().

◆ reorder() [2/2]

void casadi::DaeBuilderInternal::reorder ( const std::string &  n,
std::vector< size_t > &  ind,
const std::vector< size_t > &  v 
) const

Definition at line 1378 of file dae_builder_internal.cpp.

1379  {
1380  // Check if the sizes match
1381  casadi_assert(ind.size() == v.size(), "Cannot reorder " + n + ": "
1382  + str(v.size()) + " elements provided for " + str(ind.size()) + " components.");
1383  // Mark elements to be set
1384  std::vector<bool> set(n_variables(), false);
1385  for (size_t i : v) set.at(i) = true;
1386  // Make sure all elements are present
1387  for (size_t i : ind) casadi_assert(set.at(i), "Cannot reorder " + n + ": "
1388  + variable(i).name + " is missing.");
1389  // Set the new order
1390  std::copy(v.begin(), v.end(), ind.begin());
1391 }

References n_variables(), name(), casadi::str(), and variable().

◆ reset()

void casadi::DaeBuilderInternal::reset ( )
protected

Definition at line 4049 of file dae_builder_internal.cpp.

4049  {
4050  for (Variable* v : variables_) {
4051  std::fill(v->value.begin(), v->value.end(), nan);
4052  v->stringvalue = std::string();
4053  }
4054 }

References casadi::nan, and variables_.

◆ sanity_check()

void casadi::DaeBuilderInternal::sanity_check ( ) const

Definition at line 1639 of file dae_builder_internal.cpp.

1639  {
1640  // Time
1641  if (size(Category::T) > 0) {
1642  casadi_assert(size(Category::T) == 1, "At most one time variable allowed");
1643  casadi_assert(variable(Category::T, 0).v.is_scalar(), "Non-scalar time t");
1644  }
1645 }

References size(), casadi::T, and variable().

Referenced by add_lc(), and disp().

◆ set_attribute() [1/2]

void casadi::DaeBuilderInternal::set_attribute ( Attribute  a,
const std::string &  name,
double  val 
)
protected

Set by attribute name

Definition at line 4076 of file dae_builder_internal.cpp.

4076  {
4077  variable(name).set_attribute(a, val);
4078 }
void set_attribute(Attribute a, double val)

References name(), casadi::Variable::set_attribute(), and variable().

◆ set_attribute() [2/2]

void casadi::DaeBuilderInternal::set_attribute ( Attribute  a,
const std::vector< std::string > &  name,
const std::vector< double > &  val 
)
protected

Set by attribute name

Definition at line 4080 of file dae_builder_internal.cpp.

4081  {
4082  if (name.size() == val.size()) {
4083  // One scalar value per variable
4084  for (size_t k = 0; k < name.size(); ++k) variable(name[k]).set_attribute(a, val[k]);
4085  } else if (val.size() == size(a, name)) {
4086  // One vector slice per variable
4087  auto val_it = val.begin();
4088  for (size_t k = 0; k < name.size(); ++k) {
4089  Variable& v = variable(name[k]);
4090  auto val_next = val_it + v.size(a);
4091  v.set_attribute(a, std::vector<double>(val_it, val_next));
4092  val_it = val_next;
4093  }
4094  } else {
4095  casadi_error("Cannot set attribute " + to_string(a) + ": Argument is of length " +
4096  str(val.size()) + ", expected number of elements (" + str(size(a, name))
4097  + ") or number of variables (" + str(name.size()) + ")");
4098  }
4099 }

References name(), casadi::Variable::set_attribute(), casadi::Variable::size(), size(), casadi::str(), casadi::to_string(), and variable().

◆ set_category()

void casadi::DaeBuilderInternal::set_category ( size_t  ind,
Category  cat 
)
protected

Definition at line 3038 of file dae_builder_internal.cpp.

3038  {
3039  // Get variable reference
3040  Variable& v = variable(ind);
3041  // Quick return if same category
3042  if (v.category == cat) return;
3043  // Update category: See comment for public interface
3044  switch (cat) {
3045  case Category::U:
3046  if (v.category == Category::P || v.category == Category::C) {
3047  return set_variability(v.index, Variability::CONTINUOUS);
3048  }
3049  break;
3050  case Category::P:
3051  if (v.category == Category::U || v.category == Category::C) {
3052  return set_variability(v.index, Variability::TUNABLE);
3053  }
3054  break;
3055  case Category::C:
3056  if (v.category == Category::U || v.category == Category::P) {
3057  return set_variability(v.index, Variability::FIXED);
3058  }
3059  break;
3060  case Category::X:
3061  if (v.category == Category::Q && !v.in_rhs) {
3062  return categorize(v.index, Category::X);
3063  }
3064  break;
3065  case Category::Q:
3066  if (v.category == Category::X) {
3067  return categorize(v.index, Category::Q);
3068  }
3069  break;
3070  default:
3071  break;
3072  }
3073  // Failure if reached this point
3074  casadi_error("Cannot change category of " + v.name + " from '"
3075  + to_string(v.category) + "' to '" + to_string(cat) + "'");
3076 }
void set_variability(size_t ind, Variability variability)
Set variability.

References casadi::C, categorize(), casadi::Variable::category, casadi::CONTINUOUS, casadi::FIXED, casadi::Variable::in_rhs, casadi::Variable::index, casadi::Variable::name, casadi::P, casadi::Q, set_variability(), casadi::to_string(), casadi::TUNABLE, casadi::U, variable(), and casadi::X.

Referenced by eliminate().

◆ set_causality()

void casadi::DaeBuilderInternal::set_causality ( size_t  ind,
Causality  causality 
)
protected

Definition at line 2945 of file dae_builder_internal.cpp.

2945  {
2946  // Get variable reference
2947  Variable& v = variable(ind);
2948  // Quick return if same causality
2949  if (v.causality == causality) return;
2950  // Handle permitted changes
2951  if (v.causality == Causality::LOCAL && causality == Causality::OUTPUT) {
2952  // Add to list of outputs
2953  insert(outputs_, v.index);
2954  } else if (v.causality == Causality::OUTPUT && causality == Causality::LOCAL) {
2955  // Remove from list of outputs
2956  remove(outputs_, v.index);
2957  } else {
2958  // Not possible
2959  casadi_error("Cannot change causality of " + v.name + " which is of category '"
2960  + to_string(v.category) + "'");
2961  }
2962  // Success: Update causality
2963  v.causality = causality;
2964  // The oracle would need to be regenerated after changes to the categorization
2965  clear_cache_ = true;
2966 }

References casadi::Variable::category, casadi::Variable::causality, causality(), clear_cache_, casadi::Variable::index, insert(), casadi::LOCAL, casadi::Variable::name, casadi::OUTPUT, outputs_, remove(), casadi::to_string(), and variable().

◆ set_init()

void casadi::DaeBuilderInternal::set_init ( const std::string &  name,
const MX init_rhs 
)
protected

Definition at line 3259 of file dae_builder_internal.cpp.

3259  {
3260  // Find the algebraic variable
3261  Variable& v = variable(name);
3262  // If variable already has an initial binding equation, remove it
3263  if (!v.ieq.is_empty()) {
3264  // Remove from list of initial equations
3265  auto old_loc = std::find(init_.begin(), init_.end(), v.index);
3266  if (old_loc == init_.end()) casadi_error("Corrupted list of initial equations");
3267  init_.erase(old_loc);
3268  v.ieq = MX();
3269  }
3270  // If right-hand-side is empty, just erase
3271  if (init_rhs.is_empty()) return;
3272 
3273  // Make sure not already in list of initial equations
3274  if (std::find(init_.begin(), init_.end(), v.index) != init_.end()) {
3275  casadi_error("Initial equation for " + name + " has already been set");
3276  }
3277  // Add to list of initial equations
3278  init_.push_back(v.index);
3279  v.ieq = init_rhs;
3280 }
std::vector< MX > init_rhs() const
Initial conditions, right-hand-side.

References casadi::Variable::ieq, casadi::Variable::index, init_, init_rhs(), casadi::GenericMatrix< MatType >::is_empty(), name(), and variable().

Referenced by import_initial_equations().

◆ set_string_attribute() [1/2]

void casadi::DaeBuilderInternal::set_string_attribute ( Attribute  a,
const std::string &  name,
const std::string &  val 
)
protected

Set by attribute name (string-valued)

Definition at line 4122 of file dae_builder_internal.cpp.

4123  {
4124  variable(name).set_attribute(a, val);
4125 }

References name(), casadi::Variable::set_attribute(), and variable().

◆ set_string_attribute() [2/2]

void casadi::DaeBuilderInternal::set_string_attribute ( Attribute  a,
const std::vector< std::string > &  name,
const std::vector< std::string > &  val 
)
protected

Set by attribute name (string-valued)

Definition at line 4127 of file dae_builder_internal.cpp.

4128  {
4129  casadi_assert(name.size() == val.size(), "Dimension mismatch");
4130  for (size_t k = 0; k < name.size(); ++k) variable(name[k]).set_attribute(a, val[k]);
4131 }

References name(), casadi::Variable::set_attribute(), and variable().

◆ set_variability()

void casadi::DaeBuilderInternal::set_variability ( size_t  ind,
Variability  variability 
)
protected

Definition at line 2972 of file dae_builder_internal.cpp.

2972  {
2973  // Get variable reference
2974  Variable& v = variable(ind);
2975  // Quick return if same variability
2976  if (v.variability == variability) return;
2977  // Update category: See comment for public interface
2978  switch (v.category) {
2979  case Category::U:
2981  // Make fixed parameter
2982  categorize(v.index, Category::C);
2983  v.causality = Causality::PARAMETER;
2984  } else if (variability == Variability::TUNABLE) {
2985  // Make tunable parameter
2986  categorize(v.index, Category::P);
2987  v.causality = Causality::PARAMETER;
2988  } else {
2989  // Not possible
2990  casadi_error("The variability of " + v.name + ", which is of category 'u', can only be "
2991  "changed to 'fixed' (for no category) or 'tunable' (for category 'p')");
2992  }
2993  break;
2994  case Category::P:
2996  // Make input
2997  categorize(v.index, Category::U);
2998  v.causality = Causality::INPUT;
2999  } else if (variability == Variability::FIXED) {
3000  // Make fixed parameter
3001  categorize(v.index, Category::C);
3002  v.causality = Causality::PARAMETER;
3003  } else {
3004  // Not possible
3005  casadi_error("The variability of " + v.name + ", which is of category 'p', can only be "
3006  "changed to 'continuous' (for category 'u') or 'fixed' (for no category)");
3007  }
3008  break;
3009  case Category::C:
3011  // Make input
3012  categorize(v.index, Category::U);
3013  v.causality = Causality::INPUT;
3014  } else if (variability == Variability::TUNABLE) {
3015  // Make tunable parameter
3016  categorize(v.index, Category::P);
3017  v.causality = Causality::PARAMETER;
3018  } else {
3019  // Not possible
3020  casadi_error("The variability of " + v.name + ", which is of type 'c', can only be "
3021  "changed to 'continuous' (for category 'u') or 'tunable' (for category 'p')");
3022  }
3023  break;
3024  default:
3025  casadi_error("Cannot change variability of " + v.name + ", which is of category '"
3026  + to_string(v.category) + "'");
3027  }
3028  // Success: Update variability
3029  v.variability = variability;
3030  // The oracle would need to be regenerated after changes to the categorization
3031  clear_cache_ = true;
3032 }

References casadi::C, categorize(), casadi::Variable::category, casadi::Variable::causality, clear_cache_, casadi::CONTINUOUS, casadi::FIXED, casadi::Variable::index, casadi::INPUT, casadi::Variable::name, casadi::P, casadi::PARAMETER, casadi::to_string(), casadi::TUNABLE, casadi::U, casadi::Variable::variability, variability(), and variable().

Referenced by set_category().

◆ shared_from_this() [1/2]

B casadi::GenericSharedInternal< SharedObject , SharedObjectInternal >::shared_from_this ( )
inlineprotectedinherited

Definition at line 83 of file generic_shared_internal.hpp.

83  {
84  casadi_assert_dev(B::test_cast(static_cast<Internal*>(this)));
85  B ret;
86  ret.own(static_cast<Internal*>(this));
87  return ret;
88  }

◆ shared_from_this() [2/2]

const B casadi::GenericSharedInternal< SharedObject , SharedObjectInternal >::shared_from_this ( ) const
inlineprotectedinherited

Definition at line 92 of file generic_shared_internal.hpp.

92  {
93  casadi_assert_dev(B::test_cast(static_cast<const Internal*>(this)));
94  B ret;
95  ret.own(const_cast<Internal*>(static_cast<const Internal*>(this)));
96  return ret;
97  }

◆ size() [1/2]

casadi_int casadi::DaeBuilderInternal::size ( Attribute  a,
const std::vector< std::string > &  name 
) const
protected

Definition at line 4133 of file dae_builder_internal.cpp.

4133  {
4134  casadi_int r = 0;
4135  for (auto& n : name) r += variable(n).size(a);
4136  return r;
4137 }
casadi_int size(Attribute a) const
Total number of elements for a particular attribute.

References name(), casadi::Variable::size(), and variable().

◆ size() [2/2]

size_t casadi::DaeBuilderInternal::size ( Category  cat) const
inline

◆ sort()

void casadi::DaeBuilderInternal::sort ( Category  cat)

Definition at line 1337 of file dae_builder_internal.cpp.

1337  {
1338  casadi_assert(is_acyclic(cat), "Sorting not supported for category " + to_string(cat));
1339  // Find new order based on interdependencies
1340  std::vector<MX> v = var(indices(cat)), vdef = output(dependent_definition(cat));
1341  sort_dependent(v, vdef);
1342  // New order
1343  std::vector<size_t> new_order;
1344  for (const MX& e : v) new_order.push_back(find(e.name()));
1345  std::copy(new_order.begin(), new_order.end(), indices(cat).begin());
1346 }
static void sort_dependent(std::vector< MX > &v, std::vector< MX > &vdef)

References casadi::dependent_definition(), find(), indices(), casadi::is_acyclic(), output(), sort_dependent(), casadi::to_string(), and var().

Referenced by eliminate().

◆ sort_dependent()

void casadi::DaeBuilderInternal::sort_dependent ( std::vector< MX > &  v,
std::vector< MX > &  vdef 
)
staticprotected

Definition at line 2396 of file dae_builder_internal.cpp.

2396  {
2397  // Form function to evaluate dependent variables
2398  Function vfcn("vfcn", {vertcat(v)}, {vertcat(vdef)}, {"v"}, {"vdef"},
2399  Dict{{"allow_free", true}});
2400  // Is any variable vector-valued?
2401  bool any_vector_valued = false;
2402  for (const MX& v_i : v) {
2403  casadi_assert(!v_i.is_empty(), "Cannot have zero-dimension dependent variables");
2404  if (!v_i.is_scalar()) {
2405  any_vector_valued = true;
2406  break;
2407  }
2408  }
2409  // If vector-valued variables exists, collapse them
2410  if (any_vector_valued) {
2411  // New v corresponding to one scalar input per v argument
2412  std::vector<MX> vfcn_in(v), vfcn_arg(v);
2413  for (size_t i = 0; i < v.size(); ++i) {
2414  if (!v.at(i).is_scalar()) {
2415  vfcn_in.at(i) = MX::sym(v.at(i).name());
2416  vfcn_arg.at(i) = repmat(vfcn_in.at(i), v.at(i).size1());
2417  }
2418  }
2419  // Wrap vfcn
2420  std::vector<MX> vfcn_out = vfcn(vertcat(vfcn_arg));
2421  vfcn_out = vertsplit(vfcn_out.at(0), offset(v));
2422  // Collapse vector-valued outputs
2423  for (size_t i = 0; i < v.size(); ++i) {
2424  if (!v.at(i).is_scalar()) {
2425  vfcn_out.at(i) = dot(vfcn_out.at(i), vfcn_out.at(i));
2426  }
2427  }
2428  // Recreate vfcn with smaller dimensions
2429  vfcn = Function(vfcn.name(), {vertcat(vfcn_in)}, {vertcat(vfcn_out)},
2430  vfcn.name_in(), vfcn.name_out(), {{"allow_free", true}});
2431  }
2432  // Calculate sparsity pattern of dvdef/dv
2433  Sparsity Jv = vfcn.jac_sparsity(0, 0);
2434  // Add diagonal (equation is v-vdef = 0)
2435  Jv = Jv + Sparsity::diag(Jv.size1());
2436  // If lower triangular, nothing to do
2437  if (Jv.is_triu()) return;
2438  // Perform a Dulmage-Mendelsohn decomposition
2439  std::vector<casadi_int> rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock;
2440  (void)Jv.btf(rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock);
2441  // Reorder the variables
2442  std::vector<MX> tmp(v.size());
2443  for (size_t k = 0; k < v.size(); ++k) tmp[k] = v.at(colperm.at(k));
2444  std::copy(tmp.begin(), tmp.end(), v.begin());
2445  // Reorder the equations
2446  for (size_t k = 0; k < v.size(); ++k) tmp[k] = vdef.at(rowperm.at(k));
2447  std::copy(tmp.begin(), tmp.end(), vdef.begin());
2448 }
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
Definition: sparsity.hpp:190
T dot(const std::vector< T > &a, const std::vector< T > &b)

References casadi::dot(), and casadi::GenericMatrix< MX >::sym().

Referenced by sort().

◆ sort_z()

void casadi::DaeBuilderInternal::sort_z ( const std::vector< std::string > &  z_order)

Definition at line 1348 of file dae_builder_internal.cpp.

1348  {
1349  // Make sure lengths agree
1350  casadi_assert(z_order.size() == size(Category::Z), "Dimension mismatch");
1351  // Mark existing components in z
1352  std::vector<bool> old_z(n_variables(), false);
1353  for (size_t i : indices(Category::Z)) old_z.at(i) = true;
1354  // New vector of z
1355  std::vector<size_t> new_z;
1356  new_z.reserve(z_order.size());
1357  for (const std::string& s : z_order) {
1358  size_t i = find(s);
1359  casadi_assert(old_z.at(i), "Variable \"" + s + "\" is not an algebraic variable.");
1360  new_z.push_back(i);
1361  }
1362  // Success: Update z
1363  std::copy(new_z.begin(), new_z.end(), indices(Category::Z).begin());
1364 }

References find(), indices(), n_variables(), size(), and casadi::Z.

◆ start_all()

std::vector< double > casadi::DaeBuilderInternal::start_all ( ) const

Definition at line 977 of file dae_builder_internal.cpp.

977  {
978  std::vector<double> r;
979  for (const Variable* v : variables_) {
980  for (double s : v->start) r.push_back(s);
981  }
982  return r;
983 }

References variables_.

Referenced by generate_wrapper().

◆ string_attribute() [1/2]

std::string casadi::DaeBuilderInternal::string_attribute ( Attribute  a,
const std::string &  name 
) const
protected

Get by attribute name (string-valued)

Definition at line 4101 of file dae_builder_internal.cpp.

4102  {
4103  std::string r;
4104  variable(name).get_attribute(a, &r);
4105  return r;
4106 }

References casadi::Variable::get_attribute(), name(), and variable().

◆ string_attribute() [2/2]

std::vector< std::string > casadi::DaeBuilderInternal::string_attribute ( Attribute  a,
const std::vector< std::string > &  name 
) const
protected

Get by attribute name (string-valued)

Definition at line 4108 of file dae_builder_internal.cpp.

4109  {
4110  // Allocate return
4111  std::vector<std::string> r;
4112  r.reserve(size(a, name));
4113  // Get contribution from each variable
4114  std::string r1;
4115  for (auto& n : name) {
4116  variable(n).get_attribute(a, &r1);
4117  r.push_back(r1);
4118  }
4119  return r;
4120 }

References casadi::Variable::get_attribute(), name(), size(), and variable().

◆ tear()

void casadi::DaeBuilderInternal::tear ( )

Definition at line 1445 of file dae_builder_internal.cpp.

1445  {
1446  // Prefix
1447  const std::string res_prefix = "res__";
1448  // Get residual variables, iteration variables
1449  std::vector<std::string> res, iv, iv_on_hold;
1450  tearing_variables(&res, &iv, &iv_on_hold);
1451  // All iteration variables
1452  std::set<std::string> iv_set;
1453  for (auto& e : iv) iv_set.insert(e);
1454  for (auto& e : iv_on_hold) iv_set.insert(e);
1455  // Remove any (held or not held) iteration variables, equations from z and alg
1456  size_t sz = 0;
1457  for (size_t k = 0; k < size(Category::Z); ++k) {
1458  if (!iv_set.count(variable(Category::Z, k).name)) {
1459  // Non-iteration variable: Keep
1460  indices(Category::Z).at(k) = indices(Category::Z).at(sz);
1461  sz++;
1462  }
1463  }
1464  indices(Category::Z).resize(sz);
1465  // Remove any (held or not held) iteration variables, equations from u
1466  sz = 0;
1467  for (size_t k = 0; k < size(Category::U); ++k) {
1468  if (!iv_set.count(variable(Category::U, k).name)) {
1469  // Non-iteration variable: Keep
1470  indices(Category::U).at(k) = indices(Category::U).at(sz++);
1471  }
1472  }
1473  indices(Category::U).resize(sz);
1474  // Add algebraic variables
1475  for (auto& e : iv) indices(Category::Z).push_back(find(e));
1476  // Add output variables
1477  for (auto& e : iv_on_hold) indices(Category::U).push_back(find(e));
1478 }
void tearing_variables(std::vector< std::string > *res, std::vector< std::string > *iv, std::vector< std::string > *iv_on_hold) const
Identify free variables and residual equations.

References find(), indices(), name(), size(), tearing_variables(), casadi::U, variable(), and casadi::Z.

◆ tearing_variables()

void casadi::DaeBuilderInternal::tearing_variables ( std::vector< std::string > *  res,
std::vector< std::string > *  iv,
std::vector< std::string > *  iv_on_hold 
) const

Definition at line 1480 of file dae_builder_internal.cpp.

1481  {
1482  // Clear output
1483  if (res) res->clear();
1484  if (iv) iv->clear();
1485  if (iv_on_hold) iv_on_hold->clear();
1486  // Prefix
1487  const std::string res_prefix = "res__";
1488  // Collect hold indices
1489  std::vector<MX> r_hold, iv_hold;
1490  // Any hold variable?
1491  bool any_hold = false;
1492  // Collect residual variables, iteration variables, expression for hold indices, if any
1493  for (const Variable* v : variables_) {
1494  // Residual variables are specified with a "res__" prefix
1495  if (v->name.rfind(res_prefix, 0) == 0) {
1496  // Process iteration variable name, names of hold markers
1497  std::string iv_name, res_hold_name, iv_hold_name;
1498  // Iteration variable, hold markers are contained in the remainder of the name
1499  try {
1500  size_t pos = res_prefix.size();
1501  // Find the next "__", if any
1502  size_t end = v->name.find("__", pos);
1503  if (end == std::string::npos) end = v->name.size();
1504  // Look up iteration variable
1505  iv_name = v->name.substr(pos, end - pos);
1506  // Ensure that the variable exists
1507  casadi_assert(has(iv_name), "No such variable: " + iv_name);
1508  // Get hold indices, if any
1509  if (end != v->name.size()) {
1510  // Find next "__", read hold index for residual variable
1511  pos = end + 2;
1512  end = v->name.find("__", pos);
1513  if (end == std::string::npos) end = v->name.size();
1514  res_hold_name = v->name.substr(pos, end - pos);
1515  // Ensure that the variable exists
1516  casadi_assert(has(res_hold_name), "No such variable: " + res_hold_name);
1517  // The remainder of the name contains iv_hold_name
1518  if (end != v->name.size()) {
1519  iv_hold_name = v->name.substr(end + 2);
1520  casadi_assert(has(iv_hold_name), "No such variable: " + iv_hold_name);
1521  }
1522  }
1523  } catch (std::exception& e) {
1524  // Generate warning
1525  casadi_warning("Cannot process residual variable: " + v->name + ":" +
1526  std::string(e.what()));
1527  continue;
1528  }
1529  // Add residual variable, corresponding hold variable
1530  if (res_hold_name.empty()) {
1531  r_hold.push_back(false);
1532  } else {
1533  any_hold = true;
1534  r_hold.push_back(variable(res_hold_name).v);
1535  casadi_assert(r_hold.back().is_scalar(), "Non-scalar hold variable for " + res_hold_name);
1536  }
1537  if (res) res->push_back(v->name);
1538  // Add iteration variable, corresponding hold variable
1539  if (iv_hold_name.empty()) {
1540  iv_hold.push_back(false);
1541  } else {
1542  any_hold = true;
1543  iv_hold.push_back(variable(iv_hold_name).v);
1544  casadi_assert(iv_hold.back().is_scalar(), "Non-scalar hold variable for " + iv_hold_name);
1545  }
1546  if (iv) iv->push_back(iv_name);
1547  }
1548  }
1549  // Evaluate hold variables, if needed
1550  if (any_hold) {
1551  try {
1552  // Code below needs to be refactored
1553  casadi_error("not implemented");
1554 #if 0
1555  // Get start attributes for p
1556  Function startfun_p = attribute_fun("startfun_p", {}, {"start_p"});
1557  if (startfun_p.has_free()) {
1558  casadi_error("startfun has free variables: " + str(startfun_p.get_free()));
1559  }
1560  DM p0 = startfun_p(std::vector<DM>{}).at(0);
1561  // Create function to evaluate the hold attributes
1562  Function holdfun("holdfun", {vertcat(var(p_))},
1563  {vertcat(r_hold), vertcat(iv_hold)}, {"p"}, {"r_hold", "iv_hold"});
1564  if (holdfun.has_free()) {
1565  casadi_error("holdfun has free variables: " + str(holdfun.get_free()));
1566  }
1567  // Evaluate holdfun to get hold attributes
1568  std::vector<DM> hold0 = holdfun(std::vector<DM>{p0});
1569  std::vector<double> r_hold0 = hold0.at(0).nonzeros();
1570  std::vector<double> iv_hold0 = hold0.at(1).nonzeros();
1571  casadi_assert_dev(r_hold0.size() == res->size());
1572  casadi_assert_dev(iv_hold0.size() == iv->size());
1573  // Remove hold variables from residual variables
1574  size_t sz = 0;
1575  if (res) {
1576  for (size_t k = 0; k < res->size(); ++k) {
1577  if (!static_cast<bool>(r_hold0.at(k))) {
1578  res->at(sz++) = res->at(k);
1579  }
1580  }
1581  res->resize(sz);
1582  }
1583  // Remove hold variables from iteration variables
1584  sz = 0;
1585  for (size_t k = 0; k < iv->size(); ++k) {
1586  if (!static_cast<bool>(iv_hold0.at(k))) {
1587  if (iv) iv->at(sz++) = iv->at(k);
1588  } else {
1589  if (iv_on_hold) iv_on_hold->push_back(iv->at(k));
1590  }
1591  }
1592  if (iv) iv->resize(sz);
1593 #endif
1594  } catch (std::exception& e) {
1595  // Warning instead of error
1596  casadi_warning("Failed to evaluate hold variables: " + std::string(e.what()));
1597  }
1598  }
1599 }
Matrix< double > DM
Definition: dm_fwd.hpp:33

References casadi::Function::get_free(), has(), casadi::Function::has_free(), casadi::str(), var(), variable(), and variables_.

Referenced by tear().

◆ time()

const MX & casadi::DaeBuilderInternal::time ( ) const
protected

Definition at line 2678 of file dae_builder_internal.cpp.

2678  {
2679  casadi_assert(has_t(), "No explicit time variable");
2680  return var(indices(Category::T).at(0));
2681 }

References has_t(), indices(), casadi::T, and var().

Referenced by generate_guid().

◆ transition() [1/2]

Function casadi::DaeBuilderInternal::transition ( const std::string &  fname) const

Definition at line 2556 of file dae_builder_internal.cpp.

2556  {
2557  // If no events, return null
2558  if (when_.empty()) return Function();
2559 
2560  // If just a single event, create an event function with a dummy index input
2561  if (when_.size() == 1) return transition(fname, 0, true);
2562 
2563  // Create separate transition functions for each event
2564  std::vector<Function> f_all;
2565  for (casadi_int i = 0; i < when_.size(); ++i) {
2566  f_all.push_back(transition(fname + "_" + str(i), i));
2567  }
2568 
2569  // Make the last function the default value in the switch
2570  Function f_def = f_all.back();
2571  f_all.pop_back();
2572 
2573  // Create a switch function
2574  return Function::conditional(fname, f_all, f_def);
2575 }
static Function conditional(const std::string &name, const std::vector< Function > &f, const Function &f_def, const Dict &opts=Dict())
Constuct a switch function.
Definition: function.cpp:765

References casadi::Function::conditional(), casadi::str(), transition(), and when_.

◆ transition() [2/2]

Function casadi::DaeBuilderInternal::transition ( const std::string &  fname,
casadi_int  index,
bool  dummy_index_input = false 
) const

Definition at line 2508 of file dae_builder_internal.cpp.

2509  {
2510 
2511  // Make sure that the index is valid
2512  casadi_assert(index >= 0 && index < when_.size(), "Illegal event index");
2513 
2514  // Get input expressions for the oracle
2515  std::vector<MX> oracle_in = oracle().mx_in();
2516 
2517  // Input expressions for the event functions, without the index
2518  std::vector<MX> ret_in(DYN_NUM_IN);
2519  ret_in[DYN_T] = oracle_in.at(static_cast<size_t>(Category::T));
2520  ret_in[DYN_X] = oracle_in.at(static_cast<size_t>(Category::X));
2521  ret_in[DYN_Z] = oracle_in.at(static_cast<size_t>(Category::Z));
2522  ret_in[DYN_P] = oracle_in.at(static_cast<size_t>(Category::P));
2523  ret_in[DYN_U] = oracle_in.at(static_cast<size_t>(Category::U));
2524 
2525  // When equation left-hand sides and right-hand sides
2526  std::vector<MX> when_lhs, when_rhs;
2527  for (size_t eq : when_.at(index).second) {
2528  auto v = variable(eq).parent;
2529  when_lhs.push_back(variable(v).v);
2530  when_rhs.push_back(variable(eq).v);
2531  }
2532 
2533  // Expressions for x and z after event
2534  std::vector<MX> ret_out = {ret_in[DYN_X], ret_in[DYN_Z]};
2535  ret_out = MX::substitute(ret_out, when_lhs, when_rhs);
2536 
2537  // Remove dependent variables, if any
2538  if (size(Category::W) > 0) {
2539  // Dependent variable definitions
2540  std::vector<MX> wdef = output(OutputCategory::WDEF);
2541  // Perform in-place substitution
2542  substitute_inplace(var(Category::W), wdef, ret_out, false);
2543  }
2544 
2545  // Check if a dummy index input needes to be included
2546  if (dummy_index_input) {
2547  // Create a function with the transition input signature
2548  ret_in.insert(ret_in.begin(), MX());
2549  return Function(fname, ret_in, ret_out, event_in(), event_out());
2550  } else {
2551  // Create a function with the DAE function input signature
2552  return Function(fname, ret_in, ret_out, dyn_in(), event_out());
2553  }
2554 }
static MX substitute(const MX &ex, const MX &v, const MX &vdef)
Definition: mx.cpp:1424
std::vector< std::string > event_in()
Get input scheme of an event transition function.
Definition: integrator.cpp:256
std::vector< std::string > event_out()
Get output scheme of an event transition functions.
Definition: integrator.cpp:260
@ DYN_NUM_IN
Definition: integrator.hpp:196

References casadi::dyn_in(), casadi::DYN_NUM_IN, casadi::DYN_P, casadi::DYN_T, casadi::DYN_U, casadi::DYN_X, casadi::DYN_Z, eq(), casadi::event_in(), casadi::event_out(), casadi::Function::mx_in(), oracle(), output(), casadi::P, casadi::Variable::parent, size(), casadi::MX::substitute(), casadi::T, casadi::U, var(), variable(), casadi::W, casadi::WDEF, when_, casadi::X, and casadi::Z.

Referenced by export_fmu(), and transition().

◆ type_name()

std::string casadi::DaeBuilderInternal::type_name ( ) const
inline

Definition at line 375 of file dae_builder_internal.hpp.

375 {return "DaeBuilderInternal";}

◆ unique_name()

std::string casadi::DaeBuilderInternal::unique_name ( const std::string &  prefix,
bool  allow_no_prefix = true 
) const

Definition at line 1724 of file dae_builder_internal.cpp.

1725  {
1726  // Check if the variable exists without any prefix
1727  if (allow_no_prefix && !has(prefix)) return prefix;
1728  // Find the first available index
1729  size_t i = 0;
1730  while (has(prefix + str(i))) i++;
1731  // Return the unique name
1732  return prefix + str(i);
1733 }

References has(), and casadi::str().

Referenced by assign(), eq(), reinit(), and when().

◆ update_dependencies()

void casadi::DaeBuilderInternal::update_dependencies ( ) const

Definition at line 856 of file dae_builder_internal.cpp.

856  {
857  // Get oracle function
858  const Function& oracle = this->oracle();
859  // Dependendencies of the ODE right-hand-side
860  Sparsity dode_dxT = oracle.jac_sparsity(oracle.index_out("ode"), oracle.index_in("x")).T();
861  Sparsity dode_duT = oracle.jac_sparsity(oracle.index_out("ode"), oracle.index_in("u")).T();
862  for (casadi_int i = 0; i < size(Category::X); ++i) {
863  // Get output variable
864  const Variable& xdot = variable(variable(Category::X, i).der);
865  // Clear dependencies
866  xdot.dependencies.clear();
867  // Dependencies on states
868  for (casadi_int k = dode_dxT.colind(i); k < dode_dxT.colind(i + 1); ++k) {
869  casadi_int j = dode_dxT.row(k);
870  xdot.dependencies.push_back(variable(Category::X, j).value_reference);
871  }
872  // Dependencies on controls
873  for (casadi_int k = dode_duT.colind(i); k < dode_duT.colind(i + 1); ++k) {
874  casadi_int j = dode_duT.row(k);
875  xdot.dependencies.push_back(variable(Category::U, j).value_reference);
876  }
877  }
878  // Dependendencies of the outputs and event indicators
879  for (std::string catname : {"y", "zero"}) {
880  const std::vector<size_t>& oind = catname == "y" ? outputs_ : event_indicators_;
881  Sparsity dy_dxT = oracle.jac_sparsity(oracle.index_out(catname), oracle.index_in("x")).T();
882  Sparsity dy_duT = oracle.jac_sparsity(oracle.index_out(catname), oracle.index_in("u")).T();
883  for (casadi_int i = 0; i < oind.size(); ++i) {
884  // Get output variable
885  const Variable& y = variable(oind.at(i));
886  // Clear dependencies
887  y.dependencies.clear();
888  // Dependencies on states
889  for (casadi_int k = dy_dxT.colind(i); k < dy_dxT.colind(i + 1); ++k) {
890  casadi_int j = dy_dxT.row(k);
891  y.dependencies.push_back(variable(Category::X, j).value_reference);
892  }
893  // Dependencies on controls
894  for (casadi_int k = dy_duT.colind(i); k < dy_duT.colind(i + 1); ++k) {
895  casadi_int j = dy_duT.row(k);
896  y.dependencies.push_back(variable(Category::U, j).value_reference);
897  }
898  }
899  }
900 }
casadi_int index_in(const std::string &name) const
Find the index for a string describing a particular entry of an input scheme.
Definition: function.cpp:969
casadi_int index_out(const std::string &name) const
Find the index for a string describing a particular entry of an output scheme.
Definition: function.cpp:977
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity of all Jacobian blocks.
Definition: function.cpp:940

References casadi::Sparsity::colind(), casadi::Variable::dependencies, der(), event_indicators_, casadi::Function::index_in(), casadi::Function::index_out(), casadi::Function::jac_sparsity(), oracle(), outputs_, casadi::Sparsity::row(), size(), casadi::U, variable(), and casadi::X.

Referenced by export_fmu().

◆ var() [1/5]

std::vector<MX> casadi::DaeBuilderInternal::var ( Category  cat) const
inline

Definition at line 446 of file dae_builder_internal.hpp.

446 {return var(indices(cat));}

References var().

Referenced by var().

◆ var() [2/5]

const MX& casadi::DaeBuilderInternal::var ( Category  cat,
size_t  ind 
) const
inline

Definition at line 440 of file dae_builder_internal.hpp.

440 {return var(indices(cat).at(ind));}

References var().

Referenced by var().

◆ var() [3/5]

const MX & casadi::DaeBuilderInternal::var ( const std::string &  name) const

◆ var() [4/5]

std::vector< MX > casadi::DaeBuilderInternal::var ( const std::vector< size_t > &  ind) const

Definition at line 3956 of file dae_builder_internal.cpp.

3956  {
3957  std::vector<MX> ret;
3958  ret.reserve(ind.size());
3959  for (size_t i : ind) ret.push_back(var(i));
3960  return ret;
3961 }

References var().

◆ var() [5/5]

const MX & casadi::DaeBuilderInternal::var ( size_t  ind) const

Definition at line 3952 of file dae_builder_internal.cpp.

3952  {
3953  return variable(ind).v;
3954 }

References casadi::Variable::v, and variable().

◆ variability()

Variability casadi::DaeBuilderInternal::variability ( size_t  ind) const
protected

Definition at line 2968 of file dae_builder_internal.cpp.

2968  {
2969  return variable(ind).variability;
2970 }

References casadi::Variable::variability, and variable().

Referenced by add(), default_initial(), import_model_variables(), and set_variability().

◆ variable() [1/8]

Variable& casadi::DaeBuilderInternal::variable ( Category  cat,
size_t  ind 
)
inline

Access a variable by Category and index

Definition at line 418 of file dae_builder_internal.hpp.

418 {return variable(indices(cat).at(ind));}

References variable().

Referenced by variable().

◆ variable() [2/8]

const Variable& casadi::DaeBuilderInternal::variable ( Category  cat,
size_t  ind 
) const
inline

Access a variable by Category and index

Definition at line 419 of file dae_builder_internal.hpp.

419  {
420  return variable(indices(cat).at(ind));
421  }

◆ variable() [3/8]

Variable& casadi::DaeBuilderInternal::variable ( const MX v)
inline

Access a variable by expression

Definition at line 432 of file dae_builder_internal.hpp.

432 {return variable(find(v));}

References casadi::find(), and variable().

Referenced by variable().

◆ variable() [4/8]

const Variable& casadi::DaeBuilderInternal::variable ( const MX v) const
inline

Access a variable by expression

Definition at line 433 of file dae_builder_internal.hpp.

433 {return variable(find(v));}

References casadi::find(), and variable().

Referenced by variable().

◆ variable() [5/8]

Variable& casadi::DaeBuilderInternal::variable ( const std::string &  name)
inline

Access a variable by name

Definition at line 426 of file dae_builder_internal.hpp.

426 {return variable(find(name));}

References casadi::find(), and variable().

Referenced by variable().

◆ variable() [6/8]

const Variable& casadi::DaeBuilderInternal::variable ( const std::string &  name) const
inline

Access a variable by name

Definition at line 427 of file dae_builder_internal.hpp.

427 {return variable(find(name));}

References casadi::find(), and variable().

Referenced by variable().

◆ variable() [7/8]

Variable& casadi::DaeBuilderInternal::variable ( size_t  ind)
inline

◆ variable() [8/8]

const Variable& casadi::DaeBuilderInternal::variable ( size_t  ind) const
inline

Access a variable by index

Definition at line 413 of file dae_builder_internal.hpp.

413 {return *variables_.at(ind);}

◆ weak()

Extra doc: https://github.com/casadi/casadi/wiki/L_1ai

Definition at line 67 of file generic_shared_internal.hpp.

191  {
192  if (weak_ref_==nullptr) {
193  weak_ref_ = new GenericWeakRef<Shared, Internal>(static_cast<Internal*>(this));
194  }
195  return weak_ref_;
196  }

◆ when()

void casadi::DaeBuilderInternal::when ( const MX cond,
const std::vector< std::string > &  eqs,
const Dict opts 
)
protected

Definition at line 3200 of file dae_builder_internal.cpp.

3201  {
3202  // Read options
3203  for (auto&& op : opts) {
3204  casadi_error("No such option: " + op.first);
3205  }
3206  // Convert condition into a smooth zero crossing condition
3207  MX zero;
3208  if (cond.is_op(OP_LT)) {
3209  zero = cond.dep(0) - cond.dep(1); // Reformulate a < b to a - b < 0
3210  } else if (cond.is_op(OP_LE)) {
3211  casadi_error("Only strict inequality in zero-crossing conditions permitted, got: "
3212  + str(cond));
3213  } else {
3214  casadi_error("Cannot parse zero-crossing condition: " + str(cond));
3215  }
3216  // Create a new dependent variable for the event indicator
3218  zero, Dict());
3219  event_indicators_.push_back(e.index);
3220  categorize(e.index, Category::CALCULATED);
3221  // Convert to legacy format, pending refactoring
3222  std::vector<MX> all_lhs, all_rhs;
3223  std::vector<size_t> all_eqs;
3224  for (auto&& eq : eqs) {
3225  Variable& ee = variable(eq);
3226  casadi_assert_dev(ee.category == Category::CALCULATED);
3227  all_lhs.push_back(var(ee.parent));
3228  all_rhs.push_back(ee.v);
3229  all_eqs.push_back(ee.index);
3230  }
3231  when_.push_back(std::make_pair(e.index, all_eqs));
3232 }
@ OP_LT
Definition: calculus.hpp:70
@ OP_LE
Definition: calculus.hpp:70

References add(), casadi::CALCULATED, categorize(), casadi::Variable::category, casadi::CONTINUOUS, casadi::MX::dep(), eq(), event_indicators_, casadi::Variable::index, casadi::MX::is_op(), casadi::LOCAL, casadi::OP_LE, casadi::OP_LT, casadi::Variable::parent, casadi::str(), unique_name(), casadi::Variable::v, var(), variable(), and when_.

Referenced by import_dynamic_equations().

Friends And Related Function Documentation

◆ DaeBuilder

friend class DaeBuilder
friend

Definition at line 210 of file dae_builder_internal.hpp.

◆ FmuFunction

friend class FmuFunction
friend

Definition at line 212 of file dae_builder_internal.hpp.

Referenced by fmu_fun().

◆ FmuInternal

friend class FmuInternal
friend

Definition at line 211 of file dae_builder_internal.hpp.

◆ Variable

friend class Variable
friend

Definition at line 213 of file dae_builder_internal.hpp.

Referenced by new_variable().

Member Data Documentation

◆ author_

std::string casadi::DaeBuilderInternal::author_
protected

Definition at line 495 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ can_be_instantiated_only_once_per_process_

bool casadi::DaeBuilderInternal::can_be_instantiated_only_once_per_process_
protected

◆ clear_cache_

bool casadi::DaeBuilderInternal::clear_cache_
mutableprotected

◆ copyright_

std::string casadi::DaeBuilderInternal::copyright_
protected

Definition at line 496 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ debug_

bool casadi::DaeBuilderInternal::debug_
protected

◆ derivatives_

std::vector<size_t> casadi::DaeBuilderInternal::derivatives_
protected

Definition at line 532 of file dae_builder_internal.hpp.

Referenced by import_model_structure(), and import_model_variables().

◆ description_

std::string casadi::DaeBuilderInternal::description_
protected

Definition at line 494 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ detect_quad_

bool casadi::DaeBuilderInternal::detect_quad_
protected

◆ event_indicators_

std::vector<size_t> casadi::DaeBuilderInternal::event_indicators_
protected

◆ fmi_major_

casadi_int casadi::DaeBuilderInternal::fmi_major_
protected

◆ fmi_version_

std::string casadi::DaeBuilderInternal::fmi_version_
protected

Definition at line 491 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ fmutol_

double casadi::DaeBuilderInternal::fmutol_
protected

Definition at line 487 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and casadi::FmuInternal::init().

◆ fun_

std::vector<Function> casadi::DaeBuilderInternal::fun_
protected

Extra doc: https://github.com/casadi/casadi/wiki/L_11

Definition at line 644 of file dae_builder_internal.hpp.

Referenced by add_fun(), disp(), fun(), and has_fun().

◆ generation_date_and_time_

std::string casadi::DaeBuilderInternal::generation_date_and_time_
protected

Definition at line 499 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ generation_tool_

std::string casadi::DaeBuilderInternal::generation_tool_
protected

Definition at line 498 of file dae_builder_internal.hpp.

Referenced by casadi::FmuInternal::init(), and load_fmi_description().

◆ ignore_time_

bool casadi::DaeBuilderInternal::ignore_time_
protected

Definition at line 488 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and import_model_variables().

◆ indices_

std::vector<std::vector<size_t> > casadi::DaeBuilderInternal::indices_
protected

Definition at line 542 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and indices().

◆ init_

std::vector<size_t> casadi::DaeBuilderInternal::init_
protected

Definition at line 545 of file dae_builder_internal.hpp.

Referenced by disp(), init_lhs(), init_rhs(), and set_init().

◆ initial_unknowns_

std::vector<size_t> casadi::DaeBuilderInternal::initial_unknowns_
protected

Definition at line 532 of file dae_builder_internal.hpp.

Referenced by import_model_structure().

◆ instantiation_token_

std::string casadi::DaeBuilderInternal::instantiation_token_
protected

Definition at line 493 of file dae_builder_internal.hpp.

Referenced by casadi::FmuInternal::init(), and load_fmi_description().

◆ lc_

Function::AuxOut casadi::DaeBuilderInternal::lc_
protected

Definition at line 639 of file dae_builder_internal.hpp.

Referenced by add_lc(), and create().

◆ license_

std::string casadi::DaeBuilderInternal::license_
protected

Definition at line 497 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ model_identifier_

std::string casadi::DaeBuilderInternal::model_identifier_
protected

Definition at line 507 of file dae_builder_internal.hpp.

Referenced by import_model_exchange(), and casadi::FmuInternal::init().

◆ model_name_

std::string casadi::DaeBuilderInternal::model_name_
protected

Definition at line 492 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ name_

std::string casadi::DaeBuilderInternal::name_
protected

◆ number_of_event_indicators_

casadi_int casadi::DaeBuilderInternal::number_of_event_indicators_
protected

◆ oracle_

Function casadi::DaeBuilderInternal::oracle_[2][2][2]
mutableprotected

Extra doc: https://github.com/casadi/casadi/wiki/L_12

Definition at line 649 of file dae_builder_internal.hpp.

Referenced by clear_cache(), and oracle().

◆ outputs_

std::vector<size_t> casadi::DaeBuilderInternal::outputs_
protected

◆ provides_adjoint_derivatives_

bool casadi::DaeBuilderInternal::provides_adjoint_derivatives_
protected

◆ provides_directional_derivatives_

bool casadi::DaeBuilderInternal::provides_directional_derivatives_
protected

◆ rate_

std::vector<size_t> casadi::DaeBuilderInternal::rate_
protected

Definition at line 533 of file dae_builder_internal.hpp.

Referenced by fmu_fun(), and output().

◆ residuals_

std::vector<size_t> casadi::DaeBuilderInternal::residuals_
protected

Definition at line 532 of file dae_builder_internal.hpp.

Referenced by disp(), lift(), and output().

◆ resource_

Resource casadi::DaeBuilderInternal::resource_
protected

Definition at line 517 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and casadi::FmuInternal::init().

◆ source_files_

std::vector<std::string> casadi::DaeBuilderInternal::source_files_
protected

Definition at line 511 of file dae_builder_internal.hpp.

Referenced by import_model_exchange().

◆ start_time_

double casadi::DaeBuilderInternal::start_time_
protected

◆ step_size_

double casadi::DaeBuilderInternal::step_size_
protected

◆ stop_time_

double casadi::DaeBuilderInternal::stop_time_
protected

◆ symbolic_

bool casadi::DaeBuilderInternal::symbolic_
protected

Definition at line 520 of file dae_builder_internal.hpp.

Referenced by create(), DaeBuilderInternal(), load_fmi_description(), and oracle().

◆ tolerance_

double casadi::DaeBuilderInternal::tolerance_
protected

◆ variable_naming_convention_

std::string casadi::DaeBuilderInternal::variable_naming_convention_
protected

Definition at line 500 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ variables_

std::vector<Variable*> casadi::DaeBuilderInternal::variables_
protected

◆ varind_

std::unordered_map<std::string, size_t> casadi::DaeBuilderInternal::varind_
protected

Definition at line 536 of file dae_builder_internal.hpp.

Referenced by find(), has(), import_model_variables(), new_variable(), and prune().

◆ vrmap_

std::unordered_map<unsigned int, size_t> casadi::DaeBuilderInternal::vrmap_
protected

◆ when_

std::vector<std::pair<size_t, std::vector<size_t> > > casadi::DaeBuilderInternal::when_
protected

Definition at line 548 of file dae_builder_internal.hpp.

Referenced by disp(), import_dynamic_equations(), transition(), and when().


The documentation for this class was generated from the following files: