/* []------------------------------------------------[] | Interaction.cpp | []------------------------------------------------[] | | | AUTHOR: MFSomers 2005. | | USE: Defines an interaction than can | | be used in a classical dynamics | | framework... | | | []------------------------------------------------[] */ // Copyright (C) 2005 M.F. Somers, Theoretical Chemistry Department, Leiden University // // This is free software; you can redistribute it and/or modify it under the terms of // the GNU Lesser General Public License as published by the Free Software Foundation. // // http://www.gnu.org/licenses/lgpl.txt #include "Global.h" #include "Vector.h" #include "Constants.h" #include "ClassicalDynamics.h" /* --------------------------------------------------- Interaction ------- */ Interaction::Interaction( unsigned int TheId, Vector *UsePeriodicBox ) : Particles( 2 ) { Id = TheId; Particles[ 0 ] = NULL; Particles[ 1 ] = NULL; TheInternalFlag = 0; // we are going to use the flag for searches, see IsParticleIncluded method... Type = AGeneralInteraction; ThePeriodicBoxPointer = UsePeriodicBox; DynamicsContext = NULL; } /* ----------------------------------------------------------------------- */ Interaction::Interaction( Interaction& I ) : Particles( I.Particles.size() ) { Id = I.Id; TheInternalFlag = I.TheInternalFlag; Type = I.Type; ThePeriodicBoxPointer = I.ThePeriodicBoxPointer; DynamicsContext = NULL; for( int N = 0; N < I.Particles.size(); ++N ) Particles[ N ] = I.Particles[ N ]; } /* ----------------------------------------------------------------------- */ Interaction& Interaction::operator=( Interaction& I ) { ParticlePointer NullPointer = NULL; int N, n; if( &I == &(*this) ) return( (*this) ); Id = I.Id; TheInternalFlag = I.TheInternalFlag; Type = I.Type; ThePeriodicBoxPointer = I.ThePeriodicBoxPointer; N = I.Particles.size() - Particles.size(); if( N > 0 ) Particles.insert( Particles.end(), N, NullPointer ); for( n = 0; n < I.Particles.size(); ++n ) // copy table Particles[ n ] = I.Particles[ n ]; for( ; n < Particles.size(); ++n ) // and set rest to NULL Particles[ n ] = NULL; return( (*this) ); } /* ----------------------------------------------------------------------- */ void Interaction::IncludeParticle( Particle& P ) { int EmptySpot, Pos; ParticlePointer NullPointer = NULL; /* loop through array and find empty spot or return if particle already in list */ for( EmptySpot = -1, Pos = 0; Pos < Particles.size(); Pos++ ) { if( Particles[ Pos ] == NULL ) { if( EmptySpot <= -1 ) EmptySpot = Pos; } else if( Particles[ Pos ] -> Id == P.Id ) { if( Particles[ Pos ] != &P ) { Particles[ Pos ] = &P; P.IncludeInteraction( (*this) ); // refresh links however to this I, see ClassicalDynamics ! } return; } } if( EmptySpot <= -1 ) /* if no empty spots where found */ { Particles.insert( Particles.end(), 5, NullPointer ); EmptySpot = Pos; } Particles[ EmptySpot ] = &P; P.IncludeInteraction( (*this) ); /* now if this interaction is part of a dynamical context, and this particle is not yet included into the same context, include it into the context. if it is included however, all the copy interactions should also have it included */ if( DynamicsContext != NULL ) DynamicsContext -> IncludeParticleInInteraction( P, (*this) ); } /* ----------------------------------------------------------------------- */ int Interaction::NrOfParticlesIncluded( void ) { int p, P; for( p = P = 0; p < Particles.size(); ++p ) if( Particles[ p ] != NULL ) ++P; return( P ); } /* ----------------------------------------------------------------------- */ void Interaction::ExcludeParticle( unsigned int ID ) { int Pos; ParticlePointer P; /* loop through array remove particles with given ID */ for( Pos = 0; Pos < Particles.size(); Pos++ ) { P = Particles[ Pos ]; if( P != NULL ) if( P -> Id == ID ) { Particles[ Pos ] = NULL; P -> ExcludeInteraction( Id ); /* now if we are part of a dynamical context, make sure that the particle is also excluded from all the copy interactions within the same dynamical context */ if( DynamicsContext != NULL ) DynamicsContext -> ExcludeParticleFromInteraction( ID, Id ); } } } /* ----------------------------------------------------------------------- */ void Interaction::DeleteParticle( unsigned int ID ) { int Pos; ParticlePointer P; /* now if we are part of a dynamical context, make sure that the particle is deleted from all the copy interactions within the same dynamical context */ if( DynamicsContext != NULL ) DynamicsContext -> DeleteParticle( ID ); /* loop through array remove particles with given ID */ for( Pos = 0; Pos < Particles.size(); Pos++ ) { P = Particles[ Pos ]; if( P != NULL ) if( P -> Id == ID ) { Particles[ Pos ] = NULL; delete P; } } } /* ----------------------------------------------------------------------- */ void Interaction::ExcludeParticle( Particle& P ) { ExcludeParticle( P.Id ); } /* ----------------------------------------------------------------------- */ void Interaction::DeleteParticle( Particle& P ) { DeleteParticle( P.Id ); } /* ----------------------------------------------------------------------- */ void Interaction::ExcludeAllParticles( void ) { int Pos; ParticlePointer P; for( Pos = 0; Pos < Particles.size(); Pos++ ) { P = Particles[ Pos ]; Particles[ Pos ] = NULL; if( P != NULL ) { P -> ExcludeInteraction( Id ); /* now if we are part of a dynamical context, please exclude all particles from all the copy interactions also within the same dynamical context */ if( DynamicsContext != NULL ) DynamicsContext -> ExcludeParticleFromInteraction( P -> Id, Id ); } } } /* ----------------------------------------------------------------------- */ void Interaction::DeleteAllParticles( void ) { int Pos; ParticlePointer P; for( Pos = 0; Pos < Particles.size(); Pos++ ) { P = Particles[ Pos ]; Particles[ Pos ] = NULL; if( P != NULL ) { /* now if we are part of a dynamical context, please delete these particles also within the same context */ if( DynamicsContext != NULL ) DynamicsContext -> DeleteParticle( P -> Id ); else delete P; } } } /* ----------------------------------------------------------------------- */ int Interaction::IsParticleIncluded( unsigned int ID ) { int Size = Particles.size(); // we use the internal flag as start index of the search the next time we request // a particle in this interaction, we start off from where we left, making the force // calculations faster! int OldIndex = ( TheInternalFlag > Size ? Size : TheInternalFlag ); for( ; TheInternalFlag < Size; ++TheInternalFlag ) { if( Particles[ TheInternalFlag ] != NULL ) if( Particles[ TheInternalFlag ] -> Id == ID ) return( TheInternalFlag++ ); } for( TheInternalFlag = 0; TheInternalFlag < OldIndex; ++TheInternalFlag ) { if( Particles[ TheInternalFlag ] != NULL ) if( Particles[ TheInternalFlag ] -> Id == ID ) return( TheInternalFlag++ ); } return( -1 ); } /* ----------------------------------------------------------------------- */ int Interaction::IsParticleIncluded( Particle& P ) { return( IsParticleIncluded( P.Id ) ); } /* ----------------------------------------------------------------------- */ ParticlePointer Interaction::GetParticlePointer( int Index ) { return( ( Index < 0 ? NULL : ( Index >= Particles.size() ? NULL : Particles[ Index ] ) ) ); } /* ----------------------------------------------------------------------- */ int Interaction::GetParticleListSize( void ) { return( Particles.size() ); } /* ----------------------------------------------------------------------- */ double Interaction::InteractionPotential( void ) { return( 0.0 ); } /* ----------------------------------------------------------------------- */ Vector Interaction::InteractionForce( unsigned int ID ) { Vector Force; Force.X = Force.Y = Force.Z = 0.0; return( Force ); } /* ----------------------------------------------------------------------- */ Vector Interaction::InteractionForce( Particle &P ) { return( InteractionForce( P.Id ) ); } /* --------------------------------------------------- Functions --------- */ double TotalPotentialEnergy( const InteractionList& TheInteractions ) { int Size = TheInteractions.size(); double E = 0.0; for( int I = 0; I < Size; ++I ) if( TheInteractions[ I ] != NULL ) E += TheInteractions[ I ] -> InteractionPotential(); return( E ); } /* ----------------------------------------------------------------------- */