May I suggest that you start by adding just an exterior_edge_integral,
without any averaging etc?

That's a fairly straightforward matter that will take you through ufl, ffc,
ufc, dolfin
and give you a good understanding of the whole chain.

You'll need at least:
* A new measure type exterior_edge/de in ufl
* A new class exterior_edge_integral in ufc.h (in ffc)
* A new assemble_exterior_edges function in the dolfin assembler
but there will definitely be other details that pop up on the way.

I suggest modelling it after exterior_facet_integral, and searching for
exterior_facet in
the source code will give you some good pointers to where to begin. I also
suggest
making small pull requests during the process instead of waiting too long,
so you can
get feedback early. You can f.ex. make a pull request with just the measure
definition in ufl,
just the new class in ufc.h, without making everything work first.

Martin


On 4 September 2015 at 15:07, Martin Sandve Alnæs <marti...@simula.no>
wrote:

> I lost the list, lets keep it in the loop.
>
>
> ---------- Forwarded message ----------
> From: Martin Sandve Alnæs <marti...@simula.no>
> Date: 4 September 2015 at 14:29
> Subject: Re: [FEniCS] [RFC] Implementing edge integrals in 3D
> To: Lizao Li <lixx1...@umn.edu>
>
>
> On 14 August 2015 at 17:29, Lizao Li <lixx1...@umn.edu> wrote:
>
>> Thank you very much. This is very helpful. I have my responses inline
>> below:
>>
>> On Aug 14, 2015 04:46, "Martin Sandve Alnæs" <marti...@simula.no> wrote:
>> >
>> > Dear Larry,
>> > let me give a quick overview of how the measure domain type corresponds
>> to
>> > other components in ffc,ufc,dolfin to explain why using ds is no the
>> right approach.
>> >
>> > The measures in ufl have a domain type that explicitly means
>> > dx = integral over cells
>> > ds = integral over exterior facets (one-sided)
>> > dS = integral over interior facets (between two cells + and -)
>> > + some more specialized ones, please ignore those.
>> >
>>
>> > Look at <ffc>/ufc/ufc.h to see that each domain type corresponds to a
>> class
>> >     class <domain_type>_integral
>> > with a variant of tabulate_tensor(...) as well as a function
>> >     ufc::form::create_<domain_type>_integral(subdomain_id)
>> >
>> > In the dolfin assembler, there is
>> >   one loop over cells that calls cell_integral::tabulate_tensor(...)
>> >   one loop over exterior facets that calls
>> exterior_facet_integral::tabulate_tensor(...)
>> >   one loop over interior facets that calls
>> interior_facet_integral::tabulate_tensor(...)
>> > and notice that the various tabulate_tensor signatures are tailored to
>> match the expected data.
>> > (Note: it would be _possible_ to generalize the tabulate_tensor
>> signature,
>> > but that is a significant extra task to take on, so please ignore that
>> route).
>> >
>> > What you want is
>> > 1) a new assembler loop in dolfin that iterates over the edges and
>> collects the relevant
>> > sets of cells and facets, similar to the interior facet assembly but a
>> bit more involved
>> > 2) a ufc::edge_integral class with a tabulate_tensor signature capable
>> of taking the
>> > data the assembler needs to pass to generated code
>> > 3) a ufl Measure domain_type string "edge" exactly matching the
>> ufc::edge_integral class
>> > (the 1-1 mapping simplifies ffc)
>> > 4) a new shortname for the measure, e.g. "dE".
>> >
>> > If you really need 3 different variants of edge integrals, make 3
>> names, e.g.:
>> >
>> > de - arbitrary choice of one of the cell values (min cell index, for
>> example)
>> > dE - average over all the adjacent cell values
>> > dJ - sum over the jumps at all facets around the edge in the
>> right-handed direction (which happens to be the one I care about the most)
>> >
>>
>> The third case is similar to integrating jumps where there is a
>> difference between the interior and exterior part. So I guess I should have
>> both dj and dJ.
>>
>> > So that's my summary of the measure/integral/assembler design.
>> >
>> >
>> > However I have a clarifying question for you:
>> > Do you mean e.g.
>> > a)  integral over edge of (avg(f) * avg(g))
>> > or
>> > b)  integral over edge of (avg(f * g))
>> > and correspondingly (with jump(f) something like (f+ - f-))
>> > A)  sum_facets [ integral over facet of jump(f)*jump(g) ]
>> > or
>> > B)  sum_facets [ integral over facet of jump(f*g) ]
>> >
>> > In other words: do you mean jumps and averages of the entire integrand,
>> > or of specific functions and test functions within the integrand?
>> > Because those are not the same, and I think you might be trying
>> > to put too much into the measure definition here.
>> >
>> This is a very good question. Thanks for bringing it up. Currently I only
>> need (b) and (B). But I think the more general strategy capable of dealing
>> with all the cases outline above are more favorable. In this case, I will
>> have two measures:
>>
>> de - exterior edge measure
>> dE - interior edge measure
>>
>> then I will need more modifiers for forms like
>> f['any'] - f evaluated in an arbitrary adjacent cell
>> f['avg'] - f averaged in all adjacent cells
>> f['jump'] - the sum over jumps off all adjacent facets
>>
>> This looks closer to the design for the facet integral. Is this approach
>> more appropriate?
>>
>>
> Sorry for the slow response!
>
> I would advice trying to match these new features closely to existing
> concepts in UFL.
> Adding a new operator that is similar to something existing requires much
> less thinking
> than adding a radically new concept. In particular, currently there is no
> such thing in
> UFL as a 'modifier for a form'. But maybe you mean 'modifier for an
> expression'?
>
> Your suggestions f['foo'] are similar to the existing restrictions f('+')
> and f('-'), so lets stick to the () notation.
>
> Some points:
>
> 1) I think f('any') can be dropped, simply by defining that functions
> occuring in an integrand in a *de integral will use an arbitrary cell.
> The generated code will assume just one cell, and the assembler
> will just pick the cell with lowest index or something like that when
> computing *de integrals.
>
> 2) Perhaps instead of f('jump') we can instead reuse f('+') and f('-'),
> simply  defining + and - to be 'current' and 'previous' cell
> clockwise or counter-clockwise around the edge?
> There is a major benefit to this: reuse of the algorithms
> for propagating restrictions for interior facet integrals.
>
> Not sure about how to best handle the average over cells.
>
> Martin
>
>
>
>> > Martin
>> >
>> >
>> > On 10 August 2015 at 21:02, Martin Sandve Alnæs <marti...@simula.no>
>> wrote:
>> >>
>> >> Don't use ds or dx. One or more new measures must be added. I'm back
>> from vacation on Friday, will reply more in depth then.
>> >>
>> >> 7. aug. 2015 12.15 skrev "Garth N. Wells" <gn...@cam.ac.uk>:
>> >>>
>> >>>
>> >>> On 6 August 2015 at 07:49, Lizao Li <lixx1...@umn.edu> wrote:
>> >>>>
>> >>>> Dear all,
>> >>>>
>> >>>> I plan to implement edge integral assembly in 3D in FEniCS.
>> >>>
>> >>>
>> >>> Nice. We have an open feature issue on this,
>> https://bitbucket.org/fenics-project/dolfin/issues/106.
>> >>>
>> >>>>
>> >>>> It is good for a number of things, for example assembling the
>> canoniacl projection for 3D Nedelec edge elements. One issue is that there
>> are more than 3 cells intersecting at an edge in 3D.
>> >>>
>> >>>
>> >>> My concern has been whether we can do edge integration efficiently
>> without clever analysis of the form. For example, if an edge integral
>> doesn't need all data from all connect  cells (and there might be a lot of
>> connected cells), will an assembler that gets all data be performant?
>> >>>
>> >>>>
>> >>>> At the level of UFL, my design is to add,
>> >>>>    ds('m')     -  arbitrary choice of one of the cell values (min
>> cell index, for example)
>> >>>>    ds('avg')   -  average over all the adjacent cell values
>> >>>>    ds('jump')  -  sum over the jumps at all facets around the edge
>> in the right-handed direction (which happens to be the one I care about the
>> most)
>> >>>>
>> >>>> Suggestions, hints, and pointers to a good starting point in
>> particular are welcome~
>> >>>>
>> >>>
>> >>> I think we need something other than ds. Perhaps we need to be able
>> to pass the topological dimension to dx. Take a look in measure.py from UFL
>> for background.
>> >>>
>> >>> Garth
>> >>>
>> >>>>
>> >>>> Best regards,
>> >>>> ​Larry
>> >>>> --
>> >>>> Lizao (Larry) Li
>> >>>> Univeristy of Minnesota
>> >>>>
>> >>>> _______________________________________________
>> >>>> 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

Reply via email to