7
7
import precice
8
8
9
9
10
- def main (side = 'Dirichlet' , n = 10 , degree = 1 , timestep = .1 , alpha = 3. , beta = 1.2 ):
11
-
12
- if side == 'Dirichlet' :
13
- x_grid = np .linspace (0 , 1 , n )
14
- elif side == 'Neumann' :
15
- x_grid = np .linspace (1 , 2 , n )
16
- else :
17
- raise Exception ('invalid side {!r}' .format (side ))
10
+ def main (n = 10 , degree = 1 , timestep = .1 , alpha = 3. , beta = 1.2 ):
11
+
12
+ x_grid = np .linspace (0 , 1 , n )
18
13
y_grid = np .linspace (0 , 1 , n )
19
14
20
15
# define the Nutils mesh
21
16
domain , geom = mesh .rectilinear ([x_grid , y_grid ])
22
- coupling_boundary = domain .boundary ['right' if side ==
23
- 'Dirichlet' else 'left' ]
17
+ coupling_boundary = domain .boundary ['right' ]
24
18
coupling_sample = coupling_boundary .sample ('gauss' , degree = degree * 2 )
25
19
26
20
# Nutils namespace
@@ -44,56 +38,51 @@ def main(side='Dirichlet', n=10, degree=1, timestep=.1, alpha=3., beta=1.2):
44
38
45
39
# set boundary conditions at non-coupling boundaries
46
40
# top and bottom boundary are non-coupling for both sides
47
- sqr = domain .boundary ['top,bottom,left' if side == 'Dirichlet' else 'top,bottom,right' ].integral (
48
- '(u - uexact)^2 d:x' @ ns , degree = degree * 2 )
41
+ sqr = domain .boundary ['top,bottom,left' ].integral ('(u - uexact)^2 d:x' @ ns , degree = degree * 2 )
49
42
50
- if side == 'Dirichlet' :
51
- sqr += coupling_sample .integral ('(u - readfunc)^2 d:x' @ ns )
52
- else :
53
- res += coupling_sample .integral ('basis_n readfunc d:x' @ ns )
43
+ sqr += coupling_sample .integral ('(u - readfunc)^2 d:x' @ ns )
54
44
55
45
# preCICE setup
56
- participant = precice .Participant (side , "../precice-config.xml" , 0 , 1 )
57
- mesh_name = side + " -Mesh"
46
+ participant = precice .Participant ('Dirichlet' , "../precice-config.xml" , 0 , 1 )
47
+ mesh_name = "Dirichlet -Mesh"
58
48
vertex_ids = participant .set_mesh_vertices (
59
49
mesh_name , coupling_sample .eval (ns .x ))
60
50
precice_write = functools .partial (
61
51
participant .write_data ,
62
52
mesh_name ,
63
- "Temperature" if side == "Neumann" else " Heat-Flux" ,
53
+ "Heat-Flux" ,
64
54
vertex_ids )
65
55
precice_read = functools .partial (
66
56
participant .read_data ,
67
57
mesh_name ,
68
- "Heat-Flux" if side == "Neumann" else " Temperature" ,
58
+ "Temperature" ,
69
59
vertex_ids )
70
60
71
61
# helper functions to project heat flux to coupling boundary
72
- if side == 'Dirichlet' :
73
- # To communicate the flux to the Neumann side we should not simply
74
- # evaluate u_,i n_i as this is an unbounded term leading to suboptimal
75
- # convergence. Instead we project ∀ v: ∫_Γ v flux = ∫_Γ v u_,i n_i and
76
- # evaluate flux. While the right-hand-side contains the same unbounded
77
- # term, we can use the strong identity du/dt - u_,ii = f to rewrite it
78
- # to ∫_Ω [v (du/dt - f) + v_,i u_,i] - ∫_∂Ω\Γ v u_,k n_k, in which we
79
- # recognize the residual and an integral over the exterior boundary.
80
- # While the latter still contains the problematic unbounded term, we
81
- # can use the fact that the flux is a known value at the top and bottom
82
- # via the Dirichlet boundary condition, and impose it as constraints.
83
- rightsqr = domain .boundary ['right' ].integral (
84
- 'flux^2 d:x' @ ns , degree = degree * 2 )
85
- rightcons = solver .optimize ('fluxdofs' , rightsqr , droptol = 1e-10 )
86
- # rightcons is NaN in dofs that are NOT supported on the right boundary
87
- fluxsqr = domain .boundary ['right' ].boundary ['top,bottom' ].integral (
88
- '(flux - uexact_,0)^2 d:x' @ ns , degree = degree * 2 )
89
- fluxcons = solver .optimize ('fluxdofs' ,
90
- fluxsqr ,
91
- droptol = 1e-10 ,
92
- constrain = np .choose (np .isnan (rightcons ),
93
- [np .nan ,
94
- 0. ]))
95
- # fluxcons is NaN in dofs that are supported on ONLY the right boundary
96
- fluxres = coupling_sample .integral ('basis_n flux d:x' @ ns ) - res
62
+ # To communicate the flux to the Neumann side we should not simply
63
+ # evaluate u_,i n_i as this is an unbounded term leading to suboptimal
64
+ # convergence. Instead we project ∀ v: ∫_Γ v flux = ∫_Γ v u_,i n_i and
65
+ # evaluate flux. While the right-hand-side contains the same unbounded
66
+ # term, we can use the strong identity du/dt - u_,ii = f to rewrite it
67
+ # to ∫_Ω [v (du/dt - f) + v_,i u_,i] - ∫_∂Ω\Γ v u_,k n_k, in which we
68
+ # recognize the residual and an integral over the exterior boundary.
69
+ # While the latter still contains the problematic unbounded term, we
70
+ # can use the fact that the flux is a known value at the top and bottom
71
+ # via the Dirichlet boundary condition, and impose it as constraints.
72
+ rightsqr = domain .boundary ['right' ].integral (
73
+ 'flux^2 d:x' @ ns , degree = degree * 2 )
74
+ rightcons = solver .optimize ('fluxdofs' , rightsqr , droptol = 1e-10 )
75
+ # rightcons is NaN in dofs that are NOT supported on the right boundary
76
+ fluxsqr = domain .boundary ['right' ].boundary ['top,bottom' ].integral (
77
+ '(flux - uexact_,0)^2 d:x' @ ns , degree = degree * 2 )
78
+ fluxcons = solver .optimize ('fluxdofs' ,
79
+ fluxsqr ,
80
+ droptol = 1e-10 ,
81
+ constrain = np .choose (np .isnan (rightcons ),
82
+ [np .nan ,
83
+ 0. ]))
84
+ # fluxcons is NaN in dofs that are supported on ONLY the right boundary
85
+ fluxres = coupling_sample .integral ('basis_n flux d:x' @ ns ) - res
97
86
98
87
# write initial data
99
88
if participant .requires_initial_data ():
@@ -118,8 +107,7 @@ def main(side='Dirichlet', n=10, degree=1, timestep=.1, alpha=3., beta=1.2):
118
107
x , u , uexact = bezier .eval (['x_i' , 'u' , 'uexact' ] @ ns , lhs = lhs , t = t )
119
108
with treelog .add (treelog .DataLog ()):
120
109
export .vtk (
121
- side +
122
- "-" +
110
+ "Dirichlet-" +
123
111
str (istep ),
124
112
bezier .tri ,
125
113
x ,
@@ -157,14 +145,12 @@ def main(side='Dirichlet', n=10, degree=1, timestep=.1, alpha=3., beta=1.2):
157
145
lhs0 = lhs0 , dt = dt , t = t , readdata = readdata ))
158
146
159
147
# write data to participant
160
- if side == 'Dirichlet' :
161
- fluxdofs = solver .solve_linear (
162
- 'fluxdofs' , fluxres , arguments = dict (
163
- lhs0 = lhs0 , lhs = lhs , dt = dt , t = t ), constrain = fluxcons )
164
- write_data = coupling_sample .eval (
165
- 'flux' @ ns , fluxdofs = fluxdofs )
166
- else :
167
- write_data = coupling_sample .eval ('u' @ ns , lhs = lhs )
148
+ fluxdofs = solver .solve_linear (
149
+ 'fluxdofs' , fluxres , arguments = dict (
150
+ lhs0 = lhs0 , lhs = lhs , dt = dt , t = t ), constrain = fluxcons )
151
+ write_data = coupling_sample .eval (
152
+ 'flux' @ ns , fluxdofs = fluxdofs )
153
+
168
154
precice_write (write_data )
169
155
170
156
# do the coupling
0 commit comments