Files
lammps/src/GRANULAR/fix_heat_flow.cpp
2024-04-04 11:29:02 -06:00

221 lines
6.0 KiB
C++

/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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 "fix_heat_flow.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
#include "update.h"
#include <cstring>
using namespace LAMMPS_NS;
using namespace FixConst;
enum { NONE, CONSTANT, TYPE };
/* ---------------------------------------------------------------------- */
FixHeatFlow::FixHeatFlow(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
if (narg < 4) utils::missing_cmd_args(FLERR, "fix heat/flow", error);
cp_style = NONE;
comm_forward = 1;
comm_reverse = 1;
int ntypes = atom->ntypes;
if (strcmp(arg[3], "constant") == 0) {
if (narg != 5) error->all(FLERR, "Illegal fix heat/flow constant command");
cp_style = CONSTANT;
cp = utils::numeric(FLERR, arg[4], false, lmp);
if (cp < 0.0) error->all(FLERR, "Illegal fix heat/flow constant command value");
} else if (strcmp(arg[3], "type") == 0) {
if (narg != 4 + ntypes) error->all(FLERR, "Illegal fix heat/flow type command");
cp_style = TYPE;
memory->create(cp_type, ntypes + 1, "fix_heat_flow:cp_type");
for (int i = 1; i <= ntypes; i++) {
cp_type[i] = utils::numeric(FLERR, arg[3 + i], false, lmp);
if (cp_type[i] < 0.0) error->all(FLERR, "Illegal fix heat/flow type command value");
}
} else {
error->all(FLERR, "Unknown fix heat/flow keyword {}", arg[3]);
}
if (cp_style == NONE) error->all(FLERR, "Must specify specific heat in fix heat/flow");
dynamic_group_allow = 1;
}
/* ---------------------------------------------------------------------- */
int FixHeatFlow::setmask()
{
int mask = 0;
mask |= PRE_FORCE;
mask |= FINAL_INTEGRATE;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::init()
{
dt = update->dt;
if (!atom->temperature_flag)
error->all(FLERR, "Fix heat/flow requires atom style with temperature property");
if (!atom->heatflow_flag)
error->all(FLERR, "Fix heat/flow requires atom style with heatflow property");
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::setup_pre_force(int /*vflag*/)
{
// Identify whether this is the first instance of fix heat/flow
first_flag = 0;
int i = 0;
auto fixlist = modify->get_fix_by_style("heat/flow");
for (const auto &ifix : fixlist) {
if (strcmp(ifix->id, id) == 0) break;
i++;
}
if (i == 0) first_flag = 1;
pre_force(0);
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::pre_force(int /*vflag*/)
{
// send updated temperatures to ghosts if first instance of fix
// then clear heatflow for next force calculation
double *heatflow = atom->heatflow;
if (first_flag) {
comm->forward_comm(this);
for (int i = 0; i < atom->nmax; i++) heatflow[i] = 0.0;
}
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::final_integrate()
{
// update temperature of atoms in group
double *temperature = atom->temperature;
double *heatflow = atom->heatflow;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// add ghost contributions to heatflow if first instance of fix
if (force->newton_pair && first_flag) comm->reverse_comm(this);
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) temperature[i] += dt * heatflow[i] / (calc_cp(i) * rmass[i]);
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) temperature[i] += dt * heatflow[i] / (calc_cp(i) * mass[type[i]]);
}
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::final_integrate_respa(int /*ilevel*/, int /*iloop*/)
{
dt = update->dt;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::reset_dt()
{
dt = update->dt;
}
/* ---------------------------------------------------------------------- */
double FixHeatFlow::calc_cp(int i)
{
if (cp_style == TYPE) {
return cp_type[atom->type[i]];
} else {
return cp;
}
}
/* ---------------------------------------------------------------------- */
int FixHeatFlow::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/)
{
int i, j, m;
double *temperature = atom->temperature;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = temperature[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::unpack_forward_comm(int n, int first, double *buf)
{
int i, m, last;
m = 0;
last = first + n;
double *temperature = atom->temperature;
for (i = first; i < last; i++) temperature[i] = buf[m++];
}
/* ---------------------------------------------------------------------- */
int FixHeatFlow::pack_reverse_comm(int n, int first, double *buf)
{
int m = 0;
int last = first + n;
double *heatflow = atom->heatflow;
for (int i = first; i < last; i++) { buf[m++] = heatflow[i]; }
return m;
}
/* ---------------------------------------------------------------------- */
void FixHeatFlow::unpack_reverse_comm(int n, int *list, double *buf)
{
int m = 0;
double *heatflow = atom->heatflow;
for (int i = 0; i < n; i++) heatflow[list[i]] += buf[m++];
}