Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.29 KB | None | 0 0
  1. #include "stdafx.h"
  2. #define _USE_MATH_DEFINES
  3. # include <iostream>
  4. #include <fstream>
  5. #include <cmath>
  6. #include <math.h>
  7. using namespace std;
  8.  
  9. const double D = 1.0;
  10. const double lambda = 1; //dla metod posrednich
  11. double h = 0.02; //krok dla x
  12. double dt = (lambda*h*h) / D; //krok dla t
  13. const double x_max = 1; //maksymalny przedzial x
  14. const double x_min = 0; //minimalny przedzial x
  15. const double t_max = 0.5; //maksymalny przedzial x
  16. const double t_min = 0; //minimalny przedzial x
  17.  
  18. //wymiary macierzy do obliczeń numerycznych:
  19. int M = (int)((x_max - x_min) / h) + 1; //liczba kolumn (x) 11
  20. int N = (int)((t_max / dt) + 1); //liczba wierszy(t) 51
  21.  
  22. void rozwiazanie_analityczne(double **Analityczne)
  23. {
  24. fstream zapis;
  25. double x = x_min + h; //zmienna wartosci przestrzennej
  26. double t = dt; //zmienna kroku czasowego
  27.  
  28. zapis.open("rozw_analit.txt", ios::out);
  29.  
  30. //wyzerowanie macierzy rozwiązań analitycznych
  31. for (int i = 0; i < N; i++)
  32. for (int j = 0; j < M; j++)
  33. Analityczne[i][j] = 0.0;
  34. //wpisanie do macierzy wartości wynikłych z warunków początkowych i brzegowych
  35. //warunek poczatkowy
  36. for (int j = 0; j < M; j++)
  37. {
  38. x = h*(double)j + x_min;
  39. Analityczne[0][j] = 1.0 + cos(M_PI*x);
  40. x = x + h;
  41. }
  42. //warunki brzegowe
  43. for (int i = 1; i < N; i++)
  44. {
  45. Analityczne[i][0] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI * 0);
  46. Analityczne[i][M - 1] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI * 1); // zapisujemy do macierzy wartości wyliczone
  47. t = t + dt; //krok t
  48. }
  49. t = dt;
  50. x = x_min + h;
  51. //POZOSTAŁE PUNKTY SIATKI
  52. for (int i = 1; i < N; i++)
  53. {
  54. for (int j = 1; j < M - 1; j++)
  55. {
  56. Analityczne[i][j] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI*x); // zapisujemy do macierzy wartości wyliczone
  57. x = x + h;
  58. }
  59. x = x_min + h; //przywrócenie x do początku
  60. t = t + dt;
  61. }
  62.  
  63. //zapisujemy wyniki rozwiązania analitycznego do pliku
  64. for (int i = 0; i < N; i++)
  65. {
  66. for (int j = 0; j < M; j++)
  67. {
  68. zapis << Analityczne[i][j] << "; ";
  69. }
  70. zapis << endl;
  71. }
  72. zapis.close();
  73. }
  74.  
  75. void operacje_na_macierzy(double *l, double *u, double *d)
  76. {
  77. for (int i = 1; i < M; i++)
  78. {
  79. d[i] = d[i] - l[i - 1] * u[i - 1] / d[i - 1]; //faza eliminacji wprzód
  80. }
  81. }
  82.  
  83. void operacje_na_wektorze(double *b, double *u, double *d, double *l, double *x)
  84. {
  85. for (int i = 1; i < M; i++)
  86. {
  87. b[i] = b[i] - l[i - 1] * b[i - 1] / d[i - 1];
  88. }
  89. x[M - 1] = b[M - 1] / d[M - 1];
  90. for (int i = M - 2; i >= 0; i--)
  91. {
  92. x[i] = (b[i] - u[i] * x[i + 1]) / d[i];
  93. }
  94. }
  95.  
  96. void SOR(double **A, double *b, double *x)
  97. {
  98. double *x0_pom = new double[M];
  99. double *x0 = new double[M];
  100. double sum = 0.0;
  101. double EST = 1e-6;
  102. double omega = 0.4;
  103. double max_diff;
  104. double diff;
  105. for (int i = 0; i < M; i++)
  106. x0[i] = 0.0;
  107.  
  108. for (int i = 0; i < 100; i++) //liczba iteracji
  109. {
  110. for (int x = 0; x < M; x++)
  111. x0_pom[x] = x0[x];
  112.  
  113. for (int j = 0; j < M; j++)
  114. {
  115. sum = (1.0 - 1.0 / omega)*A[j][j] * x0[j];
  116. for (int k = j + 1; k <M; k++)
  117. sum += A[j][k] * x0_pom[k];
  118.  
  119. for (int k = 0; k < j; k++)
  120. sum += A[j][k] * x0_pom[k];
  121.  
  122. x0[j] = (b[j] - sum)*omega / A[j][j];
  123. }
  124. //sprawdzenie czy różnica pomiędzy kolejnymi przybliżeniami jest mniejsza od zadanej wielkości
  125. //poszukiwanie normy max z wektora rozwiązań
  126. max_diff = fabs(x0_pom[0] - x0[0]);
  127. for (int k = 1; k < M; k++)
  128. {
  129. diff = fabs(x0_pom[k] - x0[k]);
  130. if (diff > max_diff)
  131. max_diff = diff;
  132. }
  133. if (max_diff<EST)
  134. break;
  135. }
  136. for (int i = 0; i < M; i++)
  137. x[i] = x0[i];
  138. delete[] x0_pom;
  139. delete[] x0;
  140. }
  141.  
  142. void Crank_Nicolson(double **A)
  143. {
  144. fstream zapis;
  145. double *l, *d, *u; // wektory L, D, U
  146. double *b, *xrozw; // wektor wyrazów wolnych oraz wektor rozwiązań
  147. double xpom;
  148. l = new double[M];
  149. d = new double[M];
  150. u = new double[M];
  151. b = new double[M];
  152. xrozw = new double[M];
  153.  
  154. zapis.open("thomas.txt", ios::out);
  155. //wpisanie do macierzy wartości wynikłych z warunków początkowych i brzegowych
  156. //WARUNEK POCZĄTKOWY
  157. for (int j = 0; j < M; j++)
  158. {
  159. xpom = h*(double)j + x_min;
  160. A[0][j] = 1.0 + cos(M_PI*xpom);
  161. }
  162.  
  163. double t = dt;
  164. //BRZEGOWE
  165. for (int i = 1; i < N; i++)
  166. {
  167. A[i][0] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI*0);
  168. A[i][M -1] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI*1); // zapisujemy do macierzy wartości wyliczone
  169. t = t + dt; //krok t
  170. }
  171. t = dt;
  172. // wypełnienie l, d, u
  173. for (int j = 0; j < M; j++)
  174. l[j] = lambda / 2.0; //LOWER
  175. l[M - 2] = -1/h; //M-2
  176.  
  177. for (int j = 1; j < M - 1; j++) //DIAGONAL
  178. d[j] = -(1.0 + lambda);
  179. d[0] = -1.0 / h;
  180. d[M - 1] = 1.0/h;
  181.  
  182. for (int j = 1; j < M; j++) //UPPER
  183. u[j] = lambda / 2.0;
  184. u[0] = 1.0/h;
  185.  
  186. //operacje na l,d,u
  187. operacje_na_macierzy(l, u, d);
  188.  
  189. //pętla do obliczania przybliżeń dla kroku czasowego
  190. for (int i = 0; i < N - 1; i++)
  191. {
  192. //wypełniamy wektor wyrazów wolnych
  193. b[0] = 0.0;
  194. b[M - 1] = 0.0;
  195.  
  196. for (int j = 1; j < M - 1; j++)
  197. {
  198. b[j] = -(lambda / 2.0)*A[i][j - 1] - (1 - lambda)*A[i][j] -(lambda / 2.0)*A[i][j + 1];
  199. }
  200.  
  201.  
  202. //druga część Thomasa
  203. operacje_na_wektorze(b, u, d, l, xrozw);
  204.  
  205. //przepisanie wyników do macierzy A
  206. for (int j = 1; j<M - 1; j++)
  207. A[i + 1][j] = xrozw[j];
  208. }
  209.  
  210. //zapis do pliku macierzy A
  211. for (int i = 0; i < N; i++)
  212. {
  213. for (int j = 0; j < M; j++)
  214. {
  215. zapis << A[i][j] << "; ";
  216. }
  217. zapis << endl;
  218. }
  219. zapis.close();
  220. delete[] l;
  221. delete[] d;
  222. delete[] u;
  223. delete[] b;
  224. delete[] xrozw;
  225. }
  226.  
  227. void Crank_Nicolson_SOR(double **A)
  228. {
  229. fstream zapis;
  230. double ** macierz; //MACIERZ POMOCNICZA
  231. double *b, *xrozw; //WEKTOR WYRAZÓW WOLNYCH ORAZ POMOCNICZY WKTOR ROZWIĄZAŃ
  232. double xpom;
  233.  
  234. b = new double[M];
  235. xrozw = new double[M];
  236. macierz = new double *[M];
  237. for (int i = 0; i < M; i++)
  238. macierz[i] = new double[M];
  239. zapis.open("SOR.txt", ios::out);
  240. //wpisanie do macierzy wartości wynikłych z warunków początkowych i brzegowych
  241. //WARUNEK POCZĄTKOWY
  242.  
  243. for (int j = 0; j < M; j++)
  244. {
  245. xpom = h*(double)j + x_min;
  246. A[0][j] = 1.0 + cos(M_PI*xpom);
  247. xpom = xpom + h;
  248. }
  249.  
  250. double t = dt;
  251. //BRZEGOWE
  252. for (int i = 1; i < N; i++)
  253. {
  254. A[i][0] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI * 0);
  255. A[i][M - 1] = 1 + exp(-(M_PI*M_PI)*D*t)*cos(M_PI * 1); // zapisujemy do macierzy wartości wyliczone
  256. t = t + dt; //krok t
  257. }
  258. t = dt;
  259.  
  260. //WYZEROWANIE MACIERZY POMOCNICZEJ
  261. for (int i = 0; i < M; i++)
  262. for (int j = 0; j < M; j++)
  263. macierz[i][j] = 0.0;
  264. // PRZYGOTOWANIE MACIERZY TRÓJDIAGONALNEJ
  265. macierz[1][0] = lambda / 2.0;
  266. macierz[0][0] = -1.0/h;
  267. macierz[0][1] = 1.0/h;
  268. for (int j = 1; j < M - 1; j++)
  269. {
  270. macierz[j + 1][j] = lambda / 2.0; //LOWER
  271. macierz[j][j] = -(1.0 + lambda); //DIAGONAL
  272. macierz[j][j + 1] = lambda / 2.0; //UPPER
  273. }
  274. macierz[M - 1][M - 1] = 1.0/h;
  275. macierz[M - 1][M - 2] = -1.0/h;
  276.  
  277.  
  278. //ROZPOCZYNAMY PĘTLE W KTÓREJ OBLICZAMY KOLEJNE PRZYBLIŻENIA DLA KOLEJNYCH
  279. //PUNKTÓW NA LINII CZASOWEJ
  280. for (int i = 0; i < N - 1; i++)
  281. {
  282.  
  283. //WYPEŁNIAMY WARTOŚCIAMI WEKTOR WYRAZÓW WOLNYCH
  284. b[0] = 0.0;
  285. b[M - 1] = 0.0;
  286. for (int j = 1; j < M - 1; j++)
  287. b[j] = -(lambda / 2.0)*A[i][j - 1] - (1 - lambda)*A[i][j] - (lambda / 2.0)*A[i][j + 1];
  288.  
  289.  
  290. //ROZWIĄZUJEMY UKŁAD ALGEBRAICZNYCH RÓWNAŃ LINIOWYCH
  291. //METODĄ SOR
  292. SOR(macierz, b, xrozw);
  293.  
  294. //PRZEPISUJEMY WARTOŚCI Z WEKTORA DO MACIERZY ROZWIĄZAŃ
  295. for (int j = 1; j<M - 1; j++)
  296. A[i + 1][j] = xrozw[j];
  297. }
  298. //ZAPISUJEMY MACIERZ ROZWIĄZAŃ NUMERYCZNYCH METODĄ SOR DO PLIKU
  299. for (int i = 0; i < N; i++)
  300. {
  301. for (int j = 0; j < M; j++)
  302. {
  303. zapis << A[i][j] << "; ";
  304. }
  305. zapis << endl;
  306. }
  307. zapis.close();
  308.  
  309. for (int i = 0; i < M; i++)
  310. delete[] macierz[i];
  311. delete[] macierz;
  312. delete[] b;
  313. delete[] xrozw;
  314. }
  315.  
  316. double blad(double **Blad, double **rozwiazanie, double **analityczne, int met)
  317. {
  318. double *blad_max = new double[N];
  319.  
  320. fstream zapis;
  321. fstream zapis2;
  322. if (met) //SPRAWDZAMY DLA KTÓREJ METODY OBLICZAMY BŁĄD
  323. {//I OTWIERAMY ODPOWIEDNIE PLIKI DO ZAPISU
  324. zapis.open("blad_max_thomas.txt", ios::out);
  325. zapis2.open("blad_thomas.txt", ios::out);
  326. }
  327. else
  328. {
  329. zapis.open("blad_max_sor.txt", ios::out);
  330. zapis2.open("blad_SOR.txt", ios::out);
  331. }
  332. // ZERUJEMY WEKTOR BŁĘDÓW MAX
  333. for (int i = 0; i < N; i++)
  334. blad_max[i] = 0.0;
  335. //OBLICZAMY MACIERZ BŁĘDÓW DLA ZADANEJ METODY
  336. for (int i = 0; i < N; i++)
  337. {
  338. for (int j = 0; j < M; j++)
  339. {
  340. Blad[i][j] = fabs(analityczne[i][j] - rozwiazanie[i][j]);
  341. zapis2 << Blad[i][j] << "; ";
  342. //OBLICZAMY BŁĄD MAX DLA DANEJ CHWILI CZASU
  343. if (Blad[i][j]>blad_max[i])
  344. blad_max[i] = Blad[i][j];
  345. }
  346. zapis2 << endl;
  347. }
  348. for (int i = 0; i < N; i++)
  349. zapis << blad_max[i] << " ";
  350.  
  351. //OBLICZAMY MAX WARTOŚĆ BEZWZGLĘDNĄ DLA CZASU TMAX
  352. double tmp = Blad[N - 1][0];
  353. for (int i = 1; i < M; i++)
  354. {
  355. if (Blad[N - 1][i]>tmp)
  356. tmp = Blad[N - 1][i];
  357. }
  358. if (met)
  359. cout << "Thomas:" << h << " " << tmp <<endl;
  360. else
  361. cout << "SOR " << h << " " << tmp << endl;
  362. return tmp;
  363. zapis.close();
  364. zapis2.close();
  365. }
  366.  
  367. void zapisz_kroki()
  368. {
  369. double czas = 0.0;
  370. double przestrzen;
  371. fstream k_czas;
  372. fstream k_przestrzenne;
  373.  
  374. k_czas.open("kroki_czasowe.txt", ios::out);
  375. k_przestrzenne.open("kroki_przestrzenne.txt", ios::out);
  376.  
  377. przestrzen = x_min;
  378. //ZAPISUJEMY DO PLIKU KOLEJNE PUNKTY CZASOWE
  379. for (int i = 0; i < N; i++)
  380. {
  381. czas = dt*(double)i;
  382. k_czas << czas << endl;
  383. }
  384. //ZAPISUJEMY DO PLIKU KOLEJNE PUNKTY PRZESTRZENNE
  385. for (int i = 0; i < M; i++)
  386. {
  387. przestrzen = h*(double)i + x_min;
  388. k_przestrzenne << przestrzen << " ";
  389. }
  390. k_czas.close();
  391. k_przestrzenne.close();
  392. }
  393.  
  394. int _tmain(int argc, _TCHAR* argv[])
  395. {
  396. fstream bladd;
  397. bladd.open("bladmaxkrok.txt", ios::out);
  398. int tmp = 6;
  399. while (tmp<7)
  400. {
  401. dt = (lambda*h*h) / D;
  402. N = (int)(t_max / dt) + 2;
  403. M = (int)((x_max - x_min) / h) + 1;
  404. double **Analityczne; //macierz rozwiązań analitycznych
  405. double **rozw_thomas;//macierz rozwiązań numerycznych algorytmem thomasa
  406. double **rozw_SOR; //macierz rozwiązań numerycznych metodą SOR
  407. double **Blad;
  408. rozw_thomas = new double*[N];
  409. rozw_SOR = new double*[N];
  410. Analityczne = new double *[N];
  411. Blad = new double *[N];
  412.  
  413. for (int i = 0; i < N; i++)
  414. { //ALOKACJA PAMIĘCI
  415. Analityczne[i] = new double[M];
  416. rozw_thomas[i] = new double[M];
  417. rozw_SOR[i] = new double[M];
  418. Blad[i] = new double[M];
  419. }
  420.  
  421. bladd << h << " ";
  422. zapisz_kroki(); //ZAPISUJEMY KROKI CZASOWE I PRZESTRZENNE DO PLIKU
  423. rozwiazanie_analityczne(Analityczne); //OBLICZAMY I ZAPISUJEMY ROZWIĄZANIA ANALITYCZNE
  424. Crank_Nicolson(rozw_thomas); //OBLICZAMY ROZWIĄZANIA NUMERYCZNE ZA POMOCĄ ALGORYTMU THOMASA
  425. bladd << blad(Blad, rozw_thomas, Analityczne, 1) << " " << endl;//OBLCZAMY BŁĘDY ORAZ ZAPISUJEMY JE DO PLIKU
  426. Crank_Nicolson_SOR(rozw_SOR); //OBLICZAMY ROZWIĄZANIA NUMERYCZNE ZA POMOCĄ METODY SOR
  427. bladd << blad(Blad, rozw_SOR, Analityczne, 0) << endl; //OBLCZAMY BŁĘDY ORAZ ZAPISUJEMY JE DO PLIKU
  428.  
  429. for (int i = 0; i < N; i++) //ZWALNIAMY PAMIĘĆ
  430. {
  431. delete[] Analityczne[i];
  432. delete[] rozw_thomas[i];
  433. delete[] rozw_SOR[i];
  434. delete[] Blad[i];
  435. }
  436. delete[] Analityczne;
  437. delete[] rozw_thomas;
  438. delete[] rozw_SOR;
  439. delete[] Blad;
  440. h = h/2;
  441. tmp++;
  442. }
  443. bladd.close();
  444. system("pause");
  445. return 0;
  446. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement