Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
ILU0Preconditioner.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
8#pragma once
9#if defined (ALIEN_USE_EIGEN3)
10#if defined(ALIEN_USE_SYCL)
11 #ifdef __ACPP__
12 //#define EIGEN3_DISABLED
13 //#warning "EIGEN USE SYCL"
14 #ifdef SYCL_DEVICE_ONLY
15 #undef SYCL_DEVICE_ONLY
16 #include <Eigen/Dense>
17 #define SYCL_DEVICE_ONLY
18 #else
19 #include <Eigen/Dense>
20 #endif
21 #else
22 #include <Eigen/Dense>
23 #endif
24#else
25 #include <Eigen/Dense>
26#endif
27#endif
28#include <alien/handlers/scalar/CSRModifierViewT.h>
29
30namespace Alien
31{
32
33 template <typename ValueT>
34 struct Block1D
35 {
36 using ValueType = ValueT ;
37
38 ValueType& operator()(std::size_t i) {
39 return m_values[i];
40 }
41
42 ValueType operator()(std::size_t i) const {
43 return m_values[i];
44 }
45 ValueType* m_values = nullptr;
46 };
47
48 template <typename ValueT>
49 struct Block2D
50 {
51 using ValueType = ValueT ;
52 Block2D(int N)
53 : m_N(N)
54 , m_buffer(N*N)
55 {
56 m_values = m_buffer.data();
57 }
58
59 Block2D(ValueType* values, int N)
60 : m_values(values)
61 , m_N(N)
62 {}
63
64 Block2D(Block2D const& rhs)
65 : m_values(rhs.m_values)
66 , m_N(rhs.m_N)
67 {}
68
69 Block2D& operator = (Block2D const& rhs) {
70 for(int i=0;i<m_N*m_N;++i)
71 m_values[i] = rhs.m_values[i] ;
72 return *this ;
73 }
74
75 Block2D& operator += (Block2D const& rhs) {
76 for(int i=0;i<m_N*m_N;++i)
77 m_values[i] += rhs.m_values[i] ;
78 return *this ;
79 }
80
81 Block2D& operator -= (Block2D const& rhs) {
82 for(int i=0;i<m_N*m_N;++i)
83 m_values[i] -= rhs.m_values[i] ;
84 return *this ;
85 }
86
87 ValueType& operator()(std::size_t i, std::size_t j) {
88 return m_values[i*m_N+j];
89 }
90
91 ValueType operator()(std::size_t i, std::size_t j) const {
92 return m_values[i*m_N+j];
93 }
94 ValueType* m_values = nullptr ;
95 int m_N = 0;
96 std::vector<ValueType> m_buffer ;
97 };
98
99 template <typename ValueT>
100 struct LU
101 {
102 public:
104 using ValueType = ValueT ;
105 using Block2DType = Block2D<ValueType> ;
106
107
108 LU(int N)
109 : A(N)
110 {
111 setZero() ;
112 }
113
114 LU inv(Block2DType const& r)
115 {
116 std::copy(r.m_values,r.m_values+r.m_N*r.m_N,A.m_values) ;
117 for (int k = 0; k < A.m_N; ++k)
118 {
119 assert(A(k,k) != 0);
120 A(k,k) = 1 / A(k,k);
121 for (int i = k + 1; i < A.m_N; ++i) {
122 A(i,k) *= A(k,k);
123 }
124 for (int i = k + 1; i < A.m_N; ++i) {
125 for (int j = k + 1; j < A.m_N; ++j) {
126 A(i,j) -= A(i,k) * A(k,j);
127 }
128 }
129 }
130 return *this ;
131 }
132
135 {
136 for (int i = 0; i < A.m_N; ++i)
137 {
138 for (int j = 0; j < i; ++j) {
139 A(i,j) = 0;
140 }
141 A(i,i) = 1;
142 for (int j = i + 1; j < A.m_N; ++j) {
143 A(i,j) = 0;
144 }
145 }
146 }
147
149 void setZero()
150 {
151 Real* ptr = A.m_values;
152 for (int i = 0; i < A.m_N * A.m_N; ++i) {
153 ptr[i] = 0;
154 }
155 }
156
157 void LSolve(Block2DType& X) const
158 {
159 for (int i = 1; i < A.m_N; ++i)
160 {
161 for (int j = 0; j < i; ++j)
162 {
163 for(int k=0;k<A.m_N;++k)
164 X(i,k) -= A(i,j) * X(j,k);
165 }
166 }
167 }
168
169 void USolve(Block2DType& X) const
170 {
171 for (int i = A.m_N - 1; i >= 0; --i) {
172 for (int j = A.m_N - 1; j > i; --j) {
173 for(int k=0;k<A.m_N;++k)
174 X(i,k) -= A(i,j) * X(j,k);
175 }
176 for(int k=0;k<A.m_N;++k)
177 X(i,k) *= A(i,i);
178 }
179 }
180
181 Block2DType solve(Block2DType const& r) const
182 {
183 Block2DType results(A.m_N) ;
184 results = r ;
185 LSolve(results);
186 USolve(results);
187 return results ;
188 }
189
190 private:
191 Block2DType A;
192 };
193
194 template<typename ValueT>
195 Block2D<ValueT> operator*(Block2D<ValueT> const& l, Block2D<ValueT> const& r)
196 {
197 auto N = l.m_N;
198 Block2D<ValueT> value{l.m_N} ;
199 for(int i=0;i<N;++i)
200 for(int j=0;j<N;++j)
201 for(int k=0;k<N;++k)
202 value(i,k) += l(i,j)*r(j,k) ;
203 return value ;
204 }
205
206
207 template<typename ValueT>
208 Block2D<ValueT> operator*(Block2D<ValueT> const& l, LU<ValueT> const& r)
209 {
210 return r.solve(l) ;
211 }
212
213template <typename MatrixT, typename VectorT>
214class LUFactorisationAlgo
215{
216 public:
217 // clang-format off
218 typedef MatrixT MatrixType;
219 typedef VectorT VectorType;
220 typedef typename MatrixType::ProfileType ProfileType ;
221 typedef typename MatrixType::ValueType ValueType;
222 typedef typename MatrixType::TagType TagType ;
223 // clang-format on
224
225 LUFactorisationAlgo()
226 {}
227
228 virtual ~LUFactorisationAlgo()
229 {}
230
231 template <typename AlgebraT>
232 void baseInit(AlgebraT& algebra, MatrixT const& matrix)
233 {
234 m_is_parallel = matrix.isParallel();
235 m_alloc_size = matrix.getAllocSize();
236 if constexpr (requires{matrix.blockSize();})
237 m_block_size = matrix.blockSize();
238 else
239 m_block_size = 1 ;
240 m_distribution = matrix.distribution();
241 m_lu_matrix.reset(matrix.cloneTo(nullptr));
242 m_profile = &m_lu_matrix->getProfile();
243 m_work.resize(m_alloc_size);
244 m_work.assign(m_work.size(), -1);
245 algebra.allocate(AlgebraT::resource(matrix), m_x);
246 }
247
248 template <typename AlgebraT>
249 void init(AlgebraT& algebra, MatrixT const& matrix)
250 {
251 baseInit(algebra, matrix);
252 if(m_block_size==1)
253 factorize(*m_lu_matrix);
254 else
255 blockFactorize(*m_lu_matrix);
256
257 m_work.clear();
258 }
259
260 void factorize(MatrixT& matrix, bool bjacobi = true)
261 {
262 /*
263 *
264 For i = 1, . . . ,N Do:
265 For k = 1, . . . , i - 1 and if (i, k) 2 NZ(A) Do:
266 Compute aik := aik/akk
267 For j = k + 1, . . . and if (i, j) 2 NZ(A), Do:
268 compute aij := aij - aik.ak,j.
269 EndFor
270 EndFor
271 EndFor
272 *
273 */
274 m_bjacobi = bjacobi;
275 CSRModifierViewT<MatrixT> modifier(matrix);
276
277 // clang-format off
278 auto nrows = modifier.nrows() ;
279 auto kcol = modifier.kcol() ;
280 auto dcol = modifier.dcol() ;
281 auto cols = modifier.cols() ;
282 auto values = modifier.data() ;
283 // clang-format on
284 if (m_is_parallel) {
285 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
286 if (m_bjacobi) {
287 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
288 {
289 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
290 {
291 int krow = cols[k];
292 ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
293 values[k] = aik;
294 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
295 m_work[cols[l]] = l;
296 for (int j = k + 1; j < kcol[krow] + local_row_size[irow]; ++j) // j=k+1->n
297 {
298 int jcol = cols[j];
299 int kj = m_work[jcol];
300 if (kj != -1) {
301 values[j] -= aik * values[kj]; // aij = aij - aik*akj
302 }
303 }
304 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
305 m_work[cols[l]] = -1;
306 }
307 }
308 }
309 else {
310 typename LUSendRecvTraits<TagType>::matrix_op_type op(matrix, m_distribution, m_work);
311 op.recvLowerNeighbLUData(values);
312 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
313 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
314 {
315 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
316 {
317 int krow = cols[k];
318 ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
319 values[k] = aik;
320 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
321 m_work[cols[l]] = l;
322 for (int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j) // j=k+1->n
323 {
324 int jcol = cols[j];
325 int kj = m_work[jcol];
326 if (kj != -1) {
327 values[j] -= aik * values[kj]; // aij = aij - aik*akj
328 }
329 }
330 for (int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j) // j=k+1->n
331 {
332 int jcol = cols[j];
333 int kj = m_work[jcol];
334 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
335 values[j] -= aik * values[kj]; // aij = aij - aik*akj
336 }
337 }
338 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
339 m_work[cols[l]] = -1;
340 }
341 }
342 op.sendUpperNeighbLUData(values);
343 }
344 }
345 else {
346 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
347 {
348 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
349 {
350 int krow = cols[k];
351 ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
352 values[k] = aik;
353 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
354 m_work[cols[l]] = l;
355 for (int j = k + 1; j < kcol[irow + 1]; ++j) // j=k+1->n
356 {
357 int jcol = cols[j];
358 int kj = m_work[jcol];
359 if (kj != -1) {
360 values[j] -= aik * values[kj]; // aij = aij - aik*akj
361 }
362 }
363 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
364 m_work[cols[l]] = -1;
365 }
366 }
367 }
368 }
369
370 void solveL(ValueType const* y, ValueType* x) const
371 {
372 CSRConstViewT<MatrixT> view(*m_lu_matrix);
373 // clang-format off
374 auto nrows = view.nrows() ;
375 auto kcol = view.kcol() ;
376 auto dcol = view.dcol() ;
377 auto cols = view.cols() ;
378 auto values = view.data() ;
379 // clang-format on
380
381 for (std::size_t irow = 0; irow < nrows; ++irow) {
382 ValueType val = y[irow];
383 for (int k = kcol[irow]; k < dcol[irow]; ++k)
384 val -= values[k] * x[cols[k]];
385 x[irow] = val;
386 }
387 }
388
389 void solveU(ValueType const* y, ValueType* x) const
390 {
391 CSRConstViewT<MatrixT> view(*m_lu_matrix);
392 // clang-format off
393 auto nrows = view.nrows() ;
394 auto kcol = view.kcol() ;
395 auto dcol = view.dcol() ;
396 auto cols = view.cols() ;
397 auto values = view.data() ;
398 // clang-format on
399 if (m_is_parallel) {
400 auto& local_row_size = m_lu_matrix->getDistStructInfo().m_local_row_size;
401 for (int irow = (int)nrows - 1; irow > -1; --irow) {
402 int dk = dcol[irow];
403 ValueType val = y[irow];
404 for (int k = dk + 1; k < kcol[irow] + local_row_size[irow]; ++k) {
405 val -= values[k] * x[cols[k]];
406 }
407 x[irow] = val / values[dk];
408 }
409 }
410 else {
411 for (int irow = (int)nrows - 1; irow > -1; --irow) {
412 int dk = dcol[irow];
413 ValueType val = y[irow];
414 for (int k = dk + 1; k < kcol[irow + 1]; ++k) {
415 val -= values[k] * x[cols[k]];
416 }
417 x[irow] = val / values[dk];
418 }
419 }
420 }
421
422#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
423 inline auto inv(Eigen::Map<Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>>const & block) const
424 {
425 assert(block.determinant()!=0) ;
426 return block.inverse() ;
427 }
428#endif
429
430 void blockFactorize(MatrixT& matrix, bool bjacobi = true)
431 {
432 /*
433 *
434 For i = 1, . . . ,N Do:
435 For k = 1, . . . , i - 1 and if (i, k) 2 NZ(A) Do:
436 Compute aik := aik/akk
437 For j = k + 1, . . . and if (i, j) 2 NZ(A), Do:
438 compute aij := aij - aik.ak,j.
439 EndFor
440 EndFor
441 EndFor
442 *
443 */
444 //if constexpr (MatrixType::on_host_only)
445 {
446#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
447 using namespace Eigen;
448 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
449 using Block2DView = Eigen::Map<Block2D> ;
450
451 int N = m_block_size;
452 int N2 = N*N;
453
454 m_bjacobi = bjacobi;
455 CSRModifierViewT<MatrixT> modifier(matrix);
456
457 // clang-format off
458 auto nrows = modifier.nrows() ;
459 auto kcol = modifier.kcol() ;
460 auto dcol = modifier.dcol() ;
461 auto cols = modifier.cols() ;
462 auto values = modifier.data() ;
463
464 Block2D aik(N,N) ;
465 // clang-format on
466 /*
467 alien_info([&] {
468 cout()<<"BLOCK FACTORIZATION : "<<m_is_parallel<<" "<<m_bjacobi;
469 });*/
470 if (m_is_parallel) {
471 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
472
473 if (m_bjacobi) {
474 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
475 {
476 /*alien_info([&] {
477 cout()<<"ROW : "<<irow<<" "<<kcol[irow]<<" "<<dcol[irow]<<" "<<kcol[irow+1]-kcol[irow]<<" "<<local_row_size[irow];
478 });*/
479 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
480 {
481 int krow = cols[k];
482 /*alien_info([&] {
483 cout()<<"\tCOL : "<<k<<" "<<cols[k]<<" "<<kcol[krow]<<" "<<local_row_size[krow];
484 });*/
485
486 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
487 //values[k] = aik;
488 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
489 Block2DView(values+k*N2,N,N) = aik ;
490 /*alien_info([&] {
491 cout()<<"\t\tVALUES["<<k<<"]=";
492 for(int i=0;i<N;++i)
493 for(int j=0;j<N;++j)
494 cout()<<"\t\t\t MAT("<<i<<","<<j<<")="<<values[k*N2+i*N+j];
495 });*/
496 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
497 m_work[cols[l]] = l;
498 for (int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j) // j=k+1->n
499 {
500 int jcol = cols[j];
501 int kj = m_work[jcol];
502 if (kj != -1) {
503 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
504 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
505 /*alien_info([&] {
506 cout()<<"\t\tVALUES["<<j<<"]=";
507 for(int ii=0;ii<N;++ii)
508 for(int jj=0;jj<N;++jj)
509 cout()<<"\t\t\t MAT("<<ii<<","<<jj<<")="<<values[j*N2+ii*N+jj];
510 });*/
511 }
512 }
513 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
514 m_work[cols[l]] = -1;
515 }
516 }
517 }
518 else {
519 typename LUSendRecvTraits<TagType>::matrix_op_type op(matrix, m_distribution, m_work);
520 op.recvLowerNeighbLUData(values);
521 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
522 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
523 {
524 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
525 {
526 int krow = cols[k];
527 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
528 //values[k] = aik;
529 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
530 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
531 m_work[cols[l]] = l;
532 for (int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j) // j=k+1->n
533 {
534 int jcol = cols[j];
535 int kj = m_work[jcol];
536 if (kj != -1) {
537 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
538 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
539 }
540 }
541 for (int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j) // j=k+1->n
542 {
543 int jcol = cols[j];
544 int kj = m_work[jcol];
545 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
546 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
547 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
548 }
549 }
550 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
551 m_work[cols[l]] = -1;
552 }
553 }
554 op.sendUpperNeighbLUData(values);
555 }
556 }
557 else {
558 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
559 {
560 /*alien_info([&] {
561 cout()<<"ROW : "<<irow<<" "<<kcol[irow]<<" "<<dcol[irow]<<" "<<kcol[irow+1]-kcol[irow];
562 });*/
563 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
564 {
565 int krow = cols[k];
566 /*alien_info([&] {
567 cout()<<"\tCOL : "<<k<<" "<<cols[k];
568 });*/
569
570 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
571 //values[k] = aik;
572 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
573 Block2DView(values+k*N2,N,N) = aik ;
574 /*alien_info([&] {
575 cout()<<"\t\tVALUES["<<k<<"]=";
576 for(int i=0;i<N;++i)
577 for(int j=0;j<N;++j)
578 cout()<<"\t\t\t MAT("<<i<<","<<j<<")="<<values[k*N2+i*N+j];
579 });*/
580
581 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
582 m_work[cols[l]] = l;
583 for (int j = k + 1; j < kcol[irow + 1]; ++j) // j=k+1->n
584 {
585 int jcol = cols[j];
586 int kj = m_work[jcol];
587 if (kj != -1) {
588 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
589 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
590 /*alien_info([&] {
591 cout()<<"\t\tVALUES["<<j<<"]=";
592 for(int ii=0;ii<N;++ii)
593 for(int jj=0;jj<N;++jj)
594 cout()<<"\t\t\t MAT("<<ii<<","<<jj<<")="<<values[j*N2+ii*N+jj];
595 });*/
596 }
597 }
598 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
599 m_work[cols[l]] = -1;
600 }
601 }
602 }
603#else
604 throw Arccore::FatalErrorException(
605 A_FUNCINFO, "Eigen is required for BlockILU factorization");
606#endif
607 }
608#if defined(EIGEN3_DISABLED)
609 else
610 {
611 using Block2DType = Block2D<ValueType> ;
612
613 int N = m_block_size;
614 int NxN = N*N;
615
616 m_bjacobi = bjacobi;
617 CSRModifierViewT<MatrixT> modifier(matrix);
618
619 // clang-format off
620 auto nrows = modifier.nrows() ;
621 auto kcol = modifier.kcol() ;
622 auto dcol = modifier.dcol() ;
623 auto cols = modifier.cols() ;
624 auto values = modifier.data() ;
625
626 Block2DType aik{N};
627 LU<ValueType> lu{N};
628 // clang-format on
629 if (m_is_parallel)
630 {
631 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
632 if (m_bjacobi) {
633 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
634 {
635 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
636 {
637 int krow = cols[k];
638 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
639 //values[k] = aik;
640 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N});
641 Block2DType{values+k*NxN,N} = aik ;
642 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
643 m_work[cols[l]] = l;
644 for (int j = k + 1; j < kcol[krow] + local_row_size[irow]; ++j) // j=k+1->n
645 {
646 int jcol = cols[j];
647 int kj = m_work[jcol];
648 if (kj != -1) {
649 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
650 Block2DType{values+j*NxN,N} -= (aik * Block2DType{values+kj*NxN,N}) ;
651 }
652 }
653 for (int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
654 m_work[cols[l]] = -1;
655 }
656 }
657 }
658 else {
659 typename LUSendRecvTraits<TagType>::matrix_op_type op(matrix, m_distribution, m_work);
660 op.recvLowerNeighbLUData(values);
661 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
662 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
663 {
664 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
665 {
666 int krow = cols[k];
667 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
668 //values[k] = aik;
669 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N}) ;
670 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
671 m_work[cols[l]] = l;
672 for (int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j) // j=k+1->n
673 {
674 int jcol = cols[j];
675 int kj = m_work[jcol];
676 if (kj != -1) {
677 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
678 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
679 }
680 }
681 for (int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j) // j=k+1->n
682 {
683 int jcol = cols[j];
684 int kj = m_work[jcol];
685 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
686 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
687 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
688 }
689 }
690 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
691 m_work[cols[l]] = -1;
692 }
693 }
694 op.sendUpperNeighbLUData(values);
695 }
696 }
697 else
698 {
699 for (std::size_t irow = 1; irow < nrows; ++irow) // i=1->nrow
700 {
701 for (int k = kcol[irow]; k < dcol[irow]; ++k) // k=1 ->i-1
702 {
703 int krow = cols[k];
704 //ValueType aik = values[k] / values[dcol[krow]]; // aik = aik/akk
705 //values[k] = aik;
706 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N}) ;
707 Block2DType{values+k*NxN,N} = aik ;
708 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
709 m_work[cols[l]] = l;
710 for (int j = k + 1; j < kcol[irow + 1]; ++j) // j=k+1->n
711 {
712 int jcol = cols[j];
713 int kj = m_work[jcol];
714 if (kj != -1) {
715 //values[j] -= aik * values[kj]; // aij = aij - aik*akj
716 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
717 }
718 }
719 for (int l = kcol[krow]; l < kcol[krow + 1]; ++l)
720 m_work[cols[l]] = -1;
721 }
722 }
723 }
724 }
725#endif
726 }
727
728 void blockSolveL(ValueType const* y, ValueType* x) const
729 {
730 if constexpr (MatrixType::on_host_only)
731 {
732#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
733 using namespace Eigen;
734 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
735 using Block2DView = Eigen::Map<Block2D> ;
736 using Block1D = Eigen::Matrix<ValueType,Dynamic,1> ;
737 using Block1DView = Eigen::Map<Block1D> ;
738
739 int N = m_block_size ;
740 int N2 = N*N;
741
742
743 Block1D val(N);
744
745 CSRConstViewT<MatrixT> view(*m_lu_matrix);
746 // clang-format off
747 auto nrows = view.nrows() ;
748 auto kcol = view.kcol() ;
749 auto dcol = view.dcol() ;
750 auto cols = view.cols() ;
751 auto values = view.data() ;
752 // clang-format on
753
754 for (std::size_t irow = 0; irow < nrows; ++irow) {
755 //ValueType val = y[irow];
756 val = Block1DView(const_cast<ValueType*>(y+irow*N),N) ;
757 for (int k = kcol[irow]; k < dcol[irow]; ++k)
758 {
759 //val -= values[k] * x[cols[k]];
760 val -= Block2DView(const_cast<ValueType*>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
761 }
762 //x[irow] = val;
763 Block1DView(x+irow*N,N) = val ;
764 }
765#endif
766 }
767 }
768
769 void blockSolveU(ValueType const* y, ValueType* x) const
770 {
771 if constexpr (MatrixType::on_host_only)
772 {
773#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
774 using namespace Eigen;
775 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
776 using Block2DView = Eigen::Map<Block2D> ;
777 using Block1D = Eigen::Matrix<ValueType,Dynamic,1> ;
778 using Block1DView = Eigen::Map<Block1D> ;
779
780 int N = m_block_size;
781 int N2 = N*N;
782
783 Block1D val(N);
784
785 CSRConstViewT<MatrixT> view(*m_lu_matrix);
786 // clang-format off
787 auto nrows = view.nrows() ;
788 auto kcol = view.kcol() ;
789 auto dcol = view.dcol() ;
790 auto cols = view.cols() ;
791 auto values = view.data() ;
792 // clang-format on
793 if (m_is_parallel) {
794 auto& local_row_size = m_lu_matrix->getDistStructInfo().m_local_row_size;
795 for (int irow = (int)nrows - 1; irow > -1; --irow) {
796 int dk = dcol[irow];
797 //ValueType val = y[irow];
798 val = Block1DView(const_cast<ValueType*>(y+irow*N),N) ;
799 for (int k = dk + 1; k < kcol[irow] + local_row_size[irow]; ++k) {
800 //val -= values[k] * x[cols[k]];
801 val -= Block2DView(const_cast<ValueType*>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
802 }
803 //x[irow] = val / values[dk];
804 Block1DView(x+irow*N,N) = inv(Block2DView(const_cast<ValueType*>(values+dk*N2),N,N)) * val;
805 }
806 }
807 else {
808 for (int irow = (int)nrows - 1; irow > -1; --irow) {
809 int dk = dcol[irow];
810 //ValueType val = y[irow];
811 val = Block1DView(const_cast<ValueType*>(y+irow*N),N) ;
812 for (int k = dk + 1; k < kcol[irow + 1]; ++k) {
813 //val -= values[k] * x[cols[k]];
814 val -= Block2DView(const_cast<ValueType*>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
815 }
816 //x[irow] = val / values[dk];
817 Block1DView(x+irow*N,N) = inv(Block2DView(const_cast<ValueType*>(values+dk*N2),N,N)) * val;
818 }
819 }
820#endif
821 }
822 }
823
824
825 template <typename AlgebraT>
826 void solve([[maybe_unused]] AlgebraT& algebra, VectorType const& y, VectorType& x) const
827 {
828 if(m_block_size==1)
829 {
831 //
832 // L.X1 = Y
833 //
834 solveL(y.data(), m_x.data());
835
837 //
838 // U.X = X1
839 //
840 solveU(m_x.data(), x.data());
841 }
842 else
843 {
845 //
846 // L.X1 = Y
847 //
848 blockSolveL(y.data(), m_x.data());
849
851 //
852 // U.X = X1
853 //
854 blockSolveU(m_x.data(), x.data());
855 }
856 }
857
858 const MatrixType& getLUMatrix() const
859 {
860 return *m_lu_matrix;
861 }
862
863 protected:
864 // clang-format off
865 std::unique_ptr<MatrixType> m_lu_matrix ;
866 int m_block_size = 1;
867 ProfileType const* m_profile = nullptr;
868 mutable VectorType m_x ;
869
870 MatrixDistribution m_distribution ;
871 std::vector<int> m_work ;
872 std::size_t m_alloc_size = 0 ;
873 bool m_is_parallel = false ;
874 bool m_bjacobi = false ;
875
876 std::vector<int> m_send_lu_ibuffer ;
877 std::vector<std::vector<ValueType>> m_send_lu_buffer ;
878 // clang-format on
879};
880
881template <typename AlgebraT>
882class ILU0Preconditioner
883{
884 public:
885 // clang-format off
886 typedef AlgebraT AlgebraType ;
887 typedef typename AlgebraType::Matrix MatrixType;
888 typedef typename AlgebraType::Vector VectorType;
889 typedef typename MatrixType::ProfileType ProfileType ;
890 typedef typename MatrixType::ValueType ValueType;
891 // clang-format on
892
894
895 ILU0Preconditioner(AlgebraType& algebra, MatrixType const& matrix, ITraceMng* trace_mng = nullptr)
896 : m_algebra(algebra)
897 , m_matrix(matrix)
898 , m_trace_mng(trace_mng)
899 {
900 }
901
902 virtual ~ILU0Preconditioner(){};
903
904 void init()
905 {
906 m_algo.init(m_algebra, m_matrix);
907 }
908
909 void solve(VectorType const& y, VectorType& x) const
910 {
911 m_algo.solve(m_algebra, y, x);
912 }
913
914 void solve(AlgebraType& algebra, VectorType const& y, VectorType& x) const
915 {
916 m_algo.solve(algebra, y, x);
917 }
918
919 void update()
920 {
921 // update value from m_matrix
922 }
923
924 private:
925 // clang-format off
926 AlgebraType& m_algebra ;
927 MatrixType const& m_matrix;
928 AlgoType m_algo ;
929
930 ITraceMng* m_trace_mng = nullptr ;
931 // clang-format on
932};
933
934} // namespace Alien
Computes a matrix distribution.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17
ValueT ValueType
Type of the blocks.
void setZero()
Set zero.
void setIdentity()
Set identity.