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 <hake....@gmail.com> wrote: > On Tue, Sep 24, 2013 at 10:38 PM, Garth N. Wells <gn...@cam.ac.uk> wrote: > >> On 24 September 2013 21:24, Johan Hake <hake....@gmail.com> wrote: >> > On Tue, Sep 24, 2013 at 9:52 PM, Garth N. Wells <gn...@cam.ac.uk> >> wrote: >> >> >> >> On 24 September 2013 20:18, Anders Logg <l...@chalmers.se> 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 <hake....@gmail.com> 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 <l...@chalmers.se >> > >> >> >> 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 >> >> >> > fenics@fenicsproject.org >> >> >> > http://fenicsproject.org/mailman/listinfo/fenics >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> _______________________________________________ >> >> >> fenics mailing list >> >> >> fenics@fenicsproject.org >> >> >> http://fenicsproject.org/mailman/listinfo/fenics >> >> >> >> >> >> >> >> >> >> >> > _______________________________________________ >> >> > fenics mailing list >> >> > fenics@fenicsproject.org >> >> > http://fenicsproject.org/mailman/listinfo/fenics >> >> _______________________________________________ >> >> fenics mailing list >> >> fenics@fenicsproject.org >> >> 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 fenics@fenicsproject.org http://fenicsproject.org/mailman/listinfo/fenics