void RunTimeStep(T* mSys, const int frame) { if (!save) { Vector force = engine_anchor->Get_react_force(); Vector torque = engine_anchor->Get_react_torque(); double motor_torque = engine_anchor->Get_mot_torque(); cout << force.x << " " << force.y << " " << force.z << " " << torque.x << " " << torque.y << " " << torque.z << " " << motor_torque << " " << ANCHOR->GetPos().y << " " << ANCHOR->GetPos_dt().y << endl; ANCHOR->SetPos(ChVector<>(REFERENCE->GetPos().x, ANCHOR->GetPos().y, REFERENCE->GetPos().z)); ANCHOR->SetPos_dt(ChVector<>(REFERENCE->GetPos_dt().x, ANCHOR->GetPos_dt().y, REFERENCE->GetPos_dt().z)); ANCHOR->SetRot(REFERENCE->GetRot()); ANCHOR->SetWvel_loc(REFERENCE->GetWvel_loc()); REFERENCE->SetPos(ChVector<>(REFERENCE->GetPos().x, ANCHOR->GetPos().y, REFERENCE->GetPos().z)); REFERENCE->SetPos_dt(ChVector<>(REFERENCE->GetPos_dt().x, ANCHOR->GetPos_dt().y, REFERENCE->GetPos_dt().z)); } // real t = frame * timestep * PI * 2 * frequency; // // BLOCK->SetRot(ChQuaternion<>(1, 0, 0, 0)); // BLOCK->SetWvel_loc(ChVector<>(0, 0, 0)); // BLOCK->SetPos(ChVector<>(sin(t) * amplitude, BLOCK->GetPos().y, 0)); // BLOCK->SetPos_dt(ChVector<>(cos(t) * amplitude * 2 * PI * frequency, BLOCK->GetPos_dt().y, 0)); // // CONTAINER->SetPos(ChVector<>(sin(t) * amplitude, 0, 0)); // CONTAINER->SetPos_dt(ChVector<>(cos(t) * amplitude * 2 * PI * frequency, 0, 0)); // CONTAINER->SetWvel_loc(ChVector<>(0, 0, 0)); // CONTAINER->SetRot(ChQuaternion<>(1, 0, 0, 0)); // // // real cont_vol = (container_size.x - container_thickness * 2) * 2 * (BLOCK->GetPos().y + container_size.y - 2 * container_thickness) * (container_size.z - container_thickness * 2) * 2; // cout << layer_gen->total_volume << " " << layer_gen->total_mass << " " << cont_vol << " " << layer_gen->total_mass / cont_vol << endl; // if (save) { if (layers < 130 && frame % 80 == 0) { cout << layers << endl; layer_gen->addPerturbedVolumeMixture(R3(0, -container_size.y + container_thickness + particle_radius * 5 + frame / 14.0, 0), I3(32, 1, 32), R3(0, 0, 0), R3(0, 0, 0)); layers++; } } else { //300 - 457.2 // double time = actuator_anchor->GetChTime(); // if (ANCHOR->GetPos().y <= 300 - 457.2 && once) { // motionFunc1->Set_y0(time * -anchor_vel); // motionFunc1->Set_ang(-2); //// motionFunc2->Set_y0(time * -anchor_rot * 1 / 60.0 * 2 * CH_C_PI); //// motionFunc2->Set_ang(0); // if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(engine_anchor->Get_spe_funct())) { // mfun->Set_yconst(0); // rad/s angular speed // } // once = false; // } } }
int main(int argc, char* argv[]) { save = atoi(argv[1]); cout << save << endl; if (save) { seconds_to_simulate = 5; num_steps = seconds_to_simulate / timestep; } else { seconds_to_simulate = 300; num_steps = seconds_to_simulate / timestep; } if (argc > 2) { particle_slide_friction = atof(argv[2]); particle_roll_friction = atof(argv[3]); particle_cohesion = atof(argv[4]); data_folder = argv[5]; cout << particle_slide_friction << " " << particle_roll_friction << " " << particle_roll_friction << endl; } //========================================================================================================= ChSystemParallelDVI * system_gpu = new ChSystemParallelDVI; //========================================================================================================= //system_gpu->SetMinThreads(32); //system_gpu->SetMaxiter(max_iter); //system_gpu->SetIterLCPmaxItersSpeed(max_iter); ((ChSystemParallelDVI*) system_gpu)->DoThreadTuning(true); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIterationNormal(max_iter); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIterationSliding(max_iter); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIterationSpinning(max_iter); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIterationBilateral(0); system_gpu->SetTol(tolerance); system_gpu->SetTolSpeeds(tolerance); system_gpu->SetMaxPenetrationRecoverySpeed(1e9); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetTolerance(tolerance); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetCompliance(0); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetContactRecoverySpeed(100); ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->SetSolverType(APGDRS); //((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->DoStabilization(true); ((ChCollisionSystemParallel *) (system_gpu->GetCollisionSystem()))->SetCollisionEnvelope(particle_radius * .05); ((ChCollisionSystemParallel *) (system_gpu->GetCollisionSystem()))->setBinsPerAxis(I3(30, 60, 30)); ((ChCollisionSystemParallel *) (system_gpu->GetCollisionSystem()))->setBodyPerBin(100, 50); system_gpu->Set_G_acc(ChVector<>(0, gravity, 0)); system_gpu->SetStep(timestep); ((ChSystemParallel*) system_gpu)->SetAABB(R3(-250, -600, -250), R3(250, 600, 250)); //========================================================================================================= ChSharedPtr<ChMaterialSurface> material; material = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface); material->SetFriction(container_friction); material->SetRollingFriction(container_friction); material->SetSpinningFriction(container_friction); material->SetCompliance(0); material->SetCohesion(-100); CONTAINER = ChSharedBodyPtr(new ChBody(new ChCollisionModelParallel)); InitObject(CONTAINER, 100000, Vector(0, 0, 0), Quaternion(1, 0, 0, 0), material, true, true, -20, -20); if (save) { AddCollisionGeometry( CONTAINER, BOX, Vector(container_thickness, container_size.y, container_size.z), Vector(-container_size.x + container_thickness, container_height - container_thickness, 0), Quaternion(1, 0, 0, 0)); AddCollisionGeometry( CONTAINER, BOX, Vector(container_thickness, container_size.y, container_size.z), Vector(container_size.x - container_thickness, container_height - container_thickness, 0), Quaternion(1, 0, 0, 0)); AddCollisionGeometry( CONTAINER, BOX, Vector(container_size.x, container_size.y, container_thickness), Vector(0, container_height - container_thickness, -container_size.z + container_thickness), Quaternion(1, 0, 0, 0)); AddCollisionGeometry( CONTAINER, BOX, Vector(container_size.x, container_size.y, container_thickness), Vector(0, container_height - container_thickness, container_size.z - container_thickness), Quaternion(1, 0, 0, 0)); AddCollisionGeometry( CONTAINER, BOX, Vector(container_size.x, container_thickness, container_size.z), Vector(0, container_height - container_size.y, 0), Quaternion(1, 0, 0, 0)); //AddCollisionGeometry(CONTAINER, BOX, Vector(container_size.x, container_thickness, container_size.z), Vector(0, container_height + container_size.y, 0), Quaternion(1, 0, 0, 0)); } CONTAINER->GetMaterialSurface()->SetCohesion(container_cohesion); FinalizeObject(CONTAINER, (ChSystemParallel *) system_gpu); if (save == false) { real anchor_length = 100; real anchor_r = 35 / 2.0; real anchor_R = 150 / 4.0; real anchor_h = 50; real anchor_thickness = 6 / 2.0; real anchor_blade_width = 8; ChVector<> p1(0, 0, 0); ChVector<> p2(0, anchor_length, 0); real anchor_mass = 6208; real number_sections = 30; REFERENCE = ChSharedBodyPtr(new ChBody(new ChCollisionModelParallel)); InitObject(REFERENCE, anchor_mass, Vector(0, 200, 0), Quaternion(1, 0, 0, 0), material, false, false, -15, -15); // AddCollisionGeometry(REFERENCE, SPHERE, ChVector<>(anchor_r, 0, 0), p1, Quaternion(1, 0, 0, 0)); // AddCollisionGeometry(REFERENCE, CYLINDER, Vector(anchor_r, anchor_length, anchor_r), p2, Quaternion(1, 0, 0, 0)); // for (int i = 0; i < number_sections; i++) { // ChQuaternion<> quat, quat2; // quat.Q_from_AngAxis(i / number_sections * 2 * PI, ChVector<>(0, 1, 0)); // quat2.Q_from_AngAxis(6.5 * 2 * PI / 360.0, ChVector<>(0, 0, 1)); // quat = quat % quat2; // ChVector<> pos(sin(i / number_sections * 2 * PI) * anchor_R, i / number_sections * anchor_h, cos(i / number_sections * 2 * PI) * anchor_R); // //ChMatrix33<> mat(quat); // AddCollisionGeometry(REFERENCE, BOX, ChVector<>(anchor_blade_width, anchor_thickness, anchor_R), pos, quat); // } ANCHOR = ChSharedBodyPtr(new ChBody(new ChCollisionModelParallel)); InitObject(ANCHOR, anchor_mass, Vector(0, 200, 0), Quaternion(1, 0, 0, 0), material, true, false, -15, -15); AddCollisionGeometry(ANCHOR, SPHERE, ChVector<>(anchor_r, 0, 0), p1, Quaternion(1, 0, 0, 0)); AddCollisionGeometry(ANCHOR, CYLINDER, Vector(anchor_r, anchor_length, anchor_r), p2, Quaternion(1, 0, 0, 0)); // for (int i = 0; i < number_sections; i++) { ChQuaternion<> quat, quat2; quat.Q_from_AngAxis(i / number_sections * 2 * PI, ChVector<>(0, 1, 0)); quat2.Q_from_AngAxis(6.5 * 2 * PI / 360.0, ChVector<>(0, 0, 1)); quat = quat % quat2; ChVector<> pos(sin(i / number_sections * 2 * PI) * anchor_R, i / number_sections * anchor_h, cos(i / number_sections * 2 * PI) * anchor_R); //ChMatrix33<> mat(quat); AddCollisionGeometry(ANCHOR, BOX, ChVector<>(anchor_blade_width, anchor_thickness, anchor_R), pos, quat); } FinalizeObject(ANCHOR, (ChSystemParallel *) system_gpu); FinalizeObject(REFERENCE, (ChSystemParallel *) system_gpu); // real vol = ((ChCollisionModelParallel *) ANCHOR->GetCollisionModel())->getVolume(); // real den = .00785; // anchor_mass = den*vol; // cout<<vol<<" "<<anchor_mass<<endl; // ANCHOR->SetMass(anchor_mass); ANCHOR->SetInertiaXX(ChVector<>(12668786.72, 5637598.31, 12682519.69)); REFERENCE->SetInertiaXX(ChVector<>(12668786.72, 5637598.31, 12682519.69)); // ANCHOR->SetInertiaXX( // ChVector<>( // 1 / 12.0 * anchor_mass * (1 * 1 + anchor_R * anchor_R), // 1 / 12.0 * anchor_mass * (anchor_R * anchor_R + anchor_R * anchor_R), // 1 / 12.0 * anchor_mass * (anchor_R * anchor_R + 1 * 1))); //BLOCK = ChSharedBodyPtr(new ChBody(new ChCollisionModelParallel)); //InitObject(BLOCK, anchor_mass/2, Vector(0, 300, 0), Quaternion(1, 0, 0, 0), material, false, false, -20, -20); //AddCollisionGeometry(BLOCK, BOX, ChVector<>(1, 1, 1), Vector(0, 0, 0), Quaternion(1, 0, 0, 0)); //FinalizeObject(BLOCK, (ChSystemParallel *) system_gpu); //actuator_anchor = ChSharedPtr<ChLinkLockLock>(new ChLinkLockLock()); //actuator_anchor->Initialize(CONTAINER, BLOCK, ChCoordsys<>(ChVector<>(0, 0, 0), QUNIT)); //system_gpu->AddLink(actuator_anchor); // apply motion //motionFunc1 = new ChFunction_Ramp(0, -anchor_vel); //actuator_anchor->SetMotion_Y(motionFunc1); //actuator_anchor->SetMotion_axis(ChVector<>(0, 1, 0)); engine_anchor = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); engine_anchor->Initialize(CONTAINER, ANCHOR, ChCoordsys<>(ANCHOR->GetPos(), chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_X))); engine_anchor->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_PRISM); // also works as revolute support engine_anchor->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED); system_gpu->AddLink(engine_anchor); reference_engine = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); reference_engine->Initialize(CONTAINER, REFERENCE, ChCoordsys<>(REFERENCE->GetPos(), chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_X))); reference_engine->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_PRISM); // also works as revolute support reference_engine->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED); system_gpu->AddLink(reference_engine); if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(engine_anchor->Get_spe_funct())) { mfun->Set_yconst(anchor_rot * 1 / 60.0 * 2 * CH_C_PI); // rad/s angular speed } if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(reference_engine->Get_spe_funct())) { mfun->Set_yconst(anchor_rot * 1 / 60.0 * 2 * CH_C_PI); // rad/s angular speed } ReadAllObjectsWithGeometryChrono(system_gpu, "data/anchor/anchor.dat"); ChSharedPtr<ChMaterialSurface> material_read; material_read = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface); material_read->SetFriction(particle_slide_friction); material_read->SetRollingFriction(particle_roll_friction); material_read->SetSpinningFriction(particle_roll_friction); material_read->SetCompliance(0); material_read->SetCohesion(particle_cohesion * timestep); for (int i = 0; i < system_gpu->Get_bodylist()->size(); i++) { system_gpu->Get_bodylist()->at(i)->SetMaterialSurface(material_read); } } else { layer_gen = new ParticleGenerator<ChSystemParallelDVI>((ChSystemParallelDVI *) system_gpu); layer_gen->SetDensity(particle_density); layer_gen->SetRadius(R3(particle_radius, particle_radius * .5, particle_radius)); layer_gen->SetNormalDistribution(particle_radius, particle_std_dev, 1); layer_gen->material->SetFriction(particle_slide_friction); layer_gen->material->SetCohesion(particle_cohesion); layer_gen->material->SetRollingFriction(0); layer_gen->material->SetSpinningFriction(0); layer_gen->AddMixtureType(MIX_SPHERE); } //layer_gen->AddMixtureType(MIX_ELLIPSOID); //layer_gen->AddMixtureType(MIX_DOUBLESPHERE); //layer_gen->addPerturbedVolumeMixture(R3(0, 0, 0), I3(64, 1, 64), R3(0, 0, 0), R3(0, 0, 0)); //========================================================================================================= //Rendering specific stuff: // ChOpenGLManager * window_manager = new ChOpenGLManager(); // ChOpenGL openGLView(window_manager, system_gpu, 800, 600, 0, 0, "Test_Solvers"); // openGLView.render_camera->camera_position = glm::vec3(0, -5, -10); // openGLView.render_camera->camera_look_at = glm::vec3(0, 0, 0); // openGLView.render_camera->camera_scale = 2; // openGLView.SetCustomCallback(RunTimeStep); // openGLView.StartSpinning(window_manager); // window_manager->CallGlutMainLoop(); //========================================================================================================= int file = 0; ofstream reactionfile; if (save == false) { stringstream ss; ss << data_folder << "reactions.txt"; reactionfile.open(ss.str()); } for (int i = 0; i < num_steps; i++) { system_gpu->DoStepDynamics(timestep); double TIME = system_gpu->GetChTime(); double STEP = system_gpu->GetTimerStep(); double BROD = system_gpu->GetTimerCollisionBroad(); double NARR = system_gpu->GetTimerCollisionNarrow(); double LCP = system_gpu->GetTimerLcp(); double SHUR = ((ChLcpSolverParallelDVI*) (system_gpu->GetLcpSolverSpeed()))->solver.time_shurcompliment; double UPDT = system_gpu->GetTimerUpdate(); double RESID = ((ChLcpSolverParallelDVI *) (system_gpu->GetLcpSolverSpeed()))->GetResidual(); int BODS = system_gpu->GetNbodies(); int CNTC = system_gpu->GetNcontacts(); int REQ_ITS = ((ChLcpSolverParallelDVI*) (system_gpu->GetLcpSolverSpeed()))->GetTotalIterations(); printf("%7.4f|%7.4f|%7.4f|%7.4f|%7.4f|%7.4f|%7.4f|%7d|%7d|%7d|%7.4f\n", TIME, STEP, BROD, NARR, LCP, SHUR, UPDT, BODS, CNTC, REQ_ITS, RESID); system_gpu->gpu_data_manager->system_timer.PrintReport(); int save_every = 1.0 / timestep / 60.0; //save data every n steps if (i % save_every == 0) { stringstream ss; cout << "Frame: " << file << endl; ss << data_folder << "/" << file << ".txt"; if (save) { DumpAllObjectsWithGeometryChrono(system_gpu, "data/anchor/anchor.dat"); } else { DumpAllObjectsWithGeometryPovray(system_gpu, ss.str()); } file++; } if (save == false) { Vector force = engine_anchor->Get_react_force(); Vector torque = engine_anchor->Get_react_torque(); double motor_torque = engine_anchor->Get_mot_torque(); reactionfile << force.x << " " << force.y << " " << force.z << " " << torque.x << " " << torque.y << " " << torque.z << " " << motor_torque << " " << ANCHOR->GetPos().y << " " << ANCHOR->GetPos_dt().y << endl; } RunTimeStep(system_gpu, i); } if (save == false) { reactionfile.close(); } }
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; }