FEM: code formating, max line length < 100, fem solver
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
## @}
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user