File: Grid.hpp

package info (click to toggle)
yade 2026.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,448 kB
  • sloc: cpp: 97,645; python: 52,173; sh: 677; makefile: 162
file content (360 lines) | stat: -rw-r--r-- 18,995 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/*************************************************************************
*  Copyright (C) 2012 by François Kneib   francois.kneib@gmail.com       *
*  Copyright (C) 2012 by Bruno Chareyre   bruno.chareyre@grenoble-inp.fr     *
*  This program is free software; it is licensed under the terms of the  *
*  GNU General Public License v2 or later. See file LICENSE for details. *
*************************************************************************/

/* TABLE OF CONTENT, and the minimum you need to understand.
- 2 new shapes for grids : GridNode (vertices) and GridConnection (edges)
- 2 new contact geometries :
    * GridNodeGeom6D to handle GridNode-GridNode contacts (the internal behaviour of the grid)
    * ScGridCoGeom to handle Sphere-GridConnection contacts (the interaction between the grid and an external sphere)
        Note : the Sphere-Grid contacts are always handled by the GridConnections, but the forces are applied on the related GridNodes.
        Note : there is no contact between two GridConnections, they must be linked with GridNodes.
- The 2 related Ig2 :
    * Ig2_GridNode_GridNode_GridNodeGeom6D (doing almost the same than Ig2_Sphere_Sphere_ScGeom6D)
    * Ig2_Sphere_GridConnection_ScGridCoGeom (the biggest part of the code, it handles contact detection and history when a sphere is sliding on the grid over consecutive GridConnections)
- The Law2_ScGridCoGeom_FrictPhys_CundallStrack who handles the elastic frictional Sphere-GridConnection contact. The GridNode-GridNode law is Law2_ScGeom6D_CohFrictPhys_CohesionMoment by inheritance.
*/

#pragma once
#include "Sphere.hpp"
#include <core/Body.hpp>
#include <core/Dispatching.hpp>
#include <pkg/dem/CohesiveFrictionalContactLaw.hpp>
#include <pkg/dem/ElasticContactLaw.hpp>
#include <pkg/dem/FrictPhys.hpp>
#include <pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp>
#include <pkg/dem/ScGeom.hpp>
#ifdef YADE_OPENGL
#include <pkg/common/GLDrawFunctors.hpp>
#endif

namespace yade { // Cannot have #include directive inside.

//!##################	SHAPES   #####################

class GridConnection : public Sphere {
public:
	virtual ~GridConnection();
	Real                     getLength() const;
	Vector3r                 getSegment() const;
	void                     addPFacet(shared_ptr<Body> PF);
	vector<shared_ptr<Body>> getPFacets() const { return pfacetList; }
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(GridConnection,Sphere,"GridConnection shape (see [Effeindzourou2016]_, [Bourrier2013]_). Component of a grid designed to link two :yref:`GridNodes<GridNode>`. It is highly recommended to use :yref:`yade.gridpfacet.gridConnection` to generate correct :yref:`GridConnections<GridConnection>`.",
		((shared_ptr<Body> , node1 , ,,"First :yref:`Body` the GridConnection is connected to."))
		((shared_ptr<Body> , node2 , ,,"Second :yref:`Body` the GridConnection is connected to."))
		((bool, periodic, false,,"true if two nodes from different periods are connected."))
		 ((vector<shared_ptr<Body> >,pfacetList,,Attr::hidden,"List of :yref:`PFacet<PFacet>` the GridConnection is connected to."))
		((Vector3i , cellDist , Vector3i(0,0,0),,"Distance of bodies in cell size units, if using periodic boundary conditions. Note that periodic boundary conditions for GridConnections have not yet been fully implemented.")),
		createIndex();, /*ctor*/
		/*py*/  
		.def("addPFacet",&GridConnection::addPFacet,(boost::python::arg("Body")),"Add a PFacet to the GridConnection.")
		.def("getPFacets",&GridConnection::getPFacets,"get list of linked PFacets.") 
	);
	// clang-format on
	REGISTER_CLASS_INDEX(GridConnection, Sphere);
};
REGISTER_SERIALIZABLE(GridConnection);


class GridNode : public Sphere {
public:
	virtual ~GridNode();
	void                     addConnection(shared_ptr<Body> GC);
	void                     addPFacet(shared_ptr<Body> PF);
	vector<shared_ptr<Body>> getPFacets() const { return pfacetList; }
	vector<shared_ptr<Body>> getConnections() const { return ConnList; }

	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(GridNode,Sphere,"GridNode shape, component of a grid.\nTo create a Grid, place the nodes first, they will define the spacial discretisation of it. It is highly recommended to use :yref:`yade.gridpfacet.gridNode` to generate correct :yref:`GridNodes<GridNode>`. Note that the GridNodes should only be in an Interaction with other GridNodes. The Sphere-Grid contact is only handled by the :yref:`GridConnections<GridConnection>`.",
		((vector<shared_ptr<Body> >,pfacetList,,Attr::hidden,"List of :yref:`PFacets<PFacet>` the GridConnection is connected to."))
		((vector<shared_ptr<Body> >,ConnList,,Attr::hidden,"List of :yref:`GridConnections<GridConnection>` the GridNode is connected to.")),
		/*ctor*/
		createIndex();,
		/*py*/
		.def("addConnection",&GridNode::addConnection,(boost::python::arg("Body")),"Add a GridConnection to the GridNode.")
		.def("addPFacet",&GridNode::addPFacet,(boost::python::arg("Body")),"Add a PFacet to the GridNode.")
		.def("getPFacets",&GridNode::getPFacets,"get list of linked :yref:`PFacet`'s.") 
		.def("getConnections",&GridNode::getConnections,"get list of linked :yref:`GridConnection`'s.") 
	);
	// clang-format on
	REGISTER_CLASS_INDEX(GridNode, Sphere);
};
REGISTER_SERIALIZABLE(GridNode);


//!##################	PFacet SHAPE   #####################

class PFacet : public Shape {
public:
	virtual ~PFacet();
	/// Normals of edges
	Vector3r ne[3];
	/// Inscribing cirle radius
	Real icr;
	/// Length of the vertice vectors
	Real vl[3];
	/// Unit vertice vectors
	Vector3r vu[3];

	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR(PFacet,Shape,"PFacet (particle facet) geometry (see [Effeindzourou2016]_, [Effeindzourou2015a]_). It is highly recommended to use the helper functions in :yref:`yade.gridpfacet` (e.g., gridpfacet.pfacetCreator1-4) to generate correct :yref:`PFacet<PFacet>` elements.",
		((shared_ptr<Body> , node1 , ,,"First :yref:`Body` the Pfacet is connected to."))
		((shared_ptr<Body> , node2 , ,,"Second :yref:`Body` the Pfacet is connected to."))
		((shared_ptr<Body> , node3 , ,,"third :yref:`Body` the Pfacet is connected to."))
		((shared_ptr<Body> , conn1 , ,,"First :yref:`Body` the Pfacet is connected to."))
		((shared_ptr<Body> , conn2 , ,,"Second :yref:`Body` the Pfacet is connected to."))
		((shared_ptr<Body> , conn3 , ,,"third :yref:`Body` the Pfacet is connected to."))
		((Vector3r,normal,Vector3r(NaN,NaN,NaN),(Attr::readonly | Attr::noSave),"PFacet's normal (in local coordinate system)"))
		((Real,radius,-1,,"PFacet's radius"))
		((Real,area,NaN,(Attr::readonly | Attr::noSave),"PFacet's area"))
		((Vector3i , cellDist , Vector3i(0,0,0),,"Distance of bodies in cell size units, if using periodic boundary conditions. Note that periodic boundary conditions for PFacets have not yet been fully implemented."))
		,
		/* ctor */ createIndex();
	);
	// clang-format on
	DECLARE_LOGGER;

	REGISTER_CLASS_INDEX(PFacet, Shape);
};
REGISTER_SERIALIZABLE(PFacet);


//!##################	Contact Geometry   #####################

//!			O-O
class GridNodeGeom6D : public ScGeom6D {
public:
	virtual ~GridNodeGeom6D();
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(GridNodeGeom6D,ScGeom6D,"Geometry of a :yref:`GridNode`-:yref:`GridNode` contact. Inherits almost everything from :yref:`ScGeom6D`.",
		((shared_ptr<Body>, connectionBody,,,"Reference to the :yref:`GridNode` :yref:`Body` who is linking the two :yref:`GridNodes<GridNode>`.")),
		/* extra initializers */,
		/* ctor */ createIndex();,
		/* py */
	);
	// clang-format on
	REGISTER_CLASS_INDEX(GridNodeGeom6D, ScGeom6D);
};
REGISTER_SERIALIZABLE(GridNodeGeom6D);

//!			O/
class ScGridCoGeom : public ScGeom6D {
public:
	/// Emulate a sphere whose position is the projection of sphere's center on cylinder sphere, and with motion linearly interpolated between nodes
	State fictiousState;
	virtual ~ScGridCoGeom();
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR(ScGridCoGeom,ScGeom6D,"Geometry of a :yref:`GridConnection`-:yref:`Sphere` contact.",
		((int,isDuplicate,0,,"this flag is turned true (1) automatically if the contact is shared between two Connections. A duplicated interaction will be skipped once by the constitutive law, so that only one contact at a time is effective. If isDuplicate=2, it means one of the two duplicates has no longer geometric interaction, and should be erased by the constitutive laws."))
		((int,trueInt,-1,,"Defines the body id of the :yref:`GridConnection` where the contact is real, when :yref:`ScGridCoGeom::isDuplicate`>0."))
		((int,id3,0,,"id of the first :yref:`GridNode`. |yupdate|"))
		((int,id4,0,,"id of the second :yref:`GridNode`. |yupdate|"))
		((int,id5,-1,,"id of the third :yref:`GridNode`. |yupdate|"))
		((Vector3r,weight,Vector3r(0,0,0),,"barycentric coordinates of the projection point |yupdate|"))
		((Real,relPos,0,,"position of the contact on the connection (0: node-, 1:node+) |yupdate|")),
		createIndex(); /*ctor*/
	);
	// clang-format on
	REGISTER_CLASS_INDEX(ScGridCoGeom, ScGeom6D);
};
REGISTER_SERIALIZABLE(ScGridCoGeom);

//!			-|-
class GridCoGridCoGeom : public ScGeom {
public:
	/// Emulate a sphere whose position is the projection of sphere's center on cylinder sphere, and with motion linearly interpolated between nodes
	State fictiousState1, fictiousState2;
	virtual ~GridCoGridCoGeom();
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR(GridCoGridCoGeom,ScGeom,"Geometry of a :yref:`GridConnection`-:yref:`GridConnection` contact.",
		((Real,relPos1,0,,"position of the contact on the first connection (0: node-, 1:node+) |yupdate|"))
		((Real,relPos2,0,,"position of the contact on the first connection (0: node-, 1:node+) |yupdate|")),
		createIndex(); /*ctor*/
	);
	// clang-format on
	REGISTER_CLASS_INDEX(ScGridCoGeom, ScGeom);
};
REGISTER_SERIALIZABLE(GridCoGridCoGeom);

//!##################	IGeom Functors   #####################

//!			O-O
class Ig2_GridNode_GridNode_GridNodeGeom6D : public Ig2_Sphere_Sphere_ScGeom {
public:
	virtual bool
	             go(const shared_ptr<Shape>&       cm1,
	                const shared_ptr<Shape>&       cm2,
	                const State&                   state1,
	                const State&                   state2,
	                const Vector3r&                shift2,
	                const bool&                    force,
	                const shared_ptr<Interaction>& c) override;
	virtual bool goReverse(
	        const shared_ptr<Shape>&       cm1,
	        const shared_ptr<Shape>&       cm2,
	        const State&                   state1,
	        const State&                   state2,
	        const Vector3r&                shift2,
	        const bool&                    force,
	        const shared_ptr<Interaction>& c) override;
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS(Ig2_GridNode_GridNode_GridNodeGeom6D,Ig2_Sphere_Sphere_ScGeom,"Create/update a :yref:`GridNodeGeom6D` instance representing the geometry of a contact point between two :yref:`GridNode<GridNode>`, including relative rotations.",
		((bool,updateRotations,true,,"Precompute relative rotations. Turning this false can speed up simulations when rotations are not needed in constitutive laws (e.g. when spheres are compressed without cohesion and moment in early stage of a triaxial test), but is not foolproof. Change this value only if you know what you are doing."))
		((bool,creep,false,,"Substract rotational creep from relative rotation. The rotational creep :yref:`ScGeom6D::twistCreep` is a quaternion and has to be updated inside a constitutive law, see for instance :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`."))
	);
	// clang-format on
	FUNCTOR2D(GridNode, GridNode);
	// needed for the dispatcher, even if it is symmetric
	DEFINE_FUNCTOR_ORDER_2D(GridNode, GridNode);
};
REGISTER_SERIALIZABLE(Ig2_GridNode_GridNode_GridNodeGeom6D);

//!			-/-
class Ig2_GridConnection_GridConnection_GridCoGridCoGeom : public IGeomFunctor {
public:
	virtual bool
	             go(const shared_ptr<Shape>&       cm1,
	                const shared_ptr<Shape>&       cm2,
	                const State&                   state1,
	                const State&                   state2,
	                const Vector3r&                shift2,
	                const bool&                    force,
	                const shared_ptr<Interaction>& c) override;
	virtual bool goReverse(
	        const shared_ptr<Shape>&       cm1,
	        const shared_ptr<Shape>&       cm2,
	        const State&                   state1,
	        const State&                   state2,
	        const Vector3r&                shift2,
	        const bool&                    force,
	        const shared_ptr<Interaction>& c) override;
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS(Ig2_GridConnection_GridConnection_GridCoGridCoGeom,IGeomFunctor,"Create/update a :yref:`GridCoGridCoGeom` instance representing the geometry of a contact point between two :yref:`GridConnection` , including relative rotations.",
	);
	// clang-format on
	FUNCTOR2D(GridConnection, GridConnection);
	DEFINE_FUNCTOR_ORDER_2D(GridConnection, GridConnection);
};
REGISTER_SERIALIZABLE(Ig2_GridConnection_GridConnection_GridCoGridCoGeom);


//!			O/
class Ig2_Sphere_GridConnection_ScGridCoGeom : public IGeomFunctor {
public:
	virtual bool
	             go(const shared_ptr<Shape>&       cm1,
	                const shared_ptr<Shape>&       cm2,
	                const State&                   state1,
	                const State&                   state2,
	                const Vector3r&                shift2,
	                const bool&                    force,
	                const shared_ptr<Interaction>& c) override;
	virtual bool goReverse(
	        const shared_ptr<Shape>&       cm1,
	        const shared_ptr<Shape>&       cm2,
	        const State&                   state1,
	        const State&                   state2,
	        const Vector3r&                shift2,
	        const bool&                    force,
	        const shared_ptr<Interaction>& c) override;
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_GridConnection_ScGridCoGeom,IGeomFunctor,"Create/update a :yref:`ScGridCoGeom6D` instance representing the geometry of a contact point between a :yref:`GricConnection` and a :yref:`Sphere` including relative rotations.",
		((Real,interactionDetectionFactor,1,,"Enlarge both radii by this factor (if >1), to permit creation of distant interactions."))
	);
	// clang-format on
	FUNCTOR2D(Sphere, GridConnection);
	DEFINE_FUNCTOR_ORDER_2D(Sphere, GridConnection);
};
REGISTER_SERIALIZABLE(Ig2_Sphere_GridConnection_ScGridCoGeom);


//!##################	Laws   #####################

//!			O/
class Law2_ScGridCoGeom_FrictPhys_CundallStrack : public LawFunctor {
public:
	bool go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I) override;
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGridCoGeom_FrictPhys_CundallStrack,LawFunctor,"Law between a frictional :yref:`GridConnection` and a frictional :yref:`Sphere`. Almost the same than :yref:`Law2_ScGeom_FrictPhys_CundallStrack`, but the force is divided and applied on the two :yref:`GridNodes<GridNode>` only.",
		((bool,neverErase,false,,"Keep interactions even if particles go away from each other (only in case another constitutive law is in the scene, e.g. :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
		((int,plastDissipIx,-1,(Attr::hidden|Attr::noSave),"Index for plastic dissipation (with O.trackEnergy)"))
		((int,elastPotentialIx,-1,(Attr::hidden|Attr::noSave),"Index for elastic potential energy (with O.trackEnergy)"))
		,,
	);
	// clang-format on
	FUNCTOR2D(ScGridCoGeom, FrictPhys);
};
REGISTER_SERIALIZABLE(Law2_ScGridCoGeom_FrictPhys_CundallStrack);

class Law2_ScGridCoGeom_CohFrictPhys_CundallStrack : public LawFunctor {
public:
	bool go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I) override;
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGridCoGeom_CohFrictPhys_CundallStrack,LawFunctor,"Law between a cohesive frictional :yref:`GridConnection` and a cohesive frictional :yref:`Sphere`. Almost the same than :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`, but THE ROTATIONAL MOMENTS ARE NOT COMPUTED.",
		((bool,neverErase,false,,"Keep interactions even if particles go away from each other (only in case another constitutive law is in the scene, e.g. :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
		((int,plastDissipIx,-1,(Attr::hidden|Attr::noSave),"Index for plastic dissipation (with O.trackEnergy)"))
		,,
	);
	// clang-format on
	FUNCTOR2D(ScGridCoGeom, CohFrictPhys);
};
REGISTER_SERIALIZABLE(Law2_ScGridCoGeom_CohFrictPhys_CundallStrack);

//!			-/-
class Law2_GridCoGridCoGeom_FrictPhys_CundallStrack : public Law2_ScGeom_FrictPhys_CundallStrack {
public:
	bool go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I) override;
	// clang-format off
		YADE_CLASS_BASE_DOC_ATTRS(Law2_GridCoGridCoGeom_FrictPhys_CundallStrack,Law2_ScGeom_FrictPhys_CundallStrack,"Frictional elastic contact law between two :yref:`gridConnection` . See :yref:`Law2_ScGeom_FrictPhys_CundallStrack` for more details.",
		/*ATTRS*/
	);
	// clang-format on
	FUNCTOR2D(GridCoGridCoGeom, FrictPhys);
	DECLARE_LOGGER;
};
REGISTER_SERIALIZABLE(Law2_GridCoGridCoGeom_FrictPhys_CundallStrack);


//!##################	Bounds   #####################

class Bo1_GridConnection_Aabb : public BoundFunctor {
public:
	void go(const shared_ptr<Shape>& cm, shared_ptr<Bound>& bv, const Se3r&, const Body*) override;
	FUNCTOR1D(GridConnection);
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS(Bo1_GridConnection_Aabb,BoundFunctor,"Functor creating :yref:`Aabb` from a :yref:`GridConnection`.",
		((Real,aabbEnlargeFactor,((void)"deactivated",-1),,"Relative enlargement of the bounding box; deactivated if negative."))
	);
	// clang-format on
};
REGISTER_SERIALIZABLE(Bo1_GridConnection_Aabb);

//!##################	Rendering   #####################
#ifdef YADE_OPENGL
class Gl1_GridConnection : public GlShapeFunctor {
private:
	//static int glCylinderList;
	//void subdivideTriangle(Vector3r& v1,Vector3r& v2,Vector3r& v3, int depth);
	void drawCylinder(bool wire, Real radius, Real length, const Quaternionr& shift = Quaternionr::Identity());
	//void initGlLists(void);
public:
	void go(const shared_ptr<Shape>&, const shared_ptr<State>&, bool, const GLViewInfo&) override;
	void out(Quaternionr q);
	// clang-format off
	YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_GridConnection,GlShapeFunctor,"Renders :yref:`Cylinder` object",
		((bool,wire,false,,"Only show wireframe (controlled by ``glutSlices`` and ``glutStacks``."))
		((bool,glutNormalize,true,,"Fix normals for non-wire rendering"))
		((int,glutSlices,8,,"Number of cylinder slices."))
		((int,glutStacks,4,,"Number of cylinder stacks."))
	);
	// clang-format on
	RENDERS(GridConnection);
};
REGISTER_SERIALIZABLE(Gl1_GridConnection);
#endif

} // namespace yade