File size: 10,251 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# ***************************************************************************
# *   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.freecad.org"


import codecs
import os
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):

    if not ccxwriter.member.geos_fluidsection:
        return inpfile

    # Fluid sections:
    # fluidsection Liquid inlet outlet objs  requires special element definition
    # to fill ccxwriter.FluidInletoutlet_ele list the mat_geo_sets are needed
    # thus this has to be after the creation of mat_geo_sets
    # different pipe cross sections will generate mat_geo_sets

    ccxwriter.FluidInletoutlet_ele = []
    ccxwriter.fluid_inout_nodes_file = join(
        ccxwriter.dir_name, f"{ccxwriter.mesh_name}_inout_nodes.txt"
    )

    def get_fluidsection_inoutlet_obj_if_setdata(matgeoset):
        if (
            matgeoset["ccx_elset"]
            and not isinstance(matgeoset["ccx_elset"], str)
            and "fluidsection_obj" in matgeoset  # fluid mesh
        ):
            fluidsec_obj = matgeoset["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(mat_geo_sets):
        for matgeoset in mat_geo_sets:
            if matgeoset["ccx_elset"] and "fluidsection_obj" in matgeoset:  # fluid mesh
                fluidsec_obj = matgeoset["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 matgeoset in ccxwriter.mat_geo_sets:
        fluidsec_obj = get_fluidsection_inoutlet_obj_if_setdata(matgeoset)
        if fluidsec_obj is None:
            continue
        elsetchanged = False
        counter = 0
        for elid in matgeoset["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(matgeoset["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 mat_geo_sets and has the attributes
    # TODO: what if there are other objs in elsets?
    if is_fluidsection_inoutlet_setnames_possible(ccxwriter.mat_geo_sets) 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.member.geos_fluidsection:
        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)
        lines = inout_nodes_file.readlines()
        inout_nodes_file.close()
    else:
        FreeCAD.Console.PrintError(
            f"1DFlow inout nodes file not found: {ccxwriter.fluid_inout_nodes_file}\n"
        )
    # get nodes
    ccxwriter.get_constraints_fluidsection_nodes()
    for femobj in ccxwriter.member.geos_fluidsection:
        # 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
                                    )
                                )