def _expand_partial_derivative(self): args, indices, free, dum = self._contract_indices_for_derivative( self.expr, self.variables) obj = self.func(*args) obj._indices = indices obj._free = free obj._dum = dum result = obj if not args[0].free_symbols: return S.Zero elif isinstance(obj.expr, TensAdd): # take care of sums of multi PDs result = obj.expr.func(*[ self.func(a, *obj.variables)._expand_partial_derivative() for a in result.expr.args ]) elif isinstance(obj.expr, TensMul): # take care of products of multi PDs if len(obj.variables) == 1: # derivative with respect to single variable terms = [] mulargs = list(obj.expr.args) for ind in range(len(mulargs)): if not isinstance(sympify(mulargs[ind]), Number): # a number coefficient is not considered for # expansion of PartialDerivative d = self.func( mulargs[ind], *obj.variables)._expand_partial_derivative() terms.append( TensMul(*(mulargs[:ind] + [d] + mulargs[(ind + 1):]))) result = TensAdd.fromiter(terms) else: # derivative with respect to multiple variables # decompose: # partial(expr, (u, v)) # = partial(partial(expr, u).doit(), v).doit() result = obj.expr # init with expr for v in obj.variables: result = self.func(result, v)._expand_partial_derivative() # then throw PD on it return result