FEM: 1DFlow, ccx solver handling

This commit is contained in:
kgoao 2017-02-28 11:50:21 +01:00 committed by wmayer
parent 1e1b9a8726
commit 8bb1df3736
5 changed files with 448 additions and 51 deletions

View File

@ -40,7 +40,7 @@ class FemInputWriter():
contact_obj, planerotation_obj, transform_obj,
selfweight_obj, force_obj, pressure_obj,
temperature_obj, heatflux_obj, initialtemperature_obj,
beamsection_obj, shellthickness_obj,
beamsection_obj, shellthickness_obj, fluidsection_obj,
analysis_type, dir_name
):
self.analysis = analysis_obj
@ -60,6 +60,7 @@ class FemInputWriter():
self.heatflux_objects = heatflux_obj
self.initialtemperature_objects = initialtemperature_obj
self.beamsection_objects = beamsection_obj
self.fluidsection_objects = fluidsection_obj
self.shellthickness_objects = shellthickness_obj
self.analysis_type = analysis_type
self.dir_name = dir_name
@ -108,6 +109,11 @@ class FemInputWriter():
for femobj in self.temperature_objects: # femobj --> dict, FreeCAD document object is femobj['Object']
femobj['Nodes'] = FemMeshTools.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']
femobj['Nodes'] = FemMeshTools.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']

View File

@ -44,7 +44,7 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
contact_obj, planerotation_obj, transform_obj,
selfweight_obj, force_obj, pressure_obj,
temperature_obj, heatflux_obj, initialtemperature_obj,
beamsection_obj, shellthickness_obj,
beamsection_obj, shellthickness_obj, fluidsection_obj,
analysis_type=None, dir_name=None
):
@ -56,10 +56,11 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
contact_obj, planerotation_obj, transform_obj,
selfweight_obj, force_obj, pressure_obj,
temperature_obj, heatflux_obj, initialtemperature_obj,
beamsection_obj, shellthickness_obj,
beamsection_obj, shellthickness_obj, fluidsection_obj,
analysis_type, dir_name)
self.main_file_name = self.mesh_object.Name + '.inp'
self.file_name = self.dir_name + '/' + self.main_file_name
self.FluidInletoutlet_ele = []
print('FemInputWriterCcx --> self.dir_name --> ' + self.dir_name)
print('FemInputWriterCcx --> self.main_file_name --> ' + self.main_file_name)
print('FemInputWriterCcx --> self.file_name --> ' + self.file_name)
@ -79,6 +80,11 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
inpfile = open(self.file_name, 'a')
inpfile.write('\n\n')
# Check to see if fluid sections are in analysis and use D network element type
if self.fluidsection_objects:
inpfile.close()
FemMeshTools.write_D_network_element_to_inputfile(self.file_name)
inpfile = open(self.file_name, 'a')
# node and element sets
self.write_element_sets_material_and_femelement_type(inpfile)
if self.fixed_objects:
@ -100,6 +106,21 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.write_constraints_initialtemperature(inpfile)
self.write_femelementsets(inpfile)
# Fluid section: Inlet and Outlet requires special element definition
if self.fluidsection_objects:
InOuttest = False
for ccx_elset in self.ccx_elsets:
if ccx_elset['ccx_elset']:
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"):
InOuttest = True
if InOuttest is True:
inpfile.close()
FemMeshTools.use_correct_fluidinout_ele_def(self.FluidInletoutlet_ele, self.file_name)
inpfile = open(self.file_name, 'a')
# constraints independent from steps
if self.planerotation_objects:
self.write_constraints_planerotation(inpfile)
@ -138,6 +159,8 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.write_constraints_temperature(inpfile)
if self.heatflux_objects:
self.write_constraints_heatflux(inpfile)
if self.fluidsection_objects:
self.write_constraints_fluidsection(inpfile)
# output and step end
self.write_outputs_types(inpfile)
@ -155,7 +178,7 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
# 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.close()
inpfileMain = open(self.file_name, 'a')
inpfileMain.write('\n\n')
@ -163,9 +186,15 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
name = self.file_name[:-4]
include_name = self.main_file_name[:-4]
inpfileNodesElem = open(name + "_Node_Elem_sets.inp", 'w')
self.femmesh.writeABAQUS(name + "_Node_Elem_sets.inp")
inpfileNodesElem.close
inpfileNodesElem = open(name + "_Node_Elem_sets.inp", 'a')
inpfileNodesElem.write('\n***********************************************************\n')
inpfileNodesElem.close()
# Check to see if fluid sections are in analysis and use D network element type
if self.fluidsection_objects:
FemMeshTools.write_D_network_element_to_inputfile(name + "_Node_Elem_sets.inp")
inpfileMain.write('\n***********************************************************\n')
inpfileMain.write('**Nodes and Elements\n')
inpfileMain.write('** written by femmesh.writeABAQUS\n')
@ -238,6 +267,19 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.write_constraints_initialtemperature(inpfileMain)
self.write_femelementsets(inpfileMain)
# Fluid section: Inlet and Outlet requires special element definition
if self.fluidsection_objects:
InOuttest = False
for ccx_elset in self.ccx_elsets:
if ccx_elset['ccx_elset']:
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"):
InOuttest = True
if InOuttest is True:
FemMeshTools.use_correct_fluidinout_ele_def(self.FluidInletoutlet_ele, name + "_Node_Elem_sets.inp")
# constraints independent from steps
if self.planerotation_objects:
self.write_constraints_planerotation(inpfileMain)
@ -276,6 +318,8 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.write_constraints_temperature(inpfileMain)
if self.heatflux_objects:
self.write_constraints_heatflux(inpfileHeatflux)
if self.fluidsection_objects:
self.write_constraints_fluidsection(inpfileMain)
# include seperately written constraints in input file
inpfileMain.write('\n***********************************************************\n')
@ -308,13 +352,17 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
def write_element_sets_material_and_femelement_type(self, f):
f.write('\n***********************************************************\n')
f.write('** Element sets for materials and FEM element type (solid, shell, beam)\n')
f.write('** Element sets for materials and FEM element type (solid, shell, beam, fluid)\n')
f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name))
if len(self.material_objects) == 1:
if self.beamsection_objects and len(self.beamsection_objects) == 1: # single mat, single beam
self.get_ccx_elsets_single_mat_single_beam()
elif self.beamsection_objects and len(self.beamsection_objects) > 1: # single mat, multiple beams
self.get_ccx_elsets_single_mat_multiple_beam()
elif self.fluidsection_objects and len(self.fluidsection_objects) == 1: # single mat, single fluid
self.get_ccx_elsets_single_mat_single_fluid()
elif self.fluidsection_objects and len(self.fluidsection_objects) > 1: # single mat, multiple fluids
self.get_ccx_elsets_single_mat_multiple_fluid()
elif self.shellthickness_objects and len(self.shellthickness_objects) == 1: # single mat, single shell
self.get_ccx_elsets_single_mat_single_shell()
elif self.shellthickness_objects and len(self.shellthickness_objects) > 1: # single mat, multiple shells
@ -326,6 +374,10 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.get_ccx_elsets_multiple_mat_single_beam()
elif self.beamsection_objects and len(self.beamsection_objects) > 1: # multiple mats, multiple beams
self.get_ccx_elsets_multiple_mat_multiple_beam()
if self.fluidsection_objects and len(self.fluidsection_objects) == 1: # multiple mats, single fluid
self.get_ccx_elsets_multiple_mat_single_fluid()
elif self.fluidsection_objects and len(self.fluidsection_objects) > 1: # multiple mats, multiple fluids
self.get_ccx_elsets_multiple_mat_multiple_fluid()
elif self.shellthickness_objects and len(self.shellthickness_objects) == 1: # multiple mats, single shell
self.get_ccx_elsets_multiple_mat_single_shell()
elif self.shellthickness_objects and len(self.shellthickness_objects) > 1: # multiple mats, multiple shells
@ -334,12 +386,27 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
self.get_ccx_elsets_multiple_mat_solid()
for ccx_elset in self.ccx_elsets:
f.write('*ELSET,ELSET=' + ccx_elset['ccx_elset_name'] + '\n')
collect_ele = False
if ccx_elset['ccx_elset']:
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"):
collect_ele = True
if ccx_elset['ccx_elset']:
if ccx_elset['ccx_elset'] == self.ccx_eall:
f.write(self.ccx_eall + '\n')
else:
elsetchanged = 0
counter = 0
for elid in ccx_elset['ccx_elset']:
f.write(str(elid) + ',\n')
counter = counter + 1
if collect_ele is True and elsetchanged == 0 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
elsetchanged = 1
elif collect_ele is True and 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
else:
f.write('**No elements found for these objects\n')
@ -470,35 +537,47 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
mat_obj = femobj['Object']
mat_info_name = mat_obj.Material['Name']
mat_name = mat_obj.Name
# get material properties, Currently in SI units: M/kg/s/Kelvin
YM = FreeCAD.Units.Quantity(mat_obj.Material['YoungsModulus'])
YM_in_MPa = float(YM.getValueAs('MPa'))
PR = float(mat_obj.Material['PoissonRatio'])
# get material properties of solid material, Currently in SI units: M/kg/s/Kelvin
if mat_obj.Category == 'Solid':
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):
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
TEC = FreeCAD.Units.Quantity(mat_obj.Material['ThermalExpansionCoefficient'])
TEC_in_mmK = float(TEC.getValueAs('mm/mm/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
if mat_obj.Category == 'Solid':
TEC = FreeCAD.Units.Quantity(mat_obj.Material['ThermalExpansionCoefficient'])
TEC_in_mmK = float(TEC.getValueAs('mm/mm/K'))
elif mat_obj.Category == 'Fluid':
DV = FreeCAD.Units.Quantity(mat_obj.Material['DynamicViscosity'])
DV_in_tmms = float(DV.getValueAs('t/mm/s'))
# write material properties
f.write('** FreeCAD material name: ' + mat_info_name + '\n')
f.write('*MATERIAL, NAME=' + mat_name + '\n')
f.write('*ELASTIC\n')
f.write('{0:.0f}, {1:.3f}\n'.format(YM_in_MPa, PR))
if mat_obj.Category == 'Solid':
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):
f.write('*DENSITY\n')
f.write('{0:.3e}\n'.format(density_in_tonne_per_mm3))
if self.analysis_type == "thermomech":
f.write('*CONDUCTIVITY\n')
f.write('{0:.3f}\n'.format(TC_in_WmK))
f.write('*EXPANSION\n')
f.write('{0:.3e}\n'.format(TEC_in_mmK))
f.write('*SPECIFIC HEAT\n')
f.write('{0:.3e}\n'.format(SH_in_JkgK))
if mat_obj.Category == 'Solid':
f.write('*CONDUCTIVITY\n')
f.write('{0:.3f}\n'.format(TC_in_WmK))
f.write('*EXPANSION\n')
f.write('{0:.3e}\n'.format(TEC_in_mmK))
f.write('*SPECIFIC HEAT\n')
f.write('{0:.3e}\n'.format(SH_in_JkgK))
elif mat_obj.Category == 'Fluid':
f.write('*FLUID CONSTANTS\n')
f.write('{0:.3e}, {1:.3e}\n'.format(SH_in_JkgK, DV_in_tmms))
# nonlinear material properties
if self.solver_obj.MaterialNonlinearity == 'nonlinear':
for femobj in self.material_nonlinear_objects: # femobj --> dict, FreeCAD document object is femobj['Object']
@ -548,6 +627,22 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
setion_def = '*BEAM GENERAL SECTION, ' + elsetdef + material + section_type + '\n'
f.write(setion_def)
f.write(setion_geo)
elif 'fluidsection_obj'in ccx_elset: # fluid mesh
fluidsec_obj = ccx_elset['fluidsection_obj']
elsetdef = 'ELSET=' + ccx_elset['ccx_elset_name'] + ', '
material = 'MATERIAL=' + ccx_elset['mat_obj_name']
if fluidsec_obj.SectionType == 'Liquid':
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_geo = liquid_section_def(fluidsec_obj, section_type)
elif fluidsec_obj.SectionType == 'Gas':
section_type = fluidsec_obj.GasSectionType
elif fluidsec_obj.SectionType == 'Open Channel':
section_type = fluidsec_obj.ChannelSectionType
f.write(setion_def)
f.write(setion_geo)
elif 'shellthickness_obj'in ccx_elset: # shell mesh
shellth_obj = ccx_elset['shellthickness_obj']
elsetdef = 'ELSET=' + ccx_elset['ccx_elset_name'] + ', '
@ -735,10 +830,10 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
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']
selwei_obj_name = femobj['Object'].Name
f.write('** ' + selwei_obj_name + '\n')
selwei_obj = femobj['Object']
f.write('** ' + selwei_obj.Name + '\n')
f.write('*DLOAD\n')
f.write('Eall,GRAV,9810,0,0,-1\n')
f.write('Eall,GRAV,9810,' + str(selwei_obj.Gravity_x) + ',' + str(selwei_obj.Gravity_y) + ',' + str(selwei_obj.Gravity_z) + '\n')
f.write('\n')
# grav (erdbeschleunigung) is equal for all elements
# should be only one constraint
@ -831,28 +926,78 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
for i in v:
f.write("{},S{},{}\n".format(i[0], i[1], heatflux_obj.DFlux * 0.001))
def write_constraints_fluidsection(self, f):
f.write('\n***********************************************************\n')
f.write('** FluidSection constraints\n')
f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name))
if os.path.exists("inout_nodes.txt"):
inout_nodes_file = open("inout_nodes.txt", "r")
lines = inout_nodes_file.readlines()
inout_nodes_file.close()
# get nodes
self.get_constraints_fluidsection_nodes()
for femobj in self.fluidsection_objects: # femobj --> dict, FreeCAD document object is femobj['Object']
fluidsection_obj = femobj['Object']
if fluidsection_obj.SectionType == 'Liquid':
if fluidsection_obj.LiquidSectionType == 'PIPE INLET':
f.write('**Fluid Section Inlet \n')
if fluidsection_obj.InletPressureActive is True:
f.write('*BOUNDARY \n')
for n in femobj['Nodes']:
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
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':
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 convet unit from kg/s to t/s
elif fluidsection_obj.LiquidSectionType == 'PIPE OUTLET':
f.write('**Fluid Section Outlet \n')
if fluidsection_obj.OutletPressureActive is True:
f.write('*BOUNDARY \n')
for n in femobj['Nodes']:
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
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':
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 convet unit from kg/s to t/s
def write_outputs_types(self, f):
f.write('\n***********************************************************\n')
f.write('** Outputs --> frd file\n')
f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name))
if self.beamsection_objects or self.shellthickness_objects:
if self.beamsection_objects or self.shellthickness_objects or self.fluidsection_objects:
f.write('*NODE FILE, OUTPUT=2d\n')
else:
f.write('*NODE FILE\n')
if self.analysis_type == "thermomech": # MPH write out nodal temperatures if thermomechanical
f.write('U, NT\n')
if not self.fluidsection_objects:
f.write('U, NT\n')
else:
f.write('MF, PS\n')
else:
f.write('U\n')
f.write('*EL FILE\n')
if self.solver_obj.MaterialNonlinearity == 'nonlinear':
f.write('S, E, PEEQ\n')
else:
f.write('S, E\n')
f.write('** outputs --> dat file\n')
f.write('*NODE PRINT , NSET=Nall \n')
f.write('U \n')
f.write('*EL PRINT , ELSET=Eall \n')
f.write('S \n')
if not self.fluidsection_objects:
f.write('*EL FILE\n')
if self.solver_obj.MaterialNonlinearity == 'nonlinear':
f.write('S, E, PEEQ\n')
else:
f.write('S, E\n')
f.write('** outputs --> dat file\n')
f.write('*NODE PRINT , NSET=Nall \n')
f.write('U \n')
f.write('*EL PRINT , ELSET=Eall \n')
f.write('S \n')
def write_step_end(self, f):
f.write('\n***********************************************************\n')
@ -897,6 +1042,17 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_single_mat_single_fluid(self):
mat_obj = self.material_objects[0]['Object']
fluidsec_obj = self.fluidsection_objects[0]['Object']
ccx_elset = {}
ccx_elset['fluidsection_obj'] = fluidsec_obj
ccx_elset['ccx_elset'] = self.ccx_eall
ccx_elset['ccx_elset_name'] = get_ccx_elset_fluid_name(mat_obj.Name, fluidsec_obj.Name)
ccx_elset['mat_obj_name'] = mat_obj.Name
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_single_mat_single_shell(self):
mat_obj = self.material_objects[0]['Object']
shellth_obj = self.shellthickness_objects[0]['Object']
@ -932,6 +1088,21 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_single_mat_multiple_fluid(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
mat_obj = self.material_objects[0]['Object']
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.fluidsection_objects)
for fluidsec_data in self.fluidsection_objects:
fluidsec_obj = fluidsec_data['Object']
ccx_elset = {}
ccx_elset['fluidsection_obj'] = fluidsec_obj
ccx_elset['ccx_elset'] = fluidsec_data['FEMElements']
ccx_elset['ccx_elset_name'] = get_ccx_elset_fluid_name(mat_obj.Name, fluidsec_obj.Name, None, fluidsec_data['ShortName'])
ccx_elset['mat_obj_name'] = mat_obj.Name
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_single_mat_multiple_shell(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
@ -962,6 +1133,21 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_single_fluid(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
fluidsec_obj = self.fluidsection_objects[0]['Object']
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
for mat_data in self.material_objects:
mat_obj = mat_data['Object']
ccx_elset = {}
ccx_elset['fluidsection_obj'] = fluidsec_obj
ccx_elset['ccx_elset'] = mat_data['FEMElements']
ccx_elset['ccx_elset_name'] = get_ccx_elset_fluid_name(mat_obj.Name, fluidsec_obj.Name, mat_data['ShortName'])
ccx_elset['mat_obj_name'] = mat_obj.Name
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_single_shell(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
@ -1021,6 +1207,27 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_multiple_fluid(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.fluidsection_objects)
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
for fluidsec_data in self.fluidsection_objects:
fluidsec_obj = fluidsec_data['Object']
for mat_data in self.material_objects:
mat_obj = mat_data['Object']
ccx_elset = {}
ccx_elset['fluidsection_obj'] = fluidsec_obj
elemids = []
for elemid in fluidsec_data['FEMElements']:
if elemid in mat_data['FEMElements']:
elemids.append(elemid)
ccx_elset['ccx_elset'] = elemids
ccx_elset['ccx_elset_name'] = get_ccx_elset_fluid_name(mat_obj.Name, fluidsec_obj.Name, mat_data['ShortName'], fluidsec_data['ShortName'])
ccx_elset['mat_obj_name'] = mat_obj.Name
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name']
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_multiple_shell(self):
if not self.femelement_table:
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
@ -1055,6 +1262,17 @@ def get_ccx_elset_beam_name(mat_name, beamsec_name, mat_short_name=None, beamsec
return mat_name + beamsec_name
def get_ccx_elset_fluid_name(mat_name, fluidsec_name, mat_short_name=None, fluidsec_short_name=None):
if not mat_short_name:
mat_short_name = 'Mat0'
if not fluidsec_short_name:
fluidsec_short_name = 'Fluid0'
if len(mat_name + fluidsec_name) > 20: # max identifier lenght in CalculiX for beam elsets
return mat_short_name + fluidsec_short_name
else:
return mat_name + fluidsec_name
def get_ccx_elset_shell_name(mat_name, shellth_name, mat_short_name=None, shellth_short_name=None):
if not mat_short_name:
mat_short_name = 'Mat0'
@ -1076,4 +1294,61 @@ def get_ccx_elset_solid_name(mat_name, solid_name=None, mat_short_name=None):
else:
return mat_name + solid_name
def liquid_section_def(obj, section_type):
if section_type == 'PIPE MANNING':
manning_area = str(obj.ManningArea.getValueAs('mm^2').Value)
manning_radius = str(obj.ManningRadius.getValueAs('mm'))
manning_coefficient = str(obj.ManningCoefficient)
section_geo = manning_area + ',' + manning_radius + ',' + manning_coefficient + '\n'
return section_geo
elif section_type == 'PIPE ENLARGEMENT':
enlarge_area1 = str(obj.EnlargeArea1.getValueAs('mm^2').Value)
enlarge_area2 = str(obj.EnlargeArea2.getValueAs('mm^2').Value)
section_geo = enlarge_area1 + ',' + enlarge_area2 + '\n'
return section_geo
elif section_type == 'PIPE CONTRACTION':
contract_area1 = str(obj.ContractArea1.getValueAs('mm^2').Value)
contract_area2 = str(obj.ContractArea2.getValueAs('mm^2').Value)
section_geo = contract_area1 + ',' + contract_area2 + '\n'
return section_geo
elif section_type == 'PIPE ENTRANCE':
entrance_pipe_area = str(obj.EntrancePipeArea.getValueAs('mm^2').Value)
entrance_area = str(obj.EntranceArea.getValueAs('mm^2').Value)
section_geo = entrance_pipe_area + ',' + entrance_area + '\n'
return section_geo
elif section_type == 'PIPE DIAPHRAGM':
diaphragm_pipe_area = str(obj.DiaphragmPipeArea.getValueAs('mm^2').Value)
diaphragm_area = str(obj.DiaphragmArea.getValueAs('mm^2').Value)
section_geo = diaphragm_pipe_area + ',' + diaphragm_area + '\n'
return section_geo
elif section_type == 'PIPE BEND':
bend_pipe_area = str(obj.BendPipeArea.getValueAs('mm^2').Value)
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'
return section_geo
elif section_type == 'PIPE GATE VALVE':
gatevalve_pipe_area = str(obj.GateValvePipeArea.getValueAs('mm^2').Value)
gatevalve_closing_coeff = str(obj.GateValveClosingCoeff)
section_geo = gatevalve_pipe_area + ',' + gatevalve_closing_coeff + '\n'
return section_geo
elif section_type == 'PIPE WHITE-COLEBROOK':
colebrooke_area = str(obj.ColebrookeArea.getValueAs('mm^2').Value)
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'
return section_geo
elif section_type == 'LIQUID PUMP':
section_geo = ''
for i in range(len(obj.PumpFlowRate)):
flow_rate = str(obj.PumpFlowRate[i])
head = str(obj.PumpHeadLoss[i])
section_geo = section_geo + flow_rate + ',' + head + ','
section_geo = section_geo + '\n'
return section_geo
else:
return ''
# @}

View File

@ -406,6 +406,8 @@ def get_elset_short_name(obj, i):
return 'Mat' + str(i)
elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemBeamSection':
return 'Beam' + str(i)
elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemFluidSection':
return 'Fluid' + str(i)
elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemShellThickness':
return 'Shell' + str(i)
else:
@ -1028,7 +1030,7 @@ def get_analysis_group_elements(aAnalysis, aPart):
else:
FreeCAD.Console.PrintError('Problem: more than one object with empty references.\n')
print('We gone try to get the empty material references anyway.\n')
# ShellThickness and BeamSection could have empty references, but on solid meshes only materials should have empty references
# ShellThickness, BeamSection and FluidSection could have empty references, but on solid meshes only materials should have empty references
for er in empty_references:
print(er.Name)
group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aPart.Shape)
@ -1075,7 +1077,7 @@ def get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShap
'''get the elementIDs if the Reference shape is empty
see get_analysis_group_elements() for more informatations
on solid meshes only material objects could have an empty reference without beeing something wrong!
face meshes could have empty ShellThickness and edge meshes could have empty BeamSection
face meshes could have empty ShellThickness and edge meshes could have empty BeamSection/FluidSection
'''
# print(group_elements)
material_ref_shapes = []
@ -1424,6 +1426,89 @@ def get_cylindrical_coords(obj):
return coords
def write_D_network_element_to_inputfile(fileName):
# replace B32 elements with D elements for fluid section
f = open(fileName, 'r+')
lines = f.readlines()
f.seek(0)
for line in lines:
if line.find("B32") == -1:
f.write(line)
else:
dummy = line.replace("B32", "D")
f.write(dummy)
f.truncate()
f.close()
def use_correct_fluidinout_ele_def(FluidInletoutlet_ele, fileName):
f = open(fileName, 'r')
cnt = 0
line = f.readline()
# start reading from *ELEMENT
while line.find("Element") == -1:
line = f.readline()
cnt = cnt + 1
line = f.readline()
cnt = cnt + 1
# obtain element line numbers for inlet and outlet
while (len(line) > 1):
ind = line.find(',')
elem = line[0:ind]
for i in range(len(FluidInletoutlet_ele)):
if (elem == FluidInletoutlet_ele[i][0]):
FluidInletoutlet_ele[i][2] = cnt
line = f.readline()
cnt = cnt + 1
f.close()
# re-define elements for INLET and OUTLET
f = open(fileName, 'r+')
lines = f.readlines()
f.seek(0)
cnt = 0
elem_counter = 0
inout_nodes_file = open("inout_nodes.txt", "w")
for line in lines:
new_line = ''
for i in range(len(FluidInletoutlet_ele)):
if (cnt == FluidInletoutlet_ele[i][2]):
elem_counter = elem_counter + 1
a = line.split(',')
for j in range(len(a)):
if elem_counter == 1:
if j == 1:
new_line = new_line + ' 0,'
node1 = int(a[j + 2])
node2 = int(a[j + 1])
node3 = int(a[j])
inout_nodes_file.write(str(node1) + ',' + str(node2) + ',' + str(node3) + ',' + FluidInletoutlet_ele[i][1] + '\n')
elif j == 3:
new_line = new_line + a[j]
else:
new_line = new_line + a[j] + ','
else:
if j == 3:
new_line = new_line + ' 0\n'
node1 = int(a[j - 2])
node2 = int(a[j - 1])
node3 = int(a[j])
inout_nodes_file.write(str(node1) + ',' + str(node2) + ',' + str(node3) + ',' + FluidInletoutlet_ele[i][1] + '\n')
else:
new_line = new_line + a[j] + ','
if new_line == '':
f.write(line)
else:
f.write(new_line)
cnt = cnt + 1
f.truncate()
f.close()
inout_nodes_file.close()
def make_femmesh(mesh_data):
''' makes an FreeCAD FEM Mesh object from FEM Mesh data
'''

View File

@ -157,6 +157,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
# [{'Object':heatflux_constraints, 'xxxxxxxx':value}, {}, ...]
# [{'Object':initialtemperature_constraints, 'xxxxxxxx':value}, {}, ...]
# [{'Object':beam_sections, 'xxxxxxxx':value}, {}, ...]
# [{'Object':fluid_sections, 'xxxxxxxx':value}, {}, ...]
# [{'Object':shell_thicknesses, 'xxxxxxxx':value}, {}, ...]
# [{'Object':contact_constraints, 'xxxxxxxx':value}, {}, ...]
@ -191,6 +192,10 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
# set of beam sections from the analysis. Updated with update_objects
# Individual beam sections are Proxy.Type "FemBeamSection"
self.beam_sections = []
## @var fluid_sections
# set of fluid sections from the analysis. Updated with update_objects
# Individual fluid sections are Proxy.Type "FemFluidSection"
self.fluid_sections = []
## @var shell_thicknesses
# set of shell thicknesses from the analysis. Updated with update_objects
# Individual shell thicknesses are Proxy.Type "FemShellThickness"
@ -301,6 +306,10 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
beam_section_dict = {}
beam_section_dict['Object'] = m
self.beam_sections.append(beam_section_dict)
elif hasattr(m, "Proxy") and m.Proxy.Type == "FemFluidSection":
fluid_section_dict = {}
fluid_section_dict['Object'] = m
self.fluid_sections.append(fluid_section_dict)
elif hasattr(m, "Proxy") and m.Proxy.Type == "FemShellThickness":
shell_thickness_dict = {}
shell_thickness_dict['Object'] = m
@ -338,8 +347,8 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
if self.mesh:
if self.mesh.FemMesh.VolumeCount == 0 and self.mesh.FemMesh.FaceCount > 0 and not self.shell_thicknesses:
message += "FEM mesh has no volume elements, either define a shell thicknesses or provide a FEM mesh with volume elements.\n"
if self.mesh.FemMesh.VolumeCount == 0 and self.mesh.FemMesh.FaceCount == 0 and self.mesh.FemMesh.EdgeCount > 0 and not self.beam_sections:
message += "FEM mesh has no volume and no shell elements, either define a beam section or provide a FEM mesh with volume elements.\n"
if self.mesh.FemMesh.VolumeCount == 0 and self.mesh.FemMesh.FaceCount == 0 and self.mesh.FemMesh.EdgeCount > 0 and not self.beam_sections and not self.fluid_sections:
message += "FEM mesh has no volume and no shell elements, either define a beam/fluid section or provide a FEM mesh with volume elements.\n"
if self.mesh.FemMesh.VolumeCount == 0 and self.mesh.FemMesh.FaceCount == 0 and self.mesh.FemMesh.EdgeCount == 0:
message += "FEM mesh has neither volume nor shell or edge elements. Provide a FEM mesh with elements!\n"
# materials linear and nonlinear
@ -353,14 +362,16 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
has_no_references = True
for m in self.materials_linear:
mat_map = m['Object'].Material
if 'YoungsModulus' in mat_map:
# print Units.Quantity(mat_map['YoungsModulus']).Value
if not Units.Quantity(mat_map['YoungsModulus']).Value:
message += "Value of YoungsModulus is set to 0.0.\n"
else:
message += "No YoungsModulus defined for at least one material.\n"
if 'PoissonRatio' not in mat_map:
message += "No PoissonRatio defined for at least one material.\n" # PoissonRatio is allowed to be 0.0 (in ccx), but it should be set anyway.
mat_obj = m['Object']
if mat_obj.Category == 'Solid':
if 'YoungsModulus' in mat_map:
# print Units.Quantity(mat_map['YoungsModulus']).Value
if not Units.Quantity(mat_map['YoungsModulus']).Value:
message += "Value of YoungsModulus is set to 0.0.\n"
else:
message += "No YoungsModulus defined for at least one material.\n"
if 'PoissonRatio' not in mat_map:
message += "No PoissonRatio defined for at least one material.\n" # PoissonRatio is allowed to be 0.0 (in ccx), but it should be set anyway.
if self.analysis_type == "frequency" or self.selfweight_constraints:
if 'Density' not in mat_map:
message += "No Density defined for at least one material.\n"
@ -389,14 +400,18 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
# no check in the regard of loads (constraint force, pressure, self weight) is done because an analysis without loads at all is an valid analysis too
if self.analysis_type == "thermomech":
if not self.initialtemperature_constraints:
message += "Thermomechanical analysis: No initial temperature defined.\n"
if not self.fluid_sections:
message += "Thermomechanical analysis: No initial temperature defined.\n"
if len(self.initialtemperature_constraints) > 1:
message += "Thermomechanical analysis: Only one initial temperature is allowed.\n"
# beam sections and shell thicknesses
# beam sections, fluid sections and shell thicknesses
if self.beam_sections:
if self.shell_thicknesses:
# this needs to be checked only once either here or in shell_thicknesses
message += "Beam Sections and shell thicknesses in one analysis is not supported at the moment.\n"
if self.fluid_sections:
# this needs to be checked only once either here or in shell_thicknesses
message += "Beam Sections and Fluid Sections in one analysis is not supported at the moment.\n"
has_no_references = False
for b in self.beam_sections:
if len(b['Object'].References) == 0:
@ -420,6 +435,22 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
message += "Shell thicknesses defined but FEM mesh has volume elements.\n"
if self.mesh.FemMesh.FaceCount == 0:
message += "Shell thicknesses defined but FEM mesh has no shell elements.\n"
if self.fluid_sections:
if not self.selfweight_constraints:
message += "A fluid network analysis requires self weight constraint to be applied"
if self.analysis_type != "thermomech":
message += "A fluid network analysis can only be done in a thermomech analysis"
has_no_references = False
for f in self.fluid_sections:
if len(f['Object'].References) == 0:
if has_no_references is True:
message += "More than one fluid section has an empty references list (Only one empty references list is allowed!).\n"
has_no_references = True
if self.mesh:
if self.mesh.FemMesh.FaceCount > 0 or self.mesh.FemMesh.VolumeCount > 0:
message += "Fluid sections defined but FEM mesh has volume or shell elements.\n"
if self.mesh.FemMesh.EdgeCount == 0:
message += "Fluid sections defined but FEM mesh has no edge elements.\n"
return message
## Sets base_name

View File

@ -96,7 +96,7 @@ class FemToolsCcx(FemTools.FemTools):
self.contact_constraints, self.planerotation_constraints, self.transform_constraints,
self.selfweight_constraints, self.force_constraints, self.pressure_constraints,
self.temperature_constraints, self.heatflux_constraints, self.initialtemperature_constraints,
self.beam_sections, self.shell_thicknesses,
self.beam_sections, self.shell_thicknesses, self.fluid_sections,
self.analysis_type, self.working_dir)
self.inp_file_name = inp_writer.write_calculix_input_file()
except: