-
Notifications
You must be signed in to change notification settings - Fork 24
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
Block operators / solvers #96
Comments
Thanks for opening this issue -- I think you've hit pretty much all the major points I can think of, and also touched on several I hadn't, like vmap'ing blocks! Some initial comments:
It's not clear to me why we'd need
It sounds like this is an attempt to represent a block operator as something other than a list-of-list-of-operators. (Itself then wrapped into a FWIW we don't have to make a single choice here. Whilst we should certainly minimise the amount we create, if we need to them we can create multiple
This sounds really tough. I think figuring out what is optimal here is probably the main thing we still need to do.
I think this is probably doable by vmap'ing the creation, then indexing into them, then passing those into the That said we could consider the option of allowing a component linear operator to span multiple blocks, e.g.
for which such adjacencies are really the only scenario I can consider in which it might be advantageous not split things up.
For For the solver for the overall block operator: I think we should expect each block structure to have its own solver, which is free to do anything it likes. For example something like this: class BlockLinearOperator(AbstractLinearOperator):
operators: list[list[AbstractLinearOperator]]
...
op = BlockLinearOperator([[FooLinearOperator(), ZeroLinearOperator()], [ZeroLinearOperator(), BarLinearOperator()]])
linear_solve(op, vec, solver=BlockDiagonal()) and in particular note that there are no "tags" needed for For example WDYT? |
Following the discussion in #80 I thought it would be good to lay out some ideas for a general block matrix/operator abstraction.
Some useful types of block operators:
I think the more powerful capability is if we allow block operators where each block itself can be an arbitrary
LinearOperator
including nested block operators. This would allow for a pretty expressive API that could represent most structured sparsity patterns that commonly arise when discretizing PDEs and lots of other applications.Doing the latter would likely require a few things:
InverseLinearOperator
abstraction, that wraps another linear operator such thatInverseLinearOperator(operator).mv(x) == linear_solve(operator, x)
linear_solve
to accept an operator as the RHS, such thatlinear_solve(operator1, operator2) -> ComposedLinearOperator(InverseLinearOperator(operator1), operator2)
These would allow us to symbolically/algorithmically invert an arbitrary block operator without having to know the specifics of what each block is.
Some other thoughts:
a dense array with some special indexing to avoid having to store blocks of zeros. This is nice because arrays can be scanned/vmapped etc.
LinearOperators
than we might have to resort to lists of blocks, which (generally?) can't be scanned/vmapped as easily, so compile times might be longer? This might not be too bad if we generally assume that block_size >> num_blocks.AutoLinearSolver
but we may want to add some new tags to indicate thatAutoLinearSolver
use an iterative method in some cases etc? Or maybe havesolver
similarly be a blocked/pytree type thing allowing the user to specify which solver to use at each level/block of the operatorThe text was updated successfully, but these errors were encountered: