#ifndef THYRA_SERIAL_TRIDIAG_LINEAR_OP_HPP
#define THYRA_SERIAL_TRIDIAG_LINEAR_OP_HPP
#include "Thyra_SerialLinearOpBase.hpp"
template<class Scalar>
class SerialTridiagLinearOp : public Thyra::SerialLinearOpBase<Scalar> {
private:
Thyra::Index dim_;
std::vector<Scalar> lower_;
std::vector<Scalar> diag_;
std::vector<Scalar> upper_;
public:
using Thyra::SerialLinearOpBase<Scalar>::euclideanApply;
SerialTridiagLinearOp() : dim_(0) {}
SerialTridiagLinearOp( const Thyra::Index dim, const Scalar lower[], const Scalar diag[], const Scalar upper[] )
{ this->initialize(dim,lower,diag,upper); }
void initialize(
const Thyra::Index dim
,const Scalar lower[]
,const Scalar diag[]
,const Scalar upper[]
)
{
TEST_FOR_EXCEPT( dim < 2 );
this->setDimensions(dim,dim);
dim_ = dim;
lower_.resize(dim-1); for( int k = 0; k < dim-1; ++k ) lower_[k] = lower[k];
diag_.resize(dim); for( int k = 0; k < dim; ++k ) diag_[k] = diag[k];
upper_.resize(dim-1); for( int k = 0; k < dim-1; ++k ) upper_[k] = upper[k];
}
std::string description() const
{
return (std::string("SerialTridiagLinearOp<") + Teuchos::ScalarTraits<Scalar>::name() + std::string(">"));
}
protected:
bool opSupported(Thyra::ETransp M_trans) const { return true; }
void euclideanApply(
const Thyra::ETransp M_trans
,const RTOpPack::SubVectorT<Scalar> &x_in
,const RTOpPack::MutableSubVectorT<Scalar> *y_out
,const Scalar alpha
,const Scalar beta
) const
{
typedef Teuchos::ScalarTraits<Scalar> ST;
const Scalar *x = x_in.values();
Scalar *y = y_out->values();
Thyra::Index k = 0;
if( beta == ST::zero() ) {
for( k = 0; k < dim_; ++k ) y[k] = ST::zero();
}
else if( beta != ST::one() ) {
for( k = 0; k < dim_; ++k ) y[k] *= beta;
}
k = 0;
if( M_trans == Thyra::NOTRANS ) {
y[k] += alpha * ( diag_[k]*x[k] + upper_[k]*x[k+1] );
for( k = 1; k < dim_ - 1; ++k )
y[k] += alpha * ( lower_[k-1]*x[k-1] + diag_[k]*x[k] + upper_[k]*x[k+1] );
y[k] += alpha * ( lower_[k-1]*x[k-1] + diag_[k]*x[k] );
}
else if( M_trans == Thyra::CONJ ) {
y[k] += alpha * ( ST::conjugate(diag_[k])*x[k] + ST::conjugate(upper_[k])*x[k+1] );
for( k = 1; k < dim_ - 1; ++k )
y[k] += alpha * ( ST::conjugate(lower_[k-1])*x[k-1] + ST::conjugate(diag_[k])*x[k] + ST::conjugate(upper_[k])*x[k+1] );
y[k] += alpha * ( ST::conjugate(lower_[k-1])*x[k-1] + ST::conjugate(diag_[k])*x[k] );
}
else if( M_trans == Thyra::TRANS ) {
y[k] += alpha * ( diag_[k]*x[k] + lower_[k]*x[k+1] );
for( k = 1; k < dim_ - 1; ++k )
y[k] += alpha * ( upper_[k-1]*x[k-1] + diag_[k]*x[k] + lower_[k]*x[k+1] );
y[k] += alpha * ( upper_[k-1]*x[k-1] + diag_[k]*x[k] );
}
else if( M_trans == Thyra::CONJTRANS ) {
y[k] += alpha * ( ST::conjugate(diag_[k])*x[k] + ST::conjugate(lower_[k])*x[k+1] );
for( k = 1; k < dim_ - 1; ++k )
y[k] += alpha * ( ST::conjugate(upper_[k-1])*x[k-1] + ST::conjugate(diag_[k])*x[k] + ST::conjugate(lower_[k])*x[k+1] );
y[k] += alpha * ( ST::conjugate(upper_[k-1])*x[k-1] + ST::conjugate(diag_[k])*x[k] );
}
else {
TEST_FOR_EXCEPT(true);
}
}
};
#endif // THYRA_SERIAL_TRIDIAG_LINEAR_OP_HPP