1#ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_JAC_INCLUDED
2#define CPPAD_CG_MODEL_C_SOURCE_GEN_JAC_INCLUDED
22void ModelCSourceGen<Base>::generateJacobianSource() {
25 const std::string
jobName =
"Jacobian";
27 startingJob(
"'" +
jobName +
"'", JobTimer::GRAPH);
40 size_t m = _fun.Range();
41 size_t n = _fun.Domain();
44 if (_jacMode == JacobianADMode::Automatic) {
46 }
else if (_jacMode == JacobianADMode::Forward) {
55 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
56 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
57 langC.setParameterPrecision(_parameterPrecision);
58 langC.setGenerateFunction(_name +
"_" + FUNCTION_JACOBIAN);
60 std::ostringstream
code;
61 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"jac"));
68 size_t m = _fun.Range();
69 size_t n = _fun.Domain();
74 determineJacobianSparsity();
78 if (_jacMode == JacobianADMode::Automatic) {
79 if (_custom_jac.defined) {
80 forwardMode = estimateBestJacobianADMode(_jacSparsity.rows, _jacSparsity.cols);
91 if (_sparseJacobianReusesOne && _forwardOne &&
forwardMode) {
93 }
else if (_sparseJacobianReusesOne && _reverseOne && !
forwardMode) {
104 const std::string
jobName =
"sparse Jacobian";
107 size_t n = _fun.Domain();
109 startingJob(
"'" +
jobName +
"'", JobTimer::GRAPH);
112 handler.setJobTimer(_jobTimer);
117 for (
size_t i = 0;
i <
n;
i++) {
123 if (_loopTapes.empty()) {
127 _fun.SparseJacobianForward(
indVars, _jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols, jac,
work);
129 _fun.SparseJacobianReverse(
indVars, _jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols, jac,
work);
139 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
140 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
141 langC.setParameterPrecision(_parameterPrecision);
142 langC.setGenerateFunction(_name +
"_" + FUNCTION_SPARSE_JACOBIAN);
144 std::ostringstream
code;
145 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"jac"));
157 std::map<size_t, CompressedVectorInfo>
jacInfo;
161 for (
size_t e = 0;
e < _jacSparsity.rows.size();
e++) {
162 jacInfo[_jacSparsity.cols[
e]].indexes.push_back(_jacSparsity.rows[
e]);
165 size_t col =
it.first;
166 it.second.locations = determineOrderByCol(col,
it.second.indexes, _jacSparsity.rows, _jacSparsity.cols);
169 _cache << _name <<
"_" << FUNCTION_SPARSE_FORWARD_ONE;
174 for (
size_t e = 0;
e < _jacSparsity.rows.size();
e++) {
175 jacInfo[_jacSparsity.rows[
e]].indexes.push_back(_jacSparsity.cols[
e]);
178 size_t row =
it.first;
179 it.second.locations = determineOrderByRow(row,
it.second.indexes, _jacSparsity.rows, _jacSparsity.cols);
182 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_ONE;
193 const std::vector<size_t>&
els =
it.second.indexes;
194 const std::vector<set<size_t> >& location =
it.second.locations;
195 CPPADCG_ASSERT_UNKNOWN(
els.size() == location.size());
196 CPPADCG_ASSERT_UNKNOWN(
els.size() > 0);
200 for (
size_t e = 0;
e <
els.size();
e++) {
201 if (location[
e].size() > 1) {
214 map<size_t, bool>::const_iterator
itOrd;
215 map<size_t, std::vector<size_t> >::const_iterator
it;
221 if (!_loopTapes.empty()) {
227 FUNCTION_SPARSE_FORWARD_ONE,
"indep",
"jcol",
228 _nonLoopFor1Elements, _loopFor1Groups,
229 generateFunctionNameLoopFor1);
232 FUNCTION_SPARSE_REVERSE_ONE,
"dep",
"jrow",
233 _nonLoopRev1Elements, _loopRev1Groups,
234 generateFunctionNameLoopRev1);
240 _cache << _name <<
"_" << FUNCTION_SPARSE_JACOBIAN;
254 std::map<size_t, CompressedVectorInfo>
jacInfo,
261 std::string
argsDcl =
langC.generateDefaultFunctionArgumentsDcl();
262 std::vector<std::string>
argsDcl2 =
langC.generateDefaultFunctionArgumentsDcl2();
265 _cache <<
"#include <stdlib.h>\n"
272 " " << _baseTypeName <<
" const * inLocal[2];\n"
273 " " << _baseTypeName <<
" inLocal1 = 1;\n"
274 " " << _baseTypeName <<
" * outLocal[1];\n"
276 " " << _baseTypeName <<
" * jac = out[0];\n"
278 " inLocal[0] = in[0];\n"
279 " inLocal[1] = &inLocal1;\n"
280 " outLocal[0] = compressed;\n";
282 langC.setArgumentIn(
"inLocal");
283 langC.setArgumentOut(
"outLocal");
288 size_t index =
it.first;
289 const std::vector<size_t>&
els =
it.second.indexes;
290 const std::vector<std::set<size_t> >& location =
it.second.locations;
291 CPPADCG_ASSERT_UNKNOWN(
els.size() == location.size());
296 _cache <<
" outLocal[0] = &jac[" << *location[0].begin() <<
"];\n";
298 _cache <<
" outLocal[0] = compressed;\n";
302 for (
size_t e = 0;
e <
els.size();
e++) {
304 for (
size_t itl : location[
e]) {
305 _cache <<
"jac[" << (
itl) <<
"] = ";
307 _cache <<
"compressed[" <<
e <<
"];\n";
321 std::map<size_t, CompressedVectorInfo>
jacInfo,
328 std::string
argsDcl =
langC.generateDefaultFunctionArgumentsDcl();
329 std::vector<std::string>
argsDcl2 =
langC.generateDefaultFunctionArgumentsDcl2();
332 _cache <<
"#include <stdlib.h>\n"
337 langC.setArgumentIn(
"inLocal");
338 langC.setArgumentOut(
"outLocal");
345 size_t index =
it.first;
346 const std::vector<size_t>&
els =
it.second.indexes;
347 const std::vector<std::set<size_t> >& location =
it.second.locations;
348 CPPADCG_ASSERT_UNKNOWN(
els.size() == location.size());
358 " " << _baseTypeName <<
" const * inLocal[2];\n"
359 " " << _baseTypeName <<
" inLocal1 = 1;\n"
360 " " << _baseTypeName <<
" * outLocal[1];\n"
361 " " << _baseTypeName <<
" compressed[" <<
it.second.indexes.size() <<
"];\n"
362 " " << _baseTypeName <<
" * jac = out[0];\n"
364 " inLocal[0] = in[0];\n"
365 " inLocal[1] = &inLocal1;\n"
366 " outLocal[0] = compressed;\n";
369 for (
size_t e = 0;
e <
els.size();
e++) {
371 for (
size_t itl : location[
e]) {
372 _cache <<
"jac[" << (
itl) <<
"] = ";
374 _cache <<
"compressed[" <<
e <<
"];\n";
380 "typedef void (*cppadcg_function_type) (" <<
argsDcl <<
");\n";
387 printFileStartOpenMP(_cache);
393 printFileStartPThreads(_cache, _baseTypeName);
401 " static const cppadcg_function_type p[" <<
jacInfo.size() <<
"] = {";
403 size_t index =
it.first;
404 if (index !=
jacInfo.begin()->first) _cache <<
", ";
405 if (
it.second.ordered) {
412 " static const long offset["<<
jacInfo.size() <<
"] = {";
414 if (
it.first !=
jacInfo.begin()->first) _cache <<
", ";
415 if (
it.second.ordered) {
416 _cache << *
it.second.locations[0].begin();
422 " " << _baseTypeName <<
" inLocal1 = 1;\n"
423 " " << _baseTypeName <<
" const * inLocal[2] = {in[0], &inLocal1};\n"
424 " " << _baseTypeName <<
" * outLocal[1];\n"
425 " " << _baseTypeName <<
" * jac = out[0];\n"
430 printFunctionStartOpenMP(_cache,
jacInfo.size());
432 printLoopStartOpenMP(_cache,
jacInfo.size());
433 _cache <<
" outLocal[0] = &jac[offset[i]];\n"
435 printLoopEndOpenMP(_cache,
jacInfo.size());
441 printFunctionStartPThreads(_cache,
jacInfo.size());
443 " for(i = 0; i < " <<
jacInfo.size() <<
"; ++i) {\n"
444 " args[i] = (ExecArgStruct*) malloc(sizeof(ExecArgStruct));\n"
445 " args[i]->func = p[i];\n"
446 " args[i]->in = inLocal;\n"
447 " args[i]->out[0] = &jac[offset[i]];\n"
448 " args[i]->atomicFun = " <<
langC.getArgumentAtomic() <<
";\n"
451 printFunctionEndPThreads(_cache,
jacInfo.size());
462 if (_jacSparsity.sparsity.size() > 0) {
471 if (!_custom_jac.defined) {
472 generateSparsityIndexes(_jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols);
475 _jacSparsity.rows = _custom_jac.row;
476 _jacSparsity.cols = _custom_jac.col;
482 determineJacobianSparsity();
484 generateSparsity2DSource(_name +
"_" + FUNCTION_JACOBIAN_SPARSITY, _jacSparsity);
485 _sources[_name +
"_" + FUNCTION_JACOBIAN_SPARSITY +
".c"] = _cache.str();
static void printFunctionDeclaration(std::ostringstream &out, const std::string &returnType, const std::string &functionName, const std::vector< std::string > &arguments, const std::vector< std::string > &arguments2={})
virtual std::string generateSparseJacobianForRevMultiThreadSource(const std::string &functionName, std::map< size_t, CompressedVectorInfo > jacInfo, size_t maxCompressedSize, const std::string &functionRevFor, const std::string &revForSuffix, bool forward, MultiThreadingType multiThreadingType)
virtual void generateSparseJacobianSource(MultiThreadingType multiThreadingType)
virtual void determineJacobianSparsity()
virtual void generateSparseJacobianForRevSource(bool forward, MultiThreadingType multiThreadingType)
bool GreaterThanZero(const cg::CG< Base > &x)