int main(int argc, char** args){ double Re, UI, VI, PI, GX, GY, t_end, xlength, ylength, dt, dx, dy, alpha, omg, tau, eps, dt_value, t, res, dp, nu; double **U, **V, **P, **F, **G, **RS; double **K, **E; /* turbulent kinetic energy k, dissipation rate epsilon*/ double Fu, Fv; /* force integration variables */ double KI, EI, cn, ce, c1, c2; /* K and E: Initial values for k and epsilon */ int n, it, imax, jmax, itermax, pb, boundaries[4]; int fluid_cells; /* Number of fluid cells in our geometry */ int **Flag; /* Flagflield matrix */ char vtkname[200]; char pgm[200]; char problem[10]; /* Problem name */ char fname[200]; if(argc<2){ printf("No parameter file specified. Terminating...\n"); exit(1); } sprintf(fname, "%s%s", CONFIGS_FOLDER, args[1]); printf("%s\n",fname); read_parameters(fname, &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &itermax, &eps, boundaries, &dp, &pb, &KI, &EI, &cn, &ce, &c1, &c2, pgm, &nu, problem); /* Allocate Flag matrix */ Flag = imatrix( 0, imax+1, 0, jmax+1 ); U = matrix ( 0 , imax+1 , 0 , jmax+1 ); V = matrix ( 0 , imax+1 , 0 , jmax+1 ); P = matrix ( 0 , imax+1 , 0 , jmax+1 ); F = matrix ( 0 , imax , 0 , jmax ); G = matrix ( 0 , imax , 0 , jmax ); RS = matrix ( 0 , imax , 0 , jmax ); K = matrix ( 0 , imax+1 , 0 , jmax+1 ); E = matrix ( 0 , imax+1 , 0 , jmax+1 ); /* Initialize values to the Flag, u, v and p */ init_flag(CONFIGS_FOLDER,pgm, imax, jmax, &fluid_cells, Flag ); init_uvp(UI, VI, PI, KI, EI, imax, jmax, U, V, P, K, E, Flag, problem ); printf("Problem: %s\n", problem ); printf( "xlength = %f, ylength = %f\n", xlength, ylength ); printf( "imax = %d, jmax = %d\n", imax, jmax ); printf( "dt = %f, dx = %f, dy = %f\n", dt, dx, dy); printf( "Number of fluid cells = %d\n", fluid_cells ); printf( "Reynolds number: %f\n\n", Re); t=.0; n=0; while( t <= t_end ){ boundaryvalues( imax, jmax, U, V, K, E, boundaries, Flag ); /* special inflow boundaries, including k and eps */ spec_boundary_val( problem, imax, jmax, U, V, K, E, Re, dp, cn, ylength); /* calculate new values for k and eps */ comp_KAEP(Re, nu, cn, ce, c1, c2, alpha, dt, dx, dy, imax, jmax, U, V, K, E, GX, GY, Flag); /* calculate new values for F and G */ calculate_fg( Re, GX, GY, alpha, dt, dx, dy, imax, jmax, U, V, F, G, K, E, nu, cn, Flag ); /* calculate right hand side */ calculate_rs( dt, dx, dy, imax, jmax, F, G, RS, Flag ); it = 0; res = 10000.0; while( it < itermax && fabs(res) > eps ){ sor( omg, dx, dy, imax, jmax, fluid_cells, P, RS, Flag, &res, problem, dp ); it++; } printf("[%5d: %f] dt: %f, sor iterations: %4d \n", n, t, dt, it); /* calculate new values for u and v */ calculate_uv( dt, dx, dy, imax, jmax, U, V, F, G, P, Flag ); t += dt; n++; } sprintf(vtkname, "%s%s", VISUA_FOLDER, args[1]); write_vtkFile( vtkname, 1, xlength, ylength, imax, jmax, dx, dy, U, V, P, K, E, Flag); comp_surface_force( Re, dx, dy, imax, jmax, U, V, P, Flag, &Fu, &Fv); printf( "\nProblem: %s\n", problem ); printf( "xlength = %f, ylength = %f\n", xlength, ylength ); printf( "imax = %d, jmax = %d\n", imax, jmax ); printf( "dt = %f, dx = %f, dy = %f\n", dt, dx, dy); printf( "Number of fluid cells = %d\n", fluid_cells ); printf( "Reynolds number: %f\n", Re); printf( "Drag force = %f Lift force = %f\n", Fu, Fv); /* free memory */ free_matrix(U,0,imax+1,0,jmax+1); free_matrix(V,0,imax+1,0,jmax+1); free_matrix(P,0,imax+1,0,jmax+1); free_matrix(K,0,imax+1,0,jmax+1); free_matrix(E,0,imax+1,0,jmax+1); free_matrix(F,0,imax,0,jmax); free_matrix(G,0,imax,0,jmax); free_matrix(RS,0,imax,0,jmax); free_imatrix(Flag,0,imax+1,0,jmax+1); return 0; }
/** * The main operation reads the configuration file, initializes the scenario and * contains the main loop. So here are the individual steps of the algorithm: * * - read the program configuration file using read_parameters() * - set up the matrices (arrays) needed using the matrix() command * - create the initial setup init_uvp(), init_flag(), output_uvp() * - perform the main loop * - trailer: destroy memory allocated and do some statistics * * The layout of the grid is described by the first figure below, the enumeration * of the whole grid is given by the second figure. All the unknowns correspond * to a two dimensional degree of freedom layout, so they are not stored in * arrays, but in a matrix. * * @image html grid.jpg * * @image html whole-grid.jpg * * Within the main loop the following big steps are done (for some of the * operations a definition is defined already within uvp.h): * * - calculate_dt() Determine the maximal time step size. * - boundaryvalues() Set the boundary values for the next time step. * - calculate_fg() Determine the values of F and G (diffusion and confection). * This is the right hand side of the pressure equation and used later on for * the time step transition. * - calculate_rs() * - Iterate the pressure poisson equation until the residual becomes smaller * than eps or the maximal number of iterations is performed. Within the * iteration loop the operation sor() is used. * - calculate_uv() Calculate the velocity at the next time step. */ int main(int argn, char** args){ double Re,UI,VI,PI,GX,GY, /* problem dependent quantities */ xlength,ylength,dx,dy, /* geometry data */ t=0,t_end,dt,tau,dt_value, /* time stepping data */ alpha,omg,eps,res; /* pressure iteration data */ int it, itermax, n=0, imax, jmax; /* max iterations, iteration step and # of interior cells */ double **U, **V, **F, **G, **P, **RS; /* Read the problem parameters */ read_parameters("data/cavity100-2.dat", &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value); /* Allocate space for matrices */ U = matrix(0, imax, 0, jmax+1); F = matrix(0, imax, 0, jmax+1); V = matrix(0, imax+1, 0, jmax); G = matrix(0, imax+1, 0, jmax); P = matrix(0, imax+1, 0, jmax+1); RS= matrix(0, imax+1, 0, jmax+1); /* Assign initial values to u, v, p */ init_uvp(UI, VI, PI, imax, jmax, U, V, P); while (t < t_end){ /* Select δt according to (14) */ calculate_dt(Re, tau, &dt, dx, dy, imax, jmax, U, V); /* Set boundary values for u and v according to (15),(16) */ boundaryvalues(imax, jmax, U, V); /* Compute F (n) and G (n) according to (10),(11),(18) */ calculate_fg(Re, GX, GY, alpha, dt, dx, dy, imax, jmax, U, V, F, G); /* Compute the right-hand side rs of the pressure equation (12) */ calculate_rs(dt, dx, dy, imax, jmax, F, G, RS); it = 0; res=DBL_MAX; while (it < itermax && res > eps){ /* Perform a SOR iteration according to (19) using the provided function and retrieve the residual res */ sor(omg, dx, dy, imax, jmax, P, RS, &res); it++; } /* Compute u (n+1) and v (n+1) according to (8),(9) */ calculate_uv(dt,dx,dy,imax,jmax,U,V,F,G,P); t+=dt; n++; } /* Output of u, v, p for visualization */ write_vtkFile("visualization/cavity", n, xlength, ylength, imax, jmax, dx, dy, U, V, P); /* Freeing memory */ free_matrix(U, 0, imax, 0, jmax+1); free_matrix(F, 0, imax, 0, jmax+1); free_matrix(V, 0, imax+1, 0, jmax); free_matrix(G, 0, imax+1, 0, jmax); free_matrix(P, 0, imax+1, 0, jmax+1); free_matrix(RS, 0, imax+1, 0, jmax+1); return -1; }
int main(int argn, char** args){ if (argn !=2 ) { printf("When running the simulation, please give a valid scenario file name!\n"); return 1; } //set the scenario char *filename = NULL; filename = args[1]; //initialize variables double t = 0; /*time start*/ int it, n = 0; /*iteration and time step counter*/ double res; /*residual for SOR*/ /*arrays*/ double **U, **V, **P; double **RS, **F, **G; int **Flag; //additional data structure for arbitrary geometry /*those to be read in from the input file*/ double Re, UI, VI, PI, GX, GY, t_end, xlength, ylength, dt, dx, dy, alpha, omg, tau, eps, dt_value; int imax, jmax, itermax; double presLeft, presRight, presDelta; //for pressure stuff int wl, wr, wt, wb; char problem[32]; double vel; //in case of a given inflow or wall velocity //read the parameters, using problem.dat, including wl, wr, wt, wb read_parameters(filename, &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value, &wl, &wr, &wt, &wb, problem, &presLeft, &presRight, &presDelta, &vel); int pics = dt_value/dt; //just a helping variable for outputing vtk //allocate memory, including Flag U = matrix(0, imax+1, 0, jmax+1); V = matrix(0, imax+1, 0, jmax+1); P = matrix(0, imax+1, 0, jmax+1); RS = matrix(1, imax, 1, jmax); F = matrix(0, imax, 1, jmax); G = matrix(1, imax, 0, jmax); Flag = imatrix(0, imax+1, 0, jmax+1); // or Flag = imatrix(1, imax, 1, jmax); int kmax = 20; //test no slip boundary value function double ***U3d = (double ***) malloc((size_t)((imax+1)*(jmax+1)*(kmax+1) * sizeof(double*)) ); //test no slip boundary value function double ***V3d = (double ***) malloc((size_t)((imax+1)*(jmax+1)*(kmax+1) * sizeof(double*)) ); //test no slip boundary value function double ***W3d = (double ***) malloc((size_t)((imax+1)*(jmax+1)*(kmax+1) * sizeof(double*)) ); //test no slip boundary value function int ***Flag3d = (int ***) malloc((size_t)((imax+1)*(jmax+1)*(kmax+1) * sizeof(int*)) ); //test no slip boundary value function //initialisation, including **Flag init_flag(problem, imax, jmax, presDelta, Flag); init_uvp(UI, VI, PI, imax, jmax, U, V, P, problem); //going through all time steps while(t < t_end){ //adaptive time stepping calculate_dt(Re, tau, &dt, dx, dy, imax, jmax, U, V); //setting bound.values boundaryvalues(imax, jmax, U, V, P, wl, wr, wt, wb, F, G, problem, Flag, vel); //including P, wl, wr, wt, wb, F, G, problem //test no slip boundary value function for(int i=1; i<=imax; i++){ for(int j=1; j<=jmax; j++){ for(int k=1; k<=kmax; k++){ boundaryvalues_no_slip(i, j, k, U3d, V3d, W3d, Flag3d); //test no slip boundary value function } } } //computing F, G and right hand side of pressue eq. calculate_fg(Re, GX, GY, alpha, dt, dx, dy, imax, jmax, U, V, F, G, Flag); calculate_rs(dt, dx, dy, imax, jmax, F, G, RS); //iteration counter it = 0; do{ // //perform SOR iteration, at same time set bound.values for P and new residual value sor(omg, dx, dy, imax, jmax, P, RS, &res, Flag, presLeft, presRight); it++; }while(it<itermax && res>eps); /* if (it == itermax) { printf("Warning: sor while loop exits because it reaches the itermax. res = %f, time =%f\n", res, t); } */ //calculate U and V of this time step calculate_uv(dt, dx, dy, imax, jmax, U, V, F, G, P, Flag); //indent time and number of time steps n++; t += dt; //output of pics for animation if (n%pics==0 ){ write_vtkFile(filename, n, xlength, ylength, imax, jmax, dx, dy, U, V, P); } } //output of U, V, P at the end for visualization //write_vtkFile("DrivenCavity", n, xlength, ylength, imax, jmax, dx, dy, U, V, P); //free memory free_matrix(U, 0, imax+1, 0, jmax+1); free_matrix(V, 0, imax+1, 0, jmax+1); free_matrix(P, 0, imax+1, 0, jmax+1); free_matrix(RS, 1, imax, 1, jmax); free_matrix(F, 0, imax, 1, jmax); free_matrix(G, 1, imax, 0, jmax); free_imatrix(Flag, 0, imax+1, 0, jmax+1); free(U3d); free(V3d); free(W3d); free(Flag3d); return -1; }
int main(int argn, char** args){ double **U, **V, **P, **F, **G, **RS; const char *szFileName = "dam_break.dat"; double Re, UI, VI, PI, GX, GY, t_end, xlength, ylength, dt, dx, dy, alpha, omg, tau, eps, dt_value; double res = 0, t = 0, n = 0; int imax, jmax, itermax, it; /* Additional data structures for VOF */ double **fluidFraction; double **fluidFraction_alt; int **flagField; double **dFdx, **dFdy; int **pic; char output_dirname[60]; double epsilon = 1e-10; /* Read the program configuration file using read_parameters() */ read_parameters(szFileName, &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value); /* Set up the matrices (arrays) needed using the matrix() command */ U = matrix(0, imax , 0, jmax+1); V = matrix(0, imax+1, 0, jmax ); P = matrix(0, imax+1, 0, jmax+1); F = matrix(0, imax , 0, jmax+1); G = matrix(0, imax+1, 0, jmax ); RS= matrix(0, imax+1, 0, jmax+1); flagField = imatrix(0, imax+1, 0, jmax+1); fluidFraction = matrix(0, imax+1, 0, jmax+1); fluidFraction_alt = matrix(0, imax+1, 0, jmax+1); dFdx = matrix(0, imax+1, 0, jmax+1); dFdy = matrix(0, imax+1, 0, jmax+1); /*create a directory*/ strcpy(output_dirname, "dam_break/dam_break"); mkdir("dam_break", 0777); /* Read pgm file with domain and initial setting */ pic = read_pgm("dam_break.pgm"); init_fluidFraction(pic, fluidFraction,fluidFraction_alt, imax, jmax); /* Assign initial values to u, v, p */ init_uvp(UI, VI, PI, imax, jmax, U, V, P); /* Set valid values for the fluid fraction */ adjust_fluidFraction(fluidFraction, flagField, epsilon, imax, jmax); while(t <= t_end){ /*Select δt*/ calculate_dt(Re, tau, &dt, dx, dy, imax, jmax, U, V); /* Set boundary values for u and v */ /* boundaryvalues(imax, jmax, U, V, flagField, dx, dy); */ /* Compute F(n) and G(n) */ calculate_fg(Re, GX, GY, alpha, dt, dx, dy, imax, jmax, U, V, F, G, flagField); /* Compute the right-hand side rs of the pressure equation */ calculate_rs(dt, dx, dy, imax, jmax, F, G, RS, flagField); /* Determine the orientation of the free surfaces */ calculate_freeSurfaceOrientation(fluidFraction, flagField, dFdx, dFdy, dx, dy, imax, jmax); /* Perform SOR iterations */ it=0; res = 1e6; while(it < itermax && res > eps){ sor(omg, dx, dy, imax, jmax, P, RS, fluidFraction, flagField, dFdx, dFdy, &res); it++; } /* Compute u(n+1) and v(n+1) */ calculate_uv(dt, dx, dy, imax, jmax, U, V, F, G, P, flagField); boundaryvalues(imax, jmax, U, V, flagField, dx, dy); /* Compute fluidFraction(n+1) */ calculate_fluidFraction(fluidFraction,fluidFraction_alt, flagField, U, V, dFdx, dFdy, imax, jmax, dx, dy, dt); boundaryvalues(imax, jmax, U, V, flagField, dx, dy); /* Set valid values for the fluid fraction */ adjust_fluidFraction(fluidFraction, flagField, epsilon, imax, jmax); boundaryvalues(imax, jmax, U, V, flagField, dx, dy); if((int)n % 10 == 0) { write_vtkFile(output_dirname, n, xlength, ylength, imax, jmax, dx, dy, U, V, P, fluidFraction, flagField); } /* Print out simulation time and whether SOR converged */ printf("Time: %.4f", t); if(res > eps) {printf("\t*** Did not converge (res=%f, eps=%f)", res, eps);return -1;} printf("\n"); t = t + dt; n++; } free_matrix(U , 0, imax , 0, jmax+1); free_matrix(V , 0, imax+1, 0, jmax ); free_matrix(P , 0, imax+1, 0, jmax+1); free_matrix(F , 0, imax , 0, jmax+1); free_matrix(G , 0, imax+1, 0, jmax ); free_matrix(RS, 0, imax+1, 0, jmax+1); return -1; }
int main(int argn, char** args){ double **U, **V, **P, **F, **G, **RS; int **Flag; char problem[60]; char parameters_filename[60]; char pgm[60]; char output_dirname[60]; double Re, UI, VI, PI, GX, GY, t_end, xlength, ylength, dt, dx, dy, alpha, omg, tau, eps, dt_value, dp; double res = 0, t = 0, n = 0; int imax, jmax, itermax, it; int wl, wr, wt, wb; int timestepsPerPlotting; char old_output_filename[128]; struct dirent *old_outputfile; DIR *output_dir; /* Variables for parallel program */ int iproc, jproc, myrank, il, ir, jb, jt, rank_l, rank_r, rank_b, rank_t, omg_i, omg_j, num_proc; double min_dt; double *bufSend, *bufRecv; double totalTime = 0; struct timespec previousTime, currentTime; MPI_Init(&argn, &args); MPI_Comm_size(MPI_COMM_WORLD, &num_proc); /* Read name of the problem from the command line arguments */ if(argn > 1) { strcpy(problem, args[1]); } else { printf("\n=== ERROR: Please provide the name of the problem\n=== e.g. Run ./sim problem_name if there is a problem_name.dat file.\n\n"); MPI_Finalize(); return 1; } /* Generate input filename based on problem name */ strcpy(parameters_filename, problem); strcat(parameters_filename, ".dat"); /* Read the program configuration file using read_parameters() */ read_parameters(parameters_filename, pgm, &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value, problem, &dp, &wl, &wr, &wt, &wb, ×tepsPerPlotting, &iproc, &jproc); printf("%s\n", pgm); /* Check if the number of processes is correct */ if(iproc * jproc != num_proc) { printf("\n=== ERROR: Number of processes is incorrect (iproc=%d, jproc=%d, -np=%d) ===\n\n", iproc, jproc, num_proc); MPI_Finalize(); return 1; } /* Create folder with the name of the problem */ strcpy(output_dirname, problem); strcat(output_dirname, "/"); strcat(output_dirname, problem); mkdir(problem, 0777); output_dir = opendir(problem); /* Delete existing files in output folder*/ while((old_outputfile = readdir(output_dir))) { sprintf(old_output_filename, "%s/%s", problem, old_outputfile->d_name); remove(old_output_filename); } /* Determine subdomain and neighbours for each process */ init_parallel(iproc, jproc, imax, jmax, &myrank, &il, &ir, &jb, &jt, &rank_l, &rank_r, &rank_b, &rank_t, &omg_i, &omg_j, num_proc); /* Set up the matrices (arrays) needed using the matrix() command */ U = matrix(il-2, ir+1, jb-1, jt+1); V = matrix(il-1, ir+1, jb-2, jt+1); P = matrix(il-1, ir+1, jb-1, jt+1); F = matrix(il-2, ir+1, jb-1, jt+1); G = matrix(il-1, ir+1, jb-2, jt+1); RS= matrix(il, ir, jb, jt); Flag = imatrix(il-1, ir+1, jb-1, jt+1); /* Assign initial values to u, v, p */ init_uvp(UI, VI, PI, il, ir, jb, jt, U, V, P); /* Allocate memory for buffers */ bufSend = malloc(max(ir-il+3, jt-jb+3) * sizeof(double)); bufRecv = malloc(max(ir-il+3, jt-jb+3) * sizeof(double)); /* Initialize lower part of the domain with UI = 0 for the flow_over_step problem */ /* (this code might be moved to somewhere else later) */ if(strcmp(problem, "flow_over_step") == 0) { init_matrix(U, il, ir, jb, min(jmax/2, jt), 0); } /* Initialization of flag field */ init_flag(pgm, imax, jmax, il, ir, jb, jt, Flag, dp); if(myrank == 0) { clock_gettime(CLOCK_MONOTONIC, ¤tTime); } while(t <= t_end){ /* Select δt */ calculate_dt(Re, tau, &dt, dx, dy, il, ir, jb, jt, U, V); MPI_Allreduce(&dt, &min_dt, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); dt = min_dt; /* Set boundary values for u and v */ boundaryvalues(il, ir, jb, jt, imax, jmax, U, V, wl, wr, wt, wb, Flag); /* Set special boundary values */ spec_boundary_val(problem, il, ir, jb, jt, imax, jmax, U, V, P, Re, xlength, ylength, dp); /* Compute F(n) and G(n) */ calculate_fg(Re, GX, GY, alpha, dt, dx, dy, il, ir, jb, jt, imax, jmax, U, V, F, G, Flag); /* Compute the right-hand side rs of the pressure equation */ calculate_rs(dt, dx, dy, il, ir, jb, jt, imax, jmax, F, G, RS); /* Perform SOR iterations */ it = 0; res = 1e6; while(it < itermax && res > eps){ sor(omg, dx, dy, dp, il, ir, jb, jt, imax, jmax, rank_l, rank_r, rank_b, rank_t, P, RS, &res, Flag, bufSend, bufRecv); it++; } /* Compute u(n+1) and v(n+1) */ calculate_uv(dt, dx, dy, il, ir, jb, jt, imax, jmax, U, V, F, G, P, Flag); /* Exchange velocity strips */ uv_com(U, V, il, ir, jb, jt, rank_l, rank_r, rank_b, rank_t, bufSend, bufRecv); t = t + dt; n++; /* Generate snapshot for current timestep */ if((int) n % timestepsPerPlotting == 0) { write_vtkFile(output_dirname, myrank, n, xlength, ylength, il, ir, jb, jt, imax, jmax, dx, dy, U, V, P); } /* Print out simulation time and whether the SOR converged */ if(myrank == 0) { /* Print simulation time */ printf("Time: %.4f", t); /* Print runtime */ previousTime = currentTime; clock_gettime(CLOCK_MONOTONIC, ¤tTime); totalTime += (double)currentTime.tv_sec + 1e-9 * currentTime.tv_nsec - (double)previousTime.tv_sec - 1e-9 * previousTime.tv_nsec; printf("\tRuntime: %.3f s (avg runtime/step: %.3f s)", totalTime, totalTime/n); if(res > eps) printf("\tDid not converge (res=%f, eps=%f)", res, eps); printf("\n"); } } /* Close the output folder */ closedir(output_dir); /* Tell user where to find the output */ if(myrank == 0) { printf("Please find the output in the folder \"%s\".\n", problem); } /* Free allocated memory */ free_matrix(U, il-2, ir+1, jb-1, jt+1); free_matrix(V, il-1, ir+1, jb-2, jt+1); free_matrix(P, il-1, ir+1, jb-1, jt+1); free_matrix(F, il-2, ir+1, jb-1, jt+1); free_matrix(G, il-1, ir+1, jb-2, jt+1); free_matrix(RS, il, ir, jb, jt); free_imatrix(Flag, il-1, ir+1, jb-1, jt+1); free(bufSend); free(bufRecv); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); return 0; }
/** * The main operation reads the configuration file, initializes the scenario and * contains the main loop. So here are the individual steps of the algorithm: * * - read the program configuration file using read_parameters() * - set up the matrices (arrays) needed using the matrix() command * - create the initial setup init_uvp(), init_flag(), output_uvp() * - perform the main loop * - trailer: destroy memory allocated and do some statistics * * The layout of the grid is decribed by the first figure below, the enumeration * of the whole grid is given by the second figure. All the unknowns corresond * to a two dimensional degree of freedom layout, so they are not stored in * arrays, but in a matrix. * * @image html grid.jpg * * @image html whole-grid.jpg * * Within the main loop the following big steps are done (for some of the * operations a definition is defined already within uvp.h): * * - calculate_dt() Determine the maximal time step size. * - boundaryvalues() Set the boundary values for the next time step. * - calculate_fg() Determine the values of F and G (diffusion and confection). * This is the right hand side of the pressure equation and used later on for * the time step transition. * - calculate_rs() * - Iterate the pressure poisson equation until the residual becomes smaller * than eps or the maximal number of iterations is performed. Within the * iteration loop the operation sor() is used. * - calculate_uv() Calculate the velocity at the next time step. */ int main(int argn, char** args) { double **U, **V, **P, **R, **F, **G; double t = 0.0; double t_end, xlength, ylength, tau, omg, alpha, eps, Re, GX, GY, PI, UI, VI, dx, dy, dt, res, dt_value; int n, imax, jmax, itermax, it, i, outputCount; double nextOutput; bool outputSpecified = false; char* paraviewOutput = "./Paraview/cavity100"; char* inputFile = "./cavity100.dat"; /* statistics */ int sumIter, maxIter, minIter; double minTimeStep, maxTimestep; clock_t begin, end; double time_spent; sumIter = 0; maxIter = 0; maxTimestep = 0; begin = clock(); /* Parse command line arguments */ if (argn > 2) { for (i = 1; i < argn; i++) { if (strcmp(args[i], "-i") == 0) { inputFile = args[i + 1]; if (!outputSpecified) paraviewOutput = "./Paraview/sim"; } if (strcmp(args[i], "-o") == 0) { paraviewOutput = args[i + 1]; outputSpecified = true; } } } else if (argn == 2) { /* input file is the single argument besides fctn-name */ inputFile = args[1]; } /* Initialization */ read_parameters(inputFile, &Re, &UI, &VI, &PI, &GX, &GY, &t_end, &xlength, &ylength, &dt, &dx, &dy, &imax, &jmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value); U = matrix(0, imax, 0, jmax + 1); V = matrix(0, imax + 1, 0, jmax); P = matrix(0, imax + 1, 0, jmax + 1); R = matrix(0, imax + 1, 0, jmax + 1); F = matrix(0, imax, 0, jmax); G = matrix(0, imax, 0, jmax); n = 0; nextOutput = dt_value; init_uvp(UI, VI, PI, imax, jmax, U, V, P); minIter = itermax; minTimeStep = t_end; write_vtkFile(paraviewOutput,0,xlength,ylength,imax,jmax,dx,dy,U,V,P); outputCount = 1; while (t < t_end) { calculate_dt(Re, tau, &dt, dx, dy, imax, jmax, U, V); if (dt < minTimeStep) minTimeStep = dt; if (dt > maxTimestep) maxTimestep = dt; boundaryvalues(imax, jmax, U, V); calculate_fg(Re, GX, GY, alpha, dt, dy, dy, imax, jmax, U, V, F, G); calculate_rs(dt, dx, dy, imax, jmax, F, G, R); it = 0; while(++it < itermax) { sor(omg, dx, dy, imax, jmax, P, R, &res); if (res <= eps) break; } if (res > eps) fprintf(stderr, "WARNING: SOR did not converge in timestep %d, residual: %f\n", n + 1, res); if (it > maxIter) maxIter = it; if (it < minIter) minIter = it; sumIter += it; calculate_uv(dt, dx, dy, imax, jmax, U, V, F, G, P); t = t + dt; n++; if (t >= nextOutput) { write_vtkFile(paraviewOutput,outputCount,xlength,ylength,imax,jmax,dx,dy,U,V,P); nextOutput += dt_value; outputCount++; } } end = clock(); time_spent = (double) (end - begin) / CLOCKS_PER_SEC; /* print statistics */ printf("Simulation took %f seconds\n", time_spent); printf("Number of timesteps: %d\n", n); printf("Min. timestep: %f Max. timestep: %f Avg. timestep: %f\n", minTimeStep, maxTimestep, t_end/n); printf("Min. # iterations: %d Max. # iterations: %d Avg: %f\n", minIter, maxIter, sumIter/(double) n); /* Free memory */ free_matrix(U, 0, imax, 0, jmax + 1); free_matrix(V, 0, imax + 1, 0, jmax); free_matrix(P, 0, imax + 1, 0, jmax + 1); free_matrix(R, 0, imax, 0 ,jmax); free_matrix(F, 0, imax, 0, jmax); free_matrix(G, 0, imax, 0, jmax); return 0; }
int main(int argn, char** args){ if (argn !=2 ) { printf("When running the simulation, please give a valid geometry file name!\n"); return 1; } //set the geometry file char *filename = NULL; filename = args[1]; //initialize variables double t = 0; /*time start*/ int it, n = 0; /*iteration and time step counter*/ double res; /*residual for SOR*/ /*arrays*/ double ***U, ***V, ***W, ***P; double ***RS, ***F, ***G, ***H; int ***Flag; //additional data structure for arbitrary geometry int ***S; //additional data structure for arbitrary geometry int matrix_output = 0; /*those to be read in from the input file*/ double Re, UI, VI, WI, PI, GX, GY, GZ, t_end, xlength, ylength, zlength, dt, dx, dy, dz, alpha, omg, tau, eps, dt_value; int imax, jmax, kmax, itermax; //double presLeft, presRight, presDelta; //for pressure stuff ...TODO: not allowed for now int wl, wr, wt, wb, wf, wh; char problemGeometry[200]; //in case of a given inflow or wall velocity TODO: will we have this? needs to be a vector? double velIN; double velMW[3]; // the moving wall velocity is a vector struct particleline *Partlines = (struct particleline *)malloc((unsigned)(1 * sizeof(struct particleline))); //char szFileName[80]; //read the parameters, using problem.dat, including wl, wr, wt, wb read_parameters(filename, &Re, &UI, &VI, &WI, &PI, &GX, &GY, &GZ, &t_end, &xlength, &ylength, &zlength, &dt, &dx, &dy, &dz, &imax, &jmax, &kmax, &alpha, &omg, &tau, &itermax, &eps, &dt_value, &wl, &wr, &wf, &wh, &wt, &wb, problemGeometry, &velIN, &velMW[0]); //&presLeft, &presRight, &presDelta, &vel); //printf("d: %f, %f, %f\n", dx,dy,dz); //int pics = dt_value/dt; //just a helping variable for outputing vtk double last_output_t = -dt_value; //double every = t_end/10; //helping variable. Can be used for displaying info every tenth of the progress during simulation //allocate memory, including Flag U = matrix2(0, imax+1, 0, jmax+1, 0, kmax+1); V = matrix2(0, imax+1, 0, jmax+1, 0, kmax+1); W = matrix2(0, imax+1, 0, jmax+1, 0, kmax+1); P = matrix2(0, imax+1, 0, jmax+1, 0, kmax+1); RS = matrix2(1, imax, 1, jmax, 1, kmax); F = matrix2(0, imax, 1, jmax, 1, kmax); G = matrix2(1, imax, 0, jmax, 1, kmax); H = matrix2(1, imax, 1, jmax, 0, kmax); Flag = imatrix2(0, imax+1, 0, jmax+1, 0, kmax+1); // or Flag = imatrix(1, imax, 1, jmax); S = imatrix2(0, imax+1, 0, jmax+1, 0, kmax+1); //S = Flag -> adjust C_x Flags in helper.h //initialisation, including **Flag init_flag(problemGeometry, imax, jmax, kmax, Flag, wl, wr, wf, wh, wt, wb); //presDelta, Flag); init_particles(Flag,dx,dy,dz,imax,jmax,kmax,3,Partlines); printf("!!!!!!!!%d\n",binMatch(B_NO,B_N)); init_uvwp(UI, VI, WI, PI, Flag,imax, jmax, kmax, U, V, W, P, problemGeometry); write_particles("particles_init",0, 1, Partlines); write_imatrix2("Flag_start.txt",t,Flag, 0, imax, 1, jmax, 1, kmax); //write_flag_imatrix("Flag.txt",t,Flag, 0, imax+1, 0, jmax+1, 0, kmax+1); write_vtkFile(filename, -1, xlength, ylength, zlength, imax, jmax, kmax, dx, dy, dz, U, V, W, P,Flag); //write_vtkFile("init", n, xlength, ylength, zlength, imax, jmax, kmax, dx, dy, dz, U, V, W, P); //going through all time steps /* write_matrix2("P_start.txt",t,P, 0, imax+1, 0, jmax+1, 0, kmax+1); write_matrix2("U_start.txt",t,U, 0, imax+1, 0, jmax+1, 0, kmax+1); write_matrix2("V_start.txt",t,V, 0, imax+1, 0, jmax+1, 0, kmax+1); write_matrix2("W_start.txt",t,W, 0, imax+1, 0, jmax+1, 0, kmax+1); */ //setting bound.values boundaryvalues(imax, jmax, kmax, U, V, W, P, F, G, H, problemGeometry, Flag, velIN, velMW); //including P, wl, wr, wt, wb, F, G, problem // printf("calc bc \n"); while(t < t_end){ /*if(t - every >= 0){ printf("Calculating time %f ... \n", t); every += t; }*/ //adaptive time stepping calculate_dt(Re, tau, &dt, dx, dy, dz, imax, jmax, kmax, U, V, W); // printf("calc dt \n"); /* mark_cells(Flag,dx,dy,dz,imax,jmax,kmax,1,Partlines); set_uvwp_surface(U,V,W,P,Flag,dx,dy,dz,imax,jmax,kmax,GX,GY,GZ,dt,Re); */ //computing F, G, H and right hand side of pressue eq. calculate_fgh(Re, GX, GY, GZ, alpha, dt, dx, dy, dz, imax, jmax, kmax, U, V, W, F, G, H, Flag); // printf("calc fgh \n"); calculate_rs(dt, dx, dy, dz, imax, jmax, kmax, F, G, H, RS,Flag); // printf("calc rs \n"); //iteration counter it = 0; //write_matrix2("RS.txt",t,RS, 1, imax, 1, jmax, 1, kmax); //write_matrix2("F.txt",t,F, 0, imax, 1, jmax, 1, kmax); //write_matrix2("G.txt",t,G, 1, imax, 0, jmax, 1, kmax); //write_matrix2("H.txt",t,H, 1, imax, 1, jmax, 0, kmax); do{ // sprintf( szFileName, "P_%d.txt",it ); //write_matrix2(szFileName,1000+t,P, 0, imax+1, 0, jmax+1, 0, kmax+1); //perform SOR iteration, at same time set bound.values for P and new residual value sor(omg, dx, dy, dz, imax, jmax, kmax, P, RS, &res, Flag); //, presLeft, presRight); it++; }while(it<itermax && res>eps); /*if (it == itermax) { printf("Warning: sor while loop exits because it reaches the itermax. res = %f, time =%f\n", res, t); } */ //write_matrix2("P.txt",t,P, 0, imax+1, 0, jmax+1, 0, kmax+1); //calculate U, V and W of this time step calculate_uvw(dt, dx, dy, dz, imax, jmax, kmax, U, V, W, F, G, H, P, Flag); //write_matrix2("U.txt",t,U, 0, imax+1, 0, jmax+1, 0, kmax+1); //write_matrix2("V.txt",t,V, 0, imax+1, 0, jmax+1, 0, kmax+1); //write_matrix2("W.txt",t,W, 0, imax+1, 0, jmax+1, 0, kmax+1); // printf("calc uvw \n"); //sprintf( szFileName, "simulation/%s.%i_debug.vtk", szProblem, timeStepNumber ); //setting bound.values boundaryvalues(imax, jmax, kmax, U, V, W, P, F, G, H, problemGeometry, Flag, velIN, velMW); //including P, wl, wr, wt, wb, F, G, problem /* set_uvwp_surface(U,V,W,P,Flag,dx,dy,dz,imax,jmax,kmax,GX,GY,GZ,dt,Re); printf("advance_particles!\n"); advance_particles(dx,dy, dz,imax,jmax,kmax, dt,U,V,W,1,Partlines); */ //indent time and number of time steps printf("timer\n"); n++; t += dt; //output of pics for animation if ( t-last_output_t >= dt_value ){ //n%pics==0 ){ printf("output\n!"); write_particles(filename,n, 1, Partlines); write_vtkFile(filename, n, xlength, ylength, zlength, imax, jmax, kmax, dx, dy, dz, U, V, W, P,Flag); printf("output vtk (%d)\n",n); last_output_t = t; matrix_output++; } printf("timestep: %f - next output: %f (dt: %f) \n",t,dt_value- (t-last_output_t),dt); } //output of U, V, P at the end for visualization //write_vtkFile("DrivenCavity", n, xlength, ylength, imax, jmax, dx, dy, U, V, P); //free memory free_matrix2(U, 0, imax+1, 0, jmax+1, 0, kmax+1); free_matrix2(V, 0, imax+1, 0, jmax+1, 0, kmax+1); free_matrix2(W, 0, imax+1, 0, jmax+1, 0, kmax+1); free_matrix2(P, 0, imax+1, 0, jmax+1, 0, kmax+1); free_matrix2(RS, 1, imax, 1, jmax, 1, kmax); free_matrix2(F, 0, imax, 1, jmax, 1, kmax); free_matrix2(G, 1, imax, 0, jmax, 1, kmax); free_matrix2(H, 1, imax, 1, jmax, 0, kmax); free_imatrix2(Flag, 0, imax+1, 0, jmax+1, 0, kmax+1); free_imatrix2(S, 0, imax+1, 0, jmax+1, 0, kmax+1); //printf("\n-\n"); return -1; }