def dirichlet_ex5(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ Dirichlet bc in 1D seems to work for P1, P2 and P3, but not correct conv rates due to very small errors """ print "\nDirichlet ex5 in 1D" # data mesh = UnitIntMesh(n) f = 8. u_ex = lambda x: 4. * x[0] * (1. - x[0]) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) # solve bc = Dirichlet(fs) u = fem_solver(fs, A, rhs, bc) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def dirichlet_ex2(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ Dirichlet bc in 2D - P1 conv rate: ~2 - P2 conv rate: ~8 - P3 conv rate: ~.5 (not working) """ print "\nDirichlet ex2 in 2D" # data mesh = UnitSquareMesh(n, n, diag=diag) f = lambda x: -6 * x[0] * x[1] * (1. - x[1]) + 2 * pow(x[0], 3) g = lambda x: x[1] * (1. - x[1]) u_ex = lambda x: x[1] * (1. - x[1]) * pow(x[0], 3) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) bc1 = Dirichlet(fs, 0, 'bottom', 'top', 'left') bc2 = Dirichlet(fs, g, 'right') # solve u = fem_solver(fs, A, rhs, [bc1, bc2]) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def mixed_ex1(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ mixed bc in 1D seems to work for P1, P2 and P3, but not correct conv rates due to very small errors """ print "\nMixed bc example in 1D" # data mesh = UnitIntMesh(n) d = 1 c = 1 u_ex = lambda x: 1. - x[0]**2 + d + c * (x[0] - 1.) f = 2 # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) rhs[0] -= c # Neuman on left boundary right_bc = Dirichlet(fs, d, 'right') # Dirichlet on right boundary # solve u = fem_solver(fs, A, rhs, right_bc) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def dirichlet_ex1(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ homogenous Dirichlet bc in 2D - P1 conv rate: ~2 - P2 conv rate: ~8 - P3 conv rate: ~.5 (not working) """ print "\nDirichlet ex1 in 2D" # data mesh = UnitSquareMesh(n, n, diag=diag) f = lambda x: 32. * (x[1] * (1. - x[1]) + x[0] * (1. - x[0])) u_ex = lambda x: 16. * x[0] * (1. - x[0]) * x[1] * (1. - x[1]) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) # solve w/ homogenous Dirichlet bc bc = Dirichlet(fs) u = fem_solver(fs, A, rhs, bc) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def mixed_test(): """ Poisson problem 2D test with Neuman bc enforced by Lagrange multiplier, using mixed P1-P0 elements: ------------------------------------------------------------------ find (u,c) such that (grad u, grad v) + (c,v) = (f,v) + (g,v)_gamma, forall v (P1) (u,d) = 0, forall d (P0) ------------------------------------------------------------------ """ g = lambda x: -math.sin(math.pi * x[0]) # Neuman bc f = lambda x: 10 * math.exp(-(pow(x[0] - .5, 2) + pow(x[1] - .5, 2)) / .02) # right hand side mesh = UnitSquareMesh(32, 32) # mesh me = FiniteElement('lagrange', 1) * FiniteElement('lagrange', 0) # mixed element fs = FunctionSpace(mesh, me, gauss=4) # mixed space Auu = fs.stiffness() # u stiffness matrix Auc = fs.assemble(derivative=[False, False], n=0, m=1) # mixed mass matrix rhs_u = fs.rhs(f) + fs.assemble_boundary(g) # right hand side for u n = fs.n_nodes(0) m = fs.n_nodes(1) n_nodes = n + m print "n = {} (Solution), m = {} (Lagrange)".format(n, m) print "Auu: ", Auu.shape print "Auc: ", Auc.shape # assemble global linear system A = np.zeros((n_nodes, n_nodes)) A[:n, :n] = Auu A[:n, n:] = Auc A[n:, :n] = Auc.T rhs = np.zeros(n_nodes) rhs[:n] = rhs_u u, c = fem_solver(fs, A, rhs, CG=True) print "u: ", u.shape print "c: ", c.shape plot_sol(u, fs.node_to_coords(0), contour=True, name='Solution') plot_sol(c, fs.node_to_coords(1), contour=True, name='Lagrange')
def assemble_boundary(self, g, *args): """ assemble over boundary in case of Neuman boundary conditions (only for 2D space) Input: g - function (or constant) to be integrated with shape functions over boundary args: (optional) m (int) - if mixed space, gives number of FE (default: 0) names (strings) - names for boundary dictionary (default: entire boundary) Output: array that can be added to RHS vector to incorporate Neuman boundary conditions """ assert self.__dim == 2, 'Edge integration only for 2D function space.' # check args input if len(args) == 0: m = 0 names = [] elif isinstance(args[0], int): m = args[0] names = [args[k] for k in range(1, len(args))] else: m = 0 names = args # get boundary data edge_to_nodes = self.belt_to_nodes(m, *names) edge_to_vcoords = self.edge_to_vcoords(*names) # assemble boundary fe = FiniteElement(self.__method[m], self.__deg[m]) fe.initialize(1) b = np.zeros(self.n_nodes(m)) for n in xrange(len(edge_to_nodes)): fe.set_vertices(edge_to_vcoords[n]) b[edge_to_nodes[n]] += fe.rhs(g, self.__gauss, m) return b
def poisson_test_1d(): """ Poisson problem 1D test with homogenous Dirichlet bc """ u_ex = lambda x: 4. * x[0] * (1. - x[0]) # exact solution f = 8. # right hand side mesh = UnitIntMesh(32) fs = FunctionSpace(mesh, FiniteElement('lagrange', 1), gauss=4) A = fs.stiffness() rhs = fs.rhs(f) bc = Dirichlet(fs) u = fem_solver(fs, A, rhs, bc) plot_sol(u, fs.node_to_coords(), u_ex)
def p0_test(): """ test with P0 element """ u_ex = lambda x: 16. * x[0] * (1. - x[0]) * x[1] * (1. - x[1] ) # exact solution mesh = UnitSquareMesh(16, 16) fs = FunctionSpace(mesh, FiniteElement('lagrange', 0), gauss=4) A = fs.mass() rhs = fs.rhs(u_ex) #u = spsolve(A,rhs) #bc = Dirichlet(fs) u = fem_solver(fs, A, rhs, bcs=bc) plot_sol(u, fs.node_to_coords(), u_ex)
def neuman_ex1(n=16, deg=1, plot=True, gauss=4, diag='right'): """ Poisson w/ Neuman bc in 2D ill conditioned -> use CG - P1 conv rate: ~2 - P2 conv rate: ~6 - P3 conv rate: ~.5 (not working)""" print "\nNeuman ex1 in 2D" # data mesh = UnitSquareMesh(n, n, diag=diag) c = 2 * math.pi f = lambda x: 2 * pow(c, 2) * math.sin(c * (x[0] + x[1])) u_ex = lambda x: math.sin(c * (x[0] + x[1])) g_bottom = lambda x: -c * math.cos(c * x[0]) g_right = lambda x: c * math.cos(c * (1. + x[1])) g_top = lambda x: c * math.cos(c * (1. + x[0])) g_left = lambda x: -c * math.cos(c * x[1]) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) bottom = fs.assemble_boundary(g_bottom, 'bottom') right = fs.assemble_boundary(g_right, 'right') top = fs.assemble_boundary(g_top, 'top') left = fs.assemble_boundary(g_left, 'left') rhs += bottom + right + top + left #solve u = fem_solver(fs, A, rhs, CG=True) # u, info = cg(A, rhs) # if info == 0: # print "CG convergence OK" # else: # print "failed to converge" nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def poisson_test_2d(): """ Poisson problem 2D test with homogenous Dirichlet bc """ u_ex = lambda x: 16. * x[0] * (1. - x[0]) * x[1] * (1. - x[1] ) # exact solution f = lambda x: 32. * (x[1] * (1. - x[1]) + x[0] * (1. - x[0])) # right hand side mesh = UnitSquareMesh(16, 16, diag='right') #mesh = Gmesh('Meshes/square_P2.msh') fs = FunctionSpace(mesh, FiniteElement('lagrange', deg=1), gauss=4) A = fs.stiffness() rhs = fs.rhs(f) bc = Dirichlet(fs) u = fem_solver(fs, A, rhs, bc) plot_sol(u, fs.node_to_coords(), u_ex)
def neuman_ex4(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ Neuman bc in 2D ill conditioned -> use CG - P1 conv rate: ~1.5 - P2 conv rate: ~1.1 - P3 conv rate: ~.5 (not working) """ print "\nNeuman ex4 in 2D" # data mesh = RegularMesh(box=[[0, math.pi], [0, math.pi]], res=[n, n], diag=diag) f = 0 u_ex = lambda x: math.cos(2 * x[0]) * math.cosh(2 * x[1]) / 200 g_top = lambda x: 2 * math.cos(2 * x[0]) * math.sinh(2 * math.pi) / 200 # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) top = fs.assemble_boundary(g_top, 'top') rhs += top # solve u = fem_solver(fs, A, rhs, CG=True) #u = spsolve(A, rhs) # u, info = cg(A,rhs) # if info == 0: # print "CG convergence OK" # else: # print "failed to converge" nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def dirichlet_ex4(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ Dirichlet bc in 2D - P1 conv rate: ~2 - P2 conv rate: ~8 - P3 conv rate: ~.5 (not working) """ print "\nDirichlet ex4 in 2D" # data mesh = RegularMesh(box=[[0, math.pi], [0, math.pi]], res=[n, n], diag=diag) f = 0 u_ex = lambda x: math.cosh(x[0]) * math.sin(x[1]) g_left = lambda x: math.sin(x[1]) g_right = lambda x: math.cosh(math.pi) * math.sin(x[1]) g_bottom = 0 g_top = 0 # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) bc_left = Dirichlet(fs, g_left, 'left') bc_right = Dirichlet(fs, g_right, 'right') bc_bottom = Dirichlet(fs, g_bottom, 'bottom') bc_top = Dirichlet(fs, g_top, 'top') # solve u = fem_solver(fs, A, rhs, [bc_left, bc_right, bc_bottom, bc_top]) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()
def neuman_ex3(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ homogenous Neuman bc in 2D ill conditioned -> use CG - P1 conv rate: ~2.3 - P2 conv rate: ~6 - P3 conv rate: ~.5 (not working)""" print "\nNeuman ex3 in 2D" # data mesh = UnitSquareMesh(n, n, diag=diag) pi = math.pi f = lambda x: pi * (math.cos(pi * x[0]) + math.cos(pi * x[1])) u_ex = lambda x: (math.cos(pi * x[0]) + math.cos(pi * x[1])) / pi # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) # solve u = fem_solver(fs, A, rhs, CG=True) # u, info = cg(A,rhs) # if info == 0: # print "CG convergence OK" # else: # print "failed to converge" nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) U_ex = [u_ex(node) for node in nodes] # return error and mesh size return norm(U_ex - u), mesh.mesh_size()
def mixed_ex2(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ mixed bc in 2D P1 conv rate: ~2.1 P2 conv rate: ~6 P3 conv rate: ~.5 (not working) """ print "\nMixed bc example in 2D" # data mesh = UnitSquareMesh(n, n, diag=diag) f = lambda x: 2 * (2 * pow(x[1], 3) - 3 * pow(x[1], 2) + 1.) - 6 * ( 1. - pow(x[0], 2)) * (2 * x[1] - 1.) g = lambda x: 2 * pow(x[1], 3) - 3 * pow(x[1], 2) + 1. u_ex = lambda x: (1. - pow(x[0], 2)) * (2 * pow(x[1], 3) - 3 * pow( x[1], 2) + 1.) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) bc1 = Dirichlet(fs, 0, 'right') bc2 = Dirichlet(fs, g, 'left') # solve (homogenous Neuman on top, bottom) u = fem_solver(fs, A, rhs, [bc1, bc2]) nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) U_ex = [u_ex(node) for node in nodes] # return error and mesh size return norm(U_ex - u), mesh.mesh_size()
def neuman_ex2(n=16, deg=1, plot=True, gauss=4, diag='right'): # <---------------------------- works """ Poisson w/ homogenous Neuman bc in 1D ill conditioned -> use CG - P1 conv rate: ~1.5 - P2 conv rate: ~1.5 - P3 conv rate: ~1.5 """ print "\nNeuman ex2 in 1D" # data mesh = UnitIntMesh(n) f = lambda x: pow(2 * math.pi, 2) * math.cos(2 * math.pi * x[0]) u_ex = lambda x: math.cos(2 * math.pi * x[0]) # assemble fs = FunctionSpace(mesh, FiniteElement('lagrange', deg), gauss) A = fs.stiffness() rhs = fs.rhs(f) # solve u = fem_solver(fs, A, rhs, CG=True) # u, info = cg(A, rhs) # if info == 0: # print "CG convergence OK" # else: # print "failed to converge" nodes = fs.node_to_coords() if plot: plot_sol(u, nodes, u_ex) # return error and mesh size U_ex = [u_ex(node) for node in nodes] return norm(U_ex - u), mesh.mesh_size()