Skip to content
Snippets Groups Projects
Select Git revision
  • 0c89a26d40e4fca5f23cf3c1f105bd37f189f166
  • main default protected
  • seed_variation_ruegen
  • cami_seed_variation
  • cami_restructured
  • camis
6 results

preprocess.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    md.c 5.75 KiB
    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    
    #include "rvec.h"
    #include "md.h"
    
    /* [ASSIGNMENT] calculate energy and forces of a WCA potential (a Lennard-Jones
       potential truncated at the minimum) */
    real calc_energy_force(uint natom, rvec box, rvec *x, rvec *f) {
        uint i, j;
        real Epot, r, fscale;
        rvec rij;
        const real eps   = 2.0, sig = 1.5;
        const real rcut  = pow(2.0, 1.0/6.0) * sig;
        const real sig6  = pow(sig, 6);
        const real sig12 = pow(sig, 12);
        const real Eshift = eps;
    
        rvecary_set(natom, f, 0);
        Epot = 0;
        for (i = 0; i < natom; i++) {
            for (j = i + 1; j < natom; j++) {
                /* interaction of atoms i and j */
                /* Note: use rvec_sub_pbc(&rij, box, x[i], x[j]); to
                   calculate the distance between atoms i and j */
            }
        }
        return Epot;
    }
    
    /* [ASSIGNMENT] calculate instantaneous temperature */
    real calc_temperature(uint ndof, real Ekin, real kB) {
        return 1.0;
    }
    
    /* [ASSIGNMENT] calculate kinetic energy */
    real calc_kinetic_energy(uint natom, rvec *v, real *m) {
        real Ekin = 0;
        return Ekin;
    }
    
    /* [ASSIGNMENT] leapfrog integration step */
    real leapfrog_step(uint natom, rvec *x, rvec *v, rvec *f, real *m, real dt, rvec box) {
        real Epot = 0;
        /* x += dt * v */
        /* calc energy, forces */
        /* v += dt * f/m */
        return Epot;
    }
    
    static void print_header() {
        printf("%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\n",
               "step", "time", "E/Na", "Epot/Na", "Ekin/Na", "T", "Edrift/Na", "rel.Edrift", "vcom");
    }
    
    static void print_step_info(uint step, uint natom, real dt,
                         real E, real Epot, real Ekin, real Estart, real T, real vcom) {
        printf("%10u\t%10.5f\t%10.5f\t%10.5f\t%10.5f\t%10.5f\t%10.5f\t%10.5f\t%10.5f\n",
               step, step * dt, E/natom, Epot/natom, Ekin/natom, T,
               (E - Estart)/natom, (E - Estart)/Estart, vcom);
    }
    
    int main(int argc, char **argv) {
        uint  natom;          /* number of atoms */
        ulong nstep,          /* number of time steps to run simulation */
              nstep_print;    /* print simulation state every nstep_print steps */
        rvec  *x,             /* atom positions, x[i] is vector of coordinates of atom i */
              *v,             /* velocities */
              *f;             /* forces */
        real  *m;             /* atom masses */
        rvec  box;            /* simulation box side lengths */
        real  dt;             /* integrator timestep */
    
        uint  ndof;           /* number of degrees of freedom */
        real  volume,         /* simulation box volume */
              density,        /* system density = natom / volume */
              E,              /* total energy */
              Epot,           /* potential energy */
              Ekin,           /* kinetic energy */      
              Estart,         /* total energy at start of simulation */
              T,              /* instantaneous temperature */
              Tstart;         /* starting temperature */
        uint  step = 0;       /* integration step */
        real  vcom;           /* center of mass velocity */
    
        const real kB = 1.0;  /* Boltzmann's constant */
        const real default_mass = 3.0;
        const real max_rel_Edrift = 1.0;
    
        /* parse command-line args */
        if (argc != 7) {
            printf("usage: %s natom density Tstart dt nstep nstep_print\n", argv[0]);
            exit(EXIT_FAILURE);
        }
        natom       = atoi(argv[1]);
        density     = atof(argv[2]);
        Tstart      = atof(argv[3]);
        dt          = atof(argv[4]);
        nstep       = atol(argv[5]);
        nstep_print = atol(argv[6]);
    
        /* allocate memory */
        x = calloc(natom, sizeof *x);
        v = calloc(natom, sizeof *v);
        f = calloc(natom, sizeof *f);
        m = calloc(natom, sizeof *m);
        if (x == NULL || v == NULL || f == NULL || m == NULL) {
            printf("error: couldn't allocate memory\n");
            exit(EXIT_FAILURE);
        }
    
        /* setup */
        ndof   = NDIM * natom;
        volume = natom / density;
        rvec_set(&box, pow(volume, 1.0/NDIM));
        setup_fcc_lattice(x, natom, box);
        apply_pbc(natom, box, x);
        for (uint i = 0; i < natom; i++)
            m[i] = default_mass;
        init_velocities(natom, v, m, ndof, kB, Tstart);
    
        /* print info */
        printf("simulation box: ");
        rvec_print(box);
        printf("[ x ]\n");
        rvecary_print(x, natom);
        printf("[ v ]\n");
        rvecary_print(v, natom);
        printf("[ f ]\n");
        rvecary_print(f, natom);
    
        /* calculate starting energy etc. */
        Epot = calc_energy_force(natom, box, x, f);
        Ekin = calc_kinetic_energy(natom, v, m); 
        T = calc_temperature(ndof, Ekin, kB);
        Estart = E = Epot + Ekin;
        vcom = com_velocity(natom, v, m);
    
        /* run simulation */
        printf("START\n");
        print_header();
        print_step_info(step, natom, dt, E, Epot, Ekin, Estart, T, vcom);
        for (step = 1; step <= nstep; step++) {
            /* leapfrog integration step */
            Epot = leapfrog_step(natom, x, v, f, m, dt, box);
    
            /* apply periodic boundary conditions, move all atoms back
               into box */
            apply_pbc(natom, box, x);
    
            /* calculate properties: kinetic energy, temperature */
            Ekin = calc_kinetic_energy(natom, v, m);
            T    = calc_temperature(ndof, Ekin, kB);
            E    = Epot + Ekin;
            vcom = com_velocity(natom, v, m);
    
            /* periodically print out info */
            if (step % nstep_print == 0) {
                print_step_info(step, natom, dt, E, Epot, Ekin, Estart, T, vcom);
            }
    
            /* check if system has exploded */
            if (fabs((E - Estart) / Estart) > max_rel_Edrift) {
                printf("error: relative energy drift too large\n");
                print_step_info(step, natom, dt, E, Epot, Ekin, Estart, T, vcom);
                exit(EXIT_FAILURE);
            }
        }
    
        /* clean up */
        free(x);
        free(v);
        free(f);
        free(m);
    
        return EXIT_SUCCESS;
    }