Skip to content

[MATLAB] Migrate to generated Clib#1997

Merged
speth merged 47 commits intoCantera:mainfrom
ssun30:matlab_clibMigration
Oct 27, 2025
Merged

[MATLAB] Migrate to generated Clib#1997
speth merged 47 commits intoCantera:mainfrom
ssun30:matlab_clibMigration

Conversation

@ssun30
Copy link
Copy Markdown
Contributor

@ssun30 ssun30 commented Oct 5, 2025

Changes proposed in this pull request

This PR updates the experimental MATLAB interface to use the auto-generated Cantera Clib (produced via sourcegen), replacing the previously manually written Clib.

Specifically, this PR:

  • Updates the interface generation workflow to consume the auto-generated Clib headers instead of the manually curated set.
  • Adjusts MATLAB definition generation to reflect updated function and class names in the new Clib.
  • Removes redundant edge-case handling in ctEditLibraryDefinitions that was only required for the manually written Clib.
  • Re-enables several MATLAB unit tests that were previously excluded due to missing API functions in the old Clib.

Closes #1722

Checklist

  • The pull request includes a clear description of this code change
  • Commit messages have short titles and reference relevant issues
  • Build passes (scons build & scons test) and unit tests address code coverage
  • Style & formatting of contributed code follows contributing guidelines
  • The pull request is ready for review

@ssun30 ssun30 marked this pull request as draft October 5, 2025 19:43
@ssun30
Copy link
Copy Markdown
Contributor Author

ssun30 commented Oct 5, 2025

Hi @ischoegl , I've started migrating the MATLAB interface to the generated Clib. It won't work with the generated Clib as-is due to the following two points:

  • Only ct.h includes <stdint.h>, but several other generated headers in cantera_clib also declare functions using int32_t.
    When the MATLAB interface generator (clibgen.generateLibraryDefinition) parses these headers individually, compilation fails with:
/Users/ssun30/cantera/interfaces/clib/include/cantera_clib/ctconnector.h(139): 
error: identifier "int32_t" is undefined'

On my local machine, I got around this issue by adding <stdint.h> to other header files.

  • Several function docstrings in ct.h contain the substring %Cantera, for example, in ct_version:
/**
 * Returns the %Cantera version.
 */

MATLAB’s clibgen treats % as a comment character in MATLAB syntax. During parsing, the line is truncated at %, producing an unterminated string in the generated definectMatlab.m file and causing:

Error: String is not terminated properly.

Affected functions:
ct_version
ct_gitCommit
ct_getDataDirectories
ct_make_warnings_fatal
ct_getCanteraError

On my local machine, I got around this issue by removing the % symbol from %Cantera.

@ischoegl ischoegl added the Matlab label Oct 5, 2025
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 5, 2025

@ssun30 ... I pushed some fixes. I can compile things without needing to edit on my machine, and the toolbox loads, but the unit tests fail. Please ensure that you reset your local branch to this one to preserve my edits.

@ischoegl ischoegl force-pushed the matlab_clibMigration branch from 2952e2c to c4ea8aa Compare October 5, 2025 23:03
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 5, 2025

Codecov Report

❌ Patch coverage is 55.63380% with 189 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.47%. Comparing base (fcde484) to head (5912be6).
⚠️ Report is 47 commits behind head on main.

Files with missing lines Patch % Lines
interfaces/matlab_experimental/OneDim/Flow1D.m 0.00% 32 Missing ⚠️
interfaces/matlab_experimental/OneDim/Domain1D.m 0.00% 18 Missing ⚠️
...ces/matlab_experimental/cantera/ctBuildInterface.m 0.00% 15 Missing ⚠️
...xperimental/cantera/ctGenerateLibraryDefinitions.m 0.00% 14 Missing ⚠️
include/cantera/zeroD/ReactorBase.h 0.00% 12 Missing ⚠️
interfaces/matlab_experimental/Base/Mixture.m 50.00% 9 Missing ⚠️
interfaces/matlab_experimental/OneDim/Sim1D.m 0.00% 9 Missing ⚠️
...terfaces/matlab_experimental/Reactor/ReactorBase.m 67.85% 9 Missing ⚠️
include/cantera/oneD/Flow1D.h 20.00% 7 Missing and 1 partial ⚠️
...ab_experimental/OneDim/CounterFlowDiffusionFlame.m 0.00% 7 Missing ⚠️
... and 29 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1997      +/-   ##
==========================================
+ Coverage   75.52%   76.47%   +0.95%     
==========================================
  Files         455      464       +9     
  Lines       56938    54936    -2002     
  Branches     9363     9305      -58     
==========================================
- Hits        43001    42012     -989     
+ Misses      10764     9798     -966     
+ Partials     3173     3126      -47     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ssun30 ssun30 force-pushed the matlab_clibMigration branch from c4ea8aa to 0802ddd Compare October 8, 2025 23:23
@ssun30
Copy link
Copy Markdown
Contributor Author

ssun30 commented Oct 8, 2025

@ssun30 ... I pushed some fixes. I can compile things without needing to edit on my machine, and the toolbox loads, but the unit tests fail. Please ensure that you reset your local branch to this one to preserve my edits.

Hi @ischoegl , I've fixed most of the issues with the unit tests. But five tests remain and I'll list each of them:

sample ignite.m

Unable to resolve the name 'clib.ctMatlab.kin_getSourceTerms'.

Error in [ctArray](matlab:matlab.lang.internal.introspective.errorDocCallback('ctArray', '/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctArray.m', 6)) ([line 6](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctArray.m',6,0)))
    iok = clib.ctMatlab.(funcName)(varargin{:}, buf);
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [Kinetics/get.massProdRate](matlab:matlab.lang.internal.introspective.errorDocCallback('Kinetics/get.massProdRate', '/Users/ssun30/cantera/interfaces/matlab_experimental/Base/Kinetics.m', 458)) ([line 458](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/Base/Kinetics.m',458,0)))
            ydot = ctArray('kin_getSourceTerms', nsp, kin.kinID);
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [reactor_ode](matlab:matlab.lang.internal.introspective.errorDocCallback('reactor_ode', '/Users/ssun30/cantera/samples/matlab_experimental/reactor_ode.m', 44)) ([line 44](matlab: opentoline('/Users/ssun30/cantera/samples/matlab_experimental/reactor_ode.m',44,0)))
        ydt = total_mass * gas.massProdRate;

I didn't find the new equivalent function to kin_getSourceTerms in the generated clib.

@ssun30
Copy link
Copy Markdown
Contributor Author

ssun30 commented Oct 8, 2025

The next sample is catacomb.m

Error using [clib.ctMatlab.domain_index](matlab:matlab.lang.internal.introspective.errorDocCallback('clib.ctMatlab.domain_index'))
No method 'clib.ctMatlab.domain_index' with matching signature found.

Error in [ctFunc](matlab:matlab.lang.internal.introspective.errorDocCallback('ctFunc', '/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctFunc.m', 5)) ([line 5](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctFunc.m',5,0)))
    output = clib.ctMatlab.(funcName)(varargin{:});
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [Domain1D/get.domainIndex](matlab:matlab.lang.internal.introspective.errorDocCallback('Domain1D/get.domainIndex', '/Users/ssun30/cantera/interfaces/matlab_experimental/OneDim/Domain1D.m', 200)) ([line 200](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/OneDim/Domain1D.m',200,0)))
            i = ctFunc('domain_index', d.domainID) + 1;
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [Boundary1D/massFraction](matlab:matlab.lang.internal.introspective.errorDocCallback('Boundary1D/massFraction', '/Users/ssun30/cantera/interfaces/matlab_experimental/OneDim/Boundary1D.m', 81)) ([line 81](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/OneDim/Boundary1D.m',81,0)))
            if d.domainIndex == 0
               ^^^^^^^^^^^^^
Error in [catcomb](matlab:matlab.lang.internal.introspective.errorDocCallback('catcomb', '/Users/ssun30/cantera/samples/matlab_experimental/catcomb.m', 144)) ([line 144](matlab: opentoline('/Users/ssun30/cantera/samples/matlab_experimental/catcomb.m',144,0)))
    y = inlt.massFraction(k);

The function signature for domain_index has changed:

    /**
     *  Returns the index of the solution vector, which corresponds to component n at grid point j.
     *
     *  Wraps C++ method: `size_t Domain1D::index(size_t, size_t)`
     *
     *  @param handle       Handle to queried Domain1D object.
     *  @param n            component index
     *  @param j            grid point index
     */
    int32_t domain_index(int32_t handle, int32_t n, int32_t j);

@ssun30
Copy link
Copy Markdown
Contributor Author

ssun30 commented Oct 8, 2025

sample surf_reactor.m

Error using [ctFunc](matlab:matlab.lang.internal.introspective.errorDocCallback('ctFunc', '/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctFunc.m', 10)) ([line 10](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/Utility/ctFunc.m',10,0)))

*******************************************************************************
CanteraError thrown by Cabinet::as:
Item is not of the correct type.
*******************************************************************************

Error in [ReactorSurface/set.area](matlab:matlab.lang.internal.introspective.errorDocCallback('ReactorSurface/set.area', '/Users/ssun30/cantera/interfaces/matlab_experimental/Reactor/ReactorSurface.m', 56)) ([line 56](matlab: opentoline('/Users/ssun30/cantera/interfaces/matlab_experimental/Reactor/ReactorSurface.m',56,0)))
            ctFunc('reactor_setArea', s.id, a);
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [surf_reactor](matlab:matlab.lang.internal.introspective.errorDocCallback('surf_reactor', '/Users/ssun30/cantera/samples/matlab_experimental/surf_reactor.m', 48)) ([line 48](matlab: opentoline('/Users/ssun30/cantera/samples/matlab_experimental/surf_reactor.m',48,0)))
rsurf.area = A;
^^^^^^^^^^

I didn't find the equivalent methods for reactorsurface_area and reactorsurface_setArea in the new clib.

@ssun30
Copy link
Copy Markdown
Contributor Author

ssun30 commented Oct 8, 2025

The final errors are under ctTestThermo.m, in particular testElementalMassFraction and testNAtoms:

    --> The value does not contain the substring.
    
    Actual char:
        <no Cantera error
    Expected Substring:
        No such element

In the legacy clib, the thermo_elementIndex and thermo_speciesIndex methods have hard-coded error handling:

    size_t thermo_elementIndex(int n, const char* nm)
    {
        try {
             size_t k = ThermoCabinet::at(n)->elementIndex(nm);
             if (k == npos) {
                throw CanteraError("thermo_elementIndex",
                                   "No such element {}.", nm);
             }
             return k;
        } catch (...) {
            return handleAllExceptions(npos, npos);
        }
    }

Now the corresponding methods in the generated clib lack those checks, and thus no error message was returned.

@ssun30 ssun30 force-pushed the matlab_clibMigration branch from 0802ddd to 63b6408 Compare October 9, 2025 18:34
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 9, 2025

@ssun30 ... thank you - I'll look into the issue you pointed out shortly. We just merged #1995, which changes some of the 1D access routes (good news: things should become somewhat easier). Could you rebase? I'll try to push some fixes to the issues you pointed out thereafter.

PS: I outlined some of my thoughts on the 'onedim' portion in Cantera/enhancements#239. Only a small fraction is applicable to this PR.

@ssun30 ssun30 force-pushed the matlab_clibMigration branch from 6719908 to edb50bd Compare October 10, 2025 14:35
@ischoegl
Copy link
Copy Markdown
Member

I didn't find the new equivalent function to kin_getSourceTerms in the generated clib.

This was hard-coded in the legacy CLib, and won't be replicated as such in the generated CLib. You have two options:

  1. Implement what the old function did in MATLAB
  2. Add it to the C++ code base

@ischoegl
Copy link
Copy Markdown
Member

The function signature for domain_index has changed:

Point-wise access should be replaced by domain_value for boundaries and domain_values for flow domains.

@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 11, 2025

The final errors are under ctTestThermo.m, in particular testElementalMassFraction and testNAtoms
[...]

The underlying C++ methods return npos, and Python implements custom exception handling. The way the generated CLib works is that it will simply pass through C++ behavior, with no additional checks added.

The quick fix is to follow the Python approach, although an argument could be made to move this to C++ (which is significantly more difficult, as this changes long-standing behavior with potentially breaking changes). The best approach to implementing a change in C++ would be to create an enhancement request, as it exceeds the scope of the MATLAB toolbox. Edit: see #2004.

PS: #2010

@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 11, 2025

I didn't find the equivalent methods for reactorsurface_area and reactorsurface_setArea in the new clib.

Yes - while there was a setter/getter, it was shadowed by FlowReactor. I implemented a version that handles both in C++ - please use reactor_area and reactor_setArea and add it to the base class. The C++ fix is added to this PR.

@ischoegl
Copy link
Copy Markdown
Member

@ssun30 ... I will have a look at the 1D components as there have been significant changes. I will try to make this as close to Cantera/enhancements#239 and the corresponding Python framework as possible so this is futureproof.

@ischoegl ischoegl force-pushed the matlab_clibMigration branch 5 times, most recently from 2f38384 to cc50e2c Compare October 12, 2025 18:12
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 12, 2025

@ssun30 ... I added a new flamespeed.m example that is an almost identical replica of the C++ example. It runs and gives the same output as C++. I.e., this PR likely fixes #1722 (added this to the top description).

The catcomb.m sample runs mostly through at this point but stalls at the plotting step; the rest should be straightforward debugging. PS: pushed the remaining (trivial) fix.

Overall, there were some issues with MATLAB functions calling incorrect CLib signatures. I created convenience access points as necessary. There are two observations:

  • The MATLAB-built interface changes the signatures, which is extremely confusing, as the names still correspond to CLib
  • MATLAB does not display C++ output (which is a bug)

@ischoegl ischoegl force-pushed the matlab_clibMigration branch 6 times, most recently from 27373f8 to 0569bdf Compare October 26, 2025 15:05
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 26, 2025

@ssun30 and @speth ... I ended up simplifying ctBuildInterface as there is no need to specify two include folders. After installation, the /path/to/cantera_install/include folder holds cantera and cantera_clib in parallel folders.

The main difference is that this requires a scons install, and avoids using the build folders.

PS: I also switched to inprocess defaults on macOS and Windows, but can roll that change back. Edit: rolled back.

@ischoegl ischoegl force-pushed the matlab_clibMigration branch from 0569bdf to c066670 Compare October 26, 2025 15:12
@speth
Copy link
Copy Markdown
Member

speth commented Oct 26, 2025

The main difference is that this requires a scons install, and avoids using the build folders.

I think being able to test (both the test suite and interactively) without running scons install is incredibly valuable, and not a feature I would want to lose for the MATLAB toolbox or any of the interfaces.

@ischoegl ischoegl force-pushed the matlab_clibMigration branch 2 times, most recently from 258728c to f8c0e3a Compare October 26, 2025 16:47
@ischoegl
Copy link
Copy Markdown
Member

ischoegl commented Oct 26, 2025

I think being able to test (both the test suite and interactively) without running scons install is incredibly valuable, and not a feature I would want to lose for the MATLAB toolbox or any of the interfaces.

Fair point. Thankfully, the dependency on cantera/base/config.h in clib_defs.h was unnecessary, so I was able to maintain the simplification without needing to install. I.e.,

ctToolboxDir = '/path/to/cantera/source/interfaces/matlab_experimental';
ctIncludeDir = '/path/to/cantera/include';
ctLibDir = '/path/to/cantera/library';
ctBuildInterface(ctToolboxDir, ctIncludeDir, ctLibDir);

I'll leave this for a final review now. There are many rough edges, but the migration to the generated CLib is accomplished (thank you @ssun30!). Additional improvements can be made in follow-up PRs.

@ischoegl ischoegl requested a review from speth October 26, 2025 17:53
Copy link
Copy Markdown
Member

@speth speth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates, @ssun30 and @ischoegl. Just a couple of minor issues to fix here, mostly documentation related.

@ischoegl ischoegl force-pushed the matlab_clibMigration branch 2 times, most recently from 973c192 to f680a53 Compare October 27, 2025 13:15
Ensure enableEnergy / enableChemistry / massFlowRate are consistent
with C++ API.
@ischoegl ischoegl force-pushed the matlab_clibMigration branch from f680a53 to 5912be6 Compare October 27, 2025 14:00
@ischoegl
Copy link
Copy Markdown
Member

@speth / @ssun30 ... I went ahead and made all the requested changes, which also extend to improved exception handling for enabling/disabling energy and chemistry.

@ischoegl ischoegl requested a review from speth October 27, 2025 15:05
@ischoegl ischoegl added the clib label Oct 27, 2025
Copy link
Copy Markdown
Member

@speth speth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks good to me.

@speth speth merged commit 3de9745 into Cantera:main Oct 27, 2025
53 of 54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broken flame examples in experimental MATLAB toolbox

4 participants