Refactor preprocessing and its use in ffc
For several reasons the preprocessing needs to change significantly.
One reason is to reduce the overhead of symbolic computations in dolfin programs by minimizing the amount of processing done before a jit signature is computed and the information needed by dolfin assembly is available. Preprocessing in form.compute_form_data() should only include this minimal amount of symbolic processing. This symbolic overhead is particularly damaging in programs relying on large amounts of form generation, such as dolfin-adjoint programs, with non-trivial forms.
Another reason is that form compilers (read: uflacs) may want to do things slightly differently from what vanilla ffc does and some of the processing in preprocess() should therefore be moved to the form compiler analysis stage.
Comments (11)
-
reporter -
reporter The best course of action seems to be
- Implement a new preprocess function doing the minimal amount of work
- Transition dolfin and ffc to use this function
- Implement a stage 2 preprocess function to produce the additional form data needed by ffc to compile a form
-
reporter Here's an initial implementation of a new minimal preprocess function.
from ufl import * from ufl.algorithms.analysis import extract_terminals from ufl.algorithms.signature import compute_form_signature def preprocess2(form): domains = form.domains() subdomain_data = {} for domain in domains: l = domain.label() subdomain_data[l] = {} for integral in form.integrals(): l = integral.domain().label() t = integral.integral_type() data = subdomain_data[l].get(t) if data is None: data = integral.subdomain_data() subdomain_data[l][t] = data else: assert data.ufl_id() == integral.subdomain_data().ufl_id() terminals = extract_terminals(form) arguments = [] coefficients = [] for t in terminals: if isinstance(t, Argument): arguments.append(t) elif isinstance(t, Coefficient): coefficients.append(t) domains = sorted(domains, key=lambda x: x.label()) arguments = sorted(arguments, key=lambda x: x.number()) coefficients = sorted(coefficients, key=lambda x: x.count()) domain_numbering = dict((d,i) for i,d in enumerate(domains)) coefficient_numbering = dict((c,i) for i,c in enumerate(coefficients)) # Temporary solution: function_replace_map = dict((c, c.reconstruct(count=i)) for c,i in coefficient_numbering.items()) signature = compute_form_signature(form, function_replace_map) # Better solution: #signature = compute_form_signature2(form, domain_numbering, coefficient_numbering) return signature, domains, subdomain_data, arguments, coefficients
I'd like to get the 1.4 release out first, then make dolfin.Mesh subclass ufl.Domain and see how that affects handling of domains here, then get this in place.
-
reporter Preliminary work in
https://bitbucket.org/fenics-project/ufl/branch/martinal/topic-redesign-form-preprocessing-mechanism
This will be more merged into the Form class, making data available directly as form.coefficients(), form.arguments(), form.domains(), form.signature(), all computed when required and cached with the form object.
Next steps:
- (DONE) Implement a modified ufl.preprocess to build a FormData object based on the data now available directly from Form.
- (DONE) Change ffc to call the new preprocess only if a cached module was not found in jit.
- (DONE) Change dolfin to use new form.* accessors instead of going via form_data.
- (DONE) Remove ufl.Form.[compute_]form_data().
-
reporter The ffc side turns out to be trivial, the part that's hard to get a grasp on is the dolfin.Form use cases:
https://bitbucket.org/fenics-project/dolfin/issue/306/simplify-dolfinform-by-removing-arguments
-
reporter The ufl side of this is currently blocked by this issue: https://bitbucket.org/fenics-project/ufl/issue/37/
-
reporter Next: Test ufl/ffc branches in concert with fix to dolfin issue 306 when that is ready (after 1.4).
-
reporter All tests in ufl, ffc, dolfin now pass with the following branches:
https://bitbucket.org/fenics-project/ufl/branch/martinal/topic-redesign-form-preprocessing-mechanism
https://bitbucket.org/fenics-project/ffc/branch/martinal/topic-redesign-form-preprocessing-mechanism
The plan is to merge after the 1.4 release.
-
reporter In next.
-
reporter - changed status to resolved
-
reporter - removed milestone
Removing milestone: 1.5 (automated comment)
- Log in to comment
Based on some source code searching, the minimal form data object needs:
Snippets of form_data usage in DOLFIN:
Snippets of form_data usage in FFC if a pre-jitted module is found: