Basic operator composition #67
Basic operator composition #67
Conversation
src/DiffEqOperators.jl
Outdated
abstract type AbstractDerivativeOperator{T} <: DiffEqBase.AbstractDiffEqLinearOperator{T} end | ||
abstract type AbstractDerivativeOperator{T} <: AbstractDiffEqLinearOperator{T} end | ||
|
||
struct DEFAULT_UPDATE_FUNC end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why make it an overloaded singleton instead of a function?
Good choice. |
Some notes before moving on:
|
Ah and also I'm keeping the "AbstractDiffEqCompositeOperator" name for now. The "Abstract" should be enough to distinguish this from the concrete operator composition type. |
All good ideas. |
A thought: if you associate with each type a "description" and a "default symbol" then you could recursively walk the tree and display as a typical linear non-commutative structure. For example,
alpha = DiffEqScalar(2.0)
A = DiffEqArrayOperator(rand(2,2))
A2 = DiffEqArrayOperator(rand(2,2))
update_func = ...
B = DiffEqArrayOperator(rand(2,2); update_func=update_func)
D = DifferentialOperator(1, :forward) #or whatever those are called/
L = alpha * (A + A2) + B + D Then you could traverse the tree (numbering them with subscripts arbitrarily) to display this as
|
I like this idea! I think a further improvement could be to use multi-index the deeper the tree goes, so in your example Definitely want to try my hands on this. Seems to be a good change of style from what I've been doing the past few weeks ;) |
I still need to add some documentation and tests but this should cover all the basic compositions. In particular all arithmetics operations on the operators (including left division, Like I said about the decision to remove the decision in (By the way, in v0.7 |
Very good point. That will likely make a lot of things easier. |
For named tuples: If you are creating a lot of variations on parameters, where having defaults would be useful, then note that It is pretty slick and works with 0.6 and 0.7. I suspect that Mauro will release something soon if you need it. I also think that it is worth being dependent on the package just to use that and the |
The common default methods for the composite operators are now promoted for all of `AbstractDiffEqLinearOperators`. This allows major simplifications especially for the basic operators.
@@ -0,0 +1,94 @@ | |||
struct DiffEqIdentity{T,N} <: AbstractDiffEqLinearOperator{T} end | |||
DiffEqIdentity(u) = DiffEqIdentity{eltype(u),length(u)}() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we need this in DiffEqBase to be the default mass matrix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so.
Tests are now finished. @ChrisRackauckas do you think it's ok to close this PR for now and create a new release for DiffEqOperators? I know there are still a ton of depwarns for the derivative operators part but I want to focus on jacobians in OrdinaryDiffEq for the moment, the basis of which should be covered by this PR. |
Yup don't worry about the depwarns. I'll get femtocleaner to work through them. |
The aim is to implement the most basic subset of #60 so that basic operator compositions like addition and multiplication can be constructed, which would then enable the implementation of lazy jacobian/W operator from SciML/DifferentialEquations.jl#220.
The main improvement I'm considering is how to implement
DiffEqOperatorCombination
. The prototype in the notebook is still influenced by LinearMaps.jl in that both the component operators and their coefficients are stored. While this is perfectly fine for LinearMaps where the coefficients are constant, it would become a bit messy if we allow the coefficients to also be time-dependent. For example, in the notebook I need to also include anupdate_func
for the coefficients in addition to the update functions of the component operators.My solution to this is to add an additional type
DiffEqScaledOperator
, which is constructed by multiplying aDiffEqScalar
and another operator. The coefficients inDiffEqOperatorCombination
will be dropped. For example, a composite operator constructed asL = a * A + B
for will be constructed asIn this way, calling
update_coefficients!
to a composite operator, however complex it is, boils down to doing a tree transversal and calling the embedded update functions only on the leaf nodes (in the above case:DiffEqScalar(a)
,A
andB
).I have also added a
setval!
method to the scalar and array operators as a way to bypass theupdate_coefficients!
interface and directly mutate their value. This should be used sparsely and only in situation where outside information other than(u,p,t)
is needed to update the operator (for example,dt
for theW
operator).Finally, since
full
is deprecated in v0.7 I have switched to usingMatrix(L)
. For theas_array
function in the notebook, maybeconvert(::AbstractArray, L)
?