Thyra Version of the Day
Loading...
Searching...
No Matches
ExampleTridiagSpmdLinearOp.hpp
1// @HEADER
2// *****************************************************************************
3// Thyra: Interfaces and Support for Abstract Numerical Algorithms
4//
5// Copyright 2004 NTESS and the Thyra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP
11#define THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP
12
13#include "Thyra_LinearOpDefaultBase.hpp"
14#include "Thyra_DefaultSpmdVectorSpace.hpp"
15#include "Thyra_DetachedSpmdVectorView.hpp"
16#include "Teuchos_DefaultComm.hpp"
17#include "Teuchos_CommHelpers.hpp"
18
19
106template<class Scalar>
108public:
109
112
116 const Thyra::Ordinal localDim,
120 )
121 { this->initialize(comm, localDim, lower, diag, upper); }
122
144 void initialize(
146 const Thyra::Ordinal localDim,
150 );
151
152protected:
153
154 // Overridden from LinearOpBase
155
159
163
166 {
167 return (M_trans == Thyra::NOTRANS);
168 }
169
171 void applyImpl(
172 const Thyra::EOpTransp M_trans,
175 const Scalar alpha,
176 const Scalar beta
177 ) const;
178
179private:
180
183 Teuchos::Array<Scalar> lower_; // size = ( procRank == 0 ? localDim - 1 : localDim )
184 Teuchos::Array<Scalar> diag_; // size = localDim
185 Teuchos::Array<Scalar> upper_; // size = ( procRank == numProc-1 ? localDim - 1 : localDim )
186
187 void communicate( const bool first, const bool last,
189 const Teuchos::Ptr<Scalar> &x_km1,
190 const Teuchos::Ptr<Scalar> &x_kp1 ) const;
191
192}; // end class ExampleTridiagSpmdLinearOp
193
194
195template<class Scalar>
198 const Thyra::Ordinal localDim,
202 )
203{
204 TEUCHOS_TEST_FOR_EXCEPT( localDim < 2 );
205 comm_ = comm;
206 space_ = Thyra::defaultSpmdVectorSpace<Scalar>(comm, localDim, -1);
207 lower_ = lower;
208 diag_ = diag;
209 upper_ = upper;
210}
211
212
213template<class Scalar>
215 const Thyra::EOpTransp M_trans,
218 const Scalar alpha,
219 const Scalar beta
220 ) const
221{
222
224 typedef Thyra::Ordinal Ordinal;
225 using Teuchos::outArg;
226
227 TEUCHOS_ASSERT(this->opSupported(M_trans));
228
229 // Get constants
230 const Scalar zero = ST::zero();
231 const Ordinal localDim = space_->localSubDim();
232 const Ordinal procRank = comm_->getRank();
233 const Ordinal numProcs = comm_->getSize();
234 const Ordinal m = X_in.domain()->dim();
235
236 // Loop over the input columns
237
238 for (Ordinal col_j = 0; col_j < m; ++col_j) {
239
240 // Get access the the elements of column j
242 Thyra::DetachedSpmdVectorView<Scalar> y_vec(Y_inout->col(col_j));
243 const Teuchos::ArrayRCP<const Scalar> x = x_vec.sv().values();
244 const Teuchos::ArrayRCP<Scalar> y = y_vec.sv().values();
245
246 // Determine what process we are
247 const bool first = (procRank == 0), last = ( procRank == numProcs-1 );
248
249 // Communicate ghost elements
250 Scalar x_km1, x_kp1;
251 communicate( first, last, x(), outArg(x_km1), outArg(x_kp1) );
252
253 // Perform operation (if beta==0 then we must be careful since y could
254 // be uninitialized on input!)
255 Thyra::Ordinal k = 0, lk = 0;
256 if( beta == zero ) {
257 // First local row
258 y[k] = alpha * ( (first?zero:lower_[lk]*x_km1) + diag_[k]*x[k]
259 + upper_[k]*x[k+1] );
260 if(!first) ++lk;
261 // Middle local rows
262 for( k = 1; k < localDim - 1; ++lk, ++k )
263 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + upper_[k]*x[k+1] );
264 // Last local row
265 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k]
266 + (last?zero:upper_[k]*x_kp1) );
267 }
268 else {
269 // First local row
270 y[k] = alpha * ( (first?zero:lower_[lk]*x_km1) + diag_[k]*x[k]
271 + upper_[k]*x[k+1] ) + beta*y[k];
272 if(!first) ++lk;
273 // Middle local rows
274 for( k = 1; k < localDim - 1; ++lk, ++k )
275 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k] + upper_[k]*x[k+1] )
276 + beta*y[k];
277 // Last local row
278 y[k] = alpha * ( lower_[lk]*x[k-1] + diag_[k]*x[k]
279 + (last?zero:upper_[k]*x_kp1) ) + beta*y[k];
280 }
281
282 }
283
284}
285
286
287template<class Scalar>
289 const bool first, const bool last,
291 const Teuchos::Ptr<Scalar> &x_km1,
292 const Teuchos::Ptr<Scalar> &x_kp1
293 ) const
294{
295 typedef Thyra::Ordinal Ordinal;
296 const Ordinal localDim = space_->localSubDim();
297 const Ordinal procRank = comm_->getRank();
298 const Ordinal numProcs = comm_->getSize();
299 const bool isEven = (procRank % 2 == 0);
300 const bool isOdd = !isEven;
301 // 1) Send x[localDim-1] from each even process forward to the next odd
302 // process where it is received in x_km1.
303 if(isEven && procRank+1 < numProcs) send(*comm_, x[localDim-1], procRank+1);
304 if(isOdd && procRank-1 >= 0) receive(*comm_, procRank-1, &*x_km1);
305 // 2) Send x[0] from each odd process backward to the previous even
306 // process where it is received in x_kp1.
307 if( isOdd && procRank-1 >= 0 ) send(*comm_, x[0], procRank-1);
308 if( isEven && procRank+1 < numProcs ) receive(*comm_, procRank+1, &*x_kp1);
309 // 3) Send x[localDim-1] from each odd process forward to the next even
310 // process where it is received in x_km1.
311 if (isOdd && procRank+1 < numProcs) send(*comm_, x[localDim-1], procRank+1);
312 if (isEven && procRank-1 >= 0) receive(*comm_, procRank-1, &*x_km1);
313 // 4) Send x[0] from each even process backward to the previous odd
314 // process where it is received in x_kp1.
315 if (isEven && procRank-1 >= 0) send(*comm_, x[0], procRank-1);
316 if (isOdd && procRank+1 < numProcs) receive(*comm_, procRank+1, &*x_kp1);
317}
318
319
320#endif // THYRA_EXAMPLE_TRIDIAG_SPMD_LINEAR_OP_HPP
Simple example subclass for Spmd tridiagonal matrices.
bool opSupportedImpl(Thyra::EOpTransp M_trans) const
void initialize(const Teuchos::RCP< const Teuchos::Comm< Thyra::Ordinal > > &comm, const Thyra::Ordinal localDim, const Teuchos::ArrayView< const Scalar > &lower, const Teuchos::ArrayView< const Scalar > &diag, const Teuchos::ArrayView< const Scalar > &upper)
void applyImpl(const Thyra::EOpTransp M_trans, const Thyra::MultiVectorBase< Scalar > &X_in, const Teuchos::Ptr< Thyra::MultiVectorBase< Scalar > > &Y_inout, const Scalar alpha, const Scalar beta) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > domain() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > range() const
ExampleTridiagSpmdLinearOp(const Teuchos::RCP< const Teuchos::Comm< Thyra::Ordinal > > &comm, const Thyra::Ordinal localDim, const Teuchos::ArrayView< const Scalar > &lower, const Teuchos::ArrayView< const Scalar > &diag, const Teuchos::ArrayView< const Scalar > &upper)
const ArrayRCP< const Scalar > values() const
const ArrayRCP< Scalar > values() const
Create an explicit detached non-mutable (const) view of all of the local elements on this process of ...
const RTOpPack::ConstSubVectorView< Scalar > & sv() const
Create an explicit detached mutable (non-const) view of all of the local elements on this process of ...
const RTOpPack::SubVectorView< Scalar > & sv() const
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
Return a smart pointer for the domain space for this operator.
Node subclass that provides a good default implementation for the describe() function.
Interface for a collection of column vectors called a multi-vector.
RCP< const VectorBase< Scalar > > col(Ordinal j) const
Calls colImpl().
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
@ NOTRANS
Use the non-transposed operator.