On 02/04/2016 02:29 PM, Martin Sandve Alnæs wrote:
> That's not really intended for overloading, and it might not work in all
> scenarios or after future changes. Your overload could be "lost" during
> symbolic transformations within the form compiler.
Ok. I'll use DG0.
See the verbose explanation below for details.
> Also, are you sure you want to just set grad(f) = 0?
Yes, definitely.
To explain why I need to give you some (tedious) background: I'm trying
to write a structural finite element beam with finite rotations is
dolfin, and I'm using the rotation vector for the parametrization.
One of the tensor that must be computed is equal to the identity for a
null rotation, but is singular for a rotation of 2\pi.
This should be not a problem provided the rotation vector is
re-normalized into a rotation with $-\pi \leq
magnitude_of_rotation_vector \leq \pi$ _after_ the interpolation.
So (some code):
-----------------------------------------
parameters["form_compiler"]["quadrature_degree"] = 3
QUADRATURE_NPHI_UNWRAP_ELEMENT_VOLUME = FiniteElement("Quadrature",
mesh.ufl_cell(), 3)
cppcode_nphi_unwrap = """
class nphi_unwrap : public Expression
{
public:
nphi_unwrap() : Expression() {}
std::shared_ptr<Function> phi_function;
void eval(Array<double>& values, const Array<double>& x, const
ufc::cell& ufc_cell) const {
Array<double> phi(3);
Cell dolfin_cell(*phi_function->function_space()->mesh(),
ufc_cell.index);
phi_function->eval(phi, x, dolfin_cell, ufc_cell);
double phi1 = sqrt(phi[0] * phi[0] + phi[1] * phi[1] + phi[2] *
phi[2]);
if (phi1 > pi) {
double pi2 = 2. * pi;
int nphi = trunc(phi1 / pi2);
if ((phi1 - nphi * pi2) > pi ) nphi += 1;
values[0] = nphi * pi2;
} else {
values[0] = 0.;
}
}
};"""
NphiUnrwapVolume = Expression(cppcode_nphi_unwrap,
element=QUADRATURE_NPHI_UNWRAP_ELEMENT_VOLUME, domain=mesh)
# phi is the rotation vector
NphiUnrwapVolume.phi_function = phi
def phi_unwrapped(phi, nphi):
phi2 = dot(phi, phi)
phi1 = sqrt(phi2)
dphi = conditional(nphi > .5, nphi / phi1, 0.)
return phi * (1. - dphi)
phi_unwrapped_volume = phi_unwrapped(phi, NphiUnrwapVolume)
Gamma = function_that_compute_the_tensor(phi_unwrapped_volume)
-----------------------------------------
The functional is a function of Gamma and of grad(phi_unwrapped_volume)
and while computing grad(phi_unwrapped_volume) ufl tries to compute
grad(nphi) (if I'm understanding correctly what is going on).
Everything should work because
1) you've fixed the derivative of conditionals in uflacs
(at least for scalars)
2) when computing the derivative nphi is just a number (switch or not
switch), and as a consequence the derivative of phi_unwrapped_volume
with respect to the set on unknowns should be correct at each
integration point.
> In particular, you're not justifying the use of quadrature elements
> instead of DG0 in this email.
You are right. It occurred to me _after_ sending the email
(after and not before, as always, silly me)
that I can use DG0: what should be important is to stay away from 2\pi
at each integration point. However,
if the elements are small enough this should be guaranteed with DG0
because the switch occurs if the rotation magnitude is $\ge \pi$, well
away from the critical value of 2\pi.
Thanks again,
Marco