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_COMPLEX_FFT_LINEAR_OP_HPP
00030 #define THYRA_COMPLEX_FFT_LINEAR_OP_HPP
00031
00032 #include "Thyra_LinearOpWithSolveBase.hpp"
00033 #include "Thyra_SingleRhsLinearOpWithSolveBase.hpp"
00034 #include "Thyra_DefaultSpmdVectorSpace.hpp"
00035 #include "Thyra_DetachedVectorView.hpp"
00036 #include "serial_1D_FFT.hpp"
00037
00045 template<class RealScalar>
00046 class ComplexFFTLinearOp
00047 : virtual public Thyra::LinearOpWithSolveBase< std::complex<RealScalar> >
00048 , virtual protected Thyra::SingleRhsLinearOpWithSolveBase< std::complex<RealScalar> >
00049 {
00050 public:
00051
00053 typedef std::complex<RealScalar> Scalar;
00055 ComplexFFTLinearOp( const int N );
00056
00060 Teuchos::RCP< const Thyra::VectorSpaceBase< std::complex<RealScalar> > > range() const;
00062 Teuchos::RCP< const Thyra::VectorSpaceBase< std::complex<RealScalar> > > domain() const;
00064
00065 protected:
00066
00070 bool opSupported(Thyra::ETransp M_trans) const;
00072
00076 void apply(
00077 const Thyra::ETransp M_trans
00078 ,const Thyra::VectorBase< std::complex<RealScalar> > &x
00079 ,Thyra::VectorBase< std::complex<RealScalar> > *y
00080 ,const std::complex<RealScalar> alpha
00081 ,const std::complex<RealScalar> beta
00082 ) const;
00084
00088 bool solveSupportsTrans(Thyra::ETransp M_trans) const;
00090 bool solveSupportsSolveMeasureType(
00091 Thyra::ETransp M_trans, const Thyra::SolveMeasureType& solveMeasureType
00092 ) const;
00094
00098 Thyra::SolveStatus< std::complex<RealScalar> > solve(
00099 const Thyra::ETransp M_trans
00100 ,const Thyra::VectorBase< std::complex<RealScalar> > &b
00101 ,Thyra::VectorBase< std::complex<RealScalar> > *x
00102 ,const Thyra::SolveCriteria< std::complex<RealScalar> > *solveCriteria
00103 ) const;
00105
00106 private:
00107
00108 Teuchos::RCP< const Thyra::VectorSpaceBase< std::complex<RealScalar> > > space_;
00109
00110 };
00111
00112
00113
00114
00115 template<class RealScalar>
00116 ComplexFFTLinearOp<RealScalar>::ComplexFFTLinearOp( const int N )
00117 {
00118 space_ = Teuchos::rcp(
00119 new Thyra::DefaultSpmdVectorSpace< std::complex<RealScalar> >(
00120 int(std::pow(double(2),N))
00121 )
00122 );
00123 }
00124
00125
00126
00127 template<class RealScalar>
00128 Teuchos::RCP< const Thyra::VectorSpaceBase< std::complex<RealScalar> > >
00129 ComplexFFTLinearOp<RealScalar>::range() const
00130 {
00131 return space_;
00132 }
00133
00134 template<class RealScalar>
00135 Teuchos::RCP< const Thyra::VectorSpaceBase< std::complex<RealScalar> > >
00136 ComplexFFTLinearOp<RealScalar>::domain() const
00137 {
00138 return space_;
00139 }
00140
00141
00142
00143 template<class RealScalar>
00144 bool ComplexFFTLinearOp<RealScalar>::opSupported(Thyra::ETransp M_trans) const
00145 {
00146 return ( M_trans == Thyra::NOTRANS || M_trans == Thyra::CONJTRANS );
00147 }
00148
00149
00150
00151 template<class RealScalar>
00152 void ComplexFFTLinearOp<RealScalar>::apply(
00153 const Thyra::ETransp M_trans
00154 ,const Thyra::VectorBase< std::complex<RealScalar> > &x
00155 ,Thyra::VectorBase< std::complex<RealScalar> > *y
00156 ,const std::complex<RealScalar> alpha
00157 ,const std::complex<RealScalar> beta
00158 ) const
00159 {
00160 typedef Teuchos::ScalarTraits< std::complex<RealScalar> > ST;
00161 #ifdef TEUCHOS_DEBUG
00162 TEST_FOR_EXCEPT( !( M_trans == Thyra::NOTRANS || M_trans == Thyra::CONJTRANS ) );
00163 #endif
00164
00165 Thyra::Vt_S( y, beta );
00166
00167
00168 const Thyra::ConstDetachedVectorView<Scalar> x_ev(x);
00169 std::vector<RealScalar> data(2*x_ev.subDim());
00170 for( int k = 0; k < x_ev.subDim(); ++k ) {
00171 data[2*k] = x_ev[k].real();
00172 data[2*k+1] = x_ev[k].imag();
00173 }
00174
00175 serial_1D_FFT(
00176 &data[0]-1
00177 ,x_ev.subDim()
00178 ,Thyra::real_trans(M_trans)==Thyra::NOTRANS ? +1 : -1
00179 );
00180
00181 const Thyra::DetachedVectorView<Scalar> y_ev(*y);
00182 const Scalar scalar = alpha * Scalar(1)/ST::squareroot(x_ev.subDim());
00183 for( int k = 0; k < y_ev.subDim(); ++k ) {
00184 y_ev[k] += ( scalar * Scalar(data[2*k],data[2*k+1]) );
00185 }
00186 }
00187
00188
00189
00190 template<class RealScalar>
00191 bool ComplexFFTLinearOp<RealScalar>::solveSupportsTrans(Thyra::ETransp M_trans) const
00192 {
00193 return ( M_trans == Thyra::NOTRANS || M_trans == Thyra::CONJTRANS );
00194 }
00195
00196 template<class RealScalar>
00197 bool ComplexFFTLinearOp<RealScalar>::solveSupportsSolveMeasureType(
00198 Thyra::ETransp M_trans, const Thyra::SolveMeasureType& solveMeasureType
00199 ) const
00200 {
00201 return ( M_trans == Thyra::NOTRANS || M_trans == Thyra::CONJTRANS );
00202 }
00203
00204
00205
00206 template<class RealScalar>
00207 Thyra::SolveStatus< std::complex<RealScalar> >
00208 ComplexFFTLinearOp<RealScalar>::solve(
00209 const Thyra::ETransp M_trans
00210 ,const Thyra::VectorBase< std::complex<RealScalar> > &b
00211 ,Thyra::VectorBase< std::complex<RealScalar> > *x
00212 ,const Thyra::SolveCriteria< std::complex<RealScalar> > *solveCriteria
00213 ) const
00214 {
00215 typedef Teuchos::ScalarTraits< std::complex<RealScalar> > ST;
00216 #ifdef TEUCHOS_DEBUG
00217 TEST_FOR_EXCEPT( !( M_trans == Thyra::NOTRANS || M_trans == Thyra::CONJTRANS ) );
00218 #endif
00219 Thyra::apply( *this, M_trans==Thyra::NOTRANS?Thyra::CONJTRANS:Thyra::NOTRANS, b, x );
00220 typedef Thyra::SolveCriteria< std::complex<RealScalar> > SC;
00221 typedef Thyra::SolveStatus< std::complex<RealScalar> > SS;
00222 SS solveStatus;
00223 solveStatus.solveStatus = Thyra::SOLVE_STATUS_CONVERGED;
00224 solveStatus.achievedTol = SS::unknownTolerance();
00225 return solveStatus;
00226 }
00227
00228 #endif // THYRA_COMPLEX_FFT_LINEAR_OP_HPP