def initialize(self, num_new_particles, spill, data_arrays, substance): """ Update values of 'rise_vel' and 'droplet_diameter' data arrays for new particles. First create a droplet_size array sampled from specified distribution, then use the cython wrapped (C++) function to set the 'rise_vel' based on droplet size and properties like LE_density, water density and water_viscosity: gnome.cy_gnome.cy_rise_velocity_mover.rise_velocity_from_drop_size() """ drop_size = np.zeros((num_new_particles, ), dtype=np.float64) le_density = np.zeros((num_new_particles, ), dtype=np.float64) self.distribution.set_values(drop_size) data_arrays['droplet_diameter'][-num_new_particles:] = drop_size # Don't require a water object # water_temp = spill.water.get('temperature') # le_density[:] = substance.density_at_temp(water_temp) if spill.water is not None: water_temp = spill.water.get('temperature') le_density[:] = substance.density_at_temp(water_temp) else: le_density[:] = substance.density_at_temp() # now update rise_vel with droplet size - dummy for now rise_velocity_from_drop_size( data_arrays['rise_vel'][-num_new_particles:], le_density, drop_size, self.water_viscosity, self.water_density)
def set_newparticle_values(self, num_new_particles, current_time, time_step, data_arrays): """ SpillContainer will release elements and initialize all data_arrays to default initial value. The SpillContainer gets passed as input and the data_arrays for 'position' get initialized correctly by the release object: self.release.set_newparticle_positions() If a Spill Amount is given, the Spill object also sets the 'mass' data array; else 'mass' array remains '0' :param int num_new_particles: number of new particles that were added. Always greater than 0 :param current_time: current time :type current_time: datetime.datetime :param time_step: the time step, sometimes used to decide how many should get released. :type time_step: integer seconds :param data_arrays: dict of data_arrays provided by the SpillContainer. Look for 'positions' array in the dict and update positions for latest num_new_particles that are released :type data_arrays: dict containing numpy arrays for values Also, the set_newparticle_values() method for all element_type gets called so each element_type sets the values for its own data correctly """ mass_fluxes = [tam_drop.mass_flux for tam_drop in self.droplets] delta_masses, proportions, total_mass = self._get_mass_distribution(mass_fluxes, time_step) # set up LE distribution, the number of particles in each 'release point' LE_distribution = [int(num_new_particles * p) for p in proportions] diff = num_new_particles - sum(LE_distribution) for i in range(0, diff): LE_distribution[i % len(LE_distribution)] += 1 # compute release point location for each droplet positions = [self.start_position + FlatEarthProjection.meters_to_lonlat(d.position, self.start_position) for d in self.droplets] for p in positions: p[0][2] -= self.start_position[2] # for each release location, set the position and mass of the elements released at that location total_rel = 0 for mass_dist, n_LEs, pos, droplet in zip(delta_masses, LE_distribution, positions, self.droplets): start_idx = -num_new_particles + total_rel if start_idx == 0: break end_idx = start_idx + n_LEs if end_idx == 0: end_idx = None # print '{0} to {1}'.format(start_idx, end_idx) if start_idx == end_idx: continue data_arrays['positions'][start_idx:end_idx] = pos data_arrays['mass'][start_idx:end_idx] = mass_dist / n_LEs data_arrays['init_mass'][start_idx:end_idx] = mass_dist / n_LEs data_arrays['density'][start_idx:end_idx] = droplet.density data_arrays['droplet_diameter'][start_idx:end_idx] = np.random.normal(droplet.radius * 2, droplet.radius * 0.15, (n_LEs)) v = data_arrays['rise_vel'][start_idx:end_idx] rise_velocity_from_drop_size(v, data_arrays['density'][start_idx:end_idx], data_arrays['droplet_diameter'][start_idx:end_idx], 0.0000013, 1020) data_arrays['rise_vel'][start_idx:end_idx] = v total_rel += n_LEs self.num_released += num_new_particles self.amount_released += total_mass