diff --git a/Makefile b/Makefile index c0e74cf883cb7b7572865dbf9ff54f282e08e031..3f07f7168d85a17f57344cb146370db50a146310 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,27 @@ -.PHONY: all build clean lj_ns_cpu lj_ns_gpu +.PHONY: all build clean -all: build lj_ns_cpu lj_ns_gpu +all: build lj_cpu lj_gpu @echo "Everything was done!" build: @echo "Building pairs package..." python3 setup.py build && python3 setup.py install --user -lj_ns_cpu: +lj_ns.cpp: @echo "Generating and compiling Lennard-Jones example for CPU..." python3 examples/lj_func.py cpu -lj_ns_gpu: +lj_ns.cu: @echo "Generating and compiling Lennard-Jones example for GPU..." python3 examples/lj_func.py gpu # Targets -cpu: build lj_ns_cpu - g++ -o lj_ns lj_ns.cpp +lj_cpu: lj_ns.cpp + g++ -o lj_cpu lj_ns.cpp -gpu: build lj_ns_gpu - nvcc -o lj_ns lj_ns.cu +lj_gpu: lj_ns.cu + nvcc -o lj_gpu lj_ns.cu clean: @echo "Cleaning..." - rm -rf build lj_ns lj_ns.cpp lj_ns.cu dist pairs.egg-info functions functions.pdf + rm -rf build lj_cpu lj_gpu lj_ns.cpp lj_ns.cu dist pairs.egg-info functions functions.pdf diff --git a/examples/lj_func.py b/examples/lj_func.py index b75cd272dde75b166bf979fb05da6726ba48cdcd..9dc2fdf2613fb451409ca52fe03b649bdd223d93 100644 --- a/examples/lj_func.py +++ b/examples/lj_func.py @@ -32,13 +32,10 @@ psim.add_position('position') psim.add_vector_property('velocity') psim.add_vector_property('force', vol=True) psim.from_file("data/minimd_setup_4x4x4.input", ['mass', 'position', 'velocity']) -psim.create_cell_lists(2.8, 2.8) -psim.create_neighbor_lists() -psim.periodic(2.8) +psim.build_neighbor_lists(cutoff_radius + skin) psim.vtk_output(f"output/test_{target}") psim.compute(lj, cutoff_radius, {'sigma6': sigma6, 'epsilon': epsilon}) psim.compute(euler, symbols={'dt': dt}) -psim.target(pairs.target_cpu()) if target == 'gpu': psim.target(pairs.target_gpu()) diff --git a/runtime/domain/domain_partitioning.hpp b/runtime/domain/domain_partitioning.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d5dbdfc0e28e5d28c2d22407aa7270ab434eca71 --- /dev/null +++ b/runtime/domain/domain_partitioning.hpp @@ -0,0 +1,60 @@ +//--- +#include "pairs.hpp" + +#pragma once + +namespace pairs { + +template<int ndims> +class DomainPartitioning { +protected: + int world_size, rank; + real_t grid_min[ndims]; + real_t grid_max[ndims]; + +public: + DomainPartitioning(real_t xmin, real_t xmax, real_t ymin, real_t ymax, real_t zmin, real_t zmax) { + static_assert(ndims == 3, "Constructor called from DomainPartitioning class mismatches number of dimensions!"); + PAIRS_ASSERT(xmax > xmin); + PAIRS_ASSERT(ymax > ymin); + PAIRS_ASSERT(zmax > zmin); + + grid_min[0] = xmin; + grid_max[0] = xmax; + grid_min[1] = ymin; + grid_max[1] = ymax; + grid_min[2] = zmin; + grid_max[2] = zmax; + } + + virtual void initialize(); + virtual void finalize(); +}; + +template<int ndims> +class DimensionRanges : DomainPartitioning<ndims> { +protected: + int nranks[ndims]; + int prev[ndims]; + int next[ndims]; + int pbc_prev[ndims]; + int pbc_next[ndims]; + real_t subdom_min[ndims]; + real_t subdom_max[ndims]; + +public: + void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]) { + for(int d = 0; d < ndims; d++) { + neighbor_ranks[d * 2 + 0] = this->prev[d]; + neighbor_ranks[d * 2 + 1] = this->next[d]; + pbc[d * 2 + 0] = this->pbc_prev[d]; + pbc[d * 2 + 1] = this->pbc_next[d]; + subdom[d * 2 + 0] = this->subdom_min[d]; + subdom[d * 2 + 1] = this->subdom_max[d]; + } + } +}; + +class ListOfBoxes : DomainPartitioning {}; + +} diff --git a/runtime/domain/no_partition.hpp b/runtime/domain/no_partition.hpp new file mode 100644 index 0000000000000000000000000000000000000000..db9561f3ccf8e672816c3979f5a31aa09a9714d6 --- /dev/null +++ b/runtime/domain/no_partition.hpp @@ -0,0 +1,30 @@ +//--- +#include "pairs.hpp" +#include "domain_partitioning.hpp" + +#pragma once + +namespace pairs { + +template <int ndims> +class NoPartitioning : DimensionRanges<ndims> { +public: + void initialize(int *argc, const char **argv) { + this->world_size = 1; + this->rank = 0; + + for(int d = 0; d < ndims; d++) { + this->nranks[d] = 1; + this->prev[d] = 0; + this->next[d] = 0; + this->pbc_prev[d] = 1; + this->pbc_next[d] = -1; + this->subdom_min[d] = this->grid_min[d]; + this->subdom_max[d] = this->grid_max[d]; + } + } + + void finalize() {} +}; + +} diff --git a/runtime/domain/regular_6d_stencil.hpp b/runtime/domain/regular_6d_stencil.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a852dcbfee069f12932e4c7af98cf9801637eb21 --- /dev/null +++ b/runtime/domain/regular_6d_stencil.hpp @@ -0,0 +1,81 @@ +//--- +#include "pairs.hpp" +#include "domain_partitioning.hpp" + +#pragma once + +namespace pairs { + +template <int ndims> +class Regular6DStencil : DimensionRanges<ndims> { +public: + void setConfig() { + static_assert(ndims == 3, "setConfig() only implemented for three dimensions!"); + real_t area[ndims]; + real_t best_surf = 0.0; + + for(int d = 0; d < ndims; d++) { + this->nranks[d] = 1; + area[d] = (this->grid_max[d] - this->grid_min[d]) * (this->grid_max[d] - this->grid_min[d]); + best_surf += 2.0 * area[d]; + } + + for(int i = 1; i < world_size; i++) { + if(world_size % i == 0) { + const int rem_yz = world_size / i; + + for(int j = 0; j < rem_yz; j++) { + if(rem_yz % j == 0) { + const int k = rem_yz / j; + const real_t surf = (area[0] / i / j) + (area[1] / i / k) + (area[2] / j / k); + if(surf < best_surf) { + this->nranks[0] = i; + this->nranks[1] = j; + this->nranks[2] = k; + bestsurf = surf; + } + } + } + } + } + } + + void setBoundingBox() { + MPI_Comm cartesian; + int myloc[ndims]; + int periods[ndims]; + int rank_length[ndims]; + int reorder = 0; + + for(int d = 0; d < ndims; d++) { + periods[d] = 1; + rank_length[d] = (this->grid_max[d] - this->grid_min[d]) / this->nranks[d]; + } + + MPI_Cart_create(MPI_COMM_WORLD, ndims, this->nranks, periods, reorder, &cartesian); + MPI_Cart_get(cartesian, ndims, this->nranks, periods, myloc); + for(int d = 0; d < ndims; d++) { + MPI_Cart_shift(cartesian, d, 1, &(this->prev[d]), &(this->next[d])); + this->pbc_prev[d] = (myloc[d] == 0) ? 1 : 0; + this->pbc_next[d] = (myloc[d] == this->nranks[d]) ? -1 : 0; + this->subdom_min[d] = this->grid_min[d] + rank_length[d] * myloc[d]; + this->subdom_max[d] = this->subdom_min[d] + rank_length[d]; + } + + MPI_Comm_free(cartesian); + } + + void initialize(int *argc, const char **argv) { + MPI_Init(argc, argv); + MPI_Comm_size(MPI_COMM_WORLD, &(this->world_size)); + MPI_Comm_rank(MPI_COMM_WORLD, &(this->rank)); + this->setConfig(); + this->setBoundingBox(); + } + + void finalize() { + MPI_Finalize(); + } +}; + +} diff --git a/runtime/pairs.hpp b/runtime/pairs.hpp index 8c188b73ab439c6b3b8b11b53862d889467e5f13..a79fea8167dedb88342ea83017a282aa01d73e1e 100644 --- a/runtime/pairs.hpp +++ b/runtime/pairs.hpp @@ -243,19 +243,19 @@ public: } }; -class PairsSim { +class PairsSimulation { private: std::vector<Property> properties; std::vector<Array> arrays; DeviceFlags *prop_flags, *array_flags; int nprops, narrays; public: - PairsSim(int nprops_, int narrays_) { + PairsSimulation(int nprops_, int narrays_) { prop_flags = new DeviceFlags(nprops_); array_flags = new DeviceFlags(narrays_); } - ~PairsSim() { + ~PairsSimulation() { delete prop_flags; delete array_flags; } diff --git a/runtime/read_from_file.hpp b/runtime/read_from_file.hpp index d28d2ef6e46436f9585bf3d3e0e21e24eb0428f9..ddbc65e517cac5e13bbc56548cd8dbc10771d63f 100644 --- a/runtime/read_from_file.hpp +++ b/runtime/read_from_file.hpp @@ -9,12 +9,12 @@ namespace pairs { -size_t read_particle_data(PairsSim *ps, const char *filename, double *grid_buffer, const property_t properties[], size_t nprops) { +size_t read_particle_data(PairsSimulation *ps, const char *filename, double *grid_buffer, const property_t properties[], size_t nprops) { std::ifstream in_file(filename, std::ifstream::in); std::string line; size_t n = 0; int read_grid_data = 0; - // TODO: store this from PairsSim class + // TODO: store this from PairsSimulation class const int num_dims = 3; if(in_file.is_open()) { diff --git a/runtime/vtk.hpp b/runtime/vtk.hpp index d7d84f11a9b40958230177f7f95bf40614aac502..33d598af1bb63400851d5dff4f0ef3ddd1c76958 100644 --- a/runtime/vtk.hpp +++ b/runtime/vtk.hpp @@ -8,7 +8,7 @@ namespace pairs { -void vtk_write_data(PairsSim *ps, const char *filename, int start, int end, int timestep) { +void vtk_write_data(PairsSimulation *ps, const char *filename, int start, int end, int timestep) { std::string output_filename(filename); std::ostringstream filename_oss; filename_oss << filename << "_" << timestep << ".vtk"; diff --git a/src/pairs/code_gen/cgen.py b/src/pairs/code_gen/cgen.py index ad50e3e7235c6184ebda49ffc68c776f755ee4f5..dfec0dbf1248447669b8ef6488cb5c036e6609f7 100644 --- a/src/pairs/code_gen/cgen.py +++ b/src/pairs/code_gen/cgen.py @@ -90,7 +90,7 @@ class CGen: nprops = module.sim.properties.nprops() narrays = module.sim.arrays.narrays() self.print("int main() {") - self.print(f" PairsSim *ps = new PairsSim({nprops}, {narrays});") + self.print(f" PairsSimulation *pairs = new PairsSimulation({nprops}, {narrays});") self.generate_statement(module.block) self.print(" return 0;") self.print("}") @@ -263,54 +263,54 @@ class CGen: array_name = ast_node.array.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->copyArrayToDevice({array_id}); // {array_name}") + self.print(f"pairs->copyArrayToDevice({array_id}); // {array_name}") else: - self.print(f"ps->copyArrayToHost({array_id}); // {array_name}") + self.print(f"pairs->copyArrayToHost({array_id}); // {array_name}") if isinstance(ast_node, CopyProperty): prop_id = ast_node.prop.id() prop_name = ast_node.prop.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->copyPropertyToDevice({prop_id}); // {prop_name}") + self.print(f"pairs->copyPropertyToDevice({prop_id}); // {prop_name}") else: - self.print(f"ps->copyPropertyToHost({prop_id}); // {prop_name}") + self.print(f"pairs->copyPropertyToHost({prop_id}); // {prop_name}") if isinstance(ast_node, ClearArrayFlag): array_id = ast_node.array.id() array_name = ast_node.array.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->clearArrayDeviceFlag({array_id}); // {array_name}") + self.print(f"pairs->clearArrayDeviceFlag({array_id}); // {array_name}") else: - self.print(f"ps->clearArrayHostFlag({array_id}); // {array_name}") + self.print(f"pairs->clearArrayHostFlag({array_id}); // {array_name}") if isinstance(ast_node, ClearPropertyFlag): prop_id = ast_node.prop.id() prop_name = ast_node.prop.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->clearPropertyDeviceFlag({prop_id}); // {prop_name}") + self.print(f"pairs->clearPropertyDeviceFlag({prop_id}); // {prop_name}") else: - self.print(f"ps->clearPropertyHostFlag({prop_id}); // {prop_name}") + self.print(f"pairs->clearPropertyHostFlag({prop_id}); // {prop_name}") if isinstance(ast_node, SetArrayFlag): array_id = ast_node.array.id() array_name = ast_node.array.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->setArrayDeviceFlag({array_id}); // {array_name}") + self.print(f"pairs->setArrayDeviceFlag({array_id}); // {array_name}") else: - self.print(f"ps->setArrayHostFlag({array_id}); // {array_name}") + self.print(f"pairs->setArrayHostFlag({array_id}); // {array_name}") if isinstance(ast_node, SetPropertyFlag): prop_id = ast_node.prop.id() prop_name = ast_node.prop.name() if ast_node.context() == Contexts.Device: - self.print(f"ps->setPropertyDeviceFlag({prop_id}); // {prop_name}") + self.print(f"pairs->setPropertyDeviceFlag({prop_id}); // {prop_name}") else: - self.print(f"ps->setPropertyHostFlag({prop_id}); // {prop_name}") + self.print(f"pairs->setPropertyHostFlag({prop_id}); // {prop_name}") if isinstance(ast_node, For): iterator = self.generate_expression(ast_node.iterator) @@ -414,7 +414,7 @@ class CGen: size = self.generate_expression(ast_node.size()) if a.is_static(): - self.print(f"ps->addStaticArray({a.id()}, \"{a.name()}\", {ptr}, {d_ptr}, {size});") + self.print(f"pairs->addStaticArray({a.id()}, \"{a.name()}\", {ptr}, {d_ptr}, {size});") else: if self.target.is_gpu() and a.device_flag: @@ -423,7 +423,7 @@ class CGen: else: self.print(f"{tkw} *{ptr};") - self.print(f"ps->addArray({a.id()}, \"{a.name()}\", &{ptr}, {d_ptr}, {size});") + self.print(f"pairs->addArray({a.id()}, \"{a.name()}\", &{ptr}, {d_ptr}, {size});") if isinstance(ast_node, RegisterProperty): p = ast_node.property() @@ -449,7 +449,7 @@ class CGen: else: self.print(f"{tkw} *{ptr};") - self.print(f"ps->addProperty({p.id()}, \"{p.name()}\", &{ptr}, {d_ptr}, {ptype}, {playout}, {sizes});") + self.print(f"pairs->addProperty({p.id()}, \"{p.name()}\", &{ptr}, {d_ptr}, {ptype}, {playout}, {sizes});") if isinstance(ast_node, Timestep): self.generate_statement(ast_node.block) @@ -459,16 +459,16 @@ class CGen: ptr = p.name() d_ptr_addr = f"&d_{ptr}" if self.target.is_gpu() and p.device_flag else "nullptr" sizes = ", ".join([str(self.generate_expression(BinOp.inline(size))) for size in ast_node.sizes()]) - self.print(f"ps->reallocProperty({p.id()}, &{ptr}, {d_ptr_addr}, {sizes});") - #self.print(f"ps->reallocProperty({p.id()}, (void **) &{ptr}, (void **) &d_{ptr}, {sizes});") + self.print(f"pairs->reallocProperty({p.id()}, &{ptr}, {d_ptr_addr}, {sizes});") + #self.print(f"pairs->reallocProperty({p.id()}, (void **) &{ptr}, (void **) &d_{ptr}, {sizes});") if isinstance(ast_node, ReallocArray): a = ast_node.array() size = self.generate_expression(ast_node.size()) ptr = a.name() d_ptr_addr = f"&d_{ptr}" if self.target.is_gpu() and a.device_flag else "nullptr" - self.print(f"ps->reallocArray({a.id()}, &{ptr}, {d_ptr_addr}, {size});") - #self.print(f"ps->reallocArray({a.id()}, (void **) &{ptr}, (void **) &d_{ptr}, {size});") + self.print(f"pairs->reallocArray({a.id()}, &{ptr}, {d_ptr_addr}, {size});") + #self.print(f"pairs->reallocArray({a.id()}, (void **) &{ptr}, (void **) &d_{ptr}, {size});") if isinstance(ast_node, VarDecl): tkw = Types.c_keyword(ast_node.var.type()) @@ -518,7 +518,7 @@ class CGen: return f"e{ast_node.id()}" if isinstance(ast_node, Call): - params = ", ".join(["ps"] + [str(self.generate_expression(p)) for p in ast_node.parameters()]) + params = ", ".join(["pairs"] + [str(self.generate_expression(p)) for p in ast_node.parameters()]) return f"{ast_node.name()}({params})" if isinstance(ast_node, Cast): diff --git a/src/pairs/ir/loops.py b/src/pairs/ir/loops.py index aa86b7788e0bbb0c842a5d267efddcf8d1645632..46abc6188a129bdcde80e4df5ea8e0f53cc52bf9 100644 --- a/src/pairs/ir/loops.py +++ b/src/pairs/ir/loops.py @@ -69,14 +69,14 @@ class For(ASTNode): class ParticleFor(For): def __init__(self, sim, block=None, local_only=True): - super().__init__(sim, 0, sim.nlocal if local_only else sim.nlocal + sim.pbc.npbc, block) + super().__init__(sim, 0, sim.nlocal if local_only else sim.nlocal + sim.comm.nghost, block) self.local_only = local_only def __str__(self): return f"ParticleFor<self.iterator>" def children(self): - return [self.block, self.sim.nlocal] + ([] if self.local_only else [self.sim.pbc.npbc]) + return [self.block, self.sim.nlocal] + ([] if self.local_only else [self.sim.comm.nghost]) class While(ASTNode): diff --git a/src/pairs/sim/comm.py b/src/pairs/sim/comm.py new file mode 100644 index 0000000000000000000000000000000000000000..240305dece1e0394d09c558fe56315fab64724bd --- /dev/null +++ b/src/pairs/sim/comm.py @@ -0,0 +1,98 @@ +from pairs.ir.block import pairs_device_block, pairs_host_block +from pairs.ir.branches import Branch, Filter +from pairs.ir.loops import For, ParticleFor +from pairs.ir.utils import Print +from pairs.ir.select import Select +from pairs.ir.types import Types +from pairs.sim.lowerable import Lowerable + + +class Comm: + def __init__(self, sim): + self.sim = sim + self.nghost = sim.add_var('nghost', Types.Int32) + self.ghost_capacity = sim.add_var('ghost_capacity', Types.Int32, 100) + self.ghost_map = sim.add_array('ghost_map', [self.ghost_capacity], Types.Int32) + self.ghost_mult = sim.add_array('ghost_mult', [self.ghost_capacity, sim.ndims()], Types.Int32) + + +class DetermineGhostParticles(Lowerable): + def __init__(self, sim, comm): + super().__init__(sim) + self.comm = comm + + @pairs_host_block + def lower(self): + sim = self.sim + ndims = sim.ndims() + grid = self.sim.grid + cutneigh = self.sim.cell_spacing() + nghost = self.comm.nghost + ghost_capacity = self.comm.ghost_capacity + ghost_map = self.comm.ghost_map + ghost_mult = self.comm.ghost_mult + positions = self.sim.position() + nlocal = self.sim.nlocal + sim.module_name("setup_comm") + sim.check_resize(ghost_capacity, nghost) + + nghost.set(0) + for d in range(0, ndims): + for i in For(sim, 0, nlocal + nghost): + pos = positions[i] + grid_length = grid.length(d) + + # TODO: VecFilter? + for _ in Filter(sim, pos[d] < grid.min(d) + cutneigh): + last_pos = positions[nlocal + nghost] + ghost_map[nghost].set(i) + ghost_mult[nghost][d].set(1) + last_pos[d].set(pos[d] + grid_length) + + for d_ in [x for x in range(0, ndims) if x != d]: + ghost_mult[nghost][d_].set(0) + last_pos[d_].set(pos[d_]) + + nghost.add(1) + + for _ in Filter(sim, pos[d] > grid.max(d) - cutneigh): + last_pos = positions[nlocal + nghost] + ghost_map[nghost].set(i) + ghost_mult[nghost][d].set(-1) + last_pos[d].set(pos[d] - grid_length) + + for d_ in [x for x in range(0, ndims) if x != d]: + ghost_mult[nghost][d_].set(0) + last_pos[d_].set(pos[d_]) + + nghost.add(1) + + +class UpdateGhostParticles(Lowerable): + def __init__(self, sim, comm): + super().__init__(sim) + self.comm = comm + + @pairs_device_block + def lower(self): + sim = self.sim + ndims = sim.ndims() + grid = self.sim.grid + nghost = self.comm.nghost + ghost_map = self.comm.ghost_map + ghost_mult = self.comm.ghost_mult + positions = self.sim.position() + nlocal = self.sim.nlocal + sim.module_name("update_comm") + + for i in For(sim, 0, nghost): + # TODO: allow syntax: + # positions[nlocal + i].set(positions[ghost_map[i]] + ghost_mult[i] * grid.length) + for d in range(0, ndims): + positions[nlocal + i][d].set(positions[ghost_map[i]][d] + ghost_mult[i][d] * grid.length(d)) + + +class ExchangeParticles(Lowerable): + def __init__(self, sim, comm): + super().__init__(sim) + self.comm = comm diff --git a/src/pairs/sim/pbc.py b/src/pairs/sim/pbc.py index 3c812b395df635ea1cfbeb77c0695ad86b8c509a..47bb6676623c5d27d44ef27ba4ad0f56c740bc5c 100644 --- a/src/pairs/sim/pbc.py +++ b/src/pairs/sim/pbc.py @@ -7,52 +7,15 @@ from pairs.ir.types import Types from pairs.sim.lowerable import Lowerable -class PBC: - def __init__(self, sim, grid, cutneigh, pbc_flags=[1, 1, 1]): - self.sim = sim - self.grid = grid - self.cutneigh = cutneigh - self.pbc_flags = pbc_flags - self.npbc = sim.add_var('npbc', Types.Int32) - self.pbc_capacity = sim.add_var('pbc_capacity', Types.Int32, 100) - self.pbc_map = sim.add_array('pbc_map', [self.pbc_capacity], Types.Int32) - self.pbc_mult = sim.add_array('pbc_mult', [self.pbc_capacity, sim.ndims()], Types.Int32) - - -class UpdatePBC(Lowerable): - def __init__(self, sim, pbc): - super().__init__(sim) - self.pbc = pbc - - @pairs_device_block - def lower(self): - sim = self.sim - ndims = sim.ndims() - grid = self.pbc.grid - npbc = self.pbc.npbc - pbc_map = self.pbc.pbc_map - pbc_mult = self.pbc.pbc_mult - positions = self.pbc.sim.position() - nlocal = self.pbc.sim.nlocal - sim.module_name("update_pbc") - - for i in For(sim, 0, npbc): - # TODO: allow syntax: - # positions[nlocal + i].set(positions[pbc_map[i]] + pbc_mult[i] * grid.length) - for d in range(0, ndims): - positions[nlocal + i][d].set(positions[pbc_map[i]][d] + pbc_mult[i][d] * grid.length(d)) - - class EnforcePBC(Lowerable): - def __init__(self, sim, pbc): + def __init__(self, sim): super().__init__(sim) - self.pbc = pbc @pairs_device_block def lower(self): sim = self.sim + grid = sim.grid ndims = sim.ndims() - grid = self.pbc.grid positions = sim.position() sim.module_name("enforce_pbc") @@ -64,55 +27,3 @@ class EnforcePBC(Lowerable): for _ in Filter(sim, positions[i][d] > grid.max(d)): positions[i][d].sub(grid.length(d)) - - -class SetupPBC(Lowerable): - def __init__(self, sim, pbc): - super().__init__(sim) - self.pbc = pbc - - @pairs_host_block - def lower(self): - sim = self.sim - ndims = sim.ndims() - grid = self.pbc.grid - cutneigh = self.pbc.cutneigh - npbc = self.pbc.npbc - pbc_capacity = self.pbc.pbc_capacity - pbc_map = self.pbc.pbc_map - pbc_mult = self.pbc.pbc_mult - positions = self.pbc.sim.position() - nlocal = self.pbc.sim.nlocal - sim.module_name("setup_pbc") - sim.check_resize(pbc_capacity, npbc) - - npbc.set(0) - for d in range(0, ndims): - for i in For(sim, 0, nlocal + npbc): - pos = positions[i] - grid_length = grid.length(d) - - # TODO: VecFilter? - for _ in Filter(sim, pos[d] < grid.min(d) + cutneigh): - last_pos = positions[nlocal + npbc] - pbc_map[npbc].set(i) - pbc_mult[npbc][d].set(1) - last_pos[d].set(pos[d] + grid_length) - - for d_ in [x for x in range(0, ndims) if x != d]: - pbc_mult[npbc][d_].set(0) - last_pos[d_].set(pos[d_]) - - npbc.add(1) - - for _ in Filter(sim, pos[d] > grid.max(d) - cutneigh): - last_pos = positions[nlocal + npbc] - pbc_map[npbc].set(i) - pbc_mult[npbc][d].set(-1) - last_pos[d].set(pos[d] - grid_length) - - for d_ in [x for x in range(0, ndims) if x != d]: - pbc_mult[npbc][d_].set(0) - last_pos[d_].set(pos[d_]) - - npbc.add(1) diff --git a/src/pairs/sim/simulation.py b/src/pairs/sim/simulation.py index 22f96f8c60ceae9a4d40034136a4a1b5d8ad5173..971eda45ccf3835be693d66242842c17ccd94626 100644 --- a/src/pairs/sim/simulation.py +++ b/src/pairs/sim/simulation.py @@ -12,10 +12,11 @@ from pairs.graph.graphviz import ASTGraph from pairs.mapping.funcs import compute from pairs.sim.arrays import ArraysDecl from pairs.sim.cell_lists import CellLists, CellListsBuild, CellListsStencilBuild +from pairs.sim.comm import Comm, DetermineGhostParticles, ExchangeParticles, UpdateGhostParticles from pairs.sim.grid import Grid2D, Grid3D from pairs.sim.lattice import ParticleLattice from pairs.sim.neighbor_lists import NeighborLists, NeighborListsBuild -from pairs.sim.pbc import PBC, UpdatePBC, EnforcePBC, SetupPBC +from pairs.sim.pbc import EnforcePBC from pairs.sim.properties import PropertiesAlloc, PropertiesResetVolatile from pairs.sim.read_from_file import ReadFromFile from pairs.sim.timestep import Timestep @@ -34,12 +35,10 @@ class Simulation: self.arrays = Arrays(self) self.particle_capacity = self.add_var('particle_capacity', Types.Int32, particle_capacity) self.nlocal = self.add_var('nlocal', Types.Int32) - self.nghost = self.add_var('nghost', Types.Int32) self.resizes = self.add_array('resizes', 3, Types.Int32, arr_sync=False) self.grid = None self.cell_lists = None self.neighbor_lists = None - self.pbc = None self.scope = [] self.nested_count = 0 self.nest = False @@ -58,7 +57,8 @@ class Simulation: self.iter_id = 0 self.vtk_file = None self._target = None - self.nparticles = self.nlocal + self.nghost + self.comm = Comm(self) + self.nparticles = self.nlocal + self.comm.nghost self.properties.add_capacity(self.particle_capacity) def add_module(self, module): @@ -145,19 +145,15 @@ class Simulation: self.setups.add_statement(read_object) self.grid = read_object.grid - def create_cell_lists(self, spacing, cutoff_radius): - self.cell_lists = CellLists(self, self.grid, spacing, cutoff_radius) + def build_cell_lists(self, spacing): + self.cell_lists = CellLists(self, self.grid, spacing, spacing) return self.cell_lists - def create_neighbor_lists(self): + def build_neighbor_lists(self, spacing): + self.cell_lists = CellLists(self, self.grid, spacing, spacing) self.neighbor_lists = NeighborLists(self.cell_lists) return self.neighbor_lists - def periodic(self, cutneigh, flags=[1, 1, 1]): - self.pbc = PBC(self, self.grid, cutneigh, flags) - self.properties.add_capacity(self.pbc.pbc_capacity) - return self.pbc - def compute(self, func, cutoff_radius=None, symbols={}): return compute(self, func, cutoff_radius, symbols) @@ -220,12 +216,15 @@ class Simulation: self._target = target self.code_gen.assign_target(target) + def cell_spacing(self): + return self.cell_lists.cutoff_radius + def generate(self): assert self._target is not None, "Target not specified!" timestep = Timestep(self, self.ntimesteps, [ - (EnforcePBC(self, self.pbc), 20), - (SetupPBC(self, self.pbc), UpdatePBC(self, self.pbc), 20), + (EnforcePBC(self), 20), + (DetermineGhostParticles(self, self.comm), UpdateGhostParticles(self, self.comm), 20), (CellListsBuild(self, self.cell_lists), 20), (NeighborListsBuild(self, self.neighbor_lists), 20), PropertiesResetVolatile(self), diff --git a/src/pairs/sim/vtk.py b/src/pairs/sim/vtk.py index dc19a8ed88576c9d2df799322fb8c6ef13647484..0faf8ec739273bf58e9c96d0d5f3c13a854ffcaa 100644 --- a/src/pairs/sim/vtk.py +++ b/src/pairs/sim/vtk.py @@ -14,7 +14,7 @@ class VTKWrite(Lowerable): @pairs_inline def lower(self): nlocal = self.sim.nlocal - npbc = self.sim.pbc.npbc - nall = nlocal + npbc + nghost = self.sim.comm.nghost + nall = nlocal + nghost Call_Void(self.sim, "pairs::vtk_write_data", [self.filename + "_local", 0, nlocal, self.timestep]) - Call_Void(self.sim, "pairs::vtk_write_data", [self.filename + "_pbc", nlocal, nall, self.timestep]) + Call_Void(self.sim, "pairs::vtk_write_data", [self.filename + "_ghost", nlocal, nall, self.timestep])