From b6b9596aecc346f53ac5fa188102a8780b723655 Mon Sep 17 00:00:00 2001 From: Rafael Ravedutti <rafaelravedutti@gmail.com> Date: Tue, 28 Nov 2023 01:22:53 +0100 Subject: [PATCH] Setup copper lattice without reading from file Signed-off-by: Rafael Ravedutti <rafaelravedutti@gmail.com> --- examples/lj.py | 11 +- runtime/copper_fcc_lattice.hpp | 154 ++++++++++++++++++++++++++++ runtime/thermo.hpp | 67 ++++++++++-- src/pairs/code_gen/cgen.py | 1 + src/pairs/sim/copper_fcc_lattice.py | 34 ++++++ src/pairs/sim/simulation.py | 16 ++- src/pairs/sim/thermo.py | 19 ++++ 7 files changed, 291 insertions(+), 11 deletions(-) create mode 100644 runtime/copper_fcc_lattice.hpp create mode 100644 src/pairs/sim/copper_fcc_lattice.py create mode 100644 src/pairs/sim/thermo.py diff --git a/examples/lj.py b/examples/lj.py index b5986e5..4085490 100644 --- a/examples/lj.py +++ b/examples/lj.py @@ -29,6 +29,11 @@ ntypes = 4 sigma = 1.0 epsilon = 1.0 sigma6 = sigma ** 6 +nx = 32 +ny = 32 +nz = 32 +rho = 0.8442 +temp = 1.44 psim = pairs.simulation("lj", [pairs.point_mass()], timesteps=200, double_prec=True) psim.add_position('position') @@ -38,12 +43,12 @@ psim.add_property('force', pairs.vector(), volatile=True) psim.add_feature('type', ntypes) psim.add_feature_property('type', 'epsilon', pairs.real(), [sigma for i in range(ntypes * ntypes)]) psim.add_feature_property('type', 'sigma6', pairs.real(), [epsilon for i in range(ntypes * ntypes)]) -psim.set_domain([0.0, 0.0, 0.0, 53.747078, 53.747078, 53.747078]) -psim.read_particle_data("data/minimd_setup_32x32x32.input", ['type', 'mass', 'position', 'linear_velocity', 'flags'], pairs.point_mass()) +psim.copper_fcc_lattice(nx, ny, nz, rho, temp, ntypes) psim.reneighbor_every(20) #psim.compute_half() psim.build_neighbor_lists(cutoff_radius + skin) -psim.vtk_output(f"output/lj_{target}") +psim.compute_thermo(100) +#psim.vtk_output(f"output/lj_{target}") psim.compute(initial_integrate, symbols={'dt': dt}, pre_step=True, skip_first=True) psim.compute(lj, cutoff_radius) psim.compute(final_integrate, symbols={'dt': dt}, skip_first=True) diff --git a/runtime/copper_fcc_lattice.hpp b/runtime/copper_fcc_lattice.hpp new file mode 100644 index 0000000..e1b063b --- /dev/null +++ b/runtime/copper_fcc_lattice.hpp @@ -0,0 +1,154 @@ +#include <iostream> +#include <math.h> +#include <mpi.h> +//--- +#include "pairs.hpp" + +#pragma once + +namespace pairs { + +/* Park/Miller RNG w/out MASKING, so as to be like f90s version */ +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define MASK 123459876 + +double myrandom(int* seed) { + int k= (*seed) / IQ; + double ans; + + *seed = IA * (*seed - k * IQ) - IR * k; + if(*seed < 0) *seed += IM; + ans = AM * (*seed); + return ans; +} + +void random_reset(int *seed, int ibase, double *coord) { + int i; + char *str = (char *) &ibase; + int n = sizeof(int); + unsigned int hash = 0; + + for (i = 0; i < n; i++) { + hash += str[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + str = (char *) coord; + n = 3 * sizeof(double); + for (i = 0; i < n; i++) { + hash += str[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + // keep 31 bits of unsigned int as new seed + // do not allow seed = 0, since will cause hang in gaussian() + + *seed = hash & 0x7ffffff; + if (!(*seed)) *seed = 1; + + // warm up the RNG + + for (i = 0; i < 5; i++) myrandom(seed); + //save = 0; +} + +double copper_fcc_lattice(PairsSimulation *ps, int nx, int ny, int nz, double xprd, double yprd, double zprd, double rho, int ntypes) { + auto shape = ps->getAsIntegerProperty(ps->getPropertyByName("shape")); + auto types = ps->getAsIntegerProperty(ps->getPropertyByName("type")); + auto flags = ps->getAsIntegerProperty(ps->getPropertyByName("flags")); + auto masses = ps->getAsFloatProperty(ps->getPropertyByName("mass")); + auto positions = ps->getAsVectorProperty(ps->getPropertyByName("position")); + auto velocities = ps->getAsVectorProperty(ps->getPropertyByName("linear_velocity")); + double xlo = 0.0, xhi = xprd; + double ylo = 0.0, yhi = yprd; + double zlo = 0.0, zhi = zprd; + int natoms = 0; + int natoms_expected = 4 * nx * ny * nz; + + double alat = pow((4.0 / rho), (1.0 / 3.0)); + int ilo = (int) (xlo / (0.5 * alat) - 1); + int ihi = (int) (xhi / (0.5 * alat) + 1); + int jlo = (int) (ylo / (0.5 * alat) - 1); + int jhi = (int) (yhi / (0.5 * alat) + 1); + int klo = (int) (zlo / (0.5 * alat) - 1); + int khi = (int) (zhi / (0.5 * alat) + 1); + + ilo = MAX(ilo, 0); + ihi = MIN(ihi, 2 * nx - 1); + jlo = MAX(jlo, 0); + jhi = MIN(jhi, 2 * ny - 1); + klo = MAX(klo, 0); + khi = MIN(khi, 2 * nz - 1); + + double xtmp, ytmp, ztmp, vxtmp, vytmp, vztmp; + int i, j, k, m, n; + int sx = 0; int sy = 0; int sz = 0; + int ox = 0; int oy = 0; int oz = 0; + int subboxdim = 8; + + while(oz * subboxdim <= khi) { + k = oz * subboxdim + sz; + j = oy * subboxdim + sy; + i = ox * subboxdim + sx; + + if(((i + j + k) % 2 == 0) && + (i >= ilo) && (i <= ihi) && + (j >= jlo) && (j <= jhi) && + (k >= klo) && (k <= khi)) { + + xtmp = 0.5 * alat * i; + ytmp = 0.5 * alat * j; + ztmp = 0.5 * alat * k; + + if(ps->getDomainPartitioner()->isWithinSubdomain(xtmp, ytmp, ztmp)) { + n = k * (2 * ny) * (2 * nx) + j * (2 * nx) + i + 1; + for(m = 0; m < 5; m++) { myrandom(&n); } + vxtmp = myrandom(&n); + for(m = 0; m < 5; m++){ myrandom(&n); } + vytmp = myrandom(&n); + for(m = 0; m < 5; m++) { myrandom(&n); } + vztmp = myrandom(&n); + + masses(natoms) = 1.0; + positions(natoms, 0) = xtmp; + positions(natoms, 1) = ytmp; + positions(natoms, 2) = ztmp; + velocities(natoms, 0) = vxtmp; + velocities(natoms, 1) = vytmp; + velocities(natoms, 2) = vztmp; + types(natoms) = rand() % ntypes; + flags(natoms) = 0; + shape(natoms) = 2; // point mass + natoms++; + } + } + + sx++; + + if(sx == subboxdim) { sx = 0; sy++; } + if(sy == subboxdim) { sy = 0; sz++; } + if(sz == subboxdim) { sz = 0; ox++; } + if(ox * subboxdim > ihi) { ox = 0; oy++; } + if(oy * subboxdim > jhi) { oy = 0; oz++; } + } + + if(natoms != natoms_expected) { + std::cerr << "copper_fcc_lattice(): incorrect number of atoms " + << "(" << natoms << " / " << natoms_expected << ")" << std::endl; + exit(-1); + } + + return natoms; +} + +} diff --git a/runtime/thermo.hpp b/runtime/thermo.hpp index 4afec58..7c999d6 100644 --- a/runtime/thermo.hpp +++ b/runtime/thermo.hpp @@ -1,4 +1,5 @@ #include <iostream> +#include <math.h> #include <mpi.h> //--- #include "pairs.hpp" @@ -7,13 +8,17 @@ namespace pairs { -void compute_thermo(PairsSimulation *ps, int nlocal) { +double compute_thermo(PairsSimulation *ps, int nlocal, double xprd, double yprd, double zprd, int print) { auto masses = ps->getAsFloatProperty(ps->getPropertyByName("mass")); auto velocities = ps->getAsVectorProperty(ps->getPropertyByName("linear_velocity")); - const int natoms = 131072; - const double xprd = 53.747078; - const double yprd = 53.747078; - const double zprd = 53.747078; + int natoms = nlocal; + + if(ps->getDomainPartitioner()->getWorldSize() > 1) { + int global_natoms; + MPI_Reduce(&natoms, &global_natoms, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + natoms = global_natoms; + } + const double mvv2e = 1.0; const double dof_boltz = (natoms * 3 - 3); const double t_scale = mvv2e / dof_boltz; @@ -36,11 +41,59 @@ void compute_thermo(PairsSimulation *ps, int nlocal) { t = global_t; } - if(ps->getDomainPartitioner()->getRank() == 0) { - t = t * t_scale; + t = t * t_scale; + if(print == 1 && ps->getDomainPartitioner()->getRank() == 0) { p = (t * dof_boltz) * p_scale; std::cout << t << "\t" << p << std::endl; } + + return t; +} + +void adjust_thermo(PairsSimulation *ps, int nlocal, double xprd, double yprd, double zprd, double temp) { + auto velocities = ps->getAsVectorProperty(ps->getPropertyByName("linear_velocity")); + double vxtot = 0.0; + double vytot = 0.0; + double vztot = 0.0; + double tmp; + int natoms = nlocal; + + for(int i = 0; i < nlocal; i++) { + vxtot += velocities(i, 0); + vytot += velocities(i, 1); + vztot += velocities(i, 2); + } + + if(ps->getDomainPartitioner()->getWorldSize() > 1) { + int global_natoms; + MPI_Reduce(&natoms, &global_natoms, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + natoms = global_natoms; + MPI_Allreduce(&vxtot, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + vxtot = tmp / natoms; + MPI_Allreduce(&vytot, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + vytot = tmp / natoms; + MPI_Allreduce(&vztot, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + vztot = tmp / natoms; + } else { + vxtot /= natoms; + vytot /= natoms; + vztot /= natoms; + } + + for(int i = 0; i < nlocal; i++) { + velocities(i, 0) -= vxtot; + velocities(i, 1) -= vytot; + velocities(i, 2) -= vztot; + } + + double t = pairs::compute_thermo(ps, nlocal, xprd, yprd, zprd, 0); + double factor = sqrt(temp / t); + + for(int i = 0; i < nlocal; i++) { + velocities(i, 0) *= factor; + velocities(i, 1) *= factor; + velocities(i, 2) *= factor; + } } } diff --git a/src/pairs/code_gen/cgen.py b/src/pairs/code_gen/cgen.py index 5a17c30..dba78f3 100644 --- a/src/pairs/code_gen/cgen.py +++ b/src/pairs/code_gen/cgen.py @@ -67,6 +67,7 @@ class CGen: self.print("#include <stdlib.h>") self.print("//---") self.print("#include \"runtime/likwid-marker.h\"") + self.print("#include \"runtime/copper_fcc_lattice.hpp\"") self.print("#include \"runtime/pairs.hpp\"") self.print("#include \"runtime/read_from_file.hpp\"") self.print("#include \"runtime/timing.hpp\"") diff --git a/src/pairs/sim/copper_fcc_lattice.py b/src/pairs/sim/copper_fcc_lattice.py new file mode 100644 index 0000000..ba966a5 --- /dev/null +++ b/src/pairs/sim/copper_fcc_lattice.py @@ -0,0 +1,34 @@ +from pairs.ir.assign import Assign +from pairs.ir.block import pairs_inline +from pairs.ir.functions import Call_Int, Call_Void +from pairs.ir.particle_attributes import ParticleAttributeList +from pairs.ir.types import Types +from pairs.sim.grid import Grid3D +from pairs.sim.lowerable import Lowerable + + +class CopperFCCLattice(Lowerable): + def __init__(self, sim, nx, ny, nz, rho, temperature, ntypes): + super().__init__(sim) + self._nx = nx + self._ny = ny + self._nz = nz + self._rho = rho + self._temperature = temperature + self._ntypes = ntypes + lattice = pow((4.0 / rho), (1.0 / 3.0)) + self._xprd = nx * lattice + self._yprd = ny * lattice + self._zprd = nz * lattice + sim.set_domain([0.0, 0.0, 0.0, self._xprd, self._yprd, self._zprd]) + + @pairs_inline + def lower(self): + Assign(self.sim, self.sim.nlocal, + Call_Int(self.sim, "pairs::copper_fcc_lattice", + [self._nx, self._ny, self._nz, + self._xprd, self._yprd, self._zprd, + self._rho, self._ntypes])) + + Call_Void(self.sim, "pairs::adjust_thermo", + [self.sim.nlocal, self._xprd, self._yprd, self._zprd, self._temperature]) diff --git a/src/pairs/sim/simulation.py b/src/pairs/sim/simulation.py index 2ef4fea..c32c935 100644 --- a/src/pairs/sim/simulation.py +++ b/src/pairs/sim/simulation.py @@ -15,6 +15,7 @@ from pairs.sim.arrays import DeclareArrays from pairs.sim.cell_lists import CellLists, BuildCellLists, BuildCellListsStencil, PartitionCellLists from pairs.sim.comm import Comm from pairs.sim.contact_history import ContactHistory, BuildContactHistory, ClearUnusedContactHistory, ResetContactHistoryUsageStatus +from pairs.sim.copper_fcc_lattice import CopperFCCLattice from pairs.sim.domain import InitializeDomain from pairs.sim.domain_partitioning import DimensionRanges from pairs.sim.features import AllocateFeatureProperties @@ -24,6 +25,7 @@ from pairs.sim.lattice import ParticleLattice from pairs.sim.neighbor_lists import NeighborLists, BuildNeighborLists from pairs.sim.properties import AllocateProperties, AllocateContactProperties, ResetVolatileProperties from pairs.sim.read_from_file import ReadParticleData +from pairs.sim.thermo import ComputeThermo from pairs.sim.timestep import Timestep from pairs.sim.variables import DeclareVariables from pairs.sim.vtk import VTKWrite @@ -83,6 +85,7 @@ class Simulation: self._compute_half = False self._apply_list = None self._enable_profiler = False + self._compute_thermo = 0 def enable_profiler(self): self._enable_profiler = True @@ -210,6 +213,9 @@ class Simulation: props = [self.property(prop_name) for prop_name in prop_names] self.setups.add_statement(ReadParticleData(self, filename, props, shape_id)) + def copper_fcc_lattice(self, nx, ny, nz, rho, temperature, ntypes): + self.setups.add_statement(CopperFCCLattice(self, nx, ny, nz, rho, temperature, ntypes)) + def build_cell_lists(self, spacing): self.cell_lists = CellLists(self, self.grid, spacing, spacing) return self.cell_lists @@ -335,6 +341,9 @@ class Simulation: def domain_partitioning(self): return self._dom_part + def compute_thermo(self, every=0): + self._compute_thermo = every + def generate(self): assert self._target is not None, "Target not specified!" comm = Comm(self, self._dom_part) @@ -354,7 +363,8 @@ class Simulation: if self._use_contact_history: if self.neighbor_lists is not None: timestep_procedures.append( - (BuildContactHistory(self, self._contact_history, self.cell_lists), every_reneighbor_params)) + (BuildContactHistory(self, self._contact_history, self.cell_lists), + every_reneighbor_params)) timestep_procedures.append(ResetContactHistoryUsageStatus(self, self._contact_history)) @@ -363,6 +373,10 @@ class Simulation: if self._use_contact_history: timestep_procedures.append(ClearUnusedContactHistory(self, self._contact_history)) + if self._compute_thermo != 0: + timestep_procedures.append( + (ComputeThermo(self), {'every': self._compute_thermo})) + timestep = Timestep(self, self.ntimesteps, timestep_procedures) self.enter(timestep.block) diff --git a/src/pairs/sim/thermo.py b/src/pairs/sim/thermo.py new file mode 100644 index 0000000..557a756 --- /dev/null +++ b/src/pairs/sim/thermo.py @@ -0,0 +1,19 @@ +from pairs.ir.assign import Assign +from pairs.ir.block import pairs_inline +from pairs.ir.functions import Call_Int, Call_Void +from pairs.ir.particle_attributes import ParticleAttributeList +from pairs.ir.types import Types +from pairs.sim.grid import Grid3D +from pairs.sim.lowerable import Lowerable + + +class ComputeThermo(Lowerable): + def __init__(self, sim): + super().__init__(sim) + + @pairs_inline + def lower(self): + xprd = self.sim.grid.length(0) + yprd = self.sim.grid.length(1) + zprd = self.sim.grid.length(2) + Call_Void(self.sim, "pairs::compute_thermo", [self.sim.nlocal, xprd, yprd, zprd, 1]) -- GitLab