Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DenseMatrixInverseImpl.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/* DenseMatrixInverseImpl.h (C) 2000-2026 */
9/* */
10/* Compute the inverse of a dense matrix. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_DENSEMATRIXINVERSEIMPL_H
13#define ARCCORE_ALINA_DENSEMATRIXINVERSEIMPL_H
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#include <algorithm>
27#include <cassert>
28#include <numeric>
29#include "arccore/alina/AlinaUtils.h"
30#include "arccore/alina/ValueTypeInterface.h"
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane::Alina::detail
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
43template <typename value_type> static void
44inverse(int n, value_type* A, value_type* t, int* p)
45{
46 std::iota(p, p + n, 0);
47
48 // Perform LU-factorization of A in-place
49 for (int col = 0; col < n; ++col) {
50 // Find pivot element
51 int pivot_i = col;
52 using mag_type = typename math::scalar_of<value_type>::type;
53 mag_type pivot_mag = math::zero<mag_type>();
54 for (int i = col; i < n; ++i) {
55 int row = p[i];
56 mag_type mag = math::norm(A[row * n + col]);
57 if (mag > pivot_mag) {
58 pivot_mag = mag;
59 pivot_i = i;
60 }
61 }
62 std::swap(p[col], p[pivot_i]);
63 int pivot_row = p[col];
64 // We have found pivot element, perform Gauss elimination
65 value_type d = math::inverse(A[pivot_row * n + col]);
66 assert(!math::is_zero(d));
67 for (int i = col + 1; i < n; ++i) {
68 int row = p[i];
69 A[row * n + col] *= d;
70 for (int j = col + 1; j < n; ++j)
71 A[row * n + j] -= A[row * n + col] * A[pivot_row * n + j];
72 }
73 A[pivot_row * n + col] = d;
74 }
75
76 // Invert identity matrix in-place to get the solution.
77 for (int k = 0; k < n; ++k) {
78 // Lower triangular solve:
79 for (int i = 0; i < n; ++i) {
80 int row = p[i];
81 value_type b = (row == k) ? math::identity<value_type>() : math::zero<value_type>();
82 for (int j = 0; j < i; ++j)
83 b -= A[row * n + j] * t[j * n + k];
84 t[i * n + k] = b;
85 }
86
87 // Upper triangular solve:
88 for (int i = n; i-- > 0;) {
89 int row = p[i];
90 for (int j = i + 1; j < n; ++j)
91 t[i * n + k] -= A[row * n + j] * t[j * n + k];
92 t[i * n + k] *= A[row * n + i];
93 }
94 }
95
96 std::copy(t, t + n * n, A);
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102} // namespace Arcane::Alina::detail
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107#endif