NeoPZ
pzpolynomial.cpp
Go to the documentation of this file.
1 
6 #include "pzpolynomial.h"
7 #include "pznumeric.h"
8 #include "pzmanvector.h"
9 #include <iostream>
10 #include <algorithm>
11 #include <functional>
12 
13 using namespace std;
14 
20 int TPZPolynomial::Tartaglia(const TPZVec<REAL> &coef, TPZVec<REAL> &raiz, REAL &imagem) {
21 
22  REAL a = coef[3];
23  REAL b = coef[2];
24  REAL c = coef[1];
25  REAL d = coef[0];
26  REAL Delta; //teste;
27 
28  // cout << a << "x³ + " << b << "x² + " << c << "x + " << d << " = 0.0\n";
29  if (a == 0.0) {
30  cout << "Se a=0, a equacao nao e' do terceiro grau.";
31  return 0;
32  }
33  else if (d == 0.0) {
34  //cout <<"Se d=0, a equacao do terceiro grau tem uma raiz nula."
35  //<< "e a equacao pode ser fatorada na forma x.(ax^2+bx+c)=0.";
36  raiz[0] = 0.0;
37  Delta = b * b - 4 * a * c;
38  if (Delta > 0) {
39  raiz[1] = (-1 * b + sqrt(Delta)) / (2 * a);
40  raiz[2] = (-1 * b - sqrt(Delta)) / (2 * a);
41  //Colocação das tensões em ordem crescente
42  sort(&raiz[0], &raiz[3], greater<REAL>());
43  return 1;
44  }
45  else if (Delta < 0) {
46  raiz[1] = (-1 * b) / (2 * a);
47  raiz[2] = raiz[1];
48  imagem = fabs(Delta) / (2 * a);
49  return -1;
50 
51  }
52  else {
53  raiz[1] = (-1 * b) / (2 * a);
54  raiz[2] = raiz[1];
55  return 2;
56  }
57  }
58  REAL A = b / a;
59  REAL B = c / a;
60  REAL C = d / a;
61 
62  REAL p = B - A * A / 3.;
63  REAL q = C - A * B / 3. + 2. * A * A * A / 27.;
64  REAL D = q * q / 4. + p * p * p / 27.;
65  REAL pi = 3.1415926535897932384626;
66 
67 
68 
69  if (D < 0) {
70  REAL M = sqrt(-D);
71  REAL r = sqrt(q * q / 4. + M * M);
72  REAL t = acos(-q / 2. / r);
73  raiz[0] = 2.* pow( r, (REAL) (1. / 3.)) * cos(t / 3.) - A / 3;
74  raiz[1] = 2.* pow( r, (REAL) (1. / 3.)) * cos((t + 2. * pi) / 3.) - A / 3.;
75  raiz[2] = 2.* pow( r, (REAL) (1. / 3.)) * cos((t + 4. * pi) / 3.) - A / 3.;
76  //Colocação das tensões em ordem crescente
77  sort(&raiz[0], &raiz[3], greater<REAL>());
78  return 1;
79  }
80  else {
81  REAL u, v;
82  REAL u3 = -q / 2. + sqrt(D);
83  if (u3 < 0) {
84  u = -pow((-u3), (REAL)(1./3.));
85  }
86  else {
87  u = pow(u3, (REAL)(1./3.));
88  }
89  REAL v3 = -q / 2. - sqrt(D);
90  if (v3 < 0.) {
91  v = -pow((-v3), (REAL)(1./3.));
92  }
93  else {
94  v = pow(v3, (REAL)(1./3.));
95  }
96  raiz[0] = u + v - A / 3.;
97  Delta = (A + raiz[0]) * (A + raiz[0]) + 4 * C / raiz[0];
98  REAL Real = -(A + raiz[0]) / 2.0;
99  REAL K = fabs(Delta);
100  REAL Imag = sqrt(K) / 2.0L;
101 
102  if (Delta < 0) {
103  raiz[1] = Real;
104  raiz[2] = Real;
105  imagem = Imag;
106  return -1;
107  }
108  else {
109  raiz[1] = Real + Imag;
110  raiz[2] = Real - Imag;
111  //Colocação das tensões em ordem crescente
112  sort(&raiz[0], &raiz[3], greater<REAL>());
113  return 2;
114  }
115  }
116 }
117 
120 void TPZPolynomial::SetCoef(const REAL &c0, const REAL &c1, const REAL &c2, const REAL &c3) {
121  int i;
122  fCo[0] = c0;
123  fCo[1] = c1;
124  fCo[2] = c2;
125  fCo[3] = c3;
126  REAL max = 0;
127  for (i = 0; i < 4; i++) {
128  if (fabs(fCo[i]) > max) max = fabs(fCo[i]);
129  }
130  max = fabs(max * 1e-6L);
131  SetTolerance(max);
132  Tartaglia(fCo, fReal, fImagem);
133 }
134 
138  int i;
139  REAL max = 0.L;
140  for (i = 0; i < 4; i++) {
141  fCo[i] = coef[i];
142  if (fabs(fCo[i]) > max) max = fabs(fCo[i]);
143  }
144  max = max * 1e-6L;
145  SetTolerance(max);
146  Tartaglia(fCo, fReal, fImagem);
147 }
148 
151  int i;
152  for (i = 0; i < 3; i++)
153  if (fCo[i] == -99.999) {
154  cout << "TPZPolynomial::GetRoots.\nERRO: Coeficientes ainda nao foram especificados.\n";
155  return -1;
156  }
157  r = fReal;
158  return 1;
159 }
160 
163  fCo = coef;
164  GetRoots(r);
165  return 1;
166 }
167 
171  REAL x;
172  REAL tol = -99.999;
173  REAL der;
174  int i, j;
175  int zero = 0;
176  for (i = 0; i < 4; i++)
177  if (fabs(fCo[i]) < fTolerance) zero++;
178  if (zero == 4) {
179  for (i = 0; i < 3; i++) fReal[i] = 0.000;
180  return 1;
181  }
182  else {
183  if (fabs(fCo[0]) < fTolerance && fabs(fCo[1]) < fTolerance) {
184  X[0] = fCo[2] / fCo[3];
185  X[1] = 0.0;
186  X[2] = 0.0;
187  //Colocação das tensões em ordem crescente
188  sort(&X[0], &X[3], greater<REAL>());
189  fReal = X;
190 // copy(&X[0], &X[3], &fReal[0]);
191  }
192  else {
193  // Primeira aproximacao
194  for (i = 0; i < 3; i++) X[i] = -99.999;
195  x = fCo[2] + 1.0;
196  j = 0;
197  while (j < 10000) {
198  j++;
199  der = 3.0 * fCo[3] * x * x + 2.0 * fCo[2] * x + fCo[1];
200  if (fabs(der) < fTolerance) j = 10002;
201  else X[0] = x - ((fCo[3] * x * x * x + fCo[2] * x * x + fCo[1] * x + fCo[0]) / der);
202  tol = fabs(x - X[0]);
203  if (tol <= fTolerance) j = 10001;
204  x = X[0];
205  }
206  //Caso falhe a primeira aproximação
207  if (j == 10002 || j == 10000) {
208  x = -1e5 * x;
209  j = 0;
210  while (j < 10000) {
211  j++;
212  der = 3.0 * fCo[3] * x * x + 2.0 * fCo[2] * x + fCo[1];
213  if (fabs(der) <= fTolerance) j = 10002;
214  else X[0] = x - ((fCo[3] * x * x * x + fCo[2] * x * x + fCo[1] * x + fCo[0]) / der);
215  tol = fabs(x - X[0]);
216  if (tol <= fTolerance) j = 1001;
217  x = X[0];
218  }
219  }
220  if (j == 10002 || j == 10000) {
221  cout << "TPZPolynomial::SetRoots().\nErro no calculo das raizes!!!!! j= " << j << "\n";
222  //cout << fCo[3] << "x³ + " << fCo[2] << "x² + " << fCo[1] << "x + " << fCo[0] << " = 0.0\n";
223  return -1;
224  }
225  REAL teste;
226  teste = fCo[3] * X[0] * X[0] * X[0] + fCo[2] * X[0] + fCo[1] * X[0] + fCo[0];
227  cout << "Resultado da 1a raiz na equacao" << teste << "\n";
228  //Fim do calculo da primeira raiz (X[0])
229  //Reducao da equacao caracteristica de grau 2.
230  REAL b1, b2, b3;
231  b3 = fCo[3];
232  b2 = fCo[2] + X[0] * b3;
233  b1 = fCo[1] + X[0] * b2;
234 
236  REAL delta;
237  delta = b2 * b2 - 4.0 * b1 * b3;
238  if (delta < 0.0) {
239  cerr << "TPZPolynomial::SetRoots() - warning: Raizes nao reais!! Delta =" << delta << "\t" << X[0] << "\n";
240  cout << fCo[3] << "x >= + " << fCo[2] << "x <= + " << fCo[1] << "x + " << fCo[0] << " = 0.0\n";
241  cout << b3 << "x<= + " << b2 << "x + " << b1 << " = 0.0\n";
242  X[1] = 0.0;
243  X[2] = 0.0;
244  sort(&X[0], &X[3], greater<REAL>());
245  fReal = X;
246  }
247  else {
248  X[1] = (-b2 - sqrt(delta)) / (2.0 * b3);
249  X[2] = (-b2 + sqrt(delta)) / (2.0 * b3);
250  // Ordenando as tensoes de forma crescente
251  sort(&X[0], &X[3], greater<REAL>());
252  fReal = X;
253  }
254  }
255  }
256  return 1;
257 }
258 
260 void TPZPolynomial::SetTolerance(const REAL &tol) {
261  fTolerance = tol;
262 }
263 
265 TPZPolynomial::TPZPolynomial(const TPZVec<REAL> &coef, const REAL &tol): fReal(3), fImagem(0.0) {
266  SetTolerance(tol);
267  SetCoef(coef);
268 }
269 
272  tol = fTolerance;
273 }
274 
277  SetCoef(coef);
278 }
279 
282 }
expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ fabs
Definition: tfadfunc.h:140
TPZVec< REAL > fReal
Roots of the polynomial.
Definition: pzpolynomial.h:62
void GetTolerance(REAL &tol)
Gets the tolerance value.
TPZVec< REAL > fCo
Polynomial coefficients.
Definition: pzpolynomial.h:59
void SetCoef(const REAL &c0, const REAL &c1, const REAL &c2, const REAL &c3)
Sets up four coefficients to polynomial.
expr_ expr_ expr_ expr_ acos
Definition: tfadfunc.h:75
static const double tol
Definition: pzgeoprism.cpp:23
void SetTolerance(const REAL &tol)
REAL fTolerance
Tolerance value to computes.
Definition: pzpolynomial.h:56
TPZPlasticIntegrMem< REAL, 4 > teste
TPZPolynomial()
Default constructor.
Free store vector implementation.
int SetRoots()
Computes the roots of the polynomial and stores into the fReal.
expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ sqrt
Definition: tfadfunc.h:120
int GetRoots(const TPZVec< REAL > &coef, TPZVec< REAL > &r)
On given coefficients computes the roots of the polynomial in r.
Contains declaration of the TPZPolynomial class which implements a polynomial.
void SetTolerance(const REAL &tol)
Sets the tolerance value to computes.
TPZFlopCounter pow(const TPZFlopCounter &orig, const TPZFlopCounter &xp)
Returns the power and increments the counter of the power.
Definition: pzreal.h:487
Contains declaration of the TPZNumeric class which implements several methods to calculation.
TPZFlopCounter cos(const TPZFlopCounter &orig)
Returns the cosine in radians and increments the counter of the Cosine.
Definition: pzreal.h:514
int Tartaglia(const TPZVec< REAL > &coef, TPZVec< REAL > &real, REAL &imagem)
Computes the roots of the cubic polynomial using Tartaglia method (until 3 degree) ...