FEM: calculix writer, move material, element geometry and mat-geo-elementsets into separte methods

This commit is contained in:
Bernd Hahnebach
2021-07-12 23:44:13 +02:00
parent 9fa444c113
commit d72d24b30c
5 changed files with 432 additions and 269 deletions

View File

@@ -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

View 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 ""

View 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 ""

View File

@@ -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")

View File

@@ -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 ""
## @}