new optimizer: based on ASCO (http://asco.sf.net)
high-performance differential evolution (DE) optimization algorithmpull/1/head
parent
3998f8d1ec
commit
1cb6040524
|
@ -0,0 +1,36 @@
|
|||
%
|
||||
% asco optimizer example -- optimize the turn number of a coil
|
||||
%
|
||||
% You need asco from http://asco.sf.net
|
||||
% This is the main script.
|
||||
% - optimizer_simfun.m starts the simulator with a parameter set from
|
||||
% asco
|
||||
%
|
||||
% The goal is evaluated inside optimizer_simfun() to get as close to 2 uH.
|
||||
|
||||
% clear
|
||||
clear
|
||||
close all
|
||||
clc
|
||||
|
||||
% setup the parameters
|
||||
params = [];
|
||||
params(end+1).name = 'turns';
|
||||
params(end).range = [1 30];
|
||||
params(end).value = 4;
|
||||
params(end).step = 1;
|
||||
params(end).active = 1; % this parameter is to be optimized
|
||||
|
||||
% setup the simulation function
|
||||
folder = fileparts( mfilename('fullpath') );
|
||||
options.simfun = [folder '/optimizer_simfun.m'];
|
||||
|
||||
% additional options
|
||||
% options.octave_exe = 'octave'; % must be newer than 3.2.4 (3.3.54 works)
|
||||
options.clean = 1;
|
||||
|
||||
% start the optimization
|
||||
[params_opt,result] = optimize( 'opttmp', params, options, 'asco' );
|
||||
|
||||
% display best value
|
||||
disp( ['ASCO found the optimum turn number: ' num2str(params_opt(1).value) ' result: ' num2str(result)] );
|
|
@ -0,0 +1,134 @@
|
|||
function result = optimizer_simfun( folder, params )
|
||||
%
|
||||
% simulation function
|
||||
%
|
||||
% the variable params contains the simulation parameters
|
||||
|
||||
disp( [mfilename ': SIMULATING...'] );
|
||||
|
||||
if nargin == 0
|
||||
% visualize the structure if called without parameters
|
||||
folder = 'tmp';
|
||||
params.turns = 10;
|
||||
end
|
||||
|
||||
oldpwd = pwd;
|
||||
[a,a,a] = mkdir( folder );
|
||||
cd( folder );
|
||||
|
||||
% create the structure
|
||||
f_max = 50e6;
|
||||
structure( params, 'tmp.xml', f_max );
|
||||
|
||||
if nargin == 0
|
||||
% visualize the structure
|
||||
CSXGeomPlot('tmp.xml');
|
||||
return;
|
||||
end
|
||||
|
||||
% start simulation
|
||||
RunOpenEMS( '.', 'tmp.xml', '--engine=fastest' );
|
||||
|
||||
% postprocess the results
|
||||
L = postproc( 'tmp.xml', f_max );
|
||||
disp( ['DONE. L = ' num2str(L(1)/1e-6) ' uH'] );
|
||||
|
||||
% calculate result
|
||||
goal = 2e-6; % specify the goal: 2 uH
|
||||
result = abs(goal - L(1)); % costs must not be negative
|
||||
|
||||
% restore curent folder
|
||||
cd( oldpwd );
|
||||
|
||||
|
||||
|
||||
|
||||
% -------------------------------------------------------------------------
|
||||
% -------------------------------------------------------------------------
|
||||
|
||||
function CSX = structure( params, filename, f_max )
|
||||
% CSX = structure( params, filename )
|
||||
|
||||
unit = 1e-3; % specify length in mm
|
||||
lambda = 3e8/f_max;
|
||||
resolution = lambda/15/unit;
|
||||
mesh_size = 1.5;
|
||||
radius = 10;
|
||||
turns = params.turns;
|
||||
height = 4 * turns;
|
||||
feed_length = 10;
|
||||
|
||||
CSX = InitCSX();
|
||||
|
||||
%% create coil
|
||||
p1 = create_coil( radius, height, turns );
|
||||
p = p1(:,end) + [feed_length;0;0];
|
||||
p1 = [p1 p];
|
||||
p = p1(:,1) + [feed_length;0;0];
|
||||
p1 = [p p1];
|
||||
CSX = AddMetal(CSX,'PEC1');
|
||||
CSX = AddCurve(CSX, 'PEC1', 0, p1);
|
||||
|
||||
%% create mesh
|
||||
extraspace = 5*radius;
|
||||
mesh.x = linspace(-radius,radius,ceil(2*radius/mesh_size));
|
||||
mesh.x = [mesh.x mesh.x(1)-extraspace mesh.x(end)+extraspace];
|
||||
mesh.x = [mesh.x p1(1,1) p1(1,1)-mesh_size p1(1,1)+mesh_size];
|
||||
mesh.x = SmoothMeshLines2( mesh.x, resolution );
|
||||
mesh.y = linspace(-radius,radius,ceil(2*radius/mesh_size));
|
||||
mesh.y = [mesh.y mesh.y(1)-extraspace mesh.y(end)+extraspace];
|
||||
mesh.y = SmoothMeshLines2( mesh.y, resolution );
|
||||
mesh.z = linspace(0,height,ceil(height/mesh_size));
|
||||
mesh.z = [mesh.z mesh.z(1)-extraspace mesh.z(end)+extraspace];
|
||||
% mesh.z = [mesh.z p1(3,1) p1(3,1)-mesh_size p1(3,1)+mesh_size];
|
||||
mesh.z = SmoothMeshLines2( mesh.z, resolution );
|
||||
CSX = DefineRectGrid(CSX, unit, mesh);
|
||||
|
||||
|
||||
%% create port
|
||||
[CSX,port] = AddCurvePort( CSX, 1, 50, p1(:,1), p1(:,end), 'excite' );
|
||||
|
||||
if nargin > 1
|
||||
max_timesteps = 100000;
|
||||
min_decrement = 1e-5;
|
||||
FDTD = InitFDTD( max_timesteps, min_decrement );
|
||||
FDTD = SetGaussExcite( FDTD, 0, f_max );
|
||||
BC = {'PEC' 'PEC' 'PEC' 'PEC' 'PMC' 'PMC'};
|
||||
FDTD = SetBoundaryCond( FDTD, BC );
|
||||
|
||||
WriteOpenEMS( filename, FDTD, CSX );
|
||||
end
|
||||
|
||||
|
||||
function p = create_coil(coil_rad,coil_length,coil_turns,coil_res,winding_direction,direction,offset,angle_offset)
|
||||
if nargin < 8, angle_offset = 0; end
|
||||
if nargin < 7, offset = [0; 0; 0]; end
|
||||
if nargin < 6, direction = +1; end
|
||||
if nargin < 5, winding_direction = +1; end
|
||||
if nargin < 4, coil_res = 30; end
|
||||
dt = 1/coil_res;
|
||||
height = 0;
|
||||
|
||||
p = [];
|
||||
while abs(height) < coil_length
|
||||
angle = height / (coil_length/coil_turns) * 2*pi;
|
||||
p(1,end+1) = coil_rad * cos(angle*winding_direction+angle_offset);
|
||||
p(2,end) = coil_rad * sin(angle*winding_direction+angle_offset);
|
||||
p(3,end) = height * direction;
|
||||
p(:,end) = p(:,end) + offset;
|
||||
height = height + coil_length/coil_turns * dt;
|
||||
end
|
||||
|
||||
|
||||
|
||||
function L = postproc( filename, f_max )
|
||||
freq = linspace(0,f_max,201);
|
||||
freq(1) = []; % delete DC component
|
||||
|
||||
folder = fileparts(filename);
|
||||
U = ReadUI( 'port_ut1', folder, freq );
|
||||
I = ReadUI( 'port_it1', folder, freq );
|
||||
Z = U.FD{1}.val ./ I.FD{1}.val;
|
||||
|
||||
L = imag(Z) ./ (2*pi*freq);
|
||||
L = reshape( L, 1, [] ); % row vector
|
|
@ -0,0 +1,203 @@
|
|||
function [params,result] = optimize( optimdir, params, options, algorithm )
|
||||
%params = optimize( optimdir, params, options, algorithm )
|
||||
%
|
||||
% input:
|
||||
% optimdir: folder where to optimize
|
||||
% params: array of structures with parameters to optimize
|
||||
% .name char string parameter name (e.g. 'length1')
|
||||
% .value number
|
||||
% .step number discretization of .value
|
||||
% .range row vector range of .value (e.g. [1 10])
|
||||
% .active (0/1) 1=optimize this parameter
|
||||
% options: structure
|
||||
% .folder_matlabstart set the startup folder for matlab or octave
|
||||
% .simfun char string with the simulation function name
|
||||
% .octave_exe if this field is present, octave is used
|
||||
% .clean clean the optimization folder before optimization start
|
||||
% algorithm: 'asco' or 'simplex-downhill'
|
||||
%
|
||||
% output:
|
||||
% params: optimal values
|
||||
% result: optimization criterion for optimal values
|
||||
%
|
||||
% example:
|
||||
% see openEMS/matlab/examples/optimizer
|
||||
%
|
||||
% notes:
|
||||
% Create a file named 'STOP_OPTIMIZATION' in the optimdir folder to stop
|
||||
% the optimization process (or press Ctrl+C).
|
||||
%
|
||||
% (C) 2010 Sebastian Held <sebastian.held@gmx.de>
|
||||
|
||||
error( nargchk(3,4,nargin) );
|
||||
|
||||
% default to simplex-downhill
|
||||
if nargin < 4
|
||||
algorithm = 'simplex-downhill';
|
||||
end
|
||||
if ~strcmp( algorithm, 'asco' )
|
||||
algorithm = 'simplex-downhill';
|
||||
end
|
||||
|
||||
optimdir = absolutepath( optimdir );
|
||||
if isfield(options,'clean') && (options.clean == 1)
|
||||
[a,a,a] = rmdir( optimdir, 's' );
|
||||
end
|
||||
[a,a,a] = mkdir( optimdir );
|
||||
oldfolder = cd( optimdir );
|
||||
|
||||
if strcmp( algorithm, 'asco' )
|
||||
% ---------------------------------------------------------------------
|
||||
% selected algorithm: ASCO
|
||||
% http://asco.sourceforge.net/
|
||||
|
||||
% if ~exist( 'asco', 'file' ) && ~exist( 'asco.exe', 'file' )
|
||||
% error 'asco was not found in PATH. Download from http://asco.sf.net/'
|
||||
% end
|
||||
|
||||
% create asco config file
|
||||
fid = fopen( 'asco.cfg', 'wt' );
|
||||
fprintf( fid, '* asco configuration file\n' );
|
||||
fprintf( fid, '* http://asco.sourceforge.net/\n' );
|
||||
fprintf( fid, '* \n' );
|
||||
fprintf( fid, '* Optimization for openEMS\n\n' );
|
||||
fprintf( fid, '#Optimization Flow#\n' );
|
||||
fprintf( fid, 'Alter:no $do we want to do corner analysis?\n' );
|
||||
fprintf( fid, 'MonteCarlo:no $do we want to do MonteCarlo analysis?\n' );
|
||||
fprintf( fid, 'AlterMC cost:0.00 $point below which ALTER and/or MONTECARLO can start\n' );
|
||||
fprintf( fid, 'ExecuteRF:no $Execute or no the RF module to add RF parasitics?\n' );
|
||||
fprintf( fid, '#\n\n' );
|
||||
fprintf( fid, '#DE#\n' );
|
||||
fprintf( fid, 'choice of method:3\n' );
|
||||
fprintf( fid, 'maximum no. of iterations:50\n' );
|
||||
fprintf( fid, 'Output refresh cycle:2\n' );
|
||||
fprintf( fid, 'No. of parents NP:10\n' );
|
||||
fprintf( fid, 'Constant F:0.85\n' );
|
||||
fprintf( fid, 'Crossing Over factor CR:1\n' );
|
||||
fprintf( fid, 'Seed for pseudo random number generator:3\n' );
|
||||
fprintf( fid, 'Minimum Cost Variance:1e-6\n' );
|
||||
fprintf( fid, 'Cost objectives:10\n' );
|
||||
fprintf( fid, 'Cost constraints:100\n' );
|
||||
fprintf( fid, '#\n\n' );
|
||||
|
||||
fprintf( fid, '# Parameters #\n' );
|
||||
for n=1:numel(params)
|
||||
if params(n).active == 1
|
||||
active = 'OPT';
|
||||
else
|
||||
active = '---';
|
||||
end
|
||||
value = params(n).value / params(n).step;
|
||||
range = params(n).range / params(n).step;
|
||||
fprintf( fid, 'description:#%s#:%i:%i:%i:LIN_INT:%s\n', params(n).name, value, range(1), range(2), active );
|
||||
end
|
||||
fprintf( fid, '#\n\n' );
|
||||
|
||||
fprintf( fid, '# Measurements #\n' );
|
||||
fprintf( fid, 'value:---:MIN:0\n' );
|
||||
fprintf( fid, '#\n\n' );
|
||||
fclose(fid);
|
||||
|
||||
% create extract file
|
||||
[a,a,a]=mkdir( 'extract' );
|
||||
fid = fopen( 'extract/value', 'wt' );
|
||||
fprintf( fid, '# Info #\n' );
|
||||
fprintf( fid, 'Name:value\n' );
|
||||
fprintf( fid, 'Symbol:value\n' );
|
||||
fprintf( fid, '#\n\n' );
|
||||
fprintf( fid, '# Commands #\n' );
|
||||
fprintf( fid, '#\n\n' );
|
||||
fprintf( fid, '# Post Processing #\n' );
|
||||
fprintf( fid, 'MEASURE_VAR: #SYMBOL#: SEARCH_FOR:''value=''\n' );
|
||||
fprintf( fid, '#\n' );
|
||||
fclose(fid);
|
||||
|
||||
% create matlab parameter file
|
||||
fid = fopen( 'asco.txt', 'wt' );
|
||||
fprintf( fid, '%% this file is processed by asco and variables enclosed in ## are substituted\n' );
|
||||
fprintf( fid, 'params = [];\n' );
|
||||
for n=1:numel(params)
|
||||
fprintf( fid, 'params.%s = #%s# * %i;\n', params(n).name, params(n).name, params(n).step );
|
||||
end
|
||||
fclose(fid);
|
||||
|
||||
% create shell script
|
||||
folder_asco_helper = fileparts( mfilename('fullpath') );
|
||||
asco_sim_helper = 'optimizer_asco_sim';
|
||||
fid = fopen( 'general.sh', 'wt' );
|
||||
fprintf( fid, '#!/bin/sh\n' );
|
||||
fprintf( fid, 'rm "$2.out" 2> /dev/null\n' );
|
||||
fprintf( fid, 'mv "$1.txt" "$1.m"\n' );
|
||||
fprintf( fid, 'if [ -f STOP_OPTIMIZATION ]; then\n' );
|
||||
fprintf( fid, ' exit\n' );
|
||||
fprintf( fid, 'fi\n' );
|
||||
fprintf( fid, 'oldpwd=$PWD\n' );
|
||||
if isfield(options,'folder_matlabstart')
|
||||
% this allows to start the new matlab process in a specific folder
|
||||
% => startup.m is picked up here
|
||||
fprintf( fid, 'cd "%s"\n', functions.folder_matlabstart );
|
||||
end
|
||||
if ~isfield(options,'octave_exe')
|
||||
% matlab
|
||||
fprintf( fid, '%s/bin/matlab -nodesktop -nosplash -r "cd ''%s''; %s(''%s'',''$1'',''$2.out'',''%s''); exit"\n', matlabroot, folder_asco_helper, asco_sim_helper, optimdir, options.simfun );
|
||||
else
|
||||
% octave
|
||||
fprintf( fid, 'export LD_LIBRARY_PATH=\n' );
|
||||
fprintf( fid, '%s --silent --eval "cd ''%s''; %s(''%s'',''$1'',''$2.out'',''%s'');"\n', options.octave_exe, folder_asco_helper, asco_sim_helper, optimdir, options.simfun );
|
||||
end
|
||||
fprintf( fid, 'cd "$oldpwd"\n' );
|
||||
fclose(fid);
|
||||
fileattrib( 'general.sh', '+x' ); % make it executable
|
||||
|
||||
% clean up old data
|
||||
if exist( './best_result.mat', 'file' ), delete( 'best_result.mat' ); end
|
||||
if exist( './STOP_OPTIMIZATION', 'file' ), delete( 'STOP_OPTIMIZATION' ); end
|
||||
|
||||
% start asco
|
||||
[status,result] = unix( 'asco -general asco.txt', '-echo' );
|
||||
|
||||
% get best result
|
||||
best = load( 'best_result.mat' );
|
||||
best = best.best;
|
||||
result = best.result;
|
||||
for n=1:numel(params)
|
||||
name = params(n).name;
|
||||
if isfield(best.params,name)
|
||||
params(n).value = best.params.(name);
|
||||
end
|
||||
end
|
||||
|
||||
elseif strcmp( algorithm, 'simplex-downhill' )
|
||||
% ---------------------------------------------------------------------
|
||||
% selected algorithm: simplex-downhill
|
||||
% Thorsten Liebig <thorsten.liebig@uni-due.de>
|
||||
|
||||
error( 'not implemented yet' );
|
||||
end
|
||||
|
||||
cd( oldfolder );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function folder = absolutepath( folder )
|
||||
%folder = absolutepath( folder )
|
||||
% make the path absolute
|
||||
if isunix
|
||||
% Unix
|
||||
if folder(1) == '/'
|
||||
return
|
||||
end
|
||||
folder = fullfile( pwd, folder );
|
||||
else
|
||||
% Windows
|
||||
folder = strrep( folder, '\', '/' );
|
||||
if strcmp( folder(2:3), ':/' ) || strcmp( folder(1:2), '//' ) || (folder(1) == '/')
|
||||
return
|
||||
end
|
||||
if (folder(2) == ':') && (folder(3) ~= '/')
|
||||
error( 'relative paths with drive specifier are not supported' );
|
||||
end
|
||||
folder = fullfile( pwd, folder );
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
function optimizer_asco_sim( optimdir, inputfile, outputfile, simfun )
|
||||
%optimizer_asco_sim( optimdir, inputfile, outputfile, simfun )
|
||||
%
|
||||
% This function is called from general.sh. Do not call it yourself.
|
||||
%
|
||||
% tasks:
|
||||
% - set correct matlab path
|
||||
% - evaluate inputfile
|
||||
% - start simulation or get result from cache
|
||||
% - postprocess simulation results
|
||||
% - create output file (important: needs single \n at the first line and double \n at the last line!)
|
||||
|
||||
error( nargchk(4,4,nargin) );
|
||||
|
||||
% add CSXCAD and openEMS to the matlab path
|
||||
folder = fileparts( mfilename('fullpath') );
|
||||
addpath( folder );
|
||||
addpath( [folder '/../../CSXCAD/matlab'] );
|
||||
|
||||
% change to optimdir
|
||||
olddir = pwd;
|
||||
cd( optimdir );
|
||||
|
||||
% read parameters set by asco
|
||||
if ~isempty( strfind(inputfile,'-') )
|
||||
% matlab cannot execute a file with dashes...
|
||||
inputfile2 = strrep( inputfile,'-','_' );
|
||||
movefile( [inputfile '.m'], [inputfile2 '.m'] );
|
||||
run( inputfile2 );
|
||||
movefile( [inputfile2 '.m'], [inputfile '.m'] );
|
||||
end
|
||||
% now a structure named 'params' is available
|
||||
|
||||
% check cache
|
||||
folder = create_folder_name( params );
|
||||
if exist( ['./' folder], 'dir' ) && exist( ['./' folder '/result.mat'], 'file' )
|
||||
% read cache
|
||||
disp( 'CACHE HIT' );
|
||||
result = load( [folder '/result.mat'], 'result' );
|
||||
result = result.result;
|
||||
else
|
||||
% start simulation in folder <folder>
|
||||
disp( ['starting simulation function ' simfun] );
|
||||
disp( [' simulation folder ' folder] );
|
||||
[simfun_folder,simfun] = fileparts(simfun);
|
||||
oldpath = path;
|
||||
addpath( simfun_folder );
|
||||
fhandle = str2func(simfun); % does not work for octave-3.2.4!
|
||||
path( oldpath );
|
||||
mkdir( folder );
|
||||
result = fhandle(folder,params);
|
||||
save( [folder '/result.mat'], 'result', '-mat' );
|
||||
end
|
||||
|
||||
% write results for asco
|
||||
fid = fopen( outputfile, 'wt' );
|
||||
fprintf( fid, '\nvalue= %e\n\n', result );
|
||||
fclose( fid );
|
||||
|
||||
% update best result
|
||||
best = [];
|
||||
best.result = result;
|
||||
best.params = params;
|
||||
if exist( [pwd '/best_result.mat'], 'file' )
|
||||
old = load( 'best_result.mat', 'best' );
|
||||
if old.best.result > best.result
|
||||
save( 'best_result.mat', 'best', '-mat' );
|
||||
end
|
||||
else
|
||||
save( 'best_result.mat', 'best', '-mat' );
|
||||
end
|
||||
|
||||
% restore old folder
|
||||
cd( olddir );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function folder = create_folder_name( params )
|
||||
params = orderfields( params );
|
||||
folder = 'opt';
|
||||
fnames = fieldnames(params);
|
||||
for n=1:numel(fnames)
|
||||
folder = [folder '_' fnames{n} '=' num2str(params.(fnames{n}))];
|
||||
end
|
Loading…
Reference in New Issue