Group Abstract Group Abstract

Message Boards Message Boards

0
|
8.6K Views
|
7 Replies
|
0 Total Likes
View groups...
Share
Share this post:

A problem with using NDsolve, please help.

Posted 10 years ago

I am trying to solve numerically with NDsolve a pretty standard system of non-linear ODE's of the form y'=F(y), where y is a list of n points in the plane, and F is a certain function defined inside the program. All goes well, until I reach NDsolve. My guess is that I have an elementary syntax error in passing values of F to NDsolve, steming from my lack of experience with working with functions in Mathematica (my programming background is in C...). Thanks ahead for any suggestions. I paste the program below.

Polygon flow 

This is a numerical integration program that shows a "polygon flow" in the plane. That is, p={p[1],..., p[n]} is a list of n points, where each p[i] is in R^2, moving by a certain rule, given by the ODE p'=pflow[p]. The function pflow[p] requires a small program to evaluate it. After solving this ODE, with some initial condition p0,
the program shows how the n points move in the plane.

Preliminary definitions

In[1]:= Clear[n, canon, p0, long, e, pPlot, reflect, pPlot, pflow, A]

(* Define the number of vertices of the polygon; should be odd *)
n = 3; 

(* Define the cannonical basis of R^2  *)

canon = Table[IdentityMatrix[2][[i]], {i, 1, 2}];   

(* Define some initial polygon *)

p0 = Table[{2 Cos[i 2 Pi/n], Sin[i 2 Pi/n]} // N, {i, 1, n}]; 

(* This function "lengthen " p, by adding the 1st vertex as the  nth+1 vertex \
*)
long[p_] := Join[p, {p[[1]]}];

(* Define the list of edges (unit vectors) of the poligon *)

e[p_] := Module[{edge, lp},
  lp = long[p];
  Table[
   edge = lp[[i + 1]] - lp[[i]];
   edge/Norm[edge], {i, 1, n}]
  ]

(* This generates a drawing of the polygon *)

pPlot[p_] := Graphics[Line[long[p]]]

(* This reflects a vector v about the edge e *)

reflect[v_, e_] := -v + 2 (v.e) e

(* This is the composition of reflections about the edges of the polygon *)

A[e_] := Module[{v},
  Table[
   For[
    j = 1; v = canon[[i]], 
    j < n + 1, j++,
    v = reflect[v, e[[j]]]
    ]; v,
   {i, 1, 2}
   ]
  ]

(* This defines a vector field on the space of polygons *)
pflow[p_] := Module[
  {edges, R, u},
  edges = e[p];
  R = A[edges];

  (* R is a composition of an odd number of reflections, so is a reflection, 
  hence has a unique fixed direction. 
  We pick a unit vector in this direction at the 1st vertex, 
  then spread it around the polygon by reflections wrt the edges *)

  u = First@NullSpace[R - IdentityMatrix[2]];
  Table[
   If[
    i == 1,
    u = u/Norm[u],
    u = reflect[u, edges[[i - 1]]]
    ],
   {i, 1, n}
   ] 
  ]

Integrating the ODE p'=pflow[p]

In[11]:= (* Integration time *)
T = 10;

(*Integrating the ODE*)

s = NDSolve[{y'[t] == pflow[y[t]], y[0] == p0}, y, {t, 0, T}];
yy := y /. s;

Animate[
 Graphics[
  Line[long[yy[t]]],
  PlotRange -> 3],
 {t, 0, T},
 AnimationRate -> .1
 ]
POSTED BY: Gil Bor
7 Replies
Posted 10 years ago

Would it be possible, perhaps just to make your problem simple enough for me to understand, for you to expand your y'[t]=pflow[y[t]] into a list of explicit differential equations in terms of your y1[t], y2[t],...y6[t] and the derivatives of those and the coefficient variables that you have constructed? If that could be done then it might be possible for someone to see how to then translate that into a notation that NDSolve would correctly accept.

POSTED BY: Bill Simpson
Posted 10 years ago

That's the whole issue, that NDSolve, just like you, wants to see an explicit form of the RHS of the DE p'[t]==pflow[p], but I dont have one, since the function pflow[p] is given by some complicated program, which cannot be summarized by a "formula" (probably it can, in my case, with some effort, but it's very unnatural, and one should not be obliged to do it, the program should serve me, not the other way around). In particular, pflow can only accept as input vectors p with numerical entries, not abstract symbols.

OK, so I can tell you that after searching around and asking some experts, I learnt that there is a very simple solution to this problem in Mathematica, but which is not obvious at all and is not mentioned in the documentation (at least I couldnt find it). You just add the single word "List" after the argument in the definition of pflow (the RHS of the DE)

pflow[p_List] := Module[{...}, etc

That's all. After this you can write

psol = NDSolveValue[{p'[t] == pflow[p[t]], p[0] == p0}, p, {t, 0, T}];

and all goes well. Maybe it's in the documentation somewhere, but I didnt find it. It somehow tells NDSolve, when trying to acces pflow before starting the integration process, not to use it prematurely, but wait patiently, start with the available initial conditions which turn p into a List of numbers (without them p is just a symbol without any meaning), which will be then accepted by pflow and produce, using the integrating scheme used by NDSolve, the next value of p, etc.

Thanks again for trying to help.

POSTED BY: Gil Bor
Posted 10 years ago

I think I pinpointed the problem but do not know how to solve it. It seems to be a basic issue with NDSolve. This command expects a system of equations y'[t]==F[y[t]], where y[t] can be a vector valued function , and F[y] a a vector-valued function of a vector argument, possibly user-defined. The problem is the nature of this F[y]. If F[y] is a "formula", like F[y_]:=2y, then there is no problem. But if, like in my case, F[y] is a function that only makes sense for a vector y of numbers, then there is a problem, because before starting to solve the system, NDSolve wants to "see" the actual system of eqns, to check that the number of eqns is the same as the number of unknown (which he can deduce from the initial conditions). But NDSolve cannot substitute y in F[y] before he is actually solving the system and y has some numerical value. I read somewhere that I can modify the definition of F so as to evaluate F[y] only for vectors y of numbers, using the command VectQ (or ArrayQ, in my case, since my y is in fact an n by 2 matrix), but then NDSolve complains, saying there are not enough equations, because of the same problem, it cannot evaluate the rhs of y'[t]==F[y[t]], because F[y] does not return anything useful before the program is running.

Makes sense? Any suggestions?

Thanks again for yr attention.

POSTED BY: Gil Bor
Posted 10 years ago

Dear Bill.

I am sorry that I was not clear. Let me try again.

This is the most standard system of 1st order (non-linear) ODEs, except, perhaps, for my notation. Let us take n=3 (as I do in the beginning of my program), and denote by V the usual 6-dimensional Euclidean vector space, the set of 6-tuples of real numbers x={x1,x2,x3,x4,x5,x6}. Now given some arbitrary function y=F[x] from V to V (this is basically my pflow), it defines a system of 6 ODEs y'[t]=F[y[t]], for the 6 components y1[t], ..., y6[t] of an unknown V-valued function y[t]={y1[t], ..., y6[t]}. The program is to solve this system with a given initial condition y[0] (an element of V).

The only twist, which is probably what confuses you, is that I want for some reason the 6 components of y[t] to be "repackaged" as a nested list y[t]={{y1[t],y2[t]}, {y3[t],y4[t]}, {y5[t],y6[t]}}, because I am thinking of y as a triple of points in the cartesian plane. But this is not important, and I am happy to "Flatten" my double-nested list into an ordinary list, if it helps (I tried, it did not work).

So this is exactly what NDsolve was made for, right? Perhaps what I need are some well explained standard advanced examples, where y=F[x] is a user defined function and y[t] is some list-valued, nested (a matrix), etc. The ones on the documentation are too simple. If you can point out to such examples it will be great and save a lot of explanations.

Thanks again for yr kind attention.

POSTED BY: Gil Bor
Posted 10 years ago

I think there might be a misunderstanding or miscommunication between what NDSolve is expecting and what pflow is providing.

If you look at the documentation for NDSolve you can see that it is expecting some sort of differential equation in the usual form and it will use one of the classical methods of numerically solving that.

It isn't clear to me how your list of n pairs of real numbers is supposed to supply that needed information. Can you perhaps explain what the meaning of the list of pairs is?

Reading your code, it seems that you might expect the list to provide y[t]. If that is the case then I am puzzled by your code.

Or perhaps you expect the list to provide the derivative of y[t] and you are wanting NDSolve to find y[t].

Suppose you could interpolate your data points and get a function that mostly goes through those points. Would that approximate y[t] or the derivative of y[t]? If it is the derivative then would the integral of that interpolation perhaps be what you are looking for?

If you can help readers get up to speed then perhaps someone can help. Thanks

POSTED BY: Bill Simpson
Posted 10 years ago

Thank you very much Bill for trying to help.

The data structure that the function pflow uses, both for input and output, is a nested list of n pairs of real numbers (a vector of n points in R^2). For example, for n=3, something like {{1,2}, {3,4}, {5,6}}. I tested it by inserting the command pflow[p0] before the NDsolve command, and it seems to do its job properly. But somehow, when NDsolve calls pflow, something goes wrong.

Thanks again for yr effort, I really appreciate it.

POSTED BY: Gil Bor
Posted 10 years ago

If I remove the semicolon at the end of your NDSolve[...] and divide the input into a cell ending at that point and run your code then I get a stream of errors that all appear to be coming from pflow[] with your data structures not being compatible and with NDSolve not getting what it expects.

In[10]:=(*Integrating the ODE*)
s = NDSolve[{y'[t] == pflow[y[t]], y[0] == p0}, y, {t, 0, T}]

During evaluation of In[10]:= Join::heads: Heads y and List at positions 1 and 2 are expected to be the same. >>
During evaluation of In[10]:= Part::partw: Part 3 of Join[y[t],{t}] does not exist. >>
During evaluation of In[10]:= Part::partw: Part 4 of Join[y[t],{t}] does not exist. >>
During evaluation of In[10]:= Part::partw: Part 3 of Join[y[t],{t}] does not exist. >>
During evaluation of In[10]:= General::stop: Further output of Part::partw will be suppressed during this calculation. >>
During evaluation of In[10]:= Dot::dotsh: Tensors {1,0} and {(t-y[t])/Abs[t-y[t]]} have incompatible shapes. >>
During evaluation of In[10]:= Dot::dotsh: Tensors {1,0} and {(t-y[t])/Abs[t-y[t]]} have incompatible shapes. >>
During evaluation of In[10]:= Thread::tdlen: Objects of unequal length in {-1,0}+{(2 {1,0}.{(t+Times[<<2>>])/Abs[<<1>>]} (t-y[t]))/Abs[t-y[<<1>>]]} cannot be combined. >>
During evaluation of In[10]:= Thread::tdlen: Objects of unequal length in {(2 {1,0}.{(t+Times[<<2>>])/Abs[<<1>>]} (t-y[t]))/Abs[t-y[<<1>>]]}+{-1,0} cannot be combined. >>
During evaluation of In[10]:= Thread::tdlen: Objects of unequal length in {-((2 {1,0}.{(t+Times[<<2>>])/Abs[<<1>>]} (t-y[t]))/Abs[t-y[<<1>>]])}+{1,0} cannot be combined. >>
During evaluation of In[10]:= General::stop: Further output of Thread::tdlen will be suppressed during this calculation. >>
During evaluation of In[10]:= Dot::dotsh: Tensors {0,1} and {(t-y[t])/Abs[t-y[t]]} have incompatible shapes. >>
During evaluation of In[10]:= General::stop: Further output of Dot::dotsh will be suppressed during this calculation. >>
During evaluation of In[10]:= NullSpace::matrix: Argument {{-((2 ({Times[<<4>>]}+{-1,0}).{Power[<<2>>] Plus[<<2>>]} (-t+Join[y[<<1>>],{<<1>>}][[3]]))/Abs[Times[<<2>>]+Part[<<2>>]])}+{(2 {1,0}.{<<1>> <<1>>} (t-y[t]))/Abs[t+Times[<<2>>]]}+{-2,0}+(2 ({2 Power[<<2>>] Dot[<<2>>] Plus[<<2>>]}+{<<1>>}+{1,0}).<<1>> (-Join[y[<<1>>],{<<1>>}][[3]]+Join[y[t],{t}][[4]]))/Norm[-Part[<<2>>]+Join[<<2>>][[4]]],{-(<<1>>/<<1>>)}+<<2>>+<<1>>/<<1>>} at position 1 is not a non-empty rectangular matrix. >>
During evaluation of In[10]:= Power::infy: Infinite expression 1/0. encountered. >>
During evaluation of In[10]:= Power::infy: Infinite expression 1/0. encountered. >>
During evaluation of In[10]:= Infinity::indet: Indeterminate expression 0. ComplexInfinity encountered. >>
During evaluation of In[10]:= Infinity::indet: Indeterminate expression 0. ComplexInfinity {0,1}.{{{1.,-1.},{1.,1.},{-1.,Indeterminate}}} encountered. >>
During evaluation of In[10]:= Power::infy: Infinite expression 1/0. encountered. >>
During evaluation of In[10]:= General::stop: Further output of Power::infy will be suppressed during this calculation. >>
During evaluation of In[10]:= Infinity::indet: Indeterminate expression 0. ComplexInfinity encountered. >>
During evaluation of In[10]:= General::stop: Further output of Infinity::indet will be suppressed during this calculation. >>
During evaluation of In[10]:= NDSolve::ndnum: Encountered non-numerical value for a derivative at t == 0.`. >>
During evaluation of In[10]:= NDSolve::ndnum: Encountered non-numerical value for a derivative at t == 0.`. >>

Can you determine exactly what your pflow function should return?

Most of those error messages appear to be fairly clearly related to things not having the expected dimensions inside pflow. Can you make sense of some of those error messages and resolve the first layer of incompatibilities?

POSTED BY: Bill Simpson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard