# Differentiating space curves

I'm trying to do some very basic differential geometry of space curves. For example, a space curve $\gamma:\mathbb R\to\mathbb R^3$ has unit tangent and normal vectors given by $$t(s)=\frac{\gamma'(s)}{\lVert\gamma'(s)\rVert},\\ n(s)=\frac{t'(s)}{\lVert t'(s)\rVert}.$$ I want to define functions that would compute the tangent and normal vectors of an arbitrary curve at any $s$. I tried it in a higher-order functional style, like in say Haskell:

norm[x_] := Sqrt[x.x]
tangent[γ_] := Function[s, γ'[s]/norm[γ'[s]]]
normal[γ_] := Function[s, tangent[γ]'[s]/norm[tangent[γ]'[s]]]


(I need to define my own norm because Mathematica doesn't like to differentiate Norm.)

Unfortunately, this doesn't work. Let γ[s_] := {Cos[s], Sin[s], 0} be our test curve, a circle. Then normal[γ][1] // N does not return a vector, but instead a bizarre expression involving the dot product of 1. and a vector. I have no idea how to begin figuring out what's going on.

I can do it in a less elegant way as

tangent[γ_, s_] := γ'[s]/norm[γ'[s]]
normal[γ_, s_] := D[tangent[γ, ss], ss]/norm[D[tangent[γ, ss], ss]] /. ss -> s


but this requires the use of a dummy variable and the not-so-pretty D[tangent[γ, ss], ss] construction.

Why does my original implementation not work, and is there a simple way to fix it?

-
Have you taken a look at this mathematica.stackexchange.com/questions/18598/… ? If you put for r[t] a different curve it should work as well. –  Artes Mar 2 '13 at 23:19
@Artes: I hadn't seen that before. But I'd rather not redefine tangent and normal for every curve I might be interested in. –  Rahul Narain Mar 2 '13 at 23:42

Your normal isn't working because the derivative is getting "confused" because of the way that your functions pass parameters:

multiplyBy2[r_] := Function[s, 2 r[s]]
r[s_] := {s^2, s^2}
r'[s]
multiplyBy2'[r][s]


As demonstrated by evaluating the above, the apostrophe sees that your parameter is r, so it takes the derivative with respect to r. That's how the 1 appears in your expression. Specifically, in your original functions, this 1 (derivative of the vector with respect to itself) appears where we expect a vector still, thus creating the unwanted dot products.

This can be avoided by being more explicit with what we want to derive (note simply taking the derivative with respect to s inside the function won't work as s will be replaced by its value before the derivative is taken, resulting in an error).

Thus, in my approach, I use a "dummy" variable, true, but I think the code still remains fairly concise and avoids ReplaceAll.

norm[x_] := Sqrt[x.x]
tangent[γ_] := Function[s, γ'[s]/norm[γ'[s]]]
normal[γ_] :=
With[{deriv = Function[x, Evaluate[D[tangent[γ][x], x]]]},
Function[s, deriv[s]/norm[deriv[s]]]
]
γ[s_] := {Cos[s], Sin[s], 0}
normal[γ][1] // N


Finally, when actually using these function, such as within a manipulate, I strongly recommend that you create an evaluated version of the tangent and normal functions for the specific function that is being looked at, thus avoiding constant and expensive re-derivation. I.e., doing something like this:

solenoid[s_] := {Cos[s], Sin[s], s}
solTan = tangent[solenoid];
solNorm = normal[solenoid];


EDIT

It has come to my attention that something closer to what OP's code uses is multiplyBy2[r]'[s]. After reviewing the Trace of this expression, it is clear as to why the expression evaluates to a matrix - the ' automatically takes the derivative of the sub-expression in Function:

Function[a, x]' hi
(* hi Function[a, 0] *)


It appears that, completely independent of the parameters of the function, the ' travels to x, yielding Function[a, x'] hi (again, see the Trace). Since x is a symbol with no parameters, x' evaluates to 0.

However, in my example, something even more confusing happens: In the Trace, the following steps occur Function[s$,2 r[s$]]',Function[s$,{2 r'[s$],2 r'[s$]}], from which we can see how a matrix may result. Why this happens, I don't know. This is why we explicitly define what we are deriving with respect to. - A closer analogue would be multiplyBy2[r]'[s], but that strangely yields a matrix, which is still not what I expected. I guess I see the problem, though I'm still in the dark about why it happens. Should I just avoid using primes on higher-order functions? – Rahul Narain Mar 3 '13 at 0:27 @RahulNarain I took a look at the Trace of the expression in your comment, and, as I have singled out in my answer, for some reason, Mathematica jumps from my specified expression to something completely unexplainable. Yes, I would suggest only using primes on symbols that are defined on a "single level." – VF1 Mar 3 '13 at 0:46 As VF1's answer explains, the problem is indeed that the prime behaves strangely in tangent[γ]'. I replaced it with a function d[f_] := Function[x, Evaluate[D[f[x], x]]]  based on the construction in VF1's answer, and now everything works as expected. tangent[γ_] := Function[s, d[γ][s]/norm[d[γ][s]]] normal[γ_] := Function[s, d[tangent[γ]][s]/norm[d[tangent[γ]][s]]] γ1[s_] := {Cos[s], Sin[s], s} (* a helix! *) γ2[s_] := {s, s^2, 0} {normal[γ1][s], normal[γ2][s]} // Simplify[#, Assumptions :> s ∈ Reals] & (* {{-Cos[s], -Sin[s], 0}, {-((2 s)/Sqrt[1 + 4 s^2]), 1/Sqrt[1 + 4 s^2], 0}} *)  - Probably I should also replace every Function[s, ...] with Function[s, Evaluate[...]] for performance as VF1 suggested. Or would that have any side effects? – Rahul Narain Mar 3 '13 at 2:32 Here is a simple fix of the OP's definitions: norm[x_] := Sqrt[x.x] tangent[γ_] := Function[s, Evaluate[γ'[s]/norm[γ'[s]]]] normal[γ_] := Function[s, Evaluate[tangent[γ]'[s]/norm[tangent[γ]'[s]]]]  The evaluation of the bodies will take care of the difficulties of tangent[γ]'[s]. (The evaluation of the body of normal is not necessary, unless you plan to take its derivative.) One gets for example γ[s_] := {Cos[s], Sin[s], 0}; normal[γ][1] // N (* -> {-0.540302, -0.841471, 0.} *)  The reason for the trouble in the original definition of tangent is that the (symbolic) derivative of γ'[s]/norm[γ'[s]] is γ᾽᾽[s]/norm[γ'[s]] - norm'[γ'[s]] γ᾽[s] γ''[x]/norm[γ᾽[s]]^2  You might note that γ[s] is not treated as a vector. More precisely, when the chain rule is applied to the derivative of norm[γ'[s]], γ'[s] is treated as a scalar. N.B. There is a difference between Norm and the OP's norm. Norm assumes its arguments might be Complex, and uses Abs, which can complicate derivatives. For instance, with Norm in place of norm, normal[γ][1] // N has things like Derivative[1][Abs][0.540302] in the answer. - I'd define one function only, keep the built-in Norm and use pure functions: derVec[\[Gamma]_] := Module[{local}, local = Derivative[1][\[Gamma]]; Function[x, Evaluate[Simplify[local[x]/Norm[local[x]], Assumptions -> {x \[Element] Reals} ] ] ] ]  Example : curve = Function[s, {Cos[s], Sin[s], s}]; {tangent, normal} = Rest@NestList[derVec, curve, 2]  - This computes$\gamma''(s)/\lVert\gamma''(s)\rVert$, which is not the same as the normal. One can see this, for example, on the parabola$(s,s^2,0)\$. –  Rahul Narain Mar 3 '13 at 0:33
@RahulNarain True, should have thought about it, thanks. Will correct. –  b.gatessucks Mar 3 '13 at 0:41
@RahulNarain Done. –  b.gatessucks Mar 3 '13 at 10:11