diff --git a/src/Mod/Fem/femsolver/calculix/solver.py b/src/Mod/Fem/femsolver/calculix/solver.py index 229fb56f0a..15288a6586 100644 --- a/src/Mod/Fem/femsolver/calculix/solver.py +++ b/src/Mod/Fem/femsolver/calculix/solver.py @@ -58,16 +58,27 @@ class Proxy(solverbase.Proxy): super(Proxy, self).__init__(obj) obj.Proxy = self - # fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General") # not needed ATM + # not needed ATM + # 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::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis") + obj.addProperty( + "App::PropertyEnumeration", + "AnalysisType", + "Fem", + "Type of the analysis" + ) obj.AnalysisType = ANALYSIS_TYPES analysis_type = ccx_prefs.GetInt("AnalysisType", 0) obj.AnalysisType = ANALYSIS_TYPES[analysis_type] choices_geom_nonlinear = ["linear", "nonlinear"] - obj.addProperty("App::PropertyEnumeration", "GeometricalNonlinearity", "Fem", "Set geometrical nonlinearity") + obj.addProperty( + "App::PropertyEnumeration", + "GeometricalNonlinearity", + "Fem", + "Set geometrical nonlinearity" + ) obj.GeometricalNonlinearity = choices_geom_nonlinear nonlinear_geom = ccx_prefs.GetBool("NonlinearGeometry", False) if nonlinear_geom is True: @@ -76,43 +87,93 @@ class Proxy(solverbase.Proxy): obj.GeometricalNonlinearity = choices_geom_nonlinear[0] # linear choices_material_nonlinear = ["linear", "nonlinear"] - obj.addProperty("App::PropertyEnumeration", "MaterialNonlinearity", "Fem", "Set material nonlinearity (needs geometrical nonlinearity)") + obj.addProperty( + "App::PropertyEnumeration", + "MaterialNonlinearity", + "Fem", + "Set material nonlinearity (needs geometrical nonlinearity)" + ) obj.MaterialNonlinearity = choices_material_nonlinear obj.MaterialNonlinearity = choices_material_nonlinear[0] - obj.addProperty("App::PropertyIntegerConstraint", "EigenmodesCount", "Fem", "Number of modes for frequency calculations") + obj.addProperty( + "App::PropertyIntegerConstraint", + "EigenmodesCount", + "Fem", + "Number of modes for frequency calculations" + ) noe = ccx_prefs.GetInt("EigenmodesCount", 10) obj.EigenmodesCount = (noe, 1, 100, 1) - obj.addProperty("App::PropertyFloatConstraint", "EigenmodeLowLimit", "Fem", "Low frequency limit for eigenmode calculations") + obj.addProperty( + "App::PropertyFloatConstraint", + "EigenmodeLowLimit", + "Fem", + "Low frequency limit for eigenmode calculations" + ) ell = ccx_prefs.GetFloat("EigenmodeLowLimit", 0.0) obj.EigenmodeLowLimit = (ell, 0.0, 1000000.0, 10000.0) - obj.addProperty("App::PropertyFloatConstraint", "EigenmodeHighLimit", "Fem", "High frequency limit for eigenmode calculations") + obj.addProperty( + "App::PropertyFloatConstraint", + "EigenmodeHighLimit", + "Fem", + "High frequency limit for eigenmode calculations" + ) ehl = ccx_prefs.GetFloat("EigenmodeHighLimit", 1000000.0) obj.EigenmodeHighLimit = (ehl, 0.0, 1000000.0, 10000.0) - obj.addProperty("App::PropertyIntegerConstraint", "IterationsThermoMechMaximum", "Fem", "Maximum Number of thermo mechanical iterations in each time step before stopping jobs") + obj.addProperty( + "App::PropertyIntegerConstraint", + "IterationsThermoMechMaximum", + "Fem", + "Maximum Number of thermo mechanical iterations in each time step before stopping job" + ) niter = ccx_prefs.GetInt("AnalysisMaxIterations", 200) obj.IterationsThermoMechMaximum = niter - obj.addProperty("App::PropertyFloatConstraint", "TimeInitialStep", "Fem", "Initial time steps") + obj.addProperty( + "App::PropertyFloatConstraint", + "TimeInitialStep", + "Fem", + "Initial time steps" + ) ini = ccx_prefs.GetFloat("AnalysisTimeInitialStep", 1.0) obj.TimeInitialStep = ini - obj.addProperty("App::PropertyFloatConstraint", "TimeEnd", "Fem", "End time analysis") + obj.addProperty( + "App::PropertyFloatConstraint", + "TimeEnd", + "Fem", + "End time analysis" + ) eni = ccx_prefs.GetFloat("AnalysisTime", 1.0) obj.TimeEnd = eni - obj.addProperty("App::PropertyBool", "ThermoMechSteadyState", "Fem", "Choose between steady state thermo mech or transient thermo mech analysis") + obj.addProperty( + "App::PropertyBool", + "ThermoMechSteadyState", + "Fem", + "Choose between steady state thermo mech or transient thermo mech analysis" + ) sted = ccx_prefs.GetBool("StaticAnalysis", True) obj.ThermoMechSteadyState = sted - obj.addProperty("App::PropertyBool", "IterationsControlParameterTimeUse", "Fem", "Use the user defined time incrementation control parameter") + obj.addProperty( + "App::PropertyBool", + "IterationsControlParameterTimeUse", + "Fem", + "Use the user defined time incrementation control parameter" + ) 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") + obj.addProperty( + "App::PropertyBool", + "SplitInputWriter", + "Fem", + "Split writing of ccx input file" + ) split = ccx_prefs.GetBool("SplitInputWriter", False) obj.SplitInputWriter = split @@ -138,28 +199,88 @@ class Proxy(solverbase.Proxy): 'D_D': 1.5, 'W_G': None} p = ccx_default_time_incrementation_control_parameter - p_iter = '{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}'.format(p['I_0'], p['I_R'], p['I_P'], p['I_C'], p['I_L'], p['I_G'], '', p['I_A'], '', '') - p_cutb = '{0},{1},{2},{3},{4},{5},{6},{7}'.format(p['D_f'], p['D_C'], p['D_B'], p['D_A'], '', '', p['D_D'], '') - obj.addProperty("App::PropertyString", "IterationsControlParameterIter", "Fem", "User defined time incrementation iterations control parameter") + p_iter = '{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}'.format( + p['I_0'], + p['I_R'], + p['I_P'], + p['I_C'], + p['I_L'], + p['I_G'], + '', + p['I_A'], + '', + '' + ) + p_cutb = '{0},{1},{2},{3},{4},{5},{6},{7}'.format( + p['D_f'], + p['D_C'], + p['D_B'], + p['D_A'], + '', + '', + p['D_D'], + '' + ) + obj.addProperty( + "App::PropertyString", + "IterationsControlParameterIter", + "Fem", + "User defined time incrementation iterations control parameter" + ) obj.IterationsControlParameterIter = p_iter - obj.addProperty("App::PropertyString", "IterationsControlParameterCutb", "Fem", "User defined time incrementation cutbacks control parameter") + obj.addProperty( + "App::PropertyString", + "IterationsControlParameterCutb", + "Fem", + "User defined time incrementation cutbacks control parameter" + ) obj.IterationsControlParameterCutb = p_cutb - stringIterationsUserDefinedIncrementations = "Set to True to switch off the ccx automatic incrementation completely (ccx parameter DIRECT). Use with care. Analysis may not converge!" - obj.addProperty("App::PropertyBool", "IterationsUserDefinedIncrementations", "Fem", stringIterationsUserDefinedIncrementations) + stringIterationsUserDefinedIncrementations = ( + "Set to True to switch off the ccx automatic incrementation completely " + "(ccx parameter DIRECT). Use with care. Analysis may not converge!" + ) + obj.addProperty( + "App::PropertyBool", + "IterationsUserDefinedIncrementations", + "Fem", + stringIterationsUserDefinedIncrementations) obj.IterationsUserDefinedIncrementations = False - stringIterationsUserDefinedTimeStepLength = "Set to True to use the user defined time steps. The time steps are set with TimeInitialStep and TimeEnd" - obj.addProperty("App::PropertyBool", "IterationsUserDefinedTimeStepLength", "Fem", stringIterationsUserDefinedTimeStepLength) + stringIterationsUserDefinedTimeStepLength = ( + "Set to True to use the user defined time steps. " + "The time steps are set with TimeInitialStep and TimeEnd" + ) + obj.addProperty( + "App::PropertyBool", + "IterationsUserDefinedTimeStepLength", + "Fem", + stringIterationsUserDefinedTimeStepLength + ) obj.IterationsUserDefinedTimeStepLength = False - known_ccx_solver_types = ["default", "spooles", "iterativescaling", "iterativecholesky"] - obj.addProperty("App::PropertyEnumeration", "MatrixSolverType", "Fem", "Type of solver to use") + known_ccx_solver_types = [ + "default", + "spooles", + "iterativescaling", + "iterativecholesky" + ] + obj.addProperty( + "App::PropertyEnumeration", + "MatrixSolverType", + "Fem", + "Type of solver to use" + ) obj.MatrixSolverType = known_ccx_solver_types solver_type = ccx_prefs.GetInt("Solver", 0) obj.MatrixSolverType = known_ccx_solver_types[solver_type] - obj.addProperty("App::PropertyBool", "BeamShellResultOutput3D", "Fem", "Output 3D results for 1D and 2D analysis ") + obj.addProperty( + "App::PropertyBool", + "BeamShellResultOutput3D", + "Fem", + "Output 3D results for 1D and 2D analysis " + ) dimout = ccx_prefs.GetBool("BeamShellOutput", False) obj.BeamShellResultOutput3D = dimout diff --git a/src/Mod/Fem/femsolver/calculix/tasks.py b/src/Mod/Fem/femsolver/calculix/tasks.py index 3ac74c2305..8dbd07c246 100644 --- a/src/Mod/Fem/femsolver/calculix/tasks.py +++ b/src/Mod/Fem/femsolver/calculix/tasks.py @@ -96,7 +96,8 @@ class Solve(run.Solve): def run(self): if not _inputFileName: - # TODO do not run solver, do not try to read results in a smarter way than an Exception + # TODO do not run solver + # do not try to read results in a smarter way than an Exception raise Exception('Error on writing CalculiX input file.\n') self.pushStatus("Executing solver...\n") binary = settings.get_binary("Calculix") @@ -118,7 +119,8 @@ class Results(run.Results): def run(self): if not _inputFileName: - # TODO do not run solver, do not try to read results in a smarter way than an Exception + # TODO do not run solver + # do not try to read results in a smarter way than an Exception raise Exception('Error on writing CalculiX input file.\n') prefs = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Fem/General") @@ -173,29 +175,70 @@ class _Container(object): self.mesh = mesh else: if FreeCAD.GuiUp: - QtGui.QMessageBox.critical(None, "Missing prerequisite", message) + QtGui.QMessageBox.critical( + None, + "Missing prerequisite", + message + ) raise Exception(message + '\n') # get member - self.materials_linear = self.get_several_member('Fem::Material') - self.materials_nonlinear = self.get_several_member('Fem::MaterialMechanicalNonlinear') + # materials + self.materials_linear = self.get_several_member( + 'Fem::Material' + ) + self.materials_nonlinear = self.get_several_member( + 'Fem::MaterialMechanicalNonlinear' + ) - self.beam_sections = self.get_several_member('Fem::FemElementGeometry1D') - self.beam_rotations = self.get_several_member('Fem::FemElementRotation1D') - self.fluid_sections = self.get_several_member('Fem::FemElementFluid1D') - self.shell_thicknesses = self.get_several_member('Fem::FemElementGeometry2D') + # geometries + self.beam_sections = self.get_several_member( + 'Fem::FemElementGeometry1D' + ) + self.beam_rotations = self.get_several_member( + 'Fem::FemElementRotation1D' + ) + self.fluid_sections = self.get_several_member( + 'Fem::FemElementFluid1D' + ) + self.shell_thicknesses = self.get_several_member( + 'Fem::FemElementGeometry2D' + ) - self.constraints_contact = self.get_several_member('Fem::ConstraintContact') - self.constraints_displacement = self.get_several_member('Fem::ConstraintDisplacement') - self.constraints_fixed = self.get_several_member('Fem::ConstraintFixed') - self.constraints_force = self.get_several_member('Fem::ConstraintForce') - self.constraints_heatflux = self.get_several_member('Fem::ConstraintHeatflux') - self.constraints_initialtemperature = self.get_several_member('Fem::ConstraintInitialTemperature') - self.constraints_planerotation = self.get_several_member('Fem::ConstraintPlaneRotation') - self.constraints_pressure = self.get_several_member('Fem::ConstraintPressure') - self.constraints_selfweight = self.get_several_member('Fem::ConstraintSelfWeight') - self.constraints_temperature = self.get_several_member('Fem::ConstraintTemperature') - self.constraints_transform = self.get_several_member('Fem::ConstraintTransform') + # constraints + self.constraints_contact = self.get_several_member( + 'Fem::ConstraintContact' + ) + self.constraints_displacement = self.get_several_member( + 'Fem::ConstraintDisplacement' + ) + self.constraints_fixed = self.get_several_member( + 'Fem::ConstraintFixed' + ) + self.constraints_force = self.get_several_member( + 'Fem::ConstraintForce' + ) + self.constraints_heatflux = self.get_several_member( + 'Fem::ConstraintHeatflux' + ) + self.constraints_initialtemperature = self.get_several_member( + 'Fem::ConstraintInitialTemperature' + ) + self.constraints_planerotation = self.get_several_member( + 'Fem::ConstraintPlaneRotation' + ) + self.constraints_pressure = self.get_several_member( + 'Fem::ConstraintPressure' + ) + self.constraints_selfweight = self.get_several_member( + 'Fem::ConstraintSelfWeight' + ) + self.constraints_temperature = self.get_several_member( + 'Fem::ConstraintTemperature' + ) + self.constraints_transform = self.get_several_member( + 'Fem::ConstraintTransform' + ) def get_several_member(self, t): return femutils.get_several_member(self.analysis, t) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 4285293d8d..92cfd8ed33 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -91,10 +91,19 @@ class FemInputWriterCcx(writerbase.FemInputWriter): self.main_file_name = self.mesh_object.Name + '.inp' self.file_name = join(self.dir_name, self.main_file_name) self.FluidInletoutlet_ele = [] - self.fluid_inout_nodes_file = join(self.dir_name, (self.mesh_object.Name + '_inout_nodes.txt')) - FreeCAD.Console.PrintLog('writerbaseCcx --> self.dir_name --> ' + self.dir_name + '\n') - FreeCAD.Console.PrintLog('writerbaseCcx --> self.main_file_name --> ' + self.main_file_name + '\n') - FreeCAD.Console.PrintMessage('writerbaseCcx --> self.file_name --> ' + self.file_name + '\n') + self.fluid_inout_nodes_file = join( + self.dir_name, + '{}_inout_nodes.txt'.format(self.mesh_object.Name) + ) + FreeCAD.Console.PrintLog( + 'writerbaseCcx --> self.dir_name --> ' + self.dir_name + '\n' + ) + FreeCAD.Console.PrintLog( + 'writerbaseCcx --> self.main_file_name --> ' + self.main_file_name + '\n' + ) + FreeCAD.Console.PrintMessage( + 'writerbaseCcx --> self.file_name --> ' + self.file_name + '\n' + ) def write_calculix_input_file(self): timestart = time.clock() @@ -111,7 +120,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter): return self.file_name else: FreeCAD.Console.PrintMessage(writing_time_string + ' \n') - FreeCAD.Console.PrintError("Problems on writing input file, check report prints.\n\n") + FreeCAD.Console.PrintError( + "Problems on writing input file, check report prints.\n\n" + ) return "" def write_calculix_one_input_file(self): @@ -150,7 +161,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): if self.fluidsection_objects: if is_fluid_section_inlet_outlet(self.ccx_elsets) is True: inpfile.close() - meshtools.use_correct_fluidinout_ele_def(self.FluidInletoutlet_ele, self.file_name, self.fluid_inout_nodes_file) + meshtools.use_correct_fluidinout_ele_def( + self.FluidInletoutlet_ele, + self.file_name, + self.fluid_inout_nodes_file + ) inpfile = open(self.file_name, 'a') # constraints independent from steps @@ -204,8 +219,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): def write_calculix_splitted_input_file(self): # 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 + # 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') @@ -298,14 +315,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # Fluid section: Inlet and Outlet requires special element definition if self.fluidsection_objects: if is_fluid_section_inlet_outlet(self.ccx_elsets) is True: -<<<<<<< HEAD - FemMeshTools.use_correct_fluidinout_ele_def(self.FluidInletoutlet_ele, name + "_Node_Elem_sets.inp", self.fluid_inout_nodes_file) -======= meshtools.use_correct_fluidinout_ele_def( self.FluidInletoutlet_ele, name + "_Node_Elem_sets.inp", self.fluid_inout_nodes_file ) ->>>>>>> 5e4bf5b587... FEM: solver calculix writer and solver writer base, use small character for import identifier # constraints independent from steps if self.planerotation_objects: @@ -406,7 +419,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # we only could do this for volumes, if a mesh contains volumes # we're going to use them in the analysis # but a mesh could contain the element faces of the volumes as faces - # and the edges of the faces as edges, there we have to check for some geometric objects + # and the edges of the faces as edges + # there we have to check for some geometric objects self.get_ccx_elsets_single_mat_solid() if len(self.shellthickness_objects) == 1: self.get_ccx_elsets_single_mat_single_shell() @@ -425,8 +439,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # we only could do this for volumes, if a mseh contains volumes # we're going to use them in the analysis # but a mesh could contain the element faces of the volumes as faces - # and the edges of the faces as edges, there we have to check for some geometric objects - self.get_ccx_elsets_multiple_mat_solid() # volume is a bit special, because retrieving ids from group mesh data is implemented + # and the edges of the faces as edges + # there we have to check for some geometric objects + # volume is a bit special + # because retrieving ids from group mesh data is implemented + self.get_ccx_elsets_multiple_mat_solid() if len(self.shellthickness_objects) == 1: self.get_ccx_elsets_multiple_mat_single_shell() elif len(self.shellthickness_objects) > 1: @@ -443,25 +460,37 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # TODO: some elementIDs are collected for 1D-Flow calculation, # this should be a def somewhere else, preferable inside the get_ccx_elsets_... methods for ccx_elset in self.ccx_elsets: - if ccx_elset['ccx_elset'] and not isinstance(ccx_elset['ccx_elset'], six.string_types): # use six to be sure to be Python 2.7 and 3.x compatible + # use six to be sure to be Python 2.7 and 3.x compatible + if ccx_elset['ccx_elset'] \ + and not isinstance(ccx_elset['ccx_elset'], six.string_types): if 'fluidsection_obj'in ccx_elset: fluidsec_obj = ccx_elset['fluidsection_obj'] if fluidsec_obj.SectionType == 'Liquid': - if (fluidsec_obj.LiquidSectionType == "PIPE INLET") or (fluidsec_obj.LiquidSectionType == "PIPE OUTLET"): + if (fluidsec_obj.LiquidSectionType == "PIPE INLET") \ + or (fluidsec_obj.LiquidSectionType == "PIPE OUTLET"): elsetchanged = False counter = 0 for elid in ccx_elset['ccx_elset']: counter = counter + 1 - if (elsetchanged is False) and (fluidsec_obj.LiquidSectionType == "PIPE INLET"): - self.FluidInletoutlet_ele.append([str(elid), fluidsec_obj.LiquidSectionType, 0]) # 3rd index is to track which line number the element is defined + if (elsetchanged is False) \ + and (fluidsec_obj.LiquidSectionType == "PIPE INLET"): + # 3rd index is to track which line nr the element is defined + self.FluidInletoutlet_ele.append( + [str(elid), fluidsec_obj.LiquidSectionType, 0] + ) elsetchanged = True - elif (fluidsec_obj.LiquidSectionType == "PIPE OUTLET") and (counter == len(ccx_elset['ccx_elset'])): - self.FluidInletoutlet_ele.append([str(elid), fluidsec_obj.LiquidSectionType, 0]) # 3rd index is to track which line number the element is defined + elif (fluidsec_obj.LiquidSectionType == "PIPE OUTLET") \ + and (counter == len(ccx_elset['ccx_elset'])): + # 3rd index is to track which line nr the element is defined + self.FluidInletoutlet_ele.append( + [str(elid), fluidsec_obj.LiquidSectionType, 0] + ) # write ccx_elsets to file for ccx_elset in self.ccx_elsets: f.write('*ELSET,ELSET=' + ccx_elset['ccx_elset_name'] + '\n') - if isinstance(ccx_elset['ccx_elset'], six.string_types): # use six to be sure to be Python 2.7 and 3.x compatible + # use six to be sure to be Python 2.7 and 3.x compatible + if isinstance(ccx_elset['ccx_elset'], six.string_types): f.write(ccx_elset['ccx_elset'] + '\n') else: for elid in ccx_elset['ccx_elset']: @@ -474,10 +503,12 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Node sets for fixed constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.fixed_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.fixed_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] fix_obj = femobj['Object'] f.write('** ' + fix_obj.Label + '\n') - if self.femmesh.Volumes and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): + if self.femmesh.Volumes \ + and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): if len(femobj['NodesSolid']) > 0: f.write('*NSET,NSET=' + fix_obj.Name + 'Solid\n') for n in femobj['NodesSolid']: @@ -498,7 +529,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Node sets for prescribed displacement constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.displacement_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.displacement_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] disp_obj = femobj['Object'] f.write('** ' + disp_obj.Label + '\n') f.write('*NSET,NSET=' + disp_obj.Name + '\n') @@ -515,10 +547,14 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('** Node sets for plane rotation constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) # info about self.constraint_conflict_nodes: - # is used to check if MPC and constraint fixed and constraint displacement share same nodes, - # because MPC's and constraints fixed and constraints displacement can't share same nodes. - # Thus call write_node_sets_constraints_planerotation has to be after constraint fixed and constraint displacement - for femobj in self.planerotation_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + # is used to check if MPC and constraint fixed and + # constraint displacement share same nodes + # because MPC's and constraints fixed and + # constraints displacement can't share same nodes. + # Thus call write_node_sets_constraints_planerotation has to be + # after constraint fixed and constraint displacement + for femobj in self.planerotation_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] l_nodes = femobj['Nodes'] fric_obj = femobj['Object'] f.write('** ' + fric_obj.Label + '\n') @@ -526,7 +562,12 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # Code to extract nodes and coordinates on the PlaneRotation support face nodes_coords = [] for node in l_nodes: - nodes_coords.append((node, self.femnodes_mesh[node].x, self.femnodes_mesh[node].y, self.femnodes_mesh[node].z)) + nodes_coords.append(( + node, + self.femnodes_mesh[node].x, + self.femnodes_mesh[node].y, + self.femnodes_mesh[node].z + )) node_planerotation = meshtools.get_three_non_colinear_nodes(nodes_coords) for i in range(len(l_nodes)): if l_nodes[i] not in node_planerotation: @@ -549,7 +590,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('** Surfaces for contact constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) obj = 0 - for femobj in self.contact_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.contact_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] contact_obj = femobj['Object'] f.write('** ' + contact_obj.Label + '\n') cnt = 0 @@ -575,7 +617,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Node sets for transform constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.transform_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.transform_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] trans_obj = femobj['Object'] f.write('** ' + trans_obj.Label + '\n') if trans_obj.TransformType == "Rectangular": @@ -592,7 +635,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Node sets for temperature constraints\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.temperature_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.temperature_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] temp_obj = femobj['Object'] f.write('** ' + temp_obj.Label + '\n') f.write('*NSET,NSET=' + temp_obj.Name + '\n') @@ -604,12 +648,15 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('** Materials\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) f.write('** Young\'s modulus unit is MPa = N/mm2\n') - if self.analysis_type == "frequency" or self.selfweight_objects or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): + if self.analysis_type == "frequency" \ + or self.selfweight_objects \ + or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): f.write('** Density\'s unit is t/mm^3\n') if self.analysis_type == "thermomech": f.write('** Thermal conductivity unit is kW/mm/K = t*mm/K*s^3\n') f.write('** Specific Heat unit is kJ/t/K = mm^2/s^2/K\n') - for femobj in self.material_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.material_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] mat_obj = femobj['Object'] mat_info_name = mat_obj.Material['Name'] mat_name = mat_obj.Name @@ -619,14 +666,19 @@ class FemInputWriterCcx(writerbase.FemInputWriter): YM = FreeCAD.Units.Quantity(mat_obj.Material['YoungsModulus']) YM_in_MPa = float(YM.getValueAs('MPa')) PR = float(mat_obj.Material['PoissonRatio']) - if self.analysis_type == "frequency" or self.selfweight_objects or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): + if self.analysis_type == "frequency" \ + or self.selfweight_objects \ + or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): density = FreeCAD.Units.Quantity(mat_obj.Material['Density']) density_in_tonne_per_mm3 = float(density.getValueAs('t/mm^3')) if self.analysis_type == "thermomech": TC = FreeCAD.Units.Quantity(mat_obj.Material['ThermalConductivity']) - TC_in_WmK = float(TC.getValueAs('W/m/K')) # SvdW: Add factor to force units to results' base units of t/mm/s/K - W/m/K results in no factor needed + # SvdW: Add factor to force units to results' base units + # of t/mm/s/K - W/m/K results in no factor needed + TC_in_WmK = float(TC.getValueAs('W/m/K')) SH = FreeCAD.Units.Quantity(mat_obj.Material['SpecificHeat']) - SH_in_JkgK = float(SH.getValueAs('J/kg/K')) * 1e+06 # SvdW: Add factor to force units to results' base units of t/mm/s/K + # SvdW: Add factor to force units to results' base units of t/mm/s/K + SH_in_JkgK = float(SH.getValueAs('J/kg/K')) * 1e+06 if mat_obj.Category == 'Solid': TEC = FreeCAD.Units.Quantity(mat_obj.Material['ThermalExpansionCoefficient']) TEC_in_mmK = float(TEC.getValueAs('mm/mm/K')) @@ -641,7 +693,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('*ELASTIC\n') f.write('{0:.0f}, {1:.3f}\n'.format(YM_in_MPa, PR)) - if self.analysis_type == "frequency" or self.selfweight_objects or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): + if self.analysis_type == "frequency" \ + or self.selfweight_objects \ + or (self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState): f.write('*DENSITY\n') f.write('{0:.3e}\n'.format(density_in_tonne_per_mm3)) if self.analysis_type == "thermomech": @@ -658,7 +712,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # nonlinear material properties if self.solver_obj.MaterialNonlinearity == 'nonlinear': - for femobj in self.material_nonlinear_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.material_nonlinear_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] nl_mat_obj = femobj['Object'] if nl_mat_obj.LinearBaseMaterial == mat_obj: if nl_mat_obj.MaterialModelNonlinearity == "simple hardening": @@ -678,7 +733,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('*INITIAL CONDITIONS,TYPE=TEMPERATURE\n') for itobj in self.initialtemperature_objects: # Should only be one inittemp_obj = itobj['Object'] - f.write('{0},{1}\n'.format(self.ccx_nall, inittemp_obj.initialTemperature)) # OvG: Initial temperature + # OvG: Initial temperature + f.write('{0},{1}\n'.format(self.ccx_nall, inittemp_obj.initialTemperature)) def write_femelementsets(self, f): f.write('\n***********************************************************\n') @@ -696,21 +752,45 @@ class FemInputWriterCcx(writerbase.FemInputWriter): width = beamsec_obj.RectWidth.getValueAs('mm') section_type = ', SECTION=RECT' setion_geo = str(height) + ', ' + str(width) + '\n' - setion_def = '*BEAM SECTION, ' + elsetdef + material + section_type + '\n' - setion_nor = str(normal[0]) + ', ' + str(normal[1]) + ', ' + str(normal[2]) + '\n' + setion_def = '*BEAM SECTION, {}{}{}\n'.format( + elsetdef, + material, + section_type + ) + setion_nor = '{}, {}, {}\n'.format( + normal[0], + normal[1], + normal[2] + ) elif beamsec_obj.SectionType == 'Circular': radius = 0.5 * beamsec_obj.CircDiameter.getValueAs('mm') section_type = ', SECTION=CIRC' setion_geo = str(radius) + '\n' - setion_def = '*BEAM SECTION, ' + elsetdef + material + section_type + '\n' - setion_nor = str(normal[0]) + ', ' + str(normal[1]) + ', ' + str(normal[2]) + '\n' + setion_def = '*BEAM SECTION, {}{}{}\n'.format( + elsetdef, + material, + section_type + ) + setion_nor = '{}, {}, {}\n'.format( + normal[0], + normal[1], + normal[2] + ) elif beamsec_obj.SectionType == 'Pipe': radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs('mm') thickness = beamsec_obj.PipeThickness.getValueAs('mm') section_type = ', SECTION=PIPE' setion_geo = str(radius) + ', ' + str(thickness) + '\n' - setion_def = '*BEAM GENERAL SECTION, ' + elsetdef + material + section_type + '\n' - setion_nor = str(normal[0]) + ', ' + str(normal[1]) + ', ' + str(normal[2]) + '\n' + setion_def = '*BEAM GENERAL SECTION, {}{}{}\n'.format( + elsetdef, + material, + section_type + ) + setion_nor = '{}, {}, {}\n'.format( + normal[0], + normal[1], + normal[2] + ) f.write(setion_def) f.write(setion_geo) f.write(setion_nor) @@ -722,7 +802,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): section_type = fluidsec_obj.LiquidSectionType if (section_type == "PIPE INLET") or (section_type == "PIPE OUTLET"): section_type = "PIPE INOUT" - setion_def = '*FLUID SECTION, ' + elsetdef + 'TYPE=' + section_type + ', ' + material + '\n' + setion_def = '*FLUID SECTION, {}TYPE={}, {}\n'.format( + elsetdef, + section_type, + material + ) setion_geo = liquid_section_def(fluidsec_obj, section_type) elif fluidsec_obj.SectionType == 'Gas': section_type = fluidsec_obj.GasSectionType @@ -752,14 +836,19 @@ class FemInputWriterCcx(writerbase.FemInputWriter): step = '*STEP' if self.solver_obj.GeometricalNonlinearity == "nonlinear": if self.analysis_type == 'static' or self.analysis_type == 'thermomech': - step += ', NLGEOM' # https://www.comsol.com/blogs/what-is-geometric-nonlinearity/ + # https://www.comsol.com/blogs/what-is-geometric-nonlinearity + step += ', NLGEOM' elif self.analysis_type == 'frequency': - FreeCAD.Console.PrintMessage('Analysis type frequency and geometrical nonlinear analysis are not allowed together, linear is used instead!\n') + FreeCAD.Console.PrintMessage( + 'Analysis type frequency and geometrical nonlinear ' + 'analysis are not allowed together, linear is used instead!\n' + ) if self.solver_obj.IterationsThermoMechMaximum: if self.analysis_type == 'thermomech': step += ', INC=' + str(self.solver_obj.IterationsThermoMechMaximum) elif self.analysis_type == 'static' or self.analysis_type == 'frequency': - pass # parameter is for thermomechanical analysis only, see ccx manual *STEP + # parameter is for thermomechanical analysis only, see ccx manual *STEP + pass # write step line f.write(step + '\n') # CONTROLS line @@ -787,34 +876,54 @@ class FemInputWriterCcx(writerbase.FemInputWriter): analysis_type += ', SOLVER=ITERATIVE SCALING' elif self.solver_obj.MatrixSolverType == "iterativecholesky": analysis_type += ', SOLVER=ITERATIVE CHOLESKY' - # analysis line --> user defined incrementations --> parameter DIRECT --> completely switch off ccx automatic incrementation + # analysis line --> user defined incrementations --> parameter DIRECT + # --> completely switch off ccx automatic incrementation if self.solver_obj.IterationsUserDefinedIncrementations: if self.analysis_type == 'static': analysis_type += ', DIRECT' elif self.analysis_type == 'thermomech': analysis_type += ', DIRECT' elif self.analysis_type == 'frequency': - FreeCAD.Console.PrintMessage('Analysis type frequency and IterationsUserDefinedIncrementations are not allowed together, it is ignored\n') + FreeCAD.Console.PrintMessage( + 'Analysis type frequency and IterationsUserDefinedIncrementations ' + 'are not allowed together, it is ignored\n' + ) # analysis line --> steadystate --> thermomech only if self.solver_obj.ThermoMechSteadyState: - if self.analysis_type == 'thermomech': # bernd: I do not know if STEADY STATE is allowed with DIRECT but since time steps are 1.0 it makes no sense IMHO + # bernd: I do not know if STEADY STATE is allowed with DIRECT + # but since time steps are 1.0 it makes no sense IMHO + if self.analysis_type == 'thermomech': analysis_type += ', STEADY STATE' - self.solver_obj.TimeInitialStep = 1.0 # Set time to 1 and ignore user inputs for steady state + # Set time to 1 and ignore user inputs for steady state + self.solver_obj.TimeInitialStep = 1.0 self.solver_obj.TimeEnd = 1.0 elif self.analysis_type == 'static' or self.analysis_type == 'frequency': pass # not supported for static and frequency! # ANALYSIS parameter line analysis_parameter = '' if self.analysis_type == 'static' or self.analysis_type == 'check': - if self.solver_obj.IterationsUserDefinedIncrementations is True or self.solver_obj.IterationsUserDefinedTimeStepLength is True: - analysis_parameter = '{},{}'.format(self.solver_obj.TimeInitialStep, self.solver_obj.TimeEnd) + if self.solver_obj.IterationsUserDefinedIncrementations is True \ + or self.solver_obj.IterationsUserDefinedTimeStepLength is True: + analysis_parameter = '{},{}'.format( + self.solver_obj.TimeInitialStep, + self.solver_obj.TimeEnd + ) elif self.analysis_type == 'frequency': - if self.solver_obj.EigenmodeLowLimit == 0.0 and self.solver_obj.EigenmodeHighLimit == 0.0: + if self.solver_obj.EigenmodeLowLimit == 0.0 \ + and self.solver_obj.EigenmodeHighLimit == 0.0: analysis_parameter = '{}\n'.format(self.solver_obj.EigenmodesCount) else: - analysis_parameter = '{},{},{}\n'.format(self.solver_obj.EigenmodesCount, self.solver_obj.EigenmodeLowLimit, self.solver_obj.EigenmodeHighLimit) + analysis_parameter = '{},{},{}\n'.format( + self.solver_obj.EigenmodesCount, + self.solver_obj.EigenmodeLowLimit, + self.solver_obj.EigenmodeHighLimit + ) elif self.analysis_type == 'thermomech': - analysis_parameter = '{},{}'.format(self.solver_obj.TimeInitialStep, self.solver_obj.TimeEnd) # OvG: 1.0 increment, total time 1 for steady state will cut back automatically + # OvG: 1.0 increment, total time 1 for steady state will cut back automatically + analysis_parameter = '{},{}'.format( + self.solver_obj.TimeInitialStep, + self.solver_obj.TimeEnd + ) # write analysis type line, analysis parameter line f.write(analysis_type + '\n') f.write(analysis_parameter + '\n') @@ -823,10 +932,12 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Fixed Constraints\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.fixed_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.fixed_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] f.write('** ' + femobj['Object'].Label + '\n') fix_obj_name = femobj['Object'].Name - if self.femmesh.Volumes and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): + if self.femmesh.Volumes \ + and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): if len(femobj['NodesSolid']) > 0: f.write('*BOUNDARY\n') f.write(fix_obj_name + 'Solid' + ',1\n') @@ -857,7 +968,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Displacement constraint applied\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.displacement_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.displacement_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] f.write('** ' + femobj['Object'].Label + '\n') disp_obj = femobj['Object'] disp_obj_name = disp_obj.Name @@ -895,7 +1007,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('** Contact Constraints\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) obj = 0 - for femobj in self.contact_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.contact_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] obj = obj + 1 contact_obj = femobj['Object'] f.write('** ' + contact_obj.Label + '\n') @@ -917,7 +1030,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** PlaneRotation Constraints\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.planerotation_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.planerotation_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] f.write('** ' + femobj['Object'].Label + '\n') fric_obj_name = femobj['Object'].Name f.write('*MPC\n') @@ -943,15 +1057,25 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Self weight Constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.selfweight_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.selfweight_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] selwei_obj = femobj['Object'] f.write('** ' + selwei_obj.Label + '\n') f.write('*DLOAD\n') - f.write(self.ccx_eall + ',GRAV,9810,' + str(selwei_obj.Gravity_x) + ',' + str(selwei_obj.Gravity_y) + ',' + str(selwei_obj.Gravity_z) + '\n') + f.write( + '{},GRAV,9810,{},{},{}\n' + .format( + self.ccx_eall, + selwei_obj.Gravity_x, + selwei_obj.Gravity_y, + selwei_obj.Gravity_z + ) + ) f.write('\n') # grav (erdbeschleunigung) is equal for all elements # should be only one constraint - # different element sets for different density are written in the material element sets already + # different element sets for different density + # are written in the material element sets already def write_constraints_force(self, f): # check shape type of reference shape and get node loads @@ -961,7 +1085,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('** Node loads Constraints\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) f.write('*CLOAD\n') - for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.force_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] f.write('** ' + femobj['Object'].Label + '\n') direction_vec = femobj['Object'].DirectionVector for ref_shape in femobj['NodeLoadTable']: @@ -987,7 +1112,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n***********************************************************\n') f.write('** Element + CalculiX face + load in [MPa]\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.pressure_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] prs_obj = femobj['Object'] f.write('** ' + prs_obj.Label + '\n') rev = -1 if prs_obj.Reversed else 1 @@ -997,9 +1123,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for face, fno in ref_shape[1]: if fno > 0: # solid mesh face f.write("{},P{},{}\n".format(face, fno, rev * prs_obj.Pressure)) - elif fno == 0: # on shell mesh face: fno == 0 --> normal of element face == face normal + # on shell mesh face: fno == 0 + # normal of element face == face normal + elif fno == 0: f.write("{},P,{}\n".format(face, rev * prs_obj.Pressure)) - elif fno == -1: # on shell mesh face: fno == -1 --> normal of element face opposite direction face normal + # on shell mesh face: fno == -1 + # normal of element face opposite direction face normal + elif fno == -1: f.write("{},P,{}\n".format(face, -1 * rev * prs_obj.Pressure)) def write_constraints_temperature(self, f): @@ -1016,7 +1146,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('\n') elif fixedtemp_obj.ConstraintType == "CFlux": f.write('*CFLUX\n') - f.write('{},11,{}\n'.format(fixedtemp_obj.Name, fixedtemp_obj.CFlux * 0.001 / NumberOfNodes)) + f.write('{},11,{}\n'.format( + fixedtemp_obj.Name, + fixedtemp_obj.CFlux * 0.001 / NumberOfNodes + )) f.write('\n') def write_constraints_heatflux(self, f): @@ -1035,8 +1168,14 @@ class FemInputWriterCcx(writerbase.FemInputWriter): v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) f.write("** Heat flux on face {}\n".format(elem)) for i in v: - # SvdW: add factor to force heatflux to units system of t/mm/s/K # OvG: Only write out the VolumeIDs linked to a particular face - f.write("{},F{},{},{}\n".format(i[0], i[1], heatflux_obj.AmbientTemp, heatflux_obj.FilmCoef * 0.001)) + # SvdW: add factor to force heatflux to units system of t/mm/s/K + # OvG: Only write out the VolumeIDs linked to a particular face + f.write("{},F{},{},{}\n".format( + i[0], + i[1], + heatflux_obj.AmbientTemp, + heatflux_obj.FilmCoef * 0.001 + )) elif heatflux_obj.ConstraintType == "DFlux": f.write('*DFLUX\n') for o, elem_tup in heatflux_obj.References: @@ -1046,7 +1185,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) f.write("** Heat flux on face {}\n".format(elem)) for i in v: - f.write("{},S{},{}\n".format(i[0], i[1], heatflux_obj.DFlux * 0.001)) + f.write("{},S{},{}\n".format( + i[0], + i[1], + heatflux_obj.DFlux * 0.001 + )) def write_constraints_fluidsection(self, f): f.write('\n***********************************************************\n') @@ -1057,10 +1200,14 @@ class FemInputWriterCcx(writerbase.FemInputWriter): lines = inout_nodes_file.readlines() inout_nodes_file.close() else: - FreeCAD.Console.PrintError("1DFlow inout nodes file not found: " + self.fluid_inout_nodes_file + '\n') + FreeCAD.Console.PrintError( + "1DFlow inout nodes file not found: {}\n" + .format(self.fluid_inout_nodes_file) + ) # get nodes self.get_constraints_fluidsection_nodes() - for femobj in self.fluidsection_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + for femobj in self.fluidsection_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] fluidsection_obj = femobj['Object'] f.write('** ' + fluidsection_obj.Label + '\n') if fluidsection_obj.SectionType == 'Liquid': @@ -1072,15 +1219,27 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for line in lines: b = line.split(',') if int(b[0]) == n and b[3] == 'PIPE INLET\n': - f.write(b[0] + ',2,2,' + str(fluidsection_obj.InletPressure) + '\n') # degree of freedom 2 is for defining pressure + # degree of freedom 2 is for defining pressure + f.write('{},{},{},{}\n'.format( + b[0], + '2', + '2', + fluidsection_obj.InletPressure + )) if fluidsection_obj.InletFlowRateActive is True: f.write('*BOUNDARY,MASS FLOW \n') for n in femobj['Nodes']: for line in lines: b = line.split(',') if int(b[0]) == n and b[3] == 'PIPE INLET\n': - # degree of freedom 1 is for defining flow rate, factor applied to convert unit from kg/s to t/s - f.write(b[1] + ',1,1,' + str(fluidsection_obj.InletFlowRate * 0.001) + '\n') + # degree of freedom 1 is for defining flow rate + # factor applied to convert unit from kg/s to t/s + f.write('{},{},{},{}\n'.format( + b[1], + '1', + '1', + fluidsection_obj.InletFlowRate * 0.001 + )) elif fluidsection_obj.LiquidSectionType == 'PIPE OUTLET': f.write('**Fluid Section Outlet \n') if fluidsection_obj.OutletPressureActive is True: @@ -1089,15 +1248,27 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for line in lines: b = line.split(',') if int(b[0]) == n and b[3] == 'PIPE OUTLET\n': - f.write(b[0] + ',2,2,' + str(fluidsection_obj.OutletPressure) + '\n') # degree of freedom 2 is for defining pressure + # degree of freedom 2 is for defining pressure + f.write('{},{},{},{}\n'.format( + b[0], + '2', + '2', + fluidsection_obj.OutletPressure + )) if fluidsection_obj.OutletFlowRateActive is True: f.write('*BOUNDARY,MASS FLOW \n') for n in femobj['Nodes']: for line in lines: b = line.split(',') if int(b[0]) == n and b[3] == 'PIPE OUTLET\n': - # degree of freedom 1 is for defining flow rate, factor applied to convert unit from kg/s to t/s - f.write(b[1] + ',1,1,' + str(fluidsection_obj.OutletFlowRate * 0.001) + '\n') + # degree of freedom 1 is for defining flow rate + # factor applied to convert unit from kg/s to t/s + f.write('{},{},{},{}\n'.format( + b[1], + '1', + '1', + fluidsection_obj.OutletFlowRate * 0.001 + )) def write_outputs_types(self, f): f.write('\n***********************************************************\n') @@ -1110,7 +1281,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('*NODE FILE, OUTPUT=3d\n') else: f.write('*NODE FILE\n') - if self.analysis_type == "thermomech": # MPH write out nodal temperatures if thermomechanical + # MPH write out nodal temperatures if thermomechanical + if self.analysis_type == "thermomech": if not self.fluidsection_objects: f.write('U, NT\n') else: @@ -1123,7 +1295,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write('S, E, PEEQ\n') else: f.write('S, E\n') - # there is no need to write all integration point results as long as there is no reader for this + # there is no need to write all integration point results + # as long as there is no reader for this # see https://forum.freecadweb.org/viewtopic.php?f=18&t=29060 # f.write('** outputs --> dat file\n') # f.write('*NODE PRINT , NSET=' + self.ccx_nall + '\n') @@ -1139,11 +1312,23 @@ class FemInputWriterCcx(writerbase.FemInputWriter): def write_footer(self, f): f.write('\n***********************************************************\n') f.write('** CalculiX Input file\n') - f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) - f.write('** written by --> FreeCAD ' + self.fc_ver[0] + '.' + self.fc_ver[1] + '.' + self.fc_ver[2] + '\n') - f.write('** written on --> ' + time.ctime() + '\n') - f.write('** file name --> ' + os.path.basename(FreeCAD.ActiveDocument.FileName) + '\n') - f.write('** analysis name --> ' + self.analysis.Name + '\n') + f.write('** written by {} function\n'.format( + sys._getframe().f_code.co_name + )) + f.write('** written by --> FreeCAD {}.{}.{}\n'.format( + self.fc_ver[0], + self.fc_ver[1], + self.fc_ver[2] + )) + f.write('** written on --> {}\n'.format( + time.ctime() + )) + f.write('** file name --> {}\n'.format( + os.path.basename(FreeCAD.ActiveDocument.FileName) + )) + f.write('** analysis name --> {}\n'.format( + self.analysis.Name + )) f.write('**\n') f.write('**\n') f.write('**\n') @@ -1168,14 +1353,20 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # beam # TODO support multiple beamrotations - # we do not need any more any data from the rotation document object, thus we do not need to save the rotation document object name in the else + # we do not need any more any data from the rotation document object, + # thus we do not need to save the rotation document object name in the else def get_ccx_elsets_single_mat_single_beam(self): mat_obj = self.material_objects[0]['Object'] beamsec_obj = self.beamsection_objects[0]['Object'] beamrot_data = self.beamrotation_objects[0] for i, beamdirection in enumerate(beamrot_data['FEMRotations1D']): elset_data = beamdirection['ids'] # ID's for this direction - names = [{'short': 'M0'}, {'short': 'B0'}, {'short': beamrot_data['ShortName']}, {'short': 'D' + str(i)}] + names = [ + {'short': 'M0'}, + {'short': 'B0'}, + {'short': beamrot_data['ShortName']}, + {'short': 'D' + str(i)} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_short(names) @@ -1193,9 +1384,15 @@ class FemInputWriterCcx(writerbase.FemInputWriter): beamsec_ids = set(beamsec_data['FEMElements']) for i, beamdirection in enumerate(beamrot_data['FEMRotations1D']): beamdir_ids = set(beamdirection['ids']) - elset_data = list(sorted(beamsec_ids.intersection(beamdir_ids))) # empty intersection sets possible + # empty intersection sets possible + elset_data = list(sorted(beamsec_ids.intersection(beamdir_ids))) if elset_data: - names = [{'short': 'M0'}, {'short': beamsec_data['ShortName']}, {'short': beamrot_data['ShortName']}, {'short': 'D' + str(i)}] + names = [ + {'short': 'M0'}, + {'short': beamsec_data['ShortName']}, + {'short': beamrot_data['ShortName']}, + {'short': 'D' + str(i)} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_short(names) @@ -1215,14 +1412,20 @@ class FemInputWriterCcx(writerbase.FemInputWriter): beamdir_ids = set(beamdirection['ids']) elset_data = list(sorted(mat_ids.intersection(beamdir_ids))) if elset_data: - names = [{'short': mat_data['ShortName']}, {'short': 'B0'}, {'short': beamrot_data['ShortName']}, {'short': 'D' + str(i)}] + names = [ + {'short': mat_data['ShortName']}, + {'short': 'B0'}, + {'short': beamrot_data['ShortName']}, + {'short': 'D' + str(i)} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_short(names) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] ccx_elset['beamsection_obj'] = beamsec_obj - ccx_elset['beam_normal'] = beamdirection['normal'] # normal for this direction + # normal for this direction + ccx_elset['beam_normal'] = beamdirection['normal'] self.ccx_elsets.append(ccx_elset) def get_ccx_elsets_multiple_mat_multiple_beam(self): @@ -1235,16 +1438,25 @@ class FemInputWriterCcx(writerbase.FemInputWriter): mat_ids = set(mat_data['FEMElements']) for i, beamdirection in enumerate(beamrot_data['FEMRotations1D']): beamdir_ids = set(beamdirection['ids']) - elset_data = list(sorted(beamsec_ids.intersection(mat_ids).intersection(beamdir_ids))) # empty intersection sets possible + # empty intersection sets possible + elset_data = list(sorted( + beamsec_ids.intersection(mat_ids).intersection(beamdir_ids) + )) if elset_data: - names = [{'short': mat_data['ShortName']}, {'short': beamsec_data['ShortName']}, {'short': beamrot_data['ShortName']}, {'short': 'D' + str(i)}] + names = [ + {'short': mat_data['ShortName']}, + {'short': beamsec_data['ShortName']}, + {'short': beamrot_data['ShortName']}, + {'short': 'D' + str(i)} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_short(names) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] ccx_elset['beamsection_obj'] = beamsec_obj - ccx_elset['beam_normal'] = beamdirection['normal'] # normal for this direction + # normal for this direction + ccx_elset['beam_normal'] = beamdirection['normal'] self.ccx_elsets.append(ccx_elset) # fluid @@ -1296,9 +1508,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): mat_obj = mat_data['Object'] fluidsec_ids = set(fluidsec_data['FEMElements']) mat_ids = set(mat_data['FEMElements']) - elset_data = list(sorted(fluidsec_ids.intersection(mat_ids))) # empty intersection sets possible + # empty intersection sets possible + elset_data = list(sorted(fluidsec_ids.intersection(mat_ids))) if elset_data: - names = [{'short': mat_data['ShortName']}, {'short': fluidsec_data['ShortName']}] + names = [ + {'short': mat_data['ShortName']}, + {'short': fluidsec_data['ShortName']} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_short(names) @@ -1312,7 +1528,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): mat_obj = self.material_objects[0]['Object'] shellth_obj = self.shellthickness_objects[0]['Object'] elset_data = self.ccx_efaces - names = [{'long': mat_obj.Name, 'short': 'M0'}, {'long': shellth_obj.Name, 'short': 'S0'}] + names = [ + {'long': mat_obj.Name, 'short': 'M0'}, + {'long': shellth_obj.Name, 'short': 'S0'} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1326,7 +1545,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for shellth_data in self.shellthickness_objects: shellth_obj = shellth_data['Object'] elset_data = shellth_data['FEMElements'] - names = [{'long': mat_obj.Name, 'short': 'M0'}, {'long': shellth_obj.Name, 'short': shellth_data['ShortName']}] + names = [ + {'long': mat_obj.Name, 'short': 'M0'}, + {'long': shellth_obj.Name, 'short': shellth_data['ShortName']} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1340,7 +1562,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for mat_data in self.material_objects: mat_obj = mat_data['Object'] elset_data = mat_data['FEMElements'] - names = [{'long': mat_obj.Name, 'short': mat_data['ShortName']}, {'long': shellth_obj.Name, 'short': 'S0'}] + names = [ + {'long': mat_obj.Name, 'short': mat_data['ShortName']}, + {'long': shellth_obj.Name, 'short': 'S0'} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1356,9 +1581,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): mat_obj = mat_data['Object'] shellth_ids = set(shellth_data['FEMElements']) mat_ids = set(mat_data['FEMElements']) - elset_data = list(sorted(shellth_ids.intersection(mat_ids))) # empty intersection sets possible + # empty intersection sets possible + elset_data = list(sorted(shellth_ids.intersection(mat_ids))) if elset_data: - names = [{'long': mat_obj.Name, 'short': mat_data['ShortName']}, {'long': shellth_obj.Name, 'short': shellth_data['ShortName']}] + names = [ + {'long': mat_obj.Name, 'short': mat_data['ShortName']}, + {'long': shellth_obj.Name, 'short': shellth_data['ShortName']} + ] ccx_elset = {} ccx_elset['ccx_elset'] = ccx_elset ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1371,7 +1600,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): def get_ccx_elsets_single_mat_solid(self): mat_obj = self.material_objects[0]['Object'] elset_data = self.ccx_evolumes - names = [{'long': mat_obj.Name, 'short': 'M0'}, {'long': 'Solid', 'short': 'Solid'}] + names = [ + {'long': mat_obj.Name, 'short': 'M0'}, + {'long': 'Solid', 'short': 'Solid'} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1383,7 +1615,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for mat_data in self.material_objects: mat_obj = mat_data['Object'] elset_data = mat_data['FEMElements'] - names = [{'long': mat_obj.Name, 'short': mat_data['ShortName']}, {'long': 'Solid', 'short': 'Solid'}] + names = [ + {'long': mat_obj.Name, 'short': mat_data['ShortName']}, + {'long': 'Solid', 'short': 'Solid'} + ] ccx_elset = {} ccx_elset['ccx_elset'] = elset_data ccx_elset['ccx_elset_name'] = get_ccx_elset_name_standard(names) @@ -1393,7 +1628,14 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # Helpers -# ccx elset names: M .. Material, B .. Beam, R .. BeamRotation, D ..Direction, F .. Fluid, S .. Shell, TODO write comment into input file to elset ids and elset attributes +# ccx elset names: +# M .. Material +# B .. Beam +# R .. BeamRotation +# D ..Direction +# F .. Fluid +# S .. Shell, +# TODO write comment into input file to elset ids and elset attributes def get_ccx_elset_name_standard(names): # standard max length = 80 ccx_elset_name = '' @@ -1408,7 +1650,11 @@ def get_ccx_elset_name_standard(names): if len(ccx_elset_name) < 81: return ccx_elset_name else: - error = 'FEM: Trouble in ccx input file, because an elset name is longer than 80 character!' + ' ' + ccx_elset_name + '\n' + error = ( + 'FEM: Trouble in ccx input file, because an ' + 'elset name is longer than 80 character! {}\n' + .format(ccx_elset_name) + ) raise Exception(error) @@ -1420,7 +1666,11 @@ def get_ccx_elset_name_short(names): if len(ccx_elset_name) < 21: return ccx_elset_name else: - error = 'FEM: Trouble in ccx input file, because a beam elset name is longer than 20 character!' + ' ' + ccx_elset_name + '\n' + error = ( + 'FEM: Trouble in ccx input file, because an' + 'beam elset name is longer than 20 character! {}\n' + .format(ccx_elset_name) + ) raise Exception(error) @@ -1432,7 +1682,8 @@ def is_fluid_section_inlet_outlet(ccx_elsets): if 'fluidsection_obj'in ccx_elset: # fluid mesh fluidsec_obj = ccx_elset['fluidsection_obj'] if fluidsec_obj.SectionType == "Liquid": - if (fluidsec_obj.LiquidSectionType == "PIPE INLET") or (fluidsec_obj.LiquidSectionType == "PIPE OUTLET"): + if (fluidsec_obj.LiquidSectionType == "PIPE INLET") \ + or (fluidsec_obj.LiquidSectionType == "PIPE OUTLET"): return True return False @@ -1469,7 +1720,12 @@ def liquid_section_def(obj, section_type): bend_radius_diameter = str(obj.BendRadiusDiameter) bend_angle = str(obj.BendAngle) bend_loss_coefficient = str(obj.BendLossCoefficient) - section_geo = bend_pipe_area + ',' + bend_radius_diameter + ',' + bend_angle + ',' + bend_loss_coefficient + '\n' + section_geo = ('{},{},{},{}\n'.format( + bend_pipe_area, + bend_radius_diameter, + bend_angle, + bend_loss_coefficient + )) return section_geo elif section_type == 'PIPE GATE VALVE': gatevalve_pipe_area = str(obj.GateValvePipeArea.getValueAs('mm^2').Value) @@ -1481,7 +1737,13 @@ def liquid_section_def(obj, section_type): colebrooke_diameter = str(2 * obj.ColebrookeRadius.getValueAs('mm')) colebrooke_grain_diameter = str(obj.ColebrookeGrainDiameter.getValueAs('mm')) colebrooke_form_factor = str(obj.ColebrookeFormFactor) - section_geo = colebrooke_area + ',' + colebrooke_diameter + ',-1,' + colebrooke_grain_diameter + ',' + colebrooke_form_factor + '\n' + section_geo = ('{},{},{},{},{}\n'.format( + colebrooke_area, + colebrooke_diameter, + '-1', + colebrooke_grain_diameter, + colebrooke_form_factor + )) return section_geo elif section_type == 'LIQUID PUMP': section_geo = '' diff --git a/src/Mod/Fem/femsolver/elmer/sifio.py b/src/Mod/Fem/femsolver/elmer/sifio.py index d7c496fe48..c5c0674f54 100644 --- a/src/Mod/Fem/femsolver/elmer/sifio.py +++ b/src/Mod/Fem/femsolver/elmer/sifio.py @@ -398,14 +398,16 @@ class _Writer(object): return _TYPE_INTEGER if issubclass(dataType, float): return _TYPE_REAL - if issubclass(dataType, six.string_types): # use six to be sure to be Python 2.7 and 3.x compatible + # use six to be sure to be Python 2.7 and 3.x compatible + if issubclass(dataType, six.string_types): return _TYPE_STRING raise ValueError("Unsupported data type: %s" % dataType) def _preprocess(self, data, dataType): if issubclass(dataType, Section): return str(self._idMgr.getId(data)) - if issubclass(dataType, six.string_types): # use six to be sure to be Python 2.7 and 3.x compatible + # use six to be sure to be Python 2.7 and 3.x compatible + if issubclass(dataType, six.string_types): return '"%s"' % data return str(data) diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index 4566547676..3fc5a10a4d 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -266,7 +266,8 @@ class Writer(object): if obj is not None: for name in bodies: heatSource = getFromUi(obj.HeatSource, "W/kg", "L^2*T^-3") - # according Elmer forum W/kg is correct, http://www.elmerfem.org/forum/viewtopic.php?f=7&t=1765 + # according Elmer forum W/kg is correct + # http://www.elmerfem.org/forum/viewtopic.php?f=7&t=1765 # 1 watt = kg * m2 / s3 ... W/kg = m2 / s3 self._bodyForce(name, "Heat Source", heatSource) self._handled(obj) @@ -479,7 +480,9 @@ class Writer(object): densityQuantity = Units.Quantity(m["Density"]) dimension = "M/L^3" if name.startswith("Edge"): - density = None # not tested, but it seems needed because denisty does not exist (IMHO, bernd) + # not tested, but it seems needed + # because denisty does not exist (IMHO, bernd) + density = None if density: density.Unit = Units.Unit(-2, 1) dimension = "M/L^2" diff --git a/src/Mod/Fem/femsolver/fenics/fenics_tools.py b/src/Mod/Fem/femsolver/fenics/fenics_tools.py index 7e537e3578..b609a3e7f3 100644 --- a/src/Mod/Fem/femsolver/fenics/fenics_tools.py +++ b/src/Mod/Fem/femsolver/fenics/fenics_tools.py @@ -65,7 +65,14 @@ else: xdmffile.read(self.mesh) xdmffile.close() - def readCellExpression(self, group_value_dict, value_type="scalar", overlap=lambda x: x[0], *args, **kwargs): + def readCellExpression( + self, + group_value_dict, + value_type="scalar", + overlap=lambda x: x[0], + *args, + **kwargs + ): """ Reads cell expression and returns it. """ @@ -76,14 +83,24 @@ else: self.readMesh() xdmffile = fenics.XDMFFile(self.xdmffilename) - cf = value_type_dictionary[value_type.lower()](group_value_dict, - overlap=overlap, - *args, **kwargs) + cf = value_type_dictionary[value_type.lower()]( + group_value_dict, + overlap=overlap, + *args, **kwargs + ) cf.init() for (key, value) in cf.group_value_dict.items(): - cf.markers[key] = fenics.MeshFunction("size_t", self.mesh, self.mesh.topology().dim()) + cf.markers[key] = fenics.MeshFunction( + "size_t", + self.mesh, + self.mesh.topology().dim() + ) xdmffile.read(cf.markers[key], key) - cf.dx[key] = fenics.Measure("dx", domain=self.mesh, subdomain_data=cf.markers[key]) + cf.dx[key] = fenics.Measure( + "dx", + domain=self.mesh, + subdomain_data=cf.markers[key] + ) xdmffile.close() return cf @@ -96,10 +113,18 @@ else: ff = FacetFunctionFromXDMF(group_value_dict, *args, **kwargs) ff.init() for (key, value) in ff.group_value_dict.items(): - ff.markers[key] = fenics.MeshFunction("size_t", self.mesh, self.mesh.topology().dim() - 1) + ff.markers[key] = fenics.MeshFunction( + "size_t", + self.mesh, + self.mesh.topology().dim() - 1 + ) xdmffile.read(ff.markers[key], key) ff.marked[key] = value.get("marked", 1) - ff.ds[key] = fenics.Measure("ds", domain=self.mesh, subdomain_data=ff.markers[key]) + ff.ds[key] = fenics.Measure( + "ds", + domain=self.mesh, + subdomain_data=ff.markers[key] + ) ff.bcs[key] = value xdmffile.close() return ff @@ -108,10 +133,13 @@ else: """ Creates cell function expression from XDMF file. """ - def __init__(self, group_value_dict, - default=lambda x: 0., - check_marked=(lambda x: x == 1), overlap=lambda x: x[0], - **kwargs): + def __init__( + self, group_value_dict, + default=lambda x: 0., + check_marked=(lambda x: x == 1), + overlap=lambda x: x[0], + **kwargs + ): self.init() self.group_value_dict = group_value_dict self.check_marked = check_marked @@ -127,8 +155,10 @@ else: def eval_cell_backend(self, values, x, cell): - values_list = [func(x) for (key, func) in self.group_value_dict.items() - if self.check_marked(self.markers[key][cell.index])] + values_list = [ + func(x) for (key, func) in self.group_value_dict.items() + if self.check_marked(self.markers[key][cell.index]) + ] return_value = self.overlap(values_list) if values_list: @@ -146,13 +176,20 @@ else: class ScalarCellExpressionFromXDMF(fenics.Expression, CellExpressionFromXDMF): - def __init__(self, group_value_dict, - default=lambda x: 0., - check_marked=(lambda x: x == 1), overlap=lambda x: x[0], **kwargs): - CellExpressionFromXDMF.__init__(self, group_value_dict, - default=default, - check_marked=check_marked, - overlap=overlap) + def __init__( + self, + group_value_dict, + default=lambda x: 0., + check_marked=(lambda x: x == 1), + overlap=lambda x: x[0], + **kwargs + ): + CellExpressionFromXDMF.__init__( + self, group_value_dict, + default=default, + check_marked=check_marked, + overlap=overlap + ) def eval_cell(self, values, x, cell): self.eval_cell_backend(values, x, cell) @@ -162,13 +199,19 @@ else: class Vector3DCellExpressionFromXDMF(fenics.Expression, CellExpressionFromXDMF): - def __init__(self, group_value_dict, - default=lambda x: np.zeros((3,)), - check_marked=(lambda x: x == 1), overlap=lambda x: x[0], **kwargs): - CellExpressionFromXDMF.__init__(self, group_value_dict, - default=default, - check_marked=check_marked, - overlap=overlap) + def __init__( + self, + group_value_dict, + default=lambda x: np.zeros((3,)), + check_marked=(lambda x: x == 1), + overlap=lambda x: x[0], **kwargs + ): + CellExpressionFromXDMF.__init__( + self, group_value_dict, + default=default, + check_marked=check_marked, + overlap=overlap + ) def eval_cell(self, values, x, cell): self.eval_cell_backend(values, x, cell) @@ -178,13 +221,21 @@ else: class Vector2DCellExpressionFromXDMF(fenics.Expression, CellExpressionFromXDMF): - def __init__(self, group_value_dict, - default=lambda x: np.zeros((2,)), - check_marked=(lambda x: x == 1), overlap=lambda x: x[0], **kwargs): - CellExpressionFromXDMF.__init__(self, group_value_dict, - default=default, - check_marked=check_marked, - overlap=overlap) + def __init__( + self, + group_value_dict, + default=lambda x: np.zeros((2,)), + check_marked=(lambda x: x == 1), + overlap=lambda x: x[0], + **kwargs + ): + CellExpressionFromXDMF.__init__( + self, + group_value_dict, + default=default, + check_marked=check_marked, + overlap=overlap + ) def eval_cell(self, values, x, cell): self.eval_cell_backend(values, x, cell) @@ -210,7 +261,13 @@ else: dbcs = [] for (dict_key, dict_value) in self.bcs.items(): if dict_value["type"] == "Dirichlet": - bc = fenics.DirichletBC(vectorspace, dict_value["value"], self.markers[dict_key], dict_value.get("marked", 1), *args, **kwargs) + bc = fenics.DirichletBC( + vectorspace, + dict_value["value"], + self.markers[dict_key], + dict_value.get("marked", 1), + *args, **kwargs + ) dbcs.append(bc) return dbcs # TODO: write some functions to return integrals for Neumann and Robin diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index 1784f05584..9146586b60 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -65,7 +65,8 @@ class _SolverDlg(object): def get_binary(self): - # set the binary path to the FreeCAD defaults, ATM pure unix shell commands without path names are used + # set the binary path to the FreeCAD defaults + # ATM pure unix shell commands without path names are used # TODO see todo on use_default later in this module binary = self.default FreeCAD.Console.PrintLog('Solver binary path: {} \n'.format(binary)) @@ -86,12 +87,14 @@ class _SolverDlg(object): ''' default: - default command to run the binary, this one is taken if the UseStandardXXXLocation is not given or set to True + default command to run the binary + this one is taken if the UseStandardXXXLocationis not given or set to True param: path where these settings are saved, in FEM normally one path in one Tab in Preferences GUI use_default: the UseStandardXXXLocation parameter identifier - if this parameter is set to True FreeCAD standards for the binary are used, or FreeCAD tries to find the binary + if this parameter is set to True FreeCAD standards + for the binary are usedor FreeCAD tries to find the binary TODO: see method setup_ccx in ccx tools module, which sets up ccx binary for various os custom_path: the xxxBinaryPath parameter identifier @@ -128,7 +131,9 @@ def get_binary(name): return binary else: FreeCAD.Console.PrintError( - 'Settings solver name: {} not found in solver settings modules _SOLVER_PARAM dirctionary.\n'.format(name) + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) ) return None @@ -138,7 +143,9 @@ def get_write_comments(name): return _SOLVER_PARAM[name].get_write_comments() else: FreeCAD.Console.PrintError( - 'Settings solver name: {} not found in solver settings modules _SOLVER_PARAM dirctionary.\n'.format(name) + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) ) return None diff --git a/src/Mod/Fem/femsolver/writerbase.py b/src/Mod/Fem/femsolver/writerbase.py index 34112bc3f4..5cba2601bc 100644 --- a/src/Mod/Fem/femsolver/writerbase.py +++ b/src/Mod/Fem/femsolver/writerbase.py @@ -82,8 +82,13 @@ class FemInputWriter(): # if dir_name was not given or if it exists but isn't empty: create a temporary dir # Purpose: makes sure the analysis can be run even on wired situation if not dir_name: - FreeCAD.Console.PrintError('Error: FemInputWriter has no working_dir --> we are going to make a temporary one!\n') - self.dir_name = FreeCAD.ActiveDocument.TransientDir.replace('\\', '/') + '/FemAnl_' + analysis_obj.Uid[-4:] + FreeCAD.Console.PrintError( + 'Error: FemInputWriter has no working_dir --> ' + 'we are going to make a temporary one!\n' + ) + self.dir_name = FreeCAD.ActiveDocument.TransientDir.replace( + '\\', '/' + ) + '/FemAnl_' + analysis_obj.Uid[-4:] if not os.path.isdir(self.dir_name): os.mkdir(self.dir_name) @@ -102,7 +107,9 @@ class FemInputWriter(): self.theshape = self.mesh_object.Part self.femmesh = self.mesh_object.FemMesh else: - FreeCAD.Console.PrintError('No finite elemente mesh object was given to the writer class. In rare cases this might not be an error.\n') + FreeCAD.Console.PrintError( + 'No finite elemente mesh object was given to the writer class. ' + 'In rare cases this might not be an error.\n') self.femnodes_mesh = {} self.femelement_table = {} self.constraint_conflict_nodes = [] @@ -116,18 +123,29 @@ class FemInputWriter(): def get_constraints_fixed_nodes(self): # get nodes - for femobj in self.fixed_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint fixed:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.fixed_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint fixed:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) # add nodes to constraint_conflict_nodes, needed by constraint plane rotation for node in femobj['Nodes']: self.constraint_conflict_nodes.append(node) - # if mixed mesh with solids the node set needs to be split because solid nodes do not have rotational degree of freedom - if self.femmesh.Volumes and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): + # if mixed mesh with solids the node set needs to be split + # because solid nodes do not have rotational degree of freedom + if self.femmesh.Volumes \ + and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): print('We need to find the solid nodes.') if not self.femelement_volumes_table: - self.femelement_volumes_table = meshtools.get_femelement_volumes_table(self.femmesh) - for femobj in self.fixed_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + self.femelement_volumes_table = meshtools.get_femelement_volumes_table( + self.femmesh + ) + for femobj in self.fixed_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] nds_solid = [] nds_faceedge = [] for n in femobj['Nodes']: @@ -144,77 +162,145 @@ class FemInputWriter(): def get_constraints_displacement_nodes(self): # get nodes - for femobj in self.displacement_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint displacement:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.displacement_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint displacement:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) # add nodes to constraint_conflict_nodes, needed by constraint plane rotation for node in femobj['Nodes']: self.constraint_conflict_nodes.append(node) def get_constraints_planerotation_nodes(self): # get nodes - for femobj in self.planerotation_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint plane rotation:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.planerotation_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint plane rotation:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) def get_constraints_transform_nodes(self): # get nodes - for femobj in self.transform_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint transform nodes:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.transform_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint transform nodes:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) def get_constraints_temperature_nodes(self): # get nodes - for femobj in self.temperature_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint temperature:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.temperature_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint temperature:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) def get_constraints_fluidsection_nodes(self): # get nodes - for femobj in self.fluidsection_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint fluid section:" + ' ' + femobj['Object'].Name + '\n') - femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj) + for femobj in self.fluidsection_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint fluid section:" + ' ' + femobj['Object'].Name + '\n' + ) + femobj['Nodes'] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) def get_constraints_force_nodeloads(self): # check shape type of reference shape - for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint force:" + ' ' + femobj['Object'].Name + '\n') + for femobj in self.force_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint force:" + ' ' + femobj['Object'].Name + '\n' + ) frc_obj = femobj['Object'] if femobj['RefShapeType'] == 'Vertex': - # print("load on vertices --> we do not need the femelement_table and femnodes_mesh for node load calculation") - pass - elif femobj['RefShapeType'] == 'Face' and meshtools.is_solid_femmesh(self.femmesh) and not meshtools.has_no_face_data(self.femmesh): - # print("solid_mesh with face data --> we do not need the femelement_table but we need the femnodes_mesh for node load calculation") + FreeCAD.Console.PrintLog( + "load on vertices --> we do not need the " + "femelement_table and femnodes_mesh for node load calculation" + ) + elif femobj['RefShapeType'] == 'Face' \ + and meshtools.is_solid_femmesh(self.femmesh) \ + and not meshtools.has_no_face_data(self.femmesh): + FreeCAD.Console.PrintLog( + "solid_mesh with face data --> we do not need the " + "femelement_table but we need the femnodes_mesh for node load calculation" + ) if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes else: - # print("mesh without needed data --> we need the femelement_table and femnodes_mesh for node load calculation") + FreeCAD.Console.PrintLog( + "mesh without needed data --> we need the " + "femelement_table and femnodes_mesh for node load calculation" + ) if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: - self.femelement_table = meshtools.get_femelement_table(self.femmesh) + self.femelement_table = meshtools.get_femelement_table( + self.femmesh + ) # get node loads - FreeCAD.Console.PrintMessage(" Finite element mesh nodes will be retrieved by searching the appropriate nodes in the finite element mesh.\n") - FreeCAD.Console.PrintMessage(" The appropriate finite element mesh node load values will be calculated according to the finite element definition.\n") - for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + " Finite element mesh nodes will be retrieved by searching " + "the appropriate nodes in the finite element mesh.\n" + ) + FreeCAD.Console.PrintMessage( + " The appropriate finite element mesh node load values will " + "be calculated according to the finite element definition.\n" + ) + for femobj in self.force_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] frc_obj = femobj['Object'] if frc_obj.Force == 0: FreeCAD.Console.PrintMessage(' Warning --> Force = 0\n') if femobj['RefShapeType'] == 'Vertex': # point load on vertices - femobj['NodeLoadTable'] = meshtools.get_force_obj_vertex_nodeload_table(self.femmesh, frc_obj) + femobj['NodeLoadTable'] = meshtools.get_force_obj_vertex_nodeload_table( + self.femmesh, + frc_obj + ) elif femobj['RefShapeType'] == 'Edge': # line load on edges - femobj['NodeLoadTable'] = meshtools.get_force_obj_edge_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) + femobj['NodeLoadTable'] = meshtools.get_force_obj_edge_nodeload_table( + self.femmesh, + self.femelement_table, + self.femnodes_mesh, frc_obj + ) elif femobj['RefShapeType'] == 'Face': # area load on faces - femobj['NodeLoadTable'] = meshtools.get_force_obj_face_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) + femobj['NodeLoadTable'] = meshtools.get_force_obj_face_nodeload_table( + self.femmesh, + self.femelement_table, + self.femnodes_mesh, frc_obj + ) def get_constraints_pressure_faces(self): - # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ... + # TODO see comments in get_constraints_force_nodeloads() + # it applies here too. Mhh it applies to all constraints ... ''' # depreciated version # get the faces and face numbers - for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - femobj['PressureFaces'] = meshtools.get_pressure_obj_faces_depreciated(self.femmesh, femobj) + for femobj in self.pressure_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + femobj['PressureFaces'] = meshtools.get_pressure_obj_faces_depreciated( + self.femmesh, + femobj + ) # print(femobj['PressureFaces']) ''' @@ -223,11 +309,21 @@ class FemInputWriter(): if not self.femelement_table: self.femelement_table = meshtools.get_femelement_table(self.femmesh) if not self.femnodes_ele_table: - self.femnodes_ele_table = meshtools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) + self.femnodes_ele_table = meshtools.get_femnodes_ele_table( + self.femnodes_mesh, + self.femelement_table + ) - for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] - FreeCAD.Console.PrintMessage("Constraint pressure: " + femobj['Object'].Name + '\n') - pressure_faces = meshtools.get_pressure_obj_faces(self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj) + for femobj in self.pressure_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] + FreeCAD.Console.PrintMessage( + "Constraint pressure: " + femobj['Object'].Name + '\n' + ) + pressure_faces = meshtools.get_pressure_obj_faces( + self.femmesh, + self.femelement_table, + self.femnodes_ele_table, femobj + ) femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load', pressure_faces)] FreeCAD.Console.PrintLog('{}\n'.format(femobj['PressureFaces'])) @@ -235,42 +331,74 @@ class FemInputWriter(): # get element ids and write them into the objects FreeCAD.Console.PrintMessage('Shell thicknesses\n') if not self.femelement_faces_table: - self.femelement_faces_table = meshtools.get_femelement_faces_table(self.femmesh) - meshtools.get_femelement_sets(self.femmesh, self.femelement_faces_table, self.shellthickness_objects) + self.femelement_faces_table = meshtools.get_femelement_faces_table( + self.femmesh + ) + meshtools.get_femelement_sets( + self.femmesh, + self.femelement_faces_table, + self.shellthickness_objects + ) def get_element_geometry1D_elements(self): # get element ids and write them into the objects FreeCAD.Console.PrintMessage('Beam sections\n') if not self.femelement_edges_table: - self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh) - meshtools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.beamsection_objects) + self.femelement_edges_table = meshtools.get_femelement_edges_table( + self.femmesh + ) + meshtools.get_femelement_sets( + self.femmesh, + self.femelement_edges_table, + self.beamsection_objects + ) def get_element_rotation1D_elements(self): # get for each geometry edge direction the element ids and rotation norma FreeCAD.Console.PrintMessage('Beam rotations\n') if not self.femelement_edges_table: - self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh) - meshtools.get_femelement_direction1D_set(self.femmesh, self.femelement_edges_table, self.beamrotation_objects, self.theshape) + self.femelement_edges_table = meshtools.get_femelement_edges_table( + self.femmesh + ) + meshtools.get_femelement_direction1D_set( + self.femmesh, + self.femelement_edges_table, + self.beamrotation_objects, + self.theshape + ) def get_element_fluid1D_elements(self): # get element ids and write them into the objects FreeCAD.Console.PrintMessage('Fluid sections\n') if not self.femelement_edges_table: - self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh) - meshtools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.fluidsection_objects) + self.femelement_edges_table = meshtools.get_femelement_edges_table( + self.femmesh + ) + meshtools.get_femelement_sets( + self.femmesh, + self.femelement_edges_table, + self.fluidsection_objects + ) def get_material_elements(self): - # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects - # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites - # the femelement_table is only calculated for the highest dimension in get_femelement_table + # it only works if either Volumes or Shellthicknesses or Beamsections + # are in the material objects, it means it does not work + # for mixed meshes and multiple materials, this is checked in check_prerequisites + # the femelement_table is only calculated for + # the highest dimension in get_femelement_table FreeCAD.Console.PrintMessage('Materials\n') if self.femmesh.Volumes: - # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis - # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges, + # we only could do this for volumes, if a mesh contains volumes + # we're going to use them in the analysis + # but a mesh could contain the element faces of the volumes as faces + # and the edges of the faces as edges # there we have to check of some geometric objects all_found = False if self.femmesh.GroupCount: - all_found = meshtools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects) + all_found = meshtools.get_femelement_sets_from_group_data( + self.femmesh, + self.material_objects + ) FreeCAD.Console.PrintMessage(all_found) FreeCAD.Console.PrintMessage('\n') if all_found is False: @@ -281,17 +409,38 @@ class FemInputWriter(): if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femnodes_ele_table: - self.femnodes_ele_table = meshtools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) - control = meshtools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table) - if (self.femelement_count_test is True) and (control is False): # we only need to set it, if it is still True + self.femnodes_ele_table = meshtools.get_femnodes_ele_table( + self.femnodes_mesh, + self.femelement_table + ) + control = meshtools.get_femelement_sets( + self.femmesh, + self.femelement_table, + self.material_objects, + self.femnodes_ele_table + ) + # we only need to set it, if it is still True + if (self.femelement_count_test is True) and (control is False): self.femelement_count_test = False if self.shellthickness_objects: if not self.femelement_faces_table: - self.femelement_faces_table = meshtools.get_femelement_faces_table(self.femmesh) - meshtools.get_femelement_sets(self.femmesh, self.femelement_faces_table, self.material_objects) + self.femelement_faces_table = meshtools.get_femelement_faces_table( + self.femmesh + ) + meshtools.get_femelement_sets( + self.femmesh, + self.femelement_faces_table, + self.material_objects + ) if self.beamsection_objects or self.fluidsection_objects: if not self.femelement_edges_table: - self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh) - meshtools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.material_objects) + self.femelement_edges_table = meshtools.get_femelement_edges_table( + self.femmesh + ) + meshtools.get_femelement_sets( + self.femmesh, + self.femelement_edges_table, + self.material_objects + ) ## @} diff --git a/src/Mod/Fem/femsolver/z88/tasks.py b/src/Mod/Fem/femsolver/z88/tasks.py index e3f89eb6e6..45c50f9d36 100644 --- a/src/Mod/Fem/femsolver/z88/tasks.py +++ b/src/Mod/Fem/femsolver/z88/tasks.py @@ -91,7 +91,8 @@ class Solve(run.Solve): def run(self): # AFAIK: z88r needs to be run twice, once in test mode and once in real solve mode # the subprocess was just copied, it seems to work :-) - # TODO: search out for "Vektor GS" and "Vektor KOI" and print values, may be compared with the used ones + # TODO: search out for "Vektor GS" and "Vektor KOI" and print values + # may be compared with the used ones self.pushStatus("Executing test solver...\n") binary = settings.get_binary("Z88") self._process = subprocess.Popen( @@ -159,22 +160,39 @@ class _Container(object): self.mesh = mesh else: if FreeCAD.GuiUp: - QtGui.QMessageBox.critical(None, "Missing prerequisite", message) + QtGui.QMessageBox.critical( + None, + "Missing prerequisite", + message + ) raise Exception(message + '\n') # get member, empty lists are not supported by z88 - self.materials_linear = self.get_several_member('Fem::Material') + # materials + self.materials_linear = self.get_several_member( + 'Fem::Material' + ) self.materials_nonlinear = [] - self.beam_sections = self.get_several_member('Fem::FemElementGeometry1D') + # geometries + self.beam_sections = self.get_several_member( + 'Fem::FemElementGeometry1D' + ) self.beam_rotations = [] self.fluid_sections = [] - self.shell_thicknesses = self.get_several_member('Fem::FemElementGeometry2D') + self.shell_thicknesses = self.get_several_member( + 'Fem::FemElementGeometry2D' + ) + # constraints self.constraints_contact = [] self.constraints_displacement = [] - self.constraints_fixed = self.get_several_member('Fem::ConstraintFixed') - self.constraints_force = self.get_several_member('Fem::ConstraintForce') + self.constraints_fixed = self.get_several_member( + 'Fem::ConstraintFixed' + ) + self.constraints_force = self.get_several_member( + 'Fem::ConstraintForce' + ) self.constraints_heatflux = [] self.constraints_initialtemperature = [] self.constraints_pressure = [] diff --git a/src/Mod/Fem/femsolver/z88/writer.py b/src/Mod/Fem/femsolver/z88/writer.py index ae4103b7f3..930e1041ed 100644 --- a/src/Mod/Fem/femsolver/z88/writer.py +++ b/src/Mod/Fem/femsolver/z88/writer.py @@ -84,8 +84,12 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): ) from os.path import join self.file_name = join(self.dir_name, 'z88') - FreeCAD.Console.PrintLog('FemInputWriterZ88 --> self.dir_name --> ' + self.dir_name + '\n') - FreeCAD.Console.PrintMessage('FemInputWriterZ88 --> self.file_name --> ' + self.file_name + '\n') + FreeCAD.Console.PrintLog( + 'FemInputWriterZ88 --> self.dir_name --> ' + self.dir_name + '\n' + ) + FreeCAD.Console.PrintMessage( + 'FemInputWriterZ88 --> self.file_name --> ' + self.file_name + '\n' + ) def write_z88_input(self): timestart = time.clock() @@ -103,7 +107,10 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() - writing_time_string = "Writing time input file: " + str(round((time.clock() - timestart), 2)) + " seconds" + writing_time_string = ( + "Writing time input file: {} seconds" + .format(round((time.clock() - timestart), 2)) + ) FreeCAD.Console.PrintMessage(writing_time_string + ' \n\n') return self.dir_name @@ -118,7 +125,10 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): z8810 = {'INTORD': '3', 'INTOS': '0', 'IHFLAG': '0', 'ISFLAG': '0'} # hexa20 --> volume10 param = {4: z8804, 24: z8824, 23: z8823, 17: z8817, 16: z8816, 1: z8801, 10: z8810} # elemente 17, 16, 10, INTORD etc ... testen !!! - self.z88_element_type = importZ88Mesh.get_z88_element_type(self.femmesh, self.femelement_table) + self.z88_element_type = importZ88Mesh.get_z88_element_type( + self.femmesh, + self.femelement_table + ) if self.z88_element_type in param: self.z88_elparam = param[self.z88_element_type] else: @@ -129,7 +139,12 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): def write_z88_mesh(self): mesh_file_path = self.file_name + 'i1.txt' f = open(mesh_file_path, 'w') - importZ88Mesh.write_z88_mesh_to_file(self.femnodes_mesh, self.femelement_table, self.z88_element_type, f) + importZ88Mesh.write_z88_mesh_to_file( + self.femnodes_mesh, + self.femelement_table, + self.z88_element_type, + f + ) f.close() def write_z88_contraints(self): @@ -138,7 +153,7 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): # fixed constraints # get nodes self.get_constraints_fixed_nodes() - # write nodes to constraints_data (different from writing to file in ccxInpWriter) + # write nodes to constraints_data (different from writing to file in ccxInpWriter for femobj in self.fixed_objects: for n in femobj['Nodes']: constraints_data.append((n, str(n) + ' 1 2 0\n')) @@ -148,8 +163,10 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): # forces constraints # check shape type of reference shape and get node loads self.get_constraints_force_nodeloads() - # write node loads to constraints_data (a bit different from writing to file for ccxInpWriter) - for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] + # write node loads to constraints_data + # a bit different from writing to file for ccxInpWriter + for femobj in self.force_objects: + # femobj --> dict, FreeCAD document object is femobj['Object'] direction_vec = femobj['Object'].DirectionVector for ref_shape in femobj['NodeLoadTable']: for n in sorted(ref_shape[1]): @@ -210,17 +227,25 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): width = beam_obj.RectWidth.getValueAs('mm') height = beam_obj.RectHeight.getValueAs('mm') area = str(width * height) - elements_data.append('1 ' + str(self.element_count) + ' ' + area + ' 0 0 0 0 0 0 ') - FreeCAD.Console.PrintMessage("Be aware, only trusses are supported for edge meshes!\n") + elements_data.append( + '1 ' + str(self.element_count) + ' ' + area + ' 0 0 0 0 0 0 ' + ) + FreeCAD.Console.PrintMessage( + "Be aware, only trusses are supported for edge meshes!\n" + ) else: FreeCAD.Console.PrintError("Multiple beamsections for Z88 not yet supported!\n") elif FemMeshTools.is_face_femmesh(self.femmesh): if len(self.shellthickness_objects) == 1: thick_obj = self.shellthickness_objects[0]['Object'] thickness = str(thick_obj.Thickness.getValueAs('mm')) - elements_data.append('1 ' + str(self.element_count) + ' ' + thickness + ' 0 0 0 0 0 0 ') + elements_data.append( + '1 ' + str(self.element_count) + ' ' + thickness + ' 0 0 0 0 0 0 ' + ) else: - FreeCAD.Console.PrintError("Multiple thicknesses for Z88 not yet supported!\n") + FreeCAD.Console.PrintError( + "Multiple thicknesses for Z88 not yet supported!\n" + ) elif FemMeshTools.is_solid_femmesh(self.femmesh): elements_data.append('1 ' + str(self.element_count) + ' 0 0 0 0 0 0 0') else: @@ -234,7 +259,11 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): def write_z88_integration_properties(self): integration_data = [] - integration_data.append('1 ' + str(self.element_count) + ' ' + self.z88_elparam['INTORD'] + ' ' + self.z88_elparam['INTOS']) + integration_data.append('1 {} {} {}'.format( + self.element_count, + self.z88_elparam['INTORD'], + self.z88_elparam['INTOS'] + )) integration_properties_file_path = self.file_name + 'int.txt' f = open(integration_properties_file_path, 'w') f.write(str(len(integration_data)) + '\n') @@ -245,8 +274,12 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): def write_z88_solver_parameter(self): global z88_man_template - z88_man_template = z88_man_template.replace("$z88_param_ihflag", str(self.z88_elparam['IHFLAG'])) - z88_man_template = z88_man_template.replace("$z88_param_isflag", str(self.z88_elparam['ISFLAG'])) + z88_man_template = z88_man_template.replace( + "$z88_param_ihflag", str(self.z88_elparam['IHFLAG']) + ) + z88_man_template = z88_man_template.replace( + "$z88_param_isflag", str(self.z88_elparam['ISFLAG']) + ) solver_parameter_file_path = self.file_name + 'man.txt' f = open(solver_parameter_file_path, 'w') f.write(z88_man_template) @@ -256,7 +289,10 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): # self.z88_param_maxgs = 6000000 self.z88_param_maxgs = 50000000 # vierkantrohr global z88_dyn_template - z88_dyn_template = z88_dyn_template.replace("$z88_param_maxgs", str(self.z88_param_maxgs)) + z88_dyn_template = z88_dyn_template.replace( + "$z88_param_maxgs", + str(self.z88_param_maxgs) + ) solver_parameter_file_path = self.file_name + '.dyn' f = open(solver_parameter_file_path, 'w') f.write(z88_dyn_template)