This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Solving mixed strain-displacement formulation with linear-quadratic interpolation

0 votes

I have problems with stress oscillations and found a stabilized mixed formulation (displacement and strain). It uses linear-linear interpolation and thus doesn't fulfil the inf-sup-condition. But the stabilization accounts for this and this code seems to run.

Then i wanted to run the code with linear(strain)-quadratic(displacement) interpolations. I get errors, depending on the used solver. For example:

*** Error: Unable to successfully call PETSc function 'KSPSolve'.
*** Reason: PETSc error code is: 76 (Error in external library).
*** Where: This error was encountered inside /build/dolfin-4SStI2/dolfin-2016.2.0/dolfin/la/PETScLUSolver.cpp.
*** Process: 0
*** DOLFIN version: 2016.2.0
*** Git changeset: unknown
*** -------------------------------------------------------------------------

I don't understand it, since the only thing i change is increasing the degree of interpolation function. (I want to avoid the stabilization by fulfilling the inf-sup-condition.)

Source of the mixed formulation: http://www.sciencedirect.com/science/article/pii/S0266352X14001876

Thanks a lot.

I made a simplified version as running example:

from fenics import *
import os
import numpy as np

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
#----------------------------------------------------------------------------#
mesh = UnitSquareMesh(32, 32)

domains = CellFunction('size_t', mesh)
domains.set_all(0)

facets = FacetFunction('size_t', mesh)
facets.set_all(0)

dA = Measure("ds", domain=mesh, subdomain_data=facets)
dV = Measure("dx", domain=mesh, subdomain_data=domains)

Normale = FacetNormal(mesh)
#----------------------------------------------------------------------------#
nu = 0.45
G = 33 * 10**(-3) # [N/um^2]
lamda = 2.0*G*nu / (1.0-2.0*nu)
mu = G
lamda = ((2*mu)/(lamda + 2*mu))*lamda
#----------------------------------------------------------------------------#

ScalarSpaceCG1 = FunctionSpace(mesh,'CG',1)
TensorSpaceCG1 = TensorFunctionSpace(mesh,'CG',1)


###### Crucial Part #######
#--------------------------
TCG = TensorElement("Lagrange", mesh.ufl_cell(), 1)
#### Running version
VCG = VectorElement("Lagrange", mesh.ufl_cell(), 1)
### NOT running version
# VCG = VectorElement("Lagrange", mesh.ufl_cell(), 2)
######################

W = TCG * VCG
W = FunctionSpace(mesh, W)

(epsilon_h, u_h) = TrialFunctions(W)
(gamma_h, v_h) = TestFunctions(W)

#----------------------------------------------------------------------------#

delta = Identity(2)  

def sym_grad(u):
           return as_tensor(  0.5*(u[i].dx(j) + u[j].dx(i))  , (i,j))

def epsilon_elastisch(epsilon_gesamt):
       return as_tensor(epsilon_gesamt[i,j], (i,j))

def sigma(epsilon_elastisch):
           return as_tensor(lamda*epsilon_elastisch[k,k]*delta[i,j] + 2.0*mu*epsilon_elastisch[i,j] , (i,j))

def C_mal_T2Stufe(Tensor_2_Stufe):
           return as_tensor(lamda*Tensor_2_Stufe[k,k]*delta[i,j] + 2.0*mu*Tensor_2_Stufe[i,j] , (i,j))


#----------------------------------------------------------------------------#
# Boundary conditions

def boundary_xleft(x):
    return -DOLFIN_EPS < x[0] < DOLFIN_EPS
bc1 = DirichletBC(W.sub(1).sub(0), Constant((0.0)), boundary_xleft)

def boundary_xright(x):
    return -DOLFIN_EPS +1 < x[0] < DOLFIN_EPS +1
bc2 = DirichletBC(W.sub(1).sub(0), Constant((0.1)), boundary_xright)

def boundary_xleft_corner(x):
    return ( (-DOLFIN_EPS < x[0] < DOLFIN_EPS) and (-DOLFIN_EPS < x[1] < DOLFIN_EPS))
bc3 = DirichletBC(W.sub(1), Constant((0.0,0.0)), boundary_xleft_corner,method="pointwise")


Sigma_Global_Feld = as_matrix([[0.0, 0.0], [0.0, 0.0]])  # [N/um^2]
#----------------------------------------------------------------------------#

Eq1 = -gamma_h[i,j]*C_mal_T2Stufe(epsilon_h-sym_grad(u_h))[i,j]*dV 

Eq2 = sym_grad(v_h)[i,j]*C_mal_T2Stufe( epsilon_h )[i,j]*dV    - Sigma_Global_Feld[i,j]*Normale[j]*v_h[i]*dA

Eq = Eq1 + Eq2

a = lhs(Eq)
L = rhs(Eq)

w = Function(W)

solve (a==L, w, bcs=[bc1,bc2,bc3], solver_parameters={"linear_solver": "mumps"}, form_compiler_parameters={"optimize": True,"cpp_optimize":True})


# Post process
#-------------
(epsilon_h, u_h) = w.split()
#----------------------------------------------------------------------------#
epsilon_gesamt = epsilon_h
epsilon_elastisch = epsilon_elastisch(epsilon_gesamt)
sigma = as_tensor(lamda*epsilon_elastisch[k,k]*delta[i,j] + 2.0*mu*epsilon_elastisch[i,j] , (i,j))
#----------------------------------------------------------------------------#
epsilon_elastisch =  project( epsilon_elastisch, TensorSpaceCG1, solver_type="cg",form_compiler_parameters={"cpp_optimize":True} )

sigma =  project( sigma, TensorSpaceCG1, solver_type="cg",form_compiler_parameters={"cpp_optimize":True} )
#----------------------------------------------------------------------------#
file_verschiebung = File('verschiebung.pvd')
file_verschiebung << u_h

file_stress = File('stress.pvd')
file_stress << sigma
asked May 22, 2017 by titusf FEniCS Novice (570 points)

Hi, did you look at any of the related threads?

I did now. But it doesnt make any sense to me. Error 76 seems to be memory related. Solving a 3x3 mesh should not cause this, i guess. Also, using a different solver brings a different error message, like:

*** Warning: Krylov solver did not converge in 0 iterations (PETSc reason DIVERGED_NANORINF, residual norm ||r|| = -nan).

Could it be related to the boundary conditions? Am i doing something wrong there?

The system you assembled is far from invertible; on 16x16 square you have >1000 singular modes.

...