Trisurf Monte Carlo simulator
Samo Penic
2016-03-16 9154b3cc571c2461010573f84b91fcf84830cf5a
commit | author | age
bc14fb 1 #!/usr/bin/python3
SP 2
3 import configobj
bd6993 4 import xml.etree.ElementTree as ET
SP 5 import base64
6 import zlib
7 import io
c14bd6 8 import os
SP 9 from itertools import islice
10 import mmap
7c45b1 11 import shlex
34600b 12 import psutil
f81585 13 import time
SP 14 import datetime
15
bc14fb 16 '''
SP 17 This is a trisurf instance manager written in python
18
19
20 Invoke with:
21 tsmgr [-t tape | -r snapshot.vtu] [-s subdirectory]
22
23 If tape is specified, the trisurf wilt start from tape with initial distribution, if snapshot is specified the trisurf will be restored from given snapshot file and simulation will continue.
24
25 '''
26
9154b3 27 class FileContent:
SP 28     def __init__(self,filename):
29         self.filename=filename
30         self.data=""
31         self.readfile()
bc14fb 32
9154b3 33     def readfile(self):
SP 34         try:
35             with open (self.filename, "r") as myfile:
36                 self.data=myfile.read().replace('\n', '')
37         except:
38             pass
39
40
41     def writefile(self, data, mode='w'):
42         with open (self.filename, mode) as myfile:
43             myfile.write(data)
44
45     def getText(self):
46         return self.data
47
48     def __str__(self):
49         return self.getText()
bc14fb 50
SP 51 class Tape:
52     '''Has all the info on the tape'''
53
54     def __init__(self):
55         return
56
57     def readTape(self, tape='tape'):
58         try:
59             self.config=configobj.ConfigObj(tape)
60         except:
61             print("Error reading or parsing tape file!\n")
62             exit(1)
63
64     def setTape(self, string):
bd6993 65         self.config=configobj.ConfigObj(io.StringIO(string))
bc14fb 66         return
SP 67
68     def getValue(self,key):
69         return self.config[key]
70
c14bd6 71     def __str__(self):
SP 72         retval=""
73         for key,val in self.config.iteritems():
74             retval=retval+str(key)+" = "+str(val)+"\n"
75         return retval
bc14fb 76
c14bd6 77
SP 78
79 class Directory:
80     def __init__(self, maindir=".", simdir=""):
81         self.maindir=maindir
82         self.simdir=simdir
83         return
84
85     def fullpath(self):
86         return os.path.join(self.maindir,self.simdir)
87
88     def exists(self):
89         path=self.fullpath()
90         if(os.path.exists(path)):
91             return 1
92         else:
93             return 0
94
95     def make(self):
96         try:
97             os.makedirs(self.fullpath())
98         except:
99             print("Cannot make directory "+self.fullpath()+"\n")
100             exit(1)
101         return
102
103     def makeifnotexist(self):
104         if(self.exists()==0):
105             self.make()
106         return
107
108     def remove(self):
109         if(self.exists()):
110             try:
111                 os.rmdir(self.fullpath())
112             except:
113                 print("Cannot remove directory "+self.fullpath()+ "\n")
114                 exit(1)
115         return
116
117     def goto(self):
118         try:
119             os.chdir(self.fullpath())
120         except:
121             print("Cannot go to directory "+self.fullpath()+"\n")
122         return
123
124
125 class Statistics:
126     def __init__(self,path,filename="statistics.csv"):
127         self.path=path
128         self.filename=filename
129         self.fullname=os.path.join(path,filename)
f81585 130         self.fileOK=self.read()
c14bd6 131         return
SP 132
133     def exists(self):
134         if(os.path.isfile(self.fullname)):
135             return True
136         else:
137             return False
138
139     def mapcount(self):
140         f = open(self.fullname, "r+")
141         buf = mmap.mmap(f.fileno(), 0)
142         lines = 0
143         readline = buf.readline
144         while readline():
145             lines += 1
146         return lines
147
148     def read(self):
149         if(self.exists()):
150             nlines=self.mapcount()
151             try:
152                 with open(self.fullname, "r+") as fin:
153                     i=0;
154                     for line in fin:
155                         if(i==1):
7c45b1 156                             #print (line)
SP 157                             fields=shlex.split(line)
158                             epoch1=fields[0]
159                             n1=fields[1]
c14bd6 160                         if(i==nlines-1):
7c45b1 161                             fields=shlex.split(line)
SP 162                             epoch2=fields[0]
163                             n2=fields[1]
c14bd6 164                         i=i+1
SP 165             except:
f81585 166                 #print("Cannot read statistics file in "+self.fullname+"\n")
7c45b1 167                 return(False)
c14bd6 168         else:
f81585 169             #print("File "+self.fullname+" does not exists.\n")
7c45b1 170             return(False)
SP 171
172         self.dT=(int(epoch2)-int(epoch1))/(int(n2)-int(n1))
f81585 173         self.last=n2
SP 174         self.startDate=epoch1
7c45b1 175         return(True)
f81585 176
SP 177     def __str__(self):
178         return(str(self.fullname))
179
7c45b1 180
bc14fb 181
SP 182 class Runner:
183     '''
184     Class Runner consists of a single running or terminated instance of the trisurf
185     '''
c14bd6 186     def __init__(self, subdir='run0', tape='', snapshot=''):
SP 187         self.subdir=subdir
188         if(tape!=''):
189             self.initFromTape(tape)
190         if(snapshot!=''):
191             self.initFromSnapshot(snapshot)
192         return
193
194
a99f2b 195     def initFromTape(self, tape):
bc14fb 196         self.tape=Tape()
SP 197         self.tape.readTape(tape)
198
bd6993 199     def initFromSnapshot(self, snapshotfile):
SP 200         try:
201             tree = ET.parse(snapshotfile)
202         except:
203             print("Error reading snapshot file")
204             exit(1)
205
206         root = tree.getroot()
207         tapetxt=root.find('tape')
208         version=root.find('trisurfversion')
209         self.tape=Tape()
210         self.tape.setTape(tapetxt.text)
bc14fb 211
9154b3 212     def getPID(self):
34600b 213         self.Dir=Directory(maindir=self.maindir,simdir=self.subdir)
SP 214         self.Dir.makeifnotexist()
215         try:
216             fp = open(os.path.join(self.Dir.fullpath(),'.lock'))
217         except IOError as e:
218             return 0 #file probably does not exist. e==2??
9154b3 219         pid=fp.readline()
SP 220         fp.close()
221         return pid
222
223     def getStatus(self):
224         pid=self.getPID()
225         if(pid==0):
226             return 0
34600b 227         if(psutil.pid_exists(int(pid))):
9154b3 228             if psutil.Process(int(pid)).name=="trisurf":
SP 229                 return 1
230             else:
231                 return 0
34600b 232         else:
SP 233             return 0
bc14fb 234
SP 235     def start(self):
c14bd6 236         if(self.getStatus()==0):
SP 237             self.Dir=Directory(maindir=self.maindir,simdir=self.subdir)
238             self.Dir.makeifnotexist()
34600b 239 #            self.Dir.goto()
c14bd6 240             print("Starting trisurf-ng executable at "+self.Dir.fullpath()+"\n")
SP 241         else:
242             print("Process already running. Not starting\n")
243         return
bc14fb 244
SP 245     def stop(self):
246         pass
247
c14bd6 248     def setMaindir(self,prefix,variables):
SP 249         maindir="./"
250         for p,v in zip(prefix,variables):
251             if(v=="xk0"):
252                 tv=str(round(float(self.tape.config[v])))
253             else:
254                 tv=self.tape.config[v]
255             maindir=maindir+p+tv
256         self.maindir=maindir
257         return
258
259     def setSubdir(self, subdir="run0"):
260         self.subdir=subdir
261         return
262
263     def getStatistics(self, statfile="statistics.csv"):
7ca5ae 264         self.Dir=Directory(maindir=self.maindir,simdir=self.subdir)
34600b 265         self.statistics=Statistics(self.Dir.fullpath(), statfile)
9154b3 266         self.Comment=FileContent(os.path.join(self.Dir.fullpath(),".comment"))
SP 267         pid=self.getPID();
268         if(self.getStatus()):
269             statustxt="Running"
f81585 270         else:
9154b3 271             statustxt="Stopped"
SP 272             pid=""
273
274         if(self.statistics.fileOK):
275 #            report=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(self.statistics.startDate)))+"\t"+str(datetime.timedelta(microseconds=(int(self.tape.config['iterations'])-int(self.statistics.last))*self.statistics.dT)*1000)+" ETA\t"+"STATUS"
276             report=[time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(self.statistics.startDate))),str(datetime.timedelta(microseconds=(int(self.tape.config['iterations'])-int(self.statistics.last))*self.statistics.dT)*1000), statustxt, pid, str(self.Dir.fullpath()), self.Comment.getText()]
277         else:
278             report=["N/A","N/A\t",statustxt, pid, str(self.Dir.fullpath()), self.Comment.getText()]
f81585 279         return report
c14bd6 280
9154b3 281     def writeComment(self, data):
SP 282         self.Dir=Directory(maindir=self.maindir,simdir=self.subdir)
283         self.Comment=FileContent(os.path.join(self.Dir.fullpath(),".comment"))
284         self.Comment.writefile(data,mode='w')
285
bc14fb 286     def __str__(self):
c14bd6 287         if(self.getStatus()==0):
SP 288             str=" not running."
289         else:
290             str=" running."
291         return(self.Dir.fullpath()+str)
292
bc14fb 293