-
Notifications
You must be signed in to change notification settings - Fork 1
/
GALS_Advection_MPI.cpp
272 lines (208 loc) · 10.4 KB
/
GALS_Advection_MPI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// GALS - Before compiling the program, update the section of this program that is in the beginning of main and update all the initializer files
//
// Created by Raunak Bardia, Chia-Wei Kuo, and Arpit Agarwal on December 20, 2017.
//
// Implementing GALS for a given initial level set function
// in a specified velocity field for a grid of cells
//
// Given -
// 1. Defining function at t = 0 which implies that phi and psi values are available for all node points at t = 0
// 2. Given velocity for the complete domain at all times
//
// All required data is stored in separate 2D matrices of phi, psix, psiy and psixy
// Boundary Condition grad(velocity).n > 0
/* * * * * * * * * * * * * * MPI IMPLEMENTATION * * * * * * * * * * * * * * */
// THIS IMPLEMENTATION WON'T WORK IF THE GRID IS SMALLER THAN (2 X 2)
#include <iostream>
#include <iomanip>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <vector>
#include <tuple>
#include "VariableDefinitions.h"
#include "Hermite.h"
#include "InitializeLevelSet.h" //UPDATE THIS HEADER FILE WITH THE RELEVANT FUNCTIONS
#include "VortexVelocity.h" //UPDATE THIS HEADER FILE WITH THE RELEVANT FUNCTIONS
#include "TimeSteppingMethods.h"
#include "Allocation.h"
#include "AdvectionPointCalcs.h"
#include "Constants.h"
#include <mpi.h> // used for MPI
#include "defineMPI.h" // used for MPI
using namespace std;
using namespace galsfunctions;
using namespace mpi;
// y direction is the first index of array, x direction is the second index of array
int main(int argc, char **argv){
/* UPDATE ALL THE FOLLOWING VALUES */
#include "Setting.h"
//MAKE SURE THAT YOU HAVE ENOUGH MEMORY SPACE IF YOU ARE STORING A LOT OF TIME STEP VALUES BECAUSE IT STORES ACROSS GRID POINTS FOR EACH PRINTSTEP
/* USER UPDATE OVER */
struct timeval start1; struct timeval end1; unsigned long diff1;
/***** used for MPI only ******/
//
context ctx(&argc, &argv);
//
/***** used for MPI only ******/
unsigned int n = Tfinal/dt; //Number of time steps
if(option != 1)
printstep = n;
// Node Locations
double dx = (xlim2 - xlim1)/(nx - 1);
double dy = (ylim2 - ylim1)/(ny - 1);
vectorarray x,y;
gridnodes(x,y,xlim1,ylim1,dx,dy,nx,ny);
// Initializing at t = 0
gridarray mphi, mpsix, mpsiy, mpsixy; // level set matrix
allocate_levelset_matrices(mphi,mpsix,mpsiy,mpsixy,x,y,nx,ny); //Initializing level set matrices
gridarray tempphi(mphi), temppsix(mpsix), temppsiy(mpsiy), temppsixy(mpsixy); // Making level set matrix copies for time loop use
// Removing existing files with these names if any
remove("phi.txt");
remove("psix.txt");
remove("psiy.txt");
remove("psixy.txt");
remove("details.txt");
remove("Velocity_x.txt");
remove("Velocity_y.txt");
fileprint(mphi,mpsix,mpsiy,mpsixy,nx,ny,x,y,0.0,T_period);
/*
* Let the following represent one cell
*
* 2 3
* *
*
*
* *
* 0 1
*
* the value of the loop for this cell varies from 0 -> 3 but the (i, j) coordinates that represent these points in an array change as (i,j), (i,j+1), (i+1,j), (i+1, j+1)
*
* Hence, tempindexes take care of these changes
*
*/
ofstream details;
details.open("details.txt", ios::out | ios::app);
details<< nx << "," << ny << "," << std::fixed << std::setprecision(10) << dx << "," << dy << "," << xlim1 << "," << xlim2 << "," << ylim1 << "," << ylim2 << "," << n << "," << dt << "," << printstep;
details.close();
// TIME STEPPING LOOP
// If only the initial and final profiles are needed
gettimeofday(&start1,NULL); // start the timer
for(unsigned int t = 0; t < n; t++){
intgridarray tracker;
tracker.resize(ny,intvectorarray(nx,0));
gridarray xadv, yadv;
xadv.resize(ny,vectorarray(nx,0.0));
yadv.resize(ny,vectorarray(nx,0.0));
// used for MPI only, here I use 2 nodes
unsigned int n_Nodes = 2;
// initialize the memory contiguous matrices
double **A1, **B1, **A3, **B3, **C3;
unsigned int nnx = nx/n_Nodes;
A1 = alloc_2d_int(nnx,ny);
B1 = alloc_2d_int(nnx,ny);
A3 = alloc_2d_int(nnx,ny);
B3 = alloc_2d_int(nnx,ny);
C3 = alloc_2d_int(nnx,ny);
// end of initialization
// advection_point_MPI(x, y, xadv, yadv, t, dt, T_period,0,nx, backtrace_scheme);
// node-1
if(ctx.rank() == 0){
constexpr int source_rank = 1;
MPI_Status status;
advection_point_MPI(x, y, xadv, yadv, t, dt, T_period,0,nnx, backtrace_scheme);
// receive the data from node-2
MPI_Recv(&(A1[0][0]), ny*nnx, MPI_FLOAT, source_rank, 0, MPI_COMM_WORLD, &status);
MPI_Recv(&(B1[0][0]), ny*nnx, MPI_FLOAT, source_rank, 0, MPI_COMM_WORLD, &status);
// populate the full data to xadv and yadv
for(unsigned int i = 0; i < ny; i++){ // loop for y - rows in the array
for(unsigned int j = nnx; j < nx; j++){ // loop for x - columns in the array
xadv[i][j]=A1[j-nnx][i]; //the matrix received from node-2 is the transpose matrix
yadv[i][j]=B1[j-nnx][i];
}
}
// done for MPI task
intgridarray cellx, celly;
cellx.resize(ny,intvectorarray(nx,0));
celly.resize(ny,intvectorarray(nx,0));
// do the task in node-1
find_advection_point_location_MPI(x, y, xadv, yadv, cellx, celly, tracker, xlim1, xlim2, ylim1, ylim2,0,nnx);
// receive the data from node-2
MPI_Recv(&(A3[0][0]), ny*nnx, MPI_FLOAT, source_rank, 0, MPI_COMM_WORLD, &status);
MPI_Recv(&(B3[0][0]), ny*nnx, MPI_FLOAT, source_rank, 0, MPI_COMM_WORLD, &status);
MPI_Recv(&(C3[0][0]), ny*nnx, MPI_FLOAT, source_rank, 0, MPI_COMM_WORLD, &status);
// populate the full data to xadv and yadv
for(unsigned int i = 0; i < ny; i++){ // loop for y - rows in the array
for(unsigned int j = nnx; j < nx; j++){ // loop for x - columns in the array
cellx[i][j]=A3[j-nnx][i];
celly[i][j]=B3[j-nnx][i];
tracker[i][j]=C3[j-nnx][i];
}
}
// done for MPI task
update_levelset_data(x, y, xadv, yadv, cellx, celly, tracker, t, dt,
tempphi, temppsix, temppsiy, temppsixy, mphi, mpsix, mpsiy, mpsixy,
psischeme,backtrace_scheme,T_period);
//---------------------------------------------------------------------------------------------------------
// Update the mixed derivatives now for the remaining grid points
update_mixed_derivatives(temppsix, temppsiy, temppsixy, nx, ny, dx, dy);
//---------------------------------------------------------------------------------------------------------
// Feeding values back to the master matrix
mphi = tempphi;
mpsix = temppsix;
mpsiy = temppsiy;
mpsixy = temppsixy;
//---------------------------------------------------------------------------------------------------------
// Feeding phi, psix, psiy and psixy values in their respective files
if((t+1) % printstep == 0)
fileprint(mphi,mpsix,mpsiy,mpsixy,nx,ny,x,y,(t+1)*dt,T_period);
cout<< t+1;
cout<< " Time Step Completed" <<'\n';
//---------------------------------------------------------------------------------------------------------
xadv.clear();
yadv.clear();
tracker.clear();
cellx.clear();
celly.clear();
} // end of node-1
// task for node-2
else {
constexpr int dest_rank = 0; // We send a message to Task 0
advection_point_MPI(x, y, xadv, yadv, t, dt, T_period, nnx,nx, backtrace_scheme);
// populate data, here I transpose the matrix because for c++, matrix is read in row-wise order
for(unsigned int i = 0; i < ny; i++){ // loop for y - rows in the array
for(unsigned int j = nnx; j < nx; j++){ // loop for x - columns in the array
A1[j-nnx][i]=xadv[i][j]; // this is the transpose matrix
B1[j-nnx][i]=yadv[i][j];
}
}
//send data to node-1
MPI_Send(&(A1[0][0]), ny*nnx, MPI_FLOAT, dest_rank, 0, MPI_COMM_WORLD);
MPI_Send(&(B1[0][0]), ny*nnx, MPI_FLOAT, dest_rank, 0, MPI_COMM_WORLD);
intgridarray cellx, celly;
cellx.resize(ny,intvectorarray(nx,0));
celly.resize(ny,intvectorarray(nx,0));
find_advection_point_location_MPI(x, y, xadv, yadv, cellx, celly, tracker, xlim1, xlim2, ylim1, ylim2,nnx,nx);
// populate data, here I transpose the matrix because for c++, matrix is read in row-wise order
for(unsigned int i = 0; i < ny; i++){ // loop for y - rows in the array
for(unsigned int j = nnx; j < nx; j++){ // loop for x - columns in the array
A3[j-nnx][i]=cellx[i][j];
B3[j-nnx][i]=celly[i][j];
C3[j-nnx][i]=tracker[i][j];
}
}
//send data to node-1
MPI_Send(&(A3[0][0]), ny*nnx, MPI_FLOAT, dest_rank, 0, MPI_COMM_WORLD);
MPI_Send(&(B3[0][0]), ny*nnx, MPI_FLOAT, dest_rank, 0, MPI_COMM_WORLD);
MPI_Send(&(C3[0][0]), ny*nnx, MPI_FLOAT, dest_rank, 0, MPI_COMM_WORLD);
} // end of node-2
} // end of time marching loop
// end of timer, measure time
gettimeofday(&end1,NULL);
diff1 = 1000000 * (end1.tv_sec-start1.tv_sec)+ end1.tv_usec-start1.tv_usec;
cout<<diff1*0.001<<endl;
return 0;
}