-
-
Notifications
You must be signed in to change notification settings - Fork 391
[MATLAB] Create MLTBX toolbox file that can be published on File Exchange #1882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a45584a
eb3d6ef
0dd3159
f14f9aa
ee36386
8a9e3c8
6ec1f54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,10 +66,31 @@ | |
echo "LD_PRELOAD=$LIB_STDCXX:$LIB_OPENBLAS:$LIB_LAPACK" >> $GITHUB_ENV | ||
- name: Set up MATLAB | ||
uses: matlab-actions/setup-matlab@718d4320188c73c86eb94ce76b553cbf89778487 # v2.5.0 | ||
- name: Set MATLAB search paths for tests and build MLTBX toolbox | ||
uses: matlab-actions/run-command@v2 | ||
|
||
with: | ||
command: | | ||
toolboxPath = fullfile(getenv('CANTERA_ROOT')); | ||
libPath = fullfile(toolboxPath, 'build', 'lib'); | ||
includePath = fullfile(toolboxPath, 'include'); | ||
addpath(fullfile(toolboxPath, 'interfaces', 'matlab_experimental', 'Utility')); | ||
ctPaths(libPath, includePath, toolboxPath); | ||
buildToolbox; | ||
- name: Run tests | ||
uses: matlab-actions/run-tests@f9fc3d8ca29fadef6227fa52884b144b9011fa2f # v2.1.1 | ||
with: | ||
select-by-folder: /home/runner/work/cantera/cantera/test/matlab_experimental | ||
- name: Upload Toolbox Artifact | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: Cantera_MATLAB_toolbox | ||
path: interfaces/matlab_experimental/*.mltbx | ||
retention-days: 14 | ||
# MLTBX test is disabled until we can download packaged binaries and header files | ||
# - name: Test the MLTBX toolbox | ||
# uses: matlab-actions/run-tests@v2 | ||
# with: | ||
# select-by-folder: /home/runner/work/cantera/cantera/test/matlab_experimental | ||
ischoegl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
ubuntu-multiple-pythons: | ||
name: ${{ matrix.os }} with Python ${{ matrix.python-version }}, Numpy ${{ matrix.numpy || 'latest' }}, Cython ${{ matrix.cython || 'latest' }} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
419f9e5f-b8d1-4265-b17a-239b6536fdd2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
function buildToolbox(arg) | ||
arguments | ||
arg.version (1,:) char = '0.0.0'; | ||
arg.ctRoot (1,:) char = pwd; | ||
end | ||
|
||
ver = regexp(arg.version, '^\d+\.\d+\.\d+', 'match', 'once'); | ||
|
||
fprintf('Building toolbox version: %s\n', ver); | ||
|
||
% Read the UUID for the toolbox | ||
uuidFile = fullfile(arg.ctRoot, 'interfaces', 'matlab_experimental', 'Setup', ... | ||
'Cantera_MATLAB_Toolbox.uuid'); | ||
if isfile(uuidFile) | ||
guid = strtrim(fileread(uuidFile)); | ||
fprintf('The unique identifier for the toolbox is: %s\n', guid); | ||
else | ||
error('A unique identifier for the toolbox does not exist!'); | ||
end | ||
|
||
% Define output file | ||
outputFile = fullfile(arg.ctRoot, 'interfaces', 'matlab_experimental', ... | ||
['Cantera_MATLAB_Toolbox_', ver, '.mltbx']); | ||
|
||
% Create temporary folder for reorganizing and faster execution | ||
tmpDir = fullfile(arg.ctRoot, 'build', 'mltbx'); | ||
mkdir(tmpDir); | ||
mapping = { | ||
'interfaces/matlab_experimental', 'toolbox'; | ||
'samples/matlab_experimental', 'samples'; | ||
'test/matlab_experimental', 'test/matlab_toolbox'; | ||
'test/data', 'test/data'; | ||
'data', 'data' | ||
}; | ||
|
||
% Move all files to temporary folder | ||
allFiles = {}; | ||
for i = 1:size(mapping, 1) | ||
src = fullfile(arg.ctRoot, mapping{i, 1}); | ||
dest = fullfile(tmpDir, mapping{i, 2}); | ||
copyfile(src, dest); | ||
files = dir(fullfile(dest, '**', '*')); | ||
files = files(~[files.isdir]); | ||
filesList = fullfile({files.folder}, {files.name})'; | ||
allFiles = [allFiles; filesList]; | ||
end | ||
|
||
% Get relative paths | ||
allPaths = strsplit(genpath(tmpDir), pathsep); | ||
relPaths = cellfun(@(p) erase(p, [arg.ctRoot filesep]), allPaths, 'UniformOutput', false); | ||
relPaths = relPaths(~cellfun(@isempty, relPaths)); | ||
|
||
% Get path to the icon file | ||
iconFile = fullfile(arg.ctRoot, 'doc', 'sphinx', '_static', 'images', 'cantera-logo.png'); | ||
|
||
% Set up toolbox options | ||
opts = matlab.addons.toolbox.ToolboxOptions(tmpDir, guid); | ||
opts.ToolboxName = 'Cantera MATLAB Toolbox'; | ||
opts.ToolboxVersion = ver; | ||
opts.Summary = 'MATLAB interface for Cantera.'; | ||
opts.Description = [ | ||
'Cantera is an open-source suite of tools for problems involving', ... | ||
'involving chemical kinetics, thermodynamics, and transport processes.', ... | ||
'This toolbox includes the MATLAB interface for Cantera, example scripts, and data files.' | ||
]; | ||
opts.AuthorName = 'Cantera Developers'; % placeholder | ||
opts.AuthorEmail = '[email protected]'; % placeholder | ||
opts.ToolboxFiles = allFiles; | ||
opts.ToolboxMatlabPath = relPaths; | ||
opts.ToolboxImageFile = iconFile; | ||
opts.MinimumMatlabRelease = 'R2014b'; | ||
opts.OutputFile = outputFile; | ||
opts.SupportedPlatforms.Win64 = true; | ||
opts.SupportedPlatforms.Glnxa64 = true; | ||
opts.SupportedPlatforms.Maci64 = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this support Apple Silicon? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MATLAB will run through Rosetta 2 on Apple Silicon for releases after R2020b so even though the option is called Earlier releases will only support Mac with Intel processors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Versions 2023b and up have native support … https://www.mathworks.com/support/requirements/apple-silicon.html |
||
opts.SupportedPlatforms.MatlabOnline = false; | ||
% These options will be enabled when we host Cantera binaries somewhere | ||
% opts.RequiredAdditionalSoftware = [ | ||
% struct( ... | ||
% "Name", "CanteraBinaries", ... | ||
% "Platform", "win64", ... | ||
% "DownloadURL", "placeholder for download url", ... | ||
% "LicenseURL", "placeholder for license url"), | ||
% struct( ... | ||
% "Name", "CanteraBinaries", ... | ||
% "Platform", "maci64", ... | ||
% "DownloadURL", "placeholder for download url", ... | ||
% "LicenseURL", "placeholder for license url"), | ||
% struct( ... | ||
% "Name", "CanteraBinaries", ... | ||
% "Platform", "glnxa64", ... | ||
% "DownloadURL", "placeholder for download url", ... | ||
% "LicenseURL", "placeholder for license url"), | ||
% ]; | ||
|
||
% Package the toolbox | ||
try | ||
matlab.addons.toolbox.packageToolbox(opts); | ||
fprintf('✅ Toolbox built successfully!\n'); | ||
catch ME | ||
fprintf('❌ Toolbox build failed: %s\n', ME.message); | ||
end | ||
|
||
% Remove the temporary folder | ||
rmdir(tmpDir, 's'); | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
function downloadDependencies() | ||
% This file may not be necessary once we set up the MLTBX properly | ||
|
||
os = lower(computer); | ||
% Get platform-specific binaries | ||
switch os | ||
case {'pcwin64', 'pcwin'} | ||
platform = 'windows'; | ||
case {'maci64'} | ||
platform = 'macos'; | ||
case {'glnxa64', 'glnx86'} | ||
platform = 'linux'; | ||
otherwise | ||
error('Unsupported platform: %s', os); | ||
end | ||
|
||
% Placeholder URL for ZIP files containing the binaries and headers | ||
baseUrl = 'https://cantera.com/downloads'; | ||
zipName = sprintf('cantera-binaries-%s.zip', platform); | ||
url = fullfile(baseUrl, zipName); | ||
|
||
% Set target install folder in user path | ||
installDir = fullfile(userpath, 'Dependencies'); | ||
if ~isfolder(installDir) | ||
fprintf('Downloading dependencies for %s...\n', platform); | ||
zipFile = fullfile(tempdir, zipName); | ||
websave(zipFile, url); | ||
unzip(zipFile, installDir); | ||
fprintf('Installed to: %s\n', installDir); | ||
else | ||
fprintf('Dependencies already installed at: %s\n', installDir); | ||
end | ||
|
||
% Add to path | ||
addpath(genpath(installDir)); | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,39 @@ | ||
function ctLoad() | ||
% ctLoad | ||
% Load the Cantera C Library into Memory | ||
|
||
paths = ctPaths(); | ||
|
||
if any(cellfun(@isempty, {paths.libPath, paths.includePath, paths.toolboxPath})) | ||
error('ctLoad:MissingPath', ... | ||
'Library, header, and toolbox paths must be configured with ctPaths(libPath,includePath, toolboxPath).'); | ||
end | ||
|
||
if ispc | ||
ctName = '/bin/cantera_shared.dll'; | ||
libName = 'cantera_shared.dll'; | ||
elseif ismac | ||
ctName = '/Lib/libcantera_shared.dylib'; | ||
libName = 'libcantera_shared.dylib'; | ||
elseif isunix | ||
ctName = '/lib/libcantera_shared.so'; | ||
libName = 'libcantera_shared.so'; | ||
else | ||
error('Operating System Not Supported!'); | ||
return; | ||
error('ctLoad:UnsupportedPlatform', 'Operating system not supported.'); | ||
end | ||
|
||
root = ctRoot; | ||
if ispc | ||
root = [ctRoot, '/Library']; | ||
end | ||
fullLibPath = fullfile(paths.libPath, libName); | ||
fullHeaderPath = fullfile(paths.includePath, 'cantera', 'clib', 'ctmatlab.h'); | ||
|
||
if ~libisloaded(ctLib) | ||
[~, warnings] = loadlibrary([root, ctName], ... | ||
[root, '/include/cantera/clib/ctmatlab.h'], ... | ||
'includepath', [root, '/include'], ... | ||
'addheader', 'ct', 'addheader', 'ctfunc', ... | ||
'addheader', 'ctmultiphase', 'addheader', ... | ||
'ctonedim', 'addheader', 'ctreactor', ... | ||
'addheader', 'ctrpath', 'addheader', 'ctsurf'); | ||
[~, warnings] = loadlibrary(fullLibPath, fullHeaderPath, ... | ||
'includepath', paths.includePath, ... | ||
'addheader', 'ct', ... | ||
'addheader', 'ctfunc', ... | ||
'addheader', 'ctmultiphase', ... | ||
'addheader', 'ctonedim', ... | ||
'addheader', 'ctreactor', ... | ||
'addheader', 'ctrpath', ... | ||
'addheader', 'ctsurf'); | ||
end | ||
|
||
disp(sprintf('Cantera %s is ready for use.', ctVersion)) | ||
fprintf('Cantera %s is ready for use.\n', ctVersion); | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
function paths = ctPaths(varargin) | ||
% ctPaths :: | ||
% Configure or retrieve the library/header/toolbox paths for Cantera. | ||
% The paths are stored as MATLAB preferences. | ||
% | ||
% >> ctPaths() % Get current config as struct | ||
% >> ctPaths(libPath, includePath) % Set library/header/toolbox paths | ||
% >> ctPaths('clear') % Clear saved paths | ||
% | ||
% :return: | ||
% paths: struct with fields 'libPath', 'includePath', and | ||
% 'toolboxPath' | ||
|
||
if nargin == 1 && strcmp(varargin{1}, 'clear') | ||
if ispref('Cantera', 'Paths') | ||
paths = getpref('Cantera', 'Paths'); | ||
subDirs = strsplit(genpath(paths.toolboxPath), pathsep); | ||
currentPaths = strsplit(path, pathsep); | ||
subdirsToRemove = intersect(subDirs, currentPaths); | ||
if ~isempty(subdirsToRemove) | ||
rmpath(subdirsToRemove{:}); | ||
end | ||
rmpref('Cantera', 'Paths'); | ||
end | ||
paths = struct('libPath', '', 'includePath', '', 'toolboxPath', ''); | ||
return | ||
elseif nargin == 3 && all(cellfun(@ischar, varargin)) | ||
paths = struct('libPath', varargin{1}, ... | ||
'includePath', varargin{2}, ... | ||
'toolboxPath', varargin{3}); | ||
setpref('Cantera', 'Paths', paths); | ||
else | ||
% Load from saved preferences if available | ||
if ispref('Cantera', 'Paths') | ||
paths = getpref('Cantera', 'Paths'); | ||
return | ||
else | ||
paths = struct('libPath', '', 'includePath', '', 'toolboxPath', ''); | ||
end | ||
end | ||
|
||
if any(cellfun(@isempty, {paths.libPath, paths.includePath, paths.toolboxPath})) | ||
error('ctPaths:MissingPath', ... | ||
'Library, header, and toolbox paths must be configured with ctPaths(libPath,includePath, toolboxPath).'); | ||
end | ||
|
||
mapping = { | ||
'interfaces/matlab_experimental', 'toolbox'; | ||
'samples/matlab_experimental', 'samples'; | ||
'test/matlab_experimental', 'test/matlab_toolbox'; | ||
'test/data', 'test/data'; | ||
'data', 'data' | ||
}; | ||
|
||
% Check whether user is using Cantera source code or MLTBX based on folder structure | ||
if isfolder(fullfile(paths.toolboxPath, 'interfaces')) | ||
col = 1; | ||
else | ||
col = 2; | ||
end | ||
|
||
for i = 1:size(mapping, 1) | ||
subdir = fullfile(paths.toolboxPath, mapping{i, col}); | ||
if isfolder(subdir) | ||
addpath(genpath(subdir)); | ||
else | ||
warning('ctPaths:MissingDirectory', ... | ||
'Directory not found: %s', subdir); | ||
end | ||
end | ||
|
||
savepath(); | ||
end |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,3 @@ | ||
clear all | ||
|
||
% Copy library to test folder | ||
ctTestPath; | ||
|
||
if ispc | ||
ctName = '/build/lib/cantera_shared.dll'; | ||
elseif ismac | ||
ctName = '/build/lib/libcantera_shared.dylib'; | ||
elseif isunix | ||
ctName = '/build/lib/libcantera_shared.so'; | ||
function ctTestSetUp() | ||
ctLoad(); | ||
end | ||
% Load Cantera | ||
if ~libisloaded('libcantera_shared') | ||
[~, warnings] = loadlibrary([cantera_root, ctName], ... | ||
[cantera_root, '/include/cantera/clib/ctmatlab.h'], ... | ||
'includepath', [cantera_root, '/include'], ... | ||
'addheader', 'ct', 'addheader', 'ctfunc', ... | ||
'addheader', 'ctmultiphase', 'addheader', ... | ||
'ctonedim', 'addheader', 'ctreactor', ... | ||
'addheader', 'ctrpath', 'addheader', 'ctsurf'); | ||
end | ||
|
||
disp('Cantera is loaded for test'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,3 @@ | ||
clear all | ||
% Unload Cantera | ||
if ispc | ||
lib = 'cantera_shared'; | ||
else | ||
lib = 'libcantera_shared'; | ||
function ctTestTearDown() | ||
ctUnload(); | ||
end | ||
|
||
unloadlibrary(lib); | ||
disp('Cantera has been unloaded'); |
Uh oh!
There was an error while loading. Please reload this page.