fmu_function.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_FMU_FUNCTION_HPP
27 #define CASADI_FMU_FUNCTION_HPP
28 
29 #include "function_internal.hpp"
30 #include "fmu.hpp"
31 #include "finite_differences.hpp"
32 
34 
35 namespace casadi {
36 
37 // Forward declarations
38 class DaeBuilderInternal;
39 class FmuFunction;
40 struct InputStruct;
41 
42 // Memory object
43 struct CASADI_EXPORT FmuMemory : public FunctionMemory {
44  // Function object
45  const FmuFunction& self;
46  // Evaluation inputs
47  const double** arg;
48  // Evaluation outputs
49  double** res;
50  // Work vector for star coloring
51  casadi_int* star_iw;
52  // Extended Jacobian
53  double *jac_nz;
54  // Extended Hessian
55  double *hess_nz;
56  // Adjoint seeds, sensitivities being calculated
57  double *aseed, *asens, *pert_asens;
58  // Memory for Jacobian calculation
60  // Instance memory
61  void* instance;
62  // Additional (slave) memory objects
63  std::vector<FmuMemory*> slaves;
64  // Input and output buffers
65  std::vector<double> ibuf_, obuf_;
66  // Seeds, sensitivities
67  std::vector<double> isens_, osens_;
68  // Which inputs and outputs have been marked
69  std::vector<bool> imarked_, omarked_;
70  // Derivative with respect to
71  std::vector<size_t> wrt_;
72  // Current known/unknown variables
73  std::vector<size_t> id_in_, id_out_;
74  // Which perturbations are permitted
75  std::vector<bool> in_bounds_;
76  // Flip sign?
77  std::vector<bool> flip_;
78  // Value references
79  std::vector<unsigned int> vr_in_, vr_out_;
80  // Work vector (reals)
81  std::vector<double> v_in_, v_out_, d_in_, d_out_, fd_out_, v_pert_;
82  // Constructor
83  explicit FmuMemory(const FmuFunction& self) : self(self), instance(nullptr) {}
84 };
85 
87 enum class Parallelization {SERIAL, OPENMP, THREAD, NUMEL};
88 
90 CASADI_EXPORT std::string to_string(Parallelization v);
91 
92 // Types of inputs
93 enum class InputType {REG, FWD, ADJ, OUT, ADJ_OUT};
94 
95 // Input structure
96 struct CASADI_EXPORT InputStruct {
97  // Type of input
98  InputType type;
99  // Corresponding index in Fmu
100  size_t ind;
101  // Parse an input string
102  static InputStruct parse(const std::string& n, const Fmu* fmu,
103  std::vector<std::string>* name_in = 0,
104  std::vector<std::string>* name_out = 0);
105 };
106 
107 // Types of inputs
108 enum class OutputType {REG, FWD, ADJ, JAC, JAC_TRANS, JAC_ADJ_OUT, JAC_REG_ADJ, HESS};
109 
110 // Output structure
111 struct CASADI_EXPORT OutputStruct {
112  // Type of input
113  OutputType type;
114  // Output index in Fmu
115  size_t ind;
116  // With-respect-to index in Fmu
117  size_t wrt;
118  // Selection
119  size_t rbegin, rend, cbegin, cend;
120  // Parse an output string
121  static OutputStruct parse(const std::string& n, const Fmu* fmu,
122  std::vector<std::string>* name_in = 0,
123  std::vector<std::string>* name_out = 0);
124  // Constructor
125  OutputStruct() : ind(-1), wrt(-1), rbegin(-1), rend(-1), cbegin(-1), cend(-1) {}
126 };
127 
128 // Helper function
129 CASADI_EXPORT bool has_prefix(const std::string& s);
130 
131 // Split prefix
132 CASADI_EXPORT std::string pop_prefix(const std::string& s, std::string* rem = 0);
133 
134 class CASADI_EXPORT FmuFunction : public FunctionInternal {
135  public:
136  // FMU (shared between derivative expressions
137  Fmu fmu_;
138 
139  // Information about function inputs
140  std::vector<InputStruct> in_;
141 
142  // Information about function outputs
143  std::vector<OutputStruct> out_;
144 
145  // All Jacobian inputs and outputs
146  std::vector<size_t> jac_in_, jac_out_;
147 
148  // Nominal values for Jacobian inputs
149  std::vector<double> jac_nom_in_;
150 
151  // Sparsity of transpose (if needed)
152  std::vector<Sparsity> sp_trans_;
153  std::vector<casadi_int> sp_trans_map_;
154 
155  // What blocks exist?
156  bool has_jac_, has_fwd_, has_adj_, has_hess_;
157 
158  // Override provides_directional_derivatives, provides_adjoint_derivatives
159  bool uses_directional_derivatives_, uses_adjoint_derivatives_;
160 
162  casadi_int nfwd_, nadj_;
163 
164  // Validate derivative calculations: Move to base class?
165  bool validate_forward_, validate_hessian_;
166 
167  // User-set options
168  bool make_symmetric_;
169  double step_, abstol_, reltol_;
170  bool print_progress_, new_jacobian_, new_forward_, new_hessian_, hessian_coloring_;
171  std::string validate_ad_file_;
172 
173  // FD method as an enum
174  FdMode fd_;
175 
176  // Types of parallelization
177  Parallelization parallelization_;
178 
179  // Stats from initialization
180  Dict init_stats_;
181 
185  FmuFunction(const std::string& name, const Fmu& fmu,
186  const std::vector<std::string>& name_in,
187  const std::vector<std::string>& name_out);
188 
192  ~FmuFunction() override;
193 
197  std::string class_name() const override { return "FmuFunction";}
198 
200 
203  static const Options options_;
204  const Options& get_options() const override { return options_;}
206 
208  void init(const Dict& opts) override;
209 
210  // Identify input and output schemes from FmuFunction inputs and outputs
211  static void identify_io(
212  std::vector<std::string>* scheme_in,
213  std::vector<std::string>* scheme_out,
214  const std::vector<std::string>& name_in,
215  const std::vector<std::string>& name_out);
216 
217  // Get sparsity pattern for extended Jacobian, Hessian
218  Sparsity jac_sp_, hess_sp_;
219 
220  // Graph coloring
221  Sparsity jac_colors_, hess_colors_;
222 
223  // Nonlinearly entering variables
224  std::vector<casadi_int> nonlin_;
225 
226  // Jacobian memory
228 
229  // Number of parallel tasks
230  casadi_int max_jac_tasks_, max_hess_tasks_, max_n_tasks_;
231 
233 
236  size_t get_n_in() override { return in_.size();}
237  size_t get_n_out() override {return out_.size();}
239 
241 
244  Sparsity get_sparsity_in(casadi_int i) override;
245  Sparsity get_sparsity_out(casadi_int i) override;
247 
249 
252  std::vector<double> get_nominal_in(casadi_int i) const override;
253  std::vector<double> get_nominal_out(casadi_int i) const override;
255 
256  // Evaluate numerically
257  int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const override;
258 
259  // Evaluate all tasks numerically, serially or in parallel
260  int eval_all(FmuMemory* m, casadi_int n_task,
261  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
262 
263  // Evaluate numerically, single thread
264  int eval_task(FmuMemory* m, casadi_int task, casadi_int n_task,
265  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
266 
267  // Remove NaNs from Hessian (necessary for star coloring approach)
268  void remove_nans(double *hess_nz, casadi_int* iw) const;
269 
270  // Check extended Hessian
271  void check_hessian(FmuMemory* m, const double *hess_nz, casadi_int* iw) const;
272 
273  // Make extended Hessian symmetric
274  void make_symmetric(double *hess_nz, casadi_int* iw) const;
275 
277 
280  bool has_jac_sparsity(casadi_int oind, casadi_int iind) const override;
281  Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const override;
283 
284  // Are all inputs/outputs regular?
285  bool all_regular() const;
286 
287  // Are all inputs/outputs vectors (i.e. not Jacobian or Hessian blocks)?
288  bool all_vectors() const;
289 
290  // Factory
291  Function factory(const std::string& name,
292  const std::vector<std::string>& s_in,
293  const std::vector<std::string>& s_out,
294  const Function::AuxOut& aux,
295  const Dict& opts) const override;
296 
298 
301  bool has_jacobian() const override;
302  Function get_jacobian(const std::string& name,
303  const std::vector<std::string>& inames,
304  const std::vector<std::string>& onames,
305  const Dict& opts) const override;
307 
309 
312  bool has_forward(casadi_int nfwd) const override;
313  Function get_forward(casadi_int nfwd, const std::string& name,
314  const std::vector<std::string>& inames,
315  const std::vector<std::string>& onames,
316  const Dict& opts) const override;
318 
320 
323  bool has_reverse(casadi_int nadj) const override;
324  Function get_reverse(casadi_int nadj, const std::string& name,
325  const std::vector<std::string>& inames,
326  const std::vector<std::string>& onames,
327  const Dict& opts) const override;
329 
335  void check_mem_count(casadi_int n) const override;
336 
340  void* alloc_mem() const override;
341 
345  int init_mem(void* mem) const override;
346 
350  void free_mem(void *mem) const override;
351 
353  Dict get_stats(void* mem) const override;
354 
358  void serialize_body(SerializingStream &s) const override;
359 
363  static ProtoFunction* deserialize(DeserializingStream& s) { return new FmuFunction(s); }
364 
368  void change_option(const std::string& option_name, const GenericType& option_value) override;
369 
370  protected:
374  explicit FmuFunction(DeserializingStream& s);
375 };
376 
377 } // namespace casadi
379 
380 #endif // CASADI_FMU_FUNCTION_HPP
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:404
The casadi namespace.
Definition: archiver.hpp:32
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.