def __init__(self, state, V, *, ibp="once", solver_params=None): super().__init__(state=state, V=V, ibp=ibp, solver_params=solver_params) self.Upwind = 0.5 * (sign(dot(self.ubar, self.n)) + 1) if self.state.mesh.topological_dimension() == 2: self.perp = state.perp if state.on_sphere: outward_normals = CellNormal(state.mesh) self.perp_u_upwind = lambda q: self.Upwind('+') * cross( outward_normals('+'), q('+')) + self.Upwind('-') * cross( outward_normals('-'), q('-')) else: self.perp_u_upwind = lambda q: self.Upwind('+') * state.perp( q('+')) + self.Upwind('-') * state.perp(q('-')) self.gradperp = lambda u: state.perp(grad(u)) elif self.state.mesh.topological_dimension() == 3: if self.ibp == "twice": raise NotImplementedError( "ibp=twice is not implemented for 3d problems") else: raise RuntimeError("topological mesh dimension must be 2 or 3")
def residual(self, test, trial, trial_lagged, fields, bcs): u_adv = trial_lagged phi = test n = self.n u = trial F = -dot(u, div(outer(phi, u_adv)))*self.dx for id, bc in bcs.items(): if 'u' in bc: u_in = bc['u'] elif 'un' in bc: u_in = bc['un'] * n # this implies u_t=0 on the inflow else: u_in = zero(self.dim) F += conditional(dot(u_adv, n) < 0, dot(phi, u_in)*dot(u_adv, n), dot(phi, u)*dot(u_adv, n)) * self.ds(id) if not (is_continuous(self.trial_space) and normal_is_continuous(u_adv)): # s=0: u.n(-)<0 => flow goes from '+' to '-' => '+' is upwind # s=1: u.n(-)>0 => flow goes from '-' to '+' => '-' is upwind s = 0.5*(sign(dot(avg(u), n('-'))) + 1.0) u_up = u('-')*s + u('+')*(1-s) F += dot(u_up, (dot(u_adv('+'), n('+'))*phi('+') + dot(u_adv('-'), n('-'))*phi('-'))) * self.dS return -F
def heaviside(x): """Defines the heaviside step function in UFL. Parameters: x - single coordinate of a UFL SpatialCoordinate. """ return 0.5 * (sign(real(x)) + 1.0)
def form_function(u, h, v, q): K = 0.5 * fd.inner(u, u) n = fd.FacetNormal(mesh) uup = 0.5 * (fd.dot(u, n) + abs(fd.dot(u, n))) Upwind = 0.5 * (fd.sign(fd.dot(u, n)) + 1) eqn = (fd.inner(v, f * perp(u)) * fd.dx - fd.inner(perp(fd.grad(fd.inner(v, perp(u)))), u) * fd.dx + fd.inner(both(perp(n) * fd.inner(v, perp(u))), both(Upwind * u)) * fd.dS - fd.div(v) * (g * (h + b) + K) * fd.dx - fd.inner(fd.grad(q), u) * h * fd.dx + fd.jump(q) * (uup('+') * h('+') - uup('-') * h('-')) * fd.dS) return eqn
def vector_invariant_form(state, test, q, ibp=IntegrateByParts.ONCE): Vu = state.spaces("HDiv") dS_ = (dS_v + dS_h) if Vu.extruded else dS ubar = Function(Vu) n = FacetNormal(state.mesh) Upwind = 0.5 * (sign(dot(ubar, n)) + 1) if state.mesh.topological_dimension() == 3: if ibp != IntegrateByParts.ONCE: raise NotImplementedError # <w,curl(u) cross ubar + grad( u.ubar)> # =<curl(u),ubar cross w> - <div(w), u.ubar> # =<u,curl(ubar cross w)> - # <<u_upwind, [[n cross(ubar cross w)cross]]>> both = lambda u: 2 * avg(u) L = (inner(q, curl(cross(ubar, test))) * dx - inner(both(Upwind * q), both(cross(n, cross(ubar, test)))) * dS_) else: perp = state.perp if state.on_sphere: outward_normals = CellNormal(state.mesh) perp_u_upwind = lambda q: Upwind('+') * cross( outward_normals('+'), q('+')) + Upwind('-') * cross( outward_normals('-'), q('-')) else: perp_u_upwind = lambda q: Upwind('+') * perp(q('+')) + Upwind( '-') * perp(q('-')) if ibp == IntegrateByParts.ONCE: L = (-inner(perp(grad(inner(test, perp(ubar)))), q) * dx - inner(jump(inner(test, perp(ubar)), n), perp_u_upwind(q)) * dS_) else: L = ((-inner(test, div(perp(q)) * perp(ubar))) * dx - inner(jump(inner(test, perp(ubar)), n), perp_u_upwind(q)) * dS_ + jump(inner(test, perp(ubar)) * perp(q), n) * dS_) L -= 0.5 * div(test) * inner(q, ubar) * dx form = transporting_velocity(L, ubar) return transport(form, TransportEquationType.vector_invariant)
def advection_term(self, q): n = FacetNormal(self.state.mesh) Upwind = 0.5 * (sign(dot(self.ubar, n)) + 1) if self.state.mesh.topological_dimension() == 3: # <w,curl(u) cross ubar + grad( u.ubar)> # =<curl(u),ubar cross w> - <div(w), u.ubar> # =<u,curl(ubar cross w)> - # <<u_upwind, [[n cross(ubar cross w)cross]]>> both = lambda u: 2 * avg(u) L = (inner(q, curl(cross(self.ubar, self.test))) * dx - inner(both(Upwind * q), both(cross(n, cross(self.ubar, self.test)))) * self.dS) else: perp = self.state.perp if self.state.on_sphere: outward_normals = CellNormal(self.state.mesh) perp_u_upwind = lambda q: Upwind('+') * cross( outward_normals('+'), q('+')) + Upwind('-') * cross( outward_normals('-'), q('-')) else: perp_u_upwind = lambda q: Upwind('+') * perp(q('+')) + Upwind( '-') * perp(q('-')) if self.ibp == IntegrateByParts.ONCE: L = (-inner(perp(grad(inner(self.test, perp(self.ubar)))), q) * dx - inner(jump(inner(self.test, perp(self.ubar)), n), perp_u_upwind(q)) * self.dS) else: L = ((-inner(self.test, div(perp(q)) * perp(self.ubar))) * dx - inner(jump(inner(self.test, perp(self.ubar)), n), perp_u_upwind(q)) * self.dS + jump(inner(self.test, perp(self.ubar)) * perp(q), n) * self.dS) L -= 0.5 * div(self.test) * inner(q, self.ubar) * dx return L
# Load initial conditions onto fields if pickup: with DumbCheckpoint("chkpt_{0}".format(fname), mode=FILE_READ) as chk: chk.load(xn) init_t = chk.read_attribute("/", "time") else: un.project(uexpr, form_compiler_parameters={'quadrature_degree': 12}) Dn.interpolate(Dexpr) b.interpolate(bexpr) if COMM_WORLD.Get_rank() == 0: print("Finished setting up functions at", ctime()) # Build perp and upwind perp (including 2D version for test purposes) n = FacetNormal(mesh) s = lambda u: 0.5 * (sign(dot(u, n)) + 1) uw = lambda u, v: (s(u)('+') * v('+') + s(u)('-') * v('-')) if mesh.geometric_dimension() == 2: perp = lambda u: as_vector([-u[1], u[0]]) p_uw = lambda u, v: perp(uw(u, v)) else: perp = lambda u: cross(CellNormal(mesh), u) out_n = CellNormal(mesh) p_uw = lambda u, v: (s(u)('+') * cross(out_n('+'), v('+')) + s(u) ('-') * cross(out_n('-'), v('-'))) # Initial solve for vorticity for output eta = TestFunction(W2) q_ = TrialFunction(W2) q_eqn = eta * q_ * Dn * dx + inner(perp(grad(eta)), un) * dx - eta * f * dx
def __init__(self, state, V): super(EulerPoincareForm, self).__init__(state) dt = state.timestepping.dt w = TestFunction(V) u = TrialFunction(V) self.u0 = Function(V) ustar = 0.5*(self.u0 + u) n = FacetNormal(state.mesh) Upwind = 0.5*(sign(dot(self.ubar, n))+1) if state.mesh.geometric_dimension() == 3: if V.extruded: surface_measure = (dS_h + dS_v) else: surface_measure = dS # <w,curl(u) cross ubar + grad( u.ubar)> # =<curl(u),ubar cross w> - <div(w), u.ubar> # =<u,curl(ubar cross w)> - # <<u_upwind, [[n cross(ubar cross w)cross]]>> both = lambda u: 2*avg(u) Eqn = ( inner(w, u-self.u0)*dx + dt*inner(ustar, curl(cross(self.ubar, w)))*dx - dt*inner(both(Upwind*ustar), both(cross(n, cross(self.ubar, w))))*surface_measure - dt*div(w)*inner(ustar, self.ubar)*dx ) # define surface measure and terms involving perp differently # for slice (i.e. if V.extruded is True) and shallow water # (V.extruded is False) else: if V.extruded: surface_measure = (dS_h + dS_v) perp = lambda u: as_vector([-u[1], u[0]]) perp_u_upwind = Upwind('+')*perp(ustar('+')) + Upwind('-')*perp(ustar('-')) else: surface_measure = dS outward_normals = CellNormal(state.mesh) perp = lambda u: cross(outward_normals, u) perp_u_upwind = Upwind('+')*cross(outward_normals('+'),ustar('+')) + Upwind('-')*cross(outward_normals('-'),ustar('-')) Eqn = ( (inner(w, u-self.u0) - dt*inner(w, div(perp(ustar))*perp(self.ubar)) - dt*div(w)*inner(ustar, self.ubar))*dx - dt*inner(jump(inner(w, perp(self.ubar)), n), perp_u_upwind)*surface_measure + dt*jump(inner(w, perp(self.ubar))*perp(ustar), n)*surface_measure ) a = lhs(Eqn) L = rhs(Eqn) self.u1 = Function(V) uproblem = LinearVariationalProblem(a, L, self.u1) self.usolver = LinearVariationalSolver(uproblem, options_prefix='EPAdvection')