FEM: calculix writer, move material, element geometry and mat-geo-elementsets into separte methods
This commit is contained in:
@@ -202,6 +202,9 @@ SET(FemSolverCalculix_SRCS
|
||||
femsolver/calculix/write_constraint_temperature.py
|
||||
femsolver/calculix/write_constraint_tie.py
|
||||
femsolver/calculix/write_constraint_transform.py
|
||||
femsolver/calculix/write_femelement_geometry.py
|
||||
femsolver/calculix/write_femelement_material.py
|
||||
femsolver/calculix/write_femelement_matgeosets.py
|
||||
femsolver/calculix/write_footer.py
|
||||
femsolver/calculix/write_mesh.py
|
||||
femsolver/calculix/write_step_equation.py
|
||||
|
||||
185
src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py
Normal file
185
src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py
Normal file
@@ -0,0 +1,185 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2021 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "FreeCAD FEM calculix write inpfile femelement geometry"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
def write_femelement_geometry(f, ccxwriter):
|
||||
f.write("\n{}\n".format(59 * "*"))
|
||||
f.write("** Sections\n")
|
||||
for ccx_elset in ccxwriter.ccx_elsets:
|
||||
if ccx_elset["ccx_elset"]:
|
||||
if "beamsection_obj"in ccx_elset: # beam mesh
|
||||
beamsec_obj = ccx_elset["beamsection_obj"]
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
normal = ccx_elset["beam_normal"]
|
||||
if beamsec_obj.SectionType == "Rectangular":
|
||||
height = beamsec_obj.RectHeight.getValueAs("mm")
|
||||
width = beamsec_obj.RectWidth.getValueAs("mm")
|
||||
section_type = ", SECTION=RECT"
|
||||
section_geo = str(height) + ", " + str(width) + "\n"
|
||||
section_def = "*BEAM SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
elif beamsec_obj.SectionType == "Circular":
|
||||
radius = 0.5 * beamsec_obj.CircDiameter.getValueAs("mm")
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = str(radius) + "\n"
|
||||
section_def = "*BEAM SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
elif beamsec_obj.SectionType == "Pipe":
|
||||
radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs("mm")
|
||||
thickness = beamsec_obj.PipeThickness.getValueAs("mm")
|
||||
section_type = ", SECTION=PIPE"
|
||||
section_geo = str(radius) + ", " + str(thickness) + "\n"
|
||||
section_def = "*BEAM GENERAL SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
# see forum topic for output formatting of rotation
|
||||
# https://forum.freecadweb.org/viewtopic.php?f=18&t=46133&p=405142#p405142
|
||||
section_nor = "{:f}, {:f}, {:f}\n".format(
|
||||
normal[0],
|
||||
normal[1],
|
||||
normal[2]
|
||||
)
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
f.write(section_nor)
|
||||
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"
|
||||
section_def = "*FLUID SECTION, {}TYPE={}, {}\n".format(
|
||||
elsetdef,
|
||||
section_type,
|
||||
material
|
||||
)
|
||||
section_geo = liquid_section_def(fluidsec_obj, section_type)
|
||||
"""
|
||||
# deactivate as it would result in section_def and section_geo not defined
|
||||
# deactivated in the App and Gui object and thus in the task panel as well
|
||||
elif fluidsec_obj.SectionType == "Gas":
|
||||
section_type = fluidsec_obj.GasSectionType
|
||||
elif fluidsec_obj.SectionType == "Open Channel":
|
||||
section_type = fluidsec_obj.ChannelSectionType
|
||||
"""
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
elif "shellthickness_obj"in ccx_elset: # shell mesh
|
||||
shellth_obj = ccx_elset["shellthickness_obj"]
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
section_def = "*SHELL SECTION, " + elsetdef + material + "\n"
|
||||
section_geo = str(shellth_obj.Thickness.getValueAs("mm")) + "\n"
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
else: # solid mesh
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
section_def = "*SOLID SECTION, " + elsetdef + material + "\n"
|
||||
f.write(section_def)
|
||||
|
||||
|
||||
# ************************************************************************************************
|
||||
# Helpers
|
||||
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 = ("{},{},{},{}\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)
|
||||
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 = ("{},{},{},{},{}\n".format(
|
||||
colebrooke_area,
|
||||
colebrooke_diameter,
|
||||
"-1",
|
||||
colebrooke_grain_diameter,
|
||||
colebrooke_form_factor
|
||||
))
|
||||
return section_geo
|
||||
elif section_type == "LIQUID PUMP":
|
||||
section_geo = ""
|
||||
for i in range(len(obj.PumpFlowRate)):
|
||||
flow_rate = str(obj.PumpFlowRate[i])
|
||||
top = str(obj.PumpHeadLoss[i])
|
||||
section_geo = section_geo + flow_rate + "," + top + ","
|
||||
section_geo = section_geo + "\n"
|
||||
return section_geo
|
||||
else:
|
||||
return ""
|
||||
194
src/Mod/Fem/femsolver/calculix/write_femelement_material.py
Normal file
194
src/Mod/Fem/femsolver/calculix/write_femelement_material.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2021 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "FreeCAD FEM calculix write inpfile materials"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import FreeCAD
|
||||
|
||||
|
||||
def write_femelement_material(f, ccxwriter):
|
||||
|
||||
# helper inside class method
|
||||
def is_density_needed():
|
||||
if ccxwriter.analysis_type == "frequency":
|
||||
return True
|
||||
if (
|
||||
ccxwriter.analysis_type == "thermomech"
|
||||
and not ccxwriter.solver_obj.ThermoMechSteadyState
|
||||
):
|
||||
return True
|
||||
if ccxwriter.centrif_objects:
|
||||
return True
|
||||
if ccxwriter.selfweight_objects:
|
||||
return True
|
||||
return False
|
||||
|
||||
f.write("\n{}\n".format(59 * "*"))
|
||||
f.write("** Materials\n")
|
||||
f.write("** Young\'s modulus unit is MPa = N/mm2\n")
|
||||
if is_density_needed() is True:
|
||||
f.write("** Density\'s unit is t/mm^3\n")
|
||||
if ccxwriter.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 ccxwriter.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
|
||||
mat_label = mat_obj.Label
|
||||
# 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 is_density_needed() is True:
|
||||
density = FreeCAD.Units.Quantity(mat_obj.Material["Density"])
|
||||
density_in_tonne_per_mm3 = float(density.getValueAs("t/mm^3"))
|
||||
if ccxwriter.analysis_type == "thermomech":
|
||||
TC = FreeCAD.Units.Quantity(mat_obj.Material["ThermalConductivity"])
|
||||
# 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"])
|
||||
# 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"))
|
||||
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("** " + mat_label + "\n")
|
||||
f.write("*MATERIAL, NAME=" + mat_name + "\n")
|
||||
if mat_obj.Category == "Solid":
|
||||
f.write("*ELASTIC\n")
|
||||
f.write("{0:.0f}, {1:.3f}\n".format(YM_in_MPa, PR))
|
||||
|
||||
if is_density_needed() is True:
|
||||
f.write("*DENSITY\n")
|
||||
f.write("{0:.3e}\n".format(density_in_tonne_per_mm3))
|
||||
if ccxwriter.analysis_type == "thermomech":
|
||||
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 ccxwriter.solver_obj.MaterialNonlinearity == "nonlinear":
|
||||
|
||||
for nlfemobj in ccxwriter.material_nonlinear_objects:
|
||||
# femobj --> dict, FreeCAD document object is nlfemobj["Object"]
|
||||
nl_mat_obj = nlfemobj["Object"]
|
||||
if nl_mat_obj.LinearBaseMaterial == mat_obj:
|
||||
if nl_mat_obj.MaterialModelNonlinearity == "simple hardening":
|
||||
f.write("*PLASTIC\n")
|
||||
if nl_mat_obj.YieldPoint1:
|
||||
f.write(nl_mat_obj.YieldPoint1 + "\n")
|
||||
if nl_mat_obj.YieldPoint2:
|
||||
f.write(nl_mat_obj.YieldPoint2 + "\n")
|
||||
if nl_mat_obj.YieldPoint3:
|
||||
f.write(nl_mat_obj.YieldPoint3 + "\n")
|
||||
f.write("\n")
|
||||
|
||||
|
||||
# ************************************************************************************************
|
||||
# Helpers
|
||||
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 = ("{},{},{},{}\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)
|
||||
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 = ("{},{},{},{},{}\n".format(
|
||||
colebrooke_area,
|
||||
colebrooke_diameter,
|
||||
"-1",
|
||||
colebrooke_grain_diameter,
|
||||
colebrooke_form_factor
|
||||
))
|
||||
return section_geo
|
||||
elif section_type == "LIQUID PUMP":
|
||||
section_geo = ""
|
||||
for i in range(len(obj.PumpFlowRate)):
|
||||
flow_rate = str(obj.PumpFlowRate[i])
|
||||
top = str(obj.PumpHeadLoss[i])
|
||||
section_geo = section_geo + flow_rate + "," + top + ","
|
||||
section_geo = section_geo + "\n"
|
||||
return section_geo
|
||||
else:
|
||||
return ""
|
||||
@@ -0,0 +1,44 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2021 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "FreeCAD FEM calculix write inpfile material and geometry sets"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import six
|
||||
|
||||
|
||||
def write_femelement_matgeosets(f, ccxwriter):
|
||||
|
||||
# write ccx_elsets to file
|
||||
f.write("\n{}\n".format(59 * "*"))
|
||||
f.write("** Element sets for materials and FEM element type (solid, shell, beam, fluid)\n")
|
||||
for ccx_elset in ccxwriter.ccx_elsets:
|
||||
f.write("*ELSET,ELSET=" + ccx_elset["ccx_elset_name"] + "\n")
|
||||
# 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"]:
|
||||
f.write(str(elid) + ",\n")
|
||||
@@ -29,7 +29,6 @@ __url__ = "https://www.freecadweb.org"
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import six
|
||||
import time
|
||||
from os.path import join
|
||||
|
||||
@@ -51,6 +50,9 @@ from . import write_constraint_selfweight as con_selfweight
|
||||
from . import write_constraint_temperature as con_temperature
|
||||
from . import write_constraint_tie as con_tie
|
||||
from . import write_constraint_transform as con_transform
|
||||
from . import write_femelement_geometry
|
||||
from . import write_femelement_material
|
||||
from . import write_femelement_matgeosets
|
||||
from . import write_footer
|
||||
from . import write_mesh
|
||||
from . import write_step_equation
|
||||
@@ -161,8 +163,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
inpfile = write_mesh.write_mesh(self)
|
||||
|
||||
# element sets for materials and element geometry
|
||||
# self.write_element_sets_material_and_femelement_geometry(inpfile)
|
||||
self.write_element_sets_material_and_femelement_type(inpfile)
|
||||
write_femelement_matgeosets.write_femelement_matgeosets(inpfile, self)
|
||||
|
||||
if self.fluidsection_objects:
|
||||
# some fluidsection objs need special treatment, ccx_elsets are needed for this
|
||||
@@ -184,10 +185,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
self.write_constraints_sets(inpfile, self.sectionprint_objects, con_sectionprint)
|
||||
|
||||
# materials and fem element types
|
||||
self.write_materials(inpfile)
|
||||
write_femelement_material.write_femelement_material(inpfile, self)
|
||||
self.write_constraints_data(inpfile, self.initialtemperature_objects, con_initialtemp)
|
||||
# self.write_femelement_geometry(inpfile)
|
||||
self.write_femelementsets(inpfile)
|
||||
write_femelement_geometry.write_femelement_geometry(inpfile, self)
|
||||
|
||||
# constraints independent from steps
|
||||
self.write_constraints_data(inpfile, self.planerotation_objects, con_planerotation)
|
||||
@@ -294,267 +294,4 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
if write_after != "":
|
||||
f.write(write_after)
|
||||
|
||||
# ********************************************************************************************
|
||||
# material and fem element geometry
|
||||
# def write_element_sets_material_and_femelement_geometry(self, f):
|
||||
def write_element_sets_material_and_femelement_type(self, f):
|
||||
|
||||
# write ccx_elsets to file
|
||||
f.write("\n***********************************************************\n")
|
||||
f.write("** Element sets for materials and FEM element type (solid, shell, beam, fluid)\n")
|
||||
for ccx_elset in self.ccx_elsets:
|
||||
f.write("*ELSET,ELSET=" + ccx_elset["ccx_elset_name"] + "\n")
|
||||
# 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"]:
|
||||
f.write(str(elid) + ",\n")
|
||||
|
||||
def is_density_needed(self):
|
||||
if self.analysis_type == "frequency":
|
||||
return True
|
||||
if self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState:
|
||||
return True
|
||||
if self.centrif_objects:
|
||||
return True
|
||||
if self.selfweight_objects:
|
||||
return True
|
||||
return False
|
||||
|
||||
def write_materials(self, f):
|
||||
f.write("\n***********************************************************\n")
|
||||
f.write("** Materials\n")
|
||||
f.write("** Young\'s modulus unit is MPa = N/mm2\n")
|
||||
if self.is_density_needed() is True:
|
||||
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"]
|
||||
mat_obj = femobj["Object"]
|
||||
mat_info_name = mat_obj.Material["Name"]
|
||||
mat_name = mat_obj.Name
|
||||
mat_label = mat_obj.Label
|
||||
# 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.is_density_needed() is True:
|
||||
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"])
|
||||
# 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"])
|
||||
# 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"))
|
||||
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("** " + mat_label + "\n")
|
||||
f.write("*MATERIAL, NAME=" + mat_name + "\n")
|
||||
if mat_obj.Category == "Solid":
|
||||
f.write("*ELASTIC\n")
|
||||
f.write("{0:.0f}, {1:.3f}\n".format(YM_in_MPa, PR))
|
||||
|
||||
if self.is_density_needed() is True:
|
||||
f.write("*DENSITY\n")
|
||||
f.write("{0:.3e}\n".format(density_in_tonne_per_mm3))
|
||||
if self.analysis_type == "thermomech":
|
||||
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 nlfemobj in self.material_nonlinear_objects:
|
||||
# femobj --> dict, FreeCAD document object is nlfemobj["Object"]
|
||||
nl_mat_obj = nlfemobj["Object"]
|
||||
if nl_mat_obj.LinearBaseMaterial == mat_obj:
|
||||
if nl_mat_obj.MaterialModelNonlinearity == "simple hardening":
|
||||
f.write("*PLASTIC\n")
|
||||
if nl_mat_obj.YieldPoint1:
|
||||
f.write(nl_mat_obj.YieldPoint1 + "\n")
|
||||
if nl_mat_obj.YieldPoint2:
|
||||
f.write(nl_mat_obj.YieldPoint2 + "\n")
|
||||
if nl_mat_obj.YieldPoint3:
|
||||
f.write(nl_mat_obj.YieldPoint3 + "\n")
|
||||
f.write("\n")
|
||||
|
||||
# def write_femelement_geometry(self, f):
|
||||
def write_femelementsets(self, f):
|
||||
f.write("\n***********************************************************\n")
|
||||
f.write("** Sections\n")
|
||||
for ccx_elset in self.ccx_elsets:
|
||||
if ccx_elset["ccx_elset"]:
|
||||
if "beamsection_obj"in ccx_elset: # beam mesh
|
||||
beamsec_obj = ccx_elset["beamsection_obj"]
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
normal = ccx_elset["beam_normal"]
|
||||
if beamsec_obj.SectionType == "Rectangular":
|
||||
height = beamsec_obj.RectHeight.getValueAs("mm")
|
||||
width = beamsec_obj.RectWidth.getValueAs("mm")
|
||||
section_type = ", SECTION=RECT"
|
||||
section_geo = str(height) + ", " + str(width) + "\n"
|
||||
section_def = "*BEAM SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
elif beamsec_obj.SectionType == "Circular":
|
||||
radius = 0.5 * beamsec_obj.CircDiameter.getValueAs("mm")
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = str(radius) + "\n"
|
||||
section_def = "*BEAM SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
elif beamsec_obj.SectionType == "Pipe":
|
||||
radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs("mm")
|
||||
thickness = beamsec_obj.PipeThickness.getValueAs("mm")
|
||||
section_type = ", SECTION=PIPE"
|
||||
section_geo = str(radius) + ", " + str(thickness) + "\n"
|
||||
section_def = "*BEAM GENERAL SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
)
|
||||
# see forum topic for output formatting of rotation
|
||||
# https://forum.freecadweb.org/viewtopic.php?f=18&t=46133&p=405142#p405142
|
||||
section_nor = "{:f}, {:f}, {:f}\n".format(
|
||||
normal[0],
|
||||
normal[1],
|
||||
normal[2]
|
||||
)
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
f.write(section_nor)
|
||||
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"
|
||||
section_def = "*FLUID SECTION, {}TYPE={}, {}\n".format(
|
||||
elsetdef,
|
||||
section_type,
|
||||
material
|
||||
)
|
||||
section_geo = liquid_section_def(fluidsec_obj, section_type)
|
||||
"""
|
||||
# deactivate as it would result in section_def and section_geo not defined
|
||||
# deactivated in the App and Gui object and thus in the task panel as well
|
||||
elif fluidsec_obj.SectionType == "Gas":
|
||||
section_type = fluidsec_obj.GasSectionType
|
||||
elif fluidsec_obj.SectionType == "Open Channel":
|
||||
section_type = fluidsec_obj.ChannelSectionType
|
||||
"""
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
elif "shellthickness_obj"in ccx_elset: # shell mesh
|
||||
shellth_obj = ccx_elset["shellthickness_obj"]
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
section_def = "*SHELL SECTION, " + elsetdef + material + "\n"
|
||||
section_geo = str(shellth_obj.Thickness.getValueAs("mm")) + "\n"
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
else: # solid mesh
|
||||
elsetdef = "ELSET=" + ccx_elset["ccx_elset_name"] + ", "
|
||||
material = "MATERIAL=" + ccx_elset["mat_obj_name"]
|
||||
section_def = "*SOLID SECTION, " + elsetdef + material + "\n"
|
||||
f.write(section_def)
|
||||
|
||||
|
||||
# ************************************************************************************************
|
||||
# Helpers
|
||||
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 = ("{},{},{},{}\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)
|
||||
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 = ("{},{},{},{},{}\n".format(
|
||||
colebrooke_area,
|
||||
colebrooke_diameter,
|
||||
"-1",
|
||||
colebrooke_grain_diameter,
|
||||
colebrooke_form_factor
|
||||
))
|
||||
return section_geo
|
||||
elif section_type == "LIQUID PUMP":
|
||||
section_geo = ""
|
||||
for i in range(len(obj.PumpFlowRate)):
|
||||
flow_rate = str(obj.PumpFlowRate[i])
|
||||
top = str(obj.PumpHeadLoss[i])
|
||||
section_geo = section_geo + flow_rate + "," + top + ","
|
||||
section_geo = section_geo + "\n"
|
||||
return section_geo
|
||||
else:
|
||||
return ""
|
||||
## @}
|
||||
|
||||
Reference in New Issue
Block a user