TAGGED: cad, ironpython, python-scripting, spaceclaim
-
-
September 17, 2025 at 1:39 am
vspenergyofficial
SubscriberHello,
I’m Surya Teja and I’m using SpaceClaim (2022 R1) for my parametric hydrodynamic optimization research. The broader goal is to connect SpaceClaim geometry with Python-based sampling and optimization, where:
SpaceClaim geometric parameters serve as design variables.
AQWA provides hydrodynamic outputs.
A custom Sci-ML adaptive learning algorithm (with backpropagation) guides the next parameter set based on an external objective function.
What I’ve tried so far:
Scripting (V21 API):
I attempted to draw my geometry idea directly with scripting.
As a beginner in SpaceClaim scripting, I wasn’t able to fully complete it.
Recorded Script option:
I manually created the geometry and recorded the steps into a script.
The generated script runs correctly in the original session.
However, when I copy/paste the script into a new session (new design, new console, new script file), the run breaks with errors.
I’ve tried known tips such as avoiding extra clicks and preferring index-based selections over SmartVariables, but the errors persist.
I even tried external help (AI chatbots, documentation), but most fixes turn out redundant or incorrect.
Where I’m stuck / my questions:
Is there a recommended way to make recorded scripts replayable in fresh sessions?
Should I instead rely on recorded blocks for robust rebuilds, since they are stored inside the
.scdocfile?If blocks are the safer method, how can I:
Test them safely by re-running them to check whether they break (if this is obvious, please confirm).
Access their parameters in Python for custom sampling under constraints.
Is there any best practice for combining SpaceClaim parameters with external optimization loops (Python + AQWA) without the workflow breaking?
I’m mainly looking for a repeatable and stable approach to:
Define geometry in SpaceClaim.
Expose parameters for optimization.
Safely integrate with Python + AQWA.
Any guidance, examples, or references would be greatly appreciated.
Thanks,
Surya TejaBelow is my recorded script, please test it and rectify the errors:
# Python Script, API Version = V21# Set Sketch PlanesectionPlane = Plane.PlaneXYresult = ViewHelper.SetSketchPlane(sectionPlane, Info1)# EndBlock# Set New Sketchresult = SketchHelper.StartConstraintSketching()# EndBlock# Sketch Circleorigin = Point2D.Create(M(0), M(0))result = SketchCircle.Create(origin, M(1.75))baseSel = SelectionPoint.Create(CurvePoint1)targetSel = SelectionPoint.Create(DatumLine1)result = Constraint.CreateCoincident(baseSel, targetSel)baseSel = SelectionPoint.Create(CurvePoint1)targetSel = SelectionPoint.Create(DatumPoint1)result = Constraint.CreateCoincident(baseSel, targetSel)# EndBlock# Solidify Sketchmode = InteractionMode.Solidresult = ViewHelper.SetViewMode(mode, Info2)# EndBlock# Translate Along X Handleselection = Body1direction = Direction.DirXoptions = MoveOptions()result = Move.Translate(selection, direction, M(-8), options, Info3)# EndBlock# Extrude 1 Faceselection = Face1options = ExtrudeFaceOptions()options.ExtrudeType = ExtrudeType.Addresult = ExtrudeFaces.Execute(selection, M(4), options, Info4)# EndBlock# Extrude 1 Faceselection = Face2options = ExtrudeFaceOptions()options.ExtrudeType = ExtrudeType.Addresult = ExtrudeFaces.Execute(selection, M(4), options, Info5)# EndBlock# Set Sketch Planeselection = Face2result = ViewHelper.SetSketchPlane(selection, Info6)# EndBlock# Set New Sketchresult = SketchHelper.StartConstraintSketching()# EndBlock# Sketch Circleorigin = Point2D.Create(M(0), M(0))result = SketchCircle.Create(origin, M(1))baseSel = Curve1targetSel = Curve2result = Constraint.CreateConcentric(baseSel, targetSel)# EndBlock# Set Sketch PlanesectionPlane = Plane.Create(Frame.Create(Point.Create(M(-8), M(0), M(-4)),-Direction.DirX,-Direction.DirZ))result = ViewHelper.SetSketchPlane(sectionPlane, Info7)# EndBlock# Set New Sketchresult = SketchHelper.StartConstraintSketching()# EndBlock# Sketch Linestart = Point2D.Create(M(0), M(0))end = Point2D.Create(M(0), M(6))result = SketchLine.Create(start, end)baseSel = SelectionPoint.Create(CurvePoint2)targetSel = SelectionPoint.Create(DatumLine2)result = Constraint.CreateCoincident(baseSel, targetSel)baseSel = SelectionPoint.Create(CurvePoint3)targetSel = SelectionPoint.Create(DatumLine2)result = Constraint.CreateCoincident(baseSel, targetSel)curveSelList = Curve3result = Constraint.CreateVertical(curveSelList)baseSel = CurvePoint2targetSel = Curve4result = Constraint.CreateMidpoint(baseSel, targetSel)baseSel = SelectionPoint.Create(Curve3)targetSel = SelectionPoint.Create(Curve4)result = Constraint.CreatePerpendicular(baseSel, targetSel)baseSel = SelectionPoint.Create(Curve3)targetSel = SelectionPoint.Create(Curve5)result = Constraint.CreateParallel(baseSel, targetSel)# EndBlock# Sketch Linestart = Point2D.Create(M(0), M(6))end = Point2D.Create(M(-8), M(6))result = SketchLine.Create(start, end)baseSel = SelectionPoint.Create(CurvePoint4)targetSel = SelectionPoint.Create(CurvePoint3)result = Constraint.CreateCoincident(baseSel, targetSel)baseSel = SelectionPoint.Create(Curve6)targetSel = SelectionPoint.Create(Curve3)result = Constraint.CreatePerpendicular(baseSel, targetSel)baseSel = SelectionPoint.Create(CurvePoint4)targetSel = SelectionPoint.Create(DatumLine2)result = Constraint.CreateCoincident(baseSel, targetSel)baseSel = SelectionPoint.Create(Curve6)targetSel = SelectionPoint.Create(DatumLine2)result = Constraint.CreatePerpendicular(baseSel, targetSel)baseSel = SelectionPoint.Create(Curve6)targetSel = SelectionPoint.Create(Curve4)result = Constraint.CreateParallel(baseSel, targetSel)# EndBlock# Solidify Sketchmode = InteractionMode.Solidresult = ViewHelper.SetViewMode(mode, Info8)# EndBlock# Detach FacesselBodies = Body2result = DetachFaces.Execute(selBodies)# EndBlock# System failure: cannot generate record script selection#Error = {0}Nullable object must have a value.# EndBlock# Sweep 1 Faceselection = Face3trajectories = Selection.Create(Curve3, Curve6)options = SweepCommandOptions()options.ExtrudeType = ExtrudeType.Addoptions.Select = Trueresult = Sweep.Execute(selection, trajectories, options, Info9)# EndBlock# Detach FacesselBodies = Body3result = DetachFaces.Execute(selBodies)# EndBlock# Delete Objectsselection = CurveFolder1result = Delete.Execute(selection)# EndBlock# Delete Selectionselection = Face4result = Delete.Execute(selection)# EndBlock# Translate Along Z Handleselection = Body3direction = Direction.DirZoptions = MoveOptions()result = Move.Translate(selection, direction, M(9), options, Info10)# EndBlock# Delete Selectionselection = Face5result = Delete.Execute(selection)# EndBlock# Extrude 1 Faceselection = Face6options = ExtrudeFaceOptions()options.ExtrudeType = ExtrudeType.Cutresult = ExtrudeFaces.Execute(selection, M(-1), options, Info11)# EndBlock# Detach FacesselBodies = Body4result = DetachFaces.Execute(selBodies)# EndBlock# Delete Objectsselection = Body5result = Delete.Execute(selection)# EndBlock# Create Blendselection = EdgeSelection.Create(Edge1, Edge2)options = LoftOptions()options.GeometryCommandOptions = GeometryCommandOptions()result = Loft.Create(selection, None, options, Info12)# EndBlock# Detach FacesselBodies = Body6result = DetachFaces.Execute(selBodies)# EndBlock# Rename 'Surface' to 'Left_Buoy_Bottom_Face'selection = Body2result = RenameObject.Execute(selection,"Left_Buoy_Bottom_Face")# EndBlock# Rename 'Surface' to 'Left_Buoy_Annulus'selection = Body6result = RenameObject.Execute(selection,"Left_Buoy_Annulus")# EndBlock# Rename 'Surface' to 'Left_Lower_Tube_Annulus'selection = Body7result = RenameObject.Execute(selection,"Left_Lower_Tube_Annulus")# EndBlock# Rename 'Surface' to 'Horizontal Tube_Annulus'selection = Body8result = RenameObject.Execute(selection,"Horizontal Tube_Annulus")# EndBlock# Rename 'Surface' to 'Left_Upper_Tube_Top_Face'selection = Body4result = RenameObject.Execute(selection,"Left_Upper_Tube_Top_Face")# EndBlock# Rename 'Surface' to 'Left_Upper_Tube_Annulus'selection = Body9result = RenameObject.Execute(selection,"Left_Upper_Tube_Annulus")# EndBlock# Rename 'Surface' to 'Left_Buoy_Top_Face'selection = Body10result = RenameObject.Execute(selection,"Left_Buoy_Top_Face")# EndBlock# Create Datum Planeselection = Edge3result = DatumPlaneCreator.Create(selection, False, Info13)# EndBlock# Mirrorselection = Body2mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info14)# EndBlock# Mirrorselection = Body6mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info15)# EndBlock# Mirrorselection = Body7mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info16)# EndBlock# Mirrorselection = Body8mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info17)# EndBlock# Mirrorselection = Body4mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info18)# EndBlock# Mirrorselection = Body9mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info19)# EndBlock# Mirrorselection = Body10mirrorPlane = DatumPlane1options = MirrorOptions()result = Mirror.Execute(selection, mirrorPlane, options, Info20)# EndBlock# Delete Objectsselection = DatumPlane1result = Delete.Execute(selection)# EndBlock# Rename 'Left_Buoy_Bottom_Face' to 'Right_Buoy_Bottom_Face'selection = Body11result = RenameObject.Execute(selection,"Right_Buoy_Bottom_Face")# EndBlock# Rename 'Left_Buoy_Annulus' to 'Right_Buoy_Annulus'selection = Body12result = RenameObject.Execute(selection,"Right_Buoy_Annulus")# EndBlock# Rename 'Left_Lower_Tube_Annulus' to 'Right_Lower_Tube_Annulus'selection = Body13result = RenameObject.Execute(selection,"Right_Lower_Tube_Annulus")# EndBlock# Rename 'Left_Upper_Tube_Top_Face' to 'Right_Upper_Tube_Top_Face'selection = Body14result = RenameObject.Execute(selection,"Right_Upper_Tube_Top_Face")# EndBlock# Rename 'Left_Upper_Tube_Annulus' to 'Right_Upper_Tube_Annulus'selection = Body15result = RenameObject.Execute(selection,"Right_Upper_Tube_Annulus")# EndBlock# Rename 'Left_Buoy_Top_Face' to 'Right_Buoy_Top_Face'selection = Body16result = RenameObject.Execute(selection,"Right_Buoy_Top_Face")# EndBlock# Save FileDocumentSave.Execute(r"C:\Users\kapar\Desktop\Research\U-tube_final.scdoc", FileSettings1)# EndBlock
-
First, let us try and debug your script section by section. You have a lot here (some of it is similar so we can skip the repetitive parts). You have some Metadata in your script, therefore it needs to be saved with a .scscript and not .py file extension. That is when anyone tries to run what you wrote it will not work because things like Info1 and CurvePoint1 will be saved into this file. Let us try and create this without using these.
Second, what does your final geometry look like? You say that you will run this with different parameters, it may be useful to define some parameters (such as circle radius, extrude length, etc.) at the beginning so we know where to find these and don’t need to search the whole file to find where to change it.
Now let’s look at the first part of your script. You create a circle with radius 1.75 meters, turn this into a surface body, and move the body 8 meters in the minus X-direction and then extrude this 4 meters in the Z-direction to create a cylinder. For the sketching the circle part it would simply look like:
# Sketch Circle
origin = Point2D.Create(M(0), M(0))
result = SketchCircle.Create(origin, M(1.75))
# EndBlock
In your script you have some constraints defined that do not need to be define (based upon what I see). These are using the baseSel and targetSel that are not defined. Simply deleting them works here. Also, we will need to remove the Info2 from the # Solidify Sketch block
Now onto the translating body block. Here you have the selection Body1. The filled in circle is a surface body. This is a selection that is not defined. We will create a body selection object and the block will look something like (also removed Info3):
# Translate Along X Handle
selection = BodySelection.Create(GetRootPart().Bodies[-1]) # -1 is used to get the last created body
direction = Direction.DirX
options = MoveOptions()
result = Move.Translate(selection, direction, M(-8), options)
# EndBlock
Similarly, in the extrude block, you have Face1 which is not defined. This is a selection that is not defined. We will create a face selection object and the block will look something like (also removed Info4):
# Extrude 1 Face
selection = FaceSelection.Create(GetRootPart().Bodies[-1].Faces[0])
options = ExtrudeFaceOptions()
options.ExtrudeType = ExtrudeType.Add
result = ExtrudeFaces.Execute(selection, M(4), options)
# EndBlock
From here on it is a bit more difficult as I do not know what your geometry is. You are creating a new sketch on Face2, but I am not sure which face is meant here. If it is the upper Z face you could use FaceSelection.Create(GetRootPart().Bodies[0].Faces[1]) or Face[0] if it is the negative Z face. And then you are creating a bunch of sketches that are constrained to the existing geometry. Whether you need these or not are to be determined. Later on you have a detach faces for Body2 and then there is some kind of error. Without knowing what your intent is here, I can not advise a way forward.
Remember debug it piece by piece. Even the best programmers can make mistakes, and divide and conquer is a good approach. Based upon that first little bit, try something like this:
# Python Script, API Version = V21
cylinderRad = M(1.75) # Radius of cylinder
offsetX = M(-8) # Offset in X direction
extrudeLength = M(4) # length of extrusion
circle2Rad = M(1) # radius of 2nd circle
# Set Sketch Plane
sectionPlane = Plane.PlaneXY
result = ViewHelper.SetSketchPlane(sectionPlane)
# EndBlock
# Sketch Circle
origin = Point2D.Create(M(0), M(0))
result = SketchCircle.Create(origin, cylinderRad)
# EndBlock
# Solidify Sketch
mode = InteractionMode.Solid
result = ViewHelper.SetViewMode(mode)
# EndBlock
# Translate Along X Handle
selection = BodySelection.Create(GetRootPart().Bodies[-1]) # -1 is used to get the last created body
direction = Direction.DirX
options = MoveOptions()
result = Move.Translate(selection, direction, offsetX, options)
# EndBlock
# Extrude 1 Face
selection = FaceSelection.Create(GetRootPart().Bodies[-1].Faces[0])
options = ExtrudeFaceOptions()
options.ExtrudeType = ExtrudeType.Add
result = ExtrudeFaces.Execute(selection, extrudeLength, options)
# EndBlock
# Set Sketch Plane
selection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[1])
result = ViewHelper.SetSketchPlane(selection)
# EndBlock
# Set New Sketch
result = SketchHelper.StartConstraintSketching()
# EndBlock
# Sketch Circle
origin = Point2D.Create(M(0), M(0))
result = SketchCircle.Create(origin, circle2Rad)
# EndBlock
One of the main issues here is that you said you intend to "copy/paste the script into a new session." Whether you use metadata or index selections, those are both tied to the model and will not work when you want to use them in a different model. With metadata, it's binary data, so there's no way to change them to fit a new model. With index selection type, at least you can attmept to use it in a new model, but you would still need to figure the different indices to use in a new model, which means you would need to carefully work through just about every line of the script, practically creating the script over again.
One way to make something reliably repeatable is to have the script create all the geometry from the beginning each time. So there is no problem with different selections when starting from some beginning model.
When using recording, think of it as a way to just get the base commands to work with, and you will need to highly modify to make something robust. To make a robust script, I suggest to use the return of one command to get the selections for the next command(s). Use functions/objects after the return of creation such as these in SpaceClaim:
result.CreatedPlanes
result.CreatedCurves
result.CreatedBodies
result.CreatedFaces
And others that get what was created.
You can test what's under each python object by typing dir(object) in the one-line-entry. Also, you can usually find .GetType() under most python objects to check the type.
To effectively use the result of each creation function as input to the next operation, you need to rethink the entire script design. You will not be able to make a robust script by doing the same things as you would normally create geometry in SpaceClaim. One big reason is that SpaceClaim is not history-based when not using block recording, so sketch entities are lost when you go to 3D mode, and your script doesn't know what sketch entities produced which 3D items. You'll need to use bottom-up methods of creation to track items you created. So that means: create curves, then faces, then bodies. There is more than one way to keep the curves when you go from sketch mode to 3D, but one way is to use "SketchHelper.LayoutCurves = True" so that it doesn't try to create a fill surface automatically after it goes from 2D sketch mode to 3D.
Refer to the following example:
The above script doesn't use metadata selections or even index selection, so the script will always work. At the end, I still had the faces and body entities stored to variables so I could place in a named selection.
I did choose to use "Repair > Missing Faces" to make face6, and this does not return the face created, so I just got last face in the list. This is not the best means of creation if you wanted to track face6 to place in a named selection. It may be better to create all the wireframe edges of the body, and Fill or Blend each surface instead of pulling the 4 edges like I did so that you can track more explicitly all 6 faces made from the fill or blend operation.
Also, it's probably best to turn off sketch constraints at "File > SpaceClaim Options > Advanced > Enable constraint based sketching (restart required)." Constrains are useful if you want to set dimensions and modify after the sketch is made. But usually with a script, such as intended to be used in an optimization, it is meant for the script to be run with each iteration, so each time the script will run with the new parameter values. These would be the 3 that are set at the beginning of this example script. So there is no modification after the geometry is created, and the sketch constraints are not needed. The constraints just add a lot of complexity to script, that's not needed in this case.
Hi,
I checked with the team, and it seems to be a very long and very involved forum post. Please see if you can create a support case with Ansys or try posting this query on developer forum as well.
Regards,
Ashish Khemka
- You must be logged in to reply to this topic.
- Project lines/edges into a face with the direction normal to the face
- No preview in explorer with scdox file
- Issues after installing new service pack 2024R1 (sp5)
- Add-in Error Excel
- Problems with loading my Discovery Mesh into Fluent
- Missing SubDivWrapper.dll
- Fileformats
- Discovery 2025r2 failed to initialize
- Spaceclaim problem
- Using SpaceClaim scripts vs recorded blocks for parametric optimization workflow
-
4177
-
1487
-
1363
-
1194
-
1021
© 2025 Copyright ANSYS, Inc. All rights reserved.