Hello everyone,
I have been working on implementing k-\epsilon (k-epsilon) turbulence model in FEniCS (I have already created one post about it here, here is the link if anyone is interested: Implementing k-epsilon model in FEniCS - how to implement terms in variational formulation that depend on a solution? - variational formulation - FEniCS Project).
The question I have is not related to my previous post or to turbulence modeling in general, however I encountered the error during my work on the model. That is also the reason why my minimal working example is not so minimal, since I haven’t been able to recreate the error outside of the environment I am working in.
Now, to my problem: I have two UFL functions f_1(k, \epsilon) and f_2(k, \epsilon). Here k and \epsilon are FEniCS Functions (computed solutions of some problem). They are both finite and I can easily work with them, for example plot them using matplotlib. However when I try to work with function f_3(k, \epsilon) which is a product of f_1 and f_2, i.e.
then this doesn’t work. For example if I want to plot f_3 I get the following error:
'''
snippet from my code that demonstrates the problem
'''
c = plot(fun1, title = 'fun 1') # No problem plotting fun1
plt.colorbar(c)
plt.show()
c = plot(fun2, title = 'fun 2') # No problem plotting fun2
plt.colorbar(c)
plt.show()
c = plot(fun1 * fun2, title = 'fun 1 * fun 2') # Cannot plot fun1 * fun2. WHY??
plt.colorbar(c)
plt.show()
Traceback (most recent call last):
File "/mnt/c/Users/juraj/Desktop/Master Thesis/code/finished-models/min_ex.py", line 142, in <module>
c = plot(fun1 * fun2, title = 'fun 1 * fun 2') # Cannot plot fun1 * fun2. WHY??
File "/usr/lib/petsc/lib/python3/dist-packages/dolfin/common/plotting.py", line 436, in plot
return _plot_matplotlib(object, mesh, kwargs)
File "/usr/lib/petsc/lib/python3/dist-packages/dolfin/common/plotting.py", line 302, in _plot_matplotlib
return mplot_function(ax, obj, **kwargs)
File "/usr/lib/petsc/lib/python3/dist-packages/dolfin/common/plotting.py", line 152, in mplot_function
return ax.tricontourf(mesh2triang(mesh), C, levels, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/tri/tricontour.py", line 307, in tricontourf
return TriContourSet(ax, *args, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/tri/tricontour.py", line 29, in __init__
super().__init__(ax, *args, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/contour.py", line 812, in __init__
kwargs = self._process_args(*args, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/tri/tricontour.py", line 45, in _process_args
tri, z = self._contour_args(args, kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/tri/tricontour.py", line 72, in _contour_args
raise ValueError('z array must not contain non-finite values '
ValueError: z array must not contain non-finite values within the triangulation
I can understand what the error says, i.e. that some value in f_3 is non-finite (at least that is how I understand it) but I just don’t get why this is since both f_1 and f_2 are finite (which I deduced by the fact that matplotlib had no issue plotting them).
I would very much appreciate if anyone would be able to look at this and try to help me find where the problem is. I am sorry for the lengthy minimal working example but I could not get the error when I tried with more simple code, the part where error occurs is at the very end of the code. This is the best I could do:
from fenics import *
import matplotlib.pyplot as plt
mesh = UnitSquareMesh(4, 4)
# Create boundaries subdomains
walls = 'x[1] < DOLFIN_EPS or x[1] > 1 - DOLFIN_EPS'
inflow = 'x[0] < DOLFIN_EPS'
outflow = 'x[0] > 1 - DOLFIN_EPS'
# Choose values for initial and boundary conditions
u_init = 1
k_init = 0.1
e_init = 0.1
# Create function spaces for all variables
V = VectorFunctionSpace(mesh, "CG", 2)
Q = FunctionSpace(mesh, "CG", 1)
K = FunctionSpace(mesh, "CG", 1)
# Create boundary conditions for u,k,e
bcu = [DirichletBC(V, Constant((0.0, 0.0)), walls)]
bck = [DirichletBC(K, Constant(0.0), walls)]
bce = []
# Create boundary conditions for pressure p
bcp_inflow = DirichletBC(Q, Constant(2.0), inflow)
bcp_outflow = DirichletBC(Q, Constant(0.0), outflow)
bcp = [bcp_inflow, bcp_outflow]
# Define trial functions
u = TrialFunction(V)
p = TrialFunction(Q)
k = TrialFunction(K)
e = TrialFunction(K)
# Define test functions
v = TestFunction(V)
q = TestFunction(Q)
phi = TestFunction(K)
psi = TestFunction(K)
# Define functions for quantities at previous time
u0 = interpolate(Constant((u_init, 0)), V)
k0 = interpolate(Constant(k_init), K)
e0 = interpolate(Constant(e_init), K)
# Define functions where solutions will be stored
u1 = Function(V)
p1 = Function(Q)
k1 = Function(K)
e1 = Function(K)
# Define constantss used in variational forms
dt = Constant(0.001)
nu = Constant(0.00181818)
# Calculate distance to the wall
dfun = Expression('0.5 - abs(0.5 - x[1])', degree = 1)
# Define Min, Max function
def Max(a, b):
return (a+b+abs(a-b))/Constant(2)
# Define helping functions for k-eps model
Re_t = (1. / nu) * (k0**2 / e0)
Re_k = (1. / nu) * (sqrt(abs(k0)) * dfun)
f_nu = (1 - exp(- 0.0165 * Re_k))**2 * (1 + 20.5 / Re_t)
f_1 = 1 + (0.05 / f_nu)**3
f_2 = 1 - exp(- Re_t**2)
S_sq = 2 * inner(sym(nabla_grad(u1)), sym(nabla_grad(u1)))
# Define terms that appear in variational formulation for k-eps model
nut = Max(0.09 * f_nu * (k0**2 / e0), Constant(0.0))
prod_k = Max(nut * S_sq, Constant(0.0))
react_k = Max(e0 / k0, Constant(0.0))
prod_e = Max(1.44 * react_k * f_1 * prod_k, Constant(0.0))
react_e = Max(1.92 * react_k * f_2, Constant(0.0))
# Create variational formulation for N-S (Chorin's splitting method)
F1 = (1. / dt) * dot(u - u0, v)*dx \
+ dot(dot(u0, nabla_grad(u)), v)*dx \
+ (nu + nut) * inner(grad(u), grad(v))*dx
a_1 = lhs(F1); l_1 = rhs(F1)
a_2 = dot(grad(p), grad(q))*dx
l_2 = (-1. / dt) * dot(div(u1), q)*dx
a_3 = dot(u, v)*dx
l_3 = dot(u1, v)*dx - dt * dot(grad(p1), v)*dx
# Create variational formulation for k-eps
FK = (1. / dt) * dot(k - k0, phi)*dx \
+ dot(dot(u1, nabla_grad(k)), phi)*dx \
+ (nu + nut / 1.0) * inner(grad(k), grad(phi))*dx \
- dot(prod_k, phi)*dx + dot(react_k * k, phi)*dx
FE = (1. / dt) * dot(e - e0, psi)*dx \
+ dot(dot(u1, nabla_grad(e)), psi)*dx \
+ (nu + nut / 1.3) * inner(grad(e), grad(psi))*dx \
- dot(prod_e, psi)*dx + dot(react_e * e, psi)*dx
a_k = lhs(FK); l_k = rhs(FK)
a_e = lhs(FE); l_e = rhs(FE)
# main loop
iter_max = 3
tol = 1e-7
for iter in range(iter_max):
solve(a_1 == l_1, u1, bcu)
solve(a_2 == l_2, p1, bcp)
solve(a_3 == l_3, u1, bcu)
solve(a_k == l_k, k1, bck)
solve(a_e == l_e, e1, bce)
# Update all functions
u0.assign(u1)
k0.assign(k1)
e0.assign(e1)
###################### PROBLEM HAPPENS HERE ######################
fun1 = (1. / f_nu)**2
fun2 = (1. / f_nu)
c = plot(fun1, title = 'fun 1') # No problem plotting fun1
plt.colorbar(c)
plt.show()
c = plot(fun2, title = 'fun 2') # No problem plotting fun2
plt.colorbar(c)
plt.show()
c = plot(fun1 * fun2, title = 'fun 1 * fun 2') # Cannot plot fun1 * fun2. WHY??
plt.colorbar(c)
plt.show()
##################################################################
Thank you for reading and once again, I will appreciate any help I can get with this .