pymoo GA: OPV light-intensity dependant JV fits with SIMsalabim (fake data)
This notebook is a demonstration of how to fit light-intensity dependent JV curves with drift-diffusion models using the SIMsalabim package.
[1]:
# Import necessary libraries
import warnings, os, sys, shutil
# remove warnings from the output
os.environ["PYTHONWARNINGS"] = "ignore"
warnings.filterwarnings(action='ignore', category=FutureWarning)
warnings.filterwarnings(action='ignore', category=UserWarning)
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import default_rng
import torch, copy, uuid
import pySIMsalabim as sim
from pySIMsalabim.experiments.JV_steady_state import *
import ax, logging
from ax.utils.notebook.plotting import init_notebook_plotting, render
init_notebook_plotting() # for Jupyter notebooks
try:
from optimpv import *
from optimpv.pymooOpti.pymooOptimizer import PymooOptimizer
except Exception as e:
sys.path.append('../') # add the path to the optimpv module
from optimpv import *
from optimpv.pymooOpti.pymooOptimizer import PymooOptimizer
[INFO 08-13 17:51:30] ax.utils.notebook.plotting: Injecting Plotly library into cell. Do not overwrite or delete cell.
[INFO 08-13 17:51:30] ax.utils.notebook.plotting: Please see
(https://ax.dev/tutorials/visualizations.html#Fix-for-plots-that-are-not-rendering)
if visualizations are not rendering.
Define the parameters for the simulation
[2]:
params = [] # list of parameters to be optimized
mun = FitParam(name = 'l2.mu_n', value = 7e-8, bounds = [1e-9,1e-6], log_scale = True, value_type = 'float', fscale = None, rescale = False, display_name=r'$\mu_n$', unit='m$^2$ V$^{-1}$s$^{-1}$', axis_type = 'log', force_log = True)
params.append(mun)
mup = FitParam(name = 'l2.mu_p', value = 5e-8, bounds = [1e-9,1e-6], log_scale = True, value_type = 'float', fscale = None, rescale = False, display_name=r'$\mu_p$', unit=r'm$^2$ V$^{-1}$s$^{-1}$', axis_type = 'log', force_log = True)
params.append(mup)
bulk_tr = FitParam(name = 'l2.N_t_bulk', value = 1e20, bounds = [1e19,1e22], log_scale = True, value_type = 'float', fscale = None, rescale = False, display_name=r'$N_{T}$', unit=r'm$^{-3}$', axis_type = 'log', force_log = False)
params.append(bulk_tr)
preLangevin = FitParam(name = 'l2.preLangevin', value = 1e-2, bounds = [0.005,1], log_scale = True, value_type = 'float', fscale = None, rescale = False, display_name=r'$\gamma_{pre}$', unit=r'', axis_type = 'log', force_log = False)
params.append(preLangevin)
R_series = FitParam(name = 'R_series', value = 1e-4, bounds = [1e-5,1e-3], log_scale = True, value_type = 'float', fscale = None, rescale = False, display_name=r'$R_{series}$', unit=r'$\Omega$ m$^2$', axis_type = 'log', force_log = False)
params.append(R_series)
# save the original parameters for later
params_orig = copy.deepcopy(params)
Generate some fake data
Here we generate some fake data to fit. The data is generated using the same model as the one used for the fitting, so it is a good test of the fitting procedure. For more information on how to run SIMsalabim from python see the pySIMsalabim package.
[3]:
# Set the session path for the simulation and the input files
session_path = os.path.join(os.path.join(os.path.abspath('../'),'SIMsalabim','SimSS'))
input_path = os.path.join(os.path.join(os.path.join(os.path.abspath('../'),'Data','simsalabim_test_inputs','fakeOPV')))
simulation_setup_filename = 'simulation_setup_fakeOPV.txt'
simulation_setup = os.path.join(session_path, simulation_setup_filename)
# path to the layer files defined in the simulation_setup file
l1 = 'ZnO.txt'
l2 = 'ActiveLayer.txt'
l3 = 'BM_HTL.txt'
l1 = os.path.join(input_path, l1)
l2 = os.path.join(input_path, l2)
l3 = os.path.join(input_path, l3)
# copy this files to session_path
force_copy = True
if not os.path.exists(session_path):
os.makedirs(session_path)
for file in [l1,l2,l3,simulation_setup_filename]:
file = os.path.join(input_path, os.path.basename(file))
if force_copy or not os.path.exists(os.path.join(session_path, os.path.basename(file))):
shutil.copyfile(file, os.path.join(session_path, os.path.basename(file)))
else:
print('File already exists: ',file)
# Show the device structure
fig = sim.plot_band_diagram(simulation_setup, session_path)
# reset simss
# Set the JV parameters
Gfracs = [0.1,0.5,1.0] # Fractions of the generation rate to simulate (None if you want only one light intensity as define in the simulation_setup file)
UUID = str(uuid.uuid4()) # random UUID to avoid overwriting files
cmd_pars = [] # see pySIMsalabim documentation for the command line parameters
# Add the parameters to the command line arguments
for param in params:
cmd_pars.append({'par':param.name, 'val':str(param.value)})
# Add the layer files to the command line arguments
# cmd_pars.append({'par':'l1', 'val':l1})
# cmd_pars.append({'par':'l2', 'val':l2})
# cmd_pars.append({'par':'l3', 'val':l3})
# Run the JV simulation
ret, mess = run_SS_JV(simulation_setup, session_path, JV_file_name = 'JV.dat', G_fracs = Gfracs, parallel = True, max_jobs = 3, UUID=UUID, cmd_pars=cmd_pars)
# save data for fitting
X,y = [],[]
X_orig,y_orig = [],[]
if Gfracs is None:
data = pd.read_csv(os.path.join(session_path, 'JV_'+UUID+'.dat'), sep=r'\s+') # Load the data
Vext = np.asarray(data['Vext'].values)
Jext = np.asarray(data['Jext'].values)
G = np.ones_like(Vext)
rng = default_rng()#
noise = rng.standard_normal(Jext.shape) * 0.01 * Jext
Jext = Jext + noise
X = Vext
y = Jext
plt.figure()
plt.plot(X,y)
plt.show()
else:
for Gfrac in Gfracs:
data = pd.read_csv(os.path.join(session_path, 'JV_Gfrac_'+str(Gfrac)+'_'+UUID+'.dat'), sep=r'\s+') # Load the data
Vext = np.asarray(data['Vext'].values)
Jext = np.asarray(data['Jext'].values)
G = np.ones_like(Vext)*Gfrac
rng = default_rng()#
noise = rng.standard_normal(Jext.shape) * 0.005 * Jext
if len(X) == 0:
X = np.vstack((Vext,G)).T
y = Jext + noise
y_orig = Jext
else:
X = np.vstack((X,np.vstack((Vext,G)).T))
y = np.hstack((y,Jext+ noise))
y_orig = np.hstack((y_orig,Jext))
# remove all the current where Jext is higher than a given value
X = X[y<200]
X_orig = copy.deepcopy(X)
y_orig = y_orig[y<200]
y = y[y<200]
plt.figure()
for Gfrac in Gfracs:
plt.plot(X[X[:,1]==Gfrac,0],y[X[:,1]==Gfrac],label='Gfrac = '+str(Gfrac))
plt.xlabel('Voltage [V]')
plt.ylabel('Current density [A/m$^2$]')
plt.legend()
plt.show()


Run the optimization
[4]:
# Define the Agent and the target metric/loss function
from optimpv.DDfits.JVAgent import JVAgent
metric = 'nrmse' # can be 'nrmse', 'mse', 'mae'
loss = 'linear' # can be 'linear', 'huber', 'soft_l1'
jv = JVAgent(params, X, y, session_path, simulation_setup, parallel = True, max_jobs = 3, metric = metric, loss = loss)
# Calulate the target metric for the original parameters
best_fit_possible = loss_function(calc_metric(y,y_orig, metric_name = metric),loss)
print('Best fit: ',best_fit_possible)
Best fit: 0.001716717288438208
[5]:
# Define the optimizer
optimizer = PymooOptimizer(params=params, agents=jv, algorithm='GA', pop_size=20, n_gen=100, name='pymoo_single_obj', verbose_logging=True,max_parallelism=20, )
[6]:
optimizer.optimize() # run the optimization
[INFO 08-13 17:51:31] optimpv.pymooOptimizer: Starting optimization using GA algorithm
[INFO 08-13 17:51:31] optimpv.pymooOptimizer: Population size: 20, Generations: 100
[INFO 08-13 17:51:33] optimpv.pymooOptimizer: Generation 1: Best objective = 0.068089
=================================================
n_gen | n_eval | f_avg | f_min
=================================================
1 | 20 | 0.2168573631 | 0.0680891201
[INFO 08-13 17:51:33] optimpv.pymooOptimizer: Generation 2: Best objective = 0.063452
2 | 40 | 0.1587647959 | 0.0634523760
[INFO 08-13 17:51:34] optimpv.pymooOptimizer: Generation 3: Best objective = 0.063452
3 | 60 | 0.1275710268 | 0.0634523760
[INFO 08-13 17:51:34] optimpv.pymooOptimizer: Generation 4: Best objective = 0.059379
4 | 80 | 0.0788316421 | 0.0593788732
[INFO 08-13 17:51:34] optimpv.pymooOptimizer: Generation 5: Best objective = 0.055835
5 | 100 | 0.0648862154 | 0.0558348571
[INFO 08-13 17:51:35] optimpv.pymooOptimizer: Generation 6: Best objective = 0.047263
6 | 120 | 0.0589292144 | 0.0472634211
[INFO 08-13 17:51:35] optimpv.pymooOptimizer: Generation 7: Best objective = 0.043901
7 | 140 | 0.0540928402 | 0.0439008464
[INFO 08-13 17:51:35] optimpv.pymooOptimizer: Generation 8: Best objective = 0.031583
8 | 160 | 0.0477575469 | 0.0315832981
[INFO 08-13 17:51:36] optimpv.pymooOptimizer: Generation 9: Best objective = 0.031583
9 | 180 | 0.0416380184 | 0.0315832981
[INFO 08-13 17:51:36] optimpv.pymooOptimizer: Generation 10: Best objective = 0.031583
10 | 200 | 0.0363630676 | 0.0315832981
[INFO 08-13 17:51:36] optimpv.pymooOptimizer: Generation 11: Best objective = 0.028206
11 | 220 | 0.0329129815 | 0.0282063493
[INFO 08-13 17:51:37] optimpv.pymooOptimizer: Generation 12: Best objective = 0.022580
12 | 240 | 0.0299054569 | 0.0225798593
[INFO 08-13 17:51:37] optimpv.pymooOptimizer: Generation 13: Best objective = 0.022495
13 | 260 | 0.0270371000 | 0.0224947591
[INFO 08-13 17:51:37] optimpv.pymooOptimizer: Generation 14: Best objective = 0.016060
14 | 280 | 0.0241101607 | 0.0160599456
[INFO 08-13 17:51:38] optimpv.pymooOptimizer: Generation 15: Best objective = 0.016060
15 | 300 | 0.0233348391 | 0.0160599456
[INFO 08-13 17:51:38] optimpv.pymooOptimizer: Generation 16: Best objective = 0.015310
16 | 320 | 0.0214778058 | 0.0153101035
[INFO 08-13 17:51:38] optimpv.pymooOptimizer: Generation 17: Best objective = 0.014372
17 | 340 | 0.0189454129 | 0.0143719885
[INFO 08-13 17:51:39] optimpv.pymooOptimizer: Generation 18: Best objective = 0.014370
18 | 360 | 0.0159825322 | 0.0143702267
[INFO 08-13 17:51:39] optimpv.pymooOptimizer: Generation 19: Best objective = 0.009681
19 | 380 | 0.0145548265 | 0.0096810084
[INFO 08-13 17:51:40] optimpv.pymooOptimizer: Generation 20: Best objective = 0.009681
20 | 400 | 0.0141267152 | 0.0096810084
[INFO 08-13 17:51:40] optimpv.pymooOptimizer: Generation 21: Best objective = 0.009558
21 | 420 | 0.0133521152 | 0.0095576510
[INFO 08-13 17:51:40] optimpv.pymooOptimizer: Generation 22: Best objective = 0.009460
22 | 440 | 0.0122587502 | 0.0094602249
[INFO 08-13 17:51:41] optimpv.pymooOptimizer: Generation 23: Best objective = 0.008954
23 | 460 | 0.0104478201 | 0.0089543785
[INFO 08-13 17:51:41] optimpv.pymooOptimizer: Generation 24: Best objective = 0.008536
24 | 480 | 0.0094380986 | 0.0085356392
[INFO 08-13 17:51:41] optimpv.pymooOptimizer: Generation 25: Best objective = 0.008536
25 | 500 | 0.0092222394 | 0.0085356392
[INFO 08-13 17:51:42] optimpv.pymooOptimizer: Generation 26: Best objective = 0.008198
26 | 520 | 0.0089980646 | 0.0081982884
[INFO 08-13 17:51:42] optimpv.pymooOptimizer: Generation 27: Best objective = 0.007721
27 | 540 | 0.0085387383 | 0.0077208831
[INFO 08-13 17:51:42] optimpv.pymooOptimizer: Generation 28: Best objective = 0.007715
28 | 560 | 0.0082937641 | 0.0077145213
[INFO 08-13 17:51:43] optimpv.pymooOptimizer: Generation 29: Best objective = 0.007715
29 | 580 | 0.0081557244 | 0.0077145213
[INFO 08-13 17:51:43] optimpv.pymooOptimizer: Generation 30: Best objective = 0.007715
30 | 600 | 0.0080288140 | 0.0077145213
[INFO 08-13 17:51:43] optimpv.pymooOptimizer: Generation 31: Best objective = 0.007692
31 | 620 | 0.0079082281 | 0.0076918773
[INFO 08-13 17:51:44] optimpv.pymooOptimizer: Generation 32: Best objective = 0.007412
32 | 640 | 0.0078182838 | 0.0074124162
[INFO 08-13 17:51:44] optimpv.pymooOptimizer: Generation 33: Best objective = 0.007412
33 | 660 | 0.0077200213 | 0.0074124162
[INFO 08-13 17:51:44] optimpv.pymooOptimizer: Generation 34: Best objective = 0.007393
34 | 680 | 0.0076089550 | 0.0073926010
[INFO 08-13 17:51:45] optimpv.pymooOptimizer: Generation 35: Best objective = 0.007393
35 | 700 | 0.0075439903 | 0.0073926010
[INFO 08-13 17:51:45] optimpv.pymooOptimizer: Generation 36: Best objective = 0.007350
36 | 720 | 0.0074929350 | 0.0073500432
[INFO 08-13 17:51:45] optimpv.pymooOptimizer: Generation 37: Best objective = 0.007350
37 | 740 | 0.0074436694 | 0.0073500432
[INFO 08-13 17:51:46] optimpv.pymooOptimizer: Generation 38: Best objective = 0.007309
38 | 760 | 0.0074018496 | 0.0073086933
[INFO 08-13 17:51:46] optimpv.pymooOptimizer: Generation 39: Best objective = 0.007309
39 | 780 | 0.0073768325 | 0.0073086933
[INFO 08-13 17:51:46] optimpv.pymooOptimizer: Generation 40: Best objective = 0.007145
40 | 800 | 0.0073272761 | 0.0071449454
[INFO 08-13 17:51:47] optimpv.pymooOptimizer: Generation 41: Best objective = 0.007138
41 | 820 | 0.0072672791 | 0.0071384860
[INFO 08-13 17:51:47] optimpv.pymooOptimizer: Generation 42: Best objective = 0.007113
42 | 840 | 0.0072168723 | 0.0071126374
[INFO 08-13 17:51:47] optimpv.pymooOptimizer: Generation 43: Best objective = 0.007113
43 | 860 | 0.0071508968 | 0.0071126374
[INFO 08-13 17:51:48] optimpv.pymooOptimizer: Generation 44: Best objective = 0.007113
44 | 880 | 0.0071389344 | 0.0071126374
[INFO 08-13 17:51:48] optimpv.pymooOptimizer: Generation 45: Best objective = 0.006991
45 | 900 | 0.0071303987 | 0.0069913202
[INFO 08-13 17:51:48] optimpv.pymooOptimizer: Generation 46: Best objective = 0.006288
46 | 920 | 0.0070820610 | 0.0062875292
[INFO 08-13 17:51:49] optimpv.pymooOptimizer: Generation 47: Best objective = 0.006288
47 | 940 | 0.0070276855 | 0.0062875015
[INFO 08-13 17:51:49] optimpv.pymooOptimizer: Generation 48: Best objective = 0.006288
48 | 960 | 0.0069277645 | 0.0062875015
[INFO 08-13 17:51:49] optimpv.pymooOptimizer: Generation 49: Best objective = 0.006262
49 | 980 | 0.0066752831 | 0.0062621883
[INFO 08-13 17:51:50] optimpv.pymooOptimizer: Generation 50: Best objective = 0.006262
50 | 1000 | 0.0064529423 | 0.0062621883
[INFO 08-13 17:51:50] optimpv.pymooOptimizer: Generation 51: Best objective = 0.006262
51 | 1020 | 0.0062956747 | 0.0062621216
[INFO 08-13 17:51:50] optimpv.pymooOptimizer: Generation 52: Best objective = 0.006073
52 | 1040 | 0.0062602096 | 0.0060730813
[INFO 08-13 17:51:51] optimpv.pymooOptimizer: Generation 53: Best objective = 0.006073
53 | 1060 | 0.0062448880 | 0.0060730813
[INFO 08-13 17:51:51] optimpv.pymooOptimizer: Generation 54: Best objective = 0.006073
54 | 1080 | 0.0062266070 | 0.0060730813
[INFO 08-13 17:51:51] optimpv.pymooOptimizer: Generation 55: Best objective = 0.006073
55 | 1100 | 0.0061943125 | 0.0060730813
[INFO 08-13 17:51:52] optimpv.pymooOptimizer: Generation 56: Best objective = 0.006039
56 | 1120 | 0.0061488483 | 0.0060390618
[INFO 08-13 17:51:52] optimpv.pymooOptimizer: Generation 57: Best objective = 0.006039
57 | 1140 | 0.0061151578 | 0.0060390618
[INFO 08-13 17:51:52] optimpv.pymooOptimizer: Generation 58: Best objective = 0.005982
58 | 1160 | 0.0060799986 | 0.0059818896
[INFO 08-13 17:51:53] optimpv.pymooOptimizer: Generation 59: Best objective = 0.005804
59 | 1180 | 0.0060227365 | 0.0058044343
[INFO 08-13 17:51:53] optimpv.pymooOptimizer: Generation 60: Best objective = 0.005804
60 | 1200 | 0.0060009027 | 0.0058044343
[INFO 08-13 17:51:53] optimpv.pymooOptimizer: Generation 61: Best objective = 0.005804
61 | 1220 | 0.0059844932 | 0.0058044343
[INFO 08-13 17:51:54] optimpv.pymooOptimizer: Generation 62: Best objective = 0.005804
62 | 1240 | 0.0059628519 | 0.0058044343
[INFO 08-13 17:51:54] optimpv.pymooOptimizer: Generation 63: Best objective = 0.005787
63 | 1260 | 0.0059283759 | 0.0057867511
[INFO 08-13 17:51:54] optimpv.pymooOptimizer: Generation 64: Best objective = 0.005778
64 | 1280 | 0.0058866393 | 0.0057780420
[INFO 08-13 17:51:55] optimpv.pymooOptimizer: Generation 65: Best objective = 0.005590
65 | 1300 | 0.0058188920 | 0.0055903016
[INFO 08-13 17:51:55] optimpv.pymooOptimizer: Generation 66: Best objective = 0.005515
66 | 1320 | 0.0057443906 | 0.0055149257
[INFO 08-13 17:51:55] optimpv.pymooOptimizer: Generation 67: Best objective = 0.005475
67 | 1340 | 0.0057072682 | 0.0054747444
[INFO 08-13 17:51:56] optimpv.pymooOptimizer: Generation 68: Best objective = 0.005475
68 | 1360 | 0.0056730335 | 0.0054747444
[INFO 08-13 17:51:56] optimpv.pymooOptimizer: Generation 69: Best objective = 0.005475
69 | 1380 | 0.0055928896 | 0.0054747444
[INFO 08-13 17:51:56] optimpv.pymooOptimizer: Generation 70: Best objective = 0.005475
70 | 1400 | 0.0055537043 | 0.0054747444
[INFO 08-13 17:51:57] optimpv.pymooOptimizer: Generation 71: Best objective = 0.005290
71 | 1420 | 0.0055051376 | 0.0052897474
[INFO 08-13 17:51:57] optimpv.pymooOptimizer: Generation 72: Best objective = 0.005148
72 | 1440 | 0.0054442027 | 0.0051482856
[INFO 08-13 17:51:58] optimpv.pymooOptimizer: Generation 73: Best objective = 0.005044
73 | 1460 | 0.0053994254 | 0.0050441341
[INFO 08-13 17:51:58] optimpv.pymooOptimizer: Generation 74: Best objective = 0.005044
74 | 1480 | 0.0053582154 | 0.0050441341
[INFO 08-13 17:51:58] optimpv.pymooOptimizer: Generation 75: Best objective = 0.004923
75 | 1500 | 0.0052934862 | 0.0049229778
[INFO 08-13 17:51:59] optimpv.pymooOptimizer: Generation 76: Best objective = 0.004880
76 | 1520 | 0.0052209366 | 0.0048804693
[INFO 08-13 17:51:59] optimpv.pymooOptimizer: Generation 77: Best objective = 0.004872
77 | 1540 | 0.0051278584 | 0.0048721739
[INFO 08-13 17:51:59] optimpv.pymooOptimizer: Generation 78: Best objective = 0.004872
78 | 1560 | 0.0050221076 | 0.0048721739
[INFO 08-13 17:52:00] optimpv.pymooOptimizer: Generation 79: Best objective = 0.004872
79 | 1580 | 0.0049892467 | 0.0048721739
[INFO 08-13 17:52:00] optimpv.pymooOptimizer: Generation 80: Best objective = 0.004872
80 | 1600 | 0.0049461201 | 0.0048721739
[INFO 08-13 17:52:00] optimpv.pymooOptimizer: Generation 81: Best objective = 0.004872
81 | 1620 | 0.0049128527 | 0.0048721739
[INFO 08-13 17:52:01] optimpv.pymooOptimizer: Generation 82: Best objective = 0.004761
82 | 1640 | 0.0048802122 | 0.0047613285
[INFO 08-13 17:52:01] optimpv.pymooOptimizer: Generation 83: Best objective = 0.004729
83 | 1660 | 0.0048611801 | 0.0047291264
[INFO 08-13 17:52:01] optimpv.pymooOptimizer: Generation 84: Best objective = 0.004729
84 | 1680 | 0.0048481875 | 0.0047291264
[INFO 08-13 17:52:02] optimpv.pymooOptimizer: Generation 85: Best objective = 0.004729
85 | 1700 | 0.0048337267 | 0.0047291264
[INFO 08-13 17:52:02] optimpv.pymooOptimizer: Generation 86: Best objective = 0.004729
86 | 1720 | 0.0048003993 | 0.0047291264
[INFO 08-13 17:52:02] optimpv.pymooOptimizer: Generation 87: Best objective = 0.004729
87 | 1740 | 0.0047762766 | 0.0047291264
[INFO 08-13 17:52:03] optimpv.pymooOptimizer: Generation 88: Best objective = 0.004729
88 | 1760 | 0.0047560422 | 0.0047291264
[INFO 08-13 17:52:03] optimpv.pymooOptimizer: Generation 89: Best objective = 0.004657
89 | 1780 | 0.0047447756 | 0.0046567389
[INFO 08-13 17:52:03] optimpv.pymooOptimizer: Generation 90: Best objective = 0.004535
90 | 1800 | 0.0047113407 | 0.0045348958
[INFO 08-13 17:52:04] optimpv.pymooOptimizer: Generation 91: Best objective = 0.004535
91 | 1820 | 0.0046883146 | 0.0045348958
[INFO 08-13 17:52:04] optimpv.pymooOptimizer: Generation 92: Best objective = 0.004238
92 | 1840 | 0.0046398505 | 0.0042381191
[INFO 08-13 17:52:05] optimpv.pymooOptimizer: Generation 93: Best objective = 0.004238
93 | 1860 | 0.0045909318 | 0.0042381191
[INFO 08-13 17:52:05] optimpv.pymooOptimizer: Generation 94: Best objective = 0.004238
94 | 1880 | 0.0045287196 | 0.0042381191
[INFO 08-13 17:52:05] optimpv.pymooOptimizer: Generation 95: Best objective = 0.004238
95 | 1900 | 0.0044590777 | 0.0042381191
[INFO 08-13 17:52:06] optimpv.pymooOptimizer: Generation 96: Best objective = 0.003975
96 | 1920 | 0.0043946103 | 0.0039748214
[INFO 08-13 17:52:06] optimpv.pymooOptimizer: Generation 97: Best objective = 0.003975
97 | 1940 | 0.0042761388 | 0.0039748214
[INFO 08-13 17:52:06] optimpv.pymooOptimizer: Generation 98: Best objective = 0.003909
98 | 1960 | 0.0041571186 | 0.0039093281
[INFO 08-13 17:52:07] optimpv.pymooOptimizer: Generation 99: Best objective = 0.003862
99 | 1980 | 0.0041005916 | 0.0038622484
[INFO 08-13 17:52:07] optimpv.pymooOptimizer: Generation 100: Best objective = 0.003862
[INFO 08-13 17:52:07] optimpv.pymooOptimizer: Optimization completed after 101 generations
[INFO 08-13 17:52:07] optimpv.pymooOptimizer: Number of function evaluations: 2000
[INFO 08-13 17:52:07] optimpv.pymooOptimizer: Best objective value: 0.003862
100 | 2000 | 0.0040489995 | 0.0038622484
[6]:
<pymoo.core.result.Result at 0x7d62c2210050>
[7]:
# get the best parameters and update the params list in the optimizer and the agent
optimizer.update_params_with_best_balance()
jv.params = optimizer.params # update the params list in the agent with the best parameters
# print the best parameters
print('Best parameters:')
for p,po in zip(optimizer.params, params_orig):
print(p.name, 'fitted value:', p.value, 'original value:', po.value)
print('\nSimSS command line:')
print(jv.get_SIMsalabim_clean_cmd(jv.params)) # print the simss command line with the best parameters
Best parameters:
l2.mu_n fitted value: 6.642720385768366e-08 original value: 7e-08
l2.mu_p fitted value: 1.9475757228283802e-07 original value: 5e-08
l2.N_t_bulk fitted value: 1.4420980714287222e+20 original value: 1e+20
l2.preLangevin fitted value: 0.005045569488225461 original value: 0.01
R_series fitted value: 0.00016254324086489196 original value: 0.0001
SimSS command line:
./simss -l2.mu_n 6.642720385768366e-08 -l2.mu_p 1.9475757228283802e-07 -l2.N_t_bulk 1.4420980714287222e+20 -l2.preLangevin 0.005045569488225461 -R_series 0.00016254324086489196
[8]:
optimizer.plot_convergence(yscale='log', xscale='linear')

[9]:
# rerun the simulation with the best parameters
yfit = jv.run(parameters={}) # run the simulation with the best parameters
viridis = plt.get_cmap('viridis', len(Gfracs))
plt.figure(figsize=(10,10))
linewidth = 2
for idx, Gfrac in enumerate(Gfracs[::-1]):
plt.plot(X[X[:,1]==Gfrac,0],y[X[:,1]==Gfrac],label='Gfrac = '+str(Gfrac),color=viridis(idx),alpha=0.5,linewidth=linewidth)
plt.plot(X[X[:,1]==Gfrac,0],yfit[X[:,1]==Gfrac],label='Gfrac = '+str(Gfrac)+' fit',linestyle='--',color=viridis(idx),linewidth=linewidth)
plt.xlabel('Voltage [V]')
plt.ylabel('Current density [A m$^{-2}$]')
plt.legend()
plt.show()

[10]:
# Clean up the output files (comment out if you want to keep the output files)
sim.clean_all_output(session_path)
sim.delete_folders('tmp',session_path)
# uncomment the following lines to delete specific files
sim.clean_up_output('ZnO',session_path)
sim.clean_up_output('ActiveLayer',session_path)
sim.clean_up_output('BM_HTL',session_path)
sim.clean_up_output('simulation_setup_fakeOPV',session_path)