-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPSolver.c
More file actions
117 lines (84 loc) · 3.13 KB
/
Copy pathPSolver.c
File metadata and controls
117 lines (84 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// PSolver.c
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>
#include "PSolver.h"
// Compute root-mean-square (RMS) of a 2D array
double rms_function(int nx, int ny, double a[NX][NY]) {
double v = 0.0;
for (int j = 0; j < ny; j++) {
for (int i = 0; i < nx; i++) {
v += a[i][j] * a[i][j];
}
}
return sqrt(v / (double)(nx * ny));
}
// Compute source term f(x,y) = pi*pi*(x*x + y*y) * sin(pi*x*y)
void source_function(int nx, int ny, double f[NX][NY]) {
double x, y;
for (int j = 0; j < ny; j++) {
y = (double)j / (double)(ny - 1);
for (int i = 0; i < nx; i++) {
x = (double)i / (double)(nx - 1);
f[i][j] = pow(PI, 2) * (x * x + y * y) * sin(PI * x * y);
}
}
}
// Jacobi iterative solver for the 2D Poisson equation with Dirichlet BCs
void jacobi(int nx, int ny, double dx, double dy, double f[NX][NY], int input_iteration, int output_iteration, double u[NX][NY], double u_new[NX][NY]) {
// Precompute constants for stencil computation
double dx2 = dx * dx;
double dy2 = dy * dy;
double denom = 2.0 * (dx2 + dy2);
// Iterative loop from input_iteration to output_iteration
for (int step = input_iteration; step < output_iteration; step++) {
// Perform Jacobi update over interior points (excluding boundaries)
#pragma omp parallel for collapse(2)
for (int j = 1; j < ny - 1; j++) {
for (int i = 1; i < nx - 1; i++) {
u[i][j] = (
dy2 * (u_new[i + 1][j] + u_new[i - 1][j]) +
dx2 * (u_new[i][j + 1] + u_new[i][j - 1]) -
dx2 * dy2 * f[i][j]
) / denom;
}
}
// Copy updated values to u_new for the next iteration
#pragma omp parallel for collapse(2)
for (int j = 1; j < ny - 1; j++) {
for (int i = 1; i < nx - 1; i++) {
u_new[i][j] = u[i][j];
}
}
// Explicitly enforce zero Dirichlet boundary conditions on u_new
apply_dirichlet_bc(nx, ny, u_new);
}
}
// Exact analytical solution for comparison: u(x,y) = sin(pi*x*y)
double potential_exact_function(double x, double y) {
return sin(PI * x * y);
}
// Laplacian of the exact potential: del (del u) = pi*pi*(x*x + y*y) * sin(pi*x*y)
double laplacian_potential(double x, double y) {
return pow(PI, 2) * (x * x + y * y) * sin(PI * x * y);
}
// Utility function to print a timestamp
void timestamp() {
time_t now = time(NULL);
printf("Timestamp: %s", ctime(&now));
}
// Apply homogeneous Dirichlet boundary conditions: u = 0 on the domain boundary
void apply_dirichlet_bc(int nx, int ny, double u[NX][NY]) {
// Set left and right boundary values to 0
for (int j = 0; j < ny; j++) {
u[0][j] = 0.0; // left boundary
u[nx - 1][j] = 0.0; // right boundary
}
// Set bottom and top boundary values to 0
for (int i = 0; i < nx; i++) {
u[i][0] = 0.0; // bottom boundary
u[i][ny - 1] = 0.0; // top boundary
}
}