runSolver.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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):
  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. t0,y0,s0,lut,lutSE=getStartPoint(setup)
  61. #we should reorder S1 to match model.lutSE
  62. #S1 is nxm, so we should reorder columns
  63. sIn=numpy.zeros(s0.shape)
  64. if s0.size>0:
  65. for x in model.lutSE:
  66. #this could be modified for different ordering of lut as well
  67. sIn[:,model.lutSE[x]]=s0[:,lutSE[x]]
  68. start_time=time.time()
  69. if setup['mode']=='SequentialOdeint':
  70. t,sol,se,s1=ivp.solveSequentialOdeint(model,tmax,setup['nt'],t0,y0,sIn)
  71. if setup['mode']=='SimultaneousOdeint':
  72. t,sol,se,s1=ivp.solveSimultaneousOdeint(model,tmax,setup['nt'],t0,y0,sIn)
  73. if setup['mode']=='IVP':
  74. t,sol,se,s1=ivp.solveSequential(model,tmax,\
  75. nt=setup['nt'],\
  76. atol=setup['atol'],\
  77. rtol=setup['rtol'],method=setup['method'],\
  78. t0=t0,y0=y0,sIn=sIn)
  79. if setup['mode']=='IVPSimultaneous':
  80. t,sol,se,s1=ivp.solveSimultaneous(model,tmax,\
  81. nt=setup['nt'],\
  82. atol=setup['atol'],\
  83. rtol=setup['rtol'],method=setup['method'],\
  84. t0=t0,y0=y0,sIn=sIn)
  85. end_time=time.time()
  86. print('Time: {:.3f} s'.format(end_time-start_time))
  87. #store
  88. #interpolate on s1
  89. #s1 has shape ft x n x m
  90. #where ft is LSODE driven number of points
  91. qt,sOut=interpolate(setup,model,t,s1,t0,tmax)
  92. numpy.savetxt(os.path.join(jobDir,'t.txt'),t)
  93. numpy.savetxt(os.path.join(jobDir,'sol.txt'),sol)
  94. numpy.savetxt(os.path.join(jobDir,'se.txt'),se)
  95. numpy.savetxt(os.path.join(jobDir,'qt.txt'),qt)
  96. #this is 3D, so new routines
  97. write3D(os.path.join(jobDir,'sOut.txt'),sOut,model.lut,model.lutSE)
  98. def interpolate(setup,model,t,s1,t0,tmax):
  99. #interpolate on s1
  100. #s1 has shape ft x n x m
  101. #where ft is LSODE driven number of points
  102. sOut=numpy.zeros((setup['nt'],model.n,model.m))
  103. qt=numpy.linspace(t0,tmax,setup['nt'])
  104. for i in range(model.n):
  105. for j in range(model.m):
  106. y=s1[:,i,j]
  107. f = scipy.interpolate.interp1d(t, y, kind='cubic')
  108. sOut[:,i,j]=f(qt)
  109. return qt,sOut
  110. def invertLUT(lut):
  111. fcode=[None]*len(lut)
  112. for x in lut:
  113. fcode[lut[x]]=x
  114. return fcode
  115. def write3D(fName,a,lut,lutSE):
  116. with open(fName,'w') as f:
  117. f.write('#Shape {}\n'.format(a.shape))
  118. f.write('#Lut {}\n'.format(invertLUT(lut)))
  119. f.write('#Lut (SE) {}\n'.format(invertLUT(lutSE)))
  120. i=0
  121. for data_slice in a:
  122. f.write('#\t Slice {}\n'.format(i))
  123. numpy.savetxt(f,data_slice)
  124. i+=1
  125. def parseLUT(line,isSE=False):
  126. SE=''
  127. if isSE:
  128. SE='(SE)'
  129. header='#Lut {}'.format(SE)
  130. names=line.replace(header,'').\
  131. replace('[','').\
  132. replace(']','').\
  133. replace(' ','').\
  134. replace('\n','').\
  135. replace("'",'').\
  136. split(',')
  137. lut={names[i]:i for i in range(len(names))}
  138. return lut
  139. def parseShape(line):
  140. shape=line.replace('#Shape ','').\
  141. replace('\n','').\
  142. replace('(','').\
  143. replace(')','').\
  144. split(',')
  145. return [int(x) for x in shape]
  146. def read3D(fName):
  147. new_data=numpy.loadtxt(fName)
  148. #read and parse first three lines to get shape,lut and lutSE
  149. nLines=3
  150. with open(fName,'r') as f:
  151. lines=[f.readline() for i in range(nLines)]
  152. shape=parseShape(lines[0])
  153. lut=parseLUT(lines[1])
  154. lutSE=parseLUT(lines[2],isSE=True)
  155. return new_data.reshape(shape),lut,lutSE
  156. def loadSolutionFromRef(setup):
  157. if setup['startFromRef']=='None':
  158. return 0,numpy.array([]),numpy.array([]),numpy.array([]),numpy.array([])
  159. nixSuite=os.path.join(os.path.expanduser('~'),'software','src','nixSuite')
  160. sys.path.append(os.path.join(nixSuite,'wrapper'))
  161. import nixWrapper
  162. nixWrapper.loadLibrary('labkeyInterface')
  163. import labkeyInterface
  164. import labkeyFileBrowser
  165. net=labkeyInterface.labkeyInterface()
  166. fconfig=os.path.join(os.path.expanduser('~'),'.labkey',setup['network'])
  167. net.init(fconfig)
  168. #debug
  169. net.getCSRF()
  170. #db=labkeyDatabaseBrowser.labkeyDB(net)
  171. fb=labkeyFileBrowser.labkeyFileBrowser(net)
  172. #refFilter={'variable':'runRef','value':setup['startFromRef'],'oper':'eq'}
  173. #ds=db.selectRows(setup['project'],setup['schema'],setup['query'],[refFilter],setup['view']'WithStrings')
  174. #ordering requires the latest to be first
  175. #ref=ds['rows'][0]['runRef']
  176. #parFileString=ds['rows'][0]['parameterFileString']
  177. #parFiles=parFileString.split(';')
  178. ref=setup['startFromRef']
  179. remoteDir=fb.formatPathURL(setup['project'],'/'.join(['jobs',ref]))
  180. localDir=os.path.join(os.path.expanduser('~'),'temp')
  181. inFiles=['t.txt','sol.txt','se.txt','qt.txt','sOut.txt']
  182. #inFiles.extend(parFiles)
  183. for f in inFiles:
  184. localPath=os.path.join(localDir,f)
  185. remotePath='/'.join([remoteDir,f])
  186. fb.readFileToFile(remotePath,localPath)
  187. return loadSolutionFromDir(localDir)
  188. def loadSolutionFromDir(jobDir):
  189. t=numpy.loadtxt(os.path.join(jobDir,'t.txt'))
  190. sol=numpy.loadtxt(os.path.join(jobDir,'sol.txt'))
  191. se=numpy.loadtxt(os.path.join(jobDir,'se.txt'))
  192. sOut,lut,lutSE=read3D(os.path.join(jobDir,'sOut.txt'))
  193. qt=numpy.loadtxt(os.path.join(jobDir,'qt.txt'))
  194. return t,sol,se,sOut,qt,lut,lutSE
  195. def getStartPoint(setup):
  196. if setup['startFromRef']=='None':
  197. return 0,numpy.array([]),numpy.array([]),[],[]
  198. t,sol,se,sOut,qt,lut,lutSE=loadSolutionFromRef(setup)
  199. return t[-1],sol[-1],sOut[-1],lut,lutSE
  200. if __name__=="__main__":
  201. parFiles=sys.argv[1].split(';')
  202. jobDir=sys.argv[2]
  203. main(parFiles,jobDir)