1
$\begingroup$

I'm here with another probably simple question. So I am taking derivatives of a function with respect to another variable not used in that function. So first I define that derivative

D[r[n, k, h, L, \[Mu]], lam] = v[n, k, h, L, \[Mu]], lam]/n

So this is all well and good but then when I actually try to use that derivative in the context of another function, whoopsies it seems like mathematica has forgotten

In[773]:= D[3*r[n, k, h, L, \[Mu]], lam]

Out[773]= 0

So I checked if the original derivative is still defined and lo and behold

In[774]:= D[r[n, k, h, L, \[Mu]], lam]

Out[774]= v/n

(where v is the function of v) How do I make mathematica do this pattern matching correctly? I'm sure this has been asked before but I didn't see quite where.

I thanks to daniel have figured that using

 D[f_ : 1 r[n, k, h, L, \[Mu]], lam] ^= v/n

Gives also the wrong answer in that D[r[n, k, h, L, [Mu]], lam] gives the exact same answer as D[3*r[n, k, h, L, [Mu]], lam] which is obviously wrong

Edit: I am still unable to get this to work correctly so I've uploaded my notebook to git. You can find my full code here: https://github.com/pjdog/mathematicaStuff/blob/main/danielsonderivatives.nb

$\endgroup$
3
  • $\begingroup$ First, your definition will not work, because it tries to assigne the rule to D what is protected. You must use "UpSet": "^=". Further, MMA is a pattern matcher. If you want to match the pattern "3*r[..]" you must say: D[f_^ : 1 r[n, k, h, L, \[Mu]], lam] ^= v/n; $\endgroup$ Commented Apr 28, 2021 at 19:40
  • $\begingroup$ Because I'm an uneducated caveman I just unprotect D before using it in that way lol. I definitelly shouldnt do it that way. $\endgroup$ Commented Apr 28, 2021 at 20:24
  • $\begingroup$ ALso the code you wrote does not work correctly Daniel. The first ^ keeps the code from running $\endgroup$ Commented Apr 29, 2021 at 21:28

1 Answer 1

3
$\begingroup$

You can add the option NonConstants -> {r} to tell D that r does, indeed, depend on non-explicit variables. This is the best way, I think—then you can use all of D's standard rules. Otherwise, you'd need to define pattern-matching to account for every single possible way r could occur in an expression, which is...a lot. (You could probably also replace r with an "internal" function which does explicitly depend on lam, but I'll take the NonConstants route here.)

But it's a bit finicky to get it to work as intended, especially when considering that you might have other nonconstants, and other variables with respect to which you might be taking the derivative.

(I'd also recommend using upvalues to associate the definition with r instead of D. I also recommend making the arguments patterns by appending a _, otherwise only the literal symbols n, k, etc. will work!)

Here, I check if you're taking the derivative with respect to any other symbols as well; if not, I give v/m, and otherwise I apply the $\partial/\partial\lambda$ derivative first, get v/m, and then take the remaining derivatives of that.

r /: D[r[n_, k_, h_, L_, \[Mu]_], p1___Symbol, lam, p2___Symbol, NonConstants -> {x___, r, y___}] :=
       Switch[Hold[p1, p2],
                Hold[], v/m,
                _     , D[v/m, p1, p2, NonConstants -> {x, r, y}]
              ]

One could repeat this sort of procedure to account for nth-derivative syntax and vector derivatives—let me know if that would be useful!

You also might want to add r as a nonconstant to any evaluation of D. This requires modifying D.

Unprotect[D];Clear[D];

Block[{r}, 

 D[expr_, p__, NonConstants -> {x___}] :=
   D[expr, p, NonConstants -> {x, r}] /; FreeQ[{x}, r, {1}];

 D[expr_, p__, NonConstants -> x_Symbol] :=
   D[expr, p, NonConstants -> {x, r}] /; !MatchQ[x, r];

 D[expr_, p : ((_List | _Symbol)..)] :=
   D[expr, p, NonConstants -> {r}]

];

Protect[D];

Let me know if you'd like me to explain anything I use here!

$\endgroup$
10
  • 1
    $\begingroup$ @PaulHughes ah, I see. That usually happens when the thing you're trying to assign upvalues to only occurs deeper than the first level of the expression. So, for example, a /: f[a] := 1 will work, but a /: f[g[a]] := 1 will give you that error. Here, even though r appeared deeper, the upvalue assignment to r succeeded because r was present as a head on the first level of the expression, namely as D[r[...], ...]. If you're not assigning derivatives to functions directly like that, you might have to add a definition to D after all! $\endgroup$
    – thorimur
    Commented Apr 29, 2021 at 19:14
  • 1
    $\begingroup$ Feel free, though, to edit your question to include the more general cases that are behaving badly, and I'll try to edit my answer to help out when I have the chance :) $\endgroup$
    – thorimur
    Commented Apr 29, 2021 at 19:15
  • 1
    $\begingroup$ also, replacing v with v[n, k, h, L, \[Mu]] (no underscores) should solve the first problem you mention! $\endgroup$
    – thorimur
    Commented Apr 29, 2021 at 19:17
  • 1
    $\begingroup$ @PaulHughes you mean my code gives you that error? hmmm. copy-pasting my code to a fresh kernel, and adding the dependence on arguments for v works fine for me, no error messages. what version of mathematica are you in? and have you tried ClearAll[r] before evaluating? $\endgroup$
    – thorimur
    Commented Apr 29, 2021 at 23:56
  • 1
    $\begingroup$ @PaulHughes try r /: D[r[n_, k_, h_, L_, \[Mu]_], p1___Symbol, lam, p2___Symbol, NonConstants -> spec_] := Switch[Hold[p1, p2], Hold[], v/m, _, D[v/m, p1, p2, NonConstants -> spec]]. What do you get then? $\endgroup$
    – thorimur
    Commented Apr 30, 2021 at 3:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.