COMSOLd: a daemon for controlling COMSOL jobs

Flow chart of COMSOLd

COMSOLd is a server I have written in MATLAB for the scheduling and processing of COMSOL jobs. It allows you to control COMSOL jobs from MATLAB and it automatically converts the COMSOL output into MATLAB data structures for ease of processing. Multiple instances of COMSOLd can be run at once without conflicts arising between them. We are using it to schedule jobs from multiple users. This software package is available at https://github.com/mettw/COMSOLd.

Overview

The default programme flow for a job is shown in the figure. A configuration script written by the user defines all of the settings of the job. By placing this script in a queue directory a queue of jobs to run is established with COMSOLd running them in order of age. If the queue is long and you want a new job to run first then there is a priority queue directory that will cause COMSOLd to run jobs from that queue first.

Parameter sweeps are executed by COMSOLd rather than COMSOL itself so that data can be exported after each step of the sweep, which prevents data loss if the job ends before the sweep has completed (Due to a crash etc). It also allows one to end a long sweep for whatever reason and then restart it where it left off. The programme flow shown in the figure can be modified by the individual job and complete control over the flow of COMSOLd taken by the user so that complex programming, such as optimisation routines, can be implemented.

At the end of a sweep the data from the job is processed into MATLAB data files that can easily be accessed with the COMSOLdResults object. You create a results object with

> results = COMSOLdResults("some_job_script");

A sweep is made up of a number of different studies, and a non-sweep
job is treated like a sweep of just one study. You can see a list of
all studies in a sweep by looking at the table

> results.showSweep()

which is null for a non-sweep study. At any given time the
results object is only presenting the data from a single study within
the sweep. You can change which study is being presented with the
following methods:


results.setStudy(study_num) % Move to study number study_num in the
                            % sequence listed in results.sweep_data
results.firstStudy()
results.lastStudy()
results.nextStudy()
results.previousStudy()

To avoid generating errors by trying to access a study that does not
exist you should make use of the following methods

results.getStudyNum() % The number of the current study
results.numStudies() % The maximum value that can be passed to
% setStudy()
results.moreStudies() % Are there any more studies after the
% current one? (Boolean)
results.earlierStudies() % Are there any studies before the current
% one? (Boolean)

In general though, you will want to step through the studies one at a
time, which you can do with the convenience method

while results.stepThroughStudies()
% some code…
end

This loop will start at the first study and then step through all of
them one at a time.

Output from any derived values nodes in your MPH file can be
accessed from the ‘derived_values’ property. For example, if you output a derived values node to the filemy_parameters.txt’ and it
contained the value ‘height’, then all of the values for ‘height’
(one for each frequency in the study) can be accessed as an array
with:

results.derived_values.my_parameters.height

Cut planes and farfields (The Fourier transform of a COMSOL cut plane) have their own objects for handling the data
and these can be generated with:

cut_plane = results.getCutPlane(study, direction)

where study is either “sfg” or “signal” and direction is either “up”
or “down”. The code here is not perfectly general, but is designed
for how I happen to output the cut planes. `cut_plane’ is a
COMSOLdCutPlane object that is similar to COMSOLdResults. Likewise,

farfield = results.getFarfield(study, direction)

produces a COMSOLdFarfield object. Note that because of the large size of these files and the long time to take the Fourier transform of a cut plane, the MATLAB data files for a COMSOLdCutPlane and COMSOLdFarfield are not created until the user creates the COMSOLdCutPlane or COMSOLdFarfield object.

With a large sweep you will only want to process a subset of the data
at a time and you can do this by creating a new COMSOLdResults object
from the current one with

sub_results = results.getSubResults(parameter_name, parameter_value)

For example, we might have a sweep of

> results.showSweep()

   theta       phi_pol     DerivedValues     CutPlanes       Farfield  
 _________    _________    _____________    ___________    ____________

 "0[deg]"     "0[deg]"     {1x1 struct}     {4x7 table}    {1x1 struct}
 "0[deg]"     "90[deg]"    {1x1 struct}     {4x7 table}    {1x1 struct}
 "8[deg]"     "0[deg]"     {1x1 struct}     {4x7 table}    {1x1 struct}
 "8[deg]"     "90[deg]"    {1x1 struct}     {4x7 table}    {1x1 struct}

where phi_pol refers to the polarisation of the input beam. We
only want to process one polarisation at a time, which we can do by
using the method

> results_H = results.getSubResults('phi_pol', '0[deg]');

which is a new COMSOLdResults object which only contains the studies
with phi_pol equal to '0[deg]'.

> results_H.showSweep()

   theta      DerivedValues     CutPlanes       Farfield  
 _________    _____________    ___________    ____________

 "0[deg]"     {1x1 struct}     {4x7 table}    {1x1 struct}
 "8[deg]"     {1x1 struct}     {4x7 table}    {1x1 struct}