3-phase Composite Example¶
from hashin_shtrikman_mp.core.user_input import Aggregate, MaterialProperty, Material, MixtureProperty, Mixture, UserInput
from hashin_shtrikman_mp.core import GeneticAlgorithm
from hashin_shtrikman_mp.core.genetic_algorithm import OptimizationParams
from hashin_shtrikman_mp.core.visualization import OptimizationResultVisualizer
from hashin_shtrikman_mp.core.match_finder import MatchFinder
from IPython.display import Image
Define properties for each material
properties_mat_1 = [
MaterialProperty(prop='elec_cond_300k_low_doping', upper_bound=120, lower_bound=1e-7),
MaterialProperty(prop='therm_cond_300k_low_doping', upper_bound=2, lower_bound=1e-7),
MaterialProperty(prop='bulk_modulus', upper_bound=500, lower_bound=50),
MaterialProperty(prop='shear_modulus', upper_bound=500, lower_bound=80),
MaterialProperty(prop='universal_anisotropy', upper_bound=6, lower_bound=1),
]
properties_mat_2 = [
MaterialProperty(prop='elec_cond_300k_low_doping', upper_bound=78, lower_bound=1e-7),
MaterialProperty(prop='therm_cond_300k_low_doping', upper_bound=2, lower_bound=1e-7),
MaterialProperty(prop='bulk_modulus', upper_bound=400, lower_bound=20),
MaterialProperty(prop='shear_modulus', upper_bound=500, lower_bound=100),
MaterialProperty(prop='universal_anisotropy', upper_bound=4.3, lower_bound=1.3),
]
properties_mat_3 = [
MaterialProperty(prop='elec_cond_300k_low_doping', upper_bound=78, lower_bound=1e-7),
MaterialProperty(prop='therm_cond_300k_low_doping', upper_bound=2, lower_bound=1e-7),
MaterialProperty(prop='bulk_modulus', upper_bound=700, lower_bound=20),
MaterialProperty(prop='shear_modulus', upper_bound=600, lower_bound=100),
MaterialProperty(prop='universal_anisotropy', upper_bound=2.1, lower_bound=0.9),
]
Create an instance of the Material class for each material
mat_1 = Material(name='mat_1', properties=properties_mat_1)
mat_2 = Material(name='mat_2', properties=properties_mat_2)
mat_3 = Material(name='mat_3', properties=properties_mat_3)
Define properties for the mixture
properties_mixture = [
MixtureProperty(prop='elec_cond_300k_low_doping', desired_prop=9),
MixtureProperty(prop='therm_cond_300k_low_doping', desired_prop=0.9),
MixtureProperty(prop='bulk_modulus', desired_prop=280),
MixtureProperty(prop='shear_modulus', desired_prop=230),
MixtureProperty(prop='universal_anisotropy', desired_prop=1.5),
]
Create an instance of the Mixture class to store the desired composite properties and aggregate the materials and mixture into a list for later iteration
mixture = Mixture(name='mixture', properties=properties_mixture)
Create an instance of the Aggregate class which aggregates the material property search bounds across materials to find the maximum upper bound per property and minimum lower bound per property.
Then call get_bounds_dict to store the search bounds in a dictionary for use when finding real material matches in the Materials Project database.
aggregate = Aggregate(name='aggregate', components=[mat_1, mat_2, mat_3, mixture])
bounds_dict = aggregate.get_bounds_dict()
Create an instance of the UserInput class from the materials and mixture(s) just created
user_input= UserInput(materials=[mat_1, mat_2, mat_3], mixtures=[mixture])
Initialize an instance of the OptimizationParams class using the previously defined UserInput, as well as an instance of the GeneticAlgorithm class
optimization_parameters = OptimizationParams.from_user_input(user_input)
ga = GeneticAlgorithm()
Run the optimization $n=3$ materials. Identify the optimal properties of each material and the respective volume fractions that achieve the desired composite material properties.
ga_result = ga.run(user_input, gen_counter=False)
Create an instance of the OptimizationResultVisualizer class using the genetic algorithm result
visualizer = OptimizationResultVisualizer(ga_result)
Print the optimization results as a table. Each row represents a theoretical material.
visualizer.print_table_of_best_designs(rows=10)
Plot the genetic algorithm convergence plot
visualizer.plot_optimization_results()
Plot the contributions to the cost function for the best performer
Note on how many contributions to expect: Per property, there is
- 1 effective property term
- (Non-modulus) 2 concentration factor terms per material
- (Modulus) 2 concentration factor terms per coupled (bulk, shear) moduli per material -- not considered individual properties
For example, for a 3-phase composite which considers carrier-transport and elastic property categories, not including volume fraction, there are 5 properties per material, so in total we expect
- 5 effective property terms
- 18 = 6 concentration factor terms (load and response terms for electrical conductivity, thermal conductivity, and universal anisotropy) $\times$ 3 materials
- 6 = 2 concentration factor terms (coupled deviatoric and hydrostatic terms from coupled bulk/shear moduli) $\times$ 3 materials
visualizer.plot_cost_func_contribs()
Cost: 0.04477574762468891, Number effective properties: 5, Number of concentration factors: 24
Create an instance of the MatchFinder class using the genetic algorithm result
match_finder = MatchFinder(ga_result)
Finally, get real material matches
matches_dict = match_finder.get_material_matches(bounds_dict)
Retrieving SummaryDoc documents: 0%| | 0/261 [00:00<?, ?it/s]
Let's take a peak at the matches that were returned
print(f'Material Matches:')
for mat in matches_dict.keys():
print(f' For {mat}:')
for match_dict in matches_dict[mat]:
for mpid in match_dict.keys():
print(f' {mpid}')
Material Matches:
For mat1:
mp-684591
mp-752826
mp-3098
mp-3748
mp-3536
mp-4391
mp-5924
mp-753459
mp-2657
mp-755759
mp-4820
For mat2:
mp-684591
mp-752826
mp-3098
mp-3748
mp-3536
mp-4391
mp-5924
mp-753459
mp-2657
mp-755759
mp-4820
For mat3:
mp-684591
mp-752826
mp-3098
mp-3748
mp-3536
mp-4391
mp-5924
mp-753459
mp-2657
mp-755759
mp-4820
If the above cell fails, the Materials Project API may have been updated. Uncomment and run the following cell and then re-run the entire notebook.
#!pip install --upgrade mp-api
An extra note: For reading bulk and shear moduli from the Materials Project database, there are a few options outlined here. In hashin_shtrikman_mp we use the Voigt-Reuss-Hill average.