// Copyright (C) 2003-2009 Marc Duruflé
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.
#ifndef SELDON_FILE_UMFPACK_CXX
#include "UmfPack.hxx"
namespace Seldon
{
//! constructor
template<class T>
MatrixUmfPack_Base<T>::MatrixUmfPack_Base()
{
// first we clear arrays
Clear();
// allocation of arrays Control and Info
Control.Reallocate(UMFPACK_CONTROL);
Info.Reallocate(UMFPACK_INFO);
display_info = true;
}
template<class T>
MatrixUmfPack_Base<T>::~MatrixUmfPack_Base()
{
Clear();
}
template<class T>
void MatrixUmfPack_Base<T>::Clear()
{
n = 0;
Control.Clear(); Info.Clear();
}
//! no message will be displayed by UmfPack
template<class T>
void MatrixUmfPack_Base<T>::HideMessages()
{
display_info = false;
Control(UMFPACK_PRL) = 0;
}
//! normal amount of message displayed by UmfPack
template<class T>
void MatrixUmfPack_Base<T>::ShowMessages()
{
display_info = true;
Control(UMFPACK_PRL) = 2;
}
//! constructor
MatrixUmfPack<double>::MatrixUmfPack() : MatrixUmfPack_Base<double>()
{
umfpack_di_defaults(this->Control.GetData());
this->ShowMessages();
}
//! constructor
MatrixUmfPack<complex<double> >::MatrixUmfPack()
: MatrixUmfPack_Base<complex<double> >()
{
umfpack_zi_defaults(this->Control.GetData());
this->ShowMessages();
}
//! destructor
MatrixUmfPack<double>::~MatrixUmfPack()
{
if (this->n > 0)
{
// memory used by LU factorization is released
umfpack_di_free_numeric(&this->Numeric) ;
this->n = 0;
}
}
//! destructor
MatrixUmfPack<complex<double> >::~MatrixUmfPack()
{
if (this->n > 0)
{
// memory used by LU factorization is released
umfpack_zi_free_numeric(&this->Numeric) ;
this->n = 0;
}
}
//! factorization of a matrix in double precision
template<class Prop, class Storage, class Allocator>
void MatrixUmfPack<double>::
FactorizeMatrix(Matrix<double,Prop,Storage,Allocator> & mat,
bool keep_matrix)
{
// we clear previous factorization
Clear();
// conversion in CSR Format
Copy(mat, Acsr);
if (!keep_matrix)
mat.Clear();
// factorization with UmfPack
this->n = mat.GetM();
umfpack_di_symbolic(Acsr.GetM(), Acsr.GetN(), Acsr.GetPtr(),
Acsr.GetInd(), Acsr.GetData(), &this->Symbolic,
this->Control.GetData(), this->Info.GetData());
int status =
umfpack_di_numeric(Acsr.GetPtr(), Acsr.GetInd(), Acsr.GetData(),
this->Symbolic, &this->Numeric,
this->Control.GetData(), this->Info.GetData());
// memory for numbering scheme is released
umfpack_di_free_symbolic(&this->Symbolic) ;
// we display informations about the performed operation
if (this->display_info)
{
umfpack_di_report_status(this->Control.GetData(), status);
umfpack_di_report_info(this->Control.GetData(),this->Info.GetData());
}
}
template<class Allocator2>
void MatrixUmfPack<double>::Solve(Vector<double,VectFull,Allocator2>& x)
{
// we call UmfPack
Vector<double,VectFull,Allocator2> b(x);
int status
= umfpack_di_solve(UMFPACK_A, Acsr.GetPtr(), Acsr.GetInd(),
Acsr.GetData(), x.GetData(), b.GetData(),
this->Numeric, this->Control.GetData(),
this->Info.GetData());
// we display informations about the performed operation
if (this->display_info)
umfpack_di_report_status(this->Control.GetData(), status);
}
//! LU factorization using UmfPack in double complex precision
template<class Prop, class Storage,class Allocator>
void MatrixUmfPack<complex<double> >::
FactorizeMatrix(Matrix<complex<double>,Prop,Storage,Allocator> & mat,
bool keep_matrix)
{
Ptr.Clear(); Ind.Clear(); ValuesImag.Clear(); ValuesReal.Clear();
this->n = mat.GetM();
// conversion in CSR format
Matrix<complex<double>, General, ColSparse, Allocator> Acsr;
Copy(mat, Acsr);
if (!keep_matrix)
mat.Clear();
int nnz = Acsr.GetDataSize();
complex<double>* data = Acsr.GetData();
int* ptr_ = Acsr.GetPtr(); int* ind_ = Acsr.GetInd();
ValuesReal.Reallocate(nnz);
ValuesImag.Reallocate(nnz);
Ptr.Reallocate(this->n+1); Ind.Reallocate(nnz);
for (int i = 0; i < nnz; i++)
{
ValuesReal(i) = real(data[i]);
ValuesImag(i) = imag(data[i]);
Ind(i) = ind_[i];
}
for (int i = 0; i <= this->n; i++)
Ptr(i) = ptr_[i];
// we clear intermediary matrix Acsr
Acsr.Clear();
// we call UmfPack
umfpack_zi_symbolic(this->n, this->n, Ptr.GetData(), Ind.GetData(),
ValuesReal.GetData(),ValuesImag.GetData(),
&this->Symbolic, this->Control.GetData(),
this->Info.GetData());
int status
= umfpack_zi_numeric(Ptr.GetData(), Ind.GetData(),
ValuesReal.GetData(), ValuesImag.GetData(),
this->Symbolic, &this->Numeric,
this->Control.GetData(), this->Info.GetData());
umfpack_zi_free_symbolic(&this->Symbolic) ;
if (this->display_info)
{
umfpack_zi_report_status(this->Control.GetData(),status);
umfpack_zi_report_info(this->Control.GetData(),this->Info.GetData());
}
}
//! solves linear system in complex double precision using UmfPack
template<class Allocator2>
void MatrixUmfPack<complex<double> >::
Solve(Vector<complex<double>,VectFull,Allocator2>& x)
{
int m = x.GetM();
// creation of vectors
Vector<double> b_real(m),b_imag(m);
for (int i = 0; i < m; i++)
{
b_real(i) = real(x(i));
b_imag(i) = imag(x(i));
}
Vector<double> x_real(m),x_imag(m);
x_real.Zero();
x_imag.Zero();
int status
= umfpack_zi_solve(UMFPACK_A, Ptr.GetData(), Ind.GetData(),
ValuesReal.GetData(), ValuesImag.GetData(),
x_real.GetData(), x_imag.GetData(),
b_real.GetData(), b_imag.GetData(),
this->Numeric,
this->Control.GetData(), this->Info.GetData());
b_real.Clear();
b_imag.Clear();
for (int i = 0; i < m; i++)
x(i) = complex<double>(x_real(i), x_imag(i));
if (this->display_info)
umfpack_zi_report_status(this->Control.GetData(), status);
}
template<class T, class Prop, class Storage, class Allocator>
void GetLU(Matrix<T,Prop,Storage,Allocator>& A, MatrixUmfPack<T>& mat_lu,
bool keep_matrix = false)
{
mat_lu.FactorizeMatrix(A, keep_matrix);
}
template<class T, class Allocator>
void SolveLU(MatrixUmfPack<T>& mat_lu, Vector<T, VectFull, Allocator>& x)
{
mat_lu.Solve(x);
}
}
#define SELDON_FILE_UMFPACK_CXX
#endif