def update(self, delta_t=None, *args, **kwargs): """ Update all the particles in the bucket to the next time level.""" logger.info("In ParticleBucket.Update: %d particles", len(self.particles)) # redistribute particles to partitions in case of parallel adaptivity if Parallel.is_parallel(): self.redistribute() # reset the particle timestep if delta_t is not None: self.delta_t = delta_t self.system.temporal_cache.range(self.time, self.time + self.delta_t) live = self.system.in_system(self.pos(), len(self), self.time) _ = [] for k, part in enumerate(self): if live[k]: part.update(self.delta_t, *args, **kwargs) else: self.dead_particles.append(part) _.append(part) for part in _: self.particles.remove(part) self.redistribute() self.insert_particles(*args, **kwargs) self.time += self.delta_t for part in self: part.time = self.time
def mclaury_mass_coeff(collision, material=None): """ Wear rate coefficient of collision from Mclaury correlation""" material = material or STANDARD_MATERIAL n_exp = material['n'] coeff = material['k'] hardness = material['H'] sharpness_factor = material['F_s'] penetration_factor = material['F_B'] logger.info('collision angle: %s', collision.angle) logger.info('collision normal: %s', collision.normal) def fun(theta): """ Mclaury angle response function""" if numpy.tan(theta) > 1.0 / 3.0: return numpy.cos(theta)**2 / 3.0 #otherwise return numpy.sin(2.0 * theta) - 3.0 * numpy.sin(theta)**2 vel = numpy.sqrt(numpy.dot(collision.vel, collision.vel)) vel0 = 0.1 beta = 1.0 return (coeff * hardness * sharpness_factor * penetration_factor * (vel**n_exp * fun(collision.angle) + max(0.0, beta * (vel * numpy.sin(collision.angle) - vel0)**2)))
def __init__(self, X, V, time=0, delta_t=1.0e-3, parameters=ParticleBase.PhysicalParticle(), system=System.System(), field_data=None, online=True, **kwargs): """Initialize the bucket Args: X (float): Initial particle positions. V (float): Initial velocities """ logger.info("Initializing ParticleBucket") field_data = field_data or {} self.system = system ### pick only points which are actually in our test box live = system.in_system(X, len(X), time) X = X.compress(live, axis=0) V = V.compress(live, axis=0) self.particles = [] self.dead_particles = [] self.parameters = parameters for _, (dummy_pos, dummy_vel) in enumerate(zip(X, V)): par = Particle((dummy_pos, dummy_vel, time, delta_t), system=self.system, parameters=parameters.randomize(), **kwargs) if par.pure_lagrangian: par.vel = par.picker(par.pos, time)[0] for name, value in field_data.items(): par.fields[name] = copy.deepcopy(value[_]) if self.system.temporal_cache: dummy_u, dummy_p = par.get_fluid_properties() if dummy_u is not None: self.particles.append(par) else: self.particles.append(par) self.time = time self.delta_t = delta_t self._online = online self.solid_pressure_gradient = numpy.zeros((len(self.particles), 3)) for particle, gsp in zip(self, self.solid_pressure_gradient): particle.solid_pressure_gradient = gsp self.redistribute()
def point_average(model, bucket): """ Calculate a volume fraction estimate at the level of the grid.""" ugrid = vtk.vtkUnstructuredGrid() ugrid.DeepCopy(model) locator = vtk.vtkPointLocator() locator.SetDataSet(ugrid) locator.BuildLocator() LENGTH = 0.05 volfrac = numpy.zeros(ugrid.GetNumberOfPoints()) volume = numpy.zeros(ugrid.GetNumberOfPoints()) cell_volume = numpy.zeros(ugrid.GetNumberOfPoints()) temperature = numpy.zeros(ugrid.GetNumberOfPoints()) solid_pressure = numpy.zeros(ugrid.GetNumberOfPoints()) velocity = numpy.zeros((ugrid.GetNumberOfPoints(), 3)) for _ in range(ugrid.GetNumberOfCells()): cell = ugrid.GetCell(_) loc_vol = get_measure(cell) / cell.GetNumberOfPoints() for i in range(cell.GetNumberOfPoints()): logger.info(cell.GetPointIds().GetId(i)) cell_volume[cell.GetPointIds().GetId(i)] += loc_vol for particle in bucket: point_list = vtk.vtkIdList() locator.FindPointsWithinRadius(LENGTH, particle.pos, point_list) for _ in range(point_list.GetNumberOfIds()): point_index = point_list.GetId(_) rad2 = 0.0 * distance2(ugrid.GetPoints().GetPoint(point_index), particle.pos) rad2 /= LENGTH**2 gamma = particle.volume * numpy.exp(-rad2) volume[point_index] += gamma velocity[point_index, :] += particle.vel * gamma for _ in range(ugrid.GetNumberOfPoints()): if volume[_] > 1.0e-12: velocity[_, :] /= volume[_] volfrac = volume / cell_volume for particle in bucket: point_list = vtk.vtkIdList() locator.FindPointsWithinRadius(LENGTH, particle.pos, point_list) for _ in range(point_list.GetNumberOfIds()): point_index = point_list.GetId(_) rad2 = distance2(ugrid.GetPoints().GetPoint(point_index), particle.pos) rad2 /= LENGTH**2 gamma = particle.volume * numpy.exp(-rad2) c = distance2(particle.vel, velocity[point_index, :]) temperature[point_index] += c * gamma for _ in range(ugrid.GetNumberOfPoints()): if volume[_] > 1.0e-12: temperature[_] /= volume[_] solid_pressure = (bucket.particles[0].parameters.rho * volfrac * radial_distribution_function(volfrac) * temperature) data = [vtk.vtkDoubleArray()] data[0].SetName('SolidVolumeFraction') data.append(vtk.vtkDoubleArray()) data[1].SetName('SolidVolumeVelocity') data[1].SetNumberOfComponents(3) data.append(vtk.vtkDoubleArray()) data[2].SetName('GranularTemperature') data.append(vtk.vtkDoubleArray()) data[3].SetName('SolidPressure') for _ in range(ugrid.GetNumberOfPoints()): data[0].InsertNextValue(cell_volume[_]) data[1].InsertNextTuple3(*(velocity[_])) data[2].InsertNextValue(temperature[_]) data[3].InsertNextValue(solid_pressure[_]) pdata = vtk.vtkDoubleArray() pdata.SetName('Time') for _ in range(ugrid.GetNumberOfPoints()): pdata.InsertNextValue(bucket.time) for _ in data: ugrid.GetPointData().AddArray(_) ugrid.GetPointData().AddArray(pdata) return ugrid