diff --git a/heat_fd_solvers/heat_1d.chpl b/heat_fd_solvers/heat_1d.chpl new file mode 100644 index 0000000..a7c91df --- /dev/null +++ b/heat_fd_solvers/heat_1d.chpl @@ -0,0 +1,57 @@ +import Time.stopwatch; + +// ---- set up simulation parameters ------ +// declare configurable parameters with default values +config const xLen = 2.0, // length of the grid in x + nx = 31, // number of grid points in x + nt = 50, // number of time steps + sigma = 0.25, // stability parameter + nu = 0.05; // viscosity + +// declare non-configurable parameters +const dx : real = xLen / (nx - 1), // grid spacing in x + dt : real = sigma * dx / nu; // time step size + +var t = new stopwatch(); + +// ---- set up the grid ------ +// define a domain and subdomain to describe the grid and its interior +const indices = {0.. un; + + // update the solution over the interior of the domain in parallel + forall i in indicesInner { + u[i] = un[i] + nu * dt / dx**2 * + (un[i-1] - 2 * un[i] + un[i+1]); + } +} + +// stop timing +t.stop(); + +// ---- print final results ------ +const mean = (+ reduce u) / u.size, + stdDev = sqrt((+ reduce (u - mean)**2) / u.size); + +writeln("mean: ", mean, " stdDev: ", stdDev); +writeln("elapsed time: ", t.elapsed(), " seconds"); diff --git a/heat_fd_solvers/heat_1d_explicit.chpl b/heat_fd_solvers/heat_1d_explicit.chpl new file mode 100644 index 0000000..011dfee --- /dev/null +++ b/heat_fd_solvers/heat_1d_explicit.chpl @@ -0,0 +1,86 @@ +import Time.stopwatch; + +// ---- set up simulation parameters ------ +// declare configurable parameters with default values +config const xLen = 2.0, // length of the grid in x + nx = 31, // number of grid points in x + nt = 50, // number of time steps + sigma = 0.25, // stability parameter + nu = 0.05; // viscosity + +// declare non-configurable parameters +const dx : real = xLen / (nx - 1), // grid spacing in x + dt : real = sigma * dx / nu, // time step size + nTasks = here.maxTaskPar, // number of tasks + npt = nx / nTasks; // number of grid points per task + +param LEFT = 0, RIGHT = 1; + +var t = new stopwatch(); + +// ---- set up the grid ------ +// define a domain to describe the grid +const indices = {0.. uLocal2; + } + + // store results in the global array + u[taskIndices] = uLocal1; +} + +// start timing +t.start(); + +// run the simulation across tasks +coforall tid in 0.. uLocal2; + } + + // store results in the global array + u[taskIndices] = uLocal1; +} + +// start timing and comm diagnostics +t.start(); +startVerboseComm(); + +// run the simulation across tasks +coforall (loc, lid) in zip(Locales, 0..) do on loc { + coforall tid in 0.. 0 then ghostVecs[tidX-1, tidY][R].v = uLocal1[LL+1, ..]; + if tidX < tidXMax then ghostVecs[tidX+1, tidY][L].v = uLocal1[RR-1, ..]; + if tidY > 0 then ghostVecs[tidX, tidY-1][B].v = uLocal1[.., TT-1]; + if tidY < tidYMax then ghostVecs[tidX, tidY+1][T].v = uLocal1[.., BB+1]; + + b.barrier(); + + // run FD computation + for 1..nt { + // populate local edges from ghost regions + if tidX > 0 then uLocal1[LL, ..] = ghostVecs[tidX, tidY][L].v; + if tidX < tidXMax then uLocal1[RR, ..] = ghostVecs[tidX, tidY][R].v; + if tidY > 0 then uLocal1[.., TT] = ghostVecs[tidX, tidY][T].v; + if tidY < tidYMax then uLocal1[.., BB] = ghostVecs[tidX, tidY][B].v; + + // compute the FD kernel in parallel + forall (i, j) in localIndices { + uLocal2[i, j] = uLocal1[i, j] + + nu * dt / dy**2 * + (uLocal1[i-1, j] - 2 * uLocal1[i, j] + uLocal1[i+1, j]) + + nu * dt / dx**2 * + (uLocal1[i, j-1] - 2 * uLocal1[i, j] + uLocal1[i, j+1]); + } + + // populate ghost regions for neighboring locales + if tidX > 0 then ghostVecs[tidX-1, tidY][R].v = uLocal2[LL+1, ..]; + if tidX < tidXMax then ghostVecs[tidX+1, tidY][L].v = uLocal2[RR-1, ..]; + if tidY > 0 then ghostVecs[tidX, tidY-1][B].v = uLocal2[.., TT-1]; + if tidY < tidYMax then ghostVecs[tidX, tidY+1][T].v = uLocal2[.., BB+1]; + + // synchronize with other tasks + b.barrier(); + + // swap arrays + uLocal1 <=> uLocal2; + } + + // store results back in global array + u[localIndices] = uLocal1[localIndices]; +} + +record GhostVec { + var d: domain(1); + var v: [d] real; + + proc init() do this.d = {0..0}; + proc init(r: range(int, boundKind.both, strideKind.one)) do + this.d = {r}; +}