Shouldered "T" piece - issues with numerical stability- work arounds?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
JF2791
Posts: 19
Joined: Fri Jan 22, 2021 2:52 pm

Shouldered "T" piece - issues with numerical stability- work arounds?

Post by JF2791 »

I'm trying to produce a model of a reducing shouldered "T" piece as shown here :- https://www.nero.co.uk/Catalogue/Fittin ... ducing-Tee.

Depending on the parameters I use, the code sometimes produces the correct model, other times the BRep screws
up. I can't find a pattern to the failure, so I wrote a test program that loops over the parameters. It produces a random
pattern of failure such that I suspect a serious bug (or bugs) in the system. I'm using 0.19.

Are there any workarounds for now?

The code, and one part of the table of success/failures, follows:-

Code: Select all

import Part
from FreeCAD import Base
from FreeCAD import Vector

Delta = 1.0

def CentredBox ( Length, Width, Height, Offset=Vector(0,0,0) ) :
  Box = Part.makeBox ( Length, Width, Height, Vector ( -Length/2, -Width/2, -Height/2 ) + Offset )
  return Box

def CentredCylinder ( Radius, Height, Offset=Vector(0,0,0) ) :
  return Part.makeCylinder ( Radius, Height, Vector ( 0, 0, -Height/2 ) + Offset )

def CreateMold ( StraightLength, StraightRadius, SideLength, SideRadius, FilletRadius ) :

  TubeLength = SideLength - StraightRadius
  MainLength = max ( StraightLength, FilletRadius*2 + SideRadius*2 )

  Width  = StraightRadius*2 + FilletRadius*4 + TubeLength*2 + Delta
  Depth  = max ( StraightRadius, SideRadius ) * 2 + FilletRadius*4 + Delta
  Height = MainLength + FilletRadius*2 + Delta

  Block = CentredBox ( Width, Depth, Height )
  Hole  = CentredCylinder ( StraightRadius, Height )

  Block = Block.cut ( Hole )

  Side = CentredCylinder ( SideRadius, Width, Vector(0,0,Width/2) )
  Side.rotate ( Vector(0,0,0), Vector(0,1,0), 90 )

  Block = Block.cut ( Side )

  Block = Block.makeFillet ( FilletRadius, Block.Edges )

  return Block

def CreateShoulderedTeePiece ( StraightLength, StraightRadius, SideLength, SideRadius, FilletRadius ) :

  Mold = CreateMold (  StraightLength, StraightRadius, SideLength, SideRadius, FilletRadius )

  Radius = max ( StraightRadius, SideRadius )

  Block = CentredBox ( SideLength*2, Radius*2+Delta, StraightLength )

  return Block.cut ( Mold )

def Test ( ) :

  StraightLength =  100
  SideLength     =   50

  for FilletRadius in range (1,20) :
    print ( "FilletRadius = ", FilletRadius )
    for StraightRadius in range (5,20) :
      Line = "    "
      for SideRadius in range(5,20) :
         if SideRadius <= StraightRadius :
           try :
             Body = CreateMold (  StraightLength, StraightRadius, SideLength, SideRadius, FilletRadius )
             Line += " __ "
           except :
             Body = CentredBox ( 10, 10, 10 )
             Line += " Er " 
         else :
           Line += "    "
      print ( Line )

  return Body

if __name__ == "__main__" :  

#  Test()  # Shows the problems, but takes a LONG time to run

  import ImportGui

  doc = FreeCAD.newDocument()
  
  Body = CreateShoulderedTeePiece ( 100, 20, 50, 18, 20 )
  Part.show ( Body )

  Gui.activeDocument().activeView().viewIsometric()
  Gui.activeDocument().activeView().setCameraType("Perspective")

  doc.recompute()
  Gui.SendMsgToActiveView("ViewFit")

Code: Select all

21:59:27  FilletRadius =  19
21:59:27       Er                                                         
21:59:27       Er  Er                                                     
21:59:27       Er  __  Er                                                 
21:59:27       Er  __  __  Er                                             
21:59:27       Er  __  __  __  Er                                         
21:59:27       __  Er  __  __  __  Er                                     
21:59:27       __  __  __  __  __  __  Er                                 
21:59:27       Er  __  Er  __  __  __  __  Er                             
21:59:27       __  __  __  Er  Er  __  __  __  Er                         
21:59:27       __  __  __  __  __  __  __  __  __  Er                     
21:59:27       __  Er  __  __  __  __  __  Er  Er  __  Er                 
21:59:27       __  __  __  __  __  __  __  Er  Er  __  __  Er             
21:59:27       __  __  Er  __  __  __  __  Er  Er  Er  __  __  Er         
21:59:27       __  __  Er  __  __  __  __  Er  Er  Er  __  __  __  Er     
21:59:27       __  __  __  __  __  __  __  Er  Er  Er  Er  __  __  __  Er 
kisolre
Veteran
Posts: 4166
Joined: Wed Nov 21, 2018 1:13 pm

Re: Shouldered "T" piece - issues with numerical stability- work arounds?

Post by kisolre »

Can those parameter combinations be done by hand? Like StraighhtRadius=5, SideRadius=5, FiillletRadiius=20 ? Not seeing all the tools that make the result is hard to visualize just from code for me...
JF2791
Posts: 19
Joined: Fri Jan 22, 2021 2:52 pm

Re: Shouldered "T" piece - issues with numerical stability- work arounds?

Post by JF2791 »

Kisolre, "By hand" if you mean by constructing the part in the GUI, I have no idea, I only use the
programming interface. If by calling the function with those parameters, then yes, it fails. That is
how I started. I wanted to find out which parameters failed in order to spot the pattern. I failed,
hence writing the loops. Now I know there is no easy pattern.

Can't you run my Python code? As far as I'm aware I have shown the complete program as run on
my system after starting FreeCAD.
kisolre
Veteran
Posts: 4166
Joined: Wed Nov 21, 2018 1:13 pm

Re: Shouldered "T" piece - issues with numerical stability- work arounds?

Post by kisolre »

My thought was do you expect those combinations to work? How should the result look like?
I ran the code as it is and it produces the desired T-shape. But when both pipe radii are the same there is no single contour for the fillet to work with - there is an sharp edge in the middle. So this is one reason to break. line 57 - " if SideRadius <= StraightRadius " should be " if SideRadius < StraightRadius : ". This should get rid of the diagonal "Er" case.
Could you strip the code to just creates the different tools without applying any boolean operations for easy visualization of what is going on?
JF2791
Posts: 19
Joined: Fri Jan 22, 2021 2:52 pm

Re: Shouldered "T" piece - issues with numerical stability- work arounds?

Post by JF2791 »

Some parameter values where both pipe radii are the same do work. For instance:-

Code: Select all

  Mold = CreateMold               ( 100, 8, 50, 8, 6 )
  Tee  = CreateShoulderedTeePiece ( 100, 8, 50, 8, 6 )

  Mold.translate ( Vector ( 0, 40, 0 ) )
  Body = Mold.fuse ( Tee )
       
  Part.show ( Body )
That also splits the code out.

CreateMold cuts two cylinders out of a box and fillets it. The calculations just make sure the box is big enough to take all
the incidental unused fillets.
Post Reply