Beispiel #1
0
    def __init__(self, file_address=None):
        # set file address (using a setter method)
        [self._file_directory, self._file_name] = ['', '']
        self.file_address = file_address

        self.s = bp.Species()
        self.t = bp.Grid()
        self.t.ndim = 1
        self.p = bp.Grid()
        self.geometry = bp.Geometry()
        self.sv = bp.SVGrid()
        self.coll = bp.Collisions()
        self.scheme = bp.Scheme()
        self.output_parameters = np.array([['Mass', 'Momentum_X'],
                                           ['Momentum_X', 'Momentum_Flow_X'],
                                           ['Energy', 'Energy_Flow_X']])
        self.check_integrity(complete_check=False)
        return
Beispiel #2
0
    def load(file_address):
        """Set up and return a :class:`Simulation` instance
        based on the parameters in the given HDF5 group.

        Parameters
        ----------
        file_address : :obj:`str`, optional
            The full path to the simulation (hdf5) file.

        Returns
        -------
        self : :class:`Simulation`
        """
        assert isinstance(file_address, str)
        assert os.path.exists(file_address)
        # Open HDF5 file
        file = h5py.File(file_address, mode='r')
        assert file.attrs["class"] == "Simulation"
        self = Simulation(file_address)

        key = "Species"
        self.s = bp.Species.load(file[key])

        key = "Time_Grid"
        self.t = bp.Grid.load(file[key])
        # Todo this should (needs to) be unnecessary
        self.t.ndim = 1

        key = "Position_Grid"
        self.p = bp.Grid().load(file[key])

        key = "Geometry"
        self.geometry = bp.Geometry.load(file[key])

        key = "Velocity_Grids"
        self.sv = bp.SVGrid.load(file[key])

        key = "Collisions"
        self.coll = bp.Collisions.load(file[key])

        key = "Scheme"
        self.scheme = bp.Scheme.load(file[key])

        key = "Computation/Output_Parameters"
        shape = file[key].attrs["shape"]
        self.output_parameters = file[key][()].reshape(shape)

        file.close()
        self.check_integrity(complete_check=False)
        return self
Beispiel #3
0
    def setup_position_grid(self, grid_dimension, grid_shape, grid_spacing):
        """Set up :attr:`p` and adjust :attr:`geometry` to the new shape.
        See :class:`Grid() <Grid>`

        Parameters
        ----------
        grid_dimension : :obj:`int`
        grid_shape : :obj:`tuple` [:obj:`int`]
        grid_spacing : :obj:`float`
        """
        self.p = bp.Grid(ndim=grid_dimension,
                         shape=grid_shape,
                         physical_spacing=grid_spacing)
        # Update shape of initialization_array
        self.geometry.shape = self.p.shape
        return
Beispiel #4
0
    def setup_time_grid(self,
                        max_time,
                        number_time_steps,
                        calculations_per_time_step=1):
        """Set up :attr:`t`.

        Calculate step size and call :class:`Grid() <Grid>`.

        Parameters
        ----------
        max_time : :obj:`float`
        number_time_steps : :obj:`int`
        calculations_per_time_step : :obj:`int`
        """
        step_size = max_time / (number_time_steps - 1)
        self.t = bp.Grid(ndim=1,
                         shape=(number_time_steps, ),
                         physical_spacing=step_size,
                         spacing=calculations_per_time_step)
        return
Beispiel #5
0
    def setup(self):
        """Construct the attributes
        :attr:`Grid.iMG`,
        :attr:`Grid.index_range`,
        :attr:`Grid.vGrids`."""
        # Basic asserts : is everything configured and correct?
        self.check_integrity(False)
        assert self.is_configured

        number_of_grids = len(self.shapes)
        self.index_range = np.zeros((number_of_grids, 2), dtype=int)
        self.vGrids = np.empty(number_of_grids, dtype='object')
        # set up sub grids, one by one
        for i in range(number_of_grids):
            # Todo the physical spacing is only a dummy so far
            new_grid = bp.Grid(ndim=self.ndim,
                               shape=self.shapes[i],
                               physical_spacing=1.0,
                               spacing=self.spacings[i],
                               is_centered=True)
            self.vGrids[i] = new_grid
            self.index_range[i, 1] = self.index_range[i, 0] + new_grid.size
            if i + 1 < number_of_grids:
                self.index_range[i + 1, 0] = self.index_range[i, 1]

        # Sub grids only have a view on the data
        # The actual data are stored in the multi grid
        self.iMG = np.zeros((self.index_range[-1, 1], self.ndim), dtype=int)
        for (idx_G, G) in enumerate(self.vGrids):
            [beg, end] = self.index_range[idx_G]
            self.iMG[beg:end, :] = G.iG[...]
            G.iG = self.iMG[beg:end]

        # Todo find more elegant way for this
        self.delta = self.maximum_velocity / np.max(self.iMG)
        for G in self.vGrids:
            G.delta = self.delta
        return
Beispiel #6
0
    def setup(self, scheme, svgrid, species):
        """Generates the :attr:`relations` and :attr:`weights`.

        Parameters
        ----------
        scheme : :class:`Scheme`
        svgrid : :class:`SVGrid`
        species : :class:`Species`
        """
        assert isinstance(scheme, bp.Scheme)
        assert isinstance(svgrid, bp.SVGrid)
        assert isinstance(species, bp.Species)

        print('Generating Collision Array...')
        time_beg = time()
        # collect collisions in the following lists
        relations = []
        weights = []
        """The velocities are named in the following way:
        1. v* and w* are velocities of the first/second specimen, respectively
        2. v0 or w0 denotes the velocity before the collision
           v1 or w1 denotes the velocity after the collision
        """
        # choose function for local collisions
        if scheme.Collisions_Generation == 'UniformComplete':
            coll_func = Collisions.complete
        elif scheme.Collisions_Generation == 'Convergent':
            coll_func = Collisions.convergent
        else:
            raise NotImplementedError('Unsupported Selection Scheme: '
                                      '{}'.format(
                                          scheme.Collisions_Generation))

        grids = np.empty((4, ), dtype=object)
        # use larger grids to shift within equivalence classes
        extended_grids = np.empty((4, ), dtype=object)
        # Todo rename into species, after Model update
        species_idx = np.zeros(4, dtype=int)
        masses = np.zeros(4, dtype=int)
        # Iterate over Specimen pairs
        for (idx_v, grid_v) in enumerate(svgrid.vGrids):
            grids[0:2] = grid_v
            extended_shape = (2 * grids[0].shape[0] - grids[0].shape[0] % 2,
                              2 * grids[0].shape[0] - grids[0].shape[0] % 2)
            extended_grids[0:2] = bp.Grid(grids[0].ndim, extended_shape,
                                          grids[0].physical_spacing,
                                          grids[0].spacing,
                                          grids[0].is_centered)
            species_idx[0:2] = idx_v
            for (idx_w, grid_w) in enumerate(svgrid.vGrids):
                grids[2:4] = grid_w
                extended_shape = (2 * grids[2].shape[0] -
                                  grids[2].shape[0] % 2,
                                  2 * grids[2].shape[0] -
                                  grids[2].shape[0] % 2)
                extended_grids[2:4] = bp.Grid(grids[2].ndim, extended_shape,
                                              grids[2].physical_spacing,
                                              grids[2].spacing,
                                              grids[2].is_centered)
                species_idx[2:4] = idx_w
                masses[:] = species.mass[species_idx]
                collision_rate = species.collision_rates[idx_v, idx_w]
                index_offset = np.array(svgrid.index_range[species_idx, 0])
                # Todo may be bad for differing weights
                # skip already computed combinations
                if idx_w < idx_v:
                    continue
                # group grid[0] points by distance to grid[2]
                for equivalence_class in grids[2].group(grids[0].iG).values():
                    # only generate colliding velocities(colvels)
                    # for a representative v0 of its group,
                    v0_repr = equivalence_class[0]
                    [repr_colvels,
                     extended_weights] = coll_func(extended_grids, masses,
                                                   v0_repr, collision_rate)
                    # Get relations for other class elements by shifting
                    for v0 in equivalence_class:
                        # shift extended colvels
                        new_colvels = repr_colvels + (v0 - v0_repr)
                        # get indices
                        new_rels = np.zeros(new_colvels.shape[0:2], dtype=int)
                        for i in range(4):
                            new_rels[:,
                                     i] = grids[i].get_idx(new_colvels[:,
                                                                       i, :])
                        new_rels += index_offset

                        # remove out-of-bounds or useless collisions
                        choice = np.where(
                            # must be in the grid
                            np.all(new_rels >= index_offset, axis=1)
                            # must be effective
                            & (new_rels[..., 0] != new_rels[..., 3])
                            & (new_rels[..., 0] != new_rels[..., 1]))
                        # Add chosen Relations/Weights to the list
                        assert np.array_equal(new_colvels[choice],
                                              svgrid.iMG[new_rels[choice]])
                        relations.extend(new_rels[choice])
                        weights.extend(extended_weights[choice])
                    # relations += new_rels
                    # weights += new_weights
        self.relations = np.array(relations, dtype=int)
        self.weights = np.array(weights, dtype=float)
        # remove redundant collisions
        self.filter()
        # sort collisions for better comparability
        self.sort()
        time_end = time()
        print('Time taken =  {t} seconds\n'
              'Total Number of Collisions = {n}\n'
              ''.format(t=round(time_end - time_beg, 3), n=self.size))
        self.check_integrity()
        return
Beispiel #7
0
    def __init__(self,
                 file_address,
                 s=None,
                 t=None,
                 p=None,
                 sv=None,
                 coll=None,
                 geometry=None,
                 scheme=None,
                 output_parameters=None):
        super().__init__(file_address)

        if s is None:
            s = bp.Species()
            s.add(mass=2, collision_rate=np.array([50], dtype=float))
            s.add(mass=3, collision_rate=np.array([50, 50], dtype=float))
        else:
            assert isinstance(s, bp.Species)
        self.s = s

        if t is None:
            t = bp.Grid(ndim=1, shape=(5, ), physical_spacing=0.01, spacing=3)
        self.t = t

        if p is None:
            p = bp.Grid(ndim=1, shape=(6, ), spacing=1, physical_spacing=0.5)
        self.p = p

        if sv is None:
            spacings = bp.SVGrid.generate_spacings(s.mass)
            shapes = [(int(2 * m + 1), int(2 * m + 1)) for m in s.mass]
            sv = bp.SVGrid(
                ndim=2,
                maximum_velocity=1.5,
                shapes=shapes,
                spacings=spacings,
            )
        self.sv = sv

        if geometry is None:
            left_rho = 2 * np.ones(s.size)
            right_rho = np.ones(s.size)
            initial_drift = np.zeros((s.size, sv.ndim))
            initial_temp = np.ones(s.size)
            rules = [
                bp.ConstantPointRule(initial_rho=left_rho,
                                     initial_drift=initial_drift,
                                     initial_temp=initial_temp,
                                     affected_points=[0],
                                     velocity_grids=sv,
                                     species=s),
                bp.InnerPointRule(initial_rho=left_rho,
                                  initial_drift=initial_drift,
                                  initial_temp=initial_temp,
                                  affected_points=np.arange(1, p.size // 2),
                                  velocity_grids=sv,
                                  species=s),
                bp.InnerPointRule(initial_rho=right_rho,
                                  initial_drift=initial_drift,
                                  initial_temp=initial_temp,
                                  affected_points=np.arange(
                                      p.size // 2, p.size - 1),
                                  velocity_grids=sv,
                                  species=s),
                bp.BoundaryPointRule(
                    initial_rho=right_rho,
                    initial_drift=initial_drift,
                    initial_temp=initial_temp,
                    affected_points=[p.size - 1],
                    velocity_grids=sv,
                    reflection_rate_inverse=np.full(s.size, 0.25, dtype=float),
                    reflection_rate_elastic=np.full(s.size, 0.25, dtype=float),
                    reflection_rate_thermal=np.full(s.size, 0.25, dtype=float),
                    absorption_rate=np.full(s.size, 0.25, dtype=float),
                    surface_normal=np.array([1, 0], dtype=int),
                    species=s)
            ]
            geometry = bp.Geometry(shape=p.shape, rules=rules)
        self.geometry = geometry

        if scheme is None:
            scheme = bp.Scheme(OperatorSplitting="FirstOrder",
                               Transport="FiniteDifferences_FirstOrder",
                               Transport_VelocityOffset=np.array([-0.2, 0.0]),
                               Collisions_Generation="UniformComplete",
                               Collisions_Computation="EulerScheme")
        self.scheme = scheme

        if output_parameters is None:
            output_parameters = np.array([['Mass', 'Momentum_X'],
                                          ['Momentum_X', 'Momentum_Flow_X'],
                                          ['Energy', 'Energy_Flow_X']])
        self.output_parameters = output_parameters

        if coll is None:
            coll = bp.Collisions()
            coll.setup(scheme=self.scheme, svgrid=self.sv, species=self.s)
        self.coll = coll
        return