Reference documentation for deal.II version 8.5.1
trilinos_vector_base.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2017 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/memory_consumption.h>
17 #include <deal.II/lac/trilinos_vector_base.h>
18 
19 #ifdef DEAL_II_WITH_TRILINOS
20 
21 # include <deal.II/base/mpi.h>
22 
23 # include <cmath>
24 
25 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
26 # include <Epetra_Import.h>
27 # include <Epetra_Export.h>
28 
29 # include <boost/io/ios_state.hpp>
30 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
31 
32 
33 DEAL_II_NAMESPACE_OPEN
34 
35 namespace TrilinosWrappers
36 {
37  namespace
38  {
39 #ifndef DEAL_II_WITH_64BIT_INDICES
40  // define a helper function that queries the global vector length of an
41  // Epetra_FEVector object by calling either the 32- or 64-bit
42  // function necessary.
43  int global_length(const Epetra_FEVector &vector)
44  {
45  return vector.GlobalLength();
46  }
47 #else
48  // define a helper function that queries the global vector length of an
49  // Epetra_FEVector object by calling either the 32- or 64-bit
50  // function necessary.
51  long long int global_length(const Epetra_FEVector &vector)
52  {
53  return vector.GlobalLength64();
54  }
55 #endif
56  }
57 
58  namespace internal
59  {
60  VectorReference::operator TrilinosScalar () const
61  {
62  Assert (index < vector.size(),
63  ExcIndexRange (index, 0, vector.size()));
64 
65  // Trilinos allows for vectors to be referenced by the [] or ()
66  // operators but only () checks index bounds. We check these bounds by
67  // ourselves, so we can use []. Note that we can only get local values.
68 
69  const TrilinosWrappers::types::int_type local_index =
70  vector.vector->Map().LID(static_cast<TrilinosWrappers::types::int_type>(index));
71  Assert (local_index >= 0,
72  VectorBase::ExcAccessToNonLocalElement (index, vector.local_size(),
73  vector.vector->Map().MinMyGID(),
74  vector.vector->Map().MaxMyGID()));
75 
76 
77  return (*(vector.vector))[0][local_index];
78  }
79  }
80 
81 
82 
84  :
85  last_action (Zero),
86  compressed (true),
87  has_ghosts (false),
88 #ifdef DEAL_II_WITH_MPI
89  vector(new Epetra_FEVector(
90  Epetra_Map(0,0,Epetra_MpiComm(MPI_COMM_SELF))))
91 #else
92  vector(new Epetra_FEVector(
93  Epetra_Map(0,0,Epetra_SerialComm())))
94 #endif
95  {}
96 
97 
98 
100  :
101  Subscriptor(),
102  last_action (Zero),
103  compressed (true),
104  has_ghosts (v.has_ghosts),
105  vector(new Epetra_FEVector(*v.vector)),
106  owned_elements(complete_index_set(v.size()))
107  {}
108 
109 
110 
112  {}
113 
114 
115 
116  void
118  {
119  // When we clear the vector, reset the pointer and generate an empty
120  // vector.
121 #ifdef DEAL_II_WITH_MPI
122  Epetra_Map map (0, 0, Epetra_MpiComm(MPI_COMM_SELF));
123 #else
124  Epetra_Map map (0, 0, Epetra_SerialComm());
125 #endif
126 
127  has_ghosts = false;
128  vector.reset (new Epetra_FEVector(map));
129  last_action = Zero;
130  }
131 
132 
133 
134  VectorBase &
136  {
137  Assert (vector.get() != 0,
138  ExcMessage("Vector is not constructed properly."));
139 
140  if (local_range() != v.local_range())
141  {
142  last_action = Zero;
143  vector.reset (new Epetra_FEVector(*v.vector));
146  }
147  else
148  {
149  Assert (vector->Map().SameAs(v.vector->Map()) == true,
150  ExcMessage ("The Epetra maps in the assignment operator ="
151  " do not match, even though the local_range "
152  " seems to be the same. Check vector setup!"));
153  int ierr;
154  ierr = vector->GlobalAssemble(last_action);
155  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
156 
157  ierr = vector->Update(1.0, *v.vector, 0.0);
158  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
159 
160  last_action = Zero;
161  }
162 
163  return *this;
164  }
165 
166 
167 
168  template <typename number>
169  VectorBase &
170  VectorBase::operator = (const ::Vector<number> &v)
171  {
172  Assert (size() == v.size(),
173  ExcDimensionMismatch(size(), v.size()));
174 
175  // this is probably not very efficient
176  // but works. in particular, we could do
177  // better if we know that
178  // number==TrilinosScalar because then we
179  // could elide the copying of elements
180  //
181  // let's hope this isn't a
182  // particularly frequent operation
183  std::pair<size_type, size_type>
184  local_range = this->local_range ();
185  for (size_type i=local_range.first; i<local_range.second; ++i)
186  (*vector)[0][i-local_range.first] = v(i);
187 
188  return *this;
189  }
190 
191 
192 
193  void
195  {
196  //Select which mode to send to Trilinos. Note that we use last_action if
197  //available and ignore what the user tells us to detect wrongly mixed
198  //operations. Typically given_last_action is only used on machines that do
199  //not execute an operation (because they have no own cells for example).
200  Epetra_CombineMode mode = last_action;
201  if (last_action == Zero)
202  {
203  if (given_last_action==::VectorOperation::add)
204  mode = Add;
205  else if (given_last_action==::VectorOperation::insert)
206  mode = Insert;
207  }
208 
209 #ifdef DEBUG
210 # ifdef DEAL_II_WITH_MPI
211  // check that every process has decided to use the same mode. This will
212  // otherwise result in undefined behaviour in the call to
213  // GlobalAssemble().
214  double double_mode = mode;
215  const Epetra_MpiComm *comm_ptr
216  = dynamic_cast<const Epetra_MpiComm *>(&(vector_partitioner().Comm()));
217  Assert (comm_ptr != 0, ExcInternalError());
219  = Utilities::MPI::min_max_avg (double_mode, comm_ptr->GetMpiComm());
220  Assert(result.max-result.min<1e-5,
221  ExcMessage ("Not all processors agree whether the last operation on "
222  "this vector was an addition or a set operation. This will "
223  "prevent the compress() operation from succeeding."));
224 
225 # endif
226 #endif
227 
228  // Now pass over the information about what we did last to the vector.
229  int ierr = 0;
230  if (nonlocal_vector.get() == 0 || mode != Add)
231  ierr = vector->GlobalAssemble(mode);
232  else
233  {
234  Epetra_Export exporter(nonlocal_vector->Map(), vector->Map());
235  ierr = vector->Export(*nonlocal_vector, exporter, mode);
236  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
237  ierr = nonlocal_vector->PutScalar(0.);
238  }
239  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
240  last_action = Zero;
241 
242  compressed = true;
243  }
244 
245 
246 
247  TrilinosScalar
248  VectorBase::el (const size_type index) const
249  {
250  // Extract local indices in the vector.
251  TrilinosWrappers::types::int_type trilinos_i =
252  vector->Map().LID(static_cast<TrilinosWrappers::types::int_type>(index));
253 
254  // If the element is not present on the current processor, we can't
255  // continue. Just print out 0 as opposed to the () method below.
256  if (trilinos_i == -1)
257  return 0.;
258  else
259  return (*vector)[0][trilinos_i];
260  }
261 
262 
263 
264  TrilinosScalar
265  VectorBase::operator () (const size_type index) const
266  {
267  // Extract local indices in the vector.
268  TrilinosWrappers::types::int_type trilinos_i =
269  vector->Map().LID(static_cast<TrilinosWrappers::types::int_type>(index));
270  TrilinosScalar value = 0.;
271 
272  // If the element is not present on the current processor, we can't
273  // continue. This is the main difference to the el() function.
274  if (trilinos_i == -1)
275  {
277  vector->Map().MinMyGID(),
278  vector->Map().MaxMyGID()));
279  }
280  else
281  value = (*vector)[0][trilinos_i];
282 
283  return value;
284  }
285 
286 
287 
288  void
290  const bool allow_different_maps)
291  {
292  if (allow_different_maps == false)
293  *this += v;
294  else
295  {
297  AssertThrow (size() == v.size(),
298  ExcDimensionMismatch (size(), v.size()));
299 
300 #if DEAL_II_TRILINOS_VERSION_GTE(11,11,0)
301  Epetra_Import data_exchange (vector->Map(), v.vector->Map());
302  int ierr = vector->Import(*v.vector, data_exchange, Epetra_AddLocalAlso);
303  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
304  last_action = Add;
305 #else
306  // In versions older than 11.11 the Import function is broken for adding
307  // Hence, we provide a workaround in this case
308 
309  Epetra_MultiVector dummy(vector->Map(), 1, false);
310  Epetra_Import data_exchange (dummy.Map(), v.vector->Map());
311 
312  int ierr = dummy.Import(*v.vector, data_exchange, Insert);
313  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
314 
315  ierr = vector->Update (1.0, dummy, 1.0);
316  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
317 #endif
318  }
319  }
320 
321 
322 
323  bool
325  {
326  Assert (size() == v.size(),
327  ExcDimensionMismatch(size(), v.size()));
328  if (local_size() != v.local_size())
329  return false;
330 
331  size_type i;
332  for (i=0; i<local_size(); i++)
333  if ((*(v.vector))[0][i]!=(*vector)[0][i]) return false;
334 
335  return true;
336  }
337 
338 
339 
340  bool
342  {
343  Assert (size() == v.size(),
344  ExcDimensionMismatch(size(), v.size()));
345 
346  return (!(*this==v));
347  }
348 
349 
350 
351  bool
353  {
354  // get a representation of the vector and
355  // loop over all the elements
356  TrilinosScalar *start_ptr = (*vector)[0];
357  const TrilinosScalar *ptr = start_ptr,
358  *eptr = start_ptr + local_size();
359  unsigned int flag = 0;
360  while (ptr != eptr)
361  {
362  if (*ptr != 0)
363  {
364  flag = 1;
365  break;
366  }
367  ++ptr;
368  }
369 
370 #ifdef DEAL_II_WITH_MPI
371  // in parallel, check that the vector
372  // is zero on _all_ processors.
373  const Epetra_MpiComm *mpi_comm
374  = dynamic_cast<const Epetra_MpiComm *>(&vector->Map().Comm());
375  Assert(mpi_comm != 0, ExcInternalError());
376  unsigned int num_nonzero = Utilities::MPI::sum(flag, mpi_comm->Comm());
377  return num_nonzero == 0;
378 #else
379  return flag == 0;
380 #endif
381 
382  }
383 
384 
385 
386  bool
388  {
389 #ifdef DEAL_II_WITH_MPI
390  // if this vector is a parallel one, then
391  // we need to communicate to determine
392  // the answer to the current
393  // function. this still has to be
394  // implemented
396 #endif
397  // get a representation of the vector and
398  // loop over all the elements
399  TrilinosScalar *start_ptr;
400  int leading_dimension;
401  int ierr = vector->ExtractView (&start_ptr, &leading_dimension);
402  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
403 
404  // TODO: This
405  // won't work in parallel like
406  // this. Find out a better way to
407  // this in that case.
408  const TrilinosScalar *ptr = start_ptr,
409  *eptr = start_ptr + size();
410  bool flag = true;
411  while (ptr != eptr)
412  {
413  if (*ptr < 0.0)
414  {
415  flag = false;
416  break;
417  }
418  ++ptr;
419  }
420 
421  return flag;
422  }
423 
424 
425 
426  void
427  VectorBase::equ (const TrilinosScalar a,
428  const VectorBase &v,
429  const TrilinosScalar b,
430  const VectorBase &w)
431  {
432  // if we have ghost values, do not allow
433  // writing to this vector at all.
435  Assert (v.local_size() == w.local_size(),
436  ExcDimensionMismatch (v.local_size(), w.local_size()));
437 
438  AssertIsFinite(a);
439  AssertIsFinite(b);
440 
441  // If we don't have the same map, copy.
442  if (vector->Map().SameAs(v.vector->Map())==false)
443  {
444  sadd(0., a, v, b, w);
445  }
446  else
447  {
448  // Otherwise, just update. verify
449  // that *this does not only have
450  // the same map as v (the
451  // if-condition above) but also as
452  // w
453  Assert (vector->Map().SameAs(w.vector->Map()),
455  int ierr = vector->Update(a, *v.vector, b, *w.vector, 0.0);
456  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
457 
458  last_action = Zero;
459  }
460  }
461 
462 
463 
464  // TODO: up to now only local
465  // data printed out! Find a
466  // way to neatly output
467  // distributed data...
468  void
469  VectorBase::print (const char *format) const
470  {
471  Assert (global_length(*vector)!=0, ExcEmptyObject());
472  (void)global_length;
473 
474  for (size_type j=0; j<size(); ++j)
475  {
476  double t = (*vector)[0][j];
477 
478  if (format != 0)
479  std::printf (format, t);
480  else
481  std::printf (" %5.2f", double(t));
482  }
483  std::printf ("\n");
484  }
485 
486 
487 
488  void
489  VectorBase::print (std::ostream &out,
490  const unsigned int precision,
491  const bool scientific,
492  const bool across) const
493  {
494  AssertThrow (out, ExcIO());
495  boost::io::ios_flags_saver restore_flags(out);
496 
497  // get a representation of the
498  // vector and loop over all
499  // the elements TODO: up to
500  // now only local data printed
501  // out! Find a way to neatly
502  // output distributed data...
503  TrilinosScalar *val;
504  int leading_dimension;
505  int ierr = vector->ExtractView (&val, &leading_dimension);
506 
507  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
508  out.precision (precision);
509  if (scientific)
510  out.setf (std::ios::scientific, std::ios::floatfield);
511  else
512  out.setf (std::ios::fixed, std::ios::floatfield);
513 
514  if (across)
515  for (size_type i=0; i<size(); ++i)
516  out << static_cast<double>(val[i]) << ' ';
517  else
518  for (size_type i=0; i<size(); ++i)
519  out << static_cast<double>(val[i]) << std::endl;
520  out << std::endl;
521 
522  // restore the representation
523  // of the vector
524  AssertThrow (out, ExcIO());
525  }
526 
527 
528 
529  void
531  {
532  std::swap(last_action, v.last_action);
533  std::swap(compressed, v.compressed);
534  std::swap(vector, v.vector);
535  }
536 
537 
538 
539  std::size_t
541  {
542  //TODO[TH]: No accurate memory
543  //consumption for Trilinos vectors
544  //yet. This is a rough approximation with
545  //one index and the value per local
546  //entry.
547  return sizeof(*this)
548  + this->local_size()*( sizeof(double)+
549  sizeof(TrilinosWrappers::types::int_type) );
550  }
551 
552 } /* end of namespace TrilinosWrappers */
553 
554 
555 namespace TrilinosWrappers
556 {
557 #include "trilinos_vector_base.inst"
558 }
559 
560 DEAL_II_NAMESPACE_CLOSE
561 
562 #endif // DEAL_II_WITH_TRILINOS
reference operator()(const size_type index)
static ::ExceptionBase & ExcIO()
void sadd(const TrilinosScalar s, const VectorBase &V)
std_cxx11::shared_ptr< Epetra_MultiVector > nonlocal_vector
std::pair< size_type, size_type > local_range() const
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
static ::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void add(const std::vector< size_type > &indices, const std::vector< TrilinosScalar > &values)
static ::ExceptionBase & ExcMessage(std::string arg1)
T sum(const T &t, const MPI_Comm &mpi_communicator)
std_cxx11::shared_ptr< Epetra_FEVector > vector
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
const Epetra_Map & vector_partitioner() const
std::size_t memory_consumption() const
static ::ExceptionBase & ExcTrilinosError(int arg1)
void compress(::VectorOperation::values operation)
static ::ExceptionBase & ExcGhostsPresent()
TrilinosScalar el(const size_type index) const 1
VectorBase & operator=(const TrilinosScalar s)
static ::ExceptionBase & ExcEmptyObject()
bool operator!=(const VectorBase &v) const
static ::ExceptionBase & ExcNotImplemented()
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
Definition: mpi.cc:194
static ::ExceptionBase & ExcDifferentParallelPartitioning()
bool operator==(const VectorBase &v) const
#define AssertIsFinite(number)
Definition: exceptions.h:1197
size_type local_size() const
void print(const char *format=0) const 1
static ::ExceptionBase & ExcInternalError()
void equ(const TrilinosScalar a, const VectorBase &V)