Ejemplo n.º 1
0
 def test_grid_instance_is_initialised( self, mock_Grid_Point, mock_index ):
     #volumes = [ 0.025, 0.025, 0.025, 0.025, 0.025 ]
     #mock_volumes.return_value = volumes
     mock_index.side_effect = [ 1, 3 ]
     mock_grid_points = [ Mock( spec=Grid_Point ), Mock( spec=Grid_Point ), Mock( spec=Grid_Point ), Mock( spec=Grid_Point ), Mock( spec=Grid_Point ) ]
     for g in mock_grid_points:
         g.sites = []
     mock_Grid_Point.side_effect = mock_grid_points
     x_coordinates = np.array( [ 0.0, 1.0, 2.0, 3.0, 4.0 ] )
     b = 0.25
     c = 0.1
     limits = [ 1.0, 1.0 ]
     limits_for_laplacian = [1.0, 1.0]
     set_of_sites = MagicMock( spec=Set_of_Sites )
     sites = [ Mock( spec=Site ), Mock( spec=Site ) ]
     sites[0].x = 1.0
     sites[1].x = 3.0
     sites[0].defect_species = [ Mock( spec=DefectSpecies ) ]
     sites[1].defect_species = [ Mock( spec=DefectSpecies ) ]
     set_of_sites.__iter__.return_value = iter( sites )
     grid = Grid( x_coordinates=x_coordinates, b=b, c=c, limits=limits, limits_for_laplacian=limits_for_laplacian, set_of_sites=set_of_sites )
     self.assertEqual( grid.points, mock_grid_points )
     self.x = x_coordinates
     self.limits = limits
     self.limits_for_laplacian = limits_for_laplacian
     expected_sites_at_grid_points = [ [], [ sites[0] ], [], [ sites[1] ], [] ]
     for p, e in zip( grid.points, expected_sites_at_grid_points ):
         self.assertEqual( p.sites, e )
     for defect_species_list in [ sites[0].defect_species, sites[1].defect_species ]:
         for defect_species in defect_species_list:
             self.assertEqual( defect_species in grid.defect_species, True )
Ejemplo n.º 2
0
    def form_continuum_sites( all_sites, x_min, x_max, n_points, b, c, defect_species, limits_for_laplacian, site_labels, defect_labels ):
  
        """
        Creates a Set_of_Sites object for sites interpolated onto a regular grid, this is equivalent to assuming a continuum approximation.

        Args:
            all_sites (object): Orginal Set_of_Sites object from full data.
            x_min (float): Minimum x coordinate value defining the calculation region.
            x_max (float): Maximum x coordinate value defining the calculation region. 
            n_points (int): Number of points that the data should be interpolated on to.
            b (float): b dimension for every grid point.
            c (float): c dimension for every grid point.
            defect_species (object): Class object containing information about the defect species present in the system. 
            limits for laplacian (list): distance between the endmost sites and the midpoint of the next site outside of the calculation region for the first and last sites respectively. 
            site_labels( list ): List of strings for the different site species.
            defect_labels (list): List of strings for the different defect species.

        Returns:
            :obj:`Set_of_Sites`: Sites interpolated onto a regular grid.

	"""	    
  
        grid = np.linspace( x_min, x_max, n_points )
        limits = [grid[1] - grid[0], grid[1] - grid[0]]
        sites = []
        for label, d_label in zip(site_labels, defect_labels):
            scaling = len( all_sites.subset( label ) ) / len( grid )
            continuum_grid = Grid( grid, b, c, limits, limits_for_laplacian, all_sites.subset( label ) )
            average_energies = np.array( [ site.average_local_energy( method = 'mean' )[0] for site in all_sites.subset( label ) ] )
            new_energies = griddata( ( [ site.x for site in all_sites.subset( label ) ] ), average_energies, grid, method = 'nearest' )
            for x, e in zip( grid, new_energies):
                sites.append( Site( label, x, [ defect_species[ d_label ] ], [e], scaling = np.array( scaling ) ) )
        return Set_of_Sites( sites ), limits    
Ejemplo n.º 3
0
    def form_continuum_sites_new(all_sites, x_min, x_max, n_points, b, c,
                                 defect_species, limits_for_laplacian,
                                 site_labels, defect_labels):

        limits = [x_min, x_max]
        grid = np.linspace(x_min, x_max, n_points)
        sites = []

        for label, d_label in zip(site_labels, defect_labels):
            scaling = len(all_sites.subset(label)) / len(grid)
            continuum_grid = Grid(grid, b, c, limits, limits_for_laplacian,
                                  all_sites.subset(label))
            average_energies = np.array([
                site.average_local_energy(method='mean')[0]
                for site in all_sites.subset(label)
            ])
            new_energies = griddata(
                ([site.x for site in all_sites.subset(label)]),
                Vo.average_energies,
                grid,
                method='nearest')
            for x, e in zip(grid, new_energies):
                sites.append(
                    Site(label,
                         x, [defect_species[d_label]], [e],
                         scaling=np.array(scaling)))

        return Set_of_Sites(sites)
Ejemplo n.º 4
0
    def calculate_mobile_defect_conductivities(self,
                                               pos_or_neg_scr,
                                               scr_limit,
                                               species,
                                               mobility_scaling=False):
        """Calculate the conductivity ratio between the space charge region and the bulk both perpendicular and parallel to the grain boundary.

        A `Set_of_Sites` object is created for the sites in the space charge region, and the defect distributions calculated. The width of the space charge region is calculated and a bulk region of the same width is defined. A Set_of_Sites object for the bulk region is created and the defect distributions calculated. Taking each site as a resistor in series or parallel respectively, the conductivity is calculated and the ratio between the space charge region and the bulk is taken. 

        Args:
            pos_or_neg_scr (str): 'positive' - for a positive space charge potential.
				  'negative' - for a negative space charge potential.
            scr_limit (float): The minimum electrostatic potential that the electrostatic potential must exceed to be included in the space charge region.
            species (str): The species for which the conductivity is being calculated.
            mobility_scaling (bool): For particles on a lattice which only interact through volume exclusion, the mobility exhibits a blocking term. True if the blocking term is to be included, False if the blocking term is not to be included. Default = False.

        Returns:
            float: The perpendicular conductivity ratio. The conductivity ratio between the bulk and the space charge region perpendicular to the grain boundary.
            float: The parallel conductivity ratio. The conductivity ratio between the bulk and the space charge region parallel to the grain boundary. 

	"""
        space_charge_region = self.create_space_charge_region(
            self.subgrids[species], pos_or_neg_scr, scr_limit)
        space_charge_region_limits = self.calculate_offset(
            self.subgrids[species], np.min(space_charge_region),
            np.max(space_charge_region))
        space_charge_region_sites = self.create_subregion_sites(
            self.subgrids[species], np.min(space_charge_region),
            np.max(space_charge_region))
        for site in space_charge_region_sites:
            charge = site.defects[0].valence
            mobilities = site.defects[0].mobility
        space_charge_region_grid = Grid.grid_from_set_of_sites(
            space_charge_region_sites, space_charge_region_limits,
            space_charge_region_limits, self.grid.b, self.grid.c)
        space_charge_region_width = space_charge_region_grid.x[
            -1] - space_charge_region_grid.x[0]
        mobile_defect_density = Set_of_Sites(
            self.subgrids[species].set_of_sites
        ).subgrid_calculate_defect_density(self.subgrids[species], self.grid,
                                           self.phi, self.temp)
        space_charge_region_mobile_defect_mf = space_charge_region_sites.calculate_probabilities(
            space_charge_region_grid, self.phi, self.temp)
        space_charge_region_mobile_defect_density = space_charge_region_sites.subgrid_calculate_defect_density(
            space_charge_region_grid, self.grid, self.phi, self.temp)
        if mobility_scaling:
            mobile_defect_conductivity = space_charge_region_mobile_defect_density * (
                1 - space_charge_region_mobile_defect_mf) * charge * mobilities
        else:
            mobile_defect_conductivity = space_charge_region_mobile_defect_density * charge * mobilities
        bulk_x_max = self.bulk_x_min + space_charge_region_width
        min_bulk_index, max_bulk_index = self.find_index(
            self.subgrids[species], self.bulk_x_min, bulk_x_max)
        self.bulk_limits = self.calculate_offset(self.subgrids[species],
                                                 self.bulk_x_min, bulk_x_max)
        bulk_mobile_defect_sites = self.create_subregion_sites(
            self.subgrids[species], self.bulk_x_min, bulk_x_max)
        bulk_mobile_defect_grid = Grid.grid_from_set_of_sites(
            bulk_mobile_defect_sites, self.bulk_limits, self.bulk_limits,
            self.grid.b, self.grid.c)
        bulk_mobile_defect_density = Set_of_Sites(
            bulk_mobile_defect_grid.set_of_sites
        ).subgrid_calculate_defect_density(bulk_mobile_defect_grid, self.grid,
                                           self.phi, self.temp)
        bulk_region_mobile_defect_mf = bulk_mobile_defect_sites.calculate_probabilities(
            bulk_mobile_defect_grid, self.phi, self.temp)
        if mobility_scaling:
            bulk_mobile_defect_conductivity = bulk_mobile_defect_density * charge * mobilities
        else:
            bulk_mobile_defect_conductivity = bulk_mobile_defect_density * charge * mobilities * (
                1 - bulk_region_mobile_defect_mf)
        space_charge_array = np.column_stack(
            (mobile_defect_conductivity, space_charge_region_grid.x))
        bulk_array = np.column_stack(
            (bulk_mobile_defect_conductivity, bulk_mobile_defect_grid.x))
        if mobilities != 0.0:
            space_charge_perpendicular = sum(space_charge_region_grid.delta_x /
                                             mobile_defect_conductivity)
            self.average_bulk_mobile_defect_density = sum(
                bulk_mobile_defect_grid.delta_x *
                bulk_mobile_defect_density) / sum(
                    bulk_mobile_defect_grid.delta_x)
            bulk_perpendicular = sum(bulk_mobile_defect_conductivity /
                                     bulk_mobile_defect_grid.delta_x)
            space_charge_parallel = sum(mobile_defect_conductivity /
                                        space_charge_region_grid.delta_x)
            bulk_parallel = sum(bulk_mobile_defect_grid.delta_x /
                                bulk_mobile_defect_conductivity)
            perpendicular_conductivity_ratio = 1 / (
                space_charge_perpendicular * bulk_perpendicular)
            parallel_conductivity_ratio = space_charge_parallel * bulk_parallel
        else:
            perpendicular_conductivity_ratio = 0.0
            parallel_conductivity_ratio = 0.0


#        self.depletion_factor = 1 - ( mobile_defect_density / average_bulk )
        return perpendicular_conductivity_ratio, parallel_conductivity_ratio
Ejemplo n.º 5
0
    def calculate_mobile_defect_conductivities(
            self,
            pos_or_neg_scr: str,
            scr_limit: float,
            species: str,
            mobility_scaling: bool = False) -> Tuple[float, float]:
        """Calculate the conductivity ratio between the space charge region and the bulk both perpendicular and parallel to the grain boundary.

        A `SetOfSites` object is created for the sites in the space charge region, and the defect distributions calculated. The width of the space charge region is calculated and a bulk region of the same width is defined. A SetOfSites object for the bulk region is created and the defect distributions calculated. Taking each site as a resistor in series or parallel respectively, the conductivity is calculated and the ratio between the space charge region and the bulk is taken.

        Args:
            pos_or_neg_scr (str): 'positive' - for a positive space charge potential.
				  'negative' - for a negative space charge potential.
            scr_limit (float): The minimum electrostatic potential that the electrostatic potential must exceed to be included in the space charge region.
            species (str): The species for which the conductivity is being calculated.
            mobility_scaling (bool): For particles on a lattice which only interact through volume exclusion, the mobility exhibits a blocking term. True if the blocking term is to be included, False if the blocking term is not to be included. Default = False.

        Returns:
            float: The perpendicular conductivity ratio. The conductivity ratio between the bulk and the space charge region perpendicular to the grain boundary.
            float: The parallel conductivity ratio. The conductivity ratio between the bulk and the space charge region parallel to the grain boundary.

	    """
        # TODO: Needs refactoring.
        # TODO: Updated copy of this function from Jacob.
        space_charge_region = self.create_space_charge_region(
            self.subgrids[species], pos_or_neg_scr, scr_limit)
        space_charge_region_limits = self.calculate_offset(
            self.subgrids[species], np.min(space_charge_region),
            np.max(space_charge_region))
        space_charge_region_sites = self.create_subregion_sites(
            self.subgrids[species], np.min(space_charge_region),
            np.max(space_charge_region))
        for site in space_charge_region_sites:
            charge = site.defects[0].valence
            mobilities = site.defects[0].mobility
        space_charge_region_grid = Grid.from_set_of_sites(
            space_charge_region_sites, space_charge_region_limits,
            space_charge_region_limits, self.grid.b, self.grid.c)
        space_charge_region_width = space_charge_region_grid.x[
            -1] - space_charge_region_grid.x[0]
        mobile_defect_density = self.subgrids[
            species].set_of_sites.subgrid_calculate_defect_density(
                self.subgrids[species], self.grid, self.phi, self.temp)
        space_charge_region_mobile_defect_mf = space_charge_region_sites.calculate_probabilities(
            space_charge_region_grid, self.phi, self.temp)
        space_charge_region_mobile_defect_density = space_charge_region_sites.subgrid_calculate_defect_density(
            space_charge_region_grid, self.grid, self.phi, self.temp)
        # TODO: According to Jacob this only scales the mobility of space-charge region but not the
        # TODO: bulk region, or vice-versa depending on whether it is switched on or not?
        if mobility_scaling:
            mobile_defect_conductivity = space_charge_region_mobile_defect_density * (
                1 - space_charge_region_mobile_defect_mf) * charge * mobilities
        else:
            mobile_defect_conductivity = space_charge_region_mobile_defect_density * charge * mobilities
        # TODO: This example bulk region can overlap with the space-charge region for cells that are similar lengths to the space-charge width, and will give spurious results.
        # TODO: Possible solution: We can directly compute the bulk resistivity from the bulk site density, without having to query the space-charge model.
        # TODO: Jacob to share his working code for this from his solver.
        bulk_x_max = self.bulk_x_min + space_charge_region_width
        min_bulk_index, max_bulk_index = self.find_index(
            self.subgrids[species], self.bulk_x_min, bulk_x_max)
        self.bulk_limits = self.calculate_offset(self.subgrids[species],
                                                 self.bulk_x_min, bulk_x_max)
        bulk_mobile_defect_sites = self.create_subregion_sites(
            self.subgrids[species], self.bulk_x_min, bulk_x_max)
        bulk_mobile_defect_grid = Grid.from_set_of_sites(
            bulk_mobile_defect_sites, self.bulk_limits, self.bulk_limits,
            self.grid.b, self.grid.c)
        bulk_mobile_defect_density = bulk_mobile_defect_grid.set_of_sites.subgrid_calculate_defect_density(
            bulk_mobile_defect_grid, self.grid, self.phi, self.temp)
        bulk_region_mobile_defect_mf = bulk_mobile_defect_sites.calculate_probabilities(
            bulk_mobile_defect_grid, self.phi, self.temp)
        # TODO: According to Jacob this only scales the mobility of space-charge region but not the
        # TODO: bulk region, or vice-versa depending on whether it is switched on or not?
        if mobility_scaling:
            bulk_mobile_defect_conductivity = bulk_mobile_defect_density * charge * mobilities
        else:
            bulk_mobile_defect_conductivity = bulk_mobile_defect_density * charge * mobilities * (
                1 - bulk_region_mobile_defect_mf)
        space_charge_array = np.column_stack(
            (mobile_defect_conductivity, space_charge_region_grid.x))
        bulk_array = np.column_stack(
            (bulk_mobile_defect_conductivity, bulk_mobile_defect_grid.x))
        # TODO: This uses an incorrect definition of the perpendicular resistivity!!!
        # TODO: Jacob has fixed this!!
        # TODO: Should be refactored into its own function.
        if mobilities != 0.0:
            space_charge_perpendicular = sum(space_charge_region_grid.delta_x /
                                             mobile_defect_conductivity)
            self.average_bulk_mobile_defect_density = sum(
                bulk_mobile_defect_grid.delta_x *
                bulk_mobile_defect_density) / sum(
                    bulk_mobile_defect_grid.delta_x)
            bulk_perpendicular = sum(bulk_mobile_defect_conductivity /
                                     bulk_mobile_defect_grid.delta_x)
            space_charge_parallel = sum(mobile_defect_conductivity /
                                        space_charge_region_grid.delta_x)
            bulk_parallel = sum(bulk_mobile_defect_grid.delta_x /
                                bulk_mobile_defect_conductivity)
            perpendicular_conductivity_ratio = 1 / (
                space_charge_perpendicular * bulk_perpendicular)
            parallel_conductivity_ratio = space_charge_parallel * bulk_parallel
        else:
            perpendicular_conductivity_ratio = 0.0
            parallel_conductivity_ratio = 0.0


#        self.depletion_factor = 1 - (mobile_defect_density / average_bulk)
        return perpendicular_conductivity_ratio, parallel_conductivity_ratio