Этот пример показывает, как сгенерировать код для алгоритма 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
MEX-функция моделирует 10 000 атомов приблизительно на 1 000 шагов итерации, учитывая пустой список атомов. Возвращаемое значение является состоянием всех атомов после того, как симуляция будет завершена.
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 = 1x10000 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 = 1x10000 struct array with fields:
x
y
vx
vy
Чтобы сгенерировать библиотеку C, создайте стандартный объект настройки для библиотек:
cfg = coder.config('lib');
Включите динамическое выделение памяти
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';
В MATLAB тип данных по умолчанию является двойным. Однако целые числа обычно используются в коде С, так передайте целочисленные значения int32
в качестве примера, чтобы представлять количество атомов и итераций.
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
При создании библиотеки код сгенерирован в папке codegen/lib/run_atoms/
. Код в этой папке сам содержавший. Чтобы взаимодействовать через интерфейс со скомпилированным кодом С, вам нужны только сгенерированные заголовочные файлы и файл библиотеки.
dir codegen/lib/run_atoms
. rt_nonfinite.c run_atoms_emxutil.h .. rt_nonfinite.h run_atoms_emxutil.o buildInfo.mat rt_nonfinite.o run_atoms_initialize.c codeInfo.mat rtw_proj.tmw run_atoms_initialize.h codedescriptor.dmr rtwtypes.h run_atoms_initialize.o examples run_atoms.a run_atoms_ref.rsp interface run_atoms.c run_atoms_rtw.mk rtGetInf.c run_atoms.h run_atoms_terminate.c rtGetInf.h run_atoms.o run_atoms_terminate.h rtGetInf.o run_atoms_emxAPI.c run_atoms_terminate.o rtGetNaN.c run_atoms_emxAPI.h run_atoms_types.h rtGetNaN.h run_atoms_emxAPI.o rtGetNaN.o run_atoms_emxutil.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
), а также пользовательский код С (run_atoms_main.c
), команда codegen
автоматически генерирует код С из кода MATLAB, затем вызывает компилятор C, чтобы связать этот сгенерированный код пользовательским кодом С (run_atoms_main.c
).
codegen run_atoms run_atoms_main.c -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
После того, как симуляция завершена, это производит файл 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);