Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
polynomial.h
1/******************************************************************************
2 * Copyright (C) 2012-2024 by the GIMLi development team *
3 * Carsten Rücker 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_POLYNOMIAL__H
20#define _GIMLI_POLYNOMIAL__H
21
22#include "gimli.h"
23#include "matrix.h"
24#include "modellingbase.h"
25#include "regionManager.h"
26
27#include "numericbase.h"
28
29#include <list>
30
31namespace GIMLI{
32
33template< class ValueType > class PolynomialElement {
34public:
35 PolynomialElement(Index i, Index j, Index k, const ValueType & val)
36 : i_(i), j_(j), k_(k), val_(val){
37 }
38
39 inline ValueType operator () (const Pos & xyz) const {
40 return val_ * powInt(xyz[0], i_) * powInt(xyz[1], j_) * powInt(xyz[2], k_);
41 }
42
43 Index i_, j_, k_;
44 ValueType val_;
45};
46
48template < class ValueType > bool operator < (const PolynomialElement < ValueType > & a,
49 const PolynomialElement < ValueType > & b){
50 return ((a.i_ < b.i_) && (a.j_ < b.j_) && (a.k_ < b.k_));
51}
52
53template < class ValueType > bool operator != (const PolynomialElement < ValueType > & a,
54 const PolynomialElement < ValueType > & b){
55 return !(a == b);
56}
57
58template < class ValueType > bool operator == (const PolynomialElement < ValueType > & a,
59 const PolynomialElement < ValueType > & b){
60 return ((a.i_ == b.i_) && (a.j_ == b.j_) && (a.k_ == b.k_) && (a.val_ == b.val_));
61}
62
63
67template< class ValueType > class DLLEXPORT PolynomialFunction {
68public:
69
76
80 PolynomialFunction(const Vector < ValueType > & ax){
81 init_(ax, Vector< ValueType >(0, 0.0),
82 Vector< ValueType >(0, 0.0));
83 }
84
89 PolynomialFunction(const Vector < ValueType > & ax, const Vector < ValueType > & ay){
90 init_(ax, ay, Vector< ValueType >(0, 0.0));
91 }
92
97 PolynomialFunction(const Vector < ValueType > & ax,
98 const Vector < ValueType > & ay,
99 const Vector < ValueType > & az){
100 init_(ax, ay, az);
101 }
102
104 RMatrix & operator [] (Index k){ return mat_[k]; }
105
107 const RMatrix & operator [] (Index k) const { return mat_[k]; }
108
110 RMatrix & matR(Index k){ return mat_[k]; }
111
113 ValueType operator () (const Pos & xyz) const {
114 ValueType ret = 0.0;
115
116 for (typename std::vector <PolynomialElement < ValueType > >::const_iterator it = elementList_.begin();
117 it != elementList_.end(); it ++){
118 ret += (*it)(xyz);
119 }
120 return ret;
121 }
122
124 Vector < ValueType > operator () (const std::vector < Pos > & xyz) const {
125 Vector < ValueType > ret(xyz.size(), 0.0);
126
127 for (Index i = 0 ; i < ret.size(); i ++) ret [i] = (*this)(xyz[i]);
128
129 return ret;
130 }
131
133 Index size() const { return mat_.size(); }
134
140 PolynomialFunction < ValueType > derive(uint dim) const {
141
142 PolynomialFunction< ValueType > ret(RVector(this->size(), 0.0));
143
144 if (dim == 0){
145 for (Index k = 0; k < mat_.size(); k ++){ // z
146 for (Index j = 0; j < mat_[k].rows(); j ++){ // y
147 for (Index i = 0; i < mat_[k][j].size() -1; i ++){ // x
148 ret[k][i][j] = mat_[k][i + 1][j] * (i + 1.0);
149 }
150 }
151 }
152 } else if(dim == 1){
153 for (Index k = 0; k < mat_.size(); k ++){ // z
154 for (Index j = 0; j < mat_[k].rows() - 1; j ++){ // y
155 for (Index i = 0; i < mat_[k][j].size(); i ++){ // x
156 ret[k][i][j] = mat_[k][i][j + 1] * (j + 1.0);
157 }
158 }
159 }
160 } else if (dim == 2){
161 for (Index k = 0; k < mat_.size() -1 ; k ++){ // z
162 for (Index j = 0; j < mat_[k].rows(); j ++){ // y
163 for (Index i = 0; i < mat_[k][j].size(); i ++){ // x
164 ret[k][i][j] = mat_[k + 1][i][j] * (k + 1.0);
165 }
166 }
167 }
168 }
169 ret.fillElementList();
170 return ret;
171 }
172
173
174 void fillElementList(){
175 elementList_.clear();
176
177 for (Index k = 0; k < mat_.size(); k ++){ // z
178 for (Index j = 0; j < mat_[k].rows(); j ++){ // y
179 for (Index i = 0; i < mat_[k][j].size(); i ++){ // x
180 if (::fabs(mat_[k][i][j]) > TOLERANCE){
181 elementList_.push_back(PolynomialElement< ValueType > (i, j, k, mat_[k][i][j]));
182 }
183 }
184 }
185 }
186 }
187
188 const std::vector <PolynomialElement < ValueType > > & elements() const { return elementList_; }
189
190 void clear() {
191 elementList_.clear();
192 for (Index k = 0; k < mat_.size(); k ++){ mat_[k] *= 0.0; }
193 }
194
203 PolynomialFunction < ValueType > & fill(const Vector < ValueType > & c){
204 if (c.size() == powInt(mat_.size(), 3)) {
205 for (Index k = 0; k < mat_.size(); k ++){ // z
206 for (Index j = 0; j < mat_[k].rows(); j ++){ // y
207 for (Index i = 0; i < mat_[k][j].size(); i ++){ // x
208 if (::fabs(c[k*(size() * size())+ j * size() + i]) > TOLERANCE){
209
210// std::cout.precision(14);
211// std::cout << i << " " << j << " " << k << " " << c[k*(size() * size())+ j * size() + i] << std::endl;
212
213 //mat_[k][i][j] = round(c[k*(size() * size())+ j * size() + i], 1e-12);
214
215 mat_[k][i][j] = c[k*(size() * size())+ j * size() + i];
216 } else {
217 mat_[k][i][j] = 0.0;
218 }
219 }
220 }
221 }
222 } else if (c.size() == elementList_.size()){
223 for (Index k = 0; k < mat_.size(); k ++){ // z
224 mat_[k] *= 0.0;
225 }
226 for (Index i = 0; i < c.size(); i ++){
227 PolynomialElement< ValueType > e = elementList_[i];
228 mat_[e.k_][e.i_][e.j_] = c[i];
229 }
230 } else {
231 throwLengthError(WHERE_AM_I + " c size out of range " +
232 str(c.size()) + " needed " + str(powInt(mat_.size(), 3)) +
233 " or " + str(elementList_.size()));
234 }
235 this->fillElementList();
236 return *this;
237 }
238
240 RVector coeff() const {
241 RVector c(powInt(mat_.size(), 3));
242
243 for (Index k = 0; k < mat_.size(); k ++){ // z
244 for (Index j = 0; j < mat_[k].rows(); j ++){ // y
245 for (Index i = 0; i < mat_[k][j].size(); i ++){ // x
246 c[k*(size() * size())+ j * size() + i] = mat_[k][i][j];
247 }
248 }
249 }
250 return c;
251 }
252
253protected:
254
255 void init_(const Vector < ValueType > & ax,
256 const Vector < ValueType > & ay,
257 const Vector < ValueType > & az){
258 Index maxDim = max(max(ax.size(), ay.size()), az.size());
259
260 for (Index k = 0; k < maxDim; k ++){
261 mat_.push_back(RMatrix(maxDim, maxDim));
262 mat_[k] *= 0.0;
263 }
264
265 for (Index i = 0; i < ax.size(); i ++) mat_[0][i][0] = ax[i];
266 for (Index j = 0; j < ay.size(); j ++) mat_[0][0][j] = ay[j];
267 for (Index k = 0; k < az.size(); k ++) mat_[k][0][0] = az[k];
268 fillElementList();
269 }
270
271 std::vector < Matrix < ValueType > > mat_;
272
273 std::vector <PolynomialElement < ValueType > > elementList_;
274};
275
276template < class ValueType > bool operator == (const PolynomialFunction < ValueType > & a, const PolynomialFunction < ValueType > & b){
277 if (a.elements().size() == b.elements().size()){
278 typename std::vector <PolynomialElement < ValueType > >::const_iterator ita = a.elements().begin();
279 typename std::vector <PolynomialElement < ValueType > >::const_iterator itb = b.elements().begin();
280
281 for (; ita != a.elements().end(); ita ++, itb ++){
282 if (*ita != *itb) return false;
283 }
284 } else {
285 return false;
286 }
287
288 return true;
289}
290
291template < class ValueType > PolynomialFunction < ValueType >
292operator - (const PolynomialFunction < ValueType > & f){
293
294 PolynomialFunction < ValueType > h(Vector<ValueType>(f.size(), 0.0));
295
296 for (Index k = 0; k < f.size(); k ++){ // z
297 for (Index j = 0; j < f[k].rows(); j ++){ // y
298 for (Index i = 0; i < f[k][j].size(); i ++){ // x
299 h[k][i][j] = -f[k][i][j];
300 }
301 }
302 }
303 h.fillElementList();
304 return h;
305}
306
307template < class ValueType > PolynomialFunction < ValueType >
308operator * (const ValueType & val, const PolynomialFunction < ValueType > & f){
309
310 PolynomialFunction < ValueType > h(RVector(f.size()), 0.0);
311
312 for (Index k = 0; k < f.size(); k ++){ // z
313 for (Index j = 0; j < f[k].rows(); j ++){ // y
314 for (Index i = 0; i < f[k][j].size(); i ++){ // x
315 h[k][i][j] = f[k][i][j] * val;
316 }
317 }
318 }
319 h.fillElementList();
320 return h;
321}
322
323template < class ValueType > PolynomialFunction < ValueType >
324operator * (const PolynomialFunction < ValueType > & f, const ValueType & val){
325
326 PolynomialFunction < ValueType > h(RVector(f.size()), 0.0);
327
328 for (Index k = 0; k < f.size(); k ++){ // z
329 for (Index j = 0; j < f[k].rows(); j ++){ // y
330 for (Index i = 0; i < f[k][j].size(); i ++){ // x
331 h[k][i][j] = f[k][i][j] * val;
332 }
333 }
334 }
335 h.fillElementList();
336 return h;
337}
338
339template < class ValueType > PolynomialFunction < ValueType >
340operator + (const ValueType & val, const PolynomialFunction < ValueType > & f){
341 PolynomialFunction < ValueType > h(RVector(f.size(), 0.0));
342
343 for (Index k = 0; k < f.size(); k ++){ // z
344 for (Index j = 0; j < f[k].rows(); j ++){ // y
345 for (Index i = 0; i < f[k][j].size(); i ++){ // x
346 h[k][i][j] = f[k][i][j];
347 }
348 }
349 }
350 h[0][0][0] += val;
351 h.fillElementList();
352 return h;
353}
354
355template < class ValueType > PolynomialFunction < ValueType >
356operator + (const PolynomialFunction < ValueType > & f, const ValueType & val){
357 PolynomialFunction < ValueType > h(RVector(f.size(), 0.0));
358
359 for (Index k = 0; k < f.size(); k ++){ // z
360 for (Index j = 0; j < f[k].rows(); j ++){ // y
361 for (Index i = 0; i < f[k][j].size(); i ++){ // x
362 h[k][i][j] = f[k][i][j];
363 }
364 }
365 }
366 h[0][0][0] += val;
367 h.fillElementList();
368 return h;
369}
370
371template < class ValueType > PolynomialFunction < ValueType >
372operator + (const PolynomialFunction < ValueType > & f, const PolynomialFunction < ValueType > & g){
373
374 PolynomialFunction < ValueType > h(RVector(max(f.size(),g.size()), 0.0));
375
376 for (Index k = 0; k < f.size(); k ++){ // z
377 for (Index j = 0; j < f[k].rows(); j ++){ // y
378 for (Index i = 0; i < f[k][j].size(); i ++){ // x
379 h[k][i][j] = f[k][i][j];
380 }
381 }
382 }
383 for (Index k = 0; k < g.size(); k ++){ // z
384 for (Index j = 0; j < g[k].rows(); j ++){ // y
385 for (Index i = 0; i < g[k][j].size(); i ++){ // x
386 h[k][i][j] += g[k][i][j];
387 }
388 }
389 }
390 h.fillElementList();
391 return h;
392}
393
394template < class ValueType > PolynomialFunction < ValueType >
395operator - (const PolynomialFunction < ValueType > & f, const PolynomialFunction < ValueType > & g){
396
397 PolynomialFunction < ValueType > h(RVector(max(f.size(),g.size()), 0.0));
398
399 for (Index k = 0; k < f.size(); k ++){ // z
400 for (Index j = 0; j < f[k].rows(); j ++){ // y
401 for (Index i = 0; i < f[k][j].size(); i ++){ // x
402 h[k][i][j] = f[k][i][j];
403 }
404 }
405 }
406 for (Index k = 0; k < g.size(); k ++){ // z
407 for (Index j = 0; j < g[k].rows(); j ++){ // y
408 for (Index i = 0; i < g[k][j].size(); i ++){ // x
409 h[k][i][j] -= g[k][i][j];
410 }
411 }
412 }
413 h.fillElementList();
414 return h;
415}
416
418template < class ValueType > PolynomialFunction < ValueType >
419operator * (const PolynomialFunction < ValueType > & f, const PolynomialFunction < ValueType > & g){
420
421
422 //TODO & TEST das muss besser werden weil es nicht immer f.size() + g.size() aufspannt. bsp. x*y statt x*x
423 PolynomialFunction < ValueType > h(RVector(f.size() + g.size(), 0.0));
424
425 for (Index k = 0; k < f.size(); k ++){ // z
426 for (Index j = 0; j < f[k].rows(); j ++){ // y
427 for (Index i = 0; i < f[k][j].size(); i ++){ // x
428 for (Index gk = 0; gk < g.size(); gk ++){ // z
429 for (Index gj = 0; gj < g[gk].rows(); gj ++){ // y
430 for (Index gi = 0; gi < g[gk][gj].size(); gi ++){ // x
431 h[k + gk][i + gi][j + gj] += f[k][i][j] * g[gk][gi][gj];
432 }
433 }
434 }
435 }
436 }
437 }
438 h.fillElementList();
439 return h;
440}
441
442template < class ValueType > std::ostream & operator << (std::ostream & os, const PolynomialFunction < ValueType > & p){
443 os << "f(x,y,z) = ";
444
445 if (p.size() == 0) os << "0";
446
447 bool first = true;
448 for (Index k = 0; k < p.size() ; k ++){ // z
449 for (Index j = 0; j < p[k].rows(); j ++){ // y
450 for (Index i = 0; i < p[k][j].size(); i ++){ // x
451 if (i > 0) first = false;
452
453 std::string si = "";
454
455 ValueType v = p[k][i][j];
456 if (v == 0.0) continue;
457 if (v > 0.0) si = "+";
458
459 std::string xterm, yterm, zterm, val;
460 if (i == 0) xterm = ""; else if (i == 1) xterm = "x"; else xterm = "x^" + str(i);
461 if (j == 0) yterm = ""; else if (j == 1) yterm = "y"; else yterm = "y^" + str(j);
462 if (k == 0) zterm = ""; else if (k == 1) zterm = "z"; else zterm = "z^" + str(k);
463
464 val = str(v);
465
466 if (first){
467 if (v == -1.0) val = "-1";
468 else if (v == 1.0) val = "1";
469 } else {
470 if (::fabs(v + 1.0) < TOLERANCE) val = "-";
471 else if (::fabs(v - 1.0) < TOLERANCE) val = "";
472 }
473
474 os << si << val << xterm;
475 if (yterm != "") os << yterm;
476 if (zterm != "") os << zterm;
477 }
478 }
479 }
480
481 return os;
482}
483
484
485} // namespace GIMLI
486
487#endif // _GIMLI_POLYNOMIAL__H
Definition polynomial.h:33
PolynomialFunction(const Vector< ValueType > &ax, const Vector< ValueType > &ay)
Definition polynomial.h:89
PolynomialFunction(const Vector< ValueType > &ax)
Definition polynomial.h:80
Index size() const
Definition polynomial.h:133
PolynomialFunction(const Vector< ValueType > &ax, const Vector< ValueType > &ay, const Vector< ValueType > &az)
Definition polynomial.h:97
PolynomialFunction(uint size=0)
Definition polynomial.h:71
RVector coeff() const
Definition polynomial.h:240
RMatrix & matR(Index k)
Definition polynomial.h:110
PolynomialFunction< ValueType > & fill(const Vector< ValueType > &c)
Definition polynomial.h:203
PolynomialFunction< ValueType > derive(uint dim) const
Definition polynomial.h:140
3 dimensional vector
Definition pos.h:73
One dimensional array aka Vector of limited size.
Definition vector.h:186
GIMLi main namespace for the Geophyiscal Inversion and Modelling Library.
Definition baseentity.h:24
bool operator<(const PolynomialElement< ValueType > &a, const PolynomialElement< ValueType > &b)
Definition polynomial.h:48