deal.II version GIT relicensing-2233-g9bd70d8389 2024-12-08 16:10:00+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: LGPL-2.1-or-later
4// Copyright (C) 2016 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
16
17#ifdef DEAL_II_WITH_TRILINOS
18
20# include <deal.II/base/mpi.h>
22
24
25# include <boost/io/ios_state.hpp>
26
27# include <Epetra_Import.h>
28# include <Epetra_Map.h>
29# include <Epetra_MpiComm.h>
30
31# include <memory>
32
33
35
36namespace LinearAlgebra
37{
38 namespace EpetraWrappers
39 {
40# ifndef DOXYGEN
41 namespace internal
42 {
43 VectorReference::operator value_type() const
44 {
45 AssertIndexRange(index, vector.size());
46
47 // Trilinos allows for vectors to be referenced by the [] or ()
48 // operators but only () checks index bounds. We check these bounds by
49 // ourselves, so we can use []. Note that we can only get local values.
50
51 const TrilinosWrappers::types::int_type local_index =
52 vector.vector->Map().LID(
53 static_cast<TrilinosWrappers::types::int_type>(index));
54
55# ifndef DEAL_II_WITH_64BIT_INDICES
56 Assert(local_index >= 0,
57 ExcAccessToNonLocalElement(index,
58 vector.vector->Map().NumMyElements(),
59 vector.vector->Map().MinMyGID(),
60 vector.vector->Map().MaxMyGID()));
61# else
62 Assert(local_index >= 0,
63 ExcAccessToNonLocalElement(index,
64 vector.vector->Map().NumMyElements(),
65 vector.vector->Map().MinMyGID64(),
66 vector.vector->Map().MaxMyGID64()));
67# endif
68
69 return (*(vector.vector))[0][local_index];
70 }
71 } // namespace internal
72# endif
73
74
75 // Check that the class we declare here satisfies the
76 // vector-space-vector concept. If we catch it here,
77 // any mistake in the vector class declaration would
78 // show up in uses of this class later on as well.
79# ifdef DEAL_II_HAVE_CXX20
81# endif
82
84 : vector(new Epetra_FEVector(
85 Epetra_Map(0, 0, 0, Utilities::Trilinos::comm_self())))
86 {}
87
88
89
91 : vector(new Epetra_FEVector(V.trilinos_vector()))
92 {}
93
94
95
96 Vector::Vector(const IndexSet &parallel_partitioner,
97 const MPI_Comm communicator)
98 : vector(new Epetra_FEVector(
99 parallel_partitioner.make_trilinos_map(communicator, false)))
100 {}
101
102
103
104 void
105 Vector::reinit(const IndexSet &parallel_partitioner,
106 const MPI_Comm communicator,
107 const bool omit_zeroing_entries)
108 {
109 Epetra_Map input_map =
110 parallel_partitioner.make_trilinos_map(communicator, false);
111 if (vector->Map().SameAs(input_map) == false)
112 vector = std::make_unique<Epetra_FEVector>(input_map);
113 else if (omit_zeroing_entries == false)
114 {
115 const int ierr = vector->PutScalar(0.);
117 (void)ierr;
118 }
119 }
120
121
122
123 void
124 Vector::reinit(const Vector &V, const bool omit_zeroing_entries)
125 {
129 }
130
131
132
133 void
136 const ArrayView<double> &elements) const
137 {
138 AssertDimension(indices.size(), elements.size());
139 const auto &vector = trilinos_vector();
140 const auto &map = vector.Map();
141
142 for (unsigned int i = 0; i < indices.size(); ++i)
143 {
144 AssertIndexRange(indices[i], size());
145 const auto trilinos_i =
146 map.LID(static_cast<TrilinosWrappers::types::int_type>(indices[i]));
147 elements[i] = vector[0][trilinos_i];
148 }
149 }
150
151
152
153 Vector &
155 {
156 // Distinguish three cases:
157 // - First case: both vectors have the same layout.
158 // - Second case: both vectors have the same size but different layout.
159 // - Third case: the vectors have different size.
160 if (vector->Map().SameAs(V.trilinos_vector().Map()))
161 *vector = V.trilinos_vector();
162 else
163 {
164 if (size() == V.size())
165 {
166 Epetra_Import data_exchange(vector->Map(),
167 V.trilinos_vector().Map());
168
169 const int ierr =
172 (void)ierr;
173 }
174 else
175 vector = std::make_unique<Epetra_FEVector>(V.trilinos_vector());
176 }
177
178 return *this;
179 }
180
181
182
183 Vector &
184 Vector::operator=(const double s)
185 {
186 Assert(s == 0., ExcMessage("Only 0 can be assigned to a vector."));
187
188 const int ierr = vector->PutScalar(s);
190 (void)ierr;
191
192 return *this;
193 }
194
195
196
197 void
200 VectorOperation::values operation,
201 const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
202 &communication_pattern)
203 {
204 // If no communication pattern is given, create one. Otherwise, use the
205 // one given.
206 if (communication_pattern == nullptr)
207 {
208 // The first time import is called, a communication pattern is
209 // created. Check if the communication pattern already exists and if
210 // it can be reused.
212 V.get_stored_elements().size()) ||
214 {
217 dynamic_cast<const Epetra_MpiComm &>(vector->Comm()).Comm());
218 }
219 }
220 else
221 {
223 std::dynamic_pointer_cast<const CommunicationPattern>(
226 epetra_comm_pattern != nullptr,
227 ExcMessage("The communication pattern is not of type "
228 "LinearAlgebra::EpetraWrappers::CommunicationPattern."));
229 }
230
231 Epetra_Import import_map(epetra_comm_pattern->get_epetra_import());
232
233 // The TargetMap and the SourceMap have their roles inverted.
234 Epetra_FEVector source_vector(import_map.TargetMap());
235 double *values = source_vector.Values();
236 std::copy(V.begin(), V.end(), values);
237
246 else
248 }
249
250
251
252 Vector &
253 Vector::operator*=(const double factor)
254 {
255 AssertIsFinite(factor);
256 vector->Scale(factor);
257
258 return *this;
259 }
260
261
262
263 Vector &
264 Vector::operator/=(const double factor)
265 {
266 AssertIsFinite(factor);
267 Assert(factor != 0., ExcZero());
268 *this *= 1. / factor;
269
270 return *this;
271 }
272
273
274
275 Vector &
277 {
278 // If the maps are the same we can Update right away.
279 if (vector->Map().SameAs(V.trilinos_vector().Map()))
280 {
281 const int ierr = vector->Update(1., V.trilinos_vector(), 1.);
283 (void)ierr;
284 }
285 else
286 {
287 Assert(this->size() == V.size(),
288 ExcDimensionMismatch(this->size(), V.size()));
289
290# if DEAL_II_TRILINOS_VERSION_GTE(11, 11, 0)
291 Epetra_Import data_exchange(vector->Map(), V.trilinos_vector().Map());
292 const int ierr = vector->Import(V.trilinos_vector(),
296 (void)ierr;
297# else
298 // In versions older than 11.11 the Import function is broken for
299 // adding Hence, we provide a workaround in this case
300
301 Epetra_MultiVector dummy(vector->Map(), 1, false);
302 Epetra_Import data_exchange(dummy.Map(), V.trilinos_vector().Map());
303
304 int ierr = dummy.Import(V.trilinos_vector(), data_exchange, Insert);
306
307 ierr = vector->Update(1.0, dummy, 1.0);
309 (void)ierr;
310# endif
311 }
312
313 return *this;
314 }
315
316
317
318 Vector &
320 {
321 this->add(-1., V);
322
323 return *this;
324 }
325
326
327
328 double
329 Vector::operator*(const Vector &V) const
330 {
331 Assert(this->size() == V.size(),
332 ExcDimensionMismatch(this->size(), V.size()));
333 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
335
336 double result(0.);
337 const int ierr = vector->Dot(V.trilinos_vector(), &result);
339 (void)ierr;
340
341 return result;
342 }
343
344
345
346 void
347 Vector::add(const double a)
348 {
350 const unsigned local_size(vector->MyLength());
351 for (unsigned int i = 0; i < local_size; ++i)
352 (*vector)[0][i] += a;
353 }
354
355
356
357 void
358 Vector::add(const double a, const Vector &V)
359 {
361 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
363
364 const int ierr = vector->Update(a, V.trilinos_vector(), 1.);
366 (void)ierr;
367 }
368
369
370
371 void
372 Vector::add(const double a,
373 const Vector &V,
374 const double b,
375 const Vector &W)
376 {
377 Assert(vector->Map().SameAs(V.trilinos_vector().Map()),
379 Assert(vector->Map().SameAs(W.trilinos_vector().Map()),
383
384 const int ierr =
385 vector->Update(a, V.trilinos_vector(), b, W.trilinos_vector(), 1.);
387 (void)ierr;
388 }
389
390
391
392 void
393 Vector::sadd(const double s, const double a, const Vector &V)
394 {
395 *this *= s;
396 Vector tmp(V);
397 tmp *= a;
398 *this += tmp;
399 }
400
401
402
403 void
404 Vector::scale(const Vector &scaling_factors)
405 {
406 Assert(vector->Map().SameAs(scaling_factors.trilinos_vector().Map()),
408
409 const int ierr =
410 vector->Multiply(1.0, scaling_factors.trilinos_vector(), *vector, 0.0);
412 (void)ierr;
413 }
414
415
416
417 void
418 Vector::equ(const double a, const Vector &V)
419 {
420 // If we don't have the same map, copy.
421 if (vector->Map().SameAs(V.trilinos_vector().Map()) == false)
422 this->sadd(0., a, V);
423 else
424 {
425 // Otherwise, just update
426 int ierr = vector->Update(a, V.trilinos_vector(), 0.);
428 (void)ierr;
429 }
430 }
431
432
433
434 bool
436 {
437 // get a representation of the vector and
438 // loop over all the elements
439 double *start_ptr = (*vector)[0];
440 const double *ptr = start_ptr, *eptr = start_ptr + vector->MyLength();
441 unsigned int flag = 0;
442 while (ptr != eptr)
443 {
444 if (*ptr != 0)
445 {
446 flag = 1;
447 break;
448 }
449 ++ptr;
450 }
451
452 // Check that the vector is zero on _all_ processors.
453 const Epetra_MpiComm *mpi_comm =
454 dynamic_cast<const Epetra_MpiComm *>(&vector->Map().Comm());
455 Assert(mpi_comm != nullptr, ExcInternalError());
456 unsigned int num_nonzero = Utilities::MPI::sum(flag, mpi_comm->Comm());
457
458 return num_nonzero == 0;
459 }
460
461
462
463 double
465 {
466 double mean_value(0.);
467
468 int ierr = vector->MeanValue(&mean_value);
470 (void)ierr;
471
472 return mean_value;
473 }
474
475
476
477 double
479 {
480 double norm(0.);
481 int ierr = vector->Norm1(&norm);
483 (void)ierr;
484
485 return norm;
486 }
487
488
489
490 double
492 {
493 double norm(0.);
494 int ierr = vector->Norm2(&norm);
496 (void)ierr;
497
498 return norm;
499 }
500
501
502
503 double
505 {
506 double norm(0.);
507 int ierr = vector->NormInf(&norm);
509 (void)ierr;
510
511 return norm;
512 }
513
514
515
516 double
517 Vector::add_and_dot(const double a, const Vector &V, const Vector &W)
518 {
519 this->add(a, V);
520
521 return *this * W;
522 }
523
524
525
528 {
529# ifndef DEAL_II_WITH_64BIT_INDICES
530 return vector->GlobalLength();
531# else
532 return vector->GlobalLength64();
533# endif
534 }
535
536
537
540 {
541 return vector->MyLength();
542 }
543
544
545
548 {
549 const Epetra_MpiComm *epetra_comm =
550 dynamic_cast<const Epetra_MpiComm *>(&(vector->Comm()));
551 Assert(epetra_comm != nullptr, ExcInternalError());
552 return epetra_comm->GetMpiComm();
553 }
554
555
556
559 {
560 IndexSet is(size());
561
562 // easy case: local range is contiguous
563 if (vector->Map().LinearMap())
564 {
565# ifndef DEAL_II_WITH_64BIT_INDICES
566 is.add_range(vector->Map().MinMyGID(), vector->Map().MaxMyGID() + 1);
567# else
568 is.add_range(vector->Map().MinMyGID64(),
569 vector->Map().MaxMyGID64() + 1);
570# endif
571 }
572 else if (vector->Map().NumMyElements() > 0)
573 {
574 const size_type n_indices = vector->Map().NumMyElements();
575# ifndef DEAL_II_WITH_64BIT_INDICES
576 unsigned int *vector_indices =
577 reinterpret_cast<unsigned int *>(vector->Map().MyGlobalElements());
578# else
580 reinterpret_cast<size_type *>(vector->Map().MyGlobalElements64());
581# endif
583 }
584 is.compress();
585
586 return is;
587 }
588
589
590 void
592 {}
593
594
595
596 const Epetra_FEVector &
598 {
599 return *vector;
600 }
601
602
603
604 Epetra_FEVector &
606 {
607 return *vector;
608 }
609
610
611
612 void
613 Vector::print(std::ostream &out,
614 const unsigned int precision,
615 const bool scientific,
616 const bool across) const
617 {
618 AssertThrow(out.fail() == false, ExcIO());
619 boost::io::ios_flags_saver restore_flags(out);
620
621 // Get a representation of the vector and loop over all
622 // the elements
623 double *val;
625 int ierr = vector->ExtractView(&val, &leading_dimension);
626
628 (void)ierr;
629 out.precision(precision);
630 if (scientific)
631 out.setf(std::ios::scientific, std::ios::floatfield);
632 else
633 out.setf(std::ios::fixed, std::ios::floatfield);
634
635 if (across)
636 for (int i = 0; i < vector->MyLength(); ++i)
637 out << val[i] << ' ';
638 else
639 for (int i = 0; i < vector->MyLength(); ++i)
640 out << val[i] << std::endl;
641 out << std::endl;
642
643 // restore the representation
644 // of the vector
645 AssertThrow(out.fail() == false, ExcIO());
646 }
647
648
649
650 std::size_t
652 {
653 return sizeof(*this) +
654 vector->MyLength() *
655 (sizeof(double) + sizeof(TrilinosWrappers::types::int_type));
656 }
657
658
659
660 void
662 const MPI_Comm mpi_comm)
663 {
666 std::make_shared<CommunicationPattern>(locally_owned_elements(),
668 mpi_comm);
669 }
670 } // namespace EpetraWrappers
671} // namespace LinearAlgebra
672
674
675#endif
std::size_t size() const
Definition array_view.h:684
size_type size() const
Definition index_set.h:1776
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)
const IndexSet & get_stored_elements() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
static ::ExceptionBase & ExcIO()
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)
T sum(const T &t, const MPI_Comm mpi_communicator)