def __init__(self, mesh: fe.Mesh, density: fe.Expression, constitutive_model: ConstitutiveModelBase, bf: fe.Expression = fe.Expression('0', degree=0)): self._mesh = mesh self._density = density self._constitutive_model = constitutive_model self.bf = bf element_v = fe.VectorElement("P", mesh.ufl_cell(), 1) element_s = fe.FiniteElement("P", mesh.ufl_cell(), 1) mixed_element = fe.MixedElement([element_v, element_v, element_s]) W = fe.FunctionSpace(mesh, mixed_element) # Unknowns, values at previous step and test functions w = fe.Function(W) self.u, self.v, self.p = fe.split(w) w0 = fe.Function(W) self.u0, self.v0, self.p0 = fe.split(w0) self.a0 = fe.Function(fe.FunctionSpace(mesh, element_v)) self.ut, self.vt, self.pt = fe.TestFunctions(W) self.F = kin.def_grad(self.u) self.F0 = kin.def_grad(self.u0)
def time_discrete_terms(self): """ Apply first-order implicit Euler finite difference method. """ wnp1 = fenics.split(self._solutions[0].leaf_node()) wn = fenics.split(self._solutions[1].leaf_node()) if self.time_order == 1: return tuple([ phaseflow.backward_difference_formulas.apply_backward_euler( self._timestep_sizes[0], (wnp1[i], wn[i])) for i in range(len(wn)) ]) if self.time_order > 1: wnm1 = fenics.split(self._solutions[2].leaf_node()) if self.time_order == 2: return tuple([ phaseflow.backward_difference_formulas.apply_bdf2( (self._timestep_sizes[0], self._timestep_sizes[1]), (wnp1[i], wn[i], wnm1[i])) for i in range(len(wn)) ]) if self.time_order > 2: raise NotImplementedError()
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 problem_mix(T, dt, E, coupling, VV, boundaries, rho_s, lambda_, mu_s, f, bcs, **Solid_namespace): # Temporal parameters t = 0 k = Constant(dt) # Split problem to two 1.order differential equations psi, phi = TestFunctions(VV) # Functions, wd is for holding the solution d_ = {} w_ = {} wd_ = {} for time in ["n", "n-1", "n-2", "n-3"]: if time == "n" and E not in [None, reference]: tmp_wd = Function(VV) wd_[time] = tmp_wd wd = TrialFunction(VV) w, d = split(wd) else: wd = Function(VV) wd_[time] = wd w, d = split(wd) d_[time] = d w_[time] = w # Time derivative if coupling == "center": G = rho_s / (2 * k) * inner(w_["n"] - w_["n-2"], psi) * dx else: G = rho_s / k * inner(w_["n"] - w_["n-1"], psi) * dx # Stress tensor G += inner(Piola2(d_, w_, k, lambda_, mu_s, E_func=E), grad(psi)) * dx # External forces, like gravity G -= rho_s * inner(f, psi) * dx # d-w coupling if coupling == "CN": G += inner(d_["n"] - d_["n-1"] - k * 0.5 * (w_["n"] + w_["n-1"]), phi) * dx elif coupling == "imp": G += inner(d_["n"] - d_["n-1"] - k * w_["n"], phi) * dx elif coupling == "exp": G += inner(d_["n"] - d_["n-1"] - k * w_["n-1"], phi) * dx elif coupling == "center": G += innter(d_["n"] - d_["n-2"] - 2 * k * w["n-1"], phi) * dx else: print "The coupling %s is not implemented, 'CN', 'imp', and 'exp' are the only valid choices." sys.exit(0) # Solve if E in [None, reference]: solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace) else: solver_linear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace)
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 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 test__deepcopy__ci__(): tolerance = 1.e-6 sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() sim2 = sim.deepcopy() assert (all(sim.solution.vector() == sim2.solution.vector())) for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < tolerance) assert (not (sim.solution.vector() == sim2.solution.vector())) for it in range(2): sim2.solve(goal_tolerance=4.e-5) sim2.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim2.solution) phi = sim2.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < tolerance) assert (all(sim.solution.vector() == sim2.solution.vector()))
def test__checkpoint__ci__(): sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() checkpoint_filepath = tempfile.mkdtemp() + "/checkpoint.h5" sim.write_checkpoint(checkpoint_filepath) sim2 = CavityMeltingSimulationWithoutConcentration() sim2.read_checkpoint(checkpoint_filepath) for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < 1.e-6)
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 test__compositional_convection_coupled_melting_benchmark__amr__regression__ci__( ): sim = phaseflow.cavity_melting_simulation.CavityMeltingSimulation() sim.output_dir = tempfile.mkdtemp() + \ "/test__compositional_convection_coupled_melting/" phaseflow.helpers.mkdir_p(sim.output_dir) sim.assign_initial_values() sim.timestep_size.assign(10.) for it, epsilon_M in zip(range(4), (0.5e-3, 0.25e-3, 0.125e-3, 0.0625e-3)): if it == 1: sim.regularization_sequence = None sim.solve_with_auto_regularization(goal_tolerance=epsilon_M) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) expected_solid_area = 0.7405 solid_area = fenics.assemble(phi * fenics.dx) tolerance = 1.e-4 assert (abs(solid_area - expected_solid_area) < tolerance)
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 test__coarsen__ci__(): sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() sim.coarsen(absolute_tolerances=(1., 1., 1.e-3, 1., 1.)) for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) tolerance = 1.e-3 assert (abs(solid_area - expected_solid_area) < tolerance)
def eval_cost_fem(w, rho): u, _ = fenics.split(w) J_form = ( 0.5 * ufl.inner(alpha(rho) * u, u) * ufl.dx + mu * ufl.inner(ufl.grad(u), ufl.grad(u)) * ufl.dx ) J = fenics_adjoint.assemble(J_form) return J
def impl_dyn(w0, dt=1.e-5, t_end=1.e-4, show_plots=False): (u0, p0, v0) = fe.split(w0) bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_upv.sub(0), V_upv.sub(1), V_upv.sub(2), boundaries) # Lagrange function (without constraint) (u1, p1, v1) = fe.TrialFunctions(V_upv) (eta, q, xi) = fe.TestFunctions(V_upv) F = deformation_grad(u1) I_1, I_2, J = invariants(F) F_iso = isochronic_deformation_grad(F, J) #I_1_iso, I_2_iso = invariants(F_iso)[0:2] W = material_mooney_rivlin(I_1, I_2, c_10, c_01) g = incompr_constr(J) L = -W P = first_piola_stress(L, F) G = incompr_stress(g, F) a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v1, eta) * dx a_dyn_p = inner(g, q) * dx a_dyn_v = rho * inner(v1 - v0, xi) * dx + dt * (inner( P, grad(xi)) * dx + inner(p1 * G, grad(xi)) * dx - inner(B, xi) * dx) a = a_dyn_u + a_dyn_p + a_dyn_v w1 = fe.Function(V_upv) sol = [] t = 0 while t < t_end: print("progress: %f" % (100. * t / t_end)) fe.solve(a == 0, w1, bcs_u + bcs_p + bcs_v) if fe.norm(w1.vector()) > 1e7: print('ERROR: norm explosion') break # update initial values for next step w0.assign(w1) t += dt if show_plots: # plot result fe.plot(w0.sub(0), mode='displacement') plt.show() # save solutions sol.append(Solution(t=t)) sol[-1].upv.assign(w0) return sol, W, kappa
def melted_length_integrand(self): p, u, T, C = fenics.split(self.solution) phi = self.semi_phasefield(T=T, C=C) dx = self.integration_measure return (1. - phi) * dx
def __init__(self, mesh: fe.Mesh, constitutive_model: ConstitutiveModelBase, u_order=1, p_order=0): # TODO a lot here... element_v = fe.VectorElement("P", mesh.ufl_cell(), u_order) element_s = fe.FiniteElement("DG", mesh.ufl_cell(), p_order) # mixed_element = fe.MixedElement([element_v, element_v, element_s]) mixed_element = fe.MixedElement([element_v, element_s]) self.W = fe.FunctionSpace(mesh, mixed_element) self.V, self.Q = self.W.split() self.w = fe.Function(self.W) self.u, self.p = fe.split(self.w) w0 = fe.Function(self.W) self.u0, self.p0 = fe.split(w0) self.ut, self.pt = fe.TestFunctions(self.W) self.F = kin.def_grad(self.u) self.F0 = kin.def_grad(self.u0) S_iso = constitutive_model.iso_stress(self.u) mod_p = constitutive_model.p(self.u) J = fe.det(self.F) F_inv = fe.inv(self.F) if mod_p is None: mod_p = J**2 - 1. else: mod_p -= self.p S = S_iso + J * self.p * F_inv * F_inv.T self.d_LHS = fe.inner(fe.grad(self.ut), self.F * S) * fe.dx \ + fe.inner(mod_p, self.pt) * fe.dx # + fe.inner(mod_p, fe.tr(fe.nabla_grad(self.ut)*fe.inv(self.F))) * fe.dx self.d_RHS = (fe.inner(fe.Constant((0., 0., 0.)), self.ut) * fe.dx)
def setup_adaptive_goal_form(self): """ Set the adaptive goal based on the semi-phase-field. Here the integrated goal is equivalent to the remaining solid area. """ p, u, T = fenics.split(self.state.solution) phi = self.make_semi_phasefield_function() self.adaptive_goal_form = phi(T) * self.integration_metric
def make_time_discrete_terms(self): p_np1, u_np1, T_np1 = fenics.split(self.state.solution) p_n, u_n, T_n = fenics.split(self.old_state.solution) u = [u_np1, u_n] T = [T_np1, T_n] _phi = self.make_semi_phasefield_function() phi = [_phi(T_np1), _phi(T_n)] if self.second_order_time_discretization: p_nm1, u_nm1, T_nm1 = fenics.split(self.old_old_state.solution) u.append(u_nm1) T.append(T_nm1) phi.append(_phi(T_nm1)) if self.second_order_time_discretization: Delta_t = [ self.fenics_timestep_size, self.old_fenics_timestep_size ] else: Delta_t = self.fenics_timestep_size u_t = self.apply_time_discretization(Delta_t, u) T_t = self.apply_time_discretization(Delta_t, T) phi_t = self.apply_time_discretization(Delta_t, phi) # @todo This is wrong. return u_t, T_t, phi_t
def Vufl(soln, t): "Make a UFL object for plotting V" split = fe.split(soln.function) irho = split[0] iUs = split[1:] soln.ksdg.set_time(t) V = (soln.V(iUs, irho, params=soln.ksdg.iparams) / (soln.ksdg.iparams['sigma']**2 / 2)) fs = soln.function.function_space() cell = fs.ufl_cell() CE = fe.FiniteElement('CG', cell, soln.degree) CS = fe.FunctionSpace(fs.mesh(), CE) pV = fe.project(V, CS, solver_type='petsc') return pV
def solve_steady_state_heiser_weissinger(kappa): w = fe.Function(V_up) (u, p) = fe.split(w) p = fe.variable(p) (eta, q) = fe.TestFunctions(V_up) dw = fe.TrialFunction(V_up) kappa = fe.Constant(kappa) bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_up.sub(0), V_up.sub(1), None, boundaries) F = deformation_grad(u) I_1, I_2, J = invariants(F) F_iso = isochronic_deformation_grad(F, J) I_1_iso, I_2_iso = invariants(F)[0:2] W = material_mooney_rivlin(I_1_iso, I_2_iso, c_10, c_01) #+ incompr_relaxation(p, kappa) g = incompr_constr(J) # Lagrange function (without constraint) L = -W # Modified Lagrange function (with constraints) L_mod = L - p * g P = first_piola_stress(L, F) G = incompr_stress(g, F) # = J*fe.inv(F.T) Lp = const_eq(L_mod, p) a_static = weak_div_term(P + p * G, eta) + inner(B, eta) * dx + inner(Lp, q) * dx J_static = fe.derivative(a_static, w, dw) ffc_options = {"optimize": True} problem = fe.NonlinearVariationalProblem( a_static, w, bcs_u + bcs_p, J=J_static, form_compiler_parameters=ffc_options) solver = fe.NonlinearVariationalSolver(problem) solver.solve() return w
def test__cavity_melting_without_concentration__amr__regression__ci__(): sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(5): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < 1.e-6)
def forward(rho): """Solve the forward problem for a given fluid distribution rho(x).""" w = fenics_adjoint.Function(W) (u, p) = fenics.split(w) (v, q) = fenics.TestFunctions(W) inner, grad, dx, div = ufl.inner, ufl.grad, ufl.dx, ufl.div F = ( alpha(rho) * inner(u, v) * dx + inner(grad(u), grad(v)) * dx + inner(grad(p), v) * dx + inner(div(u), q) * dx ) bcs = [ fenics_adjoint.DirichletBC(W.sub(0).sub(1), 0, "on_boundary"), fenics_adjoint.DirichletBC(W.sub(0).sub(0), inflow_outflow_bc, "on_boundary"), ] fenics_adjoint.solve(F == 0, w, bcs=bcs) return w
def bottom_wall_shear_integrand(self): nhat = fenics.FacetNormal(self.mesh) p, u, T, C = fenics.split(self.solution) bottom_wall_id = 2 mesh_function = fenics.MeshFunction("size_t", self.mesh, self.mesh.topology().dim() - 1) self.bottom_wall.mark(mesh_function, bottom_wall_id) dot, grad = fenics.dot, fenics.grad ds = fenics.ds(domain=self.mesh, subdomain_data=mesh_function, subdomain_id=bottom_wall_id) return dot(grad(u[0]), nhat) * ds
def _create_variational_problem(m0, u0, W, dt): """We set up the variational problem.""" p, q = fc.TestFunctions(W) w = fc.Function(W) # Function to solve for m, u = fc.split(w) # Relabel i.e. initialise m_prev, u_prev as m0, u0. m_prev, u_prev = m0, u0 m_mid = 0.5 * (m + m_prev) u_mid = 0.5 * (u + u_prev) F = ( (q * u + q.dx(0) * u.dx(0) - q * m) * fc.dx + # q part (p * (m - m_prev) + dt * (p * m_mid * u_mid.dx(0) - p.dx(0) * m_mid * u_mid)) * fc.dx # p part ) J = fc.derivative(F, w) problem = fc.NonlinearVariationalProblem(F, w, J=J) solver = fc.NonlinearVariationalSolver(problem) solver.parameters["newton_solver"]["maximum_iterations"] = 100 # Default is 50 solver.parameters["newton_solver"]["error_on_nonconvergence"] = False return solver, w, m_prev, u_prev
# Define Boundaries left = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=0.0) right = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=1.0) # Define Dirichlet boundary (x = 0 or x = 1) u_left = fe.Expression(("0.0", "0.0", "0.0"), element=element_3) u_right = fe.Expression(("0.0", "0.0", "0.0"), element=element_3) p_left = fe.Constant(0.) # Define acting force b = fe.Constant((0.0, 0.0, 0.0)) # Body force per unit volume t_bar = fe.Constant((0.0, 0.0, 0.0)) # Traction force on the boundary # Define test and trial functions w = fe.Function(V) # most recently computed solution (u, p) = fe.split(w) (v, q) = fe.TestFunctions(V) dw = fe.TrialFunction(V) # Kinematics d = u.geometric_dimension() I = fe.Identity(d) # Identity tensor F = fe.variable(I + grad(u)) # Deformation gradient C = fe.variable(F.T * F) # Right Cauchy-Green tensor J = fe.det(C) DE = lambda v: 0.5 * (F.T * grad(v) + grad(v).T * F) a_0 = fe.as_vector([[1.0], [0.], [0.]])
V = fn.FunctionSpace(mesh, Mixed) # %% # define potentials and concentrations u_GND = fn.Expression('0', degree=2) #Ground u_DD = fn.Expression('0.5', degree=2) #pontential c_avg = fn.Expression('0.0001', degree=2) #average concentration # set boundary conditions bcs = [] bcs += [fn.DirichletBC(V.sub(0), u_DD, mf, 3)] bcs += [fn.DirichletBC(V.sub(0), u_GND, mf, 1)] # define problem UC = fn.Function(V) uc = fn.split(UC) # trial function potential concentration lagrange multi u, c, lam = uc[0], uc[1:M + 1], uc[M + 1:] VW = fn.TestFunctions( V) # test function potential concentration lagrange multi v, w, mu = VW[0], VW[1:M + 1], VW[M + 1:] #lets try rot r = fn.Expression('x[0]', degree=0) # changing concentrations charges Rho = 0 for i in range(M): if i % 2: Rho += -c[i] else:
def __init__( self, mesh=None, width=1.0, dim=1, nelements=8, degree=2, parameters={}, V=(lambda U: U), U0=None, rho0=None, t0=0.0, debug=False, solver_type = 'lu', preconditioner_type = 'default', periodic=True, ligands=None ): """DG solver for the periodic Keller-Segel PDE system Keyword parameters: mesh=None: the mesh on which to solve the problem width=1.0: the width of the domain dim=1: # of spatial dimensions. nelements=8: If mesh is not supplied, one will be contructed using UnitIntervalMesh, UnitSquareMesh, or UnitCubeMesh (depending on dim). dim and nelements are not needed if mesh is supplied. degree=2: degree of the polynomial approximation parameters={}: a dict giving the values of scalar parameters of .V, U0, and rho0 Expressions. This dict needs to also define numerical parameters that appear in the PDE. Some of these have defaults: dim = dim: # of spatial dimensions sigma: organism movement rate s: attractant secretion rate gamma: attractant decay rate D: attractant diffusion constant rho_min=10.0**-7: minimum feasible worm density U_min=10.0**-7: minimum feasible attractant concentration rhopen=10: penalty for discontinuities in rho Upen=1: penalty for discontinuities in U grhopen=1, gUpen=1: penalties for discontinuities in gradients V=(lambda U: U): a callable taking two numerical arguments, U and rho, or a single argument, U, and returning a single number, V, the potential corresponding to U. Use fenics versions of mathematical functions, e.g. fe.ln, abs, fe.exp. U0, rho0: Expressions, Functions, or strs specifying the initial condition. t0=0.0: initial time solver_type='lu' preconditioner_type='default' periodic=True: Allowed for compatibility, but ignored ligands=None: ignored for compatibility """ logPERIODIC('creating KSDGSolverPeriodic') self.args = dict( mesh=mesh, width=width, dim=dim, nelements=nelements, degree=degree, parameters=parameters, V=V, U0=U0, rho0=rho0, t0=t0, debug=debug, solver_type = solver_type, preconditioner_type = preconditioner_type, periodic=True, ligands=ligands ) self.debug = debug self.solver_type = solver_type self.preconditioner_type = preconditioner_type self.periodic = True self.params = self.default_params.copy() # # Store the original mesh in self.omesh. self.mesh will be the # corner mesh. # if (mesh): self.omesh = mesh else: self.omesh = box_mesh(width=width, dim=dim, nelements=nelements) self.nelements = nelements try: comm = self.omesh.mpi_comm().tompi4py() except AttributeError: comm = self.omesh.mpi_comm() self.lmesh = gather_mesh(self.omesh) omeshstats = mesh_stats(self.omesh) logPERIODIC('omeshstats', omeshstats) self.xmin = omeshstats['xmin'] self.xmax = omeshstats['xmax'] self.xmid = omeshstats['xmid'] self.delta_ = omeshstats['dx'] self.mesh = corner_submesh(self.lmesh) meshstats = mesh_stats(self.mesh) logPERIODIC('meshstats', meshstats) logPERIODIC('self.omesh', self.omesh) logPERIODIC('self.mesh', self.mesh) logPERIODIC('self.mesh.mpi_comm().size', self.mesh.mpi_comm().size) self.nelements = nelements self.degree = degree self.dim = self.mesh.geometry().dim() self.params['dim'] = self.dim self.params.update(parameters) # # Solution spaces and Functions # # The solution function space is a vector space with # 2*(2**dim) elements. The first 2**dim components are even # and odd parts of rho; These are followed by even and # odd parts of U. The array self.evenodd identifies even # and odd components. Each row is a length dim sequence 0s and # 1s and represnts one component. For instance, if evenodd[i] # is [0, 1, 0], then component i of the vector space is even # in dimensions 0 and 2 (x and z conventionally) and off in # dimension 1 (y). # self.symmetries = evenodd_symmetries(self.dim) self.signs = [fe.as_matrix(np.diagflat(1.0 - 2.0*eo)) for eo in self.symmetries] self.eomat = evenodd_matrix(self.symmetries) fss = self.make_function_space() (self.SE, self.SS, self.VE, self.VS) = [ fss[fs] for fs in ('SE', 'SS', 'VE', 'VS') ] (self.SE, self.SS, self.VE, self.VS) = self.make_function_space() self.sol = Function(self.VS) # sol, current soln logPERIODIC('self.sol', self.sol) # srhos and sUs are fcuntions defiend on subspaces self.srhos = self.sol.split()[:2**self.dim] self.sUs = self.sol.split()[2**self.dim:] # irhos and iUs are Indexed UFL expressions self.irhos = fe.split(self.sol)[:2**self.dim] self.iUs = fe.split(self.sol)[2**self.dim:] self.wrhos = TestFunctions(self.VS)[: 2**self.dim] self.wUs = TestFunctions(self.VS)[2**self.dim :] self.tdsol = TrialFunction(self.VS) # time derivatives self.tdrhos = fe.split(self.tdsol)[: 2**self.dim] self.tdUs = fe.split(self.tdsol)[2**self.dim :] bc_method = 'geometric' if self.dim > 1 else 'pointwise' rhobcs = [DirichletBC( self.VS.sub(i), Constant(0), FacesDomain(self.mesh, self.symmetries[i]), method=bc_method ) for i in range(2**self.dim) if np.any(self.symmetries[i] != 0.0)] Ubcs = [DirichletBC( self.VS.sub(i + 2**self.dim), Constant(0), FacesDomain(self.mesh, self.symmetries[i]), method=bc_method ) for i in range(2**self.dim) if np.any(self.symmetries[i] != 0.0)] self.bcs = rhobcs + Ubcs self.n = FacetNormal(self.mesh) self.h = CellDiameter(self.mesh) self.havg = fe.avg(self.h) self.dx = fe.dx self.dS = fe.dS # # record initial state # if not U0: U0 = Constant(0.0) if isinstance(U0, ufl.coefficient.Coefficient): self.U0 = U0 else: self.U0 = Expression(U0, **self.params, degree=self.degree, domain=self.mesh) if not rho0: rho0 = Constant(0.0) if isinstance(rho0, ufl.coefficient.Coefficient): self.rho0 = rho0 else: self.rho0 = Expression(rho0, **self.params, degree=self.degree, domain=self.mesh) try: V(self.U0, self.rho0) def realV(U, rho): return V(U, rho) except TypeError: def realV(U, rho): return V(U) self.V = realV self.t0 = t0 # # initialize state # # cache assigners logPERIODIC('restarting') self.restart() logPERIODIC('restart returned') return(None)
rho = fe.Constant(1) RE = 0.01 lmx = 1 # mixing length dt = 0.1 # Re = 10 / 1e-4 = 1e5 V = fe.VectorElement("Lagrange", mesh.ufl_cell(), 2) P = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1) NU = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1) if MODEL: M = fe.MixedElement([V, P, NU]) else: M = fe.MixedElement([V, P]) W = fe.FunctionSpace(mesh, M) W0 = fe.Function(W) We = fe.Function(W) u0, p0 = fe.split(We) #u0 = fe.Function((W0[0], W0[1]), 'Velocity000023.vtu') #p0 = fe.Function(W0[2]) v, q = fe.TestFunctions(W) #u, p = fe.split(W0) u, p = (fe.as_vector((W0[0], W0[1])), W0[2]) #------------------------------------------------------- # Defining essential/Dirichlet boundary conditions # Step 1: Identify all boundary segments forming Gamma_d #------------------------------------------------------- # (-3., 2.5) # | # | # |_______(0, 1.) # bc1 |
RE = 50 lmx = 1 # mixing length :) # Re = 10 / 1e-4 = 1e5 V = fe.VectorElement("Lagrange", mesh.ufl_cell(), 2) P = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1) NU = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1) if MODEL: M = fe.MixedElement([V, P, NU]) else: M = fe.MixedElement([V, P]) W = fe.FunctionSpace(mesh, M) W0 = fe.Function(W) if MODEL: (v, q, nu_test) = fe.TestFunctions(W) (u, p, nu_trial) = fe.split(W0) else: ( v, q, ) = fe.TestFunctions(W) ( u, p, ) = fe.split(W0) nu_trial = fe.Constant(5) # artificial viscosity!!! fv1 = fe.Constant(1) #------------------------------------------------------- # Defining essential/Dirichlet boundary conditions # Step 1: Identify all boundary segments forming Gamma_d
# %% # set boundary conditions GammaGND = fn.DirichletBC(V.sub(0), u_GND, boundaryGND) # ground potential at straight electrode GammaHigh = fn.DirichletBC(V.sub(0), u_DD, boundaryHigh) # high potential at shaped electrode #GammaC_GND0 = fn.DirichletBC(V.sub(0) , c_INIT, boundaryGND) #GammaC_GND1 = fn.DirichletBC(V.sub(1) , c_INIT, boundaryGND) #GammaC_GND2 = fn.DirichletBC(V.sub(2) , c_INIT, boundaryGND) bcs=[GammaGND,GammaHigh] #bcs=[GammaGND,GammaHigh,GammaC_GND0,GammaC_GND1,GammaC_GND2] # %% # define problem UC = fn.Function(V) uc = fn.split(UC) u, c1, c2, lam1, lam2 = uc[0], uc[1], uc[2], uc[3], uc[4] VW = fn.TestFunctions(V) v, w1, w2, mu1, mu2 = VW[0], VW[1], VW[2], VW[3], VW[4] #create rotation #r = fn.Expression('x[0]', degree=1) # changing concentrations charges PoissonLeft = (fn.dot(fn.grad(u), fn.grad(v)))*fn.dx PoissonRight = c1*v*fn.dx - c2*v*fn.dx NernstPlanck1 = fn.dot((-fn.grad(c1) - (c1)*fn.grad(u)),fn.grad(w1))*fn.dx NernstPlanck2 = fn.dot((-fn.grad(c2) + (c2)*fn.grad(u)),fn.grad(w2))*fn.dx Constraint1 = lam1 * w1 * fn.dx + ((c1) - c_AVG) * mu1 * fn.dx