コード例 #1
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;
}