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