runSolver.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import ivp
  2. import os
  3. import cModel
  4. import sys
  5. import json
  6. import numpy
  7. import time
  8. import scipy.interpolate
  9. defaultValues={\
  10. 'method':'LSODA',\
  11. 'atol':1e-4,\
  12. 'rtol':1e-4,\
  13. 't0':0,\
  14. 'tmax':1,\
  15. 'mode':'IVPSimultaneous',\
  16. 'nt':201,
  17. 'tUnit':'day',\
  18. 'network':'labkey-klimt.json',\
  19. 'startFromRef':'None',\
  20. 'project':'Analysis/Run',\
  21. 'schema':'lists',\
  22. 'query':'runs',\
  23. 'view':'withStrings'}
  24. def get(setup,par):
  25. try:
  26. return setup[par]
  27. except KeyError:
  28. pass
  29. return defaultValues[par]
  30. def parseSetup(setupFile):
  31. with open(setupFile,'r') as f:
  32. setup=json.load(f)
  33. out={}
  34. for p in defaultValues:
  35. out[p]=get(setup,p)
  36. return out
  37. def getScale(setup):
  38. tUnit=setup['tUnit']
  39. if tUnit=='min':
  40. return 1
  41. if tUnit=='hour':
  42. return 60
  43. if tUnit=='day':
  44. return 24*60
  45. if tUnit=='month':
  46. return 24*60*30
  47. if tUnit=='year':
  48. return 24*60*30*365
  49. return 1
  50. def main(parFiles,jobDir,startDir='NONE'):
  51. model=cModel.model()
  52. setupFile=parFiles[0]
  53. modelFile=parFiles[1]
  54. parameterFile=parFiles[2]
  55. model.parse(modelFile,parameterFile)
  56. setup=parseSetup(setupFile)
  57. scale=getScale(setup)
  58. tmax=setup['tmax']*scale
  59. print('Using {}'.format(jobDir))
  60. if startDir!='NONE':
  61. print('Using solution from {}'.format(startDir))
  62. t0,y0,s0,lut,lutSE=getStartPointFromDir(startDir)
  63. print('t0={}'.format(t0))
  64. else:
  65. t0,y0,s0,lut,lutSE=getStartPoint(setup)
  66. #we should reorder S1 to match model.lutSE
  67. #S1 is nxm, so we should reorder columns
  68. sIn=numpy.zeros(s0.shape)
  69. if s0.size>0:
  70. for x in model.lutSE:
  71. #this could be modified for different ordering of lut as well
  72. sIn[:,model.lutSE[x]]=s0[:,lutSE[x]]
  73. start_time=time.time()
  74. if setup['mode']=='SequentialOdeint':
  75. t,sol,se,s1=ivp.solveSequentialOdeint(model,tmax,setup['nt'],t0,y0,sIn)
  76. if setup['mode']=='SimultaneousOdeint':
  77. t,sol,se,s1=ivp.solveSimultaneousOdeint(model,tmax,setup['nt'],t0,y0,sIn)
  78. if setup['mode']=='IVP':
  79. t,sol,se,s1=ivp.solveSequential(model,tmax,\
  80. nt=setup['nt'],\
  81. atol=setup['atol'],\
  82. rtol=setup['rtol'],method=setup['method'],\
  83. t0=t0,y0=y0,sIn=sIn)
  84. if setup['mode']=='IVPSimultaneous':
  85. t,sol,se,s1=ivp.solveSimultaneous(model,tmax,\
  86. nt=setup['nt'],\
  87. atol=setup['atol'],\
  88. rtol=setup['rtol'],method=setup['method'],\
  89. t0=t0,y0=y0,sIn=sIn)
  90. end_time=time.time()
  91. print('Time: {:.3f} s'.format(end_time-start_time))
  92. #store
  93. #interpolate on s1
  94. #s1 has shape ft x n x m
  95. #where ft is LSODE driven number of points
  96. qt,sOut=interpolate(setup,model,t,s1,t0,tmax)
  97. numpy.savetxt(os.path.join(jobDir,'t.txt'),t)
  98. numpy.savetxt(os.path.join(jobDir,'sol.txt'),sol)
  99. numpy.savetxt(os.path.join(jobDir,'se.txt'),se)
  100. numpy.savetxt(os.path.join(jobDir,'qt.txt'),qt)
  101. #this is 3D, so new routines
  102. write3D(os.path.join(jobDir,'sOut.txt'),sOut,model.lut,model.lutSE)
  103. def interpolate(setup,model,t,s1,t0,tmax):
  104. #interpolate on s1
  105. #s1 has shape ft x n x m
  106. #where ft is LSODE driven number of points
  107. sOut=numpy.zeros((setup['nt'],model.n,model.m))
  108. qt=numpy.linspace(t0,tmax,setup['nt'])
  109. for i in range(model.n):
  110. for j in range(model.m):
  111. y=s1[:,i,j]
  112. f = scipy.interpolate.interp1d(t, y, kind='cubic')
  113. sOut[:,i,j]=f(qt)
  114. return qt,sOut
  115. def invertLUT(lut):
  116. fcode=[None]*len(lut)
  117. for x in lut:
  118. fcode[lut[x]]=x
  119. return fcode
  120. def write3D(fName,a,lut,lutSE):
  121. with open(fName,'w') as f:
  122. f.write('#Shape {}\n'.format(a.shape))
  123. f.write('#Lut {}\n'.format(invertLUT(lut)))
  124. f.write('#Lut (SE) {}\n'.format(invertLUT(lutSE)))
  125. i=0
  126. for data_slice in a:
  127. f.write('#\t Slice {}\n'.format(i))
  128. numpy.savetxt(f,data_slice)
  129. i+=1
  130. def parseLUT(line,isSE=False):
  131. SE=''
  132. if isSE:
  133. SE='(SE)'
  134. header='#Lut {}'.format(SE)
  135. names=line.replace(header,'').\
  136. replace('[','').\
  137. replace(']','').\
  138. replace(' ','').\
  139. replace('\n','').\
  140. replace("'",'').\
  141. split(',')
  142. lut={names[i]:i for i in range(len(names))}
  143. return lut
  144. def parseShape(line):
  145. shape=line.replace('#Shape ','').\
  146. replace('\n','').\
  147. replace('(','').\
  148. replace(')','').\
  149. split(',')
  150. return [int(x) for x in shape]
  151. def read3D(fName):
  152. new_data=numpy.loadtxt(fName)
  153. #read and parse first three lines to get shape,lut and lutSE
  154. nLines=3
  155. with open(fName,'r') as f:
  156. lines=[f.readline() for i in range(nLines)]
  157. shape=parseShape(lines[0])
  158. lut=parseLUT(lines[1])
  159. lutSE=parseLUT(lines[2],isSE=True)
  160. return new_data.reshape(shape),lut,lutSE
  161. def loadSolutionFromRef(setup):
  162. if setup['startFromRef']=='None':
  163. return 0,numpy.array([]),numpy.array([]),numpy.array([]),numpy.array([])
  164. nixSuite=os.path.join(os.path.expanduser('~'),'software','src','nixSuite')
  165. sys.path.append(os.path.join(nixSuite,'wrapper'))
  166. import nixWrapper
  167. nixWrapper.loadLibrary('labkeyInterface')
  168. import labkeyInterface
  169. import labkeyFileBrowser
  170. net=labkeyInterface.labkeyInterface()
  171. fconfig=os.path.join(os.path.expanduser('~'),'.labkey',setup['network'])
  172. net.init(fconfig)
  173. #debug
  174. net.getCSRF()
  175. #db=labkeyDatabaseBrowser.labkeyDB(net)
  176. fb=labkeyFileBrowser.labkeyFileBrowser(net)
  177. #refFilter={'variable':'runRef','value':setup['startFromRef'],'oper':'eq'}
  178. #ds=db.selectRows(setup['project'],setup['schema'],setup['query'],[refFilter],setup['view']'WithStrings')
  179. #ordering requires the latest to be first
  180. #ref=ds['rows'][0]['runRef']
  181. #parFileString=ds['rows'][0]['parameterFileString']
  182. #parFiles=parFileString.split(';')
  183. ref=setup['startFromRef']
  184. remoteDir=fb.formatPathURL(setup['project'],'/'.join(['jobs',ref]))
  185. localDir=os.path.join(os.path.expanduser('~'),'temp')
  186. inFiles=['t.txt','sol.txt','se.txt','qt.txt','sOut.txt']
  187. #inFiles.extend(parFiles)
  188. for f in inFiles:
  189. localPath=os.path.join(localDir,f)
  190. remotePath='/'.join([remoteDir,f])
  191. fb.readFileToFile(remotePath,localPath)
  192. return loadSolutionFromDir(localDir)
  193. def loadSolutionFromDir(jobDir):
  194. t=numpy.loadtxt(os.path.join(jobDir,'t.txt'))
  195. sol=numpy.loadtxt(os.path.join(jobDir,'sol.txt'))
  196. se=numpy.loadtxt(os.path.join(jobDir,'se.txt'))
  197. sOut,lut,lutSE=read3D(os.path.join(jobDir,'sOut.txt'))
  198. qt=numpy.loadtxt(os.path.join(jobDir,'qt.txt'))
  199. return t,sol,se,sOut,qt,lut,lutSE
  200. def getStartPointFromDir(jobDir):
  201. t,sol,se,sOut,qt,lut,lutSE=loadSolutionFromDir(jobDir)
  202. return t[-1],sol[-1],sOut[-1],lut,lutSE
  203. def getStartPoint(setup):
  204. if setup['startFromRef']=='None':
  205. return 0,numpy.array([]),numpy.array([]),[],[]
  206. t,sol,se,sOut,qt,lut,lutSE=loadSolutionFromRef(setup)
  207. return t[-1],sol[-1],sOut[-1],lut,lutSE
  208. if __name__=="__main__":
  209. parFiles=sys.argv[1].split(';')
  210. jobDir=sys.argv[2]
  211. main(parFiles,jobDir)