Skip to content

Feature/resolve timelines - #62

Open
maarten-ic wants to merge 11 commits into
developfrom
feature/resolve-timelines
Open

Feature/resolve timelines#62
maarten-ic wants to merge 11 commits into
developfrom
feature/resolve-timelines

Conversation

@maarten-ic

@maarten-ic maarten-ic commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Continuation of PR #27

  • Put determined timelines back on Component (absolute timelines) and Port (relative to Component?) objects
  • Update timeline annotations when importing/resolving (components are renamed to x.y.<component> and timeline annotations should as well to prevent clashes)
  • Move to v0_2.validation.timelines. Function: resolve_timelines() because it updates the timelines on the data objects
  • Cyclic dependency documentation (move to issue?)

Signature accepts a Sequence, but the logic previously only worked when providing a list. Other sequences silently didn't work.
Add `parent` property and `relative_to` (inspired by pathlib.Path)
@maarten-ic

maarten-ic commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author
  • Update timeline annotations when importing/resolving (components are renamed to x.y.<component> and timeline annotations should as well to prevent clashes)

N.B. Resolving imports doesn't rename components (only models) and therefore shouldn't rename timelines.
Timelines should be renamed when flattening, but that logic resides in muscle3 so it's not part of this PR.

Edit: thinking a bit more about this, I'm not sure if we must rename timelines when flattening the hierarchical models:

  1. Timelines that are exported on a model port must not change names
  2. Timelines that are internal to a model will never interact with components outside the model and so this is not a problem for the logic in this PR if they have the same name

Include information on the conduits instead of just the components.

Example error message:
> Detected a dependency cycle in model 'cycle'. The component 'first' has an F_INIT port that depends on data produced by one of its own O_F or O_I ports: Conduit(first.final -> second.init) -> Conduit(second.final -> third.init) -> Conduit(third.final -> first.init). You may have an error in the conduits or may need a different coupling schema.
@maarten-ic
maarten-ic marked this pull request as ready for review July 17, 2026 10:15
@maarten-ic

Copy link
Copy Markdown
Collaborator Author

N.B. I've improved the cyclic dependency error, hopefully this is clear enough without writing and pointing to a new documentation page.

@LourensVeen

Copy link
Copy Markdown
Contributor

Edit: thinking a bit more about this, I'm not sure if we must rename timelines when flattening the hierarchical models:

Imagine a top-level model with two components a and b, with a dispatching to b. Both a and b are implemented using a submodel, and each of those submodels has a macro-micro model inside it with components named macro and micro, and with macro's F_INIT and O_F connected to model ports.

After flattening, we have a flat model with components a.macro, a.micro, b.macro and b.micro. Component a.micro is on timeline :a.macro and component b.micro is on timeline :b.macro. Without renaming during flattening, they'd both be on :macro and would appear to be on the same timeline while they're really not.

Timelines that are exported on a model port must not change names
Timelines that are internal to a model will never interact with components outside the model and so this is not a problem for the logic in this PR if they have the same name

Timelines on ports are usually relative timelines, and those shouldn't be a problem as long as the absolute timeline they're appended to is correct. They can interact with components outside the model just fine though, we can have a component macro inside of a submodel that has its O_I and S ports connected to O_I and S ports on the submodel, and a micro component in another submodel.

@LourensVeen LourensVeen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Definitely headed in the right direction, nice work!

Comment thread ymmsl/v0_2/tests/ymmsl1/timelines.ymmsl
Comment thread ymmsl/v0_2/tests/test_timeline_resolver.py
Comment thread ymmsl/v0_2/tests/ymmsl1/timelines.ymmsl
Comment thread ymmsl/v0_2/timeline_resolver.py Outdated
Comment thread ymmsl/v0_2/timeline_resolver.py Outdated
@maarten-ic

Copy link
Copy Markdown
Collaborator Author

Edit: thinking a bit more about this, I'm not sure if we must rename timelines when flattening the hierarchical models:

Imagine a top-level model with two components a and b, with a dispatching to b. Both a and b are implemented using a submodel, and each of those submodels has a macro-micro model inside it with components named macro and micro, and with macro's F_INIT and O_F connected to model ports.

After flattening, we have a flat model with components a.macro, a.micro, b.macro and b.micro. Component a.micro is on timeline :a.macro and component b.micro is on timeline :b.macro. Without renaming during flattening, they'd both be on :macro and would appear to be on the same timeline while they're really not.

Yes, fully agreed! For complete correctness you'd have to rename these internal timelines.

My point (which I didn't describe clearly, sorry for that!) was that timeline renaming isn't required for the checks in this PR. The flattened model is more of an internal MUSCLE3 state and I expect it's not required to have the renaming functionality in to get a properly behaving simulation. We'll have to test though 🙂

@maarten-ic
maarten-ic requested a review from LourensVeen July 29, 2026 13:29
@LourensVeen

Copy link
Copy Markdown
Contributor

Ah, and after flattening the timelines aren't actually used anyway, so it would work even if we don't update them during flattening. Yes, I think that's right. And components don't get renamed during resolving, so there's no issue there either. All good.

@LourensVeen LourensVeen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few suggestions, but I think this is good to go?

model. Any of the following exceptions (which are a subclass of
:class:`ResolveTimelineException`) will be raised when the model timelines are not
consistent. See their description for more details:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can use a Raises: section for this similar to Args: to make Sphinx render it nicely:

Raises:
    :class:`CyclicDependency` if an O_F to F_INIT loop was found
    :class:`TooManyReducerFilters` if a timeline was reduced by more levels than it has



class CyclicDependency(RuntimeError):
class ResolveTimelineException(RuntimeError):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice!

This error is raised when a reducer filter attempts to reduce a conduit that
already sends on the root timeline. :class:`InconsistentTimelines` or
:class:`ConduitTimelineError` may also be raised when too many reducer filters are
applied.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"... if that doesn't reduce the timeline beyond the root timeline."

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

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants