Garfield++ v1r0
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 <iomanip>
10
11/*
12Copyright (c) 2005 Igor B. Smirnov
13
14The file can be used, copied, modified, and distributed
15according to the terms of GNU Lesser General Public License version 2.1
16as published by the Free Software Foundation,
17and provided that the above copyright notice, this permission notice,
18and notices about any modifications of the original text
19appear in all copies and in supporting documentation.
20The file is provided "as is" without express or implied warranty.
21*/
22
23const Cubic::double_complex Cubic::iu(0, 1);
24
26 double_complex& z3) const {
27 mfunname("void Cubic::find_zero(double_complex &z1, double_complex &z2, "
28 "double_complex &z3) const");
30 if (s_dxzero == 0) {
31 check_econd11a(da, == 0.0, "this is not cubic polynomial!", mcerr);
32 double a2 = db / da;
33 double a1 = dc / da;
34 double a0 = dd / da;
35 double Q = (3.0 * a1 - a2 * a2) / 9.0;
36 double R = (9.0 * a2 * a1 - 27.0 * a0 - 2.0 * a2 * a2 * a2) / 54.0;
37 double D = Q * Q * Q + R * R;
38 double sD = sqrt(fabs(D));
41 if (D >= 0.0) {
42 double t = R + sD;
43 if (t > 0.0) {
44 S = pow(t, 1 / 3.0);
45 } else if (t < 0.0) {
46 S = -pow(-t, 1 / 3.0);
47 } else {
48 S = 0.0;
49 }
50 t = R - sD;
51 if (t > 0.0) {
52 T = pow(t, 1 / 3.0);
53 } else if (t < 0.0) {
54 T = -pow(-t, 1 / 3.0);
55 } else {
56 T = 0.0;
57 }
58 } else {
59 S = pow(R + iu * sD, 1 / 3.0);
60 T = pow(R - iu * sD, 1 / 3.0);
61 }
62 z1 = -a2 / 3.0 + (S + T);
63 z2 = -a2 / 3.0 - (S + T) / 2.0 + 0.5 * iu * sqrt(3.0) * (S - T);
64 z3 = -a2 / 3.0 - (S + T) / 2.0 - 0.5 * iu * sqrt(3.0) * (S - T);
65 t.dz1 = z1;
66 t.dz2 = z2;
67 t.dz3 = z3;
68 t.s_dxzero = 3;
69 } else {
70 z1 = dz1;
71 z2 = dz2;
72 z3 = dz3;
73 }
74}
75
76int Cubic::find_real_zero(double z[3]) const {
77 mfunname("int Cubic::find_real_zero(double z[3]) const");
81 find_zero(zc1, zc2, zc3);
82 double thresh = 10.0 * DBL_MIN;
83 int q = 0;
84 if (fabs(zc1.imag()) < thresh ||
85 (zc1.real() != 0.0 && fabs(zc1.imag() / zc1.real()) < thresh)) {
86 z[q] = zc1.real();
87 q++;
88 }
89 if (fabs(zc2.imag()) < thresh ||
90 (zc2.real() != 0.0 && fabs(zc2.imag() / zc2.real()) < thresh)) {
91 z[q] = zc2.real();
92 q++;
93 }
94 if (fabs(zc3.imag()) < thresh ||
95 (zc3.real() != 0.0 && fabs(zc3.imag() / zc3.real()) < thresh)) {
96 z[q] = zc3.real();
97 q++;
98 }
99 int n1 = 0, n2 = 0;
100 for (n1 = 0; n1 < q - 1; n1++) {
101 for (n2 = n1; n2 < q; n2++) {
102 if (z[n1] > z[n2]) {
103 double t = z[n1];
104 z[n1] = z[n2];
105 z[n2] = t;
106 }
107 }
108 }
109 for (n1 = 0; n1 < q - 1; n1++) {
110 if ((fabs(z[n1]) < thresh && fabs(z[n2]) < thresh) ||
111 fabs((z[n1] - z[n1 + 1]) / (z[n1] + z[n1 + 1])) < thresh) {
112 for (n2 = n1 + 1; n2 < q - 1; n2++) {
113 z[n2] = z[n2 + 1];
114 }
115 q--;
116 n1--;
117 }
118 }
119 return q;
120}
121
122int Cubic::find_maxmin(double xmm[2], double ymm[2], int s_mm[2]) const {
123 mfunname("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++)
167 file << ' ' << r[n];
168 file << '\n';
169 double xmm[2];
170 double ymm[2];
171 int s_mm[2];
172 q = f.find_maxmin(xmm, ymm, s_mm);
173 Ifile << "Max/Min, q=" << q << '\n';
174 indn.n += 2;
175 for (n = 0; n < q; n++) {
176 Ifile << "n=" << n << " xmm[n]=" << std::setw(13) << xmm[n]
177 << " ymm[n]=" << std::setw(13) << ymm[n]
178 << " s_mm[n]=" << std::setw(13) << s_mm[n] << '\n';
179 }
180 indn.n -= 2;
181 indn.n -= 2;
182
183 return file;
184}
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:616
#define check_econd11a(a, signb, add, stream)
Definition: FunNameStack.h:395
#define mfunname(string)
Definition: FunNameStack.h:67
Definition: cubic.h:18
double s_xzero(void) const
Definition: cubic.h:25
double b(void) const
Definition: cubic.h:22
int find_maxmin(double xmm[2], double ymm[2], int s_mm[2]) const
Definition: cubic.cpp:122
int find_real_zero(double z[3]) const
Definition: cubic.cpp:76
double c(void) const
Definition: cubic.h:23
double d(void) const
Definition: cubic.h:24
double y(double x) const
Definition: cubic.h:49
double a(void) const
Definition: cubic.h:21
void find_zero(double_complex &z1, double_complex &z2, double_complex &z3) const
Definition: cubic.cpp:25
std::complex< double > double_complex
Definition: cubic.h:20
int find_zero(double xzero[2]) const
Definition: parabol.cpp:234
std::ostream & operator<<(std::ostream &file, const Cubic &f)
Definition: cubic.cpp:150
#define convmut(type)
indentation indn
Definition: prstream.cpp:13
#define Ifile
Definition: prstream.h:207
#define mcerr
Definition: prstream.h:135