def __init__(me, V, max_smooth_vectors=50): R = fenics.FunctionSpace(V.mesh(), 'R', 0) u_trial = fenics.TrialFunction(V) v_test = fenics.TestFunction(V) c_trial = fenics.TrialFunction(R) d_test = fenics.TestFunction(R) a11 = fenics.inner(fenics.grad(u_trial), fenics.grad(v_test)) * fenics.dx a12 = c_trial * v_test * fenics.dx a21 = u_trial * d_test * fenics.dx A11 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a11)) A12 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a12)) A21 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a21)) me.A = sps.bmat([[A11, A12], [A21, None]]).tocsc() solve_A = spla.factorized(me.A) m = u_trial * v_test * fenics.dx me.M = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(m)).tocsc() solve_M = spla.factorized(me.M) def solve_neumann(f_vec): fe_vec = np.concatenate([f_vec, np.array([0])]) ue_vec = solve_A(fe_vec) u_vec = ue_vec[:-1] return u_vec me.solve_neumann_linop = spla.LinearOperator((V.dim(), V.dim()), matvec=solve_neumann) me.solve_M_linop = spla.LinearOperator((V.dim(), V.dim()), matvec=solve_M) ee, UU = spla.eigsh(me.solve_neumann_linop, k=max_smooth_vectors - 1, M=me.solve_M_linop, which='LM') me.U_smooth = np.zeros((V.dim(), max_smooth_vectors)) const_fct = np.ones(V.dim()) me.U_smooth[:, 0] = const_fct / np.sqrt( np.dot(const_fct, me.M * const_fct)) me.U_smooth[:, 1:] = solve_M(UU[:, ::-1]) me.k = 0
def _assemble(self) -> Tuple[fenics.PETScMatrix, fenics.PETScMatrix]: """Construct matrices for generalized eigenvalue problem. Assemble the left and the right hand side of the eigenfunction equation into the corresponding matrices. Returns ------- A : fenics.PETScMatrix Matrix corresponding to the form $a(u, v)$. B : fenics.PETScMatrix Matrix corresponding to the form $b(u, v)$. """ V = self.vector_space u = fenics.TrialFunction(V) v = fenics.TestFunction(V) a, b = self._construct_eigenproblem(u, v) A = fenics.PETScMatrix() B = fenics.PETScMatrix() fenics.assemble(a * fenics.dx, tensor=A) fenics.assemble(b * fenics.dx, tensor=B) return A, B
def __init__(self, K): # Variables x, y = sym.symbols('x[0], x[1]', real=True, positive=True) f = sym.Function('f')(x, y) grid = np.linspace(0, 1, K + 2)[1:-1] x_obs, y_obs = np.meshgrid(grid, grid) self.x_obs, self.y_obs = x_obs.reshape(K * K), y_obs.reshape(K * K) # --- THIS PART USED TO NOT BE PARALELLIZABLE --- # # Create mesh and define function space n_mesh = 80 self.mesh = fen.UnitSquareMesh(n_mesh, n_mesh) self.f_space = fen.FunctionSpace(self.mesh, 'P', 2) # Define boundary condition # u_boundary = fen.Expression('x[0] + x[1]', degree=2) u_boundary = fen.Expression('0', degree=2) self.bound_cond = fen.DirichletBC(self.f_space, u_boundary, lambda x, on_boundary: on_boundary) # Define variational problem self.trial_f = fen.TrialFunction(self.f_space) self.test_f = fen.TestFunction(self.f_space) rhs = fen.Constant(50) self.lin_func = rhs * self.test_f * fen.dx
def generate_mesh(self, typ, order, resolution): self._mesh = mshr.generate_mesh(self._domain, resolution) self.input['mesh'] = self._mesh self._V = FEN.FunctionSpace(self._mesh, typ, order) self.input['V'] = self._V self._u = FEN.TrialFunction(self._V) self._v = FEN.TestFunction(self._V)
def solver(f, u_D, bc_funs, ndim, length, nx, ny, nz=None, degree=1): """Fenics 求解器 Args: f (Expression): [description] u_D (Expression): [description] bc_funs (List[Callable]): [description] ndim (int): [description] length (float): [description] nx (int): [description] ny (int): [description] nz (int, optional): [description]. Defaults to None. degree (int, optional): [description]. Defaults to 1. Returns: Function: 解 u """ mesh = get_mesh(length, nx, ny, nz) V = fs.FunctionSpace(mesh, "P", degree) bcs = [fs.DirichletBC(V, u_D, bc) for bc in bc_funs] u = fs.TrialFunction(V) v = fs.TestFunction(V) FF = fs.dot(fs.grad(u), fs.grad(v)) * fs.dx - f * v * fs.dx a = fs.lhs(FF) L = fs.rhs(FF) u = fs.Function(V) fs.solve(a == L, u, bcs) return u
def eva(self, num): # construct basis functions, Set num points corresponding to num basis functions basPoints = np.linspace(0, 1, num) dx = basPoints[1] - basPoints[0] aa, bb, cc = -dx, 0.0, dx for x_p in basPoints: self.theta.append( fe.interpolate( fe.Expression( 'x[0] < a || x[0] > c ? 0 : (x[0] >=a && x[0] <= b ? (x[0]-a)/(b-a) : 1-(x[0]-b)/(c-b))', degree=2, a=aa, b=bb, c=cc), self.Vc)) aa, bb, cc = aa + dx, bb + dx, cc + dx u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu) left = fe.inner(self.al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * fe.dx right = self.f * u_test * fe.dx def boundaryD(x, on_boundary): return on_boundary and fe.near(x[1], 1.0) for i in range(num): uH = fe.Function(self.Vu) bcD = fe.DirichletBC(self.Vu, self.theta[i], boundaryD) left_m, right_m = fe.assemble_system(left, right, bcD) fe.solve(left_m, uH.vector(), right_m) self.sol.append(uH)
def vjp_assemble_impl( g: np.array, fenics_output_form: ufl.Form, fenics_inputs: List[FenicsVariable], ) -> Tuple[np.array]: """Computes the gradients of the output with respect to the inputs.""" # Compute derivative form for the output with respect to each input fenics_grads_forms = [] for fenics_input in fenics_inputs: # Need to construct direction (test function) first if isinstance(fenics_input, fenics.Function): V = fenics_input.function_space() elif isinstance(fenics_input, fenics.Constant): mesh = fenics_output_form.ufl_domain().ufl_cargo() V = fenics.FunctionSpace(mesh, "Real", 0) else: raise NotImplementedError dv = fenics.TestFunction(V) fenics_grad_form = fenics.derivative(fenics_output_form, fenics_input, dv) fenics_grads_forms.append(fenics_grad_form) # Assemble the derivative forms fenics_grads = [fenics.assemble(form) for form in fenics_grads_forms] # Convert FEniCS gradients to jax array representation jax_grads = (None if fg is None else np.asarray(g * fenics_to_numpy(fg)) for fg in fenics_grads) jax_grad_tuple = tuple(jax_grads) return jax_grad_tuple
def fenics_solve(f): u = fa.Function(V, name="State") v = fn.TestFunction(V) F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f * v) * ufl.dx bcs = [fa.DirichletBC(V, 0.0, "on_boundary")] fa.solve(F == 0, u, bcs) return u
def solve_pde(self): u = fe.Function(self.function_space) v = fe.TestFunction(self.function_space) u_old = fe.project(self.u_0, self.function_space) # Todo: Average right hand side if we choose it non-constant flux = self.dt * fe.dot( self.composed_diff_coef * (fe.grad(u) + self.drift_function(u)), fe.grad(v)) * fe.dx bilin_part = u * v * fe.dx + flux funtional_part = self.rhs * v * self.dt * fe.dx + u_old * v * fe.dx full_form = bilin_part - funtional_part num_steps = int(self.T / self.dt) + 1 bc = fe.DirichletBC(self.function_space, self.u_boundary, MembraneSimulator.full_boundary) for n in range(num_steps): print("Step %d" % n) self.time += self.dt fe.solve(full_form == 0, u, bc) # fe.plot(u) # plt.show() # print(fe.errornorm(u_old, u)) u_old.assign(u) self.file << (u, self.time) f = fe.plot(u) plt.rc('text', usetex=True) plt.colorbar(f, format='%.0e') plt.title(r'Macroscopic density profile of $u(x,t)$ at $t=1$') plt.xlabel(r'$x_1$') plt.ylabel(r'$x_2$') plt.show()
def __call__(self, mesh, V=None, Vc=None): boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc = SetupUnitMeshHelper( mesh, V, Vc) self._ds_markers = boundarymarkers self._dx_markers = domainmarkers self._dx = dx self._ds = ds self._boundaries = boundaries self._subdomains = self._boundaries u = df.TrialFunction(V) v = df.TestFunction(V) alpha = df.Function(Vc, name='conductivity') alpha.vector()[:] = 1 def set_alpha(x): alpha.vector()[:] = x self._set_alpha = set_alpha a = alpha * df.inner(df.grad(u), df.grad(v)) * dx return a, set_alpha, alpha, V, Vc
def __setup_decrease_computation(self): """Initializes attributes and solver for the frobenius norm check. Returns ------- None """ if not self.angle_change > 0: raise ConfigError('MeshQuality', 'angle_change', 'This parameter has to be positive.') options = [[['ksp_type', 'preonly'], ['pc_type', 'jacobi'], ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16], ['ksp_atol', 1e-20], ['ksp_max_it', 1000]]] self.ksp_frobenius = PETSc.KSP().create() _setup_petsc_options([self.ksp_frobenius], options) self.trial_dg0 = fenics.TrialFunction(self.form_handler.DG0) self.test_dg0 = fenics.TestFunction(self.form_handler.DG0) if not (self.angle_change == float('inf')): self.search_direction_container = fenics.Function( self.form_handler.deformation_space) self.a_frobenius = self.trial_dg0 * self.test_dg0 * self.dx self.L_frobenius = fenics.sqrt( fenics.inner(fenics.grad(self.search_direction_container), fenics.grad(self.search_direction_container)) ) * self.test_dg0 * self.dx
def _make_variational_problem(V): """ Formulate the variational problem a(u, v) = L(v). Parameters ---------- V: FEniCS.FunctionSpace Returns ------- a, L: FEniCS.Expression Variational forms. """ # Define trial and test functions u = F.TrialFunction(V) v = F.TestFunction(V) # Collect Neumann conditions ds = F.Measure("ds", domain=mesh, subdomain_data=boundary_markers) integrals_N = [] for i in boundary_conditions: if isinstance(boundary_conditions[i], dict): if "Neumann" in boundary_conditions[i]: if boundary_conditions[i]["Neumann"] != 0: g = boundary_conditions[i]["Neumann"] integrals_N.append(g[0] * v * ds(i)) # Define variational problem a = F.inner(u, v) * F.dx + (DT**2) * (C**2) * F.inner( F.grad(u), F.grad(v)) * F.dx L = ((DT**2) * f[0] + 2 * u_nm1 - u_nm2) * v * F.dx + (DT**2) * (C**2) * sum(integrals_N) return a, L
def setup_vectorspace(mesh): """setup""" V = fe.VectorFunctionSpace(mesh, "CG", 1, dim=3) v = fe.TestFunction(V) u = fe.TrialFunction(V) m = fe.Function(V) Heff = fe.Function(V) return m, Heff, u, v, V
def compute_mesh_volume(self): one = fe.Constant(1) DG = fe.FunctionSpace(self.mesh, 'DG', 0) v = fe.TestFunction(DG) L = v * one * fe.dx b = fe.assemble(L) self.mesh_volume = b.get_local().sum()
def geneForwardMatrix(self, q_fun=fe.Constant(0.0), fR=fe.Constant(0.0), \ fI=fe.Constant(0.0)): if self.haveFunctionSpace == False: self.geneFunctionSpace() xx, yy, dPML, sig0_, p_ = self.domain.xx, self.domain.yy, self.domain.dPML,\ self.domain.sig0, self.domain.p # define the coefficents induced by PML sig1 = fe.Expression('x[0] > x1 && x[0] < x1 + dd ? sig0*pow((x[0]-x1)/dd, p) : (x[0] < 0 && x[0] > -dd ? sig0*pow((-x[0])/dd, p) : 0)', degree=3, x1=xx, dd=dPML, sig0=sig0_, p=p_) sig2 = fe.Expression('x[1] > x2 && x[1] < x2 + dd ? sig0*pow((x[1]-x2)/dd, p) : (x[1] < 0 && x[1] > -dd ? sig0*pow((-x[1])/dd, p) : 0)', degree=3, x2=yy, dd=dPML, sig0=sig0_, p=p_) sR = fe.as_matrix([[(1+sig1*sig2)/(1+sig1*sig1), 0.0], [0.0, (1+sig1*sig2)/(1+sig2*sig2)]]) sI = fe.as_matrix([[(sig2-sig1)/(1+sig1*sig1), 0.0], [0.0, (sig1-sig2)/(1+sig2*sig2)]]) cR = 1 - sig1*sig2 cI = sig1 + sig2 # define the coefficients with physical meaning angl_fre = self.kappa*np.pi angl_fre2 = fe.Constant(angl_fre*angl_fre) # define equations u_ = fe.TestFunction(self.V) du = fe.TrialFunction(self.V) u_R, u_I = fe.split(u_) duR, duI = fe.split(du) def sigR(v): return fe.dot(sR, fe.nabla_grad(v)) def sigI(v): return fe.dot(sI, fe.nabla_grad(v)) F1 = - fe.inner(sigR(duR)-sigI(duI), fe.nabla_grad(u_R))*(fe.dx) \ - fe.inner(sigR(duI)+sigI(duR), fe.nabla_grad(u_I))*(fe.dx) \ - fR*u_R*(fe.dx) - fI*u_I*(fe.dx) a2 = fe.inner(angl_fre2*q_fun*(cR*duR-cI*duI), u_R)*(fe.dx) \ + fe.inner(angl_fre2*q_fun*(cR*duI+cI*duR), u_I)*(fe.dx) \ # define boundary conditions def boundary(x, on_boundary): return on_boundary bc = [fe.DirichletBC(self.V.sub(0), fe.Constant(0.0), boundary), \ fe.DirichletBC(self.V.sub(1), fe.Constant(0.0), boundary)] a1, L1 = fe.lhs(F1), fe.rhs(F1) self.u = fe.Function(self.V) self.A1 = fe.assemble(a1) self.b1 = fe.assemble(L1) self.A2 = fe.assemble(a2) bc[0].apply(self.A1, self.b1) bc[1].apply(self.A1, self.b1) bc[0].apply(self.A2) bc[1].apply(self.A2) self.A = self.A1 + self.A2
def _solve_pde(self, diff_coef): # Actual PDE solver for any coefficient diff_coef u = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) a = fe.dot(diff_coef * fe.grad(u), fe.grad(v)) * fe.dx L = self.f * v * fe.dx bc = fe.DirichletBC(self.function_space, self.bc_function, PoissonSolver.boundary) fe.solve(a == L, self.solution, bc)
def solve_problem_variational_form(self): u = fa.Function(self.V) du = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) E = self._energy_density(u) * fa.dx dE = fa.derivative(E, u, v) jacE = fa.derivative(dE, u, du) fa.solve(dE == 0, u, self.bcs, J=jacE) return u
def test_formulation_1_extrap_1_material(): ''' Test function formulation() with 1 extrinsic trap and 1 material ''' dt = 1 traps = [{ "energy": 1, "materials": [1], "type": "extrinsic" }] materials = [{ "alpha": 1, "beta": 2, "density": 3, "borders": [0, 1], "E_diff": 4, "D_0": 5, "id": 1 }] mesh = fenics.UnitIntervalMesh(10) V = fenics.VectorFunctionSpace(mesh, 'P', 1, 2) W = fenics.FunctionSpace(mesh, 'P', 1) u = fenics.Function(V) u_n = fenics.Function(V) v = fenics.TestFunction(V) n = fenics.interpolate(fenics.Expression('1', degree=0), W) solutions = list(fenics.split(u)) previous_solutions = list(fenics.split(u_n)) testfunctions = list(fenics.split(v)) extrinsic_traps = [n] mf = fenics.MeshFunction('size_t', mesh, 1, 1) dx = fenics.dx(subdomain_data=mf) temp = fenics.Expression("300", degree=0) flux_ = fenics.Expression("10000", degree=0) F, expressions = FESTIM.formulation( traps, extrinsic_traps, solutions, testfunctions, previous_solutions, dt, dx, materials, temp, flux_) expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \ testfunctions[0]*dx expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \ fenics.dot( fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1) expected_form += -flux_*testfunctions[0]*dx + \ ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[1]*dx expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \ solutions[0] * (extrinsic_traps[0] - solutions[1]) * \ testfunctions[1]*dx(1) expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \ testfunctions[1]*dx(1) expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[0]*dx assert expected_form.equals(F) is True
def avg_condition_number(mesh): """Computes average mesh quality based on the condition number of the reference mapping. This quality criterion uses the condition number (in the Frobenius norm) of the (linear) mapping from the elements of the mesh to the reference element. Computes the average of the condition number over all elements. Parameters ---------- mesh : dolfin.cpp.mesh.Mesh The mesh, whose quality shall be computed. Returns ------- float The average mesh quality based on the condition number. """ DG0 = fenics.FunctionSpace(mesh, 'DG', 0) jac = Jacobian(mesh) inv = JacobianInverse(mesh) options = [ ['ksp_type', 'preonly'], ['pc_type', 'jacobi'], ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16], ['ksp_atol', 1e-20], ['ksp_max_it', 1000] ] ksp = PETSc.KSP().create() _setup_petsc_options([ksp], [options]) dx = fenics.Measure('dx', mesh) a = fenics.TrialFunction(DG0)*fenics.TestFunction(DG0)*dx L = fenics.sqrt(fenics.inner(jac, jac))*fenics.sqrt(fenics.inner(inv, inv))*fenics.TestFunction(DG0)*dx cond = fenics.Function(DG0) A, b = _assemble_petsc_system(a, L) _solve_linear_problem(ksp, A, b, cond.vector().vec(), options) cond.vector().apply('') return np.average(np.sqrt(mesh.geometric_dimension()) / cond.vector()[:])
def fenics_p_electric(self, my_d): """ @description: Solve poisson equation to get potential and electric field @Modify: 2021/08/31 """ if "plugin3D" in self.det_model: bc_l = [] bc_l = self.boundary_definition_3D(my_d, "Possion") elif "planar3D" in self.det_model: bc_l = self.boundary_definition_2D(my_d, "Possion") u = fenics.TrialFunction(self.V) v = fenics.TestFunction(self.V) if self.det_dic['name'] == "lgad3D": if self.det_dic['part'] == 2: bond = self.det_dic['bond1'] doping_avalanche = self.f_value(my_d, self.det_dic['doping1']) doping = self.f_value(my_d, self.det_dic['doping2']) f = fenics.Expression('x[2] < width ? doping1 : doping2', degree=1, width=bond, doping1=doping_avalanche, doping2=doping) elif self.det_dic['part'] == 3: bond1 = self.det_dic['bond1'] bond2 = self.det_dic['bond2'] doping1 = self.f_value(my_d, self.det_dic['doping1']) doping2 = self.f_value(my_d, self.det_dic['doping2']) doping3 = self.f_value(my_d, self.det_dic['doping3']) f = fenics.Expression( 'x[2] < bonda ? dopinga : x[2] > bondb ? dopingc : dopingb', degree=1, bonda=bond1, bondb=bond2, dopinga=doping1, dopingb=doping2, dopingc=doping3) else: print("The structure of lgad is wrong.") else: f = fenics.Constant(self.f_value(my_d)) a = fenics.dot(fenics.grad(u), fenics.grad(v)) * fenics.dx L = f * v * fenics.dx # Compute solution self.u = fenics.Function(self.V) fenics.solve(a == L, self.u, bc_l, solver_parameters=dict(linear_solver='gmres', preconditioner='ilu')) #calculate electric field W = fenics.VectorFunctionSpace(self.mesh3D, 'P', 1) self.E_field = fenics.project( fenics.as_vector((self.u.dx(0), self.u.dx(1), self.u.dx(2))), W)
def compute_operators(self): u = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) form_a = fa.inner(fa.grad(u), fa.grad(v)) * fa.dx form_b = u * v * fa.dx A = da.assemble(form_a) B = da.assemble(form_b) A_np = np.array(A.array()) B_np = np.array(B.array()) return A_np, B_np
def forward(x): u = fn.TrialFunction(V) w = fn.TestFunction(V) sigma = lmbda * tr(sym(grad(u))) * Identity(2) + 2 * G * sym( grad(u)) # Stress R = simp(x) * inner(sigma, grad(w)) * dx - dot(b, w) * dx a, L = ufl.lhs(R), ufl.rhs(R) u = fa.Function(V) fa.solve(a == L, u, bcs) return u
def test_empty_measure(): mesh, _, _, dx, ds, dS = cashocs.regular_mesh(5) V = fenics.FunctionSpace(mesh, 'CG', 1) dm = cashocs.utils.EmptyMeasure(dx) trial = fenics.TrialFunction(V) test = fenics.TestFunction(V) assert fenics.assemble(1 * dm) == 0.0 assert (fenics.assemble(test * dm).norm('linf')) == 0.0 assert (fenics.assemble(trial * test * dm).norm('linf')) == 0.0
def _solve_cell_problems(self): # Solves the cell problems (one for each space dimension) w = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) a = self.a_y * fe.dot(fe.grad(w), fe.grad(v)) * fe.dx for i in range(self.dim): L = fe.div(self.a_y * self.e_is[i]) * v * fe.dx bc = fe.DirichletBC(self.function_space, self.bc_function, PoissonSolver.boundary) fe.solve(a == L, self.cell_solutions[i], bc) fe.plot(self.cell_solutions[i])
def create_bilinear_form_and_rhs(self): # Define variational problem u = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) self.bilinear_form = (1 + self.lam * self.dt) *\ (u * v * fe.dx) + self.dt * self.diffusion_coefficient *\ (fe.dot(fe.grad(u), fe.grad(v)) * fe.dx) self.rhs = (self.u_n + self.dt * self.rhs_fun * self.u_n) * v * fe.dx
def calTrueSol(para): nx, ny = para['mesh_N'][0], para['mesh_N'][1] mesh = fe.UnitSquareMesh(nx, ny) Vu = fe.FunctionSpace(mesh, 'P', para['P']) Vc = fe.FunctionSpace(mesh, 'P', para['P']) al = fe.Constant(para['alpha']) f = fe.Expression(para['f'], degree=5) q1 = fe.interpolate(fe.Expression(para['q1'], degree=5), Vc) q2 = fe.interpolate(fe.Expression(para['q2'], degree=5), Vc) q3 = fe.interpolate(fe.Expression(para['q3'], degree=5), Vc) theta = fe.interpolate(fe.Expression(para['q4'], degree=5), Vc) class BoundaryX0(fe.SubDomain): def inside(self, x, on_boundary): return on_boundary and fe.near(x[0], 0.0) class BoundaryX1(fe.SubDomain): def inside(self, x, on_boundary): return on_boundary and fe.near(x[0], 1.0) class BoundaryY0(fe.SubDomain): def inside(self, x, on_boundary): return on_boundary and fe.near(x[1], 0.0) class BoundaryY1(fe.SubDomain): def inside(self, x, on_boundary): return on_boundary and fe.near(x[1], 1.0) boundaries = fe.MeshFunction('size_t', mesh, mesh.topology().dim() - 1) boundaries.set_all(0) bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(), BoundaryY1() bc0.mark(boundaries, 1) bc1.mark(boundaries, 2) bc2.mark(boundaries, 3) bc3.mark(boundaries, 4) domains = fe.MeshFunction("size_t", mesh, mesh.topology().dim()) domains.set_all(0) bcD = fe.DirichletBC(Vu, theta, boundaries, 4) dx = fe.Measure('dx', domain=mesh, subdomain_data=domains) ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries) u_trial, u_test = fe.TrialFunction(Vu), fe.TestFunction(Vu) u = fe.Function(Vu) left = fe.inner(al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx right = f * u_test * dx + (q1 * u_test * ds(1) + q2 * u_test * ds(2) + q3 * u_test * ds(3)) left_m, right_m = fe.assemble_system(left, right, bcD) fe.solve(left_m, u.vector(), right_m) return u
def __init__(self, mesh, constitutive_model): W = fe.FunctionSpace(mesh, "DG", 1) super().__init__(mesh, constitutive_model, W) self.w = fe.Function(W) self.p, self.p0 = self.w, fe.Function(W) self.g = fe.TestFunction(W) self.functional = fe.inner(self.p, self.g) - fe.inner( self.constitutive_model)
def mesh_gen_default(self, intervals, typ='P', order=1): """ creates a square with sides of 1, divided by intervals by default the type of the volume associated with the mesh is considered to be Lagrangian, with order 1. """ self._mesh = FEN.UnitSquareMesh(intervals, intervals) self.input['mesh'] = self._mesh self._V = FEN.FunctionSpace(self._mesh, typ, order) self.input['V'] = self._V self._u = FEN.TrialFunction(self._V) self._v = FEN.TestFunction(self._V)
def dynamic_solver_func(ncells=10, # количество узлов на заданном итервале init_time=0, # начальный момент времени end_time=10, # конечный момент времени dxdphi=1, # производная от потенциала по х dydphi=1, # производня от потенциала по у x0=0, # начальное положение по оси х vx0=1, # проекция начальной скорости на ось х y0=0, # начальное положение по оси у vy0=1): # проекция начальной скорости на ось у """ Функция на вход которой подается производная от потенциала гравитационного поля, возвращающая координаты смещенных материальных точек (частиц). """ # генерация сетки на заданном интервале времени mesh = fen.IntervalMesh(ncells, 0, end_time-init_time) welm = fen.MixedElement([fen.FiniteElement('Lagrange', fen.interval, 2), fen.FiniteElement('Lagrange', fen.interval, 2), fen.FiniteElement('Lagrange', fen.interval, 2), fen.FiniteElement('Lagrange', fen.interval, 2)]) # генерация функционального рростаанства W = fen.FunctionSpace(mesh, welm) # постановка начальных условий задачи bcsys = [fen.DirichletBC(W.sub(0), fen.Constant(x0), 'near(x[0], 0)'), fen.DirichletBC(W.sub(1), fen.Constant(vx0), 'near(x[0], 0)'), fen.DirichletBC(W.sub(2), fen.Constant(y0), 'near(x[0], 0)'), fen.DirichletBC(W.sub(3), fen.Constant(vy0), 'near(x[0], 0)')] # опееделение тестовых функций для решения задачи up = fen.Function(W) x_cor, v_x, y_cor, v_y = fen.split(up) v1, v2, v3, v4 = fen.split(fen.TestFunction(W)) # постановка задачи drdt = v; dvdt = - grad(phi) в проекциях на оси системы координат weak_form = (x_cor.dx(0) - v_x) * v1 * fen.dx + (v_x.dx(0) + dxdphi) * v2 * fen.dx \ + (y_cor.dx(0) - v_y) * v3 * fen.dx + (v_y.dx(0) + dydphi) * v4 * fen.dx # решние поставленной задачи fen.solve(weak_form == 0, up, bcs=bcsys) # определение момента времени time = fen.Point(end_time - init_time) # расчет координат и скоростей x_end_time = up(time.x())[0] vx_end_time = up(time.x())[1] y_end_time = up(time.x())[2] vy_end_time = up(time.x())[3] return x_end_time, y_end_time, vx_end_time, vy_end_time
def solve_problem_weak_form(self): u = fa.Function(self.V) du = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) F = fa.inner(fa.grad(u), fa.grad(v)) * fa.dx - self.source * v * fa.dx J = fa.derivative(F, u, du) # The problem in this case is indeed linear, but using a nonlinear # solver doesn't hurt problem = fa.NonlinearVariationalProblem(F, u, self.bcs, J) solver = fa.NonlinearVariationalSolver(problem) solver.solve() return u