Forum
Important Notice for New User Registrations
To combat an increasing number of spam and bot registrations, we now manually approve all new user registrations. While this may cause a delay until your account is approved, this step is essential to ensure the quality and security of this forum.
To help us verify your registration as legitimate, please use a clear name as user name or an official email address (such as a work, university, or similar address). If you’re concerned that we may not recognize your registration as non-spam, feel free to email us at with a request to approve your username.
Question on the DMS variable-induction closure in DData.cpp (2.0.4a source)
Quote from lullaby98 on 22. August 2026, 10:08Hi Everyone,
I’m a PhD Student working on modeling a small VAWT for micro-generation (NACA0021, chors = 0.085, H = 1.5, R= 0.515), for which some experimental data is available, and I’m trying to set up a QBlade model of it (currently running 2.0.9.7 CE on Windows). While trying to understand the DMS solver better, I looked through the last publicly available source code (2.0.4a) and ran into two things I don’t quite understand.
While working through the classical DMST closure (Paraschivoiu 2002 with the Glauert correction) by hand for some streamtubes at higher TSR (from 3 to 5), I found cases where the aerodynamic CX(a) curve and the momentum CX(a) curve don’t seem to intersect anywhere in [0,1] – meaning no equilibrium would exist for that streamtube under the classical theory. I’m not sure yet whether that’s a mistake on my end or a genuine feature of the model in that regime, so I went to look at how QBlade’s DMS module (variable induction mode) handles this internally, using the last publicly available source code (2.0.4a). While there, I ran into two things I don’t quite understand.
— 1. Fx formula (2.0.4a source, DData.cpp) —
In the variable-induction branch (m_bVariable = true), the upwind Fx term (~line 650) is:
Fx = blades*m_c_local.at(i)/8/PI_/m_radius_local.at(i)
*pow(W/m_velocity_inf.at(i),2)
*((Cn*cos(theta)+Ct*sin(theta)/cos(delta)));From what I understand of the classical DMST formulation, I would have expected an extra 1/|cos(theta)| factor in there. I don’t see it here, and I don’t see it in the downwind equivalent either (~line 891). Am I missing where it comes in, or misunderstanding the formulation?
— 2. Upwind vs downwind (2.0.4a source, DData.cpp) —
Still in the same branch, the upwind update (~line 650-666) is:
u_old = u;
u = pow(u,2)+Fx;double CTT;
CTT = 4*u*(1-u);if (CTT>0.96*F)
{
u = (18*F-20-3*pow(fabs(CTT*(50-36*F)+12*F*(3*F-4)),0.5))/(36*F-50);
}if (u<=0) u=0.01;
if (u>=1) u=0.99;while the downwind update (~line 891-897) is:
Fx = blades*m_c_local.at(i)/8/PI_/m_radius_local.at(i)
*pow(W/m_velocity_equil.at(i),2)
*((Cn*cos(theta)+Ct*sin(theta)/cos(delta)));u2_old = u2;
u2 = pow(u2,2)+Fx;if (u2>=1) u2 = 0.99;
if (u2<=0) u2 = 0.01;The downwind branch doesn’t check CTT against the 0.96*F threshold and never goes through the closed-form correction – just the clamp to [0.01, 0.99]. I don’t understand why the two branches differ here.
Thanks for the time and for any help.
Hi Everyone,
I’m a PhD Student working on modeling a small VAWT for micro-generation (NACA0021, chors = 0.085, H = 1.5, R= 0.515), for which some experimental data is available, and I’m trying to set up a QBlade model of it (currently running 2.0.9.7 CE on Windows). While trying to understand the DMS solver better, I looked through the last publicly available source code (2.0.4a) and ran into two things I don’t quite understand.
While working through the classical DMST closure (Paraschivoiu 2002 with the Glauert correction) by hand for some streamtubes at higher TSR (from 3 to 5), I found cases where the aerodynamic CX(a) curve and the momentum CX(a) curve don’t seem to intersect anywhere in [0,1] – meaning no equilibrium would exist for that streamtube under the classical theory. I’m not sure yet whether that’s a mistake on my end or a genuine feature of the model in that regime, so I went to look at how QBlade’s DMS module (variable induction mode) handles this internally, using the last publicly available source code (2.0.4a). While there, I ran into two things I don’t quite understand.
— 1. Fx formula (2.0.4a source, DData.cpp) —
In the variable-induction branch (m_bVariable = true), the upwind Fx term (~line 650) is:
Fx = blades*m_c_local.at(i)/8/PI_/m_radius_local.at(i)
*pow(W/m_velocity_inf.at(i),2)
*((Cn*cos(theta)+Ct*sin(theta)/cos(delta)));
From what I understand of the classical DMST formulation, I would have expected an extra 1/|cos(theta)| factor in there. I don’t see it here, and I don’t see it in the downwind equivalent either (~line 891). Am I missing where it comes in, or misunderstanding the formulation?
— 2. Upwind vs downwind (2.0.4a source, DData.cpp) —
Still in the same branch, the upwind update (~line 650-666) is:
u_old = u;
u = pow(u,2)+Fx;
double CTT;
CTT = 4*u*(1-u);
if (CTT>0.96*F)
{
u = (18*F-20-3*pow(fabs(CTT*(50-36*F)+12*F*(3*F-4)),0.5))/(36*F-50);
}
if (u<=0) u=0.01;
if (u>=1) u=0.99;
while the downwind update (~line 891-897) is:
Fx = blades*m_c_local.at(i)/8/PI_/m_radius_local.at(i)
*pow(W/m_velocity_equil.at(i),2)
*((Cn*cos(theta)+Ct*sin(theta)/cos(delta)));
u2_old = u2;
u2 = pow(u2,2)+Fx;
if (u2>=1) u2 = 0.99;
if (u2<=0) u2 = 0.01;
The downwind branch doesn’t check CTT against the 0.96*F threshold and never goes through the closed-form correction – just the clamp to [0.01, 0.99]. I don’t understand why the two branches differ here.
Thanks for the time and for any help.
Quote from David on 24. August 2026, 15:16Hi,
thanks for looking into this in detail.
Your reading is correct: the old DMST implementation contained inconsistencies in the streamtube force formulation and in the upwind/downwind high-induction treatment.
These issues were recently fixed. Both rotor halves now use the same local C_t-based momentum Glauert closure, with a relaxed induction update.
The 2.0.4a source is therefore no longer representative of the revised implementation.
For reference, attached you find the most recent implementation of the DMST algorithm in QBlade.
Best regards,
David
Hi,
thanks for looking into this in detail.
Your reading is correct: the old DMST implementation contained inconsistencies in the streamtube force formulation and in the upwind/downwind high-induction treatment.
These issues were recently fixed. Both rotor halves now use the same local C_t-based momentum Glauert closure, with a relaxed induction update.
The 2.0.4a source is therefore no longer representative of the revised implementation.
For reference, attached you find the most recent implementation of the DMST algorithm in QBlade.
Best regards,
David
Uploaded files:- You need to login to have access to uploads.


