Peano
Loading...
Searching...
No Matches
STDVectorStack.h
Go to the documentation of this file.
1// This file is part of the Peano project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3#pragma once
4
5#include <vector>
6#include <algorithm>
7
8#include "stacks.h"
9
13
14#include "tarch/logging/Log.h"
15#include "tarch/Assertions.h"
16#include "tarch/mpi/Rank.h"
18
19namespace peano4 {
20 namespace stacks {
21 template <class T>
22 class STDVectorStack;
23
25
26 #if defined(Parallel)
27 template <class T>
29 #endif
30 }
31}
32
75template <class T>
77 protected:
82
86 std::vector< T > _data;
87
94
97 int _ioTag;
98 #ifdef Parallel
99 MPI_Request* _ioMPIRequest;
100 #endif
101
102 public:
112 _data(),
115 _ioRank(-1),
116 _ioTag(-1)
117 #ifdef Parallel
118 ,
119 _ioMPIRequest(nullptr)
120 #endif
121 {}
122
123 ~STDVectorStack() = default;
124
129 STDVectorStack( [[maybe_unused]] const STDVectorStack<T>& stack ):
130 _data(),
133 #ifdef Parallel
134 ,
135 _ioMPIRequest(nullptr)
136 #endif
137 {
138 assertionMsg( stack._currentElement==0, "may not copy non-empty stack" );
139 #ifdef Parallel
140 assertionMsg( stack._ioMPIRequest==nullptr, "may not copy sending/receiving stack" );
141 #endif
142 }
143
147 STDVectorStack& operator=( [[maybe_unused]] const STDVectorStack<T>& stack ) {
148 assertionEquals( stack._currentElement, 0 );
150 assertion( _data.empty() );
151 }
152
156 void clone( const STDVectorStack<T>& data ) {
158 _data.clear();
159 _currentElement = data._currentElement;
160 _data.resize(_currentElement, T(T::ObjectConstruction::NoData));
161 for (int n = 0; n<_currentElement; n++) {
162 _data[n] = data._data[n];
163 }
164 }
165
172 protected:
176 friend class peano4::stacks::STDVectorStack<T>;
177
178 const int _size;
179 const int _baseElement;
181
186 _size(size),
187 _baseElement(base),
188 _stack(stack) {
189 }
190
191 public:
192 int size() const {
193 return _size;
194 }
195
196 const T& get(int index) const {
197 assertion2( index>=0, index, _size );
198 assertion2( index<_size, index, _size );
199 return _stack->_data[_baseElement+index];
200 }
201
202 T& get(int index) {
203 assertion2( index>=0, index, _size );
204 assertion2( index<_size, index, _size );
205 return _stack->_data[_baseElement+index];
206 }
207
208 std::string toString() const {
209 std::ostringstream msg;
210 msg << "(size=" << _size
211 << ",baseElement=" << _baseElement
212 << ")";
213 return msg.str();
214 }
215 };
216
218 protected:
222 friend class peano4::stacks::STDVectorStack<T>;
223
228 _size(size),
229 _baseElement(base),
230 _stack(stack) {
231 }
232
233 const int _size;
234 const int _baseElement;
236
237 public:
238 inline int size() const {
239 return _size;
240 }
241
252 inline T* set(int index, const T& value) {
253 assertion2( index>=0, index, _size );
254 assertion2( index<_size, index, _size );
255 _stack->_data[_baseElement+index] = value;
256 return &(_stack->_data[_baseElement+index]);
257 }
258
259 inline const T& get(int index) const {
260 assertion2( index>=0, index, _size );
261 assertion2( index<_size, index, _size );
262 return _stack->_data[_baseElement+index];
263 }
264
265 inline T& get(int index) {
266 assertion2( index>=0, index, _size );
267 assertion2( index<_size, index, _size );
268 return _stack->_data[_baseElement+index];
269 }
270
271 inline std::string toString() const {
272 std::ostringstream msg;
273 msg << "(size=" << _size
274 << ",baseElement=" << _baseElement
275 << ")";
276 return msg.str();
277 }
278 };
279
299 T pop() {
302 return std::move( _data[_currentElement] );
303 }
304
310 T& top(int shift=0) {
311 assertion1(shift>=0,shift);
313 return _data[_currentElement-1-shift];
314 }
315
321 const T& top(int shift=0) const {
322 assertion1(shift>=0,shift);
324 return _data[_currentElement-1-shift];
325 }
326
332 void push( const T& element ) {
333 assertion( _currentElement <= static_cast<int>(_data.size()) );
334 if (_currentElement >= static_cast<int>(_data.size()) ) {
335 assertion(_currentElement - static_cast<int>(_data.size()) <= 1 );
336 _data.push_back( element );
337 } else {
338 _data[_currentElement] = element;
339 }
341 }
342
350 PopBlockStackView popBlock(int numberOfElements) {
351 _currentElement-=numberOfElements;
353
354 PopBlockStackView result(numberOfElements, _currentElement, this);
355 return result;
356 }
357
372 PushBlockStackView pushBlock(int numberOfElements) {
373 PushBlockStackView result(numberOfElements, _currentElement, this);
374
375 _currentElement+=numberOfElements;
376
377 if (static_cast<int>(_data.size())<=_currentElement) {
378 _data.resize(_currentElement, T(T::ObjectConstruction::NoData));
379 assertion(static_cast<int>(_data.size())>=_currentElement);
380 }
381
382 return result;
383 }
384
385 int size() const {
386 return _currentElement;
387 }
388
389 bool empty() const {
390 return _currentElement==0;
391 }
392
393 void clear() {
394 _currentElement = 0;
395 }
396
404 [[maybe_unused]] int rank,
405 [[maybe_unused]] int tag,
406 [[maybe_unused]] MPI_Comm comm
407 ) {
408 #ifdef Parallel
410 assertion( _ioMPIRequest==nullptr );
412 _ioTag = tag;
413 _ioRank = rank;
414
415 logDebug( "startSend(int,int,bool)", toString());
416
417 _ioMPIRequest = new MPI_Request;
418 int result = MPI_Isend(
419 _data.data(),
421 translateContextIntoDatatype<T>( context ),
423 if (result!=MPI_SUCCESS) {
424 logError( "startSend(int,int,bool)", "was not able to send to node " << rank << " on tag " << tag
425 << ": " << tarch::mpi::MPIReturnValueToString(result)
426 );
427 }
428 #endif
429 }
430
436 [[maybe_unused]] int rank,
437 [[maybe_unused]] int tag,
438 [[maybe_unused]] MPI_Comm comm,
439 [[maybe_unused]] int numberOfElements
440 ) {
441 #ifdef Parallel
442 assertion3( _ioMode==IOMode::None, rank, tag, numberOfElements );
443 assertion3( numberOfElements>0, rank, tag, numberOfElements );
444
446 _ioTag = tag;
447 _ioRank = rank;
448
449 _data.resize(numberOfElements, T(T::ObjectConstruction::NoData));
450 _currentElement = numberOfElements;
451 assertionEquals( _data.size(), numberOfElements );
452
453 assertion( _ioMPIRequest == nullptr );
454 _ioMPIRequest = new MPI_Request;
455
456 int result = MPI_Irecv(
457 _data.data(),
458 _data.size(),
459 translateContextIntoDatatype<T>( context ),
461 if (result!=MPI_SUCCESS) {
462 logError( "startReceive(int,int,int)", "was not able to receive " << numberOfElements << " values from node " << rank << " on tag " << tag
463 << ": " << tarch::mpi::MPIReturnValueToString(result)
464 );
465 }
466
467 logDebug( "startReceive()", toString() );
468 #endif
469 }
470
484 #ifdef Parallel
485 logTraceInWith4Arguments( "tryToFinishSendOrReceive()", ::toString(_ioMode), size(), _ioRank,_ioTag );
486 bool result = true;
488 assertion( _ioMPIRequest!=nullptr );
489
490 int flag = 0;
491 MPI_Test( _ioMPIRequest, &flag, MPI_STATUS_IGNORE );
492 if (flag) {
493 result = true;
494 logDebug( "tryToFinishSendOrReceive()", "send/receive complete, free MPI request: " << toString() );
495 delete _ioMPIRequest;
496 _ioMPIRequest = nullptr;
497 if (_ioMode==IOMode::MPISend ) {
498 clear();
499 }
501 } else {
502 result = false;
503 }
504 }
505 logTraceOutWith1Argument( "tryToFinishSendOrReceive()", result );
506 return result;
507 #else
508 return true;
509 #endif
510 }
511
518 int sendingOrReceiving() const {
519 return _ioMode==IOMode::None ? -1 : _ioRank;
520 }
521
529 void reverse() {
530 std::reverse(std::begin(_data), std::end(_data));
531 }
532
533 std::string toString() const {
534 std::ostringstream msg;
535 msg << "(size=" << size()
536 << ",current-element=" << _currentElement
537 << ",io-mode=" << ::toString( _ioMode )
538 << ",rank=" << _ioRank
539 << ",tag=" << _ioTag
540 << ")";
541 return msg.str();
542 }
543};
544
545template <class T>
546tarch::logging::Log peano4::stacks::STDVectorStack<T>::_log( "peano4::stacks::STDVectorStack<T>" );
547
548template <>
550
551template <>
553
554#if defined(Parallel)
555template <class T>
557 switch (context) {
559 return T::getBoundaryExchangeDatatype();
561 return T::getMultiscaleDataExchangeDatatype();
563 return T::getForkDatatype();
565 return T::getJoinDatatype();
567 assertionMsg(false, "periodic boundary data is never exchanged via MPI" );
568 return T::getGlobalCommunciationDatatype();
569 }
570 assertionMsg(false, "no valid case statement found. This may not happen" );
571 return T::getGlobalCommunciationDatatype();
572}
573#endif
#define assertion2(expr, param0, param1)
#define assertionEquals1(lhs, rhs, a)
#define assertion3(expr, param0, param1, param2)
#define assertionEquals(lhs, rhs)
#define assertion1(expr, param)
#define assertionMsg(expr, message)
#define assertion(expr)
#define logError(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:464
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logTraceOutWith1Argument(methodName, argument0)
Definition Log.h:380
#define logTraceInWith4Arguments(methodName, argument0, argument1, argument2, argument3)
Definition Log.h:373
SendReceiveContext
There are three different scenarios when we merge data:
This class represents a whole block of the tree.
peano4::stacks::STDVectorStack< T > * _stack
PopBlockStackView(int size, int base, peano4::stacks::STDVectorStack< T > *stack)
Constructor.
T * set(int index, const T &value)
Set an entry.
peano4::stacks::STDVectorStack< T > * _stack
PushBlockStackView(int size, int base, peano4::stacks::STDVectorStack< T > *stack)
Constructor.
Default stack implementation using std::vector.
std::vector< T > _data
This is the attribute holding all the temporary stacks.
void startSend(peano4::grid::TraversalObserver::SendReceiveContext context, int rank, int tag, MPI_Comm comm)
Always pairs up with a finish... call.
bool tryToFinishSendOrReceive()
If this routine is invoked on a stack which is neither sending or receiving, then it degenerates to n...
PopBlockStackView popBlock(int numberOfElements)
This operation grabs numberOfElements from the input stack en block and returns a view to it.
int _currentElement
Identifies top element of stack.
void push(const T &element)
Pushes element to a stack.
void reverse()
Reversing a stream is something I need extremely rarely.
static tarch::logging::Log _log
Logging device.
void startReceive(peano4::grid::TraversalObserver::SendReceiveContext context, int rank, int tag, MPI_Comm comm, int numberOfElements)
void clone(const STDVectorStack< T > &data)
Clone data into the current object on which clone() is called.
STDVectorStack & operator=(const STDVectorStack< T > &stack)
One is allowed to copy a stack but it has to be empty.
PushBlockStackView pushBlock(int numberOfElements)
Push a block on the output stack.
const T & top(int shift=0) const
Get top element or shiftth top element.
T pop()
Pops element from a stack.
int sendingOrReceiving() const
I need this one to find out whether I'm waiting for data.
STDVectorStack(const STDVectorStack< T > &stack)
One is allowed to clone/copy a stack, but it has to be empty.
T & top(int shift=0)
Get top element or shiftth top element.
Log Device.
Definition Log.h:516
MPI_Datatype translateContextIntoDatatype(peano4::grid::TraversalObserver::SendReceiveContext context)
STDVectorStack< peano4::grid::GridVertex > GridVertexStack
std::string MPIReturnValueToString(int result)
Definition Rank.cpp:209