Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
linSolver.h
1/******************************************************************************
2 * Copyright (C) 2007-2024 by the GIMLi development team *
3 * Carsten Ruecker carsten@resistivity.net *
4 * *
5 * Licensed under the Apache License, Version 2.0 (the "License"); *
6 * you may not use this file except in compliance with the License. *
7 * You may obtain a copy of the License at *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 * See the License for the specific language governing permissions and *
15 * limitations under the License. *
16 * *
17 ******************************************************************************/
18
19#ifndef _GIMLI_LINSOLVER__H
20#define _GIMLI_LINSOLVER__H
21
22#include "gimli.h"
23#include "solverWrapper.h"
24#include <cmath>
25#include <map>
26
27namespace GIMLI{
28
29class SolverWrapper;
30
31enum SolverType{AUTOMATIC,LDL,CHOLMOD,UMFPACK,UNKNOWN};
32
33
34class DLLEXPORT LinSolver : public SolverWrapper{
35public:
36 LinSolver(bool verbose=false);
37
38 LinSolver(RSparseMatrix & S, bool verbose=false);
39
40 LinSolver(RSparseMapMatrix & S, bool verbose=false);
41
42 LinSolver(CSparseMatrix & S, bool verbose=false);
43
44 LinSolver(RSparseMatrix & S, SolverType solverType, bool verbose=false);
45
46 LinSolver(CSparseMatrix & S, SolverType solverType, bool verbose=false);
47
48 ~LinSolver();
49
50 RVector operator()(const RVector & rhs);
51 CVector operator()(const CVector & rhs);
52
53 void solve(const RVector & rhs, RVector & solution);
54 void solve(const CVector & rhs, CVector & solution);
55
56 RVector solve(const RVector & rhs);
57 CVector solve(const CVector & rhs);
58
59 void setSolverType(SolverType solverType=AUTOMATIC);
60
61 // void setSolver(const std::string & name);
62
64 void setMatrix(RSparseMatrix & S, int stype=-2);
65
67 void setMatrix(CSparseMatrix & S, int stype=-2);
68
69 SolverType solverType() const { return solverType_; }
70
71 std::string solverName() const;
72
73 std::string name() const { return solverName(); }
74
75protected:
76 void init_();
77
78 void initialize_(RSparseMatrix & S, int stype);
79 void initialize_(CSparseMatrix & S, int stype);
80
81 MatrixBase * cacheMatrix_;
82 SolverType solverType_;
83 SolverWrapper * solver_;
84
85 uint rows_;
86 uint cols_;
87};
88
89template < class Mat, class Vec > int solveLU(const Mat & A, Vec & x, const Vec & b){
90
91 //** from TETGEN
92
93 Mat lu(A);
94
95 int N = 0;
96 uint n = b.size();
97 int ps[n];
98
99 double scales[n];
100 double pivot, biggest, mult, tempf;
101 uint pivotindex = 0, tmpIdx = 0;
102
103 for (uint i = N; i < n + N; i++) {
104 // Find the largest element in each row for row equilibration
105 biggest = 0.0;
106 for (uint j = N; j < n + N; j++) {
107 if (biggest < (tempf = std::fabs(lu[i][j]))) biggest = tempf;
108 }
109
110 if (biggest != 0.0) scales[i] = 1.0 / biggest;
111 else {
112 scales[i] = 0.0;
113 std::cerr << WHERE_AM_I << " Zero row: singular matrix" << std::endl;
114 return false; // Zero row: singular matrix.
115 }
116 ps[i] = i; // Initialize pivot sequence.
117 }
118
119 for (uint k = N; k < n + N - 1; k++) { // For each column.
120 // Find the largest element in each column to pivot around.
121 biggest = 0.0;
122 for (uint i = k; i < n + N; i++) {
123 if (biggest < (tempf = std::fabs(lu[ps[i]][k]) * scales[ps[i]])) {
124 biggest = tempf;
125 pivotindex = i;
126 }
127 }
128 if (biggest == 0.0) {
129 std::cerr << WHERE_AM_I << " Zero column: singular matrix" << std::endl;
130 return false; // Zero column: singular matrix.
131 }
132
133 if (pivotindex != k) { // Update pivot sequence.
134 tmpIdx = ps[k];
135 ps[k] = ps[pivotindex];
136 ps[pivotindex] = tmpIdx;
137 // *d = -(*d); // ...and change the parity of d.
138 }
139
140 // Pivot, eliminating an extra variable each time
141 pivot = lu[ps[k]][k];
142
143 for (uint i = k + 1; i < n + N; i++) {
144 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
145 if (mult != 0.0) {
146 for (uint j = k + 1; j < n + N; j++) lu[ps[i]][j] -= mult * lu[ps[k]][j];
147 }
148 }
149 }
150
151 double dot = 0.0;
152
153 // Vector reduction using U triangular matrix.
154 for (uint i = N; i < n + N; i++) {
155 dot = 0.0;
156 for (uint j = N; j < i + N; j++) dot += lu[ps[i]][j] * x[j];
157 x[i] = b[ps[i]] - dot;
158 }
159
160 // Back substitution, in L triangular matrix.
161 for (int i = n + N - 1; i >= N; i--) {
162 dot = 0.0;
163 for (uint j = i + 1; j < n + N; j++) dot += lu[ps[i]][j] * x[j];
164 x[i] = (x[i] - dot) / lu[ps[i]][i];
165 }
166
167 if (rms(Vec(A * x - b)) > 1e-9){
168 std::cerr << "rms(A * x -b) " << rms((const Vec)(A * x - b)) << std::endl;
169 // std::cout << Vector(A * x - b) << std::endl;
170 // std::cout << A << b << x << std::endl;
171 return -1;
172 }
173 return 1;
174}
175
176
177} // namespace GIMLI{
178
179#endif //_GIMLI_LINSOLVER__H
void setMatrix(RSparseMatrix &S, int stype=-2)
Definition linSolver.cpp:110
Interface class for matrices.
Definition matrix.h:137
Definition solverWrapper.h:26
GIMLi main namespace for the Geophyiscal Inversion and Modelling Library.
Definition baseentity.h:24
RVector x(const R3Vector &rv)
Definition pos.cpp:107