[Help] Goal seek macro
[Help] Goal seek macro
Could somebody help creating a "goal seek" macro?
The idea is that you have a design and in it a parameter that needs to be adjusted (for example the internal volume of a glass cup) to a certain value (250ml) by adjusting some parameters. I expect that the rough (initial) design will require adjusting multiple parameters, but to get an exact result only one parameter should be tweaked at the end. My idea so far it to use two (probably selectable) DynamicData objects with three properties with predefined names  Parameter, Result , Goal. One uses Parameter in the design (Body.Pad.Height), sets Result to desired resulting parameter (Body.Shape.Volume) inputs the desired value in the Goal and runs the macro. The macro should change the value of the Parameter and recompute until Result reaches Goal within a threshold. Probably some other parameters might be required (Threshold, MaxSteps, MaxStep, StarChangeDirection, ...)
What I need is just a framework to access the data and I should be able to work it out from there.
The idea is that you have a design and in it a parameter that needs to be adjusted (for example the internal volume of a glass cup) to a certain value (250ml) by adjusting some parameters. I expect that the rough (initial) design will require adjusting multiple parameters, but to get an exact result only one parameter should be tweaked at the end. My idea so far it to use two (probably selectable) DynamicData objects with three properties with predefined names  Parameter, Result , Goal. One uses Parameter in the design (Body.Pad.Height), sets Result to desired resulting parameter (Body.Shape.Volume) inputs the desired value in the Goal and runs the macro. The macro should change the value of the Parameter and recompute until Result reaches Goal within a threshold. Probably some other parameters might be required (Threshold, MaxSteps, MaxStep, StarChangeDirection, ...)
What I need is just a framework to access the data and I should be able to work it out from there.
 Attachments

 GoalSeekTest001.FCStd
 (9.39 KiB) Downloaded 33 times
Re: [Help] Goal seek macro
The main problem for such an algorithm is the number of ways a model can trigger an error when trying to compute it with 'random' values.
May we consider that we will only use positive values as parameter ?
May we consider that we will only use positive values as parameter ?
Re: [Help] Goal seek macro
I discovered scipy python package recently.
There is an optimization tool that can do that, even with multiple variables.
My math knowledge is a bit low to fully understand this tool, but I used it successfully to compute minimal curvature for CurvesWB BlendCurve.
There is an optimization tool that can do that, even with multiple variables.
My math knowledge is a bit low to fully understand this tool, but I used it successfully to compute minimal curvature for CurvesWB BlendCurve.
Re: [Help] Goal seek macro
If you can install python.scipy, this little script seems to work :
Code: Select all
import FreeCAD
from scipy.optimize import minimize
doc1 = FreeCAD.getDocument('GoalSeekTest001')
o1 = doc1.getObject('dd')
o2 = doc1.getObject('dd001')
def compute(value):
o1.ddParameter = value[0]
doc1.recompute()
return abs(o2.ddGoal.Value  o2.ddResult.Value)
res = minimize(compute, 1, method='NelderMead', options={"maxiter": 2000, "disp": True})
print("For Height = {}, Volume = {}".format(o1.ddParameter, o2.ddResult))

 Posts: 529
 Joined: Fri Sep 18, 2020 5:40 pm
Re: [Help] Goal seek macro
Scipy is awesome, definitely the right way. You can even tell it to respect bounds on the parameters (i.e max and min value)
by changing method to e.g "LBFGSB" and setting the bounds parameter to a list of (min, max) tuples.
Re: [Help] Goal seek macro
Looks like it comes with the latest Windows LibPack (12.4.2) so the macro runs here and is Awesome \
Here is a little revised script and I need it to brake when the recompute fails. But clearly this is not the way
Code: Select all
import FreeCAD
from scipy.optimize import minimize
sel = Gui.Selection.getSelectionEx()
if len(sel)!=2:
raise Exception("Select 2 DD objects  Parameter and Goal")
o1=sel[0].Object
o2=sel[1].Object
def compute(value):
o1.ddParameter = value[0]
print(o1.ddParameter)
if not(App.ActiveDocument.recompute()):
brake
return abs(o2.ddGoal.Value  o2.ddResult.Value)
res = minimize(compute, o1.ddParameter, method='NelderMead', options={"maxiter": 100, "disp": True})
print("For Height = {}, Volume = {}".format(o1.ddParameter, o2.ddResult))
 Attachments

 GoalSeekTest002.FCStd
 (581.28 KiB) Downloaded 64 times
Re: [Help] Goal seek macro
Here is another example calculating the internal volume of a cup, 3d printed in Vase mode with wall thickness 0.8mm.
.
.
 Attachments

 GoalSeekTest003.FCStd
 (690.64 KiB) Downloaded 44 times

 Veteran
 Posts: 1349
 Joined: Thu Sep 24, 2020 10:31 pm
 Location: Hawaii
 Contact:
Re: [Help] Goal seek macro
The minimization may work better usingdef compute(value):
o1.ddParameter = value[0]
doc1.recompute()
return abs(o2.ddGoal.Value  o2.ddResult.Value)
Code: Select all
return (o2.ddGoal.Value  o2.ddResult.Value)**2
Re: [Help] Goal seek macro
Yes, it definitely takes less iterations.