Persistent Parameter Scan

For complex setups one often wants to run different (sometimes multi-dimensional) parameter scans. In this case it is worthwhile to store the results of parameter scans such that they don’t have to be recalculated in future parameter scans. To manage computational results one can make use of the class jcmwave_resultbag.

We revisit the example of a parallel parameter scan (Parallel Parameter Scan). As before we start by going into daemon mode:

jcmwave_daemon_shutdown();
jcmwave_daemon_add_workstation('Hostname', 'localhost', ...
                            'Multiplicity', 2, ...
                            'NThreads', 1);

The project files in the current example do not only depend on the rod radius but also on the two additional parameters finite_element_degree (used in mie2D.jcmpt) and maximum_sidelength (used in layout.jcmt). In general, not all parameters are varied during a parameter scan. Therefore, we define a set of default parameters:

default_keys.finite_element_degree = 3;
default_keys.maximum_sidelength = 0.1;
default_keys.radius = 0.3;

Next, we initialize a resultbag by calling jcmwave_resultbag with a filepath as parameter. The data of the resultbag will be stored to this file. If it already exists all data from this file is loaded into the resultbag.

resultbag = jcmwave_resultbag('resultbag.mat');

Warning

If you use more than one resultbag make sure that every resultbag stores its results to a different file.

With the help of Matlab’s ndgrid-function we can define a variable keyset that holds a two-dimensional parameter scan over the parameters maximum_sidelength and radius:

sidelengths = 0.5 : -0.1 : 0.1;
radii = 0.3 : 0.005 : 0.5;

[scan1,scan2] = ndgrid(sidelengths, radii);
keyset = repmat(default_keys,size(scan1)); %fill keyset with default keys

for ii = 1 : numel(keyset)
  keyset(ii).maximum_sidelength = scan1(ii);
  keyset(ii).radius = scan2(ii);
end

The structure can be easily extended to n-dimensional parameter scans by introducing additional scan grids scan3, scan4, etc.

Next, we run in parallel all the computations that are defined by the keyset:

job_ids = [];
for ii = 1 : numel(keyset)
   keys = keyset(ii);
   job_ids(end+1) = jcmwave_solve('mie2D.jcmp', keys, resultbag, 'temporary', 'yes');
end

jcmwave_daemon_wait(job_ids, resultbag);

By calling the solver command with the resultbag as the third parameter jcmwave_solve checks if the computation for the project files (mie2D.jcmpt, layout.jcmt, materials.jcm, sources.jcm) and the current keys is already contained in the resultbag. If this is the case, the computation is automatically skipped. Otherwise the new result is added to the resultbag by the function jcmwave_daemon_wait to which the resultbag is passed as the second parameter. Whenever a result is added it is also stored to the disk.

Note

Sometimes a computation does not depend on all parameters in the keys-structure (e. g. a waveguide-mode computation generally depends on fewer parameters than a subsequent scattering computation that uses a waveguide mode as light source). We can account for this by calling jcmwave_resultbag with a second parameter that defines the fieldname of all relevant parameters. For example by initializing the resultbag as

resultbag = jcmwave_resultbag('resultbag.mat',{'finite_element_degree', 'radius'});

a change of the parameter maximum_sidelength would not trigger a new computation.

For given keys the results and corresponding logs of a computation can be accessed by calling result = resultbag.get_result(keys); and log = resultbag.get_log(keys); respectively. A plot of the scattering cross section against the rod radius for different maximum sidelengths can be produced in the following way (see Figure “Scattering Cross Section”):

scattering_cross_section_scan = zeros(length(sidelengths),length(radii));
for ii = 1 : numel(keyset)
   keys = keyset(ii);
   result = resultbag.get_result(keys);
   scs = real(result{2}.ElectromagneticFieldEnergyFlux{1});
   scattering_cross_section_scan(ii) = scs;
end

plot(radii, scattering_cross_section_scan, '-+', 'LineWidth', 2);
xlabel('radius [\mu m]', 'FontSize', 14);
ylabel('integral scattering cross section', 'FontSize', 14);
legend(num2str(sidelengths','side length %.1f'));
set(gca, 'FontSize', 14);
_images/scatt_scan1.png

Scattering Cross Section

Computed scattering cross section versus rod radius for different maximum sidelengths.