8

The following problem is an exploration of what causes the error "Input is not an ordinary differential equation" in Mathematica as it seems to have changed from version 8 to version 9.

Specifically I have found that in Mathematica 9 I have come across the issue that

NDSolve[{x'[t] == 5, C'[t] == 5, x[0] == 1, C[0] == 1}, {x, C}, {t, 0, 100}]

gives the error, whereas in version 8 it does not. So something is up, but my question has more to do with if this is a bug in v8 or a bug in v9, that is, I get that C is a built in symbol: so is this error a correct catching of an input mistake? If so then

NDSolve[{C'[t] == 5, C[0] == 1}, C, {t, 0, 100}]

Should also give an error and it does not.

I really want to understand what is possibly going on, since as an ecologist I have to deal with equations that have C in them for "consumer" and I am forced to troubleshoot any issues that might come up with people not understanding the shadowing issue.

Clarification

It has been pointed out that it is bad coding style to use user defined symbols that start with a capital letter, as this will avoid clashes with Mathematica built-in definitions. That is fine, but does that matter?

What I am trying to ask more generally is whether the issue is that Mathematica is specifically checking for C and related symbols in NDSolve? Because I have no problems using symbols that have existing UpValues/DownValues as variable names (upper or lowercase) and even Protected in the exact same context.

What I want to try and understand is are there semantic reasons that this fails, ie could I cause the same error with user generated code? Or is this just a hard coded one off that Wolfram is doing for this case?

Further Clarification

If this is just an issue of using built-ins why can I use C in Solve and even DSolve! if it is an error in NDSolve? Again seems more and more like a specific check in NDSolve. For example

 DSolve[{x'[t] == 5, C'[t] == 5, x[0] == 1, C[0] == 1}, {x, C}, t]

Gives back an answer ... so suddenly this same input string is valid ODE again?

Now there are other built-ins that have this behavior such as K and Slot. As a challenge to all that would just tell me to code differently (which I do ... this is a question of why Mathematica works this way) can you use any of the reasons that you given to make a user defined symbol that will trigger the same error? If not then I will conclude that Mathematica is specifically checking for such symbols and move on. But I want to be totally clear that this is not just a question about coding style but if there are differences between system symbols and user defined symbols in this context. What if I make a package that has defined symbols in it, will I ever be able to cause the same problem if a naive user shadows some of my imported symbols into their global context?

One interesting suggestion is that somehow NDSolve is introducing C or K or Slot when it processes the input and that is causing errors. If so then I should never be able to create this problem with user defined symbols, but I do not yet know if this is the correct idea.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Gabriel
  • 2,225
  • 18
  • 19
  • 1
    Again I get this, but this breaks almost all code written by ecologists that don't understand this (which in my lab is every single person but me ... hundreds and hundreds of models, it will stop any upgrade to v9 without a lot of convincing). I want to understand why the 2d case fails, but the 1d doesn't. – Gabriel Dec 04 '12 at 08:29
  • 2
    Try it. It does. Also the 1d case with capital C works in version 9 as well – Gabriel Dec 04 '12 at 08:31
  • But why does the "fix" not work in my second example? – Gabriel Dec 04 '12 at 08:40
  • 4
    I very much doubt if there is any specific checking for C or any other symbol; this is no different to, for example, the fact that you cannot have a variable called int in (the language) C. This does not break your code; the code was broken to begin with. It's just that in M9 your bug has consequences whereas it apparently didn't in the past. One would not, after all, think to name a variable IntegerPart or For. – Oleksandr R. Dec 04 '12 at 09:37
  • 1
    @Oleksandr That's right, but MMA differs from C by having many thousands of "reserved words" (although, arguably, they are all identified by one simple rule), by allowing them to be overloaded--which is not the case for a true reserved word--and, as exemplified by this question, by not issuing informative error messages when such words are misused. (This is not to defend the coding practice exhibited here, though.) – whuber Dec 04 '12 at 15:52
  • @OleksandrR. @whuber is C really a "reserved keyword" like in C? Seems more like a library function. It would be stupid to define my own printf function and use it in C, but it certainly wouldn't give me an error for doing so. That is this seems to be more than a Shadowing issue like people seem to think. Can anyone define a symbol in Mathematica that gives the same error? – Gabriel Dec 04 '12 at 16:19
  • @Gabriel K gives the same error, for instance – acl Dec 04 '12 at 17:21
  • C is a protected System` context symbol. C[1], C[2], etc. are used to denote constants automatically generated by the system, in particular by DSolve. Using C in a differential equation is asking for trouble regardless of version. – Szabolcs Dec 04 '12 at 21:41
  • @Szabolcs I really do understand this ... but why does it work in DSolve as an ODE? Also why can I make Protected Symbols, that work. Maybe I need to rewrite this as a challenge to create a user defined symbol that will cause NDSolve to give the specific error of "Input is not an ordinary differential equation" ... as I seem to have people just thinking about coding style. It really seems that NDSolve is checking for these `System`` symbols – Gabriel Dec 04 '12 at 21:51
  • 1
    @Gabriel The point is not why it happens to appear to work in DSolve. It's that whether or not you get an error, if you do use C, there's a chance your result is incorrect. Consider DSolve[f''[x]==f[x], f[x], x] and DSolve[C''[x]==C[x], C[x], x], and you'll see where things can go wrong. Because of how the language works, it would be difficult to protect the user against mistakes like this. The syntax colouring still gives a very clear warning that you must not use C, N, K, etc. L would be fine (notice it's undefined and blue). – Szabolcs Dec 04 '12 at 22:09
  • 1
    This is not really about coding style, it's exactly the same thing as trying to use Block as a variable. Yes, it'll "work" (Solve[Block^2 == 1, Block]), but it's clear why someone who does use it might get burnt. The only protection Mathematica includes is against assigning values to these symbols, plus the syntax colouring. So unfortunately it's the user's responsibility not to use built-ins by accident. – Szabolcs Dec 04 '12 at 22:10
  • @Szabolcs yes thanks I like these points. More what I am trying to get at. You are saying that it is a specific test that Mathematica is doing to try and stop the user from getting errors. It is not something that I will be able to ever trigger with my own definitions that get shadowed since must be somehow tested for by NDSolve itself (and if so it should do the same in DSolve, 1D cases etc) and I should file a bug report. – Gabriel Dec 04 '12 at 22:20
  • 2
    It's interesting that if you replace C in your equation by any System context symbol, even a user-created one (just enter System`Boo to create Boo in that context), you'll get the error for this particular equation. But not for another equation I tried. So this error is not just an additional safety net added in version 9 (because it is not consistently issued). – Szabolcs Dec 04 '12 at 22:27
  • @Szabolcs can you give your other example as an answer with the Boo example. This seems like the smoking gun for me that it is a bug and not a safety net. I can accept that and issue the bug report. – Gabriel Dec 04 '12 at 22:32

3 Answers3

7

The symbol C is reserved for undetermined constants. From its documentation:

C[i] is the default form for the ith parameter or constant generated in representing the results of various symbolic computations.

This means even though it has no values, C can be introduced by other functions at any time, and also it might be interpreted in specific ways by various functions. Now, I can't tell you very specifically why it works in one case and not the other. My guess would be that in trying to bring the equation into a normal form, NDSolve attempts an integration or a solve which introduces another C into the equation, and then it can no longer deal with the system. In the case with only one dependent variable this doesn't happen, and so it works by chance. But in general, you're tempting fate by using C as input to the solver, be it NDSolve, DSolve, Solve, Reduce, or any of their related functions.

Also, since, say, UpValues has no such interpretation, you can probably use it safely inside of NDSolve. That still doesn't mean that's a good idea.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
Itai Seggev
  • 14,113
  • 60
  • 84
  • But I can get the same issue with using K as the variable instead of C which seems less likely to be occurring as a normalization.

    UpValues wont work since UpValues[0] will throw an error.

    – Gabriel Dec 04 '12 at 22:02
  • I like this answer the most so far, as I find the idea intriguing that it is some kind of symbolic preprocessing that is causing the error. I wish I could think of a way to test this with a built in symbol that would never arise in such a context as C K and Slot all might be candidates for this – Gabriel Dec 04 '12 at 22:16
  • Try an option name, like PlotRange. These generally have no definitions, with their significance assigned to them by the functions they are options of. Also, there are different C characters you can insert which have no built in meaning. For example escape-dsC-escape (a double struck C) or escape-C$-escape (the so-called "Formal C", which is reserved for use as a user variable). – Itai Seggev Dec 05 '12 at 00:11
2

This is not really an answer but most likely a related issue.

During my working with this issue, I think I've stumbled with another system symbol (even a set of them, since small variation of its name cause the same problem).

And this one doesn't start with an UpperCase...

The only difference between the two codes are the variables' names volume and acc

a = 80;
le = 62;
g = 9.8;
tf = 200;
b = 3.4;
r = 5.86/le;
ppa = 32*22;


ClearAll[h, t, x, u, acc, volume];
ans = Flatten@NDSolve[{
     b*u[t, x]*Derivative[0, 1][h][t, x] + 
       b*h[t, x]*Derivative[0, 1][u][t, x] + 
       b*Derivative[1, 0][h][t, x] == r,
     (r*u[t, x])/(b*g*h[t, x]) + (Abs[u[t, x]]*(b + 2*h[t, x])^(4/3)*
          u[t, x])/(a^2*(b*h[t, x])^(4/3)) + 
       Derivative[0, 1][h][t, 
        x] + (u[t, x]*Derivative[0, 1][u][t, x])/g + 
       Derivative[1, 0][u][t, x]/g == 0,
     Derivative[1, 0][acc][t, x] == b*h[t, x]*u[t, x],

     h[0, x] == 1*ppa/ppa,
     u[0, x] == 0,
     h[t, le] == acc[t, le]/ppa,
     u[t, 0] == 0,
     acc[0, x] == 1*ppa
     },
    {u, h, acc},
    {t, 0, tf},
    {x, 0, le}
    ];


ClearAll[h, t, x, u, acc, volume];
ans2 = Flatten@NDSolve[{
     b*u[t, x]*Derivative[0, 1][h][t, x] + 
       b*h[t, x]*Derivative[0, 1][u][t, x] + 
       b*Derivative[1, 0][h][t, x] == r,
     (r*u[t, x])/(b*g*h[t, x]) + (Abs[u[t, x]]*(b + 2*h[t, x])^(4/3)*
          u[t, x])/(a^2*(b*h[t, x])^(4/3)) + 
       Derivative[0, 1][h][t, 
        x] + (u[t, x]*Derivative[0, 1][u][t, x])/g + 
       Derivative[1, 0][u][t, x]/g == 0,
     Derivative[1, 0][volume][t, x] == b*h[t, x]*u[t, x],

     h[0, x] == 1*ppa/ppa,
     u[0, x] == 0,
     h[t, le] == volume[t, le]/ppa,
     u[t, 0] == 0,
     volume[0, x] == 1*ppa
     },
    {u, h, volume},
    {t, 0, tf},
    {x, 0, le}
    ];


(h/.ans)[200,0]
(*6.55942*)


(h/.ans2)[200,0]
(*2.31421*)

So, same code, different answers.

P. Fonseca
  • 6,665
  • 2
  • 28
  • 60
1

From @Szabolcs comment we see that we can recreate this issue using an arbitrary System symbol so it is not an issue of some kind of functionality of the built in symbol, though he mentions that he can find models that it will still work for so it seems to be a bug, not a check.

Gabriel
  • 2,225
  • 18
  • 19
  • 3
    Apparently NDSolve has an aversion to Systemcontext variables. What I heard is one can use an option for this: NDSolve[{x'[t] == 5, Systemccc'[t] == 5, x[0] == 1, Systemccc[0] == 1}, {x, Systemccc}, {t, 0, 100}, DependentVariables -> {x, System`ccc'}] – Daniel Lichtblau Dec 10 '12 at 21:00
  • @Gabriel: And adding DependentVariables->{x,C} to the original problem also works. It looks like just the automatic determination of the dependent variables has a problem with symbols from the System context. It might also be of interest that with version 9 this also will work: NDSolve[{x'[t] == 5, "C"'[t] == 5, x[0] == 1, "C"[0] == 1}, {x, "C"}, {t, 0, 100}] (see also my comments to this answer). That is, NDSolve now also accepts strings as variable names, which after all are just labels and don't need to be just symbols at all... – Albert Retey Mar 28 '13 at 10:14