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 218 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< MX > inputs (Category ind) const
 
std::vector< MX > outputs (Category ind) const
 
std::vector< MX > inputs (const std::vector< Category > &ind) const
 
std::vector< MX > outputs (const std::vector< Category > &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 MX & var (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=false) 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...
 
Variable & new_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 MX & var (size_t ind) const
 Get variable expression by index. More...
 
const MX & var (Category cat, size_t ind) const
 Get variable expression by category and index. More...
 
std::vector< MX > var (const std::vector< size_t > &ind) const
 Get variable expressions by index. More...
 
std::vector< MX > var (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 Function & oracle (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...
 
Variable & variable (size_t ind)
 
const Variable & variable (size_t ind) const
 
Variable & variable (Category cat, size_t ind)
 
const Variable & variable (Category cat, size_t ind) const
 
Variable & variable (const std::string &name)
 
const Variable & variable (const std::string &name) const
 
Variable & variable (const MX &v)
 
const Variable & variable (const MX &v) const
 

Protected Member Functions

casadi_int convert_index (casadi_int index) const
 
bool has_t () const
 Is there a time variable? More...
 
const MX & time () const
 
std::vector< MX > cdef () const
 Definitions of dependent constants. More...
 
std::vector< MX > init_lhs () const
 Initial conditions, left-hand-side. More...
 
std::vector< MX > init_rhs () const
 Initial conditions, right-hand-side. More...
 
Variable & add (const std::string &name, Causality causality, Variability variability, const Dict &opts)
 Add a new variable. More...
 
Variable & add (const std::string &name, Causality causality, Variability variability, const MX &expr, const Dict &opts)
 Add a new variable, expression provided. More...
 
Variable & add (const std::string &name, Causality causality, const Dict &opts)
 Add a new variable, default variability. More...
 
Variable & add (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...
 
Variable & assign (const std::string &name, const MX &val)
 Assignment inside when-equations or if-else equations. More...
 
Variable & reinit (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...
 
Variable & read_variable (const XmlNode &node, Attribute *att=nullptr)
 Read a variable. More...
 
void import_default_experiment (const XmlNode &n)
 
std::vector< casadi_int > read_dependencies (const XmlNode &n)
 
std::vector< DependenciesKind > read_dependencies_kind (const XmlNode &n, size_t ndep)
 
void import_model_exchange (const XmlNode &n)
 
void import_model_variables (const XmlNode &modvars)
 Read ModelVariables. More...
 
void import_model_structure (const XmlNode &n)
 
XmlNode import_ls_dae (const std::string &lsdae)
 
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 ()
 
B 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=nullptr)
 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_
 
bool enable_ls_dae_
 
bool enable_ls_serialization_
 
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 nzero_
 
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_
 
casadi_int orig_time_index_
 
bool detect_quad_
 
casadi_int fmi_major_
 
std::vector< Variable * > variables_
 All variables. More...
 
std::vector< size_t > der_
 
std::vector< size_t > initial_unknowns_
 
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< Function > fun_
 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)
 
Dict export_fmu (const Dict &opts) const
 Export instance into an FMU (experimental) More...
 
Dict compile_fmu (const Dict &files, const Dict &opts) const
 Compile the sources produced by export_fmu, returning the augmented file map. More...
 
std::string pack_fmu (const Dict &files, const Dict &opts) const
 Pack files (from export_fmu / compile_fmu) into a single .fmu archive (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 (bool dae=false) 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 660 of file dae_builder_internal.cpp.

662  clear_cache_ = false;
663  nzero_ = 0;
667  symbolic_ = true;
668  detect_quad_ = false;
669  start_time_ = nan;
670  stop_time_ = nan;
671  tolerance_ = nan;
672  step_size_ = nan;
673  // Default options
674  debug_ = false;
675  fmutol_ = 0;
676  ignore_time_ = false;
677  enable_ls_dae_ = true;
679  // Read options
680  for (auto&& op : opts) {
681  if (op.first=="debug") {
682  debug_ = op.second;
683  } else if (op.first=="fmutol") {
684  fmutol_ = op.second;
685  } else if (op.first=="ignore_time") {
686  ignore_time_ = op.second;
687  } else if (op.first=="detect_quad") {
688  detect_quad_ = op.second;
689  } else if (op.first=="resource_serialize_mode") {
690  resource_.change_option("serialize_mode", op.second);
691  } else if (op.first=="enable_ls_dae") {
692  enable_ls_dae_ = op.second;
693  } else if (op.first=="enable_ls_serialization") {
694  enable_ls_serialization_ = op.second;
695  } else {
696  casadi_error("No such option: " + op.first);
697  }
698  }
700 }
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
static Resource open_resource(const std::string &path)
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_, enable_ls_dae_, enable_ls_serialization_, fmutol_, ignore_time_, indices_, casadi::nan, nzero_, provides_adjoint_derivatives_, provides_directional_derivatives_, resource_, start_time_, step_size_, stop_time_, symbolic_, and tolerance_.

◆ ~DaeBuilderInternal()

casadi::DaeBuilderInternal::~DaeBuilderInternal ( )
override

Definition at line 635 of file dae_builder_internal.cpp.

635  {
636  for (Variable* v : variables_) {
637  if (v) delete v;
638  }
639 }
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 3389 of file dae_builder_internal.cpp.

3389  {
3390  // Get type
3391  Type type = Type::FLOAT64;
3392  if (opts.find("type") != opts.end()) {
3393  type = to_enum<Type>(opts.at("type").to_string());
3394  }
3395 
3396  // Default variability per FMI 3.0.2, section 2.4.7.4
3397  return add(name, causality, default_variability(causality, type), opts);
3398 }
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 3202 of file dae_builder_internal.cpp.

3203  {
3204  // No expression provided
3205  return add(name, causality, variability, MX(), opts);
3206 }
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 3208 of file dae_builder_internal.cpp.

3209  {
3210  // We will require that an independent variable is always added first in the list of variables
3211  if (causality != Causality::INDEPENDENT && n_variables() == 0) {
3212  // Add a default time variable before adding other variables
3214  // Do not categorize in T by default
3215  categorize(t.index, Category::NUMEL);
3216  // Max value if automatically added
3217  t.value_reference = static_cast<unsigned int>(-1);
3218  // Set index to -1 to indicate that it has not (yet) been encountered
3219  orig_time_index_ = -1;
3220  }
3221 
3222  // Default options
3223  std::string description, type, initial, unit, display_unit;
3224  std::vector<casadi_int> dimension = {1};
3225  double min = -casadi::inf, max = casadi::inf, nominal = 1;
3226  std::vector<double> start;
3227  // Read options
3228  for (auto&& op : opts) {
3229  if (op.first=="dimension") {
3230  dimension = op.second.to_int_vector();
3231  } else if (op.first=="description") {
3232  description = op.second.to_string();
3233  } else if (op.first=="unit") {
3234  unit = op.second.to_string();
3235  } else if (op.first=="display_unit") {
3236  display_unit = op.second.to_string();
3237  } else if (op.first=="min") {
3238  min = op.second.to_double();
3239  } else if (op.first=="max") {
3240  max = op.second.to_double();
3241  } else if (op.first=="nominal") {
3242  nominal = op.second.to_double();
3243  } else if (op.first=="start") {
3244  if (op.second.can_cast_to(OT_DOUBLE)) {
3245  start.resize(1, op.second.to_double());
3246  } else {
3247  start = op.second.to_double_vector();
3248  }
3249  } else if (op.first=="type") {
3250  type = op.second.to_string();
3251  } else if (op.first=="initial") {
3252  initial = op.second.to_string();
3253  } else {
3254  casadi_error("No such option: " + op.first);
3255  }
3256  }
3257 
3258  // Independent variable is handled separately, to ensure it's always the first variable
3259  Variable* t_var = nullptr;
3261  if (n_variables() == 0) {
3262  // Independent variable declared as first model variable
3263  orig_time_index_ = 0;
3264  } else {
3265  // Independent variable already declared automatically
3266  casadi_assert(orig_time_index_ == -1, "Only one independent variable is permitted");
3267  orig_time_index_ = n_variables() - 1;
3268  // Pointer to existing time variable
3269  t_var = &variable(0);
3270  // Revert default value reference
3271  t_var->value_reference = 0;
3272  // Update its name, if needed
3273  if (t_var->name != name) {
3274  // Remove old name from varind_
3275  varind_.erase(t_var->name);
3276  // Update Variable instance
3277  t_var->name = name;
3278  t_var->v = casadi::MX::sym(name, t_var->v.sparsity());
3279  // Add new name to varind_
3280  varind_[t_var->name] = t_var->index;
3281  }
3282  }
3283  }
3284 
3285  // Create a new variable or use existing time variable
3286  Variable& v = t_var ? *t_var : new_variable(name, dimension, expr);
3287  v.description = description;
3288  if (!type.empty()) v.type = to_enum<Type>(type);
3289  v.causality = causality;
3290  v.variability = variability;
3291  if (!start.empty()) {
3292  // Start attribute length doesn't match variable dimension
3293  if (start.size() != v.numel) {
3294  casadi_assert(start.size() == 1, "'start' must be scalar or match the number of elements");
3295  start.resize(v.numel, start.back());
3296  }
3297  v.value = v.start = start;
3298  }
3299  if (!initial.empty()) {
3300  v.initial = to_enum<Initial>(initial);
3301  } else {
3302  v.initial = default_initial(causality, variability);
3303  }
3304  if (!unit.empty()) v.unit = unit;
3305  if (!display_unit.empty()) v.display_unit = display_unit;
3306  if (min != -casadi::inf) v.min = min;
3307  if (max != casadi::inf) v.max = max;
3308  v.nominal = nominal;
3309  // Handle different categories
3310  switch (causality) {
3311  case Causality::PARAMETER:
3312  // Parameter
3314  if (v.type == Type::FLOAT64 || v.type == Type::FLOAT32) {
3315  categorize(v.index, Category::P);
3316  } else {
3317  categorize(v.index, Category::C);
3318  }
3319  } else if (variability == Variability::FIXED) {
3320  categorize(v.index, Category::C);
3321  } else {
3322  casadi_error("'parameter' causality requires 'fixed' or 'tunable' variability");
3323  }
3324  break;
3327  "'calculatedParameter' causality requires 'fixed' or 'tunable' variability");
3328  categorize(v.index, Category::D);
3329  break;
3330  case Causality::INPUT:
3331  // Control
3332  casadi_assert(variability == Variability::CONTINUOUS
3334  "'input' causality requires 'continuous' or 'discrete' variability");
3335  categorize(v.index, Category::U);
3336  break;
3337  case Causality::OUTPUT:
3338  // Type determined by providing equation, unless discrete variability
3340  // Constant output
3341  categorize(v.index, Category::C);
3342  } else if (variability == Variability::DISCRETE) {
3343  // Discrete variables are considered states with zero derivatives
3345  } else if (variability == Variability::CONTINUOUS) {
3346  // Continuous variables are considered algebraic variables until given a defining equation
3347  categorize(v.index, Category::Z);
3348  } else {
3349  casadi_error("'output' causality requires 'constant', 'continuous' or "
3350  "'discrete' variability");
3351  }
3352  break;
3353  case Causality::LOCAL:
3354  // Type determined by providing equation, unless discrete variability
3356  // Constant local
3357  categorize(v.index, Category::C);
3358  } else if (variability == Variability::DISCRETE) {
3359  // Discrete variables are considered states with zero derivatives
3361  } else if (variability == Variability::CONTINUOUS) {
3362  // Continuous variables are considered algebraic variables until given a defining equation
3363  categorize(v.index, Category::Z);
3365  // Fixed or tunable local
3366  categorize(v.index, Category::D);
3367  } else {
3368  casadi_error("'output' causality requires 'constant', 'fixed', 'tunable', 'discrete' or "
3369  "'continuous' variability");
3370  }
3371  break;
3373  // Independent variable
3374  casadi_assert(variability == Variability::CONTINUOUS,
3375  "Independent variable must be continuous");
3376  categorize(v.index, Category::T);
3377  // Initialize value to start time
3378  v.set_attribute(Attribute::VALUE, start_time_);
3379  break;
3380  default:
3381  casadi_error("Unknown causality: " + to_string(causality));
3382  }
3383  // If an output, add to list of outputs
3384  if (causality == Causality::OUTPUT) indices(Category::Y).push_back(v.index);
3385  // Return variable reference
3386  return v;
3387 }
size_t n_variables() const
Length of variables array.
std::vector< size_t > & indices(Category cat)
Classified variable indices (mutable)
std::unordered_map< std::string, size_t > varind_
Find of variable by name.
Variable & variable(size_t ind)
static Initial default_initial(Causality causality, Variability variability)
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.
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
std::string description(Category v)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
const double inf
infinity
Definition: calculus.hpp:50
std::string to_string(TypeFmi2 v)

References add(), casadi::C, casadi::CALCULATED_PARAMETER, categorize(), casadi::Variable::causality, causality(), casadi::CONSTANT, casadi::CONTINUOUS, casadi::D, default_initial(), casadi::description(), casadi::Variable::description, detect_quad_, casadi::DISCRETE, casadi::Variable::display_unit, casadi::FIXED, casadi::FLOAT32, casadi::FLOAT64, casadi::INDEPENDENT, casadi::Variable::index, indices(), casadi::inf, casadi::Variable::initial, casadi::INPUT, casadi::LOCAL, casadi::Variable::max, casadi::Variable::min, n_variables(), casadi::Variable::name, name(), new_variable(), casadi::Variable::nominal, casadi::NUMEL, casadi::Variable::numel, orig_time_index_, casadi::OT_DOUBLE, casadi::OUTPUT, casadi::P, casadi::PARAMETER, casadi::Q, casadi::Variable::set_attribute(), casadi::MX::sparsity(), casadi::Variable::start, start_time_, casadi::GenericMatrix< MX >::sym(), casadi::T, casadi::to_string(), casadi::TUNABLE, casadi::Variable::type, casadi::U, casadi::Variable::unit, casadi::Variable::v, casadi::VALUE, casadi::Variable::value, casadi::Variable::value_reference, casadi::Variable::variability, variability(), variable(), varind_, casadi::X, casadi::Y, and casadi::Z.

◆ add() [4/4]

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

Definition at line 612 of file dae_builder_internal.hpp.

612  {
613  // Per FMI 3.0.2 specification, section 2.4.7.4: Default causality is LOCAL
614  return add(name, Causality::LOCAL, opts);
615  }

References casadi::LOCAL.

◆ add_fun() [1/2]

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

Definition at line 4633 of file dae_builder_internal.cpp.

4633  {
4634  casadi_assert(!has_fun(f.name()), "Function '" + f.name() + "' already exists");
4635  fun_.push_back(f);
4636  return f;
4637 }
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 4639 of file dae_builder_internal.cpp.

4641  {
4642  casadi_assert(!has_fun(name), "Function '" + name + "' already exists");
4643 
4644  // Dependent variable definitions
4645  std::vector<MX> wdef = outputs(Category::WDEF);
4646  // Get inputs
4647  std::vector<MX> arg_ex, res_ex;
4648  for (auto&& s : arg) arg_ex.push_back(var(s));
4649  for (auto&& s : res) {
4650  // Find the binding expression FIXME(@jaeandersson)
4651  casadi_int v_ind;
4652  for (v_ind = 0; v_ind < size(Category::W); ++v_ind) {
4653  if (s == variable(indices(Category::W).at(v_ind)).name) {
4654  res_ex.push_back(wdef.at(v_ind));
4655  break;
4656  }
4657  }
4658  casadi_assert(v_ind < size(Category::W), "Cannot find dependent '" + s + "'");
4659  }
4660  Function ret(name, arg_ex, res_ex, arg, res, opts);
4661  return add_fun(ret);
4662 }
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::vector< MX > outputs(Category ind) const
std::string name
Name of the variable.

References has_fun(), indices(), casadi::Variable::name, name(), outputs(), 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 2307 of file dae_builder_internal.cpp.

2307  {
2308  // Make sure object valid
2309  sanity_check();
2310 
2311  // Make sure name is valid
2312  casadi_assert(!name.empty(), "DaeBuilderInternal::add_lc: \"name\" is empty");
2313  for (std::string::const_iterator i=name.begin(); i!=name.end(); ++i) {
2314  casadi_assert(isalnum(*i),
2315  "DaeBuilderInternal::add_lc: \"name\" must be alphanumeric");
2316  }
2317 
2318  // Consistency checks
2319  casadi_assert(!f_out.empty(), "DaeBuilderInternal::add_lc: Linear combination is empty");
2320  std::vector<bool> in_use(enum_traits<Category>::n_enum, false);
2321  for (casadi_int i=0; i < f_out.size(); ++i) {
2322  auto oind = static_cast<size_t>(to_enum<Category>(f_out[i]));
2323  casadi_assert(!in_use[oind], "DaeBuilderInternal::add_lc: Duplicate expression " + f_out[i]);
2324  in_use[oind] = true;
2325  }
2326 
2327  std::vector<std::string>& ret1 = lc_[name];
2328  if (!ret1.empty()) casadi_warning("DaeBuilderInternal::add_lc: Overwriting " << name);
2329  ret1 = f_out;
2330 }
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 2029 of file dae_builder_internal.cpp.

2029  {
2030  std::vector<std::string> r;
2031  r.reserve(n_variables());
2032  for (const Variable* v : variables_) r.push_back(v->name);
2033  return r;
2034 }

References n_variables(), and variables_.

◆ all() [2/2]

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

Definition at line 2036 of file dae_builder_internal.cpp.

2036  {
2037  return name(indices(cat));
2038 }

References indices(), and name().

◆ assign()

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

Definition at line 3776 of file dae_builder_internal.cpp.

3776  {
3777  // Create a unique name for the reinit variable
3778  std::string assign_name = unique_name("__assign__" + name + "__", true);
3779  // Add a new dependent variable defined by val
3781  val, Dict());
3782  // Classify as assign variable
3783  categorize(v.index, Category::CALCULATED);
3784  v.parent = variable(name).index;
3785  // Return the variable name
3786  return v;
3787 }
std::string unique_name(const std::string &prefix, bool allow_no_prefix=false) const
Find a unique name, with a specific prefix.
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(), load_fmi_description(), 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 4686 of file dae_builder_internal.cpp.

4686  {
4687  double ret;
4688  variable(name).get_attribute(a, &ret);
4689  return ret;
4690 }
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 4692 of file dae_builder_internal.cpp.

4693  {
4694  // Allocate return
4695  std::vector<double> r;
4696  r.reserve(size(a, name));
4697  // Get contribution from each variable
4698  std::vector<double> r1;
4699  for (const auto& n : name) {
4700  variable(n).get_attribute(a, &r1);
4701  r.insert(r.end(), r1.begin(), r1.end());
4702  }
4703  return r;
4704 }

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

◆ categorize()

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

Definition at line 3400 of file dae_builder_internal.cpp.

3400  {
3401  // Get variable reference
3402  Variable& v = variable(ind);
3403  // If same category, quick return
3404  if (v.category == cat) return;
3405  // Remove from current category, if any
3406  if (v.category != Category::NUMEL) {
3407  remove(indices(v.category), ind);
3408  v.category = Category::NUMEL;
3409  }
3410  // Add to new category, if any
3411  if (cat != Category::NUMEL) {
3412  std::vector<size_t>& indices = this->indices(cat);
3413  if (is_acyclic(cat)) {
3414  indices.push_back(ind);
3415  } else {
3416  insert(indices, ind);
3417  }
3418  v.category = cat;
3419  }
3420 }
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_ls_dae(), import_model_structure(), import_model_variables(), load_fmi_description(), reinit(), set_category(), set_variability(), and when().

◆ category()

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

Definition at line 3537 of file dae_builder_internal.cpp.

3537  {
3538  return variable(ind).category;
3539 }
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 3444 of file dae_builder_internal.cpp.

3444  {
3445  return variable(ind).causality;
3446 }

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 3134 of file dae_builder_internal.cpp.

3134  {
3135  std::vector<MX> ret;
3136  ret.reserve(size(Category::C));
3137  for (size_t c : indices(Category::C)) ret.push_back(variable(variable(c).bind).v);
3138  return ret;
3139 }

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

Referenced by oracle().

◆ class_name()

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

Implements casadi::SharedObjectInternal.

Definition at line 233 of file dae_builder_internal.hpp.

233 {return "DaeBuilderInternal";}

◆ clear_cache()

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

Definition at line 2642 of file dae_builder_internal.cpp.

2642  {
2643  for (bool sx : {false, true}) {
2644  for (bool elim_w : {false, true}) {
2645  for (bool lifted_calls : {false, true}) {
2646  Function& fref = oracle_[sx][elim_w][lifted_calls];
2647  if (!fref.is_null()) fref = Function();
2648  }
2649  }
2650  }
2651  clear_cache_ = false;
2652 }
Function oracle_[2][2][2]
Function oracles (cached)

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

Referenced by oracle().

◆ compile_fmu()

Dict casadi::DaeBuilderInternal::compile_fmu ( const Dict &  files,
const Dict &  opts 
) const

Definition at line 1346 of file dae_builder_internal.cpp.

1346  {
1347  return FmuInternal::compile_fmu(name_, files, opts);
1348 }
static Dict compile_fmu(const std::string &name, const Dict &files, const Dict &opts)
Definition: fmu.cpp:781

References casadi::FmuInternal::compile_fmu(), and name_.

◆ convert_index()

casadi_int casadi::DaeBuilderInternal::convert_index ( casadi_int  index) const
protected

Definition at line 3107 of file dae_builder_internal.cpp.

3107  {
3108  // XML index is 1-based
3109  index--;
3110  // Handle added time variables and time variables in non-first position
3111  if (orig_time_index_ < 0) {
3112  // Adjust for added time variable
3113  index++;
3114  } else if (index == orig_time_index_) {
3115  // Time variable position
3116  index = 0;
3117  } else if (orig_time_index_ > 0) {
3118  // Adjust for time variable not in first position
3119  // Example, orig_time_index_ is 2: [x0:1, x1:2, t:0, x2:3] in XML [t, x0, x1, x2] in variables_
3120  if (index == orig_time_index_) {
3121  index = 0;
3122  } else if (index < orig_time_index_) {
3123  index++;
3124  }
3125  }
3126  // Return index in variables_
3127  return index;
3128 }

References orig_time_index_.

Referenced by import_model_structure(), import_model_variables(), and read_dependencies().

◆ 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 2332 of file dae_builder_internal.cpp.

2334  {
2335  // Are there any '_' in the names?
2336  bool with_underscore = false;
2337  for (const auto *s_io : {&s_in, &s_out}) {
2338  for (const std::string& s : *s_io) {
2339  with_underscore = with_underscore || std::count(s.begin(), s.end(), '_');
2340  }
2341  }
2342  // Model equations in DLL
2343  if (!symbolic_) {
2344  // Cannot lift calls in an FMU
2345  casadi_assert(!lifted_calls, "Lifting requires a symbolic representation");
2346  // Cannot convert to SX
2347  casadi_assert(!sx, "SX expansion requires a symbolic representation");
2348  // Redirect to FmuFunction creation
2349  return fmu_fun(fname, s_in, s_out, opts);
2350  }
2351  // Replace '_' with ':', if needed
2352  if (with_underscore) {
2353  std::vector<std::string> s_in_mod(s_in), s_out_mod(s_out);
2354  for (auto *s_io : {&s_in_mod, &s_out_mod}) {
2355  for (std::string& s : *s_io) std::replace(s.begin(), s.end(), '_', ':');
2356  }
2357  // Recursive call
2358  return create(fname, s_in_mod, s_out_mod, opts, sx, lifted_calls);
2359  }
2360  // Check if dependent variables are given and needed
2361  bool elim_w = false;
2362  if (size(Category::W) > 0) {
2363  // Dependent variables exists, eliminate unless v is given
2364  elim_w = true;
2365  for (const std::string& s : s_in) {
2366  if (s == "w") {
2367  // Dependent variables are given
2368  elim_w = false;
2369  break;
2370  }
2371  }
2372  }
2373  // Are lifted calls really needed?
2374  if (lifted_calls) {
2375  // Consistency check
2376  casadi_assert(!elim_w, "Lifted calls cannot be used if dependent variables are eliminated");
2377  // Only lift calls if really needed
2378  lifted_calls = false;
2379  for (const MX& vdef_comp : outputs(Category::WDEF)) {
2380  if (vdef_comp.is_output()) {
2381  // There are indeed function calls present
2382  lifted_calls = true;
2383  break;
2384  }
2385  }
2386  }
2387  // Call factory without lifted calls
2388  std::string fname_nocalls = lifted_calls ? fname + "_nocalls" : fname;
2389  Function ret = oracle(sx, elim_w, lifted_calls).factory(fname_nocalls, s_in, s_out, lc_);
2390  // If no lifted calls, done
2391  if (!lifted_calls) return ret;
2392  // MX expressions for ret without lifted calls
2393  std::vector<MX> ret_in = ret.mx_in();
2394  std::vector<MX> ret_out = ret(ret_in);
2395  // Offsets in v
2396  std::vector<casadi_int> h_offsets = offset(var(indices(Category::W)));
2397  // Split "w", "lam_wdef" into components
2398  std::vector<MX> v_in, lam_vdef_in;
2399  for (size_t i = 0; i < s_in.size(); ++i) {
2400  if (ret.name_in(i) == "w") {
2401  v_in = vertsplit(ret_in[i], h_offsets);
2402  } else if (ret.name_in(i) == "lam_wdef") {
2403  lam_vdef_in = vertsplit(ret_in[i], h_offsets);
2404  }
2405  }
2406  // Map dependent variables into index in vector
2407  std::map<MXNode*, size_t> v_map;
2408  for (size_t i = 0; i < size(Category::W); ++i) {
2409  v_map[var(Category::W, i).get()] = i;
2410  }
2411  // Definitions of w
2412  std::vector<MX> wdef = outputs(Category::WDEF);
2413  // Collect all the call nodes
2414  std::map<MXNode*, CallIO> call_nodes;
2415  for (size_t vdefind = 0; vdefind < wdef.size(); ++vdefind) {
2416  // Current element handled
2417  const MX& vdefref = wdef.at(vdefind);
2418  // Handle function call nodes
2419  if (vdefref.is_output()) {
2420  // Get function call node
2421  MX c = vdefref.dep(0);
2422  // Find the corresponding call node in the map
2423  auto call_it = call_nodes.find(c.get());
2424  // If first time this call node is encountered
2425  if (call_it == call_nodes.end()) {
2426  // Create new CallIO struct
2427  CallIO cio;
2428  // Save function instance
2429  cio.f = c.which_function();
2430  // Expressions for function call inputs
2431  cio.v.resize(c.n_dep(), -1);
2432  cio.arg.resize(cio.v.size());
2433  for (casadi_int i = 0; i < cio.v.size(); ++i) {
2434  if (c.dep(i).is_constant()) {
2435  cio.arg.at(i) = c.dep(i);
2436  } else {
2437  size_t v_ind = v_map.at(c.dep(i).get());
2438  cio.v.at(i) = v_ind;
2439  cio.arg.at(i) = v_in.at(v_ind);
2440  }
2441  }
2442  // Allocate memory for function call outputs
2443  cio.vdef.resize(c.n_out(), -1);
2444  cio.res.resize(cio.vdef.size());
2445  // Allocate memory for adjoint seeds, if any
2446  if (!lam_vdef_in.empty()) cio.adj1_arg.resize(c.n_out());
2447  // Save to map and update iterator
2448  call_it = call_nodes.insert(std::make_pair(c.get(), cio)).first;
2449  }
2450  // Which output of the function are we calculating?
2451  casadi_int oind = vdefref.which_output();
2452  // Save output expression to structure
2453  call_it->second.vdef.at(oind) = vdefind;
2454  call_it->second.res.at(oind) = v_in.at(vdefind);
2455  // Save adjoint seed to structure, if any
2456  if (!lam_vdef_in.empty()) call_it->second.adj1_arg.at(oind) = lam_vdef_in.at(vdefind);
2457  }
2458  }
2459  // Additional term in jac_vdef_v
2460  for (size_t i = 0; i < ret_out.size(); ++i) {
2461  if (ret.name_out(i) == "jac_wdef_w") {
2462  ret_out.at(i) += jac_vdef_v_from_calls(call_nodes, h_offsets);
2463  }
2464  }
2465  // Additional term in hess_?_v_v where ? is any linear combination containing vdef
2466  MX extra_hess_v_v; // same for all linear combinations, if multiple
2467  for (auto&& e : lc_) {
2468  // Find out of vdef is part of the linear combination
2469  bool has_vdef = false;
2470  for (const std::string& r : e.second) {
2471  if (r == "wdef") {
2472  has_vdef = true;
2473  break;
2474  }
2475  }
2476  // Skip if linear combination does not depend on vdef
2477  if (!has_vdef) continue;
2478  // Search for matching function outputs
2479  for (size_t i = 0; i < ret_out.size(); ++i) {
2480  if (ret.name_out(i) == "hess_" + e.first + "_w_w") {
2481  // Calculate contribution to hess_?_v_v
2482  if (extra_hess_v_v.is_empty())
2483  extra_hess_v_v = hess_v_v_from_calls(call_nodes, h_offsets);
2484  // Add contribution to output
2485  ret_out.at(i) += extra_hess_v_v;
2486  }
2487  }
2488  }
2489  // Assemble modified return function and return
2490  ret = Function(fname, ret_in, ret_out, ret.name_in(), ret.name_out());
2491  return ret;
2492 }
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
Create fresh symbols with the names and sparsity patterns of the inputs.
Definition: function.cpp:1781
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
Build a function computing derivatives by naming inputs and outputs.
Definition: function.cpp:2009
MXNode * get() const
Get a const pointer to the node.
Definition: mx.cpp:567

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(), outputs(), 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.

180  {
181  // Note: i != this because of something something multiple inheritance
182  return str( (casadi_int)(i)) + "/" + static_cast<const Internal*>(this)->class_name();
183  }
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 3175 of file dae_builder_internal.cpp.

3175  {
3176  // According to table in FMI 2.0.2 specification, section 2.2.7
3177  switch (variability) {
3178  case Variability::CONSTANT:
3180  return Initial::EXACT;
3181  break;
3182  case Variability::FIXED:
3183  // Fall-through
3184  case Variability::TUNABLE:
3186  return Initial::EXACT;
3188  return Initial::CALCULATED;
3189  break;
3190  case Variability::DISCRETE:
3191  // Fall-through
3194  return Initial::CALCULATED;
3195  break;
3196  default: break;
3197  }
3198  // Initial value not available
3199  return Initial::NA;
3200 }

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 add(), and import_model_variables().

◆ default_variability()

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

Definition at line 3159 of file dae_builder_internal.cpp.

3159  {
3160  // Default variability per FMI 3.0.2, section 2.4.7.4
3161  // "The default for variables of causality parameter, structural parameter or
3162  // calculated parameter is fixed."
3164  return Variability::FIXED;
3165  }
3166  // "The default for variables of type Float32 and Float64 and causality other
3167  // than parameter, structuralParameter or calculatedParameter is continuous"
3168  if (type == Type::FLOAT32 || type == Type::FLOAT64) {
3169  return Variability::CONTINUOUS;
3170  } else {
3171  return Variability::DISCRETE;
3172  }
3173 }

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 2870 of file dae_builder_internal.cpp.

2872  {
2873  // Are we calculating d and/or w
2874  bool calc_d = false, calc_w = false;
2875  // Convert outputs to enums
2876  std::vector<Category> v_out;
2877  v_out.reserve(v_out.size());
2878  for (const std::string& s : s_out) {
2879  Category e = to_enum<Category>(s);
2880  if (e == Category::D) {
2881  calc_d = true;
2882  } else if (e == Category::W) {
2883  calc_w = true;
2884  } else {
2885  casadi_error("Can only calculate d and/or w");
2886  }
2887  v_out.push_back(e);
2888  }
2889  // Consistency check
2890  casadi_assert(calc_d || calc_w, "Nothing to calculate");
2891  // Convert inputs to enums
2892  std::vector<Category> v_in;
2893  v_in.reserve(v_in.size());
2894  for (const std::string& s : s_in) {
2895  Category e = to_enum<Category>(s);
2896  if (calc_d && e == Category::D) casadi_error("'d' cannot be both input and output");
2897  if (calc_w && e == Category::W) casadi_error("'w' cannot be both input and output");
2898  v_in.push_back(e);
2899  }
2900  // Collect input expressions
2901  std::vector<MX> f_in;
2902  f_in.reserve(s_in.size());
2903  for (Category v : v_in) f_in.push_back(vertcat(inputs(v)));
2904  // Collect output expressions
2905  std::vector<MX> f_out;
2906  f_out.reserve(s_out.size());
2907  for (Category v : v_out) f_out.push_back(vertcat(inputs(v)));
2908  // Variables to be substituted
2909  std::vector<MX> dw, dwdef;
2910  if (calc_d) {
2911  std::vector<MX> d = var(indices(Category::D));
2912  dw.insert(dw.end(), d.begin(), d.end());
2913  std::vector<MX> ddef = outputs(Category::DDEF);
2914  dwdef.insert(dwdef.end(), ddef.begin(), ddef.end());
2915  }
2916  if (calc_w) {
2917  std::vector<MX> w = var(indices(Category::W));
2918  dw.insert(dw.end(), w.begin(), w.end());
2919  std::vector<MX> wdef = outputs(Category::WDEF);
2920  dwdef.insert(dwdef.end(), wdef.begin(), wdef.end());
2921  }
2922  // Perform elimination
2923  substitute_inplace(dw, dwdef, f_out);
2924  // Assemble return function
2925  return Function(fname, f_in, f_out, s_in, s_out);
2926 }
std::vector< MX > inputs(Category ind) const

References casadi::D, casadi::DDEF, indices(), inputs(), outputs(), var(), casadi::W, and casadi::WDEF.

◆ der() [1/2]

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

Definition at line 2118 of file dae_builder_internal.cpp.

2118  {
2119  return const_cast<DaeBuilderInternal*>(this)->der(var, false);
2120 }
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 2122 of file dae_builder_internal.cpp.

2122  {
2123  // Must be a vector
2124  casadi_assert(var.is_column(), "Input expression must be a vector");
2125  // Quick return if symbolic variable
2126  if (var.is_symbolic()) return get_der(find(var), may_allocate);
2127  // If a vertical concatenation
2128  if (var.is_valid_input()) {
2129  // Differentiate each primitive
2130  auto var_split = var.primitives();
2131  for (MX& s : var_split) s = der(s, may_allocate);
2132  // Return the concatenation
2133  return var.join_primitives(var_split);
2134  }
2135  // Handle general case: Get dependent symbolic primitives
2136  std::vector<MX> dep = symvar(var);
2137  // Get derivatives of dependent symbolic primitives
2138  std::vector<MX> dep_der;
2139  for (size_t ind : find(dep)) dep_der.push_back(get_der(ind, may_allocate));
2140  // Forward directional derivative to get time derivative:
2141  // dot(var) = d_var/d_dep * dot(dep)
2142  std::vector<std::vector<MX>> r = {dep_der};
2143  r = forward(std::vector<MX>{var}, dep, r);
2144  casadi_assert_dev(r.size() == 1);
2145  return vertcat(r.at(0));
2146 }
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 the expression can be used as a Function input.
Definition: mx.cpp:957
std::vector< MX > primitives() const
Get the symbolic primitives of a valid Function input.
Definition: mx.cpp:965
MX join_primitives(const std::vector< MX > &v) const
Join values along the symbolic primitives of this expression.
Definition: mx.cpp:997
bool is_symbolic() const
Check if the node is a symbolic primitive (created by MX.sym)
Definition: mx.cpp:798

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 1662 of file dae_builder_internal.cpp.

1662  {
1663  // Assert correctness
1664  if (more) sanity_check();
1665 
1666  // Print dimensions
1667  stream << "nt = " << size(Category::T) << ", "
1668  << "nx = " << size(Category::X) << ", "
1669  << "nz = " << size(Category::Z) << ", "
1670  << "nq = " << size(Category::Q) << ", "
1671  << "ny = " << size(Category::Y) << ", "
1672  << "np = " << size(Category::P) << ", "
1673  << "nc = " << size(Category::C) << ", "
1674  << "nd = " << size(Category::D) << ", "
1675  << "nw = " << size(Category::W) << ", "
1676  << "nu = " << size(Category::U);
1677 
1678  // Quick return?
1679  if (!more) return;
1680  stream << std::endl;
1681 
1682  // Print the functions
1683  if (!fun_.empty()) {
1684  stream << "Functions:" << std::endl;
1685  for (const Function& f : fun_) {
1686  stream << " " << f << std::endl;
1687  }
1688  }
1689 
1690  // Print the variables, including outputs
1691  stream << "Model variables:" << std::endl;
1694  if (size(cat) > 0) {
1695  stream << " " << to_string(cat) << " = " << var(indices(cat)) << std::endl;
1696  }
1697  }
1698 
1699  // All variables that can have dependent variables
1700  for (Category cat : {Category::C, Category::D, Category::W}) {
1701  if (size(cat) > 0) {
1702  stream << "List of " << description(cat) << "s (" << to_string(cat) << "):" << std::endl;
1703  for (size_t c : indices(cat)) {
1704  const Variable& v = variable(c);
1705  stream << " " << v.name;
1706  if (v.bind >= 0) stream << " := " << variable(v.bind).v;
1707  stream << std::endl;
1708  }
1709  }
1710  }
1711 
1712  // Print derivatives
1713  for (Category cat : {Category::T, Category::X, Category::Q}) {
1714  if (size(cat) > 0) {
1715  if (cat == Category::T && indices(cat).front() == 0) continue; // skip if trivial
1716  stream << "Time derivatives of " << description(cat) << "s (" << to_string(cat) << "):"
1717  << std::endl;
1718  for (size_t k : indices(cat)) {
1719  const Variable& v = variable(k);
1720  stream << " " << v.name << ": " << der(v.v) << std::endl;
1721  }
1722  }
1723  }
1724 
1725  // Outputs
1726  if (size(Category::Y) > 0) {
1727  stream << "Outputs (y):" << std::endl;
1728  for (size_t k : indices(Category::Y)) {
1729  const Variable& v = variable(k);
1730  stream << " " << v.name << ": " << v.v << std::endl;
1731  }
1732  }
1733 
1734  if (size(Category::ALG) > 0) {
1735  stream << "Algebraic equations:" << std::endl;
1736  for (size_t k : indices(Category::ALG)) {
1737  stream << " 0 == " << variable(k).v << std::endl;
1738  }
1739  }
1740 
1741  if (!init_.empty()) {
1742  stream << "Initial equations:" << std::endl;
1743  for (size_t k : init_) {
1744  const Variable& v = variable(k);
1745  stream << " " << v.name;
1746  if (!v.ieq.is_empty()) stream << " := " << v.ieq;
1747  stream << std::endl;
1748  }
1749  }
1750 
1751  if (!when_.empty()) {
1752  stream << "When equations:" << std::endl;
1753  for (auto weq : when_) {
1754  stream << " when " << variable(weq.first).v << " < 0 : " << std::endl;
1755  for (size_t eq : weq.second) {
1756  auto v = variable(eq).parent;
1757  stream << " " << variable(v).name << " := " << variable(eq).v << std::endl;
1758  }
1759  }
1760  }
1761 }
std::vector< std::pair< size_t, std::vector< size_t > > > when_
void eq(const MX &lhs, const MX &rhs, const Dict &opts)
Add a simple equation.
MX v
Variable expression (always a vector)

References casadi::ALG, 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, casadi::P, casadi::Variable::parent, casadi::Q, sanity_check(), size(), casadi::T, casadi::to_string(), casadi::U, casadi::Variable::v, var(), variable(), casadi::W, when_, casadi::X, casadi::Y, 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 2159 of file dae_builder_internal.cpp.

2159  {
2160  // Eliminate quadratures
2161  if (cat == Category::Q) {
2162  for (size_t q : indices(cat)) set_category(q, Category::X);
2163  return;
2164  }
2165 
2166  // Assume dependent variable (c, d, w)
2167  casadi_assert(is_acyclic(cat), "Elimination not supported for category " + to_string(cat));
2168 
2169  // Quick return if no dependent variables
2170  if (size(cat) == 0) return;
2171  // Clear cache after this
2172  clear_cache_ = true;
2173  // Ensure variables are sorted
2174  sort(cat);
2175  // Expressions where the variables are also being used
2176  std::vector<MX> ex;
2177  for (const Variable* v : variables_) {
2178  if (!v->v.is_constant()) ex.push_back(v->v);
2179  }
2180  // Perform elimination
2181  std::vector<size_t> ind = indices(cat);
2182  std::vector<MX> v = var(ind);
2183  std::vector<MX> vdef = outputs(dependent_definition(cat));
2184  substitute_inplace(v, vdef, ex);
2185  // Replace binding equations
2186  auto it = ex.begin();
2187  for (Variable* v : variables_) {
2188  if (!v->v.is_constant()) v->v = *it++;
2189  }
2190  // Consistency check
2191  casadi_assert_dev(it == ex.end());
2192  // Reclassify as calculated variables
2193  for (size_t k : ind) {
2195  }
2196 }
void sort(Category cat)
Sort all variables of a category.
void set_category(size_t ind, Category cat)
Set category.
Category dependent_definition(Category cat)

References casadi::CALCULATED, categorize(), clear_cache_, casadi::dependent_definition(), indices(), casadi::is_acyclic(), outputs(), 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 3611 of file dae_builder_internal.cpp.

3611  {
3612  // Read options
3613  for (auto&& op : opts) {
3614  casadi_error("No such option: " + op.first);
3615  }
3616  // Make sure vectors
3617  casadi_assert(lhs.is_column(), "Left-hand-side must be a column vector");
3618  casadi_assert(rhs.is_column(), "Right-hand-side must be a column vector");
3619  // Make sure dense
3620  if (!lhs.is_dense()) {
3621  eq(densify(lhs), rhs, opts);
3622  return;
3623  }
3624  if (!rhs.is_dense()) {
3625  eq(lhs, densify(rhs), opts);
3626  return;
3627  }
3628  // Make sure dimensions agree
3629  if (lhs.size1() != rhs.size1()) {
3630  // Handle mismatching dimnensions by recursion
3631  if (lhs.size1() == 1 && rhs.size1() > 1) {
3632  eq(repmat(lhs, rhs.size1()), rhs, opts);
3633  return;
3634  } else if (lhs.size1() > 1 && rhs.size1() == 1) {
3635  eq(lhs, repmat(rhs, lhs.size1()), opts);
3636  return;
3637  } else {
3638  casadi_error("Mismatched dimensions: " + str(lhs.size1()) + " vs " + str(rhs.size1()));
3639  }
3640  }
3641  // Make sure right-hand-side only depends on known model variables
3642  std::vector<size_t> rhs_vars = find(symvar(rhs));
3643  // If right-hand-side contains a time derivative that hasn't been defined yet,
3644  // add a new algebraic variable der_x and the ODE "der(x) = der_x"
3645  // This ensures that the DAE stays in semi-explicit form
3646  for (size_t rhs : rhs_vars) {
3647  Variable& v = variable(rhs);
3648  if (v.category == Category::Z && v.parent >= 0) {
3649  // Find the corresponding state variable
3650  Variable& x = variable(v.parent);
3651  // The "parent" attribute is used in some other cases, like assignments
3652  casadi_assert(x.der == v.index, "Cannot handle right-hand-side variable: " + v.name);
3653  // Create a new algebraic variable der_{name}, to distinguish from der({name})
3654  Variable& der_x = add(unique_name("der_" + x.name, true),
3656  {{"dimension", {x.dimension}}});
3657  // Add the trivial ODE
3658  eq(x.get_der(*this), der_x.v, Dict());
3659  }
3660  }
3661  // Try to honor a == b as an explicit equation
3662  if (lhs.is_valid_input()) {
3663  // Explicit equation
3664  if (lhs.is_symbolic()) {
3665  // Regular symbolic: Find the variable
3666  Variable& v = variable(lhs);
3667  // Set the binding equation
3668  if (v.has_beq()) {
3669  // Treat as implicit equation via recursion
3670  eq(MX::zeros(lhs.sparsity()), lhs - rhs, opts);
3671  return;
3672  } else {
3673  // Set the binding equation
3674  Variable& beq = assign(v.name, rhs);
3675  v.bind = beq.index;
3676  }
3677  // (Re)classify variables
3678  if (v.parent >= 0) {
3679  // Derivative variable is being set - find the corresponding state variable
3680  Variable& x = variable(v.parent);
3681  // The "parent" attribute is used in some other cases, like assignments
3682  casadi_assert(x.der == v.index, "Cannot handle left-hand-side: " + str(lhs));
3683  // Reclassify as a differential state and derivative as a dependent variable
3684  if (x.category == Category::Z) {
3685  // Not previously used: Reclassify as differential state
3686  categorize(x.index, detect_quad_ && !x.in_rhs ? Category::Q : Category::X);
3687  categorize(v.index, Category::W);
3688  } else if (x.category == Category::W) {
3689  // Already given a defining equation: Create a new dependent variable and use this
3690  // for the previous definition
3691  Variable& def_x = add(unique_name("def_" + x.name, true),
3693  {{"dimension", {x.dimension}}});
3694  categorize(def_x.index, Category::W);
3695  def_x.bind = x.bind;
3696  // We can now reclassify x as a differential state
3697  x.bind = -1;
3698  categorize(x.index, Category::X);
3699  categorize(v.index, Category::W);
3700  // Add a new implicit equation: 0 == x - def_x
3702  x.v - def_x.v, {{"dimension", x.dimension}});
3703  categorize(alg.index, Category::CALCULATED);
3704  indices(Category::ALG).push_back(alg.index);
3705  } else {
3706  casadi_error("Unexpected category for " + x.name + ": " + to_string(x.category));
3707  }
3708  } else if (v.category == Category::Z) {
3709  // Reclassify as dependent variable
3710  categorize(v.index, Category::W);
3711  } else {
3712  casadi_error("Cannot handle left-hand-side: " + str(lhs) + " of category '"
3713  + to_string(v.category) + "'");
3714  }
3715  } else {
3716  // Concatenation: Split into primitives
3717  auto lhs_split = lhs.primitives();
3718  std::vector<MX> rhs_split = lhs.split_primitives(rhs);
3719  // Call recursively
3720  for (size_t k = 0; k < lhs_split.size(); ++k) {
3721  eq(lhs_split.at(k), rhs_split.at(k), opts);
3722  }
3723  return;
3724  }
3725  } else {
3726  // Implicit equation: Create residual variable
3728  lhs - rhs, {{"dimension", std::vector<casadi_int>{lhs.size1()}}});
3729  categorize(alg.index, Category::CALCULATED);
3730  indices(Category::ALG).push_back(alg.index);
3731  }
3732  // Do not allow any quadrature states in the right-hand-sides
3733  for (size_t rhs : rhs_vars) {
3734  Variable& v = variable(rhs);
3735  if (!v.in_rhs) {
3736  v.in_rhs = true;
3737  if (v.category == Category::Q) categorize(v.index, Category::X);
3738  }
3739  }
3740 }
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(), load_fmi_description(), transition(), and when().

◆ export_fmu()

Dict casadi::DaeBuilderInternal::export_fmu ( const Dict &  opts) const

Definition at line 1237 of file dae_builder_internal.cpp.

1237  {
1238  // Default options
1239  bool no_warning = false;
1240  bool with_serialization = true;
1241  for (auto&& op : opts) {
1242  if (op.first == "no_warning") {
1243  no_warning = op.second;
1244  } else if (op.first == "with_serialization") {
1245  with_serialization = op.second;
1246  } else {
1247  casadi_error("No such option: " + op.first);
1248  }
1249  }
1250  // Feature incomplete
1251  if (!no_warning) casadi_warning("FMU generation is experimental and incomplete")
1252  // GUID
1253  std::string guid = generate_guid();
1254  // Generate model function
1255  std::string dae_filename = name_;
1256  casadi_assert(size(Category::Q) == 0, "Not implemented");
1257  Function dae = shared_from_this<DaeBuilder>().create(dae_filename,
1258  {"t", "x", "z", "p", "u"}, {"ode", "alg", "y", "zero"});
1259  // Event transition function, if needed
1260  Function tfun;
1261  if (size(Category::ZERO) > 0) tfun = transition("transition_" + name_);
1262  // Generate C code for model equations
1263  Dict codegen_opts;
1264  codegen_opts["with_header"] = true;
1265  CodeGenerator gen(dae_filename, codegen_opts);
1266  gen.add(dae);
1267  gen.add(dae.forward(1));
1268  gen.add(dae.reverse(1));
1269  if (!tfun.is_null()) gen.add(tfun);
1270  // Source files
1271  std::vector<std::string> sources;
1272  sources.push_back(gen.generate());
1273  sources.push_back(dae_filename + ".h");
1274  // Make sure dependencies are up-to-date
1276  // Generate FMU wrapper file
1277  sources.push_back(generate_wrapper(guid, gen));
1278  // Generate build description
1279  sources.push_back(generate_build_description(sources));
1280  // Return object
1281  Dict ret;
1282  for (const std::string& s : sources) ret[s] = "sources/" + s;
1283  // Generate modelDescription file
1284  ret[generate_model_description(guid)] = "./modelDescription.xml";
1285 
1286  // Serialize expressions
1287  if (with_serialization) {
1288  // Layered standard for serialized CasADi
1289  std::string serialization_ls = "org.casadi.fmi-ls-serialization";
1290  // Serialized oracle
1291  std::string oracle_filename = "oracle.casadi";
1292  shared_from_this<DaeBuilder>().oracle().save(oracle_filename);
1293  ret[oracle_filename] = "extra/" + serialization_ls + "/" + oracle_filename;
1294  // Manifest file for serialized expressions
1295  XmlNode r;
1296  r.name = "fmiLayeredStandardManifest";
1297  r.set_attribute("fmi-ls:fmi-ls-name", serialization_ls);
1298  r.set_attribute("fmi-ls:fmi-ls-version", "1.0.0");
1299  r.set_attribute("fmi-ls:fmi-ls-description",
1300  "Layered standard for serialized CasADi expressions in FMU");
1301  XmlNode manifest;
1302  manifest.children.push_back(r);
1303  // Export and add to return
1304  XmlFile xml_file("tinyxml");
1305  std::string manifest_filename = serialization_ls + ".fmi-ls-manifest.xml";
1306  xml_file.dump(manifest_filename, manifest);
1307  ret[manifest_filename] = "extra/" + serialization_ls + "/fmi-ls-manifest.xml";
1308  }
1309  // LS-DAE
1310  if (size(Category::Z) > 0) {
1311  // Layered standard for DAE
1312  std::string dae_ls = "org.fmi-standard.fmi-ls-dae";
1313  // Manifest file for serialized expressions
1314  XmlNode r;
1315  r.name = "fmiLayeredStandardManifest";
1316  r.set_attribute("fmi-ls:fmi-ls-name", dae_ls);
1317  r.set_attribute("fmi-ls:fmi-ls-version", "");
1318  r.set_attribute("fmi-ls:fmi-ls-description",
1319  "Layered standard for DAE support in FMU");
1320  // Algebraic variables
1321  XmlNode a;
1322  a.name = "AlgebraicVariables";
1323  for (size_t i : indices(Category::Z)) {
1324  XmlNode v;
1325  v.name = "AlgebraicVariable";
1326  v.set_attribute("valueReference",
1327  static_cast<casadi_int>(variable(i).value_reference));
1328  a.children.push_back(v);
1329  }
1330  r.children.push_back(a);
1331  // Modified model structure
1332  r.children.push_back(generate_model_structure(true));
1333  // Finish manifest file
1334  XmlNode manifest;
1335  manifest.children.push_back(r);
1336  // Export and add to return
1337  XmlFile xml_file("tinyxml");
1338  std::string manifest_filename = dae_ls + ".fmi-ls-manifest.xml";
1339  xml_file.dump(manifest_filename, manifest);
1340  ret[manifest_filename] = "extra/" + dae_ls + "/fmi-ls-manifest.xml";
1341  }
1342  // Return list of files
1343  return ret;
1344 }
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)
XmlNode generate_model_structure(bool dae=false) const
Generate FMU ModelStructure.
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.
Definition: sx_elem.cpp:523

References casadi::CodeGenerator::add(), casadi::XmlNode::children, casadi::Function::create(), casadi::XmlFile::dump(), casadi::Function::forward(), casadi::CodeGenerator::generate(), generate_build_description(), generate_guid(), generate_model_description(), generate_model_structure(), generate_wrapper(), indices(), casadi::GenericShared< Shared, Internal >::is_null(), casadi::XmlNode::name, name_, casadi::Q, casadi::Function::reverse(), casadi::XmlNode::set_attribute(), size(), transition(), update_dependencies(), variable(), casadi::Z, and casadi::ZERO.

◆ find() [1/4]

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

Definition at line 4599 of file dae_builder_internal.cpp.

4599  {
4600  // Make sure it is a valid input
4601  casadi_assert(v.is_symbolic(), "Variable must be symbolic");
4602  // Find the prospective variable
4603  size_t ind = find(v.name());
4604  // Make sure that the expression (not just the name) is correct
4605  casadi_assert(is_equal(v, variables_.at(ind)->v),
4606  "Variable \"" + v.name() + "\" has mismatching symbolic expression");
4607  // Return index
4608  return ind;
4609 }
bool is_equal(double x, double y, casadi_int depth=0)
Definition: calculus.hpp:287

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 4593 of file dae_builder_internal.cpp.

4593  {
4594  auto it = varind_.find(name);
4595  casadi_assert(it != varind_.end(), "No such variable: \"" + name + "\".");
4596  return it->second;
4597 }

References name(), and varind_.

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

◆ find() [3/4]

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

Definition at line 4617 of file dae_builder_internal.cpp.

4617  {
4618  std::vector<size_t> r(v.size());
4619  for (size_t i = 0; i < r.size(); ++i) r[i] = find(v[i]);
4620  return r;
4621 }

References find().

◆ find() [4/4]

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

Definition at line 4611 of file dae_builder_internal.cpp.

4611  {
4612  std::vector<size_t> r(name.size());
4613  for (size_t i = 0; i < r.size(); ++i) r[i] = find(name[i]);
4614  return r;
4615 }

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 2999 of file dae_builder_internal.cpp.

3002  {
3003  // Iterator for options lookup
3004  Dict::const_iterator it;
3005  // Scheme inputs
3006  std::vector<std::string> scheme_in;
3007  bool has_in = false;
3008  it = opts.find("scheme_in");
3009  if (it != opts.end()) {
3010  try {
3011  scheme_in = it->second;
3012  } catch (std::exception& e) {
3013  casadi_error(std::string("Cannot read 'scheme_in': ") + e.what());
3014  }
3015  has_in = true;
3016  }
3017 
3018  // Scheme outputs
3019  std::vector<std::string> scheme_out;
3020  bool has_out = false;
3021  it = opts.find("scheme_out");
3022  if (it != opts.end()) {
3023  try {
3024  scheme_out = it->second;
3025  has_out = true;
3026  } catch (std::exception& e) {
3027  casadi_error(std::string("Cannot read 'scheme_out': ") + e.what());
3028  }
3029  }
3030  // If scheme_in and/or scheme_out not provided, identify from name_in, name_out
3031  if (!has_in || !has_out) {
3032  FmuFunction::identify_io(has_in ? nullptr : &scheme_in,
3033  has_out ? nullptr : &scheme_out, name_in, name_out);
3034  }
3035  // IO scheme
3036  std::map<std::string, std::vector<size_t>> scheme;
3037  it = opts.find("scheme");
3038  if (it != opts.end()) {
3039  try {
3040  // Argument is a Dict
3041  Dict scheme_dict = it->second;
3042  // Convert indices
3043  for (auto&& e : scheme_dict) {
3044  std::vector<std::string> v = e.second;
3045  scheme[e.first] = find(v);
3046  }
3047  } catch (std::exception& e) {
3048  casadi_error(std::string("Cannot read 'scheme': ") + e.what());
3049  }
3050  } else {
3051  // Initialize all scheme entries
3052  for (auto&& s : dyn_in()) scheme[s] = std::vector<size_t>();
3053  for (auto&& s : dyn_out()) scheme[s] = std::vector<size_t>();
3054  // Default IO scheme
3055  scheme["t"] = indices(Category::T);
3056  scheme["x"] = indices(Category::X);
3057  scheme["u"] = indices(Category::U);
3058  scheme["z"] = indices(Category::Z);
3059  scheme["p"] = indices(Category::P);
3060  scheme["ode"] = indices(Category::X);
3061  for (size_t& i : scheme["ode"]) i = variable(i).der;
3062  scheme["quad"] = indices(Category::Q);
3063  for (size_t& i : scheme["quad"]) i = variable(i).der;
3064  scheme["alg"] = indices(Category::ALG);
3065  scheme["y"] = indices(Category::Y);
3066  }
3067  // Auxilliary variables, if any
3068  std::vector<std::string> aux;
3069  it = opts.find("aux");
3070  if (it != opts.end()) {
3071  try {
3072  aux = it->second;
3073  } catch (std::exception& e) {
3074  casadi_error(std::string("Cannot read 'aux': ") + e.what());
3075  }
3076  }
3077  // New FMU instance (to be shared between derivative functions)
3078  Fmu fmu(name, fmi_major_ >= 3 ? FmuApi::FMI3 : FmuApi::FMI2, this,
3079  scheme_in, scheme_out, scheme, aux);
3080 
3081  // Crete new function
3082  return Function::create(new FmuFunction(name, fmu, name_in, name_out), opts);
3083 }
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:488
std::vector< std::string > dyn_out()
Get the output scheme of a DAE function.
Definition: integrator.cpp:236
std::vector< std::string > dyn_in()
Get the input scheme of a DAE function.
Definition: integrator.cpp:232

References casadi::ALG, 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(), casadi::P, casadi::Q, casadi::T, casadi::U, variable(), casadi::X, casadi::Y, and casadi::Z.

Referenced by create().

◆ fun()

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

Definition at line 4671 of file dae_builder_internal.cpp.

4671  {
4672  casadi_assert(has_fun(name), "No such function: '" + name + "'");
4673  for (const Function& f : fun_) {
4674  if (f.name()==name) return f;
4675  }
4676  return Function();
4677 }

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

◆ gather_eq()

Function casadi::DaeBuilderInternal::gather_eq ( ) const

Definition at line 3085 of file dae_builder_internal.cpp.

3085  {
3086  // Output expressions
3087  std::vector<MX> f_out;
3088  // Names of outputs
3089  std::vector<std::string> f_out_name;
3090  // Get all expressions
3091  for (Category cat : output_categories()) {
3092  std::vector<MX> v = outputs(cat);
3093  if (!v.empty()) {
3094  f_out.push_back(vertcat(v));
3095  f_out_name.push_back(to_string(cat));
3096  }
3097  }
3098  // Construct function
3099  return Function("all_eq", {}, f_out, {}, f_out_name, {{"allow_free", true}});
3100 }
std::vector< Category > output_categories()

References casadi::output_categories(), outputs(), 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 1377 of file dae_builder_internal.cpp.

1377  {
1378  std::stringstream ss;
1379  ss << "{";
1380  bool first = true;
1381  for (double e : v) {
1382  // Separator
1383  if (!first) ss << ", ";
1384  first = false;
1385  // Print element
1386  ss << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << e;
1387  }
1388  ss << "}";
1389  return ss.str();
1390 }

◆ generate() [2/2]

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

Helper function: generate constants

Definition at line 1362 of file dae_builder_internal.cpp.

1362  {
1363  std::stringstream ss;
1364  ss << "{";
1365  bool first = true;
1366  for (double e : v) {
1367  // Separator
1368  if (!first) ss << ", ";
1369  first = false;
1370  // Print element
1371  ss << e;
1372  }
1373  ss << "}";
1374  return ss.str();
1375 }

Referenced by generate_wrapper().

◆ generate_build_description()

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

Definition at line 1007 of file dae_builder_internal.cpp.

1008  {
1009  // Default arguments
1010  int fmi_major = 3;
1011  int fmi_minor = 0;
1012  std::string model_name = name_;
1013  // Construct XML file
1014  XmlNode r;
1015  // Preamble
1016  r.name = "fmiBuildDescription";
1017  r.set_attribute("fmiVersion", std::to_string(fmi_major) + "." + std::to_string(fmi_minor));
1018  // Set of source files
1019  XmlNode source_file_set;
1020  source_file_set.name = "SourceFileSet";
1021  for (auto&& f : cfiles) {
1022  XmlNode source_file;
1023  source_file.name = "SourceFile";
1024  source_file.set_attribute("name", f);
1025  source_file_set.children.push_back(source_file);
1026  }
1027  // Build configurations
1028  XmlNode bc;
1029  bc.name = "BuildConfiguration";
1030  bc.set_attribute("modelIdentifier", model_name);
1031  bc.children.push_back(source_file_set);
1032  r.children.push_back(bc);
1033  // XML file name
1034  std::string xml_filename = "buildDescription.xml";
1035  // Construct ModelDescription
1036  XmlNode build_description;
1037  build_description.children.push_back(r);
1038  // Export to file
1039  XmlFile xml_file("tinyxml");
1040  xml_file.dump(xml_filename, build_description);
1041  return xml_filename;
1042 }

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 4853 of file dae_builder_internal.cpp.

4853  {
4854  // Initialize random seed
4855  static bool initialized = false;
4856  if (!initialized) {
4857  srand(::time(nullptr)); // NOLINT(runtime/threadsafe_fn)
4858  initialized = true;
4859  }
4860  // Possible characters
4861  const char h[] = "0123456789abcdef";
4862  // Length of GUID
4863  const size_t len = 32;
4864  // Generate random hex string
4865  std::vector<char> buf(len);
4866  for (size_t i = 0; i < len; ++i)
4867  buf[i] = h[rand() % 16]; // NOLINT(runtime/threadsafe_fn)
4868  return std::string(&buf.front(), len);
4869 }

References time().

Referenced by export_fmu().

◆ generate_model_description()

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

Definition at line 1044 of file dae_builder_internal.cpp.

1044  {
1045  // Default arguments
1046  int fmi_major = 3;
1047  int fmi_minor = 0;
1048  std::string model_name = name_;
1049  std::string description; // none
1050  std::string author; // none
1051  std::string version; // none
1052  std::string copyright; // none
1053  std::string license; // none
1054  // Construct XML file
1055  XmlNode r;
1056  // Preamble
1057  r.name = "fmiModelDescription";
1058  r.set_attribute("fmiVersion", std::to_string(fmi_major) + "." + std::to_string(fmi_minor));
1059  r.set_attribute("modelName", model_name);
1060  r.set_attribute(fmi_major >= 3 ? "instantiationToken" : "guid", guid);
1061  if (!description.empty()) r.set_attribute("description", description);
1062  if (!author.empty()) r.set_attribute("author", author);
1063  if (!version.empty()) r.set_attribute("version", version);
1064  if (!copyright.empty()) r.set_attribute("copyright", copyright);
1065  if (!license.empty()) r.set_attribute("license", license);
1066  r.set_attribute("generationTool", "CasADi");
1067  r.set_attribute("generationDateAndTime", iso_8601_time());
1068  r.set_attribute("variableNamingConvention", "structured"); // flat better?
1069  if (fmi_major < 3) r.set_attribute("numberOfEventIndicators", "0");
1070 
1071  // Model exchange marker
1072  XmlNode me;
1073  me.name = "ModelExchange";
1074  me.set_attribute("modelIdentifier", model_name); // sanitize name?
1075  me.set_attribute("providesDirectionalDerivatives", "true");
1076  me.set_attribute("providesAdjointDerivatives", "true");
1077  r.children.push_back(me);
1078 
1079  // Default experiment
1080  XmlNode def_exp;
1081  def_exp.name = "DefaultExperiment";
1082  if (!std::isnan(start_time_)) def_exp.set_attribute("startTime", start_time_);
1083  if (!std::isnan(stop_time_)) def_exp.set_attribute("stopTime", stop_time_);
1084  if (!std::isnan(tolerance_)) def_exp.set_attribute("tolerance", tolerance_);
1085  if (!std::isnan(step_size_)) def_exp.set_attribute("stepSize", step_size_);
1086  if (!def_exp.attributes.empty()) r.children.push_back(def_exp);
1087 
1088  // Model variables
1089  r.children.push_back(generate_model_variables());
1090  // Model structure
1091  r.children.push_back(generate_model_structure());
1092  // XML file name
1093  std::string xml_filename = "modelDescription.xml";
1094  // Construct ModelDescription
1095  XmlNode model_description;
1096  model_description.children.push_back(r);
1097  // Export to file
1098  XmlFile xml_file("tinyxml");
1099  xml_file.dump(xml_filename, model_description);
1100  return xml_filename;
1101 }
XmlNode generate_model_variables() const
Generate FMU ModelVariables.
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 ( bool  dae = false) const

Definition at line 1113 of file dae_builder_internal.cpp.

1113  {
1114  XmlNode r;
1115  r.name = "ModelStructure";
1116  // Add outputs
1117  for (size_t i : indices(Category::Y)) {
1118  const Variable& y = variable(i);
1119  XmlNode c;
1120  c.name = "Output";
1121  c.set_attribute("valueReference", static_cast<casadi_int>(y.value_reference));
1122  c.set_attribute("dependencies", y.dependencies);
1123  r.children.push_back(c);
1124  }
1125  // Add state derivatives
1126  for (size_t i : indices(Category::X)) {
1127  const Variable& xdot = variable(variable(i).der);
1128  XmlNode c;
1129  c.name = "ContinuousStateDerivative";
1130  c.set_attribute("valueReference", static_cast<casadi_int>(xdot.value_reference));
1131  c.set_attribute("dependencies", xdot.dependencies);
1132  r.children.push_back(c);
1133  }
1134  if (dae) {
1135  for (size_t i : indices(Category::ALG)) {
1136  XmlNode f;
1137  f.name = "Formulation";
1138  f.set_attribute("index", "1");
1139  f.set_attribute("valueReference", static_cast<casadi_int>(variable(i).value_reference));
1140  f.set_attribute("dependencies", variable(i).dependencies);
1141  XmlNode c;
1142  c.name = "Residual";
1143  c.children.push_back(f);
1144  r.children.push_back(c);
1145  }
1146  } else {
1147  // Add initial unknowns: Outputs
1148  for (size_t i : indices(Category::Y)) {
1149  const Variable& y = variable(i);
1150  XmlNode c;
1151  c.name = "InitialUnknown";
1152  c.set_attribute("valueReference", static_cast<casadi_int>(y.value_reference));
1153  c.set_attribute("dependencies", y.dependencies);
1154  r.children.push_back(c);
1155  }
1156  // Add initial unknowns: State derivative
1157  for (size_t i : indices(Category::X)) {
1158  const Variable& xdot = variable(variable(i).der);
1159  XmlNode c;
1160  c.name = "InitialUnknown";
1161  c.set_attribute("valueReference", static_cast<casadi_int>(xdot.value_reference));
1162  c.set_attribute("dependencies", xdot.dependencies);
1163  r.children.push_back(c);
1164  }
1165  // Add event indicators
1166  for (size_t i : indices(Category::ZERO)) {
1167  const Variable& zero = variable(i);
1168  XmlNode c;
1169  c.name = "EventIndicator";
1170  c.set_attribute("valueReference", static_cast<casadi_int>(zero.value_reference));
1171  c.set_attribute("dependencies", zero.dependencies);
1172  r.children.push_back(c);
1173  }
1174  }
1175  return r;
1176 }

References casadi::ALG, casadi::XmlNode::children, casadi::Variable::dependencies, der(), indices(), casadi::XmlNode::name, casadi::XmlNode::set_attribute(), casadi::Variable::value_reference, variable(), casadi::X, casadi::Y, and casadi::ZERO.

Referenced by export_fmu(), and generate_model_description().

◆ generate_model_variables()

XmlNode casadi::DaeBuilderInternal::generate_model_variables ( ) const

Definition at line 1104 of file dae_builder_internal.cpp.

1104  {
1105  XmlNode r;
1106  r.name = "ModelVariables";
1107  for (auto&& v : variables_) {
1108  r.children.push_back(v->export_xml(*this));
1109  }
1110  return r;
1111 }

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 1400 of file dae_builder_internal.cpp.

1401  {
1402  // Create file
1403  std::string wrapper_filename = name_ + "_wrap.c";
1404 
1405  auto f_ptr = Filesystem::ofstream_ptr(wrapper_filename);
1406  std::ostream& f = *f_ptr;
1407  CodeGenerator::stream_open(f, false);
1408 
1409  // Add includes
1410  f << "#include <fmi3Functions.h>\n"
1411  << "#include \"" << name_ << ".h\"\n"
1412  << "\n";
1413 
1414  // Total number of variables
1415  f << "#define N_VAR " << n_variables() << "\n";
1416 
1417  // Memory size
1418  f << "#define SZ_MEM " << n_mem() << "\n";
1419 
1420  // Work vectors sizes
1421  size_t sz_arg, sz_res, sz_iw, sz_w;
1422  gen.sz_work(sz_arg, sz_res, sz_iw, sz_w);
1423  f << "#define SZ_ARG " << sz_arg << "\n"
1424  << "#define SZ_RES " << sz_res << "\n"
1425  << "#define SZ_IW " << sz_iw << "\n"
1426  << "#define SZ_W " << sz_w << "\n";
1427 
1428  // Memory offsets
1429  f << "const size_t var_offset[N_VAR + 1] = {0";
1430  size_t mem_ind = 0;
1431  for (const Variable* v : variables_) {
1432  mem_ind += v->numel;
1433  f << ", " << mem_ind;
1434  }
1435  f << "};\n\n";
1436 
1437  // Start attributes
1438  f << "casadi_real start[SZ_MEM] = " << generate(start_all()) << ";\n\n";
1439 
1440  // Differential states
1441  f << "#define N_X " << size(Category::X) << "\n"
1442  << "fmi3ValueReference x_vr[N_X] = " << generate(indices(Category::X)) << ";\n"
1443  << "\n";
1444 
1445  // Algebraic variables
1446  f << "#define N_Z " << size(Category::Z) << "\n"
1447  << "fmi3ValueReference z_vr[N_Z] = " << generate(indices(Category::Z)) << ";\n"
1448  << "\n";
1449 
1450  // Controls
1451  f << "#define N_U " << size(Category::U) << "\n"
1452  << "fmi3ValueReference u_vr[N_U] = " << generate(indices(Category::U)) << ";\n"
1453  << "\n";
1454 
1455  // Parameters
1456  f << "#define N_P " << size(Category::P) << "\n"
1457  << "fmi3ValueReference p_vr[N_P] = " << generate(indices(Category::P)) << ";\n"
1458  << "\n";
1459 
1460  // State derivatives
1461  std::vector<size_t> xdot;
1462  for (size_t v : indices(Category::X)) xdot.push_back(variable(v).der);
1463  f << "fmi3ValueReference xdot_vr[N_X] = " << generate(xdot) << ";\n"
1464  << "\n";
1465 
1466  // Outputs
1467  f << "fmi3ValueReference alg_vr[N_Z] = " << generate(indices(Category::ALG)) << ";\n"
1468  << "\n";
1469 
1470  // Outputs
1471  f << "#define N_Y " << size(Category::Y) << "\n"
1472  << "fmi3ValueReference y_vr[N_Y] = " << generate(indices(Category::Y)) << ";\n"
1473  << "\n";
1474 
1475  // Event indicators
1476  f << "#define N_ZERO " << size(Category::ZERO) << "\n"
1477  << "fmi3ValueReference zero_vr[N_ZERO] = " << generate(indices(Category::ZERO)) << ";\n"
1478  << "\n";
1479 
1480  // Memory structure
1482 
1483  // Finalize file
1484  CodeGenerator::stream_close(f, false);
1485  return wrapper_filename;
1486 }
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 casadi::ALG, der(), casadi::CodeGenerator::fmu_helpers(), generate(), indices(), n_mem(), n_variables(), name_, casadi::Filesystem::ofstream_ptr(), casadi::P, size(), start_all(), casadi::CodeGenerator::stream_close(), casadi::CodeGenerator::stream_open(), casadi::CodeGenerator::sz_work(), casadi::U, variable(), variables_, casadi::X, casadi::Y, casadi::Z, and casadi::ZERO.

Referenced by export_fmu().

◆ get_der() [1/2]

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

Definition at line 373 of file dae_builder_internal.hpp.

373 {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 376 of file dae_builder_internal.hpp.

376  {
377  return variable(ind).get_der(*this, may_allocate);
378  }

◆ get_str()

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

Definition at line 396 of file dae_builder_internal.hpp.

396  {
397  std::stringstream ss;
398  disp(ss, more);
399  return ss.str();
400  }
void disp(std::ostream &stream, bool more) const override
Print description.

◆ getCount()

Definition at line 60 of file generic_shared_internal.hpp.

210  {
211  return static_cast<const Internal*>(this)->count;
212  }

◆ has()

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

Definition at line 2025 of file dae_builder_internal.cpp.

2025  {
2026  return varind_.find(name) != varind_.end();
2027 }

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 4664 of file dae_builder_internal.cpp.

4664  {
4665  for (const Function& f : fun_) {
4666  if (f.name()==name) return true;
4667  }
4668  return false;
4669 }

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 3130 of file dae_builder_internal.cpp.

3130  {
3131  return size(Category::T) > 0;
3132 }

References size(), and casadi::T.

Referenced by set_category(), 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 4791 of file dae_builder_internal.cpp.

4792  {
4793  // Mark inputs
4794  std::vector<casadi_int> lookup(n_variables(), -1);
4795  for (size_t i = 0; i < iind.size(); ++i) lookup.at(iind[i]) = i;
4796  // Which variables enter as a nonlinear dependency in any variable in oind
4797  std::vector<bool> nonlin(iind.size(), false);
4798  // List of nonlinearly entering variables for the specific output
4799  std::vector<casadi_int> nonlin_list;
4800  // Rows and columns of the Hessian
4801  std::vector<casadi_int> row, col;
4802  // Loop over output variables
4803  for (casadi_int j = 0; j < oind.size(); ++j) {
4804  const Variable& v = variable(oind[j]);
4805  // Loop over dependencies
4806  for (size_t k = 0; k < v.dependencies.size(); ++k) {
4807  if (v.dependenciesKind.empty() || v.dependenciesKind.at(k) == DependenciesKind::DEPENDENT) {
4808  casadi_int i = lookup.at(v.dependencies[k]);
4809  if (i >= 0 && !nonlin.at(i)) {
4810  // Add to list
4811  nonlin_list.push_back(i);
4812  nonlin.at(i) = true;
4813  }
4814  }
4815  }
4816  // Add all combinations to sparsity pattern
4817  for (casadi_int k1 : nonlin_list) {
4818  for (casadi_int k2 : nonlin_list) {
4819  row.push_back(k1);
4820  col.push_back(k2);
4821  }
4822  }
4823  // If row/col vectors grow too large, remove duplicates
4824  if (col.size() > 2 * iind.size() * iind.size()) {
4825  Sparsity r = Sparsity::triplet(iind.size(), iind.size(), row, col);
4826  row = r.get_row();
4827  col = r.get_col();
4828  }
4829  // Reset nonlin, nonlin_list for next iteration
4830  for (casadi_int k : nonlin_list) nonlin[k] = false;
4831  nonlin_list.clear();
4832  }
4833  // Create sparsity pattern
4834  return Sparsity::triplet(iind.size(), iind.size(), row, col);
4835 }
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 from the (row, col) index of every nonzero.
Definition: sparsity.cpp:1157

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 2565 of file dae_builder_internal.cpp.

2566  {
2567  // Calculate all Hessian expressions
2568  for (auto&& call_ref : call_nodes) call_ref.second.calc_hess();
2569  // Row offsets in hess_v_v
2570  casadi_int voffset_begin = 0, voffset_end = 0, voffset_last = 0;
2571  // Vertical and horizontal slices of hess_v_v
2572  std::vector<MX> vblocks, hblocks;
2573  // All blocks for a block row
2574  std::map<size_t, MX> hess_brow;
2575  // Loop over block rows
2576  for (size_t vind1 = 0; vind1 < size(Category::W); ++vind1) {
2577  // Current element handled
2578  const MX& vref = var(Category::W, vind1);
2579  // Update vertical offset
2580  voffset_begin = voffset_end;
2581  voffset_end += vref.numel();
2582  // Collect all blocks for this block row
2583  hess_brow.clear();
2584  for (auto&& call_ref : call_nodes) {
2585  // Locate the specific index
2586  for (size_t iind1 = 0; iind1 < call_ref.second.v.size(); ++iind1) {
2587  if (call_ref.second.v.at(iind1) == vind1) {
2588  // Add contribution to block row
2589  for (size_t iind2 = 0; iind2 < call_ref.second.v.size(); ++iind2) {
2590  // Corresponding index in v
2591  size_t vind2 = call_ref.second.v[iind2];
2592  if (vind2 == size_t(-1)) continue;
2593  // Hessian contribution
2594  MX H_contr = call_ref.second.hess(iind1, iind2);
2595  // Insert new block or add to existing one
2596  auto it = hess_brow.find(vind2);
2597  if (it != hess_brow.end()) {
2598  it->second += H_contr;
2599  } else {
2600  hess_brow[vind2] = H_contr;
2601  }
2602  }
2603  // An index can only appear once
2604  break;
2605  }
2606  }
2607  }
2608  // If no blocks, skip row
2609  if (hess_brow.empty()) continue;
2610  // Add empty rows to vblocks, if any
2611  if (voffset_last != voffset_begin) {
2612  vblocks.push_back(MX(voffset_begin - voffset_last, h_offsets.back()));
2613  }
2614  // Collect horizontal blocks
2615  hblocks.clear();
2616  casadi_int hoffset = 0;
2617  for (auto e : hess_brow) {
2618  // Add empty block before Jacobian block, if needed
2619  if (hoffset < h_offsets.at(e.first))
2620  hblocks.push_back(MX(vref.numel(), h_offsets.at(e.first) - hoffset));
2621  // Add Jacobian block
2622  hblocks.push_back(e.second);
2623  // Update offsets
2624  hoffset = h_offsets.at(e.first + 1);
2625  }
2626  // Add trailing empty block, if needed
2627  if (hoffset < h_offsets.back())
2628  hblocks.push_back(MX(vref.numel(), h_offsets.back() - hoffset));
2629  // Add new block row to vblocks
2630  vblocks.push_back(horzcat(hblocks));
2631  // Keep track of the offset handled in jac_brow
2632  voffset_last = voffset_end;
2633  }
2634  // Add empty trailing row to vblocks, if any
2635  if (voffset_last != voffset_end) {
2636  vblocks.push_back(MX(voffset_end - voffset_last, h_offsets.back()));
2637  }
2638  // Return additional term in jac_vdef_v
2639  return vertcat(vblocks);
2640 }

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 4390 of file dae_builder_internal.cpp.

4390  {
4391  if (debug_) {
4392  uout() << "== Structure before importing binding equations ==" << std::endl;
4393  disp(uout(), true);
4394  }
4395 
4396  // Loop over binding equations
4397  for (casadi_int i = 0; i < eqs.size(); ++i) {
4398  const XmlNode& eq = eqs[i];
4399  std::string eq_name = "beq_" + str(i);
4400  // Try to read the node
4401  try {
4402  // Get the variable and binding expression
4403  Variable& var = read_variable(eq[0]);
4404  if (eq[1].size() == 1) {
4405  // Set the binding equation
4406  var.bind = assign(var.name, read_expr(eq[1][0])).index;
4407  } else {
4408  // OpenModelica 1.17 occationally generates integer values without type specifier (bug?)
4409  casadi_assert(eq[1].size() == 0, "Not implemented");
4410  casadi_int val;
4411  eq[1].get(&val);
4412  casadi_warning(var.name + " has binding equation without type specifier: " + str(val));
4413  // Set the binding equation
4414  var.bind = assign(var.name, val).index;
4415  }
4416  // Add to list of dependent parameters
4417  indices(Category::D).push_back(var.index);
4418  } catch (std::exception& e) {
4419  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
4420  }
4421  }
4422 }
Variable & read_variable(const XmlNode &node, Attribute *att=nullptr)
Read a variable.
MX read_expr(const XmlNode &node)
Read an equation.
std::string name() const
Get the name of a symbolic primitive.
Definition: mx.cpp:794
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 3837 of file dae_builder_internal.cpp.

3837  {
3838  start_time_ = n.attribute<double>("startTime", nan);
3839  stop_time_ = n.attribute<double>("stopTime", nan);
3840  tolerance_ = n.attribute<double>("tolerance", nan);
3841  step_size_ = n.attribute<double>("stepSize", nan);
3842 }

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 4424 of file dae_builder_internal.cpp.

4424  {
4425  if (debug_) {
4426  uout() << "== Structure before importing dynamic equations ==" << std::endl;
4427  disp(uout(), true);
4428  }
4429  // Add discrete states to x_
4430  // Note: Make generic, should also apply to regular FMUs
4431  for (Variable* v : variables_) {
4432  if (v->variability == Variability::DISCRETE) {
4433  categorize(v->index, Category::X);
4434  }
4435  }
4436  // Add equations
4437  for (casadi_int i = 0; i < eqs.size(); ++i) {
4438  const XmlNode& eq = eqs[i];
4439  std::string eq_name = "dyneq_" + str(i);
4440  // Try to read the node
4441  try {
4442  if (eq.name == "equ:When") { // When equation
4443  // Nodes for condition, equations
4444  const XmlNode& n_cond = eq["equ:Condition"];
4445  const XmlNode& n_equ = eq["equ:Equation"];
4446  // Consistency checks - only working for very simple expressions
4447  casadi_assert(n_cond.size() == 1, "Only one condition in when equation supported");
4448  casadi_assert(n_equ.size() == 1, "Only one equation in when equation supported");
4449  // Get expression for condition
4450  std::string cond_name = n_cond[0][0].attribute<std::string>("name");
4451  std::string when_prefix = "$whenCondition";
4452  cond_name = cond_name.substr(when_prefix.size());
4453  casadi_int ind = std::stoi(cond_name) - 1;
4454  // Left-hand-side and right-hand-side
4455  MX lhs, rhs;
4456  // Handle different types of equations
4457  if (n_equ[0].name == "exp:Sub") {
4458  // Assume equation is an assignment
4459  lhs = read_identifier(n_equ[0][0]);
4460  rhs = read_expr(n_equ[0][1]);
4461  when_.at(ind).second.push_back(assign(lhs.name(), rhs).index);
4462  } else if (n_equ[0].name == "exp:Reinit") {
4463  // Reinitialization
4464  lhs = read_identifier(n_equ[0][0]);
4465  rhs = read_expr(n_equ[0][1]);
4466  when_.at(ind).second.push_back(reinit(lhs.name(), rhs).index);
4467  } else {
4468  // Not implemented
4469  casadi_error(n_equ[0].name + " in when equation not supported");
4470  }
4471  } else if (eq.name == "equ:Equation") { // Residual equation
4472  // Consistency checks
4473  casadi_assert_dev(eq.size() == 1 && eq[0].name == "exp:Sub");
4474  // Skip if empty
4475  if (eq[0].size() == 0) {
4476  casadi_warning(eq_name + " is empty, ignored.");
4477  continue;
4478  }
4479  // Get the left-hand-sides and right-hand-sides
4480  const XmlNode& lhs = eq[0][0];
4481  const XmlNode& rhs = eq[0][1];
4482  // Right-hand-side is the binding equation
4483  MX beq = read_expr(rhs);
4484  // Left-hand-side is a variable or derivative
4485  std::string when_prefix = "$whenCondition";
4486  if (lhs.name == "exp:Der") {
4487  // Differential equation
4488  Variable& v = read_variable(lhs[0]);
4489  this->eq(der(v.v), beq, Dict());
4490  } else if (lhs.size() > 0
4491  && lhs[0].attribute<std::string>("name").rfind(when_prefix, 0) == 0) {
4492  // Get the index
4493  std::string cond_name = lhs[0].attribute<std::string>("name");
4494  if (debug_) {
4495  uout() << "Reading event indicator: " << cond_name << " := " << beq << std::endl;
4496  }
4497  cond_name = cond_name.substr(when_prefix.size());
4498  casadi_int ind = std::stoi(cond_name) - 1;
4499  // Ensure consequitive for now
4500  casadi_assert(ind == when_.size(), "Non-consequitive when conditions");
4501  // Create a when equation with no equations
4502  when(beq, {}, Dict());
4503  } else {
4504  // Regular equation
4505  Variable& v = read_variable(lhs);
4506  if (debug_) uout() << "Reading equation: " << v.name << " == " << beq << std::endl;
4507  this->eq(v.v, beq, Dict());
4508  }
4509  } else {
4510  casadi_error("Unknown dynamic equation type, got:" + eq.name);
4511  }
4512  } catch (std::exception& e) {
4513  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
4514  }
4515  }
4516 }
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 4518 of file dae_builder_internal.cpp.

4518  {
4519  if (debug_) {
4520  uout() << "== Structure before importing initial equations ==" << std::endl;
4521  disp(uout(), true);
4522  }
4523 
4524  // Hack: OpenModelica XML may contain duplicate expressions, ignore these
4525  std::set<std::string> already_added;
4526  // Add equations
4527  for (casadi_int i = 0; i < eqs.size(); ++i) {
4528  const XmlNode& eq = eqs[i];
4529  // Try to read the node
4530  std::string eq_name = "initeq_" + str(i);
4531  try {
4532  if (eq.name == "equ:Equation") { // Residual equation
4533  // Consistency checks
4534  casadi_assert_dev(eq.size() == 1 && eq[0].name == "exp:Sub");
4535  // Ensure not empty
4536  if (eq[0].size() == 0) {
4537  casadi_warning(eq_name + " is empty, ignored.");
4538  continue;
4539  }
4540  // Get the left-hand-sides and right-hand-sides
4541  const XmlNode& lhs = eq[0][0];
4542  const XmlNode& rhs = eq[0][1];
4543 
4544  // Ignore initalizations of when equation indicators
4545  if (lhs.size() > 0
4546  && lhs[0].attribute<std::string>("name").rfind("$whenCondition", 0) == 0) {
4547  continue;
4548  }
4549 
4550  // Hack: Ignore expressions that just set a $PRE variable
4551  if (lhs.size() > 0 && lhs[0].attribute<std::string>("name") == "$PRE") {
4552  casadi_warning(eq_name + " defines a pre-variable, ignored");
4553  continue;
4554  }
4555  // Right-hand-side is the binding equation
4556  MX beq = read_expr(rhs);
4557  // Left-hand-side is a variable
4558  Variable& v = read_variable(lhs);
4559  // Hack: ignore initial equations for tunable parameters
4560  if (v.variability == Variability::TUNABLE) {
4561  casadi_warning(eq_name + " defines a tunable parameter, ignored")
4562  continue;
4563  }
4564  // Hack: avoid duplicate equations
4565  std::string eq_str = str(v.v) + " == " + str(beq);
4566  auto it = already_added.insert(eq_str);
4567  if (!it.second) {
4568  casadi_warning(eq_name + " duplicate of previous equation " + eq_str + ", ignored")
4569  continue;
4570  }
4571  // Set initial condition
4572  set_init(v.name, beq);
4573  } else {
4574  casadi_error("Unknown initial equation type, got:" + eq.name);
4575  }
4576  } catch (std::exception& e) {
4577  casadi_error("Failed to read " + eq_name + ":" + str(e.what()));
4578  }
4579  }
4580 }
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_ls_dae()

XmlNode casadi::DaeBuilderInternal::import_ls_dae ( const std::string &  lsdae)
protected

Definition at line 4368 of file dae_builder_internal.cpp.

4368  {
4369  // Load function oracle from file
4370  XmlFile xml_file("tinyxml");
4371  XmlNode ls_manifest = xml_file.parse(lsdae)[0]; // One child; fmiLayeredStandardManifest
4372 
4373  // Read attributes
4374  auto ls_version = ls_manifest.attribute<std::string>("fmi-ls:fmi-ls-version", "");
4375  casadi_assert(ls_version.empty() || ls_version == "1.0",
4376  "Unsupported LS-DAE version: " + ls_version);
4377 
4378  // Process algebraic variables
4379  casadi_assert(ls_manifest.has_child("AlgebraicVariables"), "Missing 'AlgebraicVariables'");
4380  for (const XmlNode& e : ls_manifest["AlgebraicVariables"].children) {
4381  auto vr = static_cast<unsigned int>(e.attribute<casadi_int>("valueReference"));
4382  categorize(vrmap_.at(vr), Category::Z);
4383  }
4384 
4385  // Return replacement
4386  casadi_assert(ls_manifest.has_child("ModelStructure"), "Missing 'ModelStructure'");
4387  return ls_manifest["ModelStructure"];
4388 }
std::unordered_map< unsigned int, size_t > vrmap_
Find of variable by value reference.

References casadi::XmlNode::attribute(), categorize(), casadi::XmlNode::has_child(), casadi::XmlFile::parse(), vrmap_, and casadi::Z.

Referenced by import_model_structure().

◆ import_model_exchange()

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

Definition at line 3844 of file dae_builder_internal.cpp.

3844  {
3845  // Read attributes
3846  provides_directional_derivatives_ = n.attribute<bool>(
3847  fmi_major_ >= 3 ? "providesDirectionalDerivatives" : "providesDirectionalDerivative", false);
3849  = n.attribute<bool>("providesAdjointDerivatives", false);
3850  model_identifier_ = n.attribute<std::string>("modelIdentifier");
3852  n.attribute<bool>("canBeInstantiatedOnlyOncePerProcess", false);
3853  // Get list of source files
3854  if (n.has_child("SourceFiles")) {
3855  for (const XmlNode& sf : n["SourceFiles"].children) {
3856  source_files_.push_back(sf.attribute<std::string>("name"));
3857  }
3858  }
3859 }
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 4118 of file dae_builder_internal.cpp.

4118  {
4119  // Do not use the automatic selection of outputs based on output causality
4120  indices(Category::Y).clear();
4121 
4122  // Algebraic variables are handled internally in the FMU by default
4123  for (size_t i = 0; i < n_variables(); ++i) {
4124  Variable& v = variable(i);
4125  if (v.category == Category::Z) {
4126  // Mark as dependent variable, no need for an algebraic equation anymore
4127  categorize(v.index, Category::W);
4128  }
4129  }
4130 
4131  // Read structure
4132  if (fmi_major_ >= 3) {
4133  // LS-DAE
4134  bool has_lsdae = false; // use ModelStructure from LS-DAE manifest
4135  std::string lsdae = resource_.path() + "/extra/org.fmi-standard.fmi-ls-dae/fmi-ls-manifest.xml";
4136  XmlNode lsdae_ms;
4137  if (enable_ls_dae_ && Filesystem::exists(lsdae)) {
4138  try {
4139  // Import replacement ModelStructure
4140  lsdae_ms = import_ls_dae(lsdae);
4141  // Append unchanged elements
4142  for (casadi_int i = 0; i < n.size(); ++i) {
4143  const XmlNode& e = n[i];
4144  if (e.name != "ContinuousStateDerivative" && e.name != "Output") {
4145  lsdae_ms.children.push_back(e);
4146  }
4147  }
4148  // Use instead of original ModelStructure
4149  has_lsdae = true;
4150  } catch (const std::exception& e) {
4151  casadi_warning("Failed to load LS-DAE manifest: " + std::string(e.what()));
4152  }
4153  }
4154 
4155  // Loop over ModelStructure elements
4156  const XmlNode& ms = has_lsdae ? lsdae_ms : n;
4157  for (casadi_int i = 0; i < ms.size(); ++i) {
4158  const XmlNode& e = ms[i];
4159  try {
4160  // Get a reference to the variable
4161  if (e.name == "Output") {
4162  // Get index
4163  indices(Category::Y).push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
4164  // Corresponding variable
4165  Variable& v = variable(indices(Category::Y).back());
4166  // Get dependencies
4167  v.dependencies = read_dependencies(e);
4168  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
4169  // Mark interdependencies
4170  for (casadi_int d : v.dependencies) variable(d).dependency = true;
4171  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
4172  } else if (e.name == "ContinuousStateDerivative") {
4173  // Get index
4174  der_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
4175  // Corresponding variable
4176  Variable& v = variable(der_.back());
4177  // Add to list of states and derivative to list of dependent variables
4178  casadi_assert(v.parent >= 0, "Error processing derivative info for " + v.name);
4179  categorize(v.index, Category::W);
4180  categorize(v.parent, Category::X);
4181  // Map der field to derivative variable
4182  variable(v.parent).der = der_.back();
4183  // Get dependencies
4184  v.dependencies = read_dependencies(e);
4185  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
4186  // Mark interdependencies
4187  for (casadi_int d : v.dependencies) variable(d).dependency = true;
4188  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
4189  } else if (e.name == "ClockedState") {
4190  // Clocked state
4191  casadi_message("ClockedState not implemented, ignoring");
4192  } else if (e.name == "InitialUnknown") {
4193  // Get index
4194  initial_unknowns_.push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
4195  // Get dependencies
4196  for (casadi_int d : read_dependencies(e)) variable(d).dependency = true;
4197  } else if (e.name == "EventIndicator") {
4198  // Event indicator
4199  indices(Category::ZERO).push_back(vrmap_.at(e.attribute<size_t>("valueReference")));
4200  nzero_++;
4201  } else if (e.name == "Residual") {
4202  // Loop over formulations
4203  bool found = false;
4204  for (casadi_int form = 0; form < e.size(); ++form) {
4205  const XmlNode& f = e[form];
4206  auto form_index = f.attribute<size_t>("index");
4207  if (form_index == 1) {
4208  // Index-1 formulation
4209  casadi_assert(!found, "Duplicate index-1 formulations");
4210  found = true;
4211  // Get index
4212  indices(Category::ALG).push_back(vrmap_.at(
4213  f.attribute<size_t>("valueReference")));
4214  // Corresponding variable
4215  Variable& v = variable(indices(Category::ALG).back());
4216  // Get dependencies
4217  v.dependencies = read_dependencies(f);
4218  v.dependenciesKind = read_dependencies_kind(f, v.dependencies.size());
4219  }
4220  }
4221  casadi_assert(found, "Missing index-1 formulation");
4222  } else {
4223  // Unknown
4224  casadi_error("Unknown ModelStructure element: " + e.name);
4225  }
4226  } catch (const std::exception& ex) {
4227  casadi_error("Error processing ModelStructure element: " + e.name + ": " + ex.what());
4228  }
4229  }
4230  } else {
4231  // Derivatives
4232  if (n.has_child("Derivatives")) {
4233  for (const auto& e : n["Derivatives"].children) {
4234  // Get index
4235  der_.push_back(convert_index(e.attribute<casadi_int>("index", 0)));
4236  // Corresponding variable
4237  Variable& v = variable(der_.back());
4238  // Add to list of states and derivative to list of dependent variables
4239  casadi_assert(v.parent >= 0, "Error processing derivative info for " + v.name);
4240  categorize(v.index, Category::W);
4241  categorize(v.parent, Category::X);
4242  // Map der field to derivative variable
4243  variable(v.parent).der = der_.back();
4244  }
4245  }
4246 
4247  // What if dependencies attributed is missing from Outputs,Derivatives?
4248  // Depends on x_ having been populated
4249  std::vector<casadi_int> default_dependencies;
4250  default_dependencies.insert(default_dependencies.begin(),
4251  indices(Category::T).begin(), indices(Category::T).end());
4252  default_dependencies.insert(default_dependencies.begin(),
4253  indices(Category::X).begin(), indices(Category::X).end());
4254  default_dependencies.insert(default_dependencies.begin(),
4255  indices(Category::U).begin(), indices(Category::U).end());
4256  std::sort(default_dependencies.begin(), default_dependencies.end());
4257 
4258  // FMI2 standard does not allow parameters to be included in dependencies attribute
4259  // (Table in section 2.2.8)
4260  // FMI3 standard does (Table in section 2.4.8)
4261  //
4262  // A uniform treatment is unconditionally add dense dependencies to all parameters
4263  // when loading FMI2
4264 
4265  std::vector<casadi_int> additional_dependencies;
4266  additional_dependencies.insert(additional_dependencies.begin(),
4267  indices(Category::P).begin(), indices(Category::P).end());
4268  std::vector<DependenciesKind> additional_dependencies_kind(size(Category::P),
4270 
4271  // Derivatives
4272  if (n.has_child("Derivatives")) {
4273  // Separate pass for dependencies
4274  for (const auto& e : n["Derivatives"].children) {
4275  casadi_int index = convert_index(e.attribute<casadi_int>("index", 0));
4276 
4277  // Corresponding variable
4278  Variable& v = variable(index);
4279 
4280  // Get dependencies
4281  if (e.has_attribute("dependencies")) {
4282  v.dependencies = read_dependencies(e);
4283  } else {
4284  v.dependencies = default_dependencies;
4285  }
4286  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
4287 
4288  v.dependencies.insert(v.dependencies.end(),
4289  additional_dependencies.begin(), additional_dependencies.end());
4290  v.dependenciesKind.insert(v.dependenciesKind.end(),
4291  additional_dependencies_kind.begin(), additional_dependencies_kind.end());
4292 
4293  // Mark interdependencies
4294  for (casadi_int d : v.dependencies) variable(d).dependency = true;
4295  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
4296  }
4297  }
4298  // Outputs
4299  if (n.has_child("Outputs")) {
4300  for (const auto& e : n["Outputs"].children) {
4301  // Get index
4302  indices(Category::Y).push_back(convert_index(e.attribute<casadi_int>("index", 0)));
4303  // Corresponding variable
4304  Variable& v = variable(indices(Category::Y).back());
4305 
4306  // Get dependencies
4307  if (e.has_attribute("dependencies")) {
4308  v.dependencies = read_dependencies(e);
4309  } else {
4310  v.dependencies = default_dependencies;
4311  }
4312  v.dependenciesKind = read_dependencies_kind(e, v.dependencies.size());
4313 
4314  v.dependencies.insert(v.dependencies.end(),
4315  additional_dependencies.begin(), additional_dependencies.end());
4316  v.dependenciesKind.insert(v.dependenciesKind.end(),
4317  additional_dependencies_kind.begin(), additional_dependencies_kind.end());
4318 
4319  // Mark interdependencies
4320  for (casadi_int d : v.dependencies) variable(d).dependency = true;
4321  for (casadi_int d : v.dependencies) variable(d).in_rhs = true;
4322  }
4323  }
4324  // What if dependencies is missing from InitialUnknowns?
4325  // Depends on x_ having been populated
4326  default_dependencies.clear();
4327  default_dependencies.insert(default_dependencies.begin(),
4328  indices(Category::T).begin(), indices(Category::T).end());
4329  for (const Variable* v : variables_) {
4330  if (v->initial == Initial::EXACT) default_dependencies.push_back(v->index);
4331  }
4332  default_dependencies.insert(default_dependencies.begin(),
4333  indices(Category::U).begin(), indices(Category::U).end());
4334  std::sort(default_dependencies.begin(), default_dependencies.end());
4335 
4336  // Initial unknowns
4337  if (n.has_child("InitialUnknowns")) {
4338  for (const auto& e : n["InitialUnknowns"].children) {
4339  // Get index
4340  initial_unknowns_.push_back(convert_index(e.attribute<casadi_int>("index", 0)));
4341 
4342  std::vector<casadi_int> dependencies;
4343  // Get dependencies
4344  if (e.has_attribute("dependencies")) {
4345  dependencies = read_dependencies(e);
4346  } else {
4347  dependencies = default_dependencies;
4348  }
4349 
4350  dependencies.insert(dependencies.end(),
4351  additional_dependencies.begin(), additional_dependencies.end());
4352 
4353  // Get dependencies
4354  for (casadi_int d : dependencies) variable(d).dependency = true;
4355  }
4356  }
4357  }
4358 
4359  // Reclassify some states as quadratures
4360  if (detect_quad_ && fmi_major_ >= 2) {
4361  for (size_t i : der_) {
4362  size_t x = variable(i).parent;
4363  if (!variable(x).in_rhs) categorize(x, Category::Q);
4364  }
4365  }
4366 }
std::vector< size_t > initial_unknowns_
std::vector< DependenciesKind > read_dependencies_kind(const XmlNode &n, size_t ndep)
casadi_int convert_index(casadi_int index) const
std::vector< casadi_int > read_dependencies(const XmlNode &n)
XmlNode import_ls_dae(const std::string &lsdae)
static bool exists(const std::string &path)
Definition: filesystem.cpp:150
const std::string & path() const
Get path for a consumer.
Definition: resource.cpp:70
bool dependency
Do other expressions depend on this variable.

References casadi::ALG, casadi::XmlNode::attribute(), categorize(), casadi::Variable::category, casadi::XmlNode::children, convert_index(), casadi::Variable::dependencies, casadi::Variable::dependenciesKind, casadi::Variable::dependency, casadi::DEPENDENT, casadi::Variable::der, der_, detect_quad_, enable_ls_dae_, casadi::EXACT, casadi::Filesystem::exists(), fmi_major_, casadi::XmlNode::has_child(), import_ls_dae(), casadi::Variable::in_rhs, casadi::Variable::index, indices(), initial_unknowns_, n_variables(), casadi::Variable::name, casadi::XmlNode::name, nzero_, casadi::P, casadi::Variable::parent, casadi::Resource::path(), casadi::Q, read_dependencies(), read_dependencies_kind(), resource_, casadi::XmlNode::size(), size(), casadi::T, casadi::U, variable(), variables_, vrmap_, casadi::W, casadi::X, casadi::Y, casadi::Z, and casadi::ZERO.

Referenced by load_fmi_description().

◆ import_model_variables()

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

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

Definition at line 3861 of file dae_builder_internal.cpp.

3861  {
3862  // Mapping from derivative variables to corresponding state variables, FMUX only
3863  std::vector<std::pair<std::string, std::string>> fmi1_der;
3864 
3865  // Add variables
3866  for (casadi_int i = 0; i < modvars.size(); ++i) {
3867  // Get a reference to the variable
3868  const XmlNode& vnode = modvars[i];
3869 
3870  // Name of variable
3871  std::string name = vnode.attribute<std::string>("name");
3872 
3873  // Handle variable categories (FMUX)
3874  if (fmi_major_ == 1 && vnode.has_child("VariableCategory")) {
3875  std::string variable_category = vnode["VariableCategory"].text;
3876  if (variable_category == "derivative") {
3877  // Create a new derivative variable
3878  std::string x_name = vnode["QualifiedName"][0].attribute<std::string>("name");
3879  fmi1_der.push_back(std::make_pair(x_name, name));
3880  }
3881  }
3882 
3883  // When conditions are reformulated into continuous zero-crossing functions
3884  if (fmi_major_ == 1 && name.rfind("$whenCondition", 0) == 0) continue;
3885 
3886  // Time always occupies internal index 0, regardless of its position in the FMU.
3887  // Allow an explicit independent variable to replace the automatically added
3888  // placeholder, including when their names match. Processing this declaration
3889  // records its original FMU position so convert_index can translate FMI indices.
3890  auto existing = varind_.find(name);
3891  bool replaces_time = existing != varind_.end() && existing->second == 0
3892  && orig_time_index_ == -1
3893  && vnode.attribute<std::string>("causality", "") == "independent";
3894  // Ignore duplicate variables
3895  if (existing != varind_.end() && !replaces_time) {
3896  casadi_warning("Duplicate variable '" + name + "' ignored");
3897  continue;
3898  }
3899 
3900  // Dimension of the variable
3901  std::vector<casadi_int> dimension;
3902 
3903  // Type specific properties
3904  Dict opts;
3905  Type type = Type::NUMEL;
3906  casadi_int derivative = -1;
3907  if (fmi_major_ >= 3) {
3908  // FMI 3.0: Type information in the same node
3909  type = to_enum<Type>(vnode.name);
3910  // Loop over children
3911  for (casadi_int i = 0; i < vnode.size(); ++i) {
3912  const XmlNode& c = vnode[i];
3913  if (c.name == "Dimension") {
3914  bool has_start = c.has_attribute("start");
3915  bool has_vr = c.has_attribute("valueReference");
3916  casadi_assert(has_start ^ has_vr, "Inconsistent attributes");
3917  casadi_assert(!has_vr, "Structural parameter dimensions not implemented");
3918  auto dim = c.attribute<casadi_int>("start");
3919  dimension.push_back(dim);
3920  } else if (c.name == "Alias") {
3921  // Aliases currently ignored
3922  } else if (c.name == "Annotations") {
3923  // Annotations currently ignored
3924  } else {
3925  casadi_error("Cannot handle: " + c.name);
3926  }
3927  }
3928  // Type specific attributes
3929  switch (type) {
3930  case Type::FLOAT32: // fall-through
3931  case Type::FLOAT64:
3932  // Floating point valued variables
3933  opts["unit"] = vnode.attribute<std::string>("unit", "");
3934  opts["display_unit"] = vnode.attribute<std::string>("displayUnit", "");
3935  opts["min"] = vnode.attribute<double>("min", -inf);
3936  opts["max"] = vnode.attribute<double>("max", inf);
3937  opts["nominal"] = vnode.attribute<double>("nominal", 1.);
3938  opts["start"] = vnode.attribute<std::vector<double>>("start", std::vector<double>{0.});
3939  derivative = vnode.attribute<casadi_int>("derivative", -1);
3940  break;
3941  case Type::INT8: // fall-through
3942  case Type::UINT8: // fall-through
3943  case Type::INT16: // fall-through
3944  case Type::UINT16: // fall-through
3945  case Type::INT32: // fall-through
3946  case Type::UINT32: // fall-through
3947  case Type::INT64: // fall-through
3948  case Type::UINT64: // fall-through
3949  // Integer valued variables
3950  opts["min"] = vnode.attribute<double>("min", -inf);
3951  opts["max"] = vnode.attribute<double>("max", inf);
3952  break;
3953  default:
3954  break;
3955  }
3956  } else {
3957  // FMI 1.0 / 2.0: Type information in a separate node
3958  if (vnode.has_child("Real")) {
3959  type = Type::FLOAT64;
3960  const XmlNode& props = vnode["Real"];
3961  opts["unit"] = props.attribute<std::string>("unit", "");
3962  opts["display_unit"] = props.attribute<std::string>("displayUnit", "");
3963  opts["min"] = props.attribute<double>("min", -inf);
3964  opts["max"] = props.attribute<double>("max", inf);
3965  opts["nominal"] = props.attribute<double>("nominal", 1.);
3966  opts["start"] = props.attribute<double>("start", 0.);
3967  derivative = props.attribute<casadi_int>("derivative", -1);
3968  } else if (vnode.has_child("Integer")) {
3969  type = Type::INT32;
3970  const XmlNode& props = vnode["Integer"];
3971  opts["min"] = props.attribute<double>("min", -inf);
3972  opts["max"] = props.attribute<double>("max", inf);
3973  } else if (vnode.has_child("Boolean")) {
3974  type = Type::BOOLEAN;
3975  } else if (vnode.has_child("String")) {
3976  type = Type::STRING;
3977  } else if (vnode.has_child("Enumeration")) {
3978  type = Type::ENUMERATION;
3979  } else {
3980  casadi_warning("Unknown type for " + name);
3981  }
3982  }
3983 
3984  // Scalar dimension by default
3985  if (dimension.empty()) dimension.push_back(1);
3986 
3987  // Description
3988  std::string description = vnode.attribute<std::string>("description", "");
3989 
3990  // Causality (FMI 1.0 -> FMI 2.0+)
3991  std::string causality_str = vnode.attribute<std::string>("causality", "local");
3992  if (fmi_major_ == 1 && causality_str == "internal") causality_str = "local";
3993  Causality causality = to_enum<Causality>(causality_str);
3994 
3995  // Variability (FMI 1.0 -> FMI 2.0+)
3996  std::string variability_str = vnode.attribute<std::string>("variability",
3998  if (fmi_major_ == 1 && variability_str == "parameter") variability_str = "fixed";
3999  Variability variability = to_enum<Variability>(variability_str);
4000 
4001  // Initial property
4003  std::string initial_str = vnode.attribute<std::string>("initial", "");
4004  if (!initial_str.empty()) {
4005  // Consistency check
4007  "The combination causality = '" + to_string(causality) + "', "
4008  "initial = '" + initial_str + "' is not allowed per the FMI specification.");
4009  initial = to_enum<Initial>(initial_str);
4010  }
4011 
4012  // If an input has a description that starts with "PARAMETER:",
4013  // treat it as a tunable parameter
4014  if (causality == Causality::INPUT && description.rfind("PARAMETER:", 0) == 0) {
4015  // Make tunable parameter
4018  }
4019 
4020  // Create the new variable
4021  opts["type"] = to_string(type);
4022  opts["initial"] = to_string(initial);
4023  opts["description"] = description;
4024  opts["dimension"] = dimension;
4025  Variable& var = add(name, causality, variability, opts);
4026  if (debug_) uout() << "Added variable: " << var.name << std::endl;
4027 
4028  // Ignore time variable?
4030  categorize(var.index, Category::NUMEL);
4031  }
4032 
4033  // Do not permit discrete variables in x, for now
4035  categorize(var.index, Category::NUMEL);
4036  }
4037 
4038  // Derivative attribute
4039  var.der_of = derivative;
4040 
4041  // Unless detect_quad has been set, assume all variables in the right-hand-sides
4042  // Prevents changing X to Q
4043  var.in_rhs = !detect_quad_ && fmi_major_ >= 2;
4044  var.value_reference = static_cast<unsigned int>(vnode.attribute<casadi_int>("valueReference"));
4045 
4046  // Add to variable reference map
4047  vrmap_[var.value_reference] = var.index;
4048  }
4049 
4050  // Set "parent" property using "derivative" attribute
4051  for (size_t i = 0; i < n_variables(); ++i) {
4052  Variable& v = variable(i);
4053  if (v.der_of >= 0) {
4054  if (fmi_major_ >= 3) {
4055  // Value reference is given: Find corresponding variable
4056  v.parent = vrmap_.at(static_cast<unsigned int>(v.der_of));
4057  } else if (fmi_major_ > 1) {
4058  // Variable given with index-1, make index 0
4059  v.parent = convert_index(v.der_of);
4060  }
4061  // TODO(@jaeandersson): Remove this redefinition of der_of
4062  v.der_of = v.parent;
4063  }
4064  }
4065 
4066  // Map derivative variables to corresponding state variables, FMUX only
4067  for (auto& p : fmi1_der) {
4068  // Add to list of derivatives
4069  Variable& v = variable(p.first);
4070  Variable& der_v = variable(p.second);
4071  categorize(der_v.index, Category::Z);
4072  der_v.der_of = der_v.parent = v.index;
4073  v.der = der_v.index;
4074  der_.push_back(der_v.index);
4075  }
4076 }
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(), convert_index(), debug_, default_initial(), default_variability(), casadi::Variable::der, der_, casadi::Variable::der_of, casadi::description(), detect_quad_, casadi::DISCRETE, casadi::ENUMERATION, casadi::FLOAT32, casadi::FLOAT64, fmi_major_, casadi::XmlNode::has_attribute(), 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, orig_time_index_, 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 1796 of file dae_builder_internal.cpp.

1796  {
1797  return const_cast<DaeBuilderInternal*>(this)->indices(cat);
1798 }

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 3141 of file dae_builder_internal.cpp.

3141  {
3142  std::vector<MX> ret;
3143  ret.reserve(init_.size());
3144  for (size_t ind : init_) {
3145  ret.push_back(variable(ind).v);
3146  }
3147  return ret;
3148 }

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 3150 of file dae_builder_internal.cpp.

3150  {
3151  std::vector<MX> ret;
3152  ret.reserve(init_.size());
3153  for (size_t ind : init_) {
3154  ret.push_back(variable(ind).ieq);
3155  }
3156  return ret;
3157 }

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  }

◆ inputs() [1/2]

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

Definition at line 2239 of file dae_builder_internal.cpp.

2239  {
2240  // Operation only permitted for input categories
2241  casadi_assert(is_input_category(ind),
2242  to_string(ind) + " is not an input category");
2243  // Get the expressions
2244  return var(indices(ind));
2245 }
bool is_input_category(Category cat)

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

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

◆ inputs() [2/2]

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

Definition at line 2247 of file dae_builder_internal.cpp.

2247  {
2248  std::vector<MX> ret(ind.size());
2249  for (casadi_int i=0; i<ind.size(); ++i) {
2250  ret[i] = vertcat(inputs(ind[i]));
2251  }
2252  return ret;
2253 }

References inputs().

◆ insert()

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

Definition at line 3422 of file dae_builder_internal.cpp.

3422  {
3423  // Keep list ordered: Insert at location corresponding to model variable index
3424  size_t loc = v.size();
3425  for (size_t i = 0; i < v.size(); ++i) {
3426  if (variable(v[i]).index >= ind) {
3427  loc = i;
3428  break;
3429  }
3430  }
3431  v.insert(v.begin() + loc, ind);
3432 }

References variable().

Referenced by categorize(), and set_causality().

◆ iso_8601_time()

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

Definition at line 4837 of file dae_builder_internal.cpp.

4837  {
4838  // Get current time
4839  auto now = std::chrono::system_clock::now();
4840  std::time_t tt = std::chrono::system_clock::to_time_t(now);
4841  auto local_tm = *std::localtime(&tt); // NOLINT(runtime/threadsafe_fn)
4842  // Convert to ISO 8601 (YYYY-MM-DDThh:mm:ssZ) format and return
4843  std::stringstream ss;
4844  ss << local_tm.tm_year + 1900 << '-'; // YYYY-
4845  ss << std::setfill('0') << std::setw(2) << local_tm.tm_mon + 1 << '-'; // MM-
4846  ss << std::setfill('0') << std::setw(2) << local_tm.tm_mday << 'T'; // DDT
4847  ss << std::setfill('0') << std::setw(2) << local_tm.tm_hour << ':'; // hh:
4848  ss << std::setfill('0') << std::setw(2) << local_tm.tm_min << ':'; // mm:
4849  ss << std::setfill('0') << std::setw(2) << local_tm.tm_sec << 'Z'; // ssZ
4850  return ss.str();
4851 }

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 4769 of file dae_builder_internal.cpp.

4770  {
4771  // Mark inputs
4772  std::vector<casadi_int> lookup(n_variables(), -1);
4773  for (size_t i = 0; i < iind.size(); ++i)
4774  lookup.at(iind[i]) = i;
4775  // Sparsity pattern for the Jacobian block
4776  std::vector<casadi_int> row, col;
4777  // Loop over output nonzeros
4778  for (casadi_int j = 0; j < oind.size(); ++j) {
4779  for (casadi_int d : variable(oind[j]).dependencies) {
4780  casadi_int i = lookup.at(d);
4781  if (i >= 0) {
4782  row.push_back(j); // Note: May not be sorted in ascending order
4783  col.push_back(i);
4784  }
4785  }
4786  }
4787  // Assemble sparsity in triplet format
4788  return Sparsity::triplet(oind.size(), iind.size(), row, col);
4789 }

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 2494 of file dae_builder_internal.cpp.

2495  {
2496  // Calculate all Jacobian expressions
2497  for (auto call_it = call_nodes.begin(); call_it != call_nodes.end(); ++call_it) {
2498  call_it->second.calc_jac();
2499  }
2500  // Row offsets in jac_vdef_v
2501  casadi_int voffset_begin = 0, voffset_end = 0, voffset_last = 0;
2502  // Vertical and horizontal slices of jac_vdef_v
2503  std::vector<MX> vblocks, hblocks;
2504  // All blocks for this block row
2505  std::map<size_t, MX> jac_brow;
2506  // Definitions of w
2507  std::vector<MX> wdef = outputs(Category::WDEF);
2508  // Collect all Jacobian blocks
2509  for (size_t vdefind = 0; vdefind < wdef.size(); ++vdefind) {
2510  // Current element handled
2511  const MX& vdefref = wdef.at(vdefind);
2512  // Update vertical offset
2513  voffset_begin = voffset_end;
2514  voffset_end += vdefref.numel();
2515  // Handle function call nodes
2516  if (vdefref.is_output()) {
2517  // Which output of the function are we calculating?
2518  casadi_int oind = vdefref.which_output();
2519  // Get function call node
2520  MX c = vdefref.dep(0);
2521  // Find data about inputs and outputs
2522  auto call_it = call_nodes.find(c.get());
2523  casadi_assert_dev(call_it != call_nodes.end());
2524  // Collect all blocks for this block row
2525  jac_brow.clear();
2526  for (casadi_int iind = 0; iind < call_it->second.arg.size(); ++iind) {
2527  size_t vind = call_it->second.v.at(iind);
2528  if (vind != size_t(-1)) {
2529  jac_brow[vind] = call_it->second.jac(oind, iind);
2530  }
2531  }
2532  // Add empty rows to vblocks, if any
2533  if (voffset_last != voffset_begin) {
2534  vblocks.push_back(MX(voffset_begin - voffset_last, h_offsets.back()));
2535  }
2536  // Collect horizontal blocks
2537  hblocks.clear();
2538  casadi_int hoffset = 0;
2539  for (auto e : jac_brow) {
2540  // Add empty block before Jacobian block, if needed
2541  if (hoffset < h_offsets.at(e.first))
2542  hblocks.push_back(MX(vdefref.numel(), h_offsets.at(e.first) - hoffset));
2543  // Add Jacobian block
2544  hblocks.push_back(e.second);
2545  // Update offsets
2546  hoffset = h_offsets.at(e.first + 1);
2547  }
2548  // Add trailing empty block, if needed
2549  if (hoffset < h_offsets.back())
2550  hblocks.push_back(MX(vdefref.numel(), h_offsets.back() - hoffset));
2551  // Add new block row to vblocks
2552  vblocks.push_back(horzcat(hblocks));
2553  // Keep track of the offset handled in jac_brow
2554  voffset_last = voffset_end;
2555  }
2556  }
2557  // Add empty trailing row to vblocks, if any
2558  if (voffset_last != voffset_end) {
2559  vblocks.push_back(MX(voffset_end - voffset_last, h_offsets.back()));
2560  }
2561  // Return additional term in jac_vdef_v
2562  return vertcat(vblocks);
2563 }

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

Referenced by create().

◆ lift()

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

Definition at line 2198 of file dae_builder_internal.cpp.

2198  {
2199  // Not tested if w is non-empty before
2200  if (size(Category::W) > 0) casadi_warning("'w' already has entries");
2201  // Expressions where the variables are also being used
2202  std::vector<MX> ex;
2203  for (size_t v : indices(Category::X)) ex.push_back(variable(variable(variable(v).der).bind).v);
2204  for (size_t v : indices(Category::Q)) ex.push_back(variable(variable(variable(v).der).bind).v);
2205  for (size_t v : indices(Category::ALG)) ex.push_back(variable(v).v);
2206  // Lift expressions
2207  std::vector<MX> new_w, new_wdef;
2208  Dict opts{{"lift_shared", lift_shared}, {"lift_calls", lift_calls},
2209  {"prefix", "w_"}, {"suffix", ""}, {"offset", static_cast<casadi_int>(size(Category::W))}};
2210  extract(ex, new_w, new_wdef, opts);
2211  // Register as dependent variables
2212  for (size_t i = 0; i < new_w.size(); ++i) {
2213  Variable& v = new_variable(new_w.at(i).name());
2214  v.v = new_w.at(i);
2215  Variable& v_beq = assign(v.name, new_wdef.at(i));
2216  v.bind = v_beq.index;
2217  indices(Category::W).push_back(v.index);
2218  }
2219  // Get expressions
2220  auto it = ex.begin();
2221  for (size_t v : indices(Category::X)) variable(variable(variable(v).der).bind).v = *it++;
2222  for (size_t v : indices(Category::Q)) variable(variable(variable(v).der).bind).v = *it++;
2223  for (size_t v : indices(Category::ALG)) variable(v).v = *it++;
2224  // Consistency check
2225  casadi_assert_dev(it == ex.end());
2226 }

References casadi::ALG, assign(), casadi::Variable::bind, der(), casadi::Variable::index, indices(), casadi::Variable::name, new_variable(), casadi::Q, 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 702 of file dae_builder_internal.cpp.

702  {
703  // Check if file exists
705  if (Filesystem::is_enabled()) {
706  casadi_error("Could not open file '" + filename + "'.");
707  } else {
708  casadi_error("Could not open file '" + filename + "'. "
709  "Note that, since CasADi was compiled without WITH_GHC_FILESYSTEM=ON, "
710  "passing fmu files to DaeBuilder is unsupported. "
711  "You could manually unzip the FMU file and "
712  "pass the path to the unzipped directory instead.");
713  }
714  }
715 
716  // Ensure no variables already
717  casadi_assert(n_variables() == 0, "Instance already has variables");
718 
719  // Parse XML file
720  XmlFile xml_file("tinyxml");
721  XmlNode fmi_desc = xml_file.parse(filename)[0]; // One child; fmiModelDescription
722 
723  // Read FMU version
724  fmi_version_ = fmi_desc.attribute<std::string>("fmiVersion", "");
725  if (fmi_version_.rfind("1.", 0) == 0) {
726  // FMI 1.0: Only for symbolic FMUs
727  fmi_major_ = 1;
728  } else if (fmi_version_.rfind("2.", 0) == 0) {
729  // FMI 2.0
730  fmi_major_ = 2;
731  } else if (fmi_version_.rfind("3.", 0) == 0) {
732  // FMI 3
733  fmi_major_ = 3;
734  } else {
735  casadi_error("Unknown FMI version: " + fmi_version_);
736  }
737 
738  // Read attributes
739  model_name_ = fmi_desc.attribute<std::string>("modelName", "");
740  instantiation_token_ = fmi_desc.attribute<std::string>(
741  fmi_major_ >= 3 ? "instantiationToken" : "guid");
742  description_ = fmi_desc.attribute<std::string>("description", "");
743  author_ = fmi_desc.attribute<std::string>("author", "");
744  copyright_ = fmi_desc.attribute<std::string>("copyright", "");
745  license_ = fmi_desc.attribute<std::string>("license", "");
746  generation_tool_ = fmi_desc.attribute<std::string>("generationTool", "");
747  generation_date_and_time_ = fmi_desc.attribute<std::string>("generationDateAndTime", "");
748  variable_naming_convention_ = fmi_desc.attribute<std::string>("variableNamingConvention", "");
749  if (fmi_major_ >= 3) {
750  nzero_ = 0; // In FMI 3: Obtain from binary
751  } else {
752  nzero_ = fmi_desc.attribute<casadi_int>("numberOfEventIndicators", 0);
753  }
754 
755  // Process DefaultExperiment
756  if (fmi_desc.has_child("DefaultExperiment")) {
757  import_default_experiment(fmi_desc["DefaultExperiment"]);
758  }
759 
760  // Process ModelExchange
761  bool has_model_exchange = false;
762  if (fmi_desc.has_child("ModelExchange")) {
763  has_model_exchange = true;
764  import_model_exchange(fmi_desc["ModelExchange"]);
765  }
766 
767  // Process ModelVariables
768  casadi_assert(fmi_desc.has_child("ModelVariables"), "Missing 'ModelVariables'");
769  import_model_variables(fmi_desc["ModelVariables"]);
770 
771  // No explicit independent variable (FMI 2): expose the automatically added time variable
772  if (orig_time_index_ == -1 && !ignore_time_ && n_variables() > 0) categorize(0, Category::T);
773 
774  // Process model structure
775  if (fmi_desc.has_child("ModelStructure")) {
776  import_model_structure(fmi_desc["ModelStructure"]);
777  }
778 
779  // Is a symbolic representation available?
780  symbolic_ = false; // use DLL by default
781 
782  // Look for serialized CasADi expressions
784  try {
785  // Load function oracle from file
786  Function oracle = Function::load(resource_.path()
787  + "/extra/org.casadi.fmi-ls-serialization/oracle.casadi");
788  // Get expressions
789  auto oracle_in = oracle.mx_in();
790  auto oracle_out = oracle(oracle_in);
791  // Get all substitutions
792  std::vector<MX> v, vdef;
793  for (auto& arg : oracle_in) {
794  // Loop over symbolic primitives
795  for (auto& vp : arg.primitives()) {
796  // Find the variable
797  size_t ind = find(vp.name());
798  // Add to list of replacements
799  v.push_back(vp);
800  vdef.push_back(var(ind));
801  }
802  }
803  // Substitute expressions in oracle_in, oracle_out
804  oracle_in = substitute(oracle_in, v, vdef);
805  oracle_out = substitute(oracle_out, v, vdef);
806  // Process dependent variables
807  MX w_all = oracle_in.at(oracle.index_in("w"));
808  std::vector<MX> w = w_all.primitives();
809  std::vector<MX> wdef = w_all.split_primitives(oracle_out.at(oracle.index_out("wdef")));
810  // Loop over w
811  for (size_t i = 0; i < w.size(); ++i) {
812  // Find variable, corresponding assignment variable
813  Variable& w_i = variable(w[i].name());
814  Variable& assign_w_i = variable("__assign__" + w[i].name() + "__");
815  // Reclassify assign_w_i as dependent variable and update expression
816  categorize(assign_w_i.index, Category::CALCULATED);
817  assign_w_i.parent = w_i.index;
818  assign_w_i.v = wdef[i];
819  // Map binding equation
820  w_i.bind = assign_w_i.index;
821  }
822 
823  // Substitute expressions for algebraic variables, if any
824  if (size(Category::ALG) > 0) {
825  std::vector<MX> alg;
826  // Collect expressions to be replaced
827  for (size_t i : indices(Category::ALG)) {
828  alg.push_back(variable(i).v);
829  }
830  // Substitute expressions
831  MX alg_all = vertcat(alg);
832  alg = alg_all.split_primitives(oracle_out.at(oracle.index_out("alg")));
833  auto alg_it = alg.begin();
834  // Update expressions
835  for (size_t i : indices(Category::ALG)) {
836  // Substitute expression
837  Variable& v = variable(i);
839  v.v = *alg_it++;
840  }
841  }
842 
843  symbolic_ = true;
844  } catch (std::exception& e) {
845  // May want to output this information
846  (void)e; // unused
847  }
848  }
849 
850 
851  std::string onnx_filename = resource_.path()
852  + "/extra/org.lacemodelica.ls-onnx-serialization/model.onnx";
853  if (Filesystem::exists(onnx_filename)) {
854  // Load and symbolically import the ONNX model
855  GraphBuilder b(onnx_filename);
856  Function oracle = b.create("oracle", {{"symbolic", true}});
857 
858  // Get expressions
859  auto oracle_in = oracle.mx_in();
860  auto oracle_out = oracle(oracle_in);
861 
862  // Build mapping from input index to variable name
863  std::vector<std::string> input_var_names;
864  for (casadi_int i = 0; i < oracle.n_in(); ++i) {
865  input_var_names.push_back(oracle.name_in(i));
866  }
867 
868  // Get all substitutions: map oracle variables to DaeBuilder variables
869  std::vector<MX> v, vdef;
870  for (auto& arg : oracle_in) {
871  // Loop over symbolic primitives
872  for (auto& vp : arg.primitives()) {
873  // Find the variable by name
874  size_t ind = find(vp.name());
875  // Add to list of replacements
876  v.push_back(vp);
877  vdef.push_back(var(ind));
878  }
879  }
880 
881  // Substitute expressions in oracle outputs
882  oracle_out = substitute(oracle_out, v, vdef);
883 
884  // Process each output based on its category
885  // Output naming convention from Lace Modelica:
886  // eq[N] - equation residual (lhs - rhs = 0)
887  // init_eq[N] - initial equation residual
888  // start[N] - start value for variable at input index N
889  // min[N] - minimum bound for variable at input index N
890  // max[N] - maximum bound for variable at input index N
891  for (size_t i = 0; i < oracle_out.size(); ++i) {
892  std::string out_name = oracle.name_out(i);
893  MX expr = oracle_out[i];
894 
895  // Parse the output name to determine category
896  bool is_init_eq = out_name.substr(0, 8) == "init_eq[";
897  bool is_dyn_eq = out_name.substr(0, 3) == "eq[" && !is_init_eq;
898 
899  if (is_dyn_eq || is_init_eq) {
900  // Equation residual: (lhs - rhs) = 0, so lhs = rhs
901  // Check if it's a subtraction with 2 dependencies
902  if (expr.n_dep() == 2) {
903  MX lhs = expr.dep(0); // The left-hand side
904  MX rhs = expr.dep(1); // The right-hand side
905 
906  if (is_init_eq) {
907  // Initial equation: set initial value for the variable
908  if (lhs.is_symbolic()) {
909  std::string var_name = lhs.name();
910  set_init(var_name, rhs);
911  }
912  } else {
913  // Dynamic equation
914  if (lhs.is_symbolic()) {
915  // Simple variable on LHS: var = rhs (binding equation)
916  std::string var_name = lhs.name();
917  size_t var_ind = find(var_name);
918  Variable& var_ref = variable(var_ind);
919  var_ref.bind = assign(var_name, rhs).index;
920  } else {
921  // Complex expression on LHS (e.g., m*c_p*der(T))
922  // Use implicit residual form: 0 = lhs - rhs
923  eq(MX(0), lhs - rhs, Dict());
924  }
925  }
926  }
927  } else if (out_name.substr(0, 6) == "start[") {
928  // Start value: start[N] where N is the input index
929  size_t bracket_pos = out_name.find('[');
930  size_t close_pos = out_name.find(']');
931  if (bracket_pos != std::string::npos && close_pos != std::string::npos) {
932  casadi_int idx = std::stoi(out_name.substr(bracket_pos + 1, close_pos - bracket_pos - 1));
933  if (idx >= 0 && idx < static_cast<casadi_int>(input_var_names.size())) {
934  std::string var_name = input_var_names[idx];
935  Variable& var_ref = variable(var_name);
936  // If it's a constant, we can evaluate it
937  if (expr.is_constant()) {
938  DM dm_val = static_cast<DM>(expr);
939  var_ref.start = std::vector<double>(dm_val->begin(), dm_val->end());
940  }
941  // TODO(jgillis): Handle symbolic start expressions
942  }
943  }
944  } else if (out_name.substr(0, 4) == "min[") {
945  // Minimum bound: min[N] where N is the input index
946  size_t bracket_pos = out_name.find('[');
947  size_t close_pos = out_name.find(']');
948  if (bracket_pos != std::string::npos && close_pos != std::string::npos) {
949  casadi_int idx = std::stoi(out_name.substr(bracket_pos + 1, close_pos - bracket_pos - 1));
950  if (idx >= 0 && idx < static_cast<casadi_int>(input_var_names.size())) {
951  std::string var_name = input_var_names[idx];
952  Variable& var_ref = variable(var_name);
953  // If it's a constant, we can evaluate it
954  if (expr.is_constant()) {
955  DM dm_val = static_cast<DM>(expr);
956  var_ref.min = static_cast<double>(dm_val);
957  }
958  // TODO(jgillis): Handle symbolic min expressions
959  }
960  }
961  } else if (out_name.substr(0, 4) == "max[") {
962  // Maximum bound: max[N] where N is the input index
963  size_t bracket_pos = out_name.find('[');
964  size_t close_pos = out_name.find(']');
965  if (bracket_pos != std::string::npos && close_pos != std::string::npos) {
966  casadi_int idx = std::stoi(out_name.substr(bracket_pos + 1, close_pos - bracket_pos - 1));
967  if (idx >= 0 && idx < static_cast<casadi_int>(input_var_names.size())) {
968  std::string var_name = input_var_names[idx];
969  Variable& var_ref = variable(var_name);
970  // If it's a constant, we can evaluate it
971  if (expr.is_constant()) {
972  DM dm_val = static_cast<DM>(expr);
973  var_ref.max = static_cast<double>(dm_val);
974  }
975  // TODO(jgillis): Handle symbolic max expressions
976  }
977  }
978  }
979  }
980 
981  symbolic_ = true;
982  }
983 
984  // Add symbolic binding equations
985  if (fmi_desc.has_child("equ:BindingEquations")) {
986  symbolic_ = true;
987  import_binding_equations(fmi_desc["equ:BindingEquations"]);
988  }
989 
990  // Add symbolic initial equations
991  if (fmi_desc.has_child("equ:InitialEquations")) {
992  symbolic_ = true;
993  import_initial_equations(fmi_desc["equ:InitialEquations"]);
994  }
995 
996  // Add symbolic dynamic equations
997  if (fmi_desc.has_child("equ:DynamicEquations")) {
998  symbolic_ = true;
999  import_dynamic_equations(fmi_desc["equ:DynamicEquations"]);
1000  }
1001 
1002  // Ensure model equations are available, binary or symbolic
1003  casadi_assert(symbolic_ || has_model_exchange,
1004  "FMU must be of ModelExchange type or be symbolic (FMUX)");
1005 }
void import_model_structure(const XmlNode &n)
void import_dynamic_equations(const XmlNode &eqs)
void import_model_variables(const XmlNode &modvars)
Read ModelVariables.
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
const std::vector< std::string > & name_in() const
Get the names of all inputs, in order.
Definition: function.cpp:1113
casadi_int index_in(const std::string &name) const
Get the index of the input with a given name.
Definition: function.cpp:1121
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
static Function load(const std::string &filename)
Read a function from a file written by save.
Definition: function.cpp:1546
casadi_int index_out(const std::string &name) const
Get the index of the output with a given name; unknown names raise an error.
Definition: function.cpp:1129
const std::vector< std::string > & name_out() const
Get the names of all outputs, in order.
Definition: function.cpp:1117
Matrix< double > DM
Definition: dm_fwd.hpp:33
std::string filename(const std::string &path)
Definition: ghc.cpp:55

References casadi::ALG, assign(), casadi::XmlNode::attribute(), author_, casadi::Variable::bind, casadi::CALCULATED, categorize(), copyright_, casadi::MX::dep(), description_, enable_ls_serialization_, eq(), casadi::Filesystem::exists(), casadi::filename(), find(), fmi_major_, fmi_version_, generation_date_and_time_, generation_tool_, casadi::XmlNode::has_child(), ignore_time_, import_binding_equations(), import_default_experiment(), import_dynamic_equations(), import_initial_equations(), import_model_exchange(), import_model_structure(), import_model_variables(), casadi::Variable::index, casadi::Function::index_in(), casadi::Function::index_out(), indices(), instantiation_token_, casadi::MX::is_constant(), casadi::Filesystem::is_enabled(), casadi::MX::is_symbolic(), license_, casadi::Function::load(), casadi::Variable::max, casadi::Variable::min, model_name_, casadi::Function::mx_in(), casadi::MX::n_dep(), casadi::Function::n_in(), n_variables(), casadi::MX::name(), name(), casadi::Function::name_in(), casadi::Function::name_out(), nzero_, oracle(), orig_time_index_, casadi::Variable::parent, casadi::XmlFile::parse(), casadi::Resource::path(), casadi::MX::primitives(), resource_, set_init(), size(), casadi::MX::split_primitives(), casadi::Variable::start, symbolic_, casadi::T, casadi::Variable::v, var(), variable(), and variable_naming_convention_.

◆ n_mem()

size_t casadi::DaeBuilderInternal::n_mem ( ) const

Definition at line 2040 of file dae_builder_internal.cpp.

2040  {
2041  size_t n = 0;
2042  for (const Variable* v : variables_) n += v->numel;
2043  return n;
2044 }

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 4627 of file dae_builder_internal.cpp.

4627  {
4628  std::vector<std::string> r(ind.size());
4629  for (size_t i = 0; i < r.size(); ++i) r[i] = name(ind[i]);
4630  return r;
4631 }

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 2046 of file dae_builder_internal.cpp.

2047  {
2048  // Name check
2049  casadi_assert(!name.empty(), "Name is empty string");
2050  // Try to find the component
2051  casadi_assert(!has(name), "Variable \"" + name + "\" already exists.");
2052  // Index of the variable
2053  size_t ind = n_variables();
2054  // Add to the map of all variables
2055  varind_[name] = ind;
2056  variables_.push_back(new Variable(ind, name, dimension, expr));
2057  // Clear cache
2058  clear_cache_ = true;
2059  // Return reference to new variable
2060  return *variables_.back();
2061 }
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 2654 of file dae_builder_internal.cpp.

2654  {
2655  casadi_assert(symbolic_, "DaeBuilder oracle only available if symbolic representation");
2656 
2657  // Clear cache now, if necessary
2658  if (clear_cache_) clear_cache();
2659  // Create an MX oracle, if needed
2660  if (oracle_[false][elim_w][lifted_calls].is_null()) {
2661  // Oracle function inputs and outputs
2662  std::vector<MX> f_in, f_out, v;
2663  std::vector<std::string> f_in_name, f_out_name;
2664  // Index for wdef
2665  casadi_int wdef_ind = -1;
2666  // Options consistency check
2667  casadi_assert(!(elim_w && lifted_calls), "Incompatible options");
2668  // Do we need to substitute out v
2669  bool subst_v = false;
2670  // Do we need to substitute out c
2671  bool subst_c = false;
2672  // Collect all DAE input variables
2673  for (Category cat : input_categories()) {
2674  v = inputs(cat);
2675  if (elim_w && cat == Category::W) {
2676  if (!v.empty()) subst_v = true;
2677  } else if (cat == Category::C) {
2678  if (!v.empty()) subst_c = true;
2679  } else {
2680  if (v.empty()) {
2681  f_in.push_back(MX(0, 1));
2682  } else {
2683  f_in.push_back(vertcat(v));
2684  }
2685  f_in_name.push_back(to_string(cat));
2686  }
2687  }
2688 
2689  // Collect all DAE output variables
2690  for (Category cat : output_categories()) {
2691  f_out_name.push_back(to_string(cat));
2692  v = outputs(cat);
2693  if (v.empty()) {
2694  f_out.push_back(MX(0, 1));
2695  } else {
2696  if (cat == Category::WDEF) wdef_ind = f_out.size();
2697  f_out.push_back(vertcat(v));
2698  }
2699  }
2700  // Eliminate v from inputs
2701  if (subst_v) {
2702  // Dependent variable definitions
2703  std::vector<MX> wdef = outputs(Category::WDEF);
2704  // Perform in-place substitution
2705  substitute_inplace(var(Category::W), wdef, f_out, false);
2706  } else if (lifted_calls && wdef_ind >= 0) {
2707  // Dependent variable definitions
2708  std::vector<MX> wdef = outputs(Category::WDEF);
2709  // Remove references to call nodes
2710  for (MX& wdefref : wdef) {
2711  if (wdefref.is_output()) wdefref = MX::zeros(wdefref.sparsity());
2712  }
2713  // Save to oracle outputs
2714  f_out.at(wdef_ind) = vertcat(wdef);
2715  }
2716  // Substitute out c from output expressions
2717  if (subst_c) {
2718  // Expression for c and corresponding definition
2719  auto c = var(Category::C);
2720  std::vector<casadi::MX> cdef;
2721  for (size_t i = 0; i < c.size(); ++i) {
2722  cdef.push_back(variable(Category::C, i).value);
2723  }
2724  // Substitute out
2725  f_out = substitute(f_out, c, cdef);
2726  }
2727 
2728  // Create oracle
2729  oracle_[false][elim_w][lifted_calls]
2730  = Function("mx_oracle", f_in, f_out, f_in_name, f_out_name);
2731  }
2732  // Return MX oracle, if requested
2733  if (!sx) return oracle_[false][elim_w][lifted_calls];
2734  // Create SX oracle, if needed
2735  Function& sx_oracle = oracle_[true][elim_w][lifted_calls];
2736  if (sx_oracle.is_null()) sx_oracle = oracle_[false][elim_w][lifted_calls].expand("sx_oracle");
2737  // Return SX oracle reference
2738  return sx_oracle;
2739 }
std::vector< MX > cdef() const
Definitions of dependent constants.
void clear_cache() const
Problem structure has changed: Clear cache.
Function expand() const
Convert an MXFunction into an equivalent SXFunction.
Definition: function.cpp:312
std::vector< Category > input_categories()

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

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

◆ outputs() [1/2]

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

Definition at line 2255 of file dae_builder_internal.cpp.

2255  {
2256  // If defined by index set
2257  switch (ind) {
2258  case Category::Y: // fall-through
2259  case Category::ZERO: // fall-through
2260  case Category::ALG:
2261  return var(indices(ind));
2262  default: break;
2263  }
2264  // Otherwise: Defined by corresponding input category
2265  Category cat = input_category(ind);
2266 
2267  // Return object
2268  std::vector<MX> ret;
2269  ret.reserve(size(cat));
2270  // Handle different categories
2271  switch (ind) {
2272  case Category::ODE: // fall-through
2273  case Category::QUAD:
2274  // Differential state
2275  for (size_t v : indices(cat)) {
2276  const Variable& x = variable(v);
2277  if (x.der >= 0) {
2278  // Derivative variable
2279  ret.push_back(variable(variable(x.der).bind).v);
2280  } else if (x.variability == Variability::DISCRETE) {
2281  // Discrete variable - derivative is zero
2282  ret.push_back(MX::zeros(x.v.sparsity()));
2283  } else {
2284  // Missing ODE?
2285  casadi_error("Missing derivative for " + str(x.name));
2286  }
2287  }
2288  break;
2289  case Category::DDEF: // fall-through
2290  case Category::WDEF:
2291  // Defined by binding expression
2292  for (size_t d : indices(cat)) ret.push_back(variable(variable(d).bind).v);
2293  break;
2294  default: break;
2295  }
2296  return ret;
2297 }
Category input_category(Category cat)

References casadi::ALG, casadi::Variable::bind, casadi::DDEF, casadi::Variable::der, casadi::DISCRETE, indices(), casadi::input_category(), casadi::Variable::name, casadi::ODE, casadi::QUAD, 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(), outputs(), prune(), sort(), and transition().

◆ outputs() [2/2]

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

Definition at line 2299 of file dae_builder_internal.cpp.

2299  {
2300  std::vector<MX> ret(ind.size());
2301  for (casadi_int i=0; i<ind.size(); ++i) {
2302  ret[i] = vertcat(outputs(ind[i]));
2303  }
2304  return ret;
2305 }

References outputs().

◆ pack_fmu()

std::string casadi::DaeBuilderInternal::pack_fmu ( const Dict &  files,
const Dict &  opts 
) const

Definition at line 1350 of file dae_builder_internal.cpp.

1350  {
1351  std::string path = name_ + ".fmu";
1352  for (auto&& op : opts) {
1353  if (op.first == "path") {
1354  path = op.second.to_string();
1355  } else {
1356  casadi_error("No such option: " + op.first);
1357  }
1358  }
1359  return FmuInternal::pack_fmu(files, path);
1360 }
static std::string pack_fmu(const Dict &files, const std::string &path)
Definition: fmu.cpp:830

References name_, casadi::FmuInternal::pack_fmu(), and casadi::path().

◆ prune()

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

Definition at line 1819 of file dae_builder_internal.cpp.

1819  {
1820  // Function inputs and outputs
1821  std::vector<MX> f_in, f_out, v;
1822  std::vector<std::string> f_in_name, f_out_name;
1823  // Collect all DAE input variables with at least one entry, skip u
1824  for (Category cat : input_categories()) {
1825  if (prune_p && cat == Category::P) continue;
1826  if (prune_u && cat == Category::U) continue;
1827  v = inputs(cat);
1828  if (!v.empty()) {
1829  f_in.push_back(vertcat(v));
1830  f_in_name.push_back(to_string(cat));
1831  }
1832  }
1833  // Collect all DAE output variables with at least one entry
1834  for (Category cat : output_categories()) {
1835  v = outputs(cat);
1836  if (!v.empty()) {
1837  f_out.push_back(vertcat(v));
1838  f_out_name.push_back(to_string(cat));
1839  }
1840  }
1841  // Create a function
1842  Function f("prune_fcn", f_in, f_out, f_in_name, f_out_name);
1843  // Mark which variables are free
1844  std::vector<bool> free_variables(n_variables(), false);
1845  for (const std::string& s : f.get_free()) {
1846  auto it = varind_.find(s);
1847  casadi_assert(it != varind_.end(), "No such variable: \"" + s + "\".");
1848  free_variables.at(it->second) = true;
1849  }
1850  // Prune p
1851  if (prune_p) {
1852  size_t np = 0;
1853  for (size_t i = 0; i < size(Category::P); ++i) {
1854  if (!free_variables.at(indices(Category::P).at(i))) {
1855  indices(Category::P).at(np++) = indices(Category::P).at(i);
1856  }
1857  }
1858  indices(Category::P).resize(np);
1859  }
1860  // Prune u
1861  if (prune_u) {
1862  size_t nu = 0;
1863  std::vector<size_t>& u = indices(Category::U);
1864  for (size_t i = 0; i < u.size(); ++i) {
1865  if (!free_variables.at(u.at(i))) u.at(nu++) = u.at(i);
1866  }
1867  u.resize(nu);
1868  }
1869 }

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

◆ qualified_name()

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

Definition at line 2071 of file dae_builder_internal.cpp.

2071  {
2072  // std::stringstream to assemble name
2073  std::stringstream qn;
2074  bool first_part = true;
2075  if (att) *att = Attribute::VALUE; // value attribute by default
2076 
2077  // Loop over name parts
2078  for (casadi_int i=0; i<nn.size(); ++i) {
2079  // Get the name part
2080  std::string np = nn[i].attribute<std::string>("name");
2081 
2082  // Check if an attribute
2083  if (np == "$START") {
2084  if (att) {
2085  *att = Attribute::START;
2086  } else {
2087  casadi_error("Ignoring attribute " + np);
2088  }
2089  continue;
2090  } else if (np == "$PRE") {
2091  casadi_warning("$PRE attribute has not been implemented, ignoring");
2092  continue;
2093  }
2094 
2095  // Add the name part to the variable name
2096  if (!first_part) qn << ".";
2097  qn << np;
2098 
2099  // Get the index, if any
2100  if (nn[i].size()>0) {
2101  casadi_int ind;
2102  nn[i]["exp:ArraySubscripts"]["exp:IndexExpression"]["exp:IntegerLiteral"].get(&ind);
2103  qn << "[" << ind << "]";
2104  }
2105 
2106  // Dot prefix if a additional parts
2107  first_part = false;
2108  }
2109 
2110  // Return the name
2111  return qn.str();
2112 }

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 4078 of file dae_builder_internal.cpp.

4078  {
4079  // Default behaviour should be no known structure
4080  casadi_assert(n.has_attribute("dependencies"),
4081  "Default 'dependencies' not implemented");
4082  // Read list of dependencies
4083  std::vector<casadi_int> r = n.attribute<std::vector<casadi_int>>("dependencies", {});
4084  // Get corresponding variable index
4085  for (casadi_int& e : r) {
4086  if (fmi_major_ >= 3) {
4087  // Value reference is given
4088  e = vrmap_.at(static_cast<unsigned int>(e));
4089  } else {
4090  // Convert XML index to variable index
4091  e = convert_index(e);
4092  }
4093  }
4094  // Return list of dependencies
4095  return r;
4096 }

References casadi::XmlNode::attribute(), convert_index(), 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 4098 of file dae_builder_internal.cpp.

4099  {
4100  // Quick return if node not provided
4101  if (!n.has_attribute("dependenciesKind")) {
4102  // No structure known, assume general dependency
4103  return std::vector<DependenciesKind>(ndep, DependenciesKind::DEPENDENT);
4104  } else {
4105  // Read list of strings
4106  auto dk_str = n.attribute<std::vector<std::string>>("dependenciesKind");
4107  // Make sure expected length
4108  casadi_assert(dk_str.size() == ndep, "Mismatching 'dependenciesKind'");
4109  // Convert to enums
4110  std::vector<DependenciesKind> r(ndep);
4111  for (size_t i = 0; i < ndep; ++i) {
4112  r[i] = to_enum<DependenciesKind>(dk_str[i]);
4113  }
4114  return r;
4115  }
4116 }

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 1513 of file dae_builder_internal.cpp.

1513  {
1514  try {
1515  const std::string& fullname = node.name;
1516 
1517  if (fullname == "fun:If") {
1518  // Expression for condition, if and else
1519  const XmlNode& cond = node["fun:Condition"];
1520  const XmlNode& then_stmt = node["fun:Statements"];
1521  const XmlNode& else_stmt = node["fun:Else"];
1522  // Only scalar expression implemented
1523  casadi_assert(cond.size() == 1, "Only one condition in if expression supported");
1524  casadi_assert(then_stmt.size() == 1, "Only one then statement in if expression supported");
1525  casadi_assert(else_stmt.size() == 1, "Only one else statement in if expression supported");
1526  return if_else(read_expr(cond[0]), read_expr(then_stmt[0]), read_expr(else_stmt[0]));
1527  }
1528 
1529  if (fullname.find("exp:")== std::string::npos) {
1530  casadi_error("DaeBuilderInternal::read_expr: unknown - expression is supposed to "
1531  "start with 'exp:' , got " + fullname);
1532  }
1533 
1534  // Chop the 'exp:'
1535  std::string name = fullname.substr(4);
1536 
1537  // The switch below is alphabetical, and can be thus made more efficient,
1538  // for example by using a switch statement of the first three letters,
1539  // if it would ever become a bottleneck
1540  if (name=="Add") {
1541  return read_expr(node[0]) + read_expr(node[1]);
1542  } else if (name=="Acos") {
1543  return acos(read_expr(node[0]));
1544  } else if (name=="Asin") {
1545  return asin(read_expr(node[0]));
1546  } else if (name=="Atan") {
1547  return atan(read_expr(node[0]));
1548  } else if (name=="Cos") {
1549  return cos(read_expr(node[0]));
1550  } else if (name=="Der") {
1551  return variable(read_variable(node[0]).der_of).v;
1552  } else if (name=="Div") {
1553  return read_expr(node[0]) / read_expr(node[1]);
1554  } else if (name=="Exp") {
1555  return exp(read_expr(node[0]));
1556  } else if (name=="Identifier") {
1557  return read_identifier(node);
1558  } else if (name=="IntegerLiteral" || name=="BooleanLiteral") {
1559  casadi_int val;
1560  node.get(&val);
1561  return val;
1562  } else if (name=="Instant") {
1563  double val;
1564  node.get(&val);
1565  return val;
1566  } else if (name=="Log") {
1567  return log(read_expr(node[0]));
1568  } else if (name=="Not") { // Logical not
1569  return !read_expr(node[0]);
1570  } else if (name=="LogLeq") { // Logical less than equal
1571  return read_expr(node[0]) <= read_expr(node[1]);
1572  } else if (name=="LogGeq") { // Logical greater than equal
1573  return read_expr(node[0]) >= read_expr(node[1]);
1574  } else if (name=="LogLt") { // Logical less than
1575  return read_expr(node[0]) < read_expr(node[1]);
1576  } else if (name=="LogGt") { // Logical greater than
1577  return read_expr(node[0]) > read_expr(node[1]);
1578  } else if (name=="Max") {
1579  return fmax(read_expr(node[0]), read_expr(node[1]));
1580  } else if (name=="Min") {
1581  return fmin(read_expr(node[0]), read_expr(node[1]));
1582  } else if (name=="Mul") { // Multiplication
1583  return read_expr(node[0]) * read_expr(node[1]);
1584  } else if (name=="Neg") {
1585  return -read_expr(node[0]);
1586  } else if (name=="NoEvent") {
1587  // NOTE: This is a workaround, we assume that whenever NoEvent occurs,
1588  // what is meant is a switch
1589  casadi_int n = node.size();
1590 
1591  // Default-expression
1592  MX ex = read_expr(node[n-1]);
1593 
1594  // Evaluate ifs
1595  for (casadi_int i=n-3; i>=0; i -= 2) {
1596  ex = if_else(read_expr(node[i]), read_expr(node[i+1]), ex);
1597  }
1598 
1599  return ex;
1600  } else if (name=="Pow") {
1601  return pow(read_expr(node[0]), read_expr(node[1]));
1602  } else if (name=="Pre") {
1603  casadi_warning("Ignoring pre attribute");
1604  return read_expr(node[0]);
1605  } else if (name=="RealLiteral") {
1606  double val;
1607  node.get(&val);
1608  return val;
1609  } else if (name=="Sin") {
1610  return sin(read_expr(node[0]));
1611  } else if (name=="Sqrt") {
1612  return sqrt(read_expr(node[0]));
1613  } else if (name=="StringLiteral") {
1614  casadi_error(node.text);
1615  } else if (name=="Sub") {
1616  return read_expr(node[0]) - read_expr(node[1]);
1617  } else if (name=="Tan") {
1618  return tan(read_expr(node[0]));
1619  } else if (name=="Time") {
1620  return var(indices(Category::T).at(0));
1621  } else if (name=="TimedVariable") {
1622  return read_variable(node[0]).v;
1623  } else if (name=="FunctionCall") {
1624  // Get the name of the function
1625  std::string fname = qualified_name(node["exp:Name"]);
1626  casadi_warning("Function call to '" + fname + "' incomplete");
1627  // Collect the arguments
1628  const XmlNode& args = node["exp:Arguments"];
1629  std::vector<MX> farg(args.size());
1630  for (casadi_int i = 0; i < args.size(); ++i) {
1631  // Lift input arguments
1632  Variable& v = new_variable("w_" + str(size(Category::W)));
1633  // Add to list of variables
1634  indices(Category::W).push_back(v.index);
1635  // Set binding expression
1636  Variable& v_beq = assign(v.name, read_expr(args[i]));
1637  v.bind = v_beq.index;
1638  // Add to list of function arguments
1639  farg[i] = v.v;
1640  }
1641  // Return argument (scalar for now)
1642  Variable& r = new_variable("w_" + str(size(Category::W)));
1643  // Add to list of variables
1644  indices(Category::W).push_back(r.index);
1645  // Return output variable
1646  return r.v;
1647  } else if (name=="Array") {
1648  // Array of arguments
1649  std::vector<MX> v(node.size());
1650  for (casadi_int i = 0; i < v.size(); ++i) v[i] = read_expr(node[i]);
1651  return vertcat(v);
1652  }
1653 
1654  // throw error if reached this point
1655  casadi_error("Unknown node: " + name);
1656  } catch (std::exception& e) {
1657  THROW_ERROR_NODE("read_expr", node, e.what());
1658  return {};
1659  }
1660 }
static std::string qualified_name(const XmlNode &nn, Attribute *att=nullptr)
Get the qualified name.
double if_else(double x, double y, double z)
Definition: calculus.hpp:296

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 1500 of file dae_builder_internal.cpp.

1500  {
1501  Attribute att; // attribute
1502  Variable& v = read_variable(node, &att);
1503  if (att == Attribute::VALUE) {
1504  return v.v;
1505  } else if (att == Attribute::START) {
1506  return v.start;
1507  } else {
1508  casadi_error("Cannot read attribute " + to_string(att));
1509  return MX();
1510  }
1511 }

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 = nullptr 
)
protected

Definition at line 1488 of file dae_builder_internal.cpp.

1488  {
1489  try {
1490  // Qualified name
1491  std::string qn = qualified_name(node, att);
1492 
1493  return variable(qn);
1494  } catch (std::exception& e) {
1495  THROW_ERROR_NODE("read_variable", node, e.what());
1496  //return {};
1497  }
1498 }

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 3789 of file dae_builder_internal.cpp.

3789  {
3790  // Create a unique name for the reinit variable
3791  std::string reinit_name = unique_name("__reinit__" + name + "__");
3792  // Add a new dependent variable defined by val
3793  Variable& v = add(reinit_name, Causality::LOCAL, Variability::CONTINUOUS, val, Dict());
3794  // Classify as a defined variable
3795  categorize(v.index, Category::CALCULATED);
3796  v.parent = variable(name).index;
3797  // Return the variable name
3798  return v;
3799 }

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 3434 of file dae_builder_internal.cpp.

3434  {
3435  for (auto it = v.begin(); it != v.end(); ++it) {
3436  if (*it == ind) {
3437  v.erase(it);
3438  return;
3439  }
3440  }
3441  casadi_error("Variable not found");
3442 }

Referenced by categorize(), and set_causality().

◆ reorder() [1/2]

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

Definition at line 1800 of file dae_builder_internal.cpp.

1800  {
1801  reorder(to_string(cat), indices(cat), v);
1802 }
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 1804 of file dae_builder_internal.cpp.

1805  {
1806  // Check if the sizes match
1807  casadi_assert(ind.size() == v.size(), "Cannot reorder " + n + ": "
1808  + str(v.size()) + " elements provided for " + str(ind.size()) + " components.");
1809  // Mark elements to be set
1810  std::vector<bool> set(n_variables(), false);
1811  for (size_t i : v) set.at(i) = true;
1812  // Make sure all elements are present
1813  for (size_t i : ind) casadi_assert(set.at(i), "Cannot reorder " + n + ": "
1814  + variable(i).name + " is missing.");
1815  // Set the new order
1816  std::copy(v.begin(), v.end(), ind.begin());
1817 }

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

◆ reset()

void casadi::DaeBuilderInternal::reset ( )
protected

Definition at line 4679 of file dae_builder_internal.cpp.

4679  {
4680  for (Variable* v : variables_) {
4681  std::fill(v->value.begin(), v->value.end(), nan);
4682  v->stringvalue = std::string();
4683  }
4684 }

References casadi::nan, and variables_.

◆ sanity_check()

void casadi::DaeBuilderInternal::sanity_check ( ) const

Definition at line 2063 of file dae_builder_internal.cpp.

2063  {
2064  // Time
2065  if (size(Category::T) > 0) {
2066  casadi_assert(size(Category::T) == 1, "At most one time variable allowed");
2067  casadi_assert(variable(Category::T, 0).v.is_scalar(), "Non-scalar time t");
2068  }
2069 }

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 4706 of file dae_builder_internal.cpp.

4706  {
4707  variable(name).set_attribute(a, val);
4708 }
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 4710 of file dae_builder_internal.cpp.

4711  {
4712  if (name.size() == val.size()) {
4713  // One scalar value per variable
4714  for (size_t k = 0; k < name.size(); ++k) variable(name[k]).set_attribute(a, val[k]);
4715  } else if (val.size() == size(a, name)) {
4716  // One vector slice per variable
4717  auto val_it = val.begin();
4718  for (size_t k = 0; k < name.size(); ++k) {
4719  Variable& v = variable(name[k]);
4720  auto val_next = val_it + v.size(a);
4721  v.set_attribute(a, std::vector<double>(val_it, val_next));
4722  val_it = val_next;
4723  }
4724  } else {
4725  casadi_error("Cannot set attribute " + to_string(a) + ": Argument is of length " +
4726  str(val.size()) + ", expected number of elements (" + str(size(a, name))
4727  + ") or number of variables (" + str(name.size()) + ")");
4728  }
4729 }

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 3541 of file dae_builder_internal.cpp.

3541  {
3542  // Get variable reference
3543  Variable& v = variable(ind);
3544  // Quick return if same category
3545  if (v.category == cat) return;
3546  // Update category: See comment for public interface
3547  switch (cat) {
3548  case Category::U:
3549  if (v.category == Category::P || v.category == Category::C) {
3551  return;
3552  }
3553  break;
3554  case Category::P:
3555  if (v.category == Category::U || v.category == Category::C) {
3557  return;
3558  }
3559  break;
3560  case Category::C:
3561  if (v.category == Category::U || v.category == Category::P) {
3563  return;
3564  }
3565  break;
3566  case Category::X:
3567  // Can convert from Q, T or unused derivative variable
3568  if (v.category == Category::Q || v.category == Category::T
3569  || (v.category == Category::NUMEL && v.has_der())) {
3570  categorize(v.index, Category::X);
3571  return;
3572  }
3573  break;
3574  case Category::Q:
3575  // Can convert from X or T, but only if not in right-hand-side, or from unused derivative
3576  if ((!v.in_rhs && (v.category == Category::X || v.category == Category::T))
3577  || (v.category == Category::NUMEL && v.has_der())) {
3578  categorize(v.index, Category::Q);
3579  return;
3580  }
3581  break;
3582  case Category::T:
3583  // Can convert from X, Q, or unused derivative, but existing T must be removed first
3584  if (v.category == Category::X || v.category == Category::Q
3585  || (v.category == Category::NUMEL && v.has_der())) {
3586  if (has_t()) {
3587  // Move existing T variable to X or remove
3588  Variable& t_old = variable(indices(Category::T).front());
3589  categorize(t_old.index, t_old.in_rhs ? Category::X : Category::NUMEL);
3590  }
3591  categorize(v.index, Category::T);
3592  return;
3593  }
3594  break;
3595  case Category::NUMEL:
3596  // If not in right-hand-side, can convert from X, Q, or T
3597  if (!v.in_rhs && (v.category == Category::X
3598  || v.category == Category::Q
3599  || v.category == Category::T)) {
3600  categorize(v.index, Category::NUMEL);
3601  return;
3602  }
3603  default:
3604  break;
3605  }
3606  // Failure if reached this point
3607  casadi_error("Cannot change category of " + v.name + " from '"
3608  + to_string(v.category) + "' to '" + to_string(cat) + "'");
3609 }
void set_variability(size_t ind, Variability variability)
Set variability.
bool has_t() const
Is there a time variable?

References casadi::C, categorize(), casadi::Variable::category, casadi::CONTINUOUS, casadi::FIXED, casadi::Variable::has_der(), has_t(), casadi::Variable::in_rhs, casadi::Variable::index, indices(), casadi::Variable::name, casadi::NUMEL, casadi::P, casadi::Q, set_variability(), casadi::T, 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 3448 of file dae_builder_internal.cpp.

3448  {
3449  // Get variable reference
3450  Variable& v = variable(ind);
3451  // Quick return if same causality
3452  if (v.causality == causality) return;
3453  // Handle permitted changes
3454  if (v.causality == Causality::LOCAL && causality == Causality::OUTPUT) {
3455  // Add to list of outputs
3456  insert(indices(Category::Y), v.index);
3457  } else if (v.causality == Causality::OUTPUT && causality == Causality::LOCAL) {
3458  // Remove from list of outputs
3459  remove(indices(Category::Y), v.index);
3460  } else {
3461  // Not possible
3462  casadi_error("Cannot change causality of " + v.name + " which is of category '"
3463  + to_string(v.category) + "'");
3464  }
3465  // Success: Update causality
3466  v.causality = causality;
3467  // The oracle would need to be regenerated after changes to the categorization
3468  clear_cache_ = true;
3469 }

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

◆ set_init()

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

Definition at line 3801 of file dae_builder_internal.cpp.

3801  {
3802  // Find the algebraic variable
3803  Variable& v = variable(name);
3804  // If variable already has an initial binding equation, remove it
3805  if (!v.ieq.is_empty()) {
3806  // Remove from list of initial equations
3807  auto old_loc = std::find(init_.begin(), init_.end(), v.index);
3808  if (old_loc == init_.end()) casadi_error("Corrupted list of initial equations");
3809  init_.erase(old_loc);
3810  v.ieq = MX();
3811  }
3812  // If right-hand-side is empty, just erase
3813  if (init_rhs.is_empty()) return;
3814 
3815  // Make sure not already in list of initial equations
3816  if (std::find(init_.begin(), init_.end(), v.index) != init_.end()) {
3817  casadi_error("Initial equation for " + name + " has already been set");
3818  }
3819  // Add to list of initial equations
3820  init_.push_back(v.index);
3821  v.ieq = init_rhs;
3822 }
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(), and load_fmi_description().

◆ 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 4752 of file dae_builder_internal.cpp.

4753  {
4754  variable(name).set_attribute(a, val);
4755 }

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 4757 of file dae_builder_internal.cpp.

4758  {
4759  casadi_assert(name.size() == val.size(), "Dimension mismatch");
4760  for (size_t k = 0; k < name.size(); ++k) variable(name[k]).set_attribute(a, val[k]);
4761 }

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

◆ set_variability()

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

Definition at line 3475 of file dae_builder_internal.cpp.

3475  {
3476  // Get variable reference
3477  Variable& v = variable(ind);
3478  // Quick return if same variability
3479  if (v.variability == variability) return;
3480  // Update category: See comment for public interface
3481  switch (v.category) {
3482  case Category::U:
3484  // Make fixed parameter
3485  categorize(v.index, Category::C);
3486  v.causality = Causality::PARAMETER;
3487  } else if (variability == Variability::TUNABLE) {
3488  // Make tunable parameter
3489  categorize(v.index, Category::P);
3490  v.causality = Causality::PARAMETER;
3491  } else {
3492  // Not possible
3493  casadi_error("The variability of " + v.name + ", which is of category 'u', can only be "
3494  "changed to 'fixed' (for no category) or 'tunable' (for category 'p')");
3495  }
3496  break;
3497  case Category::P:
3499  // Make input
3500  categorize(v.index, Category::U);
3501  v.causality = Causality::INPUT;
3502  } else if (variability == Variability::FIXED) {
3503  // Make fixed parameter
3504  categorize(v.index, Category::C);
3505  v.causality = Causality::PARAMETER;
3506  } else {
3507  // Not possible
3508  casadi_error("The variability of " + v.name + ", which is of category 'p', can only be "
3509  "changed to 'continuous' (for category 'u') or 'fixed' (for no category)");
3510  }
3511  break;
3512  case Category::C:
3514  // Make input
3515  categorize(v.index, Category::U);
3516  v.causality = Causality::INPUT;
3517  } else if (variability == Variability::TUNABLE) {
3518  // Make tunable parameter
3519  categorize(v.index, Category::P);
3520  v.causality = Causality::PARAMETER;
3521  } else {
3522  // Not possible
3523  casadi_error("The variability of " + v.name + ", which is of type 'c', can only be "
3524  "changed to 'continuous' (for category 'u') or 'tunable' (for category 'p')");
3525  }
3526  break;
3527  default:
3528  casadi_error("Cannot change variability of " + v.name + ", which is of category '"
3529  + to_string(v.category) + "'");
3530  }
3531  // Success: Update variability
3532  v.variability = variability;
3533  // The oracle would need to be regenerated after changes to the categorization
3534  clear_cache_ = true;
3535 }

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 4763 of file dae_builder_internal.cpp.

4763  {
4764  casadi_int r = 0;
4765  for (const auto& n : name) r += variable(n).size(a);
4766  return r;
4767 }
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 1763 of file dae_builder_internal.cpp.

1763  {
1764  casadi_assert(is_acyclic(cat), "Sorting not supported for category " + to_string(cat));
1765  // Find new order based on interdependencies
1766  std::vector<MX> v = var(indices(cat)), vdef = outputs(dependent_definition(cat));
1767  sort_dependent(v, vdef);
1768  // New order
1769  std::vector<size_t> new_order;
1770  for (const MX& e : v) new_order.push_back(find(e.name()));
1771  std::copy(new_order.begin(), new_order.end(), indices(cat).begin());
1772 }
static void sort_dependent(std::vector< MX > &v, std::vector< MX > &vdef)

References casadi::dependent_definition(), find(), indices(), casadi::is_acyclic(), outputs(), 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 2816 of file dae_builder_internal.cpp.

2816  {
2817  // Form function to evaluate dependent variables
2818  Function vfcn("vfcn", {vertcat(v)}, {vertcat(vdef)}, {"v"}, {"vdef"},
2819  Dict{{"allow_free", true}});
2820  // Is any variable vector-valued?
2821  bool any_vector_valued = false;
2822  for (const MX& v_i : v) {
2823  casadi_assert(!v_i.is_empty(), "Cannot have zero-dimension dependent variables");
2824  if (!v_i.is_scalar()) {
2825  any_vector_valued = true;
2826  break;
2827  }
2828  }
2829  // If vector-valued variables exists, collapse them
2830  if (any_vector_valued) {
2831  // New v corresponding to one scalar input per v argument
2832  std::vector<MX> vfcn_in(v), vfcn_arg(v);
2833  for (size_t i = 0; i < v.size(); ++i) {
2834  if (!v.at(i).is_scalar()) {
2835  vfcn_in.at(i) = MX::sym(v.at(i).name());
2836  vfcn_arg.at(i) = repmat(vfcn_in.at(i), v.at(i).size1());
2837  }
2838  }
2839  // Wrap vfcn
2840  std::vector<MX> vfcn_out = vfcn(vertcat(vfcn_arg));
2841  vfcn_out = vertsplit(vfcn_out.at(0), offset(v));
2842  // Collapse vector-valued outputs
2843  for (size_t i = 0; i < v.size(); ++i) {
2844  if (!v.at(i).is_scalar()) {
2845  vfcn_out.at(i) = dot(vfcn_out.at(i), vfcn_out.at(i));
2846  }
2847  }
2848  // Recreate vfcn with smaller dimensions
2849  vfcn = Function(vfcn.name(), {vertcat(vfcn_in)}, {vertcat(vfcn_out)},
2850  vfcn.name_in(), vfcn.name_out(), {{"allow_free", true}});
2851  }
2852  // Calculate sparsity pattern of dvdef/dv
2853  Sparsity Jv = vfcn.jac_sparsity(0, 0);
2854  // Add diagonal (equation is v-vdef = 0)
2855  Jv = Jv + Sparsity::diag(Jv.size1());
2856  // If lower triangular, nothing to do
2857  if (Jv.is_triu()) return;
2858  // Perform a Dulmage-Mendelsohn decomposition
2859  std::vector<casadi_int> rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock;
2860  (void)Jv.btf(rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock);
2861  // Reorder the variables
2862  std::vector<MX> tmp(v.size());
2863  for (size_t k = 0; k < v.size(); ++k) tmp[k] = v.at(colperm.at(k));
2864  std::copy(tmp.begin(), tmp.end(), v.begin());
2865  // Reorder the equations
2866  for (size_t k = 0; k < v.size(); ++k) tmp[k] = vdef.at(rowperm.at(k));
2867  std::copy(tmp.begin(), tmp.end(), vdef.begin());
2868 }
static Sparsity diag(casadi_int nrow)
Create a diagonal sparsity pattern.
Definition: sparsity.hpp:723
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 1774 of file dae_builder_internal.cpp.

1774  {
1775  // Make sure lengths agree
1776  casadi_assert(z_order.size() == size(Category::Z), "Dimension mismatch");
1777  // Mark existing components in z
1778  std::vector<bool> old_z(n_variables(), false);
1779  for (size_t i : indices(Category::Z)) old_z.at(i) = true;
1780  // New vector of z
1781  std::vector<size_t> new_z;
1782  new_z.reserve(z_order.size());
1783  for (const std::string& s : z_order) {
1784  size_t i = find(s);
1785  casadi_assert(old_z.at(i), "Variable \"" + s + "\" is not an algebraic variable.");
1786  new_z.push_back(i);
1787  }
1788  // Success: Update z
1789  std::copy(new_z.begin(), new_z.end(), indices(Category::Z).begin());
1790 }

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

◆ start_all()

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

Definition at line 1392 of file dae_builder_internal.cpp.

1392  {
1393  std::vector<double> r;
1394  for (const Variable* v : variables_) {
1395  for (double s : v->start) r.push_back(s);
1396  }
1397  return r;
1398 }

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 4731 of file dae_builder_internal.cpp.

4732  {
4733  std::string r;
4734  variable(name).get_attribute(a, &r);
4735  return r;
4736 }

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 4738 of file dae_builder_internal.cpp.

4739  {
4740  // Allocate return
4741  std::vector<std::string> r;
4742  r.reserve(size(a, name));
4743  // Get contribution from each variable
4744  std::string r1;
4745  for (const auto& n : name) {
4746  variable(n).get_attribute(a, &r1);
4747  r.push_back(r1);
4748  }
4749  return r;
4750 }

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

◆ tear()

void casadi::DaeBuilderInternal::tear ( )

Definition at line 1871 of file dae_builder_internal.cpp.

1871  {
1872  // Get residual variables, iteration variables
1873  std::vector<std::string> res, iv, iv_on_hold;
1874  tearing_variables(&res, &iv, &iv_on_hold);
1875  // All iteration variables
1876  std::set<std::string> iv_set;
1877  for (auto& e : iv) iv_set.insert(e);
1878  for (auto& e : iv_on_hold) iv_set.insert(e);
1879  // Remove any (held or not held) iteration variables, equations from z and alg
1880  size_t sz = 0;
1881  for (size_t k = 0; k < size(Category::Z); ++k) {
1882  if (!iv_set.count(variable(Category::Z, k).name)) {
1883  // Non-iteration variable: Keep
1884  indices(Category::Z).at(k) = indices(Category::Z).at(sz);
1885  sz++;
1886  }
1887  }
1888  indices(Category::Z).resize(sz);
1889  // Remove any (held or not held) iteration variables, equations from u
1890  sz = 0;
1891  for (size_t k = 0; k < size(Category::U); ++k) {
1892  if (!iv_set.count(variable(Category::U, k).name)) {
1893  // Non-iteration variable: Keep
1894  indices(Category::U).at(k) = indices(Category::U).at(sz++);
1895  }
1896  }
1897  indices(Category::U).resize(sz);
1898  // Add algebraic variables
1899  for (auto& e : iv) indices(Category::Z).push_back(find(e));
1900  // Add output variables
1901  for (auto& e : iv_on_hold) indices(Category::U).push_back(find(e));
1902 }
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 1904 of file dae_builder_internal.cpp.

1905  {
1906  // Clear output
1907  if (res) res->clear();
1908  if (iv) iv->clear();
1909  if (iv_on_hold) iv_on_hold->clear();
1910  // Prefix
1911  const std::string res_prefix = "res__";
1912  // Collect hold indices
1913  std::vector<MX> r_hold, iv_hold;
1914  // Any hold variable?
1915  bool any_hold = false;
1916  // Collect residual variables, iteration variables, expression for hold indices, if any
1917  for (const Variable* v : variables_) {
1918  // Residual variables are specified with a "res__" prefix
1919  if (v->name.rfind(res_prefix, 0) == 0) {
1920  // Process iteration variable name, names of hold markers
1921  std::string iv_name, res_hold_name, iv_hold_name;
1922  // Iteration variable, hold markers are contained in the remainder of the name
1923  try {
1924  size_t pos = res_prefix.size();
1925  // Find the next "__", if any
1926  size_t end = v->name.find("__", pos);
1927  if (end == std::string::npos) end = v->name.size();
1928  // Look up iteration variable
1929  iv_name = v->name.substr(pos, end - pos);
1930  // Ensure that the variable exists
1931  casadi_assert(has(iv_name), "No such variable: " + iv_name);
1932  // Get hold indices, if any
1933  if (end != v->name.size()) {
1934  // Find next "__", read hold index for residual variable
1935  pos = end + 2;
1936  end = v->name.find("__", pos);
1937  if (end == std::string::npos) end = v->name.size();
1938  res_hold_name = v->name.substr(pos, end - pos);
1939  // Ensure that the variable exists
1940  casadi_assert(has(res_hold_name), "No such variable: " + res_hold_name);
1941  // The remainder of the name contains iv_hold_name
1942  if (end != v->name.size()) {
1943  iv_hold_name = v->name.substr(end + 2);
1944  casadi_assert(has(iv_hold_name), "No such variable: " + iv_hold_name);
1945  }
1946  }
1947  } catch (std::exception& e) {
1948  // Generate warning
1949  casadi_warning("Cannot process residual variable: " + v->name + ":" +
1950  std::string(e.what()));
1951  continue;
1952  }
1953  // Add residual variable, corresponding hold variable
1954  if (res_hold_name.empty()) {
1955  r_hold.push_back(false);
1956  } else {
1957  any_hold = true;
1958  r_hold.push_back(variable(res_hold_name).v);
1959  casadi_assert(r_hold.back().is_scalar(), "Non-scalar hold variable for " + res_hold_name);
1960  }
1961  if (res) res->push_back(v->name);
1962  // Add iteration variable, corresponding hold variable
1963  if (iv_hold_name.empty()) {
1964  iv_hold.push_back(false);
1965  } else {
1966  any_hold = true;
1967  iv_hold.push_back(variable(iv_hold_name).v);
1968  casadi_assert(iv_hold.back().is_scalar(), "Non-scalar hold variable for " + iv_hold_name);
1969  }
1970  if (iv) iv->push_back(iv_name);
1971  }
1972  }
1973  // Evaluate hold variables, if needed
1974  if (any_hold) {
1975  try {
1976  // Code below needs to be refactored
1977  casadi_error("not implemented");
1978 #if 0
1979  // Get start attributes for p
1980  Function startfun_p = attribute_fun("startfun_p", {}, {"start_p"});
1981  if (startfun_p.has_free()) {
1982  casadi_error("startfun has free variables: " + str(startfun_p.get_free()));
1983  }
1984  DM p0 = startfun_p(std::vector<DM>{}).at(0);
1985  // Create function to evaluate the hold attributes
1986  Function holdfun("holdfun", {vertcat(var(p_))},
1987  {vertcat(r_hold), vertcat(iv_hold)}, {"p"}, {"r_hold", "iv_hold"});
1988  if (holdfun.has_free()) {
1989  casadi_error("holdfun has free variables: " + str(holdfun.get_free()));
1990  }
1991  // Evaluate holdfun to get hold attributes
1992  std::vector<DM> hold0 = holdfun(std::vector<DM>{p0});
1993  std::vector<double> r_hold0 = hold0.at(0).nonzeros();
1994  std::vector<double> iv_hold0 = hold0.at(1).nonzeros();
1995  casadi_assert_dev(r_hold0.size() == res->size());
1996  casadi_assert_dev(iv_hold0.size() == iv->size());
1997  // Remove hold variables from residual variables
1998  size_t sz = 0;
1999  if (res) {
2000  for (size_t k = 0; k < res->size(); ++k) {
2001  if (!static_cast<bool>(r_hold0.at(k))) {
2002  res->at(sz++) = res->at(k);
2003  }
2004  }
2005  res->resize(sz);
2006  }
2007  // Remove hold variables from iteration variables
2008  sz = 0;
2009  for (size_t k = 0; k < iv->size(); ++k) {
2010  if (!static_cast<bool>(iv_hold0.at(k))) {
2011  if (iv) iv->at(sz++) = iv->at(k);
2012  } else {
2013  if (iv_on_hold) iv_on_hold->push_back(iv->at(k));
2014  }
2015  }
2016  if (iv) iv->resize(sz);
2017 #endif
2018  } catch (std::exception& e) {
2019  // Warning instead of error
2020  casadi_warning("Failed to evaluate hold variables: " + std::string(e.what()));
2021  }
2022  }
2023 }

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 3102 of file dae_builder_internal.cpp.

3102  {
3103  casadi_assert(has_t(), "No explicit time variable");
3104  return var(indices(Category::T).at(0));
3105 }

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 2977 of file dae_builder_internal.cpp.

2977  {
2978  // If no events, return null
2979  if (when_.empty()) return Function();
2980 
2981  // If just a single event, create an event function with a dummy index input
2982  if (when_.size() == 1) return transition(fname, 0, true);
2983 
2984  // Create separate transition functions for each event
2985  std::vector<Function> f_all;
2986  for (casadi_int i = 0; i < when_.size(); ++i) {
2987  f_all.push_back(transition(fname + "_" + str(i), i));
2988  }
2989 
2990  // Make the last function the default value in the switch
2991  Function f_def = f_all.back();
2992  f_all.pop_back();
2993 
2994  // Create a switch function
2995  return Function::conditional(fname, f_all, f_def);
2996 }
static Function conditional(const std::string &name, const std::vector< Function > &f, const Function &f_def, const Dict &opts=Dict())
Create a function that selects one of several functions by an index input.
Definition: function.cpp:917

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 2928 of file dae_builder_internal.cpp.

2929  {
2930 
2931  // Make sure that the index is valid
2932  casadi_assert(index >= 0 && index < when_.size(), "Illegal event index");
2933 
2934  // Get input expressions for the oracle
2935  const Function& oracle = this->oracle();
2936  std::vector<MX> oracle_in = oracle.mx_in();
2937 
2938  // Input expressions for the event functions, without the index
2939  std::vector<MX> ret_in(DYN_NUM_IN);
2940  ret_in[DYN_T] = oracle_in.at(oracle.index_in("t"));
2941  ret_in[DYN_X] = oracle_in.at(oracle.index_in("x"));
2942  ret_in[DYN_Z] = oracle_in.at(oracle.index_in("z"));
2943  ret_in[DYN_P] = oracle_in.at(oracle.index_in("p"));
2944  ret_in[DYN_U] = oracle_in.at(oracle.index_in("u"));
2945 
2946  // When equation left-hand sides and right-hand sides
2947  std::vector<MX> when_lhs, when_rhs;
2948  for (size_t eq : when_.at(index).second) {
2949  auto v = variable(eq).parent;
2950  when_lhs.push_back(variable(v).v);
2951  when_rhs.push_back(variable(eq).v);
2952  }
2953 
2954  // Expressions for x and z after event
2955  std::vector<MX> ret_out = {ret_in[DYN_X], ret_in[DYN_Z]};
2956  ret_out = MX::substitute(ret_out, when_lhs, when_rhs);
2957 
2958  // Remove dependent variables, if any
2959  if (size(Category::W) > 0) {
2960  // Dependent variable definitions
2961  std::vector<MX> wdef = outputs(Category::WDEF);
2962  // Perform in-place substitution
2963  substitute_inplace(var(Category::W), wdef, ret_out, false);
2964  }
2965 
2966  // Check if a dummy index input needes to be included
2967  if (dummy_index_input) {
2968  // Create a function with the transition input signature
2969  ret_in.insert(ret_in.begin(), MX());
2970  return Function(fname, ret_in, ret_out, event_in(), event_out());
2971  } else {
2972  // Create a function with the DAE function input signature
2973  return Function(fname, ret_in, ret_out, dyn_in(), event_out());
2974  }
2975 }
static MX substitute(const MX &ex, const MX &v, const MX &vdef)
Definition: mx.cpp:1518
std::vector< std::string > event_in()
Get the input scheme of an event transition function.
Definition: integrator.cpp:256
std::vector< std::string > event_out()
Get the output scheme of an event transition function.
Definition: integrator.cpp:260
@ DYN_NUM_IN
Definition: integrator.hpp:917

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::index_in(), casadi::Function::mx_in(), oracle(), outputs(), casadi::Variable::parent, size(), casadi::MX::substitute(), var(), variable(), casadi::W, casadi::WDEF, and when_.

Referenced by export_fmu(), and transition().

◆ type_name()

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

Definition at line 390 of file dae_builder_internal.hpp.

390 {return "DaeBuilderInternal";}

◆ unique_name()

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

Definition at line 2148 of file dae_builder_internal.cpp.

2149  {
2150  // Check if the variable exists without any prefix
2151  if (allow_no_prefix && !has(prefix)) return prefix;
2152  // Find the first available index
2153  size_t i = 0;
2154  while (has(prefix + str(i))) i++;
2155  // Return the unique name
2156  return prefix + str(i);
2157 }

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

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

◆ update_dependencies()

void casadi::DaeBuilderInternal::update_dependencies ( ) const

Definition at line 1178 of file dae_builder_internal.cpp.

1178  {
1179  // Get oracle function
1180  const Function& oracle = this->oracle(false, true);
1181  // Dependendencies of the ODE right-hand-side
1182  Sparsity dode_dxT = oracle.jac_sparsity(oracle.index_out("ode"), oracle.index_in("x")).T();
1183  Sparsity dode_duT = oracle.jac_sparsity(oracle.index_out("ode"), oracle.index_in("u")).T();
1184  Sparsity dode_dzT = oracle.jac_sparsity(oracle.index_out("ode"), oracle.index_in("z")).T();
1185  for (casadi_int i = 0; i < size(Category::X); ++i) {
1186  // Get output variable
1187  const Variable& xdot = variable(variable(Category::X, i).der);
1188  // Clear dependencies
1189  xdot.dependencies.clear();
1190  // Dependencies on states
1191  for (casadi_int k = dode_dxT.colind(i); k < dode_dxT.colind(i + 1); ++k) {
1192  casadi_int j = dode_dxT.row(k);
1193  xdot.dependencies.push_back(variable(Category::X, j).value_reference);
1194  }
1195  // Dependencies on algebraic variables
1196  for (casadi_int k = dode_dzT.colind(i); k < dode_dzT.colind(i + 1); ++k) {
1197  casadi_int j = dode_dzT.row(k);
1198  xdot.dependencies.push_back(variable(Category::Z, j).value_reference);
1199  }
1200  // Dependencies on controls
1201  for (casadi_int k = dode_duT.colind(i); k < dode_duT.colind(i + 1); ++k) {
1202  casadi_int j = dode_duT.row(k);
1203  xdot.dependencies.push_back(variable(Category::U, j).value_reference);
1204  }
1205  }
1206  // Dependendencies of the outputs and event indicators
1208  auto catname = to_string(cat);
1209  const std::vector<size_t>& oind = indices(cat);
1210  Sparsity dy_dxT = oracle.jac_sparsity(oracle.index_out(catname), oracle.index_in("x")).T();
1211  Sparsity dy_dzT = oracle.jac_sparsity(oracle.index_out(catname), oracle.index_in("z")).T();
1212  Sparsity dy_duT = oracle.jac_sparsity(oracle.index_out(catname), oracle.index_in("u")).T();
1213  for (casadi_int i = 0; i < oind.size(); ++i) {
1214  // Get output variable
1215  const Variable& y = variable(oind.at(i));
1216  // Clear dependencies
1217  y.dependencies.clear();
1218  // Dependencies on states
1219  for (casadi_int k = dy_dxT.colind(i); k < dy_dxT.colind(i + 1); ++k) {
1220  casadi_int j = dy_dxT.row(k);
1221  y.dependencies.push_back(variable(Category::X, j).value_reference);
1222  }
1223  // Dependencies on algebraic variables
1224  for (casadi_int k = dy_dzT.colind(i); k < dy_dzT.colind(i + 1); ++k) {
1225  casadi_int j = dy_dzT.row(k);
1226  y.dependencies.push_back(variable(Category::Z, j).value_reference);
1227  }
1228  // Dependencies on controls
1229  for (casadi_int k = dy_duT.colind(i); k < dy_duT.colind(i + 1); ++k) {
1230  casadi_int j = dy_duT.row(k);
1231  y.dependencies.push_back(variable(Category::U, j).value_reference);
1232  }
1233  }
1234  }
1235 }
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get the sparsity patterns of all Jacobian blocks.
Definition: function.cpp:1092

References casadi::ALG, casadi::Sparsity::colind(), casadi::Variable::dependencies, der(), casadi::Function::index_in(), casadi::Function::index_out(), indices(), casadi::Function::jac_sparsity(), oracle(), casadi::Sparsity::row(), size(), casadi::to_string(), casadi::U, variable(), casadi::X, casadi::Y, casadi::Z, and casadi::ZERO.

Referenced by export_fmu().

◆ var() [1/5]

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

Definition at line 461 of file dae_builder_internal.hpp.

461 {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 455 of file dae_builder_internal.hpp.

455 {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 4586 of file dae_builder_internal.cpp.

4586  {
4587  std::vector<MX> ret;
4588  ret.reserve(ind.size());
4589  for (size_t i : ind) ret.push_back(var(i));
4590  return ret;
4591 }

References var().

◆ var() [5/5]

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

Definition at line 4582 of file dae_builder_internal.cpp.

4582  {
4583  return variable(ind).v;
4584 }

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

◆ variability()

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

Definition at line 3471 of file dae_builder_internal.cpp.

3471  {
3472  return variable(ind).variability;
3473 }

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 433 of file dae_builder_internal.hpp.

433 {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 434 of file dae_builder_internal.hpp.

434  {
435  return variable(indices(cat).at(ind));
436  }

◆ variable() [3/8]

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

Access a variable by expression

Definition at line 447 of file dae_builder_internal.hpp.

447 {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 448 of file dae_builder_internal.hpp.

448 {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 441 of file dae_builder_internal.hpp.

441 {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 442 of file dae_builder_internal.hpp.

442 {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 428 of file dae_builder_internal.hpp.

428 {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.

215  {
216 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
217  auto* w = weak_ref_.load(std::memory_order_acquire);
218  if (!w) {
219  auto* nw = new GenericWeakRef<Shared, Internal>(static_cast<Internal*>(this));
220  GenericWeakRef<Shared, Internal>* expected = nullptr;
221  if (weak_ref_.compare_exchange_strong(
222  expected, nw, std::memory_order_release, std::memory_order_acquire)) {
223  w = nw;
224  } else {
225  delete nw; // lost the race; another thread published first
226  w = expected;
227  }
228  }
229  return w;
230 #else
231  if (weak_ref_==nullptr) {
232  weak_ref_ = new GenericWeakRef<Shared, Internal>(static_cast<Internal*>(this));
233  }
234  return weak_ref_;
235 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
236  }

◆ when()

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

Definition at line 3742 of file dae_builder_internal.cpp.

3743  {
3744  // Read options
3745  for (auto&& op : opts) {
3746  casadi_error("No such option: " + op.first);
3747  }
3748  // Convert condition into a smooth zero crossing condition
3749  MX zero;
3750  if (cond.is_op(OP_LT)) {
3751  zero = cond.dep(0) - cond.dep(1); // Reformulate a < b to a - b < 0
3752  } else if (cond.is_op(OP_LE)) {
3753  casadi_error("Only strict inequality in zero-crossing conditions permitted, got: "
3754  + str(cond));
3755  } else {
3756  casadi_error("Cannot parse zero-crossing condition: " + str(cond));
3757  }
3758  // Create a new dependent variable for the event indicator
3760  zero, Dict());
3761  indices(Category::ZERO).push_back(e.index);
3762  categorize(e.index, Category::CALCULATED);
3763  // Convert to legacy format, pending refactoring
3764  std::vector<MX> all_lhs, all_rhs;
3765  std::vector<size_t> all_eqs;
3766  for (auto&& eq : eqs) {
3767  Variable& ee = variable(eq);
3768  casadi_assert_dev(ee.category == Category::CALCULATED);
3769  all_lhs.push_back(var(ee.parent));
3770  all_rhs.push_back(ee.v);
3771  all_eqs.push_back(ee.index);
3772  }
3773  when_.push_back(std::make_pair(e.index, all_eqs));
3774 }
@ 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(), casadi::Variable::index, indices(), casadi::MX::is_op(), casadi::LOCAL, casadi::OP_LE, casadi::OP_LT, casadi::Variable::parent, casadi::str(), unique_name(), casadi::Variable::v, var(), variable(), when_, and casadi::ZERO.

Referenced by import_dynamic_equations().

Friends And Related Function Documentation

◆ DaeBuilder

friend class DaeBuilder
friend

Definition at line 219 of file dae_builder_internal.hpp.

◆ FmuFunction

friend class FmuFunction
friend

Definition at line 221 of file dae_builder_internal.hpp.

Referenced by fmu_fun().

◆ FmuInternal

friend class FmuInternal
friend

Definition at line 220 of file dae_builder_internal.hpp.

◆ Variable

friend class Variable
friend

Definition at line 222 of file dae_builder_internal.hpp.

Referenced by new_variable().

Member Data Documentation

◆ author_

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

Definition at line 511 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 512 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ debug_

bool casadi::DaeBuilderInternal::debug_
protected

◆ der_

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

Definition at line 551 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 510 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ detect_quad_

bool casadi::DaeBuilderInternal::detect_quad_
protected

◆ enable_ls_dae_

bool casadi::DaeBuilderInternal::enable_ls_dae_
protected

Definition at line 504 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and import_model_structure().

◆ enable_ls_serialization_

bool casadi::DaeBuilderInternal::enable_ls_serialization_
protected

Definition at line 504 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and load_fmi_description().

◆ fmi_major_

casadi_int casadi::DaeBuilderInternal::fmi_major_
protected

◆ fmi_version_

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

Definition at line 507 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ fmutol_

double casadi::DaeBuilderInternal::fmutol_
protected

Definition at line 502 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 665 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 515 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ generation_tool_

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

Definition at line 514 of file dae_builder_internal.hpp.

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

◆ ignore_time_

bool casadi::DaeBuilderInternal::ignore_time_
protected

◆ indices_

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

Definition at line 560 of file dae_builder_internal.hpp.

Referenced by DaeBuilderInternal(), and indices().

◆ init_

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

Definition at line 563 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 551 of file dae_builder_internal.hpp.

Referenced by import_model_structure().

◆ instantiation_token_

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

Definition at line 509 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 660 of file dae_builder_internal.hpp.

Referenced by add_lc(), and create().

◆ license_

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

Definition at line 513 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ model_identifier_

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

Definition at line 523 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 508 of file dae_builder_internal.hpp.

Referenced by load_fmi_description().

◆ name_

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

◆ nzero_

casadi_int casadi::DaeBuilderInternal::nzero_
protected

◆ oracle_

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

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

Definition at line 670 of file dae_builder_internal.hpp.

Referenced by clear_cache(), and oracle().

◆ orig_time_index_

casadi_int casadi::DaeBuilderInternal::orig_time_index_
protected

◆ provides_adjoint_derivatives_

bool casadi::DaeBuilderInternal::provides_adjoint_derivatives_
protected

◆ provides_directional_derivatives_

bool casadi::DaeBuilderInternal::provides_directional_derivatives_
protected

◆ resource_

Resource casadi::DaeBuilderInternal::resource_
protected

◆ source_files_

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

Definition at line 527 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 536 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 516 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 554 of file dae_builder_internal.hpp.

Referenced by add(), 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 566 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: