Forms generated with adapt() can not be assembled

Bug #1124653 reported by Simon Funke
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
DOLFIN
Fix Released
Undecided
Marie Rognes

Bug Description

Hi,

I would like to assemble a form on two different meshes using the adapt() function.
Unfortunately, the objects that are generated by adapt can not be directly passed to the assembly function
as demonstrated below (code with tested on trunk):

from dolfin import *

mesh = UnitSquareMesh(2,2)
adapt(mesh)

V = FunctionSpace(mesh, "CG", 1)
u = TrialFunction(V)
w = TestFunction(V)

form = inner(u, w)*dx
dolfin_form = Form(form) # Ideally I would want to call adapt(form), but that does not work...
adapt(dolfin_form, mesh.child(), False)
print type(dolfin_form) # <class 'dolfin.fem.form.Form'> - as expected
print type(dolfin_form.child()) # <class 'dolfin.cpp.fem.Form'> - the type should not have changed
A1 = assemble(dolfin_form) # Does work.
A2 = assemble(dolfin_form.child()) # Does not work!

# Let's try and apply some boundary conditions
bc = DirichletBC(V, Constant(0), "on_boundary")
adapt(bc, mesh.child(), V.child())
print type(bc) # <class 'dolfin.fem.bcs.DirichletBC'> - as expected
print type(bc.child()) # <class 'dolfin.cpp.fem.DirichletBC'> - the type should not have changed
bc.apply(A1)
bc.child().apply(A2)

The error message I get is:

Traceback (most recent call last):
  File "adapt_test.py", line 16, in <module>
    A2 = assemble(dolfin_form.child()) # Does not work!
  File "/home/funsi/src/dolfin/local/lib/python2.7/site-packages/dolfin/fem/assembling.py", line 155, in assemble
    common_cell=common_cell)
  File "/home/funsi/src/dolfin/local/lib/python2.7/site-packages/dolfin/fem/form.py", line 63, in __init__
    self._compiled_form = form._compiled_form
AttributeError: 'Form' object has no attribute '_compiled_form'

Thanks,

Simon

Revision history for this message
Marie Rognes (meg-simula) wrote :

Hi Simon,

The underlying cause of this issue, and most other similar issues with adapt, is that adapt here accepts Python objects but the new, adapted objects are created in the C++ layer. The Python versions typically carry more information than the C++ objects, and this additional information is then not available for the adapted objects.

A fix would be to essentially reimplement most of the adapt functions in the Python interface. Johan, could you comment on whether this is a good idea?

Changed in dolfin:
status: New → Confirmed
assignee: nobody → Marie Rognes (meg-simula)
Revision history for this message
Simon Funke (simon-funke) wrote :

Hi Marie,

thanks for the clarification.

I can see these alternatives to avoid reimplementing the adapt functions in Python:

1) The key problem is that the adapted (child) C++ object misses some information required to convert it to a Python object. Is it possible that this information can be obtained from the "parent" Python object?

2) Maybe the C++ objects are even enough for my purposes. I want to adapt a rank-2 form, assemble it, apply a (adapted) Dirichlet BC on it and solve a linear system.

Any thoughts?

Simon

Revision history for this message
Johan Hake (johan-hake) wrote : Re: [Bug 1124653] Re: Forms generated with adapt() can not be assembled

Marie and Simon!

I think adding something like:

def adapt(...):

    ret = cpp.adapt(...)
    if isinstance(ret, cpp.FunctionSpace):
        from dolfin.functions.functionspace import FunctionSpaceFromCpp
        return = FunctionSpaceFromCpp(ret)
    elif isinstance(ret, cpp.Function):
        from dolfin.functions.function import Function
        return Function(HierarchicalFunction._leaf_node(self))
    aso...

should fix the issue. This fix is also in line with similar fixes for
leaf, parent and other Hierarchical methods

I can fix this once my trunk is compiling ;)

Johan

On 02/14/2013 04:12 PM, Marie Rognes wrote:
> Hi Simon,
>
> The underlying cause of this issue, and most other similar issues with
> adapt, is that adapt here accepts Python objects but the new, adapted
> objects are created in the C++ layer. The Python versions typically
> carry more information than the C++ objects, and this additional
> information is then not available for the adapted objects.
>
> A fix would be to essentially reimplement most of the adapt functions in
> the Python interface. Johan, could you comment on whether this is a good
> idea?
>
> ** Changed in: dolfin
> Status: New => Confirmed
>
> ** Changed in: dolfin
> Assignee: (unassigned) => Marie Rognes (meg-simula)
>

Revision history for this message
Martin Sandve Alnæs (martinal) wrote :
Download full text (4.1 KiB)

I havent looked at the code, but in principle I guess dolfin.Form could be
made working with a dolfin::Form for assembly. The information is all
there, it just has to be passed on to C++ when assembling. The dolfin.Form
code is a bit fragile though...

Martin
Den 15. feb. 2013 00:55 skrev "Johan Hake" <email address hidden>
følgende:

> Marie and Simon!
>
> I think adding something like:
>
> def adapt(...):
>
> ret = cpp.adapt(...)
> if isinstance(ret, cpp.FunctionSpace):
> from dolfin.functions.functionspace import FunctionSpaceFromCpp
> return = FunctionSpaceFromCpp(ret)
> elif isinstance(ret, cpp.Function):
> from dolfin.functions.function import Function
> return Function(HierarchicalFunction._leaf_node(self))
> aso...
>
> should fix the issue. This fix is also in line with similar fixes for
> leaf, parent and other Hierarchical methods
>
> I can fix this once my trunk is compiling ;)
>
> Johan
>
> On 02/14/2013 04:12 PM, Marie Rognes wrote:
> > Hi Simon,
> >
> > The underlying cause of this issue, and most other similar issues with
> > adapt, is that adapt here accepts Python objects but the new, adapted
> > objects are created in the C++ layer. The Python versions typically
> > carry more information than the C++ objects, and this additional
> > information is then not available for the adapted objects.
> >
> > A fix would be to essentially reimplement most of the adapt functions in
> > the Python interface. Johan, could you comment on whether this is a good
> > idea?
> >
> > ** Changed in: dolfin
> > Status: New => Confirmed
> >
> > ** Changed in: dolfin
> > Assignee: (unassigned) => Marie Rognes (meg-simula)
> >
>
> --
> You received this bug notification because you are a member of DOLFIN
> Core Team, which is subscribed to DOLFIN.
> https://bugs.launchpad.net/bugs/1124653
>
> Title:
> Forms generated with adapt() can not be assembled
>
> Status in DOLFIN:
> Confirmed
>
> Bug description:
> Hi,
>
> I would like to assemble a form on two different meshes using the
> adapt() function.
> Unfortunately, the objects that are generated by adapt can not be
> directly passed to the assembly function
> as demonstrated below (code with tested on trunk):
>
> from dolfin import *
>
> mesh = UnitSquareMesh(2,2)
> adapt(mesh)
>
> V = FunctionSpace(mesh, "CG", 1)
> u = TrialFunction(V)
> w = TestFunction(V)
>
> form = inner(u, w)*dx
> dolfin_form = Form(form) # Ideally I would want
> to call adapt(form), but that does not work...
> adapt(dolfin_form, mesh.child(), False)
> print type(dolfin_form) # <class
> 'dolfin.fem.form.Form'> - as expected
> print type(dolfin_form.child()) # <class
> 'dolfin.cpp.fem.Form'> - the type should not have changed
> A1 = assemble(dolfin_form) # Does work.
> A2 = assemble(dolfin_form.child()) # Does not work!
>
> # Let's try and apply some boundary conditions
> bc = DirichletBC(V, Constant(0), "on_boundary")
> adapt(bc, mesh.child(), V.child())
> print type(bc) ...

Read more...

Revision history for this message
Johan Hake (johan-hake) wrote :

Yeah, I think you are right Martin. All the logic to create a
dolfin.Form from a cpp.Form is based on the latter being created in the
present python session. But as you say we do not have to create a
dolfin.Form as all the information is contained within the cpp.Form
adapt return. Can you try if the pasted patch fix your problem. It fixes
your script, but I guess you have other problems to throw it at ;)

Johan

=== modified file 'site-packages/dolfin/fem/assembling.py'
--- site-packages/dolfin/fem/assembling.py 2013-02-13 15:18:13 +0000
+++ site-packages/dolfin/fem/assembling.py 2013-02-15 08:01:05 +0000
@@ -147,12 +147,20 @@
     # Extract common cell from mesh (may be missing in form definition)
     common_cell = None if mesh is None else mesh.ufl_cell()

- # Wrap form
- dolfin_form = Form(form,
- function_spaces=function_spaces,
- coefficients=coefficients,
- form_compiler_parameters=form_compiler_parameters,
- common_cell=common_cell)
+ # First check if we got a cpp.Form which originates from cpp layer
+ if isinstance(form, cpp.Form) and not hasattr(form, "_compiled_form"):
+
+ # Then we just try to use that one
+ dolfin_form = form
+
+ else:
+
+ # Wrap form
+ dolfin_form = Form(form,
+ function_spaces=function_spaces,
+ coefficients=coefficients,
+
form_compiler_parameters=form_compiler_parameters,
+ common_cell=common_cell)

     # Set mesh if specified (important for functionals without a
function spaces)
     if mesh is not None:

Revision history for this message
Marie Rognes (meg-simula) wrote :

On 02/15/2013 12:48 AM, Johan Hake wrote:
> I can fix this once my trunk is compiling;)

Great, thanks! (Which ever way you decide to fix it :-) )

--
Marie

Revision history for this message
Simon Funke (simon-funke) wrote :

Hi Johann,

the changes that you proposed for dolfin/fem/assembling.py fixes the problem!

Thanks very much for that - I hope this will be one of the last hurdles for multigrid optimisation in dolfin-adjoint.

Simon

Revision history for this message
Johan Hake (johan-hake) wrote :

Cool!

Looks like I accidentally pushed the fixed in rev 7340 :)

Johan

Changed in dolfin:
status: Confirmed → Fix Committed
milestone: none → 1.1.1
Johannes Ring (johannr)
Changed in dolfin:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.