Files
LIGGGHTS-PFM/src/fix_check_timestep_sph.cpp
danielque b64c9613fe use angle brackets instead of quotes on system include files
like in LAMMPS 2015-10-31 and LIGGGHTS-PUBLIC 3.5.0
2016-09-08 13:45:53 +02:00

302 lines
8.3 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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author for SPH:
Andreas Aigner (CD Lab Particulate Flow Modelling, JKU)
andreas.aigner@jku.at
------------------------------------------------------------------------- */
#include <string.h>
#include <stdlib.h>
#include "atom.h"
#include "update.h"
#include <math.h>
#include "error.h"
#include "fix_check_timestep_sph.h"
#include "fix_property_global.h"
#include "force.h"
#include "comm.h"
#include "modify.h"
#include "fix_wall_gran.h"
#include "fix_mesh_surface.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "mpi_liggghts.h"
#include "sph_kernels.h"
using namespace LAMMPS_NS;
using namespace FixConst;
#define BIG 1000000.
/* ---------------------------------------------------------------------- */
FixCheckTimestepSph::FixCheckTimestepSph(LAMMPS *lmp, int narg, char **arg) :
FixSph(lmp, narg, arg)
{
int iarg = 3;
if (narg < iarg+2) error->all(FLERR,"Illegal fix check/timestep/sph command, not enough arguments");
nevery = atoi(arg[iarg]);
fraction_courant_lim=atof(arg[iarg+1]);
iarg += 2;
warnflag = true;
if(iarg < narg){
if (narg < iarg+2) error->all(FLERR,"Illegal fix check/timestep/sph command, not enough arguments");
if(strcmp(arg[iarg],"warn")!=0) error->all(FLERR,"Illegal fix check/timestep/sph command, use keyword 'warn'");
if(strcmp(arg[iarg+1],"no")==0) warnflag=false;
}
iarg += 2;
vector_flag = 1;
size_vector = 2;
global_freq = nevery;
extvector = 1;
fraction_courant = fraction_skin = 0.;
}
/* ---------------------------------------------------------------------- */
int FixCheckTimestepSph::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixCheckTimestepSph::init()
{
FixSph::init();
//some error checks
if(!atom->rho_flag) error->all(FLERR,"Fix check/timestep/sph can only be used together with a sph atom style");
/*
fwg = NULL;
for (int i = 0; i < modify->n_fixes_style("wall/gran"); i++)
if(static_cast<FixWallGran*>(modify->find_fix_style("wall/gran",i))->is_mesh_wall())
fwg = static_cast<FixWallGran*>(modify->find_fix_style("wall/gran",i));
*/
int ntype = atom->ntypes;
cs = static_cast<FixPropertyGlobal*>(modify->find_fix_property("speedOfSound","property/global","peratomtype",ntype,0,"check/sph/timestep"));
if(!cs) error->all(FLERR,"Fix check/timestep/sph only works with a pair style that defines speedOfSound");
}
/* ---------------------------------------------------------------------- */
void FixCheckTimestepSph::end_of_step()
{
calc_courant_estims();
double skin = neighbor->skin;
double dt = update->dt;
fraction_courant = dt/courant_time;
fraction_skin = (vmax * dt) / skin;
if(warnflag&&comm->me==0)
{
if(fraction_skin > 0.1)
{
if(screen) fprintf(screen ,"WARNING: time step too large or skin too small - particles may travel a relative distance of %g per time-step, but 0.1 * skin is %g\n",vmax*dt,0.1*skin);
if(logfile) fprintf(logfile,"WARNING: time step too large or skin too small - particles may travel a relative distance of %g per time-step, but 0.1 * skin is %g\n",vmax*dt,0.1*skin);
}
if(fraction_courant > fraction_courant_lim)
{
if(screen) fprintf(screen, "WARNING: time-step is %f %% of courant time\n",fraction_courant*100.);
if(logfile) fprintf(logfile,"WARNING: time-step is %f %% of courant time\n",fraction_courant*100.);
}
/*
if(vmax * dt > r_min)
{
if(screen) fprintf(screen ,"WARNING: time step way too large - particles move further than the minimum radius in one step\n");
if(logfile) fprintf(logfile,"WARNING: time step way too large - particles move further than the minimum radius in one step\n");
}
*/
}
}
/* ---------------------------------------------------------------------- */
void FixCheckTimestepSph::calc_courant_estims()
{
//template function for using per atom or per atomtype smoothing length
if (mass_type) calc_courant_estims_eval<1>();
else calc_courant_estims_eval<0>();
}
/* ----------------------------------------------------------------------
return fraction of courant time-step
------------------------------------------------------------------------- */
double FixCheckTimestepSph::compute_vector(int n)
{
if(n == 0) return fraction_courant;
else if(n == 1) return fraction_skin;
return 0.;
}
/* ---------------------------------------------------------------------- */
template <int MASSFLAG>
void FixCheckTimestepSph::calc_courant_estims_eval()
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double delvx,delvy,delvz,mu;
double sli,slj,slCom,cut;
int *ilist,*jlist,*numneigh,**firstneigh;
double vmag,courant_time_one;
double cmean;
int j_maxmu = 0;
double **x = atom->x;
double **v = atom->v;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
updatePtrs(); // get sl
vmax = -1;
mumax = -1;
courant_time = BIG;
// calculate minimum courant time step
//inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
for (ii=0; ii<nlocal;ii++){
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
if (MASSFLAG) {
itype = type[i];
sli = sl[itype-1];
} else {
sli = sl[i];
}
vmag = sqrt(v[i][0]*v[i][0]+v[i][1]*v[i][1]+v[i][2]*v[i][2]);
if(vmag > vmax) vmax=vmag;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
if (!(mask[j] & groupbit)) continue;
if (MASSFLAG) {
jtype = type[j];
slCom = slComType[itype][jtype];
} else {
slj = sl[j];
slCom = interpDist(sli,slj);
}
cut = slCom*kernel_cut;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut*cut) {
delvx = v[i][0] - v[j][0];
delvy = v[i][1] - v[j][1];
delvz = v[i][2] - v[j][2];
mu = slCom * (delvx*delx+delvy*dely+delvz*delz) / (rsq);
if (mu > mumax) {
mumax = mu;
j_maxmu = j;
}
}
} //neighbor loop
cmean = 0.5*(cs->values[type[i]-1]+cs->values[type[j_maxmu]-1]);
courant_time_one = sli / (cmean + mumax);
courant_time = MIN(courant_time,courant_time_one);
}
MPI_Max_Scalar(vmax,world);
MPI_Max_Scalar(courant_time,world);
/*
// get vmax of geometry
FixMeshSurface ** mesh_list;
TriMesh * mesh;
double *v_node;
double vmax_mesh=0.;
if(fwg)
{
mesh_list = fwg->mesh_list();
for(int imesh = 0; imesh < fwg->n_meshes(); imesh++)
{
mesh = (mesh_list[imesh])->triMesh();
if(mesh->isMoving())
{
// loop local elements only
for(int itri=0;itri<mesh->sizeLocal();itri++)
for(int inode=0;inode<3;inode++)
{
v_node = mesh->prop().getElementProperty<MultiVectorContainer<double,3,3> >("v")->begin()[itri][inode];
vmag = vectorMag3D(v_node);
if(vmag>vmax_mesh) vmax_mesh=vmag;
}
}
}
}
MPI_Max_Scalar(vmax_mesh,world);
// decide vmax - either particle-particle or particle-mesh contact
vmax = fmax(2.*vmax,vmax+vmax_mesh);
*/
}