Ejemplo n.º 1
0
int main( int argc, char** argv )
{
  // Command line options
  bool help_mode_enabled{ false };
  scalar end_time_override{ -1.0 };
  unsigned output_frequency{ 0 };
  std::string serialized_file_name;

  // Attempt to load command line options
  if( !parseCommandLineOptions( &argc, &argv, help_mode_enabled, end_time_override, output_frequency, serialized_file_name ) )
  {
    return EXIT_FAILURE;
  }

  // If the user requested help, print help and exit
  if( help_mode_enabled )
  {
    printUsage( argv[0] );
    return EXIT_SUCCESS;
  }

  // Check for impossible combinations of options
  #ifdef USE_HDF5
  if( g_output_forces && g_output_dir_name.empty() )
  {
    std::cerr << "Impulse output requires an output directory." << std::endl;
    return EXIT_FAILURE;
  }
  #endif

  #ifdef USE_PYTHON
  // Initialize the Python interpreter
  Py_SetProgramName( argv[0] );
  Py_Initialize();

  // Initialize a callback that will close down the interpreter
  atexit( exitCleanup );

  // Allow subsequent Python commands to use the sys module
  PythonTools::pythonCommand( "import sys" );

  // Prevent Python from intercepting the interrupt signal
  PythonTools::pythonCommand( "import signal" );
  PythonTools::pythonCommand( "signal.signal( signal.SIGINT, signal.SIG_DFL )" );

  // Initialize the callbacks
  PythonScripting::initializeCallbacks();
  #endif

  if( !serialized_file_name.empty() )
  {
    if( deserializeSystem( serialized_file_name ) == EXIT_FAILURE )
    {
      return EXIT_FAILURE;
    }
    return executeSimLoop();
  }

  // The user must provide the path to an xml scene file
  if( argc != optind + 1 )
  {
    std::cerr << "Invalid arguments. Must provide a single xml scene file name." << std::endl;
    return EXIT_FAILURE;
  }

  // Attempt to load the user-provided scene
  if( !loadXMLScene( std::string{ argv[optind] } ) )
  {
    return EXIT_FAILURE;
  }

  // Override the default end time with the requested one, if provided
  if( end_time_override > 0.0 )
  {
    g_end_time = end_time_override;
  }

  // Compute the data output rate
  assert( g_dt.positive() );
  // If the user provided an output frequency
  if( output_frequency != 0 )
  {
    const Rational<std::intmax_t> potential_steps_per_frame{ std::intmax_t( 1 ) / ( g_dt * std::intmax_t( output_frequency ) ) };
    if( !potential_steps_per_frame.isInteger() )
    {
      std::cerr << "Timestep and output frequency do not yield an integer number of timesteps for data output. Exiting." << std::endl;
      return EXIT_FAILURE;
    }
    g_steps_per_save = unsigned( potential_steps_per_frame.numerator() );
  }
  // Otherwise default to dumping every frame
  else
  {
    g_steps_per_save = 1;
  }
  assert( g_end_time > 0.0 );
  g_save_number_width = MathUtilities::computeNumDigits( 1 + unsigned( ceil( g_end_time / scalar( g_dt ) ) ) / g_steps_per_save );

  printCompileInfo( std::cout );
  std::cout << "Geometry count: " << g_sim.state().ngeo() << std::endl;
  std::cout << "Body count: " << g_sim.state().nbodies() << std::endl;

  // If there are any intitial collisions, warn the user
  {
    std::map<std::string,unsigned> collision_counts;
    std::map<std::string,scalar> collision_depths;
    std::map<std::string,scalar> overlap_volumes;
    g_sim.computeNumberOfCollisions( collision_counts, collision_depths, overlap_volumes );
    assert( collision_counts.size() == collision_depths.size() ); assert( collision_counts.size() == overlap_volumes.size() );
    if( !collision_counts.empty() )
    {
      std::cout << "Warning, initial collisions detected (name : count : total_depth : total_volume):" << std::endl;
    }
    for( const auto& count_pair : collision_counts )
    {
      const std::string& constraint_name{ count_pair.first };
      const unsigned& constraint_count{ count_pair.second };
      assert( collision_depths.find( constraint_name ) != collision_depths.cend() );
      const scalar& constraint_depth{ collision_depths[constraint_name] };
      const scalar& constraint_volume{ overlap_volumes[constraint_name] };
      std::string depth_string;
      if( !std::isnan( constraint_depth ) )
      {
        depth_string = StringUtilities::convertToString( constraint_depth );
      }
      else
      {
        depth_string = "depth_computation_not_supported";
      }
      std::string volume_string;
      if( !std::isnan( constraint_volume ) )
      {
        volume_string = StringUtilities::convertToString( constraint_volume );
      }
      else
      {
        volume_string = "volume_computation_not_supported";
      }
      std::cout << "   " << constraint_name << " : " << constraint_count << " : " << depth_string << " : " << volume_string << std::endl;
    }
  }

  if( g_end_time == SCALAR_INFINITY )
  {
    std::cout << "No end time specified. Simulation will run indefinitely." << std::endl;
  }

  //scalar total_volume = 0.0;
  //for( int bdy_idx = 0; bdy_idx < g_sim.state().nbodies(); ++bdy_idx )
  //{
  //  total_volume += g_sim.state().getGeometryOfBody( bdy_idx ).volume();
  //}
  //std::cout << "Total volume: " << total_volume << std::endl;

  return executeSimLoop();
}
Ejemplo n.º 2
0
static int deserializeSystem( const std::string& file_name )
{
  std::cout << "Loading serialized simulation state file: " << file_name << std::endl;

  // Attempt to open the input file
  std::ifstream serial_stream{ file_name, std::ios::binary };
  if( !serial_stream.is_open() )
  {
    std::cerr << "Failed to open serialization file: " << file_name << std::endl;
    std::cerr << "Exiting." << std::endl;
    return EXIT_FAILURE;
  }

  // Verify the magic number
  if( Utilities::deserialize<unsigned>( serial_stream ) != MAGIC_BINARY_NUMBER )
  {
    std::cerr << "File " << file_name << " does not appear to be a serialized 3D SCISim simulation. Exiting." << std::endl;
    return EXIT_FAILURE;
  }
  
  // Read the git revision
  {
    const std::string git_revision{ StringUtilities::deserialize( serial_stream ) };
    if( CompileDefinitions::GitSHA1 != git_revision )
    {
      std::cerr << "Warning, resuming from data file for a different git revision." << std::endl;
      std::cerr << "   Serialized Git Revision: " << git_revision << std::endl;
      std::cerr << "      Current Git Revision: " << CompileDefinitions::GitSHA1 << std::endl;
    }
    std::cout << "Git Revision: " << git_revision << std::endl;
  }

  g_sim.deserialize( serial_stream );
  g_iteration = Utilities::deserialize<unsigned>( serial_stream );
  g_unconstrained_map = RigidBody3DUtilities::deserializeUnconstrainedMap( serial_stream );
  g_dt = Utilities::deserialize<Rational<std::intmax_t>>( serial_stream );
  assert( g_dt.positive() );
  g_end_time = Utilities::deserialize<scalar>( serial_stream );
  assert( g_end_time > 0.0 );
  g_impact_operator = ConstrainedMapUtilities::deserializeImpactOperator( serial_stream );
  g_CoR = Utilities::deserialize<scalar>( serial_stream );
  assert( std::isnan(g_CoR) || g_CoR >= 0.0 ); assert( std::isnan(g_CoR) || g_CoR <= 1.0 );
  g_friction_solver = ConstrainedMapUtilities::deserializeFrictionSolver( serial_stream );
  g_mu = Utilities::deserialize<scalar>( serial_stream );
  assert( std::isnan(g_mu) || g_mu >= 0.0 );
  g_impact_friction_map = ConstrainedMapUtilities::deserializeImpactFrictionMap( serial_stream );
  {
    PythonScripting new_scripting{ serial_stream };
    swap( g_scripting, new_scripting );
  }
  #ifdef USE_HDF5
  g_output_dir_name = StringUtilities::deserialize( serial_stream );
  g_output_forces = Utilities::deserialize<bool>( serial_stream );
  #endif
  g_steps_per_save = Utilities::deserialize<unsigned>( serial_stream );
  g_output_frame = Utilities::deserialize<unsigned>( serial_stream );
  g_dt_string_precision = Utilities::deserialize<unsigned>( serial_stream );
  g_save_number_width = Utilities::deserialize<unsigned>( serial_stream );
  g_serialize_snapshots = Utilities::deserialize<bool>( serial_stream );
  g_overwrite_snapshots = Utilities::deserialize<bool>( serial_stream );

  return EXIT_SUCCESS;
}