|
40 | 40 | the heated wall of the pipe conducts heat to the inner wall, which in turns heats the fluid and |
41 | 41 | cools down the walls of the pipe. |
42 | 42 |
|
43 | | -#image |
| 43 | +
|
44 | 44 |
|
45 | 45 | The flow is smooth inside the pipe and the outer wall of the pipe is adiabatic. Fluid enters |
46 | | -at an initial temperature of 300K while the outside pipe of the wall is at some higher |
47 | | -temperature. The setup is simulated for a few iterations to allow the examination |
| 46 | +at an initial temperature of 300K while the outside pipe of the wall is at 400K. |
| 47 | +The setup is simulated for a few iterations to allow the examination |
48 | 48 | of the temperature field in the pipe. |
49 | 49 |
|
50 | 50 | """ |
|
58 | 58 | # ~~~~~~~~~~~~~~~~~~~~~~~~ |
59 | 59 | # Import ``ansys-systemcoupling-core``, ``ansys-fluent-core`` |
60 | 60 |
|
| 61 | +import ansys.mapdl.core as pymapdl |
61 | 62 | import ansys.fluent.core as pyfluent |
62 | | - |
63 | 63 | import ansys.systemcoupling.core as pysyc |
| 64 | +from ansys.systemcoupling.core import examples |
64 | 65 |
|
65 | | -# === |
66 | | - |
67 | | -# launch Fluent session and read in mesh file |
68 | | -pipe_fluid_session = pyfluent.launch_fluent(start_transcript=False) |
69 | | -pipe_fluid_mesh_file = "pipe_fluid.msh.h5" |
70 | | -pipe_fluid_session.file.read(file_type="mesh", file_name=pipe_fluid_mesh_file) |
71 | | - |
72 | | -# turn on energy model |
73 | | -pipe_fluid_session.setup.models.energy.enabled = True |
74 | | - |
75 | | -# add water material |
76 | | -pipe_fluid_session.setup.materials.database.copy_by_name( |
77 | | - type="fluid", name="water-liquid" |
78 | | -) |
79 | | - |
80 | | -# set up cell zone conditions |
81 | | -pipe_fluid_session.setup.cell_zone_conditions.fluid["fluid"].material = "water-liquid" |
82 | | - |
83 | | -# set up boundary conditions |
84 | | -pipe_fluid_session.setup.boundary_conditions.velocity_inlet[ |
85 | | - "inlet" |
86 | | -].momentum.velocity = 0.1 |
87 | | -pipe_fluid_session.setup.boundary_conditions.wall["wall"].thermal.thermal_bc = ( |
88 | | - "via System Coupling" |
89 | | -) |
90 | | - |
91 | | -# set up solver settings - 1 fluent iteration per 1 coupling iteration |
92 | | -pipe_fluid_session.solution.run_calculation.iter_count = 1 |
93 | | - |
94 | | -# === |
95 | | - |
96 | | -# launch another Fluent session and read in mesh file |
97 | | -pipe_solid_session = pyfluent.launch_fluent(start_transcript=False) |
98 | | -pipe_solid_mesh_file = "pipe_solid.msh.h5" |
99 | | -pipe_solid_session.file.read(file_type="mesh", file_name=pipe_solid_mesh_file) |
100 | | - |
101 | | -# turn on energy model |
102 | | -pipe_solid_session.setup.models.energy.enabled = True |
103 | | - |
104 | | -# add copper material |
105 | | -pipe_solid_session.setup.materials.database.copy_by_name(type="solid", name="copper") |
106 | | - |
107 | | -# set up cell zone conditions |
108 | | -pipe_solid_session.setup.cell_zone_conditions.solid["solid"].material = "copper" |
109 | | - |
110 | | -# set up boundary conditions |
111 | | -pipe_solid_session.setup.boundary_conditions.wall["outer_wall"].thermal.thermal_bc = ( |
112 | | - "Temperature" |
113 | | -) |
114 | | -pipe_solid_session.setup.boundary_conditions.wall["outer_wall"].thermal.t.value = 350 |
115 | | - |
116 | | -pipe_solid_session.setup.boundary_conditions.wall["inner_wall"].thermal.thermal_bc = ( |
117 | | - "via System Coupling" |
118 | | -) |
119 | | - |
120 | | -pipe_solid_session.setup.boundary_conditions.wall["insulated1"].thermal.thermal_bc = ( |
121 | | - "Heat Flux" |
122 | | -) |
123 | | -pipe_solid_session.setup.boundary_conditions.wall["insulated1"].thermal.q.value = 0 |
124 | | - |
125 | | -pipe_solid_session.setup.boundary_conditions.wall["insulated2"].thermal.thermal_bc = ( |
126 | | - "Heat Flux" |
| 66 | +# %% |
| 67 | +# Download the mesh file |
| 68 | +fluent_msh_file = examples.download_file( |
| 69 | + "fluid_domain.msh", "pysystem-coupling/cht_pipe" |
127 | 70 | ) |
128 | | -pipe_solid_session.setup.boundary_conditions.wall["insulated2"].thermal.q.value = 0 |
129 | | - |
130 | | -# set up solver settings - 1 fluent iteration per 1 coupling iteration |
131 | | -pipe_solid_session.solution.run_calculation.iter_count = 1 |
132 | | - |
133 | | - |
134 | | -rho_water = 998.2 |
135 | | -mu_water = 1.002e-3 |
136 | | -k_water = 0.6 |
137 | | -Pr_water = 7.0 |
138 | 71 |
|
139 | | -rho_al = 2700 |
140 | | -k_al = 237 |
141 | | -cp_al = 900 |
| 72 | +mapdl=pymapdl.launch_mapdl() |
| 73 | +mapdl.clear() |
| 74 | +mapdl.prep7() |
| 75 | + |
| 76 | +#%% |
| 77 | +#Define material properties |
| 78 | +mapdl.mp("EX", 1, 69e9) |
| 79 | +mapdl.mp("NUXY", 1, 0.33) |
| 80 | +mapdl.mp("DENS", 1, 2700) |
| 81 | +mapdl.mp("ALPX", 1, 23.6e-6) |
| 82 | +mapdl.mp("KXX", 1, 237) |
| 83 | +mapdl.mp("C", 1 , 900) |
| 84 | + |
| 85 | +#%% |
| 86 | +#Set element type to SOLID279 |
| 87 | +mapdl.et(1, 279) |
| 88 | +mapdl.keyopt(1, 2, 1) |
| 89 | +print(mapdl) |
| 90 | + |
| 91 | +#%% |
| 92 | +#Parameter of the pipe |
| 93 | +r_in=0.025 |
| 94 | +r_out=0.035 |
| 95 | +l=0.2 |
| 96 | + |
| 97 | +#%% |
| 98 | +#Create hollow pipe |
| 99 | +mapdl.cyl4(0, 0, rad1=r_in, rad2=r_out, depth=l) |
| 100 | +mapdl.esize(0.002) |
| 101 | +mapdl.vsweep(1) |
| 102 | +print(mapdl.geometry.anum) |
142 | 103 |
|
| 104 | +# %% |
| 105 | +# Biot number prediction |
| 106 | +def biot_number( |
| 107 | + rho=1000, |
| 108 | + mu=1e-3, |
| 109 | + cp=4180, |
| 110 | + k_f=0.6, |
| 111 | + k_s=237, |
| 112 | + L_c=r_out-r_in, |
| 113 | + U=0.1 |
| 114 | +): |
| 115 | + Re= (rho*U*L_c)/mu |
| 116 | + Pr= (mu*cp)/ k_f |
| 117 | + Nu= 0.023 * Re**0.8 * Pr**0.4 |
| 118 | + h= Nu * k_f / L_c |
| 119 | + Bi= h *L_c / k_s |
| 120 | + return Bi |
| 121 | +Bi=biot_number() |
| 122 | +print("The Biot number is ", Bi) |
143 | 123 |
|
144 | | -# Flow and Geometry |
145 | | - |
146 | | -u = 0.5 # velocity [m/s] |
147 | | -L = 0.5 # pipe length [m] |
148 | | -D = 0.1 # inner diameter [m] → characteristic length for fluid |
149 | | -t_wall = 0.12 # wall thickness [m] → characteristic length for solid conduction |
150 | | - |
151 | | - |
152 | | -# Functions |
153 | | - |
154 | | - |
155 | | -def getReynoldsNumber(rho, u, D, mu): |
156 | | - return rho * u * D / mu |
157 | | - |
158 | | - |
159 | | -def getPrandtlNumber(mu, cp, k): |
160 | | - return mu * cp / k |
161 | | - |
162 | | - |
163 | | -def getNusseltNumber(Re, Pr, L_over_D): |
164 | | - |
165 | | - if Re < 2300: |
166 | | - Nu = 3.66 # laminar, fully developed |
167 | | - elif Re < 10000: |
168 | | - Nu = 0.023 * Re**0.8 * Pr**0.4 # transitional approximation |
169 | | - else: |
170 | | - Nu = 0.023 * Re**0.8 * Pr**0.4 # fully turbulent |
171 | | - return Nu |
172 | | - |
173 | | - |
174 | | -def getConvectionCoefficient(Nu, k_fluid, D): |
175 | | - return Nu * k_fluid / D |
176 | | - |
177 | | - |
178 | | -def getBiotNumber(h, k_solid, t_wall): |
179 | | - return h * t_wall / k_solid |
180 | | - |
| 124 | +# %% |
| 125 | +# Creating the regions from the geometry for named selections |
| 126 | +#Inner wall NS |
| 127 | +mapdl.asel('S', 'AREA', '', 5, 6) |
| 128 | +mapdl.nsla('S', 1) |
| 129 | +mapdl.cm("FSIN_1", "NODE") |
| 130 | +mapdl.allsel() |
| 131 | + |
| 132 | +#Outer wall NS |
| 133 | +mapdl.asel('S', 'AREA', '', 3, 4) |
| 134 | +mapdl.cm("Outer_wall", "AREA") |
| 135 | +mapdl.allsel() |
| 136 | + |
| 137 | +#Outlet NS |
| 138 | +mapdl.asel('S', 'AREA', '', 2) |
| 139 | +mapdl.cm("Outlet", "AREA") |
| 140 | +mapdl.allsel() |
| 141 | + |
| 142 | +#Inlet NS |
| 143 | +mapdl.asel('S', 'AREA', '', 1) |
| 144 | +mapdl.cm("Inlet", "AREA") |
| 145 | +mapdl.allsel() |
| 146 | + |
| 147 | +#%% |
| 148 | +#Boundary conditions |
| 149 | +mapdl.cmsel('S', 'Outer_wall') |
| 150 | +mapdl.d('Outer_wall', 'TEMP', 77) |
| 151 | +mapdl.allsel() |
| 152 | + |
| 153 | +mapdl.cmsel('S', 'Inlet') |
| 154 | +mapdl.sf('ALL', 'HFLUX', 0) |
| 155 | +mapdl.allsel() |
| 156 | + |
| 157 | +mapdl.cmsel('S', 'Outlet') |
| 158 | +mapdl.sf('ALL', 'HFLUX', 0) |
| 159 | +mapdl.allsel() |
| 160 | + |
| 161 | +mapdl.cmsel('S', 'FSIN_1') |
| 162 | +mapdl.sf('FSIN_1', 'FSIN', 1) |
| 163 | +mapdl.allsel() |
| 164 | + |
| 165 | +#%% |
| 166 | +#Setup the rest of the analysis |
| 167 | +mapdl.run("/SOLU") |
| 168 | +mapdl.antype(0) |
181 | 169 |
|
182 | | -Re = getReynoldsNumber(rho_water, u, D, mu_water) |
183 | | -Pr = Pr_water # directly used |
184 | | -L_over_D = L / D |
| 170 | +# %% |
| 171 | +# Set up the fluid analysis |
| 172 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~ |
185 | 173 |
|
186 | | -Nu = getNusseltNumber(Re, Pr, L_over_D) |
187 | | -h = getConvectionCoefficient(Nu, k_water, D) |
188 | | -Bi = getBiotNumber(h, k_al, t_wall) |
| 174 | +# %% |
| 175 | +# Read the pre-created mesh file |
189 | 176 |
|
| 177 | +fluent=pyfluent.launch_fluent(start_transcript=False) |
| 178 | +fluent.file.read(file_type="mesh", file_name=fluent_msh_file) |
190 | 179 |
|
191 | | -print(f"{'Parameter':<25} {'Value':<15} {'Unit'}") |
192 | | -print("-" * 50) |
193 | | -print(f"{'Reynolds Number (Re)':<25} {Re:<15.2f}") |
194 | | -print(f"{'Prandtl Number (Pr)':<25} {Pr:<15.1f}") |
195 | | -print(f"{'Nusselt Number (Nu)':<25} {Nu:<15.2f}") |
196 | | -print(f"{'Convection coeff (h)':<25} {h:<15.1f} W/m²·K") |
197 | | -print(f"{'Biot Number (Bi)':<25} {Bi:<15.6f}") |
198 | | -print("-" * 50) |
199 | | -print(f"The Biot number is {Bi:.6f}") |
| 180 | +#%% |
| 181 | +#Define the fluid solver settings |
| 182 | +fluent.setup.models.energy.enabled =True |
200 | 183 |
|
| 184 | +#%% |
| 185 | +#Add the material |
| 186 | +fluent.setup.materials.database.copy_by_name(type="fluid", name="water-liquid") |
201 | 187 |
|
202 | | -if Bi < 0.1: |
203 | | - print("→ Bi < 0.1 → Lumped capacitance valid (uniform wall temperature)") |
204 | | -elif Bi > 10: |
205 | | - print("→ Bi > 10 → Significant temperature gradient in wall") |
206 | | -else: |
207 | | - print("→ 0.1 < Bi < 10 → Moderate internal resistance") |
208 | | -# === |
| 188 | +fluent.setup.cell_zone_conditions.fluid["fff_fluiddomain"].material = "water-liquid" |
209 | 189 |
|
210 | | -# launch System Coupling session |
211 | | -syc = pysyc.launch() |
212 | | -syc.start_output() |
| 190 | +#%% |
| 191 | +#Define boundary conditions |
| 192 | +fluent.setup.boundary_conditions.velocity_inlet["inlet"].momentum.velocity = 0.1 |
| 193 | +fluent.setup.boundary_conditions.velocity_inlet["inlet"].thermal.temperature = 300 |
| 194 | +fluent.setup.boundary_conditions.wall["inner_wall"].thermal.thermal_bc = "via System Coupling" |
213 | 195 |
|
214 | | -# add two Fluent sessions above as participants |
215 | | -fluid_name = syc.setup.add_participant(participant_session=pipe_fluid_session) |
216 | | -solid_name = syc.setup.add_participant(participant_session=pipe_solid_session) |
217 | | -syc.setup.coupling_participant[fluid_name].display_name = "Fluid" |
218 | | -syc.setup.coupling_participant[solid_name].display_name = "Solid" |
| 196 | +fluent.solution.run_calculation.iter_count = 20 |
219 | 197 |
|
220 | | -# add a coupling interface |
221 | | -interface = syc.setup.add_interface( |
222 | | - side_one_participant=fluid_name, |
223 | | - side_one_regions=["wall"], |
224 | | - side_two_participant=solid_name, |
225 | | - side_two_regions=["inner_wall"], |
| 198 | +# %% |
| 199 | +# Set up the coupled analysis |
| 200 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 201 | +# System Coupling setup involves adding the structural and fluid |
| 202 | +# participants, adding coupled interfaces and data transfers, |
| 203 | +# and setting other coupled analysis properties. |
| 204 | +syc=pysyc.launch(start_output= True) |
| 205 | + |
| 206 | +#%% |
| 207 | +# Add participants by passing session handles to System Coupling. |
| 208 | +fluid_name=syc.setup.add_participant(participant_session= fluent) |
| 209 | +solid_name=syc.setup.add_participant(participant_session= mapdl) |
| 210 | + |
| 211 | +syc.setup.coupling_participant[fluid_name].display_name= "Fluid" |
| 212 | +syc.setup.coupling_participant[solid_name].display_name= "Solid" |
| 213 | + |
| 214 | +#%% |
| 215 | +#Add coupling face and data transfers |
| 216 | +interface_name=syc.setup.add_interface( |
| 217 | + side_one_participant= fluid_name, side_one_regions= ["inner_wall"], |
| 218 | + side_two_participant= solid_name, side_two_regions= ["FSIN_1"] |
226 | 219 | ) |
227 | 220 |
|
228 | | -# set up 2-way coupling - add temperature and heat flow data transfers |
229 | | -syc.setup.add_thermal_data_transfers(interface=interface) |
| 221 | +#%% |
| 222 | +#Set up 2-way thermal FSI coupling |
| 223 | +syc.setup.add_thermal_data_transfers(interface = interface_name) |
230 | 224 |
|
231 | | -# set up coupled analysis settings |
232 | | -# it should take about 80 iterations to converge |
233 | | -syc.setup.solution_control.maximum_iterations = 100 |
| 225 | +# %% |
| 226 | +# Time step size, end time, output controls |
| 227 | +syc.setup.solution_control.time_step_size = "0.1 [s]" # time step is 0.1 [s] |
| 228 | +syc.setup.solution_control.end_time = 10 # end time is 10.0 [s] |
234 | 229 |
|
235 | | -# === |
| 230 | +syc.setup.solution_control.maximum_iterations=100 |
236 | 231 |
|
237 | | -# solve the coupled analysis |
| 232 | +# %% |
| 233 | +# Solution |
| 234 | +# -------- |
238 | 235 | syc.solution.solve() |
239 | 236 |
|
240 | | -# === |
241 | | - |
242 | | -# clean up at the end |
| 237 | +# %% |
| 238 | +# Exit |
| 239 | +# ---- |
243 | 240 | syc.end_output() |
244 | | -pipe_fluid_session.exit() |
245 | | -pipe_solid_session.exit() |
246 | 241 | syc.exit() |
| 242 | + |
0 commit comments