Arcane  4.2.2.0
Developer documentation
Loading...
Searching...
No Matches
Adapters.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/* Adapters.h (C) 2000-2026 */
9/* */
10/*---------------------------------------------------------------------------*/
11#ifndef ARCCORE_ALINA_ADAPTERS_H
12#define ARCCORE_ALINA_ADAPTERS_H
13/*---------------------------------------------------------------------------*/
14/*---------------------------------------------------------------------------*/
15
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27#include "arccore/alina/AlinaUtils.h"
28#include "arccore/alina/BuiltinBackend.h"
29#include "arccore/alina/ValueTypeInterface.h"
30#include "arccore/alina/MatrixOperationsImpl.h"
31#include "arccore/alina/CuthillMcKeeReorderer.h"
32
33#include <type_traits>
34#include <vector>
35#include <tuple>
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace Arcane::Alina::backend
41{
42
43//---------------------------------------------------------------------------
44// Specialization of matrix interface
45//---------------------------------------------------------------------------
46template <typename N, typename PRng, typename CRng, typename VRng>
47struct value_type<std::tuple<N, PRng, CRng, VRng>>
48{
49 typedef std::decay_t<decltype(std::declval<VRng>()[0])> type;
50};
51
52template <typename N, typename PRng, typename CRng, typename VRng>
53struct rows_impl<std::tuple<N, PRng, CRng, VRng>>
54{
55 static size_t get(const std::tuple<N, PRng, CRng, VRng>& A)
56 {
57 return std::get<0>(A);
58 }
59};
60
61template <typename N, typename PRng, typename CRng, typename VRng>
62struct cols_impl<std::tuple<N, PRng, CRng, VRng>>
63{
64 static size_t get(const std::tuple<N, PRng, CRng, VRng>& A)
65 {
66 return std::get<0>(A);
67 }
68};
69
70template <typename N, typename PRng, typename CRng, typename VRng>
71struct nonzeros_impl<std::tuple<N, PRng, CRng, VRng>>
72{
73 static size_t get(const std::tuple<N, PRng, CRng, VRng>& A)
74 {
75 return std::get<1>(A)[std::get<0>(A)];
76 }
77};
78
79template <typename N, typename PRng, typename CRng, typename VRng>
80struct row_iterator<std::tuple<N, PRng, CRng, VRng>>
81{
82 class type
83 {
84 public:
85
86 typedef std::decay_t<decltype(std::declval<CRng>()[0])> col_type;
87 typedef std::decay_t<decltype(std::declval<VRng>()[0])> val_type;
88
89 type(const std::tuple<N, PRng, CRng, VRng>& A, size_t row)
90 : m_col(std::begin(std::get<2>(A)))
91 , m_end(std::begin(std::get<2>(A)))
92 , m_val(std::begin(std::get<3>(A)))
93 {
94 typedef std::decay_t<decltype(std::declval<PRng>()[0])> ptr_type;
95
96 ptr_type row_begin = std::get<1>(A)[row];
97 ptr_type row_end = std::get<1>(A)[row + 1];
98
99 m_col += row_begin;
100 m_end += row_end;
101 m_val += row_begin;
102 }
103
104 operator bool() const
105 {
106 return m_col != m_end;
107 }
108
109 type& operator++()
110 {
111 ++m_col;
112 ++m_val;
113 return *this;
114 }
115
116 col_type col() const
117 {
118 return *m_col;
119 }
120
121 val_type value() const
122 {
123 return *m_val;
124 }
125
126 private:
127
128 typedef decltype(std::begin(std::declval<VRng>())) val_iterator;
129 typedef decltype(std::begin(std::declval<CRng>())) col_iterator;
130
131 col_iterator m_col;
132 col_iterator m_end;
133 val_iterator m_val;
134 };
135};
136
137template <typename N, typename PRng, typename CRng, typename VRng>
138struct row_begin_impl<std::tuple<N, PRng, CRng, VRng>>
139{
140 typedef std::tuple<N, PRng, CRng, VRng> Matrix;
141 static typename row_iterator<Matrix>::type
142 get(const Matrix& matrix, size_t row)
143 {
144 return typename row_iterator<Matrix>::type(matrix, row);
145 }
146};
147
148template <typename N, typename PRng, typename CRng, typename VRng>
149struct row_nonzeros_impl<std::tuple<N, PRng, CRng, VRng>>
150{
151 typedef std::tuple<N, PRng, CRng, VRng> Matrix;
152
153 static size_t get(const Matrix& A, size_t row)
154 {
155 return std::get<1>(A)[row + 1] - std::get<1>(A)[row];
156 }
157};
158
159template <typename N, typename PRng, typename CRng, typename VRng>
160struct ptr_data_impl<std::tuple<N, PRng, CRng, VRng>>
161{
162 typedef std::tuple<N, PRng, CRng, VRng> Matrix;
163 typedef std::decay_t<decltype(std::declval<PRng>()[0])> ptr_type;
164 typedef const ptr_type* type;
165 static type get(const Matrix& A)
166 {
167 return &std::get<1>(A)[0];
168 }
169};
170
171template <typename N, typename PRng, typename CRng, typename VRng>
172struct col_data_impl<std::tuple<N, PRng, CRng, VRng>>
173{
174 typedef std::tuple<N, PRng, CRng, VRng> Matrix;
175 typedef std::decay_t<decltype(std::declval<CRng>()[0])> col_type;
176 typedef const col_type* type;
177 static type get(const Matrix& A)
178 {
179 return &std::get<2>(A)[0];
180 }
181};
182
183template <typename N, typename PRng, typename CRng, typename VRng>
184struct val_data_impl<std::tuple<N, PRng, CRng, VRng>>
185{
186 typedef std::tuple<N, PRng, CRng, VRng> Matrix;
187 typedef std::decay_t<decltype(std::declval<VRng>()[0])> val_type;
188 typedef const val_type* type;
189 static type get(const Matrix& A)
190 {
191 return &std::get<3>(A)[0];
192 }
193};
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
198} // namespace Arcane::Alina::backend
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203namespace Arcane::Alina::adapter
204{
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
209template <class Matrix, class BlockType>
210struct block_matrix_adapter
211{
212 typedef BlockType value_type;
213 static const int BlockSize = math::static_rows<BlockType>::value;
214
215 const Matrix& A;
216
217 block_matrix_adapter(const Matrix& A)
218 : A(A)
219 {
220 precondition(
221 backend::nbRow(A) % BlockSize == 0 &&
222 backend::nbColumn(A) % BlockSize == 0,
223 "Matrix size is not divisible by block size!");
224 }
225
226 size_t rows() const
227 {
228 return backend::nbRow(A) / BlockSize;
229 }
230
231 size_t cols() const
232 {
233 return backend::nbColumn(A) / BlockSize;
234 }
235
236 size_t nonzeros() const
237 {
238 // Just an estimate:
239 return backend::nonzeros(A) / (BlockSize * BlockSize);
240 }
241
242 struct row_iterator
243 {
244 typedef typename backend::row_iterator<Matrix>::type Base;
245 typedef ptrdiff_t col_type;
246 typedef BlockType val_type;
247
248 std::array<char, sizeof(Base) * BlockSize> buf;
249 Base* base;
250
251 bool done;
252 col_type cur_col;
253 val_type cur_val;
254
255 row_iterator(const Matrix& A, col_type row)
256 : done(true)
257 {
258 base = reinterpret_cast<Base*>(buf.data());
259 for (int i = 0; i < BlockSize; ++i) {
260 new (base + i) Base(backend::row_begin(A, row * BlockSize + i));
261
262 if (base[i]) {
263 col_type col = base[i].col() / BlockSize;
264 if (done) {
265 cur_col = col;
266 done = false;
267 }
268 else {
269 cur_col = std::min<col_type>(cur_col, col);
270 }
271 }
272 }
273
274 if (done)
275 return;
276
277 // While we are gathering the current value,
278 // base iteratirs are advanced to the next block-column.
279 cur_val = math::zero<val_type>();
280 col_type end = (cur_col + 1) * BlockSize;
281 for (int i = 0; i < BlockSize; ++i) {
282 for (; base[i] && static_cast<ptrdiff_t>(base[i].col()) < end; ++base[i]) {
283 cur_val(i, base[i].col() % BlockSize) = base[i].value();
284 }
285 }
286 }
287
288 ~row_iterator()
289 {
290 for (int i = 0; i < BlockSize; ++i)
291 base[i].~Base();
292 }
293
294 operator bool() const
295 {
296 return !done;
297 }
298
299 row_iterator& operator++()
300 {
301 // Base iterators are already at the next block-column.
302 // We just need to gather the current column and value.
303 done = true;
304
305 col_type end = (cur_col + 1) * BlockSize;
306 for (int i = 0; i < BlockSize; ++i) {
307 if (base[i]) {
308 col_type col = base[i].col() / BlockSize;
309 if (done) {
310 cur_col = col;
311 done = false;
312 }
313 else {
314 cur_col = std::min<col_type>(cur_col, col);
315 }
316 }
317 }
318
319 if (done)
320 return *this;
321
322 cur_val = math::zero<val_type>();
323 end = (cur_col + 1) * BlockSize;
324 for (int i = 0; i < BlockSize; ++i) {
325 for (; base[i] && static_cast<ptrdiff_t>(base[i].col()) < end; ++base[i]) {
326 cur_val(i, base[i].col() % BlockSize) = base[i].value();
327 }
328 }
329
330 return *this;
331 }
332
333 col_type col() const
334 {
335 return cur_col;
336 }
337
338 val_type value() const
339 {
340 return cur_val;
341 }
342 };
343
344 row_iterator row_begin(size_t i) const
345 {
346 return row_iterator(A, i);
347 }
348};
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
354template <class BlockType, class Matrix>
355block_matrix_adapter<Matrix, BlockType> block_matrix(const Matrix& A)
356{
357 return block_matrix_adapter<Matrix, BlockType>(A);
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
363template <class Matrix>
364std::shared_ptr<CSRMatrix<typename math::element_of<
365 typename backend::value_type<Matrix>::type>::type,
366 typename backend::col_type<Matrix>::type,
367 typename backend::ptr_type<Matrix>::type>>
368unblock_matrix(const Matrix& B)
369{
370 typedef typename backend::value_type<Matrix>::type Block;
371 typedef typename math::element_of<Block>::type Scalar;
372 typedef typename backend::col_type<Matrix>::type Col;
373 typedef typename backend::ptr_type<Matrix>::type Ptr;
374
375 const int brows = math::static_rows<Block>::value;
376 const int bcols = math::static_cols<Block>::value;
377
378 static_assert(brows > 1 || bcols > 1, "Can not unblock scalar matrix!");
379
380 auto A = std::make_shared<CSRMatrix<Scalar, Col, Ptr>>();
381
382 A->set_size(backend::nbRow(B) * brows, backend::nbColumn(B) * bcols);
383 A->ptr[0] = 0;
384
385 const ptrdiff_t nb = backend::nbRow(B);
386
387 arccoreParallelFor(0, nb, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
388 for (ptrdiff_t ib = begin; ib < (begin + size); ++ib) {
389 auto w = backend::row_nonzeros(B, ib);
390 for (ptrdiff_t i = 0, ia = ib * brows; i < brows; ++i, ++ia) {
391 A->ptr[ia + 1] = w * bcols;
392 }
393 }
394 });
395
396 A->scan_row_sizes();
397 A->set_nonzeros();
398
399 arccoreParallelFor(0, nb, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
400 for (ptrdiff_t ib = begin; ib < (begin + size); ++ib) {
401 for (auto b = backend::row_begin(B, ib); b; ++b) {
402 auto c = b.col();
403 auto v = b.value();
404
405 for (ptrdiff_t i = 0, ia = ib * brows; i < brows; ++i, ++ia) {
406 auto row_head = A->ptr[ia];
407 for (int j = 0; j < bcols; ++j) {
408 A->col[row_head] = c * bcols + j;
409 A->val[row_head] = v(i, j);
410 ++row_head;
411 }
412 A->ptr[ia] = row_head;
413 }
414 }
415 }
416 });
417
418 std::rotate(A->ptr.data(), A->ptr.data() + A->nbRow(), A->ptr.data() + A->nbRow() + 1);
419 A->ptr[0] = 0;
420
421 return A;
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427template <class Matrix>
428struct complex_adapter
429{
431 "value type should be complex");
432
434
435 const Matrix& A;
436
437 complex_adapter(const Matrix& A)
438 : A(A)
439 {}
440
441 size_t rows() const
442 {
443 return 2 * backend::nbRow(A);
444 }
445
446 size_t cols() const
447 {
448 return 2 * backend::nbColumn(A);
449 }
450
451 size_t nonzeros() const
452 {
453 return 4 * backend::nonzeros(A);
454 }
455
456 struct row_iterator
457 {
458 typedef typename backend::row_iterator<Matrix>::type Base;
459 typedef typename Base::col_type col_type;
460
461 row_iterator(const Base& base, bool row_real)
462 : base(base)
463 , row_real(row_real)
464 , col_real(true)
465 {}
466
467 operator bool() const
468 {
469 return static_cast<bool>(base);
470 }
471
472 row_iterator& operator++()
473 {
474 col_real = !col_real;
475 if (col_real)
476 ++base;
477
478 return *this;
479 }
480
481 col_type col() const
482 {
483 if (col_real)
484 return base.col() * 2;
485 else
486 return base.col() * 2 + 1;
487 }
488
489 value_type value() const
490 {
491 if (row_real) {
492 if (col_real)
493 return std::real(base.value());
494 else
495 return -std::imag(base.value());
496 }
497 else {
498 if (col_real)
499 return std::imag(base.value());
500 else
501 return std::real(base.value());
502 }
503 }
504
505 private:
506
507 Base base;
508 bool row_real;
509 bool col_real;
510 };
511
512 row_iterator row_begin(size_t i) const
513 {
514 return row_iterator(backend::row_begin(A, i / 2), i % 2 == 0);
515 }
516};
517
518template <class Matrix>
519complex_adapter<Matrix> complex_matrix(const Matrix& A)
520{
521 return complex_adapter<Matrix>(A);
522}
523
524template <class DataType, class Range>
525auto complex_range(Range& rng) -> Span<DataType>
526{
527 DataType* b = reinterpret_cast<DataType*>(&rng[0]);
528 size_t s = 2 * std::size(rng);
529
530 return Span<DataType>(b, s);
531}
532
533/*---------------------------------------------------------------------------*/
534/*---------------------------------------------------------------------------*/
540template <class RowBuilder>
541struct matrix_builder
542{
543 typedef typename RowBuilder::val_type value_type;
544 typedef typename RowBuilder::col_type col_type;
545
546 RowBuilder build_row;
547
548 matrix_builder(const RowBuilder& row_builder)
549 : build_row(row_builder)
550 {}
551
552 size_t rows() const { return build_row.rows(); }
553 size_t cols() const { return build_row.rows(); }
554 size_t nonzeros() const { return build_row.nonzeros(); }
555
556 struct row_iterator
557 {
558 typedef RowBuilder::col_type col_type;
559 typedef RowBuilder::val_type val_type;
560
561 typedef std::vector<col_type>::const_iterator col_iterator;
562 typedef std::vector<val_type>::const_iterator val_iterator;
563
564 row_iterator(const RowBuilder& build_row, size_t i)
565 : ptr(0)
566 {
567 build_row(i, m_col, m_val);
568 }
569
570 operator bool() const
571 {
572 return m_col.size() - ptr;
573 }
574
575 row_iterator& operator++()
576 {
577 ++ptr;
578 return *this;
579 }
580
581 col_type col() const
582 {
583 return m_col[ptr];
584 }
585
586 val_type value() const
587 {
588 return m_val[ptr];
589 }
590
591 private:
592
593 int ptr;
594 std::vector<col_type> m_col;
595 std::vector<value_type> m_val;
596 };
597
598 row_iterator row_begin(size_t i) const
599 {
600 return row_iterator(build_row, i);
601 }
602};
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
608template <class RowBuilder>
609matrix_builder<RowBuilder> make_matrix(const RowBuilder& row_builder)
610{
611 return matrix_builder<RowBuilder>(row_builder);
612}
613
614/*---------------------------------------------------------------------------*/
615/*---------------------------------------------------------------------------*/
616
617template <class Matrix>
618struct reordered_matrix
619{
620 typedef backend::value_type<Matrix>::type value_type;
621 typedef backend::row_iterator<Matrix>::type base_iterator;
622
623 const Matrix& A;
624 const ptrdiff_t* perm;
625 const ptrdiff_t* iperm;
626
627 reordered_matrix(const Matrix& A, const ptrdiff_t* perm, const ptrdiff_t* iperm)
628 : A(A)
629 , perm(perm)
630 , iperm(iperm)
631 {}
632
633 size_t rows() const
634 {
635 return backend::nbRow(A);
636 }
637
638 size_t cols() const
639 {
640 return backend::nbColumn(A);
641 }
642
643 size_t nonzeros() const
644 {
645 return backend::nonzeros(A);
646 }
647
648 struct row_iterator
649 {
650 base_iterator base;
651 const ptrdiff_t* iperm;
652
653 row_iterator(const base_iterator& base, const ptrdiff_t* iperm)
654 : base(base)
655 , iperm(iperm)
656 {}
657
658 operator bool() const
659 {
660 return base;
661 }
662
663 row_iterator& operator++()
664 {
665 ++base;
666 return *this;
667 }
668
669 ptrdiff_t col() const
670 {
671 return iperm[base.col()];
672 }
673
674 value_type value() const
675 {
676 return base.value();
677 }
678 };
679
680 row_iterator row_begin(size_t i) const
681 {
682 return row_iterator(backend::row_begin(A, perm[i]), iperm);
683 }
684};
685
686/*---------------------------------------------------------------------------*/
687/*---------------------------------------------------------------------------*/
696template <class BaseIterator>
697class permutation_iterator
698{
699 public:
700
701 typedef std::random_access_iterator_tag iterator_category;
702 typedef typename std::iterator_traits<BaseIterator>::value_type value_type;
703 typedef typename std::iterator_traits<BaseIterator>::difference_type difference_type;
704 typedef typename std::iterator_traits<BaseIterator>::reference reference;
705 typedef value_type* pointer;
706
707 permutation_iterator()
708 : m_base()
709 , m_perm(nullptr)
710 {}
711
712 permutation_iterator(BaseIterator base, const ptrdiff_t* perm)
713 : m_base(base)
714 , m_perm(perm)
715 {}
716
717 reference operator*() const
718 {
719 return m_base[*m_perm];
720 }
721
722 reference operator[](difference_type i) const
723 {
724 return m_base[m_perm[i]];
725 }
726
727 permutation_iterator& operator++()
728 {
729 ++m_perm;
730 return *this;
731 }
732
733 permutation_iterator operator++(int)
734 {
735 permutation_iterator tmp(*this);
736 ++m_perm;
737 return tmp;
738 }
739
740 permutation_iterator& operator--()
741 {
742 --m_perm;
743 return *this;
744 }
745
746 permutation_iterator operator--(int)
747 {
748 permutation_iterator tmp(*this);
749 --m_perm;
750 return tmp;
751 }
752
753 permutation_iterator& operator+=(difference_type n)
754 {
755 m_perm += n;
756 return *this;
757 }
758
759 permutation_iterator& operator-=(difference_type n)
760 {
761 m_perm -= n;
762 return *this;
763 }
764
765 friend permutation_iterator operator+(permutation_iterator it, difference_type n)
766 {
767 it += n;
768 return it;
769 }
770
771 friend permutation_iterator operator+(difference_type n, permutation_iterator it)
772 {
773 it += n;
774 return it;
775 }
776
777 friend permutation_iterator operator-(permutation_iterator it, difference_type n)
778 {
779 it -= n;
780 return it;
781 }
782
783 friend difference_type operator-(const permutation_iterator& a, const permutation_iterator& b)
784 {
785 return a.m_perm - b.m_perm;
786 }
787
788 friend bool operator==(const permutation_iterator& a, const permutation_iterator& b)
789 {
790 return a.m_perm == b.m_perm;
791 }
792
793 friend bool operator!=(const permutation_iterator& a, const permutation_iterator& b)
794 {
795 return a.m_perm != b.m_perm;
796 }
797
798 friend bool operator<(const permutation_iterator& a, const permutation_iterator& b)
799 {
800 return a.m_perm < b.m_perm;
801 }
802
803 friend bool operator<=(const permutation_iterator& a, const permutation_iterator& b)
804 {
805 return a.m_perm <= b.m_perm;
806 }
807
808 friend bool operator>(const permutation_iterator& a, const permutation_iterator& b)
809 {
810 return a.m_perm > b.m_perm;
811 }
812
813 friend bool operator>=(const permutation_iterator& a, const permutation_iterator& b)
814 {
815 return a.m_perm >= b.m_perm;
816 }
817
818 private:
819
820 BaseIterator m_base;
821 const ptrdiff_t* m_perm;
822};
823
824/*---------------------------------------------------------------------------*/
825/*---------------------------------------------------------------------------*/
826
827template <class Vector>
828struct reordered_vector
829{
830 typedef backend::value_type<std::decay_t<Vector>>::type raw_value_type;
831 typedef std::conditional_t<std::is_const_v<Vector>, const raw_value_type, raw_value_type> value_type;
832
833 Vector& x;
834 const ptrdiff_t* perm;
835
836 reordered_vector(Vector& x, const ptrdiff_t* perm)
837 : x(x)
838 , perm(perm)
839 {}
840
841 size_t size() const
842 {
843 return std::size(x);
844 }
845
846 value_type& operator[](size_t i) const
847 {
848 return x[perm[i]];
849 }
850
852 begin()
853 {
855 }
856
858 begin() const
859 {
861 }
862
864 end()
865 {
866 return permutation_iterator<typename std::decay_t<Vector>::iterator>(std::begin(x), perm + size());
867 }
868
870 end() const
871 {
872 return permutation_iterator<typename std::decay_t<Vector>::const_iterator>(std::begin(x), perm + size());
873 }
874};
875
876/*---------------------------------------------------------------------------*/
877/*---------------------------------------------------------------------------*/
878
879template <class ordering = CuthillMcKeeReorderer<false>>
880class reorder
881{
882 public:
883
884 template <class Matrix>
885 explicit reorder(const Matrix& A)
886 : n(backend::nbRow(A))
887 , perm(n)
888 , iperm(n)
889 {
890 ordering::get(A, perm);
891 arccoreParallelFor(0, n, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
892 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
893 iperm[perm[i]] = i;
894 }
895 });
896 }
897
898 template <class Matrix>
899 std::enable_if_t<!backend::is_builtin_vector<Matrix>::value, reordered_matrix<Matrix>>
900 operator()(const Matrix& A) const
901 {
902 return reordered_matrix<Matrix>(A, perm.data(), iperm.data());
903 }
904
905 template <class Vector>
906 std::enable_if_t<backend::is_builtin_vector<Vector>::value, reordered_vector<Vector>>
907 operator()(Vector& x) const
908 {
909 return reordered_vector<Vector>(x, perm.data());
910 }
911
912 template <class Vector>
913 std::enable_if_t<backend::is_builtin_vector<Vector>::value, reordered_vector<const Vector>>
914 operator()(const Vector& x) const
915 {
916 return reordered_vector<const Vector>(x, perm.data());
917 }
918
919 template <class Vector1, class Vector2>
920 void forward(const Vector1& x, Vector2& y) const
921 {
922 arccoreParallelFor(0, n, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
923 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
924 y[i] = x[perm[i]];
925 }
926 });
927 }
928
929 template <class Vector1, class Vector2>
930 void inverse(const Vector1& x, Vector2& y) const
931 {
932 arccoreParallelFor(0, n, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
933 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
934 y[perm[i]] = x[i];
935 }
936 });
937 }
938
939 private:
940
941 ptrdiff_t n;
942 numa_vector<ptrdiff_t> perm, iperm;
943};
944
945/*---------------------------------------------------------------------------*/
946/*---------------------------------------------------------------------------*/
947
948template <class Matrix, class Scale>
949struct scaled_matrix
950{
951 typedef typename backend::value_type<Matrix>::type value_type;
952 typedef typename backend::value_type<Scale>::type scale_type;
953
954 const Matrix& A;
955 const Scale& s;
956
957 scaled_matrix(const Matrix& A, const Scale& s)
958 : A(A)
959 , s(s)
960 {}
961
962 size_t rows() const { return backend::nbRow(A); }
963 size_t cols() const { return backend::nbColumn(A); }
964 size_t nonzeros() const { return backend::nonzeros(A); }
965
966 struct row_iterator : public backend::row_iterator<Matrix>::type
967 {
968 typedef typename backend::row_iterator<Matrix>::type Base;
969
970 scale_type si;
971 const Scale& s;
972
973 row_iterator(const Matrix& A, const Scale& s, size_t i)
974 : Base(A, i)
975 , si(s[i])
976 , s(s)
977 {}
978
979 value_type value() const
980 {
981 return si * static_cast<const Base*>(this)->value() * s[this->col()];
982 }
983 };
984
985 row_iterator row_begin(size_t i) const
986 {
987 return row_iterator(A, s, i);
988 }
989};
990
991/*---------------------------------------------------------------------------*/
992/*---------------------------------------------------------------------------*/
993
994template <class Backend, class Scale>
995struct scaled_problem
996{
997 typedef typename Backend::params backend_params;
998
999 const std::shared_ptr<Scale> s;
1000 const backend_params& bprm;
1001
1002 scaled_problem(std::shared_ptr<Scale> s, const backend_params& bprm = backend_params())
1003 : s(s)
1004 , bprm(bprm)
1005 {}
1006
1007 template <class Matrix>
1008 scaled_matrix<Matrix, Scale> matrix(const Matrix& A) const
1009 {
1010 return scaled_matrix<Matrix, Scale>(A, *s);
1011 }
1012
1013 template <class Vector>
1014 std::shared_ptr<typename Backend::vector> rhs(const Vector& v) const
1015 {
1016 auto t = Backend::copy_vector(v, bprm);
1017 (*this)(*t);
1018 return t;
1019 }
1020
1021 template <class Vector>
1022 void operator()(Vector& x) const
1023 {
1024 typedef typename backend::value_type<Vector>::type value_type;
1025 typedef typename math::scalar_of<value_type>::type scalar_type;
1026
1027 const auto one = math::identity<scalar_type>();
1028 const auto zero = math::zero<scalar_type>();
1029
1031 backend::vmul(one, *s, x, zero, x);
1032 }
1033 else {
1034 backend::vmul(one, *Backend::copy_vector(*s, bprm), x, zero, x);
1035 }
1036 }
1037};
1038
1039/*---------------------------------------------------------------------------*/
1040/*---------------------------------------------------------------------------*/
1041
1042template <class Backend, class Matrix>
1043scaled_problem<Backend,
1044 std::vector<
1045 typename math::scalar_of<
1046 typename backend::value_type<Matrix>::type>::type>>
1047scale_diagonal(const Matrix& A,
1048 const typename Backend::params& bprm = typename Backend::params())
1049{
1050 typedef typename backend::value_type<Matrix>::type value_type;
1051 typedef typename math::scalar_of<value_type>::type scalar_type;
1052 ptrdiff_t n = backend::nbRow(A);
1053 auto s = std::make_shared<std::vector<scalar_type>>(n);
1054
1055 arccoreParallelFor(0, n, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
1056 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
1057 for (auto a = backend::row_begin(A, i); a; ++a) {
1058 if (a.col() == i) {
1059 (*s)[i] = math::inverse(sqrt(math::norm(a.value())));
1060 break;
1061 }
1062 }
1063 }
1064 });
1065
1067}
1068
1069/*---------------------------------------------------------------------------*/
1070/*---------------------------------------------------------------------------*/
1071
1072template <typename Ptr, typename Col, typename Val>
1073std::shared_ptr<CSRMatrix<Val>>
1074zero_copy(size_t nrows, size_t ncols, Ptr* ptr, Col* col, Val* val)
1075{
1076 // Check that Ptr and Col types are binary-compatible with ptrdiff_t:
1077 static_assert(std::is_integral_v<Ptr>, "Unsupported Ptr type");
1078 static_assert(std::is_integral_v<Col>, "Unsupported Col type");
1079 static_assert(sizeof(Ptr) == sizeof(Int32), "Unsupported Ptr type");
1080 static_assert(sizeof(Col) == sizeof(Int32), "Unsupported Col type");
1081
1082 auto A = std::make_shared<CSRMatrix<Val>>();
1083 A->setNbRow(nrows);
1084 A->ncols = ncols;
1085 A->setNbNonZero(nrows ? ptr[nrows] : 0);
1086
1087 A->ptr.setPointerZeroCopy(ptr);
1088 A->col.setPointerZeroCopy(col);
1089 A->val.setPointerZeroCopy(val);
1090
1091 A->own_data = false;
1092
1093 return A;
1094}
1095
1096/*---------------------------------------------------------------------------*/
1097/*---------------------------------------------------------------------------*/
1098
1099template <typename Ptr, typename Col, typename Val>
1100std::shared_ptr<CSRMatrix<Val>>
1101zero_copy(size_t n, Ptr* ptr, Col* col, Val* val)
1102{
1103 return zero_copy(n, n, ptr, col, val);
1104}
1105
1106/*---------------------------------------------------------------------------*/
1107/*---------------------------------------------------------------------------*/
1108
1109template <typename Ptr, typename Col, typename Val>
1110std::shared_ptr<CSRMatrix<Val, Col, Ptr>>
1111zero_copy_direct(size_t nrows, size_t ncols, Ptr* ptr, Col* col, Val* val)
1112{
1113 auto A = std::make_shared<CSRMatrix<Val, Col, Ptr>>();
1114 A->setNbRow(nrows);
1115 A->ncols = ncols;
1116 A->setNbNonZero(nrows ? ptr[nrows] : 0);
1117
1118 A->ptr.setPointerZeroCopy(const_cast<Ptr*>(ptr));
1119 A->col.setPointerZeroCopy(const_cast<Col*>(col));
1120 A->val.setPointerZeroCopy(const_cast<Val*>(val));
1121
1122 A->own_data = false;
1123
1124 return A;
1125}
1126
1127/*---------------------------------------------------------------------------*/
1128/*---------------------------------------------------------------------------*/
1129
1130template <typename Ptr, typename Col, typename Val>
1131std::shared_ptr<CSRMatrix<Val, Col, Ptr>>
1132zero_copy_direct(size_t n, Ptr* ptr, Col* col, Val* val)
1133{
1134 return zero_copy_direct(n, n, ptr, col, val);
1135}
1136
1137/*---------------------------------------------------------------------------*/
1138/*---------------------------------------------------------------------------*/
1139
1140} // namespace Arcane::Alina::adapter
1141
1142/*---------------------------------------------------------------------------*/
1143/*---------------------------------------------------------------------------*/
1144
1145namespace Arcane::Alina::backend
1146{
1147template <class Vector>
1148struct is_builtin_vector<adapter::reordered_vector<Vector>>
1149: is_builtin_vector<typename std::decay<Vector>::type>
1150{};
1151} // namespace Arcane::Alina::backend
1152
1153namespace Arcane::Alina::backend::detail
1154{
1155
1156template <class Matrix, class BlockType>
1157struct use_builtin_matrix_ops<adapter::block_matrix_adapter<Matrix, BlockType>>
1158: std::true_type
1159{};
1160
1161template <class Matrix>
1163: std::true_type
1164{};
1165
1166template <class RowBuilder>
1168: std::true_type
1169{};
1170
1171template <typename N, typename PRng, typename CRng, typename VRng>
1172struct use_builtin_matrix_ops<std::tuple<N, PRng, CRng, VRng>>
1173: std::true_type
1174{};
1175
1176template <class Matrix>
1177struct use_builtin_matrix_ops<adapter::reordered_matrix<Matrix>>
1178: std::true_type
1179{};
1180
1181/*---------------------------------------------------------------------------*/
1182/*---------------------------------------------------------------------------*/
1183
1184} // namespace Arcane::Alina::backend::detail
1185
1186/*---------------------------------------------------------------------------*/
1187/*---------------------------------------------------------------------------*/
1188
1189#endif
Random-access iterator over a sequence viewed through a permutation.
Definition Adapters.h:698
NUMA-aware vector container.
Definition NumaVector.h:42
Loop execution information.
Matrix class, to be used by user.
View of an array of elements of type T.
Definition Span.h:633
Class managing a 2-dimensional vector of type T.
Definition Vector2.h:38
Vector class, to be used by user.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue, IndexType_ > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applies the lambda function lambda_function concurrently over the iteration interval given by loop_ra...
Definition ParallelFor.h:86
std::int32_t Int32
Signed integer type of 32 bits.
Generates matrix rows as needed with help of user-provided functor.
Definition Adapters.h:542
Implementation for function returning the number of columns in a matrix.
Implementation for function returning the number of nonzeros in a matrix.
Metafunction that returns pointer type of a matrix.
Implementation for function returning row iterator for a matrix.
Metafunction returning the row iterator type for a matrix type.
Implementation for function returning the number of nonzeros in a matrix row.
Implementation for function returning the number of rows in a matrix.
Metafunction that returns value type of a matrix or a vector type.
Scalar type of a non-scalar type.
Number of rows for statically sized matrix types.