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
