12
12
13
13
from ufl .action import Action
14
14
from ufl .algorithms .analysis import extract_arguments
15
+ from ufl .algorithms .estimate_degrees import SumDegreeEstimator
15
16
from ufl .algorithms .map_integrands import map_integrand_dags
16
17
from ufl .algorithms .replace_derivative_nodes import replace_derivative_nodes
17
18
from ufl .argument import BaseArgument
@@ -562,6 +563,14 @@ def __init__(self, geometric_dimension):
562
563
"""Initialise."""
563
564
GenericDerivativeRuleset .__init__ (self , var_shape = (geometric_dimension ,))
564
565
self ._Id = Identity (geometric_dimension )
566
+ self .degree_estimator = SumDegreeEstimator (1 , {})
567
+
568
+ def is_cellwise_constant (self , o ):
569
+ """More precise checks for cellwise constants."""
570
+ if is_cellwise_constant (o ):
571
+ return True
572
+ degree = map_expr_dag (self .degree_estimator , o )
573
+ return degree == 0
565
574
566
575
# --- Specialized rules for geometric quantities
567
576
@@ -572,7 +581,7 @@ def geometric_quantity(self, o):
572
581
otherwise transform derivatives to reference derivatives.
573
582
Override for specific types if other behaviour is needed.
574
583
"""
575
- if is_cellwise_constant (o ):
584
+ if self . is_cellwise_constant (o ):
576
585
return self .independent_terminal (o )
577
586
else :
578
587
domain = extract_unique_domain (o )
@@ -583,7 +592,7 @@ def geometric_quantity(self, o):
583
592
def jacobian_inverse (self , o ):
584
593
"""Differentiate a jacobian_inverse."""
585
594
# grad(K) == K_ji rgrad(K)_rj
586
- if is_cellwise_constant (o ):
595
+ if self . is_cellwise_constant (o ):
587
596
return self .independent_terminal (o )
588
597
if not o ._ufl_is_terminal_ :
589
598
raise ValueError ("ReferenceValue can only wrap a terminal" )
@@ -654,8 +663,10 @@ def reference_value(self, o):
654
663
def reference_grad (self , o ):
655
664
"""Differentiate a reference_grad."""
656
665
# grad(o) == grad(rgrad(rv(f))) -> K_ji*rgrad(rgrad(rv(f)))_rj
657
- f = o .ufl_operands [0 ]
666
+ if self .is_cellwise_constant (o ):
667
+ return self .independent_terminal (o )
658
668
669
+ f = o .ufl_operands [0 ]
659
670
valid_operand = f ._ufl_is_in_reference_frame_ or isinstance (
660
671
f , (JacobianInverse , SpatialCoordinate , Jacobian , JacobianDeterminant )
661
672
)
@@ -676,7 +687,6 @@ def grad(self, o):
676
687
# Check that o is a "differential terminal"
677
688
if not isinstance (o .ufl_operands [0 ], (Grad , Terminal )):
678
689
raise ValueError ("Expecting only grads applied to a terminal." )
679
-
680
690
return Grad (o )
681
691
682
692
def _grad (self , o ):
0 commit comments