Parametric optimization with volume goal

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
CharlesM
Posts: 15
Joined: Thu Feb 02, 2023 4:14 pm

Parametric optimization with volume goal

Post by CharlesM »

Dear FreeCAD community,


I am trying to conduct volume driven parametric optimization using FreeCAD and Python. I am experiencing some problems, could you help me ?


Let's say we have a cube of side length = L , initially equal to 1. How could I create a python code that would :

1) Analyze the volume of the cube
2) Modify the driving parameter "L"
3) Stop when the goal volume is reached


I tried two things without getting the result I wanted :

1) Externally, with the following piece of code :

Code: Select all

import sys 
FREECADPATH = r'PATH\TO\FREECAD'
sys.path.append(FREECADPATH)

import FreeCAD, FreeCADGui as Gui, Part, PartDesign 
FreeCAD.openDocument(r'PATH\TO\DOCUMENT',True)

goal = FreeCAD.ActiveDocument.getObjectsByLabel("Body")[0]
vol = goal.Shape.Volume

obj = 100    #Goal volume

print(vol)
print(obj)

a = 1
if vol < obj : 
    while vol - obj < 5: 
        doc.getObject('Sketch').setDatum(9,App.Units.Quantity(a))
        a = a+1
        print(vol)      
else:  
    while vol - obj > 5:
        doc.getObject('Sketch').setDatum(9,App.Units.Quantity(a))
        a = a-1
        print(vol)

( I am quite new to FreeCAD, and I am unsure about wheter or not this is correct way (setDatum) to do what I want)



2) Inside the python console :

Code: Select all

body=FreeCAD.ActiveDocument.getObjectsByLabel("Body")[0]
>>> vol = body.Shape.Volume
>>> vol
0.9999999999999998
>>> # Gui.Selection.addSelection('learning','Body','Pad.Sketch.')
>>> # Gui.Selection.clearSelection()
>>> vol
0.9999999999999998
>>> body.recompute
<built-in method recompute of PartDesign.Body object at 0x00000265CF6F3C18>
>>> vol
0.9999999999999998
In both case, I was not able to change the volume, even though the dimensions of the cube changed in the user interface.

1mmvol.png
1mmvol.png (46.53 KiB) Viewed 542 times
100mmvol.png
100mmvol.png (52.02 KiB) Viewed 542 times









Code: Select all

OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 0.20.2.29177 +426 (Git)
Build type: Release
Branch: (HEAD detached from 0.20.2)
Hash: 930dd9a76203a3260b1e6256c70c1c3cad8c5cb8
Python 3.8.10, Qt 5.15.2, Coin 4.0.1, Vtk 8.2.0, OCC 7.6.3
Locale: French/France (fr_FR)
Last edited by CharlesM on Thu Feb 02, 2023 5:57 pm, edited 1 time in total.
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Parametric optimization with volume goal

Post by openBrain »

CharlesM wrote: Thu Feb 02, 2023 5:06 pm 2) Inside the python console :

Code: Select all

body=FreeCAD.ActiveDocument.getObjectsByLabel("Body")[0]
>>> vol = body.Shape.Volume
>>> vol
0.9999999999999998
>>> # Gui.Selection.addSelection('learning','Body','Pad.Sketch.')
>>> # Gui.Selection.clearSelection()
>>> vol
0.9999999999999998
>>> body.recompute
<built-in method recompute of PartDesign.Body object at 0x00000265CF6F3C18>
>>> vol
0.9999999999999998
2 mistakes here.

* to recompute, call

Code: Select all

body.recompute
with the parentheses

* you can't use an intermediate variable as it will store the value but loose the link. You have to evaluate

Code: Select all

body.Shape.Volume
after each modification
CharlesM
Posts: 15
Joined: Thu Feb 02, 2023 4:14 pm

Re: Parametric optimization with volume goal

Post by CharlesM »

Dear openBrain,


Thank you for your answer.


The following code works :

Code: Select all

goal = 1000000
FreeCAD.ActiveDocument.Sketch.setDatum('L',1)
cont = 1 
while True : 
    FreeCAD.ActiveDocument.Sketch.setDatum('L',cont)
    FreeCAD.ActiveDocument.recompute()
    print(FreeCAD.ActiveDocument.Body.Shape.Volume)
    cont = cont+1
    if goal - FreeCAD.ActiveDocument.Body.Shape.Volume  <= 1: 
        break
print(FreeCAD.ActiveDocument.Body.Shape.Volume)
edwilliams16
Veteran
Posts: 3180
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Parametric optimization with volume goal

Post by edwilliams16 »

You method is very slow and not robust. One simple root finder you could implement is the bisection method. https://en.wikipedia.org/wiki/Bisection_method
You start with two values of your datum, one too large, one too small and successively reduce the interval in which the correct value lies. Stop when you have reached the desired accuracy.
Post Reply