26 #ifndef SURFACE_COUPLING_H
27 #define SURFACE_COUPLING_H
33 using namespace oomph;
35 template<
class M,
class O>
75 unsigned nStep = O::getOomphTimeStep()/M::getTimeStep();
78 logger(
INFO,
"Set nStep %, change mercuryTimeStep from % to %",
79 nStep, M::getTimeStep(), O::getOomphTimeStep());
81 M::setTimeStep(O::getOomphTimeStep());
83 logger(
INFO,
"Set nStep %, change oomphTimeStep from % to %",
84 nStep, O::getOomphTimeStep(), nStep * M::getTimeStep());
85 O::setOomphTimeStep(nStep * M::getTimeStep());
89 solveSurfaceCoupling(nStep);
96 logger.assert_always(O::getOomphTimeStep()>0,
"Oomph time step not initialised");
97 logger.assert_always(M::getTimeStep()>0,
"Mercury time step not initialised");
99 logger.assert_always(!coupledBoundaries_.empty(),
"isCoupled needs to be set, e.g. via setIsCoupled([](unsigned b) { return b == Boundary::Y_MIN; })");
102 M::initialiseSolve();
105 double mercury_dt = M::getTimeStep();
106 logger(
INFO,
"Mercury time step: %", mercury_dt);
109 double oomph_dt = nStep * mercury_dt;
113 O::assign_initial_values_impulsive(oomph_dt);
116 logger(
INFO,
"Set up oomph mesh: % elements (% with traction)",
117 O::solid_mesh_pt()?O::solid_mesh_pt()->nelement():0, O::traction_mesh_pt()?O::traction_mesh_pt()->nelement():0);
120 getSCoupledElements();
123 createDPMWallsFromFiniteElems();
127 while (M::getTime() < M::getTimeMax())
129 this->actionsBeforeOomphTimeStep();
131 computeOneTimeStepForSCoupling(nStep);
133 if (M::getParticlesWriteVTK() && M::getVtkWriter()->getFileCounter() > nDone)
136 nDone = M::getVtkWriter()->getFileCounter();
148 O::initialiseSolve();
149 logger.assert_always(!coupledBoundaries_.empty(),
"isCoupled needs to be set, e.g. via setIsCoupled([](unsigned b) { return b == Boundary::Y_MIN; })");
152 double mercury_dt = M::getTimeStep();
153 logger(
INFO,
"Mercury time step: %", mercury_dt);
159 O::set_initial_conditions(0);
162 logger(
INFO,
"Set up oomph mesh: % elements (% with traction)",
163 O::solid_mesh_pt()?O::solid_mesh_pt()->nelement():0, O::traction_mesh_pt()?O::traction_mesh_pt()->nelement():0);
166 getSCoupledElements();
169 createDPMWallsFromFiniteElems();
173 while (M::getTime() < M::getTimeMax())
175 O::actionsBeforeOomphTimeStep();
176 M::computeOneTimeStep();
195 auto species = M::speciesHandler.getObject(0);
199 auto w = M::wallHandler.copyAndAddObject(wall);
210 double time0 = M::getTime();
211 double dTime = O::getOomphTimeStep();
213 std::array<Vec3D,3> dVertex = {
214 vertex[0] - vertex0[0],
215 vertex[1] - vertex0[1],
216 vertex[2] - vertex0[2]};
218 double f = ( time - time0 ) / dTime;
219 std::array<Vec3D, 3> vertex = {
220 vertex0[0] + dVertex[0] * f,
221 vertex0[1] + dVertex[1] * f,
222 vertex0[2] + dVertex[2] * f };
223 wall->
setVertices( vertex[0], vertex[1], vertex[2] );
227 Vec3D velocity = (dVertex[0]+dVertex[1]+dVertex[2])/3./dTime;
239 auto t0 = std::chrono::system_clock::now();
240 updateDPMWallsFromFiniteElems();
241 auto t1 = std::chrono::system_clock::now();
243 auto t2 = std::chrono::system_clock::now();
244 updateTractionOnFiniteElems();
245 auto t3 = std::chrono::system_clock::now();
247 auto t4 = std::chrono::system_clock::now();
248 if (logSurfaceCoupling)
logger(
INFO,
"time % Elapsed time: FEM->DEM %, DEM %, DEM->FEM %, FEM %", M::getTime(),
249 (t1-t0).count(), (t2-t1).count(), (t3-t2).count(), (t4-t3).count());
255 for (
auto sCoupledElement : sCoupledElements_)
258 Vector<Vector<double*> > position_pt = sCoupledElement.surface_node_position_pt;
260 swap(position_pt[2], position_pt[3]);
264 Vector<double> x(3, 0.0);
265 sCoupledElement.bulk_elem_pt->interpolated_x(sCoupledElement.center_local, x);
271 const unsigned nTriangles = position_pt.size();
273 while (
n < nTriangles)
276 std::array<Vec3D, 3> vertex;
280 vertex[1] =
Vec3D(*position_pt[0][0],*position_pt[0][1],*position_pt[0][2]);
281 vertex[2] =
Vec3D(*position_pt[1][0],*position_pt[1][1],*position_pt[1][2]);
285 triangleWalls_.push_back(w);
288 rotate(position_pt.begin(), position_pt.begin() + 1, position_pt.end());
298 for (
auto sCoupledElement : sCoupledElements_)
301 Vector<Vector<double*> > position_pt = sCoupledElement.surface_node_position_pt;
302 Vector<CoupledSolidNode*> node_pt = sCoupledElement.node_pt;
306 swap(position_pt[2], position_pt[3]);
309 Vector<double> x(3, 0.0);
310 sCoupledElement.bulk_elem_pt->interpolated_x(sCoupledElement.center_local, x);
311 Vec3D center {x[0], x[1], x[2]};
314 const unsigned nTriangles = position_pt.size();
316 while (
n < nTriangles)
319 std::array<Vec3D, 3> vertex;
323 vertex[1] =
Vec3D(*position_pt[0][0],
325 *position_pt[0][2]);;
326 vertex[2] =
Vec3D(*position_pt[1][0],
331 updateTriangleWall(triangleWalls_[wallID], vertex);
334 rotate(position_pt.begin(), position_pt.begin() + 1, position_pt.end());
335 rotate(node_pt.begin(), node_pt.begin() + 1, node_pt.end());
354 for (
auto sCoupledElement : sCoupledElements_)
357 Vector<Vector<double> > nodalCouplingForces;
359 bool elemIsCoupled = computeSCouplingForcesFromTriangles(sCoupledElement.bulk_elem_pt,
360 sCoupledElement.surface_node_position_pt.size(),
362 nodalCouplingForces);
365 sCoupledElement.bulk_elem_pt->set_nodal_coupling_residual(elemIsCoupled, nodalCouplingForces);
409 unsigned& wallID, Vector<Vector<double> >& nodalCouplingForces)
412 bool elemIsCoupled =
false;
415 const unsigned nnode = elem_pt->nnode();
417 const unsigned dim = elem_pt->dim();
419 nodalCouplingForces.resize(nnode, Vector<double>(dim, 0.0));
424 while (
n++ < nTriangles)
438 if (!inter->getForce().isZero())
441 Vec3D xc = inter->getContactPoint();
442 Vec3D fc = inter->getForce();
444 Vector<double> x(3, 0.0), f(3, 0.0);
453 Vector<double> s(3, 0.0);
454 GeomObject* geom_obj_pt = 0;
455 elem_pt->locate_zeta(x, geom_obj_pt, s);
458 elem_pt->shape(s, psi);
460 for (
unsigned l = 0; l < nnode; l++)
463 for (
unsigned i = 0;
i < dim;
i++)
466 nodalCouplingForces[l][
i] += f[
i] * psi(l);
470 elemIsCoupled =
true;
474 return elemIsCoupled;
570 Vector<double> listOfCoordX;
571 Vector<double> listOfCoordY;
572 Vector<double> listOfCoordZ;
575 const unsigned nnode = elem_pt->nnode();
576 for (
unsigned n = 0;
n < nnode;
n++)
578 listOfCoordX.push_back(elem_pt->node_pt(
n)->x(0));
579 listOfCoordY.push_back(elem_pt->node_pt(
n)->x(1));
580 listOfCoordZ.push_back(elem_pt->node_pt(
n)->x(2));
584 min.
X = *min_element(listOfCoordX.begin(), listOfCoordX.end());
585 min.
Y = *min_element(listOfCoordY.begin(), listOfCoordY.end());
586 min.
Z = *min_element(listOfCoordZ.begin(), listOfCoordZ.end());
587 max.
X = *max_element(listOfCoordX.begin(), listOfCoordX.end());
588 max.
Y = *max_element(listOfCoordY.begin(), listOfCoordY.end());
589 max.
Z = *max_element(listOfCoordZ.begin(), listOfCoordZ.end());
592 logger.assert_always(M::particleHandler.getLargestParticle(),
"No particles detected");
605 sCoupledElements_.clear();
608 for (
unsigned b : coupledBoundaries_)
614 unsigned n_element = this->solid_mesh_pt()->nboundary_element(b);
617 for (
unsigned e = 0; e < n_element; e++)
623 sCoupledElement.
bulk_elem_pt =
dynamic_cast<ELEMENT*
>(this->solid_mesh_pt()->boundary_element_pt(b, e));
626 sCoupledElement.
face_index = this->solid_mesh_pt()->face_index_at_boundary(b, e);
632 unsigned n_node = trac_elem.nnode();
641 for (
unsigned n = 0;
n < n_node;
n++)
646 Vector<double> s(2, 0.0);
647 trac_elem.local_coordinate_of_node(
n, s);
649 Vector<double> s_bulk(3, 0.0);
650 trac_elem.get_local_coordinate_in_bulk(s, s_bulk);
653 Vector<double*> x_pt;
654 for (
unsigned i = 0;
i < 3;
i++)
656 x_pt.push_back(&trac_elem.node_pt(
n)->x(
i));
675 sCoupledElements_.push_back(sCoupledElement);
682 coupledBoundaries_ = {b};
687 coupledBoundaries_ = std::move(b);
691 logSurfaceCoupling =
false;
708 bool logSurfaceCoupling =
true;
const unsigned n
Definition: CG3DPackingUnitTest.cpp:32
LL< Log::INFO > INFO
Info log level.
Definition: Logger.cc:55
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
Definition: BaseCoupling.h:48
void solveOomph()
Definition: BaseCoupling.h:141
double getCGWidth()
Definition: BaseCoupling.h:176
void solveMercury(unsigned long nt)
Definition: BaseCoupling.h:150
const std::vector< BaseInteraction * > & getInteractions() const
Returns a list of interactions which belong to this interactable.
Definition: BaseInteractable.h:277
void setPrescribedPosition(const std::function< Vec3D(double)> &prescribedPosition)
Allows the position of an infinite mass interactable to be prescribed.
Definition: BaseInteractable.cc:413
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:218
void setPrescribedVelocity(const std::function< Vec3D(double)> &prescribedVelocity)
Allows the velocity of an infinite mass interactable to be prescribed.
Definition: BaseInteractable.cc:444
void setGroupId(unsigned groupId)
Definition: BaseObject.h:131
void setSpecies(const ParticleSpecies *species)
Defines the species of the current wall.
Definition: BaseWall.cc:169
Definition: SCoupling.h:37
void disableLogSurfaceCoupling()
Definition: SCoupling.h:690
void getElementBoundingBox(ELEMENT *&elem_pt, Vec3D &min, Vec3D &max)
Definition: SCoupling.h:567
void coupleBoundaries(std::vector< unsigned > b)
Definition: SCoupling.h:686
void getSCoupledElements()
Definition: SCoupling.h:602
void solveSurfaceCouplingFixedSolid()
Definition: SCoupling.h:145
O::ELEMENT ELEMENT
Definition: SCoupling.h:39
void solveSurfaceCoupling(unsigned nStep)
Definition: SCoupling.h:93
void updateTractionOnFiniteElems()
Definition: SCoupling.h:345
void solveSurfaceCoupling()
Definition: SCoupling.h:72
TriangleWall * createTriangleWall(std::array< Vec3D, 3 > vertex)
Definition: SCoupling.h:192
void updateTriangleWall(TriangleWall *&wall, std::array< Vec3D, 3 > vertex)
Definition: SCoupling.h:208
void updateDPMWallsFromFiniteElems()
Definition: SCoupling.h:294
std::vector< unsigned > coupledBoundaries_
Definition: SCoupling.h:706
bool computeSCouplingForcesFromTriangles(ELEMENT *const elem_pt, const unsigned &nTriangles, unsigned &wallID, Vector< Vector< double > > &nodalCouplingForces)
Definition: SCoupling.h:408
std::vector< TriangleWall * > triangleWalls_
List of triangle walls used for the surface coupling.
Definition: SCoupling.h:700
void computeOneTimeStepForSCoupling(const unsigned &nStepsMercury)
Definition: SCoupling.h:237
Vector< SCoupledElement > sCoupledElements_
List of surface-coupled elements.
Definition: SCoupling.h:697
void coupleBoundary(unsigned b)
Definition: SCoupling.h:681
void createDPMWallsFromFiniteElems()
Definition: SCoupling.h:252
A TriangleWall is convex polygon defined as an intersection of InfiniteWall's.
Definition: TriangleWall.h:57
std::array< Vec3D, 3 > getVertices() const
Definition: TriangleWall.h:105
void setVertices(Vec3D A, Vec3D B, Vec3D C)
Sets member variables such that the wall represents a triangle with vertices A, B,...
Definition: TriangleWall.cc:165
Mdouble Y
Definition: Vector.h:66
Mdouble Z
Definition: Vector.h:66
Mdouble X
the vector components
Definition: Vector.h:66
Mdouble getZ() const
Definition: Vector.h:408
void setY(Mdouble y)
Definition: Vector.h:396
Mdouble getX() const
Definition: Vector.h:402
void setZ(Mdouble z)
Definition: Vector.h:399
void setX(Mdouble x)
Definition: Vector.h:393
Mdouble getY() const
Definition: Vector.h:405
Definition: CoupledSolidNodes.h:16
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
Definition: AnisotropicHookean.h:31
Definition: SCoupling.h:46
Vector< Vector< double * > > surface_node_position_pt
Definition: SCoupling.h:52
Vector< double > center_local
Definition: SCoupling.h:56
int face_index
Definition: SCoupling.h:50
Vector< CoupledSolidNode * > node_pt
Definition: SCoupling.h:54
ELEMENT * bulk_elem_pt
Definition: SCoupling.h:48