void add_fancy_items(ChSystemMPI& mySys, double prad, double pmass, double width, double g, double h, int n_batch, int n_curr_spheres) { int id_offset=10; double particle_mass =4.0; if (pmass>0.0){ particle_mass=pmass; } ChSharedPtr<ChBodyDEMMPI> mybody; double spacing = (width-8*prad)/(n_batch-1); double first = -(width-8*prad)/2; for(int jj=0; jj<n_batch; jj++) { ChVector<> particle_pos(-g+(ChRandom()*2*prad-prad), h, first+jj*spacing); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+jj); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } } }
virtual void onCallback(ChSharedPtr<ChBody> wheelBody, double radius, double width) { wheelBody->GetCollisionModel()->ClearModel(); wheelBody->GetCollisionModel()->AddCylinder(0.46, 0.46, width / 2); wheelBody->GetCollisionModel()->BuildModel(); wheelBody->GetMaterialSurfaceDEM()->SetFriction(mu_t); wheelBody->GetMaterialSurfaceDEM()->SetYoungModulus(Y_t); wheelBody->GetMaterialSurfaceDEM()->SetRestitution(cr_t); }
// ----------------------------------------------------------------------------- // Utility for adding (visible or invisible) walls // ----------------------------------------------------------------------------- void AddWall(ChSharedPtr<ChBody>& body, const ChVector<>& dim, const ChVector<>& loc, bool visible) { body->GetCollisionModel()->AddBox(dim.x, dim.y, dim.z, loc); if (visible == true) { ChSharedPtr<ChBoxShape> box(new ChBoxShape); box->GetBoxGeometry().Size = dim; box->Pos = loc; box->SetColor(ChColor(1, 0, 0)); box->SetFading(0.6f); body->AddAsset(box); } }
virtual void onCallback(ChSharedPtr<ChBody> wheelBody, double radius, double width) { ChCollisionModelParallel* coll_model = (ChCollisionModelParallel*)wheelBody->GetCollisionModel(); coll_model->ClearModel(); // Assemble the tire contact from 15 segments, properly offset. // Each segment is further decomposed in convex hulls. for (int iseg = 0; iseg < 15; iseg++) { ChQuaternion<> rot = Q_from_AngAxis(iseg * 24 * CH_C_DEG_TO_RAD, VECT_Y); for (int ihull = 0; ihull < num_hulls; ihull++) { std::vector<ChVector<> > convexhull; lugged_convex.GetConvexHullResult(ihull, convexhull); coll_model->AddConvexHull(convexhull, VNULL, rot); } } // Add a cylinder to represent the wheel hub. coll_model->AddCylinder(0.223, 0.223, 0.126); coll_model->BuildModel(); wheelBody->GetMaterialSurfaceDEM()->SetFriction(mu_t); wheelBody->GetMaterialSurfaceDEM()->SetYoungModulus(Y_t); wheelBody->GetMaterialSurfaceDEM()->SetRestitution(cr_t); }
void create_falling_items(ChSystemMPI& mySys, double prad, int n_bodies,double box_dim, double pmass){ double particle_mass =4.0; if (pmass>0.0){ particle_mass=pmass; } ChSharedPtr<ChBodyDEMMPI> mybody; double boxxx=box_dim-2*prad; for (int ii=0; ii<n_bodies; ii++){ ChVector<> particle_pos(ChRandom()*boxxx-boxxx/2,ChRandom()*boxxx/2+boxxx/2+prad, ChRandom()*boxxx-boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(10+ii); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } } /* ChVector<> pp1(0.5*box_dim/2,box_dim/2,0.5*box_dim/2); if (mySys.nodeMPI->IsInto(pp1)) { mybody = ChSharedPtr<ChBodyDEMMPI>(new ChBodyDEMMPI); mybody->SetIdentifier(11); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(pp1); mybody->SetMass(particle_mass); mybody->SetInertiaXX((2.0/5.0)*particle_mass*prad*prad*ChVector<>(1.0,1.0,1.0)); } ChVector<> pp2(-0.5*box_dim/2,box_dim/2,0.5*box_dim/2); if (mySys.nodeMPI->IsInto(pp2)) { mybody = ChSharedPtr<ChBodyDEMMPI>(new ChBodyDEMMPI); mybody->SetIdentifier(22); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(pp2); mybody->SetMass(particle_mass); mybody->SetInertiaXX((2.0/5.0)*particle_mass*prad*prad*ChVector<>(1.0,1.0,1.0)); } ChVector<> pp3(0.5*box_dim/2,box_dim/2,-0.5*box_dim/2); if (mySys.nodeMPI->IsInto(pp3)) { mybody = ChSharedPtr<ChBodyDEMMPI>(new ChBodyDEMMPI); mybody->SetIdentifier(33); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(pp3); mybody->SetMass(particle_mass); mybody->SetInertiaXX((2.0/5.0)*particle_mass*prad*prad*ChVector<>(1.0,1.0,1.0)); } ChVector<> pp4(-0.5*box_dim/2,box_dim/2,-0.5*box_dim/2); if (mySys.nodeMPI->IsInto(pp4)) { mybody = ChSharedPtr<ChBodyDEMMPI>(new ChBodyDEMMPI); mybody->SetIdentifier(44); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(pp4); mybody->SetMass(particle_mass); mybody->SetInertiaXX((2.0/5.0)*particle_mass*prad*prad*ChVector<>(1.0,1.0,1.0)); } */ }
void add_batch(ChSystemMPI& mySys, double prad, double box_dim, double pmass, int n_batch, int n_curr_spheres) { int id_offset=10; double particle_mass =4.0; if (pmass>0.0){ particle_mass=pmass; } ChSharedPtr<ChBodyDEMMPI> mybody; double boxxx=box_dim-4*prad; double spacing = (boxxx-8*prad)/((n_batch/4)-1); double first = -boxxx/2; int cid = 0; for(int ii=0; ii<n_batch/4; ii++) { ChVector<> particle_pos(boxxx/2-2*prad,box_dim/2+2*prad, first+ii*spacing+0.0001); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+cid); mybody->SetCollide(true); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mySys.Add(mybody); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } cid++; } for(int ii=0; ii<n_batch/4; ii++) { ChVector<> particle_pos(boxxx/2-6*prad,box_dim/2+2*prad, first+ii*spacing+0.0001); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+cid); mybody->SetCollide(true); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mySys.Add(mybody); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } cid++; } //other edge for(int ii=0; ii<n_batch/4; ii++) { ChVector<> particle_pos(first+ii*spacing+0.0001,box_dim/2+2*prad,boxxx/2-2*prad); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+cid); mybody->SetCollide(true); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mySys.Add(mybody); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } cid++; } for(int ii=0; ii<n_batch/4; ii++) { ChVector<> particle_pos(first+ii*spacing+0.0001,box_dim/2+2*prad,boxxx/2-6*prad); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+cid); mybody->SetCollide(true); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mySys.Add(mybody); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } cid++; } }
void add_falling_item(ChSystemMPI& mySys, double prad, double box_dim, double pmass, int n_curr_spheres) { int id_offset=10; double particle_mass =4.0; if (pmass>0.0){ particle_mass=pmass; } ChSharedPtr<ChBodyDEMMPI> mybody; double boxxx=box_dim-2*prad; ChVector<> particle_pos(0.8*boxxx/2,box_dim/2+2*prad, 0.6*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+1); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos2(0.8*boxxx/2,box_dim/2+2*prad, 0.2*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos2)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+2); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos2); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos3(0.8*boxxx/2,box_dim/2+2*prad, -0.2*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos3)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+3); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos3); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos4(0.8*boxxx/2,box_dim/2+2*prad, -0.6*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos4)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_spheres+4); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddSphere(prad); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos4); mybody->SetInertiaXX((2.0/5.0)*particle_mass*pow(prad,2)*ChVector<>(1,1,1)); mybody->SetMass(particle_mass); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } }
void add_other_falling_item(ChSystemMPI& mySys, double prad, double box_dim, double rho, int n_curr_bodies) { int id_offset=10; double m_s = (2/3)*CH_C_PI*pow(prad,3)*rho; double m_c = CH_C_PI*pow(prad,2)*(2*prad)*rho; double m_cube = prad*prad*prad*rho; ChVector<> pos1(0,prad,0); ChVector<> pos2(0,-prad,0); ChSharedPtr<ChBodyDEMMPI> mybody; double boxxx=box_dim-2*prad; ChVector<> particle_pos(0.8*boxxx/2,box_dim/2+2*prad, 0.6*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_bodies+1); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddBox(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos1); //mybody->GetCollisionModel()->AddCylinder(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos2); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos); //mybody->SetInertiaXX(ChVector<>(((7.0/12)*m_c+4.3*m_s)*pow(prad,2),(0.5*m_c+0.8*m_s)*pow(prad,2),((7.0/12)*m_c+4.3*m_s)*pow(prad,2))); //mybody->SetMass(m_c+2*m_s); mybody->SetInertiaXX((1.0/6.0)*m_cube*pow(prad,2)*ChVector<>(1.0,1.0,1.0)); mybody->SetMass(m_cube); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos2(0.8*boxxx/2,box_dim/2+2*prad, 0.2*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos2)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_bodies+2); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddBox(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos1); //mybody->GetCollisionModel()->AddCylinder(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos2); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos2); //mybody->SetInertiaXX(ChVector<>(((7.0/12)*m_c+4.3*m_s)*pow(prad,2),(0.5*m_c+0.8*m_s)*pow(prad,2),((7.0/12)*m_c+4.3*m_s)*pow(prad,2))); //mybody->SetMass(m_c+2*m_s); mybody->SetInertiaXX((1.0/6.0)*m_cube*pow(prad,2)*ChVector<>(1.0,1.0,1.0)); mybody->SetMass(m_cube); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos3(0.8*boxxx/2,box_dim/2+2*prad, -0.2*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos3)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_bodies+3); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddBox(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos1); //mybody->GetCollisionModel()->AddCylinder(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos2); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos3); //mybody->SetInertiaXX(ChVector<>(((7.0/12)*m_c+4.3*m_s)*pow(prad,2),(0.5*m_c+0.8*m_s)*pow(prad,2),((7.0/12)*m_c+4.3*m_s)*pow(prad,2))); //mybody->SetMass(m_c+2*m_s); mybody->SetInertiaXX((1.0/6.0)*m_cube*pow(prad,2)*ChVector<>(1.0,1.0,1.0)); mybody->SetMass(m_cube); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } ChVector<> particle_pos4(0.8*boxxx/2,box_dim/2+2*prad, -0.6*boxxx/2); if (mySys.nodeMPI->IsInto(particle_pos4)) { ChSharedPtr<ChBodyDEMMPI> mybody(new ChBodyDEMMPI); mybody->SetIdentifier(id_offset+n_curr_bodies+4); mySys.Add(mybody); mybody->GetCollisionModel()->ClearModel(); mybody->GetCollisionModel()->AddBox(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos1); //mybody->GetCollisionModel()->AddCylinder(prad,prad,prad); //mybody->GetCollisionModel()->AddSphere(prad, &pos2); mybody->GetCollisionModel()->BuildModel(); mybody->SetCollide(true); mybody->SetPos(particle_pos4); //mybody->SetInertiaXX(ChVector<>(((7.0/12)*m_c+4.3*m_s)*pow(prad,2),(0.5*m_c+0.8*m_s)*pow(prad,2),((7.0/12)*m_c+4.3*m_s)*pow(prad,2))); //mybody->SetMass(m_c+2*m_s); mybody->SetInertiaXX((1.0/6.0)*m_cube*pow(prad,2)*ChVector<>(1.0,1.0,1.0)); mybody->SetMass(m_cube); mybody->GetCollisionModel()->SyncPosition(); // really necessary? mybody->Update(); // really necessary? } }
int main(int argc, char* argv[]) { // Set path to ChronoVehicle data files vehicle::SetDataPath(CHRONO_VEHICLE_DATA_DIR); // -------------------------- // Create output directories. // -------------------------- if (povray_output) { if (ChFileutils::MakeDirectory(out_dir.c_str()) < 0) { cout << "Error creating directory " << out_dir << endl; return 1; } if (ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) { cout << "Error creating directory " << pov_dir << endl; return 1; } } // -------------- // Create system. // -------------- ChSystemParallelDEM* system = new ChSystemParallelDEM(); system->Set_G_acc(ChVector<>(0, 0, -9.81)); // ---------------------- // Enable debug log // ---------------------- ////system->SetLoggingLevel(LOG_INFO, true); ////system->SetLoggingLevel(LOG_TRACE, true); // ---------------------- // Set number of threads. // ---------------------- int max_threads = omp_get_num_procs(); if (threads > max_threads) threads = max_threads; system->SetParallelThreadNumber(threads); omp_set_num_threads(threads); cout << "Using " << threads << " threads" << endl; system->GetSettings()->perform_thread_tuning = thread_tuning; // --------------------- // Edit system settings. // --------------------- system->GetSettings()->solver.use_full_inertia_tensor = false; system->GetSettings()->solver.tolerance = tolerance; system->GetSettings()->solver.max_iteration_bilateral = max_iteration_bilateral; system->GetSettings()->solver.contact_force_model = contact_force_model; system->GetSettings()->solver.tangential_displ_mode = tangential_displ_mode; system->GetSettings()->collision.narrowphase_algorithm = NARROWPHASE_HYBRID_MPR; system->GetSettings()->collision.bins_per_axis = I3(20, 20, 10); // ------------------- // Create the terrain. // ------------------- // Ground body ChSharedPtr<ChBody> ground = ChSharedPtr<ChBody>(new ChBody(new collision::ChCollisionModelParallel, ChBody::DEM)); ground->SetIdentifier(-1); ground->SetMass(1000); ground->SetBodyFixed(true); ground->SetCollide(true); ground->GetMaterialSurfaceDEM()->SetFriction(mu_g); ground->GetMaterialSurfaceDEM()->SetYoungModulus(Y_g); ground->GetMaterialSurfaceDEM()->SetRestitution(cr_g); ground->GetMaterialSurfaceDEM()->SetCohesion(cohesion_g); ground->GetCollisionModel()->ClearModel(); // Bottom box utils::AddBoxGeometry(ground.get_ptr(), ChVector<>(hdimX, hdimY, hthick), ChVector<>(0, 0, -hthick), ChQuaternion<>(1, 0, 0, 0), true); if (terrain_type == GRANULAR) { // Front box utils::AddBoxGeometry(ground.get_ptr(), ChVector<>(hthick, hdimY, hdimZ + hthick), ChVector<>(hdimX + hthick, 0, hdimZ - hthick), ChQuaternion<>(1, 0, 0, 0), visible_walls); // Rear box utils::AddBoxGeometry(ground.get_ptr(), ChVector<>(hthick, hdimY, hdimZ + hthick), ChVector<>(-hdimX - hthick, 0, hdimZ - hthick), ChQuaternion<>(1, 0, 0, 0), visible_walls); // Left box utils::AddBoxGeometry(ground.get_ptr(), ChVector<>(hdimX, hthick, hdimZ + hthick), ChVector<>(0, hdimY + hthick, hdimZ - hthick), ChQuaternion<>(1, 0, 0, 0), visible_walls); // Right box utils::AddBoxGeometry(ground.get_ptr(), ChVector<>(hdimX, hthick, hdimZ + hthick), ChVector<>(0, -hdimY - hthick, hdimZ - hthick), ChQuaternion<>(1, 0, 0, 0), visible_walls); } ground->GetCollisionModel()->BuildModel(); system->AddBody(ground); // Create the granular material. double vertical_offset = 0; if (terrain_type == GRANULAR) { vertical_offset = CreateParticles(system); } // ----------------------------------------- // Create and initialize the vehicle system. // ----------------------------------------- utils::VehicleSystem* vehicle; utils::TireContactCallback* tire_cb; // Create the vehicle assembly and the callback object for tire contact // according to the specified type of tire/wheel. switch (wheel_type) { case CYLINDRICAL: { vehicle = new utils::VehicleSystem(system, vehicle_file_cyl, simplepowertrain_file); tire_cb = new MyCylindricalTire(); } break; case LUGGED: { vehicle = new utils::VehicleSystem(system, vehicle_file_lug, simplepowertrain_file); tire_cb = new MyLuggedTire(); } break; } vehicle->SetTireContactCallback(tire_cb); // Set the callback object for driver inputs. Pass the hold time as a delay in // generating driver inputs. MyDriverInputs driver_cb(time_hold); vehicle->SetDriverInputsCallback(&driver_cb); // Initialize the vehicle at a height above the terrain. vehicle->Initialize(initLoc + ChVector<>(0, 0, vertical_offset), initRot); // Initially, fix the chassis and wheel bodies (will be released after time_hold). vehicle->GetVehicle()->GetChassis()->SetBodyFixed(true); for (int i = 0; i < 2 * vehicle->GetVehicle()->GetNumberAxles(); i++) { vehicle->GetVehicle()->GetWheelBody(i)->SetBodyFixed(true); } // ----------------------- // Perform the simulation. // ----------------------- #ifdef CHRONO_PARALLEL_HAS_OPENGL // Initialize OpenGL opengl::ChOpenGLWindow& gl_window = opengl::ChOpenGLWindow::getInstance(); gl_window.Initialize(1280, 720, "HMMWV", system); gl_window.SetCamera(ChVector<>(0, -10, 0), ChVector<>(0, 0, 0), ChVector<>(0, 0, 1)); gl_window.SetRenderMode(opengl::WIREFRAME); #endif // Run simulation for specified time. int out_steps = std::ceil((1.0 / time_step) / out_fps); double time = 0; int sim_frame = 0; int out_frame = 0; int next_out_frame = 0; double exec_time = 0; int num_contacts = 0; while (time < time_end) { // If enabled, output data for PovRay postprocessing. if (sim_frame == next_out_frame) { cout << endl; cout << "---- Frame: " << out_frame + 1 << endl; cout << " Sim frame: " << sim_frame << endl; cout << " Time: " << time << endl; cout << " Speed: " << vehicle->GetVehicle()->GetVehicleSpeed() << endl; cout << " Avg. contacts: " << num_contacts / out_steps << endl; cout << " Execution time: " << exec_time << endl; if (povray_output) { char filename[100]; sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), out_frame + 1); utils::WriteShapesPovray(system, filename); } out_frame++; next_out_frame += out_steps; num_contacts = 0; } // Release the vehicle chassis at the end of the hold time. if (vehicle->GetVehicle()->GetChassis()->GetBodyFixed() && time > time_hold) { cout << endl << "Release vehicle t = " << time << endl; vehicle->GetVehicle()->GetChassis()->SetBodyFixed(false); for (int i = 0; i < 2 * vehicle->GetVehicle()->GetNumberAxles(); i++) { vehicle->GetVehicle()->GetWheelBody(i)->SetBodyFixed(false); } } // Update vehicle vehicle->Update(time); // Advance dynamics. #ifdef CHRONO_PARALLEL_HAS_OPENGL if (gl_window.Active()) { gl_window.DoStepDynamics(time_step); gl_window.Render(); } else break; #else system->DoStepDynamics(time_step); #endif ////progressbar(out_steps + sim_frame - next_out_frame + 1, out_steps); TimingOutput(system); // Periodically display maximum constraint violation if (monitor_bilaterals && sim_frame % bilateral_frame_interval == 0) { std::vector<double> cvec; ////vehicle->GetVehicle()->LogConstraintViolations(); cout << " Max. violation = " << system->CalculateConstraintViolation(cvec) << endl; } // Update counters. time += time_step; sim_frame++; exec_time += system->GetTimerStep(); num_contacts += system->GetNcontacts(); } // Final stats cout << "==================================" << endl; cout << "Simulation time: " << exec_time << endl; cout << "Number of threads: " << threads << endl; delete vehicle; delete tire_cb; return 0; }
int main(int argc, char* argv[]) { // Create output directories. if (ChFileutils::MakeDirectory(out_dir.c_str()) < 0) { cout << "Error creating directory " << out_dir << endl; return 1; } if (ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) { cout << "Error creating directory " << pov_dir << endl; return 1; } // ------------- // Create system // ------------- #ifdef USE_DEM cout << "Create DEM system" << endl; ChSystemParallelDEM* msystem = new ChSystemParallelDEM(); #else cout << "Create DVI system" << endl; ChSystemParallelDVI* msystem = new ChSystemParallelDVI(); #endif msystem->Set_G_acc(ChVector<>(0, 0, -gravity)); // Set number of threads. int max_threads = omp_get_num_procs(); if (threads > max_threads) threads = max_threads; msystem->SetParallelThreadNumber(threads); omp_set_num_threads(threads); cout << "Using " << threads << " threads" << endl; msystem->GetSettings()->max_threads = threads; msystem->GetSettings()->perform_thread_tuning = thread_tuning; // Edit system settings msystem->GetSettings()->solver.use_full_inertia_tensor = false; msystem->GetSettings()->solver.tolerance = tolerance; msystem->GetSettings()->solver.max_iteration_bilateral = max_iteration_bilateral; msystem->GetSettings()->solver.clamp_bilaterals = clamp_bilaterals; msystem->GetSettings()->solver.bilateral_clamp_speed = bilateral_clamp_speed; #ifdef USE_DEM msystem->GetSettings()->collision.narrowphase_algorithm = NARROWPHASE_R; msystem->GetSettings()->solver.contact_force_model = contact_force_model; msystem->GetSettings()->solver.tangential_displ_mode = tangential_displ_mode; #else msystem->GetSettings()->solver.solver_mode = SLIDING; msystem->GetSettings()->solver.max_iteration_normal = max_iteration_normal; msystem->GetSettings()->solver.max_iteration_sliding = max_iteration_sliding; msystem->GetSettings()->solver.max_iteration_spinning = max_iteration_spinning; msystem->GetSettings()->solver.alpha = 0; msystem->GetSettings()->solver.contact_recovery_speed = contact_recovery_speed; msystem->SetMaxPenetrationRecoverySpeed(contact_recovery_speed); msystem->ChangeSolverType(APGDREF); msystem->GetSettings()->collision.collision_envelope = 0.05 * r_g; #endif msystem->GetSettings()->collision.bins_per_axis = I3(10, 10, 10); // -------------- // Problem set up // -------------- // Depending on problem type: // - Select end simulation time // - Select output FPS // - Create / load objects double time_min = 0; double time_end; int out_fps; ChSharedPtr<ChBody> ground; ChSharedPtr<ChBody> loadPlate; ChSharedPtr<ChLinkLockPrismatic> prismatic; ChSharedPtr<ChLinkLinActuator> actuator; switch (problem) { case SETTLING: { time_min = time_settling_min; time_end = time_settling_max; out_fps = out_fps_settling; // Create the mechanism bodies (all fixed). CreateMechanismBodies(msystem); // Grab handles to mechanism bodies (must increase ref counts) ground = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(0)); loadPlate = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(1)); msystem->Get_bodylist()->at(0)->AddRef(); msystem->Get_bodylist()->at(1)->AddRef(); // Create granular material. int num_particles = CreateGranularMaterial(msystem); cout << "Granular material: " << num_particles << " particles" << endl; break; } case PRESSING: { time_min = time_pressing_min; time_end = time_pressing_max; out_fps = out_fps_pressing; // Create bodies from checkpoint file. cout << "Read checkpoint data from " << settled_ckpnt_file; utils::ReadCheckpoint(msystem, settled_ckpnt_file); cout << " done. Read " << msystem->Get_bodylist()->size() << " bodies." << endl; // Grab handles to mechanism bodies (must increase ref counts) ground = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(0)); loadPlate = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(1)); msystem->Get_bodylist()->at(0)->AddRef(); msystem->Get_bodylist()->at(1)->AddRef(); // Move the load plate just above the granular material. double highest, lowest; FindHeightRange(msystem, lowest, highest); ChVector<> pos = loadPlate->GetPos(); double z_new = highest + 1.01 * r_g; loadPlate->SetPos(ChVector<>(pos.x, pos.y, z_new)); // Add collision geometry to plate loadPlate->GetCollisionModel()->ClearModel(); utils::AddBoxGeometry(loadPlate.get_ptr(), ChVector<>(hdimX_p, hdimY_p, hdimZ_p), ChVector<>(0, 0, hdimZ_p)); loadPlate->GetCollisionModel()->BuildModel(); // If using an actuator, connect the load plate and get a handle to the actuator. if (use_actuator) { ConnectLoadPlate(msystem, ground, loadPlate); prismatic = msystem->SearchLink("prismatic").StaticCastTo<ChLinkLockPrismatic>(); actuator = msystem->SearchLink("actuator").StaticCastTo<ChLinkLinActuator>(); } // Release the load plate. loadPlate->SetBodyFixed(!use_actuator); break; } case TESTING: { time_end = time_testing; out_fps = out_fps_testing; // For TESTING only, increse shearing velocity. desiredVelocity = 0.5; // Create the mechanism bodies (all fixed). CreateMechanismBodies(msystem); // Create the test ball. CreateBall(msystem); // Grab handles to mechanism bodies (must increase ref counts) ground = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(0)); loadPlate = ChSharedPtr<ChBody>(msystem->Get_bodylist()->at(1)); msystem->Get_bodylist()->at(0)->AddRef(); msystem->Get_bodylist()->at(1)->AddRef(); // Move the load plate just above the test ball. ChVector<> pos = loadPlate->GetPos(); double z_new = 2.1 * radius_ball; loadPlate->SetPos(ChVector<>(pos.x, pos.y, z_new)); // Add collision geometry to plate loadPlate->GetCollisionModel()->ClearModel(); utils::AddBoxGeometry(loadPlate.get_ptr(), ChVector<>(hdimX_p, hdimY_p, hdimZ_p), ChVector<>(0, 0, hdimZ_p)); loadPlate->GetCollisionModel()->BuildModel(); // If using an actuator, connect the shear box and get a handle to the actuator. if (use_actuator) { ConnectLoadPlate(msystem, ground, loadPlate); actuator = msystem->SearchLink("actuator").StaticCastTo<ChLinkLinActuator>(); } // Release the shear box when using an actuator. loadPlate->SetBodyFixed(!use_actuator); break; } } // ---------------------- // Perform the simulation // ---------------------- // Set number of simulation steps and steps between successive output int num_steps = (int)std::ceil(time_end / time_step); int out_steps = (int)std::ceil((1.0 / time_step) / out_fps); int write_steps = (int)std::ceil((1.0 / time_step) / write_fps); // Initialize counters double time = 0; int sim_frame = 0; int out_frame = 0; int next_out_frame = 0; double exec_time = 0; int num_contacts = 0; double max_cnstr_viol[2] = {0, 0}; // Circular buffer with highest particle location // (only used for SETTLING or PRESSING) int buffer_size = std::ceil(time_min / time_step); std::valarray<double> hdata(0.0, buffer_size); // Create output files ChStreamOutAsciiFile statsStream(stats_file.c_str()); ChStreamOutAsciiFile sinkageStream(sinkage_file.c_str()); sinkageStream.SetNumFormat("%16.4e"); #ifdef CHRONO_PARALLEL_HAS_OPENGL opengl::ChOpenGLWindow& gl_window = opengl::ChOpenGLWindow::getInstance(); gl_window.Initialize(1280, 720, "Pressure Sinkage Test", msystem); gl_window.SetCamera(ChVector<>(0, -10 * hdimY, hdimZ), ChVector<>(0, 0, hdimZ), ChVector<>(0, 0, 1)); gl_window.SetRenderMode(opengl::WIREFRAME); #endif // Loop until reaching the end time... while (time < time_end) { // Current position and velocity of the shear box ChVector<> pos_old = loadPlate->GetPos(); ChVector<> vel_old = loadPlate->GetPos_dt(); // Calculate minimum and maximum particle heights double highest, lowest; FindHeightRange(msystem, lowest, highest); // If at an output frame, write PovRay file and print info if (sim_frame == next_out_frame) { cout << "------------ Output frame: " << out_frame + 1 << endl; cout << " Sim frame: " << sim_frame << endl; cout << " Time: " << time << endl; cout << " Load plate pos: " << pos_old.z << endl; cout << " Lowest point: " << lowest << endl; cout << " Highest point: " << highest << endl; cout << " Execution time: " << exec_time << endl; // Save PovRay post-processing data. if (write_povray_data) { char filename[100]; sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), out_frame + 1); utils::WriteShapesPovray(msystem, filename, false); } // Create a checkpoint from the current state. if (problem == SETTLING || problem == PRESSING) { cout << " Write checkpoint data " << flush; if (problem == SETTLING) utils::WriteCheckpoint(msystem, settled_ckpnt_file); else utils::WriteCheckpoint(msystem, pressed_ckpnt_file); cout << msystem->Get_bodylist()->size() << " bodies" << endl; } // Increment counters out_frame++; next_out_frame += out_steps; } // Check for early termination of a settling phase. if (problem == SETTLING) { // Store maximum particle height in circular buffer hdata[sim_frame % buffer_size] = highest; // Check variance of data in circular buffer if (time > time_min) { double mean_height = hdata.sum() / buffer_size; std::valarray<double> x = hdata - mean_height; double var = std::sqrt((x * x).sum() / buffer_size); // Consider the material settled when the variance is below the // specified fraction of a particle radius if (var < settling_tol * r_g) { cout << "Granular material settled... time = " << time << endl; break; } } } // Advance simulation by one step #ifdef CHRONO_PARALLEL_HAS_OPENGL if (gl_window.Active()) { gl_window.DoStepDynamics(time_step); gl_window.Render(); } else break; #else msystem->DoStepDynamics(time_step); #endif TimingOutput(msystem); // Record stats about the simulation if (sim_frame % write_steps == 0) { // write stat info int numIters = msystem->data_manager->measures.solver.maxd_hist.size(); double residual = 0; if (numIters) residual = msystem->data_manager->measures.solver.residual; statsStream << time << ", " << exec_time << ", " << num_contacts / write_steps << ", " << numIters << ", " << residual << ", " << max_cnstr_viol[0] << ", " << max_cnstr_viol[1] << ", \n"; statsStream.GetFstream().flush(); num_contacts = 0; max_cnstr_viol[0] = 0; max_cnstr_viol[1] = 0; } if (problem == PRESSING || problem == TESTING) { // Get the current reaction force or impose load plate position double cnstr_force = 0; if (use_actuator) { cnstr_force = actuator->Get_react_force().x; } else { double zpos_new = pos_old.z + desiredVelocity * time_step; loadPlate->SetPos(ChVector<>(pos_old.x, pos_old.y, zpos_new)); loadPlate->SetPos_dt(ChVector<>(0, 0, desiredVelocity)); } if (sim_frame % write_steps == 0) { // std::cout << time << ", " << loadPlate->GetPos().z << ", " << cnstr_force << ", \n"; sinkageStream << time << ", " << loadPlate->GetPos().z << ", " << cnstr_force << ", \n"; sinkageStream.GetFstream().flush(); } } // Find maximum constraint violation if (!prismatic.IsNull()) { ChMatrix<>* C = prismatic->GetC(); for (int i = 0; i < 5; i++) max_cnstr_viol[0] = std::max(max_cnstr_viol[0], std::abs(C->GetElement(i, 0))); } if (!actuator.IsNull()) { ChMatrix<>* C = actuator->GetC(); max_cnstr_viol[1] = std::max(max_cnstr_viol[2], std::abs(C->GetElement(0, 0))); } // Increment counters time += time_step; sim_frame++; exec_time += msystem->GetTimerStep(); num_contacts += msystem->GetNcontacts(); // If requested, output detailed timing information for this step if (sim_frame == timing_frame) msystem->PrintStepStats(); } // ---------------- // Final processing // ---------------- // Create a checkpoint from the last state if (problem == SETTLING || problem == PRESSING) { cout << " Write checkpoint data " << flush; if (problem == SETTLING) utils::WriteCheckpoint(msystem, settled_ckpnt_file); else utils::WriteCheckpoint(msystem, pressed_ckpnt_file); cout << msystem->Get_bodylist()->size() << " bodies" << endl; } // Final stats cout << "==================================" << endl; cout << "Number of bodies: " << msystem->Get_bodylist()->size() << endl; cout << "Simulation time: " << exec_time << endl; cout << "Number of threads: " << threads << endl; return 0; }