**PRADIS** **Написание плагин-объектов на языке PYTHON** **Программный комплекс для автоматизации моделирования нестационарных процессов в механических системах и системах иной физической природы** **Версия 4.3** Введение. ========= В этом документе говориться о правилах написания плагин объектов (моделей и првп) на языке Питон. О том, как их потом подключать к системному каталогу PRADIS, говориться в документе "Использование утилиты PARM". В нём так же упоминается, что непосредственному коду на питоне должны предшествовать некоторые комментарии, но здесь о них речь не пойдёт. Структура кода. =============== Первая строка должна быть следующего вида: from pradis.ppl.model import \* Если Вы пишете првп, то "model" нужно заменить на "ovp". Далее должен быть объявлен класс. Его название и будет именем Вашего объекта. Этот класс должен наследоваться от класса *model* (если Вы пишете модель) или *ovp* (если Вы пишете првп). Например: class MyOVP (ovp): Далее должен быть переопределён метод *Execute*. Он имеет входные параметры. Для моделей и првп они разные. Определение метода для модели должно выглядеть так: def Execute(COMMON, I, Y, X, V, A, PAR, NEW, OLD, WRK): А для ПРВП так: def Execute(COMMON, XOUT, PAR, WRK, DOF): Далее Вы пишете сам код, который реализует логику работы Вашего объекта. Тут пользователь имеет полную свободу пользоваться всеми средствами языка Питон. Выход из метода *Execute* должен быть строго определённым. Для моделей он выглядит так: res = return_result(COMMON, I, Y, X, V, A, NEW, OLD, WRK) return res Для ПРВП так: res = return_result(COMMON, XOUT, WRK) return res Детали кода. ============ Эта секция посвящена объяснению некоторых деталей написания кода, правил и возможностей. Параметры метода Execute. ------------------------- Здесь мы дадим краткое пояснение параметрам метода *Execute*. Модели. ~~~~~~~ Объявление метода для моделей выглядит так: def Execute(COMMON, I, Y, X, V, A, PAR, NEW, OLD, WRK): Здесь параметры имеют следующие значения: - **COMMON**: структура, содержащая значения непоименованной комон-области фортрана. - **I**: вектор сил (моментов) для элемента. - **Y**: якобиан модели элемента. - **X**: вектор перемещений узлов размерности EXT+ENT. Не используется при ADR=2, ADR=3. - **V**: вектор скоростей узлов размерности EXT+ENT. Не используется при ADR=3. - **A**: вектор ускорений узлов размерности EXT+ENT. - **PAR**: массив параметров модели. - **NEW**: вектор "нового состояния" модели. - **OLD**: вектор "старого состояния" модели. - **WRK**: рабочий массив для модели элемента. 1. .. rubric:: ПРВП. :name: првп. Объявление метода для ПРВП выглядит так: def Execute(COMMON, XOUT, PAR, WRK, DOF): Здесь параметры имеют следующие значения: - **COMMON**: структура, содержащая значения непоименованной комон-области фортрана. - **XOUT**: рассчитываемая выходная переменная или вектор рассчитываемых выходных переменных. - **PAR**: массив параметров ПРВП. - **WRK**: рабочий массив для ПРВП. - **DOF**: массив со значениями степеней свобод. Функции библиотеки S000J. ------------------------- При написании плагин объектов на питоне пользователю доступны функции библиотеки S000J, которые часто используются, например, в моделях на фортране. Все функции, которые были доступны на фортране, теперь доступны из питона. В этом разделе мы подробно расскажем, как ими пользоваться. Прежде всего надо подключить необходимую библиотеку к Вашему питон-файлу: from s000j import \* После этого создать объект соответствующего класса: sj = S000J() Теперь Вам будут доступны методы этого класса, которые называются как раз по названиям нужных функций (S0001, S0002, ...). И тут есть один важный момент, на который стоит обратить внимание. Он связан с передачей параметров в методы и получением результатов из них. В фортране в функции передавался набор переменных, одни из которых служили передачи данных в функцию, а другие из неё. Вызов этих функций из питона отличается тем, что выходные параметры и массивы в них нужно передавать в виде списков, предварительно занесенных в массивы специально разработанными для этого функциями. Приведём пример. Вот одна из таких функций на фортране: C Программа выдает значение функции и ее производной C при заданном значении аргумента. C C Дата создания программы 03/10/95 08:42am C Дата последней корректировки 09/14/95 11:51am C C X - заданное значение аргумента C F - значение функции при заданном значении арумента C DFDX - значение производной функции при заданном C значении аргумента C TABL - таблица значений функции (попарно - значение C аргумента/ значение функции) C N - длина таблицы. C NPNT - массив номеров точек, между которыми C находится текущая точка C Если значение аргумента меньше минимально определенного C или больше максимально определенного в таблице, то C значение функции вычисляется экстраполяцией. C SUBROUTINE S0008 (F, DFDX, X, TABL, N, NPNT ) C REAL \* 8 X, F, DFDX, TABL (1) INTEGER \* 4 N, NPOINT, J, NPNT (1) Ее вызов из модели на Питоне будет выглядеть следующим образом: F_a = CreateDoubleArrayFromList([0.]) DFDX_a = CreateDoubleArrayFromList([0.]) l = [] for i in range(REZPAR+1,len(PAR)): l.append(PAR[i]) TABL_a = CreateDoubleArrayFromList(l) NPNT_a = CreateIntArrayFromList([0,0]) sj.S0008(F_a, DFDX_a, DX, TABL_a, NPOINT, NPNT_a) l = CreateListFromDoubleArray(F_a, 1) F = l[0] l = CreateListFromDoubleArray(DFDX_a, 1) DFDX = l[0] NPNT = CreateListFromIntArray(NPNT_a, 2) DeleteArray(F_a) DeleteArray(DFDX_a) DeleteArray(TABL_a) DeleteArray(NPNT_a) Сдесь F_a и DFDX_a будут массивами, содержащими по одной выходной переменной. TABL_a будет содержать входной массив, сформированный из списка PAR. NPNT_a будет выходной массив состоящий из двух целых переменных. DX и NPOINT являются простыми входными параметрами и следовательно не нуждаются в каких либо преобразованиях. Далее идет вызов функции S0008: sj.S0008(F_a, DFDX_a, DX, TABL_a, NPOINT, NPNT_a) После этого, выходные параметры и массивы надо снова преобразовать в питоновский формат. Например из массива F_a мы сначала создаем список используя функцию CreateListFromDoubleArray: l = CreateListFromDoubleArray(F_a, 1) А затем берем первый элемент этого списка, что бы получить значение рассчитанной переменой F: F = l[0] Так же точно мы поступаем с переменной DXDF: l = CreateListFromDoubleArray(DFDX_a, 1) DFDX = l[0] А массив целочисленных выходных значений NPNT_a преобразовываем в список NPNT: NPNT = CreateListFromIntArray(NPNT_a, 2) Следует обратить внимание, что для преобразований реальных и целых массивов используются различные функции. Для реальных используются функции: CreateDoubleArrayFromList CreateListFromDoubleArray А для целых используются функции: CreateIntArrayFromList CreateListFromIntArray В конце всего разработчик модели обязательно должен освободить память, отведенную под массивы функцией DeleteArray: DeleteArray(F_a) DeleteArray(DFDX_a) DeleteArray(TABL_a) DeleteArray(NPNT_a) Вывод ошибок моделей. --------------------- При написании плагин моделей на питоне пользователь может использовать доступный набор шаблонов для сообщений об ошибках. Полный список шаблонов можно увидеть в документе "Доступные ошибки моделей". Здесь мы расскажем, как пользоваться доступными шаблонами. Допустим, Вы захотели вывести ошибку, используя шаблон 1003: 1003 08 E (M 004)(/T4,'Некорректное значение параметра:',/,T8,'параметр ',F6.0,' должен быть >= ',G11.5,/,T8,'параметр ',F6.0,' = ',G11.5) Как видите, этот шаблон требует 4 числа: 2 целых и 2 действительных (встречающиеся F6.0 - это целые числа, G11.5 - действительные). Если задать эти числа значениями 1, 2.2, 1, 1.1, то на экране это будет выглядеть так: Некорректное значение параметра: параметр 1. должен быть >= 2.2000 параметр 1. = 1.1000 Чтобы использовать шаблон, в питон-файле Вашей модели нужно сделать следующее. Подключить необходимые библиотеки: from PradisLog import \* from array import \* Библиотека *PradisLog* поставляется с комплексом PRADIS, а *array* является стандартной питоновской библиотекой. Далее нужно создать объект нужного класса: pl = PradisLog() Теперь в том месте, где Вам нужно вывести ошибку, надо написать следующее: a = array ('d', [1, 2.2, 1, 1.1]) pl.perr (1003, 4, a.buffer_info()[0]) При выполнении этих строк на экране появится именно то, что указывалось выше. Первая строка создаёт массив действительных чисел, который заполняется теми числами, которые Вы хотите видеть в шаблоне при выводе сообщения. Количество этих чисел должно строго совпадать с количеством требуемых в шаблоне. Вторая строка использует метод *perr* класса *PradisLog*. В его параметрах следует указывать номер шаблона, количество чисел в шаблоне и адрес начала массива параметров. В примере мы назвали переменные "a" и "pl", но пользователь, конечно, может называть их по-своему. Примеры. ======== Здесь приведём пример питон модели. Это уже имеющаяся в библиотеке комплекса модель MD. Вот как она могла бы выглядеть на питоне: **# Библиотека нужная для написания модели** from pradis.ppl.model import \* **# Библиотеки для вывода ошибок** from PradisLog import \* from array import \* **# Библиотека для использования функций S000J** from s000j import \* **# Объявляем класс MD и указываем, что это модель** class MD (model): **# Переопределяем метод Execute (обязательно)** def Execute(COMMON, I, Y, X, V, A, PAR, NEW, OLD, WRK): **# Далее пишем суть модели** **# Первый проход** if COMMON.NEWINT == 1: **# Создаём объект для использования функций S000J** sj = S000J() **# Используем нужную функцию** d = sj.S0005 (0.1, 0.2, 0.3, 0.4, 0.5, 1) print d **# Создаём объект для вывода ошибок** pl = PradisLog() ERR = 0 if PAR[1] < 0.: ERR = 1 if COMMON.SYSPRN > 0.: **# Выводим ошибку по шаблону 1003** a = array ('d', [1, 0, 1, PAR[1]]) pl.perr (1003, 4, a.buffer_info()[0]) if PAR[2] < 0.: ERR = 1 if COMMON.SYSPRN > 0.: **# Выводим ошибку по шаблону 1003** a = array ('d', [2, 0, 2, PAR[2]]) pl.perr (1003, 4, a.buffer_info()[0]) if ERR == 1: if COMMON.CODE < 100.: COMMON.CODE = 100. **# Выходим из модели** res = return_result(COMMON, I, Y, X, V, A, NEW, OLD, WRK) return res I[1] = A[1] \* PAR[1] I[2] = A[2] \* PAR[1] I[3] = A[3] \* PAR[2] Y[1] = PAR[1] Y[2] = 0. Y[3] = 0. Y[4] = 0. Y[5] = PAR[1] Y[6] = 0. Y[7] = 0. Y[8] = 0. Y[9] = PAR[2] **# Выходим из модели** res = return_result(COMMON, I, Y, X, V, A, NEW, OLD, WRK) return res Особенности программирования моделей и ПРВП на Питоне. ====================================================== Необходимо обратить внимание на то, что тип переменных в Питоне определяется при их инициализации. Поэтому если вы хотите работать с реальной переменной, а присвоите ей целое значение, например: R = 2 То R у вас будет целой, а не реальной переменной. Для правильной работы, задавая реальную переменную ее надо обязательно инициализировать реальной константой, т.е. константой, содержащей в себе десятичную точку, или другой реальной переменной. Например: R = 2. Эти моменты очень важно учитывать при формировании списков выходных значений. Так как в моделях все входные параметры передаются в виде списков реальных чисел, то и возвращаться из моделей должны списки реальных чисел. Поскольку Питон позволяет в один и тот же список заносить элементы разных типов, то разработчик по ошибке может занести в выходной список целочисленную константу или переменную, что неминумо приведет к ошибке.