def _update_ctx(self, ctx): ctx['gravity'] = self.gravity ctx['bc_wall'] = 'fullbb' ctx['bc_velocity'] = None ctx['bc_pressure'] = None ctx['bc_wall_'] = geo.get_bc('fullbb') ctx['bc_velocity_'] = geo.get_bc('fullbb') ctx['bc_pressure_'] = geo.get_bc('fullbb')
def define_nodes(self): radiussq = ((self.chan_diam) / 2)**2 diam = sphere_diam(self.width, geo.get_bc(self.options.bc_velocity)) x0 = int(2.4 * diam) y0 = (self.lat_ny - 1) / 2.0 z0 = (self.lat_nz - 1) / 2.0 h = 0.0 bc = geo.get_bc(self.options.bc_velocity) h = -bc.location z0 -= bc.location y0 -= bc.location hz, hy, hx = np.mgrid[0:self.lat_nz, 0:self.lat_ny, 0:self.lat_nx] # Channel walls. node_map = (y0 - (hy + h))**2 + (z0 - (hz + h))**2 >= radiussq self.set_geo(node_map, self.NODE_VELOCITY, (self.maxv, 0.0, 0.0)) # Inlet. self.set_geo(hx == 0, self.NODE_VELOCITY, (self.maxv, 0.0, 0.0)) ix0 = int(x0) iy0 = int(y0) iz0 = int(z0) rsq = diam**2 / 4.0 miny = iy0 maxy = iy0 radius = int(diam / 2) wall_map = (x0 - (hx + h))**2 + (y0 - (hy + h))**2 + (z0 - (hz + h))**2 <= rsq self.set_geo(wall_map, self.NODE_WALL) maxy = np.max(hy[wall_map]) miny = np.min(hy[wall_map]) bc = geo.get_bc(self.options.bc_wall) self.sphere_diam = float(maxy - miny) + 2.0 * bc.location diam = int(diam) self.add_force_object( 'sphere', (ix0 - diam / 2 - 3, iy0 - diam / 2 - 3, iz0 - diam / 2 - 3), (diam + 6, diam + 6, diam + 6))
def _velocity_profile(self, hi): bc = geo.get_bc(self.options.bc_wall) width = self.get_chan_width() lat_width = self.get_width() h = -bc.location return (4.0 * self.maxv/width**2 * (hi + h) * (width - hi - h))
def define_nodes(self): radiussq = ((self.chan_diam)/2)**2 diam = sphere_diam(self.width, geo.get_bc(self.options.bc_velocity)) x0 = int(2.4*diam) y0 = (self.lat_ny - 1) / 2.0 z0 = (self.lat_nz - 1) / 2.0 h = 0.0 bc = geo.get_bc(self.options.bc_velocity) h = -bc.location z0 -= bc.location y0 -= bc.location hz, hy, hx = np.mgrid[0:self.lat_nz, 0:self.lat_ny, 0:self.lat_nx] # Channel walls. node_map = (y0 - (hy + h))**2 + (z0 - (hz + h))**2 >= radiussq self.set_geo(node_map, self.NODE_VELOCITY, (self.maxv, 0.0, 0.0)) # Inlet. self.set_geo(hx == 0, self.NODE_VELOCITY, (self.maxv, 0.0, 0.0)) ix0 = int(x0) iy0 = int(y0) iz0 = int(z0) rsq = diam**2 / 4.0 miny = iy0 maxy = iy0 radius = int(diam / 2) wall_map = (x0 - (hx+h))**2 + (y0 - (hy+h))**2 + (z0 - (hz+h))**2 <= rsq self.set_geo(wall_map, self.NODE_WALL) maxy = np.max(hy[wall_map]) miny = np.min(hy[wall_map]) bc = geo.get_bc(self.options.bc_wall) self.sphere_diam = float(maxy - miny) + 2.0 * bc.location diam = int(diam) self.add_force_object('sphere', (ix0-diam/2-3, iy0-diam/2-3, iz0-diam/2-3), (diam+6, diam+6, diam+6))
def get_profile(self): # NOTE: This only works for the 'along_y' option. if geo.get_bc(self.options.bc_wall).wet_nodes: return self.vy[:, int(self.options.lat_ny / 2), int(self.options.lat_nx / 2)] else: return self.vy[1:-1, int(self.options.lat_ny / 2), int(self.options.lat_nx / 2)]
def get_profile(self): if geo.get_bc(self.options.bc_wall).wet_nodes: if self.options.horizontal: return self.vx[:,int(self.options.lat_nx/2)] else: return self.vy[int(self.options.lat_ny/2),:] else: if self.options.horizontal: return self.vx[1:-1,int(self.options.lat_nx/2)] else: return self.vy[int(self.options.lat_ny/2),1:-1]
def __init__(self, geo_class, defaults={}, args=sys.argv[1:]): opts = [] opts.append(optparse.make_option('--re', dest='re', type='int', help='Reynolds number', default=100)) defaults_ = {'lat_nz': 128, 'lat_ny': 128, 'lat_nx': 512, 'max_iters': 320000, 'model': 'mrt', 'every': 100, 'incompressible': True, 'grid': 'D3Q13', 'bc_velocity': 'fullbb', 'verbose': True} defaults_.update(defaults) lb_single.FluidLBMSim.__init__(self, geo_class, options=opts, args=args, defaults=defaults_) if self.options.batch and not ('every' in self.options.specified): self.options.every = 1000 diam = sphere_diam(self.options.lat_ny, geo.get_bc(self.options.bc_velocity)) # If the diameter here is odd, the channel width is even and we will end up # with a sphere of an even diameter so that the system can be symmetric. if diam % 2: diam -= 1.0 # maxv / visc ratio = self.options.re / diam visc = 0.12 maxv = ratio * visc # Try to keep the viscosity as high as possible to make sure the computed force # is correct. For single precision calculations, flows with low viscosity and # low flow speed can yield incorrect values. There are no such problems for # double precision simulations. if maxv > 0.1: geo_class.maxv = 0.1 self.options.visc = geo_class.maxv / ratio else: geo_class.maxv = maxv self.options.visc = visc if self.options.verbose: self._timed_print('# maxv = %s' % geo_class.maxv) self.add_iter_hook(self.options.every, self.print_force, every=True) if self.options.verbose: self.add_iter_hook(5, self.print_theoretical_drag) self.coeffs = []
def _update_ctx(self, ctx): ctx['incompressible'] = self.incompressible ctx['bc_wall'] = self.options.bc_wall ctx['bc_slip'] = self.options.bc_slip if self.geo.has_velocity_nodes: ctx['bc_velocity'] = self.options.bc_velocity else: ctx['bc_velocity'] = None if self.geo.has_pressure_nodes: ctx['bc_pressure'] = self.options.bc_pressure else: ctx['bc_pressure'] = None ctx['bc_wall_'] = geo.get_bc(self.options.bc_wall) ctx['bc_slip_'] = geo.get_bc(self.options.bc_slip) ctx['bc_velocity_'] = geo.get_bc(self.options.bc_velocity) ctx['bc_pressure_'] = geo.get_bc(self.options.bc_pressure) ctx['simtype'] = 'fluid' ctx['subgrid'] = self.options.subgrid ctx['smagorinsky_const'] = self.options.smagorinsky_const
def get_velocity_profile(self, fluid_only=False): bc = geo.get_bc(self.options.bc_wall) x = self.lat_nx/2 if fluid_only and not bc.wet_nodes: zvals = range(1, self.lat_nz-1) else: zvals = range(0, self.lat_nz) ret = [] for z in zvals: rc = math.sqrt((x-self.lat_nx/2.0+0.5)**2 + (z-self.lat_nz/2.0+0.5)**2) ret.append(self.get_velocity(rc)) return ret
def get_velocity_profile(self, fluid_only=False): bc = geo.get_bc(self.options.bc_wall) width = self.get_chan_width() lat_width = self.get_width() ret = [] h = -bc.location for x in range(0, lat_width): tx = x+h ret.append(4.0*self.maxv/width**2 * tx * (width-tx)) # Remove data corresponding to non-fluid nodes if necessary. if fluid_only and not bc.wet_nodes: return ret[1:-1] return ret
def get_velocity_profile(self, fluid_only=False): bc = geo.get_bc(self.options.bc_wall) x = self.lat_nx / 2 if fluid_only and not bc.wet_nodes: zvals = range(1, self.lat_nz - 1) else: zvals = range(0, self.lat_nz) ret = [] for z in zvals: rc = math.sqrt((x - self.lat_nx / 2.0 + 0.5)**2 + (z - self.lat_nz / 2.0 + 0.5)**2) ret.append(self.get_velocity(rc)) return ret
def get_profile(self): # NOTE: This only works for the 'along_y' option. if geo.get_bc(self.options.bc_wall).wet_nodes: return self.vy[:,int(self.options.lat_ny/2),int(self.options.lat_nx/2)] else: return self.vy[1:-1,int(self.options.lat_ny/2),int(self.options.lat_nx/2)]
def get_chan_width(self): bc = geo.get_bc(self.options.bc_wall) return self.get_width() - 1 - 2 * bc.location
def chan_diam(self): """The actual channel diameter in lattice units.""" bc = geo.get_bc(self.options.bc_velocity) return self.width - 1 - 2.0 * bc.location
def __init__(self, geo_class, defaults={}, args=sys.argv[1:]): opts = [] opts.append( optparse.make_option('--re', dest='re', type='int', help='Reynolds number', default=100)) defaults_ = { 'lat_nz': 128, 'lat_ny': 128, 'lat_nx': 512, 'max_iters': 320000, 'model': 'mrt', 'every': 100, 'incompressible': True, 'grid': 'D3Q13', 'bc_velocity': 'fullbb', 'verbose': True } defaults_.update(defaults) lb_single.FluidLBMSim.__init__(self, geo_class, options=opts, args=args, defaults=defaults_) if self.options.batch and not ('every' in self.options.specified): self.options.every = 1000 diam = sphere_diam(self.options.lat_ny, geo.get_bc(self.options.bc_velocity)) # If the diameter here is odd, the channel width is even and we will end up # with a sphere of an even diameter so that the system can be symmetric. if diam % 2: diam -= 1.0 # maxv / visc ratio = self.options.re / diam visc = 0.12 maxv = ratio * visc # Try to keep the viscosity as high as possible to make sure the computed force # is correct. For single precision calculations, flows with low viscosity and # low flow speed can yield incorrect values. There are no such problems for # double precision simulations. if maxv > 0.1: geo_class.maxv = 0.1 self.options.visc = geo_class.maxv / ratio else: geo_class.maxv = maxv self.options.visc = visc if self.options.verbose: self._timed_print('# maxv = %s' % geo_class.maxv) self.add_iter_hook(self.options.every, self.print_force, every=True) if self.options.verbose: self.add_iter_hook(5, self.print_theoretical_drag) self.coeffs = []
if options.grid: grid = options.grid else: if options.dim == "2": grid = "D2Q9" else: grid = "D3Q13" if options.drive == "force": geo_type = geo.LBMGeo.NODE_WALL else: geo_type = geo.LBMGeo.NODE_PRESSURE if options.bc: bcs = filter(lambda x: geo_type in geo.get_bc(x).supported_types, options.bc.split(",")) else: bcs = [x.name for x in geo.SUPPORTED_BCS if geo_type in x.supported_types] class LTestPoiSim(LPoiSim): def __init__(self, args, defaults): super(LTestPoiSim, self).__init__(LBMGeoPoiseuille, args, defaults) self.clear_hooks() self.add_iter_hook(self.options.max_iters - 1, self.save_output) def save_output(self): # self.result = (numpy.max(self.vy[16,1:self.geo.lat_nx-1]) / max(self.geo.get_velocity_profile())) - 1.0 self.res_maxv = numpy.max(self.geo.mask_array_by_fluid(self.vy)) self.th_maxv = max(self.geo.get_velocity_profile())