Reference documentation for deal.II version 8.4.2
trilinos_vector.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2015 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/lac/trilinos_vector.h>
17 
18 #ifdef DEAL_II_WITH_TRILINOS
19 
20 # include <deal.II/lac/trilinos_sparse_matrix.h>
21 # include <deal.II/lac/trilinos_block_vector.h>
22 
23 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
24 # include <Epetra_Import.h>
25 # include <Epetra_Vector.h>
27 
28 # include <cmath>
29 
30 
31 DEAL_II_NAMESPACE_OPEN
32 
33 namespace TrilinosWrappers
34 {
35  namespace
36  {
37 #ifndef DEAL_II_WITH_64BIT_INDICES
38  // define a helper function that queries the size of an Epetra_BlockMap object
39  // by calling either the 32- or 64-bit function necessary, and returns the
40  // result in the correct data type so that we can use it in calling other
41  // Epetra member functions that are overloaded by index type
42  int n_global_elements (const Epetra_BlockMap &map)
43  {
44  return map.NumGlobalElements();
45  }
46  // define a helper function that queries the pointer to internal array
47  // containing list of global IDs assigned to the calling processor
48  // by calling either the 32- or 64-bit function necessary, and returns the
49  // result in the correct data type so that we can use it in calling other
50  // Epetra member functions that are overloaded by index type
51  int *my_global_elements(const Epetra_BlockMap &map)
52  {
53  return map.MyGlobalElements();
54  }
55  // define a helper function that queries the global vector length of an
56  // Epetra_FEVector object by calling either the 32- or 64-bit
57  // function necessary.
58  int global_length(const Epetra_FEVector &vector)
59  {
60  return vector.GlobalLength();
61  }
62 #else
63  // define a helper function that queries the size of an Epetra_BlockMap object
64  // by calling either the 32- or 64-bit function necessary, and returns the
65  // result in the correct data type so that we can use it in calling other
66  // Epetra member functions that are overloaded by index type
67  long long int n_global_elements (const Epetra_BlockMap &map)
68  {
69  return map.NumGlobalElements64();
70  }
71  // define a helper function that queries the pointer to internal array
72  // containing list of global IDs assigned to the calling processor
73  // by calling either the 32- or 64-bit function necessary, and returns the
74  // result in the correct data type so that we can use it in calling other
75  // Epetra member functions that are overloaded by index type
76  long long int *my_global_elements(const Epetra_BlockMap &map)
77  {
78  return map.MyGlobalElements64();
79  }
80  // define a helper function that queries the global vector length of an
81  // Epetra_FEVector object by calling either the 32- or 64-bit
82  // function necessary.
83  long long int global_length(const Epetra_FEVector &vector)
84  {
85  return vector.GlobalLength64();
86  }
87 #endif
88  }
89 
90  namespace MPI
91  {
92 
93 
95  {
96  last_action = Zero;
97  vector.reset(new Epetra_FEVector(Epetra_Map(0,0,0,Utilities::Trilinos::comm_self())));
98  }
99 
100 
101 
102  Vector::Vector (const Epetra_Map &parallel_partitioning)
103  {
104  reinit (parallel_partitioning);
105  }
106 
107 
108 
109  Vector::Vector (const IndexSet &parallel_partitioning,
110  const MPI_Comm &communicator)
111  {
112  reinit (parallel_partitioning, communicator);
113  }
114 
115 
116 
118  :
119  VectorBase()
120  {
121  last_action = Zero;
122  vector.reset (new Epetra_FEVector(*v.vector));
123  has_ghosts = v.has_ghosts;
124  }
125 
126 
127 
128 #ifdef DEAL_II_WITH_CXX11
130  {
131  // initialize a minimal, valid object and swap
132  last_action = Zero;
133  vector.reset(new Epetra_FEVector(Epetra_Map(0,0,0,Utilities::Trilinos::comm_self())));
134 
135  swap(v);
136  }
137 #endif
138 
139 
140 
141  Vector::Vector (const Epetra_Map &input_map,
142  const VectorBase &v)
143  :
144  VectorBase()
145  {
146  AssertThrow (n_global_elements(input_map) == n_global_elements(v.vector->Map()),
147  ExcDimensionMismatch (n_global_elements(input_map),
148  n_global_elements(v.vector->Map())));
149 
150  last_action = Zero;
151 
152  if (input_map.SameAs(v.vector->Map()) == true)
153  vector.reset (new Epetra_FEVector(*v.vector));
154  else
155  {
156  vector.reset (new Epetra_FEVector(input_map));
157  reinit (v, false, true);
158  }
159  }
160 
161 
162 
163  Vector::Vector (const IndexSet &parallel_partitioner,
164  const VectorBase &v,
165  const MPI_Comm &communicator)
166  :
167  VectorBase()
168  {
169  AssertThrow (parallel_partitioner.size() ==
170  static_cast<size_type>(n_global_elements(v.vector->Map())),
171  ExcDimensionMismatch (parallel_partitioner.size(),
172  n_global_elements(v.vector->Map())));
173 
174  last_action = Zero;
175 
176  vector.reset (new Epetra_FEVector
177  (parallel_partitioner.make_trilinos_map(communicator,
178  true)));
179  reinit (v, false, true);
180  }
181 
182  Vector::Vector (const IndexSet &local,
183  const IndexSet &ghost,
184  const MPI_Comm &communicator)
185  :
186  VectorBase()
187  {
188  IndexSet parallel_partitioning = local;
189  parallel_partitioning.add_indices(ghost);
190  reinit(parallel_partitioning, communicator);
191  }
192 
193 
194 
196  {}
197 
198 
199 
200  void
201  Vector::reinit (const Epetra_Map &input_map,
202  const bool omit_zeroing_entries)
203  {
204  nonlocal_vector.reset();
205 
206  if (vector->Map().SameAs(input_map)==false)
207  vector.reset (new Epetra_FEVector(input_map));
208  else if (omit_zeroing_entries == false)
209  {
210  const int ierr = vector->PutScalar(0.);
211  (void)ierr;
212  Assert (ierr == 0, ExcTrilinosError(ierr));
213  }
214 
215  has_ghosts = vector->Map().UniqueGIDs()==false;
216  last_action = Zero;
217  }
218 
219 
220 
221  void
222  Vector::reinit (const IndexSet &parallel_partitioner,
223  const MPI_Comm &communicator,
224  const bool omit_zeroing_entries)
225  {
226  nonlocal_vector.reset();
227 
228  Epetra_Map map = parallel_partitioner.make_trilinos_map (communicator,
229  true);
230  reinit (map, omit_zeroing_entries);
231  }
232 
233 
234 
235  void
237  const bool omit_zeroing_entries,
238  const bool allow_different_maps)
239  {
240  nonlocal_vector.reset();
241 
242  // In case we do not allow to have different maps, this call means that
243  // we have to reset the vector. So clear the vector, initialize our map
244  // with the map in v, and generate the vector.
245  if (allow_different_maps == false)
246  {
247  if (vector->Map().SameAs(v.vector->Map()) == false)
248  {
249  vector.reset (new Epetra_FEVector(v.vector->Map()));
251  last_action = Zero;
252  }
253  else if (omit_zeroing_entries == false)
254  {
255  // old and new vectors
256  // have exactly the
257  // same map, i.e. size
258  // and parallel
259  // distribution
260  int ierr;
261  ierr = vector->GlobalAssemble (last_action);
262  (void)ierr;
263  Assert (ierr == 0, ExcTrilinosError(ierr));
264 
265  ierr = vector->PutScalar(0.0);
266  Assert (ierr == 0, ExcTrilinosError(ierr));
267 
268  last_action = Zero;
269  }
270  }
271 
272  // Otherwise, we have to check that the two vectors are already of the
273  // same size, create an object for the data exchange and then insert all
274  // the data. The first assertion is only a check whether the user knows
275  // what she is doing.
276  else
277  {
278  Assert (omit_zeroing_entries == false,
279  ExcMessage ("It is not possible to exchange data with the "
280  "option 'omit_zeroing_entries' set, which would not write "
281  "elements."));
282 
283  AssertThrow (size() == v.size(),
284  ExcDimensionMismatch (size(), v.size()));
285 
286  Epetra_Import data_exchange (vector->Map(), v.vector->Map());
287 
288  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
289  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
290 
291  last_action = Insert;
292  }
293 
294  }
295 
296 
297 
298  void
300  const bool import_data)
301  {
302  nonlocal_vector.reset();
303 
304  // In case we do not allow to have different maps, this call means that
305  // we have to reset the vector. So clear the vector, initialize our map
306  // with the map in v, and generate the vector.
307  if (v.n_blocks() == 0)
308  return;
309 
310  // create a vector that holds all the elements contained in the block
311  // vector. need to manually create an Epetra_Map.
312  size_type n_elements = 0, added_elements = 0, block_offset = 0;
313  for (size_type block=0; block<v.n_blocks(); ++block)
314  n_elements += v.block(block).local_size();
315  std::vector<TrilinosWrappers::types::int_type> global_ids (n_elements, -1);
316  for (size_type block=0; block<v.n_blocks(); ++block)
317  {
318  TrilinosWrappers::types::int_type *glob_elements =
319  my_global_elements(v.block(block).vector_partitioner());
320  for (size_type i=0; i<v.block(block).local_size(); ++i)
321  global_ids[added_elements++] = glob_elements[i] + block_offset;
322  block_offset += v.block(block).size();
323  }
324 
325  Assert (n_elements == added_elements, ExcInternalError());
326  Epetra_Map new_map (v.size(), n_elements, &global_ids[0], 0,
327  v.block(0).vector_partitioner().Comm());
328 
329  std_cxx11::shared_ptr<Epetra_FEVector> actual_vec;
330  if ( import_data == true )
331  actual_vec.reset (new Epetra_FEVector (new_map));
332  else
333  {
334  vector.reset (new Epetra_FEVector (new_map));
335  actual_vec = vector;
336  }
337 
338  TrilinosScalar *entries = (*actual_vec)[0];
339  block_offset = 0;
340  for (size_type block=0; block<v.n_blocks(); ++block)
341  {
342  v.block(block).trilinos_vector().ExtractCopy (entries, 0);
343  entries += v.block(block).local_size();
344  }
345 
346  if (import_data == true)
347  {
348  AssertThrow (static_cast<size_type>(global_length(*actual_vec))
349  == v.size(),
350  ExcDimensionMismatch (global_length(*actual_vec),
351  v.size()));
352 
353  Epetra_Import data_exchange (vector->Map(), actual_vec->Map());
354 
355  const int ierr = vector->Import(*actual_vec, data_exchange, Insert);
356  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
357 
358  last_action = Insert;
359  }
360 
361  }
362 
363 
364  void Vector::reinit(const IndexSet &locally_owned_entries,
365  const IndexSet &ghost_entries,
366  const MPI_Comm &communicator,
367  const bool vector_writable)
368  {
369  nonlocal_vector.reset();
370  if (vector_writable == false)
371  {
372  IndexSet parallel_partitioning = locally_owned_entries;
373  parallel_partitioning.add_indices(ghost_entries);
374  reinit(parallel_partitioning, communicator);
375  }
376  else
377  {
378  Epetra_Map map = locally_owned_entries.make_trilinos_map (communicator,
379  true);
380  Assert (map.IsOneToOne(),
381  ExcMessage("A writable vector must not have ghost entries in "
382  "its parallel partitioning"));
383  reinit (map);
384 
385  IndexSet nonlocal_entries(ghost_entries);
386  nonlocal_entries.subtract_set(locally_owned_entries);
387  if (Utilities::MPI::n_mpi_processes(communicator) > 1)
388  {
389  Epetra_Map nonlocal_map =
390  nonlocal_entries.make_trilinos_map(communicator, true);
391  nonlocal_vector.reset(new Epetra_MultiVector(nonlocal_map, 1));
392  }
393  }
394  }
395 
396 
397  Vector &
399  {
400  // distinguish three cases. First case: both vectors have the same
401  // layout (just need to copy the local data, not reset the memory and
402  // the underlying Epetra_Map). The third case means that we have to
403  // rebuild the calling vector.
404  if (vector->Map().SameAs(v.vector->Map()))
405  {
406  *vector = *v.vector;
407  if (v.nonlocal_vector.get() != 0)
408  nonlocal_vector.reset(new Epetra_MultiVector(v.nonlocal_vector->Map(), 1));
409  last_action = Zero;
410  }
411  // Second case: vectors have the same global
412  // size, but different parallel layouts (and
413  // one of them a one-to-one mapping). Then we
414  // can call the import/export functionality.
415  else if (size() == v.size() &&
416  (v.vector->Map().UniqueGIDs() || vector->Map().UniqueGIDs()))
417  {
418  reinit (v, false, true);
419  }
420  // Third case: Vectors do not have the same
421  // size.
422  else
423  {
424  vector.reset (new Epetra_FEVector(*v.vector));
425  last_action = Zero;
426  has_ghosts = v.has_ghosts;
427  }
428 
429  if (v.nonlocal_vector.get() != 0)
430  nonlocal_vector.reset(new Epetra_MultiVector(v.nonlocal_vector->Map(), 1));
431 
432  return *this;
433  }
434 
435 
436 
437 #ifdef DEAL_II_WITH_CXX11
439  {
440  swap(v);
441  return *this;
442  }
443 #endif
444 
445 
446 
447  Vector &
449  {
450  nonlocal_vector.reset();
451 
452  Assert (size() == v.size(), ExcDimensionMismatch(size(), v.size()));
453 
454  Epetra_Import data_exchange (vector->Map(), v.vector->Map());
455  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
456 
457  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
458 
459  last_action = Insert;
460 
461  return *this;
462  }
463 
464 
465 
466  void
468  const Vector &v)
469  {
470  Assert (m.trilinos_matrix().Filled() == true,
471  ExcMessage ("Matrix is not compressed. "
472  "Cannot find exchange information!"));
473  Assert (v.vector->Map().UniqueGIDs() == true,
474  ExcMessage ("The input vector has overlapping data, "
475  "which is not allowed."));
476 
477  if (vector->Map().SameAs(m.trilinos_matrix().ColMap()) == false)
478  {
479  vector.reset (new Epetra_FEVector(
480  m.trilinos_matrix().ColMap()
481  ));
482  }
483 
484  Epetra_Import data_exchange (vector->Map(), v.vector->Map());
485  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
486 
487  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
488 
489  last_action = Insert;
490  }
491 
492  } /* end of namespace MPI */
493 
494 
495 
496 
498  {
499  last_action = Zero;
500  Epetra_LocalMap map (0, 0, Utilities::Trilinos::comm_self());
501  vector.reset (new Epetra_FEVector(map));
502  }
503 
504 
505 
507  {
508  last_action = Zero;
509  Epetra_LocalMap map ((TrilinosWrappers::types::int_type)n, 0, Utilities::Trilinos::comm_self());
510  vector.reset (new Epetra_FEVector (map));
511  }
512 
513 
514 
515  Vector::Vector (const Epetra_Map &input_map)
516  {
517  last_action = Zero;
518  Epetra_LocalMap map (n_global_elements(input_map),
519  input_map.IndexBase(),
520  input_map.Comm());
521  vector.reset (new Epetra_FEVector(map));
522  }
523 
524 
525 
526  Vector::Vector (const IndexSet &partitioning,
527  const MPI_Comm &communicator)
528  {
529  last_action = Zero;
530  Epetra_LocalMap map (static_cast<TrilinosWrappers::types::int_type>(partitioning.size()),
531  0,
532 #ifdef DEAL_II_WITH_MPI
533  Epetra_MpiComm(communicator));
534 #else
535  Epetra_SerialComm());
536  (void)communicator;
537 #endif
538  vector.reset (new Epetra_FEVector(map));
539  }
540 
541 
542 
544  {
545  last_action = Zero;
546  Epetra_LocalMap map (n_global_elements(v.vector->Map()),
547  v.vector->Map().IndexBase(),
548  v.vector->Map().Comm());
549  vector.reset (new Epetra_FEVector(map));
550 
551  if (vector->Map().SameAs(v.vector->Map()) == true)
552  {
553  const int ierr = vector->Update(1.0, *v.vector, 0.0);
554  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
555  }
556  else
557  reinit (v, false, true);
558 
559  }
560 
561 
562 
563  void
565  const bool omit_zeroing_entries)
566  {
567  if (size() != n)
568  {
569  Epetra_LocalMap map ((TrilinosWrappers::types::int_type)n, 0,
571  vector.reset (new Epetra_FEVector (map));
572  }
573  else if (omit_zeroing_entries == false)
574  {
575  int ierr;
576  ierr = vector->GlobalAssemble(last_action);
577  (void)ierr;
578  Assert (ierr == 0, ExcTrilinosError(ierr));
579 
580  ierr = vector->PutScalar(0.0);
581  Assert (ierr == 0, ExcTrilinosError(ierr));
582  }
583 
584  last_action = Zero;
585  }
586 
587 
588 
589  void
590  Vector::reinit (const Epetra_Map &input_map,
591  const bool omit_zeroing_entries)
592  {
593  if (n_global_elements(vector->Map()) != n_global_elements(input_map))
594  {
595  Epetra_LocalMap map (n_global_elements(input_map),
596  input_map.IndexBase(),
597  input_map.Comm());
598  vector.reset (new Epetra_FEVector (map));
599  }
600  else if (omit_zeroing_entries == false)
601  {
602  int ierr;
603  ierr = vector->GlobalAssemble(last_action);
604  (void)ierr;
605  Assert (ierr == 0, ExcTrilinosError(ierr));
606 
607  ierr = vector->PutScalar(0.0);
608  Assert (ierr == 0, ExcTrilinosError(ierr));
609  }
610 
611  last_action = Zero;
612  }
613 
614 
615 
616  void
617  Vector::reinit (const IndexSet &partitioning,
618  const MPI_Comm &communicator,
619  const bool omit_zeroing_entries)
620  {
621  if (n_global_elements(vector->Map()) !=
622  static_cast<TrilinosWrappers::types::int_type>(partitioning.size()))
623  {
624  Epetra_LocalMap map (static_cast<TrilinosWrappers::types::int_type>(partitioning.size()),
625  0,
626 #ifdef DEAL_II_WITH_MPI
627  Epetra_MpiComm(communicator));
628 #else
629  Epetra_SerialComm());
630  (void)communicator;
631 #endif
632  vector.reset (new Epetra_FEVector(map));
633  }
634  else if (omit_zeroing_entries == false)
635  {
636  int ierr;
637  ierr = vector->GlobalAssemble(last_action);
638  (void)ierr;
639  Assert (ierr == 0, ExcTrilinosError(ierr));
640 
641  ierr = vector->PutScalar(0.0);
642  Assert (ierr == 0, ExcTrilinosError(ierr));
643  }
644 
645  last_action = Zero;
646  }
647 
648 
649 
650  void
652  const bool omit_zeroing_entries,
653  const bool allow_different_maps)
654  {
655  // In case we do not allow to
656  // have different maps, this
657  // call means that we have to
658  // reset the vector. So clear
659  // the vector, initialize our
660  // map with the map in v, and
661  // generate the vector.
662  (void)omit_zeroing_entries;
663  if (allow_different_maps == false)
664  {
665  if (local_range() != v.local_range())
666  {
667  Epetra_LocalMap map (global_length(*(v.vector)),
668  v.vector->Map().IndexBase(),
669  v.vector->Comm());
670  vector.reset (new Epetra_FEVector(map));
671  }
672  else
673  {
674  int ierr;
675  Assert (vector->Map().SameAs(v.vector->Map()) == true,
676  ExcMessage ("The Epetra maps in the assignment operator ="
677  " do not match, even though the local_range "
678  " seems to be the same. Check vector setup!"));
679 
680  ierr = vector->GlobalAssemble(last_action);
681  (void)ierr;
682  Assert (ierr == 0, ExcTrilinosError(ierr));
683 
684  ierr = vector->PutScalar(0.0);
685  Assert (ierr == 0, ExcTrilinosError(ierr));
686  }
687  last_action = Zero;
688  }
689 
690  // Otherwise, we have to check
691  // that the two vectors are
692  // already of the same size,
693  // create an object for the data
694  // exchange and then insert all
695  // the data.
696  else
697  {
698  Assert (omit_zeroing_entries == false,
699  ExcMessage ("It is not possible to exchange data with the "
700  "option 'omit_zeroing_entries' set, which would not write "
701  "elements."));
702 
703  AssertThrow (size() == v.size(),
704  ExcDimensionMismatch (size(), v.size()));
705 
706  Epetra_Import data_exchange (vector->Map(), v.vector->Map());
707 
708  const int ierr = vector->Import(*v.vector, data_exchange, Insert);
709  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
710 
711  last_action = Insert;
712  }
713 
714  }
715 
716 
717 
718  Vector &
720  {
721  if (size() != v.size())
722  {
723  Epetra_LocalMap map (n_global_elements(v.vector->Map()),
724  v.vector->Map().IndexBase(),
725  v.vector->Comm());
726  vector.reset (new Epetra_FEVector(map));
727  }
728 
729  reinit (v, false, true);
730  return *this;
731  }
732 
733 
734 
735  Vector &
737  {
738  if (size() != v.size())
739  {
740  Epetra_LocalMap map (n_global_elements(v.vector->Map()),
741  v.vector->Map().IndexBase(),
742  v.vector->Comm());
743  vector.reset (new Epetra_FEVector(map));
744  }
745 
746  const int ierr = vector->Update(1.0, *v.vector, 0.0);
747  Assert (ierr == 0, ExcTrilinosError(ierr));
748  (void)ierr;
749 
750  return *this;
751  }
752 
753 }
754 
755 DEAL_II_NAMESPACE_CLOSE
756 
757 #endif // DEAL_II_WITH_TRILINOS
Vector & operator=(const TrilinosScalar s)
::types::global_dof_index size_type
::ExceptionBase & ExcMessage(std::string arg1)
std_cxx11::shared_ptr< Epetra_MultiVector > nonlocal_vector
std::pair< size_type, size_type > local_range() const
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1291
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
const Epetra_Comm & comm_self()
Definition: utilities.cc:733
void reinit(const VectorBase &v, const bool omit_zeroing_entries=false, const bool allow_different_maps=false)
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:484
size_type size() const
Definition: index_set.h:1247
std::size_t size() const
std_cxx11::shared_ptr< Epetra_FEVector > vector
void subtract_set(const IndexSet &other)
Definition: index_set.cc:269
#define Assert(cond, exc)
Definition: exceptions.h:294
std::size_t size() const
void swap(Vector &u, Vector &v)
const Epetra_CrsMatrix & trilinos_matrix() const
void import_nonlocal_data_for_fe(const ::TrilinosWrappers::SparseMatrix &matrix, const Vector &vector)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:99
unsigned int n_blocks() const
::types::global_dof_index size_type
BlockType & block(const unsigned int i)