Skip to main content

Rocky Solver SDK 2024 R2

api_device_cfd_coupling

Last update: 17.07.2025
1#pragma once
2
3// Includes =================================================================================================
4#include <rocky20/api/rocky_api_cfd_functions.h>
5#include <rocky20/device/device_cfd_drag.hpp>
6#include <rocky20/device/device_cfd_coupling.hpp>
7
8namespace device
9{
10
11template<typename... Op>
12__host__ __device__
13void execute_operators(
14 const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data,
15 Op... ops)
16{
17 int dummy[sizeof...(Op)] = { (ops(particle, cfd, output, data), 0)... };
18}
19
20/*
21A utility structure to hold all device data used to execute the coupling kernel
22All data is a device data, so only the final kernel would be able to access such data
23*/
24struct CouplingDispatchData
25{
26 bool is_cuda{ false }, collect_cfd_data{ false };
27
28 SDeviceModel* device_data;
29 unsigned int* particle_indexes;
30 int n_particles;
31 void* udf_data;
32};
33
34/*
35Coupling kernel
36*/
37template <class backend, typename... Op>
38__host__ __device__
39void api_coupling_kernel(CouplingDispatchData& data, Op... operators)
40{
41 auto device_data = data.device_data;
42
43 IRockyParticle particle_api(-1, device_data);
44
46 cfd.model = device_data;
47 double3 gravity { device_data->gen->gx, device_data->gen->gy, device_data->gen->gz };
48
49#ifdef __CUDA_ARCH__
50 __shared__ CFDTimestepBin block_bins[CD_NTHREADS];
51 const int thread_index = threadIdx.x;
52 CFDTimestepBin& block_bin = block_bins[thread_index];
53#else
54 CFDTimestepBin& block_bin = device_data->cfd_monitor->thread_bins[backend::ThreadIndex()];
55#endif
56
57 block_bin.reset();
58
59 int thread_start, thread_step, thread_stop;
60 backend::ThreadIteration(thread_start, thread_step, thread_stop, data.n_particles);
61 for (auto i = thread_start; i < thread_stop; i += thread_step)
62 {
63 // particle
64 const int ip = data.particle_indexes[i];
65 particle_api._impl.reset(ip);
66 if (!particle_api._impl.particle->enabled()) {
67 continue;
68 }
69
70 const auto ic = device_data->particle_scalars->get_cfd_index(ip);
71 if (ic < 0) {
72 continue;
73 }
74
75 cfd.reset(ip, ic);
76 CFDCouplingOutput output{};
77
78 // Relative Buoyancy force, due to the relative fluid density
79 output.set_relative_buoyancy_force(
80 -cfd.get_particle_volume() * cfd.model->gen_cfd->relative_density * gravity
81 );
82
83 // Force due to pressure gradient (accounts for buoyancy and flow-induced
84 // pressure variations).
85 output.set_pressure_gradient_force(
86 -cfd.get_particle_volume() * cfd.get_fluid_pressure_gradient()
87 );
88
89 execute_operators(particle_api, cfd, output, data.udf_data, operators...);
90
91 // add forces and moments to the particle
92 auto& particle_forces = device_data->frc[ip];
93 particle_forces.fx += output.total_cfd_force.x;
94 particle_forces.fy += output.total_cfd_force.y;
95 particle_forces.fz += output.total_cfd_force.z;
96
97 if (output.has_moment()) {
98 particle_forces.mx += output.total_cfd_moment.x;
99 particle_forces.my += output.total_cfd_moment.y;
100 particle_forces.mz += output.total_cfd_moment.z;
101 }
102
103 // add critical time-step ratio to CFD Monitor
104 block_bin.check_critical_timestep(
105 device_data->get_general().dt,
106 output.drag_coefficient_fluent / particle_api.get_mass(),
107 device_data->cfd_monitor->levels
108 );
109 }
110
111#ifdef __CUDA_ARCH__
112 // Block reduce
113 device::cuda_block_reduce(
114 block_bins, device_data->cfd_monitor->thread_bins,
115 [](CFDTimestepBin &left, const CFDTimestepBin& right)
116 {
117 left.join(right);
118 }
119 );
120#endif
121}
122
123struct EmptyCustomCouplingPlugin {};
124
125struct InvalidOperator
126{
127 InvalidOperator()
128 {
129 #ifndef __CUDA_ARCH__
130 ROCKY_RUNTIME_ERROR("Invalid operation selection");
131 #endif
132 }
133
134 __host__ __device__ inline
135 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
136 {}
137};
138
139
140template <class Plugin>
141auto custom_drag_operator() { return InvalidOperator(); }
142
143template <class Plugin>
144auto custom_lift_operator() { return InvalidOperator(); }
145
146template <class Plugin>
147auto custom_virtual_mass_operator(SDeviceModel *device_data) { return InvalidOperator(); }
148
149template <class Plugin>
150auto custom_torque_operator() { return InvalidOperator(); }
151
152template <class Plugin>
153auto custom_convection_operator(SDeviceModel* device_data) { return InvalidOperator(); }
154
155/*
156Coupling Operators: executed, when enabled in the following order:
157 - Drag
158 - Lift
159 - Virtual Mass
160 - Torque
161 - Heat Convection
162 - CFD Data recorder
163 - Two Way Coupling
164 - Turbulence
165*/
166struct DragOperator
167{
168 __host__ __device__ inline
169 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
170 {
171 device::compute_cfd_drag(particle, cfd, output, data);
172 }
173};
174
175
176
177template <typename _DragLawOperator>
178struct DragParametricOperator
179{
180 __host__ __device__ inline
181 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
182 {
183 DragLaw<_DragLawOperator>(particle, cfd, output, data);
184 }
185};
186
187// Operator defined with drag laws implementation with light weight code, with less impact of performance.
188struct DragLightWeightOperator
189{
190 static bool valid(const ECFDDragLaw drag_law)
191 {
192 switch (drag_law)
193 {
194 case cfd_drag_law_SchillerNaumann1933:
195 case cfd_drag_law_Dallavalle1948:
196 case cfd_drag_law_HaiderLevenspiel1989:
197 case cfd_drag_law_MorsiAlexander1972:
198 case cfd_drag_law_WenYu1966:
199 case cfd_drag_law_Ergun1958:
200 case cfd_drag_law_GidaspowBezburuahDing1992:
201 case cfd_drag_law_HuilinGidaspow2003:
202 case cfd_drag_law_DiFelice1994:
203 case cfd_drag_law_HillKochLadd2001:
204 case cfd_drag_law_HillKoch2001:
205 case cfd_drag_law_SyamlalOBrien1987:
206 return true;
207 default:
208 return false;
209 }
210 }
211
212 __host__ __device__ inline
213 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
214 {
215 switch (cfd.cfd_particle_group->drag_law)
216 {
217 case cfd_drag_law_SchillerNaumann1933: DragLaw<SchillerNaumann1933Operator>(particle, cfd, output, data); break;
218 case cfd_drag_law_Dallavalle1948: DragLaw<Dallavalle1948Operator>(particle, cfd, output, data); break;
219 case cfd_drag_law_HaiderLevenspiel1989: DragLaw<HaiderLevenspiel1989Operator>(particle, cfd, output, data); break;
220 case cfd_drag_law_MorsiAlexander1972: DragLaw<MorsiAlexander1972Operator>(particle, cfd, output, data); break;
221 case cfd_drag_law_WenYu1966: DragLaw<WenYu1966Operator>(particle, cfd, output, data); break;
222 case cfd_drag_law_Ergun1958: DragLaw<Ergun1958Operator>(particle, cfd, output, data); break;
223 case cfd_drag_law_GidaspowBezburuahDing1992: DragLaw<GidaspowBezburuahDing1992Operator>(particle, cfd, output, data); break;
224 case cfd_drag_law_HuilinGidaspow2003: DragLaw<HuilinGidaspow2003Operator>(particle, cfd, output, data); break;
225 case cfd_drag_law_DiFelice1994: DragLaw<DiFelice1994Operator>(particle, cfd, output, data); break;
226 case cfd_drag_law_HillKochLadd2001: DragLaw<HillKochLadd2001Operator>(particle, cfd, output, data); break;
227 case cfd_drag_law_HillKoch2001: DragLaw<HillKoch2001Operator>(particle, cfd, output, data); break;
228 case cfd_drag_law_SyamlalOBrien1987: DragLaw<SyamlalOBrien1987Operator>(particle, cfd, output, data); break;
229 }
230 }
231};
232
233// Operator defined with drag laws implementation with light weight code, with less impact of performance.
234struct DragHeavyWeightOperator
235{
236 static bool valid(const ECFDDragLaw drag_law)
237 {
238 switch (drag_law)
239 {
240 case cfd_drag_law_Ganser1993:
241 case cfd_drag_law_MarheinekeWegener2011:
242 return true;
243 default:
244 return false;
245 }
246 }
247
248 __host__ __device__ inline
249 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
250 {
251 switch (cfd.cfd_particle_group->drag_law)
252 {
253 case cfd_drag_law_Ganser1993: Ganser1993Operator::DragLaw(particle, cfd, output); break;
254 case cfd_drag_law_MarheinekeWegener2011: MarheinekeWegener2011Operator::DragLaw(particle, cfd, output); break;
255 }
256 }
257};
258
259struct LiftOperator
260{
261 __host__ __device__ inline
262 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
263 {
264 device::compute_cfd_lift(particle, cfd, output, data);
265 }
266};
267
268template <typename _LiftCoeff>
269struct LiftParametricOperator
270{
271 __host__ __device__ inline
272 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
273 {
274 device::LiftLaw<_LiftCoeff>(particle, cfd, output, data);
275 }
276};
277
278struct VirtualMassOperator
279{
280 SDeviceModel* device_data;
281
282 __host__ __device__ inline
283 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
284 {
285 device::compute_cfd_virtual_mass(particle, cfd, output, data);
286 device_data->particle_scalars->get_virtual_mass(particle._impl.particle_index) = output.virtual_mass;
287 }
288};
289
290template <typename _Coeff>
291struct VirtualMassParametricOperator
292{
293 SDeviceModel* device_data;
294
295 __host__ __device__ inline
296 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
297 {
298 device::VirtualMassLaw<_Coeff>(particle, cfd, output, data);
299 device_data->particle_scalars->get_virtual_mass(particle._impl.particle_index) = output.virtual_mass;
300 }
301};
302
303struct TorqueOperator
304{
305 __host__ __device__ inline
306 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
307 {
308 device::compute_cfd_torque(particle, cfd, output, data);
309 }
310};
311
312template <typename _Coeff>
313struct TorqueParametricOperator
314{
315 __host__ __device__ inline
316 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
317 {
318 device::TorqueLaw<_Coeff>(particle, cfd, output, data);
319 }
320};
321
322struct HeatConvectionOperator
323{
324 SDeviceModel* device_data;
325
326 __host__ __device__ inline
327 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
328 {
329 device::compute_cfd_convection(particle, cfd, output, data);
330 device_data->particle_transfer_scalars->get_heat_transfer(particle._impl.particle_index) += output.heat_transfer;
331 }
332};
333
334template <typename _Coeff>
335struct HeatConvectionParametricOperator
336{
337 SDeviceModel* device_data;
338
339 __host__ __device__ inline
340 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
341 {
342 device::ConvectionLaw<_Coeff>(particle, cfd, output, data);
343 device_data->particle_transfer_scalars->get_heat_transfer(particle._impl.particle_index) += output.heat_transfer;
344 }
345};
346
347struct CFDDataRecorderOperator
348{
349 SDeviceModel* device_data;
350
351 __host__ __device__ inline
352 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
353 {
354#ifndef CFD_NO_CUSTOM_LAWS
355 if (device_data->cfd_data_recorder != nullptr && device_data->cfd_data_recorder->enabled)
356#endif
357 device_data->cfd_data_recorder->register_coupling_data(
358 output, device_data->particle_scalars, particle._impl.particle_index, device_data->gen->dt
359 );
360 }
361};
362
363struct TwoWayCouplingOperator
364{
365 SDeviceModel* device_data;
366
367 __host__ __device__ inline void operator()(
368 const IRockyParticle& particle,
369 const IRockyCFDProperties& cfd,
370 CFDCouplingOutput& output,
371 void* data)
372 {
373 if (device_data->gen_cfd->cfd_coupling_mode == cfdcTwoWay)
374 {
375 auto dt = device_data->get_general().dt;
376 auto particle_scalars = particle.get_scalars();
377
378 const auto& particle_velocity = particle.get_translational_velocity();
379 const auto& relative_velocity = cfd.get_relative_velocity();
380
381 if (device_data->gen_cfd->use_2023R2_cfd_sources)
382 {
383 particle_scalars.add_explicit_fluid_momentum(
384 particle_velocity * output.drag_coefficient_fluent * dt);
385 }
386 else
387 {
388 particle_scalars.add_explicit_fluid_momentum(
389 -output.drag_coefficient_fluent * relative_velocity * dt);
390 }
391 particle_scalars.add_implicit_fluid_momentum(-output.drag_coefficient_fluent * dt);
392
393 if (output.has_explicit_forces())
394 {
395 particle_scalars.add_explicit_fluid_momentum(
396 -output.momentum_source_explicit_fluent * dt);
397 }
398 if (output.has_heat())
399 {
400 if (device_data->gen_cfd->use_2023R2_cfd_sources)
401 {
402 particle_scalars.add_explicit_fluid_heat_transfer_rate(
403 output.heat_source_explicit_fluent * dt);
404 }
405 else
406 {
407 particle_scalars.add_explicit_fluid_heat_transfer_rate(
408 (output.heat_source_explicit_fluent
409 + output.heat_source_implicit_fluent * cfd.get_fluid_temperature())
410 * dt);
411 }
412 particle_scalars.add_implicit_fluid_heat_transfer_rate(
413 output.heat_source_implicit_fluent * dt);
414 }
415 }
416 }
417};
418
419struct TurbulenceOperator
420{
421 SDeviceModel* device_data;
422
423 __host__ __device__ inline
424 void operator()(const IRockyParticle& particle, const IRockyCFDProperties& cfd, CFDCouplingOutput& output, void* data)
425 {
426#ifndef CFD_NO_CUSTOM_LAWS
427 if (device_data->gen_cfd->use_turbulent_dispersion)
428#endif
429 update_turbulent_dispersion(
430 device_data->particle_scalars,
431 particle._impl.particle_index,
432 cfd.cfd_index,
433 device_data->get_general().dt,
434 device_data->prt_vel,
435 device_data->fluid_scalars,
436 cfd.props,
437 particle._impl.get_group(),
438 output.C_D,
439 device_data->cfd_random
440 );
441 }
442};
443
444/*
445Dispatch function, a sequence of selector function calls, that will at the end collected all operators in a
446variadic template list, used to instantiate and dispatch a kernel.
447*/
448
449template <class backend, typename... Operators>
450__global__
451void cuda_coupling_kernel(CouplingDispatchData data, Operators... operators)
452{
453 api_coupling_kernel<backend>(data, operators...);
454}
455
456template <class backend, typename... Operators>
457void omp_coupling_kernel(CouplingDispatchData &data, Operators... operators)
458{
459 // shut up nvcc compile warnings when compiling device function version using OMPBackend
460 #ifndef __CUDA_ARCH__
461
462 api_coupling_kernel<backend>(data, operators...);
463
464 #endif
465}
466
467template <typename... Operators> inline
468void dispatch_coupling_kernel(CouplingDispatchData &data, Operators... operators)
469{
470 if (data.is_cuda) {
471#ifdef __CUDACC__
472 cuda_coupling_kernel<CudaBackend><<<CD_NBLOCKS, CD_NTHREADS>>>(data, operators...);
473#else
474 ROCKY_RUNTIME_ERROR("Invalid GPU kernel execution.");
475#endif
476 }
477 else
478 omp_coupling_kernel<OMPBackend>(data, operators...);
479}
480
481/*
482Selector functions, called in ascending order
483e.g. drag -> lift -> virtual mass -> ....
484*/
485template<typename... Operators>
486void select_turbulence_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, Operators... operators)
487{
488 if (h_gen_cfd.use_turbulent_dispersion)
489 dispatch_coupling_kernel(data, operators..., TurbulenceOperator{ data.device_data });
490 else
491 dispatch_coupling_kernel(data, operators...);
492}
493
494template<typename... Operators>
495void select_coupling_mode_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, Operators... operators)
496{
497 if (h_gen_cfd.cfd_coupling_mode == cfdcTwoWay)
498 select_turbulence_and(
499 data, h_gen_cfd, operators..., TwoWayCouplingOperator{ data.device_data });
500 else
501 select_turbulence_and(data, h_gen_cfd, operators...);
502}
503
504template<typename... Operators>
505void select_cfd_data_recorder_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, Operators... operators)
506{
507#ifdef CFD_NO_CUSTOM_LAWS
508 if (data.collect_cfd_data)
509 select_coupling_mode_and(data, h_gen_cfd, operators..., CFDDataRecorderOperator{ data.device_data });
510 else
511 select_coupling_mode_and(data, h_gen_cfd, operators...);
512#else
513 // When compiling the kernel with custom laws, we must limit the number of times we instantiate the coupling kernel.
514 // To avoid code bloat, we create here just a single one with all remaining functions enabled
515 dispatch_coupling_kernel(
516 data,
517 operators...,
518 CFDDataRecorderOperator{ data.device_data },
519 TwoWayCouplingOperator{ data.device_data },
520 TurbulenceOperator{ data.device_data }
521 );
522#endif
523}
524
525template<class Plugin, typename... Operators>
526void select_convection_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& group, Operators... operators)
527{
528 switch (group.convection_law)
529 {
530 case cfd_convection_law_none:
531 select_cfd_data_recorder_and(data, h_gen_cfd, operators...);
532 break;
533#ifndef CFD_NO_CUSTOM_LAWS
534 case cfd_convection_law_custom:
535 select_cfd_data_recorder_and(data, h_gen_cfd, operators..., custom_convection_operator<Plugin>(data.device_data));
536 break;
537#endif
538 default:
539 select_cfd_data_recorder_and(data, h_gen_cfd, operators..., HeatConvectionOperator{ data.device_data });
540 }
541}
542
543template<class Plugin, typename... Operators>
544void select_torque_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& group, Operators... operators)
545{
546 switch (group.torque_law)
547 {
548 case cfd_torque_law_none:
549 select_convection_and<Plugin>(data, h_gen_cfd, group, operators...);
550 break;
551 case cfd_torque_law_DennisSinghIngham1980:
552 select_convection_and<Plugin>(data, h_gen_cfd, group, operators..., TorqueParametricOperator<DennisSinghIngham1980Operator>());
553 break;
554#ifndef CFD_NO_CUSTOM_LAWS
555 case cfd_torque_law_custom:
556 select_convection_and<Plugin>(data, h_gen_cfd, group, operators..., custom_torque_operator<Plugin>());
557 break;
558#endif
559 }
560}
561
562template<class Plugin, typename... Operators>
563void select_virtual_mass_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& group, Operators... operators)
564{
565 switch (group.virtual_mass_law)
566 {
567 case cfd_virtual_mass_law_none:
568 select_torque_and<Plugin>(data, h_gen_cfd, group, operators...);
569 break;
570#ifndef CFD_NO_CUSTOM_LAWS
571 case cfd_virtual_mass_law_custom:
572 select_torque_and<Plugin>(data, h_gen_cfd, group, operators..., custom_virtual_mass_operator<Plugin>(data.device_data));
573 break;
574#endif
575 default:
576 select_torque_and<Plugin>(data, h_gen_cfd, group, operators..., VirtualMassOperator{ data.device_data });
577 }
578}
579
580template<class Plugin, typename... Operators>
581void select_lift_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& h_group, Operators... operators)
582{
583 switch (h_group.lift_law)
584 {
585 case cfd_lift_law_none:
586 select_virtual_mass_and<Plugin>(data, h_gen_cfd, h_group, operators...);
587 break;
588 //case cfd_lift_law_Mei1992:
589 // select_virtual_mass_and<Plugin>(data, h_gen_cfd, h_group, operators..., LiftOperator<Mei1992Operator>());
590 // break;
591 //case cfd_lift_law_Saffman1968:
592 // select_virtual_mass_and<Plugin>(data, h_gen_cfd, h_group, operators..., LiftOperator<Saffman1968Operator>());
593 // break;
594#ifndef CFD_NO_CUSTOM_LAWS
595 case cfd_lift_law_custom:
596 select_virtual_mass_and<Plugin>(data, h_gen_cfd, h_group, operators..., custom_lift_operator<Plugin>());
597 break;
598#endif
599 default:
600 select_virtual_mass_and<Plugin>(data, h_gen_cfd, h_group, operators..., LiftOperator());
601 }
602}
603
604template <class Plugin>
605void select_drag_and(CouplingDispatchData& data, const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& h_group)
606{
607#ifndef CFD_NO_CUSTOM_LAWS
608 switch (h_group.drag_law)
609 {
610 case cfd_drag_law_custom:
611 select_lift_and<Plugin>(data, h_gen_cfd, h_group, custom_drag_operator<Plugin>());
612 break;
613 default: {
614#else
615 {{
616#endif
617 if (DragLightWeightOperator::valid(h_group.drag_law))
618 select_lift_and<Plugin>(data, h_gen_cfd, h_group, DragLightWeightOperator());
619 else if (DragHeavyWeightOperator::valid(h_group.drag_law))
620 select_lift_and<Plugin>(data, h_gen_cfd, h_group, DragHeavyWeightOperator());
621 else
622 select_lift_and<Plugin>(data, h_gen_cfd, h_group, DragOperator());
623 }
624 }
625}
626
627template <class Plugin>
628void select_and_dispatch_coupling_kernel(
629 bool is_cuda, bool collect_cfd_data,
630 SDeviceModel* device_data, unsigned int* particle_indexes, int n_particles, void* udf_data,
631 const cuda_general_cfd& h_gen_cfd, const CFDParticleGroup& h_group
632)
633{
634 CouplingDispatchData data{ is_cuda, collect_cfd_data, device_data, particle_indexes, n_particles, udf_data };
635 select_drag_and<Plugin>(data, h_gen_cfd, h_group);
636}
637
638template <class backend, typename _Op>
639__host__ __device__ void api_compute_cfd_data_coupling(
640 SDeviceModel* device_data, double current_time, _Op op, void* udf_data)
641{
642 IRockyDeviceModel device_model_api;
643 device_model_api._impl.model = device_data;
644 device_model_api._impl.current_time = current_time;
645
646 IRockyParticle particle_api(-1, device_data);
647
649 cfd.model = device_data;
650
651 const cuda_general& general = device_data->get_general();
652
653 int thread_start, thread_step, thread_stop;
654 backend::ThreadIteration(thread_start, thread_step, thread_stop, general.nprt_active);
655 for (int i = thread_start; i < thread_stop; i += thread_step)
656 {
657 particle_api._impl.reset(i);
658 int ind_cfd = device_data->particle_scalars->get_cfd_index(i);
659 if (!particle_api._impl.particle->enabled() || ind_cfd < 0)
660 {
661 continue;
662 }
663
664 cfd.reset(i, ind_cfd);
665
666 op(device_model_api, particle_api, cfd, udf_data);
667 }
668}
669
670} // namespace device
Definition rocky_cfd.hpp:26
ROCKY_FUNCTIONS double3 get_relative_velocity() const
Definition rocky_cfd.hpp:112
ROCKY_FUNCTIONS double get_fluid_temperature() const
Definition rocky_cfd.hpp:54
Definition rocky_model_api.hpp:19
Definition rocky_particle_api.hpp:27
ROCKY_FUNCTIONS IRockyParticleScalars get_scalars()
Definition rocky_particle_api.hpp:537
ROCKY_FUNCTIONS double3 get_translational_velocity() const
Definition rocky_particle_api.hpp:417

Connect with Ansys