Beispiel #1
0
def run_mc(args):
    temperature = args['temperature']
    dmu = args['dmu']
    mc = SemiGrandCanonicalEnsemble(
        structure=structure,
        calculator=calculator,
        temperature=temperature,
        dc_filename='sgc-T{}-dmu{:+.3f}.dc'.format(temperature, dmu),
        chemical_potentials={'Ag': 0, 'Pd': dmu})
    mc.run(number_of_trial_steps=len(structure) * 30)
Beispiel #2
0
    def test_init(self):
        """ Tests exceptions are raised during initialization. """
        with self.assertRaises(TypeError) as context:
            SemiGrandCanonicalEnsemble(structure=self.structure,
                                       calculator=self.calculator)
        self.assertTrue("required positional arguments: 'temperature'" in str(
            context.exception))

        with self.assertRaises(TypeError) as context:
            SemiGrandCanonicalEnsemble(structure=self.structure,
                                       calculator=self.calculator,
                                       temperature=self.temperature)
        self.assertTrue("required positional argument:"
                        " 'chemical_potentials'" in str(context.exception))
Beispiel #3
0
    def setUp(self):
        """Setup before each test."""
        self.calculator = ClusterExpansionCalculator(self.structure, self.ce)

        self.ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            data_container_write_period=499.0,
            ensemble_data_write_interval=25,
            trajectory_write_interval=40,
            temperature=self.temperature,
            chemical_potentials=self.chemical_potentials,
            boltzmann_constant=1e-5)
Beispiel #4
0
    def test_init_with_integer_chemical_potentials(self):
        """Tests init with integer chemical potentials."""

        chemical_potentials = {13: 5, 31: 0}
        ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            temperature=self.temperature,
            chemical_potentials=chemical_potentials)
        ensemble._do_trial_step()

        # Test both int and str
        chemical_potentials = {'Al': 5, 31: 0}
        ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            temperature=self.temperature,
            chemical_potentials=chemical_potentials)
        ensemble._do_trial_step()
Beispiel #5
0
class TestEnsemble(unittest.TestCase):
    """Container for tests of the class functionality."""
    def __init__(self, *args, **kwargs):
        super(TestEnsemble, self).__init__(*args, **kwargs)

        self.structure = bulk('Al').repeat(3)
        for i, atom in enumerate(self.structure):
            if i % 2 == 0:
                atom.symbol = 'Ga'
        cutoffs = [5, 5, 4]
        self.elements = ['Al', 'Ga']
        self.chemical_potentials = {'Al': 5, 'Ga': 0}
        self.cs = ClusterSpace(self.structure, cutoffs, self.elements)
        parameters = parameters = np.array([1.2] * len(self.cs))
        self.ce = ClusterExpansion(self.cs, parameters)
        self.temperature = 100.0

    def shortDescription(self):
        """Silences unittest from printing the docstrings in test cases."""
        return None

    def setUp(self):
        """Setup before each test."""
        self.calculator = ClusterExpansionCalculator(self.structure, self.ce)

        self.structure = bulk('Al').repeat(3)
        for i, atom in enumerate(self.structure):
            if i % 2 == 0:
                atom.symbol = 'Ga'

        self.ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            data_container_write_period=499.0,
            ensemble_data_write_interval=25,
            trajectory_write_interval=40,
            temperature=self.temperature,
            chemical_potentials=self.chemical_potentials,
            boltzmann_constant=1e-5)

    def test_do_sgc_trial_step(self):
        """Tests the do trial step."""
        chemical_potentials = self.ensemble._chemical_potentials

        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_sgc_flip(sublattice_index=sl_index,
                                      chemical_potentials=chemical_potentials)

        # repeat the test when specifying allowed species
        allowed_species = [atomic_numbers[s] for s in self.elements]
        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_sgc_flip(sublattice_index=sl_index,
                                      chemical_potentials=chemical_potentials,
                                      allowed_species=allowed_species)

    def test_do_canonical_trial_step(self):
        """Tests the do trial step."""

        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_canonical_swap(sublattice_index=sl_index)

        # repeat the test when specifying allowed species
        allowed_species = [atomic_numbers[s] for s in self.elements]
        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_canonical_swap(sublattice_index=sl_index,
                                            allowed_species=allowed_species)

    def test_do_vcsgc_flip(self):
        """Test the vcsgc flip."""
        kappa = 200
        phis = {'Al': -1}
        phis = get_phis(phis)
        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_vcsgc_flip(phis=phis,
                                        kappa=kappa,
                                        sublattice_index=sl_index)

        # repeat the test when specifying allowed species
        allowed_species = [atomic_numbers[s] for s in self.elements]
        for _ in range(10):
            sl_index = self.ensemble.get_random_sublattice_index(
                self.ensemble._flip_sublattice_probabilities)
            self.ensemble.do_vcsgc_flip(phis=phis,
                                        kappa=kappa,
                                        sublattice_index=sl_index,
                                        allowed_species=allowed_species)

    def test_get_vcsgc_free_energy_derivatives(self):
        """Test the functionality for determining the VCSGC free energy derivatives."""
        kappa = 200
        phis = {'Al': -1}
        phis = get_phis(phis)
        concentration = len([n for n in self.structure.numbers if n == 13
                             ]) / len(self.structure)
        target = {
            'free_energy_derivative_Al':
            kappa * self.ensemble.boltzmann_constant * self.temperature *
            (-2 * concentration - phis[13])
        }
        data = self.ensemble._get_vcsgc_free_energy_derivatives(phis=phis,
                                                                kappa=kappa)
        self.assertAlmostEqualDict(data, target)

        # repeat the test when specifying a sublattice index
        sublattice_index = 0
        data = self.ensemble._get_vcsgc_free_energy_derivatives(
            phis=phis, kappa=kappa, sublattice_index=sublattice_index)
        self.assertAlmostEqualDict(data, target)

    def test_get_species_counts(self):
        """Test the functionality for determining the species counts."""
        target = {
            '{}_count'.format(symbol): counts
            for symbol, counts in zip(*np.unique(
                self.structure.get_chemical_symbols(), return_counts=True))
        }
        data = self.ensemble._get_species_counts()
        self.assertDictEqual(data, target)
Beispiel #6
0
class TestEnsemble(unittest.TestCase):
    """Container for tests of the class functionality."""
    def __init__(self, *args, **kwargs):
        super(TestEnsemble, self).__init__(*args, **kwargs)

        self.structure = bulk('Al').repeat(3)
        for i, atom in enumerate(self.structure):
            if i % 2 == 0:
                atom.symbol = 'Ga'
        cutoffs = [5, 5, 4]
        elements = ['Al', 'Ga']
        self.chemical_potentials = {'Al': 5, 'Ga': 0}
        self.cs = ClusterSpace(self.structure, cutoffs, elements)
        parameters = parameters = np.array([1.2] * len(self.cs))
        self.ce = ClusterExpansion(self.cs, parameters)
        self.temperature = 100.0

    def shortDescription(self):
        """Silences unittest from printing the docstrings in test cases."""
        return None

    def setUp(self):
        """Setup before each test."""
        self.calculator = ClusterExpansionCalculator(self.structure, self.ce)

        self.ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            data_container_write_period=499.0,
            ensemble_data_write_interval=25,
            trajectory_write_interval=40,
            temperature=self.temperature,
            chemical_potentials=self.chemical_potentials,
            boltzmann_constant=1e-5)

    def test_init(self):
        """ Tests exceptions are raised during initialization. """
        with self.assertRaises(TypeError) as context:
            SemiGrandCanonicalEnsemble(structure=self.structure,
                                       calculator=self.calculator)
        self.assertTrue("required positional arguments: 'temperature'" in str(
            context.exception))

        with self.assertRaises(TypeError) as context:
            SemiGrandCanonicalEnsemble(structure=self.structure,
                                       calculator=self.calculator,
                                       temperature=self.temperature)
        self.assertTrue("required positional argument:"
                        " 'chemical_potentials'" in str(context.exception))

    def test_property_boltzmann(self):
        """Tests explicit Boltzmann constant."""
        self.assertAlmostEqual(1e-5, self.ensemble.boltzmann_constant)

    def test_property_temperature(self):
        """Tests property temperature."""
        self.assertEqual(self.ensemble.temperature, self.temperature)

    def test_property_chemical_potentials(self):
        """Tests property chemical_potentials."""
        retval = self.ensemble.chemical_potentials
        target = {13: 5, 31: 0}
        self.assertEqual(retval, target)

        # test exceptions
        with self.assertRaises(TypeError) as context:
            get_chemical_potentials('xyz')
        self.assertTrue(
            'chemical_potentials has the wrong type' in str(context.exception))

    def test_run(self):
        """Test that run function runs. """
        n = 50
        self.ensemble.run(n)
        self.assertEqual(self.ensemble.step, n)

    def test_do_trial_step(self):
        """Tests the do trial step."""
        # Do it many times and hopefully get both a reject and an accept
        for _ in range(10):
            self.ensemble._do_trial_step()

    def test_acceptance_condition(self):
        """Tests the acceptance condition method."""
        self.assertTrue(self.ensemble._acceptance_condition(-10.0))

        # at least run it for positive energy diff
        self.ensemble._acceptance_condition(10.0)

    def test_init_with_integer_chemical_potentials(self):
        """Tests init with integer chemical potentials."""

        chemical_potentials = {13: 5, 31: 0}
        ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            temperature=self.temperature,
            chemical_potentials=chemical_potentials)
        ensemble._do_trial_step()

        # Test both int and str
        chemical_potentials = {'Al': 5, 31: 0}
        ensemble = SemiGrandCanonicalEnsemble(
            structure=self.structure,
            calculator=self.calculator,
            user_tag='test-ensemble',
            random_seed=42,
            temperature=self.temperature,
            chemical_potentials=chemical_potentials)
        ensemble._do_trial_step()

    def test_get_ensemble_data(self):
        """Tests the get ensemble data method."""
        data = self.ensemble._get_ensemble_data()

        self.assertIn('potential', data.keys())
        self.assertIn('Al_count', data.keys())
        self.assertIn('Ga_count', data.keys())

        self.assertEqual(data['Al_count'], 13)
        self.assertEqual(data['Ga_count'], 14)

    def test_get_ensemble_parameters(self):
        """Tests the get ensemble parameters method."""
        self.assertEqual(self.ensemble.ensemble_parameters['n_atoms'],
                         len(self.structure))
        self.assertEqual(self.ensemble.ensemble_parameters['temperature'],
                         self.temperature)
        self.assertEqual(self.ensemble.ensemble_parameters['mu_Al'], 5)
        self.assertEqual(self.ensemble.ensemble_parameters['mu_Ga'], 0)

        self.assertEqual(
            self.ensemble.data_container.ensemble_parameters['n_atoms'],
            len(self.structure))
        self.assertEqual(
            self.ensemble.data_container.ensemble_parameters['temperature'],
            self.temperature)
        self.assertEqual(
            self.ensemble.data_container.ensemble_parameters['mu_Al'], 5)
        self.assertEqual(
            self.ensemble.data_container.ensemble_parameters['mu_Ga'], 0)

    def test_write_interval_and_period(self):
        """Tests interval and period for writing data from ensemble."""
        self.assertEqual(self.ensemble._data_container_write_period, 499.0)
        self.assertEqual(self.ensemble._ensemble_data_write_interval, 25)
        self.assertEqual(self.ensemble._trajectory_write_interval, 40)
Beispiel #7
0
# step 1: Set up structure to simulate as well as calculator
ce = ClusterExpansion.read('mixing_energy.ce')
structure = make_supercell(ce.get_cluster_space_copy().primitive_structure,
                           3 * np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]]))
calculator = ClusterExpansionCalculator(structure, ce)

# step 2: Carry out Monte Carlo simulations
# Make sure output directory exists
output_directory = 'monte_carlo_data'
try:
    mkdir(output_directory)
except FileExistsError:
    pass
for temperature in [900, 300]:
    # Evolve configuration through the entire composition range
    for dmu in np.arange(-0.7, 0.51, 0.05):
        # Initialize MC ensemble
        mc = SemiGrandCanonicalEnsemble(
            structure=structure,
            calculator=calculator,
            temperature=temperature,
            dc_filename='{}/sgc-T{}-dmu{:+.3f}.dc'.format(
                output_directory, temperature, dmu),
            chemical_potentials={
                'Ag': 0,
                'Pd': dmu
            })

        mc.run(number_of_trial_steps=len(structure) * 30)
        structure = mc.structure
# step 3: Construct cluster expansion for lattice parameter
fit_data = sc.get_fit_data(key='lattice_parameter')
opt = CrossValidationEstimator(fit_data=fit_data, fit_method='lasso')
opt.validate()
opt.train()
ce_latt_param = ClusterExpansion(cluster_space=cs, parameters=opt.parameters)

# step 4: Set up the calculator and a canonical ensemble
structure = cs.primitive_structure.repeat(3)
structure.set_chemical_symbols([chemical_symbols[0]] * len(structure))
calculator = CECalculator(structure=structure,
                          cluster_expansion=ce_mix_energies)
ensemble = SGCEnsemble(calculator=calculator,
                       structure=structure,
                       random_seed=42,
                       temperature=900.0,
                       chemical_potentials={
                           'Ag': 0,
                           'Pd': 0
                       },
                       ensemble_data_write_interval=10)

# step 5: Attach observer and run
observer = CEObserver(cluster_expansion=ce_latt_param, interval=10)
ensemble.attach_observer(observer=observer, tag='lattice_parameter')
ensemble.run(number_of_trial_steps=1000)

# step 6: Print data
print(ensemble.data_container.data)