Exemple #1
0
 def verify_box(self):
     """
     Verifies that the box is constructed properly.
     :return:
     """
     objects = np.array(self.mesh['object'])
     if 'NONE' in objects:
         console.error("WARNING! Not all coordinate spaces defined in box!",
                       verbose=True)
     else:
         console.event("Box verified!", verbose=True)
Exemple #2
0
 def insert_boundary(self,
                     temperature,
                     depth_range,
                     location,
                     material='boundary'):
     """
     Insert boundary layers in the model.
     :param temperature:
     :param depth_range:
     :param material:
     :return:
     """
     console.event("Inserting boundary ({}) into the box!".format(material),
                   verbose=self.verbose)
     t_start = time.time()
     subdf = self.mesh.query('{} <= z_vals <= {}'.format(
         depth_range[0], depth_range[1]))
     coords = np.array(subdf['coords'])
     temperatures = np.array(self.mesh['temperature'])
     objects = np.array(self.mesh['object'])
     object_ids = np.array(self.mesh['object_id'])
     for coord in coords:
         if depth_range[0] <= coords[2][self.dimension -
                                        1] <= depth_range[1]:
             index = backends.predict_index(coord=coord,
                                            max_x=self.max_x,
                                            max_y=self.max_y,
                                            max_z=self.max_z,
                                            spatial_res=self.spatial_res,
                                            verbose=self.verbose)
             console.nominal("Inserting boundary ({}) at {}...".format(
                 material, coord),
                             verbose=self.verbose)
             temperatures[index] = temperature
             objects[index] = material
             object_ids[index] = backends.generate_object_id(
                 object_type='boundary', id_val=self.id_val)
             self.id_val += 1
     self.mesh['temperature'] = temperatures
     self.mesh['object'] = objects
     self.mesh['object_id'] = object_ids
     self.boundary = True
     # the upper-most usable portion of the model is the matrix immediately below the boundary
     if location.lower() == "top" or location.lower() == "t":
         self.upper_model = round(depth_range[1] + (2 * self.spatial_res),
                                  self.spatial_sigfigs)
     elif location.lower() == "bottom" or location.lower() == "b":
         self.lower_model = round(depth_range[0] - (2 * self.spatial_res),
                                  self.spatial_sigfigs)
     console.event(
         "Finished inserting boundary ({}) into the box! (task took {}s)".
         format(material,
                time.time() - t_start),
         verbose=self.verbose)
Exemple #3
0
def object_actions(objects_df,
                   coords,
                   matrix_ids,
                   spatial_res,
                   spatial_sigfigs,
                   evolution_time,
                   initial_time,
                   max_x,
                   max_y,
                   max_z,
                   x_plus,
                   x_minus,
                   y_plus,
                   y_minus,
                   z_plus,
                   z_minus,
                   delta_time,
                   matrix_densities,
                   matrix_viscosities,
                   matrix_temperatures,
                   matrix_conductivities,
                   lower_model,
                   upper_model,
                   matrix_diffusivities,
                   verbose,
                   conduction=True):
    object_objects = np.array(objects_df['object'])
    object_object_ids = np.array(objects_df['object_id'])
    object_temperatures = np.array(objects_df['temperature'])
    object_densities = np.array(objects_df['density'])
    object_coords = np.array(objects_df['coords'], dtype=object)
    object_velocities = np.array(objects_df['velocity'], dtype=object)
    object_conductivities = np.array(objects_df['conductivity'])
    object_radii = np.array(objects_df['radius'])
    cell_vertices = np.array(objects_df['cell_vertices'], dtype=object)
    cell_indices = np.array(objects_df['cell_indices'], dtype=object)
    nearest_indices = np.array(objects_df['nearest_index'], dtype=object)
    drag_coeffs = np.array(objects_df['drag_coeff'])
    cps = np.array(objects_df['cp'])
    for object_index, object_object in enumerate(object_objects):
        object_id = object_object_ids[
            object_index]  # get the current object id
        coord = object_coords[
            object_index]  # get the current object coordinate
        #  interpolate to find the cell in which the object exists
        #  calculate the object's settling velocity
        if evolution_time == initial_time:
            initial_cell = backends.interpolate_cell(
                coord=coord,
                spatial_res=spatial_res,
                spatial_sigfigs=spatial_sigfigs,
                max_x=max_x,
                max_y=max_y,
                max_z=max_z,
                x_plus=x_plus,
                x_minus=x_minus,
                y_plus=y_plus,
                y_minus=y_minus,
                z_plus=z_plus,
                z_minus=z_minus,
                verbose=verbose)
            nearest_indices[object_index] = initial_cell[0]
            cell_indices[object_index] = initial_cell[1]
            cell_vertices[object_index] = initial_cell[2]
        velocity = dynamics.stokes_terminal(
            density=object_densities[object_index],
            density_matrix=matrix_densities[nearest_indices[object_index]],
            drag_coeff=drag_coeffs[object_index],
            radius=object_radii[object_index],
            viscosity_matrix=matrix_viscosities[nearest_indices[object_index]],
            current_coord=coord,
            lower_model=lower_model,
            upper_model=upper_model)
        #  get the object's new coordinates based on the object's velocity
        updated_coords, distance_travelled = backends.update_position(
            coord=coord,
            velocity=velocity,
            delta_time=delta_time,
            max_z=lower_model,
            spatial_res=spatial_res)
        # determine the mesh cell within which the object resides
        cell = backends.interpolate_cell(coord=updated_coords,
                                         spatial_res=spatial_res,
                                         spatial_sigfigs=spatial_sigfigs,
                                         max_x=max_x,
                                         max_y=max_y,
                                         max_z=max_z,
                                         x_plus=x_plus,
                                         x_minus=x_minus,
                                         y_plus=y_plus,
                                         y_minus=y_minus,
                                         z_plus=z_plus,
                                         z_minus=z_minus,
                                         verbose=verbose)
        # determine how much heat was produced through drag on the object
        viscous_heat = heat.viscous_dissipation(
            drag_coeff=drag_coeffs[object_index],
            cp=cps[object_index],
            delta_time=delta_time,
            matrix_density=matrix_densities[cell[0]],
            object_density=object_densities[object_index],
            object_radius=object_radii[object_index],
            object_velocity=velocity,
            distance_travelled=distance_travelled)
        # add the heat generated from viscous dissipation to the object
        object_temperatures[object_index] += viscous_heat
        # allow the heat from the object to conduct, assuming only in contact with nearest cell vertex
        if conduction:
            object_conduction = heat.object_conduction(
                object_temperatures=object_temperatures,
                object_index=object_index,
                object_k=object_conductivities[object_index],
                spatial_res=spatial_res,
                delta_time=delta_time,
                mesh_temperatures=matrix_temperatures,
                nearest_index=cell[0],
                farthest_index=cell[3],
                directional_vertices=cell[4],
                vertex_distances=cell[5],
                total_distance=cell[6],
                matrix_k=matrix_conductivities[cell[0]],
                matrix_ids=matrix_ids,
                coords=coords,
                matrix_diffusivities=matrix_diffusivities,
                spatial_sigfigs=spatial_sigfigs,
                verbose=verbose)
        console.event(
            "{} ({}) will travel from {} to {} (velocity: {})".format(
                object_object, object_id, coord, updated_coords, velocity),
            verbose=verbose)
        #  update the dataframes with the new data
        object_velocities[object_index] = velocity
        object_coords[object_index] = updated_coords
        nearest_indices[object_index] = cell[0]
        cell_indices[object_index] = cell[1]
        cell_vertices[object_index] = cell[2]
    objects_df['coords'] = object_coords
    objects_df['velocity'] = object_velocities
    objects_df['cell_vertices'] = cell_vertices
    objects_df['cell_indices'] = cell_indices
    objects_df['nearest_index'] = nearest_indices
    objects_df['temperature'] = object_temperatures
    return object_coords, nearest_indices, cell_indices
Exemple #4
0
 def build(self, spatial_res, x, y, z=None):
     """
     Constructs the mesh based on specified parameters.
     :param spatial_res:
     :param x:
     :param y:
     :param z:
     :return:
     """
     if z is not 3:
         self.dimension = 3
         self.max_x, self.max_y, self.max_z = x, y, z
     else:
         self.dimension = 2
         self.max_x, self.max_y, self.max_z = x, y, None
     self.spatial_res = spatial_res
     console.event("Constructing box...", verbose=self.verbose)
     console.nominal("Building mesh...", verbose=self.verbose)
     # instantiate the mesh
     m = mesh.Mesh(spatial_res=spatial_res,
                   x=x,
                   y=y,
                   z=z,
                   verbose=self.verbose)
     self.spatial_sigfigs = m.get_spatial_sigfigs()
     console.nominal("Assigning mesh to dataframe...", verbose=self.verbose)
     # construct the mesh
     m.build(df=self.mesh)
     console.nominal("Exiting box construction...", verbose=self.verbose)
     console.event("Box constructed!", verbose=self.verbose)
     console.event("Fetching nearest neighbors...", verbose=self.verbose)
     coords_range = range(len(self.mesh['coords']))
     # create all of the columns for the instantiated dataframes
     backends.set_columns(mesh_df=self.mesh,
                          object_df=self.objects,
                          coords_range=coords_range)
     self.x_coords = np.NAN
     self.y_coords = np.NAN
     self.z_coords = np.NAN
     spatial_sigfigs = m.get_spatial_sigfigs(
     )  # find the number of sigfigs defined by the spatial resolution
     neighbor_count = 1
     total_count = len(self.mesh['coords'])
     t_start = time.time()
     arr = np.array(
         self.mesh['coords'])  # an array of all the mesh coordinates
     x_plus = []
     x_minus = []
     y_plus = []
     y_minus = []
     z_plus = []
     z_minus = []
     # find nearest neighbors in 3D
     for coords in arr:
         if self.dimension is 3:
             console.nominal(
                 "Finding neighbor for ({}, {}, {}) ({}/{} points)".format(
                     coords[0], coords[1], coords[2], neighbor_count,
                     total_count),
                 verbose=self.verbose)
         else:
             console.nominal("Finding neighbor for ({}, {})".format(
                 coords[0], coords[1]),
                             verbose=self.verbose)
         n = neighbors.get_neighbors(verbose=self.verbose,
                                     coords=coords,
                                     max_x=x,
                                     max_y=y,
                                     max_z=z,
                                     spatial_res=spatial_res,
                                     spatial_sigfigs=spatial_sigfigs)
         x_plus.append(n[0])
         x_minus.append(n[1])
         y_plus.append(n[2])
         y_minus.append(n[3])
         if self.dimension is 3:
             z_plus.append(n[4])
             z_minus.append(n[5])
         neighbor_count += 1
     self.mesh['xplus_index'] = x_plus
     self.mesh['xminus_index'] = x_minus
     self.mesh['yplus_index'] = y_plus
     self.mesh['yminus_index'] = y_minus
     if self.dimension is 3:
         self.mesh['zplus_index'] = z_plus
         self.mesh['zminus_index'] = z_minus
     console.event(
         "Finished finding nearest neighbors! (task took {}s for {} points)"
         .format(time.time() - t_start, total_count),
         verbose=self.verbose)
     return self.mesh
Exemple #5
0
    def update(self, auto_update=True, timestep=False, animate_model=False):
        """
        Update the model over one time step. Has the ability to run the model to completion.
        :param auto_update:
        :param timestep:
        :return:
        """
        t = time.time()
        # extract values that are not updated during the loop from the dataframe as lists
        coords = np.array(self.mesh['coords'])
        x_plus = np.array(self.mesh['xplus_index'])
        x_minus = np.array(self.mesh['xminus_index'])
        y_plus = np.array(self.mesh['yplus_index'])
        y_minus = np.array(self.mesh['yminus_index'])
        z_plus = np.array(self.mesh['zplus_index'])
        z_minus = np.array(self.mesh['zminus_index'])
        object_ids = np.array(self.mesh['object_id'])
        conductivities = np.array(self.mesh['conductivity'])
        viscosity = np.array(self.mesh['viscosity'])
        density = np.array(self.mesh['density'])
        diffusivities = np.array(self.mesh['diffusivity'])
        temperatures = np.array(
            self.mesh['temperature']
        )  # load in current temperatures across the mesh
        dT_dts = np.array(self.mesh['dT_dt'])
        mesh_indices = np.array(self.mesh.index)
        len_coords = len(coords)
        # calculate the timestep based on the maximum conductivity of material in the box
        self.delta_time = backends.override_timestep(
            timestep=timestep,
            conductivities=conductivities,
            spatial_res=self.spatial_res,
            spatial_sigfigs=self.spatial_sigfigs,
            diffusivities=diffusivities,
            verbose=self.verbose)
        real_delta_time = backends.override_timestep(
            timestep=False,
            conductivities=list(conductivities),
            spatial_res=self.spatial_res,
            spatial_sigfigs=self.spatial_sigfigs,
            diffusivities=diffusivities,
            verbose=self.verbose)
        # will run model to completion while the remaining time is above 0
        while auto_update is True and self.evolution_time > 0:
            console.nominal("Model time at: {} (timestep: {})...".format(
                self.evolution_time, self.delta_time),
                            verbose=self.verbose)
            # temperatures = np.array(self.mesh['temperature'])  # load in current temperatures across the mesh
            #  perform actions on objects inside of the model but independent of the mesh
            object_coords, nearest_indices, cell_indices = objects.object_actions(
                matrix_temperatures=temperatures,
                objects_df=self.objects,
                spatial_res=self.spatial_res,
                spatial_sigfigs=self.spatial_sigfigs,
                evolution_time=self.evolution_time,
                delta_time=self.delta_time,
                initial_time=self.initial_time,
                matrix_densities=density,
                matrix_viscosities=viscosity,
                x_plus=x_plus,
                x_minus=x_minus,
                y_plus=y_plus,
                y_minus=y_minus,
                z_plus=z_plus,
                z_minus=z_minus,
                max_x=self.max_x,
                max_y=self.max_y,
                max_z=self.max_z,
                lower_model=self.lower_model,
                upper_model=self.upper_model,
                verbose=self.verbose,
                conduction=self.conduction,
                matrix_conductivities=conductivities,
                matrix_ids=object_ids,
                coords=coords,
                matrix_diffusivities=diffusivities)
            if self.conduction:
                # finite central difference conductivity across entire box
                conduction_t = time.time()
                conduction = heat.conduction(coords=coords,
                                             len_coords=len_coords,
                                             x_plus_indices=x_plus,
                                             x_minus_indices=x_minus,
                                             y_plus_indices=y_plus,
                                             y_minus_indices=y_minus,
                                             z_plus_indices=z_plus,
                                             z_minus_indices=z_minus,
                                             temperatures=temperatures,
                                             conductivities=conductivities,
                                             spatial_res=self.spatial_res,
                                             delta_time=self.delta_time,
                                             object_ids=object_ids,
                                             mesh_indices=mesh_indices,
                                             num_workers=self.num_workers,
                                             multiprocess=self.multiprocessing,
                                             real_delta_time=real_delta_time)
                # conduction will return tuple: temperature at index 0 and dT/dt at index 1
                temperatures = conduction[0]
                dT_dts = conduction[1]
                console.nominal(
                    "Finished modeling conduction! (task took {}s)".format(
                        time.time() - conduction_t),
                    verbose=self.verbose)
            # plot the model's dynamic components, remove in the operational version
            self.plots.plot_cell(object_coords=object_coords,
                                 nearest_coords=nearest_indices,
                                 vertex_indices=cell_indices,
                                 mesh_coords=coords,
                                 max_x=self.max_x,
                                 max_y=self.max_y,
                                 max_z=self.max_z,
                                 temperatures=temperatures,
                                 spatial_res=self.spatial_res,
                                 model_time=self.evolution_time,
                                 save=animate_model,
                                 show=False,
                                 heat=self.conduction)
            # update the new time in the model
            new_evolution_time = round(self.evolution_time - self.delta_time,
                                       self.spatial_sigfigs)
            self.evolution_time = new_evolution_time
            self.iterations += 1

        console.event(
            "Model time is at 0! (task took {}s ({} iterations (1 iteration = {}s), {} timestep)"
            .format(time.time() - t, self.iterations,
                    (time.time() - t) / self.iterations, self.delta_time),
            verbose=self.verbose)
        self.return_mesh(mesh=self.mesh,
                         temperature=temperatures,
                         dT_dt=dT_dts,
                         conductivity=conductivities,
                         density=density,
                         viscosity=viscosity)
        # will create animations of models if specified
        if animate_model is True:
            self.plots.animate(initial_time=self.initial_time)
        return None
Exemple #6
0
 def insert_object(self,
                   material,
                   temperature,
                   radius,
                   conductivity,
                   density,
                   drag_coeff,
                   cp,
                   x,
                   y,
                   z=None):
     """
     Insert an object in the the objects dataframe.
     :param material:
     :param temperature:
     :param radius:
     :param conductivity:
     :param x:
     :param y:
     :param z:
     :return:
     """
     console.event("Inserting object ({}) into the box!".format(material),
                   verbose=self.verbose)
     if z is None and self.dimension is 3:
         console.error("Box dimension is 3 and z is not specified!",
                       verbose=self.verbose)
         sys.exit(1)
     if self.dimension is 3 and z is not None:
         requested_coord = (x, y, z)
     elif self.dimension is 2 and z is None:
         requested_coord = (x, y)
     t_start = time.time()
     objects = self.objects['object'].tolist()
     object_ids = self.objects['object_id'].tolist()
     temperatures = self.objects['temperature'].tolist()
     radii = self.objects['radius'].tolist()
     locs = self.objects['coords'].tolist()
     densities = self.objects['density'].tolist()
     velocities = self.objects['velocity'].tolist()
     conductivities = self.objects['conductivity'].tolist()
     drag_coeffs = self.objects['drag_coeff'].tolist()
     cps = self.objects['cp'].tolist()
     console.nominal("Inserting object ({}) at {}...".format(
         material, requested_coord),
                     verbose=self.verbose)
     objects.append(material)
     object_ids.append(
         backends.generate_object_id(object_type='object',
                                     id_val=self.id_val))
     radii.append(float(radius))
     locs.append(requested_coord)
     temperatures.append(float(temperature))
     conductivities.append(float(conductivity))
     densities.append(float(density))
     velocities.append((0.0, 0.0, 0.0))
     drag_coeffs.append(float(drag_coeff))
     cps.append(float(cp))
     object_headers = [self.objects.columns.values]
     self.objects = pd.DataFrame(
     )  # reset the dataframe to avoid length issues
     self.objects['object'] = objects
     self.objects['object_id'] = object_ids
     self.objects['temperature'] = temperatures
     self.objects['radius'] = radii
     self.objects['coords'] = locs
     self.objects['conductivity'] = conductivities
     self.objects['density'] = densities
     self.objects['drag_coeff'] = drag_coeffs
     self.objects['cp'] = cps
     self.objects['velocity'] = velocities
     self.objects['nearest_index'] = np.NAN
     self.objects['cell_indices'] = np.NAN
     self.objects['cell_vertices'] = np.NAN
     self.id_val += 1
     self.object = True
     console.event(
         "Finished inserting object ({}) into the box! (task took {}s)".
         format(material,
                time.time() - t_start),
         verbose=self.verbose)
Exemple #7
0
 def insert_matrix(self, material, temperature, conductivity, density,
                   viscosity, depth_range, heat_capacity):
     """
     Insert a matrix into the model.
     :param material:
     :param temperature:
     :param conductivity:
     :param depth_range:
     :return:
     """
     console.event("Inserting matrix ({}) into the box!".format(material),
                   verbose=self.verbose)
     t_start = time.time()
     subdf = self.mesh.query('{} <= z_vals <= {}'.format(
         depth_range[0], depth_range[1]))
     self.mesh.drop(['z_vals'], axis=1)
     coords = np.array(subdf['coords'])
     temperatures = np.array(self.mesh['temperature'])
     objects = np.array(self.mesh['object'])
     object_ids = np.array(self.mesh['object_id'])
     conductivities = np.array(self.mesh['conductivity'])
     densities = np.array(self.mesh['density'])
     viscosities = np.array(self.mesh['viscosity'])
     diffusivities = np.array(self.mesh['diffusivity'])
     self.conductivities.append(conductivity)
     len_coords = len(coords)
     # insert the matrix into coordinate positions defined by the user's z-range
     # TODO: we can limit recursion time by using the index prediction equation here
     for coord in coords:
         if depth_range[0] <= coords[2][self.dimension -
                                        1] <= depth_range[1]:
             index = backends.predict_index(coord=coord,
                                            max_x=self.max_x,
                                            max_y=self.max_y,
                                            max_z=self.max_z,
                                            spatial_res=self.spatial_res,
                                            verbose=self.verbose)
             console.nominal("Inserting matrix ({}) at {}...".format(
                 material, coord),
                             verbose=self.verbose)
             temperatures[index] = float(temperature)
             conductivities[index] = float(conductivity)
             diffusivities[index] = float(conductivity /
                                          (density * heat_capacity))
             objects[index] = material
             densities[index] = float(density)
             viscosities[index] = float(viscosity)
             object_ids[index] = backends.generate_object_id(
                 object_type='matrix', id_val=self.id_val)
             self.id_val += 1
     self.mesh['temperature'] = temperatures
     self.mesh['object'] = objects
     self.mesh['object_id'] = object_ids
     self.mesh['density'] = densities
     self.mesh['viscosity'] = viscosities
     self.mesh['conductivity'] = conductivities
     self.mesh['diffusivity'] = diffusivities
     self.matrix = True
     console.event(
         "Finished inserting matrix ({}) into the box! (task took {}s)".
         format(material,
                time.time() - t_start),
         verbose=self.verbose)