Пример #1
0
import assess

nu = 1.0
n = 2
solution_upper = assess.CylindricalStokesSolutionDeltaFreeSlip(n, +1, nu=nu)
solution_lower = assess.CylindricalStokesSolutionDeltaFreeSlip(n, -1, nu=nu)
Пример #2
0
def model(disc_n):
    ncells = disc_n * 256
    nlayers = disc_n * 16

    # Construct a circle mesh and then extrude into a cylinder:
    mesh1d = CircleManifoldMesh(ncells, radius=rmin, degree=2)
    mesh = ExtrudedMesh(mesh1d, layers=nlayers, extrusion_type="radial")

    # Define geometric quantities
    X = SpatialCoordinate(mesh)
    n = FacetNormal(mesh)
    r = sqrt(X[0]**2 + X[1]**2)
    phi = atan_2(X[1], X[0])

    # Set up function spaces - currently using the Q2Q1 element pair :
    V = VectorFunctionSpace(mesh, "CG", 2)  # velocity function space (vector)
    W = FunctionSpace(mesh, "DPC", 1)  # pressure function space (scalar)
    P0 = FunctionSpace(mesh, "DQ", 0)
    Q1DG = FunctionSpace(mesh, "DQ", 1)
    Q1DGvec = VectorFunctionSpace(mesh, "DQ", 1)

    # Set up mixed function space and associated test functions:
    Z = MixedFunctionSpace([V, W])
    v, w = TestFunctions(Z)

    # Set up fields on these function spaces - split into each component so that they are easily accessible:
    z = Function(Z)  # a field over the mixed function space Z.
    u, p = split(z)
    u_, p_ = z.split()

    # Stokes related constants (note that since these are included in UFL, they are wrapped inside Constant):
    mu = Constant(1.0)  # Constant viscosity
    g = Constant(1.0)
    C_ip = Constant(
        100.0
    )  # The fudge factor for interior penalty term used in weak imposition of BCs
    p_ip = 2  # maximum polynomial degree of the _gradient_ of velocity

    marker = Function(P0)
    marker.interpolate(conditional(r < rp, 1, 0))

    # Setup UFL, incorporating Nitsche boundary conditions:
    stress = 2 * mu * sym(grad(u))
    F_stokes = inner(grad(v), stress) * dx - div(v) * p * dx + dot(
        n, v) * p * ds_tb + g * cos(nn * phi) * dot(jump(marker, n),
                                                    avg(v)) * dS_h
    F_stokes += -w * div(u) * dx + w * dot(n, u) * ds_tb  # Continuity equation

    # nitsche free slip BCs
    F_stokes += -dot(v, n) * dot(dot(n, stress), n) * ds_tb
    F_stokes += -dot(u, n) * dot(dot(n, 2 * mu * sym(grad(v))), n) * ds_tb
    F_stokes += C_ip * mu * (p_ip +
                             1)**2 * FacetArea(mesh) / CellVolume(mesh) * dot(
                                 u, n) * dot(v, n) * ds_tb

    # Nullspaces and near-nullspaces:
    xy_rot = Function(V).interpolate(as_vector(
        (-X[1], X[0])))  # rotation interpolated as vector function in V
    u_nullspace = VectorSpaceBasis([xy_rot])
    u_nullspace.orthonormalize()
    p_nullspace = VectorSpaceBasis(
        constant=True)  # constant nullspace for pressure
    Z_nullspace = MixedVectorSpaceBasis(
        Z, [u_nullspace, p_nullspace])  # combined mixed nullspace

    # Generating near_nullspaces for GAMG:
    nns_x = Function(V).interpolate(Constant([1., 0.]))
    nns_y = Function(V).interpolate(Constant([0., 1.]))
    u_near_nullspace = VectorSpaceBasis([nns_x, nns_y, xy_rot])
    u_near_nullspace.orthonormalize()
    Z_near_nullspace = MixedVectorSpaceBasis(Z, [u_near_nullspace, Z.sub(1)])

    # Solve system - configured for solving non-linear systems, where everything is on the LHS (as above)
    # and the RHS == 0.
    solve(F_stokes == 0,
          z,
          solver_parameters=stokes_solver_parameters,
          appctx={"mu": mu},
          nullspace=Z_nullspace,
          transpose_nullspace=Z_nullspace,
          near_nullspace=Z_near_nullspace)

    # take out null modes through L2 projection from velocity and pressure
    # removing rotation from velocity:
    rot = as_vector((-X[1], X[0]))
    coef = assemble(dot(rot, u_) * dx) / assemble(dot(rot, rot) * dx)
    u_.project(u_ - rot * coef, solver_parameters=project_solver_parameters)

    # removing constant nullspace from pressure
    coef = assemble(p_ * dx) / assemble(Constant(1.0) * dx(domain=mesh))
    p_.project(p_ - coef, solver_parameters=project_solver_parameters)

    solution_upper = assess.CylindricalStokesSolutionDeltaFreeSlip(
        float(nn), +1, nu=float(mu))
    solution_lower = assess.CylindricalStokesSolutionDeltaFreeSlip(
        float(nn), -1, nu=float(mu))

    # compute u analytical and error
    uxy = interpolate(as_vector((X[0], X[1])), V)
    u_anal_upper = Function(V, name="AnalyticalVelocityUpper")
    u_anal_lower = Function(V, name="AnalyticalVelocityLower")
    u_anal = Function(V, name="AnalyticalVelocity")
    u_anal_upper.dat.data[:] = [
        solution_upper.velocity_cartesian(xyi) for xyi in uxy.dat.data
    ]
    u_anal_lower.dat.data[:] = [
        solution_lower.velocity_cartesian(xyi) for xyi in uxy.dat.data
    ]
    u_anal.interpolate(marker * u_anal_lower + (1 - marker) * u_anal_upper)
    u_error = Function(V, name="VelocityError").assign(u_ - u_anal)

    # compute p analytical and error
    pxy = interpolate(as_vector((X[0], X[1])), Q1DGvec)
    pdg = interpolate(p, Q1DG)
    p_anal_upper = Function(Q1DG, name="AnalyticalPressureUpper")
    p_anal_lower = Function(Q1DG, name="AnalyticalPressureLower")
    p_anal = Function(Q1DG, name="AnalyticalPressure")
    p_anal_upper.dat.data[:] = [
        solution_upper.pressure_cartesian(xyi) for xyi in pxy.dat.data
    ]
    p_anal_lower.dat.data[:] = [
        solution_lower.pressure_cartesian(xyi) for xyi in pxy.dat.data
    ]
    p_anal.interpolate(marker * p_anal_lower + (1 - marker) * p_anal_upper)
    p_error = Function(Q1DG, name="PressureError").assign(pdg - p_anal)

    # Write output files in VTK format:
    u_.rename("Velocity")
    p_.rename("Pressure")
    u_file = File("fs_velocity_{}.pvd".format(disc_n))
    p_file = File("fs_pressure_{}.pvd".format(disc_n))

    # Write output:
    u_file.write(u_, u_anal, u_error)
    p_file.write(p_, p_anal, p_error)

    l2anal_u = math.sqrt(assemble(dot(u_anal, u_anal) * dx))
    l2anal_p = math.sqrt(assemble(dot(p_anal, p_anal) * dx))
    l2error_u = math.sqrt(assemble(dot(u_error, u_error) * dx))
    l2error_p = math.sqrt(assemble(dot(p_error, p_error) * dx))

    return l2error_u, l2error_p, l2anal_u, l2anal_p
Пример #3
0
 def case_bottom(self, n, case_kwargs):
     return assess.CylindricalStokesSolutionDeltaFreeSlip(
         n, -1, **case_kwargs)