exponenta event banner

Использование динамического распределения памяти для моделирования атомов

В этом примере показано, как создать код для алгоритма 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);

Создание функции MEX для тестирования

Используйте команду 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

Функция 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

Снова запустить функцию MEX

Продолжение моделирования с помощью еще 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

Чтобы создать библиотеку 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      

Запись основной функции 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);

Figure MATLAB Coder Atoms contains an axes. The axes contains an object of type image.