def count_nzero_grid(wfun, dh: float, re: float, ndim=0) -> float: """Count n_0 on simple grid.""" nzero = 0.0 nband = estim_nband(dh, re) if ndim <= 0: ndim = pympscore.GetSpaceDim() if ndim == 2: for i in range(-nband, nband + 1): for j in range(-nband, nband + 1): if i != 0 or j != 0: x = dh * i y = dh * j r = sqrt(x**2 + y**2) w = wfun(r, re) nzero += w elif ndim == 3: for i in range(-nband, nband + 1): for j in range(-nband, nband + 1): for k in range(-nband, nband + 1): if i != 0 or j != 0 or k != 0: x = dh * i y = dh * j z = dh * k r = sqrt(x**2 + y**2 + z**2) w = wfun(r, re) nzero += w else: raise ValueError("Invalid ndim=%s" % ndim) return nzero
def __init__(self): # bootstrap self.ndim = 2 pympscore.SetSpaceDim(ndim) print('spacedim=%d' % pympscore.GetSpaceDim()) # physical init_phys(self) # numerical init_comp(self)
def newVectorArray(numpart: int, ndim: int = 0, data_type=float, data_order: str = 'F') -> NP.ndarray: """Create new vector array. If NDIM not given, use MPS space dimension. The array is by default Fortan-style, to be consistent with Eigen. """ if ndim <= 0: ndim = pympscore.GetSpaceDim() return NP.empty((numpart, ndim), dtype=data_type, order=data_order)
def count_lambda_grid(wfun, dh: float, re: float, ndim=0) -> float: """Count lambda for Laplacian""" lam = 0.0 wgt = 0.0 nband = estim_nband(dh, re) if ndim <= 0: ndim = pympscore.GetSpaceDim() if ndim == 2: for i in range(-nband, nband + 1): for j in range(-nband, nband + 1): if i != 0 or j != 0: x = dh * i y = dh * j r = sqrt(x**2 + y**2) w = wfun(r, re) lam += w * r**2 wgt += w elif ndim == 3: for i in range(-nband, nband + 1): for j in range(-nband, nband + 1): for k in range(-nband, nband + 1): if i != 0 or j != 0 or k != 0: x = dh * i y = dh * j z = dh * k r = sqrt(x**2 + y**2 + z**2) w = wfun(r, re) lam += w * r**2 wgt += w else: raise ValueError("Invalid ndim=%s" % ndim) lam /= wgt return lam
def main2d(): '''2D run''' # bootstrap ndim = 2 pympscore.SetSpaceDim(ndim) print('spacedim=%d' % pympscore.GetSpaceDim()) # physical rho = 1.0e3 cs = 10.0 pref = rho * cs**2 nu = 1.0e-1 grav = NP.array([0.0, -9.81]) # discretization dh = 0.01 re_dens = dh * 2.1 re_grad = dh * 2.1 re_visc = dh * 4.1 re_pres = dh * 4.1 re_max = max(re_dens, re_grad, re_visc, re_pres) # weight function wfun = pympscore.StandardWeightFunction() wgradfun = wfun print(wfun) nzero = count_nzero_grid(wfun, dh, re_dens) nzero_part = count_nzero_grid(ConstWeight(), dh, re_dens) nzero_grad = count_nzero_grid(wgradfun, dh, re_grad) nzero_visc = count_nzero_grid(wfun, dh, re_visc) nzero_pres = count_nzero_grid(wfun, dh, re_pres) nlam_visc = count_lambda_grid(wfun, dh, re_visc) nlam_pres = count_lambda_grid(wfun, dh, re_pres) nsurf = nzero * 0.97 relax_pres = 0.2 nlam_pres *= relax_pres print('nzero=%g' % nzero) print('nzero_part=%g' % nzero_part) print('nzero_grad=%g' % nzero_grad) print('nzero_visc=%g' % nzero_visc) print('nzero_pres=%g' % nzero_pres) print('lambda_visc=%g' % nlam_visc) print('lambda_pres=%g' % nlam_pres) # data prob_type = -1 prob_type = 0 fluid_data = pympscore.FluidData(ndim) npart = 0 if prob_type == 0: init_pos = [] #init_pos += gen_simple_block(dh, [100,100], [-0.5,-0.5]) #init_pos += gen_simple_block(dh, [100,50], [-1.0,-0.25]) #init_pos += gen_simple_block(dh, [50,100], [0.0,-0.5]) init_pos += gen_simple_block(dh, [100, 50], [-0.5, 0.0]) init_pos += gen_simple_block(dh, [200, 10], [-1.0, -0.1]) npart = len(init_pos) # fluid_data.numParticle = npart fluid_data.alloc() NP.copyto(fluid_data.position(), init_pos) # mask walls msk: NP.ndarray = (fluid_data.position()[:,1] <= 0) else: prof = load_prof_file('input.grid', ndim) npart = prof['npart'] # fluid_data.numParticle = npart fluid_data.alloc() NP.copyto(fluid_data.position(), prof['pos']) NP.copyto(fluid_data.surfflag(), prof['type']) msk: NP.ndarray = (fluid_data.surfflag() != 0) # domain domain = pympscore.Domain() domain.vlo = [-2.5, -2.5] domain.vhi = [2.5, 2.5] print(domain) # cache re_big = re_max * 1.05 bucket = pympscore.BucketCache(domain) bucket.define(re_big) print(bucket) bucket.cachePositions(fluid_data.position()) # neighbor neigh_table = pympscore.NeighborTable() neigh_table.cutoff = re_big neigh_table.resize(fluid_data.numParticle) neigh_table.buildFromCache(bucket, fluid_data.position()) print("table size=%d" % len(neigh_table)) # expose data access numdens: NP.ndarray = fluid_data.numdens() surfflag: NP.ndarray = fluid_data.surfflag() pympscore.calcNumDens(wfun, re_dens, neigh_table, numdens) print("dens_min=%f" % numdens.min()) print("dens_max=%f" % numdens.max()) # coords: NP.ndarray = fluid_data.position() vel: NP.ndarray = fluid_data.velocity() pres: NP.ndarray = fluid_data.pressure() # assign some values vel.fill(0) pres.fill(0) # local buffers grad = newVectorArray(npart, ndim) visc = newVectorArray(npart, ndim) # iplot = 0 write_fluiddata_vtu("./output/homu%04d"%iplot, fluid_data) iplot += 1 #sys.exit(0) time = 0.0 dt = 0.001 max_step = 1000 for step in range(1, max_step+1): # build neighbor list bucket.cachePositions(coords) neigh_table.buildFromCache(bucket, coords) # compute number density pympscore.calcNumDens(wfun, re_dens, neigh_table, numdens) # tag surface part pympscore.tagSurfFlag(nsurf, numdens, surfflag) # compute viscosity for dir in range(ndim): coef = 2.0*ndim/(nlam_visc*nzero_visc) pympscore.calcLaplace(wfun, re_visc, coef, neigh_table, vel[:,dir], visc[:,dir]) # compute pressure if False: # explicit use EOS pympscore.calcPresEos(numdens, pres, pref, nzero) pympscore.calcSymGrad(wgradfun, re, nzero_grad, neigh_table, coords, pres, grad) # update acc = (-1.0/rho) * grad + nu * visc + grav #acc[:,0] += grav[0] #acc[:,1] += grav[1] vel += acc * dt vel[msk,:] = 0 coords += vel * dt else: # semi-implicit # trial move acc = nu * visc + grav vel += acc * dt vel[msk,:] = 0 coords += vel * dt neigh_table.updateInfo(coords) # pympscore.calcNumDens(wfun, re_dens, neigh_table, numdens) pympscore.tagSurfFlag(nsurf, numdens, surfflag) # rhs = (1.0/dt) / nzero * (numdens-nzero) # coef = 2.0*ndim / (nlam_pres * nzero_pres) coef *= (dt/rho) pympscore.solvePres(wfun, re_pres, coef, neigh_table, surfflag, rhs, pres) # clip pressure pres[pres<0] = 0 # pympscore.calcSymGrad(wfun, re_grad, nzero_grad, neigh_table, coords, pres, grad) # update acc = (-1.0/rho) * grad acc[msk,:] = 0 vel += acc * dt coords += acc * dt**2 # advance time time += dt if step%10 == 0: print('step=%d, time=%f' % (step,time)) write_fluiddata_vtu("./output/homu%04d"%iplot, fluid_data) iplot += 1 return