Advertisement
manac68974

Untitled

Dec 4th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.17 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <algorithm>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. #define A1 -2
  9. #define A2 3
  10. #define B1 -1
  11. #define B2 4
  12. #define M 20
  13. #define N 20
  14. #define SIZE (M + 1) * (N + 1)
  15.  
  16. const double h1 = (A2 - A1) * 1.0 / M;
  17. const double h2 = (B2 - B1) * 1.0 / N;
  18.  
  19. vector<double> w;
  20. vector<double> old_w;
  21.  
  22. // exact solution u(x, y)
  23. double u(double x, double y) {
  24. return 2.0 / (1 + pow(x, 2) + pow(y, 2));
  25. }
  26.  
  27. double k(double x, double y) {
  28. return 1 + pow(x + y, 2);
  29. }
  30.  
  31. // potential function
  32. double q(double x, double y) {
  33. return 1;
  34. }
  35.  
  36. // psi_R(x, y) = k(A2, y) * du/dx(A2, y)
  37. double psi_R(double y) {
  38. return (-12) * (pow((y + 3), 2) + 1) / pow((pow(y, 2) + 10), 2);
  39. }
  40.  
  41. // psi_L(x, y) = -k(A1, y) * du/dx(A1, y)
  42. double psi_L(double y) {
  43. return (-8) * (pow((y - 2), 2) + 1) / pow((pow(y, 2) + 5), 2);
  44. }
  45.  
  46. // psi_T(x, y) = k(x, B2) * du/dy(x, B2)
  47. double psi_T(double x) {
  48. return (-16) * (pow((x + 4), 2) + 1) / pow((pow(x, 2) + 17), 2);
  49. }
  50.  
  51. // psi_B(x, y) = -k(x, B2) * du/dy(x, B2)
  52. double psi_B(double x) {
  53. return (-4) * (pow((x - 1), 2) + 1) / pow((pow(x, 2) + 2), 2);
  54. }
  55.  
  56. // right-part function of Poisson equation
  57. double F(double x, double y) {
  58. return 2 * (pow(x,4) + pow(y,4) + 2 * (pow(x,2) + 3) * pow(y,2) + 6 * pow(x,2) + 16*x*y + 5)
  59. / pow((1 + pow(x, 2) + pow(y, 2)), 3);
  60. }
  61.  
  62.  
  63. double Get(int i, int j){
  64. return w[j*(M + 1) + i];
  65. }
  66.  
  67.  
  68. void CalculateExactSolution(vector<double> &exact) {
  69. for (int i = 0; i < M + 1; ++i)
  70. for (int j = 0; j < N + 1; ++j)
  71. exact[j * (M + 1) + i] = u(A1 + i * h1, B1 + j * h2);
  72.  
  73. //cout << "Exact solution of Poisson equation:" << endl;
  74. //PrintVector(exact);
  75. //cout << endl;
  76. }
  77.  
  78.  
  79. int IsNodeInternalCornerOrSide(int current_node_global_offset_x, int current_node_global_offset_y){
  80.  
  81. //corners
  82. //left bottom corner
  83. if (current_node_global_offset_x == 0 && current_node_global_offset_y == 0){
  84. return 2;
  85. }
  86.  
  87. //left top corner
  88. if (current_node_global_offset_x == 0 && current_node_global_offset_y == N){
  89. return 4;
  90. }
  91.  
  92. //right bottom corner
  93. if (current_node_global_offset_x == M && current_node_global_offset_y == 0){
  94. return 6;
  95. }
  96.  
  97. //right top corner
  98. if (current_node_global_offset_x == M && current_node_global_offset_y == N){
  99. return 8;
  100. }
  101.  
  102. //sides
  103. //left side
  104. if (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1 &&
  105. current_node_global_offset_x == 0){
  106. return 1;
  107. }
  108.  
  109. //right side
  110. if (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1 &&
  111. current_node_global_offset_x == M){
  112. return 3;
  113. }
  114.  
  115. //bottom side
  116. if (current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1 &&
  117. current_node_global_offset_y == 0){
  118. return 5;
  119. }
  120.  
  121. //top side
  122. if ((current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1 &&
  123. current_node_global_offset_y == N)){
  124. return 7;
  125. }
  126.  
  127. //internal
  128. if ((current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1) &&
  129. (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1)){
  130. return 0;
  131. }
  132.  
  133. return -1;
  134. }
  135.  
  136. double ComputeMagicInnerProductA_iw (int current_node_global_offset_x, int current_node_global_offset_y){
  137.  
  138. int glob_x = current_node_global_offset_x;
  139. int glob_y = current_node_global_offset_y;
  140.  
  141. double result = 0.0;
  142.  
  143. map <string,bool> neighbours = {
  144. {"left", true},
  145. {"right", true},
  146. {"bottom", true},
  147. {"top", true}
  148. };
  149.  
  150. double left_neighbour = 0.0, right_neighbour = 0.0, bottom_neighbour = 0.0, top_neighbour = 0.0, this_node = 0.0;
  151. double left_coeff = 1.0, right_coeff = 1.0, bottom_coeff = 1.0, top_coeff = 1.0, this_coeff = 1.0;
  152.  
  153. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  154. case 2:
  155. //left bottom corner
  156. neighbours["left"] = false;
  157. neighbours["bottom"] = false;
  158. break;
  159. case 4:
  160. //left top corner
  161. neighbours["left"] = false;
  162. neighbours["top"] = false;
  163. break;
  164. case 6:
  165. //right bottom corner
  166. neighbours["right"] = false;
  167. neighbours["bottom"] = false;
  168. break;
  169. case 8:
  170. //right top corner
  171. neighbours["right"] = false;
  172. neighbours["top"] = false;
  173. break;
  174. case 1:
  175. //left side
  176. neighbours["left"] = false;
  177. break;
  178. case 3:
  179. //right side
  180. neighbours["right"] = false;
  181. break;
  182. case 5:
  183. //bottom side
  184. neighbours["bottom"] = false;
  185. break;
  186. case 7:
  187. //top side
  188. neighbours["top"] = false;
  189. break;
  190. case 0:
  191. //internal
  192. break;
  193. default:
  194. cout << "[ERROR]: Bad global coords compute matrix. Global:" << glob_x << " " << glob_y<<endl;
  195. }
  196.  
  197. if (!neighbours["left"]){
  198. right_coeff = 2.0;
  199. left_coeff = 0.0;
  200. }
  201.  
  202. if (!neighbours["right"]){
  203. left_coeff = 2.0;
  204. right_coeff = 0.0;
  205. }
  206.  
  207. if (!neighbours["bottom"]){
  208. top_coeff = 2.0;
  209. bottom_coeff = 0.0;
  210. }
  211.  
  212. if (!neighbours["top"]){
  213. bottom_coeff = 2.0;
  214. top_coeff = 0.0;
  215. }
  216.  
  217.  
  218.  
  219. if (neighbours["left"]){
  220. left_coeff *= -k(x_left + (glob_x - 0.5) * h_x, y_bottom + glob_y * h_y) / pow(h_x, 2);
  221. left_neighbour = Get(glob_x - 1, glob_y);
  222. }
  223.  
  224. if (neighbours["right"]){
  225. right_coeff *= -k(x_left + (glob_x + 0.5) * h_x, y_bottom + glob_y * h_y) / pow(h_x, 2);
  226. right_neighbour = Get(glob_x + 1, glob_y);
  227. }
  228.  
  229. if (neighbours["bottom"]){
  230. bottom_coeff *= -k(x_left + glob_x * h_x, y_bottom + (glob_y - 0.5) * h_y) / pow(h_y, 2);
  231. bottom_neighbour = Get(glob_x, glob_y - 1);
  232. }
  233.  
  234. if (neighbours["top"]){
  235. top_coeff *= -k(x_left + glob_x * h_x, y_bottom + (glob_y + 0.5) * h_y) / pow(h_y, 2);
  236. top_neighbour = Get(glob_x, glob_y + 1);
  237. }
  238.  
  239. this_coeff = q(x_left + glob_x * h_x, y_bottom + glob_y * h_y) - left_coeff - right_coeff - bottom_coeff - top_coeff;
  240. this_node = Get(glob_x, glob_y);
  241.  
  242. result = left_coeff * left_neighbour +
  243. right_coeff * right_neighbour +
  244. bottom_coeff * bottom_neighbour +
  245. top_coeff * top_neighbour +
  246. this_coeff * this_node;
  247.  
  248. return result;
  249. }
  250.  
  251.  
  252.  
  253. double GetNodeFromB(int current_node_global_offset_x, int current_node_global_offset_y) {
  254.  
  255. int glob_x = current_node_global_offset_x;
  256. int glob_y = current_node_global_offset_y;
  257.  
  258. double result = 0.0;
  259.  
  260. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  261. case 2:
  262. //left bottom corner
  263. result = F(x_left, y_bottom) + 2.0 / h_x * psi_L(y_bottom) + 2.0 / h_y * psi_B(x_left);
  264. break;
  265. case 4:
  266. //left top corner
  267. result = F(x_left, y_top) + 2.0 / h_x * psi_L(y_top) + 2.0 / h_y * psi_T(x_left);
  268. break;
  269. case 6:
  270. //right bottom corner
  271. result = F(x_right, y_bottom) + 2.0 / h_x * psi_R(y_bottom) + 2.0 / h_y * psi_B(x_right);
  272. break;
  273. case 8:
  274. //right top corner
  275. result = F(x_right, y_top) + 2.0 / h_x * psi_R(y_top) + 2.0 / h_y * psi_T(x_right);
  276. break;
  277. case 1:
  278. //left side
  279. result = F(x_left, y_bottom + glob_y * h_y) + 2.0 / h_x * psi_L(y_bottom + glob_y * h_y);
  280. break;
  281. case 3:
  282. //right side
  283. result = F(x_right, y_bottom + glob_y * h_y) + 2.0 / h_x * psi_R(y_bottom + glob_y * h_y);
  284. break;
  285. case 5:
  286. //bottom side
  287. result = F(x_left + glob_x * h_x, y_bottom) + 2.0 / h_y * psi_B(x_left + glob_x * h_x);
  288. break;
  289. case 7:
  290. //top side
  291. result = F(x_left + glob_x * h_x, y_top) + 2.0 / h_y * psi_T(x_left + glob_x * h_x);
  292. break;
  293. case 0:
  294. //internal
  295. result = F(x_left + glob_x * h_x, y_bottom + glob_y * h_y);
  296. break;
  297. default:
  298. cout << "[ERROR]: Bad global coords compute matrix. Global:" << glob_x << " " << glob_y <<endl;
  299.  
  300. }
  301.  
  302. return result;
  303.  
  304. }
  305.  
  306.  
  307.  
  308. double func_inner_product(vector<double> &v1, vector<double> &v2) {
  309. double prod = 0;
  310.  
  311. // rho = 1 in case of interior points
  312. for (int i = 1; i < M; ++i)
  313. for (int j = 1; j < N; ++j)
  314. prod += v1[j * (M + 1) + i] * v2[j * (M + 1) + i];
  315.  
  316. // rho = 0.5 in case of left and right sides
  317. for (int j = 1; j < N; ++j)
  318. prod += 0.5 * (v1[j * (M + 1)] * v2[j * (M + 1)] + v1[j * (M + 1) + M] * v2[j * (M + 1) + M]);
  319.  
  320. // rho = 0.5 in case of top and bottom sides
  321. for (int i = 1; i < M; ++i)
  322. prod += 0.5 * (v1[N * (M + 1) + i] * v2[N * (M + 1) + i] + v1[i] * v2[i]);
  323.  
  324. // rho = 0.25 in case of corner points
  325. prod += 0.25 * (v1[0] * v2[0] + v1[M] * v2[M] + v1[N * (M + 1)] * v2[N * (M + 1)]
  326. + v1[N * (M + 1) + M] * v2[N * (M + 1) + M]);
  327.  
  328. prod *= h1 * h2;
  329. return prod;
  330. }
  331.  
  332. double norm(vector<double> &v) {
  333. return sqrt(func_inner_product(v, v));
  334. }
  335.  
  336. // solving system by method of least residuals
  337. void LeastResiduals(vector< vector<double> > &A, vector<double> &B) {
  338. int sz = B.size(), iterations = 0;
  339. double tau = 0.0, eps = 1e-06;
  340. vector<double> r(sz, 0.0), Ar(sz, 0.0);
  341.  
  342. do {
  343. // filling residual
  344. //for (int i = 0; i < sz; ++i)
  345.  
  346. for(int i = 0; i < M + 1; ++i){
  347. for(int j = 0; j < N + 1; ++j){
  348. //r[i] = inner_product(A[i], w) - B[i];
  349. r[j * (M + 1) + i] = ComputeMagicInnerProductA_iw(i, j) - GetNodeFromB(i, j);
  350.  
  351. old_w = w;
  352.  
  353. w = r;
  354.  
  355. // filling Ar which is product of matrix A and vector r
  356. //for (int i = 0; i < sz; ++i)
  357. //Ar[i] = inner_product(A[i], r);
  358.  
  359.  
  360. for(int i = 0; i < M + 1; ++i){
  361. for(int j = 0; j < N + 1; ++j){
  362. Ar[j * (M + 1) + i] = ComputeMagicInnerProductA_iw(i, j);
  363.  
  364. // computing iteration parameter
  365. tau = func_inner_product(Ar, r) / func_inner_product(Ar, Ar);
  366.  
  367. // computing new iteration of w
  368. for (int i = 0; i < sz; ++i)
  369. w[i] -= tau * r[i];
  370.  
  371. ++iterations;
  372.  
  373. cout << fabs(tau) * norm(r) - eps << endl;
  374. } while (fabs(tau) * norm(r) >= eps);
  375.  
  376. cout << "Number of iterations: " << iterations << endl;
  377. }
  378.  
  379. // computing norm of difference between approximate and exact solutions
  380. double Compare(vector<double> &exact) {
  381. int sz = exact.size();
  382.  
  383. // filling difference vector
  384. vector<double> diff(sz, 0.0);
  385. for (int i = 0; i < sz; ++i)
  386. diff[i] = w[i] - exact[i];
  387.  
  388. return norm(diff);
  389. }
  390.  
  391. int main() {
  392. //cout << "Starting system construction:" << endl;
  393. vector< vector<double> > A(SIZE, vector<double>(SIZE, 0.0));
  394. vector<double> B(SIZE, 0.0);
  395.  
  396. // construction of the system Aw = B
  397. ComputeRightPart(B);
  398. //cout << "[+] Right part constructed" << endl;
  399.  
  400. ComputeMatrix(A);
  401. //cout << "[+] Matrix constructed" << endl;
  402.  
  403. // calculation of the exact solution
  404. vector<double> exact(SIZE, 0.0);
  405. CalculateExactSolution(exact);
  406. //cout << "[+] Exact solution calculated" << endl;
  407.  
  408. // solving system Aw = B by method of least residuals
  409. w.resize(SIZE);
  410. LeastResiduals(A, B);
  411. cout << "[+] Approximate solution calculated" << endl;
  412.  
  413. cout << "Norm of difference between exact and approximate solutions: " << Compare(w, exact) << endl;
  414.  
  415. cout << "Done!" << endl;
  416. return 0;
  417. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement