Cleanup of python assemble
To fix this issue,
https://bitbucket.org/fenics-project/ufl/issue/7/get-rid-of-arguments-to-compute_form_data
the assemble/jit pipeline in dolfin will probably need some cleanup.
This code is really hard to follow and likely contains lot of unknown corner case bugs. There are so many possible code paths that are non-obvious and not tested that it's not feasible to preserve all possible use cases of today. It is therefore likely that some user interface regressions will be necessary.
We need to identify which features need to be preserved in the python assemble interface, so we can design a new, cleaner, and better tested implementation.
Comments (14)
-
reporter -
reporter What is the use case for passing a dolfin::Form to assemble?
Is it used for controlled "pre-jitting"? That may be important.
The code says: "First check if we got a cpp.Form which originates from cpp layer", is that an actual use case?
-
Yes, 'pre-jitting' can be important.
-
The ufc::form is something we have kept for ages. Going back to when someone (TM) needed to compile pure ufc forms.
The dolfin::Form is needed so we can assemble a:
aform = adapt(form)
The hierarchical interface of dolfin returns an adapted dolfin::Form, which contains everything it needs to be assemble.
-
reporter Use cases for passing mesh to assemble:
-
The integrand has no mesh, e.g.
Expression("x[0]")*dx().
Possible to handle by attaching mesh to measure? E.g.
Expression("x[0]")*dx(mesh)
or similar syntax.
-
The form is assembled for multiple meshes. Possible to handle by letting the user create a new or modify an existing dolfin::Form and passing that to assemble.
-
-
reporter Use cases for passing foo_domains to assemble:
- The form has no domains attached to its mesh or measures.
- The form is assembled for multiple sets of foo_domains. Probably rare.
Both cases above are possible to handle by letting the user create a new or modify an existing dolfin::Form and passing that to assemble.
-
I think dealing with dolfin::Forms should be for advanced use cases. I think reassemble any form on different mesh should be a common use case not demanding fiddling with dolfin::Form.
-
reporter Use cases for passing a dolfin::Form to assemble:
- Assembling forms from the C++ interface, e.g.: aform = adapt(form)
- Controlled pre-jitting for optimization.
- Reusing UFL form with different meshes.
- Reusing UFL form with different subdomain markers.
- Reusing UFL form with different coefficients.
- (Wrapping a UFC form?)
I see a pattern...
-
reporter Ok, so we want to keep
assemble(M, mesh=mesh)
which I guess a lot of existing code is doing. It's not possible to make this feature work with
assemble(M, mesh=mesh1d) assemble(M, mesh=mesh2d)
which is currently broken, while simultaneously keeping the memoization of compute_form_data to avoid rebuilding the preprocessed form every time.
I therefore suggest the following: Passing mesh or foo_domains arguments to assemble:
assemble(M, mesh=mymesh, cell_domains=mydomains)
behaves like this:
M2 = reconstruct_form(M, mesh=mymesh, cell_domains=mydomains) assemble(M2)
where reconstruct_form is a new utility function that builds a new Form object by reusing the integrands but creating new measures with the given mesh and domains replacing the old. I think an error should be raised if the integrands contain coefficients whose function spaces have conflicting meshes.
The original form is then untouched, and
assemble(M, mesh=mesh1d) assemble(M, mesh=mesh2d)
will work. The cost is that symbolic preprocessing will always be repeated when mesh or domains are passed to assemble, but jitting will still hit the instant cache.
Symbolic preprocessing (compute_form_data) can still be cached for all cases where mesh and domains are attached to the measures in the original form. Any code today that does
assemble(f*dx)
instead of
M = f*dx assemble(M)
is not getting caching of symbolic preprocessing anyway.
Attaching the mesh to measures is not a current feature, but something we've (I've?) been contemplating for multidomain support. The syntax may need a little bit of thought.
-
reporter I've done some cleaning up of the python assemble function in a branch that I can't merge right away.
-
reporter -
assigned issue to
-
assigned issue to
-
- changed milestone to 1.4
-
reporter - changed status to duplicate
Duplicate of
#190. -
- removed milestone
Removing milestone: 1.4 (automated comment)
- Log in to comment
What is the use case for passing a ufc::form to assemble? Earlier it was used by sfc integration tests with dolfin. Can we safely ignore it now?