1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2019 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Conlain Kelly, Nic Olsen, Ruochun Zhang, Dan Negrut, Radu Serban
13 // =============================================================================
14 
15 #pragma once
16 
17 #include "chrono_gpu/physics/ChSystemGpu_impl.h"
18 
19 namespace chrono {
20 namespace gpu {
21 
22 // Underlying implementation of the Chrono::Gpu mesh system.
23 // Implements functionality required to handle the interaction between a mesh soup and granular material.
24 //
25 // Mesh soup: a collection of meshes that each has a certain number of triangle elements. For instance, the meshes
26 // associated with the four wheels of a rover operating on granular material would be smashed into one soup having four
27 // mesh families.
28 class ChSystemGpuMesh_impl : public ChSystemGpu_impl {
29   public:
30     virtual ~ChSystemGpuMesh_impl();
31 
32   protected:
33     /// Position and rotation matrix defining the frame of a triangle mesh.
34     template <class T>
35     struct MeshFrame {
36         // TODO optimize rotations
37         T pos[3];
38         T rot_mat[9];
39     };
40 
41     /// Extra parameters needed for triangle-sphere contact.
42     struct MeshParams {
43         /// Sphere-to-mesh normal stiffness, expressed in SU (Hertzian spring)
44         float K_n_s2m_SU;
45         /// Sphere-to-mesh tangent stiffness, expressed in SU (Hertzian spring)
46         float K_t_s2m_SU;
47 
48         /// Sphere-to-mesh normal contact damping coefficient, expressed in SU
49         float Gamma_n_s2m_SU;
50         /// Sphere-to-mesh tangent contact damping coefficient, expressed in SU
51         float Gamma_t_s2m_SU;
52 
53         /// material based property
54         bool use_mat_based;
55 
56         /// effective sphere-to-mesh youngs modulus, expressed in SU
57         float E_eff_s2m_SU;
58 
59         /// effective sphere-to-mesh shear modulus, expressed in SU
60         float G_eff_s2m_SU;
61 
62         /// effective sphere-to-mesh coefficient of restitution, expressed in SU
63         float COR_s2m_SU;
64 
65         /// Acceleration caused by adhesion force (constant adhesion model)
66         float adhesionAcc_s2m;
67 
68         /// Ratio of normal force to peak tangent force, also arctan(theta) where theta is the friction angle
69         float static_friction_coeff_s2m;
70 
71         /// Coefficient of rolling resistance. Units and effect depend on the system rolling resistance model
72         float rolling_coeff_s2m_SU;
73 
74         /// Coefficient of spinning resistance. Units and effect depend on the system spinning resistance model
75         float spinning_coeff_s2m_SU;
76 
77         /// Number of triangle families
78         unsigned int num_triangle_families;
79 
80         /// Reference frames of the triangle families in single precision
81         MeshFrame<float>* fam_frame_broad;
82 
83         /// Reference frames of the triangle families in double precision
84         MeshFrame<double>* fam_frame_narrow;
85     };
86 
87     /// Structure used to hold pointers for mesh arrays.
88     /// Note: The order of the nodes in a triangle defines the positive face of the triangle; right-hand rule used.
89     struct TriangleSoup {
90         /// Total number of triangles in the soup
91         unsigned int nTrianglesInSoup;
92         /// Indicates how many meshes are squashed together in this soup
93         unsigned int numTriangleFamilies;
94         /// Each entry says what family that triagnle belongs to; size: nTrianglesInSoup
95         unsigned int* triangleFamily_ID;
96 
97         /// Entry i is the SU mass of family i
98         float* familyMass_SU;
99 
100         /// Position in local reference frame of triangle vertex 1
101         float3* node1;
102         /// Position in local reference frame of triangle vertex 2
103         float3* node2;
104         /// Position in local reference frame of triangle vertex 3
105         float3* node3;
106 
107         /// Entry i is the linear velocity of family i (rigid body motion)
108         float3* vel;
109         /// Entry i is the angular velocity of family i (rigid body motion)
110         float3* omega;
111 
112         /// Generalized forces acting on each family. Expressed
113         /// in the global reference frame. Size: 6 * numTriangleFamilies.
114         float* generalizedForcesPerFamily;
115     };
116 
getMeshSoup()117     TriangleSoup* getMeshSoup() { return meshSoup; }
getTriParams()118     MeshParams* getTriParams() { return tri_params; }
119 
120     // The system is not default-constructible
121     ChSystemGpuMesh_impl() = delete;
122 
123     /// Construct Chrono::Gpu system with given sphere radius, density, big domain dimensions and frame origin.
124     ChSystemGpuMesh_impl(float sphere_rad, float density, float3 boxDims, float3 O);
125 
126     /// combine material properties of two types to get effective ones
127     void combineMaterialSurface();
128 
129 
130     /// Apply rigid body motion to specified mesh.
131     void ApplyMeshMotion(unsigned int mesh_id,
132                          const double* pos,
133                          const double* rot,
134                          const double* lin_vel,
135                          const double* ang_vel);
136 
137     /// Initialize trimeshes before starting simulation (typically called by initialize).
138     void initializeTriangles();
139 
140     /// Clean up data structures associated with triangle mesh
141     void cleanupTriMesh();
142 
143     /// Broadphase CD for triangles
144     void runTriangleBroadphase();
145 
146     virtual double get_max_K() const override;
147 
148     template <typename T>
149     void generate_rot_matrix(const double* ep, T* rot_mat);
150 
151     static void ApplyFrameTransform(float3& p, float* pos, float* rot_mat);
152 
153     /// Advance simulation by duration in user units, return actual duration elapsed.
154     /// Requires initialize() to have been called.
155     virtual double AdvanceSimulation(float duration) override;
156 
157     /// Set of simulation parameters related to triangle data
158     MeshParams* tri_params;
159 
160     /// Clean copy of mesh soup interacting with granular material in unified memory. Stored in UU
161     TriangleSoup* meshSoup;
162 
163     /// Sphere-to-mesh normal contact stiffness, in user units (Hertzian spring)
164     double K_n_s2m_UU;
165     /// Sphere-to-mesh normal damping coefficient, in user units
166     double Gamma_n_s2m_UU;
167 
168     /// Sphere-to-mesh tangent contact stiffness, in user units (Hertzian spring)
169     double K_t_s2m_UU;
170     /// Sphere-to-mesh tangent damping coefficient, in user units
171     double Gamma_t_s2m_UU;
172 
173     /// flag for using material based property
174     bool use_mat_based = false;
175 
176     /// youngs modulus of mesh
177     double YoungsModulus_mesh_UU;
178 
179     /// Poisson ratio of mesh
180     double PoissonRatio_mesh_UU;
181 
182     /// coefficient of restitution of mesh
183     double COR_mesh_UU;
184 
185     /// Rolling friction coefficient for sphere-to-mesh -- units and effect depend on rolling resistance model
186     float rolling_coeff_s2m_UU;
187 
188     /// Spinning friction coefficient for sphere-to-mesh -- units and effect depend on spinning resistance model
189     float spinning_coeff_s2m_UU;
190 
191     /// Ratio of sphere-to-mesh adhesion to gravity (constant adhesion model)
192     float adhesion_s2m_over_gravity;
193 
194     /// Enable or disable collision between spheres and meshes
195     bool mesh_collision_enabled = true;
196 
197     /// stores list of triangles touching each SD; goes SD by SD; size can change during simulation
198     std::vector<unsigned int, cudallocator<unsigned int>> SD_trianglesInEachSD_composite;
199 
200     /// the count of triangles touching each SD; size of vector should be # of SDs
201     std::vector<unsigned int, cudallocator<unsigned int>> SD_numTrianglesTouching;
202 
203     /// offsets in the composite array for each SD; i.e., offset where each SD starts storing its triangles.
204     /// Size of vector should be # of SDs.
205     std::vector<unsigned int, cudallocator<unsigned int>> SD_TrianglesCompositeOffsets;
206 
207     /// Number of SDs that each triangle touches; stored triangle by triangle.
208     /// Nonessential array, only needed to carry out broadphase for mesh
209     std::vector<unsigned int, cudallocator<unsigned int>> Triangle_NumSDsTouching;
210 
211     /// Helper array that stores the prefix scan output done on Triangle_NumSDsTouching.
212     /// Nonessential array, only needed to carry out broadphase for mesh
213     std::vector<unsigned int, cudallocator<unsigned int>> Triangle_SDsCompositeOffsets;
214 
215     /// for each triangle, lists the collection of SDs that triangle touches; e.g., triangle 0 touches SDs 23, 32, 9,
216     /// 199; triangle 0 touchs SDs 23, 33, 109; triangle 2 touches SDs 991; triangle 3 touches 43, 23, etc.
217     /// Nonessential array, only needed to carry out broadphase for mesh
218     std::vector<unsigned int, cudallocator<unsigned int>> SDsTouchedByEachTriangle_composite_out;
219 
220     /// TriangleIDS_ByMultiplicity_out is mirroring the SDsTouchedByEachTriangle_composite_out vector. Its entries is
221     /// the list of triangle IDs, with the right multiplicity. It's used for a sort by key operation needed to figure
222     /// out what triangles are stored in each SD. Thus, for the example above, the entries would be
223     /// 0,0,0,0,1,1,1,2,3,3,etc. Nonessential array, only needed to carry out broadphase for mesh
224     std::vector<unsigned int, cudallocator<unsigned int>> TriangleIDS_ByMultiplicity_out;
225 
226     /// dummy vector used in the broadphase done for the mesh, to understand what SD contains what triangles
227     std::vector<unsigned int, cudallocator<unsigned int>> SDsTouchedByEachTriangle_composite;
228 
229     /// dummy vector used in the broadphase done for the mesh, to understand what SD contains what triangles
230     std::vector<unsigned int, cudallocator<unsigned int>> TriangleIDS_ByMultiplicity;
231 
232   public:
233     /// Get nicer handles to pointer names, enforce const-ness on the mesh params
234     typedef const chrono::gpu::ChSystemGpuMesh_impl::MeshParams* MeshParamsPtr;
235 
236     /// Get nicer handles to pointer names, enforce const-ness on the mesh params
237     typedef chrono::gpu::ChSystemGpuMesh_impl::TriangleSoup* TriangleSoupPtr;
238 
239     friend class ChSystemGpuMesh;
240 };
241 
242 }  // namespace gpu
243 }  // namespace chrono
244