View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0003191 | FreeCAD | Bug | public | 2017-09-17 15:12 | 2017-10-18 12:11 |
| Reporter | KarenRei | Assigned To | wmayer | ||
| Priority | normal | Severity | major | Reproducibility | always |
| Status | closed | Resolution | fixed | ||
| Product Version | 0.17 | ||||
| Fixed in Version | 0.17 | ||||
| Summary | 0003191: Readily reproducible memory leak - FreeCAD doesn't reclaim memory on object deletion / project close. | ||||
| Description | As in the summary. Deleting objects and closing projects doesn't free memory. Eventually FreeCAD will run the system out of memory when you keep repeating the same workflow. | ||||
| Steps To Reproduce | 1. Save the attached .dae file in /tmp 2. Run the attached python workflow in the console (you'll see some errors at the end due to a different bug related to unicode, but they don't matter) 3. Note the memory usage in top. 4. Close the project (without closing FreeCAD) and go back to step 2. Each time, on my system at least, it consumes an additional ~ 10% memory. And right now I'm using a rather simplified model. In addition to closing projects not freeing memory, manually deleting individual objects doesn't appear to free memory either. The only thing that ever seems to get the memory back is closing and restarting FreeCAD. | ||||
| Additional Information | OS: "Fedora release 24 (Twenty Four)" Word size of OS: 64-bit Word size of FreeCAD: 64-bit Version: 0.17.12122 (Git) Build type: Unknown Branch: master Hash: 501729a84cd0aeef0ae2fcf24cc832eafaf0fa13 Python version: 2.7.13 Qt version: 4.8.7 Coin version: 3.1.3 OCC version: 6.8.0.oce-0.17 Locale: Icelandic/Iceland (is_IS) | ||||
| Tags | memory leak | ||||
| FreeCAD Information | |||||
|
|
fem.py (7,235 bytes)
import importDAE, Part, ObjectsFem, Fem, FemGmshTools, FemGui, FemToolsCcx
PRESSURE_MODE = 1
MAX_DEPTH = 8.0
HEIGHT = 6.48
GROUND_DENSITY = 1500.0
GMSH_RES_METERS = 2.0
PRESSURE_LAYERS = 100
importDAE.open(u"/tmp/tmp.dae")
doc = FreeCAD.getDocument("tmp")
gui_doc = Gui.getDocument("tmp")
mesh = doc.getObject("Mesh")
ground = doc.getObject("Mesh001")
Gui.SendMsgToActiveView("ViewFit")
print "Object loaded. Making shape..."
part = doc.addObject("Part::Feature", "Hús part")
shape_tmp = Part.Shape()
shape_tmp.makeShapeFromMesh(mesh.Mesh.Topology, 0.100000)
part.Shape = shape_tmp
part.purgeTouched()
delete shape_tmp
# solidify
print "Solidifying..."
solid_tmp = part.Shape
solid_tmp = Part.Solid(solid_tmp)
solid_part = doc.addObject("Part::Feature", "Hús solid part")
solid_part.Label = "Hús solid part"
solid_part.Shape = solid_tmp
delete solid_tmp
# refining
print "Refining..."
refined_part = doc.addObject("Part::Feature", "Hús refined part")
refined_part.Shape = solid_part.Shape.removeSplitter()
# analysis
analysis_object = ObjectsFem.makeAnalysis("Analysis")
FemGui.setActiveAnalysis(doc.Analysis)
# gmsh
print "Computing gmsh..."
gmsh = ObjectsFem.makeMeshGmsh('Hús FEM')
gmsh.Part = refined_part
gmsh.CharacteristicLengthMax = 1000.0 * GMSH_RES_METERS
gmsh.CharacteristicLengthMin = 0.0
gmsh_mesh = FemGmshTools.FemGmshTools(gmsh)
error = gmsh_mesh.create_mesh()
print error
doc.Analysis.Member += [gmsh]
doc.recompute()
# solver
print "Creating solver..."
solver_object = ObjectsFem.makeSolverCalculix("CalculiX")
solver_object.GeometricalNonlinearity = 'linear'
solver_object.ThermoMechSteadyState = True
solver_object.MatrixSolverType = 'default'
solver_object.IterationsControlParameterTimeUse = False
doc.Analysis.Member = doc.Analysis.Member + [solver_object]
# material
print "Adding material..."
material_object = ObjectsFem.makeMaterialSolid("SolidMaterial")
mat = material_object.Material
mat['Name'] = "Pumicecrete"
mat['YoungsModulus'] = "5000 MPa"
mat['PoissonRatio'] = "0.17"
mat['Density'] = "1000 kg/m^3"
material_object.Material = mat
doc.Analysis.Member = doc.Analysis.Member + [material_object]
# bounding
print "Bounding..."
MIN_X = 9999999999999.9
MAX_X = -9999999999999.9
MIN_Y = 9999999999999.9
MAX_Y = -9999999999999.9
MIN_Z = 9999999999999.9
MAX_Z = -9999999999999.9
for vertex in refined_part.Shape.Vertexes:
if vertex.X > MAX_X:
MAX_X = vertex.X
if vertex.X < MIN_X:
MIN_X = vertex.X
if vertex.Y > MAX_Y:
MAX_Y = vertex.Y
if vertex.Y < MIN_Y:
MIN_Y = vertex.Y
if vertex.Z > MAX_Z:
MAX_Z = vertex.Z
if vertex.Z < MIN_Z:
MIN_Z = vertex.Z
SCALAR_X = MAX_X - MIN_X
SCALAR_Y = MAX_Y - MIN_Y
SCALAR_Z = (MAX_Z - MIN_Z) / HEIGHT
# fixed_constraint
print "Adding anchors..."
fixed_constraint = ObjectsFem.makeConstraintFixed("Anchors")
keys = []
for face_id in range(len(refined_part.Shape.Faces)):
face = refined_part.Shape.Faces[face_id]
z = (face.CenterOfMass.z - MIN_Z) / SCALAR_Z
if z < 2.7 and face.normalAt(0, 0)[2] < -0.9:
keys.append( (refined_part, "Face%d" % (face_id + 1)) )
fixed_constraint.References = keys
doc.Analysis.Member = doc.Analysis.Member + [fixed_constraint]
def sign(p0, p1, p2):
return (p0[0] - p2[0]) * (p1[1] - p2[1]) - (p1[0] - p2[0]) * (p0[1] - p2[1])
def point_in_triangle(p0, p1, p2, x, y):
pt = (x, y)
b1 = sign(pt, p0, p1) < 0.0
b2 = sign(pt, p1, p2) < 0.0
b3 = sign(pt, p2, p0) < 0.0
return (b1 == b2) & (b2 == b3)
def distance(x0, y0, x1, y1):
return ((x0-x1)**2 + (y0-y1)**2)**0.5
def ground_height(x, y):
for facet in ground.Mesh.Facets:
p = []
for i in facet.Points:
p.append( ((i[0] - MIN_X) / SCALAR_X, (i[1] - MIN_Y) / SCALAR_Y, (i[2] - MIN_Z) / SCALAR_Z) )
if point_in_triangle(p[0], p[1], p[2], x, y):
break
d0 = distance(x, y, p[0][0], p[0][1])
d1 = distance(x, y, p[1][0], p[1][1])
d2 = distance(x, y, p[2][0], p[2][1])
sum = (d0 + d1 + d2)
z = (d0 * p[0][2] + d1 * p[1][2] + d2 * p[2][2]) / sum
# print x, y, " : ", p[0][2], p[1][2], p[2][2], " : ", d0, d1, d2, " : ", z
return z
print "Adding pressures..."
if PRESSURE_MODE:
# pressure_constraint
keys = []
for i in range(PRESSURE_LAYERS):
keys.append([])
for face_id in range(len(refined_part.Shape.Faces)):
face = refined_part.Shape.Faces[face_id]
average_depth = 0.0
for vertex in face.Vertexes:
x = (vertex.X - MIN_X) / SCALAR_X
y = (vertex.Y - MIN_Y) / SCALAR_Y
z = (vertex.Z - MIN_Z) / SCALAR_Z
ground_z = ground_height(x, y)
depth = ground_z - z
# print ground_z, z, depth
if depth > 0:
average_depth += depth
average_depth /= len(face.Vertexes)
if average_depth > 0.0:
# print "Adding key: %d %f to %d" % (face_id + 1, average_depth, int(round(average_depth / MAX_DEPTH * len(keys))))
keys[int(round(average_depth / MAX_DEPTH * len(keys)))].append( (refined_part, "Face%d" % (face_id + 1)) )
for key_id in range(len(keys)):
if len(keys[key_id]) == 0:
continue
depth = key_id * MAX_DEPTH / len(keys)
# print "%d) Adding pressures for %f: " % (key_id, depth), keys[key_id]
pressure = (9.81 * GROUND_DENSITY * depth) / 1000000.0
pressure_constraint = ObjectsFem.makeConstraintPressure("Pressure %0.4f" % pressure)
pressure_constraint.References = keys[key_id]
pressure_constraint.Pressure = pressure
pressure_constraint.Reversed = False
doc.Analysis.Member = doc.Analysis.Member + [pressure_constraint]
#break
else:
# ATH: ekki tilbúið!
for key_id in range(len(keys)):
if len(keys[key_id]) == 0:
continue
depth = key_id * MAX_DEPTH / len(keys)
force_per_m2 = (9.81 * GROUND_DENSITY * depth)
m2_on_z = 0# ATH
force = force_per_m2 / m2_on_z
force_constraint = ObjectsFem.makeConstraintForce("Force %0.0f" % force)
force_constraint.References = keys[key_id]
force_constraint.Force = force
force_constraint.Reversed = False
force_constraint.Direction = (refined_part, [nafn]) # ATH
doc.Analysis.Member = doc.Analysis.Member + [force_constraint]
print "Pressures added."
## View object
#femmesh_obj = doc.addObject('Fem::FemMeshObject', 'FEM view')
#femmesh_obj.FemMesh = gmsh
#doc.Analysis.Member = doc.Analysis.Member + [femmesh_obj]
# run the analysis
FemGui.setActiveAnalysis(doc.Analysis)
fea = FemToolsCcx.FemToolsCcx()
fea.update_objects()
message = fea.check_prerequisites()
if not message:
fea.reset_all()
fea.run()
fea.load_results()
else:
FreeCAD.Console.PrintError("Houston, we have a problem! {}\n".format(message)) # in report view
print("Houston, we have a problem! {}\n".format(message)) # in python console
# run the analysis
for m in analysis_object.Member:
if m.isDerivedFrom('Fem::FemResultObject'):
result_object = m
break
gui_doc.getObject("Mesh001").Visibility = False
gui_doc.getObject("Mesh").Visibility = False
gui_doc.getObject("Hús part").Visibility = False
gui_doc.getObject("Hús solid part").Visibility = False
gui_doc.getObject("Hús refined part").Visibility = False
gmsh.ViewObject.setNodeDisplacementByVectors(result_object.NodeNumbers, result_object.DisplacementVectors)
gmsh.ViewObject.applyDisplacement(10)
|
|
|
Added forum thread: https://forum.freecadweb.org/viewtopic.php?f=8&t=24692 |
|
|
Looks like the observed memory leak was caused by the tree view which is fixed now. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2017-09-17 15:12 | KarenRei | New Issue | |
| 2017-09-17 15:12 | KarenRei | File Added: tmp.dae | |
| 2017-09-17 15:12 | KarenRei | File Added: fem.py | |
| 2017-09-30 11:27 | Kunda1 | Steps to Reproduce Updated | |
| 2017-09-30 11:28 | Kunda1 | Tag Attached: memory leak | |
| 2017-09-30 11:28 | Kunda1 | Tag Attached: #post-to-forum | |
| 2017-09-30 11:31 | Kunda1 | Summary | Readily reproducable memory leak - FreeCAD doesn't reclaim memory on object deletion / project close. => Readily reproducible memory leak - FreeCAD doesn't reclaim memory on object deletion / project close. |
| 2017-09-30 11:34 | Kunda1 | Note Added: 0010216 | |
| 2017-09-30 11:34 | Kunda1 | Tag Detached: #post-to-forum | |
| 2017-09-30 11:36 | Kunda1 | Relationship added | related to 0003025 |
| 2017-10-18 12:11 | wmayer | Assigned To | => wmayer |
| 2017-10-18 12:11 | wmayer | Status | new => closed |
| 2017-10-18 12:11 | wmayer | Resolution | open => fixed |
| 2017-10-18 12:11 | wmayer | Fixed in Version | => 0.17 |
| 2017-10-18 12:11 | wmayer | Note Added: 0010316 |
FreeCAD