Example #1
0
    x=string.split('-')
    return (int(x[0]),int(x[1]))
  else:
    return int(string)

parser = argparse.ArgumentParser(
    description="Plots for Pressure Swing Adsorption Oxygen Concentration simulation",
    epilog='''
''')

parser.add_argument("files", nargs='+',type=str, help="pickle files to plot", default=None)
parser.add_argument('-c', '--cycles', type=parseIntRange, help="cycle or range of cycles to plot, .e.g. 4 or 0-2", default=None)
parser.add_argument('-n', '--nopause', action='store_true', help="do not pause after generating plots")
options = parser.parse_args()

print('git revision:{}'.format(util.get_git_commit()))

  
class AttrDict(dict):
  def __init__(self, *args, **kwargs):
    super(AttrDict, self).__init__(*args, **kwargs)
    self.__dict__ = self

for file in options.files:
  with open(file, 'rb') as fp:
    data=pickle.load(fp)
  print('loaded {}'.format(file))
  print('cyles {}'.format(options.cycles))
  head,tail=os.path.split(file)
  print('head={} tail={}'.format(head,tail))
  #take the part up to the dash in tail, and add something
Example #2
0
def simulate(override_param, outdir=None,params_file='params',verbose=False):
  #params to override the defaults from params.py
  #plots: create output plots
  #pause: if creating plots, pause when they are displayed on screen for <Enter>
  #returns metrics of simulation as a dict, and the full params used
  #writes a log file (and optional plots) into outdir.  use outdir=None for
  #no log file and instead direct all outout to stdout.  plots will go into
  #current directory in that case.
  #params is the file to import (default is params)
  #roi is (t1,t2) time range for the spatial plots
  #returns out_place: directory+logcode prefix that it used for log file
  global gverbose
  gverbose=verbose
  params=importlib.import_module(params_file)

  np.seterr(all='warn')
  global param
  global norm
  global dg
  global count
  global tstart
  #we will alter print statement for this module to go into the log file
  global print
  if outdir is None:
    dbg=mylog.Log(outdir=None,descr='psa')
    OUTDIR='./'
  else:
    OUTDIR=outdir  # for log files and png files
    dbg=mylog.Log(outdir=OUTDIR,descr='psa')
  #change the print function in the module to print to the log file
  old_print=print
  print=dbg.print

  param=params.create_param(override_param, dbg.print)
  norm=create_norm()
  
  print('simulation params: time 0 to {}, step {}'.format(param.end_time,param.tstep))
  print('step time might be increased if long cycle time')
  print('normalization velocity {:8.3f} m/s'.format(param.norm_v0))
  print('normalization of time norm.t0 {:8.3f} sec'.format(norm.t0))
  print('starting with params import file: {}'.format(params))
  state1=init(param,norm)
  state2=init(param,norm)
  prod=AttrDict()
  prod.Pprod=1e5/norm.P0          # 1 atm to start
  prod.yprod=param.feed_O2        # fract of O2 in product tank

  #create dimensionless groups for the constants needed in the simulation
  dg=create_dgroups(norm,param,state1)

  np.set_printoptions(precision=5, edgeitems=6, linewidth=95, suppress=False)
  pp=pprint.PrettyPrinter(indent=2)

  print('git revision:{}'.format(util.get_git_commit()))
  print('log code: {}'.format(dbg.log_code))
  sys.stdout.write('log file prefix code: {}\n'.format(dbg.log_code))

  print('version:{}'.format(vinfo))
  print('plt {}'.format(matplotlib.__version__))
  #print out the parameters and numbers for the record
  print('dimensionless groups:\n',pp.pformat(dg.__dict__))
  print('parameters:\n',pp.pformat(param.__dict__))

  #create directory and log_code to prepend to out png files
  util.safe_mkdir(OUTDIR)
  out_place=os.path.join(OUTDIR,dbg.log_code)
  #write to screen, not log file
  sys.stdout.write('out_place={}\n'.format(out_place))
  #output is to 1 ATM pressure (abs)
  x01=np.hstack((state1.P,state1.T,state1.Tw,state1.xA,state1.xB,state1.yA,state1.yB))
  x02=np.hstack((state2.P,state2.T,state2.Tw,state2.xA,state2.xB,state2.yA,state2.yB))
  x03=np.array([prod.Pprod, prod.yprod])
  print(x01.shape,x02.shape,x03.shape)
  x0=np.hstack((x01,x02,x03))
  tstart=time.time()
  #time normalized by norm.t0
  #Vectorized means that myfun can take a matrix of values to evaluate dx/dt at,
  #not that x0 is a matrix
  compute_alpha(verbose=True)  # just print out the values for the log file
  #we add a small number because we want to get full cycle at end
  #also, increase tstep is a long cycle time:
  param.tstep=max(param.tstep, param.cycle_time/100)
  end_simulation=param.end_time+1e-6
  t_span=(0,end_simulation)
  #we want to include the end_simulation time
  ev=np.arange(0,end_simulation,param.tstep)
  print('t_span {}'.format(t_span))
  #print('t_eval {}'.format(ev))
  sys.stdout.write('Calling ODE solver\n')
  bunch=scipy.integrate.solve_ivp(myfun, t_span, x0, vectorized=False, t_eval=ev,
                                  method='BDF')
###                                  method='Radau')
  if not bunch.success:
    print(bunch.message)
    sys.stdout.write(bunch.message)
    return None
  print('evaluated at {} places'.format(bunch.t.size))
  print('num eval of RHS {}'.format(bunch.nfev))
  print('num eval of Jacobian {}'.format(bunch.njev))
  print('total number of elements in data is {}'.format(bunch.y.size))
  print('number of elements > 2 = {}'.format(np.sum(bunch.y>2)))
  print('number of elements > 1 = {}'.format(np.sum(bunch.y>1)))
  print('number of elements < 0 = {}'.format(np.sum(bunch.y<0)))
  
  #t will be array of time points (t_points)
  #y will be array of (n x t_points) values
  N=param.N
  #take the output data from ODE solver and place in data.<name> for plotting
  data=AttrDict()
  data.data1,data.data2,data.datap=data_to_state(bunch.y)
  data.t=bunch.t
  print('bunch.t',data.t)
  data.param=param
  print_state_ranges(data.data1)
  print_state_ranges(data.data2)
  #compute xAs at each point
  data.data1.xAs,data.data1.xBs=adsorp_equilibrium(data.data1.yA,data.data1.yB,data.data1.P)
  data.data2.xAs,data.data2.xBs=adsorp_equilibrium(data.data2.yA,data.data2.yB,data.data2.P)
  #compute velocity at each point
  data.data1.V=compute_vel(data.data1)
  data.data2.V=compute_vel(data.data2)
  #Output key statistics in log file with keywords
  #get indexes for full cycle
  print('CYCLE {:8.2f}'.format(param.cycle_time))
  print('VENT {:8.2f}'.format(param.vent_time))
  #indexes to select over - the last 2 cycles for container 1
  r=np.argmax(bunch.t>(max(bunch.t)-2*param.cycle_time))
  ret=AttrDict()
  ret.time=datetime.datetime.now().replace(microsecond=0).isoformat()
  ret.end_time=end_simulation
  ret.cycle_time=param.cycle_time
  ret.vent_time=param.vent_time
  ret.norm_t0=norm.t0
  ret.real_cycle_time=param.cycle_time*norm.t0
  ret.real_vent_time=param.vent_time*norm.t0
  #these are all min,max,mean for the last cycle of container 1
  #for container 1, we calculate parameters for all the odd cycles and store in
  # a list.  To get last one, use index [-1]
  idx=0
  ret.container_y=[]
  ret.prod_pressure=[]
  ret.prod_y=[]
  ret.prod_flow_rate=[]
  while True:
    start=param.cycle_time*idx
    stop=param.cycle_time*(idx+1)
    if stop > max(bunch.t):
      break
    #create a mask of the times for this odd cycle (starting with 1st one)
    mask=np.logical_and(start <= bunch.t, bunch.t <= stop)
    ret.container_y.append([np.min(data.data1.yA[-1,mask]),
                            np.max(data.data1.yA[-1,mask]), 
                            np.mean(data.data1.yA[-1,mask])])
    ret.prod_pressure.append([np.min(data.datap.Pprod[0,mask]),
                              np.max(data.datap.Pprod[0,mask]),
                              np.mean(data.datap.Pprod[0,mask])])
    ret.prod_y.append([np.min(data.datap.yprod[0,mask]),
                       np.max(data.datap.yprod[0,mask]),
                       np.mean(data.datap.yprod[0,mask])])
    #compute product flow in LPM
    ret.prod_flow_rate.append([product_flow_rate(np.min(data.datap.Pprod[0,mask])),
                               product_flow_rate(np.max(data.datap.Pprod[0,mask])),
                               product_flow_rate(np.mean(data.datap.Pprod[0,mask]))])
    idx+=2
    
  ret.logcode=dbg.log_code
  print('results:\n',pp.pformat(ret))
  print('These are repr() outputs for programmatic reading')
  print('PARAM {}'.format(repr(param)))
  print('RESULT {}'.format(repr(ret)))
  data.ret=ret
  #save to pickle file
  pickle_name='{}-data.pickle'.format(out_place)
  with open(pickle_name, 'wb') as fp:
    pickle.dump(data,fp)
  #close the log file because might be called again before exiting and will
  #want a new log file for that simulation
  dbg.close()
  #restore print function
  print=old_print
  return data, ret, param, pickle_name, out_place