Reference documentation for deal.II version 9.0.0
trilinos_epetra_vector.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2015 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/std_cxx14/memory.h>
17 #include <deal.II/lac/trilinos_epetra_vector.h>
18 
19 #ifdef DEAL_II_WITH_TRILINOS
20 
21 #ifdef DEAL_II_WITH_MPI
22 
23 #include <deal.II/base/index_set.h>
24 
25 #include <boost/io/ios_state.hpp>
26 #include <memory>
27 
28 #include <deal.II/lac/read_write_vector.h>
29 
30 # include <Epetra_Import.h>
31 # include <Epetra_Map.h>
32 # include <Epetra_MpiComm.h>
33 
34 
35 DEAL_II_NAMESPACE_OPEN
36 
37 namespace LinearAlgebra
38 {
39  namespace EpetraWrappers
40  {
42  :
43  vector(new Epetra_FEVector(Epetra_Map(0,0,0,Utilities::Trilinos::comm_self())))
44  {}
45 
46 
47 
49  :
50  Subscriptor(),
51  vector(new Epetra_FEVector(V.trilinos_vector()))
52  {}
53 
54 
55 
56  Vector::Vector(const IndexSet &parallel_partitioner,
57  const MPI_Comm &communicator)
58  :
59  vector(new Epetra_FEVector(parallel_partitioner.make_trilinos_map(communicator,false)))
60  {}
61 
62 
63 
64  void Vector::reinit(const IndexSet &parallel_partitioner,
65  const MPI_Comm &communicator,
66  const bool omit_zeroing_entries)
67  {
68  Epetra_Map input_map = parallel_partitioner.make_trilinos_map(communicator,false);
69  if (vector->Map().SameAs(input_map)==false)
70  vector = std_cxx14::make_unique<Epetra_FEVector>(input_map);
71  else if (omit_zeroing_entries==false)
72  {
73  const int ierr = vector->PutScalar(0.);
74  Assert(ierr==0, ExcTrilinosError(ierr));
75  (void) ierr;
76  }
77  }
78 
79 
80 
82  const bool omit_zeroing_entries)
83  {
84  // Check that casting will work.
85  Assert(dynamic_cast<const Vector *>(&V)!=nullptr, ExcVectorTypeNotCompatible());
86 
87  // Downcast V. If fails, throws an exception.
88  const Vector &down_V = dynamic_cast<const Vector &>(V);
89 
91  omit_zeroing_entries);
92  }
93 
94 
95 
97  {
98  // Distinguish three cases:
99  // - First case: both vectors have the same layout.
100  // - Second case: both vectors have the same size but different layout.
101  // - Third case: the vectors have different size.
102  if (vector->Map().SameAs(V.trilinos_vector().Map()))
103  *vector = V.trilinos_vector();
104  else
105  {
106  if (size()==V.size())
107  {
108  Epetra_Import data_exchange(vector->Map(), V.trilinos_vector().Map());
109 
110  const int ierr = vector->Import(V.trilinos_vector(), data_exchange, Insert);
111  Assert(ierr==0, ExcTrilinosError(ierr));
112  (void) ierr;
113  }
114  else
115  vector = std_cxx14::make_unique<Epetra_FEVector>(V.trilinos_vector());
116  }
117 
118  return *this;
119  }
120 
121 
122 
123  Vector &Vector::operator= (const double s)
124  {
125  Assert(s==0., ExcMessage("Only 0 can be assigned to a vector."));
126 
127  const int ierr = vector->PutScalar(s);
128  Assert(ierr == 0, ExcTrilinosError(ierr));
129  (void) ierr;
130 
131  return *this;
132  }
133 
134 
135 
137  VectorOperation::values operation,
138  std::shared_ptr<const CommunicationPatternBase> communication_pattern)
139  {
140  // If no communication pattern is given, create one. Otherwsie, use the
141  // one given.
142  if (communication_pattern == nullptr)
143  {
144  // The first time import is called, a communication pattern is created.
145  // Check if the communication pattern already exists and if it can be
146  // reused.
149  {
151  dynamic_cast<const Epetra_MpiComm &>(vector->Comm()).Comm());
152  }
153  }
154  else
155  {
157  std::dynamic_pointer_cast<const CommunicationPattern> (communication_pattern);
158  AssertThrow(epetra_comm_pattern != nullptr,
159  ExcMessage(std::string("The communication pattern is not of type ") +
160  "LinearAlgebra::EpetraWrappers::CommunicationPattern."));
161  }
162 
163  Epetra_Import import(epetra_comm_pattern->get_epetra_import());
164 
165  // The TargetMap and the SourceMap have their roles inverted.
166  Epetra_FEVector source_vector(import.TargetMap());
167  double *values = source_vector.Values();
168  std::copy(V.begin(), V.end(), values);
169 
170  if (operation==VectorOperation::insert)
171  vector->Export(source_vector, import, Insert);
172  else
173  vector->Export(source_vector, import, Add);
174  }
175 
176 
177 
178  Vector &Vector::operator*= (const double factor)
179  {
180  AssertIsFinite(factor);
181  vector->Scale(factor);
182 
183  return *this;
184  }
185 
186 
187 
188  Vector &Vector::operator/= (const double factor)
189  {
190  AssertIsFinite(factor);
191  Assert(factor!=0., ExcZero());
192  *this *= 1./factor;
193 
194  return *this;
195  }
196 
197 
198 
200  {
201  // Check that casting will work.
202  Assert(dynamic_cast<const Vector *>(&V)!=nullptr, ExcVectorTypeNotCompatible());
203 
204  // Downcast V. If fails, throws an exception.
205  const Vector &down_V = dynamic_cast<const Vector &>(V);
206  // If the maps are the same we can Update right away.
207  if (vector->Map().SameAs(down_V.trilinos_vector().Map()))
208  {
209  const int ierr = vector->Update(1., down_V.trilinos_vector(), 1.);
210  Assert(ierr==0, ExcTrilinosError(ierr));
211  (void) ierr;
212  }
213  else
214  {
215  Assert(this->size()==down_V.size(),
216  ExcDimensionMismatch(this->size(), down_V.size()));
217 
218 #if DEAL_II_TRILINOS_VERSION_GTE(11,11,0)
219  Epetra_Import data_exchange (vector->Map(), down_V.trilinos_vector().Map());
220  const int ierr = vector->Import(down_V.trilinos_vector(),
221  data_exchange, Epetra_AddLocalAlso);
222  Assert(ierr==0, ExcTrilinosError(ierr));
223  (void) ierr;
224 #else
225  // In versions older than 11.11 the Import function is broken for adding
226  // Hence, we provide a workaround in this case
227 
228  Epetra_MultiVector dummy(vector->Map(), 1, false);
229  Epetra_Import data_exchange(dummy.Map(), down_V.trilinos_vector().Map());
230 
231  int ierr = dummy.Import(down_V.trilinos_vector(), data_exchange, Insert);
232  Assert(ierr==0, ExcTrilinosError(ierr));
233 
234  ierr = vector->Update(1.0, dummy, 1.0);
235  Assert(ierr==0, ExcTrilinosError(ierr));
236  (void) ierr;
237 #endif
238  }
239 
240  return *this;
241  }
242 
243 
244 
246  {
247  this->add(-1.,V);
248 
249  return *this;
250  }
251 
252 
253 
255  {
256  // Check that casting will work.
257  Assert(dynamic_cast<const Vector *>(&V)!=nullptr,
259 
260  // Downcast V. If fails, throws an exception.
261  const Vector &down_V = dynamic_cast<const Vector &>(V);
262  Assert(this->size()==down_V.size(),
263  ExcDimensionMismatch(this->size(), down_V.size()));
264  Assert(vector->Map().SameAs(down_V.trilinos_vector().Map()),
266 
267  double result(0.);
268  const int ierr = vector->Dot(down_V.trilinos_vector(), &result);
269  Assert(ierr==0, ExcTrilinosError(ierr));
270  (void) ierr;
271 
272  return result;
273  }
274 
275 
276 
277  void Vector::add(const double a)
278  {
279  AssertIsFinite(a);
280  const unsigned local_size(vector->MyLength());
281  for (unsigned int i=0; i<local_size; ++i)
282  (*vector)[0][i] += a;
283  }
284 
285 
286 
287  void Vector::add(const double a, const VectorSpaceVector<double> &V)
288  {
289  // Check that casting will work.
290  Assert(dynamic_cast<const Vector *>(&V)!=nullptr,
292 
293  // Downcast V. If fails, throws an exception.
294  const Vector &down_V = dynamic_cast<const Vector &>(V);
295  AssertIsFinite(a);
296  Assert(vector->Map().SameAs(down_V.trilinos_vector().Map()),
298 
299  const int ierr = vector->Update(a, down_V.trilinos_vector(), 1.);
300  Assert(ierr==0, ExcTrilinosError(ierr));
301  (void) ierr;
302  }
303 
304 
305 
306  void Vector::add(const double a, const VectorSpaceVector<double> &V,
307  const double b, const VectorSpaceVector<double> &W)
308  {
309  // Check that casting will work.
310  Assert(dynamic_cast<const Vector *>(&V)!=nullptr,
312  // Check that casting will work.
313  Assert(dynamic_cast<const Vector *>(&W)!=nullptr,
315 
316  // Downcast V. If fails, throws an exception.
317  const Vector &down_V = dynamic_cast<const Vector &>(V);
318  // Downcast W. If fails, throws an exception.
319  const Vector &down_W = dynamic_cast<const Vector &>(W);
320  Assert(vector->Map().SameAs(down_V.trilinos_vector().Map()),
322  Assert(vector->Map().SameAs(down_W.trilinos_vector().Map()),
324  AssertIsFinite(a);
325  AssertIsFinite(b);
326 
327  const int ierr = vector->Update(a, down_V.trilinos_vector(), b,
328  down_W.trilinos_vector(), 1.);
329  Assert(ierr==0, ExcTrilinosError(ierr));
330  (void) ierr;
331  }
332 
333 
334 
335  void Vector::sadd(const double s, const double a,
336  const VectorSpaceVector<double> &V)
337  {
338  // Check that casting will work.
339  Assert(dynamic_cast<const Vector *>(&V)!=nullptr,
341 
342  *this *= s;
343  // Downcast V. It fails, throws an exception.
344  const Vector &down_V = dynamic_cast<const Vector &>(V);
345  Vector tmp(down_V);
346  tmp *= a;
347  *this += tmp;
348  }
349 
350 
351 
352  void Vector::scale(const VectorSpaceVector<double> &scaling_factors)
353  {
354  // Check that casting will work.
355  Assert(dynamic_cast<const Vector *>(&scaling_factors)!=nullptr,
357 
358  // Downcast scaling_factors. If fails, throws an exception.
359  const Vector &down_scaling_factors =
360  dynamic_cast<const Vector &>(scaling_factors);
361  Assert(vector->Map().SameAs(down_scaling_factors.trilinos_vector().Map()),
363 
364  const int ierr = vector->Multiply(1.0, down_scaling_factors.trilinos_vector(),
365  *vector, 0.0);
366  Assert(ierr==0, ExcTrilinosError(ierr));
367  (void) ierr;
368  }
369 
370 
371 
372  void Vector::equ(const double a, const VectorSpaceVector<double> &V)
373  {
374  // Check that casting will work.
375  Assert(dynamic_cast<const Vector *>(&V)!=nullptr,
377 
378  // Downcast V. If fails, throws an exception.
379  const Vector &down_V = dynamic_cast<const Vector &>(V);
380  // If we don't have the same map, copy.
381  if (vector->Map().SameAs(down_V.trilinos_vector().Map())==false)
382  this->sadd(0., a, V);
383  else
384  {
385  // Otherwise, just update
386  int ierr = vector->Update(a, down_V.trilinos_vector(), 0.);
387  Assert(ierr==0, ExcTrilinosError(ierr));
388  (void) ierr;
389  }
390  }
391 
392 
393 
394  bool Vector::all_zero() const
395  {
396  // get a representation of the vector and
397  // loop over all the elements
398  double *start_ptr = (*vector)[0];
399  const double *ptr = start_ptr,
400  *eptr = start_ptr + vector->MyLength();
401  unsigned int flag = 0;
402  while (ptr != eptr)
403  {
404  if (*ptr != 0)
405  {
406  flag = 1;
407  break;
408  }
409  ++ptr;
410  }
411 
412  // Check that the vector is zero on _all_ processors.
413  const Epetra_MpiComm *mpi_comm
414  = dynamic_cast<const Epetra_MpiComm *>(&vector->Map().Comm());
415  Assert(mpi_comm != nullptr, ExcInternalError());
416  unsigned int num_nonzero = Utilities::MPI::sum(flag, mpi_comm->Comm());
417 
418  return num_nonzero == 0;
419  }
420 
421 
422 
423  double Vector::mean_value() const
424  {
425  double mean_value(0.);
426 
427  int ierr = vector->MeanValue(&mean_value);
428  Assert(ierr==0, ExcTrilinosError(ierr));
429  (void) ierr;
430 
431  return mean_value;
432  }
433 
434 
435 
436  double Vector::l1_norm() const
437  {
438  double norm(0.);
439  int ierr = vector->Norm1(&norm);
440  Assert(ierr==0, ExcTrilinosError(ierr));
441  (void) ierr;
442 
443  return norm;
444  }
445 
446 
447 
448  double Vector::l2_norm() const
449  {
450  double norm(0.);
451  int ierr = vector->Norm2(&norm);
452  Assert(ierr==0, ExcTrilinosError(ierr));
453  (void) ierr;
454 
455  return norm;
456  }
457 
458 
459 
460  double Vector::linfty_norm() const
461  {
462  double norm(0.);
463  int ierr = vector->NormInf(&norm);
464  Assert(ierr==0, ExcTrilinosError(ierr));
465  (void) ierr;
466 
467  return norm;
468  }
469 
470 
471 
472  double Vector::add_and_dot(const double a,
473  const VectorSpaceVector<double> &V,
474  const VectorSpaceVector<double> &W)
475  {
476  this->add(a, V);
477 
478  return *this * W;
479  }
480 
481 
482 
483  Vector::size_type Vector::size() const
484  {
485 #ifndef DEAL_II_WITH_64BIT_INDICES
486  return vector->GlobalLength();
487 #else
488  return vector->GlobalLength64();
489 #endif
490  }
491 
492 
493 
495  {
496  const Epetra_MpiComm *epetra_comm
497  = dynamic_cast<const Epetra_MpiComm *>(&(vector->Comm()));
498  Assert (epetra_comm != nullptr, ExcInternalError());
499  return epetra_comm->GetMpiComm();
500  }
501 
502 
503 
505  {
506  IndexSet is (size());
507 
508  // easy case: local range is contiguous
509  if (vector->Map().LinearMap())
510  {
511 #ifndef DEAL_II_WITH_64BIT_INDICES
512  is.add_range(vector->Map().MinMyGID(), vector->Map().MaxMyGID()+1);
513 #else
514  is.add_range(vector->Map().MinMyGID64(), vector->Map().MaxMyGID64()+1);
515 #endif
516  }
517  else if (vector->Map().NumMyElements() > 0)
518  {
519  const size_type n_indices = vector->Map().NumMyElements();
520 #ifndef DEAL_II_WITH_64BIT_INDICES
521  unsigned int *vector_indices = (unsigned int *)vector->Map().MyGlobalElements();
522 #else
523  size_type *vector_indices = (size_type *)vector->Map().MyGlobalElements64();
524 #endif
525  is.add_indices(vector_indices, vector_indices+n_indices);
526  }
527  is.compress();
528 
529  return is;
530  }
531 
532 
533 
534  const Epetra_FEVector &Vector::trilinos_vector() const
535  {
536  return *vector;
537  }
538 
539 
540 
541  Epetra_FEVector &Vector::trilinos_vector()
542  {
543  return *vector;
544  }
545 
546 
547 
548  void Vector::print(std::ostream &out,
549  const unsigned int precision,
550  const bool scientific,
551  const bool across) const
552  {
553  AssertThrow(out, ExcIO());
554  boost::io::ios_flags_saver restore_flags(out);
555 
556  // Get a representation of the vector and loop over all
557  // the elements
558  double *val;
559  int leading_dimension;
560  int ierr = vector->ExtractView(&val, &leading_dimension);
561 
562  Assert(ierr==0, ExcTrilinosError(ierr));
563  (void) ierr;
564  out.precision (precision);
565  if (scientific)
566  out.setf(std::ios::scientific, std::ios::floatfield);
567  else
568  out.setf(std::ios::fixed, std::ios::floatfield);
569 
570  if (across)
571  for (int i=0; i<vector->MyLength(); ++i)
572  out << val[i] << ' ';
573  else
574  for (int i=0; i<vector->MyLength(); ++i)
575  out << val[i] << std::endl;
576  out << std::endl;
577 
578  // restore the representation
579  // of the vector
580  AssertThrow(out, ExcIO());
581  }
582 
583 
584 
585  std::size_t Vector::memory_consumption() const
586  {
587  return sizeof(*this)
588  + vector->MyLength()*(sizeof(double)+
589  sizeof(TrilinosWrappers::types::int_type));
590  }
591 
592 
593 
594  void Vector::create_epetra_comm_pattern(const IndexSet &source_index_set,
595  const MPI_Comm &mpi_comm)
596  {
597  source_stored_elements = source_index_set;
598  epetra_comm_pattern = std::make_shared<CommunicationPattern>
599  (locally_owned_elements(), source_index_set, mpi_comm);
600  }
601  }
602 }
603 
604 DEAL_II_NAMESPACE_CLOSE
605 
606 #endif
607 
608 #endif
virtual double l1_norm() const override
static ::ExceptionBase & ExcDifferentParallelPartitioning()
static ::ExceptionBase & ExcIO()
virtual ::IndexSet locally_owned_elements() const override
virtual double l2_norm() const override
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1619
virtual size_type size() const override
virtual void scale(const VectorSpaceVector< double > &scaling_factors) override
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
virtual std::size_t memory_consumption() const override
std::unique_ptr< Epetra_FEVector > vector
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:549
size_type size() const
Definition: index_set.h:1575
virtual void equ(const double a, const VectorSpaceVector< double > &V) override
static ::ExceptionBase & ExcMessage(std::string arg1)
T sum(const T &t, const MPI_Comm &mpi_communicator)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void create_epetra_comm_pattern(const IndexSet &source_index_set, const MPI_Comm &mpi_comm)
virtual Vector & operator*=(const double factor) override
virtual void import(const ReadWriteVector< double > &V, VectorOperation::values operation, std::shared_ptr< const CommunicationPatternBase > communication_pattern=std::shared_ptr< const CommunicationPatternBase >()) override
const Epetra_FEVector & trilinos_vector() const
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcVectorTypeNotCompatible()
void reinit(const IndexSet &parallel_partitioner, const MPI_Comm &communicator, const bool omit_zeroing_entries=false)
std::shared_ptr< const CommunicationPattern > epetra_comm_pattern
virtual void sadd(const double s, const double a, const VectorSpaceVector< double > &V) override
void add_range(const size_type begin, const size_type end)
Definition: index_set.cc:98
virtual Vector & operator+=(const VectorSpaceVector< double > &V) override
Definition: cuda.h:31
void compress() const
Definition: index_set.h:1584
virtual Vector & operator/=(const double factor) override
virtual void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const override
virtual double mean_value() const override
virtual Vector & operator-=(const VectorSpaceVector< double > &V) override
virtual double operator*(const VectorSpaceVector< double > &V) const override
virtual void add(const double a) override
static ::ExceptionBase & ExcZero()
#define AssertIsFinite(number)
Definition: exceptions.h:1299
virtual double linfty_norm() const override
const IndexSet & get_stored_elements() const
static ::ExceptionBase & ExcInternalError()
virtual double add_and_dot(const double a, const VectorSpaceVector< double > &V, const VectorSpaceVector< double > &W) override