PRAgMaTIc  master
adv_convergence.py
Go to the documentation of this file.
1 ### this a testcase for use with DOLFIN/FEniCS and PRAgMaTIc
2 ### by Kristian Ejlebjerg Jensen, January 2014, Imperial College London
3 ### the purpose of the test case is to illustrate the use of the mesh_metric2 function in connection
4 ### with a stabilization term in an advective problem.
5 ### the codes simulates a pressure driven stokes flow with a contraction implemented by means of
6 ### spatially varying damping/permeability field.
7 ### The velocity field is used in advective problem to convect step function from the inlet and since
8 ### the geometry(and stokes equation) is symmetric the profile at the outlet should converge towards
9 ### the inlet profile
10 ### the step width, number of solution<->adaptation iterations are optional input
11 ### paramters. The input parameters delta, relp and use_reform are related to a reformulation of the
12 ### advective equation aiming to enforce upper and lower bounds. One however have to allow some
13 ### deviation (intrinsic to the reformulation), and the problem becomes so non-linear that the solver fails
14 
15 from dolfin import *
16 from adaptivity import metric_pnorm, adapt, mesh_metric2, metric_ellipse
17 from pylab import polyfit, hold, show, triplot, tricontourf, colorbar, axis, box, get_cmap, figure, legend, savefig, xlabel, ylabel, title
18 from pylab import loglog as pyloglog
19 from pylab import plot as pyplot
20 from numpy import array, argsort, min, max
21 import pickle, os
22 from sympy import Symbol, diff
23 from sympy import sqrt as pysqrt
24 from numpy import abs as pyabs
25 from numpy import log as pylog
26 from numpy import exp as pyexp2
27 from numpy import sqrt as pysqrt2
28 
29 #set_log_level(WARNING)
30 set_log_level(INFO+1)
31 
32 def bnderror(u,ue,ds):
33  mesh = u.function_space().mesh()
34  V = FunctionSpace(mesh,'CG',4)
35  u = interpolate(u,V); ue = interpolate(ue,V)
36  u.vector().set_local(u.vector().array()-ue.vector().array())
37  area = assemble(interpolate(Constant(1.),FunctionSpace(mesh,'CG',1))*dx) #assemble(Constant(1)*ds(1))
38  error = pysqrt2(assemble(u**2*ds(1)))
39  return error/area
40 
41 def adv_convergence(width=2e-2, delta=1e-2, relp=1, Nadapt=10, use_adapt=True, problem=3, outname='', use_reform=False, CGorderL = [2, 3], noplot=False, Lx=3.):
42  ### SETUP SOLUTION
43  sy = Symbol('sy'); width_ = Symbol('ww')
44  if problem == 3:
45  stepfunc = 0.5+165./104./width_*sy-20./13./width_**3*sy**3-102./13./width_**5*sy**5+240./13./width_**7*sy**7
46  elif problem == 2:
47  stepfunc = 0.5+15./8./width_*sy-5./width_**3*sy**3+6./width_**5*sy**5
48  elif problem == 1:
49  stepfunc = 0.5+1.5/width_*sy-2/width_**3*sy**3
50  stepfunc = str(stepfunc).replace('sy','x[1]').replace('x[1]**2','(x[1]*x[1])')
51  #REPLACE ** with pow
52  stepfunc = stepfunc.replace('x[1]**3','pow(x[1],3.)')
53  stepfunc = stepfunc.replace('x[1]**5','pow(x[1],5.)')
54  stepfunc = stepfunc.replace('x[1]**7','pow(x[1],7.)')
55  testsol = '(-ww/2 < x[1] && x[1] < ww/2 ? ' + stepfunc +' : 0) + (ww/2<x[1] ? 1 : 0)'
56  testsol = testsol.replace('ww**2','(ww*ww)').replace('ww**3','pow(ww,3.)').replace('ww**5','pow(ww,5.)').replace('ww**7','pow(ww,7.)')
57  testsol = testsol.replace('ww',str(width))
58 
59  dp = Constant(1.)
60  fac = Constant(1+2.*delta)
61  delta = Constant(delta)
62 
63  def left(x, on_boundary):
64  return x[0] + Lx/2. < DOLFIN_EPS
65  def right(x, on_boundary):
66  return x[0] - Lx/2. > -DOLFIN_EPS
67  def top_bottom(x, on_boundary):
68  return x[1] - 0.5 > -DOLFIN_EPS or x[1] + 0.5 < DOLFIN_EPS
69  class Inletbnd(SubDomain):
70  def inside(self, x, on_boundary):
71  return x[0] + Lx/2. < DOLFIN_EPS
72  for CGorder in [2]: #CGorderL:
73  dofs = []
74  L2errors = []
75  for eta in 0.04*pyexp2(-array(range(9))*pylog(2)/2):
76  ### SETUP MESH
77  meshsz = int(round(80*0.005/(eta*(bool(use_adapt)==False)+0.05*(bool(use_adapt)==True))))
78  if not bool(use_adapt) and meshsz > 80:
79  continue
80 
81  mesh = RectangleMesh(-Lx/2.,-0.5,Lx/2.,0.5,meshsz,meshsz,"left/right")
82  # PERFORM TEN ADAPTATION ITERATIONS
83  for iii in range(Nadapt):
84  V = VectorFunctionSpace(mesh, "CG", CGorder); Q = FunctionSpace(mesh, "CG", CGorder-1)
85  W = V*Q
86  (u, p) = TrialFunctions(W)
87  (v, q) = TestFunctions(W)
88  alpha = Expression("-0.25<x[0] && x[0]<0.25 && 0. < x[1] ? 1e4 : 0")
89 
90  boundaries = FacetFunction("size_t",mesh)
91  #outletbnd = Outletbnd()
92  inletbnd = Inletbnd()
93  boundaries.set_all(0)
94  #outletbnd.mark(boundaries, 1)
95  inletbnd.mark(boundaries, 1)
96  ds = Measure("ds")[boundaries]
97  bc0 = DirichletBC(W.sub(0), Constant((0., 0.)), top_bottom)
98  bc1 = DirichletBC(W.sub(1), dp , left)
99  bc2 = DirichletBC(W.sub(1), Constant(0), right)
100  bc3 = DirichletBC(W.sub(0).sub(1), Constant(0.), left)
101  bc4 = DirichletBC(W.sub(0).sub(1), Constant(0.), right)
102  bcs = [bc0,bc1,bc2,bc3,bc4]
103 
104  bndterm = dp*dot(v,Constant((-1.,0.)))*ds(1)
105 
106  a = eta*inner(grad(u), grad(v))*dx - div(v)*p*dx + q*div(u)*dx+alpha*dot(u,v)*dx#+bndterm
107  L = inner(Constant((0.,0.)), v)*dx -bndterm
108  U = Function(W)
109  solve(a == L, U, bcs)
110  u, ps = U.split()
111 
112  #SOLVE CONCENTRATION
113  mm = mesh_metric2(mesh)
114  vdir = u/sqrt(inner(u,u)+DOLFIN_EPS)
115  if iii == 0 or use_reform == False:
116  Q2 = FunctionSpace(mesh,'CG',2); c = Function(Q2)
117  q = TestFunction(Q2); p = TrialFunction(Q2)
118  newq = (q+dot(vdir,dot(mm,vdir))*inner(grad(q),vdir)) #SUPG
119  if use_reform:
120  F = newq*(fac/((1+exp(-c))**2)*exp(-c))*inner(grad(c),u)*dx
121  J = derivative(F,c)
122  bc = DirichletBC(Q2, Expression("-log("+str(float(fac)) +"/("+testsol+"+"+str(float(delta))+")-1)"), left)
123  # bc = DirichletBC(Q, -ln(fac/(Expression(testsol)+delta)-1), left)
124  problem = NonlinearVariationalProblem(F,c,bc,J)
125  solver = NonlinearVariationalSolver(problem)
126  solver.parameters["newton_solver"]["relaxation_parameter"] = relp
127  solver.solve()
128  else:
129  a2 = newq*inner(grad(p),u)*dx
130  bc = DirichletBC(Q2, Expression(testsol), left)
131  L2 = Constant(0.)*q*dx
132  solve(a2 == L2, c, bc)
133 
134  if (not bool(use_adapt)) or iii == Nadapt-1:
135  break
136  um = project(sqrt(inner(u,u)),FunctionSpace(mesh,'CG',2))
137  H = metric_pnorm(um, eta, max_edge_ratio=1+49*(use_adapt!=2), p=2)
138  H2 = metric_pnorm(c, eta, max_edge_ratio=1+49*(use_adapt!=2), p=2)
139  #H3 = metric_pnorm(ps , eta, max_edge_ratio=1+49*(use_adapt!=2), p=2)
140  H4 = metric_ellipse(H,H2)
141  #H5 = metric_ellipse(H3,H4,mesh)
142  mesh = adapt(H4)
143  if use_reform:
144  Q2 = FunctionSpace(mesh,'CG',2)
145  c = interpolate(c,Q2)
146 
147  if use_reform:
148  c = project(fac/(1+exp(-c))-delta,FunctionSpace(mesh,'CG',2))
149  L2error = bnderror(c,Expression(testsol),ds)
150  dofs.append(len(c.vector().array())+len(U.vector().array()))
151  L2errors.append(L2error)
152 # fid = open("DOFS_L2errors_mesh_c_CG"+str(CGorder)+outname+".mpy",'w')
153 # pickle.dump([dofs[0],L2errors[0],c.vector().array().min(),c.vector().array().max()-1,mesh.cells(),mesh.coordinates(),c.vector().array()],fid)
154 # fid.close();
155  log(INFO+1,"%1dX ADAPT<->SOLVE complete: DOF=%5d, error=%0.0e, min(c)=%0.0e,max(c)-1=%0.0e" % (Nadapt, dofs[len(dofs)-1], L2error,c.vector().array().min(),c.vector().array().max()-1))
156 
157  # PLOT MESH + solution
158  figure()
159  testf = interpolate(c ,FunctionSpace(mesh,'CG',1))
160  testfe = interpolate(Expression(testsol),FunctionSpace(mesh,'CG',1))
161  vtx2dof = vertex_to_dof_map(FunctionSpace(mesh, "CG" ,1))
162  zz = testf.vector().array()[vtx2dof]; zz[zz==1] -= 1e-16
163  hh=tricontourf(mesh.coordinates()[:,0],mesh.coordinates()[:,1],mesh.cells(),zz,100,cmap=get_cmap('binary'))
164  colorbar(hh)
165  hold('on'); triplot(mesh.coordinates()[:,0],mesh.coordinates()[:,1],mesh.cells(),color='r',linewidth=0.5); hold('off')
166  axis('equal'); box('off')
167 # savefig(outname+'final_mesh_CG2.png',dpi=300) #; savefig('outname+final_mesh_CG2.eps',dpi=300)
168  #PLOT ERROR
169  figure()
170  xe = interpolate(Expression("x[0]"),FunctionSpace(mesh,'CG',1)).vector().array()
171  ye = interpolate(Expression("x[1]"),FunctionSpace(mesh,'CG',1)).vector().array()
172  I = xe - Lx/2 > -DOLFIN_EPS; I2 = ye[I].argsort()
173  pyplot(ye[I][I2],testf.vector().array()[I][I2]-testfe.vector().array()[I][I2],'-b'); ylabel('error')
174  # PLOT L2error graph
175  figure()
176  pyloglog(dofs,L2errors,'-b.',linewidth=2,markersize=16); xlabel('Degree of freedoms'); ylabel('L2 error')
177  # SAVE SOLUTION
178  dofs = array(dofs); L2errors = array(L2errors)
179  fid = open("DOFS_L2errors_CG"+str(CGorder)+outname+".mpy",'w')
180  pickle.dump([dofs,L2errors],fid)
181  fid.close();
182 # #show()
183 
184 # #LOAD SAVED SOLUTIONS
185 # fid = open("DOFS_L2errors_CG2"+outname+".mpy",'r')
186 # [dofs,L2errors] = pickle.load(fid)
187 # fid.close()
188 #
189  # PERFORM FITS ON LAST THREE POINTS
190  NfitP = 5
191  I = array(range(len(dofs)-NfitP,len(dofs)))
192  slope,ints = polyfit(pylog(dofs[I]), pylog(L2errors[I]), 1)
193  fid = open("DOFS_L2errors_CG2_fit"+outname+".mpy",'w')
194  pickle.dump([dofs,L2errors,slope,ints],fid)
195  fid.close()
196  #PLOT THEM TOGETHER
197  if CGorderL != [2]:
198  fid = open("DOFS_L2errors_CG3.mpy",'r')
199  [dofs_old,L2errors_old] = pickle.load(fid)
200  fid.close()
201  slope2,ints2 = polyfit(pylog(dofs_old[I]), pylog(L2errors_old[I]), 1)
202  figure()
203  pyloglog(dofs,L2errors,'-b.',dofs_old,L2errors_old,'--b.',linewidth=2,markersize=16)
204  hold('on'); pyloglog(dofs,pyexp2(ints)*dofs**slope,'-r',dofs_old,pyexp2(ints2)*dofs_old**slope2,'--r',linewidth=1); hold('off')
205  xlabel('Degree of freedoms'); ylabel('L2 error')
206  legend(['CG2','CG3',"%0.2f*log(DOFs)" % slope, "%0.2f*log(DOFs)" % slope2]) #legend(['new data','old_data'])
207 # savefig('comparison.png',dpi=300) #savefig('comparison.eps');
208  if not noplot:
209  show()
210 
211 if __name__=="__main__":
213 
def metric_ellipse
Definition: adaptivity.py:654
def metric_pnorm
Definition: adaptivity.py:535
def mesh_metric2
Definition: adaptivity.py:1054