5 #ifndef SURFACE_COUPLING_H
6 #define SURFACE_COUPLING_H
12 using namespace oomph;
14 template<
class M,
class O>
54 unsigned nStep = O::getOomphTimeStep()/M::getTimeStep();
57 logger(
INFO,
"Set nStep %, change mercuryTimeStep from % to %",
58 nStep, M::getTimeStep(), O::getOomphTimeStep());
60 M::setTimeStep(O::getOomphTimeStep());
62 logger(
INFO,
"Set nStep %, change oomphTimeStep from % to %",
63 nStep, O::getOomphTimeStep(), nStep * M::getTimeStep());
64 O::setOomphTimeStep(nStep * M::getTimeStep());
68 solveSurfaceCoupling(nStep, max_adapt);
75 logger.assert_always(O::getOomphTimeStep()>0,
"Oomph time step not initialised");
76 logger.assert_always(M::getTimeStep()>0,
"Mercury time step not initialised");
78 logger.assert_always(!coupledBoundaries_.empty(),
"isCoupled needs to be set, e.g. via setIsCoupled([](unsigned b) { return b == Boundary::Y_MIN; })");
84 double mercury_dt = M::getTimeStep();
85 logger(
INFO,
"Mercury time step: %", mercury_dt);
88 double oomph_dt = nStep * mercury_dt;
92 O::assign_initial_values_impulsive(oomph_dt);
95 logger(
INFO,
"Set up oomph mesh: % elements (% with traction)",
96 O::solid_mesh_pt()?O::solid_mesh_pt()->nelement():0, O::traction_mesh_pt()?O::traction_mesh_pt()->nelement():0);
99 getSCoupledElements();
102 createDPMWallsFromFiniteElems();
106 while (M::getTime() < M::getTimeMax())
108 this->actionsBeforeOomphTimeStep();
110 computeOneTimeStepForSCoupling(nStep, max_adapt);
112 if (M::getParticlesWriteVTK() && M::getVtkWriter()->getFileCounter() > nDone)
115 nDone = M::getVtkWriter()->getFileCounter();
129 solveSurfaceCoupling(nStep, max_adapt);
134 double time = O::time_stepper_pt()->time() - nStep * M::getTimeStep();;
135 double timeMax = M::getTimeMax();;
136 if (time >= timeMaxMin) {
138 logger(
INFO,
"Newton solver failed at t=% (tMax=%), but code will continue.", time, timeMax);
141 logger(
ERROR,
"Newton solver failed at t=% (tMax=%).", time, timeMax);
150 M::initialiseSolve();
151 logger.assert_always(!coupledBoundaries_.empty(),
"isCoupled needs to be set, e.g. via setIsCoupled([](unsigned b) { return b == Boundary::Y_MIN; })");
154 double mercury_dt = M::getTimeStep();
155 logger(
INFO,
"Mercury time step: %", mercury_dt);
161 this->time_pt()->initialise_dt(0);
163 this->assign_initial_values_impulsive(0);
166 logger(
INFO,
"Set up oomph mesh: % elements (% with traction)",
167 O::solid_mesh_pt()?O::solid_mesh_pt()->nelement():0, O::traction_mesh_pt()?O::traction_mesh_pt()->nelement():0);
170 getSCoupledElements();
173 createDPMWallsFromFiniteElems();
177 while (M::getTime() < M::getTimeMax())
179 this->actionsBeforeOomphTimeStep();
180 M::computeOneTimeStep();
199 auto species = M::speciesHandler.getObject(0);
203 auto w = M::wallHandler.copyAndAddObject(wall);
214 double time0 = M::getTime();
215 double dTime = O::getOomphTimeStep();
217 std::array<Vec3D,3> dVertex = {
218 vertex[0] - vertex0[0],
219 vertex[1] - vertex0[1],
220 vertex[2] - vertex0[2]};
222 double f = ( time - time0 ) / dTime;
223 std::array<Vec3D, 3> vertex = {
224 vertex0[0] + dVertex[0] *
f,
225 vertex0[1] + dVertex[1] *
f,
226 vertex0[2] + dVertex[2] *
f };
227 wall->
setVertices( vertex[0], vertex[1], vertex[2] );
231 Vec3D velocity = (dVertex[0]+dVertex[1]+dVertex[2])/3./dTime;
243 auto t0 = std::chrono::system_clock::now();
244 updateDPMWallsFromFiniteElems();
245 auto t1 = std::chrono::system_clock::now();
247 auto t2 = std::chrono::system_clock::now();
248 if (solidFeelsParticles_) {
249 updateTractionOnFiniteElems();
251 auto t3 = std::chrono::system_clock::now();
253 auto t4 = std::chrono::system_clock::now();
254 if (logSurfaceCoupling)
logger(
INFO,
"time % Elapsed time: FEM->DEM %, DEM %, DEM->FEM %, FEM %", M::getTime(),
255 (t1-t0).count(), (t2-t1).count(), (t3-t2).count(), (t4-t3).count());
258 getSCoupledElements();
259 createDPMWallsFromFiniteElems();
266 for (
auto sCoupledElement : sCoupledElements_)
271 swap(position_pt[2], position_pt[3]);
276 sCoupledElement.bulk_elem_pt->interpolated_x(sCoupledElement.center_local,
x);
282 const unsigned nTriangles = position_pt.size();
284 while (
n < nTriangles)
287 std::array<Vec3D, 3> vertex;
291 vertex[1] =
Vec3D(*position_pt[0][0],*position_pt[0][1],*position_pt[0][2]);
292 vertex[2] =
Vec3D(*position_pt[1][0],*position_pt[1][1],*position_pt[1][2]);
296 triangleWalls_.push_back(
w);
299 rotate(position_pt.begin(), position_pt.begin() + 1, position_pt.end());
309 for (
auto sCoupledElement : sCoupledElements_)
317 swap(position_pt[2], position_pt[3]);
321 sCoupledElement.bulk_elem_pt->interpolated_x(sCoupledElement.center_local,
x);
325 const unsigned nTriangles = position_pt.size();
327 while (
n < nTriangles)
330 std::array<Vec3D, 3> vertex;
334 vertex[1] =
Vec3D(*position_pt[0][0],
336 *position_pt[0][2]);;
337 vertex[2] =
Vec3D(*position_pt[1][0],
342 updateTriangleWall(triangleWalls_[wallID], vertex);
345 rotate(position_pt.begin(), position_pt.begin() + 1, position_pt.end());
346 rotate(node_pt.begin(), node_pt.begin() + 1, node_pt.end());
365 for (
auto sCoupledElement : sCoupledElements_)
370 bool elemIsCoupled = computeSCouplingForcesFromTriangles(sCoupledElement.bulk_elem_pt,
371 sCoupledElement.surface_node_position_pt.size(),
373 nodalCouplingForces);
376 sCoupledElement.bulk_elem_pt->set_nodal_coupling_residual(elemIsCoupled, nodalCouplingForces);
424 bool elemIsCoupled =
false;
427 const unsigned nnode = elem_pt->nnode();
429 const unsigned dim = elem_pt->dim();
436 while (
n++ < nTriangles)
442 if (
w->getInteractions().size() == 0)
continue;
448 for (
auto inter :
w->getInteractions())
450 if (!inter->getForce().isZero())
453 Vec3D xc = inter->getContactPoint();
454 Vec3D fc = inter->getForce();
470 elem_pt->shape(
s, psi);
472 for (
unsigned l = 0; l < nnode; l++)
475 for (
unsigned i = 0;
i < dim;
i++)
478 nodalCouplingForces[l][
i] +=
f[
i] * psi(l);
482 elemIsCoupled =
true;
486 return elemIsCoupled;
587 const unsigned nnode = elem_pt->nnode();
588 for (
unsigned n = 0;
n < nnode;
n++)
590 listOfCoordX.push_back(elem_pt->node_pt(
n)->x(0));
591 listOfCoordY.push_back(elem_pt->node_pt(
n)->x(1));
592 listOfCoordZ.push_back(elem_pt->node_pt(
n)->x(2));
596 min.X = *min_element(listOfCoordX.begin(), listOfCoordX.end());
597 min.Y = *min_element(listOfCoordY.begin(), listOfCoordY.end());
598 min.Z = *min_element(listOfCoordZ.begin(), listOfCoordZ.end());
599 max.X = *max_element(listOfCoordX.begin(), listOfCoordX.end());
600 max.Y = *max_element(listOfCoordY.begin(), listOfCoordY.end());
601 max.Z = *max_element(listOfCoordZ.begin(), listOfCoordZ.end());
604 logger.assert_always(M::particleHandler.getLargestParticle(),
"No particles detected");
617 sCoupledElements_.clear();
620 for (
unsigned b : coupledBoundaries_)
623 unsigned n_element = this->solid_mesh_pt()->nboundary_element(
b);
625 logger(
INFO,
"Coupling boundary %. which has % elements",
b, n_element);
628 for (
unsigned e = 0;
e < n_element;
e++)
634 sCoupledElement.
bulk_elem_pt =
dynamic_cast<ELEMENT*
>(this->solid_mesh_pt()->boundary_element_pt(
b,
e));
637 sCoupledElement.
face_index = this->solid_mesh_pt()->face_index_at_boundary(
b,
e);
643 unsigned n_node = trac_elem.
nnode();
652 for (
unsigned n = 0;
n < n_node;
n++)
665 for (
unsigned i = 0;
i < 3;
i++)
686 sCoupledElements_.push_back(sCoupledElement);
693 coupledBoundaries_ = {
b};
698 coupledBoundaries_ = std::move(
b);
702 logSurfaceCoupling =
false;
706 solidFeelsParticles_ =
val;
710 return solidFeelsParticles_;
727 bool logSurfaceCoupling =
true;
732 bool solidFeelsParticles_ =
true;
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
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.
LL< Log::ERROR > ERROR
Error log level.
Definition: Logger.cc:32
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Scalar * b
Definition: benchVecAdd.cpp:17
Definition: BaseCoupling.h:27
void solveOomph(int max_adapt=0)
Definition: BaseCoupling.h:120
double getCGWidth()
Definition: BaseCoupling.h:175
void solveMercury(unsigned long nt)
Definition: BaseCoupling.h:149
void setPrescribedPosition(const std::function< Vec3D(double)> &prescribedPosition)
Allows the position of an infinite mass interactable to be prescribed.
Definition: BaseInteractable.cc:391
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:197
void setPrescribedVelocity(const std::function< Vec3D(double)> &prescribedVelocity)
Allows the velocity of an infinite mass interactable to be prescribed.
Definition: BaseInteractable.cc:422
void setGroupId(unsigned groupId)
Definition: BaseObject.h:110
void setSpecies(const ParticleSpecies *species)
Defines the species of the current wall.
Definition: BaseWall.cc:148
Definition: SCoupling.h:16
void solveSurfaceCoupling(unsigned nStep, const unsigned max_adapt)
Definition: SCoupling.h:72
void disableLogSurfaceCoupling()
Definition: SCoupling.h:701
void solveSurfaceCouplingForgiving(unsigned nStep, double timeMaxMin=-constants::inf, const unsigned max_adapt=0)
Definition: SCoupling.h:126
void getElementBoundingBox(ELEMENT *&elem_pt, Vec3D &min, Vec3D &max)
Definition: SCoupling.h:579
void coupleBoundaries(std::vector< unsigned > b)
Definition: SCoupling.h:697
void getSCoupledElements()
Definition: SCoupling.h:614
bool getSolidFeelsParticles() const
Definition: SCoupling.h:709
void computeOneTimeStepForSCoupling(const unsigned &nStepsMercury, const unsigned max_adapt=0)
Definition: SCoupling.h:241
void solveSurfaceCouplingFixedSolid()
Definition: SCoupling.h:147
O::ELEMENT ELEMENT
Definition: SCoupling.h:18
void updateTractionOnFiniteElems()
Definition: SCoupling.h:356
TriangleWall * createTriangleWall(std::array< Vec3D, 3 > vertex)
Definition: SCoupling.h:196
void updateTriangleWall(TriangleWall *&wall, std::array< Vec3D, 3 > vertex)
Definition: SCoupling.h:212
void updateDPMWallsFromFiniteElems()
Definition: SCoupling.h:305
std::vector< unsigned > coupledBoundaries_
Definition: SCoupling.h:725
void solveSurfaceCoupling(const unsigned max_adapt=0)
Definition: SCoupling.h:51
bool computeSCouplingForcesFromTriangles(ELEMENT *const elem_pt, const unsigned &nTriangles, unsigned &wallID, Vector< Vector< double > > &nodalCouplingForces)
Definition: SCoupling.h:420
std::vector< TriangleWall * > triangleWalls_
List of triangle walls used for the surface coupling.
Definition: SCoupling.h:719
Vector< SCoupledElement > sCoupledElements_
List of surface-coupled elements.
Definition: SCoupling.h:716
void coupleBoundary(unsigned b)
Definition: SCoupling.h:692
void createDPMWallsFromFiniteElems()
Definition: SCoupling.h:263
void setSolidFeelsParticles(bool val)
Definition: SCoupling.h:705
A TriangleWall is convex polygon defined as an intersection of InfiniteWall's.
Definition: TriangleWall.h:36
std::array< Vec3D, 3 > getVertices() const
Definition: TriangleWall.h:84
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:144
Definition: Kernel/Math/Vector.h:30
Mdouble getZ() const
Definition: Kernel/Math/Vector.h:437
void setY(Mdouble y)
Definition: Kernel/Math/Vector.h:425
Mdouble getX() const
Definition: Kernel/Math/Vector.h:431
void setZ(Mdouble z)
Definition: Kernel/Math/Vector.h:428
void setX(Mdouble x)
Definition: Kernel/Math/Vector.h:422
Mdouble getY() const
Definition: Kernel/Math/Vector.h:434
Definition: CoupledSolidNodes.h:20
void get_local_coordinate_in_bulk(const Vector< double > &s, Vector< double > &s_bulk) const
Definition: elements.cc:6384
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Definition: elements.h:1842
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
Definition: geom_objects.h:101
virtual void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
Definition: geom_objects.h:381
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
Definition: oomph_definitions.h:222
Definition: solid_traction_elements.h:78
Definition: oomph-lib/src/generic/Vector.h:58
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23
RealScalar s
Definition: level1_cplx_impl.h:130
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
#define INFO(i)
Definition: mumps_solver.h:54
double velocity(const double &t)
Angular velocity as function of time t.
Definition: jeffery_orbit.cc:107
xc
Definition: MultiOpt.py:46
val
Definition: calibrate.py:119
int error
Definition: calibrate.py:297
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
Definition: SCoupling.h:25
Vector< Vector< double * > > surface_node_position_pt
Definition: SCoupling.h:31
Vector< double > center_local
Definition: SCoupling.h:35
int face_index
Definition: SCoupling.h:29
Vector< CoupledSolidNode * > node_pt
Definition: SCoupling.h:33
ELEMENT * bulk_elem_pt
Definition: SCoupling.h:27