33"""
44
55from __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 , \
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 , \
89 near
910from fenicsadapter import Adapter
1011import numpy as np
@@ -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
@@ -99,14 +94,15 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
9994
10095mesh = RectangleMesh (p0 , p1 , nx , ny )
10196V = FunctionSpace (mesh , 'P' , 1 )
97+ V_g = VectorFunctionSpace (mesh , 'P' , 1 )
10298
10399alpha = 1 # m^2/s, https://en.wikipedia.org/wiki/Thermal_diffusivity
104100k = 100 # kg * m / s^3 / K, https://en.wikipedia.org/wiki/Thermal_conductivity
105101
106102# Define boundary condition
107103u_D = Constant ('310' )
108104u_D_function = interpolate (u_D , V )
109- # Define flux in x direction on coupling interface (grad(u_D) in normal direction)
105+ # Define flux in y direction on coupling interface (grad(u_D) in normal direction)
110106f_N = Constant ('0' )
111107f_N_function = interpolate (f_N , V )
112108
@@ -120,7 +116,7 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
120116# Adapter definition and initialization
121117precice = Adapter (adapter_config_filename = "precice-adapter-config.json" )
122118
123- precice_dt = precice .initialize (coupling_boundary , mesh , V )
119+ precice_dt = precice .initialize (coupling_boundary , mesh , V , write_function = f_N_function )
124120
125121# Create a FEniCS Expression to define and control the coupling boundary values
126122coupling_expression = precice .create_coupling_expression ()
@@ -142,7 +138,6 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
142138
143139# Time-stepping
144140u_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
146141t = 0
147142u_D .t = t + dt
148143
@@ -151,6 +146,9 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
151146print ("output vtk for time = {}" .format (float (t )))
152147n = 0
153148
149+ fluxes = Function (V_g )
150+ fluxes .rename ("Fluxes" , "" )
151+
154152while precice .is_coupling_ongoing ():
155153
156154 if precice .is_action_required (precice .action_write_iteration_checkpoint ()): # write checkpoint
@@ -167,8 +165,9 @@ def fluxes_from_temperature_full_domain(f, v_vec, k):
167165 solve (a == L , u_np1 , bcs )
168166
169167 # Dirichlet problem obtains flux from solution and sends flux on boundary to Neumann problem
170- fluxes = fluxes_from_temperature_full_domain (F_known_u , V , k )
171- precice .write_data (fluxes )
168+ determine_heat_flux (V_g , u_np1 , k , fluxes )
169+ fluxes_y = fluxes .sub (1 ) # only exchange y component of flux.
170+ precice .write_data (fluxes_y )
172171
173172 precice_dt = precice .advance (dt (0 ))
174173
0 commit comments