Make vertcatCollapseJacs() handle constants properly.

With this, any or all of the input vector element may have
an empty jacobian vector. Any element with a non-empty
jacobian vector must still have the same block pattern.
This commit is contained in:
Atgeirr Flø Rasmussen 2015-03-24 09:48:31 +01:00
parent 085c279a0a
commit eb9b62697e

View File

@ -447,21 +447,31 @@ vertcatCollapseJacs(const std::vector<AutoDiffBlock<double> >& x)
// Count sizes, nonzeros. // Count sizes, nonzeros.
const int nx = x.size(); const int nx = x.size();
const int nb = x[0].numBlocks();
int size = 0; int size = 0;
int nnz = 0; int nnz = 0;
int elem_with_deriv = -1;
int num_blocks = 0;
for (int elem = 0; elem < nx; ++elem) { for (int elem = 0; elem < nx; ++elem) {
size += x[elem].size(); size += x[elem].size();
if (x[elem].blockPattern() != x[0].blockPattern()) { if (x[elem].derivative().empty()) {
// No nnz contributions from this element.
continue;
} else {
if (elem_with_deriv == -1) {
elem_with_deriv = elem;
num_blocks = x[elem].numBlocks();
}
}
if (x[elem].blockPattern() != x[elem_with_deriv].blockPattern()) {
OPM_THROW(std::runtime_error, "vertcatCollapseJacs(): all arguments must have the same block pattern"); OPM_THROW(std::runtime_error, "vertcatCollapseJacs(): all arguments must have the same block pattern");
} }
for (int block = 0; block < nb; ++block) { for (int block = 0; block < num_blocks; ++block) {
nnz += x[elem].derivative()[block].nonZeros(); nnz += x[elem].derivative()[block].nonZeros();
} }
} }
int num_cols = 0; int num_cols = 0;
for (int block = 0; block < nb; ++block) { for (int block = 0; block < num_blocks; ++block) {
num_cols += x[0].derivative()[block].cols(); num_cols += x[elem_with_deriv].derivative()[block].cols();
} }
// Build value for result. // Build value for result.
@ -474,6 +484,11 @@ vertcatCollapseJacs(const std::vector<AutoDiffBlock<double> >& x)
} }
assert(pos == size); assert(pos == size);
// Return a constant if we have no derivatives at all.
if (num_blocks == 0) {
return ADB::constant(std::move(val));
}
// Set up for batch insertion of all Jacobian elements. // Set up for batch insertion of all Jacobian elements.
typedef Eigen::Triplet<double> Tri; typedef Eigen::Triplet<double> Tri;
std::vector<Tri> t; std::vector<Tri> t;
@ -481,7 +496,8 @@ vertcatCollapseJacs(const std::vector<AutoDiffBlock<double> >& x)
int block_row_start = 0; int block_row_start = 0;
for (int elem = 0; elem < nx; ++elem) { for (int elem = 0; elem < nx; ++elem) {
int block_col_start = 0; int block_col_start = 0;
for (int block = 0; block < nb; ++block) { if (!x[elem].derivative().empty()) {
for (int block = 0; block < num_blocks; ++block) {
const ADB::M& jac = x[elem].derivative()[block]; const ADB::M& jac = x[elem].derivative()[block];
for (ADB::M::Index k = 0; k < jac.outerSize(); ++k) { for (ADB::M::Index k = 0; k < jac.outerSize(); ++k) {
for (ADB::M::InnerIterator i(jac, k); i ; ++i) { for (ADB::M::InnerIterator i(jac, k); i ; ++i) {
@ -492,6 +508,7 @@ vertcatCollapseJacs(const std::vector<AutoDiffBlock<double> >& x)
} }
block_col_start += jac.cols(); block_col_start += jac.cols();
} }
}
block_row_start += x[elem].size(); block_row_start += x[elem].size();
} }