forked from moebiusband/NuSiF-Solver
		
	EnhancedSolver port complete
This commit is contained in:
		| @@ -20,8 +20,10 @@ int main(int argc, char** argv) | ||||
|     Parameter p; | ||||
|     Discretization d; | ||||
|     Solver s; | ||||
|      | ||||
|  | ||||
|     initParameter(&p); | ||||
|     FILE* fp; | ||||
|     fp = initResidualWriter(); | ||||
|  | ||||
|     if (argc != 2) { | ||||
|         printf("Usage: %s <configFile>\n", argv[0]); | ||||
| @@ -32,7 +34,7 @@ int main(int argc, char** argv) | ||||
|     printParameter(&p); | ||||
|     initDiscretization(&d, &p); | ||||
|     initSolver(&s, &d, &p); | ||||
|      | ||||
|  | ||||
| #ifndef VERBOSE | ||||
|     initProgress(d.te); | ||||
| #endif | ||||
| @@ -41,8 +43,9 @@ int main(int argc, char** argv) | ||||
|     double te  = d.te; | ||||
|     double t   = 0.0; | ||||
|     int nt     = 0; | ||||
|     double res = 0.0; | ||||
|  | ||||
|     timeStart = getTimeStamp(); | ||||
|     timeStart  = getTimeStamp(); | ||||
|     while (t <= te) { | ||||
|         if (tau > 0.0) computeTimestep(&d); | ||||
|         setBoundaryConditions(&d); | ||||
| @@ -50,17 +53,21 @@ int main(int argc, char** argv) | ||||
|         computeFG(&d); | ||||
|         computeRHS(&d); | ||||
|         if (nt % 100 == 0) normalizePressure(&d); | ||||
|         solve(&s, d.p, d.rhs); | ||||
|         res = solve(&s, d.p, d.rhs); | ||||
|         adaptUV(&d); | ||||
|  | ||||
|         writeResidual(fp, t, res); | ||||
|  | ||||
|         t += d.dt; | ||||
|         nt++; | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|         printf("TIME %f , TIMESTEP %f\n", t, solver.dt); | ||||
|         printf("TIME %f , TIMESTEP %f\n", t, d.dt); | ||||
| #else | ||||
|         printProgress(t); | ||||
| #endif | ||||
|     } | ||||
|     fclose(fp); | ||||
|     timeStop = getTimeStamp(); | ||||
|     stopProgress(); | ||||
|     printf("Solution took %.2fs\n", timeStop - timeStart); | ||||
|   | ||||
| @@ -24,6 +24,8 @@ void initParameter(Parameter* param) | ||||
|     param->gamma   = 0.9; | ||||
|     param->tau     = 0.5; | ||||
|     param->levels  = 5; | ||||
|     param->presmooth = 5; | ||||
|     param->postsmooth = 5; | ||||
| } | ||||
|  | ||||
| void readParameter(Parameter* param, const char* filename) | ||||
| @@ -79,6 +81,8 @@ void readParameter(Parameter* param, const char* filename) | ||||
|             PARSE_REAL(u_init); | ||||
|             PARSE_REAL(v_init); | ||||
|             PARSE_REAL(p_init); | ||||
|             PARSE_INT(presmooth); | ||||
|             PARSE_INT(postsmooth); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ typedef struct { | ||||
|     char* name; | ||||
|     int bcLeft, bcRight, bcBottom, bcTop; | ||||
|     double u_init, v_init, p_init; | ||||
|     int presmooth, postsmooth; | ||||
| } Parameter; | ||||
|  | ||||
| void initParameter(Parameter*); | ||||
|   | ||||
| @@ -49,3 +49,22 @@ void stopProgress() | ||||
|     printf("\n"); | ||||
|     fflush(stdout); | ||||
| } | ||||
|  | ||||
| FILE* initResidualWriter() | ||||
| { | ||||
|     FILE* fp; | ||||
|     fp = fopen("residual.dat", "w"); | ||||
|  | ||||
|     if (fp == NULL) { | ||||
|         printf("Error!\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     return fp; | ||||
|  | ||||
| } | ||||
|  | ||||
| void writeResidual(FILE* fp, double ts, double res) | ||||
| { | ||||
|     fprintf(fp, "%f, %f\n", ts, res); | ||||
| } | ||||
|   | ||||
| @@ -10,5 +10,7 @@ | ||||
| extern void initProgress(double); | ||||
| extern void printProgress(double); | ||||
| extern void stopProgress(void); | ||||
| extern FILE* initResidualWriter(void); | ||||
| extern void writeResidual(FILE*, double, double); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -84,6 +84,37 @@ static double smooth(Solver* s, double* p, double* rhs, int level, int imax, int | ||||
|  | ||||
|     jsw = 1; | ||||
|  | ||||
|     for (pass = 0; pass < 2; pass++) { | ||||
|         isw = jsw; | ||||
|  | ||||
|         for (int j = 1; j < jmax + 1; j++) { | ||||
|             for (int i = isw; i < imax + 1; i += 2) { | ||||
|  | ||||
|                 P(i, j) -= factor * (RHS(i, j) - | ||||
|                           ((P(i + 1, j) - 2.0 * P(i, j) + P(i - 1, j)) * idx2 + | ||||
|                               (P(i, j + 1) - 2.0 * P(i, j) + P(i, j - 1)) * idy2)); | ||||
|  | ||||
|             } | ||||
|             isw = 3 - isw; | ||||
|         } | ||||
|         jsw = 3 - jsw; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| static double calculateResidual(Solver* s, double* p, double* rhs, int level, int imax, int jmax) | ||||
| { | ||||
|     double dx2    = s->grid->dx * s->grid->dx; | ||||
|     double dy2    = s->grid->dy * s->grid->dy; | ||||
|     double idx2   = 1.0 / dx2; | ||||
|     double idy2   = 1.0 / dy2; | ||||
|     double factor = s->omega * 0.5 * (dx2 * dy2) / (dx2 + dy2); | ||||
|     double* r     = s->r[level]; | ||||
|     double res    = 1.0; | ||||
|     int pass, jsw, isw; | ||||
|  | ||||
|     jsw = 1; | ||||
|  | ||||
|     for (pass = 0; pass < 2; pass++) { | ||||
|         isw = jsw; | ||||
|  | ||||
| @@ -94,7 +125,6 @@ static double smooth(Solver* s, double* p, double* rhs, int level, int imax, int | ||||
|                           ((P(i + 1, j) - 2.0 * P(i, j) + P(i - 1, j)) * idx2 + | ||||
|                               (P(i, j + 1) - 2.0 * P(i, j) + P(i, j - 1)) * idy2); | ||||
|  | ||||
|                 P(i, j) -= (factor * R(i, j)); | ||||
|                 res += (R(i, j) * R(i, j)); | ||||
|             } | ||||
|             isw = 3 - isw; | ||||
| @@ -110,7 +140,7 @@ static double multiGrid(Solver* s, double* p, double* rhs, int level, int imax, | ||||
| { | ||||
|     double res = 0.0; | ||||
|  | ||||
|     // coarsest level TODO: Use direct solver? | ||||
|     // coarsest level | ||||
|     if (level == COARSEST_LEVEL) { | ||||
|         for (int i = 0; i < 5; i++) { | ||||
|             smooth(s, p, rhs, level, imax, jmax); | ||||
| @@ -118,17 +148,18 @@ static double multiGrid(Solver* s, double* p, double* rhs, int level, int imax, | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|     // pre-smoothing TODO: Make smoothing steps configurable? | ||||
|     for (int i = 0; i < 5; i++) { | ||||
|     // pre-smoothing | ||||
|     for (int i = 0; i < s->presmooth; i++) { | ||||
|         smooth(s, p, rhs, level, imax, jmax); | ||||
|         if (level == FINEST_LEVEL) setBoundaryCondition(p, imax, jmax); | ||||
|     } | ||||
|  | ||||
|     res = calculateResidual(s, p, rhs, level, imax, jmax); | ||||
|  | ||||
|     // restrict | ||||
|     restrictMG(s, level, imax, jmax); | ||||
|  | ||||
|     // MGSolver on residual and error. | ||||
|     // TODO: What if there is a rest? | ||||
|     multiGrid(s, s->e[level + 1], s->r[level + 1], level + 1, imax / 2, jmax / 2); | ||||
|  | ||||
|     // prolongate | ||||
| @@ -139,8 +170,8 @@ static double multiGrid(Solver* s, double* p, double* rhs, int level, int imax, | ||||
|     if (level == FINEST_LEVEL) setBoundaryCondition(p, imax, jmax); | ||||
|  | ||||
|     // post-smoothing | ||||
|     for (int i = 0; i < 5; i++) { | ||||
|         res = smooth(s, p, rhs, level, imax, jmax); | ||||
|     for (int i = 0; i < s->postsmooth; i++) { | ||||
|         smooth(s, p, rhs, level, imax, jmax); | ||||
|         if (level == FINEST_LEVEL) setBoundaryCondition(p, imax, jmax); | ||||
|     } | ||||
|  | ||||
| @@ -154,6 +185,8 @@ void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
|     s->itermax = p->itermax; | ||||
|     s->levels  = p->levels; | ||||
|     s->grid    = &d->grid; | ||||
|     s->presmooth = p->presmooth; | ||||
|     s->postsmooth = p->postsmooth; | ||||
|  | ||||
|     int imax   = s->grid->imax; | ||||
|     int jmax   = s->grid->jmax; | ||||
| @@ -176,11 +209,13 @@ void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
|     } | ||||
| } | ||||
|  | ||||
| void solve(Solver* s, double* p, double* rhs) | ||||
| double solve(Solver* s, double* p, double* rhs) | ||||
| { | ||||
|     double res = multiGrid(s, p, rhs, 0, s->grid->imax, s->grid->jmax); | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|     printf("Residuum: %.6f\n", res); | ||||
| #endif | ||||
|  | ||||
| return res; | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
|     s->omega   = p->omg; | ||||
| } | ||||
|  | ||||
| void solve(Solver* solver, double* p, double* rhs) | ||||
| double solve(Solver* solver, double* p, double* rhs) | ||||
| { | ||||
|     int imax      = solver->grid->imax; | ||||
|     int jmax      = solver->grid->jmax; | ||||
| @@ -73,4 +73,6 @@ void solve(Solver* solver, double* p, double* rhs) | ||||
| #ifdef VERBOSE | ||||
|     printf("Solver took %d iterations to reach %f\n", it, sqrt(res)); | ||||
| #endif | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
|     s->omega   = p->omg; | ||||
| } | ||||
|  | ||||
| void solve(Solver* solver, double* p, double* rhs) | ||||
| double solve(Solver* solver, double* p, double* rhs) | ||||
| { | ||||
|     int imax      = solver->grid->imax; | ||||
|     int jmax      = solver->grid->jmax; | ||||
| @@ -65,4 +65,6 @@ void solve(Solver* solver, double* p, double* rhs) | ||||
| #ifdef VERBOSE | ||||
|     printf("Solver took %d iterations to reach %f\n", it, sqrt(res)); | ||||
| #endif | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|   | ||||
| @@ -18,9 +18,10 @@ typedef struct { | ||||
|     int itermax; | ||||
|     int levels; | ||||
|     double **r, **e; | ||||
|         int presmooth, postsmooth; | ||||
| } Solver; | ||||
|  | ||||
| extern void initSolver(Solver*, Discretization*, Parameter*); | ||||
| extern void solve(Solver*, double*, double*); | ||||
| extern double solve(Solver*, double*, double*); | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user