Skip to content

C-API v2.0 #123

Open
Open
@schmoelder

Description

Once #115 is merged, we can consider additional functionality that we would like to expose via the C-API. This issue serves as a super issue to collect ideas.

Simulating individual sections

Instead of running the complete simulations, it might be advantageous to only run a specific number of sections before deciding whether to continue or not. This is particularly useful for control algorithms but also important when evaluating cyclic stationarity etc.

For this purpose, we should reconsider the way we define section dependent parameters. Instead of globally defining the values for each section as an array in /input/model/unit_xxx/parameter_xxx, it would be convenient if we could overwrite each parameter independently for each section. For an example, refer to the SystemSolver class in the CADET-Python-Simulator which expects a Section with the following structure:

class Section:
    """
    Represents a section with start, end, connections, and section states.

    Attributes
    ----------
    start : int
        The start point of the section.
    end : int
        The end point of the section.
    connections : list[List[float]]
        Connections represented as a list of lists, where each connection is
        a list [from, to, value].
    section_states : dict[str, dict[str, npt.ArrayLike]]
        A dictionary containing the section states. The keys represent the
        state names (e.g., 'inlet'), and each state contains a dictionary
        of variable names mapped to ArrayLike values.
    """

    def __init__(
            self,
            start: int,
            end: int,
            connections: list[list[float]],
            section_states: dict[str, dict[str, npt.ArrayLike]]
            ) -> None:
        """
        Initialize a Section instance.

        Parameters
        ----------
        start : int
            The start point of the section.
        end : int
            The end point of the section.
        connections : list[list[float]]
            A list of connections, each represented as [from, to, value].
        section_states : dict[str, dict[str, npt.ArrayLike]]
            A dictionary containing the section states.
        """
        self.start = start
        self.end = end
        self.connections = connections
        self.section_states = section_states

If a parameter is not updated in a section, its previous values is used (open question: How to treat piecewise polynomial parameters?)

Conditional Events (Related: #27)

Once running individual sections is implemented, we can start adding some logic for conditional events (e.g. start next section once concentration exceeds some value). As a first step, it would also be great if we could "go back" to the beginning of the section in case we "overshot" and restart with different parameters / section time. This logic could even be implemented outside of CADET-Core which keeps the core simulator nice and clean.

Restructure the interface function arguments

Currently, we explicitly have to pass in pointers to each of the solution dimensions s.t. CADET-Core can return the number of for that dimensions and we can reshape the solution array correspondingly using numpy.

However, since for every model the dimensions of bulk, particle can change (e.g. because singleton dimensions might need to be squeezed or not), the signature for these becomes very long and tedious:

cdtResult get##NAME##Particle(cdtDriver* drv, int unitOpId SENS_IDX_SIG, int parType, double const** time, double const** data, int* nTime, int* nAxialCells, int* nRadialCells, int* nParShells, int* nComp, bool* keepAxialSingletonDimension, bool* keepParticleSingletonDimension) \

To simplify this, we could introduce a struct dimensions argument, where each key is a dimension of that solution and each value the number of entries.

cdtResult get##NAME##Particle(cdtDriver* drv, int unitOpId SENS_IDX_SIG, const** data, struct dimensions \

I haven't checked if it is possible to expose structs via ctypes in Python but there would be other options, e.g. we could simply return an array of strings and integers or just the shape as an array / tuple (we don't actually really need the dimension names, I believe).


If any of you have ideas, feel free to edit / comment.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status

      Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions