Skip to content

Extended linearity information in incidence lattice #30

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

Open
Keno opened this issue May 12, 2025 · 14 comments
Open

Extended linearity information in incidence lattice #30

Keno opened this issue May 12, 2025 · 14 comments
Assignees

Comments

@Keno
Copy link
Member

Keno commented May 12, 2025

The thermalfluid benchmark is almost linear up to parameters. We need to distinguish this case in the incidence lattice from the case where the equation is non-linear in the state. Note in particular that the coefficient may still be non-linear in other states. For example, we should infer sin(u₁) u₂ as linear in u₂ and non-linear u₁. I'm not entirely sure how to print this in the Incidence printing, but perhaps we could underline the linear arguments. As for implementation, the struct NonLinear singleton should be expanded to struct Lineararity; nonlinear::Bool; end with the nonlinear and linear the appropriate elements.

After it's supported in the lattice, there's additional work to do on the codegen side, but let's start with the lattice.

@Keno
Copy link
Member Author

Keno commented May 14, 2025

I've thought about this a little more and we should have more levels of linearity information. At the very least we need to encode whether we have any state dependence in the coefficient and whether we have any time dependence. Of course we could go all the way to just keep the full matrix, but I'm hoping to avoid that for now.

@serenity4
Copy link
Member

serenity4 commented May 14, 2025

Would you mean something like this?

struct Linearity
    state_linear::Bool
    time_linear::Bool
    # can we be state-linear, time-linear but remain nonlinear in other things?
    nonlinear::Bool
end

Or do you mean to encode mere dependence, not linearity, for state and time?

@Keno
Copy link
Member Author

Keno commented May 14, 2025

I was thinking of it more as an enum rather than bools, since I think there are combination that don't help us (mostly nonlinear with any of the others). Also state_linear is a bit misleading. It's about the coefficient of the corresponding variable, which could be nonlinear in one of the other variables (or time).

@topolarity
Copy link
Member

Seems like constant vs. linear vs. nonlinear coefficients are important to separate, since they distinguish between:

u[1] * u[2] # bilinear (linear co-efficient from the perspective of both variables)
u[2] # linear (constant co-efficient)
f(u[1]) * u[2] # non-linear co-efficient for u[2] / linear co-efficient for u[1]

I'm not sure if the bilinear form is very helpful though - is there much we can do with that, other than hopefully prove that the "other" state co-efficients are state-invariant? Are there solvers with special support for quadratic forms like that?

@serenity4
Copy link
Member

Also state_linear is a bit misleading. It's about the coefficient of the corresponding variable, which could be nonlinear in one of the other variables (or time).

I would argue that it is not misleading when considering the coefficient in isolation. The coefficient may exhibit a linear algebraic structure in a given quantity (time or another state), and we probably shouldn't consider transitive dependences yielded by these quantities. Otherwise, as you mention, a coefficient we label as time-independent but dependent on another state will most likely reflect a dependence to time through this state (unless trivially constant).

Nevertheless, it is not clear to me what the intent is given the discussion. Do we want to describe dependence and linearity information separately?

Base.@kwdef struct CoefficientInfo
    state_dependent::Bool = false # u₂, f(u₂)
    time_dependent::Bool = false # t, f(t)
    # parameter_dependent::Bool?
    any_nonlinear::Bool = false # nonlinear in any of the dependences, e.g. f(u₂) or f(t)
end
const nonlinear = CoefficientInfo(any_nonlinear = true)

Or do we want more precise linearity information for each category?

Base.@kwdef struct CoefficientInfo
    state_linear::Bool = false # u₂, f(t) * u₂
    time_linear::Bool = false # t, f(u₂) * t
    # parameter_linear::Bool?
end
const nonlinear = CoefficientInfo() # more like lack of linearity

Or something even more precise, where we express both linearity and dependence information?

# fields would need some renaming
Base.@kwdef struct CoefficientInfo
    # true: u₂, f(t) * u₂
    # false: f(u₂)
    # nothing: t, f(t)
    state_linear::Union{Bool,Nothing} = nothing
    # true: t, f(u₂) * t, 
    # false: f(t), f(t) * u₂
    # nothing: u₂, f(u₂)
    time_linear::Bool = nothing
    # parameter_linear::Bool?
end
# the notion of "nonlinear" is not well-defined, as it can imply the presence of
# one nonlinearity, or nonlinearity in all quantities.
const fully_nonlinear = CoefficientInfo(state_linear = false, time_linear = false)

@serenity4
Copy link
Member

(we can of course use an enum that represents a subset of all possibilities, but we need to figure out the internal structure for its semantics)

@Keno
Copy link
Member Author

Keno commented May 16, 2025

I'm not sure I understand the question

@serenity4
Copy link
Member

The question is, which of these representations would we want (if any)? They are not equivalent, each exposes a different set of information about the relationship between a coefficient and state/time quantities.

@Keno
Copy link
Member Author

Keno commented May 16, 2025

At this point, I don't think we care whether the coefficient itself is linear in the state or time. i.e. I don't think we need to distinguish t * u₂ and f(t) * u₂, we only care about dependence.

@serenity4
Copy link
Member

Great, that's exactly the information I was looking for, thanks.

@serenity4
Copy link
Member

For example, we should infer sin(u₁) u₂ as linear in u₂ and non-linear u₁. I'm not entirely sure how to print this in the Incidence printing, but perhaps we could underline the linear arguments.

Given that right now we print it as f(t, u₁, u₂), would it be correct/desirable to print the above example as f(u₁) * u₂ (i.e., make all linear quantities appear in an explicit product)? Otherwise, underlining sounds reasonable.

@Keno
Copy link
Member Author

Keno commented May 16, 2025

I think if we know that it's not state dependent, we should print it as fᵢ(t) * uᵢ if it's time dependent or pᵢ * uᵢ if it's not. I think if it's state dependent, we should do the underlying thing as long as we don't keep precise track of which state we're dealing with.

@Keno
Copy link
Member Author

Keno commented May 16, 2025

Actually, the problem with underlines is that it doesn't copy/paste, so we'd lose semantic information if somebody copies debug info into a bug report. Let's use the propto symbol as in f(t, ∝u₁, u₂).

@Keno
Copy link
Member Author

Keno commented May 22, 2025

Some more idle thoughts (not for the current PR, which we should finish in its current form), but if we did want to track the full matrix, we could potentially normalize to bilinear form by introducing additional variables (in the IPO representation primarily). I.e. if we see a * b *c, we would introduce an additional variable z and an equation z - b*c with the final incidence being a * z, similar to how we do the non-linear replacement right now.

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

No branches or pull requests

3 participants