1#A* -------------------------------------------------------------------
2#B* This file contains source code for the PyMOL computer program
3#C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
4#D* -------------------------------------------------------------------
5#E* It is unlawful to modify or remove this copyright notice.
6#F* -------------------------------------------------------------------
7#G* Please see the accompanying LICENSE file for further information.
8#H* -------------------------------------------------------------------
9#I* Additional authors of this source file include:
10#-* Scott Dixon, Metaphorics, LLC
11#-*
12#-*
13#Z* -------------------------------------------------------------------
14
15from __future__ import print_function
16
17from chempy import tinker,io,feedback
18from chempy.tinker import keyword
19import copy
20import string
21
22class State:
23
24    def __init__(self):
25        if feedback['verbose']:
26            print(' '+str(self.__class__)+': created.')
27        self.prefix = 'tinker'
28        self.params = tinker.params_path+'chempy.prm'
29
30        self.default = {}
31        self.default['timestep'] = 1.0
32        self.default['temperature'] = 300.0
33
34        self.keywords = {}
35        self.keywords['verbose'] = ''
36        self.keywords['cutoff'] = 8.0
37        self.keywords['randomseed'] = 1234567890
38
39        self.mapping = None
40        self.echo = 0
41        self.model = None
42        self.reset_fragile()
43        self.counter = 0
44
45    def reset_fragile(self):
46        self.restart = None
47        self.frames = None
48
49    def __write_keys(self,list):
50        f=open(self.prefix+"_inp.key",'w')
51        f.writelines(list)
52        f.close()
53
54    def analyze(self,kw=None,summary=1):
55        if feedback['actions']:
56            print(' '+str(self.__class__)+': starting energy run...')
57        io.xyz.toFile(self.model,self.prefix+"_inp.xyz",
58                          mapping = self.mapping)
59        kw_list = [ "parameters "+self.params+"\n" ]
60        for a in self.keywords.keys():
61            kw_list.append("%s %s\n" % ( a,str(self.keywords[a])))
62        kw_list.extend(keyword.get_partial_charge(self.model))
63        if kw:
64            kw_list.extend(kw)
65        self.__write_keys(kw_list)
66        tinker.do('analyze',
67                     self.prefix+"_inp",
68                     self.prefix+"_run",
69                     self.prefix+"_out",
70                     [ tinker.prefix,
71                        'E',],
72                     capture = 1 + self.echo )
73        if summary:
74# get energy information from output file
75            f = open(self.prefix+"_out.out")
76            self.summary = []
77            flag = 0
78            while 1:
79                lin = f.readline()
80                if not lin: break
81                if not flag:
82                    if lin[0:25]==' Total Potential Energy :':
83                        self.summary.append([
84                            string.strip(lin[0:23]),
85                            float(lin[25:49])])
86                        flag = 1
87                else:
88                    tok = string.split(string.strip(lin))
89                    if len(tok):
90                        if(tok[0]!='Energy'):
91                            self.summary.append([
92                                string.strip(lin[0:23]),
93                                float(lin[25:49]),
94                                int(lin[49:64])])
95            f.close()
96        else:
97            self.summary = None
98        if len(self.summary):
99             self.energy = self.summary[0][1]
100        else:
101             self.energy = None
102
103    def minimize(self,gradient=0.1,max_iter=100,
104                     kw=None,summary=1):
105        if feedback['actions']:
106            print(' '+str(self.__class__)+': starting minimization run...')
107        io.xyz.toFile(self.model,self.prefix+"_inp.xyz")
108        self.counter = self.counter + max_iter
109        kw_list = [ "parameters "+self.params+"\n" ]
110        for a in self.keywords.keys():
111            kw_list.append("%s %s\n" % ( a,str(self.keywords[a])))
112        kw_list.extend(keyword.get_partial_charge(self.model))
113        if kw:
114            kw_list.extend(kw)
115        kw_list.append("overwrite\n")
116        kw_list.append("maxiter %d\n" % max_iter)
117        self.__write_keys(kw_list)
118        tinker.do('minimize',
119                     self.prefix+"_inp",
120                     self.prefix+"_run",
121                     self.prefix+"_out",
122                     [ tinker.prefix,
123                        str(gradient),],
124                     capture = 1 + self.echo )
125        io.xyz.updateFromFile(self.model,self.prefix+"_out.xyz")
126        self.restart = None
127        if summary:
128# get energy information from output file
129            f = open(self.prefix+"_out.out")
130            step = 1
131            flag = 0
132            self.summary = []
133            while 1:
134                lin = f.readline()
135                if not lin: break
136                if not flag:
137                    if (lin[0:9]==' CG Iter ' or
138                         lin[0:9]==' QN Iter '):
139                        f.readline() # skip blank
140                        flag = 1
141                else:
142                    try:
143                        if int(lin[0:6])==step:
144                            step = step + 1
145                            self.summary.append([
146                                int(lin[0:6]),
147                                float(lin[6:19]),
148                                float(lin[19:30]),
149                                float(lin[30:41]),
150                                float(lin[41:51]),
151                                float(lin[51:60]),
152                                int(lin[60:67]),
153                                string.strip(lin[67:])])
154                    except ValueError:
155                        pass
156            f.close()
157        else:
158            self.summary = None
159        if len(self.summary):
160             self.energy = self.summary[-1][1]
161        else:
162             self.energy = None
163
164    def dynamics(self,steps=100,
165                     timestep=None,
166                     interval=None,
167                     temperature=None,
168                     kw=None,summary=1):
169        if feedback['actions']:
170            print(' '+str(self.__class__)+': starting dynamics run...')
171        io.xyz.toFile(self.model,self.prefix+"_inp.xyz")
172        self.counter = self.counter + steps * timestep
173# if restart is available, then use it.
174        if self.restart:
175            f = open(self.prefix+"_inp.dyn","w")
176            f.writelines(self.restart)
177            f.close()
178            if feedback['actions']:
179                print(' '+str(self.__class__)+': using restart information...')
180#
181        kw_list = [ "parameters "+self.params+"\n" ]
182        for a in self.keywords.keys():
183            kw_list.append("%s %s\n" % ( a,str(self.keywords[a])))
184        kw_list.extend(keyword.get_partial_charge(self.model))
185        if kw:
186            kw_list.extend(kw)
187        kw_list.append("archive\n")
188        self.__write_keys(kw_list)
189        if not timestep:
190            timestep = self.default['timestep']
191        if not temperature:
192            temperature = self.default['temperature']
193        if not interval:
194            interval = (timestep*steps)/1000.0
195        else:
196            interval = interval/1000.0
197        tinker.do('dynamic',
198                     self.prefix+"_inp",
199                     self.prefix+"_run",
200                     self.prefix+"_out",
201                     [ tinker.prefix,
202                        str(steps),
203                        str(timestep),
204                        str(interval),
205                        str(temperature)],
206                     capture = 1 + self.echo )
207        self.frames = io.arc.fromFile(self.prefix+"_out.arc")
208        if len(self.frames):
209            c = 0
210            atm = self.model.atom
211            for a in self.frames[-1]:
212                atm[c].coord = copy.deepcopy(a)
213                c = c + 1
214# get restart information
215        f = open(self.prefix+"_out.dyn")
216        self.restart = f.readlines()
217        f.close()
218# get energy information from output file
219        if summary:
220            f = open(self.prefix+"_out.out")
221            step = 1
222            flag = 0
223            self.summary = []
224            while 1:
225                lin = f.readline()
226                if not lin: break
227                if not flag:
228                    if lin[0:12]=='    MD Step ':
229                        f.readline() # skip blank
230                        flag = 1
231                else:
232                    try:
233                        if int(lin[0:10])==step:
234                            step = step + 1
235                            self.summary.append([
236                                int(lin[0:10]),
237                                float(lin[10:24]),
238                                float(lin[24:38]),
239                                float(lin[38:50]),
240                                float(lin[50:61])])
241                    except ValueError:
242                        pass
243            f.close()
244        else:
245            self.summary = None
246        if len(self.summary):
247            self.energy = self.summary[-1][1]
248        else:
249            self.energy = None
250
251
252    def load_model(self,a):
253        if feedback['verbose']:
254            print(' '+str(self.__class__)+': new model loaded.')
255        self.model = a
256        self.reset_fragile()
257