The Discrete Phase Model (DPM) in Ansys Fluent is a very powerful tool. It helps us see how particles, droplets, or bubbles move inside a fluid flow. For many problems, the standard models in Fluent work very well. But sometimes, your problem is special. What if your particles follow a unique physical law? What if you need to define a new force acting on the particles? In these situations, the standard models are not enough.
Contents
ToggleThis is where a User-Defined Function (UDF) is the perfect solution. A UDF is a custom code that you write yourself. It lets you add your own physics into the Fluent solver. With a DPM UDF, you get complete control over every particle in your simulation.
Before we start, if you are new to UDFs, it is a good idea to read our other guides first. You can learn the basics in our Introduction to UDFs and see how to use the main tools in our guide on UDF Macros. If you need to store custom data for your particles, our blog on User-Defined Memory (UDM) explains how.
In this guide, we will teach you how to write advanced UDFs for DPM. We will use a simple but powerful idea to make it easy to understand: the life story of a single particle. We will follow a particle from its birth to its death. At each stage, we will show you exactly how to use a UDF to change its story.
Creating these custom models can be complex. For difficult industrial problems, the engineers at CFDLAND have great experience. You can explore our expert UDF DPM simulation services to see how we develop advanced solutions.
The Particle’s DNA: Understanding Tracked_Particle
Before we can write any DPM UDF, we must first understand how Fluent thinks about a particle. Imagine every single particle in your simulation has a special ID card. This ID card holds all the important information about that one particle: its size, its speed, its temperature, and much more.
In the language of Fluent UDFs, this ID card is called a Tracked_Particle. It is not a physical object. It is a special data structure inside the computer’s memory that stores all the data for one particle.
This Tracked_Particle data structure is the single most important concept for writing DPM UDFs. If you can access this “ID card,” you can read, check, and change any information about the particle.
When you look at a DPM UDF code, you will always see the letter p being used, for example, in P_MASS(p). This p is the variable name we give to the Tracked_Particle ID card for the particle that the UDF is currently working on. Think of it like a key.
The variable p is the key that unlocks all the properties of one specific particle at one specific moment in time.
Every UDF that works with DPM will give you this key, p. Your job is to use this key to read information from the particle’s ID card or to write new information onto it. The table below shows a few examples of the information you can find on this ID card.
Table 1: Example Information Stored in the Tracked_Particle p Structure
| Information You Can Access | What It Represents |
| P_DIAM(p) | The current diameter of the particle. |
| P_MASS(p) | The current mass of the particle. |
| P_VEL(p) | The current velocity (speed and direction) of the particle. |
| P_T(p) | The current temperature of the particle. |
| P_TIME(p) | The current time in the particle’s life. |
The Particle’s Toolkit: Essential DPM Macros
In the last section, we learned that every particle has an ID card called Tracked_Particle p. Now, we need to learn how to read the information on that card. We cannot just ask for “mass.” We need to use a special set of tools provided by Fluent.
These tools are called Macros. A DPM Macro is a short, pre-defined command that helps you get a specific piece of information from the particle’s ID card (p). Think of these macros as your toolkit. Each tool has one specific job. One tool gets the particle’s mass, another gets its temperature, and so on. Fluent gives us many macros. It is helpful to organize them into groups based on when they get the information.

Figure 1: Particle Life cycle through a cell
Macros for Current Particle Properties:
This first set of tools tells you about the particle right now, at its current position and time in the simulation. The table below lists the most common macros for this purpose.
Table 2: Macros for Reading Current Particle Properties
| Macro Name | What It Does |
| P_DIAM(p) | Gets the particle’s current diameter. |
| P_VEL(p) | Gets the particle’s current velocity. |
| P_T(p) | Gets the particle’s current temperature. |
| P_RHO(p) | Gets the particle’s current density. |
| P_MASS(p) | Gets the particle’s current mass. |
| P_TIME(p) | Gets the current lifetime of the particle since it was injected. |
| P_LF(p) | Gets the particle’s current liquid fraction. |
| P_VFF(p) | Gets the particle’s current volatile fraction. |
Macros for Past and Initial Properties:
Sometimes, you need to know what a particle was like in the past. Fluent gives us special tools for this. One group of macros tells you about the particle’s properties when it first entered the current cell. Another group tells you about the particle’s properties when it was first born (injected) into the simulation. These historical macros are very important for calculating changes, like how much mass a particle lost as it traveled through a cell.
Table 3: Macros for Reading Historical Particle Properties
| Macro Name | What It Does |
| At Cell Entry | These macros have a 0 at the end (e.g., P_MASS0). |
| P_DIAM0(p) | Gets the particle’s diameter when it entered the current cell. |
| P_VEL0(p) | Gets the particle’s velocity when it entered the current cell. |
| P_T0(p) | Gets the particle’s temperature when it entered the current cell. |
| P_RHO0(p) | Gets the particle’s density when it entered the current cell. |
| P_MASS0(p) | Gets the particle’s mass when it entered the current cell. |
| P_TIME0(p) | Gets the particle’s time when it entered the current cell. |
| P_LF0(p) | Gets the particle’s liquid fraction when it entered the current cell. |
| At Injection | These macros have _INIT_ in their name (e.g., P_INIT_MASS). |
| P_INIT_DIAM(p) | Gets the particle’s diameter when it was first injected. |
| P_INIT_RHO(p) | Gets the particle’s density when it was first injected. |
| P_INIT_TEMP(p) | Gets the particle’s temperature when it was first injected. |
| P_INIT_LF(p) | Gets the particle’s liquid fraction when it was first injected. |
Macros for Material and Law Properties:
This final group of tools helps you get information about the material the particle is made of and the physical laws it is following.
Table 4: Macros for Reading Material and Law Properties
| Macro Name | What It Does |
| P_MATERIAL(p) | A pointer to the particle’s material data. |
| DPM_SWELLING_COEFFI(p) | Gets the swelling coefficient for devolatilization. |
| DPM_EMISSIVITY(p) | Gets the particle’s radiation emissivity. |
| DPM_SCATT_FACTOR(p) | Gets the particle’s radiation scattering factor. |
| DPM_EVAPORATION_TEMPERATURE(p) | Gets the evaporation temperature of the material. |
| DPM_BOILING_TEMPERATURE(p) | Gets the boiling temperature of the material. |
| DPM_LATENT_HEAT(p) | Gets the latent heat of the material. |
| DPM_HEAT_OF_PYROLYSIS(p) | Gets the heat of pyrolysis of the material. |
| DPM_HEAT_OF_REACTION(p) | Gets the heat of reaction of the material. |
| DPM_VOLATILE_FRACTION(p) | Gets the volatile fraction of the material. |
| DPM_CHAR_REACTION(p) | Gets the char fraction of the material. |
| DPM_SPECIFIC_HEAT(p, t) | Gets the specific heat of the material at temperature t. |
| P_EVAP_SPECIES_INDEX(p) | Gets the index for the evaporating species. |
| P_DEVOL_SPECIES_INDEX(p) | Gets the index for the devolatilizing species. |
| P_OXID_SPECIES_INDEX(p) | Gets the index for the oxidizing species. |
| P_PROD_SPECIES_INDEX(p) | Gets the index for the combustion product species. |
| P_CURRENT_LAW(p) | Gets the index number of the DPM law the particle is currently using. |
| P_NEXT_LAW(p) | Gets the index number of the DPM law the particle will use next. |
With this complete toolkit of macros, you can read almost any property of a DPM particle. This knowledge allows for the creation of highly specialized simulations, such as analyzing the efficiency of a Dry Gas Filter or modeling the effect of Brownian motion on particle filtration.

Figure 2: Modeling particle filtration with Brownian force, another example of a specialized DPM UDF.
The Particle’s Life Story: A Guide to DPM UDF Hooks
In the last section, we learned about the macro “tools” to read a particle’s ID card. Now, we will learn how to write the actual instructions for Fluent. We do this with special functions called UDF Hooks. A UDF Hook is a function that you write, which “hooks” into a specific part of the DPM calculation process. These functions always have a name that starts with DEFINE_…. By writing a function with a specific DEFINE name, you are telling Fluent: “Stop at this specific point in your calculation, and run my custom code.” Let’s organize these hooks based on their job or function.
Hooks for Particle Forces and Motion
This group of hooks gives you direct control over how a particle moves. You can change the main forces that act on the particle during its journey.
Table 5: UDF Hooks for Controlling Particle Forces
| UDF Hook Name | What It Does |
| DEFINE_DPM_DRAG | Replaces Fluent’s standard drag coefficient calculation with your own custom equation. This lets you define exactly how the fluid’s motion slows down the particle. |
| DEFINE_DPM_BODY_FORCE | Adds a new, custom force that acts on the entire particle body. The most common use is for forces that are not built into Fluent, like electromagnetic or magnetic forces. |
For example, a DEFINE_DPM_BODY_FORCE UDF is essential for simulating how magnetic nanoparticles are guided through an artery by an external magnet.

Figure 3: CFD simulation of magnetic nanoparticles in an artery, where a DEFINE_DPM_BODY_FORCE UDF is used to apply the magnetic force on the particles. See the full project at Magnetic Nanoparticles in Artery CFD Simulation.
Hooks for Custom Physics and State Changes
This group of hooks lets you create completely new physical behaviors for your particles. You can define your own rules for how particles change over time, or how they switch between different behaviors.
Table 6: UDF Hooks for Defining Custom Particle Laws
| UDF Hook Name | What It Does |
| DEFINE_DPM_LAW | This is a very powerful hook. It lets you create your own custom physical laws for the particle, such as custom models for evaporation, reaction, or melting. You can directly change the particle’s mass, diameter, and temperature inside this function. |
| DEFINE_DPM_SWITCH | Lets you create a custom rule to decide when a particle should switch from one physical law to another. For example, you can tell a particle to switch from a simple “heating” law to a “melting” law when its temperature reaches the melting point. |
Hooks for Boundary Interactions
When a particle hits a wall or another boundary, Fluent has default behaviors like “reflect,” “trap,” and “escape.” This group of hooks lets you define completely custom behaviors for what happens when a particle hits a boundary.
Table 7: UDF Hooks for Custom Boundary Conditions
| UDF Hook Name | What It Does |
| DEFINE_DPM_BC | This hook is called when a particle hits a boundary. Inside this function, you can write your own code to decide what happens next. You can make the particle stop, bounce in a special way, or trigger a custom reaction. |
| DEFINE_DPM_EROSION_RATE | This is a special type of boundary condition hook. It is used specifically to calculate custom erosion or accretion (build-up) rates on a wall surface when particles hit it. |
These hooks are critical for advanced filter simulations, where you need to define exactly when a particle gets trapped by the filter media.

Figure 4: Simulating a dry gas filter where a DEFINE_DPM_BC UDF is used to define the custom trapping efficiency of the filter element. Explore the case at Dry Gas Filter CFD Simulation.
Hooks for Data Management and Flow Interaction
This final group of hooks helps you manage the simulation. You can change particles at birth, update custom variables during their life, and control how they affect the fluid around them.
Table 8: UDF Hooks for Data, Initialization, and Sources
| UDF Hook Name | What It Does |
| DEFINE_DPM_INJECTION_INIT | This function is called one time for each particle when it is first created. You can use it to give each particle unique initial properties that are different from the injection settings. |
| DEFINE_DPM_SCALAR_UPDATE | This function is called at every single time step in a particle’s journey. It is used to update custom variables that you are storing for the particle, for example, in User-Defined Memory (UDM). |
| DEFINE_DPM_SOURCE | Controls the source terms (mass |
Conclusion
In this guide, we have explored the fundamental building blocks for creating powerful and customized Discrete Phase Model (DPM) simulations using User-Defined Functions (UDFs) in Ansys Fluent.
We began with the most basic concept: the Tracked_Particle p, which acts as the unique ID card for every particle in the simulation. We then discovered the essential toolkit of DPM Macros, which are the specific commands used to read information from this ID card, such as a particle’s mass, velocity, or temperature.
Finally, we learned about the different UDF Hooks (the DEFINE_… functions). These hooks are the most critical part, as they provide specific moments in the particle’s “life story” where an engineer can step in and apply custom physics. Whether it’s defining a new force with DEFINE_DPM_BODY_FORCE, creating a custom wall interaction with DEFINE_DPM_BC, or designing a new physical law with DEFINE_DPM_LAW, these hooks are what give UDFs their power. By combining these three elements—the particle, the macros, and the hooks—you gain complete control over the behavior of particles in your CFD simulation.
