Шаг 4. Серии и очереди расчётов

Один расчёт из Шаг 1. Первый скрипт — частный случай. Обычно интересно посмотреть, как результат меняется при варьировании параметра (или сразу нескольких).

ParameterSeries.Expand

Берёт базовую конфигурацию и словарь «какое поле → какие значения», возвращает массив независимых конфигураций:

baseCfg = CalculationConfig( ...
    'Representation', "EnergyBased", 'Material', "Aluminum", ...
    'Length_nm', 50, 'Temperature', 0.5, 'SelfConsistencySteps', 15);
baseCfg.Grid = GridConfig('zN', 40, 'eN', 200, 'eStart', -74, 'eEnd', 74);

varying = containers.Map();
varying('SpinMixingAngle') = [0, 0.05, 0.1];

cfgs = ParameterSeries.Expand(baseCfg, varying);   % 3 конфигурации

varyingcontainers.Map, а не обычная struct, потому что ключ может быть составным путём с точкой, например "Grid.zN" (struct так не умеет — точка в имени поля недопустима). Значение — вектор (или string-массив/cell-массив) значений для перебора.

Несколько параметров сразу

varying = containers.Map();
varying('SpinMixingAngle') = [0, 0.1];
varying('MisorientationAngle_Degrees') = [0, 45, 90];

cfgs = ParameterSeries.Expand(baseCfg, varying, "grid");   % 2*3 = 6

Число варьируемых параметров не ограничено — практическое ограничение только комбинаторное: в режиме "grid" (декартово произведение, по умолчанию) число конфигураций — произведение длин всех векторов.

Если декартово произведение не нужно, а нужен параллельный перебор (i-е значение первого параметра вместе с i-м значением второго) — режим "zip"; все векторы тогда должны быть одинаковой длины:

cfgsZip = ParameterSeries.Expand(baseCfg, varying, "zip");   % 2 конфигурации, не 6

Имя каждой конфигурации (cfg.TaskName) собирается автоматически из варьируемых значений: EnergyBased_Aluminum_50nm_SpinMixingAngle=0.1_MisorientationAngle_Degrees=45 — это же имя станет именем папки результата (Шаг 5. Сохранение и загрузка результатов).

Запуск серии

Два варианта, в зависимости от того, нужна ли persistent-очередь.

Просто прогнать всё и получить результаты в памяти:

results = CalculationRunner.RunMany(cfgs);
% results(i).Config, results(i).Calculation, results(i).Error

Одна упавшая конфигурация не останавливает остальные — ошибка попадает в results(i).Error, расчёт продолжается со следующей.

Через очередь (когда хочется явно видеть прогресс, сохранить очередь и продолжить в другой сессии MATLAB):

q = CalculationQueue();
q.AddMany(cfgs);
q.Save('queue.mat');     % можно закрыть MATLAB прямо сейчас

% ... позже, в новой сессии:
q2 = CalculationQueue.Load('queue.mat');
q2.RunAll();
q2.Summary();

CalculationQueue — единственный handle-класс в скрипточном слое (в отличие от конфигураций): это осознанно, очередь по своей природе общее изменяемое состояние. RunNext() выполняет только следующий pending-элемент — удобно для пошагового прогона.

И в CalculationRunner.RunMany, и в CalculationQueue после каждого запуска автоматически обновляется текстовый manifest.txt в папке серии (если задан SaveOptions — см. Шаг 5. Сохранение и загрузка результатов).

Дальше

Как результаты серии раскладываются по папкам на диске и как загрузить их обратно — Шаг 5. Сохранение и загрузка результатов.