streamlines, streaklines, and pathlines

Alert: this notebook takes a while to run.
Be ready to wait about 15 minutes for the output if your computer is slow.

This notebook creates an animation of the following overlaid dynamic images:

1. In the far background is a yellow-pink-white-gray checkerboard. Imagine that this initially square (perfectly rectilinear) checkerboard grid is spray-painted (tatooed) instantaneously onto the material at time t=0. The animation of the checkerboard then it translates to the right and distorts with deformation according to a continuum mapping function from initial coordinates (X1,X2) to deformed coordinates (x1,x2) at time t:

	x1 = t + X1
	x2 = 1/3 t (t+X1)^2 + X2
	
2. Overlaid on top of the checkerboard is a family of green streamline arrows showing velocity directions at a given instant of time. Note that they point in the whatever direction the material (checkerboard) happens to be moving.   The spatial description of the material velocity is
	v1=1
	v2=1/3 x1 (2 t+x1)

3. The red line is a path line. The part of this line to the left of the origin shows where a particular material point had been located prior to time t=0 before it arrived at the origin at time t=0. The animated part of the red path grows longer during the animation so that the tip of the red line stays always tracking with this same material point, which is clear because the evolving tip of the red line stays always on the same intersection of the checkerboard grid lines.   It might seem that the red line itself is moving, but that is an optical illusion. Hold your finger near any point on the red line to see that the red line is stationary. It shows where the particle has been in the past.  The key is that the red line shows a locus of points occupied in the past by a particular particle.  This curve only grows longer. The point being tracked by the red line in this animation has initial coordinates (0,0) at time t=0. At some τ in the past, the mapping function was

	x1 = τ + X1
	x2 = 1/3 τ (τ+X1)^2 + X2

Evaluating this using X1=X2=0 gives

	x1 = τ 
	x2 = 1/3 τ^3

These parametrically describe the path line. The parameter τ varies over times in the past up to the current time t. The part of the red line (to the left of the origin) indicates where this particle had been prior to time t=0, so that part of the path uses t<0. The animated part corresponds to t>0). 

4. The streak line shows what you would see if there were a source of dye at the origin, effectively putting tatoo ink or “spray paint” onto the material as it passes by the origin. At past time τ, the mapping was

	x1 = τ + X1
	x2 = 1/3 τ (τ+X1)^2 + X2

Suppose that there is a juvenille delinquent standing fixed at the origin spraying material as it passes by.  Putting his coordinates (x1,x2) = (0,0)  into the above past mapping gives:

	0 = τ + X1
	0 = 1/3 τ (τ+X1)^2 + X2

Solving this for (X1,X2) then tells us which material particle he was spraying at the past time τ:

	X1 = -τ
	X2 = 0

According to this result, each spraypainted point was originally on the X2=0 grid line in the past, to the left of the orgin by a distance τ. The equation for the streak line is therefore the image (deformed locations) of these points in the current configuration, found by applying the mapping at time t with X1=-τ and X2=0:

	x1 = t - τ
	x2 = 1/3 t (t-τ)^2

The blue line in the animation is this set of equations plotted parametrically with the parameter τ ranging from 0 to t.

ClearAll["Global`*"]

{tbeg,tend,dt}={0,2,0.025};
{xbeg,xend,dx}={-1,2.5,0.1};{ybeg,yend,dy}={-1,2.5,0.1};
prng={{xbeg,xend},{ybeg,yend}}
thick=0.008;

χ[X1_,X2_,t_]:={X1+t,X2 + (1/3)(((X1+t))^2)t}
χ[X_,t_]:=χ[X[[1]],X[[2]],t]
invSub=Solve[χ[X1,X2,t]=={x1,x2},{X1,X2}][[1]];
χinv[x1_,x2_,t_]:=Evaluate[Simplify[{X1,X2}/.invSub]]
χinv[x_,t_]:=χinv[x[[1]],x[[2]],t];
Print["{x1,x2} = ",χ[X1,X2,t]]
Print["{X1,X2} = ",χinv[x1,x2,t]]

X={X1,X2};
x=χ[X1,X2,t];
F=Table[D[x[[i]],X[[j]]],{i,2},{j,2}]//Simplify;F//MatrixForm
J=Det[F]//Simplify

As seen, the Jacobian is unity, implying an isochoric flow.

pathParametric=χ[0,0,t];
pathSTY=Directive[Thickness[thick],Red];
pathPLT[tend_]:=ParametricPlot[χ[0,0,t],{t,tbeg,tend},PlotStyle->pathSTY,PlotRange->prng,Epilog->{Red,PointSize[0.04],Point[χ[0,0,tend]]}]
pathPLT[tend]

path2Parametric=χ[0,0,t];
path2STY=Directive[Thickness[thick],Darker[Red]];
path2PLT=ParametricPlot[χ[0,0,t],{t,tbeg-4,tbeg},PlotStyle->pathSTY,PlotRange->prng,Epilog->{Red,PointSize[0.04],Point[χ[0,0,tend]]}]

streakParametric=χ[χinv[{0,0},τ],t]
streakSTY=Directive[Thickness[thick],Blue];
streakPLT[tend_]:=ParametricPlot[χ[χinv[{0,0},τ],tend],{τ,tbeg,tend},PlotStyle->streakSTY,PlotRange->prng]
Show[streakPLT[tend],pathPLT[tend]]

vref[X1_,X2_,t_]:=Table[D[x[[i]],t],{i,2}]//Simplify
vref[X1,X2,t]

vspa[x1_,x2_,t_]:=Evaluate[vref[X1,X2,t]/.invSub//Simplify]
vspa[x1,x2,t]

streamPLT[tend_]:=StreamPlot[vspa[x1,x2,tend],{x1,xbeg,xend},{x2,ybeg,yend},StreamStyle->Lighter[Green]];
streamPLT[tend]

χinv[xend,yend,tend]
χinv[xbeg,ybeg,tend]

tend

χ[X1,X2,t]

gridPLT[tend_]:=ParametricPlot[χ[X1,X2,tend],{X1,-5,15},{X2,-12,6},Mesh->59,PlotPoints->30,MeshShading->{{Opacity[0],Opacity[0.05]},{Directive[{Opacity[0.2],Orange}],Yellow}},PlotRange->prng]
Manipulate[Show[gridPLT[t],pathPLT[t]],
{t,dt/10,tend}]

Manipulate[Show[gridPLT[t],streamPLT[t],streakPLT[t],pathPLT[t]],
{t,dt/10,tend}]

frames=Table[Show[gridPLT[t],streamPLT[t],streakPLT[t],pathPLT[t],path2PLT],
{t,dt/10,tend,dt}];
ListAnimate[frames]

SetDirectory[NotebookDirectory[]]

Export["GridStreamStreakPath.gif",frames,AnimationRepetitions->Infinity,"DisplayDurations"->0.1]

Original code provided on the Wikipedia article about streaklines and streamlines

The wikipedia documentation for their animated gif is incorrect. They state, for example, that the vertical velocity varies with y, but this is obviously not true from their animation. They provide the following for generating the animation, but it does not produce the same animation as in the article.

(*
p=Join[{If[x<t,1/3 x^3,100],If[x<t,1/2 t x^2-1/6 x^3,100]},Table[1/2 (x^2) t+y0,{y0,-10,40,0.9}]];
Export["plot.gif",Table[Plot[p,{x,0,10.6},PlotRange->{0,10.6},AspectRatio->1,PlotRangeClipping->True,PlotStyle->PadRight[{Directive[Thickness[Medium],Red],Directive[Thickness[Medium],Blue]},60,Directive[Gray,Dashed]],Exclusions->{t},ExclusionsStyle->None,ImageSize->500,AxesLabel->{x,y},Epilog->{Line[Flatten[With[{ϵ=0.025},Table[{{x-ϵ/Sqrt[1+x^2 t^2],y-x t ϵ/Sqrt[1+x^2 t^2]},{x+ϵ/Sqrt[1+x^2 t^2],y+x t ϵ/Sqrt[1+x^2 t^2]}},{x,0.1,4,0.1},{y,0.1,4,0.1}]],1]],PointSize[0.015],Red,Point[{t,1/3 t^3}]}],{t,0,1.6,0.025}],AnimationRepetitions->Infinity,"DisplayDurations"->PadLeft[{1.5},65,0.1]]
*)