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