def boundary_definition_3D(self, my_d, model): """ @description: Get boundary definition of 3D detector with Possion and Laplace @Modify: 2021/08/31 """ bc_l = [] p_ele, n_ele = self.model_para(my_d, model) x_list = [] y_list = [] radius = my_d.e_tr[0][2] for i in range(len(my_d.e_tr)): e_i = my_d.e_tr[i] x_list.append(e_i[0]) y_list.append(e_i[1]) str_e = "x[0]>={e_0}-{e_2} && x[0]<={e_0}+"\ +"{e_2} && x[1]>={e_1}-{e_2} && "\ +"x[1]<={e_1}+{e_2} && x[2]>={e_3} \ && x[2]<={e_4} && on_boundary" elec_p = str_e.format(e_0=e_i[0], e_1=e_i[1], e_2=e_i[2], e_3=e_i[3], e_4=e_i[4]) if e_i[5] == "p": bc = fenics.DirichletBC(self.V, p_ele, elec_p) else: bc = fenics.DirichletBC(self.V, n_ele, elec_p) bc_l.append(bc) bc = self.out_column(x_list, y_list, radius, model, my_d) bc_l.append(bc) return bc_l
def main(): domain = UPDomain(mesh, IsoStVenant({'mu': 1}) # 'lambda': 1}), # user_output_fn=output_fn ) lam = 2 zero = fe.Constant(0) pull = fe.Expression('time*(lam - 1.)', time=0, lam=lam, degree=1) step1 = StaticStep( domain=domain, dbcs=[ fe.DirichletBC(domain.V.sub(0), zero, 'on_boundary && near(x[0], 0)'), fe.DirichletBC(domain.V.sub(1), zero, 'on_boundary && near(x[1], 0)'), fe.DirichletBC(domain.V.sub(2), zero, 'on_boundary && near(x[2], 0)'), fe.DirichletBC(domain.V.sub(0), pull, 'on_boundary && near(x[0], 1.)'), ], t_start=0, t_end=1., dt0=fe.Expression('dt', dt=0.1, degree=1), expressions=[pull]) solver = SolidMechanicsSolver([step1]) solver.solve() plt.plot(lams, stress) plt.show()
def boundary_conditions(self): return [ fenics.DirichletBC(self.function_space.sub(1), (1., 0.), self.lid), fenics.DirichletBC(self.function_space.sub(1), (0., 0.), self.fixed_walls) ]
def boundary_conditions(self): return [ fenics.DirichletBC(self.function_space.sub(2), self.hot_wall_temperature, self.hot_wall), fenics.DirichletBC(self.function_space.sub(2), self.cold_wall_temperature, self.cold_wall) ]
def set_bcs_staggered(self): self.middle.mark(self.boundaries, 1) self.presLoad = fe.Expression("t", t=0.0, degree=1) BC_u_left = fe.DirichletBC(self.U, fe.Constant((0., 0.)), self.left, method='pointwise') BC_u_right = fe.DirichletBC(self.U.sub(1), fe.Constant(0.), self.right, method='pointwise') BC_u_middle = fe.DirichletBC(self.U.sub(1), self.presLoad, self.middle, method='pointwise') self.BC_u = [BC_u_left, BC_u_right, BC_u_middle] self.BC_d = []
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 set_bcs_staggered(self): self.upper.mark(self.boundaries, 1) self.presLoad = fe.Expression(("t", 0), t=0.0, degree=1) BC_u_lower = fe.DirichletBC(self.U, fe.Constant((0., 0.)), self.lower) BC_u_upper = fe.DirichletBC(self.U, self.presLoad, self.upper) BC_u_left = fe.DirichletBC(self.U.sub(1), fe.Constant(0), self.left) BC_u_right = fe.DirichletBC(self.U.sub(1), fe.Constant(0), self.right) self.BC_u = [BC_u_lower, BC_u_upper, BC_u_left, BC_u_right] self.BC_d = []
def set_bcs_staggered(self): self.lower.mark(self.boundaries, 1) self.presLoad = fe.Expression("t", t=0.0, degree=1) BC_u_lower = fe.DirichletBC(self.U, fe.Constant((0., 0.)), self.lower) BC_u_segment = fe.DirichletBC(self.U.sub(1), self.presLoad, self.segment, method="pointwise") self.BC_u = [BC_u_lower, BC_u_segment] self.BC_d = []
def set_bcs_staggered(self): self.upper.mark(self.boundaries, 1) self.presLoad = fe.Expression("t", t=0.0, degree=1) BC_u_lower = fe.DirichletBC(self.U.sub(1), fe.Constant(0), self.lower) BC_u_upper = fe.DirichletBC(self.U.sub(1), self.presLoad, self.upper) BC_u_corner = fe.DirichletBC(self.U.sub(0), fe.Constant(0.0), self.corner, method='pointwise') self.BC_u = [BC_u_lower, BC_u_upper, BC_u_corner] self.BC_d = []
def boundary_conditions(self): return [ fenics.DirichletBC(self.function_space.sub(1), (0., 0.), self.walls), fenics.DirichletBC(self.function_space.sub(2), self.T(self.hot_wall_temperature_degC), self.hot_wall), fenics.DirichletBC(self.function_space.sub(2), self.T(self.cold_wall_temperature_degC), self.cold_wall) ]
def create_bcs_list(function_space, value, boundaries, idcs, **kwargs): """Create several Dirichlet boundary conditions at once. Wraps multiple Dirichlet boundary conditions into a list, in case they have the same value but are to be defined for multiple boundaries with different markers. Particularly useful for defining homogeneous boundary conditions. Parameters ---------- function_space : dolfin.function.functionspace.FunctionSpace The function space onto which the BCs should be imposed on. value : dolfin.function.constant.Constant or dolfin.function.expression.Expression or dolfin.function.function.Function or float or tuple(float) The value of the boundary condition. Has to be compatible with the function_space, so that it could also be used as ``fenics.DirichletBC(function_space, value, ...)``. boundaries : dolfin.cpp.mesh.MeshFunctionSizet The :py:class:`fenics.MeshFunction` object representing the boundaries. idcs : list[int] or int A list of indices / boundary markers that determine the boundaries onto which the Dirichlet boundary conditions should be applied to. Can also be a single integer for a single boundary. Returns ------- list[dolfin.fem.dirichletbc.DirichletBC] A list of DirichletBC objects that represent the boundary conditions. Examples -------- Generate homogeneous Dirichlet boundary conditions for all 4 sides of the unit square :: from fenics import * import cashocs mesh, _, _, _, _, _ = cashocs.regular_mesh(25) V = FunctionSpace(mesh, 'CG', 1) bcs = cashocs.create_bcs_list(V, Constant(0), boundaries, [1,2,3,4]) """ bcs_list = [] if type(idcs) == list: for i in idcs: bcs_list.append( fenics.DirichletBC(function_space, value, boundaries, i, **kwargs)) elif type(idcs) == int: bcs_list.append( fenics.DirichletBC(function_space, value, boundaries, idcs, **kwargs)) return bcs_list
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_initial_problem_v2(self): V = fn.FunctionSpace(self.mesh, 'Lagrange', 2) # Define test and trial functions. v = fn.TestFunction(V) u = fn.TrialFunction(V) # Define radial coordinates. r = fn.SpatialCoordinate(self.mesh)[0] # Define the relative permittivity. class relative_perm(fn.UserExpression): def __init__(self, markers, subdomain_ids, **kwargs): super().__init__(**kwargs) self.markers = markers self.subdomain_ids = subdomain_ids def eval_cell(self, values, x, cell): if self.markers[cell.index] == self.subdomain_ids['Vacuum']: values[0] = 1. else: values[0] = 10. rel_perm = relative_perm(self.subdomains, self.subdomains_ids, degree=0) # Define the variational form. a = r * rel_perm * fn.inner(fn.grad(u), fn.grad(v)) * self.dx L = fn.Constant(0.) * v * self.dx # Define the boundary conditions. bc1 = fn.DirichletBC(V, fn.Constant(0.), self.boundaries, self.boundaries_ids['Bottom_Wall']) bc4 = fn.DirichletBC(V, fn.Constant(-10.), self.boundaries, self.boundaries_ids['Top_Wall']) bcs = [bc1, bc4] # Solve the problem. init_phi = fn.Function(V) fn.solve(a == L, init_phi, bcs) return Poisson.block_project(init_phi, self.mesh, self.restrictions_dict['vacuum_rtc'], self.subdomains, self.subdomains_ids['Vacuum'], space_type='scalar')
def out_column(self, x_list, y_list, radius, model, my_d): x_min = min(x_list) - radius x_max = max(x_list) + radius y_min = min(y_list) - radius y_max = max(y_list) + radius x_center = my_d.e_tr[0][0] y_center = my_d.e_tr[0][1] str_e = "(x[0]-{e_0})*(x[0]-{e_0}) +(x[1]-{e_1})*(x[1]-{e_1}) >= {e_2}*{e_2}" elec_p = str_e.format(e_0=x_center, e_1=y_center, e_2=my_d.e_gap) if model == "Possion": bc = fenics.DirichletBC(self.V, 0.0, elec_p) elif model == "Laplace": bc = fenics.DirichletBC(self.V, 1.0, elec_p) return bc
def applyRightPotentialDirichletBC(self, u0): """FEniCS Dirichlet BC u0 for potential at right boundary.""" self.boundary_conditions.extend([ fn.DirichletBC( self.W.sub(0), u0, lambda x, on_boundary: self.boundary_R(x, on_boundary)) ])
def applyLeftConcentrationDirichletBC(self, k, c0): """FEniCS Dirichlet BC c0 for k'th ion species at left boundary.""" self.boundary_conditions.extend([ fn.DirichletBC( self.W.sub(k + 1), c0, lambda x, on_boundary: self.boundary_L(x, on_boundary)) ])
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 applyCentralReferenceConcentrationConstraint(self, k, c0): """FEniCS Dirichlet BC c0 for k'th ion species at right boundary.""" self.boundary_conditions.extend([ fn.DirichletBC( self.W.sub(k + 1), c0, lambda x, on_boundary: self.boundary_C(x, on_boundary)) ])
def getDirichletBCs(self, vectorspace, *args, **kwargs): dbcs = [] for (dict_key, dict_value) in self.bcs.iteritems(): if dict_value["type"] == 'Dirichlet': bc = fenics.DirichletBC(vectorspace, dict_value["value"], self.markers[dict_key], dict_value.get("marked", 1), *args, **kwargs) dbcs.append(bc) return dbcs
def get_nodepoints_from_boundary(mesh, boundaries, boundary_id): # Define an auxiliary Function Space. V = fn.FunctionSpace(mesh, 'Lagrange', 1) # Get the dimension of the auxiliary Function Space. F = V.dim() # Generate a map of the degrees of freedom (=nodes for this case). dofmap = V.dofmap() dofs = dofmap.dofs() # Apply a Dirichlet BC to a function to get nodes where the bc is applied. u = fn.Function(V) bc = fn.DirichletBC(V, fn.Constant(1.0), boundaries, 8) bc.apply(u.vector()) dofs_bc = list(np.where(u.vector()[:] == 1.0)) dofs_x = V.tabulate_dof_coordinates().reshape(F, mesh.topology().dim()) coords_r = [] coords_z = [] # Get the coordinates of the nodes on the meniscus. for dof, coord in zip(dofs, dofs_x): if dof in dofs_bc[0]: coords_r.append(coord[0]) coords_z.append(coord[1]) coords_r = np.sort(coords_r) coords_z = np.sort(coords_z)[::-1] return coords_r, coords_z
def fenics_solve(f): u = fn.Function(V, name="State") v = fn.TestFunction(V) F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f * v) * ufl.dx bcs = [fn.DirichletBC(V, 0.0, "on_boundary")] fn.solve(F == 0, u, bcs) return u, F, bcs
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 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 set_constant_concentration(self, value): function_space_copy = fenics.FunctionSpace(self.mesh, self.element()) new_solution = fenics.Function(function_space_copy) new_solution.vector()[:] = self.solution.vector() class WholeDomain(fenics.SubDomain): def inside(self, x, on_boundary): return True hack = fenics.DirichletBC(function_space_copy.sub(3), value, WholeDomain()) hack.apply(new_solution.vector()) for solution in self._solutions: solution.vector()[:] = new_solution.vector() for i in range(len(self._times)): self._times[i] = 0.
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 set_solution_on_subdomain(self, subdomain, values): """ Abuse `fenics.DirichletBC` to set values of a function on a subdomain. Parameters ---------- subdomain `fenics.SubDomain` values container of objects that would typically be passed to `fenics.DirichletBC` as the values of the boundary condition, one for each subspace of the mixed finite element solution space """ function_space = fenics.FunctionSpace(self.mesh.leaf_node(), self.element()) new_solution = fenics.Function(function_space) new_solution.vector()[:] = self.solution.vector() for function_subspace_index in range(len(fenics.split(self.solution))): hack = fenics.DirichletBC( function_space.sub(function_subspace_index), values[function_subspace_index], subdomain) hack.apply(new_solution.vector()) self.solution.vector()[:] = new_solution.vector()
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_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 test_1d_velocity_unit__ci__(): mesh = fenics.UnitIntervalMesh(5) V = fenics.VectorFunctionSpace(mesh, "P", 1) u = fenics.Function(V) bc = fenics.DirichletBC(V, [10.0], "x[0] < 0.5") print(bc.get_boundary_values())
def dirichlet(self, expression, bc_fnc=None): """ This function defines Dirichlet boundary condition based on the given expression on the boundary. Args: expression (string): The expression used to evaluate the value of the unknown on the boundary. bc_fnc (fnc): The function which evaluates which nodes belong to the boundary to which the provided expression is applied as displacement. """ bc_fnc = bc_fnc or self._default_bc_fnc return FEN.DirichletBC(self._job.V, expression, bc_fnc)