Martin Sandve Alnæs wrote: > On Thu, Mar 12, 2009 at 11:05 PM, Garth N. Wells <[email protected]> wrote: >> 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. > > This feature will without doubt lead to many users writing code where > function spaces are duplicated. If you have a form where more than one > coefficient shares same function space, you shouldn't use this feature. > Even if it is well documented, people don't generally read documentation > until things break. > > If we strictly require that functions have function spaces, we can instead > check that the form coefficient function spaces match the given function > in "L.f = f;". Then your problem is reduced to runtime "typechecking". >
The problem is the number of lines a user must program, and having intelligible names for the spaces. > >>>> 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. > > True, I'm probably exaggerating, I just had some bad experiences. > > Speaking of which, nobody answered my email about interpolate > three months ago. Many of those problems are still there. > Email is not a good bugtracker :-/ > > Should I just add unit tests that fail when I encounter some problem? > This is usually the most effective way to get things fixed - a failing unit test or demo ;), so go ahead and add it. Garth > Martin _______________________________________________ DOLFIN-dev mailing list [email protected] http://www.fenics.org/mailman/listinfo/dolfin-dev
