Advertisement
bartekltg

fenics python perm

Oct 19th, 2017
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.86 KB | None | 0 0
  1.     from fenics import*
  2.     from mshr import*
  3.     from math import pi, sin, cos, tan, pi, fabs, sqrt
  4.     import numpy
  5.    
  6.    
  7. def gowniejsza_funkcja(alpha):
  8.    
  9.        
  10.     # Angle of bypass
  11.     # alpha = pi/4
  12.     # Kinematic viscosity
  13.     nu = 1.0
  14.     # Radius of blood vessel
  15.     r1 = 1.5
  16.     # Radius of bypass
  17.     r2 = 0.5
  18.     # Length of blood vessel
  19.     l1 = 10
  20.     # Length of bypass
  21.     l2 = 6
  22.     # Left boundary of subdomain
  23.     d1 = -4.5
  24.     # Right boundary of subdomain
  25.     d2 = 4.5
  26.    
  27.     def dimensions(alpha):
  28.             # Check if dimensions of cylinders are correct
  29.             condition0 = (alpha < pi/2)
  30.             condition1 = (cos(alpha)*r2 < r1)
  31.             condition2 = (tan(alpha)*l1/2 > r1)
  32.             if (condition0) and (condition1) and (condition2):
  33.                     print 'Dimensions of cylinders are correct'
  34.             else:
  35.                     print 'Dimensions of cylinders are incorrect'
  36.    
  37.             # Check if dimensions of subdomain are correct
  38.             condition4 = (-l1/2 < d1) and (-r1/tan(alpha) - r2/sin(alpha) > d1)
  39.             condition5 = (l1/2 > d2) and (-r1/tan(alpha) + r2/sin(alpha) < d2)
  40.             if (condition4) and (condition5):
  41.                     print 'Dimensions of subdomain are correct'
  42.             else:
  43.                     print 'Dimensions of subdomain are incorrect'
  44.             return
  45.    
  46.     # Generate domain
  47.     def domain(alpha):
  48.         C1 = Rectangle(Point(-l1/2, -r1), Point(l1/2, r1))
  49.         C2 = Rectangle(Point(-l2, -r2), Point(0.0, r2))
  50.         C2_alpha = CSGRotation(C2, Point(0.0, 0.0), -alpha)
  51.         return C1 + C2_alpha
  52.    
  53.     # Define left blood vessel boundary
  54.     class Left(SubDomain):
  55.         def inside(self, x, on_boundary):
  56.             return ((x[0] + l1/2) < DOLFIN_EPS) and on_boundary
  57.     # Define right blood vessel boundary
  58.     class Right(SubDomain):
  59.         def inside(self, x, on_boundary):
  60.             return ((x[0] - l1/2) < DOLFIN_EPS) and on_boundary
  61.     # Define upper bypass boundary
  62.     class Bypass(SubDomain):
  63.         def inside(self, x, on_boundary):
  64.             return (((fabs(x[0]/tan(alpha) - x[1] + (cos(alpha)*l2)/tan(alpha) + \
  65.             sin(alpha)*l2))/sqrt((1/tan(alpha))**2 + 1)) < DOLFIN_EPS) \
  66.             and on_boundary
  67.     # Define bypass inflow subdomain
  68.     class Interior(SubDomain):
  69.         def inside(self, x, on_boundary):
  70.             return between(x[0], (d1, d2)) and between(x[1], (-r1, r1))
  71.    
  72.    
  73.     # Initialize sub-domain instances
  74.     left = Left()
  75.     right = Right()
  76.     bypass = Bypass()
  77.     interior = Interior()
  78.    
  79.     # Generate mesh
  80.     mesh = generate_mesh(domain(alpha), 32)
  81.    
  82.     # Mark domains
  83.     domains = CellFunction('size_t', mesh)
  84.     domains.set_all(0)
  85.    
  86.     # Mark boundaries
  87.     boundaries = FacetFunction('size_t', mesh)
  88.     boundaries.set_all(0)
  89.     left.mark(boundaries, 1)
  90.     right.mark(boundaries, 1)
  91.     bypass.mark(boundaries, 1)
  92.    
  93.     # Define function spaces
  94.     W2 = VectorElement('Lagrange', mesh.ufl_cell(), 2)
  95.     V2 = FunctionSpace(mesh, W2)
  96.     W1 = FiniteElement('Lagrange', mesh.ufl_cell(), 1)
  97.     V1 = FunctionSpace(mesh, W1)
  98.     W = W2 * W1
  99.     V = FunctionSpace(mesh, W)
  100.    
  101.     # Define (u1, p1) and f1
  102.     def u1():
  103.         u0 = Expression(('2*x[0]*x[1]', '-x[1]*x[1]'), degree = 2)
  104.         return interpolate(u0, V2)
  105.     def p1():
  106.         p0 = Expression('x[0] + x[1]', degree = 1)
  107.         return interpolate(p0, V1)
  108.     def f1(NS):
  109.         f = Expression(('NS*(-sin(2*x[0])*cos(x[0])*cos(x[0]) + \
  110.        2*x[1]*x[1]*cos(2*x[0])*sin(2*x[0])) + cos(x[0]) + \
  111.        nu*(2*cos(2*x[0]))', 'NS*(sin(2*x[0])*sin(2*x[0])*x[1]) + \
  112.        nu*(4*x[1]*sin(2*x[0])) + sin(x[1])'), degree = 2, nu = nu, NS = NS)
  113.         return interpolate(f, V2)
  114.    
  115.     # Define (u2, p2) and f2
  116.     def u2():
  117.         u0 = Expression(('cos(x[0])*cos(x[0])', 'x[1]*sin(2*x[0])'), degree = 2)
  118.         return interpolate(u0, V2)
  119.     def p2():
  120.         p0 = Expression('sin(x[0]) + cos(x[1])', degree = 1)
  121.         return interpolate(p0, V1)
  122.     def f2(NS):
  123.         f = Expression(('NS*(4*x[0]*x[1]*x[1]) + 1', 'NS*(4*x[0]*x[0]*x[1] \
  124.        + 2*x[1]*x[1]*x[1]) + 2*nu + 1'), degree = 2, nu = nu, NS = NS)
  125.         return interpolate(f, V2)
  126.    
  127.     # Define Neumann boundaries
  128.     def neumann_conditions(u_bc, p_bc):
  129.             n = FacetNormal(mesh)
  130.             I = Identity(mesh.geometry().dim())
  131.             return (Constant(nu)*grad(u_bc) - p_bc*I)*n
  132.     g = neumann_conditions(u1(), p1())
  133.    
  134.     # Define Dirichlet boundaries
  135.     def dirichlet_conditions(u_bc, p_bc):
  136.             b_u0 = DirichletBC(V.sub(0), u_bc, boundaries, 0)
  137.             b_p0 = DirichletBC(V.sub(1), p_bc, boundaries, 0)
  138.             return [b_u0, b_p0]
  139.     bcs  = dirichlet_conditions(u1(), p1())
  140.    
  141.     # Define measures
  142.     dx = Measure('dx', domain = mesh, subdomain_data = domains)
  143.     ds = Measure('ds', domain = mesh, subdomain_data = boundaries)
  144.    
  145.     def navier_stokes(f, bc, NS):
  146.             # Define variational forms for Stationary Navier-Stokes
  147.             def A(u_h, v_h):
  148.                     return Constant(nu)*inner(grad(u_h), grad(v_h))*dx(0)
  149.             def B(p_h, v_h):
  150.                     return p_h*div(v_h)*dx(0)
  151.             def C(u_h, w_h, v_h):
  152.                     return inner(grad(u_h)*w_h, v_h)*dx(0)
  153.             def L(v_h):
  154.                     return inner(f, v_h)*dx(0)
  155.             def S(v_h):
  156.                     return inner(g, v_h)*ds(1)
  157.    
  158.             # Define variational problem
  159.             U = TrialFunction(V)
  160.             (u, p) = split(U)
  161.             (v, q) = TestFunctions(V)
  162.             U_ = Function(V)
  163.             (u_, p_) = split(U_)
  164.             F = A(u, v) - B(p, v) + bool(NS)*C(u, u, v) - B(q, u) - L(v) - S(v)
  165.             F = action(F, U_)
  166.             J = derivative(F, U_, U)
  167.             problem = NonlinearVariationalProblem(F, U_, bc, J)
  168.    
  169.             # Create Newton solver
  170.             solver = NonlinearVariationalSolver(problem)
  171.             solver.parameters.newton_solver['absolute_tolerance'] = 1E-8
  172.             solver.parameters.newton_solver['relative_tolerance'] = 1E-7
  173.             solver.parameters.newton_solver['maximum_iterations'] = 25
  174.             solver.parameters.newton_solver['relaxation_parameter'] = 1.0
  175.             solver.parameters.newton_solver['linear_solver'] = 'gmres'
  176.             solver.parameters.newton_solver['preconditioner'] = 'ilu'
  177.             solver.parameters.newton_solver.krylov_solver['absolute_tolerance'] = 1E-9
  178.             solver.parameters.newton_solver.krylov_solver['relative_tolerance'] = 1E-7
  179.             solver.parameters.newton_solver.krylov_solver['maximum_iterations'] = 1000
  180.             solver.parameters.newton_solver.krylov_solver['monitor_convergence'] = True
  181.             solver.parameters.newton_solver.krylov_solver['nonzero_initial_guess'] = False
  182.    
  183.             # Monitor solution
  184.             PROGRESS = 16
  185.             set_log_level(PROGRESS)
  186.             info(solver.parameters.newton_solver, True)
  187.    
  188.             # Solve
  189.             solver.solve()
  190.    
  191.             return U_
  192.    
  193.     # Call navier-stokes and get sub-functions
  194.     U_s = navier_stokes(f1(0), bcs, 0)
  195.     (u_s, p_s) = U_s.split(U_s)
  196.     U_ns = navier_stokes(f1(1), bcs, 1)
  197.     (u_ns, p_ns) = U_ns.split(U_ns)
  198.    
  199.     # Compute error parameters
  200.     def errors(u0_V, u0, p0_V, p0):
  201.             u_max = numpy.abs(u0.vector().array()).max()
  202.             print 'Maximum norm of velocity: ', u_max
  203.             E_u_max = numpy.abs(u0_V.vector().array() - u0.vector().array()).max()
  204.             print 'Maximum error for velocity: ', E_u_max
  205.             u_L2 = norm(u0, norm_type = 'L2')
  206.             print 'L2 norm of velocity: ', u_L2
  207.             E_u_L2 = errornorm(u0_V, u0, norm_type = 'L2', degree_rise = 1)
  208.             print 'L2 norm of error for velocity: ', E_u_L2
  209.             p_max = numpy.abs(p0.vector().array()).max()
  210.             print 'Maximum error of pressure: ', p_max
  211.             E_p_max = numpy.abs(p0_V.vector().array() - p0.vector().array()).max()
  212.             print 'Maximum error for pressure: ', E_p_max
  213.             u_L2 = norm(p0, norm_type = 'L2')
  214.             print 'L2 norm of pressure: ', u_L2
  215.             E_p_L2 = errornorm(p0_V, p0, norm_type = 'L2', degree_rise = 1)
  216.             print 'L2 norm of error for pressure: ', E_p_L2
  217.             div_u = assemble(abs(div(u0))*dx(0))
  218.             print 'L2 norm of divergence of velocity : ', div_u
  219.             return
  220.     print 'Error parameters for Stokes: '
  221.     errors(u1(), u_s, p1(), p_s)
  222.     print 'Error parameters for Navier-Stokes: '
  223.     errors(u1(), u_ns, p1(), p_ns)
  224.    
  225.     # Mark sudomain
  226.     interior.mark(domains, 1)
  227.    
  228.     # Define cost functionals
  229.     def functionals(g1, g2):
  230.         # Viscious energy dissipation
  231.         J_1 = nu/2*assemble(abs(inner(grad(g1), grad(g1)))*dx(1))
  232.         print 'Viscious energy dissipation: ', J_1
  233.    
  234.         # Stokes-tracking type functional
  235.         J_2 = assemble(abs(inner(g1 - g2, g1 - g2))*dx(1))
  236.         print 'Stokes-tracking type functional: ', J_2
  237.    
  238.         # Vorticity
  239.         rot = grad(g1)[1,0] - grad(g1)[0,1]
  240.         J_3 = nu/2*assemble(abs(inner(rot, rot))*dx(1))
  241.         print 'Vorticity: ', J_3
  242.    
  243.         # Galilean vortex
  244.         J_4 = 1/2*assemble((det(grad(g1)) + abs(det(grad(g1))))*dx(1))
  245.         print 'Galilean vortex: ', J_4
  246.         return [J_1, J_2, J_3, J_4]
  247.    
  248.     print 'Evaluation of cost functionals: '
  249.     J = functionals(u_ns, u_s)
  250.    
  251.     # Save solution in VTK format
  252.     ufile_pvd = File('Solutions/Stokes/Velocity.pvd')
  253.     ufile_pvd << u_s
  254.     pfile_pvd = File('Solutions/Stokes/Pressure.pvd')
  255.     pfile_pvd << p_s
  256.     ufile_pvd = File('Solutions/Navier-Stokes/Velocity.pvd')
  257.     ufile_pvd << u_ns
  258.     pfile_pvd = File('Solutions/Navier-Stokes/Pressure.pvd')
  259.     pfile_pvd << p_ns
  260.    
  261.    
  262. gowniejsza_funkcja(pi/4)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement