144template <class SC, class LO, class GO, class NO>
145void BlockMultiVector<SC,LO,GO,NO>::addBlock(const MultiVectorPtr_Type& multiVector,
int i){
147 TEUCHOS_TEST_FOR_EXCEPTION( multiVector.is_null(), std::runtime_error,
"MultiVector which you want to add to BlockMultiVector is null.")
148 if ( blockMultiVector_.size()>0 && !blockMultiVector_[0].is_null() )
149 TEUCHOS_TEST_FOR_EXCEPTION( multiVector->getNumVectors()!=blockMultiVector_[0]->getNumVectors(), std::logic_error,
"MultiVectors for BlockMultiVector have different numbers of vectors.");
151 if (i>blockMultiVector_.size()-1)
152 blockMultiVector_.resize( blockMultiVector_.size()+1 );
154 blockMultiVector_[i] = multiVector;
156 blockMap_->addBlock( multiVector->getMap(), i );
160template <
class SC,
class LO,
class GO,
class NO>
161void BlockMultiVector<SC,LO,GO,NO>::merge(){
162 if ( mergedMap_.is_null() ) {
164 mergedMap_ = Teuchos::rcp_const_cast<Map_Type>(blockMap_->getMergedMap());
168 mergedMultiVector_ = Teuchos::rcp(
new MultiVector_Type( mergedMap_, blockMultiVector_[0]->getNumVectors() ) );
169 this->determineLocalOffsets();
170 this->determineGlobalOffsets();
172 for (UN i=0; i<blockMultiVector_.size(); i++) {
173 if ( !blockMultiVector_[i].is_null() )
174 this->mergeBlock( i );
176 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"MultiVector in BlockMultiVector is null.")
180template <
class SC,
class LO,
class GO,
class NO>
181void BlockMultiVector<SC,LO,GO,NO>::mergeBlock(UN block){
183 MultiVectorPtr_Type mv = blockMultiVector_[block];
184 Teuchos::ArrayRCP<const SC> values;
185 GO offset = globalBlockOffsets_[block];
186 UN numVectors = mv->getNumVectors();
187 for (UN j=0; j<numVectors; j++) {
188 values = mv->getData(j);
189 for (UN i=0; i<values.size(); i++) {
190 mergedMultiVector_->replaceGlobalValue( mv->getMap()->getGlobalElement(i) + offset, j, values[i]);
195template <
class SC,
class LO,
class GO,
class NO>
196void BlockMultiVector<SC,LO,GO,NO>::split(){
197 TEUCHOS_TEST_FOR_EXCEPTION( mergedMultiVector_.is_null(), std::runtime_error,
"MergedMultiVector is null and we cannot use split on it. Use merge() first to generate the MergedMultiVector.")
199 for (UN i=0; i<blockMultiVector_.size(); i++) {
200 if ( !blockMultiVector_[i].is_null() )
201 this->splitBlock( i );
203 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"MultiVector in BlockMultiVector is null.")
207template <
class SC,
class LO,
class GO,
class NO>
208void BlockMultiVector<SC,LO,GO,NO>::splitBlock(UN block){
210 MultiVectorPtr_Type mv = blockMultiVector_[block];
211 MapConstPtr_Type map = mv->getMap();
212 Teuchos::ArrayRCP<const SC> values;
213 GO offset = globalBlockOffsets_[block];
214 UN numVectors = mv->getNumVectors();
215 UN numElements = (UN) map->getNodeNumElements();
216 for (UN j=0; j<numVectors; j++) {
217 values = mergedMultiVector_->getData(j);
218 for (UN i=0; i<numElements; i++) {
219 GO globalIndex = map->getGlobalElement(i) + offset;
220 LO index = mergedMultiVector_->getMap()->getLocalElement( globalIndex );
221 mv->replaceGlobalValue( mv->getMap()->getGlobalElement(i), j, values[index]);
226template <
class SC,
class LO,
class GO,
class NO>
227void BlockMultiVector<SC,LO,GO,NO>::determineLocalOffsets(){
229 typedef Teuchos::ScalarTraits<LO> LOST;
230 localBlockOffsets_ = Teuchos::ArrayRCP<LO>( blockMultiVector_.size(), LOST::zero() );
232 for (UN i=1; i<blockMultiVector_.size() ; i++)
233 localBlockOffsets_[i] = localBlockOffsets_[i-1] + blockMultiVector_[i-1]->getMap()->getMaxLocalIndex() + 1;
237template <
class SC,
class LO,
class GO,
class NO>
238void BlockMultiVector<SC,LO,GO,NO>::determineGlobalOffsets(){
240 typedef Teuchos::ScalarTraits<GO> GOST;
241 globalBlockOffsets_ = Teuchos::ArrayRCP<GO>( blockMultiVector_.size(), GOST::zero() );
243 for (UN i=1; i<blockMultiVector_.size() ; i++)
244 globalBlockOffsets_[i] = globalBlockOffsets_[i-1] + blockMultiVector_[i-1]->getMap()->getMaxAllGlobalIndex() + 1;
248template <
class SC,
class LO,
class GO,
class NO>
249void BlockMultiVector<SC,LO,GO,NO>::setMergedVector( MultiVectorPtr_Type& mv ){
251 mergedMultiVector_ = mv;
252 mergedMap_ = mv->getMapNonConst();
253 this->determineLocalOffsets();
254 this->determineGlobalOffsets();
258template <
class SC,
class LO,
class GO,
class NO>
259Teuchos::RCP< Thyra::MultiVectorBase<SC> > BlockMultiVector<SC,LO,GO,NO>::getThyraMultiVector( ) {
260 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_.size() == 0, std::logic_error,
"BlockMultiVector size is 0.")
261 Teuchos::RCP<Thyra::MultiVectorBase<SC> > thyraMV;
263 thyraMV = mergedMultiVector_->getThyraMultiVector( );
267template <class SC, class LO, class GO, class NO>
268Teuchos::RCP<const Thyra::MultiVectorBase<SC> > BlockMultiVector<SC,LO,GO,NO>::getThyraMultiVectorConst( ) {
269 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_.size() == 0, std::logic_error,
"BlockMultiVector size is 0.")
270 Teuchos::RCP<const Thyra::MultiVectorBase<SC> > thyraMV;
272 thyraMV = mergedMultiVector_->getThyraMultiVector( );
276template <class SC, class LO, class GO, class NO>
277Teuchos::RCP< Thyra::ProductMultiVectorBase<SC> > BlockMultiVector<SC,LO,GO,NO>::getProdThyraMultiVector( ) {
279 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_.size() == 0, std::logic_error,
"BlockMultiVector size is 0.")
281 Teuchos::Array< Teuchos::RCP< const Thyra::VectorSpaceBase< SC > > > vectorSpaces( blockMultiVector_.size() );
282 Teuchos::Array< Teuchos::RCP< Thyra::MultiVectorBase< SC > > > multiVecs( blockMultiVector_.size() );
283 for (
int i=0; i<blockMultiVector_.size(); i++){
284 multiVecs[i] = blockMultiVector_[i]->getThyraMultiVector();
285 vectorSpaces[i] = multiVecs[i]->range();
288 const Teuchos::RCP< Thyra::DefaultProductVectorSpace<SC> > productSpace = Thyra::productVectorSpace<SC>( vectorSpaces );
290 return Thyra::defaultProductMultiVector<SC>( productSpace, multiVecs );
293template <
class SC,
class LO,
class GO,
class NO>
294Teuchos::RCP<const Thyra::ProductMultiVectorBase<SC> > BlockMultiVector<SC,LO,GO,NO>::getThyraProdMultiVectorConst( )
const{
295 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"We need to implement this.")
296 Teuchos::RCP< const Thyra::ProductMultiVectorBase<SC> > thyraProdMV;
300template <class SC, class LO, class GO, class NO>
301void BlockMultiVector<SC,LO,GO,NO>::fromThyraMultiVector( Teuchos::RCP< Thyra::MultiVectorBase<SC> > thyraMV) {
302 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_.size() == 0, std::logic_error,
"BlockMultiVector size is 0.")
303 if (blockMultiVector_.size() == 1){
304 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_[0].is_null(), std::runtime_error,
"Block in BlockMultiVector is null.")
305 blockMultiVector_[0]->fromThyraMultiVector( thyraMV );
308 if (mergedMultiVector_.is_null())
310 mergedMultiVector_->fromThyraMultiVector( thyraMV );
316template <
class SC,
class LO,
class GO,
class NO>
317void BlockMultiVector<SC,LO,GO,NO>::fromThyraProdMultiVector( Teuchos::RCP< Thyra::ProductMultiVectorBase<SC> > thyraMV) {
318 TEUCHOS_TEST_FOR_EXCEPTION( blockMultiVector_.size() == 0, std::logic_error,
"BlockMultiVector size is 0.")
319 for (
int i=0; i<this->size(); i++) {
320 this->getBlockNonConst(i)->fromThyraMultiVector( thyraMV->getNonconstMultiVectorBlock( i ) );
325template <
class SC,
class LO,
class GO,
class NO>
326void BlockMultiVector<SC,LO,GO,NO>::norm2(
const Teuchos::ArrayView<
typename Teuchos::ScalarTraits<SC>::magnitudeType> &norms)
const {
327 typedef Teuchos::ScalarTraits<SC> ST;
328 for (
int j=0; j<norms.size(); j++)
329 norms[j] = ST::zero();
331 for (
int i=0; i<size(); i++) {
332 Teuchos::Array<SC> partialNorm(norms.size());
333 blockMultiVector_[i]->norm2(partialNorm());
334 for (
int j=0; j<partialNorm.size(); j++)
335 norms[j] += partialNorm[j]*partialNorm[j];
337 for (
int j=0; j<norms.size(); j++)
338 norms[j] = ST::squareroot( norms[j] );
341template <
class SC,
class LO,
class GO,
class NO>
342void BlockMultiVector<SC,LO,GO,NO>::normInf(
const Teuchos::ArrayView<
typename Teuchos::ScalarTraits<SC>::magnitudeType> &norms)
const {
343 typedef Teuchos::ScalarTraits<SC> ST;
344 for (
int j=0; j<norms.size(); j++)
345 norms[j] = ST::zero();
347 for (
int i=0; i<size(); i++) {
348 Teuchos::Array<SC> partialNorm(norms.size());
349 blockMultiVector_[i]->normInf(partialNorm());
350 for (
int j=0; j<partialNorm.size(); j++)
351 if(partialNorm[j]>norms[j])
352 norms[j] = partialNorm[j];
357template <
class SC,
class LO,
class GO,
class NO>
358void BlockMultiVector<SC,LO,GO,NO>::dot(BlockMultiVectorConstPtr_Type a,
const Teuchos::ArrayView<
typename Teuchos::ScalarTraits<SC>::magnitudeType> &dots) {
360 for (
int j=0; j<dots.size(); j++)
361 dots[j] = Teuchos::ScalarTraits<SC>::zero();
363 Teuchos::Array<SC> partialDots(dots.size());
364 for (
int i=0; i<size(); i++) {
365 blockMultiVector_[i]->dot( a->getBlock(i), partialDots() );
366 for (
int j=0; j<partialDots.size(); j++)
367 dots[j] += partialDots[j];
371template <
class SC,
class LO,
class GO,
class NO>
372typename BlockMultiVector<SC,LO,GO,NO>::BlockMultiVectorPtr_Type BlockMultiVector<SC,LO,GO,NO>::sumColumns()
const{
374 BlockMultiVectorPtr_Type sumBlockMV = Teuchos::rcp(
new BlockMultiVector_Type ( blockMap_, 1 ) );
376 for (
int i=0; i<this->size(); i++) {
377 MultiVectorConstPtr_Type tmpMV = this->getBlock(i);
378 MultiVectorPtr_Type sumMV = tmpMV->sumColumns();
379 sumBlockMV->addBlock( sumMV, i );
384template <
class SC,
class LO,
class GO,
class NO>
385void BlockMultiVector<SC,LO,GO,NO>::update(
const SC& alpha,
const BlockMultiVector_Type& A,
const SC& beta) {
387 TEUCHOS_TEST_FOR_EXCEPTION( size() != A.size(), std::logic_error,
"BlockMultiVector sizes are not equal for update.")
389 for (
int i=0; i<size(); i++) {
390 MultiVectorConstPtr_Type tmpA = A[i];
391 blockMultiVector_[i]->update( alpha, *tmpA, beta );
395template <
class SC,
class LO,
class GO,
class NO>
396void BlockMultiVector<SC,LO,GO,NO>::multiply(Teuchos::ETransp transA, Teuchos::ETransp transB,
const SC &alpha, BlockMultiVectorConstPtr_Type &A, BlockMultiVectorConstPtr_Type &B,
const SC &beta){
400 for (
int i=0; i<this->size(); i++){
401 MultiVectorConstPtr_Type a = A->getBlock(i);
402 MultiVectorConstPtr_Type b = B->getBlock(i);
403 this->getBlockNonConst(i)->multiply( transA, transB, alpha, a, b, beta );
407template <
class SC,
class LO,
class GO,
class NO>
408void BlockMultiVector<SC,LO,GO,NO>::update(
const SC& alpha,
const BlockMultiVector_Type& A,
const SC& beta ,
const BlockMultiVector_Type& B,
const SC& gamma) {
410 TEUCHOS_TEST_FOR_EXCEPTION( size() != A.size(), std::logic_error,
"BlockMultiVector sizes are not equal for update.")
412 for (
int i=0; i<size(); i++) {
413 MultiVectorConstPtr_Type tmpA = A[i];
414 MultiVectorConstPtr_Type tmpB = B[i];
415 blockMultiVector_[i]->update( alpha, *tmpA, beta, *tmpB, gamma);
419template <
class SC,
class LO,
class GO,
class NO>
420void BlockMultiVector<SC,LO,GO,NO>::putScalar(
const SC& alpha ) {
421 for (
int i=0; i<size(); i++) {
422 blockMultiVector_[i]->putScalar( alpha );
426template <
class SC,
class LO,
class GO,
class NO>
427void BlockMultiVector<SC,LO,GO,NO>::scale(
const SC& alpha ) {
428 for (
int i=0; i<size(); i++) {
429 blockMultiVector_[i]->scale( alpha );
433template <
class SC,
class LO,
class GO,
class NO>
434void BlockMultiVector<SC,LO,GO,NO>::writeMM(std::string fN)
const{
435 for (
int i=0; i<size(); i++) {
436 if (!blockMultiVector_[i].is_null() ){
437 std::string fileName = fN + std::to_string(i) +
".mm" ;
438 blockMultiVector_[i]->writeMM(fileName);
443template <
class SC,
class LO,
class GO,
class NO>
444void BlockMultiVector<SC,LO,GO,NO>::print(Teuchos::EVerbosityLevel verbLevel){
446 for (UN i=0; i<blockMultiVector_.size(); i++) {
447 if ( !blockMultiVector_[i].is_null() ) {
448 blockMultiVector_[i]->print( verbLevel );
453template <
class SC,
class LO,
class GO,
class NO>
454typename BlockMultiVector<SC,LO,GO,NO>::BlockMapConstPtr_Type BlockMultiVector<SC,LO,GO,NO>::getMap()
const{
459template <
class SC,
class LO,
class GO,
class NO>
460typename BlockMultiVector<SC,LO,GO,NO>::MultiVectorConstPtr_Type BlockMultiVector<SC,LO,GO,NO>::getMergedVector(){
461 if (this->size()>1) {
463 return mergedMultiVector_;
466 return this->getBlockNonConst(0);
469template <
class SC,
class LO,
class GO,
class NO>
471 if (this->size()>1) {
473 return mergedMultiVector_;
476 return this->getBlockNonConst(0);