dump.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 "dump.hpp"
27 #include "casadi_os.hpp"
28 #include "dm.hpp"
29 #include "filesystem_impl.hpp"
30 #include <iomanip>
31 namespace casadi {
32 
34  dump_count_ = 0;
35  }
36 
37  Dump::Dump(const MX& x, const std::string& base_filename,
38  const std::string& dir, const std::string& format, bool verbose)
39  : base_filename_(base_filename), dir_(dir), format_(format), verbose_(verbose) {
40  casadi_assert_dev(x.nnz()>0);
41  set_dep(x);
43  finalize();
44  }
45 
46  void ensure_directory_exists(const std::string& dir) {
47  if (Filesystem::is_enabled()) {
48  std::string effective_dir = Filesystem::ensure_trailing_slash(dir);
49  casadi_assert(Filesystem::ensure_directory_exists(effective_dir),
50  "Unable to create the required directory for '" + effective_dir + "'.");
51  }
52  }
53 
54  void Dump::finalize() {
56  }
57 
58  std::string Dump::disp(const std::vector<std::string>& arg) const {
59  return "dump(" + arg.at(0) + ", " + base_filename_ + ")";
60  }
61 
62  void Dump::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
63  const std::vector<bool>& unique) const {
64  Dict opts;
65  if (!dir_.empty()) opts["dir"] = dir_;
66  if (!format_.empty()) opts["format"] = format_;
67  if (verbose_) opts["verbose"] = true;
68  res[0] = arg[0].dump(base_filename_, opts);
69  }
70 
71  int Dump::eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
72  if (arg[0]!=res[0]) {
73  std::copy(arg[0], arg[0]+nnz(), res[0]);
74  }
75  return 0;
76  }
77 
78  int Dump::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
79  // Build filename with counter
80  std::stringstream ss;
81  ss << std::setfill('0') << std::setw(6) << dump_count_++;
82  std::string format = format_.empty() ? "mtx" : format_;
83  std::string filename = base_filename_ + "." + ss.str() + "." + format;
84  if (!dir_.empty()) filename = dir_ + filesep() + filename;
85  // Dump to file
86  if (verbose_) {
87  uout() << "dump -> " << filename << std::endl;
88  }
89  DM::to_file(filename, sparsity(), arg[0], format);
90  // Perform operation
91  if (arg[0]!=res[0]) {
92  std::copy(arg[0], arg[0]+nnz(), res[0]);
93  }
94  return 0;
95  }
96 
97  int Dump::sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
98  if (arg[0]!=res[0]) {
99  std::copy(arg[0], arg[0]+nnz(), res[0]);
100  }
101  return 0;
102  }
103 
104  int Dump::sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
105  bvec_t *a = arg[0];
106  bvec_t *r = res[0];
107  casadi_int n = nnz();
108  if (a != r) {
109  for (casadi_int i=0; i<n; ++i) {
110  *a++ |= *r;
111  *r++ = 0;
112  }
113  }
114  return 0;
115  }
116 
119  }
120 
122  const std::vector<casadi_int>& arg,
123  const std::vector<casadi_int>& res,
124  const std::vector<bool>& arg_is_ref,
125  std::vector<bool>& res_is_ref) const {
126  std::string format = format_.empty() ? "mtx" : format_;
127  std::string effective_dir = g.dump_dir_prefix + dir_ + g.dump_dir_suffix;
128  std::string prefix;
129  if (!effective_dir.empty()) prefix = effective_dir + "/";
130  // prefix + base_filename + "." + 6 digits + "." + format + null
131  casadi_int buf_size = prefix.size() + base_filename_.size()
132  + 1 + 6 + 1 + format.size() + 1;
133  std::string a = g.work(arg[0], dep(0).nnz(), arg_is_ref[0]);
134  // Block scope for dump variables
135  g << "{\n";
136  g << "static int dump_id = 0;\n";
137  g << "char dump_fname[" << buf_size << "];\n";
138  g << "FILE* dump_file;\n";
139  g << "snprintf(dump_fname, " << buf_size << ", \"" << prefix << base_filename_
140  << ".%06d." << format << "\", dump_id++);\n";
141  if (verbose_) {
142  g << g.printf("dump -> %s\\n", "dump_fname") << "\n";
143  }
144  g << "dump_file = fopen(dump_fname, \"w\");\n";
145  g << "if (dump_file) {\n";
146  g << g.to_file("dump_file", dep(0).sparsity(), a) << ";\n";
147  g << "fclose(dump_file);\n";
148  g << "}\n";
149  g << "}\n";
150  // Copy
151  generate_copy(g, arg, res, arg_is_ref, res_is_ref, 0);
152  }
153 
156  s.version("Dump", 1);
157  s.pack("Dump::base_filename", base_filename_);
158  s.pack("Dump::dir", dir_);
159  s.pack("Dump::format", format_);
160  s.pack("Dump::verbose", verbose_);
161  }
162 
164  s.version("Dump", 1);
165  s.unpack("Dump::base_filename", base_filename_);
166  s.unpack("Dump::dir", dir_);
167  s.unpack("Dump::format", format_);
168  s.unpack("Dump::verbose", verbose_);
169  finalize();
170  }
171 
172 } // namespace casadi
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string printf(const std::string &str, const std::vector< std::string > &arg=std::vector< std::string >())
Printf.
std::string to_file(const std::string &f, const Sparsity &sp, const std::string &x)
Write matrix to file in MatrixMarket format.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: dump.cpp:154
Dump(const MX &x, const std::string &base_filename, const std::string &dir, const std::string &format, bool verbose)
Constructor.
Definition: dump.cpp:37
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
Definition: dump.cpp:104
void reset_dump_count()
Reset the dump counter.
Definition: dump.cpp:33
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: dump.cpp:58
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: dump.cpp:78
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Definition: dump.cpp:71
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
Definition: dump.cpp:62
void add_dependency(CodeGenerator &g) const override
Add dependencies for code generation.
Definition: dump.cpp:117
void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const override
Generate code for the operation.
Definition: dump.cpp:121
void finalize()
Validate options (called from constructors)
Definition: dump.cpp:54
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
Definition: dump.cpp:97
static std::string ensure_trailing_slash(const std::string &path)
Definition: filesystem.cpp:155
static bool ensure_directory_exists(const std::string &path)
Definition: filesystem.cpp:105
static bool is_enabled()
Definition: filesystem.cpp:83
casadi_int nnz() const
Get the number of (structural) non-zero elements.
Node class for MX objects.
Definition: mx_node.hpp:51
void generate_copy(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref, casadi_int i) const
Definition: mx_node.cpp:460
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:410
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:427
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:392
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:530
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:224
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:228
MX - Matrix expression.
Definition: mx.hpp:92
const Sparsity & sparsity() const
Get the sparsity pattern.
Definition: mx.cpp:612
void to_file(const std::string &filename, const std::string &format="") const
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
The casadi namespace.
Definition: archiver.cpp:28
unsigned long long bvec_t
std::string filesep()
Definition: casadi_os.cpp:71
void ensure_directory_exists(const std::string &dir)
Definition: dump.cpp:46
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
std::ostream & uout()
std::string filename(const std::string &path)
Definition: ghc.cpp:55