# Generating matrix of distances between points in cylindrical coordinates

I am working on an analytical model for the sound intensity generated from a vibrating cylinder. Part of this work requires me to split the cylinder up into a number of elements, with the more elements increasing the accuracy of my results.

I am fairly new to Mathematica and would like to generate a function that will have the following inputs and output.

Input: Number of vertical partitions (nn), number of circumferential partitions (mm), and Cylinder height (L) and, outer radius (a).

Output: Matrix where each element contains distance between the centroid's of two of the elements.

For example, for a cylinder with height L = 2 m and outer radius a = 1 m and we split the cylinder into 4 elements we would have nn = 1 vertical partition and mm = 2 circumferential partitions. The function would then output a 4 by 4 matrix containing the distance between element 1 and elements 1, 2, 3 and 4, element 2 and elements 1, 2, 3 and 4, etc.

So far I have managed to produce a table containing the coordinates of the centroid of each element. Using,

CentroidList = Table[{tr = a, t\[Theta] = (i*\[Pi])/mm, tz = (j*L)/(2*nn)}, {i,Range[1, 2*mm, 2]}, {j, j = 1, j = 2*nn, j = j + 1}]


Now I am trying to use this Table to generate the matrix which will contain the distance between each of the centroids. What is the best way to do this?

So far I have only been able to produce the distance between two centroids by using the following (where I must manually input the indexes for Part[ ] to get the correct result);

Example, distance between centroid of element 1 and centroid of element 2:

r12 = Sqrt[(Part[CentroidList, 1, 1, 1]*
Cos[Part[CentroidList, 1, 1, 2]] -
Part[CentroidList, 1, 2, 1]*
Cos[Part[CentroidList, 1, 2, 2]])^2 + (Part[CentroidList, 1, 1,
1]*Sin[Part[CentroidList, 1, 1, 2]] -
Part[CentroidList, 1, 2, 1]*
Sin[Part[CentroidList, 1, 2, 2]])^2 + (Part[CentroidList, 1, 1,
3] - Part[CentroidList, 1, 2, 3])^2]


Is is possible to repeat this calculation (automatically changing the indexing in Part[ ]) and assigning the result to a particular location in a matrix?

• I don't want to commit to an answer until you confirm, but will With[{a = 1, nn = 1, mm = 2, L = 2}, CentroidList = Table[{a, i π/mm, j L/(2 nn)}, {i, 1, 2 mm, 2}, {j, 1, 2 nn}]]; DistanceMatrix[Flatten[Apply[Append[#1 Through[{Cos, Sin}[#2]], #3] &, CentroidList, {2}], 1]] suit your needs? (A lot of what you were trying to do in Table[] didn't really need to be done.) Jul 8 '16 at 8:36
• This is great! The only issue is that when you select a larger number of elements say; nn = 4 and mm = 4 then this also produces the distance between the edges of the elements and the centroid (which aren't required). I was able to fix this though by changing the i and j indexing to match what I had in my original Centroid List. With[{a = 1, nn = 1, mm = 2, L = 2}, CentroidList = Table[{a, i \[Pi]/mm, j L/(2 nn)}, {i, Range[1, 2 mm, 2]}, {j, j = 1, 2 nn, j = j + 1}]]; DistanceMatrix[ Flatten[Apply[Append[#1 Through[{Cos, Sin}[#2]], #3] &, CentroidList, {2}], 1]] Jul 9 '16 at 2:45
• You do not need to do assignment in Table[]'s iterator argument; you can just as easily write Table[{a, i π/mm, j L/(2 nn)}, {i, 1, 2 mm, 2}, {j, 1, 2 nn}]. Jul 9 '16 at 3:18

Here is a slight rewriting of your centroidList for the specific case you mention.

a = 1; nn = 1; mm = 2; L = 2;
centroidList = Flatten[Table[{a, (i*\[Pi])/mm, (j*L)/(2*nn)},
{i, 1, 2*mm, 2}, {j, 1, 2*nn}], 1]

{{1, \[Pi]/2, 1}, {1, \[Pi]/2, 2}, {1, (3 \[Pi])/2, 1}, {1, (3 \[Pi])/ 2, 2}}


To calculate the distance matrix, you can use the Norm function.

dist = Table[Norm[centroidList[[i]] - centroidList[[j]]],
{i, 1, Length[centroidList]}, {j, 1, Length[centroidList]}]

dist//MatrixForm


Of course, this implements the Euclidean norm, and yours is different. Here is a function that calculates the distance d[ ]. Then this can be placed in the Table straightforwardly:

d[{a1_, a2_, a3_}, {b1_, b2_, b3_}] :=
Sqrt[(a1*Cos[a2] - b1*Cos[b2])^2 + (a1*Sin[a2] - b1*Sin[b2])^2 + (a3 - b3)^2];

Table[d[centroidList[[i]], centroidList[[j]]], {i, 1,
Length[centroidList]}, {j, 1, Length[centroidList]}] // MatrixForm


Or, equivalently, you can use the DistanceMatrix command (as suggested by J.M.) with this modified metric:

DistanceMatrix[centroidList, DistanceFunction -> d]


or the Outer product (as suggested by Quantum_Oli)

Outer[d, centroidList, centroidList, 1]


to get the same result.

• Why not use DistanceMatrix[] instead? Jul 8 '16 at 8:27
• @J.M. - I think he doesn't really want the Euclidean norm, so I tried to write it so that it would be easier to modify for his specific case (which seems to involve Sin's and Cos's). Jul 8 '16 at 8:29
• Well, he's taking the distance of points in cylindrical coordinates, apparently, so do a Cartesian conversion first, and then DistanceMatrix[] is easily applied. Jul 8 '16 at 8:37
• Would Outer be preferable to Table in this case? Jul 8 '16 at 9:39
• This is great. thank you for the help. The only issue is that when a larger number of elements are selected (say nn =4 and mm = 4) the indexing for i and j results in the center of the edges of the elements being included in the centroidList. To get around this the indexing needs to skip the even numbers so i and j would take the values 1, 3, 5, etc. I believe the indexing for i and j that I used in my original centroidList will fix this issue. Jul 9 '16 at 3:03