32 #include <oomph-lib-config.h> 57 if (dist_matrix_pt != 0)
74 "Zero diagonal in matrix --> Cannot use diagonal preconditioner.",
75 OOMPH_CURRENT_FUNCTION,
76 OOMPH_EXCEPTION_LOCATION);
97 for(
unsigned i=0;
i<n_row;
i++)
103 "Zero diagonal in matrix --> Cannot use diagonal preconditioner.",
104 OOMPH_CURRENT_FUNCTION,
105 OOMPH_EXCEPTION_LOCATION);
130 std::ostringstream error_message_stream;
132 <<
"The r vector must have the same distribution as the preconditioner. " 133 <<
"(this is the same as the matrix passed to setup())";
135 (error_message_stream.str(),
136 OOMPH_CURRENT_FUNCTION,
137 OOMPH_EXCEPTION_LOCATION);
143 std::ostringstream error_message_stream;
145 <<
"The z vector distribution has been setup; it must have the " 146 <<
"same distribution as the r vector (and preconditioner).";
148 (error_message_stream.str(),
149 OOMPH_CURRENT_FUNCTION,
150 OOMPH_EXCEPTION_LOCATION);
182 if (Inv_lumped_diag_pt !=0) {
delete[] this->Inv_lumped_diag_pt; }
183 Inv_lumped_diag_pt =
new double[this->Nrow];
186 for (
unsigned i = 0;
i < Nrow;
i++)
188 Inv_lumped_diag_pt[
i] = 0.0;
195 int* m_row_index = cc_matrix_pt->
row_index();
196 double* m_value = cc_matrix_pt->
value();
197 unsigned m_nnz = cc_matrix_pt->
nnz();
200 Positive_matrix =
true;
203 for(
unsigned i=0;
i< m_nnz;
i++)
206 if (m_value[
i] < 0.0) { Positive_matrix =
false; }
209 Inv_lumped_diag_pt[m_row_index[
i]] += m_value[
i];
213 for (
unsigned i = 0;
i < Nrow;
i++)
215 Inv_lumped_diag_pt[
i] = 1.0 / Inv_lumped_diag_pt[
i];
238 if (Inv_lumped_diag_pt !=0) {
delete[] this->Inv_lumped_diag_pt; }
239 Inv_lumped_diag_pt =
new double[this->Nrow];
242 for (
unsigned i = 0;
i < Nrow;
i++)
244 Inv_lumped_diag_pt[
i] = 0.0;
248 int* m_row_start = cr_matrix_pt->
row_start();
249 double* m_value = cr_matrix_pt->
value();
252 Positive_matrix =
true;
255 for(
unsigned i=0;
i< Nrow;
i++)
257 Inv_lumped_diag_pt[
i] = 0.0;
258 for (
int j = m_row_start[
i]; j < m_row_start[
i+1]; j++)
261 if (m_value[j] < 0.0) { Positive_matrix =
false; }
264 Inv_lumped_diag_pt[
i] += m_value[j];
267 Inv_lumped_diag_pt[
i] = 1.0/Inv_lumped_diag_pt[
i];
278 template<
typename MATRIX>
285 std::ostringstream error_message_stream;
287 <<
"The r vector must have teh same distribution as the preconditioner. " 288 <<
"(this is the same as the matrix passed to setup())";
290 (error_message_stream.str(),
291 OOMPH_CURRENT_FUNCTION,
292 OOMPH_EXCEPTION_LOCATION);
298 std::ostringstream error_message_stream;
300 <<
"The z vector distribution has been setup; it must have the " 301 <<
"same distribution as the r vector (and preconditioner).";
303 (error_message_stream.str(),
304 OOMPH_CURRENT_FUNCTION,
305 OOMPH_EXCEPTION_LOCATION);
311 for (
unsigned i=0;
i<Nrow;
i++)
313 z[
i]=Inv_lumped_diag_pt[
i]*r[
i];
334 if(cc_matrix_pt == 0)
336 std::ostringstream error_msg;
337 error_msg <<
"Failed to conver matrix_pt to CCDoubleMatrix*.";
339 OOMPH_CURRENT_FUNCTION,
340 OOMPH_EXCEPTION_LOCATION);
345 int n_row=cc_matrix_pt->
nrow();
363 m_value = cc_matrix_pt->
value();
366 for (
int i = 0;
i < n_row;
i++)
368 for (
int j = m_column_start[
i]; j < m_column_start[
i+1]; j++)
370 if (m_row_index[j] >
i)
383 L_column_start.resize(n_row+1);
384 L_row_entry.resize(l_nz);
387 U_column_start.resize(n_row+1);
388 U_row_entry.resize(u_nz);
391 L_column_start[0] = 0;
392 U_column_start[0] = 0;
395 for (
int i = 0;
i < n_row;
i++)
397 L_column_start[
i+1] = L_column_start[
i];
398 U_column_start[
i+1] = U_column_start[
i];
399 for (
int j = m_column_start[
i]; j < m_column_start[
i+1]; j++)
401 if (m_row_index[j] >
i)
403 int k = L_column_start[
i+1]++;
404 L_row_entry[k].index() = m_row_index[j];
405 L_row_entry[k].value() = m_value[j];
409 int k = U_column_start[
i+1]++;
410 U_row_entry[k].index() = m_row_index[j];
411 U_row_entry[k].value() = m_value[j];
419 for (
unsigned i = 0;
i < unsigned(n_row);
i++)
422 std::sort(L_row_entry.begin() + L_column_start[
i],
423 L_row_entry.begin() + L_column_start[
i+1]);
426 std::sort(U_row_entry.begin() + U_column_start[
i],
427 U_row_entry.begin() + U_column_start[
i+1]);
433 int i;
unsigned j, pn, qn, rn; pn = 0; qn=0; rn = 0;
435 for (i = 0; i < n_row - 1; i++) {
436 multiplier = U_row_entry[U_column_start[i+1]-1].value();
437 for (j = L_column_start[i]; j < L_column_start[i+1]; j++)
438 L_row_entry[j].value() /= multiplier;
439 for (j = U_column_start[i+1]; j < U_column_start[i+2]-1; j++)
441 multiplier = U_row_entry[j].value();
443 rn = L_column_start[i+1];
444 for (pn = L_column_start[U_row_entry[j].index()];
445 pn < L_column_start[U_row_entry[j].index()+1] &&
446 static_cast<int>(L_row_entry[pn].index()) <= i + 1; pn++)
448 while (qn < U_column_start[i+2] &&
449 U_row_entry[qn].index() < L_row_entry[pn].index())
451 if (qn < U_column_start[i+2] &&
452 L_row_entry[pn].index() == U_row_entry[qn].index())
453 U_row_entry[qn].value() -= multiplier * L_row_entry[pn].value();
455 for ( ; pn < L_column_start[U_row_entry[j].index()+1]; pn++)
457 while (rn < L_column_start[i+2] &&
458 L_row_entry[rn].index() < L_row_entry[pn].index())
460 if (rn < L_column_start[i+2] &&
461 L_row_entry[pn].index() == L_row_entry[rn].index())
462 L_row_entry[rn].value() -= multiplier * L_row_entry[pn].value();
478 if(cr_matrix_pt == 0)
480 std::ostringstream error_msg;
481 error_msg <<
"Failed to conver matrix_pt to CRDoubleMatrix*.";
483 OOMPH_CURRENT_FUNCTION,
484 OOMPH_EXCEPTION_LOCATION);
489 bool built_global =
false;
496 cr_matrix_pt = global_matrix_pt;
506 int n_row=cr_matrix_pt->
nrow();
520 m_value = cr_matrix_pt->
value();
523 for (
int i = 0;
i < n_row;
i++)
525 for (
int j = m_row_start[
i]; j < m_row_start[
i+1]; j++)
527 if (m_column_index[j] <
i)
540 L_row_start.resize(n_row+1);
541 L_row_entry.resize(l_nz);
544 U_row_start.resize(n_row+1);
545 U_row_entry.resize(u_nz);
552 for (
int i = 0;
i < n_row;
i++)
554 L_row_start[
i+1] = L_row_start[
i];
555 U_row_start[
i+1] = U_row_start[
i];
556 for (
int j = m_row_start[
i]; j < m_row_start[
i+1]; j++)
558 if (m_column_index[j] <
i)
560 int k = L_row_start[
i+1]++;
561 L_row_entry[k].value() = m_value[j];
562 L_row_entry[k].index() = m_column_index[j];
566 int k = U_row_start[
i+1]++;
567 U_row_entry[k].value() = m_value[j];
568 U_row_entry[k].index() = m_column_index[j];
575 unsigned i, j, pn, qn, rn; pn = 0; qn=0; rn = 0;
577 for (i = 1; i < static_cast<unsigned>(n_row); i++) {
578 for (j = L_row_start[i]; j < L_row_start[i+1]; j++)
580 pn = U_row_start[L_row_entry[j].index()];
581 multiplier = (L_row_entry[j].value() /= U_row_entry[pn].value());
584 for (pn++; pn < U_row_start[L_row_entry[j].index()+1] &&
585 U_row_entry[pn].index() <
i; pn++)
587 while (qn < L_row_start[i+1] && L_row_entry[qn].index()
588 < U_row_entry[pn].index())
590 if (qn < L_row_start[i+1] && U_row_entry[pn].index() ==
591 L_row_entry[qn].index())
592 L_row_entry[qn].value() -= multiplier * U_row_entry[pn].value();
594 for ( ; pn < U_row_start[L_row_entry[j].index()+1]; pn++)
596 while (rn < U_row_start[i+1] && U_row_entry[rn].index()
597 < U_row_entry[pn].index())
599 if (rn < U_row_start[i+1] && U_row_entry[pn].index()
600 == U_row_entry[rn].index())
601 U_row_entry[rn].value() -= multiplier * U_row_entry[pn].value();
643 for (
unsigned i = 0; i < static_cast<unsigned>(n_row);
i++)
645 for (
unsigned j = L_column_start[
i]; j < L_column_start[
i+1]; j++)
647 z[L_row_entry[j].index()] = z[L_row_entry[j].index()] -
648 z[
i]*L_row_entry[j].value();
654 for(
int i =n_row-1;
i >= 0;
i--)
656 x = z[
i]/U_row_entry[U_column_start[
i+1]-1].value();
658 for (
unsigned j = U_column_start[
i]; j < U_column_start[
i+1]-1;j++)
660 z[U_row_entry[j].index()] = z[U_row_entry[j].index()]
661 -x*U_row_entry[j].value();
668 z.redistribute(z_dist);
701 for (
int i = 0;
i < n_row;
i++)
704 for (
unsigned j = L_row_start[
i]; j < L_row_start[
i+1]; j++)
706 t = t + L_row_entry[j].value() * z[L_row_entry[j].index()];
712 for (
int i = n_row-1;
i >= 0;
i--)
715 for (
unsigned j = U_row_start[
i]+1; j < U_row_start[
i+1]; j++)
717 t = t + U_row_entry[j].value() * z[U_row_entry[j].index()];
720 z[
i] = z[
i] / U_row_entry[U_row_start[
i]].value();
726 z.redistribute(z_dist);
int * column_index()
Access to C-style column index array.
virtual DoubleMatrixBase * matrix_pt() const
Get function for matrix pointer.
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
Apply the preconditioner. Pure virtual generic interface function. This method should apply the preco...
double * values_pt()
access function to the underlying values
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to z, i.e. z=D^-1.
void setup()
Setup the preconditioner (store diagonal) from the fully assembled matrix.
int * row_index()
Access to C-style row index array.
Vector< double > Inv_diag
Vector of inverse diagonal entries.
bool distributed() const
access function to the distributed - indicates whether the distribution is serial or distributed ...
double * value()
Access to C-style value array.
unsigned long nnz() const
Return the number of nonzero entries.
bool distributed() const
distribution is serial or distributed
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
Matrix-based lumped preconditioner.
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
Base class for any linear algebra object that is distributable. Just contains storage for the LinearA...
CRDoubleMatrix * global_matrix() const
if this matrix is distributed then a the equivalent global matrix is built using new and returned...
void setup()
Setup the preconditioner (store diagonal) from the fully assembled matrix. Problem pointer is ignored...
unsigned first_row() const
access function for the first row on this processor
A class for compressed column matrices that store doubles.
unsigned nrow() const
access function to the number of global rows.
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to z, i.e. z=D^-1.
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
virtual const OomphCommunicator * comm_pt() const
Get function for comm pointer.
virtual void setup()=0
Setup the preconditioner. Pure virtual generic interface function.
unsigned nrow_local() const
access function for the num of local rows on this processor.
int * column_start()
Access to C-style column_start array.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
unsigned long nrow() const
Return the number of rows of the matrix.
int * row_start()
Access to C-style row_start array.
A class for compressed row matrices. This is a distributable object.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
T * value()
Access to C-style value array.
unsigned long nrow() const
Return the number of rows of the matrix.