diff --git a/data/examples/FemCalculixCantilever2D.FCStd b/data/examples/FemCalculixCantilever2D.FCStd index 00c69faea..7029b54be 100644 Binary files a/data/examples/FemCalculixCantilever2D.FCStd and b/data/examples/FemCalculixCantilever2D.FCStd differ diff --git a/data/examples/FemCalculixCantilever3D.FCStd b/data/examples/FemCalculixCantilever3D.FCStd index 5b50ab2d9..f00197039 100644 Binary files a/data/examples/FemCalculixCantilever3D.FCStd and b/data/examples/FemCalculixCantilever3D.FCStd differ diff --git a/src/Mod/Fem/FemInputWriterCcx.py b/src/Mod/Fem/FemInputWriterCcx.py index 75e87aea1..6516e3756 100644 --- a/src/Mod/Fem/FemInputWriterCcx.py +++ b/src/Mod/Fem/FemInputWriterCcx.py @@ -57,11 +57,20 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter): temperature_obj, heatflux_obj, initialtemperature_obj, beamsection_obj, shellthickness_obj, analysis_type, dir_name) - self.file_name = self.dir_name + '/' + self.mesh_object.Name + '.inp' + self.main_file_name = self.mesh_object.Name + '.inp' + self.file_name = self.dir_name + '/' + self.main_file_name print('FemInputWriterCcx --> self.dir_name --> ' + self.dir_name) + print('FemInputWriterCcx --> self.main_file_name --> ' + self.main_file_name) print('FemInputWriterCcx --> self.file_name --> ' + self.file_name) def write_calculix_input_file(self): + if self.solver_obj.SplitInputWriter == True: + self.write_calculix_splitted_input_file() + else: + self.write_calculix_one_input_file() + return self.file_name + + def write_calculix_one_input_file(self): timestart = time.clock() self.femmesh.writeABAQUS(self.file_name) @@ -144,7 +153,171 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter): self.write_footer(inpfile) inpfile.close() print("Writing time input file: " + str(time.clock() - timestart) + ' \n') - return self.file_name + + def write_calculix_splitted_input_file(self): + timestart = time.clock() + + # reopen file with "append" and add the analysis definition + # first open file with "write" to ensure that each new iteration of writing of inputfile starts in new file + # first open file with "write" to ensure that the .writeABAQUS also writes in inputfile + inpfileMain = open(self.file_name, 'w') + inpfileMain.close + inpfileMain = open(self.file_name, 'a') + inpfileMain.write('\n\n') + + # write nodes and elements + name = self.file_name[:-4] + include_name = self.main_file_name[:-4] + + inpfileNodesElem = open(name + "_Node_Elem_sets.inp", 'w') + self.femmesh.writeABAQUS(name + "_Node_Elem_sets.inp") + inpfileNodesElem.close + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('**Nodes and Elements\n') + inpfileMain.write('** written by femmesh.writeABAQUS\n') + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_Elem_sets.inp \n") + + # create seperate inputfiles for each node set or constraint + if self.fixed_objects or self.displacement_objects or self.planerotation_objects: + inpfileNodes = open(name + "_Node_sets.inp", 'w') + if self.analysis_type == "thermomech" and self.temperature_objects: + inpfileNodeTemp = open(name + "_Node_Temp.inp", 'w') + if self.force_objects: + inpfileForce = open(name + "_Node_Force.inp", 'w') + if self.pressure_objects: + inpfilePressure = open(name + "_Pressure.inp", 'w') + if self.analysis_type == "thermomech" and self.heatflux_objects: + inpfileHeatflux = open(name + "_Node_Heatlfux.inp", 'w') + if self.contact_objects: + inpfileContact = open(name + "_Surface_Contact.inp", 'w') + if self.transform_objects: + inpfileTransform = open(name + "_Node_Transform.inp", 'w') + + # node and element sets + self.write_element_sets_material_and_femelement_type(inpfileMain) + if self.fixed_objects: + self.write_node_sets_constraints_fixed(inpfileNodes) + if self.displacement_objects: + self.write_node_sets_constraints_displacement(inpfileNodes) + if self.planerotation_objects: + self.write_node_sets_constraints_planerotation(inpfileNodes) + if self.contact_objects: + self.write_surfaces_contraints_contact(inpfileContact) + if self.transform_objects: + self.write_node_sets_constraints_transform(inpfileTransform) + + # write commentary and include statement for static case node sets + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('**Node sets for constraints\n') + inpfileMain.write('** written by write_node_sets_constraints_fixed\n') + inpfileMain.write('** written by write_node_sets_constraints_displacement\n') + inpfileMain.write('** written by write_node_sets_constraints_planerotation\n') + if self.fixed_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_sets.inp \n") + + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('** Surfaces for contact constraint\n') + inpfileMain.write('** written by write_surfaces_contraints_contact\n') + if self.contact_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Surface_Contact.inp \n") + + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('** Node sets for transform constraint\n') + inpfileMain.write('** written by write_node_sets_constraints_transform\n') + if self.transform_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_Transform.inp \n") + + if self.analysis_type == "thermomech" and self.temperature_objects: + self.write_node_sets_constraints_temperature(inpfileNodeTemp) + + # include seperately written temperature constraint in input file + if self.analysis_type == "thermomech": + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('**Node sets for temperature constraint\n') + inpfileMain.write('** written by write_node_sets_constraints_temperature\n') + if self.temperature_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_Temp.inp \n") + + # materials and fem element types + self.write_materials(inpfileMain) + if self.analysis_type == "thermomech" and self.initialtemperature_objects: + self.write_constraints_initialtemperature(inpfileMain) + self.write_femelementsets(inpfileMain) + + # constraints independent from steps + if self.planerotation_objects: + self.write_constraints_planerotation(inpfileMain) + if self.contact_objects: + self.write_constraints_contact(inpfileMain) + if self.transform_objects: + self.write_constraints_transform(inpfileMain) + + # step begin + if self.analysis_type == "frequency": + self.write_step_begin_static_frequency(inpfileMain) + self.write_analysis_frequency(inpfileMain) + elif self.analysis_type == "static": + self.write_step_begin_static_frequency(inpfileMain) + elif self.analysis_type == "thermomech": + self.write_step_begin_thermomech(inpfileMain) + self.write_analysis_thermomech(inpfileMain) + + # constraints depend on step used in all analysis types + if self.fixed_objects: + self.write_constraints_fixed(inpfileMain) + if self.displacement_objects: + self.write_constraints_displacement(inpfileMain) + + # constraints depend on step and depending on analysis type + if self.analysis_type == "frequency": + pass + elif self.analysis_type == "static": + if self.selfweight_objects: + self.write_constraints_selfweight(inpfileMain) + if self.force_objects: + self.write_constraints_force(inpfileForce) + if self.pressure_objects: + self.write_constraints_pressure(inpfilePressure) + elif self.analysis_type == "thermomech": + if self.selfweight_objects: + self.write_constraints_selfweight(inpfileMain) + if self.force_objects: + self.write_constraints_force(inpfileForce) + if self.pressure_objects: + self.write_constraints_pressure(inpfilePressure) + if self.temperature_objects: + self.write_constraints_temperature(inpfileMain) + if self.heatflux_objects: + self.write_constraints_heatflux(inpfileHeatflux) + + # include seperately written constraints in input file + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('** Node loads\n') + inpfileMain.write('** written by write_constraints_force\n') + if self.force_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_Force.inp \n") + + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('** Element + CalculiX face + load in [MPa]\n') + inpfileMain.write('** written by write_constraints_pressure\n') + if self.pressure_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Pressure.inp \n") + + if self.analysis_type == "thermomech": + inpfileMain.write('\n***********************************************************\n') + inpfileMain.write('** Convective heat transfer (heat flux)\n') + inpfileMain.write('** written by write_constraints_heatflux\n') + if self.heatflux_objects: + inpfileMain.write('*INCLUDE,INPUT=' + include_name + "_Node_Heatlfux.inp \n") + + # output and step end + self.write_outputs_types(inpfileMain) + self.write_step_end(inpfileMain) + + # footer + self.write_footer(inpfileMain) + inpfileMain.close() + print("Writing time input file: " + str(time.clock() - timestart) + ' \n') def write_element_sets_material_and_femelement_type(self, f): f.write('\n***********************************************************\n') diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui index 708550139..25bc8b147 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui @@ -6,16 +6,16 @@ 0 0 - 555 - 652 + 536 + 752 CalculiX - - - + + + @@ -33,26 +33,33 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - QLayout::SetNoConstraint - - - - - - - false + + + + + + + CalculiX binary + + + + + + + Use standard ccx binary path + + + true - ExternalEditorPath + UseStandardCcxLocation Mod/Fem/Ccx - + false @@ -68,7 +75,7 @@ - + false @@ -108,7 +115,14 @@ - + + + + Editor + + + + Use internal editor for .inp files @@ -125,13 +139,6 @@ - - - Editor - - - - false @@ -147,26 +154,42 @@ - - - - Use standard ccx binary path - - - true + + + + false - UseStandardCcxLocation + ExternalEditorPath Mod/Fem/Ccx - - + + - CalculiX binary + Split .inp + + + + + + + true + + + Split writing of .inp + + + false + + + SplitInputWriter + + + Mod/Fem/Ccx @@ -340,13 +363,6 @@ - - - - Non-linear geometry - - - @@ -354,6 +370,13 @@ + + + + Non-linear geometry + + + @@ -509,8 +532,8 @@ Frequency defaults - - + + @@ -617,19 +640,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp index 0bf52e32e..04f245df8 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp @@ -69,6 +69,7 @@ void DlgSettingsFemCcxImp::saveSettings() fc_ext_editor->onSave(); cb_ccx_binary_std->onSave(); fc_ccx_binary_path->onSave(); + cb_split_inp_writer->onSave(); } void DlgSettingsFemCcxImp::loadSettings() @@ -92,6 +93,7 @@ void DlgSettingsFemCcxImp::loadSettings() fc_ext_editor->onRestore(); cb_ccx_binary_std->onRestore(); fc_ccx_binary_path->onRestore(); + cb_split_inp_writer->onRestore(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/Mod/Fem/Ccx"); diff --git a/src/Mod/Fem/_FemSolverCalculix.py b/src/Mod/Fem/_FemSolverCalculix.py index 954cd690a..327da9cd1 100644 --- a/src/Mod/Fem/_FemSolverCalculix.py +++ b/src/Mod/Fem/_FemSolverCalculix.py @@ -43,8 +43,8 @@ class _FemSolverCalculix(): fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General") ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx") - obj.addProperty("App::PropertyPath", "WorkingDir", "Fem", "Working directory for calculations") - obj.WorkingDir = fem_prefs.GetString("WorkingDir", "") + obj.addProperty("App::PropertyPath", "WorkingDir", "Fem", "Working directory for calculations, will only be used it is left blank in preferences") + # the working directory is not set, the solver working directory is only used if the preferences working directory is left blank obj.addProperty("App::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis") obj.AnalysisType = FemToolsCcx.FemToolsCcx.known_analysis_types @@ -97,6 +97,10 @@ class _FemSolverCalculix(): use_non_ccx_iterations_param = ccx_prefs.GetInt("UseNonCcxIterationParam", False) obj.IterationsControlParameterTimeUse = use_non_ccx_iterations_param + obj.addProperty("App::PropertyBool", "SplitInputWriter", "Fem", "Split writing of ccx input file") + split = ccx_prefs.GetBool("SplitInputWriter", False) + obj.SplitInputWriter = split + ccx_default_time_incrementation_control_parameter = { # iteration parameter 'I_0': 4,