2.7. Optimizer¶
See Also
Overview¶
Optimize specified parameters against user specified objective function. Ideal for finding optimal model parameters. A optimizer instance is created through the Optimizer constructor.
The Optimizer Constructor¶
-
class
Optimzer(job, func, xinit, method=SIMPLEX, verbosity=1, d=None, maxiter=MAXITER, tolerance=TOL, descriptors=None, funcargs=[], Ns=10)¶ Create a Optimzer object and set up the simulation.
The job string is the simulation ID. The Permutator creates a job.eval/ directory in the simulation directory. The ith individual job is then run in job.eval/eval_i/.
The Optimzer writes relevant simulation information to job.eval/job.xml. The Matmodlab.Visualizer can read the job.xml file and display the permutated job.
func is a function that evaluates a Matmodlab simulation. It is called as func(x, xnames, d, job, *funcargs), where x are the current values of the permutated variables, xnames are their names, d is the simulation directory of the current job, job is the job ID, and funcargs are additional arguments to be sent to func.
xinit is a list of initial values of the simulation parameters to be optimized. Each member of the list must be a OptimizeVariable instance.
The following arguments are optional
method is the method for determining how to combine parameter values. One of
SIMPLEX,POWELL,COBYLA, orBRUTE.maxiter is the integer maximum number of iterations and tolerance is the tolerance. The default tolerance is 1e-8.
descriptors is a list of descriptors for the values returned from func.
d is the parent directory to run jobs. If the directory does not exist, it will be created. If the directory exists and bu is False, the directory will be first erased and then re-created. If the directory exists but bu is True, the directory is archived.
Ns is the number of evaluations per dimension for brute force optimization.
OptimizeVariable Factory Method¶
-
OptimizeVariable(name, initial_value, bounds=None)¶ Create a OptimizeVariable object
name is the name of variable and initial_value is its initial value. bounds are the bounds on the variable given as (lower_bound, upper_bound). Bounds are only applicable if the optimizer method is
COBYLA.
Example¶
The following input demonstrates how to optimize the K and G
parameters and can be found in matmodlab/examples/optimize.py. The objective function calls calculate_bounded_area to find the area between the calculated stress strain curve and the experimental.
The Example Script¶
import os
import numpy as np
from matmodlab import *
import matmodlab.utils.fileio as ufio
import matmodlab.utils.numerix.nonmonotonic as unnm
filename = os.path.join(get_my_directory(), "optimize.xls")
strain_exp, stress_exp = zip(*ufio.loadfile(filename, sheet="MML", disp=0,
columns=["STRAIN_XX", "STRESS_XX"]))
def func(x=[], xnames=[], evald="", job="", *args):
mps = MaterialPointSimulator(job)
xp = dict(zip(xnames, x))
NU = 0.32 # poisson's ratio for aluminum
parameters = {"K": xp["E"]/3.0/(1.0-2.0*NU), "G": xp["E"]/2.0/(1.0+NU),
"Y0": xp["Y0"], "H": xp["H"], "BETA": 0.0}
mps.Material("vonmises", parameters)
# create steps from data. note, len(columns) below is < len(descriptors).
# The missing columns are filled with zeros -> giving uniaxial stress in
# this case. Declaring the steps this way does require loading the excel
# file anew for each run
mps.DataSteps(filename, steps=30, sheet='MML',
columns=('STRAIN_XX',), descriptors='ESS')
mps.run()
if not mps.ran:
return 1.0e9
strain_sim, stress_sim = zip(*mps.get("STRAIN_XX", "STRESS_XX"))
error = unnm.calculate_bounded_area(strain_exp, stress_exp,
strain_sim, stress_sim)
return error
E = OptimizeVariable("E", 2.0e6, bounds=(1.0e5, 1.0e7))
Y0= OptimizeVariable("Y0", 0.3e5, bounds=(1.0e4, 1.0e6))
H = OptimizeVariable("H", 1.0e6, bounds=(1.0e4, 1.0e7))
optimizer = Optimizer("optimize", func, [E, Y0, H], method=POWELL,
maxiter=200, tolerance=1.e-3)
optimizer.run()
How Does the Script Work?¶
This section describes each part of the example script
from matmodlab import *
import matmodlab.utils.fileio as ufio
import matmodlab.utils.numerix.nonmonotonic as unnm
filename = os.path.join(get_my_directory(), "optimize.xls")
strain_exp, stress_exp = zip(*ufio.loadfile(filename, sheet="MML", disp=0,
columns=["STRAIN_XX", "STRESS_XX"]))
This statement makes the Matmodlab objects accessible to the script and import other functions for reading Excel data files and comparing two curves. The experimental data is read and stored.
E = OptimizeVariable("E", 2.0e6, bounds=(1.0e5, 1.0e7))
Y0= OptimizeVariable("Y0", 0.3e5, bounds=(1.0e4, 1.0e6))
H = OptimizeVariable("H", 1.0e6, bounds=(1.0e4, 1.0e7))
These statements define parameters E, Y0, and H to be the variable to be optimized.
optimizer = Optimizer("optimize", func, [E, Y0, H], method=POWELL,
maxiter=200, tolerance=1.e-3)
This statement instantiates the Optimzer object, using the POWELL method.
optimizer.run()
This statement runs the job.
def func(x, xnames, d, job, *args):
mps = MaterialPointSimulator(job)
xp = dict(zip(xnames, x))
NU = 0.32 # poisson's ratio for aluminum
parameters = {"K": xp["E"]/3.0/(1.0-2.0*NU), "G": xp["E"]/2.0/(1.0+NU),
"Y0": xp["Y0"], "H": xp["H"], "BETA": 0.0}
mps.Material("vonmises", parameters)
These statements define the function exercised by the Optimzer. The first lines are the instantiation of the MaterialPointSimulator, and its material. The current parameters are passed in from Matmodlab.
mps.DataSteps(filename, steps=30, sheet='MML',
columns=('STRAIN_XX',), descriptors='ESS')
mps.run()
These statements create the analysis steps from the experimental data file and run the simulation
strain_sim, stress_sim = zip(*mps.get("STRAIN_XX", "STRESS_XX"))
error = unnm.calculate_bounded_area(strain_exp, stress_exp,
strain_sim, stress_sim)
return error
These statements read in the analysis results and compute the error between them and the experimental data.