PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/test/unit/fem/python/Form.py

https://bitbucket.org/rbrault/dolfin
Python | 438 lines | 301 code | 90 blank | 47 comment | 16 complexity | 7220abb278e7edf51f460174e12fbea3 MD5 | raw file
  1. """Unit tests for the fem interface"""
  2. # Copyright (C) 2011 Johan Hake
  3. #
  4. # This file is part of DOLFIN.
  5. #
  6. # DOLFIN is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Lesser General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # DOLFIN is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License
  17. # along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # First added: 2011-12-02
  20. # Last changed: 2012-12-11
  21. #
  22. # Modified by Marie E. Rognes (meg@simula.no), 2012
  23. import unittest
  24. import numpy
  25. import ufl
  26. from dolfin import *
  27. class FormTest(unittest.TestCase):
  28. def setUp(self):
  29. self.mesh = UnitSquareMesh(10, 10)
  30. self.V = FunctionSpace(self.mesh, "CG", 1)
  31. self.f = Expression("sin(pi*x[0]*x[1])")
  32. self.v = TestFunction(self.V)
  33. self.u = TrialFunction(self.V)
  34. def test_assemble(self):
  35. ufl_form = self.f*self.u*self.v*dx
  36. dolfin_form = Form(ufl_form)
  37. ufc_form = dolfin_form._compiled_form
  38. A_ufl_norm = assemble(ufl_form).norm("frobenius")
  39. A_dolfin_norm = assemble(dolfin_form).norm("frobenius")
  40. A_ufc_norm = assemble(ufc_form, coefficients=[self.f],
  41. function_spaces=[self.V, self.V]).norm("frobenius")
  42. self.assertAlmostEqual(A_ufl_norm, A_dolfin_norm)
  43. self.assertAlmostEqual(A_ufl_norm, A_ufc_norm)
  44. class FormTestsOverManifolds(unittest.TestCase):
  45. def setUp(self):
  46. # Boundary mesh not running in parallel
  47. if MPI.num_processes() > 1:
  48. return
  49. # 1D in 2D spaces
  50. self.square = UnitSquareMesh(2, 2)
  51. self.mesh1 = BoundaryMesh(self.square, "exterior")
  52. self.V1 = FunctionSpace(self.mesh1, "CG", 1)
  53. self.VV1 = VectorFunctionSpace(self.mesh1, "CG", 1)
  54. self.Q1 = FunctionSpace(self.mesh1, "DG", 0)
  55. # 2D in 3D spaces
  56. self.cube = UnitCubeMesh(2, 2, 2)
  57. self.mesh2 = BoundaryMesh(self.cube, "exterior")
  58. self.V2 = FunctionSpace(self.mesh2, "CG", 1)
  59. self.VV2 = VectorFunctionSpace(self.mesh2, "CG", 1)
  60. self.Q2 = FunctionSpace(self.mesh2, "DG", 0)
  61. def test_assemble_functional(self):
  62. # Boundary mesh not running in parallel
  63. if MPI.num_processes() > 1:
  64. return
  65. u = Function(self.V1)
  66. u.vector()[:] = 1.0
  67. surfacearea = assemble(u*dx)
  68. self.assertAlmostEqual(surfacearea, 4.0)
  69. u = Function(self.V2)
  70. u.vector()[:] = 1.0
  71. surfacearea = assemble(u*dx)
  72. self.assertAlmostEqual(surfacearea, 6.0)
  73. f = Expression("1.0")
  74. u = interpolate(f, self.V1)
  75. surfacearea = assemble(u*dx)
  76. self.assertAlmostEqual(surfacearea, 4.0)
  77. f = Expression("1.0")
  78. u = interpolate(f, self.V2)
  79. surfacearea = assemble(u*dx)
  80. self.assertAlmostEqual(surfacearea, 6.0)
  81. def test_assemble_linear(self):
  82. # Boundary mesh not running in parallel
  83. if MPI.num_processes() > 1:
  84. return
  85. u = Function(self.V1)
  86. w = TestFunction(self.Q1)
  87. u.vector()[:] = 0.5
  88. facetareas = assemble(u*w*dx).array().sum()
  89. self.assertAlmostEqual(facetareas, 2.0)
  90. u = Function(self.V2)
  91. w = TestFunction(self.Q2)
  92. u.vector()[:] = 0.5
  93. a = u*w*dx
  94. b = assemble(a)
  95. facetareas = assemble(u*w*dx).array().sum()
  96. self.assertAlmostEqual(facetareas, 3.0)
  97. mesh = UnitSquareMesh(8, 8)
  98. bdry = BoundaryMesh(mesh, "exterior")
  99. V = FunctionSpace(mesh, "CG", 1)
  100. u = TrialFunction(V)
  101. v = TestFunction(V)
  102. BV = FunctionSpace(bdry, "CG", 1)
  103. bu = TrialFunction(BV)
  104. bv = TestFunction(BV)
  105. a = assemble(inner(u, v)*ds).array().sum()
  106. b = assemble(inner(bu, bv)*dx).array().sum()
  107. self.assertAlmostEqual(a, b)
  108. def test_assemble_bilinear_1D_2D(self):
  109. # Boundary mesh not running in parallel
  110. if MPI.num_processes() > 1:
  111. return
  112. V = FunctionSpace(self.square, 'CG', 1)
  113. u = TrialFunction(V)
  114. v = TestFunction(V)
  115. bu = TrialFunction(self.V1)
  116. bv = TestFunction(self.V1)
  117. a = assemble(inner(u, v)*ds).array().sum()
  118. b = assemble(inner(bu, bv)*dx).array().sum()
  119. self.assertAlmostEqual(a, b)
  120. bottom = compile_subdomains("near(x[1], 0.0)")
  121. foo = abs(assemble(inner(grad(u)[0], grad(v)[0])*ds(0),
  122. exterior_facet_domains=bottom).array()).sum()
  123. BV = FunctionSpace(SubMesh(self.mesh1, bottom), "CG", 1)
  124. bu = TrialFunction(BV)
  125. bv = TestFunction(BV)
  126. bar = abs(assemble(inner(grad(bu), grad(bv))*dx).array()).sum()
  127. self.assertAlmostEqual(bar, foo)
  128. def test_assemble_bilinear_2D_3D(self):
  129. # Boundary mesh not running in parallel
  130. if MPI.num_processes() > 1:
  131. return
  132. V = FunctionSpace(self.cube, 'CG', 1)
  133. u = TrialFunction(V)
  134. v = TestFunction(V)
  135. bu = TrialFunction(self.V2)
  136. bv = TestFunction(self.V2)
  137. a = assemble(inner(u, v)*ds).array().sum()
  138. b = assemble(inner(bu, bv)*dx).array().sum()
  139. self.assertAlmostEqual(a, b)
  140. bottom = compile_subdomains("near(x[1], 0.0)")
  141. foo = abs(assemble(inner(grad(u)[0], grad(v)[0])*ds(0),
  142. exterior_facet_domains=bottom).array()).sum()
  143. BV = FunctionSpace(SubMesh(self.mesh1, bottom), "CG", 1)
  144. bu = TrialFunction(BV)
  145. bv = TestFunction(BV)
  146. bar = abs(assemble(inner(grad(bu), grad(bv))*dx).array()).sum()
  147. self.assertAlmostEqual(bar, foo)
  148. class FormTestsOverFunnySpaces(unittest.TestCase):
  149. def setUp(self):
  150. # Boundary mesh not running in parallel
  151. if MPI.num_processes() > 1:
  152. return
  153. # Set-up meshes
  154. n = 16
  155. plane = compile_subdomains("near(x[1], 1.0)")
  156. self.square = UnitSquareMesh(n, n)
  157. self.square3d = SubMesh(BoundaryMesh(UnitCubeMesh(n, n, n), "exterior"), plane)
  158. # Define global normal and create orientation map
  159. global_normal = Expression(("0.0", "1.0", "0.0"))
  160. self.square3d.init_cell_orientations(global_normal)
  161. self.CG2 = VectorFunctionSpace(self.square, "CG", 1)
  162. self.CG3 = VectorFunctionSpace(self.square3d, "CG", 1)
  163. self.RT2 = FunctionSpace(self.square, "RT", 1)
  164. self.RT3 = FunctionSpace(self.square3d, "RT", 1)
  165. self.DG2 = FunctionSpace(self.square, "DG", 0)
  166. self.DG3 = FunctionSpace(self.square3d, "DG", 0)
  167. self.W2 = self.RT2*self.DG2
  168. self.W3 = self.RT3*self.DG3
  169. def test_basic_rt(self):
  170. # Boundary mesh not running in parallel
  171. if MPI.num_processes() > 1:
  172. return
  173. f2 = Expression(("2.0", "1.0"))
  174. f3 = Expression(("1.0", "0.0", "2.0"))
  175. u2 = TrialFunction(self.RT2)
  176. u3 = TrialFunction(self.RT3)
  177. v2 = TestFunction(self.RT2)
  178. v3 = TestFunction(self.RT3)
  179. # Project
  180. pw2 = project(f2, self.RT2)
  181. pw3 = project(f3, self.RT3)
  182. pa2 = assemble(inner(pw2, pw2)*dx)
  183. pa3 = assemble(inner(pw3, pw3)*dx)
  184. # Project explicitly
  185. a2 = inner(u2, v2)*dx
  186. a3 = inner(u3, v3)*dx
  187. L2 = inner(f2, v2)*dx
  188. L3 = inner(f3, v3)*dx
  189. w2 = Function(self.RT2)
  190. w3 = Function(self.RT3)
  191. A2 = assemble(a2)
  192. b2 = assemble(L2)
  193. A3 = assemble(a3)
  194. b3 = assemble(L3)
  195. solve(A2, w2.vector(), b2)
  196. solve(A3, w3.vector(), b3)
  197. a2 = assemble(inner(w2, w2)*dx)
  198. a3 = assemble(inner(w3, w3)*dx)
  199. # Compare various results
  200. self.assertAlmostEqual((w2.vector() - pw2.vector()).norm("l2"), 0.0,
  201. places=6)
  202. self.assertAlmostEqual(a3, 5.0)
  203. self.assertAlmostEqual(a2, a3)
  204. self.assertAlmostEqual(pa2, a2)
  205. self.assertAlmostEqual(pa2, pa3)
  206. def test_mixed_poisson_solve(self):
  207. # Boundary mesh not running in parallel
  208. if MPI.num_processes() > 1:
  209. return
  210. f = Constant(1.0)
  211. # Solve mixed Poisson on standard unit square
  212. (sigma2, u2) = TrialFunctions(self.W2)
  213. (tau2, v2) = TestFunctions(self.W2)
  214. a = (inner(sigma2, tau2) + div(tau2)*u2 + div(sigma2)*v2)*dx
  215. L = f*v2*dx
  216. w2 = Function(self.W2)
  217. solve(a == L, w2)
  218. # Solve mixed Poisson on unit square in 3D
  219. (sigma3, u3) = TrialFunctions(self.W3)
  220. (tau3, v3) = TestFunctions(self.W3)
  221. a = (inner(sigma3, tau3) + div(tau3)*u3 + div(sigma3)*v3)*dx
  222. L = f*v3*dx
  223. w3 = Function(self.W3)
  224. solve(a == L, w3)
  225. # Check that results are about the same
  226. self.assertAlmostEqual(assemble(inner(w2, w2)*dx),
  227. assemble(inner(w3, w3)*dx))
  228. class TestGeometricQuantitiesOverManifolds(unittest.TestCase):
  229. def setUp(self):
  230. # Boundary mesh not running in parallel
  231. if MPI.num_processes() > 1:
  232. return
  233. m = 3
  234. self.m = m
  235. plane = compile_subdomains("near(x[1], 0.0)")
  236. self.mesh1 = BoundaryMesh(UnitSquareMesh(m, m), "exterior")
  237. self.bottom1 = SubMesh(self.mesh1, plane)
  238. self.mesh2 = BoundaryMesh(UnitCubeMesh(m, m, m), "exterior")
  239. self.bottom2 = SubMesh(self.mesh2, plane)
  240. line = compile_subdomains("near(x[0], 0.0)")
  241. self.mesh3 = BoundaryMesh(SubMesh(self.mesh2, plane), "exterior")
  242. self.bottom3 = SubMesh(self.mesh3, line)
  243. def test_normals_2D_1D(self):
  244. # Boundary mesh not running in parallel
  245. if MPI.num_processes() > 1:
  246. return
  247. "Testing assembly of normals for 1D meshes embedded in 2D"
  248. n = ufl.Cell("interval", geometric_dimension=2).n
  249. a = inner(n, n)*ds
  250. value_bottom1 = assemble(a, mesh=self.bottom1)
  251. self.assertAlmostEqual(value_bottom1, 2.0)
  252. b = inner(n('+'), n('+'))*dS
  253. b1 = assemble(b, mesh=self.bottom1)
  254. c = inner(n('+'), n('-'))*dS
  255. c1 = assemble(c, mesh=self.bottom1)
  256. self.assertAlmostEqual(b1, self.m-1)
  257. self.assertAlmostEqual(c1, - b1)
  258. def test_normals_3D_1D(self):
  259. "Testing assembly of normals for 1D meshes embedded in 3D"
  260. # Boundary mesh not running in parallel
  261. if MPI.num_processes() > 1:
  262. return
  263. n = ufl.Cell("interval", geometric_dimension=3).n
  264. a = inner(n, n)*ds
  265. v1 = assemble(a, mesh=self.bottom3)
  266. self.assertAlmostEqual(v1, 2.0)
  267. b = inner(n('+'), n('+'))*dS
  268. b1 = assemble(b, mesh=self.bottom3)
  269. c = inner(n('+'), n('-'))*dS
  270. c1 = assemble(c, mesh=self.bottom3)
  271. self.assertAlmostEqual(b1, self.m-1)
  272. self.assertAlmostEqual(c1, - b1)
  273. def test_normals_3D_2D(self):
  274. "Testing assembly of normals for 2D meshes embedded in 3D"
  275. # Boundary mesh not running in parallel
  276. if MPI.num_processes() > 1:
  277. return
  278. n = ufl.Cell("triangle", geometric_dimension=3).n
  279. a = inner(n, n)*ds
  280. v1 = assemble(a, mesh=self.bottom2)
  281. self.assertAlmostEqual(v1, 4.0)
  282. b = inner(n('+'), n('+'))*dS
  283. b1 = assemble(b, mesh=self.bottom2)
  284. c = inner(n('+'), n('-'))*dS
  285. c1 = assemble(c, mesh=self.bottom2)
  286. self.assertAlmostEqual(c1, - b1)
  287. def test_cell_volume(self):
  288. "Testing assembly of volume for embedded meshes"
  289. # Boundary mesh not running in parallel
  290. if MPI.num_processes() > 1:
  291. return
  292. volume = ufl.Cell("interval", geometric_dimension=2).volume
  293. a = volume*dx
  294. b = assemble(a, mesh=self.bottom1)
  295. self.assertAlmostEqual(b, 1.0/self.m)
  296. volume = ufl.Cell("interval", geometric_dimension=3).volume
  297. a = volume*dx
  298. b = assemble(a, mesh=self.bottom3)
  299. self.assertAlmostEqual(b, 1.0/self.m)
  300. volume = ufl.Cell("triangle", geometric_dimension=3).volume
  301. a = volume*dx
  302. b = assemble(a, mesh=self.bottom2)
  303. self.assertAlmostEqual(b, 1.0/(2*self.m*self.m))
  304. def test_circumradius(self):
  305. "Testing assembly of circumradius for embedded meshes"
  306. # Boundary mesh not running in parallel
  307. if MPI.num_processes() > 1:
  308. return
  309. r = ufl.Cell("interval", geometric_dimension=2).circumradius
  310. a = r*dx
  311. b = assemble(a, mesh=self.bottom1)
  312. self.assertAlmostEqual(b, 0.5*(1.0/self.m))
  313. r = ufl.Cell("interval", geometric_dimension=3).circumradius
  314. a = r*dx
  315. b = assemble(a, mesh=self.bottom3)
  316. self.assertAlmostEqual(b, 0.5*(1.0/self.m))
  317. r = ufl.Cell("triangle", geometric_dimension=2).circumradius
  318. a = r*dx
  319. b0 = assemble(a, mesh=UnitSquareMesh(self.m, self.m))
  320. r = ufl.Cell("triangle", geometric_dimension=3).circumradius
  321. a = r*dx
  322. b1 = assemble(a, mesh=self.bottom2)
  323. self.assertAlmostEqual(b0, b1)
  324. def test_facetarea(self):
  325. "Testing assembly of facet area for embedded meshes"
  326. # Boundary mesh not running in parallel
  327. if MPI.num_processes() > 1:
  328. return
  329. area = ufl.Cell("interval", geometric_dimension=2).facet_area
  330. a = area*ds
  331. b = assemble(a, mesh=self.bottom1)
  332. self.assertAlmostEqual(b, 2.0)
  333. area = ufl.Cell("interval", geometric_dimension=3).facet_area
  334. a = area*ds
  335. b = assemble(a, mesh=self.bottom3)
  336. self.assertAlmostEqual(b, 2.0)
  337. area = ufl.Cell("triangle", geometric_dimension=2).facet_area
  338. a = area*ds
  339. b0 = assemble(a, mesh=UnitSquareMesh(self.m, self.m))
  340. area = ufl.Cell("triangle", geometric_dimension=3).facet_area
  341. a = area*ds
  342. b1 = assemble(a, mesh=self.bottom2)
  343. self.assertAlmostEqual(b0, b1)
  344. if __name__ == "__main__":
  345. print ""
  346. print "Testing PyDOLFIN Form operations"
  347. print "------------------------------------------------"
  348. unittest.main()