[Mesh] Add unit tests for NASTRAN reader

Also make some minor deprecation and verbosity cleanups to the Mesh unit
test cases.
This commit is contained in:
Chris Hennes
2021-09-25 16:05:19 -05:00
parent 63369a9c38
commit ba5adca79b
5 changed files with 155 additions and 18 deletions

View File

@@ -12,6 +12,7 @@ try:
except Exception:
import thread
from os.path import join
#---------------------------------------------------------------------------
# define the functions to test the FreeCAD mesh module
@@ -167,7 +168,7 @@ class MeshGeoTestCases(unittest.TestCase):
f1 = planarMeshObject.Facets[0]
f2 = planarMeshObject.Facets[1]
res=f1.intersect(f2)
self.failUnless(len(res) == 0)
self.assertTrue(len(res) == 0)
def testIntersection2(self):
@@ -182,7 +183,7 @@ class MeshGeoTestCases(unittest.TestCase):
f2 = planarMeshObject.Facets[1]
# does definitely NOT intersect
res=f1.intersect(f2)
self.failUnless(len(res) == 0)
self.assertTrue(len(res) == 0)
class PivyTestCases(unittest.TestCase):
def setUp(self):
@@ -208,11 +209,11 @@ class PivyTestCases(unittest.TestCase):
rp.setRay(coin.SbVec3f(-16.05,16.0,16.0),coin.SbVec3f(0,-1,0))
rp.apply(view.getSoRenderManager().getSceneGraph())
pp=rp.getPickedPoint()
self.failUnless(pp != None)
self.assertTrue(pp != None)
det=pp.getDetail()
self.failUnless(det.getTypeId() == coin.SoFaceDetail.getClassTypeId())
self.assertTrue(det.getTypeId() == coin.SoFaceDetail.getClassTypeId())
det=coin.cast(det,str(det.getTypeId().getName()))
self.failUnless(det.getFaceIndex() == 1)
self.assertTrue(det.getFaceIndex() == 1)
def testPrimitiveCount(self):
if not FreeCAD.GuiUp:
@@ -231,8 +232,8 @@ class PivyTestCases(unittest.TestCase):
view.setAxisCross(False)
pc=coin.SoGetPrimitiveCountAction()
pc.apply(view.getSceneGraph())
self.failUnless(pc.getTriangleCount() == 2)
#self.failUnless(pc.getPointCount() == 6)
self.assertTrue(pc.getTriangleCount() == 2)
#self.assertTrue(pc.getPointCount() == 6)
def tearDown(self):
#closing doc
@@ -243,15 +244,15 @@ class PivyTestCases(unittest.TestCase):
def loadFile(name):
#lock.acquire()
mesh=Mesh.Mesh()
FreeCAD.Console.PrintMessage("Create mesh instance\n")
#FreeCAD.Console.PrintMessage("Create mesh instance\n")
#lock.release()
mesh.read(name)
FreeCAD.Console.PrintMessage("Mesh loaded successfully.\n")
#FreeCAD.Console.PrintMessage("Mesh loaded successfully.\n")
def createMesh(r,s):
FreeCAD.Console.PrintMessage("Create sphere (%s,%s)...\n"%(r,s))
#FreeCAD.Console.PrintMessage("Create sphere (%s,%s)...\n"%(r,s))
mesh=Mesh.createSphere(r,s)
FreeCAD.Console.PrintMessage("... destroy sphere\n")
#FreeCAD.Console.PrintMessage("... destroy sphere\n")
class LoadMeshInThreadsCases(unittest.TestCase):
@@ -267,7 +268,7 @@ class LoadMeshInThreadsCases(unittest.TestCase):
mesh=Mesh.createSphere(10.0,100) # a fine sphere
name=tempfile.gettempdir() + os.sep + "mesh.stl"
mesh.write(name)
FreeCAD.Console.PrintMessage("Write mesh to %s\n"%(name))
#FreeCAD.Console.PrintMessage("Write mesh to %s\n"%(name))
#lock=thread.allocate_lock()
for i in range(2):
thread.start_new(loadFile,(name,))
@@ -295,9 +296,9 @@ class PolynomialFitCases(unittest.TestCase):
v.append(FreeCAD.Vector(2,2,0.0))
d = Mesh.polynomialFit(v)
c = d["Coefficients"]
print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
#print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
for i in d["Residuals"]:
self.failUnless(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
def testFitExact(self):
# symmetric
@@ -310,9 +311,9 @@ class PolynomialFitCases(unittest.TestCase):
v.append(FreeCAD.Vector(2,1,0.0))
d = Mesh.polynomialFit(v)
c = d["Coefficients"]
print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
#print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
for i in d["Residuals"]:
self.failUnless(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
def testFitBad(self):
# symmetric
@@ -328,9 +329,32 @@ class PolynomialFitCases(unittest.TestCase):
v.append(FreeCAD.Vector(2,2,0.0))
d = Mesh.polynomialFit(v)
c = d["Coefficients"]
print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
#print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
for i in d["Residuals"]:
self.failIf(math.fabs(i) < 0.0001, "Residual %f must be higher" % math.fabs(i))
self.assertFalse(math.fabs(i) < 0.0001, "Residual %f must be higher" % math.fabs(i))
def tearDown(self):
pass
class NastranReader(unittest.TestCase):
def setUp(self):
self.test_dir = join(FreeCAD.getHomePath(), "Mod", "Mesh", "App", "TestData")
def testEightCharGRIDElement(self):
m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRID_CQUAD4.bdf")
self.assertEqual(m.CountPoints,10)
self.assertEqual(m.CountFacets,8) # Quads split into two triangles
def testDelimitedGRIDElement(self):
m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_Delimited_GRID_CQUAD4.bdf")
self.assertEqual(m.CountPoints,10)
self.assertEqual(m.CountFacets,8) # Quads split into two triangles
def testSixteenCharGRIDElement(self):
m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRIDSTAR_CQUAD4.bdf")
self.assertEqual(m.CountPoints,4)
self.assertEqual(m.CountFacets,2) # Quads split into two triangles
def tearDown(self):
pass

View File

@@ -0,0 +1,35 @@
$-------------------------------------------------------------------------------
$ Nastran case control file
$ Part of the FreeCAD unit test system.
$ This case uses space-delimited floating-point numbers that are not aligned to
$ eight-character field widths.
$-------------------------------------------------------------------------------
$ Exec control section
$-------------------------------------------------------------------------------
ID TESTCASE,Nastran
APP DISP
SOL 1
TIME 20
CEND
$-------------------------------------------------------------------------------
$ Case control section
$-------------------------------------------------------------------------------
MAXLINES = 1000000
TITLE = TESTCASE
SUBTITLE = Test case for FreeCAD Mesh NASTRAN input
GRID 1 0.00E+00 0.00E+00 0.00E+00
GRID 2 0.00E+00 0.500000 0.00E+00
GRID 3 0.00E+00 1.000000 0.00E+00
GRID 4 0.00E+00 1.500000 0.00E+00
GRID 5 0.00E+00 2.000000 0.00E+00
GRID 6 0.00E+00 0.00E+00 0.500000
GRID 7 0.00E+00 0.500000 0.500000
GRID 8 0.00E+00 1.000000 0.500000
GRID 9 0.00E+00 1.500000 0.500000
GRID 10 0.00E+00 2.000000 0.500000
CQUAD4 1 400 1 6 7 2
CQUAD4 2 400 2 7 8 3
CQUAD4 3 400 3 8 9 4
CQUAD4 4 400 4 9 10 5
ENDDATA

View File

@@ -0,0 +1,29 @@
-------------------------------------------------------------------------------
$ Nastran case control file
$ Part of the FreeCAD unit test system.
$ This cases uses the high-prevision 16-char width GRID* element with no
$ delimiter.
$-------------------------------------------------------------------------------
$ Exec control section
$-------------------------------------------------------------------------------
ID TESTCASE,Nastran
APP DISP
SOL 1
TIME 20
CEND
$-------------------------------------------------------------------------------
$ Case control section
$-------------------------------------------------------------------------------
MAXLINES = 1000000
TITLE = TESTCASE
SUBTITLE = Test case for FreeCAD Mesh NASTRAN input
GRID* 1 0.00000000000000-1.
* 0.
GRID* 2 1.00000000000000-1.
* 0.
GRID* 3 0.000000000000001.
* 0.
GRID* 4 1.000000000000001.
* 0.
CQUAD4 1 400 1 2 4 3

View File

@@ -0,0 +1,33 @@
$-------------------------------------------------------------------------------
$ Nastran case control file
$ Part of the FreeCAD unit test system.
$-------------------------------------------------------------------------------
$ Exec control section
$-------------------------------------------------------------------------------
ID TESTCASE,Nastran
APP DISP
SOL 1
TIME 20
CEND
$-------------------------------------------------------------------------------
$ Case control section
$-------------------------------------------------------------------------------
MAXLINES = 1000000
TITLE = TESTCASE
SUBTITLE = Test case for FreeCAD Mesh NASTRAN input
GRID 1 0.00E+000.00E+000.00E+00
GRID 2 0.00E+000.5000000.00E+00
GRID 3 0.00E+001.0000000.00E+00
GRID 4 0.00E+001.5000000.00E+00
GRID 5 0.00E+002.0000000.00E+00
GRID 6 0.00E+000.00E+000.500000
GRID 7 0.00E+000.5000000.500000
GRID 8 0.00E+001.0000000.500000
GRID 9 0.00E+001.5000000.500000
GRID 10 0.00E+002.0000000.500000
CQUAD4 1 400 1 6 7 2
CQUAD4 2 400 2 7 8 3
CQUAD4 3 400 3 8 9 4
CQUAD4 4 400 4 9 10 5
ENDDATA

View File

@@ -10,6 +10,12 @@ set(Mesh_Scripts
App/MeshTestsApp.py
)
set(MeshTestDataFiles
App/TestData/NASTRAN_Test_GRID_CQUAD4.bdf
App/TestData/NASTRAN_Test_Delimited_GRID_CQUAD4.bdf
App/TestData/NASTRAN_Test_GRIDSTAR_CQUAD4.bdf
)
if(BUILD_GUI)
list (APPEND Mesh_Scripts InitGui.py)
endif(BUILD_GUI)
@@ -18,15 +24,25 @@ add_custom_target(MeshScripts ALL
SOURCES ${Mesh_Scripts}
)
add_custom_target(MeshTestData ALL
SOURCES ${MeshTestDataFiles}
)
fc_target_copy_resource_flat(MeshScripts
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_BINARY_DIR}/Mod/Mesh
${Mesh_Scripts}
)
fc_copy_sources(MeshTestData "${CMAKE_BINARY_DIR}/Mod/Mesh/" ${MeshTestDataFiles})
INSTALL(
FILES
${Mesh_Scripts}
DESTINATION
Mod/Mesh
)
INSTALL(FILES ${MeshTestDataFiles} DESTINATION Mod/Mesh/Data)