VSPAero and PDT correct use case

49 views
Skip to first unread message

Omer Kandemir

unread,
Mar 2, 2026, 8:13:39 AM (6 days ago) Mar 2
to OpenVSP
Hi everyone, 

I'm trying to correct CD0 value of VSPAero output by Parasite Drag Tool using python API. However, whenever I try to execute ParasiteDragAnaylsis just before VSPAero, VSPAero gives the following error:

"ERROR 1: Unable to create case file: C:/dev/null.vspaero
File: D:\a\OpenVSP\OpenVSP\src\geom_core\VSPAEROMgr.cpp"

 I believe it has something to do with CompGeom of ParasiteDrag interfering with VSPAero results. But I don't know how to avoid that. I have checked the group conversations but couldn't find something regarding that.  The script that I'm using for ParasiteDrag analysis is as follows: 

vsp.SetAnalysisInputDefaults('ParasiteDrag')
        cls.set_vsp_parasite_drag_set(parasite_drag_comps)
        if compute_geom:
            vsp.SetIntAnalysisInput("ParasiteDrag", "RecomputeGeom", [True])
            vsp.SetVSP3FileName('/dev/null')
            # comp_res_id = vsp.FindLatestResultsID( "Comp_Geom" )
            # print(comp_res_id)
            results = vsp.parse_results_object(vsp.ExecAnalysis("ParasiteDrag"))
            vsp.Update()
If I try to execute ParasiteDrag analysis after VSPAero, then the parasite drag results does not makes sense. Is there a way to tackle this issue? Thank you for your answers in advance. 

Brandon Litherland

unread,
Mar 2, 2026, 12:48:17 PM (5 days ago) Mar 2
to OpenVSP
I'm not sure what exactly you've done yet to track this down, but there are two different areas that you have to capture parasite drag tool parameters.  
The first is the PD tool variables themselves.  You'll find these in the Analysis Manager under "ParasiteDrag" and can see the different variables with vsp.GetAnalysisInputNames("ParasiteDrag") as so:

In [5]: vsp.GetAnalysisInputNames('ParasiteDrag')
Out[5]:
('AltLengthUnit',
 'Altitude',
 'DeltaTemp',
 'Density',
 'DynaVisc',
 'ExportSubCompFlag',
 'FileName',
 'FreestreamPropChoice',
 'GeomSet',
 'KineVisc',
 'LamCfEqnChoice',
 'LengthUnit',
 'Mach',
 'ModeID',
 'PresUnit',
 'Pressure',
 'Re_L',
 'RecomputeGeom',
 'RefFlag',
 'SpecificHeatRatio',
 'Sref',
 'TempUnit',
 'Temperature',
 'TurbCfEqnChoice',
 'UseModeFlag',
 'VelocityUnit',
 'Vinf',
 'WingID')

You'll want to pay special attention to the GeomSet or Set variables to ensure that the correct components are included in the analysis.  Oddly, the API echo of the input names shows "GeomSet" but the name shown if you pull up the Design Variable GUI and choose ParasiteDragSettings container, ParasiteDrag group, the name is "Set". Weird.  I'm not sure exactly if there are two instances of these settings in the API or not.  Meaning, I wonder if there is a SetParmVal option using ParasiteDragSettings vs setting them directly with the Analysis Manager.  Careful there, I suppose.

Secondly, are the component-assigned PD tool settings.  These are the variable you'll find in the PD tool as rows for each component such as the FF Equation, interference factor Q, percent laminar, etc. For each component in your model, there is a group called "ParasiteDragProps" with a list of parms that affect these settings.  These must be set using vsp.SetParmVal() on the component and not in the parasite drag tool settings.  It's easy to get tripped up with this differentiation but when you think about it, it makes sense to have component-specific settings kept under the geom and not in the analysis.

This may or may not help your case along but hopefully it will inform other users attempting to use the PD tool via the API.

Omer Kandemir

unread,
Mar 3, 2026, 9:44:20 AM (5 days ago) Mar 3
to OpenVSP
Hi Brandon,

Thank you for the quick reply. To clarify my setup :
  • I build aircraft components in Python (dataclasses for wing/fuse/etc.), then generate geometry via the OpenVSP Python API. (Which is quite similar to SUAVE approach)

  • Each component has an exposed2freeStream flag. If True, I put it into a VSP set that I name “ParasiteDrag” (so the PDT only includes those components).

  • Each component also stores its own PDT per-component properties (FF equation, Q, % laminar, etc.), which I set via SetParmVal() on the component under ParasiteDragProps (not in the analysis manager).

Then my sequence is:

  1. Run ParasiteDrag (setting VelocityUnit/LengthUnit/Sref/etc.).

  2. Immediately afterwards run VSPAEROComputeGeometry, where I create two sets (“Thin” and “Thick”) and feed them into the analysis inputs (GeomSet, ThinGeomSet).

If I run VSPAEROComputeGeometry alone (without ParasiteDrag beforehand), I get results consistent with the GUI.
If I run ParasiteDrag first, VSPAEROComputeGeometry fails to execute.


As far as "GeomSet" I know that it's taking the correct set which is  “ParasiteDrag”   set that I create in VSP object. 


I also share my ParasiteDrag object and the staticmethod that I use for  VSPAEROComputeGeometry   :


"""""""""""""""""""""""""""""""""""""""""""
@dataclass
class ParasiteDrag:
    FF_EQN: Dict[str,float] = field(default_factory=lambda:  { "FF_B_MANUAL": 0,"FF_B_SCHEMENSKY_BODY": 1,"FF_B_SCHEMENSKY_NACELLE": 2,
                "FF_B_HOERNER_STREAMBODY": 3,"FF_B_TORENBEEK": 4,"FF_B_SHEVELL": 5,
                "FF_B_COVERT": 6,"FF_B_JENKINSON_FUSE": 7,"FF_B_JENKINSON_WING_NACELLE": 8,
                "FF_B_JENKINSON_AFT_FUSE_NACELLE": 9,"FF_W_MANUAL": 0,"FF_W_EDET_CONV": 1,
                "FF_W_EDET_ADV": 2,"FF_W_HOERNER": 3,"FF_W_COVERT": 4,"FF_W_WILLIAMS": 5,
                "FF_W_KROO": 6,"FF_W_TORENBEEK": 7,"FF_W_DATCOM": 8,"FF_W_SCHEMENSKY_6_SERIES_AF": 9,
                "FF_W_SCHEMENSKY_4_SERIES_AF": 10,"FF_W_JENKINSON_WING": 11,"FF_W_JENKINSON_TAIL": 12,
                "FF_W_SCHEMENSKY_SUPERCRITICAL_AF": 13})
    CDp: float = 0
    excrescence: Dict[str,float] = field(default_factory=lambda: {"ExcresType":2,"ExcresVal":20})
    vsp_obj: VSP = None
    def __post_init__(self):
        self.set_excrescence_drag(self.excrescence)
    def get_parasite_drag(self,sref,speed,alt,first_val,speed_unit=vsp.V_UNIT_MACH,length_unit=vsp.LEN_M):
        """
       

        Parameters
        ----------
        sref : float
            wing reference area.
        speed : float
            freestream air speed, needs to be as the same unit as speed_unit variable.
        alt : float
            altitude in ft.
        first_val : boolean
            compute geom flag for OpenVSP, True for the initial parasite drag point, False for the remaining points .
        speed_unit : vsp.V_UNIT,optional
            speed_unit to be used for OpenVSP PDT. The default is vsp.V_UNIT_MACH.
        length_unit : vsp.V_UNIT, optional
            length_unit to be used for OpenVSP PDT. The default is vsp.LEN_M.

        Returns
        -------
        None. Calculates cDp (parasite drag)


        Uses component drag build up method via OpenVSP's PDT
        (https://vspu.larc.nasa.gov/training-content/chapter-3-model-analysis-in-openvsp/parasite-drag/)
        Based on form factor equations
        Each parasite drag component object has their own FF_EQN attribute, please check related objects.
        """
        # print(f"We are in parasite drag refArea,speed,altitude are: {sref,speed,alt}")
        self.set_parasite_drag_properties(self.FF_EQN,self.vsp_obj.parasite_drag_comps)
        self.set_vsp_parasite_drag_set(self.vsp_obj.parasite_drag_comps)
        # Reset default values to ensure values that have been read from a vsp file are used by default
        vsp.SetAnalysisInputDefaults('ParasiteDrag')
        cont_id = vsp.FindContainer("ParasiteDragSettings", 0 )
        # inputs that don't change during a sweep
        vsp.SetIntAnalysisInput("ParasiteDrag", "VelocityUnit", [speed_unit])
        if length_unit is not None:
            vsp.SetIntAnalysisInput("ParasiteDrag", "LengthUnit", [length_unit])
            vsp.SetParmVal(cont_id,"LengthUnit",'ParasiteDrag',length_unit)
        vsp.SetStringAnalysisInput("ParasiteDrag", "FileName", ["/dev/null"])
        if sref is not None:
            vsp.SetIntAnalysisInput("ParasiteDrag", "RefFlag", [0])
            vsp.SetDoubleAnalysisInput("ParasiteDrag", "Sref", [float(sref)])
            vsp.SetParmVal(cont_id,"Sref",'ParasiteDrag',float(sref))
        vsp.SetVSP3FileName('/dev/null')
        vsp.SetDoubleAnalysisInput("ParasiteDrag", "Vinf", [float(speed)])
        vsp.SetDoubleAnalysisInput("ParasiteDrag", "Altitude", [float(alt)])
        if first_val:

            vsp.SetIntAnalysisInput("ParasiteDrag", "RecomputeGeom", [True])
            first_val = False
        else:
            vsp.SetIntAnalysisInput("ParasiteDrag", "RecomputeGeom", [False])

        results = vsp.parse_results_object(vsp.ExecAnalysis("ParasiteDrag"))
        self.results = results
        self.get_wetted_areas(self.vsp_obj.parasite_drag_comps, results)
        self.CDp = results.Total_CD_Total[0]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""


""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@staticmethod
    def compute_vsp_aero_geom(thin_components,thick_components,compgeom_name = "VSPAEROComputeGeometry"):
        vsp.SetAnalysisInputDefaults(compgeom_name)
        thin_set_id = vsp.SET_FIRST_USER + 1
        thick_set_id = vsp.SET_FIRST_USER + 2
        vsp.SetSetName(thin_set_id,"Thin")
        vsp.SetSetName(thick_set_id,"Thick")
        # vsp.SetVSP3FileName('/dev/null')
        for thin_comp in thin_components:
            if thin_comp:
                vsp.SetSetFlag(thin_comp.vspID,thin_set_id,True)
        for thick_comp in thick_components:
            if thick_comp:
                vsp.SetSetFlag(thick_comp.vspID,thick_set_id,True)
        vsp.SetIntAnalysisInput(compgeom_name, "GeomSet", [thick_set_id])
        vsp.SetIntAnalysisInput(compgeom_name, "ThinGeomSet", [thin_set_id])
        cont_id = vsp.FindContainer("VSPAEROSettings", 0 )
        vsp.SetParmVal(cont_id,"ThinGeomSet",'VSPAERO',thin_set_id)
        vsp.SetParmVal(cont_id,"GeomSet",'VSPAERO',thick_set_id)
        vsp.Update()
        compgeom_resid = vsp.ExecAnalysis(compgeom_name)
        return compgeom_name

Brandon Litherland

unread,
Mar 4, 2026, 6:53:46 AM (4 days ago) Mar 4
to OpenVSP
Hmm.  I'd have to do some tests myself to see if I can get it to recreate the issue.  What VSP version are you using, out of curiosity?
VSPAEROComputeGeometry and CompGeom, for parasite drag, are two different analyses producing two different result IDs so they shouldn't conflict.  Furthermore, running the PD tool and compgeom shouldn't result in a new mesh component as a result.  It should be eliminated once PD is done with the result and has the values, I'd think.  So the resulting compgeom intersected mesh shouldn't be hanging around with inherited Set membership from the parents and getting added to VSPAEROComputeGeometry.  You could try storing your PD results that you care about to use them later, then try DeleteResult or DeleteAllResults which should clear anything hanging out in memory that could be affecting the VSPAERO job.  Without understanding exactly what's going on through testing, this is more of a sledgehammer solution than a correct fix.

Omer Kandemir

unread,
Mar 4, 2026, 7:42:35 AM (4 days ago) Mar 4
to OpenVSP
I'm using 3.46. PDT itself does not create a mesh component but If I'm not mistaken vsp.ComputeCompGeom creates a mesh component. I tried both  DeleteResult and DeleteAllResults but they did not work. 
Reply all
Reply to author
Forward
0 new messages