Skip to content

Commit 1f0622b

Browse files
committed
FEAT: connectivity for dipole grid
1 parent 9c9ac14 commit 1f0622b

File tree

1 file changed

+124
-4
lines changed

1 file changed

+124
-4
lines changed

src/init_mag_grid.cpp

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,127 @@
55

66
#include "aether.h"
77

8+
// ----------------------------------------------------------------------
9+
// Create connectivity between the nodes for message passing for dipole
10+
// (this looks a lot like sphere, since they are very related)
11+
// ----------------------------------------------------------------------
12+
13+
void Grid::create_dipole_connection(Quadtree quadtree) {
14+
15+
std::string function = "Grid::create_dipole_connection";
16+
static int iFunction = -1;
17+
report.enter(function, iFunction);
18+
19+
IsLatLonGrid = true;
20+
21+
// Get some coordinates and sizes in normalized coordinates:
22+
arma_vec lower_left_norm = quadtree.get_vect("LL");
23+
arma_vec middle_norm = quadtree.get_vect("MID");
24+
arma_vec size_right_norm = quadtree.get_vect("SR");
25+
arma_vec size_up_norm = quadtree.get_vect("SU");
26+
27+
// Move to the next block in 4 directions:
28+
arma_vec down_norm = middle_norm - 0.51 * size_up_norm;
29+
arma_vec up_norm = middle_norm + 0.51 * size_up_norm;
30+
arma_vec left_norm = middle_norm - 0.51 * size_right_norm;
31+
arma_vec right_norm = middle_norm + 0.51 * size_right_norm;
32+
33+
// The first component could wrap around:
34+
right_norm(0) = fmod(right_norm(0), quadtree.limit_high(0));
35+
left_norm(0) = fmod((left_norm(0) + quadtree.limit_high(0)),
36+
quadtree.limit_high(0));
37+
38+
// These should be the exact edge of the face.
39+
// The from and to processors should get these in the same place,
40+
// so they can be used to match which processor to send / receive info
41+
edge_Xp = middle_norm + size_right_norm / 2.0;
42+
// wrap in longitude:
43+
edge_Xp(0) = fmod(edge_Xp(0), quadtree.limit_high(0));
44+
edge_Xm = middle_norm - size_right_norm / 2.0;
45+
edge_Yp = middle_norm + size_up_norm / 2.0;
46+
edge_Ym = middle_norm - size_up_norm / 2.0;
47+
// by default, edge_Z isn't even an edge, since most processors should
48+
// not exchange messages in the Z direction.
49+
edge_Z = middle_norm;
50+
51+
iProcYm = quadtree.find_point(down_norm) + iMember * nGrids;
52+
iProcYp = quadtree.find_point(up_norm) + iMember * nGrids;
53+
iProcXm = quadtree.find_point(left_norm) + iMember * nGrids;
54+
iProcXp = quadtree.find_point(right_norm) + iMember * nGrids;
55+
iProcZ = iProc;
56+
57+
iRoot = quadtree.find_root(middle_norm);
58+
iRootYm = quadtree.find_root(down_norm);
59+
iRootYp = quadtree.find_root(up_norm);
60+
iRootXm = quadtree.find_root(left_norm);
61+
iRootXp = quadtree.find_root(right_norm);
62+
iRootZ = iRoot;
63+
64+
// If we are a closed field-line, then we want to exchange messages
65+
// along the Z direction, which turns out to be the same processor
66+
// as the Y direction, so just take that one:
67+
IsClosed = false;
68+
if ((middle_norm(1) < 0) && (up_norm(1) > 0)) {
69+
// We are in the south and need to pass to the north:
70+
iRootZ = iRootYp;
71+
iProcZ = iProcYp;
72+
edge_Z = edge_Yp;
73+
// To make the point unique, we need to alter the edge location
74+
// otherwise the message passing will get confused. Since the
75+
// points are "higher" than the other edges, let's just add some
76+
// to the 3rd dimension:
77+
edge_Z(2) = 5.0;
78+
IsClosed = true;
79+
}
80+
if ((middle_norm(1) > 0) && (down_norm(1) < 0)) {
81+
// We are in the north and need to pass to the south:
82+
iRootZ = iRootYm;
83+
iProcZ = iProcYm;
84+
edge_Z = edge_Ym;
85+
// See note above...
86+
edge_Z(2) = 5.0;
87+
IsClosed = true;
88+
}
89+
90+
// Check if touching South Pole:
91+
if (lower_left_norm(1) == quadtree.limit_low(1)) {
92+
DoesTouchSouthPole = true;
93+
94+
// edges need to be adjusted to deal with longitudes, since the
95+
// pole will 180deg different for the from and to processors
96+
if (edge_Ym(0) < 1.0)
97+
edge_Ym(0) += 0.5;
98+
else
99+
edge_Ym(0) -= 0.5;
100+
}
101+
102+
// Check if touching North Pole:
103+
if (lower_left_norm(1) + size_up_norm(1) == quadtree.limit_high(1)) {
104+
DoesTouchNorthPole = true;
105+
106+
// edge need to be adjusted to deal with longitudes, since the
107+
// pole will 180deg different for the from and to processors
108+
if (edge_Yp(0) < 1.0)
109+
edge_Yp(0) += 0.5;
110+
else
111+
edge_Yp(0) -= 0.5;
112+
}
113+
114+
if (report.test_verbose(2))
115+
std::cout << "connectivity : "
116+
<< " iProc : " << iProc << "\n"
117+
<< " isnorth : " << DoesTouchNorthPole << "\n"
118+
<< " issouth : " << DoesTouchSouthPole << "\n"
119+
<< " iProcYm : " << iProcYm << "\n"
120+
<< " iProcYp : " << iProcYp << "\n"
121+
<< " iProcXm : " << iProcXm << "\n"
122+
<< " iProcXp : " << iProcXp << "\n";
123+
124+
report.exit(function);
125+
return;
126+
}
127+
128+
8129
// ----------------------------------------------------------------------
9130
// Routine to convert p and q to r and theta. Can be solved iteratively,
10131
// or with approach from (Swisdak, 2006), who solved it analytically:
@@ -99,10 +220,9 @@ bool Grid::init_dipole_grid(Quadtree quadtree_ion, Planets planet) {
99220
IsCubeSphereGrid = false;
100221
IsDipole = true;
101222

102-
// report.print(0, "Creating inter-node connections Grid");
103-
104-
//if (!Is0D & !Is1Dz)
105-
// create_sphere_connection(quadtree_ion);
223+
report.print(0, "Creating inter-node dipole connections");
224+
if (!Is0D & !Is1Dz)
225+
create_dipole_connection(quadtree_ion);
106226

107227
report.print(0, "Creating Dipole Grid");
108228

0 commit comments

Comments
 (0)