def test_constructor(self): # # Define mesh, element, and dofhandler # mesh = QuadMesh(box=[0, 20, 0, 20], resolution=(20, 20), periodic={0, 1}) dim = mesh.dim() element = QuadFE(dim, 'Q2') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler, 'u') alph = 2 kppa = 1 # Symmetric tensor gma T + bta* vv^T gma = 0.1 bta = 25 p = lambda x: 10/np.pi*(0.75*np.sin(np.pi*x[:,0]/10)+\ 0.25*np.sin(np.pi*x[:,1]/10)) f = Nodal(f=p, basis=basis) fx = f.differentiate((1, 0)) fy = f.differentiate((1, 1)) #plot.contour(f) x = np.linspace(0, 20, 12) X, Y = np.meshgrid(x, x) xy = np.array([X.ravel(), Y.ravel()]).T U = fx.eval(xy).reshape(X.shape) V = fy.eval(xy).reshape(X.shape) v1 = lambda x: -0.25 * np.cos(np.pi * x[:, 1] / 10) v2 = lambda x: 0.75 * np.cos(np.pi * x[:, 0] / 10) U = v1(xy).reshape(X.shape) V = v2(xy).reshape(X.shape) #plt.quiver(X,Y, U, V) #plt.show() h11 = Explicit(lambda x: gma + bta * v1(x) * v1(x), dim=2) h12 = Explicit(lambda x: bta * v1(x) * v2(x), dim=2) h22 = Explicit(lambda x: gma + bta * v2(x) * v2(x), dim=2) tau = (h11, h12, h22) #tau = (Constant(2), Constant(1), Constant(1)) # # Define default elliptic field # u = EllipticField(dofhandler, kappa=1, tau=tau, gamma=2) Q = u.precision() v = Nodal(data=u.sample(mode='precision', decomposition='chol'), basis=basis) plot = Plot(20) plot.contour(v)
def test_eval(self): # # 1D # # Define Kernel function def k_fn(x,y,c = 2): return x*y + c k = Explicit(f=lambda x,y,c: x*y+c, parameters={'c':1}, n_variables=2, dim=1) # Construct kernel, specifying parameter c kernel = Kernel(k) # Evaluation points x = np.ones((11,1)) y = np.linspace(0,1,11)[:,None] # Check accuracy self.assertTrue(np.allclose(kernel.eval((x,y)), x*y+1)) # Define kernel with default parameters k.set_parameters({'c':2}) kernel = Kernel(k) # Check accuracy self.assertTrue(np.allclose(kernel.eval((x,y)), x*y+2))
def test_constructor(self): """ Test initialization """ f = Explicit(lambda x, a: a * x**2, parameters={'a': 1}, dim=1, n_variables=1) f.eval(1) self.assertAlmostEqual(f.eval(1), 1) # # Errors # self.assertRaises(Exception, Explicit)
def test_assemble_iiform(self): mesh = Mesh1D(resolution=(1, )) Q1 = QuadFE(1, 'DQ1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler, 'u') k = Explicit(lambda x, y: x * y, n_variables=2, dim=1) kernel = Kernel(k) form = IIForm(kernel, test=phi, trial=phi) assembler = Assembler(form, mesh) assembler.assemble() Ku = Nodal(lambda x: 1 / 3 * x, basis=phi) #af = assembler.af[0]['bilinear'] M = assembler.get_matrix().toarray() u = Nodal(lambda x: x, basis=phi) u_vec = u.data() self.assertTrue(np.allclose(M.dot(u_vec), Ku.data()))
def test_assemble_ipform(self): # ===================================================================== # Test 7: Assemble Kernel # ===================================================================== mesh = Mesh1D(resolution=(10, )) Q1 = QuadFE(1, 'DQ1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler, 'u') k = Explicit(lambda x, y: x * y, n_variables=2, dim=1) kernel = Kernel(k) form = IPForm(kernel, test=phi, trial=phi) assembler = Assembler(form, mesh) assembler.assemble() #af = assembler.af[0]['bilinear'] M = assembler.get_matrix().toarray() u = Nodal(lambda x: x, basis=phi) v = Nodal(lambda x: 1 - x, basis=phi) u_vec = u.data() v_vec = v.data() I = v_vec.T.dot(M.dot(u_vec)) self.assertAlmostEqual(I[0, 0], 1 / 18)
def test_add_rules(self): # Define explicit function rule = lambda x, a: a * x**2 parameters = [{'a': 1}, {'a': 2}] f = Explicit(rule, parameters=parameters, dim=1) # Raises an error attempt to add multiple functions self.assertRaises(Exception, f.add_rule, *(lambda x: x, ), **{'parameters': [{}, {}]}) # Add a single rule and evaluate at a point f.add_rule(lambda x: x) x = 2 vals = [4, 8, 2] for i in range(3): #(*(x,),**{'a':1})) self.assertEqual(f.eval(x)[0, i], vals[i])
def test_n_samples(self): # # 1D # # Define mesh mesh = Mesh1D(resolution=(10,)) # Define function f = Explicit([lambda x: x, lambda x: -2+2*x**2], dim=1) n_samples = f.n_samples() k = Kernel(f) n_points = 101 x0, x1 = mesh.bounding_box() x = np.linspace(x0,x1,n_points) self.assertEqual(k.eval(x).shape, (n_points, n_samples)) self.assertTrue(np.allclose(k.eval(x)[:,0],x)) self.assertTrue(np.allclose(k.eval(x)[:,1], -2+2*x**2))
def test_set_rules(self): # # Errors # # Number of parameter dicts differs from number of rules flist = [lambda x, a: a * x**2, lambda x: x] plist = [{}, {}, {}] self.assertRaises(Exception, Explicit, *(flist, ), **{ 'parameters': plist, 'dim': 1 }) # Specify that function is symmetric, but n_variables=1 f = lambda x: x self.assertRaises(Exception, Explicit, *(f, ), **{'symmetric': True}) # # Expected # # Only one set of parameters multiple functions f = Explicit(flist, parameters={}, dim=1) self.assertEqual(len(f.parameters()), 2) # Only one function multiple parameters rule = lambda x, a: a * x**2 parameters = [{'a': 1}, {'a': 2}] f = Explicit(rule, parameters=parameters, dim=1) self.assertEqual(len(f.rules()), 2)
def test_set_parameters(self): # Define explicit function rule = lambda x, a: a * x[:, 0] - x[:, 1] parms = [{'a': 1}, {'a': 2}] f = Explicit(rule, parameters=parms, dim=2) x = (1, 2) self.assertTrue(np.allclose(f.eval(x), np.array([-1, 0]))) # Modify parameter f.set_parameters({'a': 2}, pos=0) self.assertTrue(np.allclose(f.eval(x), np.array([0, 0])))
def test_eval_interpolation(self): # # 1D # # Mesh mesh = Mesh1D(resolution=(3, )) # Finite element space etype = 'Q1' element = QuadFE(1, etype) # Dofhandler dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions phi = Basis(dofhandler, 'u') # Symmetric kernel function kfns = { 'symmetric': lambda x, y: x * y, 'non_symmetric': lambda x, y: x - y } vals = { 'symmetric': np.array([0, 1 / 9 * (1 - 8 / 27)]), 'non_symmetric': np.array([1 / 3 * (-1 + 8 / 27), 1 / 6 * 5 / 9 - 1 / 3 * 19 / 27]) } for ktype in ['symmetric', 'non_symmetric']: # Get kernel function kfn = kfns[ktype] # Define integral kernel kernel = Kernel(Explicit(kfn, dim=1, n_variables=2)) # Define Bilinear Form form = IIForm(kernel, trial=phi, test=phi) # # Compute inputs required for evaluating form_loc # # Assembler assembler = Assembler(form, mesh) # Cells cj = mesh.cells.get_child(2) ci = mesh.cells.get_child(0) # Gauss nodes and weights on cell xj_g, wj_g, phij, dofsj = assembler.shape_eval(cj) # # Evaluate form # form_loc = form.eval(cj, xj_g, wj_g, phij, dofsj) # # Define functions # u = Nodal(lambda x: x, basis=phi) # # Get local node values # # Degrees of freedom cj_dofs = phi.dofs(cj) ci_dofs = phi.dofs(ci) uj = u.data()[np.array(cj_dofs)] # Evaluate Ici Icj k(x,y) y dy (1-x)dx fa = form_loc[ci_dofs].dot(uj) fe = vals[ktype][:, None] self.assertTrue(np.allclose(fa, fe))
def test_subsample_deterministic(self): """ When evaluating a deterministic function while specifying a subsample, n_subsample copies of the function output should be returned. """ # # Deterministic functions # # Functions fns = { 1: { 1: lambda x: x[:, 0]**2, 2: lambda x, y: x[:, 0] + y[:, 0] }, 2: { 1: lambda x: x[:, 0]**2 + x[:, 1]**2, 2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1] } } # Singletons x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}} xv = { 1: { 1: [(2, ), (2, )], 2: ([(3, ), (3, )], [(4, ), (4, )]) }, 2: { 1: [(1, 2), (1, 2)], 2: ([(1, 2), (1, 2)], [(3, 4), (3, 4)]) } } vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}} subsample = np.array([2, 3], dtype=np.int) for dim in [1, 2]: # # Iterate over dimension # # DofHandler if dim == 1: mesh = Mesh1D(box=[0, 5], resolution=(1, )) elif dim == 2: mesh = QuadMesh(box=[0, 5, 0, 5]) element = QuadFE(dim, 'Q2') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) for n_variables in [1, 2]: # # Iterate over number of variables # # # Explicit # f = fns[dim][n_variables] # Explicit fe = Explicit(f, n_variables=n_variables, dim=dim, \ subsample=subsample) # Nodal fn = Nodal(f, n_variables=n_variables, basis=basis, dim=dim, \ dofhandler=dofhandler, subsample=subsample) # Constant fc = Constant(1, n_variables=n_variables, \ subsample=subsample) # Singleton input xn = x[dim][n_variables] # Explicit self.assertEqual(fe.eval(xn).shape[1], len(subsample)) self.assertEqual(fe.eval(xn)[0, 0], vals[dim][n_variables]) self.assertEqual(fe.eval(xn)[0, 1], vals[dim][n_variables]) # Nodal self.assertEqual(fn.eval(xn).shape[1], len(subsample)) self.assertAlmostEqual( fn.eval(xn)[0, 0], vals[dim][n_variables]) self.assertAlmostEqual( fn.eval(xn)[0, 1], vals[dim][n_variables]) # Constant self.assertEqual(fc.eval(xn).shape[1], len(subsample)) self.assertAlmostEqual(fc.eval(xn)[0, 0], 1) self.assertAlmostEqual(fc.eval(xn)[0, 1], 1) # Vector input xn = xv[dim][n_variables] n_points = 2 # Explicit self.assertEqual(fe.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertEqual( fe.eval(xn)[i][j], vals[dim][n_variables]) # Nodal self.assertEqual(fn.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertAlmostEqual( fn.eval(xn)[i][j], vals[dim][n_variables]) # Constant self.assertEqual(fc.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertEqual(fc.eval(xn)[i][j], 1)
def test_eval(self): # # Evaluate single univariate/bivariate functions in 1 or 2 dimensions # fns = { 1: { 1: lambda x: x**2, 2: lambda x, y: x + y }, 2: { 1: lambda x: x[:, 0]**2 + x[:, 1]**2, 2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1] } } # Singletons x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}} vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}} for dim in [1, 2]: # # Iterate over dimension # for n_variables in [1, 2]: # # Iterate over number of variables # fn = fns[dim][n_variables] f = Explicit(fn, n_variables=n_variables, dim=dim) xn = x[dim][n_variables] self.assertEqual(f.eval(xn), vals[dim][n_variables]) # # Evaluate sampled functions # fns = { 1: { 1: lambda x, a: a * x**2, 2: lambda x, y, a: a * (x + y) }, 2: { 1: lambda x, a: a * (x[:, 0]**2 + x[:, 1]**2), 2: lambda x, y, a: a * (x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1]) } } pars = [{'a': 1}, {'a': 2}] # # Singletons # x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}} vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}} for dim in [1, 2]: # # Iterate over dimension # for n_variables in [1, 2]: # # Iterate over number of variables # fn = fns[dim][n_variables] f = Explicit(fn, parameters=pars, n_variables=n_variables, dim=dim) xn = x[dim][n_variables] self.assertEqual(f.eval(xn)[0][0], vals[dim][n_variables]) self.assertEqual(f.eval(xn)[0][1], 2 * vals[dim][n_variables]) # # 2 points # n_points = 2 x = { 1: { 1: [(2, ), (2, )], 2: ([(3, ), (3, )], [(4, ), (4, )]) }, 2: { 1: [(1, 2), (1, 2)], 2: ([(1, 2), (1, 2)], [(3, 4), (3, 4)]) } } for dim in [1, 2]: # # Iterate over dimension # for n_variables in [1, 2]: # # Iterate over number of variables # fn = fns[dim][n_variables] f = Explicit(fn, parameters=pars, n_variables=n_variables, dim=dim) xn = x[dim][n_variables] self.assertEqual(f.eval(xn).shape[0], n_points) self.assertEqual(f.eval(xn).shape[1], f.n_samples()) for i in range(f.n_samples()): for j in range(2): val = pars[i]['a'] * vals[dim][n_variables] self.assertEqual(f.eval(xn)[j, i], val)
def test_integrals_2d(self): """ Test Assembly of some 2D systems """ mesh = QuadMesh(box=[1, 2, 1, 2], resolution=(2, 2)) mesh.cells.get_leaves()[0].mark(0) mesh.cells.refine(refinement_flag=0) # Kernel kernel = Kernel(Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2)) problem = Form(kernel) assembler = Assembler(problem, mesh=mesh) assembler.assemble() self.assertAlmostEqual(assembler.get_scalar(), 9 / 4) # # Linear forms (x,x) and (x,x') over [1,2]^2 = 7/3, 3/2 # # Elements Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Dofhandlers dQ1 = DofHandler(mesh, Q1) dQ2 = DofHandler(mesh, Q2) dQ3 = DofHandler(mesh, Q3) # Distribute dofs [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]] for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function xfn = Nodal(f=lambda x: x[:, 0], basis=phi) yfn = Nodal(f=lambda x: x[:, 1], basis=phi) # Kernel kernel = Kernel(xfn) # Form problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]] # Assembly assembler = Assembler(problem, mesh) assembler.assemble() # Check b^Tx = (x,y) b0 = assembler.get_vector(0) self.assertAlmostEqual(np.sum(b0 * yfn.data()[:, 0]), 9 / 4) b1 = assembler.get_vector(1) self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2) self.assertAlmostEqual(np.sum(b1 * yfn.data()[:, 0]), 0) # # Bilinear forms # # Compute (1,x,y) = 9/4, or (xy, 1, 1) = 9/4 for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') phi_y = Basis(dQ, 'uy') # Kernel function xyfn = Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2) xfn = Nodal(f=lambda x: x[:, 0], basis=phi) yfn = Nodal(f=lambda x: x[:, 1], basis=phi) # Form problems = [[Form(1, test=phi, trial=phi)], [Form(Kernel(xfn), test=phi, trial=phi_x)], [Form(Kernel(xyfn), test=phi_y, trial=phi_x)]] # Assemble assembler = Assembler(problems, mesh) assembler.assemble() x = xfn.data()[:, 0] y = yfn.data()[:, 0] for i_problem in range(3): A = assembler.get_matrix(i_problem) self.assertAlmostEqual(y.T.dot(A.dot(x)), 9 / 4)
from mesh import QuadMesh, Mesh1D from plot import Plot from fem import QuadFE, DofHandler from function import Explicit import numpy as np plot = Plot() mesh = Mesh1D() Q0 = QuadFE(1, 'DQ0') dh0 = DofHandler(mesh, Q0) n_levels = 10 for l in range(n_levels): mesh.cells.refine(new_label=l) dh0.distribute_dofs(subforest_flag=l) f = Explicit(lambda x: np.abs(x - 0.5), dim=1) fQ = f.interpolant(dh0, subforest_flag=3) plot.line(fQ, mesh) plot.mesh(mesh, dofhandler=dh0, subforest_flag=0) mesh = QuadMesh(resolution=(10, 10)) plot.mesh(mesh)
dofhandler = DofHandler(mesh, element) comment.tic('distribute dofs') dofhandler.distribute_dofs() comment.toc() print('number of dofs:', dofhandler.n_dofs()) # Basis functions p_u = Basis(dofhandler, 'u') p_ux = Basis(dofhandler, 'ux') p_uy = Basis(dofhandler, 'uy') pp_u = Basis(dofhandler, 'u') f = lambda x: x[:, 0] * (1 - x[:, 0]) * x[:, 1] * (1 - x[:, 1]) qq = Explicit(f=f, dim=2) fNodal = Nodal(f=f, basis=p_u) qk = Kernel(f=[qq], F=lambda qq, mu=3: 3 * qq) p_inflow = lambda x, y: np.ones(shape=x.shape) p_outflow = lambda x, y: np.zeros(shape=x.shape) c_inflow = lambda x, y: np.zeros(shape=x.shape) # ============================================================================= # Solve the steady state flow equations # ============================================================================= # Define problem flow_problem = [
he.mark('B') mesh.tear_region('B') # ============================================================================= # Functions # ============================================================================= Q1 = QuadFE(2, 'Q1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') uy = Basis(dofhandler, 'uy') epsilon = 1e-6 vx = Explicit(f=lambda x: -x[:, 1], dim=2) vy = Explicit(f=lambda x: x[:, 0], dim=2) uB = Explicit(f=lambda x: np.cos(2 * np.pi * (x[:, 1] + 0.25)), dim=2) problem = [ Form(epsilon, trial=ux, test=ux), Form(epsilon, trial=uy, test=uy), Form(vx, trial=ux, test=u), Form(vy, trial=uy, test=u), Form(0, test=u) ] print('assembling', end=' ') assembler = Assembler(problem, mesh) assembler.assemble() print('done')
def test_integrals_1d(self): """ Test system assembly """ # # Constant form # # Mesh mesh = Mesh1D(box=[1, 2], resolution=(1, )) # Kernel kernel = Kernel(Explicit(f=lambda x: x[:, 0], dim=1)) problem = Form(kernel) assembler = Assembler(problem, mesh=mesh) assembler.assemble() self.assertAlmostEqual(assembler.get_scalar(), 3 / 2) # # Linear forms (x,x) and (x,x') over [1,2] = 7/3, 3/2 # # Elements Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Dofhandlers dQ1 = DofHandler(mesh, Q1) dQ2 = DofHandler(mesh, Q2) dQ3 = DofHandler(mesh, Q3) # Distribute dofs [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]] for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function xfn = Nodal(f=lambda x: x[:, 0], basis=phi) # Kernel kernel = Kernel(xfn) # Form problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]] # Assembly assembler = Assembler(problem, mesh) assembler.assemble() # Check b^Tx = (x,x) b0 = assembler.get_vector(0) self.assertAlmostEqual(np.sum(b0 * xfn.data()[:, 0]), 7 / 3) b1 = assembler.get_vector(1) self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2) # # Bilinear forms # # Compute (1,x,x) = 7/3, or (x^2, 1, 1) = 7/3 for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function x2fn = Explicit(f=lambda x: x[:, 0]**2, dim=1) xfn = Nodal(f=lambda x: x[:, 0], basis=phi) # Form problems = [[Form(1, test=phi, trial=phi)], [Form(Kernel(xfn), test=phi, trial=phi_x)], [Form(Kernel(x2fn), test=phi_x, trial=phi_x)]] # Assemble assembler = Assembler(problems, mesh) assembler.assemble() x = xfn.data()[:, 0] for i_problem in range(3): A = assembler.get_matrix(i_problem) self.assertAlmostEqual(x.T.dot(A.dot(x)), 7 / 3) # ====================================================================== # Test 1: Assemble simple bilinear form (u,v) on Mesh1D # ====================================================================== # Mesh mesh = Mesh1D(resolution=(1, )) Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Test and trial functions dhQ1 = DofHandler(mesh, QuadFE(1, 'Q1')) dhQ1.distribute_dofs() u = Basis(dhQ1, 'u') v = Basis(dhQ1, 'v') # Form form = Form(trial=u, test=v) # Define system system = Assembler(form, mesh) # Get local information cell = mesh.cells.get_child(0) si = system.shape_info(cell) # Compute local Gauss nodes xg, wg, phi, dofs = system.shape_eval(cell) self.assertTrue(cell in xg) self.assertTrue(cell in wg) # Compute local shape functions self.assertTrue(cell in phi) self.assertTrue(u in phi[cell]) self.assertTrue(v in phi[cell]) self.assertTrue(u in dofs[cell]) # Assemble system system.assemble() # Extract system bilinear form A = system.get_matrix() # Use bilinear form to integrate x^2 over [0,1] f = Nodal(lambda x: x, basis=u) fv = f.data()[:, 0] self.assertAlmostEqual(np.sum(fv * A.dot(fv)), 1 / 3) # ====================================================================== # Test 3: Constant form (x^2,.,.) over 1D mesh # ====================================================================== # Mesh mesh = Mesh1D(resolution=(10, )) # Nodal kernel function Q2 = QuadFE(1, 'Q2') dhQ2 = DofHandler(mesh, Q2) dhQ2.distribute_dofs() phiQ2 = Basis(dhQ2) f = Nodal(lambda x: x**2, basis=phiQ2) kernel = Kernel(f=f) # Form form = Form(kernel=kernel) # Generate and assemble the system system = Assembler(form, mesh) system.assemble() # Check self.assertAlmostEqual(system.get_scalar(), 1 / 3) # ===================================================================== # Test 4: Periodic Mesh # ===================================================================== # # TODO: NO checks yet # mesh = Mesh1D(resolution=(2, ), periodic=True) # Q1 = QuadFE(1, 'Q1') dhQ1 = DofHandler(mesh, Q1) dhQ1.distribute_dofs() u = Basis(dhQ1, 'u') form = Form(trial=u, test=u) system = Assembler(form, mesh) system.assemble() # ===================================================================== # Test 5: Assemble simple sampled form # ====================================================================== mesh = Mesh1D(resolution=(3, )) Q1 = QuadFE(1, 'Q1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler) xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) f = lambda x, a: a * x fdata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = f(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=phi) kernel = Kernel(fn) # # Integrate I[0,1] ax^2 dx by using the linear form (ax,x) # v = Basis(dofhandler, 'v') form = Form(kernel=kernel, test=v) system = Assembler(form, mesh) system.assemble() one = np.ones(n_points) for i in range(n_samples): b = system.get_vector(i_sample=i) self.assertAlmostEqual(one.dot(b), 0.5 * a[i]) # # Integrate I[0,1] ax^4 dx using bilinear form (ax, x^2, x) # Q2 = QuadFE(1, 'Q2') dhQ2 = DofHandler(mesh, Q2) dhQ2.distribute_dofs() u = Basis(dhQ2, 'u') # Define form form = Form(kernel=kernel, test=v, trial=u) # Define and assemble system system = Assembler(form, mesh) system.assemble() # Express x^2 in terms of trial function basis dhQ2.distribute_dofs() xvQ2 = dhQ2.get_dof_vertices() xv_squared = xvQ2**2 for i in range(n_samples): # # Iterate over samples # # Form sparse matrix A = system.get_matrix(i_sample=i) # Evaluate the integral I = np.sum(xv * A.dot(xv_squared)) # Compare with expected result self.assertAlmostEqual(I, 0.2 * a[i]) # ===================================================================== # Test 6: Working with submeshes # ===================================================================== mesh = Mesh1D(resolution=(2, ))
def test_eval_projection(self): """ Test validity of the local projection-based kernel. Choose u, v in V k(x,y) in VxV (symmetric/non-symm) cell01, cell02 Compare v^T*Kloc*u ?= Icell01 Icell02 k(x,y)u(y)dy dx """ # # 1D # # Mesh mesh = Mesh1D(resolution=(3, )) # Finite element space etype = 'Q1' element = QuadFE(1, etype) # Dofhandler dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions phi = Basis(dofhandler, 'u') # Symmetric kernel function kfns = { 'symmetric': lambda x, y: x * y, 'non_symmetric': lambda x, y: x - y } vals = { 'symmetric': (1 / 2 * 1 / 9 - 1 / 3 * 1 / 27) * (1 / 3 - 1 / 3 * 8 / 27), 'non_symmetric': (1 / 18 - 1 / 3 * 1 / 27) * (1 / 2 - 2 / 9) + (1 / 18 - 1 / 3) * (1 / 3 - 1 / 3 * 8 / 27) } for ktype in ['symmetric', 'non_symmetric']: # Get kernel function kfn = kfns[ktype] # Define integral kernel kernel = Kernel(Explicit(kfn, dim=1, n_variables=2)) # Define Bilinear Form form = IPForm(kernel, trial=phi, test=phi) # # Compute inputs required for evaluating form_loc # # Assembler assembler = Assembler(form, mesh) # Cells ci = mesh.cells.get_child(0) cj = mesh.cells.get_child(2) # Shape function info on cells ci_sinfo = assembler.shape_info(ci) cj_sinfo = assembler.shape_info(cj) # Gauss nodes and weights on cell xi_g, wi_g, phii, dofsi = assembler.shape_eval(ci) xj_g, wj_g, phij, dofsj = assembler.shape_eval(cj) # # Evaluate form # form_loc = form.eval((ci,cj), (xi_g,xj_g), \ (wi_g,wj_g), (phii,phij), (dofsi,dofsj)) # # Define functions # u = Nodal(f=lambda x: x, basis=phi) v = Nodal(f=lambda x: 1 - x, basis=phi) # # Get local node values # # Degrees of freedom ci_dofs = phi.dofs(ci) cj_dofs = phi.dofs(cj) uj = u.data()[np.array(cj_dofs)] vi = v.data()[np.array(ci_dofs)] if ktype == 'symmetric': # Local form by hand c10 = 1 / 54 c11 = 1 / 27 c20 = 3 / 2 - 1 - 3 / 2 * 4 / 9 + 8 / 27 c21 = 4 / 27 fl = np.array([[c10 * c20, c10 * c21], [c11 * c20, c11 * c21]]) # Compare computed and explicit local forms self.assertTrue(np.allclose(fl, form_loc)) # Evaluate Ici Icj k(x,y) y dy (1-x)dx fa = np.dot(vi.T, form_loc.dot(uj)) fe = vals[ktype] self.assertAlmostEqual(fa, fe)
def reference_solution(): """ Use sparse grid method to compute a benchmark solution """ mesh = QuadMesh(resolution=(10,10)) mesh.mark_region('boundary', lambda x,y:True, entity_type='half_edge', on_boundary=True) element = QuadFE(mesh.dim(), 'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() n = dofhandler.n_dofs() phi = Basis(dofhandler, 'u') phi_x = Basis(dofhandler, 'ux') phi_y = Basis(dofhandler, 'uy') yd_fn = Explicit(lambda x: np.sin(2*np.pi*x[:,0])*np.sin(2*np.pi*x[:,1]),dim=2) g = np.ones((n,1)) # # Random diffusion coefficient # # Sparse grid tasmanian_library="/home/hans-werner/bin/TASMANIAN-6.0/libtasmaniansparsegrid.so" grid = TasmanianSG.TasmanianSparseGrid(tasmanian_library=tasmanian_library) dimensions = 4 outputs = 1 depth = 4 type = 'tensor' rule = 'gauss-legendre' grid.makeGlobalGrid(dimensions, outputs, depth, type, rule) Y = grid.getPoints() w = grid.getQuadratureWeights() n_samples = grid.getNumPoints() x = dofhandler.get_dof_vertices() a_nodal = 1 + 0.1*(np.outer(np.cos(np.pi*x[:,1]),Y[:,0])+\ np.outer(np.cos(np.pi*x[:,0]),Y[:,1])+\ np.outer(np.sin(2*np.pi*x[:,1]),Y[:,2])+\ np.outer(np.sin(2*np.pi*x[:,0]),Y[:,3])) a = Nodal(data=a_nodal, dofhandler=dofhandler) yd_vec = yd_fn.eval(x) problems = [[Form(a, test=phi_x, trial=phi_x), Form(a, test=phi_y, trial=phi_y)], [Form(1, test=phi, trial=phi)]] assembler = Assembler(problems, mesh) assembler.assemble() A = assembler.af[0]['bilinear'].get_matrix() M = assembler.af[1]['bilinear'].get_matrix() state = LS(phi) state.add_dirichlet_constraint('boundary') adjoint = LS(phi) adjoint.add_dirichlet_constraint('boundary') tau = 10 k_max = 20 alpha = 0.1 u = np.zeros((n,1)) norm_dJ_iter = [] J_iter = [] u_iter = [] for k in range(k_max): print('iteration', k) # # Compute average cost and gradient # dJ = np.zeros((n,1)) J = 0 print('sampling') for n in range(n_samples): print(n) yn, pn, Jn, dJn = cost_gradient(state,adjoint,A[n],M, g,u,yd_vec,alpha) J += w[n]*Jn dJ += w[n]*dJn print('') norm_dJ = np.sqrt(dJ.T.dot(M.dot(dJ))) # # Store current iterates # norm_dJ_iter.append(norm_dJ) J_iter.append(J) u_iter.append(u) # # Check for convergence # if norm_dJ<1e-8: break # # Update iterate # u -= tau*dJ
# ----------------------------------------------------------------------------- # Observations # ----------------------------------------------------------------------------- # Determine vertices corresponding to production wells n_prod = 4 h = (x_max-x_min)/(n_prod+2) x_prod = np.array([(i+1)*h for i in range(n_prod)]) v = dh_y.get_dof_vertices() dofs_prod = [] for x in x_prod: dofs_prod.append(np.argmin(abs(v-x))) # # Target pressure at production wells # z_fn = Explicit(f=lambda x: 3-4*(x[:,0]-1)**2, dim=1, mesh=mesh) z_data = z_fn.eval(v[dofs_prod]) # ----------------------------------------------------------------------------- # Control # ----------------------------------------------------------------------------- # Determine the vertices corresponding to the injection wells n_inj = 6 h = (x_max-x_min)/(n_inj+2) x_inj = np.array([(i+1)*h for i in range(n_inj)]) dofs_inj = [] for x in x_inj: dofs_inj.append(np.argmin(abs(v-x))) u_data = np.zeros((ny,1)) u_data[dofs_inj] = 1
xy = np.array([X.ravel(), Y.ravel()]).T cells_production = mesh.bin_points(xy) # Mark vertices for cell, dummy in cells_production: cell.get_vertex(2).mark('production') # Extract degrees of freedom production_dofs = dh_Q1.get_region_dofs(entity_type='vertex', entity_flag='production') v_production = dh_Q1.get_dof_vertices(dofs=production_dofs) # Target pressure at production wells z_fn = Explicit(f=lambda x: 3 - 4 * (x[:, 0] - 1)**2 - 8 * (x[:, 1] - 0.5)**2, dim=2, mesh=mesh) y_target = z_fn.eval(v_production) # # Locations of injection wells # n_injection = (5, 4) # resolution x_injection = np.linspace(0.5, 1.5, n_injection[0]) y_injection = np.linspace(0.25, 0.75, n_injection[1]) X, Y = np.meshgrid(x_injection, y_injection) xy = np.array([X.ravel(), Y.ravel()]).T cells_injection = mesh.bin_points(xy) # Mark vertices for cell, dummy in cells_injection:
nt = np.int((t1 - t0) / dt) # Initial condition u0 = Constant(0) # Left Dirichlet condition def u_left(x): n_points = x.shape[0] u = np.zeros((n_points, 1)) left_strip = (x[:, 0] >= 4) * (x[:, 0] <= 6) * (abs(x[:, 1]) < 1e-9) u[left_strip, 0] = 1 return u u_left = Explicit(f=u_left, mesh=mesh) # Define problems Dx = 1 Dy = 0.1 * Dx Form(1, trial=v, test=v) k_max = 1 up = Nodal(f=lambda x: x[:, 1]**2, dofhandler=V1) um = Nodal(f=lambda x: x[:, 0], dofhandler=V1) residual = [Form(1, test=v)] """ residual = [Form(Kernel(f=up),test=v), Form(Kernel(f=um), test=v), Form(Kernel(f=up),test=v_x)]
def test04_1d_periodic(self): # # Dirichlet Problem on a Periodic Mesh # # Define mesh, element mesh = Mesh1D(resolution=(100, ), periodic=True) element = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # Exact solution ue = Nodal(f=lambda x: np.sin(2 * np.pi * x), basis=u) # # Mark dirichlet regions # bnd_left = lambda x: np.abs(x) < 1e-9 mesh.mark_region('left', bnd_left, entity_type='vertex') # # Set up forms # # Bilinear form a = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux) # Linear form f = Explicit(lambda x: 4 * np.pi**2 * np.sin(2 * np.pi * x), dim=1) L = Form(kernel=Kernel(f), test=u) # # Assemble # problem = [a, L] assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(u, A=A, b=b) # Add dirichlet constraint system.add_dirichlet_constraint('left', 0, on_boundary=False) # Assemble constraints #system.set_constraint_relation() #system.incorporate_constraints() system.solve_system() #system.resolve_constraints() # Compare with interpolant of exact solution ua = system.get_solution(as_function=True) #plot = Plot(2) #plot.line(ua) #plot.line(ue) self.assertTrue(np.allclose(ua.data(), ue.data()))
def test_constructor(self): # ===================================================================== # Test 1D # ===================================================================== # # Kernel consists of a single explicit Function: # f1 = lambda x: x+2 f = Explicit(f1, dim=1) k = Kernel(f) x = np.linspace(0,1,100) n_points = len(x) # Check that it evaluates correctly. self.assertTrue(np.allclose(f1(x), k.eval(x).ravel())) # Check shape of kernel self.assertEqual(k.eval(x).shape, (n_points,1)) # # Kernel consists of a combination of two explicit functions # f1 = Explicit(lambda x: x+2, dim=1) f2 = Explicit(lambda x: x**2 + 1, dim=1) F = lambda f1, f2: f1**2 + f2 f_t = lambda x: (x+2)**2 + x**2 + 1 k = Kernel([f1,f2], F=F) # Check evaluation self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel())) # Check shape self.assertEqual(k.eval(x).shape, (n_points,1)) # # Same thing as above, but with nodal functions # mesh = Mesh1D(resolution=(1,)) Q1 = QuadFE(1,'Q1') Q2 = QuadFE(1,'Q2') dQ1 = DofHandler(mesh,Q1) dQ2 = DofHandler(mesh,Q2) # Distribute dofs [dQ.distribute_dofs() for dQ in [dQ1,dQ2]] # Basis functions phi1 = Basis(dQ1,'u') phi2 = Basis(dQ2,'u') f1 = Nodal(lambda x: x+2, basis=phi1) f2 = Nodal(lambda x: x**2 + 1, basis=phi2) k = Kernel([f1,f2], F=F) # Check evaluation self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel())) # # Replace f2 above with its derivative # k = Kernel([f1,f2], derivatives=['f', 'fx'], F=F) f_t = lambda x: (x+2)**2 + 2*x # Check derivative evaluation F = F(f1, df2_dx) self.assertTrue(np.allclose(f_t(x), k.eval(x).ravel())) # # Sampling # one = Constant(1) f1 = Explicit(lambda x: x**2 + 1, dim=1) # Sampled function a = np.linspace(0,1,11) n_samples = len(a) # Define Dofhandler dh = DofHandler(mesh, Q2) dh.distribute_dofs() dh.set_dof_vertices() xv = dh.get_dof_vertices() n_dofs = dh.n_dofs() phi = Basis(dh, 'u') # Evaluate parameterized function at mesh dof vertices f2_m = np.empty((n_dofs, n_samples)) for i in range(n_samples): f2_m[:,i] = xv.ravel() + a[i]*xv.ravel()**2 f2 = Nodal(data=f2_m, basis=phi) # Define kernel F = lambda f1, f2, one: f1 + f2 + one k = Kernel([f1,f2,one], F=F) # Evaluate on a fine mesh x = np.linspace(0,1,100) n_points = len(x) self.assertEqual(k.eval(x).shape, (n_points, n_samples)) for i in range(n_samples): # Check evaluation self.assertTrue(np.allclose(k.eval(x)[:,i], f1.eval(x)[:,i] + x + a[i]*x**2+ 1)) # # Sample multiple constant functions # f1 = Constant(data=a) f2 = Explicit(lambda x: 1 + x**2, dim=1) f3 = Nodal(data=f2_m[:,-1], basis=phi) F = lambda f1, f2, f3: f1 + f2 + f3 k = Kernel([f1,f2,f3], F=F) x = np.linspace(0,1,100) for i in range(n_samples): self.assertTrue(np.allclose(k.eval(x)[:,i], \ a[i] + f2.eval(x)[:,i] + f3.eval(x)[:,i])) # # Submeshes # mesh = Mesh1D(resolution=(1,)) mesh_labels = Tree(regular=False) mesh = Mesh1D(resolution=(1,)) Q1 = QuadFE(1,'Q1') Q2 = QuadFE(1,'Q2') dQ1 = DofHandler(mesh,Q1) dQ2 = DofHandler(mesh,Q2) # Distribute dofs [dQ.distribute_dofs() for dQ in [dQ1,dQ2]] # Basis p1 = Basis(dQ1) p2 = Basis(dQ2) f1 = Nodal(lambda x: x, basis=p1) f2 = Nodal(lambda x: -2+2*x**2, basis=p2) one = Constant(np.array([1,2])) F = lambda f1, f2, one: 2*f1**2 + f2 + one I = mesh.cells.get_child(0) kernel = Kernel([f1,f2, one], F=F) rule1D = GaussRule(5,shape='interval') x = I.reference_map(rule1D.nodes())
import numpy as np import matplotlib.pyplot as plt """ Error analysis for advection diffusion equation -epsilon*(d^2u_dx^2 + d^2u_dy^2) + vx*du_dx + vy*du_dy = f subject to dirichlet boundary conditions. """ # # Define functions # # Exact solution ue = Explicit(f=lambda x: np.sin(x[:, 0]) * np.sin(x[:, 1]), n_variables=1, dim=2) # Forcing function ffn = lambda x: 2*eps*np.sin(x[:,0])*np.sin(x[:,1]) + \ x[:,0]*np.cos(x[:,0])*np.sin(x[:,1]) + \ x[:,1]*np.sin(x[:,0])*np.cos(x[:,1]) f = Explicit(ffn, dim=2) # Velocity function vx = Explicit(lambda x: x[:, 0], dim=2) vy = Explicit(lambda x: x[:, 1], dim=2) errors = {} for resolution in [(5, 5), (10, 10), (20, 20), (40, 40)]: #
Q1 = QuadFE(2,'Q1') # element for pressure Q2 = QuadFE(2,'Q2') # element for velocity # Dofhandler DQ1 = DofHandler(mesh, Q1) DQ2 = DofHandler(mesh, Q2) # Time discretization T = 1 nt = 101 t = np.linspace(0,T,nt) # Problem Parameters g = 10 gma = 0.1 U = 0.1 tht = 1 nu = Explicit(f=lambda x: np.sin(x[:,0])**2+1, dim=2) # Explicit solution u1 = Explicit(f=lambda x,t: t[:,0]**3*np.sin(np.pi*x[:,0])*np.sin(np.pi*x[:,1]),\ dim=2, n_variables=2) # # Iterate over time ss # u = np.empty() for i in range(nt): pass