deal.II version GIT relicensing-6839-g338455934c 2026-10-02 12:10:01+00:00
\(\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\}}\)
Loading...
Searching...
No Matches
trilinos_vector.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2008 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
14
15#ifdef DEAL_II_WITH_TRILINOS
16
17# include <deal.II/base/mpi.h>
19
24
25# include <boost/io/ios_state.hpp>
26
28# include <Epetra_Export.h>
29# include <Epetra_Import.h>
30# include <Epetra_Vector.h>
32
33# include <cmath>
34# include <memory>
35
36
37
38#endif // DEAL_II_WITH_TRILINOS
39
41
42#ifdef DEAL_II_WITH_TRILINOS
43
44namespace TrilinosWrappers
45{
46# ifndef DOXYGEN
47 namespace internal
48 {
49 VectorReference::operator TrilinosScalar() const
50 {
51 AssertIndexRange(index, vector.size());
52
53 // Trilinos allows for vectors to be referenced by the [] or ()
54 // operators but only () checks index bounds. We check these bounds by
55 // ourselves, so we can use []. Note that we can only get local values.
56
57 const TrilinosWrappers::types::int_type local_index =
58 vector.vector->Map().LID(
59 static_cast<TrilinosWrappers::types::int_type>(index));
60# ifndef DEAL_II_WITH_64BIT_INDICES
61 Assert(local_index >= 0,
63 index,
64 vector.vector->Map().NumMyElements(),
65 vector.vector->Map().MinMyGID(),
66 vector.vector->Map().MaxMyGID()));
67# else
68 Assert(local_index >= 0,
70 index,
71 vector.vector->Map().NumMyElements(),
72 vector.vector->Map().MinMyGID64(),
73 vector.vector->Map().MaxMyGID64()));
74# endif
75
76
77 return (*(vector.vector))[0][local_index];
78 }
79 } // namespace internal
80# endif
81
82 namespace MPI
83 {
85 : last_action(Zero)
86 , compressed(true)
87 , has_ghosts(false)
88 , vector(new Epetra_FEVector(
89 Epetra_Map(0, 0, 0, Utilities::Trilinos::comm_self())))
90 {}
91
92
93
94 Vector::Vector(const IndexSet &parallel_partitioning,
95 const MPI_Comm communicator)
96 : Vector()
97 {
98 reinit(parallel_partitioning, communicator);
99 }
100
101
102
104 : Vector()
105 {
107 vector = std::make_unique<Epetra_FEVector>(*v.vector);
109 }
110
111
112
113 Vector::Vector(Vector &&v) // NOLINT
114 : Vector()
115 {
116 // initialize a minimal, valid object and swap
117 static_cast<EnableObserverPointer &>(*this) =
118 static_cast<EnableObserverPointer &&>(v);
119 swap(v);
120 }
121
122
123
124 Vector::Vector(const IndexSet &parallel_partitioner,
125 const Vector &v,
126 const MPI_Comm communicator)
127 : Vector()
128 {
130 static_cast<size_type>(
134 v.vector->Map())));
135
136 vector = std::make_unique<Epetra_FEVector>(
137 parallel_partitioner.make_trilinos_map(communicator, true));
138
140
141 Epetra_Import data_exchange(vector->Map(), v.vector->Map());
142
143 const int ierr = vector->Import(*v.vector, data_exchange, Insert);
145
147 }
148
149
150
152 const IndexSet &ghost,
153 const MPI_Comm communicator)
154 : Vector()
155 {
156 reinit(local, ghost, communicator, false);
157 }
158
159
160
161 void
163 {
164 // When we clear the vector, reset the pointer and generate an empty
165 // vector.
166 Epetra_Map map(0, 0, Epetra_MpiComm(MPI_COMM_SELF));
167
168 has_ghosts = false;
169 vector = std::make_unique<Epetra_FEVector>(map);
171 }
172
173
174
175 void
176 Vector::reinit(const IndexSet &parallel_partitioner,
177 const MPI_Comm communicator,
178 const bool /*omit_zeroing_entries*/)
179 {
180 nonlocal_vector.reset();
181
182 const bool overlapping =
183 !parallel_partitioner.is_ascending_and_one_to_one(communicator);
184
185 Epetra_Map map =
186 parallel_partitioner.make_trilinos_map(communicator, overlapping);
187
188 vector = std::make_unique<Epetra_FEVector>(map);
189
190 has_ghosts = vector->Map().UniqueGIDs() == false;
191
192 // If the IndexSets are overlapping, we don't really know
193 // which process owns what. So we decide that no process
194 // owns anything in that case. In particular asking for
195 // the locally owned elements is not allowed.
196 if (has_ghosts)
197 {
200 }
201 else
203
204 if constexpr (running_in_debug_mode())
205 {
208
210 }
211
213 }
214
215
216
217 void
218 Vector::reinit(const Vector &v, const bool omit_zeroing_entries)
219 {
220 nonlocal_vector.reset();
221
222 // check equality for MPI communicators: We can only choose the fast
223 // version in case the underlying Epetra_MpiComm object is the same,
224 // otherwise we might access an MPI_Comm object that has been
225 // deleted
226 const Epetra_MpiComm *my_comm =
227 dynamic_cast<const Epetra_MpiComm *>(&vector->Comm());
228 const Epetra_MpiComm *v_comm =
229 dynamic_cast<const Epetra_MpiComm *>(&v.vector->Comm());
230 const bool same_communicators = my_comm != nullptr && v_comm != nullptr &&
231 my_comm->DataPtr() == v_comm->DataPtr();
232 if (!same_communicators || vector->Map().SameAs(v.vector->Map()) == false)
233 {
234 vector = std::make_unique<Epetra_FEVector>(v.vector->Map());
238 }
239 else if (omit_zeroing_entries == false)
240 {
241 // old and new vectors have exactly the same map, i.e. size and
242 // parallel distribution
243 int ierr = vector->GlobalAssemble(last_action);
245
246 ierr = vector->PutScalar(0.0);
248
250 }
251
252 if constexpr (running_in_debug_mode())
253 {
254 const Epetra_MpiComm *comm_ptr =
255 dynamic_cast<const Epetra_MpiComm *>(&(v.vector->Comm()));
256 Assert(comm_ptr != nullptr, ExcInternalError());
260 }
261 }
262
263
264
265 void
266 Vector::reinit(const MPI::BlockVector &v, const bool import_data)
267 {
268 nonlocal_vector.reset();
271
272 // In case we do not allow to have different maps, this call means that
273 // we have to reset the vector. So clear the vector, initialize our map
274 // with the map in v, and generate the vector.
275 if (v.n_blocks() == 0)
276 return;
277
278 // create a vector that holds all the elements contained in the block
279 // vector. need to manually create an Epetra_Map.
280 size_type n_elements = 0, added_elements = 0, block_offset = 0;
281 for (size_type block = 0; block < v.n_blocks(); ++block)
282 n_elements += v.block(block).vector->Map().NumMyElements();
283 std::vector<TrilinosWrappers::types::int_type> global_ids(n_elements, -1);
284 for (size_type block = 0; block < v.n_blocks(); ++block)
285 {
288 v.block(block).trilinos_partitioner());
289 size_type vector_size = v.block(block).vector->Map().NumMyElements();
290 for (size_type i = 0; i < vector_size; ++i)
292 owned_elements.add_indices(v.block(block).owned_elements,
294 block_offset += v.block(block).size();
295 }
296
297 Assert(n_elements == added_elements, ExcInternalError());
298 Epetra_Map new_map(v.size(),
299 n_elements,
300 global_ids.data(),
301 0,
302 v.block(0).trilinos_partitioner().Comm());
303
304 auto actual_vec = std::make_unique<Epetra_FEVector>(new_map);
305
306 TrilinosScalar *entries = (*actual_vec)[0];
307 for (size_type block = 0; block < v.n_blocks(); ++block)
308 {
309 v.block(block).trilinos_vector().ExtractCopy(entries, 0);
310 entries += v.block(block).vector->Map().NumMyElements();
311 }
312
313 if (import_data == true)
314 {
316 *actual_vec)) == v.size(),
318 *actual_vec),
319 v.size()));
320
321 Epetra_Import data_exchange(vector->Map(), actual_vec->Map());
322
323 const int ierr = vector->Import(*actual_vec, data_exchange, Insert);
325
327 }
328 else
329 vector = std::move(actual_vec);
330 if constexpr (running_in_debug_mode())
331 {
332 const Epetra_MpiComm *comm_ptr =
333 dynamic_cast<const Epetra_MpiComm *>(&(vector->Comm()));
334 Assert(comm_ptr != nullptr, ExcInternalError());
337
339 }
340 }
341
342
343
344 void
345 Vector::reinit(const IndexSet &locally_owned_entries,
346 const IndexSet &ghost_entries,
347 const MPI_Comm communicator,
348 const bool vector_writable)
349 {
350 nonlocal_vector.reset();
352 if (vector_writable == false)
353 {
356 Epetra_Map map =
357 parallel_partitioner.make_trilinos_map(communicator, true);
358 vector = std::make_unique<Epetra_FEVector>(map);
359 }
360 else
361 {
362 Epetra_Map map =
363 locally_owned_entries.make_trilinos_map(communicator, true);
364 Assert(map.IsOneToOne(),
365 ExcMessage("A writable vector must not have ghost entries in "
366 "its parallel partitioning"));
367
368 if (vector->Map().SameAs(map) == false)
369 vector = std::make_unique<Epetra_FEVector>(map);
370 else
371 {
372 const int ierr = vector->PutScalar(0.);
374 }
375
378 if (Utilities::MPI::n_mpi_processes(communicator) > 1)
379 {
380 Epetra_Map nonlocal_map =
381 nonlocal_entries.make_trilinos_map(communicator, true);
383 std::make_unique<Epetra_MultiVector>(nonlocal_map, 1);
384 }
385 }
386
387 has_ghosts = vector->Map().UniqueGIDs() == false;
388
390
391 if constexpr (running_in_debug_mode())
392 {
395
397 }
398 }
399
400
401
402 void
404 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
405 const bool make_ghosted,
406 const bool vector_writable)
407 {
408 if (make_ghosted)
409 {
410 Assert(partitioner->ghost_indices_initialized(),
411 ExcMessage("You asked to create a ghosted vector, but the "
412 "partitioner does not provide ghost indices."));
413
414 this->reinit(partitioner->locally_owned_range(),
415 partitioner->ghost_indices(),
416 partitioner->get_mpi_communicator(),
418 }
419 else
420 {
421 this->reinit(partitioner->locally_owned_range(),
422 partitioner->get_mpi_communicator());
423 }
424 }
425
426
427
428 Vector &
430 {
431 Assert(vector.get() != nullptr,
432 ExcMessage("Vector is not constructed properly."));
433
434 // check equality for MPI communicators to avoid accessing a possibly
435 // invalid MPI_Comm object
436 const Epetra_MpiComm *my_comm =
437 dynamic_cast<const Epetra_MpiComm *>(&vector->Comm());
438 const Epetra_MpiComm *v_comm =
439 dynamic_cast<const Epetra_MpiComm *>(&v.vector->Comm());
440 const bool same_communicators = my_comm != nullptr && v_comm != nullptr &&
441 my_comm->DataPtr() == v_comm->DataPtr();
442 // Need to ask MPI whether the communicators are the same. We would like
443 // to use the following checks but currently we cannot make sure the
444 // memory of my_comm is not stale from some MPI_Comm_free
445 // somewhere. This can happen when a vector lives in GrowingVectorMemory
446 // data structures. Thus, the following code is commented out.
447 //
448 // if (my_comm != nullptr &&
449 // v_comm != nullptr &&
450 // my_comm->DataPtr() != v_comm->DataPtr())
451 // {
452 // int communicators_same = 0;
453 // const int ierr = MPI_Comm_compare (my_comm->GetMpiComm(),
454 // v_comm->GetMpiComm(),
455 // &communicators_same);
456 // AssertThrowMPI(ierr);
457 // if (!(communicators_same == MPI_IDENT ||
458 // communicators_same == MPI_CONGRUENT))
459 // same_communicators = false;
460 // else
461 // same_communicators = true;
462 // }
463
464 // distinguish three cases. First case: both vectors have the same
465 // layout (just need to copy the local data, not reset the memory and
466 // the underlying Epetra_Map). The third case means that we have to
467 // rebuild the calling vector.
468 if (same_communicators && v.vector->Map().SameAs(vector->Map()))
469 {
470 *vector = *v.vector;
471 if (v.nonlocal_vector.get() != nullptr)
473 std::make_unique<Epetra_MultiVector>(v.nonlocal_vector->Map(), 1);
475 }
476 // Second case: vectors have the same global
477 // size, but different parallel layouts (and
478 // one of them a one-to-one mapping). Then we
479 // can call the import/export functionality.
480 else if (size() == v.size() &&
481 (v.vector->Map().UniqueGIDs() || vector->Map().UniqueGIDs()))
482 {
483 Epetra_Import data_exchange(vector->Map(), v.vector->Map());
484
485 const int ierr = vector->Import(*v.vector, data_exchange, Insert);
487
489 }
490 // Third case: Vectors do not have the same
491 // size.
492 else
493 {
494 vector = std::make_unique<Epetra_FEVector>(*v.vector);
498 }
499
500 if (v.nonlocal_vector.get() != nullptr)
502 std::make_unique<Epetra_MultiVector>(v.nonlocal_vector->Map(), 1);
503
504 return *this;
505 }
506
507
508
509 Vector &
511 {
512 static_cast<EnableObserverPointer &>(*this) =
513 static_cast<EnableObserverPointer &&>(v);
514 swap(v);
515 return *this;
516 }
517
518
519
520 template <typename number>
521 Vector &
522 Vector::operator=(const ::Vector<number> &v)
523 {
524 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
525
526 // this is probably not very efficient but works. in particular, we could
527 // do better if we know that number==TrilinosScalar because then we could
528 // elide the copying of elements
529 //
530 // let's hope this isn't a particularly frequent operation
531 std::pair<size_type, size_type> local_range = this->local_range();
532 for (size_type i = local_range.first; i < local_range.second; ++i)
533 (*vector)[0][i - local_range.first] = v(i);
534
535 return *this;
536 }
537
538
539
540 void
542 const Vector &v)
543 {
544 Assert(m.trilinos_matrix().Filled() == true,
545 ExcMessage("Matrix is not compressed. "
546 "Cannot find exchange information!"));
547 Assert(v.vector->Map().UniqueGIDs() == true,
548 ExcMessage("The input vector has overlapping data, "
549 "which is not allowed."));
550
551 if (vector->Map().SameAs(m.trilinos_matrix().ColMap()) == false)
552 vector =
553 std::make_unique<Epetra_FEVector>(m.trilinos_matrix().ColMap());
554
555 Epetra_Import data_exchange(vector->Map(), v.vector->Map());
556 const int ierr = vector->Import(*v.vector, data_exchange, Insert);
557
559
561 }
562
563
564 void
566 const VectorOperation::values operation)
567 {
568 Assert(
569 this->size() == rwv.size(),
571 "Both vectors need to have the same size for import_elements() to work!"));
572 // TODO: a generic import_elements() function should handle any kind of
573 // data layout in ReadWriteVector, but this function is of limited use as
574 // this class will (hopefully) be retired eventually.
577
579 {
580 for (const auto idx : this->locally_owned_elements())
581 (*this)[idx] = rwv[idx];
582 }
584 {
585 for (const auto idx : this->locally_owned_elements())
586 (*this)[idx] += rwv[idx];
587 }
588 else
590
591 this->compress(operation);
592 }
593
594
595 void
597 {
598 Assert(has_ghost_elements() == false,
600 "Calling compress() is only useful if a vector "
601 "has been written into, but this is a vector with ghost "
602 "elements and consequently is read-only. It does "
603 "not make sense to call compress() for such "
604 "vectors."));
605
606 // Select which mode to send to Trilinos. Note that we use last_action if
607 // available and ignore what the user tells us to detect wrongly mixed
608 // operations. Typically given_last_action is only used on machines that
609 // do not execute an operation (because they have no own cells for
610 // example).
611 Epetra_CombineMode mode = last_action;
612 if (last_action == Zero)
613 {
615 mode = Add;
617 mode = Insert;
618 else
619 Assert(
620 false,
622 "compress() can only be called with VectorOperation add, insert, or unknown"));
623 }
624 else
625 {
626 Assert(
627 ((last_action == Add) &&
629 ((last_action == Insert) &&
632 "The last operation on the Vector and the given last action in the compress() call do not agree!"));
633 }
634
635
636 if constexpr (running_in_debug_mode())
637 {
638 // check that every process has decided to use the same mode. This
639 // will otherwise result in undefined behavior in the call to
640 // GlobalAssemble().
641 const double double_mode = mode;
642 const Epetra_MpiComm *comm_ptr = dynamic_cast<const Epetra_MpiComm *>(
643 &(trilinos_partitioner().Comm()));
644 Assert(comm_ptr != nullptr, ExcInternalError());
645
648 Assert(result.max == result.min,
650 "Not all processors agree whether the last operation on "
651 "this vector was an addition or a set operation. This will "
652 "prevent the compress() operation from succeeding."));
653 }
654
655 // Now pass over the information about what we did last to the vector.
656 if (nonlocal_vector.get() == nullptr || mode != Add)
657 {
658 const auto ierr = vector->GlobalAssemble(mode);
660 }
661 else
662 {
663 Epetra_Export exporter(nonlocal_vector->Map(), vector->Map());
664
665 int ierr = vector->Export(*nonlocal_vector, exporter, mode);
667
668 ierr = nonlocal_vector->PutScalar(0.);
670 }
672
673 compressed = true;
674 }
675
676
677
679 Vector::operator()(const size_type index) const
680 {
681 // Extract local indices in the vector.
683 static_cast<TrilinosWrappers::types::int_type>(index));
684 TrilinosScalar value = 0.;
685
686 // If the element is not present on the current processor, we can't
687 // continue. This is the main difference to the el() function.
688 if (trilinos_i == -1)
689 {
690# ifndef DEAL_II_WITH_64BIT_INDICES
691 Assert(false,
693 vector->Map().NumMyElements(),
694 vector->Map().MinMyGID(),
695 vector->Map().MaxMyGID()));
696# else
697 Assert(false,
699 vector->Map().NumMyElements(),
700 vector->Map().MinMyGID64(),
701 vector->Map().MaxMyGID64()));
702# endif
703 }
704 else
705 value = (*vector)[0][trilinos_i];
706
707 return value;
708 }
709
710
711
712 void
713 Vector::add(const Vector &v, const bool allow_different_maps)
714 {
715 if (allow_different_maps == false)
716 *this += v;
717 else
718 {
720 AssertThrow(size() == v.size(),
722
723 Epetra_Import data_exchange(vector->Map(), v.vector->Map());
724 const int ierr =
728 }
729 }
730
731
732
733 bool
735 {
736 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
737 if (vector->Map().NumMyElements() != v.vector->Map().NumMyElements())
738 return false;
739
740 size_type vector_size = vector->Map().NumMyElements();
741 for (size_type i = 0; i < vector_size; ++i)
742 if ((*(v.vector))[0][i] != (*vector)[0][i])
743 return false;
744
745 return true;
746 }
747
748
749
750 bool
752 {
753 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
754
755 return (!(*this == v));
756 }
757
758
759
760 bool
762 {
763 const TrilinosScalar *start_ptr = (*vector)[0];
764
765 const bool local_all_zero =
766 std::all_of(start_ptr,
768 numbers::value_is_zero<TrilinosScalar>);
769
772 }
773
774
775
776 bool
778 {
779 const bool has_negative = std::any_of((*vector)[0],
780 (*vector)[0] + locally_owned_size(),
781 [](const TrilinosScalar &v) {
782 return v < TrilinosScalar();
783 });
784
786 }
787
788
789
790 void
791 Vector::print(std::ostream &out,
792 const unsigned int precision,
793 const bool scientific,
794 const bool across) const
795 {
796 AssertThrow(out.fail() == false, ExcIO());
797 boost::io::ios_flags_saver restore_flags(out);
798
799
800 out.precision(precision);
801 if (scientific)
802 out.setf(std::ios::scientific, std::ios::floatfield);
803 else
804 out.setf(std::ios::fixed, std::ios::floatfield);
805
806 size_type vector_size = vector->Map().NumMyElements();
807 if (size() != vector_size)
808 {
809 auto global_id = [&](const size_type index) {
810 return gid(vector->Map(), index);
811 };
812 out << "size:" << size()
813 << " locally_stored_size:" << vector->Map().NumMyElements()
814 << " :" << std::endl;
815 for (size_type i = 0; i < vector_size; ++i)
816 out << "[" << global_id(i) << "]: " << (*(vector))[0][i]
817 << std::endl;
818 }
819 else
820 {
821 TrilinosScalar *val;
823 int ierr = vector->ExtractView(&val, &leading_dimension);
824
826 if (across)
827 for (size_type i = 0; i < size(); ++i)
828 out << static_cast<double>(val[i]) << ' ';
829 else
830 for (size_type i = 0; i < size(); ++i)
831 out << static_cast<double>(val[i]) << std::endl;
832 out << std::endl;
833 }
834
835 AssertThrow(out.fail() == false, ExcIO());
836 }
837
838
839
840 void
841 Vector::swap(Vector &v) noexcept
842 {
843 std::swap(last_action, v.last_action);
844 std::swap(compressed, v.compressed);
845 std::swap(has_ghosts, v.has_ghosts);
846 std::swap(vector, v.vector);
847 std::swap(nonlocal_vector, v.nonlocal_vector);
848 std::swap(owned_elements, v.owned_elements);
849 }
850
851
852
853 std::size_t
855 {
856 // TODO[TH]: No accurate memory
857 // consumption for Trilinos vectors
858 // yet. This is a rough approximation with
859 // one index and the value per local
860 // entry.
861 return sizeof(*this) +
862 this->vector->Map().NumMyElements() *
863 (sizeof(double) + sizeof(TrilinosWrappers::types::int_type));
864 }
865
866 // explicit instantiations
867# ifndef DOXYGEN
868# include "lac/trilinos_vector.inst"
869# endif
870 } // namespace MPI
871} // namespace TrilinosWrappers
872
873
874#endif // DEAL_II_WITH_TRILINOS
virtual size_type size() const override
unsigned int n_blocks() const
BlockType & block(const unsigned int i)
size_type n_elements() const
Definition index_set.h:1917
void set_size(const size_type size)
Definition index_set.h:1747
void clear()
Definition index_set.h:1735
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
size_type size() const override
const IndexSet & get_stored_elements() const
void compress(VectorOperation::values operation)
void add(const std::vector< size_type > &indices, const std::vector< TrilinosScalar > &values)
std::unique_ptr< Epetra_MultiVector > nonlocal_vector
void import_elements(const LinearAlgebra::ReadWriteVector< double > &rwv, const VectorOperation::values operation)
MPI_Comm get_mpi_communicator() const
void swap(Vector &v) noexcept
void reinit(const Vector &v, const bool omit_zeroing_entries=false)
const Epetra_BlockMap & trilinos_partitioner() const
reference operator()(const size_type index)
void import_nonlocal_data_for_fe(const ::TrilinosWrappers::SparseMatrix &matrix, const Vector &vector)
std::unique_ptr< Epetra_FEVector > vector
size_type size() const override
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
IndexSet locally_owned_elements() const
std::pair< size_type, size_type > local_range() const
bool operator!=(const Vector &v) const
bool operator==(const Vector &v) const
size_type locally_owned_size() const
Vector & operator=(const TrilinosScalar s)
std::size_t memory_consumption() const
const Epetra_CrsMatrix & trilinos_matrix() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcGhostsPresent()
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void swap(BlockVector &u, BlockVector &v) noexcept
TrilinosWrappers::types::int_type global_length(const Epetra_MultiVector &vector)
int gid(const Epetra_BlockMap &map, int i)
TrilinosWrappers::types::int_type * my_global_elements(const Epetra_BlockMap &map)
TrilinosWrappers::types::int64_type n_global_elements(const Epetra_BlockMap &map)
T sum(const T &t, const MPI_Comm mpi_communicator)
bool logical_and(const bool t, const MPI_Comm mpi_communicator)
T logical_or(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:103
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm mpi_communicator)
Definition mpi.cc:77
double TrilinosScalar
Definition types.h:188