/*
   Project: Adun

   Copyright (C) 2005 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

/**
\note Using double quotes here with icc causes
many "function x referenced but not defined"
for external functions. I cannot figure this
out at all..
*/

#include <Base/AdForceFieldFunctions.h>

inline void AdHarmonicBondEnergy(double* bond, double* bnd_pot, double **coordinates)
{
	register int i;
	int atom_one, atom_two;
	double eq_sep, bnd_cnst, acceleration_mag;
	Vector3D seperation_s;

	//translate the information in bond

	atom_one = (int)bond[0];
	atom_two = (int)bond[1];
	bnd_cnst = bond[2];	
	eq_sep = bond[3];

	//calculate interatomic distance
	
	for(i=3; --i>=0;)
		*(seperation_s.vector + i) = coordinates[atom_two][i] - coordinates[atom_one][i];

	//calculate the length of the seperation vector

	Ad3DVectorLength(&seperation_s);

	//calcualte acceleration magnitude

	acceleration_mag = -1*bnd_cnst*(seperation_s.length - eq_sep);

	//calculate potential

	*bnd_pot = *bnd_pot - acceleration_mag*(seperation_s.length - eq_sep)*0.5;
}

inline void AdHarmonicBondAcceleration(double* bond, double* bnd_pot)
{
	register int i;
	int atom_one, atom_two;
	double acceleration_mag, eq_sep, bnd_cnst, holder, rlength, rmass_one, rmass_two;
	Vector3D seperation_s;

	//translate the information in bond

	atom_one = (int)bond[0];
	atom_two = (int)bond[1];
	bnd_cnst = bond[2];	
	eq_sep = bond[3];
	rmass_one = coordinates[atom_one][4];
	rmass_two = coordinates[atom_two][4];

	//calculate interatomic distance
	
	for(i=3; --i>=0;)
		*(seperation_s.vector + i) = coordinates[atom_two][i] - coordinates[atom_one][i];

	//calculate the length of the seperation vector

	Ad3DVectorLength(&seperation_s);

	//calcualte acceleration magnitude

	acceleration_mag = -1*bnd_cnst*(seperation_s.length - eq_sep);

	//calculate potential

	*bnd_pot = *bnd_pot - acceleration_mag*(seperation_s.length - eq_sep)*0.5;

	rlength = 1/seperation_s.length;

	//calculate acceleration on atom one

	for(i=0; i<3; i++)
	{	
		holder = acceleration_mag*seperation_s.vector[i]*rlength;
		accelerations[atom_two][i] += holder*rmass_two;
		accelerations[atom_one][i] = accelerations[atom_one][i]  - holder*rmass_one;
	}
}

inline void AdHarmonicBondForce(double* bond, double* bnd_pot)
{
	register int i;
	int atom_one, atom_two;
	double acceleration_mag, eq_sep, bnd_cnst, holder, rlength;
	Vector3D seperation_s;

	//translate the information in bond

	atom_one = (int)bond[0];
	atom_two = (int)bond[1];
	bnd_cnst = bond[2];	
	eq_sep = bond[3];

	//calculate interatomic distance
	
	for(i=3; --i>=0;)
		*(seperation_s.vector + i) = coordinates[atom_two][i] - coordinates[atom_one][i];

	//calculate the length of the seperation vector

	Ad3DVectorLength(&seperation_s);

	//calcualte acceleration magnitude

	acceleration_mag = -1*bnd_cnst*(seperation_s.length - eq_sep);

	//calculate potential

	*bnd_pot = *bnd_pot - acceleration_mag*(seperation_s.length - eq_sep)*0.5;

	rlength = 1/seperation_s.length;

	//calculate acceleration on atom one

	for(i=0; i<3; i++)
	{	
		holder = acceleration_mag*seperation_s.vector[i]*rlength;
		accelerations[atom_two][i] += holder;
		accelerations[atom_one][i] -= holder;
	}
}


