Files
LIGGGHTS-PFM/src/cfd_datacoupling_file.cpp
2014-08-28 19:59:48 +02:00

518 lines
14 KiB
C++

/* ----------------------------------------------------------------------
LIGGGHTS - LAMMPS Improved for General Granular and Granular Heat
Transfer Simulations
LIGGGHTS is part of the CFDEMproject
www.liggghts.com | www.cfdem.com
Christoph Kloss, christoph.kloss@cfdem.com
Copyright 2009-2012 JKU Linz
Copyright 2012- DCS Computing GmbH, Linz
LIGGGHTS is based on LAMMPS
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
This software is distributed under the GNU General Public License.
See the README file in the top-level directory.
------------------------------------------------------------------------- */
#include "sys/stat.h"
#include "string.h"
#include "stdlib.h"
#include "atom.h"
#include "comm.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "memory.h"
#include "modify.h"
#include "math.h"
#include "vector_liggghts.h"
#include "fix_property_atom.h"
#include "fix_property_global.h"
#include "fix_cfd_coupling.h"
#include "cfd_datacoupling_file.h"
#include <iostream>
#include <fstream>
#include <unistd.h>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define sleep Sleep
#endif
using namespace LAMMPS_NS;
using namespace std;
/* ---------------------------------------------------------------------- */
CfdDatacouplingFile::CfdDatacouplingFile(LAMMPS *lmp, int iarg,int narg, char **arg,FixCfdCoupling *fc) :
CfdDatacoupling(lmp, iarg, narg, arg,fc)
{
iarg_ = iarg;
int n_arg = narg - iarg_;
//NP fprintf(screen,"jarg %d, narg %d \n",jarg,narg);
if(n_arg < 1) error->all(FLERR,"Cfd file coupling: wrong # arguments");
liggghts_is_active = true;
firstexec = true;
this->fc_ = fc;
is_parallel = false;
filepath = new char[strlen(arg[iarg_])+2];
strcpy(filepath,arg[iarg_]);
//NP deleted to make it compatible to zueblin model where this is a file name, not a dir name
//NP if(filepath[strlen(arg[iarg])]!='/') strcat(filepath,"/");
t0 = -1;
iarg_++;
append = 1;
}
/* ---------------------------------------------------------------------- */
CfdDatacouplingFile::~CfdDatacouplingFile()
{
delete []filepath;
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::post_create()
{
if(!is_parallel && comm->nprocs > 1) error->all(FLERR,"Fix couple/cfd with file coupling is for serial computation only");
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::exchange()
{
void *dummy = NULL;
// write to file
for(int i = 0; i < npush_; i++)
{
push(pushnames_[i],pushtypes_[i],dummy,"");
}
// read from files
for(int i = 0; i < npull_; i++)
{
pull(pullnames_[i],pulltypes_[i],dummy,"");
}
}
/* ---------------------------------------------------------------------- */
//NP called with from = NULL
void CfdDatacouplingFile::pull(const char *name, const char *type, void *&from, const char *datatype)
{
CfdDatacoupling::pull(name,type,from,datatype);
int len1 = -1, len2 = -1;
void * to = find_pull_property(name,type,len1,len2);
if(to && strcmp(type,"scalar-atom") == 0)
{
readScalarData(name,(double*)to);
}
else if(to && strcmp(type,"vector-atom") == 0)
{
readVectorData(name,(double**)to);
}
else if(to && strcmp(type,"vector-global") == 0)
{
readGlobalVectorData(name,(double*)from,len1);
}
else if(to && strcmp(type,"array-global") == 0)
{
readGlobalArrayData(name,(double**)from,len1,len2);
}
else
{
if(screen) fprintf(screen,"LIGGGHTS could not find property %s to write data from calling program to.\n",name);
lmp->error->all(FLERR,"This error is fatal");
}
}
/* ---------------------------------------------------------------------- */
//NP called with to = NULL
void CfdDatacouplingFile::push(const char *name, const char *type, void *&to, const char *datatype)
{
CfdDatacoupling::push(name,type,to,datatype);
int len1 = -1, len2 = -1;
if(t0 == -1) t0 = update->ntimestep;
if(update->ntimestep > t0) firstexec = false;
void * from = find_push_property(name,type,len1,len2);
//NPfprintf(screen,"called for var %s, style %s, from is %s \n",name,type,(from==NULL?"NULL":"not NULL"));
if(from && strcmp(type,"scalar-atom") == 0)
{
writeScalarData(name,(double*)from);
}
else if(from && strcmp(type,"vector-atom") == 0)
{
writeVectorData(name,(double**)from);
}
else if(from && strcmp(type,"vector-global") == 0)
{
writeGlobalVectorData(name,(double*)from,len1);
}
else if(from && strcmp(type,"array-global") == 0)
{
writeGlobalArrayData(name,(double**)from,len1,len2);
}
else
{
if(screen) fprintf(screen,"LIGGGHTS could not find property %s to write to calling program.\n",name);
lmp->error->all(FLERR,"This error is fatal");
}
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
char * CfdDatacouplingFile::getFilePath(const char *name, bool flag)
{
//NP if append flag set to false, do not expect 0 or 1 to be appended
if(!append) {
//NP Richard: keep interface consistent! returned char should be deleted by caller
char *file = new char[strlen(name)+1];
strcpy(file,name);
return file;
}
//NP otherwise, expect 0 or 1 to be appended according to flag
char *file = new char[strlen(filepath)+strlen(name)+3];
strcpy(file,filepath);
strcat(file,name);
if(flag) strcat(file,"0");
else strcat(file,"1");
return file;
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::op_complete(const char *name)
{
if(!append) return;
char *oldfile = getFilePath(name,true);
char *newfile = getFilePath(name,false);
/*NL*///fprintf(screen,"renaming %s to %s\n",oldfile,newfile);
rename(oldfile,newfile);
delete []oldfile;
delete []newfile;
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::readVectorData(const char *name, double ** field)
{
// get output path
char *file = getFilePath(name,true);
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
/*NL*///fprintf(screen,"Fix couple/cfd/file: reading from file: %s\n",file);
// set file pointer
ifstream inputPtr(file);
// skip lines starting with #
while(inputPtr.peek() == '#') inputPtr.ignore(1000,'\n');
// write data to variable
int numberOfParticles;
inputPtr >> numberOfParticles;
/*NL*///fprintf(screen,"numberOfParticles %d atom->nlocal %d \n",numberOfParticles,atom->nlocal);
if(atom->nlocal!=numberOfParticles) error->all(FLERR,"Fix couple/cfd/file: Data corruption: # particles in file does not match # particles in LIGGGHTS.\n"
"Note that file-based coupling currently does not support inserting or deleting particles during a coupled run.");
for(int index = 0;index < numberOfParticles; ++index)
{
for(int i=0;i<3;i++) inputPtr >> field[index][i];
}
// clean up inputStream
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::readScalarData(const char* name, double *field)
{
// get output path
char *file = getFilePath(name,true);
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
/*NL*///fprintf(screen,"Fix couple/cfd/file: reading from file: %s\n",file);
// set file pointer
ifstream inputPtr(file);
// skip lines starting with #
while(inputPtr.peek() == '#') inputPtr.ignore(1000,'\n');
// write data to variable
int numberOfParticles;
inputPtr >> numberOfParticles;
if(atom->nlocal!=numberOfParticles) error->all(FLERR,"Fix couple/cfd/file: Data corruption: # particles in file does not match # particles in LIGGGHTS.\n"
"Note that file-based coupling currently does not support inserting or deleting particles during a coupled run.");
// write data to variable
for(int index = 0;index < numberOfParticles; ++index)
{
inputPtr >> field[index];
}
// clean up inputStream
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::readGlobalArrayData(const char *name, double ** field, int &len1, int &len2)
{
// get output path
char *file = getFilePath(name,true);
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
/*NL*///fprintf(screen,"Fix couple/cfd/file: reading from file: %s\n",file);
// set file pointerfrom
ifstream inputPtr(file);
// skip lines starting with #
while(inputPtr.peek() == '#') inputPtr.ignore(1000,'\n');
// write data to variable
int l1,l2;
inputPtr >> l1;
inputPtr >> l2;
if(l1 != len1 || l2 != len2)
error->one(FLERR,"Global array received has different length than the corresponding global array in LIGGGHTS");
/*NL*///fprintf(screen,"lens %d %d \n",l1,l2);
for(int index = 0; index < len1; ++index)
{
for(int i = 0; i < len2; i++)
{
if(inputPtr.eof())
error->one(FLERR,"Global array received has different length than the corresponding global array in LIGGGHTS");
inputPtr >> field[index][i];
/*NL*///fprintf(screen,"i %d j %d val %f\n",index,i,field[index][i]);
}
}
// clean up inputStream
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::readGlobalVectorData(const char* name, double *field, int &len)
{
// get output path
char *file = getFilePath(name,true);
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
/*NL*///fprintf(screen,"Fix couple/cfd/file: reading from file: %s\n",file);
// set file pointer
int l1;
ifstream inputPtr(file);
// skip lines starting with #
while(inputPtr.peek() == '#') inputPtr.ignore(1000,'\n');
inputPtr >> l1;
if(l1 != len) error->all(FLERR,"Global vector received has different length than the corresponding global array in LIGGGHTS");
// write data to variable
for(int index = 0;index < len; ++index)
{
inputPtr >> field[index];
}
// clean up inputStream
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::writeVectorData(const char *name, double ** field)
{
// get output path
char *file = getFilePath(name,true);
if(!firstexec)
{
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
}
/*NL*///fprintf(screen,"Fix couple/cfd/file: writing to file: %s\n",file);
// set file pointer
ofstream outputPtr(file);
// write data to file
int numberOfParticles = atom->nlocal;
outputPtr << numberOfParticles << endl;
for(int index = 0;index < numberOfParticles; ++index)
{
for(int i=0;i<3;i++) outputPtr << field[index][i] << " ";
outputPtr << endl;
}
// clean up outputStream and rename file
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::writeScalarData(const char* name, double * field)
{
// get output path
char *file = getFilePath(name,true);
if(!firstexec)
{
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
}
/*NL*///fprintf(screen,"Fix couple/cfd/file: writing to file: %s\n",file);
// set file pointer
ofstream outputPtr(file);
// write data to file
int numberOfParticles = atom->nlocal;
outputPtr << numberOfParticles << endl;
for(int index = 0;index < numberOfParticles; ++index)
{
outputPtr << field[index] << endl;
}
// clean up outputStream and rename file
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::writeGlobalVectorData(const char *name, double *field, int len)
{
if(len < 0) error->all(FLERR,"Internal error in CfdDatacouplingFile");
// get output path
char *file = getFilePath(name,true);
if(!firstexec)
{
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
}
/*NL*///fprintf(screen,"Fix couple/cfd/file: writing to file: %s\n",file);
// set file pointer
ofstream outputPtr(file);
// write data to file
outputPtr << len << endl;
for(int index = 0;index < len; ++index)
{
outputPtr << field[index];
outputPtr << endl;
}
// clean up outputStream and rename file
delete []file;
op_complete(name);
}
/* ---------------------------------------------------------------------- */
void CfdDatacouplingFile::writeGlobalArrayData(const char* name, double **field, int len1, int len2)
{
if(len1 < 0 || len2 < 0) error->all(FLERR,"Internal error in CfdDatacouplingFile");
// get output path
char *file = getFilePath(name,true);
if(!firstexec)
{
fprintf(screen,"Fix couple/cfd/file: waiting for file: %s\n",file);
struct stat st;
while (stat(file,&st)) sleep(10);
}
/*NL*///fprintf(screen,"Fix couple/cfd/file: writing to file: %s\n",file);
// set file pointer
ofstream outputPtr(file);
// write data to file
outputPtr << len1 << endl;
outputPtr << len2 << endl;
for(int index = 0;index < len1; ++index)
{
for(int i=0;i<len2;i++) outputPtr << field[index][i] << " ";
outputPtr << endl;
}
// clean up outputStream and rename file
delete []file;
op_complete(name);
}