/*
   Project: Adun

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

   Author: Michael Johnston

   Created: 2005-06-23 11:06:55 +0200 by 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.
*/
#include <GRFNonbondedCalculator.h>

@implementation GRFNonbondedCalculator

- (void) evaluateForces;
{
	ListElement* list_p;

	/**
	\note May be quicker to get the number of nonbonded interactions and then use a for loop here
	**/
	
	vdwPotential = 0;
	estPotential = 0;

	list_p = interactionList->next;
  	while(list_p->next != NULL)
  	{
  		AdEnzymixGRFNonbondedForce(list_p, &vdwPotential, &estPotential,
				permittivity, coordinates->matrix, forces->matrix, cutoff, b0, b1);
 		list_p = list_p->next;
  	}
}

- (void) evaluateTypeOneVDWForces
{
	NSLog(@"Method (%@) not implemented", NSStringFromSelector(_cmd));
}

- (void) evaluateElectostaticForces
{
	NSLog(@"Method (%@) not implemented", NSStringFromSelector(_cmd));
}

- (void) evaluatePotential;
{
	ListElement* list_p;

	vdwPotential = 0;
	estPotential = 0;

	list_p = interactionList->next;
  	while(list_p->next != NULL)
  	{
  		AdEnzymixGRFNonbondedEnergy(list_p, &vdwPotential, &estPotential,
				permittivity, coordinates->matrix, cutoff, b0);
 		list_p = list_p->next;
  	}
}

/******************

Creation and Maintenance

*******************/

- (void) _calculateGRFParameters
{
	b0 = (epsilon1 - 2*epsilon2*(1 + kappa*cutoff))/epsilon2*(1 + kappa*cutoff);
	b1 = (epsilon1 - 4*epsilon2)*(1+kappa*cutoff) - 2*epsilon2*(kappa*cutoff)*(kappa*cutoff);
	b1 /= (epsilon1 - 2*epsilon2)*(1+kappa*cutoff) + epsilon2*(kappa*cutoff)*(kappa*cutoff);

	b0 += 1;
	b0 /= cutoff;

	b1 += 1;
	b1 /= pow(cutoff,3);

	NSDebugLLog(@"GRFNonbondedCalculator", @"B0 initial value %lf. B1 inital value %lf", b0, b1);
}

- (id) init
{
	return [self initWithEnvironment: nil];
}

- (id) initWithEnvironment: (id) object
{
	[self initWithEnvironment: object observe: YES];
}

- (id) initWithEnvironment: (id) object observe: (BOOL) value 
{
	if(self = [super initWithEnvironment: object observe: value])
	{
		forces = NULL;
		coordinates = NULL;

		if(environment == nil)
		{
			cutoff = 12;
			permittivity = PI4EP_R;
			epsilon1 = 1;
			epsilon2 = 78;
			kappa = 0;
		}
		else
		{
			cutoff = [[environment valueForKey: @"CutOff"] floatValue];
			epsilon1 = [[environment valueForKeyPath: 
					@"options.Electrostatic.ShortRange.GRF.Epsilon1"] doubleValue];
			epsilon2 = [[environment valueForKeyPath:
					 @"options.Electrostatic.ShortRange.GRF.Epsilon2"] doubleValue];
			kappa = [[environment valueForKeyPath: 
					@"options.Electrostatic.ShortRange.GRF.Kappa"] doubleValue];
			permittivity = epsilon1*PI4EP_R;
		}

		NSDebugLLog(@"GRFNonbondedCalculator", @"Epsilon1 %lf. Epsilon2 %lf. Kappa %lf", epsilon1, epsilon2, kappa);
		NSDebugLLog(@"GRFNonbondedCalculator", @"Standard coulomb constant is %lf", permittivity);
		[self _calculateGRFParameters];
	}

	return self;
}

- (void) dealloc
{
	[super dealloc];
}

/**Accessors**/

- (void) setInteractions: (NSValue*) NonbondedInteractionLists;
{	
	interactionList = (ListElement*)[NonbondedInteractionLists pointerValue];
}

- (void) setCoordinates: (NSValue*) value
{
	coordinates = [value pointerValue];
}

- (void) useExternalForceMatrix: (AdMatrix*) matrix
{
	forces = matrix;
}

- (double) ElectrostaticPotential
{
	return estPotential;
}

- (double) VDWPotential
{
	return vdwPotential;
}

- (void) setCutOff: (NSNumber*) aNumber
{
	cutoff = [aNumber floatValue];
	[self _calculateGRFParameters];
} 

@end
