1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2020 projectchrono.org
5 // All right 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: Radu Serban
13 // =============================================================================
14 //
15 // Definition of the MPI granular TERRAIN NODE (using Chrono::Distributed).
16 //
17 // The global reference frame has Z up, X towards the front of the vehicle, and
18 // Y pointing to the left.
19 //
20 // =============================================================================
21 
22 #ifndef TESTRIG_TERRAIN_NODE_GRANULAR_MPI_H
23 #define TESTRIG_TERRAIN_NODE_GRANULAR_MPI_H
24 
25 #include "chrono/utils/ChUtilsSamplers.h"
26 #include "chrono/utils/ChUtilsInputOutput.h"
27 #include "chrono_distributed/physics/ChSystemDistributed.h"
28 
29 #include "chrono_vehicle/cosim/terrain/ChVehicleCosimTerrainNodeChrono.h"
30 
31 #include "chrono_thirdparty/rapidjson/document.h"
32 
33 namespace chrono {
34 namespace vehicle {
35 
36 /// @addtogroup vehicle_cosim_chrono
37 /// @{
38 
39 /// Definition of the MPI granular terrain node (using Chrono::Distributed).
40 class CH_VEHICLE_API ChVehicleCosimTerrainNodeGranularMPI : public ChVehicleCosimTerrainNodeChrono {
41   public:
42     /// Create a Chrono::Distributed granular terrain node.
43     ChVehicleCosimTerrainNodeGranularMPI(double length, double width);
44 
45     /// Create a Chrono::Distributed granular terrain node and set parameters from the provided JSON specfile.
46     ChVehicleCosimTerrainNodeGranularMPI(const std::string& specfile);
47 
48     ~ChVehicleCosimTerrainNodeGranularMPI();
49 
GetSystem()50     virtual ChSystem* GetSystem() override { return m_system; }
51 
52     /// Set the number of OpenMP threads for each Chrono::Multicore terrain simulation (default: 1).
53     void SetNumThreads(int num_threads);
54 
55     /// Set full terrain specification from JSON specfile.
56     void SetFromSpecfile(const std::string& specfile);
57 
58     /// Set container wall thickness (default: 0.2)
59     void SetWallThickness(double thickness);
60 
61     /// Set properties of granular material.
62     void SetGranularMaterial(double radius,  ///< particle radius (default: 0.01)
63                              double density  ///< particle material density (default: 2000)
64     );
65 
66     /// Set the material properties for terrain.
67     /// These parameters characterize the material for the container and the granular material.
68     /// Tire contact material is received from the MBS node.
69     void SetMaterialSurface(const std::shared_ptr<ChMaterialSurfaceSMC>& mat);
70 
71     /// Specify whether contact coefficients are based on material properties (default: true).
72     void UseMaterialProperties(bool flag);
73 
74     /// Set the normal contact force model (default: Hertz).
75     void SetContactForceModel(ChSystemSMC::ContactForceModel model);
76 
77     /// Set the tangential contact displacement model (default: OneStep).
78     void SetTangentialDisplacementModel(ChSystemSMC::TangentialDisplacementModel model);
79 
80     /// Set sampling method for generation of granular material.
81     /// The granular material is created in the volume defined by the x-y dimensions of the terrain patch and the
82     /// specified initial height, using the specified sampling type, layer by layer or all at once.
83     /// Note: for correct HCP, do not initialize in layers!
84     void SetSamplingMethod(utils::SamplingType type,   ///< volume sampling type (default POISSON_DISK)
85                            double init_height,         ///< height of granular material at initialization (default 0.2)
86                            double sep_factor = 1.001,  ///< radius inflation factor for initial separation
87                            bool in_layers = false      ///< initialize material in layers
88     );
89 
90     /// Set sweeping sphere radius for proxy bodies (default 5e-3).
91     /// This value is used as a "thickness" for collision meshes (a non-zero value can improve robustness of the
92     /// collision detection algorithm).
SetProxyContactRadius(double radius)93     void SetProxyContactRadius(double radius) { m_radius_p = radius; }
94 
95     /// Write checkpoint to the specified file (which will be created in the output directory).
96     virtual void WriteCheckpoint(const std::string& filename) const override;
97 
98     /// Estimate packing density (eta) of granular material in current configuration.
99     /// Note that porosity is phi=1-eta and void ratio is e=(1-eta)/eta=phi/(1-phi).
100     /// The function also returns the current depth of granular material.
101     double CalculatePackingDensity(double& depth);
102 
103   private:
104     /// Additional data for tire proxy bodies
105     struct TireData {
106         std::vector<uint> m_gids;              ///< global indices of proxy bodies
107         std::unordered_map<uint, uint> m_map;  ///< map from global ID to triangle index
108         unsigned int m_start_tri;              ///< start triangle index for proxy body identifiers
109     };
110 
111     ChSystemDistributed* m_system;  ///< containing system
112     bool m_constructed;             ///< system construction completed?
113     bool m_proxies_constructed;     ///< proxy bodies created?
114 
115     int m_sub_rank;  ///< MPI rank within the terrain MPI intracommunicator
116 
117     double m_hthick;                    ///< container wall half-thickness
118     double m_radius_p;                  ///< radius for a proxy body
119     std::vector<TireData> m_tire_data;  ///< data for the vehicle tire proxies
120 
121     utils::SamplingType m_sampling_type;  ///< sampling method for generation of particles
122     double m_init_depth;                  ///< height of granular maerial initialization volume
123     double m_separation_factor;           ///< radius inflation factor for initial particle separation
124     bool m_in_layers;                     ///< initialize material layer-by-layer (true) or all at once (false)
125 
126     unsigned int m_num_particles;  ///< number of granular material bodies
127     double m_radius_g;             ///< radius of one particle of granular material
128     double m_rho_g;                ///< particle material density
129 
SupportsMeshInterface()130     virtual bool SupportsMeshInterface() const override { return true; }
131 
132     virtual void Construct() override;
133 
134     /// Return current total number of contacts.
GetNumContacts()135     virtual int GetNumContacts() const override { return m_system->GetNcontacts(); }
136 
137     virtual void CreateMeshProxies(unsigned int i) override;
138     virtual void UpdateMeshProxies(unsigned int i, MeshState& mesh_state) override;
139     virtual void GetForcesMeshProxies(unsigned int i, MeshContact& mesh_contact) override;
140 
141     virtual void CreateWheelProxy(unsigned int i) override;
142     virtual void UpdateWheelProxy(unsigned int i, BodyState& spindle_state) override;
143     virtual void GetForceWheelProxy(unsigned int i, TerrainForce& wheel_contact) override;
144 
145     virtual void OnAdvance(double step_size) override;
146     virtual void OnOutputData(int frame) override;
147     virtual void Render(double time) override;
148 
149     /// Create the Chrono::Distributed system.
150     void CreateSystem();
151 
152     /// Distribute tire mesh information from main terrain node to intra-communicator.
153     void ScatterInitData(unsigned int i);
154 
155     /// Create the tire mesh proxy bodies.
156     void CreateMeshProxiesInternal(unsigned int i);
157     void CreateWheelProxyInternal(unsigned int i);
158 
159     /// Calculate current height of granular terrain.
160     double CalcCurrentHeight();
161 
162     /// Calculate total kinetic energy of granular material.
163     double CalcTotalKineticEnergy();
164 
165     static ChVector<> CalcBarycentricCoords(const ChVector<>& v1,
166                                             const ChVector<>& v2,
167                                             const ChVector<>& v3,
168                                             const ChVector<>& vP);
169 };
170 
171 /// @} vehicle_cosim_chrono
172 
173 }  // end namespace vehicle
174 }  // end namespace chrono
175 
176 #endif
177