mpi_alltoall on nonequal number of grids and processes - mpi

I understand the general usage of MPI_alltoall, which can be described by the following figure
But in practice, it is almost not always that the number of processes will equal to the number grids. The above case assume process = grid = 4. If numbers are not equal, I will have rectangular grids. Below I show an example showing a similar alltoall operation, but nonequal number of grids and processes (grid = 8, process = 2).
My question is then very straightforward, how should I achieve that?
I have looked over alltoallv, but I don't think it will work.
Any suggestions are welcome.
Thank you

a "natural" alltoall would be
MPI_Alltoall(sbuf, 4, MPI_INT, rbuf, 4, MPI_INT, MPI_COMM_WORLD);
and you would end up with
P0 = { A0, A1, A2, A3, C0, C1, C2, C3}
P1 = { B0, B1, B2, B3, D0, D1, D2, D3}
your case is a bit convoluted and you have to use (complex) derived datatypes. (note I did not free the intermediate datatypes in order to keep the code readable)
MPI_Datatype tmp, stype, rtype;
/* derived datatype for send */
MPI_Type_vector(2, 1, 4, MPI_INT, &tmp); /* {0, 4} */
MPI_Type_create_resized(tmp, 0, 4, &tmp); /* next type starts at 1 */
MPI_Type_contiguous(2, tmp, &tmp); /* {0, 4, 1, 5} */
MPI_Type_create_resized(tmp, 0, 8, &stype); /* next type starts at 2, likely unnecessary */
MPI_Type_commit(&stype);
/* derived datatype for recv */
MPI_Type_vector(2, 2, 4, MPI_INT, &tmp); /* {0, 1, 4, 5 } */
MPI_Type_create_resized(tmp, 0, 8, &rtype); /* next type starts at 2 */
MPI_Type_commit(&rtype);
/* all2all */
/* thanks to the derived datatypes :
P0 sends {A0, B0, A1, B1} to P0 and {A2, B2, A3, B3} to P1
P0 receives {A0, B0, .., .., A1, B1, .., ..} from itself, and
{ .., .., C0, D0, .., .., C1, D1} from P1 } */
MPI_Alltoall(sbuf, 1, stype, rbuf, 1, rtype, MPI_COMM_WORLD);

Related

"Almost-structured" 2d quadrilateral mesh in Gmsh

I'd like to generate a two-dimensional quadrilateral mesh using Gmsh. The mesh should be such that its cells are "as quadratic as possible" with a given edge length. That is, if the geometry is simple, I'd expect a perfectly structured grid, and if the geometry is more complex, I'd only expect local distortion.
Consider the following minimal example:
lc = 1;
Point(1) = {0, 0, 0, lc};
Point(2) = {10, 0, 0, lc} ;
Point(3) = {10, 4, 0, lc} ;
Point(4) = {0, 4, 0, lc} ;
Point(5) = {1, 1, 0, lc} ;
Point(6) = {3, 1, 0, lc} ;
Point(7) = {2, 2, 0, lc} ;
Line(1) = {1,2} ;
Line(2) = {3,2} ;
Line(3) = {3,4} ;
Line(4) = {4,1} ;
Line(5) = {5,6} ;
Line(6) = {6,7} ;
Line(7) = {7,5} ;
Line Loop(1) = {4,1,-2,3} ;
Line Loop(2) = {5,6,7} ;
Plane Surface(1) = {1,2} ;
The above yields a highly unstructured mesh, despite there being only a small hole in an otherwise simple and rectangular geometry:
What I'd have in mind is something like this (taken from Automesh2d's web site, a commercial mesh generator):
Can I get a similar "quasi-structured," two-dimensional quadrilateral mesh also using Gmsh (or for that matter, using any open source software)? I'd really appreciate any support.
This should be possible using Transfinite Lines. You define a Transfinite Line between certain points, in your case between the corner points of your large rectangle. While doing so, you can specify how many nodes should be included on this line. If you choose the same number of nodes on the opposing lines of the rectangle, you should be doing fine. Recombine the surface and you're done.
In this simple YouTube-Tutorial, you'll be guided through it step-by-step.
I have quickly tried a similar geometry to yours, this is what I get:
Mesh

MPI Communication Pattern

I was wondering if there was a smart way to do this. Let's say I have three nodes, 0, 1, 2. And let's say each node has an array, a0, a1, a2. If the contents of each node is something like
a0 = {0, 1, 2, 1}
a1 = {1, 2, 2, 0}
a2 = {0, 0, 1, 2}
Is there a clever communication pattern so to move each number to it's corresponding node, i.e.
a0 = {0, 0, 0, 0}
a1 = {1, 1, 1, 1}
a2 = {2, 2, 2, 2}
The approach I have in mind, would involve sorting and temporary buffers, but I was wondering if there was a smarter way?
You can use MPI_Alltoallv for this in the following way:
Sort the local_data (a) by corresponding node of each element in increasing order.
Create a send_displacements array such that send_displacements[r] indicates the index of the first element in the local_data that refers to node r.
Create a send_counts array such that send_counts[r] equals the number of elements in local_data that correspond to node r. This can be computed send_counts[r] = send_displacements[r+1] - send_displacements[r] except for the last rank.
MPI_Alltoall(send_counts, 1, MPI_INT, recv_counts, 1, MPI_INT, comm)
Compute recv_displacements such that recv_displacements[r] = sum(recv_counts[r'] for all r' < r).
Prepare a recv_data with sum(recv_counts) elements.
MPI_Alltoallv(local_data, send_counts, send_displacements, MPI_INT, recv_data, recv_counts, recv_displacements, MPI_INT, comm)

Mathematica: part assignment

I'm trying to implement an algorithm to build a decision tree from a dataset.
I wrote a function to calculate the information gain between a subset and a particular partition, then I try all the possible partition and want to choose the "best" partition, in the sense that it's got the lowest entropy.
This procedure must be recursive, hence, after the first iteration, it needs to work for every subset of the partition you got in the previous step.
These are the data:
X = {{1, 0, 1, 1}, {1, 1, 1, 1}, {0, 1, 1, 1}, {1, 1, 1, 0}, {1, 1, 0, 0}}
Xfin[0]=X
This is the function: for every subset of the partition, it tries all the possible partitions and calculate the IG. Then it selects the partition with IGMAX:
Partizioneottimale[X_, n_] :=
For[l = 1, l <= Length[Flatten[X[n], n - 1]], l++,
For[v = 1, v <= m, v++,
If[IG[X[n][[l]], Partizione[X[n][[l]], v]] == IGMAX[X[n][[l]]],
X[n + 1][[l]] := Partizione[X[n][[l]], v]]]]
then I call it:
Partizioneottimale[Xfin, 0]
and it works fine for the first one:
Xfin[1]
{{{1, 0, 1, 1}, {1, 1, 1, 1}, {0, 1, 1, 1}, {1, 1, 1, 0}}, {{1, 0, 0, 0}}}
That is the partition with lowest entropy.
But it doesn't work for the next ones:
Partizioneottimale[Xfin, 1]
Set delayed::steps : Xfin[1+1] in the part assignment is not a symbol
Has anybody any idea about how to solve this?
Thanks
without unraveling all your logic a simple fix is this:
Partizioneottimale[X_, n_] := (
xnp1 = Table[Null, {Length[Flatten[X[n], n - 1]]}] ;
For[l = 1, l <= Length[Flatten[X[n], n - 1]], l++,
For[v = 1, v <= m, v++,
If[IG[X[n][[l]], Partizione[X[n][[l]], v]] == IGMAX[X[n][[l]]],
xnp1[[l]] = Partizione[X[n][[l]], v]]]] ;
X[n+1] = xnp1 ; )

How do I write an Euler function in Mathematica?

I programmed a Euler function but misread the instructions, so now I have to make a new one, but I can't figure it out.
I have made the following automatic Euler function.
f[x_, y_] := -x y^2;
x0 = 0;
y0 = 2;
xend = 2;
steps = 20;
h = (xend - x0)/steps // N;
x = x0;
y = y0;
eulerlist = {{x, y}};
For[i = 1, i <= steps, y = f[x, y]*h + y;
x = x + h;
eulerlist = Append[eulerlist, {x, y}];
i++
]
Print[eulerlist]
But it just generates the list I have specified.
I would like to have a Euler function which is able to generate this form:
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
I don't seem to get any further.
It is not clear what you are asking, but if what you want is to be able to input
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
and get
{{0,2},{0.1,2.},{0.2,1.96},{0.3,1.88317},{0.4,1.77678},{0.5,1.6505},{0.6,1.51429},{0.7,1.37671},{0.8,1.24404},{0.9,1.12023},{1.,1.00728},{1.1,0.905822},{1.2,0.815565},{1.3,0.735748},{1.4,0.665376},{1.5,0.603394},{1.6,0.548781},{1.7,0.500596},{1.8,0.457994},{1.9,0.420238},{2.,0.386684}}
Then you need to write a function definition like this:
Euler[y0_, f_, {x0_, xend_}, steps_Integer?Positive] := (* body *)
Notice the underscores to denote patterns, the := to denote delayed evaluation and the pattern specification Integer?Positive.
As for the body of the function -- oh my goodness could you have picked a less Mathematica-style approach? Perhaps not. Procedural loops and Append are almost never the best way to do anything in Mathematica.
Here is a better solution.
Euler[y_, y0_, f_, {x_, x0_, xend_}, steps_Integer?Positive] :=
With[{h = N[(xend - x0)/steps], ff = Function[{x, y}, f]},
NestList[{#[[1]] + h, ff[#[[1]], #[[2]]]*h + #[[2]]} &, {x0, y0},
steps]]
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
{{0, 2}, {0.1, 2.}, {0.2, 1.96}, {0.3, 1.88317}, {0.4,
1.77678}, {0.5, 1.6505}, {0.6, 1.51429}, {0.7, 1.37671}, {0.8,
1.24404}, {0.9, 1.12023}, {1., 1.00728}, {1.1, 0.905822}, {1.2,
0.815565}, {1.3, 0.735748}, {1.4, 0.665376}, {1.5, 0.603394}, {1.6,
0.548781}, {1.7, 0.500596}, {1.8, 0.457994}, {1.9, 0.420238}, {2.,
0.386684}}
If you want something that outputs Euler[y, 2, -x y^2, {x, 0, 2}, 20], then typing it into the notebook is the quickest method.

Transforming matrix diagonals to ragged array?

I'm trying to come up with a non brute-force solution to the following problem. Given a matrix of arbitrary size:
[6 0 3 5]
[3 7 1 4]
[1 4 8 2]
[0 2 5 9]
Transform its diagonals to a list of vectors, like so:
(0)
(1, 2)
(3, 4, 5)
(6, 7, 8, 9)
(0, 1, 2)
(3, 4)
(5)
(Working from bottom left to top right in this example)
Is there an elegant way to do this short of iterating up the left column and across the top row?
I would just write a little function to transform the vector indices into matrix indices.
Say the matrix is NxN square, then there will be 2N-1 vectors; if we number the vectors from 0 to 2N-2, element k of vector n will be at row max(N-1-n+k,k) and column max(n+k-N+1,k) (or in reverse, the matrix element at row i, column j will be element min(i,j) of vector N-1+j-i). Then whenever you need to access an element of a vector, just convert the coordinates from k,n to i,j (that is, convert vector indices to matrix indices) and access the appropriate element of the matrix. Instead of actually having a list of vectors, you'll wind up with something that emulates a list of vectors, in the sense that it can give you any desired element of any vector in the list - which is really just as good. (Welcome to duck typing ;-)
If you're going to access every element of the matrix, though, it might just be quicker to iterate, rather than doing this computation every time.
(non-checked code)
Something like this (java code):
// suppose m is the matrix, so basically an int[][] array with r rows and c columns
// m is an int[rows][cols];
List result = new ArrayList(rows + cols - 1);
for (int i = 0; i < (rows + cols - 1))
{
int y;
int x;
if (i < rows)
{
x = 0;
y = rows - i - 1;
}
else
{
x = i - rows + 1;
y = 0;
}
Vector v = new Vector();
while (y < rows && x < cols)
{
y++;
x++;
v.add(new Integer(m[y][c]));
}
result.add(v);
}
// result now contains the vectors you wanted
Edit: i had x and y mixed up, corrected now.
Mathematica:
m = {{6, 0, 3, 5},
{3, 7, 1, 4},
{1, 4, 8, 2},
{0, 2, 5, 9}};
Table[Diagonal[m, i], {i, 1 - Length#m, Length#m[[1]] - 1}]
Which gives a list of the i'th diagonals where the 0th diagonal is the main diagonal, i = -1 gives the one below it, etc. In other words, it returns:
{{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {0, 1, 2}, {3, 4}, {5}}
Of course using the built-in Diagonal function is kind of cheating. Here's an implementation of Diagonal from scratch:
(* Grab the diagonal starting from element (i,j). *)
diag0[m_,i_,j_] := Table[m[[i+k, j+k]], {k, 0, Min[Length[m]-i, Length#m[[1]]-j]}]
(* The i'th diagonal -- negative means below the main diagonal, positive above. *)
Diagonal[m_, i_] := If[i < 0, diag0[m, 1-i, 1], diag0[m, 1, i+1]]
The Table function is basically a for loop that collects into a list. For example,
Table[2*i, {i, 1, 5}]
returns {2,4,6,8,10}.

Resources