GrayScott::GrayScott(int N, double L, double dt, double Du, double Dv, double F, double k, int nSteps, std::string pngname) : N_(N) , Ntot_(N*N) // , L_(L) , dx_((double) L / (double) N) , dt_(dt) , nSteps_(nSteps) , currStep_(0) , Du_(Du) , Dv_(Dv) , F_(F) , k_(k) , matU1_(N, -Du*dt/(2.*dx_*dx_), 1.+Du*dt/(dx_*dx_), -Du*dt/(2.*dx_*dx_)) , matU2_(N, -Du*dt/(2.*dx_*dx_), 1.+Du*dt/(dx_*dx_), -Du*dt/(2.*dx_*dx_)) // equal to matU1_, since we have a square grid (dx==dy) , matV1_(N, -Dv*dt/(2.*dx_*dx_), 1.+Dv*dt/(dx_*dx_), -Dv*dt/(2.*dx_*dx_)) , matV2_(N, -Dv*dt/(2.*dx_*dx_), 1.+Dv*dt/(dx_*dx_), -Dv*dt/(2.*dx_*dx_)) , pngName_(pngname) { // create directory to save output to time_t rawtime; struct tm * timeinfo; char buffer[80]; time (&rawtime); timeinfo = localtime(&rawtime); strftime(buffer,80,"%d-%m-%Y_%H-%M-%S",timeinfo); std::string timeString(buffer); dirPath_ = "data/" + timeString + "/"; boost::filesystem::path dir(dirPath_); boost::filesystem::create_directory(dir); initialize_fields(); }
/** * \brief Sets the type of this entity. * * When the type changes, all fields are reset to their default value. * * \param type The new type. */ void EntityData::set_type(EntityType type) { if (type == this->type) { return; } this->type = type; initialize_fields(); }
/** * \brief Creates data for an entity of the given type. * \param type A type of entity. */ EntityData::EntityData(EntityType type) : type(type), name(), layer(0), xy(), fields() { initialize_fields(); }
/** * \brief Creates data for an entity of a default-constructed type. */ EntityData::EntityData() : type(), name(), layer(LAYER_LOW), xy(), fields() { initialize_fields(); }
int main (int argc, char ** argv) { int i; /* * this is set to either euler or runge_kutta_4 */ enum solver_t solver; /* * bc (boundary condition) can be either periodic or no_slip */ enum bc_t bc; /* * these specify the geometry of the area to be simulated * tdim ist the total number of points, i.e. tdim = xdim *ydim */ int xdim, ydim, tdim; double dx, dy; /* * this holds the neighbors */ int **neighbors; /* * this holds latitude and longitude values of each point */ unsigned int *lat, *lon; /* * this holds order of the data to be printed out */ unsigned int *print_out_order; /* * these control temporal aspects of the simulation */ long int ncycle; double dt = 5.1; long int n_iter = 25800; int write_out_interval = 5000; /* * these hold the physical parameters * * f0: coriolis parameter (1/1sec) * beta: linear beta for coriolis force (1/(meter sec)) * forcingTerm: Wind stress amplitude "tau_0"(N/meter^2) * dissipationTerm: "A" viscosity coefficient (meters^2/sec) * RayleighFriction: Rayleigh friction parameter (1/sec) */ double f0 = 5.0e-5; double beta =2e-11; double forcingTerm = 0.0005; double dissipationTerm = 0.00005; double RayleighFriction = 5e-8; /* * upper layer equilibrium depth (meters) */ double EquilibriumDepth = 50000.0; double A; /* * this holds the physical parameters and the forcing */ double *parameters; double *x_forcing, *y_forcing, *z_forcing; /* * "fields" holds the values of the u, v and P fields */ double *fields; double *u, *v, *P; /* * "fields_prev" holds the u, v and P values of the previous time step */ //double *fields_prev; //double *u_prev, *v_prev, *P_prev; /* * these are temporary storage locations * for the Runge-Kutta scheme */ double *temp_dots_rk; double *temp_fields_rk; /* * read parameters from command line */ if(argc == 2){ get_parameters(argv[1], &xdim, &ydim, &dx, &dy, &n_iter, &dt, &write_out_interval, &bc, &solver, &f0, &beta, &forcingTerm, &dissipationTerm, &RayleighFriction, &EquilibriumDepth, &A); } else{ fprintf(stderr, "ERROR: You need to give a file containing the parameters as an argument!\n"); exit(1); } print_parameters(xdim, ydim, dx, dy, n_iter, dt, write_out_interval, bc, solver, f0, beta, forcingTerm, dissipationTerm, RayleighFriction, EquilibriumDepth, A); tdim = xdim*ydim; /* * allocate arrays containing geometrical information and fill these */ lat = calloc(tdim, sizeof(unsigned int)); lon = calloc(tdim, sizeof(unsigned int)); print_out_order = calloc(tdim, sizeof(unsigned int)); neighbors = calloc(tdim, sizeof(int*)); for(i=0; i< tdim; i++){ neighbors[i] = calloc(4, sizeof(int)); } initialize_geometry(xdim, ydim, neighbors, lat, lon, print_out_order); /* * allocate memory for physical parameters and forcing */ parameters = calloc(5+3*tdim, sizeof(double)); parameters[0] = f0; parameters[1] = beta; parameters[2] = forcingTerm; parameters[3] = dissipationTerm; parameters[4] = RayleighFriction; x_forcing = parameters + 5; y_forcing = parameters + 5 + tdim; z_forcing = parameters + 5 + 2*tdim; /* * allocate "fields" and set addresses for u, v, and P */ fields = calloc(3*tdim, sizeof(double)); u = fields; v = fields + tdim; P = fields + 2 * tdim; /* * allocate "fields_prev" and set addresses for u_prev, v_prev, and P_prev */ //fields_prev = calloc(3*tdim, sizeof(double)); //u_prev = fields_prev; //v_prev = fields_prev + tdim; //P_prev = fields_prev + 2 * tdim; double *fields_dot; fields_dot = calloc(3*tdim, sizeof(double)); /* * allocate memory for temporary Runge-Kutta storage locations */ temp_dots_rk = calloc(3*tdim, sizeof(double)); temp_fields_rk = calloc(3*tdim, sizeof(double)); /* * initialize fields */ initialize_fields (u, v, P, x_forcing, y_forcing, z_forcing, xdim, ydim, dx, dy, EquilibriumDepth, A, neighbors, lat, lon, bc); /* * loop through time steps to do the actual simulation */ for (ncycle=0; ncycle<n_iter; ncycle++) { //printf("step #%li\n", ncycle); /* * print result */ if(ncycle % write_out_interval == 0){ print_field(u, "u", ncycle, xdim, ydim, print_out_order); print_field(v, "v", ncycle, xdim, ydim, print_out_order); print_field(P, "P", ncycle, xdim, ydim, print_out_order); printf("%li ", ncycle); fflush(stdout); } Fcalc(fields_dot, fields, parameters, xdim, ydim, dx, dy, neighbors, lat, bc, print_out_order, ncycle); //for (i=0;i<3*tdim;i++) { // fields_prev[i] = fields[i]; //} if(solver == runge_kutta_4){ /* * Runge-Kutta 4th order * * dt * y_1 = y_0 + ---- (y'_0 + 2 * y'_A + 2 * y'_B +y'_C) * 6 */ /* dt * first step: y_A = y_0 + ---- y'_0 * 2 */ for (i=0; i < 3*tdim; i++) { temp_fields_rk[i] = fields[i]+0.5*dt*fields_dot[i]; } Fcalc(temp_dots_rk, temp_fields_rk, parameters, xdim, ydim, dx, dy, neighbors, lat, bc, print_out_order, ncycle); for (i=0; i < 3*tdim; i++) { fields_dot[i] += 2*temp_dots_rk[i]; } /* dt * second step: y_B = y_0 + ---- y'_A * 2 */ for (i=0; i < 3*tdim; i++) { temp_fields_rk[i] = fields[i]+0.5*dt*temp_dots_rk[i]; } Fcalc(temp_dots_rk, temp_fields_rk, parameters, xdim, ydim, dx, dy, neighbors, lat, bc, print_out_order, ncycle); for (i=0; i < 3*tdim; i++) { fields_dot[i] += 2*temp_dots_rk[i]; } /* * third step: y_C = y_0 + dt * y'_B */ for (i=0; i < 3*tdim; i++){ temp_fields_rk[i] = fields[i]+dt*temp_dots_rk[i]; } Fcalc(temp_dots_rk, temp_fields_rk, parameters, xdim, ydim, dx, dy, neighbors, lat, bc, print_out_order, ncycle); for (i=0; i < 3*tdim; i++) { fields_dot[i] += temp_dots_rk[i]; } /* dt * final step: y_1 = y_0 + ---- (y'_0 + 2 * y'_A + 2 * y'_B +y'_C) * 6 */ for (i=0; i < 3*tdim; i++) { fields_dot[i] /= 6.0; fields[i] += dt*fields_dot[i]; } } else{ if(solver == euler){ /* * the Euler scheme */ for (i=0; i < 3*tdim; i++) { fields[i] += dt*fields_dot[i]; } } else{ fprintf(stderr, "ERROR: No valid solver was found\n"); exit(2); } } } printf("\n"); return(0); }
GrayScott::GrayScott(int N, double rmin, double rmax, double dt, double Du, double Dv, double F, double k, int nSteps, std::string pngname, world_info w, bool localtranspose, unsigned int nthreads) : N_(N) , Ntot_(N*N) // , L_(L) , dx_((double) (rmax-rmin) / (double) (N-1)) , dt_(dt)//(dx_*dx_ / (2.*std::max(Du,Dv))) , nSteps_(nSteps) , currStep_(0) , Du_(Du) , Dv_(Dv) , uCoeff(Du_*dt_/(2.*dx_*dx_)) , vCoeff(Dv_*dt_/(2.*dx_*dx_)) , F_(F) , k_(k) , matU1_(N, -Du*dt/(2.*dx_*dx_), 1.+Du*dt/(dx_*dx_), -Du*dt/(2.*dx_*dx_)) // , matU2_(N, -Du*dt/(2.*dx_*dx_), 1.+Du*dt/(dx_*dx_), -Du*dt/(2.*dx_*dx_)) // equal to matU1_, since we have a square grid (dx==dy) , matV1_(N, -Dv*dt/(2.*dx_*dx_), 1.+Dv*dt/(dx_*dx_), -Dv*dt/(2.*dx_*dx_)) // , matV2_(N, -Dv*dt/(2.*dx_*dx_), 1.+Dv*dt/(dx_*dx_), -Dv*dt/(2.*dx_*dx_)) , pngName_(pngname) , world(w) , rmin_(rmin) , rmax_(rmax) , localtranspose_(localtranspose) , nthreads_(nthreads) { if (world.rank == 0) { // create directory to save output to time_t rawtime; struct tm * timeinfo; char buffer[80]; time (&rawtime); timeinfo = localtime(&rawtime); strftime(buffer,80,"%d-%m-%Y_%H-%M-%S",timeinfo); std::string timeString(buffer); dirPath_ = "data/" + timeString + "/"; boost::filesystem::path dir(dirPath_); // boost::filesystem::create_directory(dir); } // global grid Nx_glo = N; Ny_glo = N; NN_glo = Nx_glo * Ny_glo; // local grid Nx_loc = Nx_glo / world.dims_x; Ny_loc = Ny_glo / world.dims_y; NN_loc = Nx_loc * Ny_loc; Nb_loc = Ny_loc/Nx_loc; // build process geometry with cartesian communicator int periods[2] = {false, false}; int dims[2] = {world.dims_x, world.dims_y}; MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, true, &cart_comm); MPI_Comm_rank(cart_comm, &world.cart_rank); MPI_Cart_shift(cart_comm, 0, 1, &world.top_proc, &world.bottom_proc); int coords[2]; MPI_Cart_coords(cart_comm, world.cart_rank, 2, coords); world.coord_x = coords[0]; world.coord_y = coords[1]; // datatypes // build contiguous (rows) vectors for boundaries. // each process has multiple rows in the grid MPI_Type_contiguous(Ny_loc, MPI_DOUBLE, &bottom_boundary); MPI_Type_commit(&bottom_boundary); MPI_Type_contiguous(Ny_loc, MPI_DOUBLE, &top_boundary); MPI_Type_commit(&top_boundary); // build datatypes for transpose MPI_Datatype block_send, block_col, block_recv; // send datatype int sizes[2] = {Nx_loc, Ny_loc}; // size of global array int subsizes[2] = {Nx_loc, Nx_loc}; // size of sub-region (square) int starts[2] = {0,0}; // where does the first subarray begin (which index) MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &block_send); MPI_Type_commit(&block_send); // resize -> make contiguous MPI_Type_create_resized(block_send, 0, Nx_loc*sizeof(double), &block_resized_send); MPI_Type_free(&block_send); MPI_Type_commit(&block_resized_send); // receive datatype MPI_Type_vector(Nx_loc, 1, Ny_loc, MPI_DOUBLE, &block_col); MPI_Type_commit(&block_col); MPI_Type_hvector(Nx_loc, 1, sizeof(double), block_col, &block_recv); MPI_Type_free(&block_col); MPI_Type_commit(&block_recv); // resize data structure, so that it is contigious (for alltoall) MPI_Type_create_resized(block_recv, 0, 1*sizeof(double), &block_resized_recv); MPI_Type_free(&block_recv); MPI_Type_commit(&block_resized_recv); // sub-domain boundaries xmin_loc = rmin + world.coord_x * Nx_loc * dx_; xmax_loc = xmin_loc + (Nx_loc - 1) * dx_; ymin_loc = rmin + world.coord_y * Ny_loc * dx_; ymax_loc = ymin_loc + (Ny_loc - 1) * dx_; initialize_fields(); MPI_Barrier(MPI_COMM_WORLD); }