From fcb98782a564f23aa1fce6b44ed3308421fceb61 Mon Sep 17 00:00:00 2001 From: Cian Wilson Date: Sat, 1 Oct 2022 11:32:53 -0400 Subject: [PATCH 1/2] A possible fix for taking the derivative of vector coefficients w.r.t. a scalar. Also adding a test. --- test/test_derivative.py | 24 ++++++++++++++++++++++++ ufl/algorithms/apply_derivatives.py | 8 ++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/test/test_derivative.py b/test/test_derivative.py index c9ce779bf..efc48f7d1 100755 --- a/test/test_derivative.py +++ b/test/test_derivative.py @@ -484,6 +484,30 @@ def test_coefficient_derivatives(self): self.assertEqual(replace(actual, fd.function_replace_map), expected) +def test_vector_coefficient_scalar_derivatives(self): + V = FiniteElement("Lagrange", triangle, 1) + VV = VectorElement("Lagrange", triangle, 1) + + dv = TestFunction(V) + + df = Coefficient(VV, count=0) + g = Coefficient(VV, count=1) + f = Coefficient(VV, count=2) + u = Coefficient(V, count=3) + cd = {f: df} + + integrand = inner(f, g) + + i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)] + expected = as_tensor(df[i1]*dv, (i1,))[i0]*g[i0] + + F = integrand*dx + J = derivative(F, u, dv, cd) + fd = compute_form_data(J) + actual = fd.preprocessed_form.integrals()[0].integrand() + assert (actual*dx).signature() == (expected*dx).signature() + + def test_vector_coefficient_derivatives(self): V = VectorElement("Lagrange", triangle, 1) VV = TensorElement("Lagrange", triangle, 1) diff --git a/ufl/algorithms/apply_derivatives.py b/ufl/algorithms/apply_derivatives.py index c4123f3cc..e505bbe46 100644 --- a/ufl/algorithms/apply_derivatives.py +++ b/ufl/algorithms/apply_derivatives.py @@ -859,8 +859,12 @@ def coefficient(self, o): for do, v in zip(dos, self._v): so, oi = as_scalar(do) rv = len(v.ufl_shape) - oi1 = oi[:-rv] - oi2 = oi[-rv:] + if rv == 0: + oi1 = oi[:] + oi2 = () + else: + oi1 = oi[:-rv] + oi2 = oi[-rv:] prod = so * v[oi2] if oi1: dosum += as_tensor(prod, oi1) From 289a9384711eb04788186f7a94ee3196518a7f1d Mon Sep 17 00:00:00 2001 From: Cian Wilson Date: Wed, 12 Oct 2022 11:53:24 -0400 Subject: [PATCH 2/2] A slightly neater version that handles scalar derivatives of vectors. --- ufl/algorithms/apply_derivatives.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ufl/algorithms/apply_derivatives.py b/ufl/algorithms/apply_derivatives.py index e505bbe46..302ba04fd 100644 --- a/ufl/algorithms/apply_derivatives.py +++ b/ufl/algorithms/apply_derivatives.py @@ -858,13 +858,9 @@ def coefficient(self, o): dosum = Zero(o.ufl_shape) for do, v in zip(dos, self._v): so, oi = as_scalar(do) - rv = len(v.ufl_shape) - if rv == 0: - oi1 = oi[:] - oi2 = () - else: - oi1 = oi[:-rv] - oi2 = oi[-rv:] + rv = len(oi) - len(v.ufl_shape) + oi1 = oi[:rv] + oi2 = oi[rv:] prod = so * v[oi2] if oi1: dosum += as_tensor(prod, oi1)