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  // Extended Jacobian
51  double *jac_nz;
52  // Extended Hessian
53  double *hess_nz;
54  // Adjoint seeds, sensitivities being calculated
55  double *aseed, *asens, *pert_asens;
56  // Memory for Jacobian calculation
57  casadi_jac_data<double> jac_data, adj_data;
58  // Instance memory
59  void* instance;
60  // Additional (slave) memory objects
61  std::vector<FmuMemory*> slaves;
62  // Input and output buffers
63  std::vector<double> ibuf_, obuf_;
64  // Seeds, sensitivities
65  std::vector<double> isens_, osens_;
66  // Which inputs and outputs have been marked
67  std::vector<bool> imarked_, omarked_;
68  // Derivative with respect to
69  std::vector<size_t> wrt_;
70  // Current known/unknown variables
71  std::vector<size_t> id_in_, id_out_;
72  // Which perturbations are permitted
73  std::vector<bool> in_bounds_;
74  // Flip sign?
75  std::vector<bool> flip_;
76  // Value references
77  std::vector<unsigned int> vr_in_, vr_out_;
78  // Work vector (reals)
79  std::vector<double> v_in_, v_out_, d_in_, d_out_, fd_out_, v_pert_;
80  // Timing, number of calls
81  size_t n_get_all, n_get_directional, n_get_adjoint;
82  double t_get_all, t_get_directional, t_get_adjoint;
83  // Constructor
84  explicit FmuMemory(const FmuFunction& self) : self(self), instance(nullptr) {}
85 };
86 
88 enum class Parallelization {SERIAL, OPENMP, THREAD, NUMEL};
89 
91 CASADI_EXPORT std::string to_string(Parallelization v);
92 
93 // Types of inputs
94 enum class InputType {REG, FWD, ADJ, OUT, ADJ_OUT};
95 
96 // Input structure
97 struct CASADI_EXPORT InputStruct {
98  // Type of input
99  InputType type;
100  // Corresponding index in Fmu
101  size_t ind;
102  // Parse an input string
103  static InputStruct parse(const std::string& n, const Fmu* fmu,
104  std::vector<std::string>* name_in = nullptr,
105  std::vector<std::string>* name_out = nullptr);
106 };
107 
108 // Types of inputs
109 enum class OutputType {REG, FWD, ADJ, JAC, JAC_TRANS, JAC_ADJ_OUT, JAC_REG_ADJ, HESS};
110 
111 // Output structure
112 struct CASADI_EXPORT OutputStruct {
113  // Type of input
114  OutputType type;
115  // Output index in Fmu
116  size_t ind;
117  // With-respect-to index in Fmu
118  size_t wrt;
119  // Selection
120  size_t rbegin, rend, cbegin, cend;
121  // Parse an output string
122  static OutputStruct parse(const std::string& n, const Fmu* fmu,
123  std::vector<std::string>* name_in = nullptr,
124  std::vector<std::string>* name_out = nullptr);
125  // Constructor
126  OutputStruct() : ind(-1), wrt(-1), rbegin(-1), rend(-1), cbegin(-1), cend(-1) {}
127 };
128 
129 // Helper function
130 CASADI_EXPORT bool has_prefix(const std::string& s);
131 
132 // Split prefix
133 CASADI_EXPORT std::string pop_prefix(const std::string& s, std::string* rem = nullptr);
134 
135 class CASADI_EXPORT FmuFunction : public FunctionInternal {
136  public:
137  // FMU (shared between derivative expressions
138  Fmu fmu_;
139 
140  // Information about function inputs
141  std::vector<InputStruct> in_;
142 
143  // Information about function outputs
144  std::vector<OutputStruct> out_;
145 
146  // All Jacobian inputs and outputs
147  std::vector<size_t> jac_in_, jac_out_;
148 
149  // Nominal values for Jacobian inputs
150  std::vector<double> jac_nom_in_;
151 
152  // Sparsity of transpose (if needed)
153  std::vector<Sparsity> sp_trans_;
154  std::vector<casadi_int> sp_trans_map_;
155 
156  // What blocks exist?
157  bool has_jac_, has_fwd_, has_adj_, has_hess_;
158 
159  // Override provides_directional_derivatives, provides_adjoint_derivatives
160  bool uses_directional_derivatives_, uses_adjoint_derivatives_;
161 
163  casadi_int nfwd_, nadj_;
164 
165  // Validate derivative calculations: Move to base class?
166  bool validate_forward_, validate_hessian_;
167 
168  // User-set options
169  double step_, abstol_, reltol_;
170  bool print_progress_, new_jacobian_, new_forward_, new_hessian_, fd_flip_,
171  make_symmetric_, hessian_coloring_, asymmetric_hessian_coloring_,
172  enable_forward_jacobian_, enable_adjoint_jacobian_, enable_adjoint_hessian_;
173  std::string validate_ad_file_;
174 
175  // FD method as an enum
176  FdMode fd_;
177 
178  // Types of parallelization
179  Parallelization parallelization_;
180 
181  // Stats from initialization
182  Dict init_stats_;
183 
187  FmuFunction(const std::string& name, const Fmu& fmu,
188  const std::vector<std::string>& name_in,
189  const std::vector<std::string>& name_out);
190 
194  ~FmuFunction() override;
195 
199  std::string class_name() const override { return "FmuFunction";}
200 
202 
205  static const Options options_;
206  const Options& get_options() const override { return options_;}
208 
210  void init(const Dict& opts) override;
211 
212  // Identify input and output schemes from FmuFunction inputs and outputs
213  static void identify_io(
214  std::vector<std::string>* scheme_in,
215  std::vector<std::string>* scheme_out,
216  const std::vector<std::string>& name_in,
217  const std::vector<std::string>& name_out);
218 
219  // Get sparsity pattern for extended Jacobian, Hessian
220  Sparsity jac_sp_, hess_sp_, adj_sp_;
221 
222  // Graph coloring
223  Sparsity jac_colors_, adj_colors_, hess_colors_, hess_uni_colors_;
224 
225  // Which color is used to calculate a given nonzero in the Hessian?
226  std::vector<casadi_int> which_hess_color_;
227 
228  // Nonlinearly entering variables
229  std::vector<casadi_int> nonlin_;
230 
231  // Jacobian memory
232  casadi_jac_prob<double> jac_prob_, adj_prob_;
233 
234  // Number of parallel tasks
235  casadi_int max_jac_tasks_, max_hess_tasks_, max_adj_tasks_, max_n_tasks_;
236 
238 
241  size_t get_n_in() override { return in_.size();}
242  size_t get_n_out() override {return out_.size();}
244 
246 
249  Sparsity get_sparsity_in(casadi_int i) override;
250  Sparsity get_sparsity_out(casadi_int i) override;
252 
254 
257  std::vector<double> get_nominal_in(casadi_int i) const override;
258  std::vector<double> get_nominal_out(casadi_int i) const override;
260 
261  // Evaluate numerically
262  int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const override;
263 
264  // Evaluate all tasks numerically, serially or in parallel
265  int eval_all(FmuMemory* m, casadi_int n_task,
266  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
267 
268  // Evaluate numerically, single thread
269  int eval_task(FmuMemory* m, casadi_int task, casadi_int n_task,
270  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
271 
272  // Finalize Hessian creation
273  void finalize_hessian(FmuMemory* m, double *hess_nz, casadi_int* iw) const;
274 
276 
279  bool has_jac_sparsity(casadi_int oind, casadi_int iind) const override;
280  Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const override;
282 
283  // Are all inputs/outputs regular?
284  bool all_regular() const;
285 
286  // Are all inputs/outputs vectors (i.e. not Jacobian or Hessian blocks)?
287  bool all_vectors() const;
288 
289  // Factory
290  Function factory(const std::string& name,
291  const std::vector<std::string>& s_in,
292  const std::vector<std::string>& s_out,
293  const Function::AuxOut& aux,
294  const Dict& opts) const override;
295 
297 
300  bool has_jacobian() const override;
301  Function get_jacobian(const std::string& name,
302  const std::vector<std::string>& inames,
303  const std::vector<std::string>& onames,
304  const Dict& opts) const override;
306 
308 
311  bool has_forward(casadi_int nfwd) const override;
312  Function get_forward(casadi_int nfwd, const std::string& name,
313  const std::vector<std::string>& inames,
314  const std::vector<std::string>& onames,
315  const Dict& opts) const override;
317 
319 
322  bool has_reverse(casadi_int nadj) const override;
323  Function get_reverse(casadi_int nadj, const std::string& name,
324  const std::vector<std::string>& inames,
325  const std::vector<std::string>& onames,
326  const Dict& opts) const override;
328 
334  void check_mem_count(casadi_int n) const override;
335 
339  void* alloc_mem() const override;
340 
344  int init_mem(void* mem) const override;
345 
349  void free_mem(void *mem) const override;
350 
352  Dict get_stats(void* mem) const override;
353 
357  void serialize_body(SerializingStream &s) const override;
358 
362  static ProtoFunction* deserialize(DeserializingStream& s) { return new FmuFunction(s); }
363 
367  void change_option(const std::string& option_name, const GenericType& option_value) override;
368 
369  protected:
373  explicit FmuFunction(DeserializingStream& s);
374 };
375 
376 } // namespace casadi
378 
379 #endif // CASADI_FMU_FUNCTION_HPP
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:447
The casadi namespace.
Definition: archiver.hpp:32
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.