VolumeCoupling Class Reference

#include <VCoupling.h>

+ Inheritance diagram for VolumeCoupling:

Classes

struct  DPMVCoupledElement
 

Public Types

typedef VolumeCoupledElement< OomphProblem::ELEMENT > VELEMENT
 

Public Member Functions

 VolumeCoupling ()=default
 
 VolumeCoupling (const double &wMin, const bool &flag)
 
void computeExternalForces (BaseParticle *CI) override
 
void actionsAfterTimeStep () override
 
void solveVolumeCoupling (const double &width)
 
void solveVolumeCoupling ()
 
void computeOneTimeStepForVCoupling (const unsigned &nstep)
 
void solveFirstHalfTimeStep ()
 
void solveSecondHalfTimeStep ()
 
void checkParticlesInFiniteElems ()
 
void setNodalWeightOnCubicMesh ()
 
void setNodalWeightByDistance ()
 
void getProjectionAndProjected (const DPMVCoupledElement &coupled_elem, Vector< Vector< double >> &couplingMatrix, Vector< Vector< double >> &nodalDisplDPM)
 
void getProjectionMatrix (const DPMVCoupledElement &coupled_elem, Vector< Vector< double >> &couplingMatrix)
 
void computeCouplingForce ()
 
void computeCouplingOnFEM ()
 
void computeCouplingOnDPM ()
 
void computeNodalCouplingForces (VELEMENT *&elem_pt, const unsigned &nnode, const unsigned &dim, const Vector< Vector< double >> &nodalDisplDPM, Vector< Vector< double >> &nodalCouplingForces)
 
void getBulkStiffness (VELEMENT *&elem_pt, Vector< Vector< double >> &bulkStiffness)
 
void getInvCoupledMassPerTime (const DPMVCoupledElement &elem, const Vector< Vector< double >> &couplingMatrix, const Vector< Vector< double >> &bulkStiffness, Vector< double > &invCMassPerTime)
 
void computeWeightOnParticles ()
 
void setExplicit (const bool &flag)
 
- Public Member Functions inherited from BaseCoupling< M, O >
 BaseCoupling ()=default
 
void setName (std::string name)
 
std::string getName () const
 
void removeOldFiles () const
 
void writeEneTimeStep (std::ostream &os) const override
 
void writeEneHeader (std::ostream &os) const override
 
void solveOomph (int max_adapt=0)
 
void checkResidual ()
 
void solveMercury (unsigned long nt)
 
void setCGWidth (const double &width)
 
double getCGWidth ()
 
bool useCGMapping ()
 
CGFunctions::LucyXYZ getCGFunction ()
 

Private Attributes

Vector< DPMVCoupledElementlistOfDPMVCoupledElements_
 
double weightMin_ = 0.0
 
bool explicit_ = false
 

Member Typedef Documentation

◆ VELEMENT

typedef VolumeCoupledElement<OomphProblem::ELEMENT> VolumeCoupling::VELEMENT

Constructor & Destructor Documentation

◆ VolumeCoupling() [1/2]

VolumeCoupling::VolumeCoupling ( )
default

◆ VolumeCoupling() [2/2]

VolumeCoupling::VolumeCoupling ( const double wMin,
const bool flag 
)
inline
36  {
37  setExplicit(flag);
38  weightMin_ = wMin;
39  }
void setExplicit(const bool &flag)
Definition: VCoupling.h:957
double weightMin_
Definition: VCoupling.h:964

References setExplicit(), and weightMin_.

Member Function Documentation

◆ actionsAfterTimeStep()

void VolumeCoupling::actionsAfterTimeStep ( )
inlineoverride

Override actionsAfterTimeStep to reset vcoupling force

Todo:
actions after time step should be user-defined, so not be used here
62  {
63  // Reset coupling weights and forces to default values
64  for (BaseParticle* p : particleHandler)
65  {
66  if (!p->isFixed())
67  {
68  // reset the coupling force to zero for the next time step
69  p->resetCouplingForce();
70  p->resetInvCouplingWeight();
71  p->resetCouplingMass();
72  }
73  }
74 
75  // check how much equilibrium is broken
76  const auto p = particleHandler.getLastObject();
77  Vec3D f = p->getMass() * getGravity();
78  Vec3D a = p->getForce();
79  if (a.getLengthSquared() > 1.0e-5 * f.getLengthSquared())
80  {
81  logger(INFO, "time %, body force: %, total force: %, position %",
82  getTime(), f, a, p->getPosition());
83  }
84 
85  // check if each particle-wall interaction is unique
86  for (auto p : particleHandler)
87  {
88  unsigned n = 0;
89  for (auto i : p->getInteractions())
90  {
91  if (i->getI()->getName() == "TriangleWall") n++;
92  }
93  if (n > 1)
94  {
95  logger(INFO, "particle % is interacting with % TriangleWalls", p->getId(), n);
96  for (auto i : p->getInteractions())
97  {
98  if (i->getI()->getName() == "TriangleWall")
99  {
100  logger(INFO, "particle % is interacting with wall %", p->getId(), i->getI()->getId());
101  }
102  }
103  }
104  }
105  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
@ INFO
float * p
Definition: Tutorial_Map_using.cpp:9
Definition: BaseParticle.h:33
Definition: Kernel/Math/Vector.h:30
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
const Scalar * a
Definition: level2_cplx_impl.h:32

References a, f(), i, INFO, logger, n, and p.

Referenced by solveSecondHalfTimeStep().

◆ checkParticlesInFiniteElems()

void VolumeCoupling::checkParticlesInFiniteElems ( )
inline
262  {
263  // how many bulk elements in total
264  unsigned n_element = OomphProblem::solid_mesh_pt()->nelement();
265 
266  // loop over the bulk elements
267  for (unsigned e = 0; e < n_element; e++)
268  {
269  // get pointer to the bulk element
270  auto bulk_elem_pt = dynamic_cast<VELEMENT*>(OomphProblem::solid_mesh_pt()->element_pt(e));
271 
272  // get number of nodes in the bulk element
273  const unsigned nnode = bulk_elem_pt->nnode();
274 
275  // Set up memory for the shape/test functions
276  Shape psi(nnode);
277 
278  // three arrays that contain the x, y and z coordinates of the bulk element
279  Vector<double> listOfCoordX;
280  Vector<double> listOfCoordY;
281  Vector<double> listOfCoordZ;
282 
283  // get the x, y and z coordinates of the bulk element
284  for (unsigned n = 0; n < nnode; n++)
285  {
286  listOfCoordX.push_back(bulk_elem_pt->node_pt(n)->x(0) * Global_Physical_Variables::lenScale);
287  listOfCoordY.push_back(bulk_elem_pt->node_pt(n)->x(1) * Global_Physical_Variables::lenScale);
288  listOfCoordZ.push_back(bulk_elem_pt->node_pt(n)->x(2) * Global_Physical_Variables::lenScale);
289  }
290 
291  // get the bounding box of the bulk element
292  Vec3D min;
293  min.X = *min_element(listOfCoordX.begin(), listOfCoordX.end());
294  min.Y = *min_element(listOfCoordY.begin(), listOfCoordY.end());
295  min.Z = *min_element(listOfCoordZ.begin(), listOfCoordZ.end());
296  Vec3D max;
297  max.X = *max_element(listOfCoordX.begin(), listOfCoordX.end());
298  max.Y = *max_element(listOfCoordY.begin(), listOfCoordY.end());
299  max.Z = *max_element(listOfCoordZ.begin(), listOfCoordZ.end());
300 
301  // extend the bounding box if construct mapping with coarse graining
302  min -= Vec3D(1.0, 1.0, 1.0) * ( getCGWidth() - 2 * particleHandler.getLargestParticle()->getRadius() );
303  max += Vec3D(1.0, 1.0, 1.0) * ( getCGWidth() - 2 * particleHandler.getLargestParticle()->getRadius() );
304 
305  // get particles if there are in the bounding box
306  Vector<BaseParticle*> pList;
307  getParticlesInCell(min, max, pList);
308  if (pList.size() != 0)
309  {
310  DPMVCoupledElement DPM_coupled_elem;
311  // save the extended particle list if construct mapping with coarse graining functions
312  if (useCGMapping())
313  { DPM_coupled_elem.listOfCoupledParticlesExt = pList; }
314  // check if a particle resides within the bulk element
315  for (auto it = pList.begin(); it != pList.end(); it++)
316  {
317  Vector<double> s(3, 0.0), x(3, 0.0);
318  GeomObject* geom_obj_pt = 0;
319  // get global coordinates of particle center (DPM)
320  Vec3D xp = ( *it )->getPosition();
322  x[0] = xp.getX();
323  x[1] = xp.getY();
324  x[2] = xp.getZ();
325  // get local coordinates of particle center (FEM)
326  bulk_elem_pt->locate_zeta(x, geom_obj_pt, s);
327  // If true, the iterator is decremented after it is passed to erase() but before erase() is executed
328  if (geom_obj_pt == nullptr)
329  { pList.erase(it--); }
330  else
331  {
332  // save local coordinates of particle center
333  DPM_coupled_elem.listOfParticleCentersLoc.push_back(s);
334  // evaluate shape functions at particle center
335  bulk_elem_pt->shape(s, psi);
336  Vector<double> shapes;
337  for (unsigned l = 0; l < nnode; l++) shapes.push_back(psi(l));
338  // save shape functions at particle center
339  DPM_coupled_elem.listOfShapesAtParticleCenters.push_back(shapes);
340  }
341  }
342  // if there are particles in the bulk element (check with locate_zeta)
343  if (pList.size() != 0)
344  {
345  // save pointer to the bulk element and the pointer list to particles
346  DPM_coupled_elem.bulk_elem_pt = bulk_elem_pt;
347  DPM_coupled_elem.listOfCoupledParticles = pList;
348  listOfDPMVCoupledElements_.push_back(DPM_coupled_elem);
349  }
350  }
351  }
352  }
Array< double, 1, 3 > e(1./3., 0.5, 2.)
bool useCGMapping()
Definition: BaseCoupling.h:180
double getCGWidth()
Definition: BaseCoupling.h:175
Mdouble getZ() const
Definition: Kernel/Math/Vector.h:437
Mdouble getX() const
Definition: Kernel/Math/Vector.h:431
Mdouble getY() const
Definition: Kernel/Math/Vector.h:434
VolumeCoupledElement< OomphProblem::ELEMENT > VELEMENT
Definition: VCoupling.h:13
Vector< DPMVCoupledElement > listOfDPMVCoupledElements_
Definition: VCoupling.h:962
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23
RealScalar s
Definition: level1_cplx_impl.h:130
double lenScale
Length scale.
Definition: VCoupledElement.h:10
list x
Definition: plotDoE.py:28

References VolumeCoupling::DPMVCoupledElement::bulk_elem_pt, e(), BaseCoupling< M, O >::getCGWidth(), Vec3D::getX(), Vec3D::getY(), Vec3D::getZ(), Global_Physical_Variables::lenScale, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticles, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticlesExt, listOfDPMVCoupledElements_, VolumeCoupling::DPMVCoupledElement::listOfParticleCentersLoc, VolumeCoupling::DPMVCoupledElement::listOfShapesAtParticleCenters, max, min, n, s, BaseCoupling< M, O >::useCGMapping(), and plotDoE::x.

Referenced by computeOneTimeStepForVCoupling().

◆ computeCouplingForce()

void VolumeCoupling::computeCouplingForce ( )
inline
573  {
574  // first loop over the coupled bulk elements
575  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
576  {
577  // get pointer to the bulk element
578  VELEMENT* elem_pt = coupled_elem.bulk_elem_pt;
579  // get particles and the number of coupled particles in the bulk element
580  Vector<BaseParticle*> particles;
581  if (!useCGMapping())
582  { particles = coupled_elem.listOfCoupledParticles; }
583  else
584  { particles = coupled_elem.listOfCoupledParticlesExt; }
585  const unsigned nParticles = particles.size();
586  // get number of nodes in the bulk element
587  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
588  // prepare projection matrix
589  Vector<Vector<double>> couplingMatrix(nnode, Vector<double>(nParticles, 0.0));
590  // prepare vector of nodal displacements projected from particle centers
591  const unsigned dim = elem_pt->dim();
592  Vector<Vector<double>> nodalDisplDPM(nnode, Vector<double>(dim, 0.0));
593  // compute projected nodal displacements
594  getProjectionAndProjected(coupled_elem, couplingMatrix, nodalDisplDPM);
595  // compute nodal coupling forces by penalizing the difference in displacement
596  Vector<Vector<double>> nodalCouplingForces(nnode, Vector<double>(dim, 0.0));
597  computeNodalCouplingForces(elem_pt, nnode, dim, nodalDisplDPM, nodalCouplingForces);
598  // get coupling forces projected from coupled nodes to particles (note couplingMatrix^{-1} = couplingMatrix^T)
599  Vector<Vector<double>> particleCouplingForces(nParticles, Vector<double>(dim, 0.0));
600  for (unsigned i = 0; i < nParticles; i++)
601  {
602  for (unsigned k = 0; k < dim; k++)
603  {
604  for (unsigned j = 0; j < nnode; j++)
605  {
606  // note that particle and nodal coupling forces are in opposite directions
607  // the negative sign on the FEM side is taken care of in by element
608  particleCouplingForces[i][k] += couplingMatrix[j][i] * nodalCouplingForces[j][k];
609  }
610  }
611  // add particle coupling forces to be used by actionsAfterTimeStep(...)
612  auto p = particles[i];
613  Vec3D cForce = Vec3D(particleCouplingForces[i][0],
614  particleCouplingForces[i][1],
615  particleCouplingForces[i][2]);
616  // if construct mapping with coarse graining, add elements' contribution to particle coupling forces
617  if (!useCGMapping())
618  {
619  p->setCouplingForce(cForce * Global_Physical_Variables::forceScale());
620  }
621  // otherwise, set particle coupling force since the operation is locally within each element
622  else
623  {
624  p->addCouplingForce(cForce * Global_Physical_Variables::forceScale());
625  }
626  }
627  // assign nodal coupling force to the element to be used by element::fill_in_contribution_to_residuals(...)
628  elem_pt->set_nodal_coupling_residual(nodalCouplingForces);
629  }
630  }
void computeNodalCouplingForces(VELEMENT *&elem_pt, const unsigned &nnode, const unsigned &dim, const Vector< Vector< double >> &nodalDisplDPM, Vector< Vector< double >> &nodalCouplingForces)
Definition: VCoupling.h:762
void getProjectionAndProjected(const DPMVCoupledElement &coupled_elem, Vector< Vector< double >> &couplingMatrix, Vector< Vector< double >> &nodalDisplDPM)
Definition: VCoupling.h:439
char char char int int * k
Definition: level2_impl.h:374
list nParticles
Definition: MergeRestartFiles.py:46
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References computeNodalCouplingForces(), getProjectionAndProjected(), i, j, k, listOfDPMVCoupledElements_, MergeRestartFiles::nParticles, p, and BaseCoupling< M, O >::useCGMapping().

Referenced by computeOneTimeStepForVCoupling().

◆ computeCouplingOnDPM()

void VolumeCoupling::computeCouplingOnDPM ( )
inline
722  {
723  // first loop over the coupled bulk elements
724  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
725  {
726  // get pointer to the bulk element
727  VELEMENT* elem_pt = coupled_elem.bulk_elem_pt;
728 
729  // get particles and the number of coupled particles in the bulk element
730  Vector<BaseParticle*> particles;
731  if (!useCGMapping())
732  { particles = coupled_elem.listOfCoupledParticles; }
733  else
734  { particles = coupled_elem.listOfCoupledParticlesExt; }
735  const unsigned nParticles = particles.size();
736 
737  // get number of nodes in the bulk element
738  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
739  const unsigned dim = elem_pt->dim();
740 
741  // loop over the particles
742  for (unsigned m = 0; m < nParticles; m++)
743  {
744  // get "residual" from the bulk element
745  Vec3D cForce;
746  for (unsigned l = 0; l < nnode; l++)
747  {
748  double coupling = elem_pt->getCouplingStiffness(m, l);
749  // get the nodal displacement
750  Vec3D force = coupling * Vec3D(elem_pt->nodal_position(0, l, 0) - elem_pt->nodal_position(1, l, 0),
751  elem_pt->nodal_position(0, l, 1) - elem_pt->nodal_position(1, l, 1),
752  elem_pt->nodal_position(0, l, 2) - elem_pt->nodal_position(1, l, 2));
753  // add contributions to the coupling force
754  cForce += force;
755  }
756  // add the second particle coupling force: penalty*\PI_{\alpha i}*V_{ij}*u_j
757  particles[m]->addCouplingForce(cForce * Global_Physical_Variables::forceScale());
758  }
759  }
760  }
int * m
Definition: level2_cplx_impl.h:294

References listOfDPMVCoupledElements_, m, MergeRestartFiles::nParticles, and BaseCoupling< M, O >::useCGMapping().

Referenced by computeOneTimeStepForVCoupling().

◆ computeCouplingOnFEM()

void VolumeCoupling::computeCouplingOnFEM ( )
inline
633  {
634  // first loop over the coupled bulk elements
635  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
636  {
637  // get pointer to the bulk element
638  VELEMENT* elem_pt = coupled_elem.bulk_elem_pt;
639 
640  // get particles and the number of coupled particles in the bulk element
641  Vector<BaseParticle*> particles;
642  if (!useCGMapping())
643  { particles = coupled_elem.listOfCoupledParticles; }
644  else
645  { particles = coupled_elem.listOfCoupledParticlesExt; }
646  const unsigned nParticles = particles.size();
647 
648  // get number of nodes in the bulk element
649  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
650  const unsigned dim = elem_pt->dim();
651 
652  // prepare projection matrix \Pi_{i,\alpha}
653  Vector<Vector<double>> couplingMatrix(nnode, Vector<double>(nParticles, 0.0));
654  // fill in the projection matrix of the coupled bulk element
655  getProjectionMatrix(coupled_elem, couplingMatrix);
656 
657  // prepare the coupled stiffness matrix of the bulk element, penalty*V_{ij}
658  Vector<Vector<double>> bulkStiffness(nnode, Vector<double>(nnode, 0.0));
659  // fill in the volume coupled stiffness matrix
660  getBulkStiffness(elem_pt, bulkStiffness);
661  // assign penalty*\Pi_{\alpha,i}*V_{i,j} to the VCoupled element
662  Vector<Vector<double>> couplingStiffness(nParticles, Vector<double>(nnode, 0.0));
663  for (unsigned m = 0; m < nParticles; m++)
664  {
665  for (unsigned j = 0; j < nnode; j++)
666  {
667  for (unsigned i = 0; i < nnode; i++)
668  {
669  couplingStiffness[m][j] += couplingMatrix[i][m] * bulkStiffness[i][j];
670  }
671  }
672  }
673  elem_pt->setCouplingStiffness(couplingStiffness);
674 
675  // prepare the coupling residual projected from the particles to the node
676  Vector<Vector<double>> nodalResidualDPM(nnode, Vector<double>(dim, 0.0));
677 
678  // get displacement u(t+dt) = v(t+0.5dt)*dt after integrateBeforeForceComputation(...)
679  for (unsigned m = 0; m < nParticles; m++)
680  {
681  Vec3D cForce;
682  for (unsigned l = 0; l < nnode; l++)
683  {
684  for (unsigned ll = 0; ll < nnode; ll++)
685  {
686  for (unsigned mm = 0; mm < nParticles; mm++)
687  {
688  // change finite element coupling stiffness into the DEM scale
689  cForce += couplingMatrix[l][m] * bulkStiffness[l][ll] *
690  Global_Physical_Variables::stiffScale() * couplingMatrix[ll][mm] *
691  (particles[mm]->getPosition() - particles[mm]->getPreviousPosition());
692  }
693  }
694  }
695  // add the first particle coupling force: -penalty*\PI_{\alpha i}*V_{ij}*\PI_{j \beta}*u_\beta
696  particles[m]->addCouplingForce(-cForce);
697  }
698  // compute the residual projected from the particles to the nodes
699  for (unsigned i = 0; i < nnode; i++)
700  {
701  for (unsigned j = 0; j < nnode; j++)
702  {
703  for (unsigned m = 0; m < nParticles; m++)
704  {
705  Vec3D displ = (particles[m]->getPosition() - particles[m]->getPreviousPosition()) / Global_Physical_Variables::lenScale;
706  double particleStiffness = bulkStiffness[i][j] * couplingMatrix[j][m];
707  nodalResidualDPM[i][0] -= particleStiffness * displ.getX();
708  nodalResidualDPM[i][1] -= particleStiffness * displ.getY();
709  nodalResidualDPM[i][2] -= particleStiffness * displ.getZ();
710  }
711  }
712  }
713  // assign residual to the coupled bulk element to be used by element::fill_in_contribution_to_residuals(...)
714  elem_pt->set_nodal_coupling_residual(nodalResidualDPM);
715 
716  // assign Jacobian to the coupled bulk element to be used by element::fill_in_contribution_to_residuals(...)
717  elem_pt->set_nodal_coupling_jacobian(bulkStiffness);
718  }
719  }
void getProjectionMatrix(const DPMVCoupledElement &coupled_elem, Vector< Vector< double >> &couplingMatrix)
Definition: VCoupling.h:479
void getBulkStiffness(VELEMENT *&elem_pt, Vector< Vector< double >> &bulkStiffness)
Definition: VCoupling.h:811

References getBulkStiffness(), getProjectionMatrix(), Vec3D::getX(), Vec3D::getY(), Vec3D::getZ(), i, j, Global_Physical_Variables::lenScale, listOfDPMVCoupledElements_, m, MergeRestartFiles::nParticles, and BaseCoupling< M, O >::useCGMapping().

Referenced by computeOneTimeStepForVCoupling().

◆ computeExternalForces()

void VolumeCoupling::computeExternalForces ( BaseParticle CI)
inlineoverride

Override computeExternalForces to add the vcoupling forces

45  {
46  //Checks that the current particle is not "fixed"
47  //and hence infinitely massive!
48  if (!CI->isFixed())
49  {
50  // Applying the force due to bodyForce_fct (F = m.g)
51  CI->addForce(getGravity() * CI->getMass());
52  // add particle coupling force 1/w_i*f_i^c to the total force
53  CI->addForce(CI->getCouplingForce());
54  }
55  }
void addForce(const Vec3D &addForce)
Adds an amount to the force on this BaseInteractable.
Definition: BaseInteractable.cc:94
bool isFixed() const override
Is fixed Particle function. It returns whether a Particle is fixed or not, by checking its inverse Ma...
Definition: BaseParticle.h:72
Mdouble getMass() const
Returns the particle's mass.
Definition: BaseParticle.h:305

References BaseInteractable::addForce(), BaseParticle::getMass(), and BaseParticle::isFixed().

◆ computeNodalCouplingForces()

void VolumeCoupling::computeNodalCouplingForces ( VELEMENT *&  elem_pt,
const unsigned nnode,
const unsigned dim,
const Vector< Vector< double >> &  nodalDisplDPM,
Vector< Vector< double >> &  nodalCouplingForces 
)
inline
765  {
766  // get the difference between nodal displacement from FEM and projected ones from DPM
767  Vector<Vector<double>> nodalDisplDiff(nnode, Vector<double>(dim, 0));
768  for (unsigned l = 0; l < nnode; l++)
769  {
770  for (unsigned i = 0; i < dim; i++)
771  {
772  double displFEM = elem_pt->nodal_position(0, l, i) - elem_pt->nodal_position(1, l, i);
773  double displDPM = nodalDisplDPM[l][i];
774  nodalDisplDiff[l][i] = displDPM - displFEM;
775  }
776  }
777  // Set up memory for the shape functions
778  Shape psi(nnode);
779  DShape dpsidxi(nnode, dim);
780  const unsigned n_intpt = elem_pt->integral_pt()->nweight();
781  // Loop over the integration points
782  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
783  {
784  // Get the integral weight
785  double w = elem_pt->integral_pt()->weight(ipt);
786  // Call the derivatives of the shape functions (and get Jacobian)
787  double J = elem_pt->dshape_lagrangian_at_knot(ipt, psi, dpsidxi);
788  // Loop over the test functions, nodes of the element
789  for (unsigned l = 0; l < nnode; l++)
790  {
791  // Loop over the nodes of the element again
792  for (unsigned ll = 0; ll < nnode; ll++)
793  {
794  double vol = Global_Physical_Variables::penalty * psi(ll) * psi(l) * w * J;
795  /*
796  for (unsigned i=0; i<dim; i++)
797  {
798  vol += Global_Physical_Variables::penalty*2*Global_Physical_Variables::L/3.0 * dpsidxi(ll,i)*dpsidxi(l,i)*w*J;
799  }
800  */
801  for (unsigned i = 0; i < dim; i++)
802  {
803  nodalCouplingForces[l][i] += -vol * nodalDisplDiff[l][i];
804  }
805  }
806  }
807  }
808  }
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
RowVector3d w
Definition: Matrix_resize_int.cpp:3

References i, J, and w.

Referenced by computeCouplingForce().

◆ computeOneTimeStepForVCoupling()

void VolumeCoupling::computeOneTimeStepForVCoupling ( const unsigned nstep)
inline
159  {
162  // setNodalWeightOnCubicMesh();
165  if (explicit_)
166  {
168  solve();
169  solveMercury(nstep);
170  }
171  else
172  {
175  solveOomph();
178  solveMercury(nstep - 1);
179  }
180  }
void solveOomph(int max_adapt=0)
Definition: BaseCoupling.h:120
void solveMercury(unsigned long nt)
Definition: BaseCoupling.h:149
void setNodalWeightByDistance()
Definition: VCoupling.h:394
void computeCouplingForce()
Definition: VCoupling.h:572
void computeCouplingOnDPM()
Definition: VCoupling.h:721
void solveFirstHalfTimeStep()
Definition: VCoupling.h:185
void checkParticlesInFiniteElems()
Definition: VCoupling.h:261
bool explicit_
Definition: VCoupling.h:966
void computeCouplingOnFEM()
Definition: VCoupling.h:632
void solveSecondHalfTimeStep()
Definition: VCoupling.h:233
void computeWeightOnParticles()
Definition: VCoupling.h:884
Update the problem specs before solve
Definition: steady_axisym_advection_diffusion.cc:353

References checkParticlesInFiniteElems(), computeCouplingForce(), computeCouplingOnDPM(), computeCouplingOnFEM(), computeWeightOnParticles(), explicit_, listOfDPMVCoupledElements_, setNodalWeightByDistance(), solve, solveFirstHalfTimeStep(), BaseCoupling< M, O >::solveMercury(), BaseCoupling< M, O >::solveOomph(), and solveSecondHalfTimeStep().

Referenced by solveVolumeCoupling().

◆ computeWeightOnParticles()

void VolumeCoupling::computeWeightOnParticles ( )
inline
885  {
886  // first loop over the coupled bulk elements
887  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
888  {
889  // get pointer to the bulk element
890  VELEMENT* elem_pt = coupled_elem.bulk_elem_pt;
891  // Find out how many nodes there are
892  const unsigned n_node = elem_pt->nnode();
893  // Set up memory for the shape/test functions
894  Shape psi(n_node);
895  // loop over the particles in the bulk element
896  for (unsigned i = 0; i < coupled_elem.listOfCoupledParticles.size(); i++)
897  {
898  auto shapes = coupled_elem.listOfShapesAtParticleCenters[i];
899  // Compute weight at particle center
900  double weightAtCenter = 0;
901  for (unsigned l = 0; l < n_node; l++)
902  {
903  CoupledSolidNode* node_pt = dynamic_cast<CoupledSolidNode*>(elem_pt->node_pt(l));
904  weightAtCenter += shapes[l] * node_pt->get_coupling_weight();
905  }
906  double invWeightAtCenter = 1.0 / weightAtCenter;
907 
908  // get point to particle i in the coupled bulk element and set the coupling weight
909  auto p = coupled_elem.listOfCoupledParticles[i];
910  p->setInvCouplingWeight(invWeightAtCenter);
911 
912  // skip particle i if no interactions
913  if (p->getInteractions().size() == 0) continue;
914 
915  if (explicit_)
916  {
917  // loop over interactions with particle i (FIXME accessing coupled interactions is n squared...)
918  for (auto inter : p->getInteractions())
919  {
920  // skip if the coupling weight is already computed
921  if (inter->isCoupled())
922  { continue; }
923  else
924  {
925  // check if a contact point resides within the bulk element
926  Vector<double> s(3, 0.0), x(3, 0.0);
927  GeomObject* geom_obj_pt = 0;
928  // get global coordinates of contact point (DPM)
929  Vec3D xc = inter->getContactPoint();
931  x[0] = xc.getX();
932  x[1] = xc.getY();
933  x[2] = xc.getZ();
934  // get local coordinates of contact point (FEM)
935  elem_pt->locate_zeta(x, geom_obj_pt, s);
936  // if true compute weight at contact point
937  if (geom_obj_pt != nullptr)
938  {
939  // Get shape/test functions
940  elem_pt->shape(s, psi);
941  double weightAtContactPoint = 0;
942  for (unsigned l = 0; l < n_node; l++)
943  {
944  CoupledSolidNode* node_pt = dynamic_cast<CoupledSolidNode*>(elem_pt->node_pt(l));
945  weightAtContactPoint += node_pt->get_coupling_weight() * psi(l);
946  }
947  inter->setCouplingWeight(weightAtContactPoint);
948  inter->setCoupled();
949  }
950  }
951  }
952  }
953  }
954  }
955  }
xc
Definition: MultiOpt.py:46

References explicit_, i, Global_Physical_Variables::lenScale, listOfDPMVCoupledElements_, p, s, plotDoE::x, and MultiOpt::xc.

Referenced by computeOneTimeStepForVCoupling().

◆ getBulkStiffness()

void VolumeCoupling::getBulkStiffness ( VELEMENT *&  elem_pt,
Vector< Vector< double >> &  bulkStiffness 
)
inline
812  {
813  // get number of nodes in the bulk element
814  const unsigned nnode = elem_pt->nnode();
815  // get dimension of the problem
816  const unsigned dim = elem_pt->dim();
817  // Set up memory for the shape functions
818  Shape psi(nnode);
819  DShape dpsidxi(nnode, dim);
820  const unsigned n_intpt = elem_pt->integral_pt()->nweight();
821  // Loop over the integration points
822  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
823  {
824  // Get the integral weight
825  double w = elem_pt->integral_pt()->weight(ipt);
826  // Call the derivatives of the shape functions (and get Jacobian)
827  double J = elem_pt->dshape_lagrangian_at_knot(ipt, psi, dpsidxi);
828  // Loop over the test functions, nodes of the element
829  for (unsigned l = 0; l < nnode; l++)
830  {
831  // Loop over the nodes of the element again
832  for (unsigned ll = 0; ll < nnode; ll++)
833  {
834  bulkStiffness[l][ll] += Global_Physical_Variables::penalty * psi(l) * psi(ll) * w * J;
835  }
836  }
837  }
838  }

References J, and w.

Referenced by computeCouplingOnFEM().

◆ getInvCoupledMassPerTime()

void VolumeCoupling::getInvCoupledMassPerTime ( const DPMVCoupledElement elem,
const Vector< Vector< double >> &  couplingMatrix,
const Vector< Vector< double >> &  bulkStiffness,
Vector< double > &  invCMassPerTime 
)
inline
842  {
843  // get number of nodes in the bulk element
844  const unsigned nnode = bulkStiffness.size();
845  // get number of coupled particles in the bulk element
846  const unsigned nParticles = invCMassPerTime.size();
847  // get coupled particles in the bulk element
848  Vector<BaseParticle*> particles;
849  if (!useCGMapping())
850  { particles = elem.listOfCoupledParticles; }
851  else
852  { particles = elem.listOfCoupledParticlesExt; }
853  // loop over the particles
854  for (unsigned m = 0; m < nParticles; m++)
855  {
856  // get particle mass
857  double particleMass = particles[m]->getMass() / particles[m]->getInvCouplingWeight();
858  // initialize additional coupling mass from the bulk element
859  double cMassPerTimeSquared = 0.0;
860  // loop over the nodes
861  for (unsigned l = 0; l < nnode; l++)
862  {
863  // loop over the nodes again
864  for (unsigned ll = 0; ll < nnode; ll++)
865  {
866  // add contributions to the coupling stiffness or mass over time squared
867  cMassPerTimeSquared += couplingMatrix[l][m] * bulkStiffness[l][ll] * couplingMatrix[ll][m];
868  }
869  }
870  cMassPerTimeSquared *= 0.5;
871  // add coupling mass to the particle (in the DPM scale)
872  double cMass = cMassPerTimeSquared * Global_Physical_Variables::stiffScale() * pow(getTimeStep(), 2);
873  particles[m]->setCouplingMass(cMass);
874  // set coupling mass/time only along the diagonal (lumped version)
875  double scale = Global_Physical_Variables::massScale() / Global_Physical_Variables::timeScale;
876  double oomph_dt = time_pt()->dt(0);
877  invCMassPerTime[m] = 1.0 / ( particleMass / getTimeStep() / scale + cMassPerTimeSquared * oomph_dt );
878  }
879  }
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
double timeScale
Time scale.
Definition: VCoupledElement.h:13

References VolumeCoupling::DPMVCoupledElement::listOfCoupledParticles, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticlesExt, m, MergeRestartFiles::nParticles, Eigen::bfloat16_impl::pow(), Global_Physical_Variables::timeScale, and BaseCoupling< M, O >::useCGMapping().

◆ getProjectionAndProjected()

void VolumeCoupling::getProjectionAndProjected ( const DPMVCoupledElement coupled_elem,
Vector< Vector< double >> &  couplingMatrix,
Vector< Vector< double >> &  nodalDisplDPM 
)
inline
441  {
442  // get coupled particles in the bulk element
443  Vector<BaseParticle*> particles;
444  if (!useCGMapping())
445  { particles = coupled_elem.listOfCoupledParticles; }
446  else
447  { particles = coupled_elem.listOfCoupledParticlesExt; }
448  // get number of coupled particles in the bulk element
449  const unsigned nParticles = particles.size();
450  // get nodal coordinates of the bulk element
451  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
452  // get dimension of the problem
453  const unsigned dim = coupled_elem.bulk_elem_pt->dim();
454  // prepare vector of particle displacement
455  Vector<Vector<double>> particleDispl(nParticles, Vector<double>(dim, 0));
456  // fill in the projection matrix of the coupled bulk element
457  getProjectionMatrix(coupled_elem, couplingMatrix);
458  // get particle displacements
459  for (unsigned m = 0; m < nParticles; m++)
460  {
461  Vec3D displ = (particles[m]->getPosition() - particles[m]->getPreviousPosition()) / Global_Physical_Variables::lenScale;
462  particleDispl[m][0] = displ.getX();
463  particleDispl[m][1] = displ.getY();
464  particleDispl[m][2] = displ.getZ();
465  }
466  // get projected nodal displacement field from particle displacement at the center
467  for (unsigned i = 0; i < nnode; i++)
468  {
469  for (unsigned k = 0; k < dim; k++)
470  {
471  for (unsigned j = 0; j < nParticles; j++)
472  {
473  nodalDisplDPM[i][k] += couplingMatrix[i][j] * particleDispl[j][k];
474  }
475  }
476  }
477  }

References VolumeCoupling::DPMVCoupledElement::bulk_elem_pt, getProjectionMatrix(), Vec3D::getX(), Vec3D::getY(), Vec3D::getZ(), i, j, k, Global_Physical_Variables::lenScale, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticles, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticlesExt, m, MergeRestartFiles::nParticles, and BaseCoupling< M, O >::useCGMapping().

Referenced by computeCouplingForce().

◆ getProjectionMatrix()

void VolumeCoupling::getProjectionMatrix ( const DPMVCoupledElement coupled_elem,
Vector< Vector< double >> &  couplingMatrix 
)
inline
480  {
481  // get number of coupled particles in the bulk element
482  const unsigned nParticles = couplingMatrix[0].size();
483  // get nodal coordinates of the bulk element
484  const unsigned nnode = couplingMatrix.size();
485  const unsigned dim = coupled_elem.bulk_elem_pt->dim();
486  // if construct mapping with FEM basis functions
487  if (!useCGMapping())
488  {
489  // loop over shape functions at the nodes
490  for (unsigned l = 0; l < nnode; l++)
491  {
492  double sum = 0;
493  // loop over shape functions at the particles
494  for (unsigned m = 0; m < nParticles; m++)
495  {
496  // get the l-th shape function evaluated at the center of particle m
497  double shape = coupled_elem.listOfShapesAtParticleCenters[m][l];
498  // shape function weighted by particle volume N_{l,m}*V_m
499  shape *= coupled_elem.listOfCoupledParticles[m]->getVolume();
500  couplingMatrix[l][m] = shape;
501  sum += shape;
502  }
503  // normalize each row of the projection matrix to sum to one
504  for (unsigned m = 0; m < nParticles; m++)
505  {
506  // projection rule defined as N_{l,m}*V_m / sum_m N_{l,m}*V_m
507  if (sum != 0)
508  { couplingMatrix[l][m] /= sum; }
509  }
510  }
511  }
512  else
513  {
514  // set up memory for the shape functions
515  Shape psi(nnode);
516  // set up memory for the local and global coordinates
517  Vector<double> s(dim), x(dim);
518  // get the element pointer
519  auto el_pt = coupled_elem.bulk_elem_pt;
520  // get the number of integration points
521  const unsigned n_intpt = el_pt->integral_pt()->nweight();
522  // loop over the integration points
523  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
524  {
525  // get the integral weight
526  double w = el_pt->integral_pt()->weight(ipt);
527  // find the shape functions at the integration points r_i
528  el_pt->shape_at_knot(ipt, psi);
529  // get the value of the local coordinates at the integration point
530  for (unsigned i = 0; i < dim; i++)
531  { s[i] = el_pt->integral_pt()->knot(ipt, i); }
532  // get the value of the global coordinates at the integration point
533  el_pt->interpolated_x(s, x);
534  // loop over the nodes
535  for (unsigned l = 0; l < nnode; l++)
536  {
537  // loop over shape functions at the particles
538  for (unsigned m = 0; m < nParticles; m++)
539  {
540  // set CG coordinates
541  CGCoordinates::XYZ coord;
542  coord.setXYZ(Vec3D(x[0], x[1], x[2]));
543  // evaluate the value of CG function around particle m at CGcoords \phi(\vec r_i-r_m)
544  double phi = getCGFunction().evaluateCGFunction(
545  coupled_elem.listOfCoupledParticlesExt[m]->getPosition() /
547  // CG mapping defined as \tilde{N_{l,m}}_ipt = w_ipt * \phi(\vec r_i-r_m) * N_l(r_i)
548  double shape = w * phi * psi(l);
549  // CG mapping weighted by particle volume \tilde{N_{l,m}}*V_m
550  shape *= coupled_elem.listOfCoupledParticlesExt[m]->getVolume();
551  // sum over the integration points
552  couplingMatrix[l][m] += shape;
553  }
554  }
555  }
556  // normalize each row of the projection matrix to sum to one
557  for (unsigned l = 0; l < nnode; l++)
558  {
559  double sum = 0;
560  for (unsigned m = 0; m < nParticles; m++)
561  { sum += couplingMatrix[l][m]; }
562  for (unsigned m = 0; m < nParticles; m++)
563  {
564  // projection rule defined as \tilde{N_{l,m}}*V_m / sum_m \tilde{N_{l,m}}*V_m
565  if (sum != 0)
566  { couplingMatrix[l][m] /= sum; }
567  }
568  }
569  }
570  }
CGFunctions::LucyXYZ getCGFunction()
Definition: BaseCoupling.h:183
Defines the position of the CGPoint, in the non-averaged directions, i.e. all directions on which spa...
Definition: XYZ.h:59
void setXYZ(Vec3D p)
Returns the position of the current CGPoint, in the non-averaged directions.
Definition: XYZ.cc:64
Mdouble evaluateCGFunction(const Vec3D &position, const Coordinates &r)
Evaluates the coarse-graining function.
void shape(const double &s, double *Psi)
Definition: shape.h:564

References VolumeCoupling::DPMVCoupledElement::bulk_elem_pt, CGFunctions::Polynomial< Coordinates >::evaluateCGFunction(), BaseCoupling< M, O >::getCGFunction(), i, Global_Physical_Variables::lenScale, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticles, VolumeCoupling::DPMVCoupledElement::listOfCoupledParticlesExt, VolumeCoupling::DPMVCoupledElement::listOfShapesAtParticleCenters, m, MergeRestartFiles::nParticles, s, CGCoordinates::XYZ::setXYZ(), oomph::OneDimLagrange::shape(), BaseCoupling< M, O >::useCGMapping(), w, and plotDoE::x.

Referenced by computeCouplingOnFEM(), and getProjectionAndProjected().

◆ setExplicit()

void VolumeCoupling::setExplicit ( const bool flag)
inline
958  { explicit_ = flag; }

References explicit_.

Referenced by VolumeCoupling().

◆ setNodalWeightByDistance()

void VolumeCoupling::setNodalWeightByDistance ( )
inline

used in computeOneTimeStepForVCoupling (VolumeCoupling)

assign coupling weight to coupled solid nodes implicit volume coupling allows the minimal coupling weight to be very small e.g. double weightMin = 0.1 for the explicit volume coupling scheme

395  {
396  unsigned direction = 1;
397  // store the position[direction] of all coupled nodes in a vector
398  Vector<double> listOfPos;
399  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
400  {
401  // get pointers to all nodes of the bulk element
402  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
403  for (unsigned n = 0; n < nnode; n++)
404  {
405  CoupledSolidNode* node_pt = dynamic_cast<CoupledSolidNode*>(coupled_elem.bulk_elem_pt->node_pt(n));
406  listOfPos.push_back(node_pt->x(direction));
407  }
408  }
409  // get the minimum and maximum coordinates[direction]
410  auto posMin = *min_element(listOfPos.begin(), listOfPos.end());
411  auto posMax = *max_element(listOfPos.begin(), listOfPos.end());
417  double weightMax = 1.0 - weightMin_;
418  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
419  {
420  // get pointers to all nodes of the bulk element
421  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
422  for (unsigned n = 0; n < nnode; n++)
423  {
424  CoupledSolidNode* node_pt = dynamic_cast<CoupledSolidNode*>(coupled_elem.bulk_elem_pt->node_pt(n));
425  // assign nodal coupling weight using a linear function of distance
426  double weight = weightMin_
427  + ( weightMax - weightMin_ ) / ( posMax - posMin ) * ( node_pt->x(direction) - posMin );
428  // // assign nodal coupling weight using a cosine function of distance
429  // double amp = 0.5*(weightMax - weightMin_);
430  // double omega = M_PI/(posMax-posMin);
431  // double weight = weightMin_ + amp - amp*cos(omega*(node_pt->x(direction)-posMin));
432  node_pt->set_coupling_weight(weight);
433  // cout << "Set weight to " << node_pt->get_coupling_weight();
434  // cout << " at a distance of " << node_pt->x(direction)-posMin <<endl;
435  }
436  }
437  }

References listOfDPMVCoupledElements_, n, and weightMin_.

Referenced by computeOneTimeStepForVCoupling().

◆ setNodalWeightOnCubicMesh()

void VolumeCoupling::setNodalWeightOnCubicMesh ( )
inline

VolumeCoupling: setNodalWeightOnCubicMesh

358  {
359  // get a full list of all nodes that are coupled
360  Vector<CoupledSolidNode*> listOfSolidNodes;
361  for (DPMVCoupledElement coupled_elem : listOfDPMVCoupledElements_)
362  {
363  // get pointers to all nodes of the bulk element
364  const unsigned nnode = coupled_elem.bulk_elem_pt->nnode();
365  for (unsigned n = 0; n < nnode; n++)
366  {
367  CoupledSolidNode* node_pt = dynamic_cast<CoupledSolidNode*>(coupled_elem.bulk_elem_pt->node_pt(n));
368  // if it is not a boundary node, add it to the list
369  if (!node_pt->is_on_boundary())
370  {
371  listOfSolidNodes.push_back(node_pt);
372  }
373  // set nodal weights to one if it is a boundary node
374  else
375  { node_pt->set_coupling_weight(0.5); }
376  }
377  }
378  // count number of occurrences of a node and set nodal weights
379  for (CoupledSolidNode* node_pt : listOfSolidNodes)
380  {
381  unsigned n = count(listOfSolidNodes.begin(), listOfSolidNodes.end(), node_pt);
382  if (n == pow(2, getSystemDimensions()))
383  { node_pt->set_coupling_weight(0.5); }
384  else
385  { node_pt->set_coupling_weight(0.5); }
386  // cout << "The solid node " << node_pt << " is shared by " << n << " coupled elements. ";
387  // cout << "Set weight to " << node_pt->get_coupling_weight() << endl;
388  }
389  }

References listOfDPMVCoupledElements_, n, and Eigen::bfloat16_impl::pow().

◆ solveFirstHalfTimeStep()

void VolumeCoupling::solveFirstHalfTimeStep ( )
inline

Used in OomphMercuryCoupling::computeOneTimeStepForVCoupling to do the actions before time step

Todo:
MX: this is not true anymore. all boundaries are handled here. particles have received a position update, so here the deletion boundary deletes particles \TODO add particles need a periodic check
Bug:
{In chute particles are added in actions_before_time_set(), however they are not written to the xballs data yet, but can have a collision and be written to the fstat data}
186  {
187  logger(DEBUG, "starting solveHalfTimeStep()");
188 
189  logger(DEBUG, "about to call writeOutputFiles()");
190  writeOutputFiles(); //everything is written at the beginning of the time step!
191 
192  logger(DEBUG, "about to call hGridActionsBeforeIntegration()");
193  hGridActionsBeforeIntegration();
194 
195  //Computes the half-time step velocity and full time step position and updates the particles accordingly
196  logger(DEBUG, "about to call integrateBeforeForceComputation()");
197  integrateBeforeForceComputation();
198  //New positions require the MPI and parallel periodic boundaries to do things
199  logger(DEBUG, "about to call performGhostParticleUpdate()");
200  performGhostParticleUpdate();
201 
205 
206  logger(DEBUG, "about to call checkInteractionWithBoundaries()");
207  checkInteractionWithBoundaries(); // INSERTION boundaries handled
208 
209  logger(DEBUG, "about to call hGridActionsAfterIntegration()");
210  hGridActionsAfterIntegration();
211 
212  // Compute forces
214  // INSERTION/DELETION boundary flag change
215  for (BaseBoundary* b : boundaryHandler)
216  {
217  b->checkBoundaryBeforeTimeStep(this);
218  }
219 
220  logger(DEBUG, "about to call actionsBeforeTimeStep()");
221  actionsBeforeTimeStep();
222 
223  logger(DEBUG, "about to call checkAndDuplicatePeriodicParticles()");
224  checkAndDuplicatePeriodicParticles();
225 
226  logger(DEBUG, "about to call hGridActionsBeforeTimeStep()");
227  hGridActionsBeforeTimeStep();
228  }
@ DEBUG
Scalar * b
Definition: benchVecAdd.cpp:17
Definition: BaseBoundary.h:28

References b, DEBUG, and logger.

Referenced by computeOneTimeStepForVCoupling().

◆ solveSecondHalfTimeStep()

void VolumeCoupling::solveSecondHalfTimeStep ( )
inline

Used in OomphMercuryCoupling::computeOneTimeStepForVCoupling to do the actions after time step

234  {
235  //Creates and updates interactions and computes forces based on these
236  logger(DEBUG, "about to call computeAllForces()");
237  computeAllForces();
238 
239  logger(DEBUG, "about to call removeDuplicatePeriodicParticles()");
240  removeDuplicatePeriodicParticles();
241 
242  //Computes new velocities and updates the particles accordingly
243  logger(DEBUG, "about to call integrateAfterForceComputation()");
244  integrateAfterForceComputation();
245 
246  logger(DEBUG, "about to call actionsAfterTimeStep()");
248 
249  //erase interactions that have not been used during the last time step
250  logger(DEBUG, "about to call interactionHandler.eraseOldInteractions(getNumberOfTimeSteps())");
251  interactionHandler.eraseOldInteractions(getNumberOfTimeSteps());
252  logger(DEBUG, "about to call interactionHandler.actionsAfterTimeStep()");
253  interactionHandler.actionsAfterTimeStep();
254  particleHandler.actionsAfterTimeStep();
255 
256  continueInTime();
257 
258  logger(DEBUG, "finished computeOneTimeStep()");
259  }
void actionsAfterTimeStep() override
Definition: VCoupling.h:61

References actionsAfterTimeStep(), DEBUG, and logger.

Referenced by computeOneTimeStepForVCoupling().

◆ solveVolumeCoupling() [1/2]

void VolumeCoupling::solveVolumeCoupling ( )
inline
118  {
119  initialiseSolve();
120 
121  // get the time step of mercuryProb
122  double mercury_dt = getTimeStep();
123  /*
124  // %TODO use the DPM time scale to non-dimensionalise the OomphProblem<SELEMENT,TIMESTEPPER>?
125  Global_Physical_Variables::timeScale = mercury_dt;
126  */
127 
128  /* // get number of mercury-steps per Oomph-step (critical time step = intrinsic_time or from_eigen)
129  double oomph_dt = 0.2*Global_Physical_Variables::intrinsic_time;
130  double oomph_dt = 0.2*OomphProblem::get_critical_timestep_from_eigen();
131  unsigned nstep = unsigned(floor(oomph_dt/mercury_dt));
132  */
133  unsigned nstep = 1;
134  double oomph_dt = nstep * mercury_dt;
135 
136  // setup initial conditions
137  OomphProblem::set_initial_conditions(oomph_dt);
138  // MercuryBeam::set_initial_conditions();
139 
140  // This is the main loop over advancing time
141  unsigned nDone = 0;
142  while (getTime() < getTimeMax())
143  {
144  // solve the coupled problem for one time step
146  // write outputs of the oomphProb
147  if (getVtkWriter()->getFileCounter() > nDone)
148  {
149  OomphProblem::doc_solution();
150  nDone = getVtkWriter()->getFileCounter();
151  }
152  }
153  // close output files of mercuryProb
154  finaliseSolve();
155  }
void computeOneTimeStepForVCoupling(const unsigned &nstep)
Definition: VCoupling.h:158

References computeOneTimeStepForVCoupling().

Referenced by solveVolumeCoupling().

◆ solveVolumeCoupling() [2/2]

void VolumeCoupling::solveVolumeCoupling ( const double width)
inline
109  {
110  // set the coarse-grainning width w.r.t. length scale
111  setCGWidth(width * particleHandler.getLargestParticle()->getRadius());
112  // solve volume coupled OomphMercuryProblem
114  }
void setCGWidth(const double &width)
Definition: BaseCoupling.h:157
void solveVolumeCoupling()
Definition: VCoupling.h:117

References BaseCoupling< M, O >::setCGWidth(), and solveVolumeCoupling().

Member Data Documentation

◆ explicit_

bool VolumeCoupling::explicit_ = false
private

◆ listOfDPMVCoupledElements_

◆ weightMin_

double VolumeCoupling::weightMin_ = 0.0
private

The documentation for this class was generated from the following file: