math-library
/
Engine.cpp
420 строк · 9.4 Кб
1
2#include <assert.h>
3#include <iostream>
4#include <fstream>
5#include <math.h>
6
7#include "Constants.h"
8#include "Engine.h"
9
10#define L(x1,x2) (fabs(x1-x2))
11
12using namespace std;
13
14void Progonka(int N, CMatrix &A,CMatrix &B,CMatrix &C,CMatrix &F, double m1,double n1,double m2,double n2, CMatrix &Y)
15{
16CMatrix Alpha(N+1), Beta(N+1);
17
18Alpha(1) = m1; Beta(1) = n1;
19for(int i=1; i<N; i++)
20{
21Alpha(i+1) = B(i)/(C(i) - A(i)*Alpha(i));
22Beta(i+1) = (A(i)*Beta(i) + F(i))/(C(i) - A(i)*Alpha(i));
23}
24
25Y(N) = (n2 + m2*Beta(N))/(1 - m2*Alpha(N));
26for(int i=N-1; i>=0; i--) Y(i) = Alpha(i+1)*Y(i+1) + Beta(i+1);
27}
28
29double Simpson(CInterval &AB, double (*getF)(double))
30{
31if(AB.N() % 2) AB.ReBorn(AB.X1(), AB.X2(), AB.N()+1); //N должно быть четным
32
33double I = 0;
34
35for(int i=1; i<AB.N(); i+=2) I += getF(AB.X(i));
36I *= 2;
37for(int i=2; i<=AB.N()-2; i+=2) I += getF(AB.X(i));
38I = AB.H()/3.*(
39getF(AB.X1()) + I*2 + getF(AB.X2())
40);
41
42return I;
43}
44
45void mSOLVE(CMatrix &a, CMatrix &b, CMatrix &X)
46{
47int Size = a.GetM();
48assert(a.GetN() == Size && b.GetM() == Size);
49
50CMatrix A(a), B(b); //Создаем копии матриц, т.к. над ними проводим действия
51
52//Приведение матрицы к треугольному виду
53for(int Curr=0; Curr<Size; Curr++)
54{
55int MaxNm = Curr;
56
57//Поиск максимального элемента в столбце Curr
58for(int i=Curr+1; i<Size; i++)
59if(A(i,Curr)>A(i,MaxNm)) MaxNm = i;
60
61//Перестановка строк
62if(MaxNm!=Curr)
63{
64A.SwapLines(Curr,MaxNm); B.SwapLines(Curr,MaxNm);
65}
66
67//Деление на коэффициент при первом члене
68B(Curr) = B(Curr)/A(Curr,Curr);
69for(int i=Size-1; i>=Curr; i--) A(Curr,i) = A(Curr,i)/A(Curr,Curr);
70
71//Вычитание строк
72for(int line=Curr+1; line<Size; line++)
73{
74B(line) = B(line) - B(Curr)*A(line,Curr);
75for(int i=Size-1; i>=Curr; i--)
76A(line,i) = A(line,i) - A(Curr,i)*A(line,Curr);
77}
78}
79
80//Нахождение решения системы по треугольной матрице
81double d;
82for(int i=Size-1; i>=0; i--)
83{
84d = B(i);
85for(int j=i+1; j<Size; j++) d -= A(i,j)*X(j);
86X(i) = d/A(i,i);
87}
88}
89
90void mINV(CMatrix &A, CMatrix &invA)
91{
92assert(A.GetN() == A.GetM());
93
94int Size = A.GetM();
95invA.SetSize(Size,Size);
96
97CMatrix E(Size),T(Size);
98for(int i=0; i<Size; i++)
99{
100E = 0; E(i) = 1;
101mSOLVE(A,E,T);
102
103for(int j=0; j<Size; j++) invA(j,i) = T(j);
104}
105}
106
107double mDET(CMatrix &A)
108{
109int Size = A.GetM();
110assert(A.GetN() == Size);
111
112int NSw = 0; //Количество перестановок строк
113
114//Приведение матрицы к треугольному виду
115for(int Curr=0; Curr<Size; Curr++)
116{
117int MaxNm = Curr;
118
119//Поиск максимального элемента в столбце Curr
120for(int i=Curr+1; i<Size; i++) if(A(i,Curr)>A(i,MaxNm)) MaxNm = i;
121
122//Перестановка строк
123if(MaxNm!=Curr) { A.SwapLines(Curr,MaxNm); NSw++; }
124
125//Деление на коэффициент при первом члене
126// for(i=Size-1; i>=Curr; i--) A(Curr,i) = A(Curr,i)/A(Curr,Curr);
127
128//Вычитание строк
129for(int line=Curr+1; line<Size; line++)
130for(int i=Size-1; i>=Curr; i--) A(line,i) = A(line,i) - A(Curr,i)/A(Curr,Curr)*A(line,Curr);
131}
132
133double DET = (NSw % 2) ? -1:1;
134for(int i=0; i<Size; i++) DET *= A(i,i);
135
136return DET;
137}
138
139double FindMinMax(CInterval &AB, double(*f)(double), int find_max)
140{
141double x[4];
142x[0] = AB.X1(); x[2] = AB.X2();
143x[1] = x[0] + 2/(3+sqrt(5))*(x[2]-x[0]);
144
145while(x[2]-x[0]>AB.H())
146{
147x[3] = x[0]+x[2]-x[1];
148int m_i = 0, f_i = 0;
149
150//поиск минимальной из 4 точек
151for(int i=1; i<4; i++) if(find_max*(f(x[i])-f(x[m_i])) > 0) m_i = i;
152
153//поиск наиболее удаленной от минимума точки
154for(int i=1; i<4; i++) if(L(x[m_i],x[i]) > L(x[m_i],x[f_i])) f_i = i;
155
156//перенумеровываем точки, чтобы наиболее удаленная стала 4-й
157if(f_i!=3) x[f_i] = x[3];
158
159//упорядочение
160double d;
161
162for(m_i=0; m_i<=1; m_i++)
163{
164int min = m_i;
165for(int i=1; i<=2; i++) if(x[i]<x[m_i]) min = i;
166
167d = x[min];
168x[min] = x[m_i];
169x[m_i] = d;
170}
171}
172return 0.5*(x[2]+x[0]);
173}
174
175void SaveFunc(CInterval &AB, double (*func)(int), char *fname)
176{
177ofstream f(fname);
178for(int i=0; i<=AB.N(); i++) f<< AB.X(i) <<" "<< func(i) <<"\n";
179f.close();
180}
181
182void SaveFunc(CInterval &AB, double (*func)(double), char *fname)
183{
184ofstream f(fname);
185for(int i=0; i<=AB.N(); i++) f<< AB.X(i) <<" "<< func(AB.X(i)) <<"\n";
186f.close();
187}
188
189void SaveFunc(CInterval &t, double(*x)(double), double (*func)(double), char *fname)
190{
191ofstream f(fname);
192for(int i=0; i<=t.N(); i++) f<< x( t.X(i) )<<" "<< func( t.X(i) ) <<"\n";
193f.close();
194}
195
196void SaveCorrelationFunc(CMatrix &A, char *fname, double precision)
197{
198assert(0<precision && precision<=1 && A.GetM()>=1);
199
200double Min = A.Min(), Max = A.Max();
201CInterval AB(Min, Max, (Max-Min)*precision);
202CMatrix P(AB.N(),2); //Частоты
203P = 0;
204
205for(int i=0; i<A.GetM(); i++)
206{
207double f_i = A(i);
208int num_of_f_i = AB.i(f_i);
209
210if(num_of_f_i != AB.N()) //CInterval включает обе границы диапазона 0..N; CMatrix - только 0
211{
212P(num_of_f_i,0) = A(i);
213P(num_of_f_i,1) += 1;
214}
215}
216
217//Нормировка
218//
219double max = P(0,1);
220for(int i=1; i<P.GetM(); i++) if(P(i,1) > max) max = P(i,1);
221for(int i=0; i<P.GetM(); i++) P(i,1) /= max;
222
223P.Save(fname);
224}
225
226void SaveCorrelationFunc(CInterval &AB, double (*func)(double), char *fname, double precision)
227{
228CMatrix A(AB.N());
229for(int i=0; i<AB.N(); i++) A(i) = func(AB.X(i));
230
231SaveCorrelationFunc(A,fname,precision);
232}
233
234CMatrix::CMatrix(int m, int n)
235{
236assert(m>=1 && n>=0);
237pData = new double[(M = m)*(N = n)];
238assert(pData);
239}
240
241void CMatrix::Save(char *fname, bool orig_view)
242{
243ofstream f(fname);
244
245if(orig_view)
246for(int i=0; i<M; i++)
247{
248for(int j=0; j<N; j++) f<< (*this)(i,j) <<" ";
249f<<"\n";
250}
251else
252for(int j=0; j<N; j++)
253{
254for(int i=0; i<M; i++) f<< (*this)(i,j) <<" ";
255f<<"\n";
256}
257
258f.close();
259}
260
261void CMatrix::SwapLines(int m1, int m2)
262{
263assert(m1<M && m2<M && m1>=0 && m2>=0);
264
265double el;
266for(int i=0; i<N; i++)
267{
268el = *(pData + m1*N + i);
269*(pData + m1*N + i) = *(pData + m2*N + i);
270*(pData + m2*N + i) = el;
271}
272}
273
274void CMatrix::SwapCols(int n1, int n2)
275{
276assert(n1<N && n2<N && n1>=0 && n2>=0);
277
278double el;
279for(int i=0; i<N; i++)
280{
281el = *(pData + i*N + n1);
282*(pData + i*N + n1) = *(pData + i*N + n2);
283*(pData + i*N + n2) = el;
284}
285}
286
287CMatrix &CMatrix::operator=(CMatrix &right)
288{
289if(&right != this)
290{
291SetSize(right.M,right.N);
292
293for(int i=0; i<M; i++)
294for(int j=0; j<N; j++) *(pData + i*N + j) = *(right.pData + i*N + j);
295}
296return *this;
297}
298
299CMatrix &CMatrix::operator=(double d)
300{
301for(int i=0; i<M; i++)
302for(int j=0; j<N; j++) *(pData + i*N + j) = d;
303
304return *this;
305}
306
307CMatrix &CMatrix::operator-()
308{
309for(int i=0; i<M; i++)
310for(int j=0; j<N; j++) *(pData + i*N + j) = -(*(pData + i*N + j));
311
312return *this;
313}
314
315bool CMatrix::operator==(CMatrix &right)
316{
317assert(M==right.M && N==right.N);
318
319for(int i=0; i<M; i++)
320for(int j=0; j<N; j++) if(*(pData + i*N + j) != *(right.pData + i*N + j)) return false;
321
322return true;
323}
324
325double Round(double d)
326{
327double r = ceil(d); //Использование (int) недопустимо!
328if(fabs(d-r) > 0.5) return r += sign(d); else return r;
329}
330
331CMatrix::~CMatrix()
332{
333if(!pData) delete [] pData;
334}
335
336void CMatrix::SetSize(int m, int n) //!Память не освобождается, если L-массив УЖЕ имеет нужные размеры
337{
338assert(m>=1 && n>=0);
339
340if(M!=m || N!=n)
341{
342if(!pData) delete [] pData;
343pData = new double[(M = m)*(N = n)];
344assert(pData);
345}
346}
347
348double CMatrix::Max()
349{
350double Max = (*this)(0,0);
351
352for(int i=0; i<M; i++)
353for(int j=0; j<N; j++) if((*this)(i,j)>Max) Max = (*this)(i,j);
354
355return Max;
356}
357
358double CMatrix::Min()
359{
360double Min = (*this)(0,0);
361
362for(int i=0; i<M; i++)
363for(int j=0; j<N; j++) if((*this)(i,j)<Min) Min = (*this)(i,j);
364
365return Min;
366}
367
368CMatrix::CMatrix(CMatrix &M)
369{
370*this = M;
371}
372
373void empty_func(CLattice &Lattice) {}
374
375void MMD(CLattice &Lattice, double dt, int StepsCount, bool sEnergy, void (*func)(CLattice &))
376{
377int i,k, N = Lattice.N;
378CMatrix F1(N,3),F2(N,3);
379double t_2 = dt/2.;
380bool flag;
381
382Lattice.CalcForces(F1);
383
384double E0 = Lattice.getE_k() + Lattice.getU(); //Потенциальная энергия известна только после вызова CalcForces()
385
386for(int step=0; step<StepsCount; step++)
387{
388for(k=0; k<3; k++)
389for(i=0; i<N; i++) Lattice.XYZ(i,k) += dt*(Lattice.VXYZ(i,k) + t_2*F1(i,k));
390
391flag = CheckValue(Lattice.XYZ,Lattice.L); //Вылетевшие частицы впускаем через противоположную стенку
392if(!flag) //Проверка, не пролетает ли частица за dt больше L
393{
394cout<< "\nstep = "<< step <<"\n! dt is large !\n" <<endl; exit(1);
395}
396
397Lattice.CalcForces(F2);
398
399for(k=0; k<3; k++)
400for(i=0; i<N; i++) Lattice.VXYZ(i,k) += t_2*(F1(i,k) + F2(i,k));
401F1 = F2;
402
403if(sEnergy)
404{
405double H = 0;
406for(k=0; k<3; k++)
407for(i=0; i<N; i++) H += pow(Lattice.VXYZ(i,k),2) + pow(F2(i,k),2);
408
409double dE_H = (Lattice.getE_k()+Lattice.getU() - E0)/H;
410
411for(k=0; k<3; k++)
412for(i=0; i<N; i++)
413{
414Lattice.XYZ(i,k) += F2(i,k)*dE_H;
415Lattice.VXYZ(i,k) -= Lattice.VXYZ(i,k)*dE_H;
416}
417} //if
418
419func(Lattice);
420}
421}