예제 #1
0
파일: Solvers.cpp 프로젝트: OPSand/Project5
// a single Leapfrog step (parameter = step length)
void Solvers::Leapfrog(double step)
{
	int n = this->_leapfrog->n(); // number of celestial bodies

	double halfStep = (step / 2.0);

	// calculate forces/accelerations based on current postions
	this->_leapfrog->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_leapfrog->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// Leapfrog algorithm, step 1
			*(cb->velocity) += halfStep * cb->acc();

			// Leapfrog algorithm, step 2
			*(cb->position) += step * *(cb->velocity);
		}
	}

	// calculate the forces using the new positions
	this->_leapfrog->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_leapfrog->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// Leapfrog algorithm, step 3
			*(cb->velocity) += halfStep * cb->acc();
		}
	}
}
예제 #2
0
파일: Solvers.cpp 프로젝트: OPSand/Project5
// a single Euler-Cromer step (parameter = step length)
void Solvers::Euler(double step)
{
	int n = this->_euler->n(); // number of celestial bodies

	// calculate forces/accelerations based on current postions
	this->_euler->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_euler->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// acc -> velocity (Euler-Cromer, for testing only)
			*(cb->velocity) += step * cb->acc();

			// velocity -> position (Euler-Cromer, for testing only)
			*(cb->position) += step * *(cb->velocity);
		}
	}
}
예제 #3
0
파일: Solvers.cpp 프로젝트: OPSand/Project5
// a single Runge-Kutta step (parameter = step length)
void Solvers::RK4(double step)
{
	int n = this->_rk4->n();

	// matrices for Runge-Kutta values:
	mat k1_v(this->_rk4->dim(), n); // k1, velocity
	mat k1_p(this->_rk4->dim(), n); // k1, position
	mat k2_v(this->_rk4->dim(), n); // k2, velocity (etc.)
	mat k2_p(this->_rk4->dim(), n);
	mat k3_v(this->_rk4->dim(), n);
	mat k3_p(this->_rk4->dim(), n);
	mat k4_v(this->_rk4->dim(), n);
	mat k4_p(this->_rk4->dim(), n);

	// initial position and velocity for each celestial body
	mat orig_v(this->_rk4->dim(), n);
	mat orig_p(this->_rk4->dim(), n);

	#pragma region k1

	// calculate forces/accelerations based on current postions
	this->_rk4->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_rk4->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// store initial position and velocity
			orig_v.col(j) = *(cb->velocity);
			orig_p.col(j) = *(cb->position);

			// save values
			k1_v.col(j) = step * cb->acc();
			k1_p.col(j) = step * *(cb->velocity);

			// advance to mid-point after k1
			*(cb->velocity) = orig_v.col(j) + 0.5 * k1_v.col(j);
			*(cb->position) = orig_p.col(j) + 0.5 * k1_p.col(j);
		}
	}

	#pragma endregion

	#pragma region k2

	// calculate forces/accelerations based on current postions
	this->_rk4->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_rk4->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// save values
			k2_v.col(j) = step * cb->acc();
			k2_p.col(j) = step * *(cb->velocity);

			// switch to new mid-point using k2 instead
			*(cb->velocity) = orig_v.col(j) + 0.5 * k2_v.col(j);
			*(cb->position) = orig_p.col(j) + 0.5 * k2_p.col(j);
		}
	}

	#pragma endregion

	#pragma region k3

	// calculate forces/accelerations based on current postions
	this->_rk4->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_rk4->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
		// save values
			k3_v.col(j) = step * cb->acc();
			k3_p.col(j) = step * *(cb->velocity);

			// switch to end-point
			*(cb->velocity) = orig_v.col(j) + k3_v.col(j);
			*(cb->position) = orig_p.col(j) + k3_p.col(j);
		}
	}

	#pragma endregion

	#pragma region k4

	// calculate forces/accelerations based on current postions
	this->_rk4->setForces();

	for (int j = 0; j < n; j++) // for each celestial body
	{
		CelestialBody* cb = this->_rk4->body(j);

		if (!cb->fixed) // a fixed celestial body will never move
		{
			// save values
			k4_v.col(j) = step * cb->acc();
			k4_p.col(j) = step * *(cb->velocity);

			// finally, update position and velocity
			*(cb->velocity) = orig_v.col(j) + (1.0 / 6.0)*(k1_v.col(j) + 2.0 * k2_v.col(j) + 2.0 * k3_v.col(j) + k4_v.col(j));
			*(cb->position) = orig_p.col(j) + (1.0 / 6.0)*(k1_p.col(j) + 2.0 * k2_p.col(j) + 2.0 * k3_p.col(j) + k4_p.col(j));
		}
	}

	#pragma endregion
}