Skip to content

Commit 5f4031f

Browse files
Merge pull request precice#124 from precice/fenics-adapter-v1.0.0
Ensure compatibility of tutorials with fenics-adapter v1.0.0
2 parents 95cc1ed + 6e285bd commit 5f4031f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2495
-97
lines changed

CHT/flow-over-plate/buoyantPimpleFoam-fenics/Solid/heat.py

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
"""
44

55
from __future__ import print_function, division
6-
from fenics import Function, SubDomain, RectangleMesh, BoxMesh, FunctionSpace, Point, Expression, Constant, DirichletBC, \
7-
TrialFunction, TestFunction, File, solve, plot, lhs, rhs, grad, inner, dot, dx, ds, assemble, interpolate, project, \
8-
near
9-
from fenicsadapter import Adapter
6+
from fenics import Function, SubDomain, RectangleMesh, BoxMesh, FunctionSpace, VectorFunctionSpace, Point, \
7+
Expression, Constant, DirichletBC, \
8+
TrialFunction, TestFunction, File, solve, plot, lhs, rhs, grad, inner, dot, dx, ds, interpolate, project, \
9+
near, MeshFunction, MPI
10+
from fenicsprecice import Adapter
1011
import numpy as np
1112

1213

@@ -59,27 +60,21 @@ def inside(self, x, on_boundary):
5960
return False
6061

6162

62-
def fluxes_from_temperature_full_domain(f, v_vec, k):
63-
"""Computes flux from weak form (see p.3 in Toselli, Andrea, and Olof
64-
Widlund. Domain decomposition methods-algorithms and theory. Vol. 34.
65-
Springer Science & Business Media, 2006.).
66-
67-
:param f: weak form with known u^{n+1}
68-
:param v_vec: vector function space
63+
def determine_heat_flux(V_g, u, k, flux):
64+
"""
65+
compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu
66+
:param V_g: Vector function space
67+
:param u: solution where gradient is to be determined
6968
:param k: thermal conductivity
70-
:return: fluxes function
69+
:param flux: returns calculated flux into this value
7170
"""
72-
fluxes_vector = assemble(f) # assemble weak form -> evaluate integral
73-
v = TestFunction(v_vec)
74-
fluxes = Function(v_vec) # create function for flux
75-
area = assemble(v * ds).get_local()
76-
for i in range(area.shape[0]):
77-
if area[i] != 0: # put weight from assemble on function
78-
fluxes.vector()[i] = - k * fluxes_vector[i] / area[i] # scale by surface area
79-
else:
80-
assert (abs(fluxes_vector[i]) < 1E-9) # for non surface parts, we expect zero flux
81-
fluxes.vector()[i] = - k * fluxes_vector[i]
82-
return fluxes
71+
72+
w = TrialFunction(V_g)
73+
v = TestFunction(V_g)
74+
75+
a = inner(w, v) * dx
76+
L = inner(-k * grad(u), v) * dx
77+
solve(a == L, flux)
8378

8479

8580
# Create mesh and define function space
@@ -88,7 +83,7 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
8883
nz = 1
8984

9085
fenics_dt = 0.01 # time step size
91-
dt_out = 0.2
86+
dt_out = 0.2 # interval for writing VTK files
9287
y_top = 0
9388
y_bottom = y_top - .25
9489
x_left = 0
@@ -99,16 +94,16 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
9994

10095
mesh = RectangleMesh(p0, p1, nx, ny)
10196
V = FunctionSpace(mesh, 'P', 1)
97+
V_g = VectorFunctionSpace(mesh, 'P', 1)
10298

10399
alpha = 1 # m^2/s, https://en.wikipedia.org/wiki/Thermal_diffusivity
104100
k = 100 # kg * m / s^3 / K, https://en.wikipedia.org/wiki/Thermal_conductivity
105101

106102
# Define boundary condition
107103
u_D = Constant('310')
108104
u_D_function = interpolate(u_D, V)
109-
# Define flux in x direction on coupling interface (grad(u_D) in normal direction)
110-
f_N = Constant('0')
111-
f_N_function = interpolate(f_N, V)
105+
# We will only exchange flux in y direction on coupling interface. No initialization necessary.
106+
V_flux_y = V_g.sub(1)
112107

113108
coupling_boundary = TopBoundary()
114109
bottom_boundary = BottomBoundary()
@@ -120,7 +115,7 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
120115
# Adapter definition and initialization
121116
precice = Adapter(adapter_config_filename="precice-adapter-config.json")
122117

123-
precice_dt = precice.initialize(coupling_boundary, mesh, V)
118+
precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V_flux_y)
124119

125120
# Create a FEniCS Expression to define and control the coupling boundary values
126121
coupling_expression = precice.create_coupling_expression()
@@ -142,13 +137,26 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
142137

143138
# Time-stepping
144139
u_np1 = Function(V)
145-
F_known_u = u_np1 * v / dt * dx + alpha * dot(grad(u_np1), grad(v)) * dx - u_n * v / dt * dx
146140
t = 0
147141
u_D.t = t + dt
148142

143+
# mark mesh w.r.t ranks
144+
ranks = File("Solid/VTK/ranks%s.pvd.pvd" % precice.get_participant_name())
145+
mesh_rank = MeshFunction("size_t", mesh, mesh.topology().dim())
146+
mesh_rank.set_all(MPI.rank(MPI.comm_world))
147+
mesh_rank.rename("myRank", "")
148+
ranks << mesh_rank
149+
150+
# Create output file
149151
file_out = File("Solid/VTK/%s.pvd" % precice.get_participant_name())
152+
file_out << u_n
153+
154+
print("output vtk for time = {}".format(float(t)))
150155
n = 0
151156

157+
fluxes = Function(V_g)
158+
fluxes.rename("Fluxes", "")
159+
152160
while precice.is_coupling_ongoing():
153161

154162
if precice.is_action_required(precice.action_write_iteration_checkpoint()): # write checkpoint
@@ -165,8 +173,9 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
165173
solve(a == L, u_np1, bcs)
166174

167175
# Dirichlet problem obtains flux from solution and sends flux on boundary to Neumann problem
168-
fluxes = fluxes_from_temperature_full_domain(F_known_u, V, k)
169-
precice.write_data(fluxes)
176+
determine_heat_flux(V_g, u_np1, k, fluxes)
177+
fluxes_y = fluxes.sub(1) # only exchange y component of flux.
178+
precice.write_data(fluxes_y)
170179

171180
precice_dt = precice.advance(dt(0))
172181

@@ -177,17 +186,17 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
177186
n = n_cp
178187
else: # update solution
179188
u_n.assign(u_np1)
180-
t += dt
189+
t += float(dt)
181190
n += 1
182191

183192
if precice.is_time_window_complete():
184-
# if abs(t % dt_out) < 10e-5: # output if t is a multiple of dt_out
193+
tol = 10e-5 # we need some tolerance, since otherwise output might be skipped.
194+
if abs((t + tol) % dt_out) < 2*tol: # output if t is a multiple of dt_out
195+
print("output vtk for time = {}".format(float(t)))
185196
file_out << u_n
186197

187198
# Update dirichlet BC
188-
u_D.t = t + dt(0)
189-
190-
file_out << u_n
199+
u_D.t = t + float(dt)
191200

192201
# Hold plot
193202
precice.finalize()

CHT/flow-over-plate/buoyantPimpleFoam-fenics/precice-config.xml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<sink filter="%Severity% > debug and %Rank% = 0" format="---[precice] %ColorizedSeverity% %Message%" enabled="true"/>
77
</log>
88

9-
<solver-interface dimensions="3">
9+
<solver-interface dimensions="2">
1010

1111
<data:scalar name="Temperature"/>
1212
<data:scalar name="Heat-Flux"/>
@@ -23,32 +23,32 @@
2323

2424
<participant name="Fluid">
2525
<use-mesh name="Fluid-Mesh" provide="yes"/>
26+
<use-mesh name="Solid-Mesh" from="Solid"/>
2627
<read-data name="Heat-Flux" mesh="Fluid-Mesh"/>
2728
<write-data name="Temperature" mesh="Fluid-Mesh"/>
29+
<mapping:nearest-neighbor direction="read" from="Solid-Mesh" to="Fluid-Mesh" constraint="consistent"/>
2830
</participant>
2931

3032
<participant name="Solid">
3133
<use-mesh name="Fluid-Mesh" from="Fluid"/>
3234
<use-mesh name="Solid-Mesh" provide="yes"/>
3335
<read-data name="Temperature" mesh="Solid-Mesh"/>
3436
<write-data name="Heat-Flux" mesh="Solid-Mesh"/>
35-
<mapping:nearest-neighbor direction="read" from="Fluid-Mesh" to="Solid-Mesh" constraint="consistent" timing="initial"/>
36-
<mapping:nearest-neighbor direction="write" from="Solid-Mesh" to="Fluid-Mesh" constraint="consistent" timing="initial"/>
37+
<mapping:nearest-neighbor direction="read" from="Fluid-Mesh" to="Solid-Mesh" constraint="consistent"/>
3738
</participant>
3839

3940
<m2n:sockets from="Fluid" to="Solid"/>
4041

4142
<coupling-scheme:serial-implicit>
4243
<time-window-size value="0.01"/>
4344
<max-time value="1"/>
44-
<max-iterations value="200"/>
4545
<participants first="Fluid" second="Solid"/>
4646
<exchange data="Temperature" mesh="Fluid-Mesh" from="Fluid" to="Solid"/>
47-
<exchange data="Heat-Flux" mesh="Fluid-Mesh" from="Solid" to="Fluid"/>
47+
<exchange data="Heat-Flux" mesh="Solid-Mesh" from="Solid" to="Fluid"/>
48+
<max-iterations value="200"/>
4849
<relative-convergence-measure limit="1.0e-6" data="Temperature" mesh="Fluid-Mesh"/>
49-
<extrapolation-order value="0"/>
5050
<acceleration:IQN-ILS>
51-
<data mesh="Fluid-Mesh" name="Heat-Flux" />
51+
<data mesh="Solid-Mesh" name="Heat-Flux" />
5252
<initial-relaxation value="0.01" />
5353
<max-used-iterations value="80" />
5454
<time-windows-reused value="10" />

FSI/cylinderFlap/OpenFOAM-FEniCS/.gitignore renamed to FSI/cylinderFlap_2D/OpenFOAM-FEniCS/.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
Fluid
1+
!Fluid
2+
Fluid/*
23
!Fluid/0
34
!Fluid/0.orig
45
!Fluid/constant
6+
Fluid/constant/polyMesh
57
!Fluid/system
68
!Fluid/Fluid.foam
79
!Fluid/precice-adapter-config.yml
8-
Solid
10+
!Solid
11+
Solid/*
912
!Solid/cyl-flap.py
1013
!Solid/precice-adapter-config-fsi-s.json
1114
*.log

0 commit comments

Comments
 (0)