Part of the complexity in this chain steps from the numerous dolfin
signatures. As discussed before, these also need cleanup to clarify
collective/non-collective operations. While at it, we could also vectorize
on x by allowing a number of coordinates wherever there's an x argument in
the code below.
For a moment I'd like to ignore the ufc/ffc parts and figure out how many
eval signatures we really need in dolfin? In particular to resolve the
collective/non-collective part. Then we can design the callback mechanism
to match the ideal dolfin design.
Here's one take (dodging the type of 'cell'):
class GenericFunction
{
public:
// Known cell on process, non-collective call:
// Note: If we allow multiple x within cell,
// the implementation can be vectorized
virtual void noncollective_eval(v, x, cell) const = 0;
// Unknown cell, collective call:
// Note: there could be a non-collective version with
// unknown cell, which would fail if the point(s) are not local
void collective_eval(v, x) const // not virtual!
{
// Note: If we allow multiple x, we can reduce
// the number of mpi calls significantly in here
cell = find cell x is on
if on this process:
noncollective_eval(v, x, cell)
send v
else:
receive v
// vectorized would be something like his:
find all (x,cell) on this process
non_collective_eval(v,x,cell) for all local points
send and receive all v
}
};
class Function: public GenericFunction
{
public:
virtual void noncollective_eval(v, x, cell) const
{
dofs = restrict to cell
fe = evaluate basis in x on cell
v = sum dofs*fe
}
};
class Expression: public GenericFunction
{
public:
virtual void noncollective_eval(v, x, cell) const = 0;
};
class MyExpression: public Expression
{
public:
virtual void noncollective_eval(v, x, cell)
{
v = user defined code (may involve e.g. cell number lookup)
}
}
I don't really see why we need more than one collective and one
non-collective eval.
Martin
On 3 September 2015 at 11:54, Chris Richardson <[email protected]> wrote:
>
> This is a mailing list continuation of a bitbucket discussion:
>
> https://bitbucket.org/fenics-project/dolfin/pull-requests/240/interpolation-improvements
>
> I have been trying to clean up Function::interpolate() a bit.
> The following issues have come up:
>
> 1. The chain of function calls is long and complex:
>
> e.g. to interpolate in the general case from another Function v:
>
> - this is just an illustrative sketch, with details removed:
>
> Function::interpolate(GenericFunction& v)
> FunctionSpace::interpolate(Vector& coeffs, const GenericFunction& v)
> Iterate over cells {
> v.restrict(cell_coeffs, element, cell, coords, ufc_cell)
> Function::restrict(w, element, cell, coords, ufc_cell)
> ...
> restrict_as_ufc_function(w, element, dolfin_cell, coords, ufc_cell)
> element.evaluate_dofs()
> ufc_element->evaluate_dofs()
> ufc_function::evaluate(vals, coords, ufc_cell)
> GenericFunction::evaluate(vals, coords, ufc_cell)
> GenericFunction::eval(vals, x, ufc_cell)
> GenericFunction::eval(vals, x)
> Function::eval(vals, x)
> {
> id = mesh.bb_tree.compute_first_entity_collision(point)
> Cell (mesh, id)
> Function::eval(val, x, cell, ufc_cell)
> restrict(coeffs, element, cell, coords, ufc_cell)
> element.evaluate_basis()
> values += coeffs * basis
> }
>
> 2. Many calls use ufc_cell and dolfin_cell with the same data. This looks
> bad, and is bad. Can we find a way to transition away from needing both?
>
> 3. In parallel, this model totally breaks down, as it is only at the very
> bottom that we realise the point is 'off process' and we need a collective
> operation to get it.
>
>
> _______________________________________________
> fenics mailing list
> [email protected]
> http://fenicsproject.org/mailman/listinfo/fenics
>
_______________________________________________
fenics mailing list
[email protected]
http://fenicsproject.org/mailman/listinfo/fenics