00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP
00030 #define THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP
00031
00032 #include "Thyra_SpmdLinearOpBase.hpp"
00033 #include "Teuchos_DefaultComm.hpp"
00034 #include "Teuchos_CommHelpers.hpp"
00035
00133 template<class Scalar>
00134 class ExampleTridiagSpmdLinearOp : public Thyra::SpmdLinearOpBase<Scalar> {
00135 private:
00136
00137 Teuchos::RCP<const Teuchos::Comm<Thyra::Index> > comm_;
00138 int procRank_;
00139 int numProcs_;
00140 Thyra::Index localDim_;
00141 std::vector<Scalar> lower_;
00142 std::vector<Scalar> diag_;
00143 std::vector<Scalar> upper_;
00144
00145 void communicate( const bool first, const bool last, const Scalar x[], Scalar *x_km1, Scalar *x_kp1 ) const;
00146
00147 public:
00148
00150 using Thyra::SpmdLinearOpBase<Scalar>::euclideanApply;
00151
00153 ExampleTridiagSpmdLinearOp() : procRank_(0), numProcs_(0) {}
00154
00156 ExampleTridiagSpmdLinearOp(
00157 const Teuchos::RCP<const Teuchos::Comm<Thyra::Index> > &comm
00158 ,const Thyra::Index localDim, const Scalar lower[], const Scalar diag[], const Scalar upper[] )
00159 { this->initialize(comm,localDim,lower,diag,upper); }
00160
00180 void initialize(
00181 const Teuchos::RCP<const Teuchos::Comm<Thyra::Index> > &comm
00182 ,const Thyra::Index localDim
00183 ,const Scalar lower[]
00184 ,const Scalar diag[]
00185 ,const Scalar upper[]
00186 )
00187 {
00188 TEST_FOR_EXCEPT( localDim < 2 );
00189 this->setLocalDimensions(comm,localDim,localDim);
00190 comm_ = Teuchos::DefaultComm<Thyra::Index>::getDefaultSerialComm(comm);
00191 localDim_ = localDim;
00192 numProcs_ = comm->getSize();
00193 procRank_ = comm->getRank();
00194 const Thyra::Index
00195 lowerDim = ( procRank_ == 0 ? localDim - 1 : localDim ),
00196 upperDim = ( procRank_ == numProcs_-1 ? localDim - 1 : localDim );
00197 lower_.resize(lowerDim); for( int k = 0; k < lowerDim; ++k ) lower_[k] = lower[k];
00198 diag_.resize(localDim); for( int k = 0; k < localDim; ++k ) diag_[k] = diag[k];
00199 upper_.resize(upperDim); for( int k = 0; k < upperDim; ++k ) upper_[k] = upper[k];
00200 }
00201
00202
00203
00204 std::string description() const
00205 {
00206 return (std::string("ExampleTridiagSpmdLinearOp<") + Teuchos::ScalarTraits<Scalar>::name() + std::string(">"));
00207 }
00208
00209 protected:
00210
00211
00212
00213
00214 bool opSupported( Thyra::EOpTransp M_trans ) const
00215 {
00216 typedef Teuchos::ScalarTraits<Scalar> ST;
00217 return (M_trans == Thyra::NOTRANS || (!ST::isComplex && M_trans == Thyra::CONJ) );
00218 }
00219
00220
00221
00222 void euclideanApply(
00223 const Thyra::EOpTransp M_trans
00224 ,const RTOpPack::ConstSubVectorView<Scalar> &local_x_in
00225 ,const RTOpPack::SubVectorView<Scalar> *local_y_out
00226 ,const Scalar alpha
00227 ,const Scalar beta
00228 ) const
00229 {
00230 typedef Teuchos::ScalarTraits<Scalar> ST;
00231 TEST_FOR_EXCEPTION( M_trans != Thyra::NOTRANS, std::logic_error, "Error, can not handle transpose!" );
00232
00233 const Scalar zero = ST::zero();
00234
00235 const Scalar *x = local_x_in.values().get();
00236 Scalar *y = local_y_out->values().get();
00237
00238 const bool first = ( procRank_ == 0 ), last = ( procRank_ == numProcs_-1 );
00239
00240 Scalar x_km1, x_kp1;
00241 communicate( first, last, x, &x_km1, &x_kp1 );
00242
00243 Thyra::Index k = 0, lk = 0;
00244 if( beta == zero ) {
00245 y[k] = alpha * ( (first?zero:lower_[lk]*x_km1) + diag_[k]*x[k] + upper_[k]*x[k+1] ); if(!first) ++lk;
00246 for( k = 1; k < localDim_ - 1; ++lk, ++k )
00247 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + upper_[k]*x[k+1] );
00248 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + (last?zero:upper_[k]*x_kp1) );
00249 }
00250 else {
00251 y[k] = alpha * ( (first?zero:lower_[lk]*x_km1) + diag_[k]*x[k] + upper_[k]*x[k+1] ) + beta*y[k]; if(!first) ++lk;
00252 for( k = 1; k < localDim_ - 1; ++lk, ++k )
00253 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + upper_[k]*x[k+1] ) + beta*y[k];
00254 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + (last?zero:upper_[k]*x_kp1) ) + beta*y[k];
00255 }
00256
00257 }
00258
00259 };
00260
00261
00262
00263 template<class Scalar>
00264 void ExampleTridiagSpmdLinearOp<Scalar>::communicate(
00265 const bool first, const bool last, const Scalar x[], Scalar *x_km1, Scalar *x_kp1
00266 ) const
00267 {
00268 const bool isEven = (procRank_ % 2 == 0);
00269 const bool isOdd = !isEven;
00270
00271
00272 if( isEven && procRank_+1 < numProcs_ ) send(*comm_,x[localDim_-1],procRank_+1);
00273 if( isOdd && procRank_-1 >= 0 ) receive(*comm_,procRank_-1,x_km1);
00274
00275
00276 if( isOdd && procRank_-1 >= 0 ) send(*comm_,x[0],procRank_-1);
00277 if( isEven && procRank_+1 < numProcs_ ) receive(*comm_,procRank_+1,x_kp1);
00278
00279
00280 if( isOdd && procRank_+1 < numProcs_ ) send(*comm_,x[localDim_-1],procRank_+1);
00281 if( isEven && procRank_-1 >= 0 ) receive(*comm_,procRank_-1,x_km1);
00282
00283
00284 if(isEven && procRank_-1 >= 0 ) send(*comm_,x[0],procRank_-1);
00285 if(isOdd && procRank_+1 < numProcs_ ) receive(*comm_,procRank_+1,x_kp1);
00286 }
00287
00288 #endif // THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP