def draglift(simulations, sortby="dx", **kwargs): """ Compute mean drag coefficient, rms lift coefficient, and Strouhal number for flow past a circular cylinder. If the flow is steady, only drag and lift coefficients are computed. Call signature: draglift(simulations, d_cylinder=0.1, u_0=1.0, flow_dir='y', t_start=-1, sortby='dx'): Keyword arguments: *simulations* array of simulation names to be included in the computations *d_cylinder*: diameter of the cylinder *u_0* velocity at the inlet *flow_dir*: direction of the flow *t_start* time to start the drag computations from should be where the a steady vortex shedding has developed *sortby* property to sort the arrays by typical choices for parametric studies are grid size, length of domain, etc. Returns object with information: sim-name, drag (mean), lift (rms), and st (non-dim shedding frequency) """ sims = [] for simulation in simulations: sims.append(sim.get(simulation, quiet=True)) # Sort simulations sims = sim.sort(sims, sortby, reverse=True) draglift_tmp = [] for i, thissim in enumerate(sims): draglift_tmp.append(Draglift()) draglift_tmp[i].set_name(thissim) draglift_tmp[i].compute(thissim, **kwargs) return draglift_tmp
def twonorm_accuracy1D(simulations, field='ur', strip=1, direction='r', varfile='ogvar.dat', noerr=True, quiet=True): """ Assessment of accuracy of simulation: Computes the two-norm error of all available simulation, where the simulation with the maximum amount of grid points is used as the correct/reference solution. E.g., for runs with grid points assessment of accuracy of x-component of velocity along the y-direction, for runs with grid points nxgrid = n, 2n, 4n, 8n, compute || u_n - u_0 || = dy \sum\limits_{n=0}^n (sqrt(u_n(x_n)-u_0(x_8n))) for all runs (except for the 8n case, used as reference). Requires that the runs have matching grids, that is, grid refined by a factor of 2m, and grids adjusted so that the grid point overlap (needs ofset if periodic BC is used). call signature: twonorm_accuracy(simulations) Keyword arguments: *simulations* array of simulation names to be included in the computations *field* variable used in accuracy assessment *varfile*: name of varfile to read from each sim *noerr*: set to false if you want to return an array of maximum error along strip, in addition to the two-norm Returns array of two-norms where the larges array is used as base """ import numpy as np import os as os from pencil import read from pencil import sim # Find directories to include in accuracy assessment sims = [] for simulation in simulations: sims.append(sim.get(simulation, quiet=True)) # Sort runs by size of grid spacing sims = sim.sort(sims, 'dx', reverse=True) # From this point we only need the varfile to compute accuracy # Need to update dim to ogdim for reading of ogvar to be done # correctly from simulation object for i, thissim in enumerate(sims): sims[i].dim = read.ogdim(datadir=thissim.datadir) sims[i] = read.ogvar(sim=thissim, trimall=True, varfile=varfile) # Check that increase in size is correct for use in two-norm calculation nsims = len(sims) nx_min = sims[0].r.size ny_min = sims[0].th.size for thissim in sims: if ((thissim.r.size - 1) % (nx_min - 1) != 0): print('ERROR: Incorrect size in r-dir') print('sims.r', thissim.r.size) print('nx_min', nx_min) return False if (thissim.th.size % ny_min != 0): print('ERROR: Incorrect size in th-dir') return False # Check that all var-files are for the same time t = sims[0].t for thissim in sims: if thissim.t != t: print('WARNING: Incorrect time for one or more simulations') # Now we are sure that first coordinate of r and th are the same for all runs # Can compute the two-norms for increasing sizes. Use largest size as normalization of error twonorms = np.zeros(nsims - 1) maxerrs = np.zeros(nsims - 1) # Compute array of factor used to jump indices when comparing two arrays of size N and 2N etc. # Usually n2_fac = [8, 4, 2] or similar n2_fac = np.empty(nsims - 1) for i, thissim in enumerate(sims[:-1]): n2_fac[i] = thissim.dx / sims[-1].dx u2 = getattr(sims[-1], field) if not (field == 'ux' or field == 'uy'): u2 = u2[0, :, :] for i, thissim in enumerate(sims[:-1]): u1 = getattr(thissim, field) if not (field == 'ux' or field == 'uy'): u1 = u1[0, :, :] dr = np.empty(thissim.r.size) dr[0:-1] = thissim.r[1:] - thissim.r[0:-1] dr[-1] = dr[-2] dth = thissim.dy twonorms[i] = 0. n2 = n2_fac[i] if (direction == 'r'): r = sims[0].r[strip] j = int(strip * sims[0].dx / thissim.dx) for k in range(thissim.th.size): twonorms[i] = twonorms[i] + dth * r * ( u1[k, j] - u2[int(k * n2), int(j * n2)])**2 elif (direction == 'th'): k = int(strip * sims[0].dx / thissim.dx) for j in range(thissim.r.size): twonorms[i] = twonorms[i] + dr[j] * ( u1[k, j] - u2[int(k * n2), int(j * n2)])**2 else: print('ERROR: Invalid direction chosen') return False twonorms[i] = np.sqrt(twonorms[i]) if not noerr: return twonorms, maxerrs else: return twonorms
def twonorm_accuracy(simulations, field='ux', strip=0, var_file='ogvar.dat', direction='x', noerr=True, quiet=True): """ Assessment of accuracy of simulation: Computes the two-norm error of all available simulation, where the simulation with the maximum amount of grid points is used as the correct/reference solution. E.g., for runs with grid points assessment of accuracy of x-component of velocity along the y-direction, for runs with grid points nxgrid = n, 2n, 4n, 8n, compute || u_n - u_0 || = dy \sum\limits_{n=0}^n (sqrt(u_n(x_n)-u_0(x_8n))) for all runs (except for the 8n case, used as reference). Requires that the runs have matching grids, that is, grid refined by a factor of 2m, and grids adjusted so that the grid point overlap (needs ofset if periodic BC is used). call signature: twonorm_accuracy(simulations) Keyword arguments: *simulations* array of simulation names to be included in the computations *field* variable used in accuracy assessment *strip*: index for strip along coordinate *var_file*: name of varfile to read from each sim *direction*: compute two-norm along 'x' or 'y' direction *noerr*: set to false if you want to return an array of maximum error along strip, in addition to the two-norm Returns array of two-norms where the larges array is used as base """ import numpy as np import os as os from pencil import read from pencil import sim # Find directories to include in accuracy assessment sims = [] for simulation in simulations: sims.append(sim.get(simulation, quiet=True)) # Sort runs by size of grid spacing if (direction == 'x' or direction == 'r'): sims = sim.sort(sims, 'nx', reverse=False) elif (direction == 'y' or direction == 'th'): sims = sim.sort(sims, 'ny', reverse=False) # From this point we only need the varfile to compute accuracy # Need to update dim to ogdim for reading of ogvar to be done # correctly from simulation object for i, thissim in enumerate(sims): sims[i].dim = read.ogdim(datadir=thissim.datadir) sims[i] = read.ogvar(sim=thissim, trimall=True, var_file=var_file) # Check that increase in size is correct for use in two-norm calculation nsims = len(sims) nx_min = sims[0].r.size ny_min = sims[0].th.size for thissim in sims: if ((thissim.r.size - 1) % (nx_min - 1) != 0): print('ERROR: Incorrect size in r-dir') print('sims.r', thissim.r.size) print('nx_min', nx_min) return False if (thissim.th.size % ny_min != 0): print('ERROR: Incorrect size in th-dir') return False # Check that all var-files are for the same time t = sims[0].t for thissim in sims: if thissim.t != t: print('WARNING: Incorrect time for one or more simulations') # Now we are sure that first coordinate of r and th are the same for all runs # Can compute the two-norms for increasing sizes. Use largest size as normalization of error twonorms = np.zeros(nsims - 1) maxerrs = np.zeros(nsims - 1) if (direction == 'x' or direction == 'r'): dh = sims[0].dx n2_factor = int(dh / sims[-1].dx) elif (direction == 'y' or direction == 'th'): dh = sims[0].dy n2_factor = int(dh / sims[-1].dy) attribute = getattr(sims[-1], field) if (field == 'ux' or field == 'uy'): u2 = attribute[0::n2_factor, 0::n2_factor] else: u2 = attribute[0, 0::n2_factor, 0::n2_factor] strip = int(strip) if (direction == 'x' or direction == 'r'): dh = sims[-1].dx dx_max = sims[0].dx n2_factor = int(thissim.dx / dh) #for i,thissim in enumerate(sims[:-1]): # strips[i]=int(thissim.dx/dx_max*strip) #n1_factor = int(sims[0].dx/sims[-1].dx) elif (direction == 'y' or direction == 'th'): dh = sims[-1].dy dx_max = sims[0].dy #for i,thissim in enumerate(sims[:-1]): # strips[i]=int(thissim.dy/dx_max*strip) #n1_factor = int(sims[0].dx/sims[-1].dy) attribute = getattr(sims[-1], field) # if(field=='ux' or field=='uy'): # u2 = attribute[0::n2_factor,0::n2_factor] # else: # u2 = attribute[0,0::n2_factor,0::n2_factor] j = 1 for i, thissim in enumerate(sims[:-1]): n1_factor = 1 if (direction == 'x' or direction == 'r'): n2_factor = int(thissim.dx / dh) elif (direction == 'y' or direction == 'th'): n2_factor = int(thissim.dy / dh) u1 = getattr(thissim, field) if (field == 'ux' or field == 'uy'): u2 = attribute[0::n2_factor, 0::n2_factor] #u1 = u1[0::n1_factor] else: u2 = attribute[0, 0::n2_factor, 0::n2_factor] u1 = u1[0, :, :] #0::n1_factor,:] #u1 = u1[0,0::n1_factor,:] radius_l = sims[-1].r[0::n2_factor] if (direction == 'x' or direction == 'r'): twonorms[i] = (twonorm(u1[:, strip * j], u2[:, strip * j], thissim.dy * sims[0].r[strip])) maxerrs[i] = (maxerror(u1[:, strip * j], u2[:, strip * j])) elif (direction == 'y' or direction == 'th'): twonorms[i] = (twonorm(u1[strip * j, :], u2[strip * j, :], thissim.dx)) maxerrs[i] = (maxerror(u1[strip * j, :], u2[strip * j, :])) j = j * 2 # n1_factor = 1 # u1 = getattr(thissim,field) # if(not(field=='ux' or field=='uy')): # u1=u1[0,:,:] # # if(direction=='x' or direction=='r'): # n1_factor = int(dx_max/thissim.dx) # n2_factor = int(thissim.dx/dh) # u1 = u1[:,0::n1_factor] # u2 = attribute[0,0::n2_factor,0::n2_factor] # u2 = u2[:,0::n1_factor] # elif(direction=='y' or direction=='th'): # n1_factor = int(dx_max/thissim.dy) # n2_factor = int(thissim.dy/dh) # u1 = u1[0::n1_factor,:] # u2 = attribute[0,0::n2_factor,0::n2_factor] # u2 = u2[0::n1_factor,:] # # if(direction=='x' or direction=='r'): # twonorms[i] = (twonorm(u1[:,strip],u2[:,strip],thissim.dy*sims[0].r[strip])) # maxerrs[i] = (maxerror(u1[:,strip],u2[:,strip])) # elif(direction=='y' or direction=='th'): # twonorms[i] = (twonorm(u1[strip,:],u2[strip,:],thissim.dx)) # maxerrs[i] = (maxerror(u1[strip,:],u2[strip,:])) if (not quiet): print('Two-norm computed for field:', field, ', along strip:', strip) if (direction == 'x'): print('Along x-direction') elif (direction == 'r'): print('Along r-direction') elif (direction == 'y'): print('Along y-direction') elif (direction == 'th'): print('Along th-direction') if not noerr: return twonorms, maxerrs else: return twonorms