FEM: calculix writer, move constraint fluidsection in separate module
This commit is contained in:
@@ -192,6 +192,7 @@ SET(FemSolverCalculix_SRCS
|
||||
femsolver/calculix/con_contact.py
|
||||
femsolver/calculix/con_displacement.py
|
||||
femsolver/calculix/con_fixed.py
|
||||
femsolver/calculix/con_fluidsection.py
|
||||
femsolver/calculix/con_force.py
|
||||
femsolver/calculix/con_heatflux.py
|
||||
femsolver/calculix/con_initialtemperature.py
|
||||
|
||||
220
src/Mod/Fem/femsolver/calculix/con_fluidsection.py
Normal file
220
src/Mod/Fem/femsolver/calculix/con_fluidsection.py
Normal file
@@ -0,0 +1,220 @@
|
||||
# ***************************************************************************
|
||||
# * 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 constraint fluidsection"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import six
|
||||
from os.path import join
|
||||
|
||||
import FreeCAD
|
||||
|
||||
from femmesh import meshtools
|
||||
|
||||
|
||||
# ********************************************************************************************
|
||||
# handle elements for constraints fluidsection with Liquid Inlet or Outlet
|
||||
# belongs to write_constraints_fluidsection, should be next method
|
||||
# leave the constraints fluidsection code as the last constraint method in this module
|
||||
# as it is none standard constraint method compared to all other constraints
|
||||
def handle_fluidsection_liquid_inlet_outlet(inpfile, ccxwriter):
|
||||
|
||||
# Fluid sections:
|
||||
# fluidsection Liquid inlet outlet objs requires special element definition
|
||||
# to fill ccxwriter.FluidInletoutlet_ele list the ccx_elset are needed
|
||||
# thus this has to be after the creation of ccx_elsets
|
||||
# different pipe cross sections will generate ccx_elsets
|
||||
|
||||
ccxwriter.FluidInletoutlet_ele = []
|
||||
ccxwriter.fluid_inout_nodes_file = join(
|
||||
ccxwriter.dir_name,
|
||||
"{}_inout_nodes.txt".format(ccxwriter.mesh_name)
|
||||
)
|
||||
|
||||
def get_fluidsection_inoutlet_obj_if_setdata(ccx_elset):
|
||||
if (
|
||||
ccx_elset["ccx_elset"]
|
||||
# use six to be sure to be Python 2.7 and 3.x compatible
|
||||
and not isinstance(ccx_elset["ccx_elset"], six.string_types)
|
||||
and "fluidsection_obj" in ccx_elset # fluid mesh
|
||||
):
|
||||
fluidsec_obj = ccx_elset["fluidsection_obj"]
|
||||
if (
|
||||
fluidsec_obj.SectionType == "Liquid"
|
||||
and (
|
||||
fluidsec_obj.LiquidSectionType == "PIPE INLET"
|
||||
or fluidsec_obj.LiquidSectionType == "PIPE OUTLET"
|
||||
)
|
||||
):
|
||||
return fluidsec_obj
|
||||
return None
|
||||
|
||||
def is_fluidsection_inoutlet_setnames_possible(ccx_elsets):
|
||||
for ccx_elset in ccx_elsets:
|
||||
if (
|
||||
ccx_elset["ccx_elset"]
|
||||
and "fluidsection_obj" in ccx_elset # fluid mesh
|
||||
):
|
||||
fluidsec_obj = ccx_elset["fluidsection_obj"]
|
||||
if (
|
||||
fluidsec_obj.SectionType == "Liquid"
|
||||
and (
|
||||
fluidsec_obj.LiquidSectionType == "PIPE INLET"
|
||||
or fluidsec_obj.LiquidSectionType == "PIPE OUTLET"
|
||||
)
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
# collect elementIDs for fluidsection Liquid inlet outlet objs
|
||||
# if they have element data (happens if not "eall")
|
||||
for ccx_elset in ccxwriter.ccx_elsets:
|
||||
fluidsec_obj = get_fluidsection_inoutlet_obj_if_setdata(ccx_elset)
|
||||
if fluidsec_obj is None:
|
||||
continue
|
||||
elsetchanged = False
|
||||
counter = 0
|
||||
for elid in ccx_elset["ccx_elset"]:
|
||||
counter = counter + 1
|
||||
if (elsetchanged is False) \
|
||||
and (fluidsec_obj.LiquidSectionType == "PIPE INLET"):
|
||||
# 3rd index is to track which line nr the element is defined
|
||||
ccxwriter.FluidInletoutlet_ele.append(
|
||||
[str(elid), fluidsec_obj.LiquidSectionType, 0]
|
||||
)
|
||||
elsetchanged = True
|
||||
elif (fluidsec_obj.LiquidSectionType == "PIPE OUTLET") \
|
||||
and (counter == len(ccx_elset["ccx_elset"])):
|
||||
# 3rd index is to track which line nr the element is defined
|
||||
ccxwriter.FluidInletoutlet_ele.append(
|
||||
[str(elid), fluidsec_obj.LiquidSectionType, 0]
|
||||
)
|
||||
|
||||
# create the correct element definition for fluidsection Liquid inlet outlet objs
|
||||
# at least one "fluidsection_obj" needs to be in ccx_elsets and has the attributes
|
||||
# TODO: what if there are other objs in elsets?
|
||||
if is_fluidsection_inoutlet_setnames_possible(ccxwriter.ccx_elsets) is not None:
|
||||
# it is not distinguished if split input file
|
||||
# for split input file the main file is just closed and reopend even if not needed
|
||||
inpfile.close()
|
||||
meshtools.use_correct_fluidinout_ele_def(
|
||||
ccxwriter.FluidInletoutlet_ele,
|
||||
ccxwriter.femmesh_file,
|
||||
ccxwriter.fluid_inout_nodes_file
|
||||
)
|
||||
inpfile = codecs.open(ccxwriter.file_name, "a", encoding="utf-8")
|
||||
|
||||
return inpfile
|
||||
|
||||
|
||||
# ********************************************************************************************
|
||||
# TODO:
|
||||
# split method into separate methods and move some part into base writer
|
||||
# see also method handle_fluidsection_liquid_inlet_outlet
|
||||
def write_constraints_fluidsection(f, ccxwriter):
|
||||
if not ccxwriter.fluidsection_objects:
|
||||
return
|
||||
if ccxwriter.analysis_type not in ["thermomech"]:
|
||||
return
|
||||
|
||||
# write constraint to file
|
||||
f.write("\n***********************************************************\n")
|
||||
f.write("** FluidSection constraints\n")
|
||||
if os.path.exists(ccxwriter.fluid_inout_nodes_file):
|
||||
inout_nodes_file = open(ccxwriter.fluid_inout_nodes_file, "r")
|
||||
lines = inout_nodes_file.readlines()
|
||||
inout_nodes_file.close()
|
||||
else:
|
||||
FreeCAD.Console.PrintError(
|
||||
"1DFlow inout nodes file not found: {}\n"
|
||||
.format(ccxwriter.fluid_inout_nodes_file)
|
||||
)
|
||||
# get nodes
|
||||
ccxwriter.get_constraints_fluidsection_nodes()
|
||||
for femobj in ccxwriter.fluidsection_objects:
|
||||
# femobj --> dict, FreeCAD document object is femobj["Object"]
|
||||
fluidsection_obj = femobj["Object"]
|
||||
f.write("** " + fluidsection_obj.Label + "\n")
|
||||
if fluidsection_obj.SectionType == "Liquid":
|
||||
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":
|
||||
# degree of freedom 2 is for defining pressure
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[0],
|
||||
"2",
|
||||
"2",
|
||||
fluidsection_obj.InletPressure
|
||||
))
|
||||
if fluidsection_obj.InletFlowRateActive is True:
|
||||
f.write("*BOUNDARY,MASS FLOW \n")
|
||||
for n in femobj["Nodes"]:
|
||||
for line in lines:
|
||||
b = line.split(",")
|
||||
if int(b[0]) == n and b[3] == "PIPE INLET\n":
|
||||
# degree of freedom 1 is for defining flow rate
|
||||
# factor applied to convert unit from kg/s to t/s
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[1],
|
||||
"1",
|
||||
"1",
|
||||
fluidsection_obj.InletFlowRate * 0.001
|
||||
))
|
||||
elif fluidsection_obj.LiquidSectionType == "PIPE OUTLET":
|
||||
f.write("**Fluid Section Outlet \n")
|
||||
if fluidsection_obj.OutletPressureActive is True:
|
||||
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":
|
||||
# degree of freedom 2 is for defining pressure
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[0],
|
||||
"2",
|
||||
"2",
|
||||
fluidsection_obj.OutletPressure
|
||||
))
|
||||
if fluidsection_obj.OutletFlowRateActive is True:
|
||||
f.write("*BOUNDARY,MASS FLOW \n")
|
||||
for n in femobj["Nodes"]:
|
||||
for line in lines:
|
||||
b = line.split(",")
|
||||
if int(b[0]) == n and b[3] == "PIPE OUTLET\n":
|
||||
# degree of freedom 1 is for defining flow rate
|
||||
# factor applied to convert unit from kg/s to t/s
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[1],
|
||||
"1",
|
||||
"1",
|
||||
fluidsection_obj.OutletFlowRate * 0.001
|
||||
))
|
||||
@@ -42,6 +42,7 @@ from . import con_centrif
|
||||
from . import con_contact
|
||||
from . import con_displacement
|
||||
from . import con_fixed
|
||||
from . import con_fluidsection
|
||||
from . import con_force
|
||||
from . import con_heatflux
|
||||
from . import con_initialtemperature as con_initialtemp
|
||||
@@ -192,7 +193,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
|
||||
if self.fluidsection_objects:
|
||||
# some fluidsection objs need special treatment, ccx_elsets are needed for this
|
||||
inpfile = self.handle_fluidsection_liquid_inlet_outlet(inpfile)
|
||||
inpfile = con_fluidsection.handle_fluidsection_liquid_inlet_outlet(inpfile, self)
|
||||
|
||||
# element sets constraints
|
||||
self.write_constraints_sets(inpfile, self.centrif_objects, con_centrif)
|
||||
@@ -234,7 +235,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
self.write_constraints_sets(inpfile, self.pressure_objects, con_pressure)
|
||||
self.write_constraints_data(inpfile, self.temperature_objects, con_temperature)
|
||||
self.write_constraints_sets(inpfile, self.heatflux_objects, con_heatflux)
|
||||
self.write_constraints_fluidsection(inpfile)
|
||||
con_fluidsection.write_constraints_fluidsection(inpfile, self)
|
||||
|
||||
# output and step end
|
||||
self.write_outputs_types(inpfile)
|
||||
@@ -365,189 +366,6 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
if write_after != "":
|
||||
f.write(write_after)
|
||||
|
||||
# ********************************************************************************************
|
||||
# handle elements for constraints fluidsection with Liquid Inlet or Outlet
|
||||
# belongs to write_constraints_fluidsection, should be next method
|
||||
# leave the constraints fluidsection code as the last constraint method in this module
|
||||
# as it is none standard constraint method compared to all other constraints
|
||||
def handle_fluidsection_liquid_inlet_outlet(self, inpfile):
|
||||
|
||||
# Fluid sections:
|
||||
# fluidsection Liquid inlet outlet objs requires special element definition
|
||||
# to fill self.FluidInletoutlet_ele list the ccx_elset are needed
|
||||
# thus this has to be after the creation of ccx_elsets
|
||||
# different pipe cross sections will generate ccx_elsets
|
||||
|
||||
self.FluidInletoutlet_ele = []
|
||||
self.fluid_inout_nodes_file = join(
|
||||
self.dir_name,
|
||||
"{}_inout_nodes.txt".format(self.mesh_name)
|
||||
)
|
||||
|
||||
def get_fluidsection_inoutlet_obj_if_setdata(ccx_elset):
|
||||
if (
|
||||
ccx_elset["ccx_elset"]
|
||||
# use six to be sure to be Python 2.7 and 3.x compatible
|
||||
and not isinstance(ccx_elset["ccx_elset"], six.string_types)
|
||||
and "fluidsection_obj" in ccx_elset # fluid mesh
|
||||
):
|
||||
fluidsec_obj = ccx_elset["fluidsection_obj"]
|
||||
if (
|
||||
fluidsec_obj.SectionType == "Liquid"
|
||||
and (
|
||||
fluidsec_obj.LiquidSectionType == "PIPE INLET"
|
||||
or fluidsec_obj.LiquidSectionType == "PIPE OUTLET"
|
||||
)
|
||||
):
|
||||
return fluidsec_obj
|
||||
return None
|
||||
|
||||
def is_fluidsection_inoutlet_setnames_possible(ccx_elsets):
|
||||
for ccx_elset in ccx_elsets:
|
||||
if (
|
||||
ccx_elset["ccx_elset"]
|
||||
and "fluidsection_obj" in ccx_elset # fluid mesh
|
||||
):
|
||||
fluidsec_obj = ccx_elset["fluidsection_obj"]
|
||||
if (
|
||||
fluidsec_obj.SectionType == "Liquid"
|
||||
and (
|
||||
fluidsec_obj.LiquidSectionType == "PIPE INLET"
|
||||
or fluidsec_obj.LiquidSectionType == "PIPE OUTLET"
|
||||
)
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
# collect elementIDs for fluidsection Liquid inlet outlet objs
|
||||
# if they have element data (happens if not "eall")
|
||||
for ccx_elset in self.ccx_elsets:
|
||||
fluidsec_obj = get_fluidsection_inoutlet_obj_if_setdata(ccx_elset)
|
||||
if fluidsec_obj is None:
|
||||
continue
|
||||
elsetchanged = False
|
||||
counter = 0
|
||||
for elid in ccx_elset["ccx_elset"]:
|
||||
counter = counter + 1
|
||||
if (elsetchanged is False) \
|
||||
and (fluidsec_obj.LiquidSectionType == "PIPE INLET"):
|
||||
# 3rd index is to track which line nr the element is defined
|
||||
self.FluidInletoutlet_ele.append(
|
||||
[str(elid), fluidsec_obj.LiquidSectionType, 0]
|
||||
)
|
||||
elsetchanged = True
|
||||
elif (fluidsec_obj.LiquidSectionType == "PIPE OUTLET") \
|
||||
and (counter == len(ccx_elset["ccx_elset"])):
|
||||
# 3rd index is to track which line nr the element is defined
|
||||
self.FluidInletoutlet_ele.append(
|
||||
[str(elid), fluidsec_obj.LiquidSectionType, 0]
|
||||
)
|
||||
|
||||
# create the correct element definition for fluidsection Liquid inlet outlet objs
|
||||
# at least one "fluidsection_obj" needs to be in ccx_elsets and has the attributes
|
||||
# TODO: what if there are other objs in elsets?
|
||||
if is_fluidsection_inoutlet_setnames_possible(self.ccx_elsets) is not None:
|
||||
# it is not distinguished if split input file
|
||||
# for split input file the main file is just closed and reopend even if not needed
|
||||
inpfile.close()
|
||||
meshtools.use_correct_fluidinout_ele_def(
|
||||
self.FluidInletoutlet_ele,
|
||||
self.femmesh_file,
|
||||
self.fluid_inout_nodes_file
|
||||
)
|
||||
inpfile = codecs.open(self.file_name, "a", encoding="utf-8")
|
||||
|
||||
return inpfile
|
||||
|
||||
# ********************************************************************************************
|
||||
# constraints fluidsection
|
||||
# TODO:
|
||||
# split method into separate methods and move some part into base writer
|
||||
# see also method handle_fluidsection_liquid_inlet_outlet
|
||||
def write_constraints_fluidsection(self, f):
|
||||
if not self.fluidsection_objects:
|
||||
return
|
||||
if self.analysis_type not in ["thermomech"]:
|
||||
return
|
||||
|
||||
# write constraint to file
|
||||
f.write("\n***********************************************************\n")
|
||||
f.write("** FluidSection constraints\n")
|
||||
if os.path.exists(self.fluid_inout_nodes_file):
|
||||
inout_nodes_file = open(self.fluid_inout_nodes_file, "r")
|
||||
lines = inout_nodes_file.readlines()
|
||||
inout_nodes_file.close()
|
||||
else:
|
||||
FreeCAD.Console.PrintError(
|
||||
"1DFlow inout nodes file not found: {}\n"
|
||||
.format(self.fluid_inout_nodes_file)
|
||||
)
|
||||
# get nodes
|
||||
self.get_constraints_fluidsection_nodes()
|
||||
for femobj in self.fluidsection_objects:
|
||||
# femobj --> dict, FreeCAD document object is femobj["Object"]
|
||||
fluidsection_obj = femobj["Object"]
|
||||
f.write("** " + fluidsection_obj.Label + "\n")
|
||||
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":
|
||||
# degree of freedom 2 is for defining pressure
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[0],
|
||||
"2",
|
||||
"2",
|
||||
fluidsection_obj.InletPressure
|
||||
))
|
||||
if fluidsection_obj.InletFlowRateActive is True:
|
||||
f.write("*BOUNDARY,MASS FLOW \n")
|
||||
for n in femobj["Nodes"]:
|
||||
for line in lines:
|
||||
b = line.split(",")
|
||||
if int(b[0]) == n and b[3] == "PIPE INLET\n":
|
||||
# degree of freedom 1 is for defining flow rate
|
||||
# factor applied to convert unit from kg/s to t/s
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[1],
|
||||
"1",
|
||||
"1",
|
||||
fluidsection_obj.InletFlowRate * 0.001
|
||||
))
|
||||
elif fluidsection_obj.LiquidSectionType == "PIPE OUTLET":
|
||||
f.write("**Fluid Section Outlet \n")
|
||||
if fluidsection_obj.OutletPressureActive is True:
|
||||
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":
|
||||
# degree of freedom 2 is for defining pressure
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[0],
|
||||
"2",
|
||||
"2",
|
||||
fluidsection_obj.OutletPressure
|
||||
))
|
||||
if fluidsection_obj.OutletFlowRateActive is True:
|
||||
f.write("*BOUNDARY,MASS FLOW \n")
|
||||
for n in femobj["Nodes"]:
|
||||
for line in lines:
|
||||
b = line.split(",")
|
||||
if int(b[0]) == n and b[3] == "PIPE OUTLET\n":
|
||||
# degree of freedom 1 is for defining flow rate
|
||||
# factor applied to convert unit from kg/s to t/s
|
||||
f.write("{},{},{},{}\n".format(
|
||||
b[1],
|
||||
"1",
|
||||
"1",
|
||||
fluidsection_obj.OutletFlowRate * 0.001
|
||||
))
|
||||
|
||||
# ********************************************************************************************
|
||||
# step begin and end
|
||||
def write_step_begin(self, f):
|
||||
|
||||
Reference in New Issue
Block a user