Библиотека вспомогательных утилит ivutils
это набор утилит C++ для создания численных приложений. ivutils использовались при написании программ EMTL (electromagnetic modeling) и Microvolt (semiconductor device modeling)
Для использования ivutils, нужно их скачать и скомпилировать с вашим кодом: ivutils.zip
ivutils включает следующие утилиты:
файлы h hpp cpp | описание |
---|---|
vector_3 basis_3 | n-ые вектора и линейные преобразования над ними |
vector_set | упаковщики последовательностей векторов |
contour | контура |
plane_3 region_2 region_3 | 2D и 3D геометрические тела |
gnudump | рисование геометрических тел в gnuplot и VTK |
grid | однородная и неоднородная сетки для хранения и интерполяции данных |
linsolv | интерфейс для решения системы линейных уравнений с помощью LAPACK и PARDISO |
refobj pencil | умные указатели для контроля над памятью, выделяемой под динамические объекты |
math_utils | полезные математические функции |
utiltl | полезные итераторы, модификаторы, и т. д. |
seqpack | упаковщики данных |
logger | интерфейс для хранения данных по их символическим именам (с расширенной функциональностью чем у map) |
logexc | логгеры для записи выходных сообщений во время работы программы и обработки исключений |
loggerio detector | детекторы для записи данных в двоичные или текстовые файлы во время расчета |
component | конфигурационные настройки таймеры для измерения машинного времени, затраченного на выбранные функции компоненты для создания численных приложений |
string_utils | полезные функции для работы со строками |
alg_parser | парсеры математических выражений |
read_ini | парсеры простых ини-файлов |
ifmpi implmpi | интерфейс для работы с MPI |
qsub.py | Скрипт для запуска задач на произвольном суперкомпьютере |
Makefile.arch Makefile.target | Makefile для компиляции на произвольной архитектуре |
Ниже мы прилагаем некоторые примеры использования ivutils.
Парсер математических выражений
Интерфейс для разбора математических выражений. Он позволяет обрабатывать строки, содержащие арифметические операции, скобки и функции, и вычислять значение заданного выражения.
Например
#include "alg_parser.h" int main(){ AlgebraicParser AP; double val; // here calculated value will be recorded int res=AP("sqrt(5+cos(3*pi))", &val); // if res=1 expression is correct res=AP("1e-5", &val); // if res=1 expression is correct return 0; }
Код:
Пример работы:
Геометрические тела
Ниже мы вкратце перечислим классы, отвечающие некоторым используемым геометрическим телам. Со всем списком можно ознакомиться в справке для пользователя.
Класс вектор Vector_3. В его конструкторе задаются три координаты x, y и z. Вектора можно складывать, вычитать, умножать на число, умножать скалярно (с помощью оператора *) и векторно (с помощью оператора %). Например,
Vector_3 v1(1,0,0),v2(0,1,0); Vector_3 v0=a%b-Vector_3(0,0,1); // v0 равен Vector_3(0,0,0)
Если в конструкторе вектора задается меньше трех координат, то незаданные координаты полагаются равными последней заданной. Например, Vector_3(1)=Vector_3(1,1,1). Также Vector_3()=Vector_3(0,0,0), так как первая координата по умолчанию равна нулю.
Векторам с целочисленными координатами отвечает класс iVector_3.
Тела, описывающие геометрические классы, являются наследниками класса Region_3. Класс Region_3 (а также его наследники) имеет следующую фунциональность:
- он может проверять, находится ли произвольная точка внутри или снаружи
- он может находить ближайшую точку на поверхности от выбранного положения
- он может находить пересечение с произвольной прямой
- он может находить сечение с произвольным плоским контуром
Ниже мы приводии примеры функций, которые могут использоваться для создания некоторых распространенных объектов.
Region_3 *GetHalfSpace(const Vector_3 &n, const Vector_3 &pos);возвращает полупространство, n - нормаль к граничной плоскости, pos - произвольная точка на этой плоскости. Например,
Region_3 *reg = GetHalfSpace(Vector_3(0,0,1), Vector_3(0,0,0));возвращает полупространству соответсвующее положительной части оси z.
Region_3 *GetPlate(const Vector_3 &n, const Vector_3 &pos, vec_type width);возвращает бесконечную пластинку (пространство между двумя параллельным плоскостями), n - нормаль к плоскостям, pos - точка на некоторой плоскости, width - расстояние между этой плоскостью и соседней плоскостью.
Region_3 *getBox(const &Vector_3 a, const &Vector_3 b);возвращает параллелепипед с ребрами параллельными координатным осям. a и b - противоположные вершины параллелепипеда.
Region_3 *GetSphere(vec_type R, const &Vector_3 center);возвращает сферу радиуса R и центром center.
Region_3 *GetCylinder(const Vector_3 &origin, Vector_3 n, vec_type R, valtype h);возвращает цилиндр, origin - точка на оси цилиндра, n - направление оси, R - радиус, h - высота (если h=0, цилиндр считается бесконечным).
Region *GetCone(const Vector_3 &origin, Vector_3 n, vec_type R, vec_type h);возвращает конус, все параметры имеют такое же значение как и для GetCylinder.
Также имеются многогранник, цилиндр и пирамида с основанием в виде произвольного многоугольника. Тела можно растягивать, поворачивать, брать их пересечения и объединения. Гладкие тела, например конус, можно конструировать как многогранники с большим количеством граней. Все это задокументировано в region.h.
Скрипт для запуска задач на произвольном суперкомпьютере
Для расчета больших задач используются суперкомьютеры.
Запуск задач на них предполагает:
- создание сценария, в котором вы указываете имя исполняемого файла, требуемое количество процессоров, время исполнения и т. д.
- запуск этого сценария, что приводит к постановке задачи очередь и последущему ее выполнению.
Различные суперкомпьютеры используют различный синтаксис для создания и запуска таких сценариев. Ручное создание таких сценариев под каждую задачу весьма времезатратно.
Для упрощения этой работы, мы создали специальный скрипт qsub.py на языке python. Он позволяет запускать задачи на произвольном суперкомпьютере, и является переносимым с одного суперкомпьютера на другой. Для определения, какой суперкомпьютер используется в данный момент, скрипт использует команду UNIX 'hostname'.
Для использования скрипта, нужно написать инструкцию, как создавать сценарий и запускать его на вашем суперкомпьютере в функции make_script. Это уже сделано для некоторых суперкомпьютеров: SciNet (Канада), суперкомпьютер Курчатовского Института, МВС-100K (МСЦ РАН), СКИФ МГУ и т. д.
После этого вы можете использовать функцию qsub со следующими аргументами:
qsub(workdir,worksubdir,prog,args,time,np,ppn=0,task='',fname='',act=1,skip='')
Эта функция создает директорию workdir/worksubdir, копирует туда исполняемый файл prog, создает там сценарий SCRIPT.sh для запуска исполняемого файла с аргументами командной строки args на np процессорах на количество секунд time (на некоторых суперкомпьютерах время можно не указывать).
Необязательные параметры функции qsub:
ppn - количество процессоров, используемое на узле (значение по умолчанию ppn=0 приводит к тому, что по возможности используется полное число процессоров на узле),
task - имя задачи,
fname - имя файла или список файлов, которые будут копироваться в workdir/worksubdir,
act - 1 (поставить задачу в очередь) или 0 (не делать этого). В любом случае команда для запуска скрипта будет записана в файл QSUB.sh,
skip - если файл с этим именем будет найден в workdir/worksubdir, функция qsub не выполнится.
Например, допустим ваш исполняемый файл 'a.out' находится в текущей папке '.'. Скопируем в эту папку скрипт 'qsub.py' и создадим в ней 'script.py':
#! /usr/bin/python from qsub import * qsub('.','test','a.out','',60*60,8)
Сделаем его исполняемым
chmod u+x script.py
и выполним его
./script.py
В результате в текущей папке будет создана поддиректория test, куда будет перенесен исполняемый файл a.out, а также создан сценарий SCRIPT.sh для запуска этого файла на 8 процессорах на час и файл QSUB.sh, для запуска этого сценария.
Как правило, на разных суперкомпьютерах вы имеете различные пути к домашней директории, где вы компилируете ваш проект, и к рабочей директории, где вы исполняете задачу и сохраняете ее результат. Вы можете прописать такие пути для каждого суперкомпьютера и пользователя (который определяется функцией UNIX 'whoami') в функции getdirs.
После этого вы можете пользоваться функцией qsub_appl:
qsub_appl(workdir,worksubdir,prog,args,time,np,ppn=0,task='',fname='',act=1,skip='')
Аргументы этой функции такие же, как и у функции qsub. Единственное отличие в том, что директория workdir/worksubdir будет создаваться в вашей рабочей директории, а исполняемый файл prog и вспомогательный файл fname будут искаться в вашей домашней директории.