deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00: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_epetra_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) 2016 - 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
18# include <deal.II/base/mpi.h>
20
22
23# include <boost/io/ios_state.hpp>
24
26# include <Epetra_Import.h>
27# include <Epetra_Map.h>
28# include <Epetra_MpiComm.h>
30
31
32
33# include <memory>
34
35
36
37#endif
38
40
41#ifdef DEAL_II_WITH_TRILINOS
42
43namespace LinearAlgebra
44{
45 namespace EpetraWrappers
46 {
47# ifndef DOXYGEN
48 namespace internal
49 {
50 VectorReference::operator value_type() const
51 {
52 AssertIndexRange(index, vector.size());
53
54 // Trilinos allows for vectors to be referenced by the [] or ()
55 // operators but only () checks index bounds. We check these bounds by
56 // ourselves, so we can use []. Note that we can only get local values.
57
58 const TrilinosWrappers::types::int_type local_index =
59 vector.vector->Map().LID(
60 static_cast<TrilinosWrappers::types::int_type>(index));
61
62# ifndef DEAL_II_WITH_64BIT_INDICES
63 Assert(local_index >= 0,
64 ExcAccessToNonLocalElement(index,
65 vector.vector->Map().NumMyElements(),
66 vector.vector->Map().MinMyGID(),
67 vector.vector->Map().MaxMyGID()));
68# else
69 Assert(local_index >= 0,
70 ExcAccessToNonLocalElement(index,
71 vector.vector->Map().NumMyElements(),
72 vector.vector->Map().MinMyGID64(),
73 vector.vector->Map().MaxMyGID64()));
74# endif
75
76 return (*(vector.vector))[0][local_index];
77 }
78 } // namespace internal
79# endif
80
81
82 // Check that the class we declare here satisfies the
83 // vector-space-vector concept. If we catch it here,
84 // any mistake in the vector class declaration would
85 // show up in uses of this class later on as well.
86# ifdef DEAL_II_HAVE_CXX20
88# endif
89
91 : vector(new Epetra_FEVector(
92 Epetra_Map(0, 0, 0, Utilities::Trilinos::comm_self())))
93 {}
94
95
96
98 : vector(new Epetra_FEVector(V.trilinos_vector()))
99 {}
100
101
102
103 Vector::Vector(const IndexSet &parallel_partitioner,
104 const MPI_Comm communicator)
105 : vector(new Epetra_FEVector(
106 parallel_partitioner.make_trilinos_map(communicator, false)))
107 {}
108
109
110
111 void
112 Vector::reinit(const IndexSet &parallel_partitioner,
113 const MPI_Comm communicator,
114 const bool omit_zeroing_entries)
115 {
116 Epetra_Map input_map =
117 parallel_partitioner.make_trilinos_map(communicator, false);
118 if (vector->Map().SameAs(input_map) == false)
119 vector = std::make_unique<Epetra_FEVector>(input_map);
120 else if (omit_zeroing_entries == false)
121 {
122 const int ierr = vector->PutScalar(0.);
123 Assert(ierr == 0, ExcTrilinosError(ierr));
124 }
125 }
126
127
128
129 void
130 Vector::reinit(const Vector &V, const bool omit_zeroing_entries)
131 {
132 reinit(V.locally_owned_elements(),
133 V.get_mpi_communicator(),
134 omit_zeroing_entries);
135 }
136
137
138
139 void
142 const ArrayView<double> &elements) const
143 {
144 AssertDimension(indices.size(), elements.size());
145 const auto &vector = trilinos_vector();
146 const auto &map = vector.Map();
147
148 for (unsigned int i = 0; i < indices.size(); ++i)
149 {
150 AssertIndexRange(indices[i], size());
151 const auto trilinos_i =
152 map.LID(static_cast<TrilinosWrappers::types::int_type>(indices[i]));
153 elements[i] = vector[0][trilinos_i];
154 }
155 }
156
157
158
159 Vector &
161 {
162 // Distinguish three cases:
163 // - First case: both vectors have the same layout.
164 // - Second case: both vectors have the same size but different layout.
165 // - Third case: the vectors have different size.
166 if (vector->Map().SameAs(V.trilinos_vector().Map()))
167 *vector = V.trilinos_vector();
168 else
169 {
170 if (size() == V.size())
171 {
172 Epetra_Import data_exchange(vector->Map(),
173 V.trilinos_vector().Map());
174
175 const int ierr =
176 vector->Import(V.trilinos_vector(), data_exchange, Insert);
177 Assert(ierr == 0, ExcTrilinosError(ierr));
178 }
179 else
180 vector = std::make_unique<Epetra_FEVector>(V.trilinos_vector());
181 }
182
183 return *this;
184 }
185
186
187
188 Vector &
189 Vector::operator=(const double s)
190 {
191 if (s != 0.)
193 Assert(s == 0., ExcMessage("Only 0 can be assigned to a vector."));
194
195 const int ierr = vector->PutScalar(s);
196 Assert(ierr == 0, ExcTrilinosError(ierr));
197
198 return *this;
199 }
200
201
202
203 void
206 VectorOperation::values operation,
207 const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
208 &communication_pattern)
209 {
210 // If no communication pattern is given, create one. Otherwise, use the
211 // one given.
212 if (communication_pattern == nullptr)
213 {
214 // The first time import is called, a communication pattern is
215 // created. Check if the communication pattern already exists and if
216 // it can be reused.
218 V.get_stored_elements().size()) ||
219 (source_stored_elements != V.get_stored_elements()))
220 {
222 V.get_stored_elements(),
223 dynamic_cast<const Epetra_MpiComm &>(vector->Comm()).Comm());
224 }
225 }
226 else
227 {
229 std::dynamic_pointer_cast<const CommunicationPattern>(
230 communication_pattern);
232 epetra_comm_pattern != nullptr,
233 ExcMessage("The communication pattern is not of type "
234 "LinearAlgebra::EpetraWrappers::CommunicationPattern."));
235 }
236
237 Epetra_Import import_map(epetra_comm_pattern->get_epetra_import());
238
239 // The TargetMap and the SourceMap have their roles inverted.
240 Epetra_FEVector source_vector(import_map.TargetMap());
241 double *values = source_vector.Values();
242 std::copy(V.begin(), V.end(), values);
243
244 if (operation == VectorOperation::insert)
245 vector->Export(source_vector, import_map, Insert);
246 else if (operation == VectorOperation::add)
247 vector->Export(source_vector, import_map, Add);
248 else if (operation == VectorOperation::max)
249 vector->Export(source_vector, import_map, Epetra_Max);
250 else if (operation == VectorOperation::min)
251 vector->Export(source_vector, import_map, Epetra_Min);
252 else
254 }
255
256
257
258 Vector &
259 Vector::operator*=(const double factor)
260 {
261 // if we have ghost values, do not allow
262 // writing to this vector at all.
264 AssertIsFinite(factor);
265
266 vector->Scale(factor);
267
268 return *this;
269 }
270
271
272
273 Vector &
274 Vector::operator/=(const double factor)
275 {
276 // if we have ghost values, do not allow
277 // writing to this vector at all.
279 AssertIsFinite(factor);
280 Assert(factor != 0., ExcZero());
281
282 *this *= 1. / factor;
283
284 return *this;
285 }
286
287
288
289 Vector &
291 {
292 // if we have ghost values, do not allow
293 // writing to this vector at all.
295
296 // If the maps are the same we can Update right away.
297 if (vector->Map().SameAs(V.trilinos_vector().Map()))
298 {
299 const int ierr = vector->Update(1., V.trilinos_vector(), 1.);
300 Assert(ierr == 0, ExcTrilinosError(ierr));
301 }
302 else
303 {
304 Assert(this->size() == V.size(),
305 ExcDimensionMismatch(this->size(), V.size()));
306
307 Epetra_Import data_exchange(vector->Map(), V.trilinos_vector().Map());
308 const int ierr = vector->Import(V.trilinos_vector(),
309 data_exchange,
310 Epetra_AddLocalAlso);
311 Assert(ierr == 0, ExcTrilinosError(ierr));
312 }
313
314 return *this;
315 }
316
317
318
319 Vector &
321 {
322 // if we have ghost values, do not allow
323 // writing to this vector at all.
325
326 this->add(-1., V);
327
328 return *this;
329 }
330
331
332
333 double
334 Vector::operator*(const Vector &V) const
335 {
336 Assert(this->size() == V.size(),
337 ExcDimensionMismatch(this->size(), V.size()));
338 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
340
341 double result(0.);
342 const int ierr = vector->Dot(V.trilinos_vector(), &result);
343 Assert(ierr == 0, ExcTrilinosError(ierr));
344
345 return result;
346 }
347
348
349
350 void
351 Vector::add(const double a)
352 {
353 // if we have ghost values, do not allow
354 // writing to this vector at all.
357
358 const unsigned local_size(vector->MyLength());
359 for (unsigned int i = 0; i < local_size; ++i)
360 (*vector)[0][i] += a;
361 }
362
363
364
365 void
366 Vector::add(const double a, const Vector &V)
367 {
368 // if we have ghost values, do not allow
369 // writing to this vector at all.
372 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
374
375 const int ierr = vector->Update(a, V.trilinos_vector(), 1.);
376 Assert(ierr == 0, ExcTrilinosError(ierr));
377 }
378
379
380
381 void
382 Vector::add(const double a,
383 const Vector &V,
384 const double b,
385 const Vector &W)
386 {
387 // if we have ghost values, do not allow
388 // writing to this vector at all.
390 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
392 Assert(vector->Map().SameAs(W.trilinos_vector().Map()),
396
397 const int ierr =
398 vector->Update(a, V.trilinos_vector(), b, W.trilinos_vector(), 1.);
399 Assert(ierr == 0, ExcTrilinosError(ierr));
400 }
401
402
403
404 void
405 Vector::sadd(const double s, const double a, const Vector &V)
406 {
407 // if we have ghost values, do not allow
408 // writing to this vector at all.
410
411 *this *= s;
412 Vector tmp(V);
413 tmp *= a;
414 *this += tmp;
415 }
416
417
418
419 void
420 Vector::scale(const Vector &scaling_factors)
421 {
422 // if we have ghost values, do not allow
423 // writing to this vector at all.
425 Assert(vector->Map().SameAs(scaling_factors.trilinos_vector().Map()),
427
428 const int ierr =
429 vector->Multiply(1.0, scaling_factors.trilinos_vector(), *vector, 0.0);
430 Assert(ierr == 0, ExcTrilinosError(ierr));
431 }
432
433
434
435 void
436 Vector::equ(const double a, const Vector &V)
437 {
438 // if we have ghost values, do not allow
439 // writing to this vector at all.
441
442 // If we don't have the same map, copy.
443 if (vector->Map().SameAs(V.trilinos_vector().Map()) == false)
444 this->sadd(0., a, V);
445 else
446 {
447 // Otherwise, just update
448 int ierr = vector->Update(a, V.trilinos_vector(), 0.);
449 Assert(ierr == 0, ExcTrilinosError(ierr));
450 }
451 }
452
453
454
455 bool
457 {
458 const double *start_ptr = (*vector)[0];
459
460 const bool local_all_zero = std::all_of(start_ptr,
461 start_ptr + locally_owned_size(),
462 numbers::value_is_zero<double>);
463
464 return Utilities::MPI::logical_and(local_all_zero,
466 }
467
468
469
470 double
472 {
474
475 double mean_value(0.);
476
477 int ierr = vector->MeanValue(&mean_value);
478 Assert(ierr == 0, ExcTrilinosError(ierr));
479
480 return mean_value;
481 }
482
483
484
485 double
487 {
489
490 double norm = 0;
491 int ierr = vector->Norm1(&norm);
492 Assert(ierr == 0, ExcTrilinosError(ierr));
493
494 return norm;
495 }
496
497
498
499 double
501 {
503
504 double norm = 0;
505 int ierr = vector->Norm2(&norm);
506 Assert(ierr == 0, ExcTrilinosError(ierr));
507
508 return norm;
509 }
510
511
512
513 double
515 {
516 double norm = 0;
517 int ierr = vector->NormInf(&norm);
518 Assert(ierr == 0, ExcTrilinosError(ierr));
519
520 return norm;
521 }
522
523
524
525 double
526 Vector::add_and_dot(const double a, const Vector &V, const Vector &W)
527 {
529
530 this->add(a, V);
531
532 return *this * W;
533 }
534
535
536
539 {
540# ifndef DEAL_II_WITH_64BIT_INDICES
541 return vector->GlobalLength();
542# else
543 return vector->GlobalLength64();
544# endif
545 }
546
547
548
551 {
552 return vector->MyLength();
553 }
554
555
556
559 {
560 const Epetra_MpiComm *epetra_comm =
561 dynamic_cast<const Epetra_MpiComm *>(&(vector->Comm()));
562 Assert(epetra_comm != nullptr, ExcInternalError());
563 return epetra_comm->GetMpiComm();
564 }
565
566
567
570 {
571 IndexSet is(size());
572
573 // easy case: local range is contiguous
574 if (vector->Map().LinearMap())
575 {
576# ifndef DEAL_II_WITH_64BIT_INDICES
577 is.add_range(vector->Map().MinMyGID(), vector->Map().MaxMyGID() + 1);
578# else
579 is.add_range(vector->Map().MinMyGID64(),
580 vector->Map().MaxMyGID64() + 1);
581# endif
582 }
583 else if (vector->Map().NumMyElements() > 0)
584 {
585 const size_type n_indices = vector->Map().NumMyElements();
586# ifndef DEAL_II_WITH_64BIT_INDICES
587 unsigned int *vector_indices =
588 reinterpret_cast<unsigned int *>(vector->Map().MyGlobalElements());
589# else
590 size_type *vector_indices =
591 reinterpret_cast<size_type *>(vector->Map().MyGlobalElements64());
592# endif
593 is.add_indices(vector_indices, vector_indices + n_indices);
594 }
595 is.compress();
596
597 return is;
598 }
599
600
601 void
603 {}
604
605
606
607 const Epetra_FEVector &
609 {
610 return *vector;
611 }
612
613
614
615 Epetra_FEVector &
617 {
618 return *vector;
619 }
620
621
622
623 void
624 Vector::print(std::ostream &out,
625 const unsigned int precision,
626 const bool scientific,
627 const bool across) const
628 {
629 AssertThrow(out.fail() == false, ExcIO());
630 boost::io::ios_flags_saver restore_flags(out);
631
632 // Get a representation of the vector and loop over all
633 // the elements
634 double *val;
635 int leading_dimension;
636 int ierr = vector->ExtractView(&val, &leading_dimension);
637
638 Assert(ierr == 0, ExcTrilinosError(ierr));
639 out.precision(precision);
640 if (scientific)
641 out.setf(std::ios::scientific, std::ios::floatfield);
642 else
643 out.setf(std::ios::fixed, std::ios::floatfield);
644
645 if (across)
646 for (int i = 0; i < vector->MyLength(); ++i)
647 out << val[i] << ' ';
648 else
649 for (int i = 0; i < vector->MyLength(); ++i)
650 out << val[i] << std::endl;
651 out << std::endl;
652
653 // restore the representation
654 // of the vector
655 AssertThrow(out.fail() == false, ExcIO());
656 }
657
658
659
660 std::size_t
662 {
663 return sizeof(*this) +
664 vector->MyLength() *
665 (sizeof(double) + sizeof(TrilinosWrappers::types::int_type));
666 }
667
668
669
670 void
672 const MPI_Comm mpi_comm)
673 {
674 source_stored_elements = source_index_set;
676 std::make_shared<CommunicationPattern>(locally_owned_elements(),
677 source_index_set,
678 mpi_comm);
679 }
680 } // namespace EpetraWrappers
681} // namespace LinearAlgebra
682
683
684#endif
std::size_t size() const
Definition array_view.h:737
size_type size() const
Definition index_set.h:1759
Epetra_Map make_trilinos_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
void add_range(const size_type begin, const size_type end)
Definition index_set.h:1786
void compress() const
Definition index_set.h:1767
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
void equ(const double a, const Vector &V)
void compress(const VectorOperation::values operation)
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
std::unique_ptr< Epetra_FEVector > vector
const Epetra_FEVector & trilinos_vector() const
void import_elements(const ReadWriteVector< double > &V, VectorOperation::values operation, const std::shared_ptr< const Utilities::MPI::CommunicationPatternBase > &communication_pattern={})
void sadd(const double s, const double a, const Vector &V)
virtual size_type size() const override
void scale(const Vector &scaling_factors)
void create_epetra_comm_pattern(const IndexSet &source_index_set, const MPI_Comm mpi_comm)
std::shared_ptr< const CommunicationPattern > epetra_comm_pattern
void reinit(const IndexSet &parallel_partitioner, const MPI_Comm communicator, const bool omit_zeroing_entries=false)
virtual void extract_subvector_to(const ArrayView< const types::global_dof_index > &indices, const ArrayView< double > &elements) const override
double add_and_dot(const double a, const Vector &V, const Vector &W)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#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 & ExcZero()
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIsFinite(number)
static ::ExceptionBase & ExcDifferentParallelPartitioning()
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
bool logical_and(const bool t, const MPI_Comm mpi_communicator)