В этом примере показано, как создать код для алгоритма MATLAB ®, который выполняет моделирование подпрыгивания «атомов» и возвращает результат после ряда итераций. Нет верхних границ по количеству атомов, которые принимает алгоритм, поэтому в этом примере используется преимущество динамического распределения памяти.
Предпосылки для этого примера отсутствуют.
run_atoms Функция run_atoms.m функция выполняет моделирование отскока атомов (также применяя гравитацию и потери энергии).
help run_atoms atoms = run_atoms(atoms,n)
atoms = run_atoms(atoms,n,iter)
Where 'atoms' the initial and final state of atoms (can be empty)
'n' is the number of atoms to simulate.
'iter' is the number of iterations for the simulation
(if omitted it is defaulted to 3000 iterations.)
Создание объекта конфигурации создания кода
cfg = coder.config; % Enable dynamic memory allocation for variable size matrices. cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';
Создайте структуру шаблона «Atom», чтобы предоставить компилятору необходимую информацию о типах входных параметров. Атом - это структура с четырьмя полями (x, y, vx, vy), задающими положение и скорость в декартовых координатах.
atom = struct('x', 0, 'y', 0, 'vx', 0, 'vy', 0);
Используйте команду codegen со следующими аргументами:
-args {coder.typeof(atom, [1 Inf]),0,0} указывает, что первый аргумент является вектором строк атомов, где число столбцов потенциально бесконечно. Второй и третий аргументы являются скалярными двойными значениями.
-config cfg включает динамическое выделение памяти, определяемое переменной рабочей области cfg
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),0,0} -config cfg -o run_atoms_mex
Code generation successful.
Функция MEX моделирует 10000 атомов приблизительно за 1000 итерационных шагов при наличии пустого списка атомов. Возвращаемое значение является состоянием всех атомов после завершения моделирования.
atoms = repmat(atom,1,0); atoms = run_atoms_mex(atoms,10000,1000)
Iteration: 50 Iteration: 100 Iteration: 150 Iteration: 200 Iteration: 250 Iteration: 300 Iteration: 350 Iteration: 400 Iteration: 450 Iteration: 500 Iteration: 550 Iteration: 600 Iteration: 650 Iteration: 700 Iteration: 750 Iteration: 800 Iteration: 850 Iteration: 900 Iteration: 950 Iteration: 1000 Completed iterations: 1000
atoms=1×10000 struct array with fields:
x
y
vx
vy
Продолжение моделирования с помощью еще 500 шагов итерации
atoms = run_atoms_mex(atoms,10000,500)
Iteration: 50 Iteration: 100 Iteration: 150 Iteration: 200 Iteration: 250 Iteration: 300 Iteration: 350 Iteration: 400 Iteration: 450 Iteration: 500 Completed iterations: 500
atoms=1×10000 struct array with fields:
x
y
vx
vy
Чтобы создать библиотеку C, создайте стандартный объект конфигурации для библиотек:
cfg = coder.config('lib');Включить динамическое выделение памяти
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';В MATLAB тип данных по умолчанию - двойной. Однако в коде C обычно используются целые числа, поэтому проходите int32 целочисленные значения для представления числа атомов и итераций.
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
Code generation successful.
При создании библиотеки код генерируется в папке codegen/lib/run_atoms/. Код в этой папке является автономным. Для взаимодействия с скомпилированным кодом C необходимы только созданные файлы заголовков и файл библиотеки.
dir codegen/lib/run_atoms. rtGetNaN.h run_atoms_emxAPI.h .. rtGetNaN.o run_atoms_emxAPI.o .gitignore rt_nonfinite.c run_atoms_emxutil.c _clang-format rt_nonfinite.h run_atoms_emxutil.h buildInfo.mat rt_nonfinite.o run_atoms_emxutil.o codeInfo.mat rtw_proj.tmw run_atoms_initialize.c codedescriptor.dmr rtwtypes.h run_atoms_initialize.h compileInfo.mat run_atoms.a run_atoms_initialize.o defines.txt run_atoms.c run_atoms_rtw.mk examples run_atoms.h run_atoms_terminate.c interface run_atoms.o run_atoms_terminate.h rtGetInf.c run_atoms_data.c run_atoms_terminate.o rtGetInf.h run_atoms_data.h run_atoms_types.h rtGetInf.o run_atoms_data.o rtGetNaN.c run_atoms_emxAPI.c
Обычно основной функцией является зависящий от платформы код, который выполняет рендеринг или какую-либо другую обработку. В этом примере чистая функция ANSI-C создает файл run_atoms_state.m который (при выполнении) содержит конечное состояние моделирования атома.
type run_atoms_main.c/* Include standard C libraries */
#include <stdio.h>
/* The interface to the main function we compiled. */
#include "codegen/exe/run_atoms/run_atoms.h"
/* The interface to EMX data structures. */
#include "codegen/exe/run_atoms/run_atoms_emxAPI.h"
int main(int argc, char **argv)
{
FILE *fid;
int i;
emxArray_Atom *atoms;
/* Main arguments unused */
(void) argc;
(void) argv;
/* Initially create an empty row vector of atoms (1 row, 0 columns) */
atoms = emxCreate_Atom(1, 0);
/* Call the function to simulate 10000 atoms in 1000 iteration steps */
run_atoms(atoms, 10000, 1000);
/* Call the function again to do another 500 iteration steps */
run_atoms(atoms, 10000, 500);
/* Print the result to a file */
fid = fopen("atoms_state.txt", "w");
for (i = 0; i < atoms->size[1]; i++) {
fprintf(fid, "%f %f %f %f\n",
atoms->data[i].x, atoms->data[i].y, atoms->data[i].vx, atoms->data[i].vy);
}
/* Close the file */
fclose(fid);
/* Free memory */
emxDestroyArray_Atom(atoms);
return(0);
}
cfg = coder.config('exe'); cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';
Необходимо передать функцию (run_atoms.m), а также пользовательский код C (run_atoms_main.c) codegen команда автоматически генерирует код C из кода MATLAB, затем вызывает компилятор C для объединения этого сгенерированного кода с пользовательским кодом C (run_atoms_main.c).
codegen run_atoms run_atoms_main.c -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
Code generation successful.
После завершения моделирования создается файл atoms_state.txt. Файл TXT 10000x4 матрица, где каждый ряд - положение и скорость атома (x, y, vx, vy) представление текущего состояния целой системы.
system(['.' filesep 'run_atoms']);
Запуск созданного исполняемого файла atoms_state.txt. Теперь заново создайте массив структуры из сохраненной матрицы:
load atoms_state.txt -ascii clear atoms for i = 1:size(atoms_state,1) atoms(1,i).x = atoms_state(i,1); atoms(1,i).y = atoms_state(i,2); atoms(1,i).vx = atoms_state(i,3); atoms(1,i).vy = atoms_state(i,4); end
Звонить run_atoms_mex с нулевыми итерациями только для визуализации.
run_atoms_mex(atoms, 10000, 0);
