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_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_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 test03_dJdq(): """ Compute dJdq for a simple problem, check that it works """ # # Mesh # mesh = Mesh1D(resolution=(20, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10) # # Element # Q = QuadFE(mesh.dim(), 'Q3') dh = DofHandler(mesh, Q) dh.distribute_dofs() nx = dh.n_dofs() x = dh.get_dof_vertices() # # Basis # phi = Basis(dh, 'v') phi_x = Basis(dh, 'vx') # # Parameters # # Reference q q_ref = Nodal(data=np.zeros(nx), basis=phi) # Perturbation dq = Nodal(data=np.ones(nx), basis=phi) # # Sample Reference QoI # J, u_ref = sample_qoi(q_ref.data(), dh, return_state=True) u_ref = Nodal(data=u_ref, basis=phi) # # Compute dJdq # # Perturbation method Jp_per = dJdq_per(q_ref, dq, dh) # Sensitivity method Jp_sen = dJdq_sen(q_ref, u_ref, dq) # Adjoint method Jp_adj = dJdq_adj(q_ref, u_ref, dq) # Check that the answers are close to -1 assert np.allclose(Jp_per, -1) assert np.allclose(Jp_sen, -1) assert np.allclose(Jp_adj, -1)
def sensitivity_sample_qoi(exp_q, dofhandler): """ Sample QoI by means of Taylor expansion J(q+dq) ~= J(q) + dJdq(q)dq """ # Basis phi = Basis(dofhandler, 'v') phi_x = Basis(dofhandler, 'vx') # Define problem exp_q_fn = Nodal(data=exp_q, basis=phi) primal = [Form(exp_q_fn, test=phi_x, trial=phi_x), Form(1, test=phi)] adjoint = [Form(exp_q_fn, test=phi_x, trial=phi_x), Form(0, test=phi)] qoi = [Form(exp_q_fn, test=phi_x)] problems = [primal, adjoint, qoi] # Define assembler assembler = Assembler(problems) # # Dirichlet conditions for primal problem # assembler.add_dirichlet('left', 0, i_problem=0) assembler.add_dirichlet('right', 1, i_problem=0) # Dirichlet conditions for adjoint problem assembler.add_dirichlet('left', 0, i_problem=1) assembler.add_dirichlet('right', -1, i_problem=1) # Assemble system assembler.assemble() # Compute solution and qoi at q (primal) u = assembler.solve(i_problem=0) # Compute solution of the adjoint problem v = assembler.solve(i_problem=1) # Evaluate J J = u.dot(assembler.get_vector(2)) # # Assemble gradient # ux_fn = Nodal(data=u, basis=phi_x) vx_fn = Nodal(data=v, basis=phi_x) k_int = Kernel(f=[exp_q_fn, ux_fn, vx_fn], F=lambda exp_q, ux, vx: exp_q * ux * vx) problem = [Form(k_int, test=phi)] assembler = Assembler(problem) assembler.assemble() dJ = -assembler.get_vector() return dJ
def test_n_samples(self): # # Sampled Case # meshes = {1: Mesh1D(), 2: QuadMesh()} elements = {1: QuadFE(1, 'Q2'), 2: QuadFE(2, 'Q2')} # Use function to set data fns = { 1: { 1: lambda x: 2 * x[:, 0]**2, 2: lambda x, y: 2 * x[:, 0] + 2 * y[:, 0] }, 2: { 1: lambda x: x[:, 0]**2 + x[:, 1], 2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1] } } # n_samples = 2 parms = {1: {1: [{}, {}], 2: [{}, {}]}, 2: {1: [{}, {}], 2: [{}, {}]}} for dim in [1, 2]: mesh = meshes[dim] element = elements[dim] dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) for n_variables in [1, 2]: fn = fns[dim][n_variables] parm = parms[dim][n_variables] # # Deterministic # f = Nodal(f=fn, mesh=mesh, basis=basis, element=element, dim=dim, n_variables=n_variables) self.assertEqual(f.n_samples(), 1) # # Sampled # f = Nodal(f=fn, parameters=parm, basis=basis, mesh=mesh, element=element, dim=dim, n_variables=n_variables) self.assertEqual(f.n_samples(), 2)
def test02a_sensitivity_gradient(): """ Test whether the sensitivity and adjoint calculations give the same gradient """ # Mesh mesh = Mesh1D(resolution=(100, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-10) # Element Q = QuadFE(mesh.dim(), 'Q2') dh = DofHandler(mesh, Q) dh.distribute_dofs() n_dofs = dh.n_dofs() phi = Basis(dh, 'u') # Covariance cov = Covariance(dh, name='gaussian', parameters={'l': 0.05}) cov.compute_eig_decomp() lmd, V = cov.get_eig_decomp() d = len(lmd) # Coarse field (single sample) d0 = 2 z0 = np.random.randn(d0, 1) q0 = sample_q0(V, lmd, d0, z0) q0_fn = Nodal(data=q0, basis=phi) # State J0, u0 = sample_qoi(q0, dh, return_state=True) u0_fn = Nodal(data=u0, basis=phi) # Compute gradient using sensitivity dJs = np.zeros(n_dofs) for i in range(n_dofs): # Define perturbation dq = np.zeros(n_dofs) dq[i] = 1 dq_fn = Nodal(data=dq, basis=phi) # Compute gradient using sensitivity dJs[i] = dJdq_sen(q0_fn, u0_fn, dq_fn) dJs_fn = Nodal(data=dJs, basis=phi) plot = Plot() plot.line(dJs_fn) # Compute gradient using adjoint method dJa = dJdq_adj(q0_fn, u0_fn) dJa_fn = Nodal(data=dJa, basis=phi) print(dJa) plot.line(dJa_fn)
def test02_1d_dirichlet_higher_order(self): mesh = Mesh1D() for etype in ['Q2', 'Q3']: element = QuadFE(1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions ux = Basis(dofhandler, 'ux') u = Basis(dofhandler, 'u') # Exact solution ue = Nodal(f=lambda x: x * (1 - x), basis=u) # Define coefficient functions one = Constant(1) two = Constant(2) # Define forms a = Form(kernel=Kernel(one), trial=ux, test=ux) L = Form(kernel=Kernel(two), test=u) problem = [a, L] # Assemble problem assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # Set up linear system system = LinearSystem(u, A=A, b=b) # Boundary functions bnd_left = lambda x: np.abs(x) < 1e-9 bnd_right = lambda x: np.abs(1 - x) < 1e-9 # Mark mesh mesh.mark_region('left', bnd_left, entity_type='vertex') mesh.mark_region('right', bnd_right, entity_type='vertex') # Add Dirichlet constraints to system system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 0) # Solve system system.solve_system() system.resolve_constraints() # Compare solution with the exact solution ua = system.get_solution(as_function=True) self.assertTrue(np.allclose(ua.data(), ue.data()))
def test01_solve_2d(self): """ Solve a simple 2D problem with no hanging nodes """ mesh = QuadMesh(resolution=(5, 5)) # Mark dirichlet boundaries mesh.mark_region('left', lambda x, dummy: np.abs(x) < 1e-9, entity_type='half_edge') mesh.mark_region('right', lambda x, dummy: np.abs(x - 1) < 1e-9, entity_type='half_edge') Q1 = QuadFE(mesh.dim(), 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() phi = Basis(dQ1, 'u') phi_x = Basis(dQ1, 'ux') phi_y = Basis(dQ1, 'uy') problem = [ Form(1, test=phi_x, trial=phi_x), Form(1, test=phi_y, trial=phi_y), Form(0, test=phi) ] assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_dirichlet('right', dir_fn=1) assembler.assemble() # Get matrix dirichlet correction and right hand side A = assembler.get_matrix().toarray() x0 = assembler.assembled_bnd() b = assembler.get_vector() ua = np.zeros((phi.n_dofs(), 1)) int_dofs = assembler.get_dofs('interior') ua[int_dofs, 0] = np.linalg.solve(A, b - x0) dir_bc = assembler.get_dirichlet() dir_vals = np.array([dir_bc[dof] for dof in dir_bc]) dir_dofs = [dof for dof in dir_bc] ua[dir_dofs] = dir_vals ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi) ue = ue_fn.data() self.assertTrue(np.allclose(ue, ua)) self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
def get_solution(self, as_function=True): """ Returns the solution of the linear system """ if not as_function: # # Return solution vector # return self.__u else: # # Return solution as nodal function # u = Nodal(data=self.__u, basis=self.get_basis()) return u
def test_edge_integrals(self): """ Test computing """ mesh = QuadMesh(resolution=(1, 1)) Q = QuadFE(2, 'Q1') dQ = DofHandler(mesh, Q) dQ.distribute_dofs() phi = Basis(dQ, 'u') f = Nodal(data=np.ones((phi.n_dofs(), 1)), basis=phi) kernel = Kernel(f) form = Form(kernel, dmu='ds') assembler = Assembler(form, mesh) cell = mesh.cells.get_leaves()[0] shape_info = assembler.shape_info(cell) xg, wg, phi, dofs = assembler.shape_eval(cell)
def set_diffusion(dQ, z): """ Generate sample of diffusion coefficient Inputs: dQ: DofHandler, dofhandler object z: (n_samples, n_dim) array of sample points in [0,1]^2 """ x = dQ.get_dof_vertices() q_vals = 1 + 0.1 *np.outer(np.cos(1*np.pi*x[:,0]),z[:,0])+\ 0.05 *np.outer(np.cos(2*np.pi*x[:,0]),z[:,1])+\ 0.01 *np.outer(np.cos(3*np.pi*x[:,0]),z[:,2])+\ 0.005*np.outer(np.cos(4*np.pi*x[:,0]),z[:,3]) q_fn = Nodal(dofhandler=dQ, data=q_vals) return q_fn
def sample_state(mesh,dQ,z,mflag,reference=False): """ Compute the sample output corresponding to a given input """ n_samples = z.shape[0] q = set_diffusion(dQ,z) phi = Basis(dQ,'u', mflag) phi_x = Basis(dQ, 'ux', mflag) if reference: problems = [[Form(q,test=phi_x,trial=phi_x), Form(1,test=phi)], [Form(1,test=phi, trial=phi)], [Form(1,test=phi_x, trial=phi_x)]] else: problems = [[Form(q,test=phi_x,trial=phi_x), Form(1,test=phi)]] assembler = Assembler(problems, mesh, subforest_flag=mflag) assembler.assemble() A = assembler.af[0]['bilinear'].get_matrix() b = assembler.af[0]['linear'].get_matrix() if reference: M = assembler.af[1]['bilinear'].get_matrix() K = assembler.af[2]['bilinear'].get_matrix() system = LS(phi) system.add_dirichlet_constraint('left') system.add_dirichlet_constraint('right') n_dofs = dQ.n_dofs(subforest_flag=mflag) y = np.empty((n_dofs,n_samples)) for n in range(n_samples): system.set_matrix(A[n]) system.set_rhs(b.copy()) system.solve_system() y[:,n] = system.get_solution(as_function=False)[:,0] y_fn = Nodal(dofhandler=dQ,subforest_flag=mflag,data=y) if reference: return y_fn, M, K else: return y_fn
def test01_solve_1d(self): """ Test solving 1D systems """ mesh = Mesh1D(resolution=(20, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-9) Q1 = QuadFE(1, 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() phi = Basis(dQ1, 'u') phi_x = Basis(dQ1, 'ux') problem = [Form(1, test=phi_x, trial=phi_x), Form(0, test=phi)] assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_dirichlet('right', dir_fn=1) assembler.assemble() # Get matrix dirichlet correction and right hand side A = assembler.get_matrix().toarray() x0 = assembler.assembled_bnd() b = assembler.get_vector() ua = np.zeros((phi.n_dofs(), 1)) int_dofs = assembler.get_dofs('interior') ua[int_dofs, 0] = np.linalg.solve(A, b - x0) dir_bc = assembler.get_dirichlet() dir_vals = np.array([dir_bc[dof] for dof in dir_bc]) dir_dofs = [dof for dof in dir_bc] ua[dir_dofs] = dir_vals ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi) ue = ue_fn.data() self.assertTrue(np.allclose(ue, ua)) self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
def test_constructor(self): # # Errors # # Nothing specified self.assertRaises(Exception, Nodal) # Nominal case mesh = QuadMesh() element = QuadFE(2, 'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) data = np.arange(0, 4) f = Nodal(data=data, basis=basis, mesh=mesh, element=element) self.assertEqual(f.dim(), 2) self.assertTrue(np.allclose(f.data().ravel(), data)) # Now change the data -> Error false_data = np.arange(0, 6) self.assertRaises( Exception, Nodal, **{ 'data': false_data, 'mesh': mesh, 'element': element }) # Now omit mesh or element kwargs = {'data': data, 'mesh': mesh} self.assertRaises(Exception, Nodal, **kwargs) kwargs = {'data': data, 'element': element} self.assertRaises(Exception, Nodal, **kwargs)
def test_constructor(self): """ GMRF """ mesh = Mesh1D(resolution=(1000, )) element = QuadFE(1, 'Q1') dofhandler = DofHandler(mesh, element) cov_kernel = CovKernel(name='matern', dim=2, \ parameters= {'sgm': 1, 'nu': 2, 'l': 0.1, 'M': None}) print('assembling covariance') covariance = Covariance(cov_kernel, dofhandler) print('defining gmrf') X = GMRF(covariance=covariance) print('sampling') Xh = Nodal(data=X.chol_sample(), dofhandler=dofhandler) print('plotting') plot = Plot() plot.line(Xh) '''
def reference_qoi(f, tht, basis, region, n=1000000, verbose=True): """ Parameters ---------- f : lambda function, Function of θ to be integrated. tht : GaussianField, Random field θ defined on mesh in terms of its mean and covariance basis : Basis, Basis function defining the nodal interpolant. It incorporates the mesh, the dofhandler, and the derivative. region : meshflag, Flag indicating the region of integration n : int, default=1000000 Sample size Returns ------- Q_ref : double, Reference quantity of interest err : double, Expected RMSE given by var(Q)/n. """ # # Assemble integral # batch_size = 100000 n_batches = n // batch_size + (0 if (n % batch_size) == 0 else 1) if verbose: print('Computing Reference Quantity of Interest') print('========================================') print('Sample size: ', n) print('Batch size: ', batch_size) print('Number of batches: ', n_batches) Q_smpl = np.empty(n) for k in range(n_batches): # Determine sample sizes for each batch if k < n_batches - 1: n_sample = batch_size else: # Last sample may be smaller than batch_size n_sample = n - k * batch_size if verbose: print(' - Batch Number ', k) print(' - Sample Size: ', n_sample) print(' - Sampling random field') # Sample from field tht_smpl = tht.sample(n_sample) # Define kernel tht_n = Nodal(data=tht_smpl, basis=basis) kf = Kernel(tht_n, F=f) # Define forms if k == 0: problems = [[Form(kernel=kf, flag=region)], [Form(flag=region)]] else: problems = [Form(kernel=kf, flag=region)] if verbose: print(' - Assembling.') # Compute the integral assembler = Assembler(problems, basis.mesh()) assembler.assemble() # # Compute statistic # # Get samples if k == 0: dx = assembler.get_scalar(i_problem=1) if verbose: print(' - Updating samples \n') batch_sample = assembler.get_scalar(i_problem=0, i_sample=None) Q_smpl[k * batch_size:k * batch_size + n_sample] = batch_sample / dx # Compute mean and MSE Q_ref = np.mean(Q_smpl) err = np.var(Q_smpl) / n # Return reference return Q_ref, err
z, w = hermite_rule(k, depth) n_sg = len(w) # Generate truncated field at the sparse grid points eta_trunc_sg = V[:, :k].dot(np.diag(np.sqrt(D[:k])).dot(z.T)) # Generate a Monte Carlo sample on top of sparse grid n_mc = 20 zz = np.random.randn(n_dofs - k, n_mc) eta_tail_mc = V[:, k:].dot(np.diag(np.sqrt(D[k:]))).dot(zz) # ----------------------------------------------------------------------------- # Sample and Integrate # ----------------------------------------------------------------------------- # Samples of random field theta_trunc = Nodal(data=eta_trunc_sg[:, [50]] + eta_tail_mc, basis=phi_1) # Assembler k = Kernel(theta_trunc, F=lambda tht: tht**2) problem = Form(flag='integration', kernel=k) assembler = Assembler(problem, mesh) assembler.assemble() v = assembler.get_scalar(i_sample=3) #plot = Plot(quickview=False) #fig, ax = plt.subplots() #plot.mesh(mesh,regions=[('region','cell')]) """ ax = plot.line(theta_trunc, axis=ax, i_sample=np.arange(n_mc), plot_kwargs={'linewidth':0.2,
def plot_heuristics(f, tht, basis, region, condition): """ Parameters ---------- f : lambda, Function of θ to be integrated. n : int, Sample size for Monte Carlo sample """ tht.update_support() # # Plot samples of the random field # n = 10000 tht_sample = tht.sample(n) tht_fn = Nodal(data=tht_sample, basis=basis) # # Compute the quantity of interest # # Define the kernel kf = Kernel(tht_fn, F=f) # Assemble over the mesh problems = [[Form(kernel=kf, flag=region)], [Form(flag=region)]] assembler = Assembler(problems, basis.mesh()) assembler.assemble() # Extract sample dx = assembler.get_scalar(i_problem=1) q_sample = assembler.get_scalar(i_sample=None) / dx # # Compute correlation coefficients of q with spatial data # plot = Plot(quickview=False) fig, ax = plt.subplots() plt_args = {'linewidth': 0.5, 'color': 'k'} ax = plot.line(tht_fn, axis=ax, i_sample=list(range(100)), plot_kwargs=plt_args) fig.savefig('ex01_sample_paths.eps') fig, ax = plt.subplots() ftht = Nodal(data=f(tht_sample), basis=basis) ax = plot.line(ftht, axis=ax, i_sample=list(range(100)), plot_kwargs=plt_args) fig.savefig('ex01_integrand.eps') fig, ax = plt.subplots(1, 1) plt.hist(q_sample, bins=50, density=True) ax.set_title(r'Histogram $Q(\theta)$') fig.savefig('ex01_histogram.eps') plt.close('all') dh = basis.dofhandler() n_dofs = dh.n_dofs() # Extract the region on which we condition cnd_dofs = dh.get_region_dofs(entity_flag=condition) I = np.eye(n_dofs) I = I[cnd_dofs, :] # Measured tht tht_msr = tht_sample[cnd_dofs, 0][:, None] n_cnd = 30 cnd_tht = tht.condition(I, tht_msr, n_samples=n_cnd) #cnd_tht_data = np.array([tht_sample[:,0] for dummy in range(n_cnd)]) #cnd_tht_data[cnd_dofs,:] = cnd_tht cnd_tht_fn = Nodal(data=f(cnd_tht), basis=basis) fig, ax = plt.subplots() ax = plot.line(cnd_tht_fn, axis=ax, i_sample=np.arange(n_cnd), plot_kwargs=plt_args) fig.tight_layout() plt.show()
def test08_1d_sampled_rhs(self): # # Mesh # mesh = Mesh1D(resolution=(1, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-9, on_boundary=True) # # Elements # Q3 = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, Q3) dofhandler.distribute_dofs() # # Basis # v = Basis(dofhandler, 'u') vx = Basis(dofhandler, 'ux') # # Define sampled right hand side and exact solution # xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) f = lambda x, a: a * x u = lambda x, a: a / 6 * (x - x**3) + x fdata = np.zeros((n_points, n_samples)) udata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = f(xv, a[i]).ravel() udata[:, i] = u(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=v) ue = Nodal(data=udata, basis=v) # # Forms # one = Constant(1) a = Form(Kernel(one), test=vx, trial=vx) L = Form(Kernel(fn), test=v) problem = [a, L] # # Assembler # assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(v, A=A, b=b) # Set constraints system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 1) #system.set_constraint_relation() #system.incorporate_constraints() # Solve and resolve constraints system.solve_system() #system.resolve_constraints() # Extract finite element solution ua = system.get_solution(as_function=True) # Check that the solution is close print(ue.data()[:, [0]]) print(ua.data()) self.assertTrue(np.allclose(ue.data()[:, [0]], ua.data()))
def test09_1d_inverse(self): """ Compute the inverse of a matrix and apply it to a vector/matrix. """ # # Mesh # mesh = Mesh1D(resolution=(1, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-9, on_boundary=True) # # Elements # Q3 = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, Q3) dofhandler.distribute_dofs() # # Basis # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # # Define sampled right hand side and exact solution # xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) ffn = lambda x, a: a * x ufn = lambda x, a: a / 6 * (x - x**3) + x fdata = np.zeros((n_points, n_samples)) udata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = ffn(xv, a[i]).ravel() udata[:, i] = ufn(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=u) ue = Nodal(data=udata, basis=u) # # Forms # one = Constant(1) a = Form(Kernel(one), test=ux, trial=ux) L = Form(Kernel(fn), test=u) problem = [[a], [L]] # # Assembler # assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector(i_problem=1) # # Linear System # system = LinearSystem(u, A=A) # Set constraints system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 1) system.solve_system(b) # Extract finite element solution ua = system.get_solution(as_function=True) system2 = LinearSystem(u, A=A, b=b) # Set constraints system2.add_dirichlet_constraint('left', 0) system2.add_dirichlet_constraint('right', 1) system2.solve_system() u2 = system2.get_solution(as_function=True) # Check that the solution is close self.assertTrue(np.allclose(ue.data()[:, 0], ua.data()[:, 0])) self.assertTrue(np.allclose(ue.data()[:, [0]], u2.data()))
def test01_1d_dirichlet_linear(self): """ Solve one dimensional boundary value problem with dirichlet conditions on left and right """ # # Define mesh # mesh = Mesh1D(resolution=(10, )) for etype in ['Q1', 'Q2', 'Q3']: element = QuadFE(1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() phi = Basis(dofhandler) # # Exact solution # ue = Nodal(f=lambda x: x, basis=phi) # # Define Basis functions # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # # Define bilinear form # one = Constant(1) zero = Constant(0) a = Form(kernel=Kernel(one), trial=ux, test=ux) L = Form(kernel=Kernel(zero), test=u) problem = [a, L] # # Assemble # assembler = Assembler(problem, mesh) assembler.assemble() # # Form linear system # A = assembler.get_matrix() b = assembler.get_vector() system = LinearSystem(u, A=A, b=b) # # Dirichlet conditions # # Boundary functions bm_left = lambda x: np.abs(x) < 1e-9 bm_rght = lambda x: np.abs(x - 1) < 1e-9 # Mark boundary regions mesh.mark_region('left', bm_left, on_boundary=True) mesh.mark_region('right', bm_rght, on_boundary=True) # Add Dirichlet constraints system.add_dirichlet_constraint('left', ue) system.add_dirichlet_constraint('right', ue) # # Solve system # #system.solve_system() system.solve_system() # # Get solution # #ua = system.get_solution(as_function=True) uaa = system.get_solution(as_function=True) #uaa = uaa.data().ravel() # Compare with exact solution #self.assertTrue(np.allclose(ua.data(), ue.data())) self.assertTrue(np.allclose(uaa.data(), ue.data()))
def test05_2d_dirichlet(self): """ Two dimensional Dirichlet problem with hanging nodes """ # # Define mesh # mesh = QuadMesh(resolution=(1, 2)) mesh.cells.get_child(1).mark(1) mesh.cells.refine(refinement_flag=1) mesh.cells.refine() # # Mark left and right boundaries # bm_left = lambda x, dummy: np.abs(x) < 1e-9 bm_right = lambda x, dummy: np.abs(1 - x) < 1e-9 mesh.mark_region('left', bm_left, entity_type='half_edge') mesh.mark_region('right', bm_right, entity_type='half_edge') for etype in ['Q1', 'Q2', 'Q3']: # # Element # element = QuadFE(2, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # # Basis # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') uy = Basis(dofhandler, 'uy') # # Construct forms # ue = Nodal(f=lambda x: x[:, 0], basis=u) ax = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux) ay = Form(kernel=Kernel(Constant(1)), trial=uy, test=uy) L = Form(kernel=Kernel(Constant(0)), test=u) problem = [ax, ay, L] # # Assemble # assembler = Assembler(problem, mesh) assembler.assemble() # # Get system matrices # A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(u, A=A, b=b) # # Constraints # # Add dirichlet conditions system.add_dirichlet_constraint('left', ue) system.add_dirichlet_constraint('right', ue) # # Solve # system.solve_system() #system.resolve_constraints() # # Check solution # ua = system.get_solution(as_function=True) self.assertTrue(np.allclose(ua.data(), ue.data()))
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()))
# Assembler system # assembler = Assembler([problem], mesh) assembler.add_dirichlet(None, ue) assembler.assemble() # # Get solution # ua = assembler.solve() # # Compute the error # e_vec = ua[:, None] - ue.interpolant(dofhandler).data() efn = Nodal(data=e_vec, basis=u, dim=2) # # Record error # errors[resolution][eps][etype] = max(np.abs(e_vec)) headers = ('Resolution', 'Q1:1', 'Q1:1e-3', 'Q1:1e-6', 'Q2:1', 'Q2:1e-3', 'Q2:1e-6') print('{:<12} {:<10} {:<10} {:<10} {:<10} {:<10} {:<10}'.format(*headers)) for resolution in errors.keys(): er = errors[resolution] row = [resolution[0],er[1]['Q1'][0], er[1e-3]['Q1'][0], er[1e-6]['Q1'][0], \ er[1]['Q2'][0], er[1e-3]['Q2'][0], er[1e-6]['Q2'][0]]
phiy_1 = Basis(dQ1, 'vy') phi_2 = Basis(dQ2) phix_2 = Basis(dQ2, 'vx') phiy_2 = Basis(dQ2, 'vy') # # Define Random field # cov = Covariance(dQ0, name='gaussian', parameters={'l': 0.01}) cov.compute_eig_decomp() q = GaussianField(dQ0.n_dofs(), K=cov) # Sample Random field n_samples = 100 eq = Nodal(basis=phi_0, data=np.exp(q.sample(n_samples))) plot.contour(eq, n_sample=25) # # Compute state # # Define weak form state = [[ Form(eq, test=phix_1, trial=phix_1), Form(eq, test=phiy_1, trial=phiy_1), Form(1, test=phi_1) ], [Form(1, test=phi_1, flag='dmn')]] # Assemble system
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 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))
state = LS(phi) state.add_dirichlet_constraint('left', 1) state.add_dirichlet_constraint('right', 0) state.set_constraint_relation() adjoint = LS(phi) adjoint.add_dirichlet_constraint('left', 0) adjoint.add_dirichlet_constraint('right', 0) adjoint.set_constraint_relation() # ============================================================================= # System Parameters # ============================================================================= # Target y_target = Nodal(f=lambda x: 3 - 4 * (x[:, 0] - 1)**2, dim=1, dofhandler=dh) y_data = y_target.data() # Regularization parameter #gamma = 0.00001 gamma = 1e-5 # Inital guess u = np.zeros((m, 1)) # # Diffusion Parameter # # Initialize diffusion q = Nodal(data=np.empty((m, 1)), dofhandler=dh)
phi = Basis(dQ1) phi_x = Basis(dQ1, derivative='vx') phi_y = Basis(dQ1, derivative='vy') # # Diffusion Parameter # # Covariance Matrix K = Covariance(dQ1, name='exponential', parameters={'sgm': 1, 'l': 0.1}) # Gaussian random field θ tht = GaussianField(dQ1.n_dofs(), K=K) # Sample from field tht_fn = Nodal(data=tht.sample(n_samples=3), basis=phi) plot = Plot() plot.contour(tht_fn) # # Advection # v = [0.1, -0.1] plot.mesh(mesh, regions=[('in', 'edge'), ('out', 'edge'), ('reg', 'cell')]) k = Kernel(tht_fn, F=lambda tht: np.exp(tht)) adv_diff = [ Form(k, trial=phi_x, test=phi_x), Form(k, trial=phi_y, test=phi_y), Form(0, test=phi),