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