heatconv.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. """Heat equation in moving media."""
  2. # Credits: Jan Blechta
  3. # https://github.com/blechta/fenics-handson/blob/master/heatconv
  4. from dolfin import *
  5. set_log_level(30)
  6. # Create mesh and build function space
  7. mesh = UnitSquareMesh(30, 30, "crossed")
  8. V = FunctionSpace(mesh, "Lagrange", 1)
  9. # Create boundary markers
  10. tdim = mesh.topology().dim()
  11. boundary_parts = MeshFunction("size_t", mesh, tdim - 1)
  12. left = AutoSubDomain(lambda x: near(x[0], 0.0))
  13. right = AutoSubDomain(lambda x: near(x[0], 1.0))
  14. bottom = AutoSubDomain(lambda x: near(x[1], 0.0))
  15. left.mark(boundary_parts, 1)
  16. right.mark(boundary_parts, 2)
  17. bottom.mark(boundary_parts, 2)
  18. # Initial condition and right-hand side
  19. ic = Expression("""pow(x[0] - 0.25, 2) + pow(x[1] - 0.25, 2) < 0.2*0.2
  20. ? -25.0 * ((pow(x[0] - 0.25, 2) + pow(x[1] - 0.25, 2)) - 0.2*0.2)
  21. : 0.0""", degree=1,
  22. )
  23. f = Expression("""pow(x[0] - 0.75, 2) + pow(x[1] - 0.75, 2) < 0.2*0.2
  24. ? 1.0
  25. : 0.0""", degree=1,
  26. )
  27. # Equation coefficients
  28. K = Constant(1e-2) # thermal conductivity
  29. g = Constant(0.01) # Neumann heat flux
  30. b = Expression(("-(x[1] - 0.5)", "x[0] - 0.5"), degree=1) # convecting velocity
  31. # Define boundary measure on Neumann part of boundary
  32. dsN = Measure("ds", subdomain_id=1, subdomain_data=boundary_parts)
  33. # Define steady part of the equation
  34. def operator(u, v):
  35. return (K * inner(grad(u), grad(v)) - f * v + dot(b, grad(u)) * v
  36. ) * dx - K * g * v * dsN
  37. # Define trial and test function and solution at previous time-step
  38. u = TrialFunction(V)
  39. v = TestFunction(V)
  40. u0 = Function(V)
  41. # Time-stepping parameters
  42. dt = 0.02
  43. theta = Constant(0.5) # Crank-Nicolson scheme
  44. # Define time discretized equation
  45. F = ((1.0 / dt) * inner(u - u0, v) * dx
  46. + theta * operator(u, v)
  47. + (1.0 - theta) * operator(u0, v)
  48. )
  49. # Define boundary condition
  50. bc = DirichletBC(V, Constant(0.0), boundary_parts, 2)
  51. # Prepare solution function and solver
  52. u = Function(V)
  53. problem = LinearVariationalProblem(lhs(F), rhs(F), u, bc)
  54. solver = LinearVariationalSolver(problem)
  55. # Prepare initial condition
  56. u0.interpolate(ic)
  57. u.interpolate(ic)
  58. ######################################################Time-stepping
  59. from vedo.dolfin import plot
  60. t = 0.0
  61. while t < 3:
  62. solver.solve()
  63. plot(u,
  64. text=__doc__+"\nTemperature at t = %g" % t,
  65. style=2,
  66. axes=3,
  67. lw=0, # no mesh edge lines
  68. warp_zfactor=0.1,
  69. isolines={"n": 12, "lw":1, "c":'black', "alpha":0.1},
  70. scalarbar=False,
  71. interactive=False,
  72. ).clear()
  73. # Move to next time step
  74. u0.assign(u)
  75. t += dt