git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@26 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2006-09-27 19:51:33 +00:00
parent 3422cb245c
commit 222c95507e
536 changed files with 108384 additions and 0 deletions

396
src/write_restart.cpp Normal file
View File

@ -0,0 +1,396 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
www.cs.sandia.gov/~sjplimp/lammps.html
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "write_restart.h"
#include "system.h"
#include "atom.h"
#include "group.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "update.h"
#include "domain.h"
#include "modify.h"
#include "universe.h"
#include "comm.h"
#include "output.h"
#include "thermo.h"
#include "memory.h"
#include "error.h"
enum {IGNORE,WARN,ERROR}; // same as thermo.cpp
/* ---------------------------------------------------------------------- */
WriteRestart::WriteRestart()
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
}
/* ----------------------------------------------------------------------
called as write_restart command in input script
------------------------------------------------------------------------- */
void WriteRestart::command(int narg, char **arg)
{
if (domain->box_exist == 0)
error->all("Write_restart command before simulation box is defined");
if (narg != 1) error->all("Illegal write_restart command");
// if filename contains a "*", replace with current timestep
char *ptr;
int n = strlen(arg[0]) + 16;
char *file = new char[n];
if (ptr = strchr(arg[0],'*')) {
*ptr = '\0';
sprintf(file,"%s%d%s",arg[0],update->ntimestep,ptr+1);
} else strcpy(file,arg[0]);
// init entire system since comm->exchange is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
if (comm->me == 0 && screen)
fprintf(screen,"System init for write_restart ...\n");
sys->init();
// move atoms to new processors before writing file
// enforce PBC before in case atoms are outside box
domain->pbc();
domain->reset_box();
comm->setup();
comm->exchange();
write(file);
delete [] file;
}
/* ----------------------------------------------------------------------
called from output within run/minimize loop
file = final file name to write, except may contain a "%"
------------------------------------------------------------------------- */
void WriteRestart::write(char *file)
{
// natoms = sum of nlocal = value to write into restart file
// if unequal and thermo lostflag is "error", don't write restart file
double rlocal = atom->nlocal;
MPI_Allreduce(&rlocal,&natoms,1,MPI_DOUBLE,MPI_SUM,world);
if (natoms != atom->natoms && output->thermo->lostflag == ERROR)
error->all("Atom count is inconsistent, cannot write restart file");
// check if filename contains "%"
int multiproc;
if (strchr(file,'%')) multiproc = 1;
else multiproc = 0;
// open single restart file or base file for multiproc case
if (me == 0) {
char *hfile;
if (multiproc) {
char *hfile = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(hfile,"%s%s%s",file,"base",ptr+1);
*ptr = '%';
} else hfile = file;
fp = fopen(hfile,"wb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",hfile);
error->one(str);
}
if (multiproc) delete [] hfile;
}
// write header, groups, ntype-length arrays, force field, fix info
if (me == 0) {
header();
group->write_restart(fp);
if (atom->mass_require) mass();
if (atom->dipole_require) dipole();
force_fields();
}
modify->write_restart(fp);
// communication buffer for all my atom's info
// max_size = largest buffer needed by any proc
int max_size;
int send_size = atom->size_restart();
MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world);
double *buf;
if (me == 0)
buf = (double *)
memory->smalloc(max_size*sizeof(double),"write_restart:buf");
else
buf = (double *)
memory->smalloc(send_size*sizeof(double),"write_restart:buf");
// pack my atom data into buf
int n = 0;
for (int i = 0; i < atom->nlocal; i++) n += atom->pack_restart(i,&buf[n]);
// if single file:
// write one chunk of atoms per proc to file
// proc 0 pings each proc, receives its chunk, writes to file
// all other procs wait for ping, send their chunk to proc 0
// else if one file per proc:
// each proc opens its own file and writes its chunk directly
if (multiproc == 0) {
int tmp,recv_size;
MPI_Status status;
MPI_Request request;
if (me == 0) {
for (int iproc = 0; iproc < nprocs; iproc++) {
if (iproc) {
MPI_Irecv(buf,max_size,MPI_DOUBLE,iproc,0,world,&request);
MPI_Send(&tmp,0,MPI_INT,iproc,0,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_DOUBLE,&recv_size);
} else recv_size = send_size;
fwrite(&recv_size,sizeof(int),1,fp);
fwrite(buf,sizeof(double),recv_size,fp);
}
fclose(fp);
} else {
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
MPI_Rsend(buf,send_size,MPI_DOUBLE,0,0,world);
}
} else {
if (me == 0) fclose(fp);
char *perproc = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(perproc,"%s%d%s",file,me,ptr+1);
*ptr = '%';
fp = fopen(perproc,"wb");
delete [] perproc;
if (fp == NULL) error->one("Cannot open restart file");
fwrite(&send_size,sizeof(int),1,fp);
fwrite(buf,sizeof(double),send_size,fp);
fclose(fp);
}
memory->sfree(buf);
}
/* ----------------------------------------------------------------------
proc 0 writes out problem description
------------------------------------------------------------------------- */
void WriteRestart::header()
{
write_char(0,universe->version);
write_char(1,update->unit_style);
write_int(2,update->ntimestep);
write_int(3,force->dimension);
write_int(4,nprocs);
write_int(5,comm->procgrid[0]);
write_int(6,comm->procgrid[1]);
write_int(7,comm->procgrid[2]);
write_int(8,force->newton_pair);
write_int(9,force->newton_bond);
write_int(10,domain->xperiodic);
write_int(11,domain->yperiodic);
write_int(12,domain->zperiodic);
write_int(13,domain->boundary[0][0]);
write_int(14,domain->boundary[0][1]);
write_int(15,domain->boundary[1][0]);
write_int(16,domain->boundary[1][1]);
write_int(17,domain->boundary[2][0]);
write_int(18,domain->boundary[2][1]);
// atom_style must be written before atom class values
// so read_restart can create class before reading class values
// if style = hybrid, also write sub-class names (1 to nwords)
write_char(19,atom->style);
if (strcmp(atom->style,"hybrid") == 0) {
char **words;
int nwords = atom->style2arg(words);
int nm1 = nwords - 1;
fwrite(&nm1,sizeof(int),1,fp);
for (int i = 1; i < nwords; i++) {
int n = strlen(words[i]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(words[i],sizeof(char),n,fp);
}
for (int i = 0; i < nwords; i++) delete [] words[i];
delete [] words;
}
write_double(20,natoms);
write_int(21,atom->ntypes);
write_int(22,atom->nbonds);
write_int(23,atom->nbondtypes);
write_int(24,atom->bond_per_atom);
write_int(25,atom->nangles);
write_int(26,atom->nangletypes);
write_int(27,atom->angle_per_atom);
write_int(28,atom->ndihedrals);
write_int(29,atom->ndihedraltypes);
write_int(30,atom->dihedral_per_atom);
write_int(31,atom->nimpropers);
write_int(32,atom->nimpropertypes);
write_int(33,atom->improper_per_atom);
write_double(34,domain->boxxlo);
write_double(35,domain->boxxhi);
write_double(36,domain->boxylo);
write_double(37,domain->boxyhi);
write_double(38,domain->boxzlo);
write_double(39,domain->boxzhi);
write_double(40,force->special_lj[1]);
write_double(41,force->special_lj[2]);
write_double(42,force->special_lj[3]);
write_double(43,force->special_coul[1]);
write_double(44,force->special_coul[2]);
write_double(45,force->special_coul[3]);
// -1 flag signals end of header
int flag = -1;
fwrite(&flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 writes out atom masses
------------------------------------------------------------------------- */
void WriteRestart::mass()
{
fwrite(&atom->mass[1],sizeof(double),atom->ntypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 writes out dipole moments
------------------------------------------------------------------------- */
void WriteRestart::dipole()
{
fwrite(&atom->dipole[1],sizeof(double),atom->ntypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 writes out force field styles and data
------------------------------------------------------------------------- */
void WriteRestart::force_fields()
{
int n;
if (force->pair) n = strlen(force->pair_style) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(force->pair_style,sizeof(char),n,fp);
force->pair->write_restart(fp);
}
if (atom->bonds_allow) {
if (force->bond) n = strlen(force->bond_style) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(force->bond_style,sizeof(char),n,fp);
force->bond->write_restart(fp);
}
}
if (atom->angles_allow) {
if (force->angle) n = strlen(force->angle_style) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(force->angle_style,sizeof(char),n,fp);
force->angle->write_restart(fp);
}
}
if (atom->dihedrals_allow) {
if (force->dihedral) n = strlen(force->dihedral_style) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(force->dihedral_style,sizeof(char),n,fp);
force->dihedral->write_restart(fp);
}
}
if (atom->impropers_allow) {
if (force->improper) n = strlen(force->improper_style) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(force->improper_style,sizeof(char),n,fp);
force->improper->write_restart(fp);
}
}
}
/* ----------------------------------------------------------------------
write_int - write a flag and an int into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_int(int flag, int value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
write_double - write a flag and a double into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_double(int flag, double value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(double),1,fp);
}
/* ----------------------------------------------------------------------
write_char - write a flag and a char str into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_char(int flag, char *value)
{
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(value) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(value,sizeof(char),n,fp);
}