Mantid
Loading...
Searching...
No Matches
Quadratic.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#include <algorithm>
8#include <boost/multi_array.hpp>
9#include <complex>
10#include <fstream>
11#include <iomanip>
12#include <list>
13#include <map>
14#include <set>
15#include <sstream>
16#include <stack>
17#include <vector>
18
24#include "MantidKernel/Logger.h"
25#include "MantidKernel/Matrix.h"
27#include "MantidKernel/V3D.h"
28
30
31namespace Mantid::Geometry {
32namespace {
33Kernel::Logger logger("Quadratic");
34}
36using Kernel::V3D;
37
39 : Surface(), BaseEqn(10)
43{}
44
45double Quadratic::eqnValue(const Kernel::V3D &Pt) const
53{
54 double res(0.0);
55 res += BaseEqn[0] * Pt[0] * Pt[0];
56 res += BaseEqn[1] * Pt[1] * Pt[1];
57 res += BaseEqn[2] * Pt[2] * Pt[2];
58 res += BaseEqn[3] * Pt[0] * Pt[1];
59 res += BaseEqn[4] * Pt[0] * Pt[2];
60 res += BaseEqn[5] * Pt[1] * Pt[2];
61 res += BaseEqn[6] * Pt[0];
62 res += BaseEqn[7] * Pt[1];
63 res += BaseEqn[8] * Pt[2];
64 res += BaseEqn[9];
65 return res;
66}
67
68int Quadratic::side(const Kernel::V3D &Pt) const
77{
78 double res = eqnValue(Pt);
79 if (fabs(res) < Tolerance)
80 return 0;
81 return (res > 0) ? 1 : -1;
82}
83
93{
94 Kernel::V3D N(2 * BaseEqn[0] * Pt[0] + BaseEqn[3] * Pt[1] + BaseEqn[4] * Pt[2] + BaseEqn[6],
95 2 * BaseEqn[1] * Pt[1] + BaseEqn[3] * Pt[0] + BaseEqn[5] * Pt[2] + BaseEqn[7],
96 2 * BaseEqn[2] * Pt[2] + BaseEqn[4] * Pt[0] + BaseEqn[5] * Pt[1] + BaseEqn[8]);
97 N.normalize();
98 return N;
99}
100
109{
110 A.setMem(3, 3); // set incase memory out
111 for (int i = 0; i < 3; i++)
112 A[i][i] = BaseEqn[i];
113
114 A[0][1] = A[1][0] = BaseEqn[3] / 2.0;
115 A[0][2] = A[2][0] = BaseEqn[4] / 2.0;
116 A[1][2] = A[2][1] = BaseEqn[5] / 2.0;
117
118 for (int i = 0; i < 3; i++)
119 B[i] = BaseEqn[6 + i];
120 C = BaseEqn[9];
121}
122
123double Quadratic::distance(const Kernel::V3D &Pt) const
129{
130 // Job 1 :: Create matrix and vector representation
132 Kernel::V3D B;
133 double cc;
134 matrixForm(A, B, cc);
135
136 // Job 2 :: calculate the diagonal matrix
139 if (!A.Diagonalise(R, D)) {
140 logger.warning() << "Problem with matrix :: distance now guessed at\n";
141 return distance(Pt);
142 }
143
144 Kernel::V3D alpha = R.Tprime() * Pt;
145 Kernel::V3D beta = R.Tprime() * B;
146
147 // Calculate fundermental equation:
148 const double aa(alpha[0]);
149 const double aa2(aa * aa);
150 const double ab(alpha[1]);
151 const double ab2(ab * ab);
152 const double ac(alpha[2]);
153 const double ac2(ac * ac);
154
155 const double ba(beta[0]);
156 const double ba2(ba * ba);
157 const double bb(beta[1]);
158 const double bb2(bb * bb);
159 const double bc(beta[2]);
160 const double bc2(bc * bc);
161
162 const double da(D[0][0]);
163 const double da2(da * da);
164 const double db(D[1][1]);
165 const double db2(db * db);
166 const double dc(D[2][2]);
167 const double dc2(dc * dc);
168
170
171 T[0] = aa * ba + ab * bb + ac * bc + cc + aa2 * da + ab2 * db + ac2 * dc;
172
173 T[1] = -ba2 - bb2 - bc2 + 4 * ab * bb * da + 4 * ac * bc * da + 4 * cc * da + 4 * aa * ba * db + 4 * ac * bc * db +
174 4 * cc * db + 4 * aa2 * da * db + 4 * ab2 * da * db + 4 * aa * ba * dc + 4 * ab * bb * dc + 4 * cc * dc +
175 4 * aa2 * da * dc + 4 * ac2 * da * dc + 4 * ab2 * db * dc + 4 * ac2 * db * dc;
176
177 T[2] = -ba2 * da - 4 * bb2 * da - 4 * bc2 * da + 4 * ab * bb * da2 + 4 * ac * bc * da2 + 4 * cc * da2 - 4 * ba2 * db -
178 bb2 * db - 4 * bc2 * db + 16 * ac * bc * da * db + 16 * cc * da * db + 4 * ab2 * da2 * db + 4 * aa * ba * db2 +
179 4 * ac * bc * db2 + 4 * cc * db2 + 4 * aa2 * da * db2 - 4 * ba2 * dc - 4 * bb2 * dc - bc2 * dc +
180 16 * ab * bb * da * dc + 16 * cc * da * dc + 4 * ac2 * da2 * dc + 16 * aa * ba * db * dc + 16 * cc * db * dc +
181 16 * aa2 * da * db * dc + 16 * ab2 * da * db * dc + 16 * ac2 * da * db * dc + 4 * ac2 * db2 * dc +
182 4 * aa * ba * dc2 + 4 * ab * bb * dc2 + 4 * cc * dc2 + 4 * aa2 * da * dc2 + 4 * ab2 * db * dc2;
183
184 T[3] = -4 * bb2 * da2 - 4 * bc2 * da2 - 4 * ba2 * da * db - 4 * bb2 * da * db - 16 * bc2 * da * db +
185 16 * ac * bc * da2 * db + 16 * cc * da2 * db - 4 * ba2 * db2 - 4 * bc2 * db2 + 16 * ac * bc * da * db2 +
186 16 * cc * da * db2 - 4 * ba2 * da * dc - 16 * bb2 * da * dc - 4 * bc2 * da * dc + 16 * ab * bb * da2 * dc +
187 16 * cc * da2 * dc - 16 * ba2 * db * dc - 4 * bb2 * db * dc - 4 * bc2 * db * dc + 64 * cc * da * db * dc +
188 16 * ab2 * da2 * db * dc + 16 * ac2 * da2 * db * dc + 16 * aa * ba * db2 * dc + 16 * cc * db2 * dc +
189 16 * aa2 * da * db2 * dc + 16 * ac2 * da * db2 * dc - 4 * ba2 * dc2 - 4 * bb2 * dc2 + 16 * ab * bb * da * dc2 +
190 16 * cc * da * dc2 + 16 * aa * ba * db * dc2 + 16 * cc * db * dc2 + 16 * aa2 * da * db * dc2 +
191 16 * ab2 * da * db * dc2;
192
193 T[4] = -4 * bb2 * da2 * db - 16 * bc2 * da2 * db - 4 * ba2 * da * db2 - 16 * bc2 * da * db2 +
194 16 * ac * bc * da2 * db2 + 16 * cc * da2 * db2 - 16 * bb2 * da2 * dc - 4 * bc2 * da2 * dc -
195 16 * ba2 * da * db * dc - 16 * bb2 * da * db * dc - 16 * bc2 * da * db * dc + 64 * cc * da2 * db * dc -
196 16 * ba2 * db2 * dc - 4 * bc2 * db2 * dc + 64 * cc * da * db2 * dc + 16 * ac2 * da2 * db2 * dc -
197 4 * ba2 * da * dc2 - 16 * bb2 * da * dc2 + 16 * ab * bb * da2 * dc2 + 16 * cc * da2 * dc2 -
198 16 * ba2 * db * dc2 - 4 * bb2 * db * dc2 + 64 * cc * da * db * dc2 + 16 * ab2 * da2 * db * dc2 +
199 16 * aa * ba * db2 * dc2 + 16 * cc * db2 * dc2 + 16 * aa2 * da * db2 * dc2;
200
201 T[5] = -16 * bc2 * da2 * db2 - 16 * bb2 * da2 * db * dc - 16 * bc2 * da2 * db * dc - 16 * ba2 * da * db2 * dc -
202 16 * bc2 * da * db2 * dc + 64 * cc * da2 * db2 * dc - 16 * bb2 * da2 * dc2 - 16 * ba2 * da * db * dc2 -
203 16 * bb2 * da * db * dc2 + 64 * cc * da2 * db * dc2 - 16 * ba2 * db2 * dc2 + 64 * cc * da * db2 * dc2;
204
205 T[6] = 16 * da * db * dc * (-bc2 * da * db - bb2 * da * dc - ba2 * db * dc + 4 * cc * da * db * dc);
206
207 std::vector<double> TRange = T.realRoots(1e-10);
208 if (TRange.empty())
209 return -1.0;
210
211 double Out = -1;
212 Kernel::V3D xvec;
213 std::vector<double>::const_iterator vc;
214 for (vc = TRange.begin(); vc != TRange.end(); ++vc) {
215 const double daI = 1.0 + 2 * (*vc) * da;
216 const double dbI = 1.0 + 2 * (*vc) * db;
217 const double dcI = 1.0 + 2 * (*vc) * dc;
218 if ((daI * daI) > Tolerance || ((dbI * dbI) > Tolerance && (dcI * dcI) < Tolerance)) {
219 Kernel::Matrix<double> DI(3, 3);
220 DI[0][0] = 1.0 / daI;
221 DI[1][1] = 1.0 / dbI;
222 DI[2][2] = 1.0 / dcI;
223 xvec = R * (DI * (alpha - beta * *vc)); // care here: to avoid 9*9 +9*3 in
224 // favour of 9*3+9*3 ops.
225 const double Dist = xvec.distance(Pt);
226 if (Out < 0 || Out > Dist)
227 Out = Dist;
228 }
229 }
230 return Out;
231}
232
239{
240 const double res = eqnValue(Pt);
241 return (std::abs(res) <= Tolerance);
242}
243
249{
250 BaseEqn[9] += Pt[0] * (Pt[0] * BaseEqn[0] - BaseEqn[6]) + Pt[1] * (Pt[1] * BaseEqn[1] - BaseEqn[7]) +
251 Pt[2] * (Pt[2] * BaseEqn[2] - BaseEqn[8]) + BaseEqn[4] * Pt[0] * Pt[1] + BaseEqn[5] * Pt[0] * Pt[2] +
252 BaseEqn[6] * Pt[1] * Pt[2];
253 BaseEqn[6] += -2 * BaseEqn[0] * Pt[0] - BaseEqn[3] * Pt[1] - BaseEqn[4] * Pt[2];
254 BaseEqn[7] += -2 * BaseEqn[1] * Pt[1] - BaseEqn[3] * Pt[0] - BaseEqn[5] * Pt[2];
255 BaseEqn[8] += -2 * BaseEqn[2] * Pt[2] - BaseEqn[4] * Pt[0] - BaseEqn[5] * Pt[1];
256}
257
263{
265 MA.Invert();
266 const double a(MA[0][0]), b(MA[0][1]), c(MA[0][2]);
267 const double d(MA[1][0]), e(MA[1][1]), f(MA[1][2]);
268 const double g(MA[2][0]), h(MA[2][1]), j(MA[2][2]);
269 double B[9];
270 B[0] = BaseEqn[0] * a * a + BaseEqn[1] * d * d + BaseEqn[2] * g * g + BaseEqn[3] * a * d + BaseEqn[4] * a * g +
271 BaseEqn[5] * d * g;
272
273 B[1] = BaseEqn[0] * b * b + BaseEqn[1] * e * e + BaseEqn[2] * h * h + BaseEqn[3] * b * e + BaseEqn[4] * b * h +
274 BaseEqn[5] * e * h;
275
276 B[2] = BaseEqn[0] * c * c + BaseEqn[1] * f * f + BaseEqn[2] * j * j + BaseEqn[3] * c * f + BaseEqn[4] * c * j +
277 BaseEqn[5] * f * j;
278
279 B[3] = 2.0 * (BaseEqn[0] * a * b + BaseEqn[1] * d * e + BaseEqn[2] * g * h) + BaseEqn[3] * (a * e + b * d) +
280 BaseEqn[4] * (a * h + b * g) + BaseEqn[5] * (d * j + e * g);
281
282 B[4] = 2.0 * (BaseEqn[0] * a * c + BaseEqn[1] * d * f + BaseEqn[2] * g * j) + BaseEqn[3] * (a * f + c * d) +
283 BaseEqn[4] * (a * j + c * h) + BaseEqn[5] * (d * j + f * h);
284
285 B[5] = 2.0 * (BaseEqn[0] * b * c + BaseEqn[1] * e * f + BaseEqn[2] * h * j) + BaseEqn[3] * (b * f + c * e) +
286 BaseEqn[4] * (b * j + c * h) + BaseEqn[5] * (e * j + f * h);
287
288 B[6] = BaseEqn[6] * a + BaseEqn[7] * d + BaseEqn[8] * g;
289
290 B[7] = BaseEqn[6] * b + BaseEqn[7] * e + BaseEqn[8] * h;
291
292 B[8] = BaseEqn[6] * c + BaseEqn[7] * f + BaseEqn[8] * j;
293
294 for (int i = 0; i < 9; i++) // Item 9 left alone
295 BaseEqn[i] = B[i];
296}
297
303{
305 for (int i = 0; i < 10; i++)
306 logger.debug() << BaseEqn[i] << " ";
307 logger.debug() << '\n';
308}
309
310void Quadratic::write(std::ostream &OX) const
317{
318 std::ostringstream cx;
319 writeHeader(cx);
320 cx.precision(Surface::Nprecision);
321 cx << "gq ";
322 for (int i = 0; i < 4; i++)
323 cx << " " << BaseEqn[i] << " ";
324 cx << " " << BaseEqn[5] << " ";
325 cx << " " << BaseEqn[4] << " ";
326 for (int i = 6; i < 10; i++)
327 cx << " " << BaseEqn[i] << " ";
329}
330
331std::unique_ptr<Quadratic> Quadratic::clone() const { return std::unique_ptr<Quadratic>(doClone()); }
332
333} // namespace Mantid::Geometry
#define fabs(x)
Definition: Matrix.cpp:22
double distance(const Kernel::V3D &) const override
distance between point and surface (approx)
Definition: Quadratic.cpp:123
Kernel::V3D surfaceNormal(const Kernel::V3D &) const override
Normal at surface.
Definition: Quadratic.cpp:84
bool onSurface(const Kernel::V3D &) const override
is point valid on surface
Definition: Quadratic.cpp:233
std::vector< double > BaseEqn
Base equation (as a 10 point vector)
Definition: Quadratic.h:35
void displace(const Kernel::V3D &) override
Apply a general displacement to the surface.
Definition: Quadratic.cpp:244
void rotate(const Kernel::Matrix< double > &) override
Rotate the surface by matrix MX.
Definition: Quadratic.cpp:258
std::unique_ptr< Quadratic > clone() const
Definition: Quadratic.cpp:331
void matrixForm(Kernel::Matrix< double > &, Kernel::V3D &, double &) const
Converts the baseEqn into the matrix form such that.
Definition: Quadratic.cpp:101
void print() const override
Print out the genreal equation for debugging.
Definition: Quadratic.cpp:298
void write(std::ostream &) const override
Writes out an MCNPX surface description Note : Swap since base equation is swapped in gq output (mcnp...
Definition: Quadratic.cpp:310
int side(const Kernel::V3D &) const override
Determine if the the Point is true to the surface or on the other side.
Definition: Quadratic.cpp:68
Quadratic * doClone() const override=0
Abstract clone function.
double eqnValue(const Kernel::V3D &) const
Helper function to calcuate the value of the equation at a fixed point.
Definition: Quadratic.cpp:45
Holds a basic quadratic surface.
Definition: Surface.h:33
static const int Nprecision
Precision of the output.
Definition: Surface.h:41
virtual void print() const
Simple print out function for surface header.
Definition: Surface.cpp:63
Numerical Matrix class.
Definition: Matrix.h:42
T Invert()
LU inversion routine.
Definition: Matrix.cpp:924
Matrix< T > Tprime() const
Transpose the matrix.
Definition: Matrix.cpp:766
int Diagonalise(Matrix< T > &, Matrix< T > &) const
(only Symmetric matrix)
Definition: Matrix.cpp:1319
Class for 3D vectors.
Definition: V3D.h:34
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition: V3D.h:287
double normalize()
Make a normalized vector (return norm value)
Definition: V3D.cpp:130
Holds a polynominal as a primary type.
Definition: PolyBase.h:31
std::vector< double > realRoots(double const =-1.0)
Get just the real roots.
Definition: PolyBase.cpp:412
MANTID_KERNEL_DLL void writeMCNPX(const std::string &Line, std::ostream &OX)
Write file in standard MCNPX input form.
Definition: Strings.cpp:421
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12