PRAgMaTIc  master
ellipse_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
4 ### 1. derive a forcing term that gives rise to a step function with a curvature (hence the name)
5 ### 2. solve a poisson equation with the forcing term using 2D anisotropic adaptivity
6 ### 3. calculate and plot the L2error of the resulting solution as function of the number of degrees
7 ### of freedom for 2nd and third order discretization.
8 ### the width of the step and the number of solition<->adaptation iterations
9 ### are optional input parameters. Furthermore the continuity of the step function
10 ### can be controlled by, i.e. problem=2 gives continuity of 2nd order derivatives
11 ### the options use_adapt, noplot and outname relate to the possibility of making a concise graph comparing
12 ### no, isotropic and anisotropic adaptation convergence as a function of the step width.
13 
14 from dolfin import *
15 from adaptivity import metric_pnorm, adapt, logproject
16 from pylab import polyfit, hold, show, triplot, tricontourf, colorbar, axis, box, get_cmap, figure, legend, savefig, xlabel, ylabel, title, xlim, ylim
17 from pylab import loglog as pyloglog
18 from numpy import array
19 import pickle, os
20 from sympy import Symbol, diff
21 from sympy import sqrt as pysqrt
22 from numpy import abs as pyabs
23 from numpy import log as pylog
24 from numpy import exp as pyexp2
25 
26 #set_log_level(WARNING)
27 set_log_level(INFO+1)
28 
29 def ellipse_convergence(asp=2,width=1e-2, Nadapt=10, eta_list=0.04*pyexp2(-array(range(15))*pylog(2)/2), \
30 use_adapt=True, problem=2, outname='', CGorderL = [2, 3], noplot=False, octaveimpl=False):
31  ### SETUP SOLUTION
32  sx = Symbol('sx'); sy = Symbol('sy'); width_ = Symbol('ww'); asp_ = Symbol('a')
33  rrpy = pysqrt(sx*sx/asp_+sy*sy*asp_)
34  if problem == 2:
35  stepfunc = 0.5+165./104./width_*(rrpy-0.25)-20./13./width_**3*(rrpy-0.25)**3-102./13./width_**5*(rrpy-0.25)**5+240./13./width_**7*(rrpy-0.25)**7
36  elif problem == 1:
37  stepfunc = 0.5+15./8./width_*(rrpy-0.25)-5./width_**3*(rrpy-0.25)**3+6./width_**5*(rrpy-0.25)**5
38  else:
39  stepfunc = 0.5+1.5/width_*(rrpy-0.25)-2/width_**3*(rrpy-0.25)**3
40 
41  ddstepfunc = str(diff(stepfunc,sx,sx)+diff(stepfunc,sy,sy)).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
42  stepfunc = str(stepfunc).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
43  #REPLACE ** with pow
44  stepfunc = stepfunc.replace('(a*(x[1]*x[1]) + (x[0]*x[0])/a)**(1/2)','sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a)')
45  ddstepfunc = ddstepfunc.replace('(a*(x[1]*x[1]) + (x[0]*x[0])/a)**(1/2)','sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a)')
46  ddstepfunc = ddstepfunc.replace('(a*(x[1]*x[1]) + (x[0]*x[0])/a)**(3/2)','pow(a*x[1]*x[1]+x[0]*x[0]/a,1.5)')
47  ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**2','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,2.)')
48  ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**3','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,3.)')
49  ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**4','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,4.)')
50  ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**5','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,5.)')
51  ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**6','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,6.)')
52  stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**3','pow(sqrt(a*x[1]*x[1] + x[0]*x[0]/a) - 0.25,3.)')
53  stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**5','pow(sqrt(a*x[1]*x[1] + x[0]*x[0]/a) - 0.25,5.)')
54  stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**7','pow(sqrt(a*x[1]*x[1] + x[0]*x[0]/a) - 0.25,7.)')
55  testsol = '(0.25-ww/2<sqrt(x[0]*x[0]/a+x[1]*x[1]*a) && sqrt(x[0]*x[0]/a+x[1]*x[1]*a) < 0.25+ww/2 ? (' + stepfunc + ') : 0) + (0.25+ww/2<sqrt(x[0]*x[0]/a+x[1]*x[1]*a) ? 1 : 0)'
56 # testsol = '(0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + stepfunc + ')) : (0.25<sqrt(x[0]*x[0]+x[1]*x[1]) ? 1 : 0)'
57  ddtestsol = '0.25-ww/2<sqrt(x[0]*x[0]/a+x[1]*x[1]*a) && sqrt(x[0]*x[0]/a+x[1]*x[1]*a) < 0.25+ww/2 ? (' + ddstepfunc + ') : 0'
58 
59 # A = array([[0.5,0.5**3,0.5**5],[1,3*0.5**2,5*0.5**4],[0,6*0.5,20*0.5**3]]); b = array([0.5,0,0])
60 # from numpy.linalg import solve as pysolve #15/8,-5,6
61 # X = pysolve(A,b); from numpy import linspace; xx = linspace(-0.5,0.5,100)
62 # from pylab import plot as pyplot; pyplot(xx,X[0]*xx+X[1]*xx**3+X[2]*xx**5,'-b')
63 # rrpy = pysqrt(sx*sx+sy*sy)
64 #
65 # ddstepfunc = str(diff(stepfunc,sx,sx)+diff(stepfunc,sy,sy)).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
66 # stepfunc = str(stepfunc).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
67 # #REPLACE ** with pow
68 # ddstepfunc = ddstepfunc.replace('(a*(x[1]*x[1]) + (x[0]*x[0])/a)**(3/2)','pow(a*x[1]*x[1]+x[0]*x[0]/a,1.5)')
69 # ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**2','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,2.)')
70 # ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**3','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,3.)')
71 # ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**4','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,4.)')
72 # stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**3','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,3.)')
73 # stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**5','pow(sqrt(a*x[1]*x[1]+x[0]*x[0]/a) - 0.25,5.)')
74 # testsol = '(0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + stepfunc + ') : 0) + (0.25+ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) ? 1 : 0)'
75 ## testsol = '(0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + stepfunc + ')) : (0.25<sqrt(x[0]*x[0]+x[1]*x[1]) ? 1 : 0)'
76 # ddtestsol = '0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + ddstepfunc + ') : 0'
77 # else: # problem == 0:
78 # rrpy = pysqrt(sx*sx+sy*sy)
79 # #'if(t<2*WeMax,0,if(t<4*WeMax,0.5+3/2/(2*WeMax)*(t-3*WeMax)-2/(2*WeMax)^3*(t-3*WeMax)^3,1))'; %0.5+3/2/dx*(x-xc)-2/dx^3*(x-xc)^3
80 # ddstepfunc = str(diff(stepfunc,sx,sx)+diff(stepfunc,sy,sy)).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
81 # stepfunc = str(stepfunc).replace('sx','x[0]').replace('sy','x[1]').replace('x[0]**2','(x[0]*x[0])').replace('x[1]**2','(x[1]*x[1])')
82 # #REPLACE ** with pow
83 # ddstepfunc = ddstepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**2','pow(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25,2.)')
84 # ddstepfunc = ddstepfunc.replace('(a*(x[1]*x[1]) + (x[0]*x[0])/a)**(3/2)','pow(a*(x[1]*x[1]) + (x[0]*x[0])/a,1.5)')
85 # stepfunc = stepfunc.replace('(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25)**3','pow(sqrt(a*(x[1]*x[1]) + (x[0]*x[0])/a) - 0.25,3.)')
86 # testsol = '0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + stepfunc + ') : (0.25<sqrt(x[0]*x[0]+x[1]*x[1]) ? 1 : 0)'
87 # ddtestsol = '0.25-ww/2<sqrt(x[0]*x[0]+x[1]*x[1]) && sqrt(x[0]*x[0]+x[1]*x[1]) < 0.25+ww/2 ? (' + ddstepfunc + ') : 0'
88 
89  ddtestsol = ddtestsol.replace('a**2','(a*a)').replace('ww**2','(ww*ww)').replace('ww**3','pow(ww,3.)').replace('ww**4','pow(ww,4.)').replace('ww**5','pow(ww,5.)').replace('ww**6','pow(ww,6.)').replace('ww**7','pow(ww,7.)')
90  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.)')
91  ddtestsol = ddtestsol.replace('ww',str(width)).replace('a',str(asp))
92  testsol = testsol.replace('ww',str(width)).replace('a',str(asp))
93  ddtestsol = '-('+ddtestsol+')'
94 
95  def boundary(x):
96  return x[0]+0.5 < DOLFIN_EPS or 0.5-x[0] < DOLFIN_EPS or x[1]+0.5 < DOLFIN_EPS or 0.5-x[1] < DOLFIN_EPS
97 
98  for CGorder in CGorderL:
99  dofs = []
100  L2errors = []
101  #for eta in [0.16, 0.08, 0.04, 0.02, 0.01, 0.005, 0.0025] #, 0.0025/2, 0.0025/4, 0.0025/8]: #
102  for eta in eta_list:
103  ### SETUP MESH
104  meshsz = int(round(80*0.005/(eta*(bool(use_adapt)==False)+0.05*(bool(use_adapt)==True))))
105  if (not bool(use_adapt)) and meshsz > 80:
106  continue
107 
108  mesh = RectangleMesh(-0.0,-0.0,0.5*sqrt(asp),0.5/sqrt(asp),meshsz,meshsz,"left/right")
109  # PERFORM TEN ADAPTATION ITERATIONS
110  for iii in range(Nadapt):
111  V = FunctionSpace(mesh, "CG", CGorder); dis = TrialFunction(V); dus = TestFunction(V); u = Function(V)
112  #V2 = FunctionSpace(mesh, "CG", CGorder+2)
113  R = Expression(ddtestsol) #interpolate(Expression(ddtestsol),V2)
114  a = inner(grad(dis), grad(dus))*dx
115  L = R*dus*dx
116  bc = DirichletBC(V, Expression(testsol), boundary) #Constant(0.)
117  solve(a == L, u, bc)
118  if not bool(use_adapt):
119  break
120  H = metric_pnorm(u, eta, max_edge_ratio=1+49*(use_adapt!=2), p=2)
121  H = logproject(H)
122  if iii != Nadapt-1:
123  mesh = adapt(H, octaveimpl=octaveimpl, debugon=False)
124 
125  L2error = errornorm(Expression(testsol), u, degree_rise=CGorder+2, norm_type='L2')
126  dofs.append(len(u.vector().array()))
127  L2errors.append(L2error)
128  log(INFO+1,"%1dX ADAPT<->SOLVE complete: DOF=%5d, error=%0.0e" % (Nadapt, dofs[len(dofs)-1], L2error))
129 
130  # PLOT MESH + solution
131  figure()
132  testf = interpolate(u ,FunctionSpace(mesh,'CG',1))
133  testfe = interpolate(Expression(testsol),FunctionSpace(mesh,'CG',1))
134  vtx2dof = vertex_to_dof_map(FunctionSpace(mesh, "CG" ,1))
135  zz = testf.vector().array()[vtx2dof]; zz[zz==1] -= 1e-16
136  hh=tricontourf(mesh.coordinates()[:,0],mesh.coordinates()[:,1],mesh.cells(),zz,100,cmap=get_cmap('binary'))
137  colorbar(hh)
138  axis('equal'); axis('off'); box('off'); xlim([0,0.5*sqrt(asp)]); ylim([0, 0.5/sqrt(asp)]); savefig('solution.png',dpi=300)
139  figure()
140  hold('on'); triplot(mesh.coordinates()[:,0],mesh.coordinates()[:,1],mesh.cells(),color='r',linewidth=0.5); hold('off')
141  axis('equal'); box('off')
142  axis('off'); xlim([0,0.5*sqrt(asp)]); ylim([0, 0.5/sqrt(asp)])
143  savefig(outname+'final_mesh_CG2.png',dpi=300) #; savefig('outname+final_mesh_CG2.eps',dpi=300)
144  #PLOT ERROR
145  figure()
146  zz = pyabs(testf.vector().array()-testfe.vector().array())[vtx2dof]; zz[zz==1] -= 1e-16
147  hh=tricontourf(mesh.coordinates()[:,0],mesh.coordinates()[:,1],mesh.cells(),zz,100,cmap=get_cmap('binary'))
148  colorbar(hh); axis('equal'); box('off'); title('error')
149  # PLOT L2error graph
150  figure()
151  pyloglog(dofs,L2errors,'-b.',linewidth=2,markersize=16); xlabel('Degree of freedoms'); ylabel('L2 error')
152  # SAVE SOLUTION
153  dofs = array(dofs); L2errors = array(L2errors)
154  fid = open("DOFS_L2errors_CG"+str(CGorder)+outname+".mpy",'w')
155  pickle.dump([dofs,L2errors],fid)
156  fid.close();
157 
158  #LOAD SAVED SOLUTIONS
159  fid = open("DOFS_L2errors_CG2"+outname+".mpy",'r')
160  [dofs,L2errors] = pickle.load(fid)
161  fid.close()
162 
163  # PERFORM FITS ON LAST THREE POINTS
164  NfitP = 9
165  I = array(range(len(dofs)-NfitP,len(dofs)))
166  slope,ints = polyfit(pylog(dofs[I]), pylog(L2errors[I]), 1)
167  if slope < -0.7:
168  fid = open("DOFS_L2errors_CG2_fit"+outname+".mpy",'w')
169  pickle.dump([dofs,L2errors,slope,ints],fid)
170  fid.close()
171  log(INFO+1,'succes')
172  else:
173  os.system('rm '+outname+'.lock')
174  log(INFO+1,'fail')
175  #PLOT THEM TOGETHER
176  if CGorderL != [2]:
177  fid = open("DOFS_L2errors_CG3.mpy",'r')
178  [dofs_old,L2errors_old] = pickle.load(fid)
179  fid.close()
180  slope2,ints2 = polyfit(pylog(dofs_old[I]), pylog(L2errors_old[I]), 1)
181  figure()
182  pyloglog(dofs,L2errors,'-b.',dofs_old,L2errors_old,'--b.',linewidth=2,markersize=16)
183  hold('on'); pyloglog(dofs,pyexp2(ints)*dofs**slope,'-r',dofs_old,pyexp2(ints2)*dofs_old**slope2,'--r',linewidth=1); hold('off')
184  xlabel('Degree of freedoms'); ylabel('L2 error')
185  legend(['CG2','CG3',"%0.2f*log(DOFs)" % slope, "%0.2f*log(DOFs)" % slope2]) #legend(['new data','old_data'])
186 # savefig('comparison.png',dpi=300) #savefig('comparison.eps');
187  if not noplot:
188  show()
189 
190 if __name__=="__main__":
191  ellipse_convergence(asp=1, octaveimpl=True, width=2e-2)
192 # ellipse_convergence(asp=1)
193  #ellipse_convergence(asp=1,width=1e-1, CGorderL=[2], eta_list=[0.001], problem=1) #for presentation
194 
195 
def metric_pnorm
Definition: adaptivity.py:535
def logproject
Definition: adaptivity.py:966