Пример #1
0
// 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);
}
Пример #2
0
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 */