def setup_derived_attributes(self): """ Extend the boundary condition definitions to 3D. """ ConvectionCoupledMeltingOctadecanePCMBenchmarkSimulation.setup_derived_attributes( self) self.zmin = -self.depth_3d / 2. self.zmax = self.depth_3d / 2. T_hot = fenics.Constant(self.hot_wall_temperature) T_cold = fenics.Constant(self.cold_wall_temperature) self.boundary_conditions = [{ "subspace": 1, "location": self.walls, "value": (0., 0., 0.) }, { "subspace": 2, "location": self.left_wall, "value": T_hot }, { "subspace": 2, "location": self.right_wall, "value": T_cold }]
def setup_governing_form(self): """ Implement the variational form per @cite{zimmerman2018monolithic}. """ Pr = fenics.Constant(self.prandtl_number) Ste = fenics.Constant(self.stefan_number) f_B = self.make_buoyancy_function() phi = self.make_semi_phasefield_function() mu = self.make_phase_dependent_material_property_function( P_L=fenics.Constant(self.liquid_viscosity), P_S=fenics.Constant(self.solid_viscosity)) gamma = fenics.Constant(self.penalty_parameter) p, u, T = fenics.split(self.state.solution) u_t, T_t, phi_t = self.make_time_discrete_terms() psi_p, psi_u, psi_T = fenics.TestFunctions(self.function_space) dx = self.integration_metric inner, dot, grad, div, sym = fenics.inner, fenics.dot, fenics.grad, fenics.div, fenics.sym self.governing_form = ( -psi_p * (div(u) + gamma * p) + dot(psi_u, u_t + f_B(T) + dot(grad(u), u)) - div(psi_u) * p + 2. * mu(phi(T)) * inner(sym(grad(psi_u)), sym(grad(u))) + psi_T * (T_t - 1. / Ste * phi_t) + dot(grad(psi_T), 1. / Pr * grad(T) - T * u)) * dx
def __init__( self, time_order=1, integration_measure=fenics.dx(metadata={"quadrature_degree": 8}), uniform_gridsize=20, setup_solver=True): self.uniform_gridsize = uniform_gridsize self.cold_wall_temperature_before_freezing = fenics.Constant(0.1) self.cold_wall_temperature_during_freezing = fenics.Constant(-1.1) super().__init__(time_order=time_order, integration_measure=integration_measure, setup_solver=setup_solver, initial_uniform_gridsize=uniform_gridsize) self.hot_wall_temperature.assign(1.25) self.cold_wall_temperature.assign(0.25) if setup_solver: self.solver.parameters["newton_solver"]["maximum_iterations"] = 12
def setup_derived_attributes(self): """ Add attributes which should not be modified directly, related to the boundary conditions and initial values. """ CavityBenchmarkPhaseChangeSimulation.setup_derived_attributes(self) T_hot = fenics.Constant(self.hot_wall_temperature) T_cold = fenics.Constant(self.cold_wall_temperature) self.boundary_conditions = [{ "subspace": 1, "location": self.walls, "value": (0., 0.) }, { "subspace": 2, "location": self.left_wall, "value": T_hot }, { "subspace": 2, "location": self.right_wall, "value": T_cold }] self.initial_temperature = "T_hot + x[0]*(T_cold - T_hot)" self.initial_temperature = self.initial_temperature.replace( "T_hot", str(self.hot_wall_temperature)) self.initial_temperature = self.initial_temperature.replace( "T_cold", str(self.cold_wall_temperature))
def __init__(self): self.source_function = fenics.Constant(0.0) self.dirichlet_bc = fenics.Constant(0.0) self.g = fenics.Constant(0.0) self.problem_number = 0 self.integral_constraint = False self.ak = None # Use this for analytical property field
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 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 problem(self, constitutive_relation) -> ProblemForm: return ElastodynamicsForm( mass_density=1.0, eta_m=fenics.Constant(0.0), eta_k=fenics.Constant(0.0), constitutive_relation=constitutive_relation, generalized_alpha_parameters=self.alpha_params, delta_t=self.time_params.delta_t, f_ext=self.boundary_excitation.value)
def LoadCaseDefinition(LoadCase, FinalRelativeStretch, RelativeStepSize, Dimensions, BCsType=False): Normal = fe.Constant((0, 0, 1)) # Normal to moving side if LoadCase == 'Compression': InitialState = 1 if BCsType == 'Ideal': u_0 = fe.Constant((1E-3)) # Little displacement to avoid NaN values (Ogden) u_1 = fe.Expression(('(s-1)*h'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed else: u_0 = fe.Constant((0, 0, 1E-3)) # Little displacement to avoid NaN values (Ogden) u_1 = fe.Expression(('0', '0', '(s-1)*h'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed Dir = fe.Constant((0,0,1)) # Deformation direction NumberSteps = FinalRelativeStretch / RelativeStepSize # Number of steps DeltaStretch = -RelativeStepSize elif LoadCase == 'Tension': InitialState = 1 if BCsType == 'Ideal': u_0 = fe.Constant((-1E-3)) # Little displacement to avoid NaN values (Ogden) u_1 = fe.Expression(('(s-1)*h'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed else: u_0 = fe.Constant((0, 0, -1E-3)) # Little displacement to avoid NaN values (Ogden) u_1 = fe.Expression(('0', '0', '(s-1)*h'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed Dir = fe.Constant((0,0,1)) # Deformation direction NumberSteps = FinalRelativeStretch / RelativeStepSize # Number of steps DeltaStretch = RelativeStepSize elif LoadCase == 'SimpleShear': InitialState = 0 if BCsType == 'Ideal': u_0 = fe.Constant((-1E-3, 0, 0)) # Little displacement to avoid NaN values u_1 = fe.Expression(('s*h', '0', '0'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed else: u_0 = fe.Constant((-1E-3, 0, 0)) # Little displacement to avoid NaN values u_1 = fe.Expression(('s*h', '0', '0'), degree=1, s = InitialState, h = Dimensions[2] ) # Displacement imposed Dir = fe.Constant((1,0,0)) # Deformation direction NumberSteps = FinalRelativeStretch / RelativeStepSize # Number of steps DeltaStretch = RelativeStepSize else : print('Incorrect load case name') print('Load cases available are:') print('Compression') print('Tension') print('SimpleShear') return [u_0, u_1, InitialState, Dir, Normal, NumberSteps, DeltaStretch]
def sample_dirichlet_boundary_condition(self): u0 = df.Constant(0) u1 = df.Constant(1) bcs_specs = [ DirichletSpecification(u1, self._boundaries['right']), DirichletSpecification(u0, self._boundaries['left']) ] bcs_wrapper = DirichletBoundaryCondition(bcs_specs) return bcs_wrapper
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 make_semi_phasefield_function(self): """ Semi-phase-field mapping from temperature """ T_r = fenics.Constant(self.regularization_central_temperature) r = fenics.Constant(self.regularization_smoothing_parameter) def phi(T): return 0.5 * (1. + fenics.tanh((T_r - T) / r)) return phi
def compute_analytical_solutions_fully_broken(self, x): x1 = x[0] x2 = x[1] u1 = fe.Constant(0.) u2 = fe.conditional(fe.gt(x2, self.height / 2.), self.fix_load, fe.Constant(0.)) u_exact = fe.as_vector([u1, u2]) distance_field, _ = distance_function_segments_ufl( x, self.control_points, self.impact_radii) d_exact = fe.exp(-distance_field / (self.l0)) return u_exact, d_exact
def sample_dirichlet_boundary_condition(self, dbe=None): low_left = -0.5 high_left = 0.5 low_right = -0.5 high_right = 0.5 if dbe is None: u0 = np.random.uniform(low=low_left, high=high_left) u1 = np.random.uniform(low=low_left, high=high_left) u2 = np.random.uniform(low=low_right, high=high_right) u3 = np.random.uniform(low=low_right, high=high_right) dbe_data = dict() dbe_data['u0'] = u0 dbe_data['u1'] = u1 dbe_data['u2'] = u2 dbe_data['u3'] = u3 else: # dbe_data = dbe.data assert dbe.type == 'NDP' u0 = df.Constant(dbe_data['u0']) u1 = df.Constant(dbe_data['u1']) u2 = df.Constant(dbe_data['u2']) u3 = df.Constant(dbe_data['u3']) leftBoundary = df.Expression('u0*(1-x[1]) + u1*x[1]', u0=u0, u1=u1, degree=1) rightBoundary = df.Expression('u2*(1-x[1]) + u3*x[1]', u2=u2, u3=u3, degree=1) bcs_specs = [ DirichletSpecification(rightBoundary, self._boundaries['right']), DirichletSpecification(leftBoundary, self._boundaries['left']) ] # this is quite awkward in order to avoid circular dependencies if dbe is None: bcs_wrapper = DirichletBoundaryCondition(bcs_specs, encoding_data=dbe_data, encoding_type='NDP') else: bcs_wrapper = DirichletBoundaryCondition(bcs_specs, encoding=dbe) return bcs_wrapper
def __init__(self, para): # para = [nx, ny, FunctionSpace, degree, ...] self.nx, self.ny = para['mesh_N'][0], para['mesh_N'][1] self.mesh = fe.UnitSquareMesh(self.nx, self.ny) self.Vu = fe.FunctionSpace(self.mesh, 'P', para['P']) self.Vc = fe.FunctionSpace(self.mesh, 'P', para['P']) self.sol = [] self.al = fe.Constant(1.0) self.f = fe.Constant(0.0) self.q = fe.Constant(0.0) self.theta = [] self.mE = 0
def darcy_problem_1(): s = Scenario() s.problem_number = 1 s.source_function = fenics.Constant(3.0) s.dirichlet_bc = fenics.Expression("0.0", degree=1) def boundary(x, on_boundary): return x[0] < fenics.DOLFIN_EPS or x[0] > 1.0 - fenics.DOLFIN_EPS s.gamma_dirichlet = boundary s.g = fenics.Constant(0.0) return s
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 make_buoyancy_function(self): Pr = fenics.Constant(self.prandtl_number) Ra = fenics.Constant(self.rayleigh_number) g = fenics.Constant(self.gravity) def f_B(T): """ Idealized linear Boussinesq Buoyancy with $Re = 1$ """ return T * Ra * g / Pr return f_B
def __init__(self, active_seg_coords, passive_seg_coords, cm=.1, rm=1, dt=0.0001): self.active_seg_coords = active_seg_coords self.passive_seg_coords = passive_seg_coords self.active_seg_current = 1.0 # constant across entire seg self.passive_seg_im = fe.Constant(0) # initial value self.passive_seg_vm = fe.Constant(-80) # initial value self.dt = dt self.cm = cm self.rm = rm
def xest_second_tutorial(self): T = 2.0 # final time num_steps = 50 # number of time steps dt = T / num_steps # time step size # Create mesh and define function space nx = ny = 30 mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2), nx, ny) V = fenics.FunctionSpace(mesh, 'P', 1) # Define boundary condition def boundary(x, on_boundary): return on_boundary bc = fenics.DirichletBC(V, fenics.Constant(0), boundary) # Define initial value u_0 = fenics.Expression('exp(-a*pow(x[0], 2) - a*pow(x[1], 2))', degree=2, a=5) u_n = fenics.interpolate(u_0, V) # Define variational problem u = fenics.TrialFunction(V) v = fenics.TestFunction(V) f = fenics.Constant(0) F = u * v * fenics.dx + dt * fenics.dot(fenics.grad(u), fenics.grad( v)) * fenics.dx - (u_n + dt * f) * v * fenics.dx a, L = fenics.lhs(F), fenics.rhs(F) # Create VTK file for saving solution vtkfile = fenics.File( os.path.join(os.path.dirname(__file__), 'output', 'heat_gaussian', 'solution.pvd')) # Time-stepping u = fenics.Function(V) t = 0 not_initialised = True for n in range(num_steps): # Update current time t += dt # Compute solution fenics.solve(a == L, u, bc) # Save to file and plot solution vtkfile << (u, t) # Here we'll need to call tripcolor ourselves to get access to the color range fenics.plot(u) animation_camera.snap() u_n.assign(u) animation = animation_camera.animate() animation.save( os.path.join(os.path.dirname(__file__), 'output', 'heat_gaussian.mp4'))
def solve_poisson_eps(h, eps, plot=False): eps = fe.Constant(eps) n = int(1 / h) # Create mesh and define function space mesh = fe.UnitIntervalMesh(n) V = fe.FunctionSpace(mesh, 'P', 1) # Define boundary condition u_D = fe.Constant(0.0) # Find exact solution: u_exact = fe.Expression( "(1./2 - x[0]) * (2 * x[0] + eps/(2*pi) * sin(2*pi*x[0]/eps)) " "+ eps*eps/(2*pi*2*pi) * (1 - cos(2*pi*x[0]/eps)) + x[0]*x[0]", eps=eps, degree=4) def boundary(x, on_boundary): return on_boundary bc = fe.DirichletBC(V, u_D, boundary) # Define variational problem u = fe.TrialFunction(V) v = fe.TestFunction(V) f = fe.Constant(1) A = fe.Expression('1./(2+cos(2*pi*x[0]/eps))', eps=eps, degree=2) a = A * fe.dot(fe.grad(u), fe.grad(v)) * fe.dx L = f * v * fe.dx # Compute solution u = fe.Function(V) fe.solve(a == L, u, bc) if plot: # Plot solution fe.plot(u) fe.plot(u_exact, mesh=mesh) # Hold plot fe.interactive() # # Save solution to file in VTK format # vtkfile = fe.File('poisson/solution.pvd') # vtkfile << u # Compute error err_norm = fe.errornorm(u_exact, u, 'L2') return err_norm
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 setup_derived_attributes(self): """ Set attributes which shouldn't be touched by the user. """ self.fenics_timestep_size = fenics.Constant(self.timestep_size) if self.second_order_time_discretization: self.old_fenics_timestep_size = fenics.Constant(self.timestep_size) if self.quadrature_degree is None: self.integration_metric = fenics.dx else: self.integration_metric = fenics.dx(metadata={'quadrature_degree': self.quadrature_degree})
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 nonzero_initial_guess(self, x): x1 = x[0] x2 = x[1] u1 = fe.Constant(0.) u2 = self.fix_load * x2 / self.height u_initial = fe.as_vector([u1, u2]) return u_initial
def Istim(t): if (stim_t1 <= t and t <= stim_t1 + stim_dur1): return waveS1 if (stim_t2 <= t and t <= stim_t2 + stim_dur2): return waveS2 else: return fn.Constant(0.0)
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 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 sample_neumann_boundary_condition(self): c = 0 fe = df.Constant(c) ns = NeumannSpecification('dx', expression=fe, subdomain=None) nbc = NeumannBoundaryCondition([ns]) return nbc
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()