Advertisement
manac68974

Untitled

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