OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main.cu
1//
2// Created by jstark on 2023-05-05.
3//
38
39#include <iostream>
40#include <typeinfo>
41
42#include "CSVReader/CSVReader.hpp"
43
44// Include redistancing files
48#include "level_set/redistancing_Sussman/HelpFunctionsForGrid.hpp" // For the ghost initialization
49#include "RemoveLines.hpp" // For removing thin (diagonal or straight) lines
50
51#include "FiniteDifference/FD_simple.hpp"
52
53#include "DiffusionSpace_sparseGrid.hpp"
54#include "HelpFunctions_diffusion.hpp"
55
56#include "Decomposition/Distribution/BoxDistribution.hpp"
57
58const size_t dims = 3;
59
60// Property indices full grid
61const size_t PHI_FULL = 0;
62
64
65const openfpm::vector<std::string> prop_names_full = {"Phi_Sussman_Out"};
66
67
68// Property indices sparse grid
69const size_t PHI_PHASE = 0;
70const size_t U_N = 1;
71const size_t U_NPLUS1 = 2;
72const size_t K_SINK = 3;
73
74
76const openfpm::vector<std::string> prop_names_sparse = {"PHI_PHASE",
77 "U_N",
78 "U_NPLUS1",
79 "K_SINK"};
80
81
82// Space indices
83constexpr size_t x = 0, y = 1, z = 2;
84
85// input
86const std::string path_to_redistancing_result =
87 "/MY_PATH/porous_ceramics/sussman_with_cuda/build/output_sussman_sparse_grid_porousCeramics_1216x1016x941/";
88
89
90const std::string redistancing_filename = "sparseGrid_initial.hdf5";
91
92const std::string path_to_size = path_to_redistancing_result;
93
94const std::string output_name = "output_heat_conduction_porous_ceramics_1216x1016x941_sparse_grid";
95
96
97int main(int argc, char* argv[])
98{
99 // Initialize library.
100 openfpm_init(&argc, &argv);
101 auto & v_cl = create_vcluster();
102
103 timer t_total;
104 timer t_iterative_diffusion_total;
105 timer t_iteration_wct;
106 timer t_GPU;
107
108
109 t_total.start();
110
112 // Set current working directory, define output paths and create folders where output will be saved
113 std::string cwd = get_cwd();
114 const std::string path_output = cwd + "/" + output_name + "/";
116
117 if(v_cl.rank()==0) std::cout << "Redistancing result will be loaded from " << path_to_redistancing_result << redistancing_filename << std::endl;
118
119 if(v_cl.rank()==0) std::cout << "Outputs will be saved to " << path_output << std::endl;
120
124 // Create full grid and load redistancing result
126 // Read size of sussman redistancing output grid from csv files
129
130 size_t m, n;
131 read_csv_to_vector(path_to_size + "/N.csv", v_sz, m, n);
132 read_csv_to_vector(path_to_size + "/L.csv", v_L, m, n);
133
134 const float Lx_low = 0.0;
135 const float Lx_up = v_L.get(x);
136 const float Ly_low = 0.0;
137 const float Ly_up = v_L.get(y);
138 const float Lz_low = 0.0;
139 const float Lz_up = v_L.get(z);
140
142 size_t sz[dims] = {v_sz.get(x), v_sz.get(y), v_sz.get(z)};
143 Box<dims, float> box({Lx_low, Ly_low, Lz_low}, {Lx_up, Ly_up, Lz_up});
144 Ghost<dims, long int> ghost(1);
145
146 // Defining the decomposition and the input grid type
149 grid_in_type g_dist(sz, box, ghost);
150
151 std::cout << "Rank " << v_cl.rank() << " starts loading redistancing result..." << std::endl;
152 g_dist.load(path_to_redistancing_result + "/" + redistancing_filename); // Load SDF
153 std::cout << "Rank " << v_cl.rank() << " finished loading redistancing result." << std::endl;
154
157 // Get sparse grid of heat conduction domain
159 // Create sparse grid
160 std::cout << "Rank " << v_cl.rank() << " starts creating sparse grid." << std::endl;
161
162
163 typedef sgrid_dist_id_gpu<dims, float, props_sparse, CudaMemory, Dec> sparse_grid_type;
164 sparse_grid_type g_sparse(sz, box, ghost);
165 g_sparse.setPropNames(prop_names_sparse);
166
167
168 const float d_low = 0.0, d_up = Lx_up;
169 get_diffusion_domain_sparse_grid<PHI_FULL, PHI_PHASE>(g_dist, g_sparse, d_low, d_up);
170
171 // Alternatively: load sparse grid of diffusion domain from HDF5 file
172 // g_sparse.load(path_to_redistancing_result + "/" + redistancing_filename);
173
174 std::cout << "Rank " << v_cl.rank() << " finished creating sparse grid." << std::endl;
175
177 // Define parameters for heat conduction
179 const float u0 = 1.0; // Initial heat from one side
180 const float D = 0.1; // Heat diffusivity
181 const float sink_rate = 0.1; // Rate of heat loss at solid-air interface
182 std::cout << "Diffusion coefficient in s/(mm^2): " << D << std::endl;
183 std::cout << "Sink rate in 1/s: " << sink_rate << std::endl;
184
185 // Set initial condition: initial heat source is a sphere of radius R at the domain center
186 const float center[dims] = {(Lx_up+Lx_low)/(float)2,
187 (Ly_up+Ly_low)/(float)2,
188 (Lz_up+Lz_low)/(float)2};
189 const float R = Lz_up / 4.0;
190
191 auto dom = g_sparse.getDomainIterator();
192 while(dom.isNext())
193 {
194 auto key = dom.get();
195
196 // Initial condition: heat comes from sphere at center
197 Point<dims, float> coords = g_sparse.getPos(key);
198
199 if(((coords.get(x) - center[x]) * (coords.get(x) - center[x])
200 + (coords.get(y) - center[y]) * (coords.get(y) - center[y])
201 + (coords.get(z) - center[z]) * (coords.get(z) - center[z])) <= R * R)
202 {
203 g_sparse.template insertFlush<U_N>(key) = u0;
204 }
205 else g_sparse.template insertFlush<U_N>(key) = 0.0;
206
207 ++dom;
208 }
209
211
216 // Defining the functor that will be passed to the GPU to simulate reaction-diffusion
217 // GetCpBlockType<typename SGridGpu, unsigned int prp, unsigned int stencil_size>
218 typedef typename GetCpBlockType<decltype(g_sparse),0,1>::type CpBlockType;
219
220 const float dx = g_sparse.spacing(x), dy = g_sparse.spacing(y), dz = g_sparse.spacing(z);
221 // Stability criterion for FTCS : dt = 1/4 * 1/(1/dx^2 + 1/dy^2)
222 const float dt = diffusion_time_step(g_sparse, D);
223 std::cout << "dx, dy, dz = " << g_sparse.spacing(x) << "," << g_sparse.spacing(y) << "," << g_sparse.spacing(z) << std::endl;
224 std::cout << "dt = 1/(4D) * 1/(1/dx^2 + 1/dy^2 + 1/dz^2) = " << dt << std::endl;
225
226 auto func_heatDiffusion_withSink = [dx, dy, dz, dt, d_low, D, sink_rate] __device__ (
227 float & u_out, // concentration output
228 float & phi_out, // sdf of domain output (dummy)
229 CpBlockType & u, // concentration input
230 CpBlockType & phi, // sdf of domain (for boundary conditions)
231 auto & block,
232 int offset,
233 int i,
234 int j,
235 int k
236 )
237 {
239 // Stencil
240 // Concentration
241 float u_c = u(i, j, k);
242 float u_px = u(i+1, j, k);
243 float u_mx = u(i-1, j, k);
244 float u_py = u(i, j+1, k);
245 float u_my = u(i, j-1, k);
246 float u_pz = u(i, j, k+1);
247 float u_mz = u(i, j, k-1);
248
249 // Signed distance function
250 float phi_c = phi(i, j, k);
251 float phi_px = phi(i+1, j, k);
252 float phi_mx = phi(i-1, j, k);
253 float phi_py = phi(i, j+1, k);
254 float phi_my = phi(i, j-1, k);
255 float phi_pz = phi(i, j, k+1);
256 float phi_mz = phi(i, j, k-1);
257
258 // Get sink term
259 float k_sink = 0; // Sink equal to zero in bulk and equal to sink_rate only at the surfaces
260
261 // Impose no-flux boundary conditions and sink term at the surface (i.e., when neighbor is outside)
262 if (phi_px <= d_low + std::numeric_limits<float>::epsilon()) {u_px = u_c; k_sink = sink_rate;}
263 if (phi_mx <= d_low + std::numeric_limits<float>::epsilon()) {u_mx = u_c; k_sink = sink_rate;}
264 if (phi_py <= d_low + std::numeric_limits<float>::epsilon()) {u_py = u_c; k_sink = sink_rate;}
265 if (phi_my <= d_low + std::numeric_limits<float>::epsilon()) {u_my = u_c; k_sink = sink_rate;}
266 if (phi_pz <= d_low + std::numeric_limits<float>::epsilon()) {u_pz = u_c; k_sink = sink_rate;}
267 if (phi_mz <= d_low + std::numeric_limits<float>::epsilon()) {u_mz = u_c; k_sink = sink_rate;}
268
269 block.template get<K_SINK>()[offset] = k_sink; // Just for checking in paraview
270
271 // Compute concentration of next time point
272 u_out = u_c + dt * ( D * ((u_px + u_mx - 2 * u_c)/(dx * dx)
273 + (u_py + u_my - 2 * u_c)/(dy * dy)
274 + (u_pz + u_mz - 2 * u_c)/(dz * dz))
275 - k_sink * u_c);
276
277
278 // dummy outs
279 phi_out = phi_c;
280 };
281
283
284
286 // Create text file to which wall clock time for iteration incl. ghost communication will be saved
287 std::string path_time_filewct = path_output + "/time_wct_incl_ghostCommunication" + std::to_string(v_cl.rank()) + ".txt";
288 std::ofstream out_wct_file(path_time_filewct, std::ios_base::app);
289
290 // Create text file to which GPU time will be saved
291 std::string path_time_filegpu = path_output + "/time_GPU" + std::to_string(v_cl.rank()) + ".txt";
292 std::ofstream out_GPUtime_file(path_time_filegpu, std::ios_base::app);
293
294
295 // Iterative diffusion
296 // const size_t iterations = 1e6;
297 const size_t iterations = 103;
298 const size_t number_write_outs = 10;
299 const size_t interval_write = iterations / number_write_outs; // Find interval for writing to reach
300 size_t iter = 0;
301 float t = 0;
302
303 // Copy from host to GPU for simulation
304 g_sparse.template hostToDevice<U_N, U_NPLUS1, K_SINK, PHI_PHASE>();
305 g_sparse.template ghost_get<PHI_PHASE, K_SINK>(RUN_ON_DEVICE | SKIP_LABELLING);
306 t_iterative_diffusion_total.start();
307 while(iter <= iterations)
308 {
309 if (iter % 2 == 0)
310 {
311 t_iteration_wct.start();
312 g_sparse.template ghost_get<U_N>(RUN_ON_DEVICE | SKIP_LABELLING);
313 t_GPU.startGPU();
314 g_sparse.template conv2_b<
315 U_N,
316 PHI_PHASE,
317 U_NPLUS1,
318 PHI_PHASE, 1>
319 ({0, 0, 0},
320 {(long int) sz[x]-1, (long int) sz[y]-1, (long int) sz[z]-1},
321 func_heatDiffusion_withSink);
322 t_GPU.stopGPU();
323 t_iteration_wct.stop();
324
325 // Write out time to text-file
326 out_wct_file << t_iteration_wct.getwct() << ",";
327 out_GPUtime_file << t_GPU.getwctGPU() << ",";
328
329 t_iteration_wct.reset();
330 }
331 else
332 {
333 t_iteration_wct.start();
334 g_sparse.template ghost_get<U_NPLUS1>(RUN_ON_DEVICE | SKIP_LABELLING);
335 t_GPU.startGPU();
336 g_sparse.template conv2_b<
337 U_NPLUS1,
338 PHI_PHASE,
339 U_N,
340 PHI_PHASE, 1>
341 ({0, 0, 0},
342 {(long int) sz[x]-1, (long int) sz[y]-1, (long int) sz[z]-1},
343 func_heatDiffusion_withSink);
344 t_GPU.stopGPU();
345 t_iteration_wct.stop();
346
347 // Write out time to text-file
348 out_wct_file << t_iteration_wct.getwct() << ",";
349 out_GPUtime_file << t_GPU.getwctGPU() << ",";
350
351 t_iteration_wct.reset();
352 }
353
354
355 if (iter % interval_write == 0)
356 {
357 // Copy from GPU to host for writing
358 g_sparse.template deviceToHost<U_N, U_NPLUS1, K_SINK, PHI_PHASE>();
359
360 // Write g_sparse to vtk
361 g_sparse.write_frame(path_output + "g_sparse_diffuse", iter, FORMAT_BINARY);
362
363 if (iter % 2 == 0)
364 {
365 monitor_total_concentration<U_N>(g_sparse, t, iter, path_output,"total_conc.csv");
366 }
367 else
368 {
369 monitor_total_concentration<U_NPLUS1>(g_sparse, t, iter, path_output,"total_conc.csv");
370 }
371 }
372
373 t += dt;
374 iter += 1;
375 }
376 t_iterative_diffusion_total.stop();
377 std::cout << "Rank " << v_cl.rank() << " total time for iterative diffusion incl. write outs: " << t_iterative_diffusion_total.getwct() << std::endl;
378 std::cout << "Rank " << v_cl.rank() << " finished diffusion." << std::endl;
379
384 t_total.stop();
385 std::cout << "Rank " << v_cl.rank() << " total time for the whole programm : " << t_total.getwct() << std::endl;
386
387
388 openfpm_finalize();
389 return 0;
390}
391
Header file containing help-functions that perform on OpenFPM-grids.
Header file containing functions for loading pixel values from 2D image or 3D image stack (volume) st...
Header file containing functions for creating files and folders.
static void create_directory_if_not_exist(std::string path, bool silent=0)
Creates a directory if not already existent.
static std::string get_cwd()
Gets the current working directory and returns path as string.
Class for reinitializing a level-set function into a signed distance function using Sussman redistanc...
This class represent an N-dimensional box.
Definition Box.hpp:61
This class decompose a space into sub-sub-domains and distribute them across processors.
Derivative second order on h (spacing)
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition Point.hpp:172
This is a distributed grid.
Implementation of 1-D std::vector like structure.
Class for cpu time benchmarking.
Definition timer.hpp:28
void stop()
Stop the timer.
Definition timer.hpp:119
void reset()
Reset the timer.
Definition timer.hpp:154
void start()
Start the timer.
Definition timer.hpp:90
double getwct()
Return the elapsed real time.
Definition timer.hpp:130
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data
get the type of the block
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...