Anders Logg wrote: > On Thu, Mar 12, 2009 at 05:41:42PM +0100, Martin Sandve Alnæs wrote: >> On Thu, Mar 12, 2009 at 5:26 PM, Anders Logg <[email protected]> wrote: >>> On Thu, Mar 12, 2009 at 04:59:43PM +0100, Martin Sandve Alnæs wrote: >>>> On Thu, Mar 12, 2009 at 4:33 PM, Anders Logg <[email protected]> wrote: >>>>> On Thu, Mar 12, 2009 at 01:42:55PM +0100, Martin Sandve Alnæs wrote: >>>>>> On Thu, Mar 12, 2009 at 1:16 PM, Johan Hake <[email protected]> wrote: >>>>>>> On Thursday 12 March 2009 12:58:33 Garth N. Wells wrote: >>>>>>>> Anders Logg wrote: >>>>>>>>> On Thu, Mar 12, 2009 at 10:46:14AM +0100, Martin Sandve Alnæs wrote: >>>>>>>>>> On Thu, Mar 12, 2009 at 10:32 AM, Anders Logg <[email protected]> wrote: >>>>>>>>>>> On Thu, Mar 12, 2009 at 10:25:36AM +0100, Martin Sandve Alnæs wrote: >>>>>>>>>>>> I have serious problems with the idea of letting user-defined >>>>>>>>>>>> functions change nature to discrete functions as a side effect >>>>>>>>>>>> of other operations, effectively hiding the user-defined >>>>>>>>>>>> implementation of eval. >>>>>>>>>>>> >>>>>>>>>>>> (I know this concept wasn't introduced in this discussion, but it's >>>>>>>>>>>> related). >>>>>>>>>>> You mean by calling u.vector()? Yes, I agree it's problematic. >>>>>>>>>>> >>>>>>>>>>> But I don't know how to handle it otherwise. Consider the following >>>>>>>>>>> example: >>>>>>>>>>> >>>>>>>>>>> u = Function(V) >>>>>>>>>>> solve(A, u.vector(), b) >>>>>>>>>>> >>>>>>>>>>> First u is a user-defined function since it doesn't have a >>>>>>>>>>> vector. Then it becomes discrete when we ask for the vector. >>>>>>>>>>> >>>>>>>>>>> The problem I think is that there is no way for us to check whether >>>>>>>>>>> a >>>>>>>>>>> user has overloaded eval() without trying to call it. >>>>>>>>>> If we didn't require that user-defined functions had a function space >>>>>>>>>> for various operations, this wouldn't be as large a problem. >>>>>>>>>> Then you could do >>>>>>>>>> >>>>>>>>>> class MyFunction(Function) >>>>>>>>>> { >>>>>>>>>> MyFunction(V): Function(V) {} >>>>>>>>>> MyFunction(): Function() {} >>>>>>>>>> void eval(...) { ... } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> MyFunction f; >>>>>>>>>> f.vector(); // error, no function space! >>>>>>>>>> >>>>>>>>>> MyFunction f(V); >>>>>>>>>> f.vector(); // ok, should interpolate and make f discrete >>>>>>>>>> >>>>>>>>>> This is already possible, but function spaces get attached >>>>>>>>>> unneccesarily: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> 1) It's not necessary to attach function spaces to functions for >>>>>>>>>> assembly, since a user-defined function is evaluated through >>>>>>>>>> ufc::finite_element::evaluate_dofs for each cell anyway. >>>>>>>>>> This would remove the need for the side-effect in >>>>>>>>>> >>>>>>>>>> MyFunction f; >>>>>>>>>> MyForm a; >>>>>>>>>> a.f = f; // attaches function space to f >>>>>>> Isn't the function space used to deduct the value rank during assemble >>>>>>> now? If >>>>>>> we go for this approach we probably need to readd the rank function and >>>>>>> make >>>>>>> it virtual? >>>>>> I don't see how the current approach with rank deducted from >>>>>> some function space is any safer than deducting it from the >>>>>> finite element of the form. Which is to say: this is unsafe, the >>>>>> user should define the rank when defining eval. >>>>> We just removed the rank() and dim() arguments from the Function >>>>> interface as they are not needed. >>>> Are not needed because a Function always has a FunctionSpace >>>> or for some other reason? If we don't require a FunctionSpace >>>> I think they should be re-added. I expect to be able to use a Function >>>> for other things than assembly, e.g., if I get some arbitrary Function >>>> to some code: >>>> >>>> void foo(Function & f) >>>> { >>>> ... compute something with f >>>> } >>>> >>>> I can't know the dimensions of arguments to f. >>>> This means I can't write generic code to do something with Functions. >>> One of the simplifying assumptions we made a while back when >>> redesigning the Function classes was that a Function always has a >>> FunctionSpace. This still seems to be a good assumption and perhaps we >>> should enforce it even stronger than we do now. >>> >>> It would also make it easy to check for errors during assembly. The >>> form knows the correct FunctionSpace and the assembler may compare >>> that FunctionSpace against the FunctionSpace of the Function. >> I'm happy with "a Function always has a FunctionSpace" concept if it is >> strictly enforced at construction time. The current situation is not so, >> and since I'm allowed to create a user function without a function space >> I expect to be able to use it where it makes sense. >> >> C++ is often much easier to work with if objects are completely initialized >> at >> construction time, then there are a lot of mistakes you're just not >> allowed to make. > > I agree completely. This is the approach we tried to follow in the > recent redesign of Function. That's why one first needs to create a > mesh, then a function space, then a form. I'm not sure why we > decided not to enforce the requirement of having a function space for > coefficients. > > It seems it wouldn't be anymore difficult than what we have now. For > example, the Poisson demo would be > > UnitSquare mesh(32, 32); > PoissonFunctionSpace V(mesh); > > PoissonBilinearForm a(V, V); > PoissonLinearForm L(V); > Source f(V); > L.f = f; // without side effect >
That's OK, but if you have >5 coefficients with >5 different functions spaces, it's not nice. >>>>> I don't think having rank(), dim(), geometric_dimension() as mandatory >>>>> in the Function interface would help. I've seen more examples of >>>>> programs breaking from rank() and dim() being implemented incorrectly >>>>> than I've seen programs breaking from eval() being implemented >>>>> incorrectly. And no error-checking can save a user from typing >>>>> >>>>> values[100] = x[30] >>>>> >>>>> inside eval(), unless we move away from arrays to some bounds-checking >>>>> type for the arguments to eval. >>>> Ok, it probably isn't a big problem to not have a check for this in >>>> assembly. >>>> The main error this kind of check used to catch was mismatch between >>>> function argument order in forms, which isn't a problem anymore. >>>> >>>> >>>>>>> The geometric dimension is proably deducable from other places during >>>>>>> assemble. >>>>>> Of course, but that doesn't guarantee that the Function and the Form >>>>>> uses the same dimensions. Error checking is _the_ reason for >>>>>> making the user provide this information explicitly. >>>>>> >>>>>> The point of having explicit rank in a Function is not that the expected >>>>>> rank isn't available during assembly, but because the actual rank of the >>>>>> Function should be _checked against_ the rank expected for the form >>>>>> argument. >>>>>> >>>>>> In general, I find it very frustrating that DOLFIN has so little >>>>>> error checking. >>>>> No one objects to error-checking. Error-checking is good and we should >>>>> do more of it. Feel free to add as much as you like. Make sure to >>>>> include clear and sensible error messages. >>>> I'm sorry, I don't have any time to donate for this, my time is >>>> better spent with UFL anyway. >>>> >>>> I'm trying to adapt a habit of always documenting my assumptions >>>> of input arguments to a function with checks and assertions. >>>> It's way harder to add checks to other peoples code or code I >>>> wrote myself long ago. >>>> >>>> I believe the only way to do better at this point is if everybody >>>> starts writing checks whenever new code is added or old >>>> code is modified. It also makes reading code easier! >>> Yes, that works fine if you know what you want to do from the start, >>> but I find that the design is often evolving and I wouldn't know which >>> unit tests to write until the code is finished. >> Tests are hard, I know... But here I was thinking about simple >> things like matching dimensions and vector sizes etc. > > Yes, and I agree it's important. The tests are missing simply because we've > either been lazy or been pressed on time (and most often the latter). > I think that this point is being exaggerated. We can and should add more tests, but there are tests. DOLFIN is not devoid of error checking. Garth > > > ------------------------------------------------------------------------ > > _______________________________________________ > DOLFIN-dev mailing list > [email protected] > http://www.fenics.org/mailman/listinfo/dolfin-dev _______________________________________________ DOLFIN-dev mailing list [email protected] http://www.fenics.org/mailman/listinfo/dolfin-dev
