Reference documentation for deal.II version 9.2.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
trilinos_vector.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2020 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
17 
18 #ifdef DEAL_II_WITH_TRILINOS
19 
20 # include <deal.II/base/mpi.h>
22 
27 
28 # include <boost/io/ios_state.hpp>
29 
30 # include <Epetra_Export.h>
31 # include <Epetra_Import.h>
32 # include <Epetra_Vector.h>
33 
34 # include <cmath>
35 
36 
38 
39 namespace TrilinosWrappers
40 {
41 # ifndef DOXYGEN
42  namespace internal
43  {
44  VectorReference::operator TrilinosScalar() const
45  {
46  AssertIndexRange(index, vector.size());
47 
48  // Trilinos allows for vectors to be referenced by the [] or ()
49  // operators but only () checks index bounds. We check these bounds by
50  // ourselves, so we can use []. Note that we can only get local values.
51 
52  const TrilinosWrappers::types::int_type local_index =
53  vector.vector->Map().LID(
54  static_cast<TrilinosWrappers::types::int_type>(index));
55  Assert(local_index >= 0,
57  index,
58  vector.local_size(),
59  vector.vector->Map().MinMyGID(),
60  vector.vector->Map().MaxMyGID()));
61 
62 
63  return (*(vector.vector))[0][local_index];
64  }
65  } // namespace internal
66 # endif
67 
68  namespace MPI
69  {
71  : Subscriptor()
72  , last_action(Zero)
73  , compressed(true)
74  , has_ghosts(false)
75  , vector(new Epetra_FEVector(
76  Epetra_Map(0, 0, 0, Utilities::Trilinos::comm_self())))
77  {}
78 
79 
80 
81  Vector::Vector(const IndexSet &parallel_partitioning,
82  const MPI_Comm &communicator)
83  : Vector()
84  {
85  reinit(parallel_partitioning, communicator);
86  }
87 
88 
89 
91  : Vector()
92  {
94  vector = std_cxx14::make_unique<Epetra_FEVector>(*v.vector);
96  }
97 
98 
99 
100  Vector::Vector(Vector &&v) noexcept
101  : Vector()
102  {
103  // initialize a minimal, valid object and swap
104  swap(v);
105  }
106 
107 
108 
109  Vector::Vector(const IndexSet &parallel_partitioner,
110  const Vector & v,
111  const MPI_Comm &communicator)
112  : Vector()
113  {
114  AssertThrow(parallel_partitioner.size() ==
115  static_cast<size_type>(
117  ExcDimensionMismatch(parallel_partitioner.size(),
119  v.vector->Map())));
120 
121  vector = std_cxx14::make_unique<Epetra_FEVector>(
122  parallel_partitioner.make_trilinos_map(communicator, true));
123  reinit(v, false, true);
124  }
125 
126 
127 
128  Vector::Vector(const IndexSet &local,
129  const IndexSet &ghost,
130  const MPI_Comm &communicator)
131  : Vector()
132  {
133  reinit(local, ghost, communicator, false);
134  }
135 
136 
137 
138  void
140  {
141  // When we clear the vector, reset the pointer and generate an empty
142  // vector.
143 # ifdef DEAL_II_WITH_MPI
144  Epetra_Map map(0, 0, Epetra_MpiComm(MPI_COMM_SELF));
145 # else
146  Epetra_Map map(0, 0, Epetra_SerialComm());
147 # endif
148 
149  has_ghosts = false;
150  vector = std_cxx14::make_unique<Epetra_FEVector>(map);
151  last_action = Zero;
152  }
153 
154 
155 
156  void
157  Vector::reinit(const IndexSet &parallel_partitioner,
158  const MPI_Comm &communicator,
159  const bool /*omit_zeroing_entries*/)
160  {
161  nonlocal_vector.reset();
162 
163  const bool overlapping =
164  !parallel_partitioner.is_ascending_and_one_to_one(communicator);
165 
166  Epetra_Map map =
167  parallel_partitioner.make_trilinos_map(communicator, overlapping);
168 
169  vector = std_cxx14::make_unique<Epetra_FEVector>(map);
170 
171  has_ghosts = vector->Map().UniqueGIDs() == false;
172 
173  // If the IndexSets are overlapping, we don't really know
174  // which process owns what. So we decide that no process
175  // owns anything in that case. In particular asking for
176  // the locally owned elements is not allowed.
177  if (has_ghosts)
178  {
181  }
182  else
183  owned_elements = parallel_partitioner;
184 
185 # ifdef DEBUG
186  const size_type n_elements_global =
188 
189  Assert(has_ghosts || n_elements_global == size(), ExcInternalError());
190 # endif
191 
192  last_action = Zero;
193  }
194 
195 
196 
197  void
199  const bool omit_zeroing_entries,
200  const bool allow_different_maps)
201  {
202  nonlocal_vector.reset();
203 
204  // In case we do not allow to have different maps, this call means that
205  // we have to reset the vector. So clear the vector, initialize our map
206  // with the map in v, and generate the vector.
207  if (allow_different_maps == false)
208  {
209  // check equality for MPI communicators: We can only choose the fast
210  // version in case the underlying Epetra_MpiComm object is the same,
211  // otherwise we might access an MPI_Comm object that has been
212  // deleted
213 # ifdef DEAL_II_WITH_MPI
214  const Epetra_MpiComm *my_comm =
215  dynamic_cast<const Epetra_MpiComm *>(&vector->Comm());
216  const Epetra_MpiComm *v_comm =
217  dynamic_cast<const Epetra_MpiComm *>(&v.vector->Comm());
218  const bool same_communicators =
219  my_comm != nullptr && v_comm != nullptr &&
220  my_comm->DataPtr() == v_comm->DataPtr();
221 # else
222  const bool same_communicators = true;
223 # endif
224  if (!same_communicators ||
225  vector->Map().SameAs(v.vector->Map()) == false)
226  {
227  vector = std_cxx14::make_unique<Epetra_FEVector>(v.vector->Map());
229  last_action = Zero;
231  }
232  else if (omit_zeroing_entries == false)
233  {
234  // old and new vectors have exactly the same map, i.e. size and
235  // parallel distribution
236  int ierr;
237  ierr = vector->GlobalAssemble(last_action);
238  (void)ierr;
239  Assert(ierr == 0, ExcTrilinosError(ierr));
240 
241  ierr = vector->PutScalar(0.0);
242  Assert(ierr == 0, ExcTrilinosError(ierr));
243 
244  last_action = Zero;
245  }
246  }
247 
248  // Otherwise, we have to check that the two vectors are already of the
249  // same size, create an object for the data exchange and then insert all
250  // the data. The first assertion is only a check whether the user knows
251  // what they are doing.
252  else
253  {
254  Assert(omit_zeroing_entries == false,
255  ExcMessage(
256  "It is not possible to exchange data with the "
257  "option 'omit_zeroing_entries' set, which would not write "
258  "elements."));
259 
260  AssertThrow(size() == v.size(),
261  ExcDimensionMismatch(size(), v.size()));
262 
263  Epetra_Import data_exchange(vector->Map(), v.vector->Map());
264 
265  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
266  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
267 
268  last_action = Insert;
269  }
270 # if defined(DEBUG) && defined(DEAL_II_WITH_MPI)
271  const Epetra_MpiComm *comm_ptr =
272  dynamic_cast<const Epetra_MpiComm *>(&(v.vector->Comm()));
273  Assert(comm_ptr != nullptr, ExcInternalError());
274  const size_type n_elements_global =
275  Utilities::MPI::sum(owned_elements.n_elements(), comm_ptr->Comm());
276  Assert(has_ghosts || n_elements_global == size(), ExcInternalError());
277 # endif
278  }
279 
280 
281 
282  void
283  Vector::reinit(const MPI::BlockVector &v, const bool import_data)
284  {
285  nonlocal_vector.reset();
288 
289  // In case we do not allow to have different maps, this call means that
290  // we have to reset the vector. So clear the vector, initialize our map
291  // with the map in v, and generate the vector.
292  if (v.n_blocks() == 0)
293  return;
294 
295  // create a vector that holds all the elements contained in the block
296  // vector. need to manually create an Epetra_Map.
297  size_type n_elements = 0, added_elements = 0, block_offset = 0;
298  for (size_type block = 0; block < v.n_blocks(); ++block)
299  n_elements += v.block(block).local_size();
300  std::vector<TrilinosWrappers::types::int_type> global_ids(n_elements, -1);
301  for (size_type block = 0; block < v.n_blocks(); ++block)
302  {
303  TrilinosWrappers::types::int_type *glob_elements =
305  v.block(block).trilinos_partitioner());
306  for (size_type i = 0; i < v.block(block).local_size(); ++i)
307  global_ids[added_elements++] = glob_elements[i] + block_offset;
308  owned_elements.add_indices(v.block(block).owned_elements,
309  block_offset);
310  block_offset += v.block(block).size();
311  }
312 
313  Assert(n_elements == added_elements, ExcInternalError());
314  Epetra_Map new_map(v.size(),
315  n_elements,
316  global_ids.data(),
317  0,
318  v.block(0).trilinos_partitioner().Comm());
319 
320  auto actual_vec = std_cxx14::make_unique<Epetra_FEVector>(new_map);
321 
322  TrilinosScalar *entries = (*actual_vec)[0];
323  for (size_type block = 0; block < v.n_blocks(); ++block)
324  {
325  v.block(block).trilinos_vector().ExtractCopy(entries, 0);
326  entries += v.block(block).local_size();
327  }
328 
329  if (import_data == true)
330  {
332  *actual_vec)) == v.size(),
334  *actual_vec),
335  v.size()));
336 
337  Epetra_Import data_exchange(vector->Map(), actual_vec->Map());
338 
339  const int ierr = vector->Import(*actual_vec, data_exchange, Insert);
340  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
341 
342  last_action = Insert;
343  }
344  else
345  vector = std::move(actual_vec);
346 # if defined(DEBUG) && defined(DEAL_II_WITH_MPI)
347  const Epetra_MpiComm *comm_ptr =
348  dynamic_cast<const Epetra_MpiComm *>(&(vector->Comm()));
349  Assert(comm_ptr != nullptr, ExcInternalError());
350  const size_type n_elements_global =
351  Utilities::MPI::sum(owned_elements.n_elements(), comm_ptr->Comm());
352 
353  Assert(has_ghosts || n_elements_global == size(), ExcInternalError());
354 # endif
355  }
356 
357 
358 
359  void
360  Vector::reinit(const IndexSet &locally_owned_entries,
361  const IndexSet &ghost_entries,
362  const MPI_Comm &communicator,
363  const bool vector_writable)
364  {
365  nonlocal_vector.reset();
366  owned_elements = locally_owned_entries;
367  if (vector_writable == false)
368  {
369  IndexSet parallel_partitioner = locally_owned_entries;
370  parallel_partitioner.add_indices(ghost_entries);
371  Epetra_Map map =
372  parallel_partitioner.make_trilinos_map(communicator, true);
373  vector = std_cxx14::make_unique<Epetra_FEVector>(map);
374  }
375  else
376  {
377  Epetra_Map map =
378  locally_owned_entries.make_trilinos_map(communicator, true);
379  Assert(map.IsOneToOne(),
380  ExcMessage("A writable vector must not have ghost entries in "
381  "its parallel partitioning"));
382 
383  if (vector->Map().SameAs(map) == false)
384  vector = std_cxx14::make_unique<Epetra_FEVector>(map);
385  else
386  {
387  const int ierr = vector->PutScalar(0.);
388  (void)ierr;
389  Assert(ierr == 0, ExcTrilinosError(ierr));
390  }
391 
392  IndexSet nonlocal_entries(ghost_entries);
393  nonlocal_entries.subtract_set(locally_owned_entries);
394  if (Utilities::MPI::n_mpi_processes(communicator) > 1)
395  {
396  Epetra_Map nonlocal_map =
397  nonlocal_entries.make_trilinos_map(communicator, true);
399  std_cxx14::make_unique<Epetra_MultiVector>(nonlocal_map, 1);
400  }
401  }
402 
403  has_ghosts = vector->Map().UniqueGIDs() == false;
404 
405  last_action = Zero;
406 
407 # ifdef DEBUG
408  const size_type n_elements_global =
410 
411  Assert(has_ghosts || n_elements_global == size(), ExcInternalError());
412 # endif
413  }
414 
415 
416 
417  Vector &
419  {
420  Assert(vector.get() != nullptr,
421  ExcMessage("Vector is not constructed properly."));
422 
423  // check equality for MPI communicators to avoid accessing a possibly
424  // invalid MPI_Comm object
425 # ifdef DEAL_II_WITH_MPI
426  const Epetra_MpiComm *my_comm =
427  dynamic_cast<const Epetra_MpiComm *>(&vector->Comm());
428  const Epetra_MpiComm *v_comm =
429  dynamic_cast<const Epetra_MpiComm *>(&v.vector->Comm());
430  const bool same_communicators = my_comm != nullptr && v_comm != nullptr &&
431  my_comm->DataPtr() == v_comm->DataPtr();
432  // Need to ask MPI whether the communicators are the same. We would like
433  // to use the following checks but currently we cannot make sure the
434  // memory of my_comm is not stale from some MPI_Comm_free
435  // somewhere. This can happen when a vector lives in GrowingVectorMemory
436  // data structures. Thus, the following code is commented out.
437  //
438  // if (my_comm != nullptr &&
439  // v_comm != nullptr &&
440  // my_comm->DataPtr() != v_comm->DataPtr())
441  // {
442  // int communicators_same = 0;
443  // const int ierr = MPI_Comm_compare (my_comm->GetMpiComm(),
444  // v_comm->GetMpiComm(),
445  // &communicators_same);
446  // AssertThrowMPI(ierr);
447  // if (!(communicators_same == MPI_IDENT ||
448  // communicators_same == MPI_CONGRUENT))
449  // same_communicators = false;
450  // else
451  // same_communicators = true;
452  // }
453 # else
454  const bool same_communicators = true;
455 # endif
456 
457  // distinguish three cases. First case: both vectors have the same
458  // layout (just need to copy the local data, not reset the memory and
459  // the underlying Epetra_Map). The third case means that we have to
460  // rebuild the calling vector.
461  if (same_communicators && v.vector->Map().SameAs(vector->Map()))
462  {
463  *vector = *v.vector;
464  if (v.nonlocal_vector.get() != nullptr)
465  nonlocal_vector = std_cxx14::make_unique<Epetra_MultiVector>(
466  v.nonlocal_vector->Map(), 1);
467  last_action = Zero;
468  }
469  // Second case: vectors have the same global
470  // size, but different parallel layouts (and
471  // one of them a one-to-one mapping). Then we
472  // can call the import/export functionality.
473  else if (size() == v.size() &&
474  (v.vector->Map().UniqueGIDs() || vector->Map().UniqueGIDs()))
475  {
476  reinit(v, false, true);
477  }
478  // Third case: Vectors do not have the same
479  // size.
480  else
481  {
482  vector = std_cxx14::make_unique<Epetra_FEVector>(*v.vector);
483  last_action = Zero;
486  }
487 
488  if (v.nonlocal_vector.get() != nullptr)
490  std_cxx14::make_unique<Epetra_MultiVector>(v.nonlocal_vector->Map(),
491  1);
492 
493  return *this;
494  }
495 
496 
497 
498  Vector &
499  Vector::operator=(Vector &&v) noexcept
500  {
501  swap(v);
502  return *this;
503  }
504 
505 
506 
507  template <typename number>
508  Vector &
509  Vector::operator=(const ::Vector<number> &v)
510  {
511  Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
512 
513  // this is probably not very efficient but works. in particular, we could
514  // do better if we know that number==TrilinosScalar because then we could
515  // elide the copying of elements
516  //
517  // let's hope this isn't a particularly frequent operation
518  std::pair<size_type, size_type> local_range = this->local_range();
519  for (size_type i = local_range.first; i < local_range.second; ++i)
520  (*vector)[0][i - local_range.first] = v(i);
521 
522  return *this;
523  }
524 
525 
526 
527  void
529  const Vector & v)
530  {
531  Assert(m.trilinos_matrix().Filled() == true,
532  ExcMessage("Matrix is not compressed. "
533  "Cannot find exchange information!"));
534  Assert(v.vector->Map().UniqueGIDs() == true,
535  ExcMessage("The input vector has overlapping data, "
536  "which is not allowed."));
537 
538  if (vector->Map().SameAs(m.trilinos_matrix().ColMap()) == false)
539  vector =
540  std_cxx14::make_unique<Epetra_FEVector>(m.trilinos_matrix().ColMap());
541 
542  Epetra_Import data_exchange(vector->Map(), v.vector->Map());
543  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
544 
545  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
546 
547  last_action = Insert;
548  }
549 
550 
551  void
553  const VectorOperation::values operation)
554  {
555  Assert(
556  this->size() == rwv.size(),
557  ExcMessage(
558  "Both vectors need to have the same size for import() to work!"));
559  // TODO: a generic import() function should handle any kind of data layout
560  // in ReadWriteVector, but this function is of limited use as this class
561  // will (hopefully) be retired eventually.
564 
565  if (operation == VectorOperation::insert)
566  {
567  for (const auto idx : this->locally_owned_elements())
568  (*this)[idx] = rwv[idx];
569  }
570  else if (operation == VectorOperation::add)
571  {
572  for (const auto idx : this->locally_owned_elements())
573  (*this)[idx] += rwv[idx];
574  }
575  else
576  AssertThrow(false, ExcNotImplemented());
577 
578  this->compress(operation);
579  }
580 
581 
582  void
584  {
585  // Select which mode to send to Trilinos. Note that we use last_action if
586  // available and ignore what the user tells us to detect wrongly mixed
587  // operations. Typically given_last_action is only used on machines that
588  // do not execute an operation (because they have no own cells for
589  // example).
590  Epetra_CombineMode mode = last_action;
591  if (last_action == Zero)
592  {
593  if (given_last_action == ::VectorOperation::add)
594  mode = Add;
595  else if (given_last_action == ::VectorOperation::insert)
596  mode = Insert;
597  else
598  Assert(
599  false,
600  ExcMessage(
601  "compress() can only be called with VectorOperation add, insert, or unknown"));
602  }
603  else
604  {
605  Assert(
606  ((last_action == Add) &&
607  (given_last_action == ::VectorOperation::add)) ||
608  ((last_action == Insert) &&
609  (given_last_action == ::VectorOperation::insert)),
610  ExcMessage(
611  "The last operation on the Vector and the given last action in the compress() call do not agree!"));
612  }
613 
614 
615 # ifdef DEBUG
616 # ifdef DEAL_II_WITH_MPI
617  // check that every process has decided to use the same mode. This will
618  // otherwise result in undefined behaviour in the call to
619  // GlobalAssemble().
620  double double_mode = mode;
621  const Epetra_MpiComm *comm_ptr =
622  dynamic_cast<const Epetra_MpiComm *>(&(trilinos_partitioner().Comm()));
623  Assert(comm_ptr != nullptr, ExcInternalError());
625  Utilities::MPI::min_max_avg(double_mode, comm_ptr->GetMpiComm());
626  Assert(result.max - result.min < 1e-5,
627  ExcMessage(
628  "Not all processors agree whether the last operation on "
629  "this vector was an addition or a set operation. This will "
630  "prevent the compress() operation from succeeding."));
631 
632 # endif
633 # endif
634 
635  // Now pass over the information about what we did last to the vector.
636  int ierr = 0;
637  if (nonlocal_vector.get() == nullptr || mode != Add)
638  ierr = vector->GlobalAssemble(mode);
639  else
640  {
641  Epetra_Export exporter(nonlocal_vector->Map(), vector->Map());
642  ierr = vector->Export(*nonlocal_vector, exporter, mode);
643  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
644  ierr = nonlocal_vector->PutScalar(0.);
645  }
646  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
647  last_action = Zero;
648 
649  compressed = true;
650  }
651 
652 
653 
655  Vector::operator()(const size_type index) const
656  {
657  // Extract local indices in the vector.
658  TrilinosWrappers::types::int_type trilinos_i = vector->Map().LID(
659  static_cast<TrilinosWrappers::types::int_type>(index));
660  TrilinosScalar value = 0.;
661 
662  // If the element is not present on the current processor, we can't
663  // continue. This is the main difference to the el() function.
664  if (trilinos_i == -1)
665  {
666  Assert(false,
668  local_size(),
669  vector->Map().MinMyGID(),
670  vector->Map().MaxMyGID()));
671  }
672  else
673  value = (*vector)[0][trilinos_i];
674 
675  return value;
676  }
677 
678 
679 
680  void
681  Vector::add(const Vector &v, const bool allow_different_maps)
682  {
683  if (allow_different_maps == false)
684  *this += v;
685  else
686  {
688  AssertThrow(size() == v.size(),
689  ExcDimensionMismatch(size(), v.size()));
690 
691 # if DEAL_II_TRILINOS_VERSION_GTE(11, 11, 0)
692  Epetra_Import data_exchange(vector->Map(), v.vector->Map());
693  int ierr =
694  vector->Import(*v.vector, data_exchange, Epetra_AddLocalAlso);
695  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
696  last_action = Add;
697 # else
698  // In versions older than 11.11 the Import function is broken for
699  // adding Hence, we provide a workaround in this case
700 
701  Epetra_MultiVector dummy(vector->Map(), 1, false);
702  Epetra_Import data_exchange(dummy.Map(), v.vector->Map());
703 
704  int ierr = dummy.Import(*v.vector, data_exchange, Insert);
705  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
706 
707  ierr = vector->Update(1.0, dummy, 1.0);
708  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
709 # endif
710  }
711  }
712 
713 
714 
715  bool
716  Vector::operator==(const Vector &v) const
717  {
718  Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
719  if (local_size() != v.local_size())
720  return false;
721 
722  size_type i;
723  for (i = 0; i < local_size(); ++i)
724  if ((*(v.vector))[0][i] != (*vector)[0][i])
725  return false;
726 
727  return true;
728  }
729 
730 
731 
732  bool
733  Vector::operator!=(const Vector &v) const
734  {
735  Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
736 
737  return (!(*this == v));
738  }
739 
740 
741 
742  bool
744  {
745  // get a representation of the vector and
746  // loop over all the elements
747  TrilinosScalar * start_ptr = (*vector)[0];
748  const TrilinosScalar *ptr = start_ptr, *eptr = start_ptr + local_size();
749  unsigned int flag = 0;
750  while (ptr != eptr)
751  {
752  if (*ptr != 0)
753  {
754  flag = 1;
755  break;
756  }
757  ++ptr;
758  }
759 
760 # ifdef DEAL_II_WITH_MPI
761  // in parallel, check that the vector
762  // is zero on _all_ processors.
763  const Epetra_MpiComm *mpi_comm =
764  dynamic_cast<const Epetra_MpiComm *>(&vector->Map().Comm());
765  Assert(mpi_comm != nullptr, ExcInternalError());
766  unsigned int num_nonzero = Utilities::MPI::sum(flag, mpi_comm->Comm());
767  return num_nonzero == 0;
768 # else
769  return flag == 0;
770 # endif
771  }
772 
773 
774 
775  bool
777  {
778 # ifdef DEAL_II_WITH_MPI
779  // if this vector is a parallel one, then
780  // we need to communicate to determine
781  // the answer to the current
782  // function. this still has to be
783  // implemented
785 # endif
786  // get a representation of the vector and
787  // loop over all the elements
788  TrilinosScalar *start_ptr;
789  int leading_dimension;
790  int ierr = vector->ExtractView(&start_ptr, &leading_dimension);
791  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
792 
793  // TODO: This
794  // won't work in parallel like
795  // this. Find out a better way to
796  // this in that case.
797  const TrilinosScalar *ptr = start_ptr, *eptr = start_ptr + size();
798  bool flag = true;
799  while (ptr != eptr)
800  {
801  if (*ptr < 0.0)
802  {
803  flag = false;
804  break;
805  }
806  ++ptr;
807  }
808 
809  return flag;
810  }
811 
812 
813 
814  void
815  Vector::print(std::ostream & out,
816  const unsigned int precision,
817  const bool scientific,
818  const bool across) const
819  {
820  AssertThrow(out, ExcIO());
821  boost::io::ios_flags_saver restore_flags(out);
822 
823 
824  out.precision(precision);
825  if (scientific)
826  out.setf(std::ios::scientific, std::ios::floatfield);
827  else
828  out.setf(std::ios::fixed, std::ios::floatfield);
829 
830  if (size() != local_size())
831  {
832  auto global_id = [&](const size_type index) {
833  return gid(vector->Map(), index);
834  };
835  out << "size:" << size() << " local_size:" << local_size() << " :"
836  << std::endl;
837  for (size_type i = 0; i < local_size(); ++i)
838  out << "[" << global_id(i) << "]: " << (*(vector))[0][i]
839  << std::endl;
840  }
841  else
842  {
843  TrilinosScalar *val;
844  int leading_dimension;
845  int ierr = vector->ExtractView(&val, &leading_dimension);
846 
847  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
848  if (across)
849  for (size_type i = 0; i < size(); ++i)
850  out << static_cast<double>(val[i]) << ' ';
851  else
852  for (size_type i = 0; i < size(); ++i)
853  out << static_cast<double>(val[i]) << std::endl;
854  out << std::endl;
855  }
856 
857  AssertThrow(out, ExcIO());
858  }
859 
860 
861 
862  void
864  {
868  std::swap(vector, v.vector);
871  }
872 
873 
874 
875  std::size_t
877  {
878  // TODO[TH]: No accurate memory
879  // consumption for Trilinos vectors
880  // yet. This is a rough approximation with
881  // one index and the value per local
882  // entry.
883  return sizeof(*this) +
884  this->local_size() *
885  (sizeof(double) + sizeof(TrilinosWrappers::types::int_type));
886  }
887 
888  // explicit instantiations
889 # ifndef DOXYGEN
890 # include "trilinos_vector.inst"
891 # endif
892  } // namespace MPI
893 } // namespace TrilinosWrappers
894 
896 
897 #endif // DEAL_II_WITH_TRILINOS
IndexSet
Definition: index_set.h:74
IndexSet::subtract_set
void subtract_set(const IndexSet &other)
Definition: index_set.cc:258
TrilinosWrappers::MPI::Vector
Definition: trilinos_vector.h:400
LinearAlgebraDealII::Vector
Vector< double > Vector
Definition: generic_linear_algebra.h:43
StandardExceptions::ExcIO
static ::ExceptionBase & ExcIO()
TrilinosWrappers::SparseMatrix
Definition: trilinos_sparse_matrix.h:515
VectorOperation::insert
@ insert
Definition: vector_operation.h:49
StandardExceptions::ExcNotImplemented
static ::ExceptionBase & ExcNotImplemented()
BlockVectorBase::size
std::size_t size() const
TrilinosWrappers::MPI::Vector::vector
std::unique_ptr< Epetra_FEVector > vector
Definition: trilinos_vector.h:1315
IndexSet::size
size_type size() const
Definition: index_set.h:1635
TrilinosWrappers::MPI::Vector::print
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
Definition: trilinos_vector.cc:815
TrilinosWrappers::MPI::Vector::locally_owned_elements
IndexSet locally_owned_elements() const
TrilinosWrappers
Definition: types.h:161
AssertIndexRange
#define AssertIndexRange(index, range)
Definition: exceptions.h:1649
trilinos_index_access.h
TrilinosWrappers::MPI::BlockVector
Definition: trilinos_parallel_block_vector.h:75
trilinos_sparse_matrix.h
MPI_Comm
VectorOperation::add
@ add
Definition: vector_operation.h:53
Physics::Elasticity::Kinematics::e
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
IndexSet::make_trilinos_map
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:596
TrilinosWrappers::MPI::Vector::last_action
Epetra_CombineMode last_action
Definition: trilinos_vector.h:1296
TrilinosWrappers::MPI::Vector::import_nonlocal_data_for_fe
void import_nonlocal_data_for_fe(const ::TrilinosWrappers::SparseMatrix &matrix, const Vector &vector)
Definition: trilinos_vector.cc:528
TrilinosWrappers::MPI::Vector::nonlocal_vector
std::unique_ptr< Epetra_MultiVector > nonlocal_vector
Definition: trilinos_vector.h:1322
Utilities::MPI::MinMaxAvg::max
double max
Definition: mpi.h:705
TrilinosWrappers::MPI::Vector::Vector
Vector()
Definition: trilinos_vector.cc:70
TrilinosWrappers::MPI::Vector::local_size
size_type local_size() const
TrilinosWrappers::MPI::Vector::ExcAccessToNonLocalElement
static ::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
TrilinosWrappers::MPI::swap
void swap(BlockVector &u, BlockVector &v)
Definition: trilinos_parallel_block_vector.h:423
Subscriptor
Definition: subscriptor.h:62
IndexSet::n_elements
size_type n_elements() const
Definition: index_set.h:1833
IndexSet::set_size
void set_size(const size_type size)
Definition: index_set.h:1623
Utilities::MPI::MinMaxAvg
Definition: mpi.h:687
TrilinosWrappers::MPI::Vector::compress
void compress(::VectorOperation::values operation)
Definition: trilinos_vector.cc:583
TrilinosWrappers::MPI::Vector::operator=
Vector & operator=(const TrilinosScalar s)
TrilinosWrappers::MPI::Vector::swap
void swap(Vector &v)
Definition: trilinos_vector.cc:863
StandardExceptions::ExcMessage
static ::ExceptionBase & ExcMessage(std::string arg1)
TrilinosWrappers::MPI::Vector::size
size_type size() const
double
read_write_vector.h
mpi.h
TrilinosWrappers::MPI::Vector::trilinos_partitioner
const Epetra_BlockMap & trilinos_partitioner() const
DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:358
BlockVectorBase::n_blocks
unsigned int n_blocks() const
IndexSet::is_ascending_and_one_to_one
bool is_ascending_and_one_to_one(const MPI_Comm &communicator) const
Definition: index_set.cc:666
TrilinosWrappers::MPI::Vector::operator==
bool operator==(const Vector &v) const
Definition: trilinos_vector.cc:716
Utilities::MPI::sum
T sum(const T &t, const MPI_Comm &mpi_communicator)
VectorOperation::values
values
Definition: vector_operation.h:40
MemorySpace::swap
void swap(MemorySpaceData< Number, MemorySpace > &, MemorySpaceData< Number, MemorySpace > &)
Definition: memory_space.h:103
TrilinosWrappers::MPI::Vector::has_ghosts
bool has_ghosts
Definition: trilinos_vector.h:1308
IndexSet::clear
void clear()
Definition: index_set.h:1611
TrilinosWrappers::SparseMatrix::trilinos_matrix
const Epetra_CrsMatrix & trilinos_matrix() const
TrilinosWrappers::MPI::Vector::clear
void clear()
Definition: trilinos_vector.cc:139
Utilities::Trilinos::comm_self
const Epetra_Comm & comm_self()
Definition: utilities.cc:1114
LinearAlgebra::ReadWriteVector
Definition: read_write_vector.h:131
internal::dummy
const types::global_dof_index * dummy()
Definition: dof_handler.cc:59
unsigned int
value
static const bool value
Definition: dof_tools_constraints.cc:433
StandardExceptions::ExcInternalError
static ::ExceptionBase & ExcInternalError()
TrilinosWrappers::global_length
TrilinosWrappers::types::int_type global_length(const Epetra_MultiVector &vector)
Definition: trilinos_index_access.h:184
Assert
#define Assert(cond, exc)
Definition: exceptions.h:1419
TrilinosWrappers::MPI::Vector::all_zero
bool all_zero() const
Definition: trilinos_vector.cc:743
TrilinosWrappers::gid
int gid(const Epetra_BlockMap &map, int i)
Definition: trilinos_vector.h:199
Utilities::MPI::n_mpi_processes
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:117
Utilities::MPI::min_max_avg
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
Definition: mpi.cc:91
StandardExceptions::ExcGhostsPresent
static ::ExceptionBase & ExcGhostsPresent()
StandardExceptions::ExcDimensionMismatch
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
TrilinosWrappers::my_global_elements
TrilinosWrappers::types::int_type * my_global_elements(const Epetra_BlockMap &map)
Definition: trilinos_index_access.h:98
LinearAlgebra::ReadWriteVector::size
size_type size() const
internal
Definition: aligned_vector.h:369
TrilinosScalar
double TrilinosScalar
Definition: types.h:158
TrilinosWrappers::MPI::Vector::owned_elements
IndexSet owned_elements
Definition: trilinos_vector.h:1327
memory.h
TrilinosWrappers::MPI::Vector::import
void import(const LinearAlgebra::ReadWriteVector< double > &rwv, const VectorOperation::values operation)
Definition: trilinos_vector.cc:552
TrilinosWrappers::MPI::Vector::add
void add(const std::vector< size_type > &indices, const std::vector< TrilinosScalar > &values)
DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:359
BlockVectorBase::block
BlockType & block(const unsigned int i)
IndexSet::add_indices
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1704
Utilities::MPI::MinMaxAvg::min
double min
Definition: mpi.h:699
TrilinosWrappers::MPI::Vector::local_range
std::pair< size_type, size_type > local_range() const
TrilinosWrappers::MPI::Vector::reinit
void reinit(const Vector &v, const bool omit_zeroing_entries=false, const bool allow_different_maps=false)
Definition: trilinos_vector.cc:198
trilinos_vector.h
TrilinosWrappers::MPI::Vector::operator()
reference operator()(const size_type index)
LinearAlgebra::ReadWriteVector::get_stored_elements
const IndexSet & get_stored_elements() const
AssertThrow
#define AssertThrow(cond, exc)
Definition: exceptions.h:1531
TrilinosWrappers::MPI::Vector::ExcTrilinosError
static ::ExceptionBase & ExcTrilinosError(int arg1)
Utilities
Definition: cuda.h:31
TrilinosWrappers::MPI::Vector::has_ghost_elements
bool has_ghost_elements() const
TrilinosWrappers::MPI::Vector::compressed
bool compressed
Definition: trilinos_vector.h:1302
TrilinosWrappers::n_global_elements
TrilinosWrappers::types::int_type n_global_elements(const Epetra_BlockMap &map)
Definition: trilinos_index_access.h:40
TrilinosWrappers::MPI::Vector::memory_consumption
std::size_t memory_consumption() const
Definition: trilinos_vector.cc:876
trilinos_parallel_block_vector.h
TrilinosWrappers::MPI::Vector::is_non_negative
bool is_non_negative() const
Definition: trilinos_vector.cc:776
int
TrilinosWrappers::MPI::Vector::operator!=
bool operator!=(const Vector &v) const
Definition: trilinos_vector.cc:733