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; }
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; }