def _CenterVector(mesh, Center): '''DLT vector pointing on each facet from one Center to the other''' # Cell-cell distance for the interior facet is defined as a distance # of circumcenters. For exterior it is facet centor to circumcenter # For facet centers we use DLT projection if mesh.topology().dim() > 1: L = df.VectorFunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0) else: L = df.VectorFunctionSpace(mesh, 'CG', 1) fK = df.FacetArea(mesh) l = df.TestFunction(L) x = df.SpatialCoordinate(mesh) facet_centers = df.Function(L) df.assemble((1 / fK) * df.inner(x, l) * df.ds, tensor=facet_centers.vector()) cell_centers = Center(mesh) cc = df.Function(L) # Finally we assemble magniture of the vector that is determined by the # two centers df.assemble( (1 / fK('+')) * df.inner(cell_centers('+') - cell_centers('-'), l('+')) * df.dS + (1 / fK) * df.inner(cell_centers - facet_centers, l) * df.ds, tensor=cc.vector()) return cc
def testFacetArea(): references = [(UnitIntervalMesh(MPI.comm_world, 1), 2, 2), (UnitSquareMesh( MPI.comm_world, 1, 1), 4, 4), (UnitCubeMesh(MPI.comm_world, 1, 1, 1), 6, 3)] for mesh, surface, ref_int in references: c0 = ufl.FacetArea(mesh) c1 = dolfin.FacetArea(mesh) assert (c0) assert (c1)
def testFacetArea(): references = [(UnitIntervalMesh(1), 2, 2),\ (UnitSquareMesh(1,1), 4, 4),\ (UnitCubeMesh(1,1,1), 6, 3)] for mesh, surface, ref_int in references: c = Constant(1, mesh.ufl_cell()) # FIXME c0 = ufl.FacetArea(mesh) c1 = dolfin.FacetArea(mesh) assert round(assemble(c * dx(mesh)) - 1, 7) == 0 assert round(assemble(c * ds(mesh)) - surface, 7) == 0 assert round(assemble(c0 * ds(mesh)) - ref_int, 7) == 0 assert round(assemble(c1 * ds(mesh)) - ref_int, 7) == 0
def testFacetArea(self): if MPI.size(mpi_comm_world()) == 1: references = [(UnitIntervalMesh(1), 2, 2),\ (UnitSquareMesh(1,1), 4, 4),\ (UnitCubeMesh(1,1,1), 6, 3)] for mesh, surface, ref_int in references: c = Constant(1, mesh.ufl_cell()) # FIXME c0 = ufl.FacetArea(mesh) c1 = dolfin.FacetArea(mesh) self.assertAlmostEqual(assemble(c * dx, mesh=mesh), 1) self.assertAlmostEqual(assemble(c * ds, mesh=mesh), surface) self.assertAlmostEqual(assemble(c0 * ds, mesh=mesh), ref_int) self.assertAlmostEqual(assemble(c1 * ds, mesh=mesh), ref_int)
def _CenterDistance(mesh, Center): '''Magnitude of Centervector as a DLT function''' if mesh.topology().dim() > 1: L = df.FunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0) else: L = df.FunctionSpace(mesh, 'CG', 1) fK = df.FacetArea(mesh) l = df.TestFunction(L) cc = Center(mesh) distance = df.Function(L) # We use P0 projection df.assemble(1 / fK('+') * df.inner(df.sqrt(df.dot(cc('+'), cc('+'))), l('+')) * df.dS + 1 / fK * df.inner(df.sqrt(df.dot(cc, cc)), l) * df.ds, tensor=distance.vector()) return distance
def define_coupled_equation(self): """ Setup the coupled Navier-Stokes equation This implementation assembles the full LHS and RHS each time they are needed """ sim = self.simulation mpm = sim.multi_phase_model mesh = sim.data['mesh'] Vcoupled = sim.data['Vcoupled'] u_conv = sim.data['u_conv'] # Unpack the coupled trial and test functions uc = dolfin.TrialFunction(Vcoupled) vc = dolfin.TestFunction(Vcoupled) ulist = [] vlist = [] sigmas, taus = [], [] for d in range(sim.ndim): ulist.append(uc[d]) vlist.append(vc[d]) indices = list( range(1 + sim.ndim * (d + 1), 1 + sim.ndim * (d + 2))) sigmas.append([uc[i] for i in indices]) taus.append([vc[i] for i in indices]) u = dolfin.as_vector(ulist) v = dolfin.as_vector(vlist) p = uc[sim.ndim] q = vc[sim.ndim] sigma = dolfin.as_tensor(sigmas) tau = dolfin.as_tensor(taus) c1, c2, c3 = sim.data['time_coeffs'] dt = sim.data['dt'] g = sim.data['g'] n = dolfin.FacetNormal(mesh) h = dolfin.FacetArea(mesh) # Fluid properties rho = mpm.get_density(0) mu = mpm.get_laminar_dynamic_viscosity(0) # Upwind and downwind velocities w_nU = (dot(u_conv, n) + abs(dot(u_conv, n))) / 2.0 w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2.0 u_uw_s = dolfin.conditional(dolfin.gt(dot(u_conv, n), 0.0), 1.0, 0.0)('+') u_uw = u_uw_s * u('+') + (1 - u_uw_s) * u('-') # LDG penalties # kappa_0 = Constant(4.0) # kappa = mu*kappa_0/h C11 = avg(mu / h) D11 = avg(h / mu) C12 = 0.2 * n('+') D12 = 0.2 * n('+') def ojump(v, n): return outer(v, n)('+') + outer(v, n)('-') # Interior facet fluxes # u_hat_dS = avg(u) # sigma_hat_dS = avg(sigma) - avg(kappa)*ojump(u, n) # p_hat_dS = avg(p) u_hat_s_dS = avg(u) + dot(ojump(u, n), C12) u_hat_p_dS = avg(u) + D11 * jump(p, n) + D12 * jump(u, n) sigma_hat_dS = avg(sigma) - C11 * ojump(u, n) - outer( jump(sigma, n), C12) p_hat_dS = avg(p) - dot(D12, jump(p, n)) # Time derivative up = sim.data['up'] upp = sim.data['upp'] eq = rho * dot(c1 * u + c2 * up + c3 * upp, v) / dt * dx # LDG equation 1 eq += inner(sigma, tau) * dx eq += dot(u, div(mu * tau)) * dx eq -= dot(u_hat_s_dS, jump(mu * tau, n)) * dS # LDG equation 2 eq += (inner(sigma, grad(v)) - p * div(v)) * dx eq -= (inner(sigma_hat_dS, ojump(v, n)) - p_hat_dS * jump(v, n)) * dS eq -= dot(u, div(outer(v, rho * u_conv))) * dx eq += rho('+') * dot(u_conv('+'), n('+')) * dot(u_uw, v('+')) * dS eq += rho('-') * dot(u_conv('-'), n('-')) * dot(u_uw, v('-')) * dS momentum_sources = sim.data['momentum_sources'] + [rho * g] eq -= dot(sum(momentum_sources), v) * dx # LDG equation 3 eq -= dot(u, grad(q)) * dx eq += dot(u_hat_p_dS, jump(q, n)) * dS # Dirichlet boundary dirichlet_bcs = get_collected_velocity_bcs(sim, 'dirichlet_bcs') for ds, u_bc in dirichlet_bcs.items(): # sigma_hat_ds = sigma - kappa*outer(u, n) sigma_hat_ds = sigma - C11 * outer(u - u_bc, n) u_hat_ds = u_bc p_hat_ds = p # LDG equation 1 eq -= dot(u_hat_ds, dot(mu * tau, n)) * ds # LDG equation 2 eq -= (inner(sigma_hat_ds, outer(v, n)) - p_hat_ds * dot(v, n)) * ds eq += rho * w_nU * dot(u, v) * ds eq += rho * w_nD * dot(u_bc, v) * ds # LDG equation 3 eq += dot(u_hat_ds, q * n) * ds # Neumann boundary neumann_bcs = get_collected_velocity_bcs(sim, 'neumann_bcs') assert not neumann_bcs for ds, du_bc in neumann_bcs.items(): # Divergence free criterion if self.use_grad_q_form: eq += q * dot(u, n) * ds else: eq -= q * dot(u, n) * ds # Convection eq += rho * w_nU * dot(u, v) * ds # Diffusion u_hat_ds = u sigma_hat_ds = outer(du_bc, n) / mu eq -= dot(u_hat_ds, dot(mu * tau, n)) * ds eq -= inner(sigma_hat_ds, outer(v, n)) * ds # Pressure if not self.use_grad_p_form: eq += p * dot(v, n) * ds a, L = dolfin.system(eq) self.form_lhs = a self.form_rhs = L self.tensor_lhs = None self.tensor_rhs = None
def __init__(self, mesh, orientation): if orientation is None: # We assume convex domain and take center as ... orientation = mesh.coordinates().mean(axis=0) if isinstance(orientation, df.Mesh): # We set surface normal as outer with respect to orientation mesh assert orientation.id() in mesh.parent_entity_map n = df.FacetNormal(orientation) hA = df.FacetArea(orientation) # Project normal, we have a function on mesh DLT = df.VectorFunctionSpace(orientation, 'Discontinuous Lagrange Trace', 0) n_ = df.Function(DLT) df.assemble((1 / hA) * df.inner(n, df.TestFunction(DLT)) * df.ds, tensor=n_.vector()) # Now we get it to manifold dx_ = df.Measure('dx', domain=mesh) V = df.VectorFunctionSpace(mesh, 'DG', 0) df.Function.__init__(self, V) hK = df.CellVolume(mesh) n_vec = xii.ii_convert( xii.ii_assemble( (1 / hK) * df.inner(xii.Trace(n_, mesh), df.TestFunction(V)) * dx_)) self.vector()[:] = n_vec return None # Manifold assumption assert 1 <= mesh.topology().dim() < mesh.geometry().dim() gdim = mesh.geometry().dim() # Orientation from inside point if isinstance(orientation, (list, np.ndarray, tuple)): assert len(orientation) == gdim kwargs = {'x0%d' % i: val for i, val in enumerate(orientation)} orientation = ['x[%d] - x0%d' % (i, i) for i in range(gdim)] orientation = df.Expression(orientation, degree=1, **kwargs) assert orientation.ufl_shape == (gdim, ) V = df.VectorFunctionSpace(mesh, 'DG', 0, gdim) df.Function.__init__(self, V) n_values = self.vector().get_local() X = mesh.coordinates() dd = X[np.argmin(X[:, 0])] - X[np.argmax(X[:, 0])] values = [] R = np.array([[0, -1], [1, 0]]) for cell in df.cells(mesh): n = cell.cell_normal().array()[:gdim] x = cell.midpoint().array()[:gdim] # Disagree? if np.inner(orientation(x), n) < 0: n *= -1. values.append(n / np.linalg.norm(n)) values = np.array(values) for sub in range(gdim): dofs = V.sub(sub).dofmap().dofs() n_values[dofs] = values[:, sub] self.vector().set_local(n_values) self.vector().apply('insert')