PreconditionerConvertFieldTypeAdapter.hpp
Go to the documentation of this file.
1/*
2 Copyright 2022-2023 SINTEF AS
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef OPM_PRECONDITIONERCONVERTOFLOATADAPTER_HPP
20#define OPM_PRECONDITIONERCONVERTOFLOATADAPTER_HPP
21#include <cusparse.h>
22#include <dune/istl/bcrsmatrix.hh>
23#include <dune/istl/preconditioner.hh>
32
33
34namespace Opm::cuistl
35{
84template <class CudaPreconditionerType, class M, class X, class Y, int l = 1>
86{
87public:
89 using matrix_type = typename std::remove_const<M>::type;
90
92 using domain_type = X;
94 using range_type = Y;
96 using field_type = typename X::field_type;
97
98
99 using domain_type_to = typename CudaPreconditionerType::domain_type;
101 using range_type_to = typename CudaPreconditionerType::range_type;
103 using field_type_to = typename domain_type_to::field_type;
104
105
106 using block_type = typename domain_type::block_type;
107
108 using XTo = Dune::BlockVector<Dune::FieldVector<field_type_to, block_type::dimension>>;
109 using YTo = Dune::BlockVector<Dune::FieldVector<field_type_to, block_type::dimension>>;
111 typename Dune::BCRSMatrix<Dune::FieldMatrix<field_type_to, block_type::dimension, block_type::dimension>>;
112
121 : m_matrix(matrix)
122 , m_convertedMatrix(createConvertedMatrix())
123 {
124 }
125
127 virtual void pre([[maybe_unused]] X& x, [[maybe_unused]] Y& b) override
128 {
129 static_assert(!detail::shouldCallPreconditionerPre<CudaPreconditionerType>(),
130 "We currently do not support Preconditioner::pre().");
131 }
132
134 virtual void apply(X& v, const Y& d) override
135 {
136 OPM_ERROR_IF(!m_underlyingPreconditioner,
137 "You need to set the underlying preconditioner with setUnderlyingPreconditioner.");
138 XTo convertedV(v.N());
139 for (size_t i = 0; i < v.N(); ++i) {
140 for (size_t j = 0; j < block_type::dimension; ++j) {
141 // This is probably unnecessary, but doing it anyway:
142 convertedV[i][j] = field_type_to(v[i][j]);
143 }
144 }
145 YTo convertedD(d.N());
146 for (size_t i = 0; i < d.N(); ++i) {
147 for (size_t j = 0; j < block_type::dimension; ++j) {
148 convertedD[i][j] = field_type_to(d[i][j]);
149 }
150 }
151
152 m_underlyingPreconditioner->apply(convertedV, convertedD);
153
154 for (size_t i = 0; i < v.N(); ++i) {
155 for (size_t j = 0; j < block_type::dimension; ++j) {
156 v[i][j] = field_type(convertedV[i][j]);
157 }
158 }
159 }
160
162 virtual void post([[maybe_unused]] X& x) override
163 {
164 static_assert(!detail::shouldCallPreconditionerPost<CudaPreconditionerType>(),
165 "We currently do not support Preconditioner::post().");
166 }
167
169 virtual Dune::SolverCategory::Category category() const override
170 {
171 return m_underlyingPreconditioner->category();
172 }
173
174 virtual void update() override
175 {
176 OPM_ERROR_IF(!m_underlyingPreconditioner,
177 "You need to set the underlying preconditioner with setUnderlyingPreconditioner.");
178 updateMatrix();
179 m_underlyingPreconditioner->update();
180 }
181
183 {
184 return m_convertedMatrix;
185 }
186
187 void setUnderlyingPreconditioner(const std::shared_ptr<CudaPreconditionerType>& conditioner)
188 {
189 m_underlyingPreconditioner = conditioner;
190 }
191
192
193private:
194 void updateMatrix()
195 {
196 const auto nnz = m_matrix.nonzeroes() * m_matrix[0][0].N() * m_matrix[0][0].N();
197 const auto dataPointerIn = static_cast<const field_type*>(&((m_matrix[0][0][0][0])));
198 auto dataPointerOut = static_cast<field_type_to*>(&((m_convertedMatrix[0][0][0][0])));
199
200 std::vector<field_type_to> buffer(nnz, 0);
201 for (size_t i = 0; i < nnz; ++i) {
202 dataPointerOut[i] = field_type_to(dataPointerIn[i]);
203 }
204 }
205 matrix_type_to createConvertedMatrix()
206 {
207 // TODO: Check if this whole conversion can be done more efficiently.
208 const auto N = m_matrix.N();
209 matrix_type_to matrixBuilder(N, N, m_matrix.nonzeroes(), matrix_type_to::row_wise);
210 {
211 auto rowIn = m_matrix.begin();
212 for (auto rowOut = matrixBuilder.createbegin(); rowOut != matrixBuilder.createend(); ++rowOut) {
213 for (auto column = rowIn->begin(); column != rowIn->end(); ++column) {
214 rowOut.insert(column.index());
215 }
216 ++rowIn;
217 }
218 }
219
220 for (auto row = m_matrix.begin(); row != m_matrix.end(); ++row) {
221 for (auto column = row->begin(); column != row->end(); ++column) {
222 for (size_t i = 0; i < block_type::dimension; ++i) {
223 for (size_t j = 0; j < block_type::dimension; ++j) {
224 matrixBuilder[row.index()][column.index()][i][j]
225 = field_type_to(m_matrix[row.index()][column.index()][i][j]);
226 }
227 }
228 }
229 }
230
231 return matrixBuilder;
232 }
233 const M& m_matrix;
234 matrix_type_to m_convertedMatrix;
236 std::shared_ptr<CudaPreconditionerType> m_underlyingPreconditioner;
237};
238} // end namespace Opm::cuistl
239
240#endif
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:32
Converts the field type (eg. double to float) to benchmark single precision preconditioners.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:86
virtual void update() override
Definition: PreconditionerConvertFieldTypeAdapter.hpp:174
PreconditionerConvertFieldTypeAdapter(const M &matrix)
Constructor.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:120
typename domain_type::block_type block_type
Definition: PreconditionerConvertFieldTypeAdapter.hpp:106
typename CudaPreconditionerType::domain_type domain_type_to
Definition: PreconditionerConvertFieldTypeAdapter.hpp:99
typename X::field_type field_type
The field type of the preconditioner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:96
virtual void pre(X &x, Y &b) override
Not used at the moment.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:127
typename Dune::BCRSMatrix< Dune::FieldMatrix< field_type_to, block_type::dimension, block_type::dimension > > matrix_type_to
Definition: PreconditionerConvertFieldTypeAdapter.hpp:111
const matrix_type_to & getConvertedMatrix() const
Definition: PreconditionerConvertFieldTypeAdapter.hpp:182
void setUnderlyingPreconditioner(const std::shared_ptr< CudaPreconditionerType > &conditioner)
Definition: PreconditionerConvertFieldTypeAdapter.hpp:187
virtual void post(X &x) override
Not used at the moment.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:162
Dune::BlockVector< Dune::FieldVector< field_type_to, block_type::dimension > > XTo
Definition: PreconditionerConvertFieldTypeAdapter.hpp:108
Y range_type
The range type of the preconditioner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:94
virtual void apply(X &v, const Y &d) override
Apply the preconditoner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:134
X domain_type
The domain type of the preconditioner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:92
virtual Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: PreconditionerConvertFieldTypeAdapter.hpp:169
typename CudaPreconditionerType::range_type range_type_to
The range type of the preconditioner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:101
typename std::remove_const< M >::type matrix_type
The matrix type the preconditioner is for.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:89
typename domain_type_to::field_type field_type_to
The field type of the preconditioner.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:103
Dune::BlockVector< Dune::FieldVector< field_type_to, block_type::dimension > > YTo
Definition: PreconditionerConvertFieldTypeAdapter.hpp:109
Definition: CuBlockPreconditioner.hpp:29