5 #ifndef SCALE_COUPLING_H
6 #define SCALE_COUPLING_H
11 #include "../Coupling/BaseCoupling.h"
16 using namespace oomph;
18 template<
class M,
class O>
51 if (coupledElement_pt !=
nullptr) {
53 coupledElement_pt =
nullptr;
60 if (coupledElement_pt != coupledElementNew) {
61 if (coupledElement_pt !=
nullptr) {
64 logger(
VERBOSE,
"Moved particle % from element % to %", particle->
getIndex(), coupledElement_pt, coupledElementNew);
69 coupledElement_pt = coupledElementNew;
86 return coupledElements_;
91 return coupledParticles_;
101 couplingWeight_ = couplingWeight;
108 unsigned nStep = O::getOomphTimeStep()/M::getTimeStep();
111 logger(
INFO,
"Set nStep %, change mercuryTimeStep from % to %",
112 nStep, M::getTimeStep(), O::getOomphTimeStep());
114 M::setTimeStep(O::getOomphTimeStep());
116 logger(
INFO,
"Set nStep %, change oomphTimeStep from % to %",
117 nStep, O::getOomphTimeStep(), nStep * M::getTimeStep());
118 O::setOomphTimeStep(nStep * M::getTimeStep());
121 solveScaleCoupling(nStep);
130 logger.assert_always(O::getOomphTimeStep()>0,
"Oomph time step not initialised");
131 logger.assert_always(M::getTimeStep()>0,
"Mercury time step not initialised");
133 logger.assert_always((
bool)couplingWeight_,
"Coupling weight is not set");
136 initialiseCoupledElements();
140 while (M::getTime() < M::getTimeMax())
142 O::actionsBeforeOomphTimeStep();
144 computeOneTimeStepScaleCoupling(nStep);
146 if (M::getParticlesWriteVTK() && M::getVtkWriter()->getFileCounter() > nDone)
149 nDone = M::getVtkWriter()->getFileCounter();
161 auto nelement = O::mesh_pt()->nelement();
162 for (
int e=0;
e < nelement; ++
e) {
163 bool coupledElement =
false;
164 auto* el_pt =
dynamic_cast<ELEMENT*
>(O::mesh_pt()->finite_element_pt(
e));
165 auto nnode = el_pt->nnode();
167 for (
int n=0;
n < nnode; ++
n) {
168 auto* n_pt =
dynamic_cast<SolidNode*
>(el_pt->node_pt(
n));
169 nodalCouplingWeights[
n] = couplingWeight_(n_pt->xi(0), n_pt->xi(1), n_pt->xi(2));
170 if (nodalCouplingWeights[
n]>0) {
171 coupledElement =
true;
172 logger(
VERBOSE,
"Coupled element at % % %, weight %",n_pt->xi(0), n_pt->xi(1), n_pt->xi(2), nodalCouplingWeights[
n]);
175 if (coupledElement) {
176 coupledElements_.push_back({el_pt});
177 el_pt->set_coupling_weight(nodalCouplingWeights);
180 logger(
INFO,
"% of % el_pts are coupled", coupledElements_.size(), nelement);
185 updateCoupledElements();
186 computeCouplingForce();
188 this->solveMercury(nStep);
198 for (
auto& coupledElement : coupledElements_)
200 ELEMENT* el_pt = coupledElement.el_pt;
201 const unsigned nnode = el_pt->nnode();
202 const unsigned dim = el_pt->dim();
204 for (
int n=0;
n<nnode; ++
n) {
205 auto* n_pt =
dynamic_cast<SolidNode *
>(el_pt->node_pt(
n));
206 for (
int d = 0; d < dim; ++d) {
216 coupledParticles_.resize(M::particleHandler.getSize());
218 for (
int p=0;
p<coupledParticles_.size(); ++
p) {
220 Vec3D pos = M::particleHandler.getObject(
p)->getPosition();
223 logger(
VERBOSE,
"Particle % of % is in coupling zone",
p, M::particleHandler.getSize());
231 if (geom_obj_pt!=
nullptr) {
237 for (
auto& coupledElement : coupledElements_) {
238 coupledElement.el_pt->locate_zeta(
x,geom_obj_pt,
s);
239 if (geom_obj_pt!=
nullptr) {
240 logger(
VERBOSE,
"Coupled particle % to element % at % % %",
p, &coupledElement,
s[0],
s[1],
s[2]);
260 const unsigned nnode = coupledElement.
el_pt->nnode();
261 const unsigned dim = coupledElement.
el_pt->dim();
275 coupledElement.
el_pt->shape(coupledParticles_[particle->
getIndex()].s, psi);
276 for (
unsigned n=0;
n < nnode;
n++) {
277 projectionMatrix[
n][
p] = psi(
n) * particle->
getVolume();
281 for (
unsigned n=0;
n < nnode;
n++) {
284 sum += projectionMatrix[
n][
p];
288 projectionMatrix[
n][
p] /= sum;
292 return projectionMatrix;
299 for (
const auto& coupledElement : coupledElements_)
305 ELEMENT* el_pt = coupledElement.el_pt;
306 const unsigned nParticles = coupledElement.coupledParticles.size();
308 const unsigned nnode = coupledElement.el_pt->nnode();
310 const unsigned dim = el_pt->dim();
312 computeNodalCouplingForces(coupledElement, projectionMatrix);
317 for (
unsigned d=0; d < dim; d++) {
318 double forceComponent = 0;
319 for (
unsigned n=0;
n < nnode;
n++) {
321 forceComponent += projectionMatrix[
n][
p] * el_pt->get_coupling_residual(
n, d);
338 const unsigned nnode = el_pt->nnode();
339 const unsigned dim = el_pt->dim();
345 for (
unsigned n=0;
n < nnode;
n++) {
346 for (
unsigned d=0; d < dim; d++) {
347 double nodalVelocityDPM = 0;
349 nodalVelocityDPM += projectionMatrix[
n][
p] * coupledElement.
coupledParticles[
p]->getVelocity().getComponent(d);
351 double nodalVelocityFEM = el_pt->dnodal_position_gen_dt(
n,0,d);
352 nodalVelocityDifference[
n][d] = nodalVelocityDPM-nodalVelocityFEM;
361 DShape dpsidxi(nnode,dim);
362 const unsigned n_in = el_pt->integral_pt()->nweight();
364 for (
unsigned in=0; in<n_in; in++)
367 double w = el_pt->integral_pt()->weight(in);
369 double J = el_pt->dshape_lagrangian_at_knot(in,psi,dpsidxi);
371 for (
unsigned n=0;
n < nnode;
n++)
374 for (
unsigned nn=0; nn < nnode; nn++)
376 double volume = penalty_ * psi(nn) * psi(
n) *
w *
J;
378 for (
unsigned d=0; d < dim; d++)
381 double displacement = nodalVelocityDifference[
n][d] * O::time_pt()->dt(0);
382 nodalCouplingForces[
n][d] -= volume * displacement;
390 coupledElement.
el_pt->set_coupling_residual(nodalCouplingForces);
392 logger(
VERBOSE,
"VelocityDifference % % %, coupling force % % % on element %, node 0, particles %",
393 nodalVelocityDifference[0][0], nodalVelocityDifference[0][1], nodalVelocityDifference[0][2],
394 nodalCouplingForces[0][0], nodalCouplingForces[0][1], nodalCouplingForces[0][2],
404 p->addForce(M::getGravity() *
p->getMass());
407 double couplingWeight = couplingWeight_(
p->getPosition().X,
p->getPosition().Y,
p->getPosition().Z);
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
LL< Log::VERBOSE > VERBOSE
Verbose information.
Definition: Logger.cc:36
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
RowVector3d w
Definition: Matrix_resize_int.cpp:3
float * p
Definition: Tutorial_Map_using.cpp:9
Definition: BaseCoupling.h:27
unsigned int getIndex() const
Returns the index of the object in the handler.
Definition: BaseObject.h:97
Definition: BaseParticle.h:33
virtual Mdouble getVolume() const
Get Particle volume function, which required a reference to the Species vector. It returns the volume...
Definition: BaseParticle.cc:126
Definition: ScaleCoupling.h:19
void solveScaleCoupling(unsigned nStep)
Solve scale-coupled problem.
Definition: ScaleCoupling.h:127
void setCouplingWeight(const std::function< double(double x, double y, double z)> &couplingWeight)
Sets weight function (determines which nodes/el_pts are in coupling zone)
Definition: ScaleCoupling.h:100
void computeCouplingForce()
Computes coupling force for each element and particle.
Definition: ScaleCoupling.h:296
void updateCoupledElements()
Updates the coupledElements and coupledParticles vectors: finds which particles interact with which e...
Definition: ScaleCoupling.h:192
O::ELEMENT ELEMENT
type of el_pt in O (e.g. RefineableQDPVDElement<3, 2>)
Definition: ScaleCoupling.h:22
std::function< double(double x, double y, double z)> couplingWeight_
Definition: ScaleCoupling.h:27
std::vector< CoupledElement > coupledElements_
Vector of all coupled elements.
Definition: ScaleCoupling.h:38
const std::vector< CoupledParticle > & getCoupledParticles()
get coupled particle
Definition: ScaleCoupling.h:90
void computeOneTimeStepScaleCoupling(unsigned nStep)
What to do in each time step.
Definition: ScaleCoupling.h:184
const std::vector< CoupledElement > & getCoupledElements()
get coupled element
Definition: ScaleCoupling.h:85
void solveScaleCoupling()
Computes nStep, the ratio of FEM and DEM time steps, then calls solveSurfaceCoupling(nStep)
Definition: ScaleCoupling.h:105
std::vector< CoupledParticle > coupledParticles_
The i-th element of this vector describes the coupling properties of the i-th DPM particle.
Definition: ScaleCoupling.h:77
void computeExternalForces(BaseParticle *p) override
Applies coupling force to MercuryDPM in each time step.
Definition: ScaleCoupling.h:399
void computeNodalCouplingForces(const CoupledElement &coupledElement, const Vector< Vector< double >> &projectionMatrix)
Computes coupling force for each node.
Definition: ScaleCoupling.h:331
void setPenalty(double penalty)
Sets penalty parameter.
Definition: ScaleCoupling.h:95
void initialiseCoupledElements()
initialises the coupledElements vector
Definition: ScaleCoupling.h:158
Vector< Vector< double > > computeProjectionMatrix(const CoupledElement &coupledElement)
Computes projectionMatrix.
Definition: ScaleCoupling.h:255
Definition: Kernel/Math/Vector.h:30
Mdouble Y
Definition: Kernel/Math/Vector.h:45
Mdouble Z
Definition: Kernel/Math/Vector.h:45
Mdouble X
the vector components
Definition: Kernel/Math/Vector.h:45
void setComponent(int index, double val)
Sets the requested component of this Vec3D to the requested value.
Definition: Vector.cc:197
Definition: geom_objects.h:101
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23
Scalar * y
Definition: level1_cplx_impl.h:128
RealScalar s
Definition: level1_cplx_impl.h:130
#define isfinite(X)
Definition: main.h:111
#define INFO(i)
Definition: mumps_solver.h:54
list nParticles
Definition: MergeRestartFiles.py:46
const Mdouble NaN
Definition: GeneralDefine.h:22
const Mdouble inf
Definition: GeneralDefine.h:23
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
Stores properties of a coupled element: pointer to the element and list of particles coupled to it.
Definition: ScaleCoupling.h:30
std::vector< BaseParticle * > coupledParticles
Definition: ScaleCoupling.h:34
ELEMENT * el_pt
Definition: ScaleCoupling.h:32
For all particles, stores coupling properties: coupling force, pointer to coupled element and locatio...
Definition: ScaleCoupling.h:41
CoupledElement * coupledElement_pt
Element in which this particle resides (null if particle is not coupled)
Definition: ScaleCoupling.h:45
Vec3D couplingForce
Coupling force.
Definition: ScaleCoupling.h:43
void setCoupledElement(CoupledElement *coupledElementNew, BaseParticle *particle)
Remove particle from coupledParticle.coupledElement.particles and set coupledParticle....
Definition: ScaleCoupling.h:59
void removeCoupledElement(BaseParticle *particle)
Removes particle from coupledParticle.coupledElement.particles and sets coupledParticle....
Definition: ScaleCoupling.h:50
Vector< double > s
Location of particle in coupled element, returned by locate zeta.
Definition: ScaleCoupling.h:47