Example #1
0
void reference_integration() {
	DEBUG_OUTPUT(2, "Make a copy of ensemble for reference ensemble" );
	reference_ens = initial_ens.clone();
	DEBUG_OUTPUT(1, "Reference integration" );
	prepare_integrator();
	integ->set_ensemble( reference_ens );
	integ->integrate();
}
Example #2
0
void prepare_integrator () {
	// Initialize Integrator
	DEBUG_OUTPUT(2, "Initializing integrator" );
	double begin_time = initial_ens.time_ranges().average;
	double destination_time = cfg.optional("destination_time", begin_time + 10 * M_PI );
	integ = integrator::create(cfg);
	integ->set_ensemble(current_ens);
	integ->set_destination_time ( destination_time );
	SYNC;
}
Example #3
0
// Since our program is short, we can put everything in the main function.
int main(int argc, char* argv[]){

    // First we create our reference ensemble. We use the automatic generation using generate_ensemble function
    // This function creates a very stable ensemble of systems for us.
    defaultEnsemble ref = generate_ensemble(cfg);

    // We have to make a copy of initial conditions. We would like to compare the results to initial conditions
    // after integration
    defaultEnsemble ens = ref.clone();


    // Initialize Swarm library. Basically, it initializes CUDA system and default logging system.
    swarm::init(cfg);

    // Select and create the integrator. While you can create an integrator by calling its constructor directly.
    // It is recommended to use integrator::create since it gives you more flexibility at runtime.
    // The create function looks in the swarm library and finds the integrator you requested from 
    // the list of available plugins. 
    Pintegrator integ = integrator::create(cfg);

    // Now we set-up the integrator for integrating.
    //
    // First set the ensemble. For a GPU integrator, the GPU memory will be allocated.
    integ->set_ensemble(ens);
    // Now set the destination time where we want to stop the integration.
    integ->set_destination_time ( destination_time );
    // Need to synchronize because \ref integrator::set_ensemble may upload data to GPU.
    SYNC;

    // Now that everything is set-up, it is safe to pull the trigger and 
    // call the integrate method on integrator. Note that since we didn't set
    // a logger for the integrator, it will use the default logging system.
    integ->integrate();
    // Need to synchronize because integrate is a GPU call.
    SYNC;

    // Once the integration done, we need to examine the data. The easiest
    // check is to see if the systems have preserved energy.
    //
    // find_max_energy_conservation_error is a utility function that compares
    // two ensemble of systems. We compare our working ensemble ens to the 
    // unchanged ensemble ref.
    double max_deltaE = find_max_energy_conservation_error(ens, ref );
    std::cout << "Max Energy Conservation Error =  " << max_deltaE << std::endl;

    // This concludes the program, at this point you will need to clean up the data and ensembles.
    // But most of Swarm-NG objects are stored in reference-counter pointers and will be automatically
    // deallocated by C++ runtime library.
    return 0;
}
Example #4
0
void stability_test() {

	defaultEnsemble &ens = current_ens;

	double begin_time = ens.time_ranges().median;
	double destination_time = cfg.optional("destination_time", begin_time + 10 * M_PI );
	double interval = cfg.optional("interval", (destination_time-begin_time) ) ; 
	double logarithmic = cfg.optional("logarithmic", 0 ) ; 
	double allowed_deltaE =  cfg.optional("allowed_deltaE", 0.01 );

	if(destination_time < begin_time ) ERROR("Destination time should be larger than begin time");
	if(interval < 0) ERROR("Interval cannot be negative");
	if(interval < 0.001) ERROR("Interval too small");
	if(logarithmic != 0 && logarithmic <= 1) ERROR("logarithm base should be greater than 1");


	std::cout << "Time, Energy Conservation Factor (delta E/E), Active Systems" << std::endl;
	for(double time = begin_time; time < destination_time; ) {

		if(logarithmic > 1)
			time = (time > 0) ? time * logarithmic : interval;
		else
			time += interval;

		double effective_time = min(time,destination_time);
		integ->set_destination_time ( effective_time );

		DEBUG_OUTPUT(2, "Integrator ensemble" );
		integ->integrate();

		SYNC;
		DEBUG_OUTPUT(2, "Check energy conservation" );
                ensemble::range_t deltaE_range = energy_conservation_error_range(ens, initial_ens );

		int active_systems = ens.nsys() - number_of_disabled_systems( ens );
		std::cout << effective_time << ", " << deltaE_range.max << ", " << deltaE_range.median << ", " << active_systems << std::endl;
		
		if(deltaE_range.median > allowed_deltaE){
			INFO_OUTPUT(0, "At least half of systems are too unstable to conserve energy. dE/E: " << deltaE_range.median << std::endl );
			exit(1);
		}

	}

}
Example #5
0
int main(int argc, char* argv[] ) 
{
  // We keep it simple, later on one can use boost::program_options to 
  // have more options
  // but now we only use two configuration files. It is because the 
  // initial conditions configuration file can get really big and 
  // it has very little to do with other configuration options.
  if(argc < 3) cout << "Usage: montecarlo_ecclimit <integration configuration> <initial conditions configuration>" << endl;

  // First one is the configuration for integration
  string integ_configfile = argv[1];
  // the second one is the configuration for generating
  //  initial conditions it is used by \ref generate_ensemble_with_randomized_initial_conditions
  string initc_configfile = argv[2];
  
  cfg = config::load(integ_configfile);
  
  // 1.read keplerian coordinates from a file
  // 2.generate guesses based on the keplerian coordinates
  // 3.convert keplerian coordinates to an ensemble
  // The following line that is taken from swarm_tutorial_montecarlo.cpp
  // does the first three steps. Its pretty amazing.
  defaultEnsemble ens ; 
  if( cfg.count("input") ) 
    {    ens = snapshot::load(cfg["input"]);  }
  else
    {    ens = generate_ensemble_with_randomized_initial_conditions( config::load(initc_configfile) );  }
	
  // save the ensemble as a snapshot
  if(cfg.count("initial_snapshot"))
    {    snapshot::save( ens, cfg["initial_snapshot"] );	}

  defaultEnsemble ens_init = ens.clone() ;
  std::vector<std::vector<double> > semimajor_axes_init = calc_semimajor_axes(ens);

  // We want to find the ones that are really stable, so we integrate for
  // a really long time and over time we get rid of unstable ones. 
  double destination_time = cfg.optional("destination_time", 1.0E6);
  
  
  swarm::init(cfg);
  Pintegrator integ = integrator::create(cfg);
  integ->set_ensemble(ens);
  integ->set_destination_time ( destination_time );
  // We can set the following two items if we really need
  // longer integrations before we stop for checking the
  // ensemble and saving snapshots.
  // one kernel call to allow for prompt CPU pruning of unstable systems
  int max_kernel_calls_per_integrate = cfg.optional("max_kernel_calls_per_integrate",1);
  // 10^2 inner orbits at 200 time steps per inner orbit
  int max_itterations_per_kernel_call = cfg.optional("max_itterations_per_kernel_call",20000);
  integ->set_max_attempts( max_kernel_calls_per_integrate ); 
  integ->set_max_iterations ( max_itterations_per_kernel_call ); 
  SYNC;

  // integrate ensemble
  //  - drop the unstable ones as you go
  //  - redistribute the systems for better efficiency
  //  - save the results periodically
  //  This can be an infitie loop. but we can always get out of this
  //  the best way to do it is to use Ctrl-C. Further wecan
  //  define Ctrl-C signal handler to get out
  //  of this loop in a safe way. But we really want this loop
  //  to run for a long time
  reactivate_systems(ens);
  // EBF Experiment trying to expose host log.
  swarm::log::ensemble(*(swarm::log::manager::default_log()->get_hostlog()),ens);
  integ->flush_log();

  catch_ctrl_c();
  while( number_of_active_systems(ens) > 0 && integration_loop_not_aborted_yet ) {

    // 1. Integrate, we could use core_integrate but the general integrate
    // saves all the headache. We should only use core_integrate if we are
    // going to do everything on GPU, but since we are saving a snapshot in 
    // the middle, there's no point. It also has a nice for loop and can
    // to several kernel calls.
    integ->integrate();
    
    // 2. CPU-based tests to identify systems that can be terminated
    int active_ones = number_of_active_systems(ens);
    const double deltaa_frac_threshold = cfg.optional("deltaa_frac_threshold", 0.5);
    disable_unstable_systems( ens, semimajor_axes_init, deltaa_frac_threshold );
    //    double med_deltaE = find_median_energy_conservation_error(ens, ens_init );
    double max_deltaE = find_max_energy_conservation_error(ens, ens_init );
    std::cerr << "# Time: " << ens.time_ranges().min << " " << ens.time_ranges().median << " " << ens.time_ranges().max << " Systems: " << ens.nsys() << ", " << active_ones << ", ";
    active_ones = number_of_active_systems(ens);    
    std::cerr << active_ones << "  max|dE/E|= " << max_deltaE << "\n";

    // EBF Experiment trying to expose host log.  
    swarm::log::ensemble_enabled(*(swarm::log::manager::default_log()->get_hostlog()),ens);
    integ->flush_log();

    if (!cfg.count("input") && cfg.count("replace_unstable") )
      {
	int nsys_to_replace = number_of_disabled_systems( ens ) ;
	if( nsys_to_replace >0 ) 
	  {
	    replace_disabled_systems( ens );
	    integ->set_ensemble( ens );
	  }
      }
    else
      {
    // 3. Now we need to get rid of the inactive ones. There 
    // should be some criteria, whatever it is we are
    // going to put it in a function and call it \ref needs_shrinking
    if ( needs_shrinking( ens ) ) 
      {
	// Now this function will take care of trimming for us
	// We need to create a new ensemble of a smaller size
	// thats why we need to call set_ensemble again. because
	// the GPU ensemble should get recreated for us.
	//  we need better memory management to safely allow
	//  the following statement. Right now we don't have a
	//  very good automatic memory management
	//	std::cerr << "# Removing disabled systems\n";
	ens = trim_disabled_systems( ens );
	//	std::cerr << "# Testing if ens has any systems left.\n";
	if(ens.nsys()>0)
	  {
	    // std::cerr << "# Setting ensemble for integrator\n";
	    // WARNING: This appears to be the cause of SEGFAULT
	    //          if the ensemble is empty.  
	    integ->set_ensemble( ens );
	  }
	//	std::cerr << "# Time: " << ens.time_ranges() << " Total Systems: " << ens.nsys() << " Active Systems: " << active_ones << ", ";
	//	active_ones = number_of_active_systems(ens);    
	//	std::cerr << active_ones << "\n";
      }
      }
    //    std::cerr << std::endl;

    // 4. We need to save a snapshot in case system crashes or someone
    // gets tired of it and hits Ctrl-C
    //    std::cerr << "# Saving snapshot\n";
    save_snapshot( ens );
    write_stable_systems(ens,ens_init);    
  }

  // Now we are at the end of the system, before we examine
  // the output we need to 
  //  std::cerr << "# Removing disabled systems\n";
  if(number_of_active_systems(ens)>0)
    {
      ens = trim_disabled_systems( ens );
      //  std::cerr << "# Saving snapshot\n";
      save_snapshot( ens );
    }

  write_stable_systems(ens,ens_init);
}
Example #6
0
void generic_integrate () {
	DEBUG_OUTPUT(2, "Integrator ensemble" );
	integ->integrate();
}