Usage examples
Last update: 08.07.2024
Usage examples
The first section of this chapter provides a step-by-step description of the implementation of a simple but fully functional module using the Rocky Solver SDK. The whole process is covered, from the implementation of all the required source files, until the execution of the compiled module. The second section describes the code associated to a custom module that implements a contact model.
A simple custom module
This section describes the implementation of the code of a simple module in order to illustrate the use of the Rocky Solver SDK. The example module is called Spherical Region
. Its only purpose is to allow users to define a region of spherical shape inside the simulation domain, and mark all particles located inside this region at any given time.
The source files detailed below should be saved in the following directory structure:
The following sections reproduce and describe the content of each one of the four source files. For a walk-through example of setting up and using this simple custom module, refer to Tutorial 23: Rocky Solver SDK.
File spherical_region.plugin
The purpose of this file is to give Rocky general information about the module. For instance, line 2 defines the name of the module as it must be displayed in the Rocky UI. Similarly, line 3 gives the name of the compiled library file of the module in the filesystem. The data in the block between lines 5 and 9 is displayed within the Info tab associated to the module in the Rocky UI.
File spherical_region.py
This is a Python file that specifies which are the module parameters that must be displayed in the Rocky UI*. When a project is set up in Rocky and the module is enabled, users will be able to enter values for all parameters defined in this file, through the Rocky UI. Refer to chapter Module specification for a complete description of how different types of data can be specified by means of this file.
SDK utilities necessary for specifying the module data are imported in the block between lines 1 and 5. Line 7 defines the name of the module that Rocky must show in the UI. Beginning at line 10, the auxiliary class SphericalRegionModel
is defined, which includes the specification of the four parameters that the model needs. They are the three Cartesian coordinates of the sphere center and the sphere radius.
Between lines 18 and 26, the SphericalRegionSpecs
class is defined, which in this case includes only the definition of the name of the module and the specification of the parameters previously included in the SphericalRegionModel
class. Additionally, the CreateAddin
method is defined, which handles the loading of the compiled library file for the module when the simulation starts.
Finally, at line 29, the definition of the SphericalRegionModule
class is included. Only one method is implemented in this class, get_addin_specs
, which makes available all the specifications made previously in the file.
File spherical_region.pdf
This is an optional help file that may include usage instructions and/or technical details about the implementation of the module. If included, Rocky will automatically link it to a special icon displayed in the UI that will allow users of the module to open the file.
File CMakeLists.txt
This file includes compilation, linkage and install instructions in the CMake language, needed to build the module. Several commands defined by the Rocky SDK are used in order to simplify this file. The content of this file must be practically the same reproduced below for any custom module implemented using the Rocky Solver SDK. Users only have to replace the actual name of the compiled library at line 3 and define the ROCKY_PLUGINS_PATH
environment variable with the directory in which the compiled modules must be installed, if this definition has not been made previously.
If the module includes a help pdf
file, the line 8 must include this file in the list of module assets, in the following way:
On the other hand, if for some reason the module must be installed in a directory different from the one pointed to by the environment variable ROCKY_PLUGINS_PATH
, the following additional line can be inserted between lines 3 and 5:
where custom_path
is the path of the folder where the module must be installed, relative to the source directory being processed.
File spherical_region.cu
This file includes the C++ code that implements the intended functionality of the module during the execution of a simulation. Every function defined in this file must be executed at strategic points when a simulation is running in Rocky. These points are defined via the simulation hooks described in the chapter Solver Hooks, and must therefore be chosen carefully by taking into account what operations the module must perform and what information provided by Rocky will be necessary for their execution. In order to interact with Rocky, the Solver SDK classes and methods described in chapter Class Reference must be used.
The directive in line 1 enables the execution of the module in single or multi-GPU configurations. When this line is included, the module must define a ROCKY_PLUGIN_INITIALIZE_CUDA
function in order to allocate memory in the GPU and to copy the module data to the GPU, as described below.
In line 5, a custom data structure ModuleData
is defined, that will be used to store the data needed by the module. In this case, the structure includes the coordinates of the center point*, the radius of the sphere and an index to identify the particle scalar that will be used to identify the particles inside the spherical region.
**In order to simplify the code, the Rocky Solver SDK provides the struct double3 for defining 3D points and 3D vectors. It includes as data members the three coordinates x, y and z. Special operators for this struct are also defined, for addition, subtraction, and multiplication by a scalar. Moreover, the functions dot, cross, and get_norm are also provided, for obtaining the dot product, the cross product, and the norm, respectively.*
In line 12, the name and the version of the module implemented by the code in the file are defined. Afterwards, between lines 14 and 23, the code associated to the hook ROCKY_PLUGIN_CONFIGURE
is defined. Here, an instance of the custom struct
is allocated and the corresponding pointer is named module_data
. Next, the values of the four module parameters entered through the Rocky UI are retrieved from the function argument input_data
, and assigned to the corresponding variables in the object pointed by module_data
. Finally, in line 23, this pointer is converted to a void pointer in order to assign it to the function argument data
, which Rocky will store and make available in subsequent stages of the simulation.
Between lines 26 and 31, the code associated to the hook ROCKY_PLUGIN_SETUP
is defined. As in other preprocessing hooks, the arguments provided are an IRockyModel
object, named simply model
, and the void pointer that was defined previously in ROCKY_PLUGIN_CONFIGURE
. In order to have access to the data stored previously, the void pointer must be converted back into a ModuleData pointer, as it is done in line 28. In this specific case, the only operation performed in this block is to define a particle scalar variable that will be used to mark particles inside the spherical region. In line 29, the object that handles operations with particle scalars is defined. Subsequently, in line 30 the custom particle scalar is specified. The two arguments in the add
function are the label that must associated to the particle scalar in the Rocky UI, and the unit. After creating the particle scalar, the add
function will return an integer index that, in this case, will be stored in module_data->scalar_index
. Any subsequent operation involving that specific particle scalar will require the use of that index.
In order to avoid precision loss because of roundoff errors, Rocky works internally with dimensionless variables. Therefore, the module has to nondimensionalize all custom parameters previously defined, in order to use them in operations involving data coming from the Rocky solver. This operation is made in the block beginning at line 33, within the ROCKY_PLUGIN_NON_DIMENSIONALIZE
hook. In this case all parameters are lengths, so they are nondimensionalized using the length factor provided by the corresponding method of the model
object.
Between lines 42 and 50, the module data is copied to the GPU devices. This kind of operation is mandatory when a module is intended for execution in single or multi-GPU configurations. The hook ROCKY_PLUGIN_INITIALIZE_CUDA
provides two generic pointers as arguments: host_data
and device_data
. The first one points to the object that currently stores the data defined in the previous pre-processing functions. The objective of this function is to allocate a memory block of the right size in the GPU devices, copy the module data pointed by host_data
to that memory block, and finally assign to device_data
the pointer that points to the beginning of that block. This is done in lines 47 (memory allocation), 48 (data copy) and 49 (conversion to a generic pointer and assigment device_data
).
The only operation performed by the module during the time iterative process is the one implemented in the block beginning at line 52. This operation is associated to the ROCKY_PLUGIN_POST_MOVE_PARTICLES
hook, which is executed inside a loop over the active particles in the simulation, after the position and velocities of the particles were updated in Rocky. In line 58, the distance between the centroid of the current particle and the center of the spherical region is calculated. If that distance is less than the region radius, the particle is considered to be inside the region. The scalar value associated to the particle is set be equal to 1 in that case, and equal to 0 otherwise. The block is closed by the ROCKY_PLUGIN_POST_MOVE_PARTICLES_END
function call, during which Rocky takes care of some additional operations needed to execute the module code correctly. Note that any of the functions associated to a hook executed during the time iterative loop must be closed by a similar function.
Finally, the ROCKY_PLUGIN_TEAR_DOWN
hook frees the memory allocated for the local data structure in the CPU memory area. The equivalent operation on the GPU memory area is made in the ROCKY_PLUGIN_TEAR_DOWN_CUDA
hook.
Building procedures
This section shows a way to compile the module spherical_region
described in the previous section.
Building in Centos 7
In the conda
command prompt that was activated in section Build Tools - Linux, navigate to the spherical_region
directory and execute the following commands:
On successful execution of the above commands, the compiled content of the spherical_region
module is available in the folder pointed by the ROCKY_PLUGINS_PATH
environment variable:
Building in Windows 10
Open the e x64 Native Tools Command Prompt for VS 2019
, navigate to the spherical_region
directory and execute the following commands:
On successful execution of the above commands, the compiled content of the spherical_region
module is available in the folder pointed to by the ROCKY_PLUGINS_PATH
environment variable:
Running the module in Rocky
After having completed successfully all the steps described in previous sections, the new module will be ready to be executed in a Rocky simulation. Restart the Rocky application in order for it to acknowledge the recently created module.
When selecting the Modules item in the Data panel, the name of the new module must appear in the list of modules recognized by Rocky, displayed in the Data Editors panel. The activation of the module in a simulation requires that the corresponding checkbox is turned on, as shown in Figure 5.1.

Figure 5.1: The new module displayed in the Data Editors panel.
After the module is activated, a new item with the module name will be added under the Modules item in the Data panel, as shown in Figure 5.2. The selection of this item gives access to the general custom parameters defined in the model section of the specifications file spherical_region.py
. The default values displayed are those defined in that file. Users of the module can alter those values at their convenience. On the other hand, if the Info tab is selected, the reference data included in the spherical_region.plugin
is displayed in the panel.

Figure 5.2: The custom parameters for the module displayed in the Data Editors panel.

Figure 5.3: The module's Info tab on the Data Editors panel
In order to test the module, any new project can be set up in Rocky and then the Spherical Region module must be enabled, defining the proper values for the module parameters. After processing the simulation, the Inside Sphere scalar can be selected in the list of particle properties in the Properties tab, and visualized in a 3D view window at any output time. All particles inside the specified spherical region will have an scalar value equal to 1, as depicted in the example of Figure 5.4, while particles outside it will have associated a zero value.

Figure 5.4: Example of a simulation processed using the new module.
A module implementing a custom
As an example of the implementation of a custom model using the Rocky Solver SDK, this section describes the code associated to a custom module that implements a contact model, including the calculation of both components of the contact force, as well as the calculation of the impact energy.
A contact model may include in the most general case the calculation of both components of the contact force, and, if necessary, the calculation of the impact energy during a collision. Usually the tangential component of the contact force depends on the normal component, and the impact energy on both of them. Because of that, they are calculated in a fixed sequence, as shown schematically in Figure 5.4.

Figure 5.5: Contact model pipeline in Rocky.
The Rocky Solver SDK gives some flexibility regarding the implementation of custom contact force models. For instance, users can choose to implement only the normal contact force, combining it with a built-in tangential force model in Rocky. Or, conversely, users may implement only the tangential contact force, using as input the normal contact force calculated by a built-in model in Rocky. In these cases, users only need to implement whichever force component they want to customize in their module, then in runtime, Rocky will calculate the other component with the respective model selected in the Rocky UI.
On the other hand, users may implement the calculation of both contact force components within a custom module, including the calculation of the impact energy as well. Impact energy is used in Rocky as the main input parameter for the built-in instantaneous breakage models; therefore, users will need to implement a custom impact energy calculation only if they intend to use a custom contact force model along with such breakage models. Even in that case, users may choose not to implement the calculation of the impact energy. Rocky will use in such situation a standard calculation based on the impact work, as defined in equation 4.10 of the DEM Technical Manual. Also, when a module implements only either a normal or a tangential force model, Rocky uses standard calculations for the other one.
The remainder of this chapter will describe the implementation of a custom module including the calculation of both components of the contact force and the calculation of the impact energy as well. The normal and tangential force models included in the module are simplified versions of two built-in models in Rocky, the Hysteretic Linear Spring and the Linear Spring Coulomb Limit, respectively. Moreover, the impact energy calculation included in the module is the one used in Rocky when the Hysteretic Linear Spring model is selected as normal contact force.
Module specification file
The following listing reproduces the Python file that includes the specifications for the custom module, which is named simply as Contact Model Example
.
The only parameters added by the module are two material interaction properties defined between lines 21 and 24. Both of them are used in the tangential contact force calculation. The first one is the ratio of the tangential stiffness to the normal stiffness, while the second one is the value of the tangential relative velocity that marks the onset of the sliding between the colliding entities.
Between lines 33 and 37, the module specifies that it will implement a custom normal force model, a custom tangential force model and a custom impact energy calculation. In runtime, Rocky will read these specifications and will override those model categories, using instead the custom models implemented by the module, as explained in section Specification of custom models.
Implementation of the contact model
This section describes the different parts that make up the custom_model_example.cu
file that includes the C++ code that implements the custom models.
The initial part of the file reproduced above includes the definition of the preprocessor name ROCKY_CUDA_API
that enables the compilation of the module in CUDA and, in turn, enables the possibility of the module being used in a simulation processed on GPU. Subsequently, between lines 5 and 9, it is defined a local struct
that will hold the values entered through the Rocky UI for the two material interaction parameters that the module uses. Then, between lines 11 and 19, another local struct
is defined, that will store the indices attributed in runtime to the contact scalars that the module will create. Additionally, that struct
includes an array to store the values of the custom properties associated to all material interactions in the project.
Note: Here ppi stands for particle-particle index, while pti stands for particle-triangle index.
The code block above implements three utility functions that simplify the handling of contact scalars. They allow to treat in a unified way, with a single function, both types of contact scalars, namely particle-to-particle and particle-to-triangle contact scalars.
The block above includes the associated code to the initialization and termination hooks. As most of these operations were covered in chapter Rocky module examples, they will be described here very briefly.
In the ROCKY_PLUGIN_CONFIGURE
hook, the values for the two module parameters per material interaction, entered through the Rocky UI, are stored in the array within the module local struct
defined previously. Subsequently, in the ROCKY_PLUGIN_SETUP
hook, contact scalars are created for storing the values of the contact forces calculated in the module. This storage is necessary because both the normal and tangential force models being implemented depend upon the history; therefore, in order to calculate the force values at a given timestep, the values from the previous timestep are required to be available.
In the ROCKY_PLUGIN_INITIALIZE_CUDA
hook, the local module data is copied to GPU devices after being allocated the required memory block there. On the other hand, that memory block is freed in the ROCKY_PLUGIN_TEAR_DOWN_CUDA
hook. An equivalent operation for the memory allocated in CPU is made in the ROCKY_PLUGIN_TEAR_DOWN
hook.
The block of code above implements a simplified but functional form of the Hysteretic Linear Spring normal contact force. As this is a history-dependent model, the needed previous value of the normal contact force is retrieved from the corresponding contact scalar in line 120. Subsequently, the stiffnesses corresponding to the loading and unloading portions of the collision cycle are calculated using the equations in section 2.1.1.1 of the DEM Technical Manual. Both stiffness values are multiplied by the Contact Stiffness Multiplier, which is an advanced material interaction parameter that might be used to prevent large overlaps in certain specific situations. Also, The stiffness value returned by the get_equivalent_stiffness function is already multiplied by the Numerical Softening Factor, which is commonly used for increasing the simulation timestep. For more details about this factor, please refer to section 5.3.4 of the DEM Technical Manual.
Using the current overlap value and its variation during the timestep, two possible values of the normal contact force are calculated, one located on a loading path and other located on an unloading path. The new normal contact force will be the minimum between those two values, as long it is positive. If that minimum value is negative, the new normal contact force will be set to zero. In line 133 that new value is passed as argument to the set_normal_force
method of the output_data
object. This operation is mandatory, because only in that way Rocky will become aware of the new force value calculated by the module. From that point on, Rocky will use internally that force for solving the particles' motion equations and perform all the other operations that may need it.
As a final operation of the normal force calculation, the new normal contact force value is set also to the corresponding contact scalar in line 135, in order to preserve it and make it available during the next time iteration.
The implementation of the Linear Spring Coulomb Limit tangential force model is made in the code reproduced above. The model needs material interaction properties defined by both Rocky and the module itself. Because of that, two material interaction objects are defined in lines 142 and 143 in order to retrieve those property values. Next, in line 145, the previous tangential force vector is defined as zero if the current timestep is the first one in the collision, or, otherwise, its components are retrieved from custom contact scalars. Subsequently, the tangential component of the relative velocity at the contact point, pre-calculated by Rocky, is retrieved, and with it the tangential relative displacement during the timestep is calculated.
Note: This is a simplified version of the model implemented in Rocky. Some additional operations are ignored for the sake of simplicity. For instance, Rocky introduces correction terms to take into account the change on the normal direction and a possible viscous dissipation, that this implementation does not address
In line 154, the normal stiffness value is retrieved, and with it and the tangential stiffness ratio, the tangential stiffness is determined in line 155. Then, in line 157, the possible new value of the tangential force vector is calculated using equation 2.18 of the DEM Technical Manual. As in this model the magnitude of the tangential contact force cannot exceed the so-called Coulomb limit, calculated in line 159, the tangential force is rescaled if that condition is not satisfied, in line
- Additionally, the sliding condition is verified in line 164, comparing the magnitude of the relative tangential velocity with the sliding threshold value defined as a material interaction property. The boolean value indicating if the sliding condition is true or false is passed to Rocky using the
set_sliding
method of theoutput_data
object, in line 165. In case that the Coulomb limit is not exceeded, the sliding condition is always false, and that value is set in line 169.
The tangential contact force just calculated is passed also to Rocky by means of the set_tangential_force
method of the output_data
object, in line 172. The specification of both the sliding state and the tangential force vector is mandatory for a module implementing a tangential contact force model. As a final step, the components of the tangential force are stored in the contact scalars previously created, in order to make available those values in the next time iteration.
The module example presented in this chapter includes also the code for the calculation of the impact energy. This code reproduces the one implemented in Rocky and used when the Hysteretic Linear Spring model is active in a simulation. It is based on equation 4.11 of the DEM Technical Manual. Both the normal and the tangential contact force values calculated in previous steps, retrieved in lines 185 and 186, are needed in that expression. It actually represents the impact energy accumulated in the contact since the collision started. However, Rocky expects as output of the calculation the portions of that impact energy that are attributed to each colliding entity. Because of that, in lines 189 and 190, two values of impact energy are set using the set_home_impact_energy
and set_near_impact_energy
methods of the output_data
object, respectively.
After the module is built following the steps given in section 5.1.6, the module will be available to be used in Rocky. When the Contact Model Example
is enabled in a Rocky project, the models of normal and tangential forces, besides the impact energy model implemented on it will override built-in models in those categories. This will be indicated within the Physics | Momentum tab, which will appear as shown in Figure 5.5.

Figure 5.6: The normal force, tangential force and impact energy categories overriden by the models implemented in Contact Model Example.
A module implementing variable properties
As an example of the implementation of modules that override built-in constant properties in Rocky, this section describes a module that converts the particle's thermal conductivity into a function of the temperature. Additionally, the module makes possible also to define the temperature of boundaries as a function of the position. The functional relation for the thermal conductivity that the module implements is the following: $$ K_p = K_O ( 1 + C_L T_p ) $$ where \(K_O\) and \(C_L\) are two module parameters and \(T_p\) is the particle temperature. On the other hand, the modules allows to define the temperature of boundary triangles as a quadratic function of the \(x\)-coordinate: $$ T_t = T_O ( 1 + C_Q \,x_t^2 ) $$ where \(T_O\) and \(C_Q\) are two module parameters and \(x_t\) is the \(x\)-coordinate of the triangle's centroid.
Module specification file
The following listing reproduces the Python file with the specifications of the module, which is named as Variable Properties Example
.
Lines 18 and 19 of this file define the two parameters used in thermal conductivity equation as material properties. This means that different values can be entered through the Rocky UI for each one of the materials defined in a project. Similarly, lines 24 and 25 define the two parameters included in the boundary temperature equation as geometry properties. Therefore, different values of these parameters could be specified for each geometry in a project.
Note: However, since the module will define the thermal conductivity as a variable property for particles exclusively, only parameter values from materials associated to particles will be effectively used by the module.
The class defined in lines 28 to 30 specifies which material properties associated to particles will be overridden by the module. In this case, the thermal conductivity is the only property specified. That property is associated to an particle scalar variable defined internally in Rocky (ThermalConductivity
) which the solver will use to store the values calculated by the module. A similar specification is made between lines 30 and 35 for the temperature of the boundary triangles. For more details about the specification of variable properties, please refer to section 2.9.
Since the module will define the thermal conductivity as a variable property for particles exclusively, only parameter values from materials associated to particles will be effectively used by the module.
Module implementation
This section describes the C++ code of the main parts of the variable_properties_example.cu
file. The code from initialization and termination hooks related to CUDA operations is omitted, since it was described in previous examples. This code implements the calculation of the property values per particle and per boundary triangle that the module must deliver to the Rocky solver. In turn, the Rocky solver will use these values internally in the thermal model calculations.
The code block above defines data structures for the module to store the parameter values that users of the module entered via the Rocky UI.
The code associated to the ROCKY_PLUGIN_CONFIGURE
hook receives the parameter values delivered by the Rocky UI, and then stores them in the data structures previously defined. On the other hand, the ROCKY_PLUGIN_SETUP
hook is only used to verify if the project has the thermal model enabled. The module will perform its operations only if that is the case. Then the module parameters are non-dimensionalized, in order to be used in the calculations that must be made later on, during the simulation.
Since the module is intended to be used with static boundaries only, it needs to prescribe the temperature of the boundary triangles only once, during the initialization. In order to do that, the ROCKY_PLUGIN_INITIALIZE_TRIANGLE
hook is used in the following way:

Figure 5.7: Example of the temperature distribution on a boundary specified by the module.
The code above applies boundary temperature equation shown above to the calculation of the temperature of every boundary triangle in the simulation. If the temperature distribution should be applied only to specific boundaries, the code above must be modified in order to filter the triangles belonging to those boundaries. Figure 5.7 shows an example of the resulting temperature distribution in a specific case.
The thermal conductivity as a function of the particle's temperature. Since this temperature is updated at every time iteration during the simulation, the module needs to update the conductivity values at every iteration as well. That update must be done within an iteration hook executed before the heat transfer calculation, which are made right afterwards the contact forces calculation. Therefore, the ROCKY_PLUGIN_PRE_FORCE_ON_PARTICLES
hook is the most adequate for that task, as shown in the following code block:
This code calculates the thermal conductivity for all active particles at a given time, according to thermal conductivity equation mentioned previously. The conductivity value just calculated is passed to the Rocky solver in the line 111 using the set_thermal_conductivity
method. The Rocky Solver SDK includes equivalent methods associated to particles, triangles and contacts, for every property that can be overridden by a custom module. Figure 5.8 shows an example of a particle bed in which the particles' thermal conductivity has been calculated by the module described in this section.
When a custom module that implements a variable property is active in a simulation, Rocky will issue a warning message, indicating which properties are being overridden by the module. Although the constant property values being replaced will remain editable in the Rocky UI, it is important to note that they will be ignored in all the calculations done by the Rocky solver.

Figure 5.8: Example of the variable thermal conductivity on particles specified by the module
A module implementing a custom SPH model
As an example of the implementation of a custom SPH model using the Rocky Solver SDK, this section describes the code associated to a custom module that implements simultaneously the Large Eddy Simulation (LES) turbulence model*, the Morris viscosity model and the Free Slip boundary condition type. Be aware that when implementing forces or parameters directly related to forces, a custom module must implement the calculation of all relevant forces, as it is being done in this example. Note that not all forces or options present in Rocky are replicated in this module example, but only the most important ones.
**For more information about the model implemented in this example, refer to "Numerical modelling of complex turbulent free-surface flows with the SPH method: an overview", Violeau D., Issa, R., International Journal of Numerical Methods in Fluids, vol. 53, pp. 277-304, 2007.*
Module specification file
The following listing reproduces the Python file that includes the specifications for the custom module, which is named simply as LES Turbulence Model
.
Implementation of the SPH LES turbulence model
This section describes the different parts that make up the sph_les_model.cu
file that includes the C++ code implementing the custom models.
The initial part of the file reproduced above includes the definition of the preprocessor name ROCKY_CUDA_API
that enables the compilation of the module in CUDA and, in turn, enables the module to be used in a simulation processed on GPU. Subsequently, between lines 8 and 13, it is defined a local struct
that will be used to store the data needed by the module. In the current module, a parameter needed is the index turbulent_viscosity_index
assigned to a scalar that stores the turbulent viscosity calculated during the simulation. The other two parameters are needed to store the data entered by the user via the Rocky UI.
The block above includes the associated code to the initialization hooks. As most of these operations were covered in chapter Rocky module examples, they will be described here very briefly.
In the ROCKY_PLUGIN_CONFIGURE
hook, the values for the module parameter are stored in the array within the module local struct
defined previously. Subsequently, in the ROCKY_PLUGIN_SETUP
hook, a scalar is created for storing the values of the turbulent viscosity calculated in the module. This scalar is needed as the values from neighbor elements must be accumulated in order to approximate the tensor of strain rate as a previous step for calculating the turbulent viscosity. In the lines 68-70, three operations made on the scalar that stores turbulent viscosity are made: reset values, sum of values associated to elements in the halo regions between GPUs, and copy of values of those elements between GPUs. The last two operations are done only when the module is being employed in simulations with multi GPU. According to the specification made, the order of operations in the module is the following:
1. Reset of scalars
Hook PRE_FORCE_ON_ELEMENT_INTERACTIONS
Hook PRE_FORCE_ON_TRIANGLE_INTERACTIONS
Sum of halo values between GPUs
Hook PRE_FORCE_ON_ELEMENTS
Copy of halo values between GPUs
Hook FORCE_ON_ELEMENT_INTERACTIONS
Hook FORCE_ON_TRIANGLE_INTERACTIONS
In the ROCKY_PLUGIN_INITIALIZE_CUDA
hook, the local module data is copied to GPU devices after being allocated the required memory block there.
The block of code above implements the calculation of the rate of strain tensor for the SPH elements that are in contact, which is used to calculate the turbulent viscosity values in the following steps. The rate of strain tensor, d_shear
, is calculated according to the equation available in section 2.4 of the SPH Technical Manual.
The block of code above implements the turbulence viscosity calculation, including the rate of strain tensor previously calculated and considering the Smagorinsky constant, the LES distance factor parameter and the initial SPH elements spacing. It represents exactly the same equation for the turbulent viscosty term calculation used in the LES model and available in section 2.3 of the SPH Technical Manual.
The block of code above implements the LES turbulence SPH force model. The elements accelerations due to pressure and viscous forces are calculated, regarding Morris formulation for the laminar viscosity available in section 2.3.3.1 of the SPH Technical Manual. Bear in mind that this hook overrides all internal force calculations. Thus, the pressure forces are calculated besides the viscous ones, which are the only affected by the turbulent viscosity previously calculated.
The block of code above implements the normal boundary forces calculation regarding the free slip boundary condition, that uses the DEM-style interaction between the elements and the boundaries triangles. The normal repulsive forces are calculated for the SPH elements using the spring-dashpot model, with an elastic and a viscous terms, using the equations in section Specification of custom models of the SPH Technical Manual.
After the module is built following the steps given in section Building Procedures, the module will be available to be used in Rocky. When the SPH LES Turbulence Model
is enabled in a Rocky project, the models of turbulence, viscosity and boundary forces implemented on it will override built-in models in those categories.