[firedrake] Enforcing slip boundary condition strongly
David Ham
David.Ham at imperial.ac.uk
Fri Jul 10 11:37:46 BST 2015
That's quite yuck, however I can see the attraction as we're kind of sort
of not mucking with the PyOP2 interface.
However the generated code is specific to BCs applied to a particular
component, which doesn't satisfy Justin's (very standard) use case.
I think we need to encode *which* component we're changing into the map
value. EG.
val = -val -(2**(30-i))
where i is the component. This can be decoded to zero the correct entry in
a general purpose way. The downside is that we limit ourselves to about
half a billion nodes per core. I think that's OK.
On Fri, 10 Jul 2015 at 11:11 Mitchell, Lawrence <
lawrence.mitchell at imperial.ac.uk> wrote:
>
> > On 10 Jul 2015, at 10:25, David Ham <David.Ham at imperial.ac.uk> wrote:
> >
> > Hi Colin,
> >
> > That does not appear to be what Justin is asking for. He is asking how
> to set a Dirichlet condition on one component of a VectorFunctionSpace. I'm
> not sure we can do that right now, but I think this should be fixable. I
> want to check what the Dolfin syntax for this is (so we maintain
> compatibility) and then try to fix it. (Of course someone might want to
> pleasantly surprise me and tell me we can do this already!)
>
> We can't do it at the moment, the rest of this email explains why and
> sketches a possible solution.
>
> OK, so there are two aspects to this, which make things somewhat tricky.
>
> Our data model for indexing vector fields is that we store the Map to the
> node and stack the dofs on top.
>
> To apply such slip BCs, where we only set one of the two dofs, we need to
> do the following:
>
> - Apply the BC value to the appropriate part of the vector. I think this
> is reasonably straightforward and appear to have something that works.
>
> - Fix up the operator appropriately. This latter option is trickier. The
> way we currently do this is to drop boundary conditions on the floor when
> assembling the operator. This is done by flagging the appropriate
> rows/columns to be dropped by putting a negative value in the Map at the
> appropriate place and letting PETSc do the rest.
>
> For vector-valued fields we do block insertion, i.e. we insert a 2x2 block
> at each location in the matrix indexed by the base map. So the current
> setup can only drop complete blocks, rather than part of one (as required
> in this case).
>
> The question is, then, how to communicate the relevant bit of information
> into the code that inserts.
>
> How about this:
>
> When we splat the values in the Map we convert:
>
> val => -(val + 1)
>
> If we're apply the BC on part of the map we decorate it with the index
> offset.
>
> We then build a local (unrolled map) and fix up the entries. The negative
> offset encoding allows us to recover the correct value.
>
> So assembly turns from:
>
> A = build_element_tensor(...);
> MatSetValuesBlockedLocal(block_rows, block_cols, A);
>
> Into:
>
> A = build_element_tensor(...);
> {
> PetscInt rows[arity*dim];
> PetscInt cols[arity*dim];
> // Assume we're setting the bc on the second component.
> for ( i = 0; i < arity; i++ ) {
> if (row_map[i] < 0) {
> rows[i*dim + 0] = dim*(-(row_map[i] + 1));
> rows[i*dim + 1] = -1;
> } else {
> rows[i*dim + 0] = dim*row_map[i];
> rows[i*dim + 1] = dim*row_map[i] + 1;
> }
> }
> // Same for cols
> MatSetValuesLocal(rows, cols, A);
> }
>
> All the other options I came up with seem more complicated.
>
> Lawrence
>
-------------- next part --------------
HTML attachment scrubbed and removed
More information about the firedrake
mailing list