int main(void){ double *u_past; double *u_present; double delta_x=0.01; int n_x = (int)(10.0/delta_x); double delta_t = 1E-4; int n_t = (int)(2.0/delta_t); double c = 1.0; int i; /*reserva memoria*/ u_past = malloc(n_x * sizeof(double)); u_present = malloc(n_x * sizeof(double)); /*inicializacion*/ initial_condition(u_past, n_x, delta_x); for(i=0;i<n_t;i++){ update_u(u_present, u_past, n_x,delta_x, delta_t, c); copy(u_present, u_past, n_x); } /*imprime en pantalla*/ print_u(u_past, n_x); return 0; }
tree hide_evolution_in_other_loops_than_loop (tree chrec, unsigned loop_num) { struct loop *loop = get_loop (cfun, loop_num), *chloop; if (automatically_generated_chrec_p (chrec)) return chrec; switch (TREE_CODE (chrec)) { case POLYNOMIAL_CHREC: chloop = get_chrec_loop (chrec); if (chloop == loop) return build_polynomial_chrec (loop_num, hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), loop_num), CHREC_RIGHT (chrec)); else if (flow_loop_nested_p (chloop, loop)) /* There is no evolution in this loop. */ return initial_condition (chrec); else { gcc_assert (flow_loop_nested_p (loop, chloop)); return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), loop_num); } default: return chrec; } }
tree hide_evolution_in_other_loops_than_loop (tree chrec, unsigned loop_num) { if (automatically_generated_chrec_p (chrec)) return chrec; switch (TREE_CODE (chrec)) { case POLYNOMIAL_CHREC: if (CHREC_VARIABLE (chrec) == loop_num) return build_polynomial_chrec (loop_num, hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), loop_num), CHREC_RIGHT (chrec)); else if (CHREC_VARIABLE (chrec) < loop_num) /* There is no evolution in this loop. */ return initial_condition (chrec); else return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), loop_num); default: return chrec; } }
tree initial_condition (tree chrec) { if (automatically_generated_chrec_p (chrec)) return chrec; if (TREE_CODE (chrec) == POLYNOMIAL_CHREC) return initial_condition (CHREC_LEFT (chrec)); else return chrec; }
int main() { const double ti=0.0; const double te=17.0652165601579625588917206249; std::vector<double> position; std::vector<double> velocity; initial_condition(position, velocity); //euler(position, velocity, ti, te); rk4(position, velocity, ti, te); return 0; }
static bool main_loop (void) { unsigned int app_state = 0; unsigned long int counter = 0; double s, t; initial_condition(n, px, py, vx, vy, m); s = 0.0; NBODY_OMP_PARALLEL do { NBODY_OMP_MASTER { t = timer(); } physics_advance(dt, n, px, py, vx, vy, m); NBODY_OMP_MASTER { t = timer() - t; s += t; if (draw_redraw()) { draw_particles(dt, n, px, py, vx, vy, m); app_state = draw_input(app_state, &dt); } counter += 1; if ((counter % 1000LU) == 0) printf("%lu\n", counter); } NBODY_OMP_BARRIER ; } while (! (app_state & EXIT) && ! (app_state & RESET)); printf("%lu physics iterations over %f seconds, ratio %f\n", counter, s, counter/s); return app_state & RESET; }
int main(){ double x_f = 1.0; int n_x = 1000; double delta_x = 0.001; double delta_t = 5E-4; int n_t = 350.0; double c = 1.0; double r = c * delta_t/delta_x; double *u_past = malloc(n_x*sizeof(double)); double *u_present = malloc(n_x*sizeof(double)); double *u_future = malloc(n_x*sizeof(double)); initial_condition(u_past, n_x, delta_x); /*print_u(u_past, n_x, delta_x);*/ u_past[0] = 0.0; u_past[n_x-1] = 0.0; u_present[0] = 0.0; u_present[n_x-1] = 0.0; first_iteration(u_present, u_past, n_x, r); copy(u_present, u_past, n_x); /*print_u(u_present, n_x, delta_x);*/ int i; for(i=0;i<n_t;i++){ update_u(u_future, u_present, u_past, n_x, r); copy(u_present, u_past, n_x); copy(u_future, u_present, n_x); } print_u(u_present, n_x, delta_x); return 0; }
int main ( ) /******************************************************************************/ /* Purpose: FD1D_ADVECTION_FTCS solves the advection equation using the FTCS method. Discussion: The FTCS method is unstable for the advection problem. Given a smooth initial condition, successive FTCS approximations will exhibit erroneous oscillations of increasing magnitude. Licensing: This code is distributed under the GNU LGPL license. Modified: 25 December 2012 Author: John Burkardt */ { double a; double b; double c; char command_filename[] = "advection_commands.txt"; FILE *command_unit; char data_filename[] = "advection_data.txt"; FILE *data_unit; double dt; double dx; int i; int j; int jm1; int jp1; int nx; int nt; int nt_step; int plotstep; double t; double *u; double *unew; double *x; timestamp ( ); printf ( "\n" ); printf ( "FD1D_ADVECTION_FTCS:\n" ); printf ( " C version\n" ); printf ( "\n" ); printf ( " Solve the constant-velocity advection equation in 1D,\n" ); printf ( " du/dt = - c du/dx\n" ); printf ( " over the interval:\n" ); printf ( " 0.0 <= x <= 1.0\n" ); printf ( " with periodic boundary conditions, and\n" ); printf ( " with a given initial condition\n" ); printf ( " u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" ); printf ( " = 0 elsewhere.\n" ); printf ( "\n" ); printf ( " We use a method known as FTCS:\n" ); printf ( " FT: Forward Time : du/dt = (u(t+dt,x)-u(t,x))/dt\n" ); printf ( " CS: Centered Space: du/dx = (u(t,x+dx)-u(t,x-dx))/2/dx\n" ); nx = 101; dx = 1.0 / ( double ) ( nx - 1 ); a = 0.0; b = 1.0; x = r8vec_linspace_new ( nx, a, b ); nt = 1000; dt = 1.0 / ( double ) ( nt ); c = 1.0; u = initial_condition ( nx, x ); /* Open data file, and write solutions as they are computed. */ data_unit = fopen ( data_filename, "wt" ); t = 0.0; fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[0], t, u[0] ); for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = 100; printf ( "\n" ); printf ( " Number of nodes NX = %d\n", nx ); printf ( " Number of time steps NT = %d\n", nt ); printf ( " Constant velocity C = %g\n", c ); unew = ( double * ) malloc ( nx * sizeof ( double ) ); for ( i = 0; i < nt; i++ ) { for ( j = 0; j < nx; j++ ) { jm1 = i4_wrap ( j - 1, 0, nx - 1 ); jp1 = i4_wrap ( j + 1, 0, nx - 1 ); unew[j] = u[j] - c * dt / dx / 2.0 * ( u[jp1] - u[jm1] ); } for ( j = 0; j < nx; j++ ) { u[j] = unew[j]; } if ( i == nt_step - 1 ) { t = ( double ) ( i ) * dt; for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = nt_step + 100; } } /* Close the data file once the computation is done. */ fclose ( data_unit ); printf ( "\n" ); printf ( " Plot data written to the file \"%s\"\n", data_filename ); /* Write gnuplot command file. */ command_unit = fopen ( command_filename, "wt" ); fprintf ( command_unit, "set term png\n" ); fprintf ( command_unit, "set output 'advection.png'\n" ); fprintf ( command_unit, "set grid\n" ); fprintf ( command_unit, "set style data lines\n" ); fprintf ( command_unit, "unset key\n" ); fprintf ( command_unit, "set xlabel '<---X--->'\n"); fprintf ( command_unit, "set ylabel '<---Time--->'\n" ); fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename ); fprintf ( command_unit, "quit\n" ); fclose ( command_unit ); printf ( " Gnuplot command data written to the file \"%s\"\n", command_filename ); /* Free memory. */ free ( u ); free ( unew ); free ( x ); /* Terminate. */ printf ( "\n" ); printf ( "FD1D_ADVECTION_FTCS\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
int main ( ) /******************************************************************************/ /* Purpose: FD1D_ADVECTION_LAX_WENDROFF: advection equation using Lax-Wendroff method. Licensing: This code is distributed under the GNU LGPL license. Modified: 11 March 2013 Author: John Burkardt */ { double a; double b; double c; double c1; double c2; char command_filename[] = "advection_commands.txt"; FILE *command_unit; char data_filename[] = "advection_data.txt"; FILE *data_unit; double dt; double dx; int i; int j; int jm1; int jp1; int nx; int nt; int nt_step; int plotstep; double t; double *u; double *unew; double *x; timestamp ( ); printf ( "\n" ); printf ( "FD1D_ADVECTION_LAX_WENDROFF:\n" ); printf ( " C version\n" ); printf ( "\n" ); printf ( " Solve the constant-velocity advection equation in 1D,\n" ); printf ( " du/dt = - c du/dx\n" ); printf ( " over the interval:\n" ); printf ( " 0.0 <= x <= 1.0\n" ); printf ( " with periodic boundary conditions, and\n" ); printf ( " with a given initial condition\n" ); printf ( " u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" ); printf ( " = 0 elsewhere.\n" ); printf ( "\n" ); printf ( " We modify the FTCS method using the Lax-Wendroff method:\n" ); nx = 101; dx = 1.0 / ( double ) ( nx - 1 ); a = 0.0; b = 1.0; x = r8vec_linspace_new ( nx, a, b ); nt = 1000; dt = 1.0 / ( double ) ( nt ); c = 1.0; c1 = 0.5 * c * dt / dx; c2 = 0.5 * pow ( c * dt / dx, 2 ); u = initial_condition ( nx, x ); /* Open data file, and write solutions as they are computed. */ data_unit = fopen ( data_filename, "wt" ); t = 0.0; fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[0], t, u[0] ); for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = 100; printf ( "\n" ); printf ( " Number of nodes NX = %d\n", nx ); printf ( " Number of time steps NT = %d\n", nt ); printf ( " Constant velocity C = %g\n", c ); printf ( " CFL condition: dt (%g) <= dx / c (%g)\n", dt, dx / c ); unew = ( double * ) malloc ( nx * sizeof ( double ) ); for ( i = 0; i < nt; i++ ) { for ( j = 0; j < nx; j++ ) { jm1 = i4_wrap ( j - 1, 0, nx - 1 ); jp1 = i4_wrap ( j + 1, 0, nx - 1 ); unew[j] = u[j] - c1 * ( u[jp1] - u[jm1] ) + c2 * ( u[jp1] - 2.0 * u[j] + u[jm1] ); } for ( j = 0; j < nx; j++ ) { u[j] = unew[j]; } if ( i == nt_step - 1 ) { t = ( double ) ( i ) * dt; for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = nt_step + 100; } } /* Close the data file once the computation is done. */ fclose ( data_unit ); printf ( "\n" ); printf ( " Plot data written to the file \"%s\"\n", data_filename ); /* Write gnuplot command file. */ command_unit = fopen ( command_filename, "wt" ); fprintf ( command_unit, "set term png\n" ); fprintf ( command_unit, "set output 'advection_lax_wendroff.png'\n" ); fprintf ( command_unit, "set grid\n" ); fprintf ( command_unit, "set style data lines\n" ); fprintf ( command_unit, "unset key\n" ); fprintf ( command_unit, "set xlabel '<---X--->'\n"); fprintf ( command_unit, "set ylabel '<---Time--->'\n" ); fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename ); fprintf ( command_unit, "quit\n" ); fclose ( command_unit ); printf ( " Gnuplot command data written to the file \"%s\"\n", command_filename ); /* Free memory. */ free ( u ); free ( unew ); free ( x ); /* Terminate. */ printf ( "\n" ); printf ( "FD1D_ADVECTION_LAX_WENDROFF\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
void update ( int id, int p ) /******************************************************************************/ /* Purpose: UPDATE computes the solution of the heat equation. Discussion: If there is only one processor ( P == 1 ), then the program writes the values of X and H to files. Parameters: Input, int ID, the id of this processor. Input, int P, the number of processors. */ { double cfl; double *h; FILE *h_file; double *h_new; int i; int j; int j_min = 0; int j_max = 400; double k = 0.002; int n = 11; MPI_Status status; int tag; double time; double time_delta; double time_max = 10.0; double time_min = 0.0; double time_new; double *x; double x_delta; FILE *x_file; double x_max = 1.0; double x_min = 0.0; /* Have process 0 print out some information. */ if ( id == 0 ) { printf ( "\n" ); printf ( " Compute an approximate solution to the time dependent\n" ); printf ( " one dimensional heat equation:\n" ); printf ( "\n" ); printf ( " dH/dt - K * d2H/dx2 = f(x,t)\n" ); printf ( "\n" ); printf ( " for %f = x_min < x < x_max = %f\n", x_min, x_max ); printf ( "\n" ); printf ( " and %f = time_min < t <= t_max = %f\n", time_min, time_max ); printf ( "\n" ); printf ( " Boundary conditions are specified at x_min and x_max.\n" ); printf ( " Initial conditions are specified at time_min.\n" ); printf ( "\n" ); printf ( " The finite difference method is used to discretize the\n" ); printf ( " differential equation.\n" ); printf ( "\n" ); printf ( " This uses %d equally spaced points in X\n", p * n ); printf ( " and %d equally spaced points in time.\n", j_max ); printf ( "\n" ); printf ( " Parallel execution is done using %d processors.\n", p ); printf ( " Domain decomposition is used.\n" ); printf ( " Each processor works on %d nodes, \n", n ); printf ( " and shares some information with its immediate neighbors.\n" ); } /* Set the X coordinates of the N nodes. We don't actually need ghost values of X but we'll throw them in as X[0] and X[N+1]. */ x = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); for ( i = 0; i <= n + 1; i++ ) { x[i] = ( ( double ) ( id * n + i - 1 ) * x_max + ( double ) ( p * n - id * n - i ) * x_min ) / ( double ) ( p * n - 1 ); } /* In single processor mode, write out the X coordinates for display. */ if ( p == 1 ) { x_file = fopen ( "x_data.txt", "w" ); for ( i = 1; i <= n; i++ ) { fprintf ( x_file, " %f", x[i] ); } fprintf ( x_file, "\n" ); fclose ( x_file ); } /* Set the values of H at the initial time. */ time = time_min; h = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); h_new = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); h[0] = 0.0; for ( i = 1; i <= n; i++ ) { h[i] = initial_condition ( x[i], time ); } h[n+1] = 0.0; time_delta = ( time_max - time_min ) / ( double ) ( j_max - j_min ); x_delta = ( x_max - x_min ) / ( double ) ( p * n - 1 ); /* Check the CFL condition, have processor 0 print out its value, and quit if it is too large. */ cfl = k * time_delta / x_delta / x_delta; if ( id == 0 ) { printf ( "\n" ); printf ( "UPDATE\n" ); printf ( " CFL stability criterion value = %f\n", cfl ); } if ( 0.5 <= cfl ) { if ( id == 0 ) { printf ( "\n" ); printf ( "UPDATE - Warning!\n" ); printf ( " Computation cancelled!\n" ); printf ( " CFL condition failed.\n" ); printf ( " 0.5 <= K * dT / dX / dX = %f\n", cfl ); } return; } /* In single processor mode, write out the values of H. */ if ( p == 1 ) { h_file = fopen ( "h_data.txt", "w" ); for ( i = 1; i <= n; i++ ) { fprintf ( h_file, " %f", h[i] ); } fprintf ( h_file, "\n" ); } /* Compute the values of H at the next time, based on current data. */ for ( j = 1; j <= j_max; j++ ) { time_new = ( ( double ) ( j - j_min ) * time_max + ( double ) ( j_max - j ) * time_min ) / ( double ) ( j_max - j_min ); /* Send H[1] to ID-1. */ if ( 0 < id ) { tag = 1; MPI_Send ( &h[1], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD ); } /* Receive H[N+1] from ID+1. */ if ( id < p-1 ) { tag = 1; MPI_Recv ( &h[n+1], 1, MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD, &status ); } /* Send H[N] to ID+1. */ if ( id < p-1 ) { tag = 2; MPI_Send ( &h[n], 1, MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD ); } /* Receive H[0] from ID-1. */ if ( 0 < id ) { tag = 2; MPI_Recv ( &h[0], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD, &status ); } /* Update the temperature based on the four point stencil. */ for ( i = 1; i <= n; i++ ) { h_new[i] = h[i] + ( time_delta * k / x_delta / x_delta ) * ( h[i-1] - 2.0 * h[i] + h[i+1] ) + time_delta * rhs ( x[i], time ); } /* H at the extreme left and right boundaries was incorrectly computed using the differential equation. Replace that calculation by the boundary conditions. */ if ( 0 == id ) { h_new[1] = boundary_condition ( x[1], time_new ); } if ( id == p - 1 ) { h_new[n] = boundary_condition ( x[n], time_new ); } /* Update time and temperature. */ time = time_new; for ( i = 1; i <= n; i++ ) { h[i] = h_new[i]; } /* In single processor mode, add current solution data to output file. */ if ( p == 1 ) { for ( i = 1; i <= n; i++ ) { fprintf ( h_file, " %f", h[i] ); } fprintf ( h_file, "\n" ); } } if ( p == 1 ) { fclose ( h_file ); } free ( h ); free ( h_new ); free ( x ); return; }
int main(int argc, char **argv){ int i,j,k,n; int nsteps=150; double dt =0.01; /* Computational (2D polar) grid coordinates */ int nx1 = 400; int nx2 = 400; //number of ghost cells on both sides of each dimension //only need 1 for piecewise constant method //need 2 for piecewise linear reconstruction int num_ghost = 2; int nx1_r = nx1; int nx2_r = nx2; nx1 += 2*num_ghost; nx2 += 2*num_ghost; /*non-ghost indices */ int is = num_ghost; int ie= is+nx1_r; int js = num_ghost; int je = js+nx2_r; //convention: these ranges refer to the non-ghost cells //however, the ghost cells have real coordinate interpretations //this means that we must be sure that the number of ghost cells makes sense with the range of coordinates //this is a big problem if the phi polar coordinate runs the whole range [0,2pi) for example //further, all mesh structures (zonal and nodal) will be nx1 x nx2, although we may not fill the ghost entries with anything meaningful //this is to standardize the loop indexing from is:ie /*another convention: when the phi coordinate is periodic, do we repeat the boundary mesh points? yes for now */ double lx1 = 2.0;//these values are inclusive [x1_i, x1_f] double lx2 = M_PI; double x1_i = 0.5; double x2_i = 0.0; double dx2 = lx2/(nx2_r-1); double x2_f = x2_i + lx2; if(X2_PERIODIC){ dx2 = 2*M_PI/(nx2_r); lx2 = dx2*(nx2_r-1); x2_i = 0.0; } double dx1 = lx1/(nx1_r-1); double x1_f = x1_i + lx1; printf("dx1=%lf dx2=%lf \n",dx1,dx2); /*Cell centered (zonal) values of computational coordinate position */ double *x1 = (double *) malloc(sizeof(double)*nx1); double *x2 = (double *) malloc(sizeof(double)*nx2); x1[is] = x1_i; x2[js] = x2_i; for(i=is+1; i<ie; i++){ x1[i] = x1[i-1] + dx1; // printf("%lf\n",x1[i]); } for(i=js+1; i<je; i++){ x2[i] = x2[i-1] + dx2; //printf("%lf\n",x2[i]); } /*Mesh edge (nodal) values of computational coordinate position */ double *x1_b = (double *) malloc(sizeof(double)*(nx1+1)); double *x2_b = (double *) malloc(sizeof(double)*(nx2+1)); x1_b[is] = x1_i - dx1/2; x2_b[js] = x2_i - dx2/2; for(i=is+1; i<=ie; i++){ x1_b[i] = x1_b[i-1] + dx1; // printf("%lf\n",x1_b[i]); } for(i=js+1; i<=je; i++){ x2_b[i] = x2_b[i-1] + dx2; //printf("%lf\n",x2_b[i]); } /*Cell centered (zonal) values of physical coordinate position */ //These must be 2D arrays since coordinate transformation is not diagonal //indexed by x1 rows and x2 columns double **x = (double **) malloc(sizeof(double *)*nx1); double **y = (double **) malloc(sizeof(double *)*nx1); double *dataX = (double *) malloc(sizeof(double)*nx1*nx2); double *dataY = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ x[i] = &(dataX[nx2*i]); y[i] = &(dataY[nx2*i]); } /*precompute coordinate mappings */ for(i=is; i<ie; i++){ for(j=js; j<je; j++){ x[i][j] = X_physical(x1[i],x2[j]); y[i][j] = Y_physical(x1[i],x2[j]); } } /*Mesh edge (nodal) values of physical coordinate position */ double **x_b = (double **) malloc(sizeof(double *)*(nx1+1)); double **y_b = (double **) malloc(sizeof(double *)*(nx1+1)); double *dataXb = (double *) malloc(sizeof(double)*(nx1+1)*(nx2+1)); double *dataYb = (double *) malloc(sizeof(double)*(nx1+1)*(nx2+1)); for(i=0; i<=nx1; i++){ x_b[i] = &(dataXb[(nx2+1)*i]); y_b[i] = &(dataYb[(nx2+1)*i]); } for(i=is; i<=ie; i++){ for(j=js; j<=je; j++){ x_b[i][j] = X_physical(x1_b[i],x2_b[j]); y_b[i][j] = Y_physical(x1_b[i],x2_b[j]); } } /*Edge normal vectors in Cartesian coordinates */ // point radially outward and +\phi /*Coordinate cell capacity */ double **kappa; double *datakappa; kappa = (double **) malloc(sizeof(double *)*nx1); datakappa = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ kappa[i] = &(datakappa[nx2*i]); } for(i=is; i<ie; i++){ for(j=js; j<je; j++){ kappa[i][j] = x1[i]*dx1*dx2/(dx1*dx2); // C_ij/(dx1*dx2) //capacity in ghost cells kappa[ie][j] = (x1[ie-1]+dx1)*dx1*dx2/(dx1*dx2); } kappa[i][je] = (x1[i]+dx1)*dx1*dx2/(dx1*dx2); } /*Average normal edge velocities */ //now we move from cell centered quantities to edge quantities //the convention in this code is that index i refers to i-1/2 edge double **U, **V; double *dataU, *dataV; U = (double **) malloc(sizeof(double *)*nx1); V = (double **) malloc(sizeof(double *)*nx1); dataU = (double *) malloc(sizeof(double)*nx1*nx2); dataV = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ U[i] = &(dataU[nx2*i]); V[i] = &(dataV[nx2*i]); } /*Option #1 for computing edge velocities: path integral of Cartesian stream function */ /* Stream function */ //probably dont need this array //this variable is cell centered stream /* double **stream; double *datastream; stream = (double **) malloc(sizeof(double *)*nx1); datastream = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ stream[i] = &(datastream[nx2*i]); } for(i=is; i<ie; i++){ for(j=js; j<je; j++){ stream[i][j] = stream_function(x[i][j],y[i][j]); } } for(i=is; i<ie; i++){ for(j=js; j<je; j++){ //go an additional step to capture nx2_r+1/2 //average the corner stream functions U[i][j]= (stream_function(X_physical(x1[i]-dx1/2,x2[j]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j]+dx2/2)) - stream_function(X_physical(x1[i]-dx1/2,x2[j]-dx2/2),Y_physical(x1[i]-dx1/2,x2[j]-dx2/2)))/(dx2); V[i][j]= -(stream_function(X_physical(x1[i]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i]+dx1/2,x2[j]-dx2/2)) - stream_function(X_physical(x1[i]-dx1/2,x2[j]-dx2/2),Y_physical(x1[i]-dx1/2,x2[j]-dx2/2)))/dx1; if(j==10) printf("i=%d, u,v=%lf,%lf\n",i,U[i][j],V[i][j]); } j=je; U[i][j]= (stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+3*dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+3*dx2/2)) - stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+dx2/2)))/(dx2); V[i][j]= -(stream_function(X_physical(x1[i]+dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]+dx1/2,x2[j-1]+dx2/2)) - stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+dx2/2)))/dx1; } i=ie; for(j=js; j<je; j++){ U[i][j]= (stream_function(X_physical(x1[i-1]+dx1/2,x2[j]+dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]+dx2/2)) - stream_function(X_physical(x1[i-1]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]-dx2/2)))/(dx2); V[i][j]= -(stream_function(X_physical(x1[i-1]+3*dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+3*dx1/2,x2[j]-dx2/2)) - stream_function(X_physical(x1[i-1]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]-dx2/2)))/dx1; } */ double ux,vy,temp; for(i=is; i<=ie; i++){ for(j=js; j<=je; j++){ /*Option #2: directly specify velocity in Cartesian coordinate basis as a function of cartesian position*/ //radial face i-1/2 velocity_physical(X_physical(x1_b[i],x2_b[j]+dx2/2),Y_physical(x1_b[i],x2_b[j]+dx2/2),&ux,&vy); // Average normal edge velocity: just transform face center velocity to local orthonormal basis? vector_physical_to_coordinate(ux,vy,x2_b[j]+dx2/2,&U[i][j],&temp); #ifdef HORIZONTAL //EXACT SOLUTION FOR EDGE VELOCITY FOR HORIZONTAL FLOW // printf("U_before = %lf\n",U[i][j]); U[i][j] = (sin(x2_b[j]+dx2) - sin(x2_b[j]))/(dx2); // printf("U_after = %lf\n",U[i][j]); #endif //phi face j-1/2 velocity_physical(X_physical(x1_b[i]+dx1/2,x2_b[j]),Y_physical(x1_b[i]+dx1/2,x2_b[j]),&ux,&vy); vector_physical_to_coordinate(ux,vy,x2_b[j],&temp,&V[i][j]); #if defined(SEMI_CLOCK) || defined(GAUSS_CLOCK) velocity_coordinate(x1_b[i],x2_b[j],&U[i][j],&V[i][j]); #endif // printf("U,V = %lf,%lf\n",U[i][j],V[i][j]); } } /* check normalization of velocities */ /* these are naturally not normalized because the cell has finite volume so the edge velocities arent the velocity of the same point */ double norm; double max_deviation =0.0; for(i=is; i<=ie; i++){ for(j=js; j<=je; j++){ norm = sqrt(U[i][j]*U[i][j] + V[i][j]*V[i][j]); if (fabs(norm-1.0) > max_deviation) max_deviation = fabs(norm-1.0); // printf("%0.12lf\n",norm); } } // printf("maximum deviation from 1.0 = %0.12lf\n",max_deviation); /*Option #3: specify velocity in polar coordinates */ /*Check CFL condition, reset timestep */ float **cfl_array; float *dataCFL; cfl_array = (float **) malloc(sizeof(float *)*nx1); dataCFL = (float *) malloc(sizeof(float)*nx1*nx2); for(i=0; i<nx1; i++){ cfl_array[i] = &(dataCFL[nx2*i]); } for(i=1; i<nx1; i++){ for(j=1; j<nx2; j++){ //based on edge velocities or cell centered u,v? if (i >=is && i< ie && j >=js && j <je) cfl_array[i][j] = fabs(U[i][j])*dt/dx1 + fabs(V[i][j])*dt/(x1_b[i]*dx2); //use boundary radius else cfl_array[i][j] =0.0; } } //find maximum CFL value in domain float max_cfl = find_max(dataCFL,nx1*nx2); printf("Largest CFL number = %lf\n",max_cfl); if (max_cfl > CFL || AUTO_TIMESTEP){//reset timestep if needed dt = CFL*dt/max_cfl; for(i=1; i<nx1; i++){ for(j=1; j<nx2; j++){ if (i >=is && i< ie && j >=js && j <je) cfl_array[i][j] = fabs(U[i][j])*dt/dx1 + fabs(V[i][j])*dt/(x1_b[i]*dx2); else cfl_array[i][j] =0.0; } } } max_cfl = find_max(dataCFL,nx1*nx2); printf("Largest CFL number = %lf\n",max_cfl); #ifdef SEMI_CLOCK nsteps = M_PI/dt; printf("nsteps = %d, dt = %lf, t_final = %lf\n",nsteps,dt,nsteps*dt); #endif #ifdef GAUSS_CLOCK nsteps = 2*M_PI/dt; //turn dt down until mod(2*MPI,nsteps) = 0 double remainder = 2*M_PI -nsteps*dt; double extra = remainder/nsteps; double dt_new = dt +extra; printf("nsteps = %d, dt = %lf, dt_new =%lf, remainder = %lf, t_final = %lf t_final_new =%lf\n",nsteps,dt,dt_new,remainder,nsteps*dt,nsteps*dt_new); max_cfl *= dt_new/dt; dt = dt_new; printf("Largest CFL number = %lf\n",max_cfl); #endif /*Conserved variable on the computational coordinate mesh*/ double **Q; double *dataQ; //make contiguous multiarray Q = (double **) malloc(sizeof(double *)*nx1); dataQ = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ Q[i] = &(dataQ[nx2*i]); } /*Initial condition */ //specified as a function of cartesian physical cooridnates, as is the stream function for(i=is; i<ie; i++){ for(j=js; j<je; j++){ Q[i][j] = initial_condition(x[i][j],y[i][j]); } } //net fluctuations/fluxes double U_plus,U_minus,V_plus,V_minus; double **net_fluctuation; double *dataFlux; net_fluctuation = (double **) malloc(sizeof(double *)*nx1); dataFlux = (double *) malloc(sizeof(double)*nx1*nx2); for(i=0; i<nx1; i++){ net_fluctuation[i] = &(dataFlux[nx2*i]); } /* Using Visit VTK writer */ char filename[20]; int dims[] = {nx1_r+1, nx2_r+1, 1}; //dont output ghost cells. //nodal variables have extra edge point int nvars = 2; int vardims[] = {1, 3}; //Q is a scalar, velocity is a 3-vector int centering[] = {0, 1}; // Q is cell centered, velocity is defined at edges const char *varnames[] = {"Q", "edge_velocity"}; /* Curvilinear mesh points stored x0,y0,z0,x1,y1,z1,...*/ //An array of size nI*nJ*nK*3 . These points are nodal, not zonal... unfortunatley float *pts = (float *) malloc(sizeof(float)*(nx1_r+1)*(nx2_r+1)*3); //The array should be layed out as (pt(i=0,j=0,k=0), pt(i=1,j=0,k=0), ... //pt(i=nI-1,j=0,k=0), pt(i=0,j=1,k=0), ...). int index=0; for(k=0; k<1; k++){ for(j=js; j<=je; j++){ for(i=is; i<=ie; i++){ pts[index] = x_b[i][j]; pts[++index] = y_b[i][j]; pts[++index] = 0.0; index++; } } } /* pack U and V into a vector */ float *edge_vel = (float *) malloc(sizeof(float)*(nx1_r+1)*(nx2_r+1)*3); //An array of size nI*nJ*nK*3 index=0; for(k=0; k<1; k++){ for(j=js; j<=je; j++){ for(i=is; i<=ie; i++){ vector_coordinate_to_physical(U[i][j],V[i][j], x2[j], &ux,&vy); //edge_vel[index] = U[i][j]; //edge_vel[++index] = V[i][j]; edge_vel[index] = ux; edge_vel[++index] = vy; edge_vel[++index] = 0.0; index++; } } } // vars An array of variables. The size of vars should be nvars. // The size of vars[i] should be npts*vardim[i]. float *realQ; realQ =(float *) malloc(sizeof(double)*nx1_r*nx2_r); float *vars[] = {(float *) realQ, (float *)edge_vel}; /*-----------------------*/ /* Main timestepping loop */ /*-----------------------*/ for (n=0; n<nsteps; n++){ /*Boundary conditions */ //bcs are specified along a computational coord direction, but are a function of the physical coordinate of adjacent "real cells" for(k=0;k<num_ghost; k++){ for (j=js; j<je; j++){ Q[k][j] = bc_x1i(x[is][j],y[is][j]); Q[nx1-1-k][j] = bc_x1f(x[ie-1][j],y[ie-1][j],(n+1)*dt); } for (i=is; i<ie; i++){ if(X2_PERIODIC){ Q[i][k] = Q[i][je-1-k]; Q[i][nx2-1-k] = Q[i][js+k]; } else{ Q[i][k] = bc_x2i(x[i][js],y[i][js]); Q[i][nx2-1-k] = bc_x2f(x[i][je-1],y[i][je-1]); } } } double flux_limiter =0.0; double *qmu = (double *) malloc(sizeof(double)*3); //manually copy array for computing slope limiters /* Donor cell upwinding */ for (i=is; i<ie; i++){ for (j=js; j<je; j++){ /* First coordinate */ U_plus = fmax(U[i][j],0.0); // max{U_{i-1/2,j},0.0} LHS boundary U_minus = fmin(U[i+1][j],0.0); // min{U_{i+1/2,j},0.0} RHS boundary /*Fluctuations: A^+ \Delta Q_{i-1/2,j} + A^- \Delta Q_{i+1/2,j} */ // net_fluctuation[i][j] = dt/(kappa[i][j]*dx1)*(U_plus*(Q[i][j] - Q[i-1][j]) + U_minus*(Q[i+1][j] - Q[i][j])); /* First order fluxes: F_i+1/2 - F_i-1/2 */ net_fluctuation[i][j] = dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(fmax(U[i+1][j],0.0)*Q[i][j] + U_minus*Q[i+1][j])-x1_b[i]*(U_plus*Q[i-1][j] + fmin(U[i][j],0.0)*Q[i][j])); #ifdef SECOND_ORDER /* Second order fluxes */ if (U[i+1][j] > 0.0){ //middle element is always the upwind element qmu[0] = Q[i-1][j]; qmu[1] = Q[i][j]; qmu[2] = Q[i+1][j]; flux_limiter= flux_PLM(dx1,qmu); } else{ qmu[0] = Q[i+2][j]; qmu[1] = Q[i+1][j]; qmu[2] = Q[i][j]; flux_limiter= flux_PLM(dx1,qmu); /* if (flux_limiter != 0.0){ printf("i,j: %d,%d F_{i+1/2} flux limiter: %lf\n",i,j,flux_limiter); printf("Q0 = %lf Q1= %lf Q2 = %lf\n",qmu[0],qmu[1],qmu[2]); } */ } //F^H_{i+1/2,j} net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(1-dt*fabs(U[i+1][j])/(dx1))*fabs(U[i+1][j])*flux_limiter/2); // net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*((kappa[i][j]/x1_b[i+1]-dt*fabs(U[i+1][j])/(x1_b[i+1]*dx1))*fabs(U[i+1][j])*flux_limiter/2); // net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(kappa[i][j]/x1_b[i+1]-dt*fabs(U[i+1][j])/(x1_b[i+1]*dx1))*fabs(U[i+1][j])*flux_limiter/2); if (U[i][j] > 0.0){ qmu[0] = Q[i-2][j]; //points to the two preceeding bins; qmu[1] = Q[i-1][j]; qmu[2] = Q[i][j]; flux_limiter= flux_PLM(dx1,qmu); } else{ qmu[0] = Q[i+1][j]; //centered around current bin qmu[1] = Q[i][j]; qmu[2] = Q[i-1][j]; flux_limiter= flux_PLM(dx1,qmu); } //F^H_{i-1/2,j} net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*(x1_b[i]*(1-dt*fabs(U[i][j])/(dx1))*fabs(U[i][j])*flux_limiter/2); // net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*((kappa[i-1][j]/x1_b[i]-dt*fabs(U[i][j])/(x1_b[i]*dx1))*fabs(U[i][j])*flux_limiter/2); //net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*(x1_b[i]*(kappa[i-1][j]/x1_b[i]-dt*fabs(U[i][j])/(x1_b[i]*dx1))*fabs(U[i][j])*flux_limiter/2); #endif /* Second coordinate */ V_plus = fmax(V[i][j],0.0); // max{V_{i,j-1/2},0.0} LHS boundary V_minus = fmin(V[i][j+1],0.0); // min{V_{i,j+1/2},0.0} RHS boundary /*Fluctuations: B^+ \Delta Q_{i,j-1/2} + B^- \Delta Q_{i,j+1/2} */ //net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*(V_plus*(Q[i][j] - Q[i][j-1]) + V_minus*(Q[i][j+1] - Q[i][j])); /* Fluxes: G_i,j+1/2 - G_i,j-1/2 */ net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((fmax(V[i][j+1],0.0)*Q[i][j] + V_minus*Q[i][j+1])-(V_plus*Q[i][j-1] + fmin(V[i][j],0.0)*Q[i][j])); #ifdef SECOND_ORDER /* Second order fluxes */ if (V[i][j+1] > 0.0){ qmu[0] = Q[i][j-1]; //points to the two preceeding bins; qmu[1] = Q[i][j]; qmu[2] = Q[i][j+1]; flux_limiter= flux_PLM(dx2,qmu); } else{ qmu[0] = Q[i][j+2]; //centered around current bin qmu[1] = Q[i][j+1]; qmu[2] = Q[i][j]; flux_limiter= flux_PLM(dx2,qmu); /* if (flux_limiter != 0.0){ printf("i,j: %d,%d F_{i+1/2} flux limiter: %lf\n",i,j,flux_limiter); printf("Q0 = %lf Q1= %lf Q2 = %lf\n",qmu[0],qmu[1],qmu[2]); } */ } //G^H_{i,j+1/2} net_fluctuation[i][j] -= dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j+1])/(kappa[i][j]*dx2))*fabs(V[i][j+1])*flux_limiter/2); //net_fluctuation[i][j] -= dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j+1])/(dx2))*fabs(V[i][j+1])*flux_limiter/2); if (V[i][j] > 0.0){ qmu[0] = Q[i][j-2]; //points to the two preceeding bins; qmu[1] = Q[i][j-1]; qmu[2] = Q[i][j]; flux_limiter = flux_PLM(dx2,qmu); } else{ qmu[0] = Q[i][j+1]; //centered around current bin qmu[1] = Q[i][j]; qmu[2] = Q[i][j-1]; flux_limiter= flux_PLM(dx2,qmu); } //G^H_{i,j-1/2} net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j])/(kappa[i][j]*dx2))*fabs(V[i][j])*flux_limiter/2); //net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j])/(dx2))*fabs(V[i][j])*flux_limiter/2); #endif } } /*Apply fluctuations */ for (i=is; i<ie; i++) for (j=js; j<je; j++){ Q[i][j] -= net_fluctuation[i][j]; } /*Source terms */ for (i=is; i<ie; i++) for (j=js; j<je; j++){ } /*Output */ //for now, explicitly copy subarray corresponding to real zonal info: index=0; for (k=0; k<1; k++){ for (j=js; j<je; j++){ for (i=is; i<ie; i++){ //index =(j-num_ghost)*nx2_r + (i-num_ghost); realQ[index] = (float) Q[i][j];//*kappa[i][j]; //\bar{q}=qk density in computational space index++; } } } //debug only horizontal flow /* if (find_max(realQ,nx1_r*nx2_r) > 1.1){ printf("Q greater than 1.0!\n"); for (i=1;i<nx1; i++){ for (j=1; j<nx2; j++){ if (Q[i][j] > 1.0){ printf("i=%d j=%d Q[i][j] = %0.10lf\n",i,j,Q[i][j]); return(0); } } } }*/ sprintf(filename,"advect-%.3d.vtk",n); if(!OUTPUT_INTERVAL){ if (n==nsteps-1) //for only the final result write_curvilinear_mesh(filename,3,dims, pts, nvars,vardims, centering, varnames, vars);} else{ if (!(n%OUTPUT_INTERVAL)) //HAVENT CHECKED THIS write_curvilinear_mesh(filename,3,dims, pts, nvars,vardims, centering, varnames, vars);} printf("step: %d time: %lf max{Q} = %0.7lf min{Q} = %0.7lf sum{Q} = %0.7lf \n", n+1,(n+1)*dt,find_max(realQ,nx1_r*nx2_r),find_min(realQ,nx1_r*nx2_r),sum(realQ,nx1_r*nx2_r)); } return(0); }