Garfield++ v2r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
cubic.cpp
Go to the documentation of this file.
1#include <cfloat>
2#include <iomanip>
6
7/*
8Copyright (c) 2005 Igor B. Smirnov
9
10The file can be used, copied, modified, and distributed
11according to the terms of GNU Lesser General Public License version 2.1
12as published by the Free Software Foundation,
13and provided that the above copyright notice, this permission notice,
14and notices about any modifications of the original text
15appear in all copies and in supporting documentation.
16The file is provided "as is" without express or implied warranty.
17*/
18
19namespace Heed {
20
21const Cubic::double_complex Cubic::iu(0, 1);
22
24 double_complex& z3) const {
25 mfunname("void Cubic::find_zero(...) const");
26 const Cubic& t = (*this);
27 if (s_dxzero != 0) {
28 z1 = dz1;
29 z2 = dz2;
30 z3 = dz3;
31 return;
32 }
33
34 check_econd11a(da, == 0.0, "this is not cubic polynomial!", mcerr);
35 double a2 = db / da;
36 double a1 = dc / da;
37 double a0 = dd / da;
38 double Q = (3.0 * a1 - a2 * a2) / 9.0;
39 double R = (9.0 * a2 * a1 - 27.0 * a0 - 2.0 * a2 * a2 * a2) / 54.0;
40 double D = Q * Q * Q + R * R;
41 double sD = sqrt(fabs(D));
44 if (D >= 0.0) {
45 double tt = R + sD;
46 if (tt > 0.0) {
47 S = pow(tt, 1 / 3.0);
48 } else if (tt < 0.0) {
49 S = -pow(-tt, 1 / 3.0);
50 } else {
51 S = 0.0;
52 }
53 tt = R - sD;
54 if (tt > 0.0) {
55 T = pow(tt, 1 / 3.0);
56 } else if (tt < 0.0) {
57 T = -pow(-tt, 1 / 3.0);
58 } else {
59 T = 0.0;
60 }
61 } else {
62 S = pow(R + iu * sD, 1 / 3.0);
63 T = pow(R - iu * sD, 1 / 3.0);
64 }
65 z1 = -a2 / 3.0 + (S + T);
66 z2 = -a2 / 3.0 - (S + T) / 2.0 + 0.5 * iu * std::sqrt(3.0) * (S - T);
67 z3 = -a2 / 3.0 - (S + T) / 2.0 - 0.5 * iu * std::sqrt(3.0) * (S - T);
68 t.dz1 = z1;
69 t.dz2 = z2;
70 t.dz3 = z3;
71 t.s_dxzero = 3;
72}
73
74int Cubic::find_real_zero(double z[3]) const {
75 mfunname("int Cubic::find_real_zero(double z[3]) const");
79 find_zero(zc1, zc2, zc3);
80 double thresh = 10.0 * DBL_MIN;
81 int q = 0;
82 if (fabs(zc1.imag()) < thresh ||
83 (zc1.real() != 0.0 && fabs(zc1.imag() / zc1.real()) < thresh)) {
84 z[q] = zc1.real();
85 q++;
86 }
87 if (fabs(zc2.imag()) < thresh ||
88 (zc2.real() != 0.0 && fabs(zc2.imag() / zc2.real()) < thresh)) {
89 z[q] = zc2.real();
90 q++;
91 }
92 if (fabs(zc3.imag()) < thresh ||
93 (zc3.real() != 0.0 && fabs(zc3.imag() / zc3.real()) < thresh)) {
94 z[q] = zc3.real();
95 q++;
96 }
97 int n2 = 0;
98 for (int n1 = 0; n1 < q - 1; n1++) {
99 for (n2 = n1; n2 < q; n2++) {
100 if (z[n1] > z[n2]) {
101 double t = z[n1];
102 z[n1] = z[n2];
103 z[n2] = t;
104 }
105 }
106 }
107 for (int n1 = 0; n1 < q - 1; n1++) {
108 // TODO: debug.
109 if ((fabs(z[n1]) < thresh && fabs(z[n2]) < thresh) ||
110 fabs((z[n1] - z[n1 + 1]) / (z[n1] + z[n1 + 1])) < thresh) {
111 for (n2 = n1 + 1; n2 < q - 1; n2++) {
112 z[n2] = z[n2 + 1];
113 }
114 q--;
115 n1--;
116 }
117 }
118 return q;
119}
120
121int Cubic::find_maxmin(double xmm[2], double ymm[2], int s_mm[2]) const {
122 mfunname(
123 "int Cubic::find_maxmin(double xmm[2], double ymm[2], int s_mm[2]) "
124 "const");
125 double ap = 3 * da;
126 double bp = 2 * db;
127 double cp = dc;
128 Parabol par(ap, bp, cp);
129 s_mm[0] = 0;
130 s_mm[1] = 0;
131 int qz = par.find_zero(xmm);
132 if (qz == 1) {
133 s_mm[0] = 0;
134 }
135 if (qz == 2) {
136 if (a() > 0) {
137 s_mm[0] = 1;
138 s_mm[1] = -1;
139 } else {
140 s_mm[0] = -1;
141 s_mm[1] = 1;
142 }
143 }
144 for (int n = 0; n < qz; ++n) {
145 ymm[n] = y(xmm[n]);
146 }
147 return qz;
148}
149
150std::ostream& operator<<(std::ostream& file, const Cubic& f) {
154 Ifile << "Cubic: s_xzero=" << f.s_xzero() << '\n';
155 indn.n += 2;
156 f.find_zero(z1, z2, z3);
157 Ifile << "Cubic: a=" << f.a() << " b=" << f.b() << " c=" << f.c()
158 << " d=" << f.d() << '\n';
159 file << " z1,2,3=" << z1 << ' ' << z2 << ' ' << z3 << '\n';
160 double r[3];
161 int q;
162 q = f.find_real_zero(r);
163 Ifile << "The number of real zeros =" << q << '\n';
164 int n;
165 Ifile << "Solutions=";
166 for (n = 0; n < q; n++) file << ' ' << r[n];
167 file << '\n';
168 double xmm[2];
169 double ymm[2];
170 int s_mm[2];
171 q = f.find_maxmin(xmm, ymm, s_mm);
172 Ifile << "Max/Min, q=" << q << '\n';
173 indn.n += 2;
174 for (n = 0; n < q; n++) {
175 Ifile << "n=" << n << " xmm[n]=" << std::setw(13) << xmm[n]
176 << " ymm[n]=" << std::setw(13) << ymm[n]
177 << " s_mm[n]=" << std::setw(13) << s_mm[n] << '\n';
178 }
179 indn.n -= 2;
180 indn.n -= 2;
181
182 return file;
183}
184}
#define check_econd11a(a, signb, add, stream)
Definition: FunNameStack.h:172
#define mfunname(string)
Definition: FunNameStack.h:45
Find solution to cubic equation.
Definition: cubic.h:22
void find_zero(double_complex &z1, double_complex &z2, double_complex &z3) const
Definition: cubic.cpp:23
double s_xzero() const
Definition: cubic.h:29
std::complex< double > double_complex
Definition: cubic.h:24
double a() const
Definition: cubic.h:25
double b() const
Definition: cubic.h:26
double y(double x) const
Definition: cubic.h:51
int find_maxmin(double xmm[2], double ymm[2], int s_mm[2]) const
Definition: cubic.cpp:121
double c() const
Definition: cubic.h:27
int find_real_zero(double z[3]) const
Definition: cubic.cpp:74
double d() const
Definition: cubic.h:28
int find_zero(double xzero[2]) const
Definition: parabol.cpp:229
Definition: BGMesh.cpp:5
std::ostream & operator<<(std::ostream &file, const BGMesh &bgm)
Definition: BGMesh.cpp:36
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:337
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615
indentation indn
Definition: prstream.cpp:15
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314
#define Ifile
Definition: prstream.h:196
#define mcerr
Definition: prstream.h:128