Great! This will be very useful.

Martin


On 8 November 2013 16:15, Johan Hake <[email protected]> wrote:

> I now have a working implementation of sub function assignment.
>
>
> https://bitbucket.org/fenics-project/dolfin/pull-request/60/subfunction-assignment
>
> It uses the proposed FunctionAssigner class. It is pretty powerfull, as
> the added unit test shows.
>
> I have added a free function assign which makes the following possible:
>
>   mesh = UnitSquareMesh(10,10)
>   V = FunctionSpace(mesh, "CG", 1)
>   VV = VectorFunctionSpace(mesh, "CG", 1)
>
>   U = Function(VV)
>   u0, u1 = Function(V), Function(V)
>
>   assign(U.sub(0), u0) # 1-1
>   assign(U, [u0, u1])  # N-1
>   assign([u0, u1], U)  # 1-N
>
> The FunctionAssigner class can be used to cache dof indices for the
> assignment, speeding up each assignment considerably. The above assignments
> would then be:
>
>   assigner_1_1.FunctionAssigner(VV.sub(0), V)
>   assigner_N_1.FunctionAssigner(VV, [V,V])
>   assigner_1_N.FunctionAssigner([V,V], VV)
>
>   assigner_1_1.assign(U.sub(0), u0) # 1-1
>   assigner_N_1.assign(U, [u0, u1])  # N-1
>   assigner_1_N.assign([u0, u1], U)  # 1-N
>
> To be able to implement this I needed to make sub dofmaps carry the
> ownership range from the parent dofmap. This might introduce some
> regressions. I have fixed at least 2 picked up by the unit tests. To
> determine if a dofmap is a view or not I just added a private flag which is
> set during construction of the sub dofmap.
>
> I hope this might be of interest.
>
> Johan
>
>
> On Tue, Sep 24, 2013 at 10:50 PM, Johan Hake <[email protected]> wrote:
>
>> On Tue, Sep 24, 2013 at 10:38 PM, Garth N. Wells <[email protected]> wrote:
>>
>>>  On 24 September 2013 21:24, Johan Hake <[email protected]> wrote:
>>> > On Tue, Sep 24, 2013 at 9:52 PM, Garth N. Wells <[email protected]>
>>> wrote:
>>> >>
>>> >> On 24 September 2013 20:18, Anders Logg <[email protected]> wrote:
>>> >> > Yes, I like DofMapToDofMapMapping much better.
>>> >> >
>>> >>
>>> >> I like the design, much the name looks horrible! :-)
>>> >
>>> >
>>> > What design? A class that hold the mapping between 1-N,N-1,1-1
>>> dofmaps? If
>>> > so I agree.
>>>
>>> Yes. The simple C++ approach is to just use a map class, but this is
>>> hard wrap in Python.
>>
>>
>> How would you use a map class in C++ that is general enough to hold the
>> three mappings?
>>
>> Also for this to make any sense in a function assignment setting the
>> mapping, really the dofs for each function/subfunction, need to be
>> contiguous arrays that can be used efficiently in
>> GenericVector::{get_local,set_local} calls.
>>
>> Johan
>>
>>
>>  > But it is not clear to me what you think the syntax for the
>>> > assignment statement should be.
>>> >
>>> > I do not think:
>>> >
>>> >   dmtdmm = DofMapToDofMapMapping([V,V,V], VV)
>>> >   assign([u0,u1,u2],u, dmtdmm)
>>> >
>>> > is better than for example:
>>> >
>>> >   dmtdmm = DofMapToDofMapMapping([V,V,V], VV)
>>> >   dmtdmm.assign([u0,u1,u2],u)
>>> >
>>>
>>> The former is better because if 'DofMapToDofMapMapping' is just about
>>> the relationship between dofmaps, in clean design it shouldn't know
>>> about Functions.
>>> Garth
>>>
>>> > The first is similar to what Martin suggested and the latter is
>>> basically
>>> > what I first suggested with a different naming.
>>> >
>>> >
>>> > We can still support a more general free function:
>>> >
>>> >   assign([u0,u1,u2],u)
>>> >
>>> > where a DofMapToDofMapMapping is created inside the assign function
>>> and then
>>> > discarded.
>>> >
>>> >> > My suggestion for a short name would be
>>> >> >
>>> >> >   DofMapTransformation
>>> >> >
>>> >>
>>> >> I don't like this name - it doesn't make clear that if defined a
>>> >> relationship between two domps.
>>> >
>>> >
>>> > Agree. No dofmaps are transformed.
>>> >
>>> >  I don't have a good name suggestion just yet, but maybe we should
>>> >>
>>> >> raise the abstraction. A dofmap is a type of graph, and what we want
>>> >> is the relationship between a graph and some subgraph (related to
>>> >> this, I'd like to use a more graph-centric approach in DofMapBuilder
>>> >> to simplify it and to extend the functionality).
>>> >
>>> >
>>> > Sounds good. I suppose a general mapping class between dofmaps could be
>>> > useful for different cases. However, I am not sure what these cases
>>> are, and
>>> > I have therefor difficulties envision how such class should be
>>> looking. I
>>> > have one particular task in mind, and for that I need a mapping between
>>> > 1-N,N-1,1-1 dofmaps.
>>> >
>>> >>
>>> >> > Yes, BoundingBoxTree has a lot of methods but it is an
>>> implementation
>>> >> > detail that the methods are actually implemented as part of the
>>> >> > BoundingBoxTree class hierarchy (and not outsourced to algorithm
>>> >> > classes as we do in other places).
>>> >>
>>> >
>>> > And what is the difference? Couldn't an assign method be implemented
>>> as part
>>> > of a DofMapToDofMapMapping class?
>>> >
>>> >  > I just want to stay away from the horror in
>>> dolfin/common/unittest.h:
>>> >>
>>> >> >
>>> >> >   CppUnit::TestResult result;
>>> >> >   CppUnit::TestResultCollector collected_results;
>>> >> >   result.addListener(&collected_results);
>>> >> >   CppUnit::TestRunner runner;
>>> >> >
>>> >> >
>>> runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
>>> >> >   runner.run(result);
>>> >> >   CppUnit::CompilerOutputter outputter(&collected_results,
>>> std::cerr);
>>> >> >   outputter.write ();
>>> >> >   return collected_results.wasSuccessful () ? 0 : 1;
>>> >
>>> >
>>> > I think this example is just stupid. It has nothing to do with what I
>>> > suggested. As I said we can hide the instantiation of the class within
>>> a
>>> > free function for people who wants to solve a problem with a small
>>> script
>>> > with nice syntax. I suggest adding a useful class that solves a
>>> problem many
>>> > has requested in an elegant way.
>>> >
>>> >> > Adding FunctionAssigner is just one class but it's a slippery
>>> >> > slope... :-)
>>> >
>>> >
>>> > The slope is as slippery as adding DOLFIN_EPS_LARGE, which easily
>>> could lead
>>> > to the addition of DOLFIN_EPS_NOT_SO_LARGE ;)
>>> >
>>> > Johan
>>> >
>>> >
>>> >>
>>> >> > --
>>> >> > Anders
>>> >> >
>>> >> >
>>> >> > On Tue, Sep 24, 2013 at 10:44:05AM +0200, Martin Sandve Alnæs wrote:
>>> >> >> Would you agree that that the BoundingBoxTree represents data
>>> >> >> associations, not
>>> >> >> an operation, similar to my just-now suggestion
>>> DofMapToDofMapMapping
>>> >> >> instead
>>> >> >> of FunctionAssigner? An object that represents the mapping could
>>> >> >> conceivably be
>>> >> >> useful for operations other than assign as well.
>>> >> >>
>>> >> >> Martin
>>> >> >>
>>> >> >>
>>> >> >> On 24 September 2013 10:39, Johan Hake <[email protected]> wrote:
>>> >> >>
>>> >> >>     Well, we have the BoundingBoxTree, which similarly caches data
>>> that
>>> >> >> speed
>>> >> >>     up certain operations. We also have a Solver class and a free
>>> >> >> function
>>> >> >>     solve, an Assembler class and a free function assemble.
>>> Similarly
>>> >> >> we could
>>> >> >>     have a free function assign, which construct a FunctionAssign
>>> >> >> object.
>>> >> >>     However there is a lot of data which could be reused in the
>>> >> >> FunctionAssign
>>> >> >>     object. If a user want to utelize that he should instantiate
>>> the
>>> >> >> object and
>>> >> >>     use that in his code.
>>> >> >>
>>> >> >>     Johan
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >>     On Tue, Sep 24, 2013 at 10:27 AM, Anders Logg <
>>> [email protected]>
>>> >> >> wrote:
>>> >> >>
>>> >> >>         Is it possible to solve this without introducing the design
>>> >> >> pattern
>>> >> >>         with a class FunctionAssigner? We have been careful to
>>> avoid
>>> >> >> this in
>>> >> >>         other places.
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >>         On Mon, Sep 23, 2013 at 07:20:03PM +0200, Johan Hake wrote:
>>> >> >>         > I am working on sub-function assignment. To facilitate
>>> >> >> caching of dof
>>> >> >>         indices
>>> >> >>         > for a particular assignment combination I suggest
>>> introducing
>>> >> >> a
>>> >> >>         > FunctionAssigner class which caches the necessary indices
>>> >> >> (dofs) for
>>> >> >>         the whole
>>> >> >>         > domain.
>>> >> >>         >
>>> >> >>         > Something like:
>>> >> >>         >
>>> >> >>         >   mesh = UnitSquareMesh(10,10)
>>> >> >>         >   V = FunctionSpace(mesh, "CG", 1)
>>> >> >>         >   VV = V*V
>>> >> >>         >
>>> >> >>         >   # Assign two scalar functions to the components of a
>>> mixed
>>> >> >> function
>>> >> >>         >   assigner0 = FunctionAssigner([V, V], VV)
>>> >> >>         >
>>> >> >>         >   # Assign components of a mixed function to scalar
>>> Functions
>>> >> >>         >   assigner1 = FunctionAssigner(VV, [V, V])
>>> >> >>         >
>>> >> >>         >   # Assign a scalar function to a component of a mixed
>>> >> >> function
>>> >> >>         >   assigner2 = FunctionAssigner(V, VV.sub(1))
>>> >> >>         >
>>> >> >>         >   u0, u1 = Function(V), Function(V)
>>> >> >>         >   U = Function(VV)
>>> >> >>         >
>>> >> >>         > Then in some time loop:
>>> >> >>         >
>>> >> >>         >   while t < tstop:
>>> >> >>         >       ...
>>> >> >>         >       assigner0.assign([u0, u1], U)
>>> >> >>         >       ...
>>> >> >>         >       assigner1.assign(U, [u0, u1])
>>> >> >>         >       ...
>>> >> >>         >       assigner2.assign(u0, U.sub(1))
>>> >> >>         >
>>> >> >>         > In C++ the equivalent to a list of Foo will be a
>>> std::vector
>>> >> >> of
>>> >> >>         shared Foos.
>>> >> >>         >
>>> >> >>         > Comments?
>>> >> >>         >
>>> >> >>         > By using sub spaces and sub functions we avoid using
>>> indices
>>> >> >> in the
>>> >> >>         interface,
>>> >> >>         > which I think is neat. However, there are some
>>> limitations
>>> >> >> with the
>>> >> >>         present
>>> >> >>         > interface:
>>> >> >>         >
>>> >> >>         > 1) The FunctionAssigner needs to have access to the local
>>> >> >> ownership
>>> >> >>         range of a
>>> >> >>         > sub dofmap, but that is not possible as it is set to 0,0
>>> >> >> during
>>> >> >>         construction.
>>> >> >>         > Could we add a proper local ownership range to a sub
>>> dofmap?
>>> >> >>         > 2) The FunctionAssigner need to be able to access the
>>> private
>>> >> >> _vector
>>> >> >>         of a
>>> >> >>         > parent Function during the assignment, as calling
>>> >> >> subfunc.vector()
>>> >> >>         raises an
>>> >> >>         > error. This can be fixed by a friend statement. Is that
>>> >> >> acceptable?
>>> >> >>         >
>>> >> >>         > Johan
>>> >> >>
>>> >> >>         > _______________________________________________
>>> >> >>         > fenics mailing list
>>> >> >>         > [email protected]
>>> >> >>         > http://fenicsproject.org/mailman/listinfo/fenics
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >>     _______________________________________________
>>> >> >>     fenics mailing list
>>> >> >>     [email protected]
>>> >> >>     http://fenicsproject.org/mailman/listinfo/fenics
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> > _______________________________________________
>>> >> > fenics mailing list
>>> >> > [email protected]
>>> >> > http://fenicsproject.org/mailman/listinfo/fenics
>>> >> _______________________________________________
>>> >> fenics mailing list
>>> >> [email protected]
>>> >> http://fenicsproject.org/mailman/listinfo/fenics
>>>
>>>
>>>
>>> --
>>> Garth N. Wells
>>> Department of Engineering, University of Cambridge
>>> http://www.eng.cam.ac.uk/~gnw20
>>>
>>
>>
>
> _______________________________________________
> fenics mailing list
> [email protected]
> http://fenicsproject.org/mailman/listinfo/fenics
>
>
_______________________________________________
fenics mailing list
[email protected]
http://fenicsproject.org/mailman/listinfo/fenics

Reply via email to