// Fixed step Backward Euler ODE solver void back_euler(ode_workspace *odews) { // Declare and initialise additional workspace variables double *beta, *w, *x; // arrays workspace *W; W = odews->W; int ny = W->nu; beta = zerosv(ny); w = zerosv(ny); x = zerosv(ny); double t = odews->t0; double tnext; // Initial newton_matrix computation newton_matrix(odews); int jac_needed = 0; // flag to say that Jacobian is current int converged = 0; write_data(W, t, odews->y); // Write initial data to file write_flow(W, t, W->q, W->q0); write_pressure(W, t, W->p, W->p0); MPI_Barrier(MPI_COMM_WORLD); // Timestep loop for (int i = 0; t < odews->tf; i++) { // Perform a Jacobian update if necessary. This is in sync across // all processors if (jac_needed) { jacupdate(W, t, odews->y); jac_needed = 0; newton_matrix(odews); } // Copy values from previous completed timestep dcopy(ny, odews->y, beta); dcopy(ny, odews->y, w); tnext = t + odews->dt; // Indicate that we haven't converged yet W->flag[W->rank] = 0; converged = 0; // Newton loop for (int k = 0; k < odews->maxits; k++) { evaluate(W, tnext, w, odews->f); // f = g(w) // evaluate also exchanges convergence information. If everyone // has converged, then we can stop. Everyone likewise gets the // request for Jacobian update if (all(W->flag, W->n_procs)) { converged = 1; if (k > odews->nconv) { jac_needed = 1; } break; // w contains the correct value } // Form x = w - beta - dt g (our fcn value for Newton) dcopy(ny, w, x); daxpy(ny, -1, beta, x); daxpy(ny, -odews->dt, odews->f, x); // TEST x[0] = radius etc. - w is the state var value, x is passed on to Newton // for (int la = 0; la < 27; la++) // { // printf("iteration %d, state variable %2d - x: %e w: %e\n", k, la, x[la], w[la] ); // } W->flag[W->rank] = sizecheck(x, ny, odews->ftol); // function value size check lusoln(odews, x); // solve (x is now increment) W->flag[W->rank] |= sizecheck(x, ny, odews->ytol); // increment size check daxpy(ny, -1, x, w); // update w with new value } if (!converged) { printf("Newton iteration failed to converge\n"); exit(1); } t = tnext; dcopy(ny, w, odews->y); // update y values if (fmod(t, odews->dtwrite) < odews->dt) { write_data(W, t, odews->y); write_flow(W, t, W->q, W->q0); write_pressure(W, t, W->p, W->p0); if (W->rank == 0) { printf("time: %e \n",t); } } } free(w); free(x); free(beta); }
int main(int argc, char *argv[]) { FILE *fctl, *fvic_input, *fout, *finput; char *fname_ctl, *fname_input, *fname_vic_input; char vic_path[1024], out_path[1024]; int *startdate, *enddate; int endtime; int ngrid, nheadwaters; int *vic_row, *vic_col; int **vic_ts; int nt; int t, n; int ndays; int nrows, ncols, row, col; int max_t = 1024*2000; // TJT arbitrary - fix this int count; float *ll_limits; float *lat, *lon, *nlinks; float *alpha, *beta; float *dx; float *dist; float **back_index; float *vic_factor, *vic_lat, *vic_lon; float vic_resn; float ***vic_runoff; float ***flow_out; float vic_min_lat, vic_max_lat, vic_min_lon, vic_max_lon; double begin; double time_spent; begin = omp_get_wtime(); /* Read in arguments */ if(argc!=4) { printf("Bad usage!\n"); exit(4); } fname_ctl = argv[1]; fname_input = argv[2]; fname_vic_input = argv[3]; startdate = (int*)calloc(3,sizeof(int)); enddate = (int*)calloc(3,sizeof(int)); // Read in control file data // TJT add check ot make sure control file has right number of inputs fctl = fopen(fname_ctl,"r"); if (fctl==NULL) { printf("Couldn't open %s!\n", fname_ctl); exit(4); } fscanf(fctl, "%s", vic_path); fscanf(fctl,"%s", out_path); fscanf(fctl, "%d %d %d", &startdate[0], &startdate[1], &startdate[2]); fscanf(fctl, "%d %d %d", &enddate[0], &enddate[1], &enddate[2]); fscanf(fctl, "%f", &vic_resn); fclose(fctl); printf("Vic path: %s\n", vic_path); printf("Output file: %s\n", out_path); /* Get the number of grids */ finput = fopen(fname_input, "r"); if (finput==NULL) { printf("Couldn't open %s!\n", fname_input); exit(4); } fread(&ngrid, sizeof(int),1,finput); fclose(finput); //printf("Ngrids %d\n", ngrid); // Now allocate ll_limits = (float*)calloc(4,sizeof(float)); lat = (float*)calloc(ngrid,sizeof(float)); lon = (float*)calloc(ngrid,sizeof(float)); dx = (float*)calloc(ngrid,sizeof(float)); nlinks = (float*)calloc(ngrid,sizeof(float)); alpha = (float*)calloc(ngrid,sizeof(float)); beta = (float*)calloc(ngrid,sizeof(float)); back_index = (float**)calloc(ngrid,sizeof(float*)); for (n=0; n<ngrid; n++) { back_index[n] = (float*)calloc(8,sizeof(float)); } vic_lat = (float*)calloc(ngrid,sizeof(float)); vic_lon = (float*)calloc(ngrid,sizeof(float)); vic_factor = (float*)calloc(ngrid,sizeof(float)); vic_row = (int*)calloc(ngrid, sizeof(int)); vic_col = (int*)calloc(ngrid, sizeof(int)); // Read in input data nheadwaters = read_network_data(ll_limits, lat, lon, dx, nlinks, alpha, beta, back_index, fname_input); printf("Network data read\n"); // Read in vic input data read_vic_network_data(vic_factor, vic_lat, vic_lon, ngrid, fname_vic_input); //printf("557 %.4f %.4f %.4f\n", vic_lat[557], vic_lon[557], vic_factor[557]); printf("Vic network info read\n"); // Calculate endtime - number of seconds of the simulation endtime = calculate_nsecs(startdate, enddate); // Do some more allocating for vic data ndays = endtime / 86400; vic_min_lat = floor(ll_limits[0]); vic_max_lat = ceil(ll_limits[1]); vic_min_lon = floor(ll_limits[2]); vic_max_lon = ceil(ll_limits[3]); nrows = (int)((vic_max_lat - vic_min_lat) / vic_resn); ncols = (int)((vic_max_lon - vic_min_lon) / vic_resn); vic_runoff= (float***)calloc(nrows,sizeof(float**)); for(row=0;row<nrows;row++) { vic_runoff[row] = (float**)calloc(ncols,sizeof(float*)); for (col=0; col<ncols; col++) { vic_runoff[row][col] = (float*)calloc(ndays, sizeof(float)); } } vic_ts= (int**)calloc(ndays,sizeof(int*)); for(row=0;row<ndays;row++) { vic_ts[row] = (int*)calloc(4,sizeof(int)); } // Read in VIC generated runoff printf("Starting to read in the VIC runoff data\n"); read_vic_runoff(vic_runoff, vic_ts, vic_resn, endtime, startdate, enddate, ll_limits, vic_path); printf("Read in the VIC runoff data\n"); // Set up the associated vic rows/cols for each node associate_vic_network(vic_row, vic_col, lat, lon, ll_limits, ngrid, vic_resn); printf("Associated the vic network with links\n"); flow_out= (float***)calloc(nrows,sizeof(float**)); for(row=0;row<nrows;row++) { flow_out[row] = (float**)calloc(ncols,sizeof(float*)); for (col=0; col<ncols; col++) { flow_out[row][col] = (float*)calloc(ndays, sizeof(float)); } } // TJT can stop passing lat and lon this was just to debug printf("Routing the flow...\n"); nt = route_flow(startdate, endtime, alpha, beta, vic_runoff, dx, ngrid, nheadwaters, dist, nlinks, back_index, vic_factor, vic_row, vic_col, vic_ts, flow_out); printf("Routing done!\n"); printf("Saving the output...\n"); write_flow(flow_out, nrows, ncols, ndays, vic_min_lat, vic_min_lon, vic_resn, vic_ts, out_path); printf("Saving complete!\n"); time_spent = (double)(omp_get_wtime()-begin)/60; printf("Execution Time: %f (min)\n",time_spent); return(1); } /* end of main function */