Skip to content

update flepimop2 provider pacakge#12

Open
MacdonaldJoshuaCaleb wants to merge 6 commits intomainfrom
reduce_introspection
Open

update flepimop2 provider pacakge#12
MacdonaldJoshuaCaleb wants to merge 6 commits intomainfrom
reduce_introspection

Conversation

@MacdonaldJoshuaCaleb
Copy link
Collaborator

@MacdonaldJoshuaCaleb MacdonaldJoshuaCaleb commented Feb 13, 2026

This pull request consolidates and refactors the integration between flepimop2 and op_engine, moving all engine logic and configuration into a single file (__init__.py). It removes the separate config.py and engine.py modules, simplifies dependency management in pyproject.toml, and updates linting rules. The new implementation provides a streamlined, self-contained flepimop2 engine backed by op_engine, with improved configuration validation and runtime checks.

Engine integration and refactoring:

  • Merged all engine logic and configuration into src/flepimop2/engine/op_engine/__init__.py, replacing the previous split between engine.py and config.py. The new implementation defines the OpEngineFlepimop2Engine and its configuration in a single file, with improved runtime validation and operator handling.

Dependency and build configuration:

  • Updated pyproject.toml to reference op-engine directly from its GitHub repository, removing the sibling directory wiring and simplifying dependency management.
    Linting and code quality:

  • Added per-file ignore rules in pyproject.toml for the new consolidated __init__.py, disabling specific lint and docstyle checks to accommodate the new implementation.

  • Aligned provider package with the expectations setup in flepimop2 #118

Closes #6 obsoletes #10, #11 due to changes introduced in flepimop2 #118

@MacdonaldJoshuaCaleb MacdonaldJoshuaCaleb changed the title reduce introspection in flepimop2 provider package update flepimop2 provider pacakge Feb 17, 2026
Copy link
Collaborator

@TimothyWillard TimothyWillard left a comment

Choose a reason for hiding this comment

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

It would nice to see a bit more DRY, especially for low hanging fruit like using types from flepimop2 or helpers already defined in op_engine.

Comment on lines 140 to 141
dt_min: float = Field(default=0.0, ge=0.0)
dt_max: float = Field(default=float("inf"), gt=0.0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does dt_min == 0.0 mean infer lower bound and dt_max == math.inf mean infer upper bound? Minor, but seems like a more natural choice would be None since that indicates no user statement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I kept dt_min=0.0 and dt_max=inf intentionally because those are the native op_engine DtControllerConfig sentinel values for ‘no additional bound’. Switching to None in the provider would require extra normalization logic and would diverge from core config semantics without changing behavior. If we want None ergonomics, we should introduce it consistently in op_engine itself first, then mirror it here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, that seems reasonable to mirror the API of op_engine here. I guess just noting its a bit weird to use concrete values rather than values that indicate "no statement", but I guess this is outside the scope of this PR then.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not a TODO for you @MacdonaldJoshuaCaleb instead for me, but probably need to provide some kind of default system/engine as part of the integration testing utilities bundled with flepimop2.

Copy link
Member

@pearsonca pearsonca left a comment

Choose a reason for hiding this comment

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

Minor questions, but seems fine?

return None


def _rhs_from_stepper(
Copy link
Member

Choose a reason for hiding this comment

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

work for another day: if adapter is necessary, we should probably be working the pipeline definition a bit. i imagine generally engines may need to adapt SystemABC somewhat, but all this re-shaping seems problematic.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This actually seems fine to me, and within the scope of engines. This is taking a stepper function and then vectorizing it because that's the type of "stepper" that op_engine expects. I don't think flepimop2 should get into the business of trying to figure out the correct way(s) to generalize steppers. However, I do think this could be simplified a bit by the introduction of proper "build" mechanics, see ACCIDDA/flepimop2#130, ACCIDDA/flepimop2#129 (comment).

Copy link
Member

Choose a reason for hiding this comment

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

I'm mostly bothered by the shaping related checks than the reshaping itself. I should have said if this amount of adaptor required

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see, I think this is a consequence of the outputs being unstructured numpy arrays. To address this would require adding more structure on that front. Perhaps ACCIDDA/flepimop2#147 is a first step to that, but definitely more work required beyond that.

Copy link
Collaborator Author

@MacdonaldJoshuaCaleb MacdonaldJoshuaCaleb left a comment

Choose a reason for hiding this comment

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

Why not use op_engine.types.as_float_1d?

as part of the simplifications I got rid of the types.py file

from flepimop2.exceptions import ValidationIssue
from flepimop2.system.abc import SystemABC, SystemProtocol
from pydantic import BaseModel, ConfigDict, Field, model_validator
from flepimop2.typing import StateChangeEnum # noqa: TC002
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of noqaing, why not move this under the type checking imports as the lint rule suggests? See https://docs.astral.sh/ruff/rules/typing-only-third-party-import/.

return None


def _rhs_from_stepper(
Copy link
Collaborator

Choose a reason for hiding this comment

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

This actually seems fine to me, and within the scope of engines. This is taking a stepper function and then vectorizing it because that's the type of "stepper" that op_engine expects. I don't think flepimop2 should get into the business of trying to figure out the correct way(s) to generalize steppers. However, I do think this could be simplified a bit by the introduction of proper "build" mechanics, see ACCIDDA/flepimop2#130, ACCIDDA/flepimop2#129 (comment).

Comment on lines 140 to 141
dt_min: float = Field(default=0.0, ge=0.0)
dt_max: float = Field(default=float("inf"), gt=0.0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, that seems reasonable to mirror the API of op_engine here. I guess just noting its a bit weird to use concrete values rather than values that indicate "no statement", but I guess this is outside the scope of this PR then.

"""flepimop2 engine adapter backed by op_engine.CoreSolver."""

module: Literal["flepimop2.engine.op_engine"] = "flepimop2.engine.op_engine"
state_change: StateChangeEnum
Copy link
Collaborator

Choose a reason for hiding this comment

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

Okay, I'm a bit confused about this one. It seems like this seems to indicate that op_engine handles multiple different kinds of state change steppers, but requires user configuration to do so? If op_engine can handle multiple kinds of state change steppers it should just use system.state_change to infer the settings for op_engine. However, it appears like a validation is done, and then self.state_change is never used? So can op_engine actually handle steppers of different state changes, from your description of the package I thought it could only handle "flow"?

if isinstance(system_axis, str | int):
operator_axis = system_axis

stepper: SystemProtocol = system._stepper # noqa: SLF001
Copy link
Collaborator

Choose a reason for hiding this comment

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

Another argument for pushing ACCIDDA/flepimop2#130 forward in the workplan

tr=operators.get("tr"),
bdf2=operators.get("bdf2"),
)
__all__ = ["OpEngineEngineConfig", "_coerce_operator_specs", "_has_operator_specs"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why export _coerce_operator_specs & _has_operator_specs? These seem like private utilities.


[tool.ruff.lint.per-file-ignores]
"tests/**/*" = ["INP001", "S101"]
"src/flepimop2/engine/op_engine/__init__.py" = ["C901", "DOC201", "DOC501", "PLR0912", "PLR0913", "PLR0914", "PLR0915", "RUF067"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

This makes me a bit weary to ignore so many linting/formatting suggestions. Perhaps outside the scope of this PR, but I think these rules exist to indicate where there might be refactoring/documentation opportunities. Although, for RUF067 we also need to think about that on the flepimop2 front, the way we've structured the package as being an implicit namespace package with dynamic module loading makes it a little annoying to work around this one.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Simplify typing in flepimop2 provider package

3 participants