discretization.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. import numpy as np
  2. from numpy import sin, cos, pi
  3. from scipy.linalg import block_diag
  4. import matplotlib.pyplot as plt
  5. from matplotlib import rc
  6. plt.rc('text', usetex=True)
  7. plt.rc('font', family='serif')
  8. class HDPG1d(object):
  9. """
  10. 1d advection hdg solver outlined in 'an implicit HHDG method for
  11. confusion'. Test case: /tau = 1, convection only, linear and higher order.
  12. Please enter number of elements and polynomial order, i.e., HDG1d(10,2)
  13. """
  14. # stablization parameter
  15. tau_pos = 1e-6
  16. tau_neg = 1e-6
  17. # advection constant
  18. c = 0
  19. # diffusion constant
  20. kappa = 1e-6
  21. def __init__(self, n_ele, p):
  22. self.n_ele = n_ele
  23. # number of the shape functions (thus porder + 1)
  24. self.p = p + 1
  25. def bc(self, case, t=None):
  26. # boundary condition
  27. if case == 0:
  28. # advection-diffusion
  29. bc = [0, 0]
  30. if case == 1:
  31. # simple convection
  32. # bc = np.sin(2*np.pi*t)
  33. # adjoint boundary
  34. bc = [0, 1]
  35. return bc
  36. def shape(self, x, p):
  37. """ evaluate shape functions at give locations"""
  38. # coeffient matrix
  39. A = np.array([np.linspace(-1, 1, p)]).T**np.arange(p)
  40. C = np.linalg.inv(A).T
  41. x = np.array([x]).T
  42. shp = C.dot((x**np.arange(p)).T)
  43. shpx = C[:, 1::1].dot((x**np.arange(p - 1) * np.arange(1, p)).T)
  44. return shp, shpx
  45. def forcing(self, x):
  46. # f = np.cos(2*np.pi*x)
  47. # f = 4*pi**2*sin(2*pi*x)
  48. f = 1
  49. return f
  50. def mesh(self, n_ele, index, x):
  51. """generate mesh"""
  52. # if n_ele < 1 or n_ele > self.n_ele:
  53. # raise RuntimeError('Bad Element number')
  54. in_value = np.zeros(len(index))
  55. for i in np.arange(len(index)):
  56. in_value[i] = (x[index[i]] + x[index[i] - 1]) / 2
  57. x_c = np.sort(np.insert(x, 0, in_value))
  58. x_i = np.linspace(x_c[n_ele - 1], x_c[n_ele], num=self.p)
  59. dx = x_c[n_ele] - x_c[n_ele - 1]
  60. return x_i, dx, x_c
  61. def uexact(self, x):
  62. # Ue = self.bc(0) + np.sin(2*pi*x)
  63. Ue = (np.exp(1 / self.kappa * (x - 1)) - 1) / \
  64. (np.exp(-1 / self.kappa) - 1)
  65. return Ue
  66. def matrix_gen(self, index, x):
  67. n_ele = self.n_ele
  68. # # space size
  69. # dx = 1/n_ele
  70. # order of polynomial shape functions
  71. p = self.p
  72. # order of gauss quadrature
  73. gorder = 2 * p
  74. # shape function and gauss quadrature
  75. xi, wi = np.polynomial.legendre.leggauss(gorder)
  76. shp, shpx = self.shape(xi, p)
  77. # ---------------------------------------------------------------------
  78. # advection constant
  79. con = self.c
  80. # diffusion constant
  81. kappa = self.kappa
  82. # number of nodes (solution U)
  83. n_ele = self.n_ele + len(index)
  84. # elemental forcing vector
  85. F = np.zeros(p * n_ele)
  86. for i in range(1, n_ele + 1):
  87. x_i, dx_i, _ = self.mesh(i, index, x)
  88. f = dx_i / 2 * \
  89. shp.dot(wi * self.forcing(x[0] + 1 / 2 * (1 + xi) * dx_i))
  90. F[(i - 1) * p:(i - 1) * p + p] = f
  91. # elemental m (for convection only)
  92. # m = dx/2*shp.dot(np.diag(wi).dot(shp.T))
  93. # add boundary
  94. F[0] += (con + self.tau_pos) * self.bc(0)[0]
  95. F[-1] += (-con + self.tau_neg) * self.bc(0)[1]
  96. # elemental d
  97. # d = con*(-shpx.T*np.ones((gorder,p))).T.dot(np.diag(wi).dot(shp.T))
  98. d = shp.dot(np.diag(wi).dot(shp.T))
  99. # d[0, 0] += self.tau_pos
  100. # d[-1, -1] += self.tau_neg
  101. # elemental a
  102. a = 1 / kappa * shp.dot(np.diag(wi).dot(shp.T))
  103. # elemental b
  104. b = (shpx.T * np.ones((gorder, p))).T.dot(np.diag(wi).dot(shp.T))
  105. # elemental h
  106. h = np.zeros((2, 2))
  107. h[0, 0], h[-1, -1] = -con - self.tau_pos, con - self.tau_neg
  108. # mappinng matrix
  109. map_h = np.zeros((2, n_ele), dtype=int)
  110. map_h[:, 0] = np.arange(2)
  111. for i in np.arange(1, n_ele):
  112. map_h[:, i] = np.arange(
  113. map_h[2 - 1, i - 1], map_h[2 - 1, i - 1] + 2)
  114. # assemble H and eliminate boundaries
  115. H = np.zeros((n_ele + 1, n_ele + 1))
  116. for i in range(n_ele):
  117. for j in range(2):
  118. m = map_h[j, i]
  119. for k in range(2):
  120. n = map_h[k, i]
  121. H[m, n] += h[j, k]
  122. H = H[1:n_ele][:, 1:n_ele]
  123. # elemental g
  124. g = np.zeros((2, p))
  125. g[0, 0], g[-1, -1] = self.tau_pos, self.tau_neg
  126. # mapping matrix
  127. map_g_x = map_h
  128. map_g_y = np.arange(p * n_ele, dtype=int).reshape(n_ele, p).T
  129. # assemble global G
  130. G = np.zeros((n_ele + 1, p * n_ele))
  131. for i in range(n_ele):
  132. for j in range(2):
  133. m = map_g_x[j, i]
  134. for k in range(p):
  135. n = map_g_y[k, i]
  136. G[m, n] += g[j, k]
  137. G = G[1:n_ele, :]
  138. # elemental e
  139. e = np.zeros((p, 2))
  140. e[0, 0], e[-1, -1] = -con - self.tau_pos, con - self.tau_neg
  141. # mapping matrix
  142. map_e_x = np.arange(p * n_ele, dtype=int).reshape(n_ele, p).T
  143. map_e_y = map_h
  144. # assemble global E
  145. E = np.zeros((p * n_ele, n_ele + 1))
  146. for i in range(n_ele):
  147. for j in range(p):
  148. m = map_e_x[j, i]
  149. for k in range(2):
  150. n = map_e_y[k, i]
  151. E[m, n] += e[j, k]
  152. E = E[:, 1:n_ele]
  153. # L, easy in 1d
  154. L = np.zeros(n_ele - 1)
  155. # elemental c
  156. c = np.zeros((p, 2))
  157. c[0, 0], c[-1, -1] = -1, 1
  158. # assemble global C
  159. C = np.zeros((p * n_ele, n_ele + 1))
  160. for i in range(n_ele):
  161. for j in range(p):
  162. m = map_e_x[j, i]
  163. for k in range(2):
  164. n = map_e_y[k, i]
  165. C[m, n] += c[j, k]
  166. C = C[:, 1:n_ele]
  167. # L, easy in 1d
  168. L = np.zeros(n_ele - 1)
  169. # R, easy in 1d
  170. R = np.zeros(p * n_ele)
  171. R[0] = self.bc(0)[0]
  172. R[-1] = -self.bc(0)[1]
  173. return d, m, E, G, H, F, L, a, b, C, R
  174. def solve_local(self, index, x):
  175. """ solve the 1d advection equation wit local HDG"""
  176. d, _, E, G, H, F, L, a, b, C, R = self.matrix_gen(index, x)
  177. # find dx
  178. dx = np.zeros(self.n_ele + len(index))
  179. for i in range(1, self.n_ele + len(index) + 1):
  180. x_i, dx_i, x_n = self.mesh(i, index, x)
  181. dx[i - 1] = dx_i
  182. # assemble global D
  183. bb = np.zeros((self.p, self.p))
  184. bb[0, 0] = self.tau_pos
  185. bb[-1, -1] = self.tau_neg
  186. D = np.repeat(dx, self.p) / 2 * block_diag(*[d] * (
  187. self.n_ele + len(index))) + block_diag(*[bb] * (self.n_ele + len(index)))
  188. # assemble global A
  189. A = np.repeat(dx, self.p) / 2 * block_diag(*
  190. [a] * (self.n_ele + len(index)))
  191. # assemble global B
  192. B = block_diag(*[b] * (self.n_ele + len(index)))
  193. # solve U and \lambda
  194. K = -np.concatenate((C.T, G), axis=1).dot(np.linalg.inv(
  195. np.bmat([[A, -B], [B.T, D]])).dot(np.concatenate((C, E)))) + H
  196. F_hat = np.array([L]).T - np.concatenate((C.T, G), axis=1).dot(np.linalg.inv(
  197. np.bmat([[A, -B], [B.T, D]]))).dot(np.array([np.concatenate((R, F))]).T)
  198. lamba = np.linalg.solve(K, F_hat)
  199. U = np.linalg.inv(np.bmat([[A, -B], [B.T, D]])).dot(
  200. np.array([np.concatenate((R, F))]).T - np.concatenate((C, E)).dot(lamba))
  201. return U, lamba
  202. def solve_adjoint(self, index, x, u, u_hat):
  203. self.p = self.p + 1
  204. d, _, E, G, H, F, L, a, b, C, R = self.matrix_gen(index, x)
  205. # add boundary
  206. F = np.zeros(len(F))
  207. R[-1] = -self.bc(1)[1]
  208. # find dx
  209. dx = np.zeros(self.n_ele + len(index))
  210. for i in range(1, self.n_ele + len(index) + 1):
  211. x_i, dx_i, x_n = self.mesh(i, index, x)
  212. dx[i - 1] = dx_i
  213. # assemble global D
  214. bb = np.zeros((self.p, self.p))
  215. bb[0, 0] = self.tau_pos
  216. bb[-1, -1] = self.tau_neg
  217. D = np.repeat(dx, self.p) / 2 * block_diag(*[d] * (
  218. self.n_ele + len(index))) + block_diag(*[bb] * (self.n_ele + len(index)))
  219. # assemble global A
  220. A = np.repeat(dx, self.p) / 2 * block_diag(*
  221. [a] * (self.n_ele + len(index)))
  222. # assemble global B
  223. B = block_diag(*[b] * (self.n_ele + len(index)))
  224. # # assemble global matrix LHS
  225. LHS = np.bmat([[A, -B, C], [B.T, D, E], [C.T, G, H]])
  226. # solve U and \lambda
  227. U = np.linalg.solve(LHS.T, np.concatenate((R, F, L)))
  228. return U[0:2 * self.p * (self.n_ele + len(index))], U[2 * self.p * (self.n_ele + len(index)):len(U)]
  229. def diffusion(self):
  230. """solve 1d convection with local HDG"""
  231. # begin and end time
  232. t, T = 0, 1
  233. # time marching step for diffusion equation
  234. dt = 1e-3
  235. d, m, E, G, H, F, L, a, b, C, R = self.matrix_gen()
  236. # add time derivatives to the space derivatives (both are
  237. # elmental-wise)
  238. d = d + 1 / dt * m
  239. # assemble global D
  240. D = block_diag(*[d] * self.n_ele)
  241. # assemble global A
  242. A = block_diag(*[a] * self.n_ele)
  243. # assemble global B
  244. B = block_diag(*[b] * self.n_ele)
  245. # initial condition
  246. X = np.zeros(self.p * self.n_ele)
  247. for i in range(1, self.n_ele + 1):
  248. x = self.mesh(i)
  249. X[(i - 1) * self.p:(i - 1) * self.p + self.p] = x
  250. U = np.concatenate((pi * cos(pi * X), sin(pi * X)))
  251. # assemble M
  252. M = block_diag(*[1 / dt * m] * self.n_ele)
  253. # time marching
  254. while t < T:
  255. # add boundary conditions
  256. F_dynamic = F + \
  257. M.dot(U[self.n_ele * self.p:2 * self.n_ele * self.p])
  258. # assemble global matrix LHS
  259. LHS = np.bmat([[A, -B, C], [B.T, D, E], [C.T, G, H]])
  260. # solve U and \lambda
  261. U = np.linalg.solve(LHS, np.concatenate((R, F_dynamic, L)))
  262. # plot solutions
  263. plt.clf()
  264. plt.plot(X, U[self.n_ele * self.p:2 * self.n_ele * self.p], '-r.')
  265. plt.plot(X, sin(pi * X) * np.exp(-pi**2 * t))
  266. plt.ylim([0, 1])
  267. plt.grid()
  268. plt.pause(1e-3)
  269. plt.close()
  270. print("Diffusion equation du/dt - du^2/d^2x = 0 with u_exact ="
  271. ' 6sin(pi*x)*exp(-pi^2*t).')
  272. plt.figure(1)
  273. plt.plot(X, U[self.n_ele * self.p:2 * self.n_ele * self.p], '-r.')
  274. plt.plot(X, sin(pi * X) * np.exp(-pi**2 * T))
  275. plt.xlabel('x')
  276. plt.ylabel('y')
  277. plt.legend(('Numberical', 'Exact'), loc='upper left')
  278. plt.title('Simple Diffusion Equation Solution at t = {}'.format(T))
  279. plt.grid()
  280. plt.savefig('diffusion', bbox_inches='tight')
  281. plt.show(block=False)
  282. return U
  283. def errorL2(self):
  284. # evaluate error
  285. errorL2 = 0.
  286. # solve and track solving time
  287. x = np.linspace(0, 1, self.n_ele + 1)
  288. U, _ = self.solve_local([], x)
  289. errorL2 = np.abs(U[self.p * self.n_ele - 1] - np.sqrt(self.kappa))
  290. return errorL2
  291. def conv(self):
  292. p = np.arange(2, 6)
  293. n_ele = 2**np.arange(1, 9)
  294. legend = []
  295. errorL2 = np.zeros((n_ele.size, p.size))
  296. for i in range(p.size):
  297. self.p = p[i]
  298. for j, n in enumerate(n_ele):
  299. self.n_ele = n
  300. print(self.errorL2())
  301. errorL2[j, i] = self.errorL2()
  302. legend.append('p = {}'.format(p[i] - 1))
  303. # loglog plot
  304. plt.figure(3)
  305. plt.loglog(n_ele, errorL2, '-o')
  306. plt.legend((legend))
  307. plt.xlabel('Number of nodes')
  308. plt.ylabel('L2 norm(log)')
  309. plt.title('Convergence rate(log)')
  310. plt.grid()
  311. plt.savefig('con_rate_uni.pdf', bbox_inches='tight')
  312. # output then save the convergence rates
  313. rate = np.log(errorL2[0:-1, :] /
  314. errorL2[1:errorL2.size, :]) / np.log(2)
  315. for i in range(p.size):
  316. print('p = {}, convergence rate = {:.4f}'.format(
  317. p[i] - 1, rate[-1, i]))
  318. np.savetxt('Con_rate.csv', rate, fmt='%10.4f',
  319. delimiter=',', newline='\n')
  320. return n_ele, errorL2
  321. def residual(self, U, hat_U, z, hat_z, dx, index, x_c):
  322. n_ele = self.n_ele
  323. # order of polynomial shape functions
  324. p = self.p
  325. p_l = p - 1
  326. # order of gauss quadrature
  327. gorder = 2 * p
  328. # shape function and gauss quadrature
  329. xi, wi = np.polynomial.legendre.leggauss(gorder)
  330. shp, shpx = self.shape(xi, p)
  331. shp_l, shpx_l = self.shape(xi, p_l)
  332. # ---------------------------------------------------------------------
  333. # advection constant
  334. con = self.c
  335. # diffusion constant
  336. kappa = self.kappa
  337. z_q, z_u, z_hat = np.zeros(self.p * self.n_ele), \
  338. np.zeros(self.p * self.n_ele), np.zeros(self.n_ele - 1)
  339. q, u, lamba = np.zeros(p_l * self.n_ele), \
  340. np.zeros(p_l * self.n_ele), np.zeros(self.n_ele - 1)
  341. for i in np.arange(self.p * self.n_ele):
  342. z_q[i] = z[i]
  343. z_u[i] = z[i + self.p * self.n_ele]
  344. for i in np.arange(p_l * self.n_ele):
  345. q[i] = U[i]
  346. u[i] = U[i + p_l * self.n_ele]
  347. for i in np.arange(self.n_ele - 1):
  348. z_hat[i] = hat_z[i]
  349. # add boundary condtions to U_hat
  350. U_hat = np.zeros(self.n_ele + 1)
  351. for i, x in enumerate(hat_U):
  352. U_hat[i + 1] = x
  353. U_hat[0] = self.bc(0)[0]
  354. U_hat[-1] = self.bc(0)[1]
  355. # L, easy in 1d
  356. L = np.zeros(n_ele + 1)
  357. # R, easy in 1d
  358. RR = np.zeros(p * n_ele)
  359. # elemental forcing vector
  360. F = np.zeros(p * n_ele)
  361. for i in range(1, n_ele + 1):
  362. f = dx[i - 1] / 2 * \
  363. shp.dot(
  364. wi * self.forcing(x_c[0] + 1 / 2 * (1 + xi) * dx[i - 1]))
  365. F[(i - 1) * p:(i - 1) * p + p] = f
  366. # elemental h
  367. h = np.zeros((2, 2))
  368. h[0, 0], h[-1, -1] = -con - self.tau_pos, con - self.tau_neg
  369. # mappinng matrix
  370. map_h = np.zeros((2, n_ele), dtype=int)
  371. map_h[:, 0] = np.arange(2)
  372. for i in np.arange(1, n_ele):
  373. map_h[:, i] = np.arange(
  374. map_h[2 - 1, i - 1], map_h[2 - 1, i - 1] + 2)
  375. # assemble H and eliminate boundaries
  376. H = np.zeros((n_ele + 1, n_ele + 1))
  377. for i in range(n_ele):
  378. for j in range(2):
  379. m = map_h[j, i]
  380. for k in range(2):
  381. n = map_h[k, i]
  382. H[m, n] += h[j, k]
  383. H = H[1:n_ele][:, 1:n_ele]
  384. # elemental g
  385. g = np.zeros((2, p_l))
  386. g[0, 0], g[-1, -1] = self.tau_pos, self.tau_neg
  387. # mapping matrix
  388. map_g_x = map_h
  389. map_g_y = np.arange(p_l * n_ele, dtype=int).reshape(n_ele, p_l).T
  390. # assemble global G
  391. G = np.zeros((n_ele + 1, p_l * n_ele))
  392. for i in range(n_ele):
  393. for j in range(2):
  394. m = map_g_x[j, i]
  395. for k in range(p_l):
  396. n = map_g_y[k, i]
  397. G[m, n] += g[j, k]
  398. G = G[1:n_ele, :]
  399. # elemental c
  400. c = np.zeros((p_l, 2))
  401. c[0, 0], c[-1, -1] = -1, 1
  402. # mapping matrix
  403. map_e_x = np.arange(p_l * n_ele, dtype=int).reshape(n_ele, p_l).T
  404. map_e_y = map_h
  405. # assemble global C
  406. C = np.zeros((p_l * n_ele, n_ele + 1))
  407. for i in range(n_ele):
  408. for j in range(p_l):
  409. m = map_e_x[j, i]
  410. for k in range(2):
  411. n = map_e_y[k, i]
  412. C[m, n] += c[j, k]
  413. C = C[:, 1:n_ele]
  414. # L, easy in 1d
  415. L = np.zeros(n_ele - 1)
  416. # residual vector
  417. R = np.zeros(self.n_ele)
  418. for i in np.arange(self.n_ele):
  419. a = dx[i] / 2 * 1 / kappa * \
  420. ((shp.T).T).dot(np.diag(wi).dot(shp_l.T))
  421. b = ((shpx.T) * np.ones((gorder, p))
  422. ).T.dot(np.diag(wi).dot(shp_l.T))
  423. b_t = ((shpx_l.T) * np.ones((gorder, p_l))
  424. ).T.dot(np.diag(wi).dot(shp.T))
  425. d = dx[i] / 2 * shp.dot(np.diag(wi).dot(shp_l.T))
  426. d[0, 0] += self.tau_pos
  427. d[-1, -1] += self.tau_neg
  428. h = np.zeros((2, 2))
  429. h[0, 0], h[-1, -1] = -con - self.tau_pos, con - self.tau_neg
  430. g = np.zeros((2, p_l))
  431. g[0, 0], g[-1, -1] = self.tau_pos, self.tau_neg
  432. e = np.zeros((p, 2))
  433. e[0, 0], e[-1, -1] = -con - self.tau_pos, con - self.tau_neg
  434. c = np.zeros((p, 2))
  435. c[0, 0], c[-1, -1] = -1, 1
  436. m = np.zeros((2, p_l))
  437. m[0, 0], m[-1, -1] = -1, 1
  438. # local error
  439. R[i] = (np.concatenate((a.dot(q[p_l * i:p_l * i + p_l]) + -b.dot(u[p_l * i:p_l * i + p_l]) + c.dot(U_hat[i:i + 2]),
  440. b_t.T.dot(q[p_l * i:p_l * i + p_l]) + d.dot(u[p_l * i:p_l * i + p_l]) + e.dot(U_hat[i:i + 2]))) - np.concatenate((RR[p * i:p * i + p], F[p * i:p * i + p]))).dot(1 - np.concatenate((z_q[p * i:p * i + p], z_u[p * i:p * i + p])))
  441. com_index = np.argsort(np.abs(R))
  442. # select \theta% elements with the large error
  443. theta = 0.15
  444. refine_index = com_index[int(self.n_ele * (1 - theta)):len(R)]
  445. self.p = self.p - 1
  446. # global error
  447. R_g = (C.T.dot(q) + G.dot(u) + H.dot(U_hat[1:-1])).dot(1 - z_hat)
  448. return np.abs(np.sum(R) + np.sum(R_g)), refine_index + 1
  449. def adaptive(self):
  450. x = np.linspace(0, 1, self.n_ele + 1)
  451. index = []
  452. U, hat_U = self.solve_local(index, x)
  453. U_adjoint, hat_adjoint = self.solve_adjoint(index, x, U, hat_U)
  454. X = np.zeros(self.p * self.n_ele)
  455. dx = np.zeros(self.n_ele + len(index))
  456. for i in range(1, self.n_ele + 1):
  457. x_i, dx_i, x_n = self.mesh(i, index, x)
  458. X[(i - 1) * self.p:(i - 1) * self.p + self.p] = x_i
  459. dx[i - 1] = dx_i
  460. numAdaptive = 28
  461. trueError = np.zeros((2, numAdaptive))
  462. estError = np.zeros((2, numAdaptive))
  463. for i in np.arange(numAdaptive):
  464. est_error, index = self.residual(
  465. U, hat_U, U_adjoint, hat_adjoint, dx, index, x)
  466. index = index.tolist()
  467. U, hat_U = self.solve_local(index, x)
  468. U_adjoint, hat_adjoint = self.solve_adjoint(index, x, U, hat_U)
  469. self.p = self.p - 1
  470. X = np.zeros(self.p * (self.n_ele + len(index)))
  471. dx = np.zeros(self.n_ele + len(index))
  472. for j in range(1, self.n_ele + len(index) + 1):
  473. x_i, dx_i, x_n = self.mesh(j, index, x)
  474. X[(j - 1) * self.p:(j - 1) * self.p + self.p] = x_i
  475. dx[j - 1] = dx_i
  476. x = x_n
  477. estError[0, i] = self.n_ele
  478. estError[1, i] = est_error
  479. self.n_ele = self.n_ele + len(index)
  480. # U_1d = np.zeros(len(U))
  481. # for j in np.arange(len(U)):
  482. # U_1d[j] = U[j]
  483. # Unum = np.array([])
  484. # Xnum = np.array([])
  485. # Qnum = np.array([])
  486. # for j in range(1, self.n_ele + 1):
  487. # # Gauss quadrature
  488. # gorder = 10 * self.p
  489. # xi, wi = np.polynomial.legendre.leggauss(gorder)
  490. # shp, shpx = self.shape(xi, self.p)
  491. # Xnum = np.hstack((Xnum, (X[(j - 1) * self.p + self.p - 1] + X[(j - 1) * self.p]) / 2 + (
  492. # X[(j - 1) * self.p + self.p - 1] - X[(j - 1) * self.p]) / 2 * xi))
  493. # Unum = np.hstack(
  494. # (Unum, shp.T.dot(U_1d[int(len(U) / 2) + (j - 1) * self.p:int(len(U) / 2) + j * self.p])))
  495. # Qnum = np.hstack(
  496. # (Qnum, shp.T.dot(U_1d[int((j - 1) * self.p):j * self.p])))
  497. # if i in [0, 4, 9, 19]:
  498. # plt.plot(Xnum, Unum, '-', color='C3')
  499. # plt.plot(X, U[int(len(U) / 2):len(U)], 'C3.')
  500. # plt.xlabel('$x$', fontsize=17)
  501. # plt.ylabel('$u$', fontsize=17)
  502. # plt.axis([-0.05, 1.05, 0, 1.3])
  503. # plt.grid()
  504. # # plt.savefig('u_test_{}.pdf'.format(i+1))
  505. # plt.show()
  506. # plt.clf()
  507. trueError[0, i] = self.n_ele
  508. trueError[1, i] = U[self.n_ele * self.p - 1] - np.sqrt(self.kappa)
  509. self.p = self.p + 1
  510. return trueError, estError
  511. # test = HDPG1d(2, 2)
  512. # _, trueError, estError = test.adaptive()
  513. # p = np.arange(3, 4)
  514. # n_ele = 2**np.arange(1, 8)
  515. # legend = []
  516. # errorL2 = np.zeros((n_ele.size, p.size))
  517. # for i in range(p.size):
  518. # test.p = p[i]
  519. # for j, n in enumerate(n_ele):
  520. # test.n_ele = n
  521. # print(test.errorL2())
  522. # errorL2[j, i] = test.errorL2()
  523. # plt.loglog(trueError[0, 0:-1], np.abs(trueError[1, 0:-1]), '-ro')
  524. # plt.axis([1, 250, 1e-13, 1e-2])
  525. # plt.loglog(n_ele, errorL2, '-o')
  526. # plt.loglog(estError[0, :], estError[1, :], '--', color='#1f77b4')
  527. # plt.xlabel('Number of elements', fontsize=17)
  528. # plt.ylabel('Error', fontsize=17)
  529. # plt.grid()
  530. # plt.legend(('Adaptive', 'Uniform', 'Estimator'), loc=3, fontsize=15)
  531. # # plt.savefig('conv{}p{}_4_test.pdf'.format(15, test.p))
  532. # plt.show()