I finally found a solution to my problem, it was not so difficult, but still it took me a while to figure it out. In case anyone else is interested, I present the details.
First, here is my code for the polar case:
polarCoordD :: ((Double,Double) :~> (Double,Double)) polarCoordD = \(r,phi) -> pairD (polarx (r,phi), polary (r,phi)) where polarx :: (Double,Double) :~> Double polarx = \(r,phi) -> (fst . unpairD $ (idD) (r,phi))*cos( snd . unpairD $ idD (r, phi)) polary :: (Double,Double) :~> Double polary = \(r,phi) -> (fst . unpairD $ (idD) (r,phi))*sin( snd . unpairD $ idD (r, phi))
The key was to make the "differentiation variable" (idD)
aware of the tuple (r, phi)
, which contains two variables that I want to differentiate. Then I have to unzip the tuple via unpairD
and select the first and second part of the resulting pair (in polarx
and polary
). Both are packaged again in pairs. Maybe there is a more elegant way to do this, but the way I finally understood it.
From here it is easy to pass to cylindrical coordinates or, in fact, to any other curved system of orthogonal coordinates. For cylindrical coordinates we get:
cylCoordD :: (Vec3 Double :~> Vec3 Double) cylCoordD = \(r,phi,z) -> tripleD (cylx (r,phi,z), cyly (r,phi,z),cylz (0,0,z)) where cylx :: (Double,Double,Double) :~> Double cylx = \(r,phi,z) -> (fst' . untripleD $ (idD) (r,phi,z))*cos( snd' . untripleD $ idD (r, phi,z)) cyly :: (Double,Double,Double) :~> Double cyly = \(r,phi,z) -> (fst' . untripleD $ (idD) (r,phi,z))*sin( snd' . untripleD $ idD (r, phi,z)) cylz :: (Double,Double,Double) :~> Double cylz = \(_,_,z) -> third . untripleD $ idD (0,0,z) fst' :: (a,b,c) -> a fst' (x,_,_) = x snd' :: (a,b,c) -> b snd' (_,y,_) = y third :: (a,b,c) -> c third (_,_,z) = z
where Vec3 Double
belongs to type Vec3 a = (a, a, a)
. Now we can even build the transformation matrix:
let transmat = \(r,phi,z) -> powVal $ liftD3 (,,) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Left ())) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Right (Left ()))) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Right (Right ()))) *Main> transmat (2, rad 0, 0) ((1.0,0.0,0.0),(0.0,1.0,0.0),(0.0,0.0,1.0)) *Main> transmat (2, rad 90, 0) ((6.123233995736766e-17,1.0,0.0),(-1.0,6.123233995736766e-17,0.0),(0.0,0.0,1.0))
rad
is a convenience feature
rad :: Double -> Double rad = (pi*) . (*recip 180)
Now it would be interesting to convert this โmatrixโ into the matrix type Numeric Prelude
and / or hmatrix
, but I'm not sure if that would be even useful. But still, this would be a good example of using a vector-space
package.
I still need to figure out the use and especially the use of line cards.