KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
amgcl_distributed_csr_conversion_utilities.h
Go to the documentation of this file.
1 
2 // | / |
3 // ' / __| _` | __| _ \ __|
4 // . \ | ( | | ( |\__ \.
5 // _|\_\_| \__,_|\__|\___/ ____/
6 // Multi-Physics
7 //
8 // License: BSD License
9 // Kratos default license: kratos/license.txt
10 //
11 // Main authors: Denis Demidov
12 // Riccardo Rossi
13 //
14 //
15 
16 #if !defined(KRATOS_DISTRIBUTED_CSR_CONVERSION_UTILITIES_H_INCLUDED)
17 #define KRATOS_DISTRIBUTED_CSR_CONVERSION_UTILITIES_H_INCLUDED
18 
19 // System includes
20 
21 // External includes
22 #include <amgcl/backend/builtin.hpp>
23 #include <amgcl/backend/interface.hpp>
24 #include <amgcl/mpi/distributed_matrix.hpp>
25 #include <amgcl/adapter/zero_copy.hpp>
26 
27 // Project includes
31 
32 namespace Kratos
33 {
34 
39 {
40 
41 public:
42 
46  template< class TDataType, class TIndexType >
49  DenseVector<TIndexType>& global_index2,
50  bool MoveToBackend=true)
51  {
52  IndexType chunk = rA.local_size1();
53  auto loc_a = amgcl::adapter::zero_copy(chunk,
54  rA.GetDiagonalBlock().index1_data().begin(),
55  rA.GetDiagonalBlock().index2_data().begin(),
56  rA.GetDiagonalBlock().value_data().begin()
57  );
58  loc_a->ncols = rA.GetDiagonalBlock().size2(); //important if the matrix is not square
59 
60  auto rem_a = amgcl::adapter::zero_copy(chunk,
61  rA.GetOffDiagonalBlock().index1_data().begin(),
62  global_index2.data().begin(),
63  rA.GetOffDiagonalBlock().value_data().begin()
64  );
65 
66  rem_a->ncols = rA.GetOffDiagonalBlock().size2(); //important if the matrix is not square
67 
68  auto raw_mpi_comm = MPIDataCommunicator::GetMPICommunicator( rA.GetComm());
69  amgcl::mpi::communicator comm(raw_mpi_comm);
70 
71  auto pAmgcl = Kratos::make_shared<amgcl::mpi::distributed_matrix<amgcl::backend::builtin<double>>>(comm, loc_a, rem_a);
72 
73  if(MoveToBackend)
74  pAmgcl->move_to_backend();
75 
76  return pAmgcl;
77  }
78 
79  template< class TDataType, class TIndexType >
81  amgcl::mpi::distributed_matrix<amgcl::backend::builtin<double>>& rA, //cannot be made const since i need to modify some data in-place,
82  const DataCommunicator& kratos_comm
83  )
84  {
85  if(!rA.local())
86  KRATOS_ERROR << "matrix A was moved to backend, so it is impossible to convert it back to CSR matrix" << std::endl;
87 
88  auto pAconverted = Kratos::make_unique<DistributedCsrMatrix<TDataType, TIndexType>>(kratos_comm);
89 
90  MPI_Comm amgcl_raw_comm = rA.comm();
91  if(amgcl_raw_comm != MPIDataCommunicator::GetMPICommunicator( kratos_comm) )
92  KRATOS_ERROR << "MPI communicator mismatch between the communicator passed to the conversion function and the one used internally by amgcl" << std::endl;
93 
94  //create row numbering and col numbering
95  pAconverted->pGetRowNumbering() = Kratos::make_unique<DistributedNumbering<IndexType>>(kratos_comm,rA.local()->nrows);
96  pAconverted->pGetColNumbering() = Kratos::make_unique<DistributedNumbering<IndexType>>(kratos_comm,rA.local()->ncols);
97 
98  //here we fill the global to local mapping
99  const auto& comm_pattern = rA.cpat();
100  for(TIndexType i=0; i<rA.remote()->nnz; ++i) //TODO: i suspect there is a smarter way to do this
101  {
102  TIndexType id = rA.remote()->col[i];
103  TIndexType local_id = comm_pattern.local_index(id);
104  pAconverted->GetOffDiagonalLocalIds()[id] = local_id;
105  rA.remote()->col[i] = local_id; //note that here we overwrite the amgcl data!
106  }
107 
108  //here we fill the local to global mapping (the inverse of the previous one)
109  pAconverted->GetOffDiagonalGlobalIds().resize(pAconverted->GetOffDiagonalLocalIds().size());
110 
111  for(auto item : pAconverted->GetOffDiagonalLocalIds())
112  {
113  pAconverted->GetOffDiagonalGlobalIds()[item.second] = item.first; //item.second=local_id, item.first=global_id
114  }
115 
116  //setting col size for both matrices
117  pAconverted->GetDiagonalBlock().SetColSize(rA.local()->ncols);
118  pAconverted->GetOffDiagonalBlock().SetColSize(pAconverted->GetOffDiagonalGlobalIds().size());
119 
120  //convert diagonal block
121  pAconverted->pGetDiagonalBlock() = std::move(AmgclCSRConversionUtilities::ConvertToCsrMatrix<TDataType,TIndexType>(*(rA.local().get())));
122 
123  //convert off diagonal block. Note that we need to change the usage of the index2. We do it in place
124  pAconverted->pGetOffDiagonalBlock() = std::move(AmgclCSRConversionUtilities::ConvertToCsrMatrix<TDataType,TIndexType>(*(rA.remote().get())));
125 
126  //fill the vector importer, so that the matrix can be used to do calculations
127  pAconverted->pGetVectorImporter() = Kratos::make_unique<DistributedVectorImporter<TDataType,IndexType>>(
128  kratos_comm,pAconverted->GetOffDiagonalGlobalIds(),
129  pAconverted->GetColNumbering()
130  );
131 
132  //the following data are simply not available in Amgcl.
133  //warning: THE IMPORTANT IMPLICATION IS THAT THE MATRIX CANNOT BE USED FOR ASSEMBLY WITHOUT PROVIDING MORE INFORMATION
134  // mSendCachedIJ
135  // mRecvCachedIJ
136  // mOffDiagonalLocalIds
137  // mOffDiagonalGlobalIds
138  // mfem_assemble_colors
139 
140  return pAconverted;
141  }
142 
143  template< class TDataType, class TIndexType >
146  )
147  {
148  auto& comm = rA.GetComm();
149 
150  bool move_to_backend=false; //important!
151  auto offdiag_global_index2 = rA.GetOffDiagonalIndex2DataInGlobalNumbering();
152  const auto pAamgcl = ConvertToAmgcl<TDataType,TIndexType>(rA, offdiag_global_index2, move_to_backend);
153 
154  const auto pAamgcl_transpose = transpose(*pAamgcl);
155 
156  return ConvertToCsrMatrix<TDataType,TIndexType>(*pAamgcl_transpose, comm);
157  }
158 };
159 
160 }
161 
162 #endif // KRATOS_DISTRIBUTED_CSR_CONVERSION_UTILITIES_H_INCLUDED
Definition: amgcl_distributed_csr_conversion_utilities.h:39
static DistributedCsrMatrix< TDataType, TIndexType >::Pointer Transpose(const DistributedCsrMatrix< TDataType, TIndexType > &rA)
Definition: amgcl_distributed_csr_conversion_utilities.h:144
static Kratos::shared_ptr< amgcl::mpi::distributed_matrix< amgcl::backend::builtin< double > > > ConvertToAmgcl(const DistributedCsrMatrix< TDataType, TIndexType > &rA, DenseVector< TIndexType > &global_index2, bool MoveToBackend=true)
Definition: amgcl_distributed_csr_conversion_utilities.h:47
static DistributedCsrMatrix< TDataType, TIndexType >::UniquePointer ConvertToCsrMatrix(amgcl::mpi::distributed_matrix< amgcl::backend::builtin< double >> &rA, const DataCommunicator &kratos_comm)
Definition: amgcl_distributed_csr_conversion_utilities.h:80
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
This class implements "serial" CSR matrix, including capabilities for FEM assembly.
Definition: distributed_csr_matrix.h:58
TIndexType local_size1() const
Definition: distributed_csr_matrix.h:314
CsrMatrix< TDataType, TIndexType > & GetOffDiagonalBlock()
Definition: distributed_csr_matrix.h:352
const DataCommunicator & GetComm() const
Definition: distributed_csr_matrix.h:329
DenseVector< TIndexType > GetOffDiagonalIndex2DataInGlobalNumbering() const
Definition: distributed_csr_matrix.h:431
CsrMatrix< TDataType, TIndexType > & GetDiagonalBlock()
Definition: distributed_csr_matrix.h:348
Definition: amatrix_interface.h:41
iterator begin()
Definition: amatrix_interface.h:241
static MPI_Comm GetMPICommunicator(const DataCommunicator &rDataCommunicator)
Get the underlying MPI_Comm instance.
Definition: mpi_data_communicator.cpp:431
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
#define KRATOS_ERROR
Definition: exception.h:161
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
std::shared_ptr< T > shared_ptr
Definition: smart_pointers.h:27
integer i
Definition: TensorModule.f:17