VM2D  1.12
Vortex methods for 2D flows simulation
Gpu2D.cpp
Go to the documentation of this file.
1 /*--------------------------------*- VM2D -*-----------------*---------------*\
2 | ## ## ## ## #### ##### | | Version 1.12 |
3 | ## ## ### ### ## ## ## ## | VM2D: Vortex Method | 2024/01/14 |
4 | ## ## ## # ## ## ## ## | for 2D Flow Simulation *----------------*
5 | #### ## ## ## ## ## | Open Source Code |
6 | ## ## ## ###### ##### | https://www.github.com/vortexmethods/VM2D |
7 | |
8 | Copyright (C) 2017-2024 I. Marchevsky, K. Sokol, E. Ryatina, A. Kolganova |
9 *-----------------------------------------------------------------------------*
10 | File name: Gpu2D.cpp |
11 | Info: Source code of VM2D |
12 | |
13 | This file is part of VM2D. |
14 | VM2D is free software: you can redistribute it and/or modify it |
15 | under the terms of the GNU General Public License as published by |
16 | the Free Software Foundation, either version 3 of the License, or |
17 | (at your option) any later version. |
18 | |
19 | VM2D is distributed in the hope that it will be useful, but WITHOUT |
20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
22 | for more details. |
23 | |
24 | You should have received a copy of the GNU General Public License |
25 | along with VM2D. If not, see <http://www.gnu.org/licenses/>. |
26 \*---------------------------------------------------------------------------*/
27 
28 
40 #include "Gpu2D.h"
41 
42 #include "Airfoil2D.h"
43 #include "Boundary2D.h"
44 #include "MeasureVP2D.h"
45 #include "Mechanics2D.h"
46 #include "Passport2D.h"
47 #include "StreamParser.h"
48 #include "Velocity2D.h"
49 #include "Wake2D.h"
50 #include "World2D.h"
51 
52 using namespace VM2D;
53 
54 
55 //int Gpu::nReserve = 0;
56 
57 Gpu::Gpu(const World2D& W_)
58  : W(W_)
59 {
60 #if defined(__CUDACC__) || defined(USE_CUDA)
61 
62 
63 // Откомментировать следующую строку, если запускается счет на кластере, каждый узел которого
64 // имеет несколько видеокарт, при этом хочется одновременно решать несколько задач --- каждую на своей видеокарте ---
65 // каждая задача по своему номеру, деленному по модулю числа видеокарт на узле будет привязана к своей видеокарте;
66 // на каждый узел при этом отправлять СТОЛЬКО MPI-нитей, СКОЛЬКО ТАМ ВИДЕОКАРТ;
67 // число задач НАСТОЯТЕЛЬНО РЕКОМЕНДУЕТСЯ ВЫБИРАТЬ ТОЧНО РАВНЫМ СУММАРНОМУ ЧИСЛУ ВИДЕОКАРТ,
68 // т.е. чтобы все задачи стартовали сразу же.
69 //
70 // Uncomment the following string if the program runs on the computer cluster with several graphic cards on every node
71 // and you want to solve several tasks simultaneously --- EVERY TASK ON ITS OWN GRAPHIC CARD;
72 // every task will be associated with separate graphic card;
73 // send THE SAME AMOUNT OF MPI-THREADS for the node as THE NUMBER OF GRAPHIC CARDS on this node;
74 // IT IS STRONGLY RECOMMENDED TO CHOOSE THE NUMBER OF TASKS EXACTLY EQUAL TO TOTAL VIDEO CARDs NUMBERS,
75 // i.e. to start all the tasks simultaneously.
76 
77 //cuDevice(W.getPassport().problemNumber % 4); //The index of the used video card will be equal to the task number
78  // in the task list (to modulo 4 --- number of graphic cards on each node)
79 
80 
81  cuSetConstants(sizeof(Vortex2D)/sizeof(double), Vortex2D::offsPos / sizeof(double), Vortex2D::offsGam / sizeof(double) );
82 
83  n_CUDA_wake = 0;
84  n_CUDA_bodies = 0;
85  n_CUDA_source = 0;
86  n_CUDA_afls = 0;
87 
88  n_CUDA_velVP = 0;
89 #endif
90 }
91 
92 
94 {
95 #if defined(__CUDACC__) || defined(USE_CUDA)
96  ReleaseDevMem(W.getWake().devVtxPtr, 1);
97  ReleaseDevMem(W.getWake().devVelPtr, 2);
98  ReleaseDevMem(W.getWake().devRadPtr, 3);
99  ReleaseDevMem(W.getWake().devI0Ptr, 4);
100  ReleaseDevMem(W.getWake().devI1Ptr, 5);
101  ReleaseDevMem(W.getWake().devI2Ptr, 6);
102  ReleaseDevMem(W.getWake().devI3Ptr, 7);
103 
104  ReleaseDevMem(W.getWake().devMeshPtr, 8);
105  ReleaseDevMem(W.getWake().devNeiPtr, 9);
106 
107  if (W.getSource().vtx.size() > 0)
108  ReleaseDevMem(W.getSource().devVtxPtr, 10);
109 
110  for (size_t s = 0; s < 1/*n_CUDA_afls*/; ++s)
111  {
112  ReleaseDevMem(W.getBoundary(s).virtualWake.devVtxPtr, 11);
113  ReleaseDevMem(W.getBoundary(s).virtualWake.devVelPtr, 12);
114  ReleaseDevMem(W.getBoundary(s).virtualWake.devRadPtr, 13);
115  ReleaseDevMem(W.getBoundary(s).virtualWake.devI0Ptr, 14);
116  ReleaseDevMem(W.getBoundary(s).virtualWake.devI1Ptr, 15);
117  ReleaseDevMem(W.getBoundary(s).virtualWake.devI2Ptr, 16);
118  ReleaseDevMem(W.getBoundary(s).virtualWake.devI3Ptr, 17);
119 
120  ReleaseDevMem(W.getBoundary(s).afl.devRPtr, 18);
121  ReleaseDevMem(W.getBoundary(s).afl.devRhsPtr, 19);
122  ReleaseDevMem(W.getBoundary(s).afl.devRhsLinPtr, 191);
123 
124  ReleaseDevMem(W.getBoundary(s).afl.devFreeVortexSheetPtr, 20);
125  ReleaseDevMem(W.getBoundary(s).afl.devAttachedVortexSheetPtr, 21);
126  ReleaseDevMem(W.getBoundary(s).afl.devAttachedSourceSheetPtr, 22);
127 
128  ReleaseDevMem(W.getBoundary(s).afl.devMeanEpsOverPanelPtr, 23);
129  ReleaseDevMem(W.getBoundary(s).afl.devViscousStressesPtr, 24);
130  }
131 
132  if (n_CUDA_afls)
133  {
134  ReleaseDevMem(dev_ptr_nPanels, 25);
135  ReleaseDevMem(dev_ptr_nVortices, 26);
136 
137  ReleaseDevMem(dev_ptr_ptr_vtx, 27);
138  ReleaseDevMem(dev_ptr_ptr_vel, 28);
139  ReleaseDevMem(dev_ptr_ptr_rad, 29);
140  ReleaseDevMem(dev_ptr_ptr_i0, 30);
141  ReleaseDevMem(dev_ptr_ptr_i1, 31);
142  ReleaseDevMem(dev_ptr_ptr_i2, 32);
143  ReleaseDevMem(dev_ptr_ptr_i3, 33);
144 
145  ReleaseDevMem(dev_ptr_ptr_r, 34);
146  ReleaseDevMem(dev_ptr_ptr_rhs, 35);
147 
148  ReleaseDevMem(dev_ptr_ptr_freeVortexSheet, 36);
149  ReleaseDevMem(dev_ptr_ptr_attachedVortexSheet, 37);
150  ReleaseDevMem(dev_ptr_ptr_attachedSourceSheet, 38);
151 
152  ReleaseDevMem(dev_ptr_ptr_meanEpsOverPanel, 39);
153 
154  ReleaseDevMem(dev_ptr_ptr_viscousStresses, 40);
155  }
156 
157  if (W.getMeasureVP().getWakeVP().vtx.size())
158  {
159  ReleaseDevMem(W.getMeasureVP().getWakeVP().devVtxPtr, 41);
160  ReleaseDevMem(W.getMeasureVP().getWakeVP().devVelPtr, 42);
161  ReleaseDevMem(W.getMeasureVP().getWakeVP().devRadPtr, 43);
162  }
163 #endif
164 }
165 
166 #if defined(__CUDACC__) || defined(USE_CUDA)
167 
168 
169 //Обновление состояния следа wake
170 void Gpu::RefreshWake(int code)
171 {
172  if (W.getWake().vtx.size() > 0)
173  {
174  //Если зарезервировано меньше, чем вихрей в пелене
175  if (W.getWake().vtx.size() > n_CUDA_wake)
176  {
177  size_t curLength = n_CUDA_wake;
178 
179  //Освобождаем всю память на видеокарте
180  if (curLength > 0)
181  {
182  ReleaseDevMem(W.getWake().devVtxPtr, 44);
183  ReleaseDevMem(W.getWake().devVelPtr, 45);
184  ReleaseDevMem(W.getWake().devRadPtr, 46);
185  ReleaseDevMem(W.getWake().devI0Ptr, 47);
186  ReleaseDevMem(W.getWake().devI1Ptr, 48);
187  ReleaseDevMem(W.getWake().devI2Ptr, 49);
188  ReleaseDevMem(W.getWake().devI3Ptr, 50);
189 
190  ReleaseDevMem(W.getWake().devMeshPtr, 51);
191  ReleaseDevMem(W.getWake().devNeiPtr, 52);
192  }
193 
194  size_t sz = curLength;
195  while (W.getWake().vtx.size() > sz)
196  sz += INC_VORT_DEV;
197 
198  //Резервируем новое количество памяти
199  W.getWake().devVtxPtr = ReserveDevMem<double, sizeof(Vortex2D) / sizeof(double)>(sz, n_CUDA_wake);
200 
201  W.getWake().devVelPtr = ReserveDevMem<double, 2>(sz, n_CUDA_wake);
202  W.getWake().devRadPtr = ReserveDevMem<double, 1>(sz, n_CUDA_wake);
203 
204  W.getWake().devI0Ptr = ReserveDevMem<double, 1>(sz, n_CUDA_wake);
205  W.getWake().devI1Ptr = ReserveDevMem<double, 1>(sz, n_CUDA_wake);
206  W.getWake().devI2Ptr = ReserveDevMem<double, 2>(sz, n_CUDA_wake);
207  W.getWake().devI3Ptr = ReserveDevMem<double, 2>(sz, n_CUDA_wake);
208 
209  W.getWake().devMeshPtr = ReserveDevMem<int, 2>(sz, n_CUDA_wake);
210  W.getWake().devNeiPtr = ReserveDevMem<int, 1>(sz, n_CUDA_wake);
211 
212  //mesh.resize(n_CUDA_vel, { 0, 0 });
213 
214  W.getInfo('i') << "CUDA memory resize: " << curLength << " -> " << n_CUDA_wake << " vortices" << std::endl;
215  }// if (W.getWake().vtx.size() > n_CUDA_wake)
216 
217  //Обнуляем память, выделенную выше для хранения следа
218  cuClearWakeMem(W.getWake().vtx.size(), W.getWake().devVtxPtr);
219 
220  //Копирование следа на видеокарту
221  //double t1 = omp_get_wtime();
222  //cuCopyWakeToDevAsync(W.getWake().vtx.size(), W.getWake().vtx.data(), W.getWake().devVtxPtr, 1);
223  cuCopyWakeToDev(W.getWake().vtx.size(), W.getWake().vtx.data(), W.getWake().devVtxPtr, 1);
224  //double t2 = omp_get_wtime();
225  //std::cout << "CopyTime = " << t2 - t1 << std::endl;
226  }
227 
228  if (W.getSource().vtx.size() > 0)
229  {
230  //Если зарезервировано меньше, чем источников в пелене
231  if (W.getSource().vtx.size() > n_CUDA_source)
232  {
233  size_t curLength = n_CUDA_source;
234 
235  //Освобождаем всю память на ведеокарте
236  if (curLength > 0)
237  ReleaseDevMem(W.getSource().devVtxPtr, 53);
238 
239  size_t sz = curLength;
240  while (W.getSource().vtx.size() > sz)
241  sz += INC_VORT_DEV;
242 
243  //Резервируем новое количество памяти
244  W.getSource().devVtxPtr = ReserveDevMem<double, sizeof(Vortex2D) / sizeof(double)>(sz, n_CUDA_source);
245 
246 
247  W.getInfo('i') << "CUDA memory resize: " << curLength << " -> " << sz << " sources" << std::endl;
248  }// if (W.getSource().vtx.size() > N_CUDA_source)
249 
250 
251  //Обнуляем память, выделенную выше для хранения следа
252  cuClearWakeMem(W.getSource().vtx.size(), W.getSource().devVtxPtr);
253 
254  //Копирование следа на видеокарту
255  cuCopyWakeToDev(W.getSource().vtx.size(), W.getSource().vtx.data(), W.getSource().devVtxPtr, 2);
256 
257 
258  }
259 }
260 
261 
262 
263 //Обновление состояния сетки для вычисления VP
264 void Gpu::RefreshVP(int code)
265 {
266  if (W.getMeasureVP().getWakeVP().vtx.size() > 0)
267  {
268  //Если зарезервировано меньше, чем вихрей в пелене
269  if (W.getMeasureVP().getWakeVP().vtx.size() > n_CUDA_velVP)
270  {
271  size_t curLength = n_CUDA_velVP;
272 
273  //Освобождаем всю память на видеокарте
274  if (curLength > 0)
275  {
276  ReleaseDevMem(W.getMeasureVP().getWakeVP().devVtxPtr, 54);
277  ReleaseDevMem(W.getMeasureVP().getWakeVP().devVelPtr, 55);
278  ReleaseDevMem(W.getMeasureVP().getWakeVP().devRadPtr, 56);
279  }
280 
281  size_t sz = curLength;
282  while (W.getMeasureVP().getWakeVP().vtx.size() > sz)
283  sz += INC_VORT_DEV;
284 
285  //Резервируем новое количество памяти
286  W.getMeasureVP().getWakeVP().devVtxPtr = ReserveDevMem<double, sizeof(Vortex2D) / sizeof(double)>(sz, n_CUDA_velVP);
287  W.getMeasureVP().getWakeVP().devVelPtr = ReserveDevMem<double, 2>(sz, n_CUDA_velVP);
288  W.getMeasureVP().getWakeVP().devRadPtr = ReserveDevMem<double, 1>(sz, n_CUDA_velVP);
289 
290  W.getInfo('i') << "CUDA memory resize: " << curLength << " -> " << n_CUDA_velVP << " points_VP" << std::endl;
291  }// if (W.getWake().vtx.size() > N_CUDA_velvp)
292 
293  //Обнуляем память, выделенную выше для хранения следа
294  cuClearWakeMem(W.getMeasureVP().getWakeVP().vtx.size(), W.getMeasureVP().getWakeVP().devVtxPtr);
295 
296  //Копирование следа на видеокарту
297  cuCopyWakeToDev(W.getMeasureVP().getWakeVP().vtx.size(), W.getMeasureVP().getWakeVP().vtx.data(), W.getMeasureVP().getWakeVP().devVtxPtr, 3);
298  }
299 }
300 
301 
302 
303 //Обновление состояния всех профилей и слоев на них
304 void Gpu::RefreshAfls(int code)
305 {
306  //std::cout << "RefreshAfls (code = " << code << ") start" << std::endl;
307 
308  if (W.getNumberOfBoundary() > 0)
309  {
310  if (W.getNumberOfBoundary() > n_CUDA_afls)
311  {
312  //Обнуление массива на хосте, содержащего количество панелей на профилях
313  n_CUDA_panel.resize(W.getNumberOfBoundary(), 0);
314 
315  if (n_CUDA_afls)
316  for (size_t s = 0; s < 1/*n_CUDA_afls*/; ++s)
317  {
318  ReleaseDevMem(W.getBoundary(s).afl.devRPtr, 57);
319  ReleaseDevMem(W.getBoundary(s).afl.devRhsPtr, 58);
320  ReleaseDevMem(W.getBoundary(s).afl.devRhsLinPtr, 581);
321  ReleaseDevMem(W.getBoundary(s).afl.devMeanEpsOverPanelPtr, 59);
322 
323  ReleaseDevMem(W.getBoundary(s).afl.devFreeVortexSheetPtr, 60);
324  ReleaseDevMem(W.getBoundary(s).afl.devAttachedVortexSheetPtr, 61);
325  ReleaseDevMem(W.getBoundary(s).afl.devAttachedSourceSheetPtr, 62);
326 
327  ReleaseDevMem(W.getBoundary(s).afl.devViscousStressesPtr, 63);
328  }
329 
330  if (n_CUDA_afls)
331  {
332  ReleaseDevMem(dev_ptr_nPanels, 64);
333  ReleaseDevMem(dev_ptr_ptr_r, 65);
334  ReleaseDevMem(dev_ptr_ptr_rhs, 66);
335 
336  ReleaseDevMem(dev_ptr_ptr_freeVortexSheet, 67);
337  ReleaseDevMem(dev_ptr_ptr_attachedVortexSheet, 68);
338  ReleaseDevMem(dev_ptr_ptr_attachedSourceSheet, 69);
339 
340  ReleaseDevMem(dev_ptr_nVortices, 70);
341  ReleaseDevMem(dev_ptr_ptr_vtx, 71);
342  ReleaseDevMem(dev_ptr_ptr_rad, 72);
343  ReleaseDevMem(dev_ptr_ptr_vel, 73);
344  ReleaseDevMem(dev_ptr_ptr_i0, 74);
345  ReleaseDevMem(dev_ptr_ptr_i1, 75);
346  ReleaseDevMem(dev_ptr_ptr_i2, 76);
347  ReleaseDevMem(dev_ptr_ptr_i3, 77);
348  }
349 
350  //Временный массив для агрегации числа панелей (без округления вверх до блока) на профилях для их последующей отправки в dev_ptr_nPanels
351  std::vector<size_t> host_nPanels(0);
352 
353  size_t totnPanels = 0, totnPanelsUP;
354  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
355  {
356  const size_t& nps = W.getBoundary(s).afl.getNumberOfPanels();
357  host_nPanels.push_back(nps);
358  totnPanels += nps;
359  }
360  dev_ptr_nPanels = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_nPanels.data());
361 
362  const int totNVars = (int)totnPanels * (W.getPassport().numericalSchemes.boundaryCondition.second + 1);
363 
364  W.getBoundary(0).afl.devRPtr = ReserveDevMem<double, 4>(totnPanels, totnPanelsUP);
365  W.getBoundary(0).afl.devRhsPtr = ReserveDevMem<double, 1>(totnPanels, totnPanelsUP);
366  W.getBoundary(0).afl.devRhsLinPtr = ReserveDevMem<double, 1>(totnPanels, totnPanelsUP);
367  W.getBoundary(0).afl.devMeanEpsOverPanelPtr = ReserveDevMem<double, 1>(totnPanels, totnPanelsUP);//MeanEpsOverPanel
368 
369  W.getBoundary(0).afl.devFreeVortexSheetPtr = ReserveDevMem<double, 1>(totNVars, totnPanelsUP);//devFreeVortexSheetPtr
370  W.getBoundary(0).afl.devAttachedVortexSheetPtr = ReserveDevMem<double, 1>(totNVars, totnPanelsUP);//devAttachedVortexSheetPtr
371  W.getBoundary(0).afl.devAttachedSourceSheetPtr = ReserveDevMem<double, 1>(totNVars, totnPanelsUP);//devAttachedSourceSheetPtr
372 
373  W.getBoundary(0).afl.devViscousStressesPtr = ReserveDevMem<double, 1>(totnPanels, totnPanelsUP);//ViscousStress
374 
375  for (size_t s = 1; s < W.getNumberOfBoundary(); ++s)
376  {
377  W.getBoundary(s).afl.devRPtr = W.getBoundary(s - 1).afl.devRPtr + 4 * host_nPanels[s - 1];
378  W.getBoundary(s).afl.devRhsPtr = W.getBoundary(s - 1).afl.devRhsPtr + 1 * host_nPanels[s - 1];
379  W.getBoundary(s).afl.devRhsLinPtr = W.getBoundary(s - 1).afl.devRhsLinPtr + 1 * host_nPanels[s - 1];
380  W.getBoundary(s).afl.devMeanEpsOverPanelPtr = W.getBoundary(s - 1).afl.devMeanEpsOverPanelPtr + 1 * host_nPanels[s - 1];
381 
382  W.getBoundary(s).afl.devFreeVortexSheetPtr = W.getBoundary(s - 1).afl.devFreeVortexSheetPtr + 1 * host_nPanels[s - 1];
383  W.getBoundary(s).afl.devAttachedVortexSheetPtr = W.getBoundary(s - 1).afl.devAttachedVortexSheetPtr + 1 * host_nPanels[s - 1];
384  W.getBoundary(s).afl.devAttachedSourceSheetPtr = W.getBoundary(s - 1).afl.devAttachedSourceSheetPtr + 1 * host_nPanels[s - 1];
385 
386  W.getBoundary(s).afl.devViscousStressesPtr = W.getBoundary(s - 1).afl.devViscousStressesPtr + 1 * host_nPanels[s - 1];
387  }
388 
389  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
390  {
391  W.getBoundary(s).afl.tmpRhs.resize(totNVars, 0.0);
392  W.getBoundary(s).afl.tmpViscousStresses.resize(W.getBoundary(s).afl.getNumberOfPanels(), 0.0);
393  }// for s
394 
395  //Временные массивы для агрегации указателей на видеокарте
396  std::vector<double*> host_ptr_r;
397  std::vector<double*> host_ptr_rhs;
398  std::vector<double*> host_ptr_rhsLin;
399 
400  std::vector<double*> host_ptr_freeVortexSheet;
401  std::vector<double*> host_ptr_attachedVortexSheet;
402  std::vector<double*> host_ptr_attachedSourceSheet;
403 
404  std::vector<double*> host_ptr_meanEpsOverPanel;
405 
406  std::vector<double*> host_ptr_viscousStresses;
407 
408  for (size_t q = 0; q < W.getNumberOfBoundary(); ++q)
409  {
410  host_ptr_r.push_back(W.getBoundary(q).afl.devRPtr);
411  host_ptr_rhs.push_back(W.getBoundary(q).afl.devRhsPtr);
412  host_ptr_rhsLin.push_back(W.getBoundary(q).afl.devRhsLinPtr);
413 
414  host_ptr_freeVortexSheet.push_back(W.getBoundary(q).afl.devFreeVortexSheetPtr);
415  host_ptr_attachedVortexSheet.push_back(W.getBoundary(q).afl.devAttachedVortexSheetPtr);
416  host_ptr_attachedSourceSheet.push_back(W.getBoundary(q).afl.devAttachedSourceSheetPtr);
417 
418  host_ptr_meanEpsOverPanel.push_back(W.getBoundary(q).afl.devMeanEpsOverPanelPtr);
419 
420  host_ptr_viscousStresses.push_back(W.getBoundary(q).afl.devViscousStressesPtr);
421  }
422 
423  dev_ptr_ptr_r = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_r.data());
424  dev_ptr_ptr_rhs = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_rhs.data());
425 
426  dev_ptr_ptr_freeVortexSheet = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_freeVortexSheet.data());
427  dev_ptr_ptr_attachedVortexSheet = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_attachedVortexSheet.data());
428  dev_ptr_ptr_attachedSourceSheet = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_attachedSourceSheet.data());
429 
430  dev_ptr_ptr_viscousStresses = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_viscousStresses.data());
431 
432  dev_ptr_ptr_meanEpsOverPanel = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), host_ptr_meanEpsOverPanel.data());
433 
434 
435  std::vector<double*> zeroPtrVec(W.getNumberOfBoundary(), nullptr);
436  dev_ptr_ptr_vtx = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
437  dev_ptr_ptr_rad = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
438  dev_ptr_ptr_vel = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
439  dev_ptr_ptr_i0 = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
440  dev_ptr_ptr_i1 = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
441  dev_ptr_ptr_i2 = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
442  dev_ptr_ptr_i3 = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroPtrVec.data());
443 
444  std::vector<size_t> zeroVec(W.getNumberOfBoundary(), 0);
445  dev_ptr_nVortices = ReserveDevMemAndCopyFixedArray(W.getNumberOfBoundary(), zeroVec.data());
446 
447  }//if (W.getNumberOfBoundary() > n_CUDA_afls)
448 
449 
450  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
451  {
452  size_t np = W.getBoundary(s).afl.getNumberOfPanels();
453  size_t nv = W.getBoundary(s).GetUnknownsSize();
454 
455  //Копирование вершин профиля на видеокарту
456  std::vector<double> rbegend(4 * np);
457  for (size_t q = 0; q < np; ++q)
458  {
459  rbegend[4 * q + 0] = W.getBoundary(s).afl.getR(q)[0];
460  rbegend[4 * q + 1] = W.getBoundary(s).afl.getR(q)[1];
461  rbegend[4 * q + 2] = W.getBoundary(s).afl.getR(q+1)[0];
462  rbegend[4 * q + 3] = W.getBoundary(s).afl.getR(q+1)[1];
463  }
464 
465  cuCopyFixedArrayPoint4D(W.getBoundary(s).afl.devRPtr, (Point2D*)rbegend.data(), np, code);
466 
467  //Копирование слоев на видеокарту
468  std::vector<double> host_freeVortexSheet(nv);
469  std::vector<double> host_attachedVortexSheet(nv);
470  std::vector<double> host_attachedSourceSheet(nv);
471 
472  const Sheet& sh = W.getBoundary(s).sheets;
473 
474  int sch = W.getPassport().numericalSchemes.boundaryCondition.second;
475 
476  for (size_t p = 0; p < np; ++p)
477  {
478  host_attachedVortexSheet[p] = sh.attachedVortexSheet(p, 0);
479  host_attachedSourceSheet[p] = sh.attachedSourceSheet(p, 0);
480 
481  host_freeVortexSheet[p] = sh.freeVortexSheet(p, 0);
482  }//for p
483 
484  if(sch == 1)
485  for (size_t p = 0; p < np; ++p)
486  {
487  host_attachedVortexSheet[np + p] = sh.attachedVortexSheet(p, 1);
488  host_attachedSourceSheet[np + p] = sh.attachedSourceSheet(p, 1);
489 
490  host_freeVortexSheet[np + p] = sh.freeVortexSheet(p, 1);
491  }//for p
492 
493  cuCopyFixedArray(W.getBoundary(s).afl.devFreeVortexSheetPtr, host_freeVortexSheet.data(), sizeof(double) * host_freeVortexSheet.size());
494  cuCopyFixedArray(W.getBoundary(s).afl.devAttachedVortexSheetPtr, host_attachedVortexSheet.data(), sizeof(double)* host_attachedVortexSheet.size());
495  cuCopyFixedArray(W.getBoundary(s).afl.devAttachedSourceSheetPtr, host_attachedSourceSheet.data(), sizeof(double)* host_attachedSourceSheet.size());
496  }
497  }
498  n_CUDA_afls = W.getNumberOfBoundary();
499 }//RefreshAfls()
500 
501 
502 //Обновление состояния "виртуальных следов" - только что рожденных вихрей на профилях
503 void Gpu::RefreshVirtualWakes(int code)
504 {
505  if (n_CUDA_virtWake.size() == 0)
506  {
507  n_CUDA_virtWake.resize(W.getNumberOfBoundary(), 0);
508  n_CUDA_totalVirtWake = 0;
509  }
510 
511  size_t totnVirt = 0, totnPan = 0;
512  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
513  {
514  totnVirt += W.getBoundary(s).virtualWake.vtx.size();
515  totnPan += W.getBoundary(s).afl.getNumberOfPanels();
516  }
517 
518  const size_t& szVtx = std::max(totnVirt, W.getPassport().wakeDiscretizationProperties.minVortexPerPanel * totnPan);
519 
520  //Чистим все массивы
521  if (szVtx > n_CUDA_totalVirtWake)
522  {
523  if (n_CUDA_totalVirtWake > 0)
524  for (size_t s = 0; s < 1/*W.getNumberOfBoundary()*/; ++s)
525  {
526  ReleaseDevMem(W.getBoundary(s).virtualWake.devVtxPtr, 70);
527  ReleaseDevMem(W.getBoundary(s).virtualWake.devVelPtr, 71);
528  ReleaseDevMem(W.getBoundary(s).virtualWake.devRadPtr, 72);
529  ReleaseDevMem(W.getBoundary(s).virtualWake.devI0Ptr, 73);
530  ReleaseDevMem(W.getBoundary(s).virtualWake.devI1Ptr, 74);
531  ReleaseDevMem(W.getBoundary(s).virtualWake.devI2Ptr, 75);
532  ReleaseDevMem(W.getBoundary(s).virtualWake.devI3Ptr, 76);
533  }
534 
535  if (n_CUDA_afls)
536  {
537  W.getBoundary(0).virtualWake.devVtxPtr = ReserveDevMem<double, sizeof(Vortex2D) / sizeof(double)>(szVtx, n_CUDA_totalVirtWake);
538  W.getBoundary(0).virtualWake.devVelPtr = ReserveDevMem<double, 2>(szVtx, n_CUDA_totalVirtWake);
539  W.getBoundary(0).virtualWake.devRadPtr = ReserveDevMem<double, 1>(szVtx, n_CUDA_totalVirtWake);
540 
541  std::cout << "szVtx = " << szVtx << ", n_CUDA_totalVirtWake = " << n_CUDA_totalVirtWake << std::endl;
542 
543  W.getBoundary(0).virtualWake.devI0Ptr = ReserveDevMem<double, 1>(szVtx, n_CUDA_totalVirtWake);
544  W.getBoundary(0).virtualWake.devI1Ptr = ReserveDevMem<double, 1>(szVtx, n_CUDA_totalVirtWake);
545  W.getBoundary(0).virtualWake.devI2Ptr = ReserveDevMem<double, 2>(szVtx, n_CUDA_totalVirtWake);
546  W.getBoundary(0).virtualWake.devI3Ptr = ReserveDevMem<double, 2>(szVtx, n_CUDA_totalVirtWake);
547  }
548  }
549 
550  for (size_t s = 1; s < W.getNumberOfBoundary(); ++s)
551  {
552  size_t nprev = W.getBoundary(s - 1).virtualWake.vtx.size();
553  W.getBoundary(s).virtualWake.devVtxPtr = W.getBoundary(s - 1).virtualWake.devVtxPtr + (sizeof(Vortex2D) / sizeof(double)) * nprev;
554  W.getBoundary(s).virtualWake.devVelPtr = W.getBoundary(s - 1).virtualWake.devVelPtr + 2 * nprev;
555  W.getBoundary(s).virtualWake.devRadPtr = W.getBoundary(s - 1).virtualWake.devRadPtr + 1 * nprev;
556  W.getBoundary(s).virtualWake.devI0Ptr = W.getBoundary(s - 1).virtualWake.devI0Ptr + 1 * nprev;
557  W.getBoundary(s).virtualWake.devI1Ptr = W.getBoundary(s - 1).virtualWake.devI1Ptr + 1 * nprev;
558  W.getBoundary(s).virtualWake.devI2Ptr = W.getBoundary(s - 1).virtualWake.devI2Ptr + 2 * nprev;
559  W.getBoundary(s).virtualWake.devI3Ptr = W.getBoundary(s - 1).virtualWake.devI3Ptr + 2 * nprev;
560  }
561 
562  std::vector<size_t> host_nVortices(0);
563  host_nVortices.reserve(W.getNumberOfBoundary());
564 
565  for (size_t q = 0; q < W.getNumberOfBoundary(); ++q)
566  host_nVortices.push_back(W.getBoundary(q).virtualWake.vtx.size());
567 
568  cuCopyFixedArray(dev_ptr_nVortices, host_nVortices.data(), W.getNumberOfBoundary()*sizeof(size_t));
569 
570  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
571  {
572  //Временные массивы для агрегации указателей на видеокарте
573  std::vector<double*> host_ptr_vtx;
574  std::vector<double*> host_ptr_vel;
575  std::vector<double*> host_ptr_rad;
576  std::vector<double*> host_ptr_i0;
577  std::vector<double*> host_ptr_i1;
578  std::vector<double*> host_ptr_i2;
579  std::vector<double*> host_ptr_i3;
580 
581  for (size_t q = 0; q < W.getNumberOfBoundary(); ++q)
582  {
583  host_ptr_vtx.push_back(W.getBoundary(q).virtualWake.devVtxPtr);
584  host_ptr_vel.push_back(W.getBoundary(q).virtualWake.devVelPtr);
585  host_ptr_rad.push_back(W.getBoundary(q).virtualWake.devRadPtr);
586  host_ptr_i0.push_back(W.getBoundary(q).virtualWake.devI0Ptr);
587  host_ptr_i1.push_back(W.getBoundary(q).virtualWake.devI1Ptr);
588  host_ptr_i2.push_back(W.getBoundary(q).virtualWake.devI2Ptr);
589  host_ptr_i3.push_back(W.getBoundary(q).virtualWake.devI3Ptr);
590  }
591 
592  size_t nBytes = W.getNumberOfBoundary() * sizeof(double*);
593  cuCopyFixedArray(dev_ptr_ptr_vtx, host_ptr_vtx.data(), nBytes);
594  cuCopyFixedArray(dev_ptr_ptr_rad, host_ptr_rad.data(), nBytes);
595  cuCopyFixedArray(dev_ptr_ptr_vel, host_ptr_vel.data(), nBytes);
596  cuCopyFixedArray(dev_ptr_ptr_i0, host_ptr_i0.data(), nBytes);
597  cuCopyFixedArray(dev_ptr_ptr_i1, host_ptr_i1.data(), nBytes);
598  cuCopyFixedArray(dev_ptr_ptr_i2, host_ptr_i2.data(), nBytes);
599  cuCopyFixedArray(dev_ptr_ptr_i3, host_ptr_i3.data(), nBytes);
600  }//if (n_CUDA_virtWake[s] < W.getBoundary(s).virtualWake.vtx.size())
601 
602  //Обнуляем память, выделенную выше для хранения виртуального следа
603  if (W.getNumberOfBoundary() > 0)
604  {
605  cuClearWakeMem(szVtx, W.getBoundary(0).virtualWake.devVtxPtr);
606  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
607  cuCopyWakeToDev(W.getBoundary(s).virtualWake.vtx.size(), W.getBoundary(s).virtualWake.vtx.data(), W.getBoundary(s).virtualWake.devVtxPtr, 4);
608  }
609 }
610 
611 #endif
const double & freeVortexSheet(size_t n, size_t moment) const
Definition: Sheet2D.h:99
Заголовочный файл с описанием класса Passport (двумерный) и cоответствующими структурами ...
const double & attachedVortexSheet(size_t n, size_t moment) const
Definition: Sheet2D.h:104
Заголовочный файл с описанием класса Wake.
std::pair< std::string, int > boundaryCondition
Метод аппроксимации граничных условий
Definition: Passport2D.h:199
Заголовочный файл с описанием класса World2D.
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition: World2D.h:164
Заголовочный файл с описанием класса Airfoil.
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition: World2D.h:197
Заголовочный файл с описанием класса Mechanics.
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition: Airfoil2D.h:101
const WakeDataBase & getSource() const
Возврат константной ссылки на источники в области течения
Definition: World2D.h:207
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition: Airfoil2D.h:139
Класс, опеделяющий слои на поверхности обтекаемого профиля
Definition: Sheet2D.h:61
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition: World2D.h:153
#define INC_VORT_DEV
Definition: Gpudefs.h:74
Definition: Airfoil2D.h:45
const MeasureVP & getMeasureVP() const
Возврат константной ссылки на measureVP.
Definition: World2D.h:175
Заголовочный файл с описанием класса StreamParser.
std::vector< Vortex2D > vtx
Список вихревых элементов
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition: Passport2D.h:302
Класс, опеделяющий двумерный вектор
Definition: Point2D.h:75
const World2D & W
Константная ссылка на решаемую задачу
Definition: Gpu2D.h:71
VMlib::LogStream & getInfo() const
Возврат ссылки на объект LogStream Используется в техничеcких целях для организации вывода ...
Definition: WorldGen.h:74
Sheet sheets
Слои на профиле
Definition: Boundary2D.h:95
Заголовочный файл с описанием класса MeasureVP.
const double & attachedSourceSheet(size_t n, size_t moment) const
Definition: Sheet2D.h:109
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition: World2D.h:222
Класс, опеделяющий двумерный вихревой элемент
Definition: Vortex2D.h:51
~Gpu()
Definition: Gpu2D.cpp:93
int minVortexPerPanel
Минимальное число вихрей, рождаемых на каждой панели профииля
Definition: Passport2D.h:154
VirtualWake virtualWake
Виртуальный вихревой след конкретного профиля
Definition: Boundary2D.h:85
Класс, опеделяющий текущую решаемую задачу
Definition: World2D.h:68
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition: Passport2D.h:299
Заголовочный файл с описанием класса Velocity.
const WakeDataBase & getWakeVP() const
Возврат wakeVP.
Definition: MeasureVP2D.h:120
Заголовочный файл с описанием класса Gpu.
Gpu(const World2D &W_)
Конструктор
Definition: Gpu2D.cpp:57
Заголовочный файл с описанием класса Boundary.
size_t GetUnknownsSize() const
Возврат размерности вектора решения
Definition: Boundary2D.cpp:71
const Airfoil & afl
Definition: Boundary2D.h:76