Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SolverUtils.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/* SolverUtils.h (C) 2000-2026 */
9/* */
10/* Utility functions for solver classes. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_SOLVERUTILS_H
13#define ARCCORE_ALINA_SOLVERUTILS_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 "arccore/alina/ValueTypeInterface.h"
27
28#include <iostream>
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Alina
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39enum class ePreconditionerSideType
40{
41 left,
42 right
43};
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48inline std::ostream& operator<<(std::ostream& os, ePreconditionerSideType p)
49{
50 switch (p) {
51 case ePreconditionerSideType::left:
52 return os << "left";
53 case ePreconditionerSideType::right:
54 return os << "right";
55 default:
56 return os << "???";
57 }
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63inline std::istream& operator>>(std::istream& in, ePreconditionerSideType& p)
64{
65 std::string val;
66 in >> val;
67
68 if (val == "left")
69 p = ePreconditionerSideType::left;
70 else if (val == "right")
71 p = ePreconditionerSideType::right;
72 else
73 throw std::invalid_argument("Invalid preconditioning side. "
74 "Valid choices are: left, right.");
75
76 return in;
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
83template <class Precond, class Matrix, class VecF, class VecX, class VecT> void
84preconditioner_spmv(ePreconditionerSideType pside, const Precond& P, const Matrix& A,
85 const VecF& F, VecX& X, VecT& T)
86{
87 typedef typename backend::value_type<Matrix>::type value;
88 typedef typename math::scalar_of<value>::type scalar;
89
90 static const scalar one = math::identity<scalar>();
91 static const scalar zero = math::zero<scalar>();
92
93 if (pside == ePreconditionerSideType::left) {
94 backend::spmv(one, A, F, zero, T);
95 P.apply(T, X);
96 }
97 else {
98 P.apply(F, T);
99 backend::spmv(one, A, T, zero, X);
100 }
101}
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106} // namespace Arcane::Alina
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
111namespace Arcane::Alina::detail
112{
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
122{
123 template <class Vec1, class Vec2>
125 operator()(const Vec1& x, const Vec2& y) const
126 {
127 return backend::inner_product(x, y);
128 }
129
130 int rank() const
131 {
132 return 0;
133 }
134};
135
137template <class T>
138void generate_plane_rotation(T dx, T dy, T& cs, T& sn)
139{
140 if (math::is_zero(dy)) {
141 cs = 1;
142 sn = 0;
143 }
144 else if (std::abs(dy) > std::abs(dx)) {
145 T tmp = dx / dy;
146 sn = math::inverse(sqrt(math::identity<T>() + tmp * tmp));
147 cs = tmp * sn;
148 }
149 else {
150 T tmp = dy / dx;
151 cs = math::inverse(sqrt(math::identity<T>() + tmp * tmp));
152 sn = tmp * cs;
153 }
154}
155
156template <class T>
157void apply_plane_rotation(T& dx, T& dy, T cs, T sn)
158{
159 T tmp = math::adjoint(cs) * dx + math::adjoint(sn) * dy;
160 dy = -sn * dx + cs * dy;
161 dx = tmp;
162}
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167} // namespace Arcane::Alina::detail
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172#endif
Default inner product getter for iterative solvers.
Default implementation for inner product.