void problem_output(){
	if (output_check(10000.)){
		output_timing();
		integrator_synchronize();
		FILE* f = fopen("energy.txt","a");
		double e = energy();
		fprintf(f,"%e %e %e\n",t, fabs((e-e_init)/e_init), tools_megno());
		fclose(f);
		printf("  Y = %.3f",tools_megno());
	}
}
void problem_output(){
	if (output_check(10.*2.*M_PI)){  
		output_timing();
	}
	if (output_check(2.*M_PI)){  
		FILE* f = fopen("energy.txt","a");
		integrator_synchronize();
		double e = tools_energy();
		fprintf(f,"%e %e\n",t, fabs((e-e_init)/e_init));
		fclose(f);
	}
}
Exemple #3
0
void iterate(void){	
	// A 'DKD'-like integrator will do the first 'D' part.
	PROFILING_START()
	integrator_part1();
	PROFILING_STOP(PROFILING_CAT_INTEGRATOR)

	// Check for root crossings.
	PROFILING_START()
	boundaries_check();     
	PROFILING_STOP(PROFILING_CAT_BOUNDARY)

	// Update and simplify tree. 
	// Prepare particles for distribution to other nodes. 
	// This function also creates the tree if called for the first time.
	PROFILING_START()
#ifdef TREE
	tree_update();          
#endif //TREE

#ifdef MPI
	// Distribute particles and add newly received particles to tree.
	communication_mpi_distribute_particles();
#endif // MPI

#ifdef GRAVITY_TREE
	// Update center of mass and quadrupole moments in tree in preparation of force calculation.
	tree_update_gravity_data(); 
	
#ifdef MPI
	// Prepare essential tree (and particles close to the boundary needed for collisions) for distribution to other nodes.
	tree_prepare_essential_tree_for_gravity();

	// Transfer essential tree and particles needed for collisions.
	communication_mpi_distribute_essential_tree_for_gravity();
#endif // MPI
#endif // GRAVITY_TREE

	// Calculate accelerations. 
	gravity_calculate_acceleration();
	if (N_megno){
		gravity_calculate_variational_acceleration();
	}
	// Calculate non-gravity accelerations. 
	if (problem_additional_forces) problem_additional_forces();
	if (problem_additional_forces_with_parameters) problem_additional_forces_with_parameters(particles, t, dt, G, N, N_megno);
	PROFILING_STOP(PROFILING_CAT_GRAVITY)

	// A 'DKD'-like integrator will do the 'KD' part.
	PROFILING_START()
	integrator_part2();
	if (problem_post_timestep_modifications){
		integrator_synchronize();
		problem_post_timestep_modifications();
		if (integrator == WHFAST || integrator == HYBRID){
			integrator_whfast_recalculate_jacobi_this_timestep = 1;
		}
	}
	if (problem_post_timestep_modifications_with_parameters){
		integrator_synchronize();
		problem_post_timestep_modifications_with_parameters(particles, t, dt, G, N, N_megno);
		if (integrator == WHFAST || integrator == HYBRID){
			integrator_whfast_recalculate_jacobi_this_timestep = 1;
		}
	}
	PROFILING_STOP(PROFILING_CAT_INTEGRATOR)

	// Do collisions here. We need both the positions and velocities at the same time.
#ifndef COLLISIONS_NONE
	// Check for root crossings.
	PROFILING_START()
	boundaries_check();     
	PROFILING_STOP(PROFILING_CAT_BOUNDARY)

	// Search for collisions using local and essential tree.
	PROFILING_START()
	collisions_search();

	// Resolve collisions (only local particles are affected).
	collisions_resolve();
	PROFILING_STOP(PROFILING_CAT_COLLISION)
#endif  // COLLISIONS_NONE

#ifdef OPENGL
	PROFILING_START()
	display();
	PROFILING_STOP(PROFILING_CAT_VISUALIZATION)
#endif // OPENGL
	problem_output();
	// Check if the simulation finished.
#ifdef MPI
	int _exit_simulation = 0;
	MPI_Allreduce(&exit_simulation, &_exit_simulation,1,MPI_INT,MPI_MAX,MPI_COMM_WORLD);
	exit_simulation = _exit_simulation;
#endif // MPI
	// @TODO: Adjust timestep so that t==tmax exaclty at the end.
	if((t+dt>tmax && tmax!=0.0) || exit_simulation==1){
#ifdef GRAVITY_GRAPE
		gravity_finish();
#endif // GRAVITY_GRAPE
		problem_finish();
		struct timeval tim;
		gettimeofday(&tim, NULL);
		double timing_final = tim.tv_sec+(tim.tv_usec/1000000.0);
		printf("\nComputation finished. Total runtime: %f s\n",timing_final-timing_initial);
#ifdef MPI
		MPI_Finalize();
#endif // MPI
		exit(0);
	}
}