18#include <boost/timer/timer.hpp>
19#include <dune/istl/preconditioners.hh>
27 extern "C" void dgetrf_(
int *m,
int *n,
double *a,
int *lda,
int *ipiv,
int *info);
28 extern "C" void dgetrs_(
char *trans,
int *n,
int *nrhs,
double *a,
int *lda,
int *ipiv,
29 double *b,
int *ldb,
int *info);
37 typedef typename Op::domain_type domain_type;
38 typedef typename Op::domain_type range_type;
39 typedef typename domain_type::field_type field_type;
42 static int const category = Dune::SolverCategory::sequential;
50 size_t k, n = A.
nrows();
55 iBlocksColIndices.resize(n);
59 iBlocksColIndices[k] = k;
65 iBlocksColIndices.resize(n);
70 iBlocksColIndices[k] = k;
80 size_t i, k, nBlocks = last-first, cnt, nnz = A.
nnz();
81 iBlocks.resize(nBlocks+1);
83 std::vector<size_t> nCounts(nBlocks);
84 for (k=0; k<nBlocks; k++)
90 size_t ri = A.
ridx[i];
91 size_t ci = A.
cidx[i];
92 if ((ri>=first)&&(ri<last))
94 if ((ci<first)||(ci>=last))
113 iBlocksColIndices.resize(cnt);
115 for (k=1; k<=nBlocks; k++)
117 iBlocks[k] = iBlocks[k-1]+nCounts[k-1];
118 iBlocksColIndices[iBlocks[k-1]] = first+k-1;
121 assert(iBlocks[nBlocks]==cnt);
125 for (i=0; i<nnz; i++)
127 size_t ri = A.
ridx[i];
128 size_t ci = A.
cidx[i];
129 if ((ri>=first)&&(ri<last))
131 if ((ci<first)||(ci>=last))
133 iBlocksColIndices[iBlocks[ri-first]+nCounts[ri-first]] = ci;
152 size_t i, k, n = A.
nrows(), nnz = A.
nnz();
155 size_t nBlocks = iBlocks.size()-1;
162 blocks.resize(nBlocks);
163 ipiv.resize(nBlocks);
164 size_t maxBlockSize = -1;
165 size_t memSize = 0, inverseIndexSize = 0;
166 for (k=0; k<nBlocks; k++)
168 int blockSize = iBlocks[k+1]-iBlocks[k];
169 if (blockSize>maxBlockSize)
170 maxBlockSize = blockSize;
171 memSize += blockSize*blockSize;
172 inverseIndexSize += blockSize;
178 blocks[0] = (field_type*)malloc(memSize*
sizeof(field_type));
179 ipiv[0] = (
int*)malloc(inverseIndexSize*
sizeof(
int));
180 for (k=1; k<nBlocks; k++)
182 int blockSize = iBlocks[k]-iBlocks[k-1];
183 blocks[k] = blocks[k-1]+blockSize*blockSize;
184 ipiv[k] = ipiv[k-1]+blockSize;
195 std::vector<size_t> usedCnts(n);
196 std::vector<size_t> usedIn(n+1);
197 std::vector<size_t> usedInIndices(inverseIndexSize);
201 for (k=0; k<nBlocks; k++)
203 for (i=iBlocks[k]; i<iBlocks[k+1]; i++)
205 usedCnts[iBlocksColIndices[i]]++;
217 if (cnt!=inverseIndexSize) printf(
"Assert cnt=%ld!=%ld=inverseIndexSize\n", cnt, inverseIndexSize);
218 usedIn[n] = inverseIndexSize;
222 for (k=0; k<nBlocks; k++)
224 for (i=iBlocks[k]; i<iBlocks[k+1]; i++)
226 size_t ii = iBlocksColIndices[i];
227 usedInIndices[usedIn[ii]+usedCnts[ii]] = k;
240 for (i=0; i<nnz; i++)
242 size_t ri = A.
ridx[i];
243 size_t ci = A.
cidx[i];
244 field_type vali = A.
data[i];
245 for (k=usedIn[ri]; k<usedIn[ri+1]; k++)
247 size_t kk = usedInIndices[k];
249 size_t subi, subk, bsize = iBlocks[kk+1]-iBlocks[kk];
251 for (subi=iBlocks[kk]; subi<iBlocks[kk+1]; subi++)
252 if (ri==iBlocksColIndices[subi])
break;
253 if (subi==iBlocks[kk+1])
continue;
255 for (subk=iBlocks[kk]; subk<iBlocks[kk+1]; subk++)
256 if (ci==iBlocksColIndices[subk])
break;
257 if (subk==iBlocks[kk+1])
continue;
261 blocks[kk][subi*bsize+subk] = vali;
267 for (k=0; k<nBlocks; k++)
269 size_t bsize = iBlocks[k+1]-iBlocks[k];
280 if (fabs(blocks[k][0])<1.0e-20)
282 printf(
"error diagonal element to small %e\n", blocks[k][0]);
285 blocks[k][0] = 1.0/blocks[k][0];
289 int info, f_n = bsize;
290 dgetrf_(&f_n, &f_n, blocks[k], &f_n, ipiv[k], &info);
293 printf(
"error from dgetrf_: info = %d, block=%ld %8p, bsize=%ld\n", info,
294 k, blocks[k], bsize);
302 std::cout <<
"PrecondType::ADDITIVESCHWARZ: n=" << n <<
", nnz=" << nnz <<
", time=" << boost::timer::format(timer.elapsed()) <<
"\n";
312 virtual void pre(domain_type&, range_type&) {}
313 virtual void post (domain_type&) {}
315 virtual void apply (domain_type& x, range_type
const& y)
319 std::vector<field_type> b(n), bb(n), bbb(n);
321 int nBlocks = iBlocks.size()-1;
323 for (k=0; k<nBlocks; k++)
325 int nn, nrhs = 1, lda, ldb, info, cnt;
326 char trans[1] = {
'N'};
328 for (i=iBlocks[k]; i<iBlocks[k+1]; i++)
330 size_t ii = iBlocksColIndices[i];
335 nn = lda = ldb = iBlocks[k+1]-iBlocks[k];
339 bb[0] = bb[0]*blocks[k][0];
343 dgetrs_(trans, &nn, &nrhs, blocks[k], &lda, ipiv[k], &bb[0], &ldb, &info);
346 printf(
"error from dgetrs_: info =%d\n", info);
351 for (i=iBlocks[k]; i<iBlocks[k+1]; i++)
353 size_t ii = iBlocksColIndices[i];
363 std::vector<size_t> iBlocks, iBlocksColIndices;
364 std::vector<field_type*> blocks;
365 std::vector<int*> ipiv;
366 boost::timer::cpu_timer timer;
virtual void apply(domain_type &x, range_type const &y)
virtual void pre(domain_type &, range_type &)
~AdditiveSchwarzPreconditioner()
static int const category
AdditiveSchwarzPreconditioner(Op const &op, size_t first, size_t last, int verbosity=2)
void init(MatrixAsTriplet< field_type > &A, int verbosity=2)
AdditiveSchwarzPreconditioner(Op const &op, schwarzType select, int verbosity=2)
virtual void post(domain_type &)
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
std::vector< SparseIndexInt > ridx
row indices
std::vector< SparseIndexInt > cidx
column indices
std::vector< Scalar > data
data
void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info)
void dgetrs_(char *trans, int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info)