diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 5e1fef5db1..6de3ea80b4 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -254,6 +254,7 @@ SET(FemTestsCcx_SRCS SET(FemTestsElmer_SRCS femtest/data/elmer/__init__.py femtest/data/elmer/case_mm.sif + femtest/data/elmer/elmer_ccxcanti_faceload_mm.sif femtest/data/elmer/group_mesh.geo femtest/data/elmer/ELMERSOLVER_STARTINFO ) diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py b/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py index d9592fced8..adb04b0e24 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py @@ -73,7 +73,10 @@ def setup_cantileverbase(doc=None, solvertype="ccxtools"): )[0] solver_object.WorkingDir = u"" elif solvertype == "elmer": - analysis.addObject(ObjectsFem.makeSolverElmer(doc, "SolverElmer")) + solver_object = analysis.addObject( + ObjectsFem.makeSolverElmer(doc, "SolverElmer") + )[0] + ObjectsFem.makeEquationElasticity(doc, solver_object) elif solvertype == "z88": analysis.addObject(ObjectsFem.makeSolverZ88(doc, "SolverZ88")) if solvertype == "calculix" or solvertype == "ccxtools": @@ -93,7 +96,9 @@ def setup_cantileverbase(doc=None, solvertype="ccxtools"): mat["YoungsModulus"] = "210000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" - mat["ThermalExpansionCoefficient"] = "0.012 mm/m/K" + if solvertype == "elmer": + # set ThermalExpansionCoefficient, elmer elasticity needs it FIXME + mat["ThermalExpansionCoefficient"] = "0.012 mm/m/K" material_object.Material = mat # fixed_constraint diff --git a/src/Mod/Fem/femtest/app/test_solver_elmer.py b/src/Mod/Fem/femtest/app/test_solver_elmer.py index 95af9abe02..b2d9f6b5c1 100644 --- a/src/Mod/Fem/femtest/app/test_solver_elmer.py +++ b/src/Mod/Fem/femtest/app/test_solver_elmer.py @@ -150,3 +150,47 @@ class TestSolverElmer(unittest.TestCase): self.assertFalse(ret, "GMSH geo write file test failed.\n{}".format(ret)) fcc_print("--------------- End of FEM tests solver framework solver Elmer -----------") + + # ******************************************************************************************** + def test_elmer_ccxcanti_faceload( + self + ): + fcc_print("\n------------- Start of FEM elmer tests for ccx cantilever faceload -------") + + # set up the Elmer static analysis example + from femexamples.ccx_cantilever_faceload import setup + setup(self.document, "elmer") + + solver_obj = self.document.SolverElmer + + base_name = "elmer_ccxcanti_faceload" + analysis_dir = testtools.get_unit_test_tmp_dir(self.temp_dir, solver_obj.Name) + + # save the file + save_fc_file = join(analysis_dir, solver_obj.Name + "_" + base_name + ".FCStd") + fcc_print("Save FreeCAD file to {}...".format(save_fc_file)) + self.document.saveAs(save_fc_file) + + # write input files + fcc_print("Checking FEM input file writing for Elmer solver framework solver ...") + machine_elmer = solver_obj.Proxy.createMachine( + solver_obj, + analysis_dir, + True + ) + machine_elmer.target = femsolver.run.PREPARE + machine_elmer.start() + machine_elmer.join() # wait for the machine to finish. + + # compare case input file + test_file_dir_elmer = join(testtools.get_fem_test_home_dir(), "elmer") + fcc_print(test_file_dir_elmer) + + fcc_print("Test writing case file") + casefile_given = join(test_file_dir_elmer, "elmer_ccxcanti_faceload_mm.sif") + casefile_totest = join(analysis_dir, "case.sif") + fcc_print("Comparing {} to {}".format(casefile_given, casefile_totest)) + ret = testtools.compare_files(casefile_given, casefile_totest) + self.assertFalse(ret, "case write file test failed.\n{}".format(ret)) + + fcc_print("--------------- End of FEM elmer tests for ccx cantilever faceload ---------") diff --git a/src/Mod/Fem/femtest/data/elmer/elmer_ccxcanti_faceload_mm.sif b/src/Mod/Fem/femtest/data/elmer/elmer_ccxcanti_faceload_mm.sif new file mode 100644 index 0000000000..26a17d558f --- /dev/null +++ b/src/Mod/Fem/femtest/data/elmer/elmer_ccxcanti_faceload_mm.sif @@ -0,0 +1,90 @@ +Check Keywords Warn + +Header + Mesh DB "." +End + +Solver 1 + Bubbles = Logical False + Calculate Pangle = Logical False + Calculate Principal = Logical False + Calculate Strains = Logical False + Calculate Stresses = Logical False + Displace mesh = Logical False + Eigen Analysis = Logical False + Eigen System Values = Integer 5 + Equation = String "Elasticity" + Exec Solver = String "Always" + Linear System Abort Not Converged = Logical False + Linear System Convergence Tolerance = Real 1e-08 + Linear System Iterative Method = String "BiCGStab" + Linear System Max Iterations = Integer 500 + Linear System Precondition Recompute = Integer 1 + Linear System Preconditioning = String "ILU0" + Linear System Residual Output = Integer 1 + Linear System Solver = String "Iterative" + Optimize Bandwidth = Logical True + Procedure = File "StressSolve" "StressSolver" + Stabilize = Logical True + Steady State Convergence Tolerance = Real 1e-05 + Variable = String "Displacement" + Variable DOFs = Integer 3 +End + +Simulation + BDF Order = Integer 1 + Coordinate Mapping(3) = Integer 1 2 3 + Coordinate System = String "Cartesian 3D" + Output Intervals = Integer 1 + Simulation Type = String "Steady state" + Steady State Max Iterations = Integer 1 + Steady State Min Iterations = Integer 0 + Timestepping Method = String "BDF" + Use Mesh Names = Logical True +End + +Constants +End + +Body 1 + Equation = Integer 1 + Material = Integer 1 + Name = String "Solid1" +End + +Material 1 + Density = Real 7.9e-06 + Heat expansion Coefficient = Real 1.2e-05 + Poisson ratio = Real 0.3 + Youngs Modulus = Real 210000000.0 +End + +Equation 1 + Active Solvers(2) = Integer 1 2 +End + +Solver 2 + Equation = String "ResultOutput" + Exec Solver = String "After simulation" + Output File Name = File "case" + Procedure = File "ResultOutputSolve" "ResultOutputSolver" + Vtu Format = Logical True +End + +Boundary Condition 1 + Displacement 1 = Real 0.0 + Displacement 2 = Real 0.0 + Displacement 3 = Real 0.0 + Name = String "Face1" +End + +Boundary Condition 2 + Force 1 = Real -0.0 + Force 1 Normalize by Area = Logical True + Force 2 = Real -0.0 + Force 2 Normalize by Area = Logical True + Force 3 = Real -9000000000.0 + Force 3 Normalize by Area = Logical True + Name = String "Face2" +End + diff --git a/src/Mod/Fem/femtest/test_commands.sh b/src/Mod/Fem/femtest/test_commands.sh index 12443420bd..22a9f832c5 100644 --- a/src/Mod/Fem/femtest/test_commands.sh +++ b/src/Mod/Fem/femtest/test_commands.sh @@ -83,6 +83,7 @@ make -j 4 && ./bin/FreeCADCmd -t femtest.app.test_result.TestResult.test_rho make -j 4 && ./bin/FreeCADCmd -t femtest.app.test_result.TestResult.test_disp_abs make -j 4 && ./bin/FreeCADCmd -t femtest.app.test_solver_calculix.TestSolverCalculix.test_solver_calculix make -j 4 && ./bin/FreeCADCmd -t femtest.app.test_solver_elmer.TestSolverElmer.test_solver_elmer +make -j 4 && ./bin/FreeCADCmd -t femtest.app.test_solver_elmer.TestSolverElmer.test_elmer_ccxcanti_faceload # methods in FreeCAD @@ -316,3 +317,8 @@ import unittest unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName( 'femtest.app.test_solver_elmer.TestSolverElmer.test_solver_elmer' )) + +import unittest +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName( + 'femtest.app.test_solver_elmer.TestSolverElmer.test_elmer_ccxcanti_faceload' +))