Particles driven by a rotating coil

Problem description:

This tutorial simulates particle flows around a coil for a short time. The code can be found in CoilSelfTest.cpp. It treats particles placed in a feeder being driven forward by a rotating coil.

Headers

The following headers are included:

These are basically the headers used for the beginner tutorials, except for the additional Coil class.

Before the main function

CoilSelfTest, like many of the previous tutorials, inherits from the Mercury3D class.

class CoilSelfTest : public Mercury3D
[CST:headers]
Definition: CoilSelfTest.cpp:43
This adds on the hierarchical grid code for 3D problems.
Definition: Mercury3D.h:37

The different components of the class will be explained in turn in the following.

step 1: Define Walls
The particles are initially contained by a container made up of six walls, five of which are defined to be infinite. The wall in the positive Z-direction is different. Its normal is set (rightWall->set(...) in the positive Z-direction (Vec3D(0, 0, 1)), is set a distance zMax_ (which is returned by getZMax()) from the origin, and contains a 'hole' (which is practically a horizontal tube, since the wall is 'infinite') around the X-axis of radius 1.0 in order to let the particles through.

w.setSpecies(speciesHandler.getObject(0));
//front wall
w.set(Vec3D(-1, 0, 0), Vec3D(getXMin(), 0, 0));
wallHandler.copyAndAddObject(w);
//back wall
w.set(Vec3D(1, 0, 0), Vec3D(getXMax(), 0, 0));
wallHandler.copyAndAddObject(w);
//bottom wall
w.set(Vec3D(0, -1, 0), Vec3D(0, getYMin(), 0));
wallHandler.copyAndAddObject(w);
//top wall
w.set(Vec3D(0, 1, 0), Vec3D(0, getYMax(), 0));
wallHandler.copyAndAddObject(w);
//left wall
w.set(Vec3D(0, 0, -1), Vec3D(0, 0, getZMin()));
wallHandler.copyAndAddObject(w);
//right wall
rightWall.setSpecies(speciesHandler.getObject(0));
rightWall.set(Vec3D(0, 0, 1), getZMax(), 1.0);
wallHandler.copyAndAddObject(rightWall);
void setSpecies(const ParticleSpecies *species)
Defines the species of the current wall.
Definition: BaseWall.cc:169
Definition: InfiniteWallWithHole.h:38
void set(Vec3D normal, Mdouble position, Mdouble holeRadius)
Defines a standard wall, given an outward normal vector s. t. normal*x=position.
Definition: InfiniteWallWithHole.cc:72
A infinite wall fills the half-space {point: (position_-point)*normal_<=0}.
Definition: InfiniteWall.h:48
void set(Vec3D normal, Vec3D point)
Defines a standard wall, given an outward normal vector s.t. normal*x=normal*point for all x of the w...
Definition: InfiniteWall.cc:118
Definition: Vector.h:51

step 2: Coil
After that the Coil object is added. Its geometrical properties are subsequently set by using the Coil::set() method, specifying its starting position (the origin, i.e. Vec3D(0,0,0)), its length (1.0), its radius (1.0 - particleRadius), its number of turns (2.0), its rotation speed (-1.0 revelations per second) and its thickness (0.5 * particleRadius).
NB: its direction or central axis is not specified, since these are the Z-direction and the Z-axis, respectively, by default.

// creation of the coil and setting of its properties
Coil coil;
coil.setSpecies(speciesHandler.getObject(0));
// the syntax to set the coil geometry is as follows:
// set(Start position, Length, Radius, Number of turns, Rotation speed, Thickness)
coil.set(Vec3D(0, 0, 0), 1.0, 1.0 - particleRadius, 2.0, -1.0, 0.5 * particleRadius);
auto pCoil = wallHandler.copyAndAddObject(coil);
This class defines a coil in the z-direction from a (constant) starting point, a (constant) length L,...
Definition: Coil.h:41
void set(Vec3D Start, Mdouble length, Mdouble radius, Mdouble numberOfRevelations, Mdouble omega, Mdouble thickness)
Set all parameters of this Coil.
Definition: Coil.cc:102

step 3: Create Particles
The particle properties are set subsequently. The particleHandler is cleared just to be sure it is empty, then the particle to be copied into the container is created and the previously set species is assigned to it. The particle is assigned a zero velocity and the previously defined particle radius.

particleHandler.clear();
p0.setSpecies(speciesHandler.getObject(0));
p0.setVelocity(Vec3D(0.0, 0.0, 0.0));
p0.setRadius(particleRadius);
void setVelocity(const Vec3D &velocity)
set the velocity of the BaseInteractable.
Definition: BaseInteractable.cc:350
virtual void setRadius(Mdouble radius)
Sets the particle's radius_ (and adjusts the mass_ accordingly, based on the particle's species)
Definition: BaseParticle.cc:553
void setSpecies(const ParticleSpecies *species)
Definition: BaseParticle.cc:818
A spherical particle is the most simple particle used in MercuryDPM.
Definition: SphericalParticle.h:37

step 4: Place Particles
After specifying the particle properties, the container is filled with copies of the particle. In this example, particles are placed in a rectangular grid pattern, on evenly spaced positions. First, the number of particles that fit in each direction is computed. Then, a triple for-loop passes every possible particle position, and a particle is placed on the position if there's no part of the coil there.

// Nx*Ny*Nz particles are created and placed on evenly spaced positions in
// the domain [xMin_,xMax_]*[yMin_,yMax_]*[zMin_,zMax_] (unless their position
// is already occupied by the coil).
const unsigned int Nx = static_cast<unsigned int> (std::floor((getXMax() - getXMin()) / (2.1 * particleRadius)));
const unsigned int Ny = static_cast<unsigned int> (std::floor((getYMax() - getYMin()) / (2.1 * particleRadius)));
const unsigned int Nz = static_cast<unsigned int> (std::floor((getZMax() - getZMin()) / (2.1 * particleRadius)));
Mdouble distance;
Vec3D normal;
for (unsigned int i = 0; i < Nx; i++)
{
for (unsigned int j = 0; j < Ny; j++)
{
for (unsigned int k = 0; k < Nz; k++)
{
p0.setPosition(Vec3D(getXMin() + (getXMax() - getXMin()) * (0.5 + i) / Nx,
getYMin() + (getYMax() - getYMin()) * (0.5 + j) / Ny,
getZMin() + (getZMax() - getZMin()) * (0.5 + k) / Nz));
if (!pCoil->getDistanceAndNormal(p0, distance, normal)) //if there is no collision with the coil
{
particleHandler.copyAndAddObject(p0);
}
else
{
logger(DEBUG, "particle at position % could not be inserted", p0.getPosition());
}
}
}
}
double Mdouble
Definition: GeneralDefine.h:34
LL< Log::DEBUG > DEBUG
Debug information.
Definition: Logger.cc:58
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
virtual void setPosition(const Vec3D &position)
Sets the position of this BaseInteractable.
Definition: BaseInteractable.h:239
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:218
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51

Data members:
CoilSelfTest only has two (public) data members, namely a pointer to the coil:

Coil* coil;
Mdouble particleRadius;

Actions Before TimeStep:
The actionsBeforeTimeStep() method specifies all actions that need to be performed at the beginning of each time step, i.e. before the actual numerical solution at that time step is computed. In this case, it states that from 1 second into the simulation time and onward, the coil should turn with the given rotational speed.

void actionsBeforeTimeStep() override
{
if (getTime() > 1)
{
coil->move_time(getTimeStep());
}
}
void move_time(Mdouble dt)
Rotate the Coil for a period dt, so that the offset_ changes with omega_*dt.
Definition: Coil.cc:214

Main Function

In the main program, a CoilSelfTest object is created, after which some of its basic properties are set like its number of dimensions (three), time step and saving parameters. Lastly, the problem is actually solved by calling its solve() method.

int main(int argc UNUSED, char* argv[] UNUSED)
{
// create CoilSelfTest object
CoilSelfTest problem;
// set some basic problem properties
problem.setName("CoilSelfTest");
problem.setSystemDimensions(3);
problem.setGravity(Vec3D(0.0, -9.8, 0.0));
// set problem geometry
problem.setXMax(1.0);
problem.setYMax(5.0);
problem.setZMax(2.0);
problem.setXMin(-1.0);
problem.setYMin(-1.0);
problem.setTimeMax(0.5);
problem.particleRadius = 0.2;
species.setDensity(1000);
Mdouble tc = 0.05;
Mdouble restitutionCoefficient = 0.8;
Mdouble particleMass = pow(problem.particleRadius, 3) * constants::pi * 4.0 / 3.0 * species.getDensity();
species.setCollisionTimeAndRestitutionCoefficient(tc, restitutionCoefficient, particleMass);
problem.speciesHandler.copyAndAddObject(species);
problem.setTimeStep(0.02 * 0.05);
problem.getTimeStep()));
problem.solve();
}
#define UNUSED
Definition: GeneralDefine.h:39
int main(int argc, char *argv[])
Definition: T_protectiveWall.cpp:215
std::enable_if<!std::is_pointer< U >::value, U * >::type copyAndAddObject(const U &object)
Creates a copy of a Object and adds it to the BaseHandler.
Definition: BaseHandler.h:379
Mdouble particleRadius
Definition: CoilSelfTest.cpp:152
void setSaveCount(unsigned int saveCount)
Sets File::saveCount_ for all files (ene, data, fstat, restart, stat)
Definition: DPMBase.cc:408
SpeciesHandler speciesHandler
A handler to that stores the species type i.e. LinearViscoelasticSpecies, etc.
Definition: DPMBase.h:1427
void setYMin(Mdouble newYMin)
Sets the value of YMin, the lower bound of the problem domain in the y-direction.
Definition: DPMBase.cc:1034
void setName(const std::string &name)
Allows to set the name of all the files (ene, data, fstat, restart, stat)
Definition: DPMBase.cc:422
Mdouble getTimeStep() const
Returns the simulation time step.
Definition: DPMBase.cc:1250
void setYMax(Mdouble newYMax)
Sets the value of YMax, the upper bound of the problem domain in the y-direction.
Definition: DPMBase.cc:1191
void setXMax(Mdouble newXMax)
Sets the value of XMax, the upper bound of the problem domain in the x-direction.
Definition: DPMBase.cc:1165
void setZMax(Mdouble newZMax)
Sets the value of ZMax, the upper bound of the problem domain in the z-direction.
Definition: DPMBase.cc:1217
void setTimeStep(Mdouble newDt)
Sets a new value for the simulation time step.
Definition: DPMBase.cc:1234
void setTimeMax(Mdouble newTMax)
Sets a new value for the maximum simulation duration.
Definition: DPMBase.cc:873
void setSystemDimensions(unsigned int newDim)
Sets the system dimensionality.
Definition: DPMBase.cc:1417
void solve()
The work horse of the code.
Definition: DPMBase.cc:4270
void setXMin(Mdouble newXMin)
Sets the value of XMin, the lower bound of the problem domain in the x-direction.
Definition: DPMBase.cc:1010
Mdouble getTimeMax() const
Returns the maximum simulation duration.
Definition: DPMBase.cc:888
void setGravity(Vec3D newGravity)
Sets a new value for the gravitational acceleration.
Definition: DPMBase.cc:1383
void setCollisionTimeAndRestitutionCoefficient(Mdouble tc, Mdouble eps, BaseParticle *p)
Sets k, disp such that it matches a given tc and eps for a collision of two copies of particle p.
Definition: LinearViscoelasticNormalSpecies.cc:212
void setDensity(Mdouble density)
Definition: ParticleSpecies.cc:108
Mdouble getDensity() const
Allows density_ to be accessed.
Definition: ParticleSpecies.cc:118
const Mdouble pi
Definition: ExtendedMath.h:45
unsigned int getSaveCountFromNumberOfSavesAndTimeMaxAndTimeStep(unsigned int numberOfSaves, Mdouble timeMax, Mdouble timeStep)
Returns the correct saveCount if the total number of saves, the final time and the time step is known...
Definition: FormulaHelpers.cc:96

Next, the particle species is defined. The particles in this problem will use a linear visco-elastic (normal) contact model. The dissipation and stiffness defining the contact model can be set in different ways. In this example the contact model properties are set by giving a collision time, coefficient of restitution and the particle mass.

species.setDensity(1000);
Mdouble tc = 0.05;
Mdouble restitutionCoefficient = 0.8;
Mdouble particleMass = pow(problem.particleRadius, 3) * constants::pi * 4.0 / 3.0 * species.getDensity();
species.setCollisionTimeAndRestitutionCoefficient(tc, restitutionCoefficient, particleMass);
problem.speciesHandler.copyAndAddObject(species);

Reference:

Imole, O. I., Krijgsman, D., Weinhart, T., Magnanimo, V., Montes, B. E. C., Ramaioli, M., & Luding, S. (2016). Reprint of" Experiments and discrete element simulation of the dosing of cohesive powders in a simplified geometry". Powder technology, 293, 69-81.

(Return to Overview of advanced tutorials)