manac68974

Untitled

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