jit_function.cpp
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 #include "jit_function.hpp"
27 #include "casadi_misc.hpp"
28 
29 #include <fstream>
30 #include <iostream>
31 #include <sstream>
32 
33 namespace casadi {
34  JitFunction::JitFunction(const std::string& name, const std::string& body,
35  const std::vector<std::string>& name_in,
36  const std::vector<std::string>& name_out,
37  const std::vector<Sparsity>& sparsity_in,
38  const std::vector<Sparsity>& sparsity_out)
39  : FunctionInternal(name), body_(body) {
40  // Set sparsity
43  name_in_ = name_in;
44  name_out_ = name_out;
45 
46  // Default options
47  jit_ = true; // override default
48  buffered_ = true;
49  enable_fd_ = true; // override default
50  }
51 
54  {{"buffered",
55  {OT_BOOL,
56  "Buffer the calls, user does not need to "}},
57  {"jac",
58  {OT_STRING,
59  "Function body for Jacobian"}},
60  {"hess",
61  {OT_STRING,
62  "Function body for Hessian"}}
63  }
64  };
65 
66  void JitFunction::init(const Dict& opts) {
67  // Call the initialization method of the base class
69 
70  // Read options
71  for (auto&& op : opts) {
72  if (op.first=="buffered") {
73  buffered_ = op.second;
74  } else if (op.first=="jac") {
75  jac_body_ = op.second.to_string();
76  } else if (op.first=="hess") {
77  hess_body_ = op.second.to_string();
78  }
79  }
80 
81  // Arrays for holding inputs and outputs
82  if (buffered_) {
83  alloc_w(nnz_in() + nnz_out());
84  }
85  }
86 
88  clear_mem();
89  }
90 
92  // Add all input arguments as local variables
93  for (casadi_int i=0; i<n_in_; ++i) {
94  g.local(name_in_[i], "const casadi_real", "*");
95  if (buffered_) {
96  g << g.copy("*arg++", nnz_in(i), "w") << "\n"
97  << name_in_[i] << " = w; w += " << nnz_in(i) << ";\n";
98  } else {
99  g << name_in_[i] << " = *arg++;\n";
100  }
101  }
102 
103  // Add all output arguments as local variables
104  for (casadi_int i=0; i<n_out_; ++i) {
105  g.local(name_out_[i], "casadi_real", "*");
106  if (buffered_) {
107  g << name_out_[i] << " = w; w += " << nnz_out(i) << ";\n";
108  } else {
109  g << name_out_[i] << " = *res++;\n";
110  }
111  }
112 
113  // Codegen function body
114  g << body_;
115 
116  // Get results
117  for (casadi_int i=0; i<n_out_; ++i) {
118  if (buffered_) {
119  g << g.copy(name_out_[i], nnz_out(i), "*res++") << "\n";
120  }
121  }
122  }
123 
125  return !jac_body_.empty();
126  }
127 
128  Function JitFunction::get_jacobian(const std::string& name,
129  const std::vector<std::string>& inames,
130  const std::vector<std::string>& onames,
131  const Dict& opts) const {
132  // Create a JIT-function for the Jacobian
133  Dict jac_opts;
134  if (!hess_body_.empty()) jac_opts["jac"] = hess_body_;
135  return Function::jit(name, jac_body_, inames, onames, jac_opts);
136  }
137 
138 } // namespace casadi
Helper class for C code generation.
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
Internal class for Function.
void init(const Dict &opts) override
Initialize.
std::vector< Sparsity > sparsity_in_
Input and output sparsity.
const Sparsity & sparsity_in(casadi_int ind) const
Input/output sparsity.
bool jit_
Use just-in-time compiler.
size_t n_in_
Number of inputs and outputs.
casadi_int nnz_in() const
Number of input/output nonzeros.
static const Options options_
Options.
std::vector< Sparsity > sparsity_out_
const Sparsity & sparsity_out(casadi_int ind) const
Input/output sparsity.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
casadi_int nnz_out() const
Number of input/output nonzeros.
std::vector< std::string > name_out_
std::vector< std::string > name_in_
Input and output scheme.
Function object.
Definition: function.hpp:60
static Function jit(const std::string &name, const std::string &body, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts=Dict())
Create a just-in-time compiled function from a C language string.
Definition: function.cpp:285
JitFunction(const std::string &name, const std::string &body, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const std::vector< Sparsity > &sparsity_in, const std::vector< Sparsity > &sparsity_out)
Constructor.
bool has_jacobian() const override
Jacobian of all outputs with respect to all inputs.
void init(const Dict &opts) override
Initialize.
static const Options options_
Options.
Function get_jacobian(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Jacobian of all outputs with respect to all inputs.
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
~JitFunction() override
Destructor.
std::string hess_body_
void clear_mem()
Clear all memory (called from destructor)
The casadi namespace.
Definition: archiver.cpp:28
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Options metadata for a class.
Definition: options.hpp:40