def _fluxes(h, q, g): r"""Calculate the flux of mass and momentum for the shallow water equations""" I = firedrake.Identity(2) F_h = q F_q = outer(q, q) / h + 0.5 * g * h**2 * I return F_h, F_q
def initialize_solvers(self): # Kinematics # Right Cauchy-Green tensor if self.nonlin: d = self.X.geometric_dimension() I = fd.Identity(d) # Identity tensor F = I + fd.grad(self.X) # Deformation gradient C = F.T * F E = (C - I) / 2. # Green-Lagrangian strain # E = 1./2.*( fd.grad(self.X).T + fd.grad(self.X) + fd.grad(self.X).T * fd.grad(self.X) ) # alternative equivalent definition else: E = 1. / 2. * (fd.grad(self.X).T + fd.grad(self.X) ) # linear strain self.W = (self.lam / 2.) * (fd.tr(E))**2 + self.mu * fd.tr(E * E) # f = fd.Constant((0, 0, -self.g)) # body force / rho # T = self.surface_force() # Total potential energy Pi = self.W * fd.dx # Compute first variation of Pi (directional derivative about X in the direction of v) F_expr = fd.derivative(Pi, self.X, self.v) self.DBC = fd.DirichletBC(self.V, fd.as_vector([0., 0., 0.]), self.bottom_id) # delX = fd.nabla_grad(self.X) # delv_B = fd.nabla_grad(self.v) # T_x_dv = self.lam * fd.div(self.X) * fd.div(self.v) \ # + self.mu * ( fd.inner( delX, delv_B + fd.transpose(delv_B) ) ) self.a_U = fd.dot(self.trial, self.v) * fd.dx # self.L_U = ( fd.dot( self.U, self.v ) - self.dt/2./self.rho * T_x_dv ) * fd.dx self.L_U = fd.dot( self.U, self.v) * fd.dx - self.dt / 2. / self.rho * F_expr #\ # + self.dt/2./self.rho*fd.dot(T,self.v)*fd.ds(1) # surface force at x==0 plane # + self.dt/2.*fd.dot(f,self.v)*fd.dx # body force self.a_X = fd.dot(self.trial, self.v) * fd.dx # self.L_interface = fd.dot(self.phi_vect, self.v) * fd.ds(self.interface_id) self.L_X = fd.dot((self.X + self.dt * self.U), self.v) * fd.dx #\ # - self.dt/self.rho * self.L_interface self.LVP_U = fd.LinearVariationalProblem(self.a_U, self.L_U, self.U, bcs=[self.DBC]) self.LVS_U = fd.LinearVariationalSolver(self.LVP_U) self.LVP_X = fd.LinearVariationalProblem(self.a_X, self.L_X, self.X, bcs=[self.DBC]) self.LVS_X = fd.LinearVariationalSolver(self.LVP_X)
dt = np.sqrt(tol) dtc = fd.Constant(dt) n = fd.FacetNormal(mesh) h = fd.sqrt(2) * fd.CellVolume(mesh) / fd.CellDiameter(mesh) # advective velocity velocity = fd.Function(vDG1) velocity.interpolate(v_inlet) vnorm = fd.sqrt(fd.dot(velocity, velocity)) # upwind term vn = 0.5 * (fd.dot(velocity, n) + abs(fd.dot(velocity, n))) cupw = fd.conditional(fd.dot(velocity, n) > 0, ch, lmbd_h) # Diffusion tensor Diff = fd.Identity(mesh.geometric_dimension()) * Dm # Diff = fd.Identity(mesh.geometric_dimension())*(Dm + d_t*vnorm) + \ # fd.Constant(d_l-d_t)*fd.outer(velocity, velocity)/vnorm # stability # tau = fd.Constant(1.0) / h + abs(fd.dot(velocity, n)) tau = fd.Constant(5) / h + vn # numerical flux chat = lmbd_h qhat = qh + tau * (ch - chat) * n + velocity * chat # qhat_n = fd.dot(qh, n) + tau*(ch - chat) + chat*vn a_u = ( fd.inner(fd.inv(Diff) * qh, vh) * fd.dx - ch * fd.div(vh) * fd.dx + # internal faces
L = p_out*fd.inner(v, n)*fd.ds(outlet) + \ fd.inner(f, v)*fd.dx + idt*c_t*p0*q*fd.dx # ------------------------------------------------------------------------- # transport # coefficients K = fd.Constant(K) Dt = fd.Constant(dt) c_mid = 0.5 * (c + c0) # Crank-Nicolson timestepping # advective velocity vel = fd.Function(V, name='velocity') vnorm = fd.sqrt(fd.dot(vel, vel)) # Diffusion tensor Diff = fd.Identity(mesh.geometric_dimension())*(Dm + alphaT*vnorm) + \ (alphaL-alphaT)*fd.outer(vel, vel)/vnorm # source term fc = fd.Constant(s) # weak form (transport) F1 = w * (c - c0) * fd.dx + Dt * (w * fd.dot(vel, fd.grad(c_mid)) + fd.dot( fd.grad(w), Diff * fd.grad(c_mid)) + w * K * c_mid - fc * w) * fd.dx # - Dt*h_n*w*fd.ds(outlet) # strong form R = (c - c0) + Dt * (fd.dot(vel, fd.grad(c_mid)) - fd.div(Diff * fd.grad(c_mid)) + K * c_mid - fc) # *** Adding SUPG stabilizing and shock cap. terms ***
# 3.4) Variational Form # ---------------------- # coefficients dt = np.sqrt(tol) dtc = fd.Constant(dt) n = fd.FacetNormal(mesh) h = fd.sqrt(2) * fd.CellVolume(mesh) / fd.CellDiameter(mesh) # advective velocity velocity = fd.Function(vDG1) velocity.interpolate(fd.Constant(v_inlet)) vnorm = fd.sqrt(fd.dot(velocity, velocity)) # Diffusion tensor if d_t < 0: Diff = fd.Identity(mesh.geometric_dimension()) * Dm else: Diff = fd.Identity(mesh.geometric_dimension())*(Dm + d_t*vnorm) + \ fd.Constant(d_l-d_t)*fd.outer(velocity, velocity)/vnorm # upwind ter # vn = 0.5*(fd.dot(velocity, n) + abs(fd.dot(velocity, n))) # cupw = fd.conditional(vn < 0, ch, lmbd_h) # stability tau_d = fd.Constant(max([Dm, tau_e])) / h tau_a = abs(fd.dot(velocity, n)) # tau_a = vn # numerical flux chat = lmbd_h
def sigma(u): d = u.geometric_dimension() # space dimension return self.lam * fd.nabla_div(u) * fd.Identity( d) + 2 * self.mu * epsilon(u)
# way #1: natural bdr condition # src = None # nat_bdr = fd.conditional(x**2 + y**2 < h_mesh**2, # -0.1, 0.) # 10 m3/d # way #2: source term nat_bdr = None src = fd.conditional(x**2 + y**2 < h_mesh**2, 0.1 * n, 0.) # 10 m3/d/m3 # %% # physical parameters beta = 4.5e-8 # 1/Pa rho = lambda x: 1000 * (1 + beta * (x - 1e5)) mu = 1e-3 phi = 0.1 k = 1e-14 * fd.Identity(dim) g_ = -10 # None (without gravity) g = fd.as_vector( tuple([0 for d in range(dim - 1)]) + (0 if g_ is None else -g_, )) # %% # set forms # --------- W = fd.FunctionSpace(mesh, "CG", 1) q = fd.TestFunction(W) p = fd.Function(W, name="p") p0 = fd.Function(W, name="p0")
def Identity(dim): r"""Return the unit tensor of a given dimension""" if dim == 1: return firedrake.Constant(1.0) return firedrake.Identity(dim)