1 // -*- C++ -*-
2 // Potential.h: Abstract base class for all potentials.
3 //
4 // Copyright (C) 2001-2012 Jakob Schiotz and Center for Individual
5 // Nanoparticle Functionality, Department of Physics, Technical
6 // University of Denmark.  Email: schiotz@fysik.dtu.dk
7 //
8 // This file is part of Asap version 3.
9 // Asap is released under the GNU Lesser Public License (LGPL) version 3.
10 // However, the parts of Asap distributed within the OpenKIM project
11 // (including this file) are also released under the Common Development
12 // and Distribution License (CDDL) version 1.0.
13 //
14 // This program is free software: you can redistribute it and/or
15 // modify it under the terms of the GNU Lesser General Public License
16 // version 3 as published by the Free Software Foundation.  Permission
17 // to use other versions of the GNU Lesser General Public License may
18 // granted by Jakob Schiotz or the head of department of the
19 // Department of Physics, Technical University of Denmark, as
20 // described in section 14 of the GNU General Public License.
21 //
22 // This program is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // and the GNU Lesser Public License along with this program.  If not,
29 // see <http://www.gnu.org/licenses/>.
30 
31 
32 #ifndef POTENTIAL_H
33 #define POTENTIAL_H
34 
35 #include "AsapPython.h"
36 #include <vector>
37 
38 #include "Exception.h"
39 #include "AsapObject.h"
40 #include "SymTensor.h"
41 
42 using std::vector;
43 
44 namespace ASAPSPACE {
45 
46 class Atoms;
47 class Vec;
48 class SuperCell;
49 class NeighborLocator;
50 
51 class Potential; // Defined later in this file.
52 
53 /// The Python object corresponding to a Potential object.
54 typedef struct {
55   PyObject_HEAD
56   Potential *cobj;      // Access through this object, either same as orig_cobj or a wrapper.
57   Potential *orig_cobj; // The actual potential object
58   PyObject *weakrefs;
59   bool setatoms_called; // True if SetAtoms has been called.
60 } PyAsap_PotentialObject;
61 
62 bool PyAsap_PotentialCheck(PyObject *obj);  // Implemented in PotentialInterface.cpp
63 
64 //typedef double symTensor[6];
65 
66 /// Abstract base class of all potentials.
67 
68 /// A Potential calculates forces, energies and stresses for a list of
69 /// atoms.  A given instance of a Potential is associated with a
70 /// specific Atoms object on a one-to-one bases, this is established
71 /// when Atoms.SetCalculator() is called.
72 ///
73 /// Four types of classes are derived from Potential.
74 ///   - Concrete implementations of potentials, such as EMT
75 ///     and MoPotential, LJPotential, BrennerPotential.
76 ///   - Potentials wrapping concrete implementations, but providing
77 ///     special functionalily, such as ParallelPotential (implementing
78 ///     parallel simulations) or QCPotential (implementing the
79 ///     QuasiContinuum method).
80 class Potential : public AsapObject
81 {
82 public:
83   Potential(PyObject *self, int verbose=0) {
84     atoms=NULL;
85     this->self = self;
86     this->verbose = verbose;
87   }
88 
~Potential()89   virtual ~Potential() {}
90 
91   /// Set the atoms belonging to this potential.
92 
93   /// This is called automatically by Atoms.SetCalculator() and should
94   /// not be called elsewhere.
95   ///
96   /// Any wrapping Potential (such as ParallelPotential) that needs to
97   /// chain to another Potential's SetAtoms method MUST instead call
98   /// Potential::SetAtoms_ThroughPython.
99   virtual void SetAtoms(PyObject *a, Atoms* accessobj = NULL) = 0;
100 
101   virtual void SetAtoms_ThroughPython(PyObject *a, Atoms* accessobj = NULL);
102 
103   /// Calculate the total energy of the system.
104   virtual double GetPotentialEnergy(PyObject *a) = 0;
105 
106   /// Calculate the forces on all atoms and return the result.
107   virtual const vector<Vec> &GetForces(PyObject *a) = 0;
108 
109   /// Calculate the "virials" of the atoms.
110   ///
111   /// The virial divided by the atomic volume is the stress of an atom.
112   virtual const vector<SymTensor> &GetVirials(PyObject *a) = 0;
113 
114   /// Calculate the total "virial" of the system.
115   ///
116   /// The virial gives the stress of the sytem when divided by the system volume.
117   virtual SymTensor GetVirial(PyObject *a);
118 
119   /// Calculate the energy of all atoms.
120   virtual const vector<double> &GetPotentialEnergies(PyObject *a) = 0;
121 
122   // The following three functions are used to check if recalculations
123   // are needed.  If a potential does not contain any logic to prevent
124   // recalculations, these functions should return True.
125 
126   /// Is work required to calculate the energy?
CalcReq_Energy(PyObject * pyatoms)127   virtual bool CalcReq_Energy(PyObject *pyatoms) {return true;}
128 
129   /// Is work required to calculate the forces?
CalcReq_Forces(PyObject * pyatoms)130   virtual bool CalcReq_Forces(PyObject *pyatoms) {return true;}
131 
132   /// Is work required to calculate the stress?
CalcReq_Virial(PyObject * pyatoms)133   virtual bool CalcReq_Virial(PyObject *pyatoms) {return CalcReq_Virials(pyatoms);}
CalcReq_Virials(PyObject * pyatoms)134   virtual bool CalcReq_Virials(PyObject *pyatoms) {return true;}
135 
136   // Check if Neighbor lists are up to date.
137   //virtual void CheckNeighborLists() = 0;
138 
139   /// Return the neighbor list.
140 
141   /// Return a BORROWED reference to the Python object containing
142   /// neighbor list for the
143   /// potential, if this type of potential supports it, and if it is
144   /// defined now.  Otherwise, return NULL without setting a Python
145   /// error.
GetNeighborList()146   virtual PyObject *GetNeighborList() const {return NULL;}
147 
148   /// Return the cutoff radius used in the potential.
149   virtual double GetCutoffRadius() const = 0;
150 
151   /// Return the lattice constant of the material, if well-defined.
152 
153   /// If a lattice constant of the material can be defined, return it
154   /// in Angstrom, otherwise throw an exception.
155   virtual double GetLatticeConstant() const = 0;
156 
157   /// Can this potential be used in parallel simulations?
158 
159   ///
160   /// ParallelPotential checks this and protests if false.  Note that
161   /// ParallelPotential itself returns false if this method is called,
162   /// as it cannot be passed to another instance of ParallelPotential.
Parallelizable()163   virtual bool Parallelizable() const {return false;}
164 
165   /// Print memory usage
166   virtual long PrintMemory() const = 0;
167 
168   /// Clean up after an exception.  Called by the interface code.
169   void RecoverAfterException();
170 
171   /// Return the atomic volumes that should be used to calculate the stresses
172   ///
173   /// If an empty volumes vector is returned, GetStress will divide the unit
174   /// cell evenly amongst the atoms.  Can only be used after a call to GetVirials
175   /// with the same atoms; returns cached data, no atoms object is therefore passed
GetAtomicVolumes(vector<double> & volumes)176   virtual void GetAtomicVolumes(vector<double> &volumes) {volumes.clear();}
177 
178 protected:
179   Atoms *atoms;
180   PyObject *self;              ///< This objects Python counterpart
181   int verbose;     // Verbosity level.
182 };
183 
184 } // end namespace
185 
186 #endif // POTENTIAL_H
187