/* simtop.cc Simulation of a fluid of molecules each consisting of four Lennard-Jones sites. This program is meant for the purpose of illustrating the use of the implementation of the exact rotation of a rigid body in the context of the symplectic integration scheme using the exact rotation matrix. The calculations of the forces and the random number generator are therefore implemented only in the most straightforward but computationally costly way. To compile type: c++ simtop.cc tops.cc -lm -o simtop To run type: simtop Input: The input file should contain a list of numbers which signify number of particles linear size of the cubic simulation box run-time of the simulation integration step-size Output: The program writes a line per time step containing five columns representing time, total energy, translational kinetic energy, rotational kinetic energy and potential energy. Ramses van Zon Last modified: May 29, 2009 */ #include #include #include #include #include #include "tops.h" using namespace std; // To obtain a random number between 0 and 1 double rnd() { return rand()/(double)RAND_MAX; } // The Molecule structure contains the properties of one molecule. struct Molecule { Vector q; // the position Vector p; // the momentum Matrix A; // the attitude Vector L; // the angular momentum Vector F; // the force Vector t; // the torque double V; // the potential energy }; // The System class contains all the molecules and the methods to // initialize and perform the simulation. class System { private: static const int nSites = 4; // the number of site in each molecule static const Vector site[nSites]; // the sites in the molecule static const Vector I; // the moments of inertia of a molecule static const double m; // the mass of a molecule static double cubic[4]; // the interpolation coefficients static TopRecur top; // see tops.h and doctops.pdf int N; // the number of particles double L; // the linear length of the (cubic) system double RUNTIME; // the runtime double DT; // the integration time step Molecule*mol; // the molecules // To pre-compute interpolation coefficients. static const double RCA = 2.5; static const double RCB = 4; static const double RCA2 = 6.25; static const double RCB2 = 16; void computeCubicCoefficients() { double ir2 = 1.0/(double)RCA2; double ir6 = ir2*ir2*ir2; double V = ir6*(4*ir6-4); double F = ir6*(48*ir6-24)/RCA; double a = RCB-RCA; double b = 3*V-a*F; double c = -(2*V-a*F); double ia2 = 1/(a*a); double ia3 = ia2/a; cubic[0] = b*RCB2*ia2+c*RCB*RCB2*ia3; cubic[1] = -2*b*RCB*ia2-3*c*RCB2*ia3; cubic[2] = b*ia2+3*c*RCB*ia3; cubic[3] = -c*ia3; } // To compute the site-site potential with a smooth cut-off. // For r < RCA, full Lennard-Jones is used; // for r > RCB, the potential and force are both zero; // for RCA < r < RCB, an interpolating cubic is used. void siteForce(const Vector&r, Vector&f, double&V) const { double r2 = r.nrm2(); if (r2>RCB2) { V = 0.0; f.zero(); } else if (r2>RCA2) { // smooth interpolation double rnrm = sqrt(r2); V = cubic[0]+rnrm*cubic[1]+r2*(cubic[2]+rnrm*cubic[3]); f = -(cubic[1]/rnrm+2*cubic[2]+3*rnrm*cubic[3])*r; } else { double ir2 = 1/r2; double ir6 = ir2*ir2*ir2; V = ir6*(4*ir6-4); f = ir6*ir2*(48*ir6-24)*r; } } // To compute the force F and torque t on molecule B due to A. void molForce(const Molecule&A, const Molecule&B, const Vector&r, Vector&F, Vector&t, double&V) const { V = 0; F.zero(); t.zero(); for (int a=0; a> N; f >> L; f >> RUNTIME; f >> DT; // initialize the system mol = new Molecule[N]; // generate random initial conditions for (int i=0; i's name System system; // the system object // initialize if (argc>1) system.initialize(argv[1]); else system.initialize(def_ini); // run the simulation system.run(); }