Примеры
Все примеры на этой странице прогнаны на реальном проекте — дипольной антенне из комплекта примеров GAMMA — и приведены с фактическим результатом.
Открыть, посчитать, выгрузить, сохранить
Сценарий CalculateAndExport.gcp:
REM Без этих переменных сценарий работал бы с пустыми путями
Break IfVariableIsNotDefined GAMMA_PROJECT
Break IfVariableIsNotDefined GAMMA_EXPORT_DIR
REM
Directory Create "%GAMMA_EXPORT_DIR%"
Project Open "%GAMMA_PROJECT%"
Mode Set FEM
Solver Start
Solver RecalcSMatrix
CalculationResult Export SNP "%GAMMA_EXPORT_DIR%"
Project Save
Project Close
REM Журнал покажет, на какой строке сценарий остановился
CommandProcessorLog Export "%GAMMA_EXPORT_DIR%\scenario.log"
Exit
Запуск:
set GAMMA_PROJECT=D:\Work\Dipole.gma
set GAMMA_EXPORT_DIR=D:\Work\Export
Gamma.exe CalculateAndExport.gcp
if %errorlevel% neq 0 (
echo [ERROR] сценарий завершился с кодом %errorlevel%
exit /b 1
)
Результат: код возврата 0, в каталоге экспорта Dipole_1.s1p,
Dipole_2.s1p и scenario.log.
То же самое из Python
import os
import sys
import gammapy as gamma
def main(project, export_dir):
os.makedirs(export_dir, exist_ok=True)
with gamma.service.start() as app:
gamma.service.set_verbose_mode(app, False)
app.project_open(project)
app.mode_set('FEM')
app.solver_start()
app.solver_recalc_s_matrix()
app.calculation_result_export('SNP', export_dir)
app.project_save()
app.project_close()
print('готово, файлов: %d' % len(os.listdir(export_dir)))
main(sys.argv[1], sys.argv[2])
Проверять код возврата не нужно: неуспешная команда возбудит исключение, и скрипт завершится с ненулевым кодом.
Пакетный обход каталога
Запуск GAMMA стоит дороже, чем открытие проекта, поэтому весь пакет обрабатывается в одном экземпляре приложения.
import glob
import os
import sys
import gammapy as gamma
def run_one(app, project, export_root):
name = os.path.splitext(os.path.basename(project))[0]
export_dir = os.path.join(export_root, name)
os.makedirs(export_dir, exist_ok=True)
app.project_open(project)
try:
app.mode_set('FEM')
app.solver_start()
app.calculation_result_export('SNP', export_dir)
app.project_save()
finally:
# Незакрытый проект сломал бы следующую итерацию
app.project_close()
def main(source_dir, export_root):
# "~tmp<Имя>.gma" — файл восстановления рядом с проектом, он тоже
# попадает под маску *.gma. Считать его не нужно.
projects = sorted(p for p in glob.glob(os.path.join(source_dir, '*.gma'))
if not os.path.basename(p).startswith('~tmp'))
failed = []
with gamma.service.start() as app:
gamma.service.set_verbose_mode(app, False)
for i, project in enumerate(projects, 1):
print('[%d/%d] %s' % (i, len(projects),
os.path.basename(project)), flush=True)
try:
run_one(app, project, export_root)
except Exception as error:
print(' ОШИБКА:', error)
failed.append(os.path.basename(project))
print('%d из %d успешно' % (len(projects) - len(failed), len(projects)))
return 1 if failed else 0
sys.exit(main(sys.argv[1], sys.argv[2]))
Фактический прогон на двух проектах:
[1/2] Dipole.gma
ok, 236.6 s
[2/2] WaveguideTee.gma
ok, 32.5 s
2 of 2 succeeded
Разброс времени между двумя небольшими проектами — семикратный, и почти всё время сценария занимает сам расчёт: в замере это 271 секунда из 277. Планируя пакетный прогон, ориентируйтесь на самый тяжёлый проект, а не на среднее.
Перенос настроек решателя
Project Open "%GAMMA_PROJECT%"
REM Посмотреть параметры
FEMSolverSettings Get Solution.SweepType
FEMSolverSettings Get Refinement.MaxPasses
REM Изменить и вернуть к значению по умолчанию
FEMSolverSettings Set Refinement.MaxPasses 12
FEMSolverSettings Reset Refinement.MaxPasses
REM Выгрузить весь набор и загрузить обратно
FEMSolverSettings Export "%GAMMA_SETTINGS%"
FEMSolverSettings Import "%GAMMA_SETTINGS%"
Project Close
Exit
Формат файла определяется расширением: .ini, .json или .txt. Первые два
покрывают всё состояние настроек, включая параметры без имени в командном
процессоре; .txt — только те параметры, что адресуются командой.
Перенос горячих клавиш
REM Действия одного режима. Без открытого проекта режим называется явно
Shortcuts Get File.New Mode=FEM
Shortcuts Get All Mode=FEM
REM Назначить, проверить и сбросить к значению по умолчанию
Shortcuts Set File.Save Ctrl+Shift+S Mode=FEM
Shortcuts Reset File.Save Mode=FEM
REM Выгрузить весь набор режима и загрузить обратно
Shortcuts Export "%GAMMA_SHORTCUTS%" Mode=FEM
Shortcuts Import "%GAMMA_SHORTCUTS%" Mode=FEM
Exit
Действие адресуется своим objectName — File.New, Common.Edit.Rename — а
не подписью в меню: подпись меняется вместе с языком интерфейса, имя нет.
Полный список действий режима выдаёт Shortcuts Get All.
Команда работает с действиями одного режима — того же набора, что
показывает диалог «Настройка горячих клавиш». Режим берётся из открытого
проекта; когда проекта нет, его нужно назвать через Mode=, иначе команда
откажется работать, а не вернёт пустой список. Режим, не покрытый лицензией,
тоже отклоняется.
Формат файла определяется расширением: .xml, .txt или .json. Файл .xml
совместим с диалогом — выгруженное командой можно загрузить кнопкой «Импорт» и
наоборот.
Изменение записывается в реестр сразу, а не при выходе из приложения — чтобы скрипт не терял настройку, если процесс после него завершат принудительно.
Выгрузить журнал приложения
REM Журнал приложения - не журнал команд: это то, что пишут решатель,
REM построитель сетки и остальные подсистемы
Project Open "%GAMMA_PROJECT%"
REM Все записи, независимо от категории и уровня
Log Export All "%GAMMA_EXPORT_DIR%\application.log"
REM Только открытая вкладка журнала - то же, что делает кнопка окна
Log Export "%GAMMA_EXPORT_DIR%\application_page.log"
REM UTF-8, если журнал потом разбирается find/findstr
Log Export Encoding=UTF-8 All "%GAMMA_EXPORT_DIR%\application_utf8.log"
Log Clear
Project Close
Exit
Фактический прогон на дипольной антенне: код возврата 0, три файла —
| Файл | Размер | Записей |
|---|---|---|
application.log | 3 668 байт | 19: 13 в категории common, 6 в mesher |
application_page.log | 2 474 байта | 13, только common |
application_utf8.log | 1 871 байт | те же 19 |
Записи в журнале появляются уже от одного Project Open — расчёт для этого
не нужен: при открытии проекта журнал восстанавливается с диска. Разница
между первым и вторым файлом — это разница между двумя пунктами меню кнопки:
с флагом All выгружаются все категории, без него — только та вкладка, что
открыта.
Каждая строка файла — одна запись в формате JSONL, тот же формат, в котором
приложение пишет свои *.log рядом с проектом:
{"cat":"common","lvl":"stat","txt":"Hello World"}
По умолчанию файл пишется в UTF-16 — как и все остальные журналы приложения.
Encoding=UTF-8 нужен, если журнал потом разбирается однобайтовыми
средствами.
Log Clear очищает журнал целиком, как кнопка «Очистить» в окне. Экспорт
сразу после очистки даёт файл из одной метки порядка байт — 2 байта, ноль
записей.