Beispiel #1
0
    def __init__(self,
                 form,
                 Space,
                 bcs=[],
                 name="x",
                 matvec=[None, None],
                 method="default",
                 solver_type="cg",
                 preconditioner_type="default"):

        Function.__init__(self, Space, name=name)
        self.form = form
        self.method = method
        self.bcs = bcs
        self.matvec = matvec
        self.trial = trial = TrialFunction(Space)
        self.test = test = TestFunction(Space)
        Mass = inner(trial, test) * dx()
        self.bf = inner(form, test) * dx()
        self.rhs = Vector(self.vector())

        if method.lower() == "default":
            self.A = A_cache[(Mass, tuple(bcs))]
            self.sol = Solver_cache[(Mass, tuple(bcs), solver_type,
                                     preconditioner_type)]

        elif method.lower() == "lumping":
            assert Space.ufl_element().degree() < 2
            self.A = A_cache[(Mass, tuple(bcs))]
            ones = Function(Space)
            ones.vector()[:] = 1.
            self.ML = self.A * ones.vector()
            self.ML.set_local(1. / self.ML.array())
Beispiel #2
0
    def solve(self, dt):
        self.u = Function(self.V0)
        self.w = TestFunction(self.V0)
        self.du = TrialFunction(self.V0)

        x = SpatialCoordinate(self.mesh0)

        L = inner( self.S(), self.eps(self.w) )*dx(degree=4)\
        - inner( self.b, self.w )*dx(degree=4)\
        - inner( self.h, self.w )*ds(degree=4)\
        + inner( 1e-6*self.u, self.w )*ds(degree=4)\
        - inner( min_value(x[2]+self.ut[2]+self.u[2], 0) * Constant((0,0,-1.0)), self.w )*ds(degree=4)

        a = derivative(L, self.u, self.du)

        problem = NonlinearVariationalProblem(L, self.u, bcs=[], J=a)
        solver = NonlinearVariationalSolver(problem)

        solver.solve()

        self.ut.vector()[:] = self.ut.vector()[:] + self.u.vector()[:]

        ALE.move(self.mesh, Function(self.V, self.u.vector()))

        self.v.vector()[:] = self.u.vector()[:] / dt
        self.n = FacetNormal(self.mesh)
Beispiel #3
0
    def __new__(cls, mesh, tolerance=1e-12):
        dim = mesh.geometry().dim()
        X = MeshPool._X[dim - 1]

        test = assemble(dot(X, X) * CellVolume(mesh)**(0.25) *
                        dx()) * assemble(Constant(1) * dx(domain=mesh))
        assert test > 0.0
        assert test < np.inf

        # Do a garbage collect to collect any garbage references
        # Needed for full parallel compatibility
        gc.collect()
        keys = np.array(MeshPool._existing.keys())
        self = None
        if len(keys) > 0:
            diff = np.abs(keys - test) / np.abs(test)
            idx = np.argmin(np.abs(keys - test))

            if diff[idx] <= tolerance and isinstance(
                    mesh, type(MeshPool._existing[keys[idx]])):
                self = MeshPool._existing[keys[idx]]

        if self is None:
            self = mesh
            MeshPool._existing[test] = self
        return self
Beispiel #4
0
    def __init__(self, p_, Space, i=0, bcs=[], name="grad", method={}):

        assert len(p_.ufl_shape) == 0
        assert i >= 0 and i < Space.mesh().geometry().dim()

        solver_type = method.get('solver_type', 'cg')
        preconditioner_type = method.get('preconditioner_type', 'default')
        solver_method = method.get('method', 'default')
        low_memory_version = method.get('low_memory_version', False)

        OasisFunction.__init__(self, p_.dx(i), Space, bcs=bcs, name=name,
                               method=solver_method, solver_type=solver_type,
                               preconditioner_type=preconditioner_type)

        self.i = i
        Source = p_.function_space()
        if not low_memory_version:
            self.matvec = [
                A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], p_]

        if solver_method.lower() == "gradient_matrix":
            from fenicstools import compiled_gradient_module
            DG = FunctionSpace(Space.mesh(), 'DG', 0)
            G = assemble(TrialFunction(DG) * self.test * dx())
            dg = Function(DG)
            dP = assemble(TrialFunction(p_.function_space()).dx(i)
                          * TestFunction(DG) * dx())
            self.WGM = compiled_gradient_module.compute_weighted_gradient_matrix(
                G, dP, dg)
Beispiel #5
0
    def __init__(self, form, Space, bcs=[],
                 name="x",
                 matvec=[None, None],
                 method="default",
                 solver_type="cg",
                 preconditioner_type="default"):

        Function.__init__(self, Space, name=name)
        self.form = form
        self.method = method
        self.bcs = bcs
        self.matvec = matvec
        self.trial = trial = TrialFunction(Space)
        self.test = test = TestFunction(Space)
        Mass = inner(trial, test) * dx()
        self.bf = inner(form, test) * dx()
        self.rhs = Vector(self.vector())

        if method.lower() == "default":
            self.A = A_cache[(Mass, tuple(bcs))]
            self.sol = Solver_cache[(Mass, tuple(
                bcs), solver_type, preconditioner_type)]

        elif method.lower() == "lumping":
            assert Space.ufl_element().degree() < 2
            self.A = A_cache[(Mass, tuple(bcs))]
            ones = Function(Space)
            ones.vector()[:] = 1.
            self.ML = self.A * ones.vector()
            self.ML.set_local(1. / self.ML.array())
Beispiel #6
0
 def __init__(self, form, Space, bcs=[], 
              name="x", 
              matvec=[None, None], 
              method="default", 
              solver_type="cg", 
              preconditioner_type="default"):
     
     Function.__init__(self, Space, name=name)
     self.form = form
     self.method = method
     self.bcs = bcs
     self.matvec = matvec
     self.trial = trial = TrialFunction(Space)
     self.test = test = TestFunction(Space)
     Mass = inner(trial, test)*dx()
     self.bf = inner(form, test)*dx()
     self.rhs = Vector(self.vector())
     
     if method.lower() == "default":
         self.A = A_cache[(Mass, tuple(bcs))]
         self.sol = KrylovSolver(solver_type, preconditioner_type)
         self.sol.parameters["preconditioner"]["structure"] = "same"
         self.sol.parameters["error_on_nonconvergence"] = False
         self.sol.parameters["monitor_convergence"] = False
         self.sol.parameters["report"] = False
             
     elif method.lower() == "lumping":
         assert Space.ufl_element().degree() < 2
         self.A = A_cache[(Mass, tuple(bcs))]
         ones = Function(Space)
         ones.vector()[:] = 1.
         self.ML = self.A * ones.vector()
         self.ML.set_local(1. / self.ML.array())
Beispiel #7
0
    def __init__(self,
                 form,
                 mesh,
                 bcs=[],
                 name="CG1",
                 method={},
                 bounded=False):

        solver_type = method.get('solver_type', 'cg')
        preconditioner_type = method.get('preconditioner_type', 'default')
        solver_method = method.get('method', 'default')
        self.bounded = bounded

        Space = FunctionSpace(mesh, "CG", 1)
        OasisFunction.__init__(self,
                               form,
                               Space,
                               bcs=bcs,
                               name=name,
                               method=solver_method,
                               solver_type=solver_type,
                               preconditioner_type=preconditioner_type)

        if solver_method.lower() == "weightedaverage":
            from fenicstools import compiled_gradient_module
            DG = FunctionSpace(mesh, 'DG', 0)
            # Cannot use cache. Matrix will be modified
            self.A = assemble(TrialFunction(DG) * self.test * dx())
            self.dg = dg = Function(DG)
            compiled_gradient_module.compute_DG0_to_CG_weight_matrix(
                self.A, dg)
            self.bf_dg = inner(form, TestFunction(DG)) * dx()
def err_est_fun(mesh_name2, hol_cyl, T_sol1, T_sol2, deg_choice2, hol_cyl2,
                count_it):
    '''
    Error estimate.
    '''
    #comm1 = MPI.COMM_WORLD

    #rank1 = comm1.Get_rank()

    #e1 = sqrt(int_Omega (T - T_ex)**2. dx)/sqrt(int_Omega T**2. dx)
    #do.assemble yields integration
    e1 = do.sqrt(do.assemble(pow(T_sol2 - T_sol1, 2.) * do.dx(domain = hol_cyl))) / \
         do.sqrt(do.assemble(pow(T_sol1, 2.) * do.dx(domain = hol_cyl)))

    #sometimes e1 does not work properly (it might be unstable) -> e2
    #the degree of piecewise polynomials used to approximate T_th and T...
    #...will be the degree of T + degree_rise
    e2 = do.errornorm(T_sol1, T_sol2, norm_type = 'l2', degree_rise = 2, mesh = hol_cyl2) / \
         do.sqrt(do.assemble(pow(T_sol1, 2.) * do.dx(domain = hol_cyl)))

    print 'err: count_t = {}, error_1 = {}, error_2 = {}'.format(
        count_it, e1, e2)

    #print 'rank = ', rank1, ',
    print 'max(T_sol) = ', max(T_sol2.vector().array())
    #print 'rank = ', rank1, ',
    print 'min(T_sol) = ', min(T_sol2.vector().array()), '\n'

    return e1, e2
Beispiel #9
0
    def __init__(self, aneurysm, near_vessel, *args, **kwargs):
        Field.__init__(self, *args, **kwargs)
        
        self.aneurysm = aneurysm
        self.near_vessel = near_vessel

        self.Vnv = assemble(Constant(1)*dx(near_vessel[1], domain=near_vessel[0].mesh(), subdomain_data=near_vessel[0]))
        self.Va = assemble(Constant(1)*dx(aneurysm[1], domain=aneurysm[0].mesh(), subdomain_data=aneurysm[0]))
 def _setup_energy(self, rho, vel, gvec, x0):
     """
     Calculate kinetic and potential energy
     """
     x = df.SpatialCoordinate(self.mesh)
     self._form_E_k = Form(1 / 2 * rho * dot(vel, vel) *
                           dx(domain=self.mesh))
     self._form_E_p = Form(rho * dot(-gvec, x - x0) * dx(domain=self.mesh))
Beispiel #11
0
    def __init__(self, aneurysm, near_vessel, *args, **kwargs):
        Field.__init__(self, *args, **kwargs)

        self.aneurysm = aneurysm
        self.near_vessel = near_vessel

        self.Vnv = assemble(
            Constant(1) * dx(near_vessel[1],
                             domain=near_vessel[0].mesh(),
                             subdomain_data=near_vessel[0]))
        self.Va = assemble(
            Constant(1) * dx(aneurysm[1],
                             domain=aneurysm[0].mesh(),
                             subdomain_data=aneurysm[0]))
Beispiel #12
0
    def __init__(self, u_, Space, bcs=[], name="div", method={}):

        solver_type = method.get('solver_type', 'cg')
        preconditioner_type = method.get('preconditioner_type', 'default')
        solver_method = method.get('method', 'default')
        low_memory_version = method.get('low_memory_version', False)

        OasisFunction.__init__(self, div(u_), Space, bcs=bcs, name=name,
                               method=solver_method, solver_type=solver_type,
                               preconditioner_type=preconditioner_type)

        Source = u_[0].function_space()
        if not low_memory_version:
            self.matvec = [[A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], u_[i]]
                           for i in range(Space.mesh().geometry().dim())]

        if solver_method.lower() == "gradient_matrix":
            from fenicstools import compiled_gradient_module
            DG = FunctionSpace(Space.mesh(), 'DG', 0)
            G = assemble(TrialFunction(DG) * self.test * dx())
            dg = Function(DG)
            self.WGM = []
            st = TrialFunction(Source)
            for i in range(Space.mesh().geometry().dim()):
                dP = assemble(st.dx(i) * TestFunction(DG) * dx)
                A = Matrix(G)
                self.WGM.append(compiled_gradient_module.compute_weighted_gradient_matrix(A, dP, dg))
Beispiel #13
0
def divergence_matrix(mesh):
    CR = VectorFunctionSpace(mesh, 'CR', 1)
    DG = FunctionSpace(mesh, 'DG', 0)
    A = cg1_cr_interpolation_matrix(mesh)
    M = assemble(dot(div(TrialFunction(CR)), TestFunction(DG)) * dx())
    C = compiled_cr_module.cr_divergence_matrix(M, A, DG, CR)
    return C
Beispiel #14
0
  def dx(self, domain = "all", dx = None):
    """
    Convenience wrapper for integral-cell measure. If the mesh does not contain
    any cell domains, the measure for the whole mesh is returned.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        name or ID of domain
      dx (:class:`dolfin:Measure`)
        alternative measure

    *Returns*
      :class:`dolfin:Measure`
        the measure


        # Compute volume of magnetic domain
        assemble(Constant(1.0) * state.dx('magnetic'))

        # Compute volume of domain with ID 3
        assemble(Constant(1.0) * state.dx(3))
    """
    # return measure for whole mesh if no domains are defined
    if not self.mesh_has_domains(): return self._dx

    domain_ids = self.domain_ids(domain)
    # XXX fall back to zero measure
    if len(domain_ids) == 0: domain_ids = (999999,)

    if dx == None: dx = self._dx

    return reduce(lambda x,y: x+y, map(lambda i: dx(i), domain_ids))
Beispiel #15
0
    def __init__(
        self,
        mesh,
        field,
        strain_tensor="E",
        dmu=None,
        approx="original",
        F_ref=None,
        isochoric=True,
        displacement_space="CG_2",
        interpolation_space="CG_1",
        description="",
    ):

        ModelObservation.__init__(self,
                                  mesh,
                                  target_space="R_0",
                                  description=description)

        # Check that the given field is a vector of the same dim as the mesh
        dim = mesh.geometry().dim()
        # assert isinstance(field, (dolfin.Function, dolfin.Constant)
        assert field.ufl_shape[0] == dim
        approxs = ["project", "interpolate", "original"]
        msg = 'Expected "approx" for be one of {}, got {}'.format(
            approxs, approx)
        self.field = field

        assert approx in approxs, msg
        self._approx = approx

        self._F_ref = F_ref if F_ref is not None else dolfin.Identity(dim)

        self._isochoric = isochoric

        tensors = ["gradu", "E", "almansi"]
        msg = "Expected strain tensor to be one of {}, got {}".format(
            tensors, strain_tensor)
        assert strain_tensor in tensors, msg
        self._tensor = strain_tensor

        if dmu is None:
            dmu = dolfin.dx(domain=mesh)
        assert isinstance(dmu, dolfin.Measure)
        self._dmu = dmu

        self._vol = dolfin_adjoint.Constant(
            dolfin.assemble(dolfin.Constant(1.0) * dmu))

        # These spaces are only used if you want to project
        # or interpolate the displacement before assigning it
        # Space for interpolating the displacement if needed
        family, degree = interpolation_space.split("_")
        self._interpolation_space = dolfin.VectorFunctionSpace(
            mesh, family, int(degree))

        # Displacement space
        family, degree = displacement_space.split("_")
        self._displacement_space = dolfin.VectorFunctionSpace(
            mesh, family, int(degree))
Beispiel #16
0
    def test_to_DG0(self):
        subdomains = (df.CompiledSubDomain('near(x[0], 0.5)'), df.DomainBoundary())
        
        for subd in subdomains: 
            mesh = df.UnitCubeMesh(4, 4, 4)
            facet_f = df.MeshFunction('size_t', mesh, 2, 0)
            subd.mark(facet_f, 1)
                
            submesh = EmbeddedMesh(facet_f, 1)

            transfer = SubMeshTransfer(mesh, submesh)

            V = df.FunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0)
            Vsub = df.FunctionSpace(submesh, 'DG', 0)
                
            to_Vsub = transfer.compute_map(Vsub, V, strict=False)
            # Set degree 0 to get the quad order right
            f = df.Expression('x[0] + 2*x[1] - x[2]', degree=0)
                
            fV = df.interpolate(f, V)
            fsub = df.Function(Vsub)
                
            to_Vsub(fsub, fV)
                
            error = df.inner(fsub - f, fsub - f)*df.dx(domain=submesh)
            error = df.sqrt(abs(df.assemble(error)))
                
            self.assertTrue(error < 1E-13)
def divergence_matrix(mesh):
    CR = VectorFunctionSpace(mesh, 'CR', 1)
    DG = FunctionSpace(mesh, 'DG', 0)
    A = cg1_cr_interpolation_matrix(mesh)    
    M  = assemble(dot(div(TrialFunction(CR)), TestFunction(DG))*dx())
    C = compiled_cr_module.cr_divergence_matrix(M, A, DG, CR)
    return C
Beispiel #18
0
def test_mat_without_dictionnary():
    """FenicsPart instance initialized with only one instance of Material"""
    L_x, L_y = 1, 1
    mesh = fe.RectangleMesh(fe.Point(0.0, 0.0), fe.Point(L_x, L_y), 10, 10)
    dimensions = np.array(((L_x, 0.0), (0.0, L_y)))
    E, nu = 1, 0.3
    material = mat.Material(E, nu, "cp")
    rect_part = part.FenicsPart(
        mesh,
        materials=material,
        subdomains=None,
        global_dimensions=dimensions,
        facet_regions=None,
    )
    elem_type = "CG"
    degree = 2
    strain_fspace = fe.FunctionSpace(
        mesh,
        fe.VectorElement(elem_type, mesh.ufl_cell(), degree, dim=3),
    )
    strain = fe.project(fe.Expression(("1.0+x[0]*x[0]", "0", "1.0"), degree=2),
                        strain_fspace)
    stress = mat.sigma(rect_part.elasticity_tensor, strain)
    energy = fe.assemble(fe.inner(stress, strain) * fe.dx(rect_part.mesh))
    energy_theo = E / (1 + nu) * (1 + 28 / (15 * (1 - nu)))
    assert energy == approx(energy_theo, rel=1e-13)
def verify_function_slice(func_slice, u, cpp_2d, expected_area):
    u_2D = func_slice.get_slice(u)

    # The 2D solution we want to obtain
    analytical = dolfin.Expression(cpp_2d, degree=2 + 3)

    comm = dolfin.MPI.comm_world
    if comm.rank == 0:
        error = dolfin.errornorm(analytical, u_2D)
        mesh = func_slice.slice_function_space.mesh()
        area = dolfin.assemble(1 * dolfin.dx(domain=mesh))

        if True:
            import matplotlib

            matplotlib.use('Agg')
            from matplotlib import pyplot

            fig = pyplot.figure()
            dolfin.plot(u_2D)
            pyplot.gca().view_init(90, 270)
            pyplot.gca().set_proj_type('ortho')
            pyplot.gca().set_xlabel('x')
            pyplot.gca().set_ylabel('y')
            fig.savefig('test_func_slice.png')
    else:
        error = 0.0
        area = 0.0

    assert dolfin.MPI.max(comm, error) < 0.015
    area = dolfin.MPI.sum(comm, area)
    assert abs(area - expected_area) < 1e-8
Beispiel #20
0
        def forward(control, annotate=True):

            self.reset_problem()
            annotation.annotate = annotate

            states = []
            functional_values = []

            functional = self.create_functional()
            functionals_time = []

            gen = self.iteration(control)
            for count in gen:

                # Collect stuff
                states.append(dolfin.Vector(self.problem.state.vector()))
                functional_values.append(functional)
                functionals_time.append(functional)

            return forward_result(
                functional=dolfin_adjoint.assemble(
                    list_sum(functionals_time) / self._meshvol *
                    dolfin.dx(domain=self.problem.geometry.mesh)),
                converged=True,
            )
Beispiel #21
0
def get_residual_form(u, v, rho_e, method='RAMP'):

    df.dx = df.dx(metadata={"quadrature_degree": 4})
    # stiffness = rho_e/(1 + 8. * (1. - rho_e))

    if method == 'SIMP':
        stiffness = rho_e**3
    else:  #RAMP
        stiffness = rho_e / (1 + 8. * (1. - rho_e))

    # print('the value of stiffness is:', rho_e.vector().get_local())
    # Kinematics
    k = 3e1
    E = k * stiffness
    nu = 0.3
    mu, lmbda = (E / (2 * (1 + nu))), (E * nu / ((1 + nu) * (1 - 2 * nu)))

    d = len(u)
    I = df.Identity(d)  # Identity tensor
    F = I + df.grad(u)  # Deformation gradient
    C = F.T * F  # Right Cauchy-Green tensor

    E_ = 0.5 * (C - I)  # Green--Lagrange strain
    S = 2.0 * mu * E_ + lmbda * df.tr(E_) * df.Identity(
        d)  # stress tensor (C:eps)
    psi = 0.5 * df.inner(S, E_)  # 0.5*eps:C:eps

    # Total potential energy
    Pi = psi * df.dx
    # Solve weak problem obtained by differentiating Pi:
    res = df.derivative(Pi, u, v)
    return res
Beispiel #22
0
def test_2_materials():
    """FenicsPart instance initialized with only one instance of Material in the materials dictionnary"""
    L_x, L_y = 1, 1
    mesh = fe.RectangleMesh(fe.Point(-L_x, -L_y), fe.Point(L_x, L_y), 20, 20)
    dimensions = np.array(((2 * L_x, 0.0), (0.0, 2 * L_y)))
    subdomains = fe.MeshFunction("size_t", mesh, 2)

    class Right_part(fe.SubDomain):
        def inside(self, x, on_boundary):
            return x[0] >= 0 - fe.DOLFIN_EPS

    subdomain_right = Right_part()
    subdomains.set_all(0)
    subdomain_right.mark(subdomains, 1)
    E_1, E_2, nu = 1, 3, 0.3
    materials = {0: mat.Material(1, 0.3, "cp"), 1: mat.Material(3, 0.3, "cp")}
    rect_part = part.FenicsPart(mesh, materials, subdomains, dimensions)
    elem_type = "CG"
    degree = 2
    strain_fspace = fe.FunctionSpace(
        mesh,
        fe.VectorElement(elem_type, mesh.ufl_cell(), degree, dim=3),
    )
    strain = fe.project(fe.Expression(("1.0+x[0]*x[0]", "0", "1.0"), degree=2),
                        strain_fspace)
    stress = mat.sigma(rect_part.elasticity_tensor, strain)
    energy = fe.assemble(fe.inner(stress, strain) * fe.dx(rect_part.mesh))
    energy_theo = 2 * ((E_1 + E_2) / (1 + nu) * (1 + 28 / (15 * (1 - nu))))
    assert energy == approx(energy_theo, rel=1e-13)
Beispiel #23
0
def strain_cross_energy(sig, eps, mesh, area):
    """
    Calcul de l'energie croisée des champs de contrainte sig et de deformation eps.
    """
    # TODO : Redondant. Voir si cela est nécessaire.

    return fe.assemble(fe.inner(sig, eps) * fe.dx(mesh)) / area
Beispiel #24
0
def test_local_assembler_1D():
    mesh = UnitIntervalMesh(MPI.comm_world, 20)
    V = FunctionSpace(mesh, 'CG', 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    c = Cell(mesh, 0)

    a_scalar = 1.0 * dx(domain=mesh)
    a_vector = v * dx
    a_matrix = u * v * dx

    A_scalar = assemble_local(a_scalar, c)
    A_vector = assemble_local(a_vector, c)
    A_matrix = assemble_local(a_matrix, c)

    assert isinstance(A_scalar, float)
    assert numpy.isclose(A_scalar, 0.05)

    assert isinstance(A_vector, numpy.ndarray)
    assert A_vector.shape == (2,)
    assert numpy.isclose(A_vector[0], 0.025)
    assert numpy.isclose(A_vector[1], 0.025)

    assert isinstance(A_matrix, numpy.ndarray)
    assert A_matrix.shape == (2, 2)
    assert numpy.isclose(A_matrix[0, 0], 1 / 60)
    assert numpy.isclose(A_matrix[0, 1], 1 / 120)
    assert numpy.isclose(A_matrix[1, 0], 1 / 120)
    assert numpy.isclose(A_matrix[1, 1], 1 / 60)
Beispiel #25
0
    def __init__(self, V, parameters=None):
        # Set parameters
        self.parameters = self.default_parameters()
        if parameters is not None:
            self.parameters.update(parameters)

        # Set-up mass matrix for L^2 projection
        self.V = V
        self.u = df.TrialFunction(self.V)
        self.v = df.TestFunction(self.V)
        self.m = df.inner(self.u, self.v) * df.dx()
        self.M = df.assemble(self.m)
        self.b = df.Vector(V.mesh().mpi_comm(), V.dim())

        solver_type = self.parameters["linear_solver_type"]
        assert(solver_type == "lu" or solver_type == "cg"),  \
            "Expecting 'linear_solver_type' to be 'lu' or 'cg'"
        if solver_type == "lu":
            df.debug("Setting up direct solver for projecter")
            # Customize LU solver (reuse everything)
            solver = df.LUSolver(self.M)
            solver.parameters["same_nonzero_pattern"] = True
            solver.parameters["reuse_factorization"] = True
        else:
            df.debug("Setting up iterative solver for projecter")
            # Customize Krylov solver (reuse everything)
            solver = df.KrylovSolver("cg", "ilu")
            solver.set_operator(self.M)
            solver.parameters["preconditioner"]["structure"] = "same"
            # solver.parameters["nonzero_initial_guess"] = True
        self.solver = solver
Beispiel #26
0
    def test_to_DG0_subdomain(self):
        mesh = df.UnitSquareMesh(4, 4)
        cell_f = df.MeshFunction('size_t', mesh, 2, 0)
        df.CompiledSubDomain('x[0] < 0.5 + DOLFIN_EPS').mark(cell_f, 1)

        submesh = EmbeddedMesh(cell_f, 1)

        transfer = SubMeshTransfer(mesh, submesh)

        V = df.FunctionSpace(mesh, 'DG', 0)
        Vsub = df.FunctionSpace(submesh, 'DG', 0)

        to_Vsub = transfer.compute_map(Vsub, V, strict=True)
        # Set degree 0 to get the quad order right
        f = df.Expression('x[0] + 2*x[1]', degree=0)

        fV = df.interpolate(f, V)
        fsub = df.Function(Vsub)

        to_Vsub(fsub, fV)

        error = df.inner(fsub - f, fsub - f)*df.dx(domain=submesh)
        error = df.sqrt(abs(df.assemble(error)))

        self.assertTrue(error < 1E-13)
    def create(self):
        self.metadata = {
            "quadrature_degree": self.deg_q,
            "quadrature_scheme": "default",
        }
        self.dxm = df.dx(metadata=self.metadata,
                         subdomain_data=self.mesh_function)

        # solution field
        Ed = df.VectorElement("CG", self.mesh.ufl_cell(), degree=self.deg_d)
        Ee = df.FiniteElement("CG", self.mesh.ufl_cell(), degree=self.deg_d)

        self.V = df.FunctionSpace(self.mesh, Ed * Ee)
        self.Vd, self.Ve = self.V.split()

        self.dd, self.de = df.TrialFunctions(self.V)
        self.d_, self.e_ = df.TestFunctions(self.V)

        self.u = df.Function(self.V, name="d-e mixed space")
        self.d, self.e = df.split(self.u)

        # generic quadrature function spaces
        VQF, VQV, VQT = c.helper.spaces(self.mesh, self.deg_q,
                                        c.q_dim(self.constraint))

        # quadrature functions
        Q = c.Q
        # inputs to the model
        self.q_in = OrderedDict()
        self.q_in[Q.EPS] = df.Function(VQV, name="current strains")
        self.q_in[Q.E] = df.Function(
            VQF, name="current nonlocal equivalent strains")

        self.q_in_calc = {}
        self.q_in_calc[Q.EPS] = c.helper.LocalProjector(
            self.eps(self.d), VQV, self.dxm)
        self.q_in_calc[Q.E] = c.helper.LocalProjector(self.e, VQF, self.dxm)

        # outputs of the model
        self.q = {}
        self.q[Q.SIGMA] = df.Function(VQV, name="current stresses")
        self.q[Q.DSIGMA_DEPS] = df.Function(VQT, name="stress-strain tangent")
        self.q[Q.DSIGMA_DE] = df.Function(
            VQV, name="stress-nonlocal-strain tangent")
        self.q[Q.EEQ] = df.Function(VQF,
                                    name="current (local) equivalent strain")
        self.q[Q.DEEQ] = df.Function(VQV,
                                     name="equivalent-strain-strain tangent")

        self.q_history = {
            Q.KAPPA: df.Function(VQF, name="current history variable kappa")
        }

        self.n = len(self.q[Q.SIGMA].vector().get_local()) // c.q_dim(
            self.constraint)
        self.nq = self.n // self.mesh.num_cells()
        self.ip_flags = None
        if self.mesh_function is not None:
            self.ip_flags = np.repeat(self.mesh_function.array(), self.nq)
Beispiel #28
0
    def pressure_correction(self):
        """
        Solve the pressure correction equation

        We handle the case where only Neumann conditions are given
        for the pressure by taking out the nullspace, a constant shift
        of the pressure, by providing the nullspace to the solver
        """
        p = self.simulation.data['p']
        p_hat = self.simulation.data['p_hat']

        # Temporarily store the old pressure
        p_hat.vector().zero()
        p_hat.vector().axpy(-1, p.vector())

        # Assemble the A matrix only the first inner iteration
        if self.inner_iteration == 1:
            self.Ap = dolfin.as_backend_type(self.eq_pressure.assemble_lhs())
        A = self.Ap
        b = dolfin.as_backend_type(self.eq_pressure.assemble_rhs())

        # Inform PETSc about the null space
        if self.remove_null_space:
            if self.pressure_null_space is None:
                # Create vector that spans the null space
                null_vec = dolfin.Vector(p.vector())
                null_vec[:] = 1
                null_vec *= 1 / null_vec.norm("l2")

                # Create null space basis object
                self.pressure_null_space = dolfin.VectorSpaceBasis([null_vec])

            # Make sure the null space is set on the matrix
            if self.inner_iteration == 1:
                A.set_nullspace(self.pressure_null_space)

            # Orthogonalize b with respect to the null space
            self.pressure_null_space.orthogonalize(b)

        # Solve for the new pressure correction
        self.niters_p = self.pressure_solver.inner_solve(
            A,
            p.vector(),
            b,
            in_iter=self.inner_iteration,
            co_iter=self.co_inner_iter)

        # Removing the null space of the matrix system is not strictly the same as removing
        # the null space of the equation, so we correct for this here
        if self.remove_null_space:
            dx2 = dolfin.dx(domain=p.function_space().mesh())
            vol = dolfin.assemble(dolfin.Constant(1) * dx2)
            pavg = dolfin.assemble(p * dx2) / vol
            p.vector()[:] -= pavg

        # Calculate p_hat = p_new - p_old
        p_hat.vector().axpy(1, p.vector())

        return p_hat.vector().norm('l2')
Beispiel #29
0
def main():
    fsr = FunctionSubspaceRegistry()

    deg = 2
    mesh = dolfin.UnitSquareMesh(100, 3)
    muc = mesh.ufl_cell()
    el_w = dolfin.FiniteElement('DG', muc, deg - 1)
    el_j = dolfin.FiniteElement('BDM', muc, deg)
    el_DG0 = dolfin.FiniteElement('DG', muc, 0)
    el = dolfin.MixedElement([el_w, el_j])
    space = dolfin.FunctionSpace(mesh, el)
    DG0 = dolfin.FunctionSpace(mesh, el_DG0)
    fsr.register(space)
    facet_normal = dolfin.FacetNormal(mesh)
    xyz = dolfin.SpatialCoordinate(mesh)

    trial = dolfin.Function(space)
    test = dolfin.TestFunction(space)

    w, c = dolfin.split(trial)
    v, phi = dolfin.split(test)

    sympy_exprs = derive_exprs()
    exprs = {
        k: sympy_dolfin_printer.to_ufl(sympy_exprs['R'], mesh, v)
        for k, v in sympy_exprs['quantities'].items()
    }

    f = exprs['f']
    w0 = dolfin.project(dolfin.conditional(dolfin.gt(xyz[0], 0.5), 1.0, 0.3),
                        DG0)
    w_BC = exprs['w']

    dx = dolfin.dx()
    form = (+v * dolfin.div(c) * dx - v * f * dx +
            dolfin.exp(w + w0) * dolfin.dot(phi, c) * dx +
            dolfin.div(phi) * w * dx -
            (w_BC - w0) * dolfin.dot(phi, facet_normal) * dolfin.ds() -
            (w0('-') - w0('+')) * dolfin.dot(phi('+'), facet_normal('+')) *
            dolfin.dS())

    solver = NewtonSolver(form,
                          trial, [],
                          parameters=dict(relaxation_parameter=1.0,
                                          maximum_iterations=15,
                                          extra_iterations=10,
                                          relative_tolerance=1e-6,
                                          absolute_tolerance=1e-7))

    solver.solve()

    with closing(XdmfPlot("out/qflop_test.xdmf", fsr)) as X:
        CG1 = dolfin.FunctionSpace(mesh, dolfin.FiniteElement('CG', muc, 1))
        X.add('w0', 1, w0, CG1)
        X.add('w_c', 1, w + w0, CG1)
        X.add('w_e', 1, exprs['w'], CG1)
        X.add('f', 1, f, CG1)
        X.add('cx_c', 1, c[0], CG1)
        X.add('cx_e', 1, exprs['c'][0], CG1)
Beispiel #30
0
        def matvec(self, b):
            '''Action on vector from V1'''
            V, Q = self.V1, self.V0
            
            gamma_mesh = V.mesh()
            auxiliary_facet_f = self.facet_f
            aux_mesh = auxiliary_facet_f.mesh()
            
            # The problem for uh
            V2 = df.FunctionSpace(aux_mesh, Q.ufl_element().family(), Q.ufl_element().degree())
            u, v = df.TrialFunction(V2), df.TestFunction(V2)

            # Wrap the vector as function ...
            f = df.Function(V, b)
            # ... to be used in the weak form for the Laplacian
            a = df.inner(df.grad(u), df.grad(v))*df.dx + df.inner(u, v)*df.dx
            L = df.inner(f, Trace(v, gamma_mesh))*df.dx(domain=gamma_mesh)

            A, b = list(map(xii.assembler.xii_assembly.assemble, (a, L)))
            # We have boundary conditions to apply
            # bc = df.DirichletBC(V2, df.Constant(0), auxiliary_facet_f, 1)
            # A, b = apply_bc(A, b, bc)

            uh = df.Function(V2)
            df.solve(A, uh.vector(), b)

            # Now take trace of that
            ext_mesh = Q.mesh()
            # Get the trace at extended domain by projection
            p, q = df.TrialFunction(Q), df.TestFunction(Q)
            
            f = Trace(uh, ext_mesh)
            a = df.inner(p, q)*df.dx
            L = df.inner(f, q)*df.dx(domain=ext_mesh)

            A, b  = list(map(xii.assembler.xii_assembly.assemble, (a, L)))
            # We have boundary conditions to apply
            # FIXME: inherit from uh?
            # bc = df.DirichletBC(Q, uh, 'on_boundary')
            # A, b = apply_bc(A, b, bc)

            qh = df.Function(Q)
            df.solve(A, qh.vector(), b)

            return qh.vector()
Beispiel #31
0
    def compute(self, get):
        u = get("Velocity")
        assemble(dot(u[1].dx(0) - u[0].dx(1), self.q) * dx(), tensor=self.L)
        self.bc.apply(self.L)

        self.solver.solve(self.psi.vector(), self.L)
        #solve(self.A, self.psi.vector(), self.L)

        return self.psi
Beispiel #32
0
def test_nasty_jit_caching_bug():

    # This may result in something like "matrices are not aligned"
    # from FIAT if the JIT caching does not recognize that the two
    # forms are different

    default_parameters = parameters["form_compiler"]["representation"]
    for representation in ["quadrature"]:

        parameters["form_compiler"]["representation"] = representation

        M1 = assemble(Constant(1.0)*dx(UnitSquareMesh(4, 4)))
        M2 = assemble(Constant(1.0)*dx(UnitCubeMesh(4, 4, 4)))

        assert round(M1 - 1.0, 7) == 0
        assert round(M2 - 1.0, 7) == 0

    parameters["form_compiler"]["representation"] = default_parameters
Beispiel #33
0
            def __init__(self, valuename, nu, subdomain,*args, **kwargs):
                Field.__init__(self, *args, **kwargs)
                self.valuename = valuename
                mf = subdomain[0]
                idx = subdomain[1]
                self.dx = dx(idx, domain=mf.mesh(), subdomain_data=mf)
                self.vol = assemble(Constant(1)*self.dx)

                self.nu = nu
Beispiel #34
0
    def set_cell_domains(self, cell_domains, cell_mark_value):
        """Set cell domain mesh function

        Needed if the functional is to be calculated over only part of the domain
        """
        self.cell_domains = cell_domains
        self.cell_mark_value = cell_mark_value
        self.dx = dx(self.cell_mark_value)
        self.dirty = True
Beispiel #35
0
    def set_cell_domains(self, cell_domains, cell_mark_value):
        """Set cell domain mesh function

        Needed if the functional is to be calculated over only part of the domain
        """
        self.cell_domains = cell_domains
        self.cell_mark_value = cell_mark_value
        self.dx = dx(self.cell_mark_value)
        self.dirty = True
Beispiel #36
0
    def __call__(self, u=None, assemb_rhs=True):
        if isinstance(u, Coefficient): 
            self.matvec[1] = u
            self.bf = u.dx(self.i)*self.test*dx()

        if self.method.lower() == "gradient_matrix":    
            self.vector()[:] = self.WGM * self.matvec[1].vector()
        else:
            OasisFunction.__call__(self, assemb_rhs=assemb_rhs)
def make_mass_matrix_quadrature_lumping(function_space_V):
    V = function_space_V
    u_trial = dl.TrialFunction(V)
    v_test = dl.TestFunction(V)
    # mass lumping scheme code by Jeremy Bleyer
    # See: https://comet-fenics.readthedocs.io/en/latest/demo/tips_and_tricks/mass_lumping.html
    mass_form = u_trial * v_test * dl.dx(scheme="lumped", degree=2)
    ML = dl.assemble(mass_form)
    return ML
Beispiel #38
0
def test_nasty_jit_caching_bug():

    # This may result in something like "matrices are not aligned"
    # from FIAT if the JIT caching does not recognize that the two
    # forms are different

    default_parameters = parameters["form_compiler"]["representation"]
    for representation in ["quadrature"]:

        parameters["form_compiler"]["representation"] = representation

        M1 = assemble(Constant(1.0) * dx(UnitSquareMesh(4, 4)))
        M2 = assemble(Constant(1.0) * dx(UnitCubeMesh(4, 4, 4)))

        assert round(M1 - 1.0, 7) == 0
        assert round(M2 - 1.0, 7) == 0

    parameters["form_compiler"]["representation"] = default_parameters
Beispiel #39
0
            def __init__(self, valuename, nu, subdomain, *args, **kwargs):
                Field.__init__(self, *args, **kwargs)
                self.valuename = valuename
                mf = subdomain[0]
                idx = subdomain[1]
                self.dx = dx(idx, domain=mf.mesh(), subdomain_data=mf)
                self.vol = assemble(Constant(1) * self.dx)

                self.nu = nu
Beispiel #40
0
    def compute(self, get):
        u = get("Velocity")
        assemble(dot(u[1].dx(0)-u[0].dx(1), self.q)*dx(), tensor=self.L)
        self.bc.apply(self.L)

        self.solver.solve(self.psi.vector(), self.L)
        #solve(self.A, self.psi.vector(), self.L)

        return self.psi
Beispiel #41
0
def divergence_matrix(mesh):
    CR = VectorFunctionSpace(mesh, 'CR', 1)
    DG = FunctionSpace(mesh, 'DG', 0)
    A = cg1_cr_interpolation_matrix(mesh)
    M  = assemble(dot(div(TrialFunction(CR)), TestFunction(DG))*dx())
    compiled_cr_module.cr_divergence_matrix(M, A, DG, CR)
    M_mat = as_backend_type(M).mat()
    M_mat.matMult(A.mat())
    return M
Beispiel #42
0
 def __init__(self, form, mesh, bcs=[], name="CG1", method={}, bounded=False):
     
     solver_type = method.get('solver_type', 'cg')
     preconditioner_type = method.get('preconditioner_type', 'default')
     solver_method = method.get('method', 'default')
     self.bounded = bounded
     
     Space = FunctionSpace(mesh, "CG", 1)
     OasisFunction.__init__(self, form, Space, 
                            bcs=bcs, name=name, 
                            method=solver_method, solver_type=solver_type,
                            preconditioner_type=preconditioner_type)
             
     if solver_method.lower() == "weightedaverage":
         from fenicstools import compiled_gradient_module
         DG = FunctionSpace(mesh, 'DG', 0)
         self.A = assemble(TrialFunction(DG)*self.test*dx()) # Cannot use cache. Matrix will be modified
         self.dg = dg = Function(DG)
         compiled_gradient_module.compute_DG0_to_CG_weight_matrix(self.A, dg)
         self.bf_dg = inner(form, TestFunction(DG))*dx()
Beispiel #43
0
    def compute(self, get):
        t1 = get("t")
        t0 = get("t", -1)
        dt = Constant(t1 - t0)
        u = get("Velocity")

        hF = self._hF
        hK = self._hK
        scaling = 1.0 / hK
        assemble((dt * sqrt(u**2) / hF)*self._v*scaling*dx(),
                 tensor=self._cfl.vector())

        return self._cfl
Beispiel #44
0
def _print_diagnostics(
    theta0,
    umax,
    submesh_workpiece,
    wpi_area,
    subdomain_materials,
    wpi,
    rho,
    mu,
    char_length,
    grav,
):
    av_temperature = assemble(theta0 * dx(submesh_workpiece)) / wpi_area
    vec = theta0.vector()
    temperature_difference = vec.max() - vec.min()
    info("Max temperature: {:e}".format(vec.max()))
    info("Min temperature: {:e}".format(vec.min()))
    info("Av  temperature: {:e}".format(av_temperature))
    info("")
    info("Max velocity: {:e}".format(umax))
    info("")
    char_velocity = umax
    melt_material = subdomain_materials[wpi]
    rho_const = rho(av_temperature)

    cp = melt_material.specific_heat_capacity
    if not isinstance(cp, float):
        cp = cp(av_temperature)
    k = melt_material.thermal_conductivity
    if not isinstance(k, float):
        k = k(av_temperature)

    mu_const = mu(av_temperature)
    #
    info("Prandtl number: {:e}".format(_get_prandtl(mu_const, rho_const, cp, k)))
    info(
        "Reynolds number: {:e}".format(
            _get_reynolds(rho_const, mu_const, char_length, char_velocity)
        )
    )
    info(
        "Grashof number: {:e}".format(
            _get_grashof(
                rho, mu_const, grav, av_temperature, char_length, temperature_difference
            )
        )
    )
    return
Beispiel #45
0
    def before_first_compute(self, get):
        u = get("Velocity")
        assert len(u) == 2, "Can only compute stream function for 2D problems"
        V = u.function_space()
        spaces = SpacePool(V.mesh())
        degree = V.ufl_element().degree()
        V = spaces.get_space(degree, 0)

        psi = TrialFunction(V)
        self.q = TestFunction(V)
        a = dot(grad(psi), grad(self.q))*dx()

        self.bc = DirichletBC(V, Constant(0), DomainBoundary())
        self.A = assemble(a)
        self.L = Vector()
        self.bc.apply(self.A)
        self.solver = KrylovSolver(self.A, "cg")
        self.psi = Function(V)
Beispiel #46
0
    def add_fields(self):
        Field.start_recording()

        params = self.params.copy_recursive()
        if not self.params.debug:
            params["save"] = False
            params["plot"] = False
        params.pop("debug")
        params.pop("use_timeaverage")
        params.pop("finalize")
        T0, T1 = self.params.start_time, self.params.end_time
        assert T0 != Field.default_params().start_time
        assert T1 != Field.default_params().end_time

        tau = Magnitude("WSS")
        if self.params.use_timeaverage:
            tau = TimeAverage(tau, params=params)

        threshold = DomainAvg(tau, cell_domains=self.near_vessel[0], indicator=self.near_vessel[1], label="nv") + \
                    DomainSD(tau, cell_domains=self.aneurysm[0], indicator=self.aneurysm[1], label="aneurysm")
        threshold.name = "threshold_sci_nv"
        mask = Threshold(tau, threshold, dict(threshold_by="above"))

        mf = self.aneurysm[0]
        idx = self.aneurysm[1]

        Aa = ConstantField(assemble(Constant(1)*dx(idx, domain=mf.mesh(), subdomain_data=mf)))
        Aa.name = "AneurysmArea"
        Fh = Aa*DomainAvg(tau*mask, cell_domains=mf, indicator=idx, params=params)
        Fh.name = "HighShear"
        Ah = Aa*DomainAvg(mask, cell_domains=mf, indicator=idx, params=params)+ConstantField(1e-12)
        Ah.name = "HighShearArea"
        Fa = Aa*DomainAvg(tau, cell_domains=mf, indicator=idx, params=params)
        Fa.name = "TotalShear"

        f = (Fh/Fa)/(Ah/Aa)

        if not self.params.use_timeaverage:
            f = TimeAverage(f, params=params)

        self.valuename = f.name

        fields = Field.stop_recording()
        return fields
Beispiel #47
0
    def assemble_rhs(self, u=None):
        """
        Assemble right hand side trial.dx(i)*test*dx.

        Possible Coefficient u may replace p_ and makes it possible
        to use this Function to compute both grad(p) and grad(dp), i.e.,
        the gradient of pressure correction.

        """
        if isinstance(u, Coefficient):
            self.matvec[1] = u
            self.bf = u.dx(self.i) * self.test * dx()

        if not self.matvec[0] is None:
            mat, func = self.matvec
            self.rhs.zero()
            self.rhs.axpy(1.0, mat * func.vector())
        else:
            assemble(self.bf, tensor=self.rhs)
Beispiel #48
0
def sobolev_norm(u, p, k=1, domain=None):
    """Return Sobolev seminorm on W^{k, p} of function u. If u is
    None, return infinity."""
    # Special case
    if u is None:
        return np.infty

    # Prepare exponent and measure
    p = Constant(p) if p is not 2 else p
    dX = dx(domain)

    # Take derivative if k==1
    if k == 1:
        u = grad(u)
    elif k == 0:
        u = u
    else:
        raise NotImplementedError

    # Assemble functional and return
    return assemble(inner(u, u)**(p/2)*dX)**(1.0/float(p))
Beispiel #49
0
# Right hand side and boundary value for velocity
f = Expression(('sin(pi*x[1])', 'cos(pi*(x[0]+x[1]))'))
g = Constant((0, 0))

N = 20
gamma_d = 'everywhere'
Ad, ud, pd, eigs_d = dolfin_system(f=f, g=g, N=N, gamma_d=gamma_d)
Ac, uc, pc, eigs_c = cbc_block_system(f=f, g=g, N=N, gamma_d=gamma_d)

plt.figure()
plt.suptitle('DOLFIN')
plt.spy(Ad, marker='.')

plt.figure()
plt.suptitle('CBC.BLOCK')
plt.spy(Ac, marker='.')
plt.show()

mesh = UnitSquareMesh(20, 20)
print 'Velocity diff', assemble(inner(ud-uc, ud-uc)*dx(domain=mesh))
print 'Pressure diff', assemble(inner(pd-pc, pd-pc)*dx(domain=mesh))

print 'DOLFIN eigs', eigs_d
print 'CBC.BLOCK eigs', eigs_c
print 'Norm of diff', (eigs_d - eigs_c).dot(eigs_d - eigs_c)


# All okay
# Setting sigma for eigensolver to detect zero!
# Sign of a21 to get eigenvalue agreement with DOLFIN
    def _evaluateLocalEstimator(cls, mu, w, coeff_field, pde, f, quadrature_degree, epsilon=1e-5):
        """Evaluation of patch local equilibrated estimator."""

        # prepare numerical flux and f
        sigma_mu, f_mu = evaluate_numerical_flux(w, mu, coeff_field, f)

        # ###################
        # ## MIXED PROBLEM ##
        # ###################

        # get setup data for mixed problem
        V = w[mu]._fefunc.function_space()
        mesh = V.mesh()
        mesh.init()
        degree = element_degree(w[mu]._fefunc)

        # data for nodal bases
        V_dm = V.dofmap()
        V_dofs = dict([(i, V_dm.cell_dofs(i)) for i in range(mesh.num_cells())])
        V1 = FunctionSpace(mesh, 'CG', 1)   # V1 is to define nodal base functions
        phi_z = Function(V1)
        phi_coeffs = np.ndarray(V1.dim())
        vertex_dof_map = V1.dofmap().vertex_to_dof_map(mesh)
        # vertex_dof_map = vertex_to_dof_map(V1)
        dof_list = vertex_dof_map.tolist()
        # DG0 localisation
        DG0 = FunctionSpace(mesh, 'DG', 0)
        DG0_dofs = dict([(c.index(),DG0.dofmap().cell_dofs(c.index())[0]) for c in cells(mesh)])
        dg0 = TestFunction(DG0)
        # characteristic function of patch
        xi_z = Function(DG0)
        xi_coeffs = np.ndarray(DG0.dim())
        # mesh data
        h = CellSize(mesh)
        n = FacetNormal(mesh)
        cf = CellFunction('size_t', mesh)
        # setup error estimator vector
        eq_est = np.zeros(DG0.dim())

        # setup global equilibrated flux vector
        DG = VectorFunctionSpace(mesh, "DG", degree)
        DG_dofmap = DG.dofmap()

        # define form functions
        tau = TrialFunction(DG)
        v = TestFunction(DG)

        # define global tau
        tau_global = Function(DG)
        tau_global.vector()[:] = 0.0

        # iterate vertices
        for vertex in vertices(mesh):
            # get patch cell indices
            vid = vertex.index()
            patch_cid, FF_inner, FF_boundary = get_vertex_patch(vid, mesh, layers=1)

            # set nodal base function
            phi_coeffs[:] = 0
            phi_coeffs[dof_list.index(vid)] = 1
            phi_z.vector()[:] = phi_coeffs

            # set characteristic function and mark patch
            cf.set_all(0)
            xi_coeffs[:] = 0
            for cid in patch_cid:
                xi_coeffs[DG0_dofs[int(cid)]] = 1
                cf[int(cid)] = 1
            xi_z.vector()[:] = xi_coeffs

            # determine local dofs
            lDG_cell_dofs = dict([(cid, DG_dofmap.cell_dofs(cid)) for cid in patch_cid])
            lDG_dofs = [cd.tolist() for cd in lDG_cell_dofs.values()]
            lDG_dofs = list(iter.chain(*lDG_dofs))

            # print "\nlocal DG subspace has dimension", len(lDG_dofs), "degree", degree, "cells", len(patch_cid), patch_cid
            # print "local DG_cell_dofs", lDG_cell_dofs
            # print "local DG_dofs", lDG_dofs

            # create patch measures
            dx = Measure('dx')[cf]
            dS = Measure('dS')[FF_inner]

            # define forms
            alpha = Constant(1 / epsilon) / h
            a = inner(tau,v) * phi_z * dx(1) + alpha * div(tau) * div(v) * dx(1) + avg(alpha) * jump(tau,n) * jump(v,n) * dS(1)\
                + avg(alpha) * jump(xi_z * tau,n) * jump(v,n) * dS(2)
            L = -alpha * (div(sigma_mu) + f) * div(v) * phi_z * dx(1)\
                - avg(alpha) * jump(sigma_mu,n) * jump(v,n) * avg(phi_z)*dS(1)

    #        print "L2 f + div(sigma)", assemble((f + div(sigma)) * (f + div(sigma)) * dx(0))

            # assemble forms
            lhs = assemble(a, form_compiler_parameters={'quadrature_degree': quadrature_degree})
            rhs = assemble(L, form_compiler_parameters={'quadrature_degree': quadrature_degree})

            # convert DOLFIN representation to scipy sparse arrays
            rows, cols, values = lhs.data()
            lhsA = sps.csr_matrix((values, cols, rows)).tocoo()

            # slice sparse matrix and solve linear problem
            lhsA = coo_submatrix_pull(lhsA, lDG_dofs, lDG_dofs)
            lx = spsolve(lhsA, rhs.array()[lDG_dofs])
            # print ">>> local solution lx", type(lx), lx
            local_tau = Function(DG)
            local_tau.vector()[lDG_dofs] = lx
            # print "div(tau)", assemble(inner(div(local_tau),div(local_tau))*dx(1))

            # add up local fluxes
            tau_global.vector()[lDG_dofs] += lx

        # evaluate estimator
        # maybe TODO: re-define measure dx
        eq_est = assemble( inner(tau_global, tau_global) * dg0 * (dx(0)+dx(1)),\
                           form_compiler_parameters={'quadrature_degree': quadrature_degree})

        # reorder according to cell ids
        eq_est = eq_est[DG0_dofs.values()].array()
        global_est = np.sqrt(np.sum(eq_est))
        # eq_est_global = assemble( inner(tau_global, tau_global) * (dx(0)+dx(1)), form_compiler_parameters={'quadrature_degree': quadrature_degree} )
        # global_est2 = np.sqrt(np.sum(eq_est_global))
        return global_est, FlatVector(np.sqrt(eq_est))#, tau_global
Beispiel #51
0
    def __init__(self, Vh, covariance, mean=None):
        """
        Constructor

        Inputs:
        - :code:`Vh`:             Finite element space on which the prior is
                                  defined. Must be the Real space with one global 
                                  degree of freedom
        - :code:`covariance`:     The covariance of the prior. Must be a
                                  :code:`numpy.ndarray` of appropriate size
        - :code:`mean`(optional): Mean of the prior distribution. Must be of
                                  type `dolfin.Vector()`
        """

        self.Vh = Vh

        if Vh.dim() != covariance.shape[0] or Vh.dim() != covariance.shape[1]:
            raise ValueError("Covariance incompatible with Finite Element space")

        if not np.issubdtype(covariance.dtype, np.floating):
            raise TypeError("Covariance matrix must be a float array")

        self.covariance = covariance
        
        #np.linalg.cholesky automatically provides more error checking, 
        #so use those
        self.chol = np.linalg.cholesky(self.covariance)

        self.chol_inv = scila.solve_triangular(
                                        self.chol,
                                        np.identity(Vh.dim()),
                                        lower=True)

        self.precision = np.dot(self.chol_inv.T, self.chol_inv)

        trial = dl.TrialFunction(Vh)
        test  = dl.TestFunction(Vh)
        
        domain_measure_inv = dl.Constant(1.0 \
                                / dl.assemble(dl.Constant(1.) * dl.dx(Vh.mesh())))

        #Identity mass matrix
        self.M = dl.assemble(domain_measure_inv * dl.inner(trial, test) * dl.dx)
        self.Msolver = Operator2Solver(self.M)

        if mean:
            self.mean = mean
        else:
            tmp = dl.Vector()
            self.M.init_vector(tmp, 0)
            tmp.zero()
            self.mean = tmp

        if Vh.dim() == 1:
            trial = dl.as_matrix([[trial]])
            test  = dl.as_matrix([[test]])

        #Create form matrices 
        covariance_op = dl.as_matrix(list(map(list, self.covariance)))
        precision_op  = dl.as_matrix(list(map(list, self.precision)))
        chol_op       = dl.as_matrix(list(map(list, self.chol)))
        chol_inv_op   = dl.as_matrix(list(map(list, self.chol_inv)))

        #variational for the regularization operator, or the precision matrix
        var_form_R = domain_measure_inv \
                     * dl.inner(test, dl.dot(precision_op, trial)) * dl.dx

        #variational for the inverse regularization operator, or the covariance
        #matrix
        var_form_Rinv = domain_measure_inv \
                        * dl.inner(test, dl.dot(covariance_op, trial)) * dl.dx

        #variational form for the square root of the regularization operator
        var_form_R_sqrt = domain_measure_inv \
                          * dl.inner(test, dl.dot(chol_inv_op.T, trial)) * dl.dx

        #variational form for the square root of the inverse regularization 
        #operator
        var_form_Rinv_sqrt = domain_measure_inv \
                             * dl.inner(test, dl.dot(chol_op, trial)) * dl.dx

        self.R         = dl.assemble(var_form_R)
        self.RSolverOp = dl.assemble(var_form_Rinv)
        self.Rsolver   = Operator2Solver(self.RSolverOp)
        self.sqrtR     = dl.assemble(var_form_R_sqrt)
        self.sqrtRinv  = dl.assemble(var_form_Rinv_sqrt)
Beispiel #52
0
def compute_time_errors(problem, MethodClass, mesh_sizes, Dt):

    mesh_generator, solution, f, mu, rho, cell_type = problem()
    # Translate data into FEniCS expressions.
    sol_u = Expression((smp.printing.ccode(solution['u']['value'][0]),
                        smp.printing.ccode(solution['u']['value'][1])
                        ),
                       degree=_truncate_degree(solution['u']['degree']),
                       t=0.0,
                       cell=cell_type
                       )
    sol_p = Expression(smp.printing.ccode(solution['p']['value']),
                       degree=_truncate_degree(solution['p']['degree']),
                       t=0.0,
                       cell=cell_type
                       )

    fenics_rhs0 = Expression((smp.printing.ccode(f['value'][0]),
                              smp.printing.ccode(f['value'][1])
                              ),
                             degree=_truncate_degree(f['degree']),
                             t=0.0,
                             mu=mu, rho=rho,
                             cell=cell_type
                             )
    # Deep-copy expression to be able to provide f0, f1 for the Dirichlet-
    # boundary conditions later on.
    fenics_rhs1 = Expression(fenics_rhs0.cppcode,
                             degree=_truncate_degree(f['degree']),
                             t=0.0,
                             mu=mu, rho=rho,
                             cell=cell_type
                             )
    # Create initial states.
    p0 = Expression(
        sol_p.cppcode,
        degree=_truncate_degree(solution['p']['degree']),
        t=0.0,
        cell=cell_type
        )

    # Compute the problem
    errors = {'u': numpy.empty((len(mesh_sizes), len(Dt))),
              'p': numpy.empty((len(mesh_sizes), len(Dt)))
              }
    for k, mesh_size in enumerate(mesh_sizes):
        info('')
        info('')
        with Message('Computing for mesh size %r...' % mesh_size):
            mesh = mesh_generator(mesh_size)
            mesh_area = assemble(1.0 * dx(mesh))
            W = VectorFunctionSpace(mesh, 'CG', 2)
            P = FunctionSpace(mesh, 'CG', 1)
            method = MethodClass(W, P,
                                 rho, mu,
                                 theta=1.0,
                                 #theta=0.5,
                                 stabilization=None
                                 #stabilization='SUPG'
                                 )
            u1 = Function(W)
            p1 = Function(P)
            err_p = Function(P)
            divu1 = Function(P)
            for j, dt in enumerate(Dt):
                # Prepare previous states for multistepping.
                u = [Expression(
                    sol_u.cppcode,
                    degree=_truncate_degree(solution['u']['degree']),
                    t=0.0,
                    cell=cell_type
                    ),
                    # Expression(
                    #sol_u.cppcode,
                    #degree=_truncate_degree(solution['u']['degree']),
                    #t=0.5*dt,
                    #cell=cell_type
                    #)
                    ]
                sol_u.t = dt
                u_bcs = [DirichletBC(W, sol_u, 'on_boundary')]
                sol_p.t = dt
                #p_bcs = [DirichletBC(P, sol_p, 'on_boundary')]
                p_bcs = []
                fenics_rhs0.t = 0.0
                fenics_rhs1.t = dt
                method.step(dt,
                            u1, p1,
                            u, p0,
                            u_bcs=u_bcs, p_bcs=p_bcs,
                            f0=fenics_rhs0, f1=fenics_rhs1,
                            verbose=False,
                            tol=1.0e-10
                            )
                sol_u.t = dt
                sol_p.t = dt
                errors['u'][k][j] = errornorm(sol_u, u1)
                # The pressure is only determined up to a constant which makes
                # it a bit harder to define what the error is. For our
                # purposes, choose an alpha_0\in\R such that
                #
                #    alpha0 = argmin ||e - alpha||^2
                #
                # with  e := sol_p - p.
                # This alpha0 is unique and explicitly given by
                #
                #     alpha0 = 1/(2|Omega|) \int (e + e*)
                #            = 1/|Omega| \int Re(e),
                #
                # i.e., the mean error in \Omega.
                alpha = assemble(sol_p * dx(mesh)) \
                    - assemble(p1 * dx(mesh))
                alpha /= mesh_area
                # We would like to perform
                #     p1 += alpha.
                # To avoid creating a temporary function every time, assume
                # that p1 lives in a function space where the coefficients
                # represent actual function values. This is true for CG
                # elements, for example. In that case, we can just add any
                # number to the vector of p1.
                p1.vector()[:] += alpha
                errors['p'][k][j] = errornorm(sol_p, p1)

                show_plots = False
                if show_plots:
                    plot(p1, title='p1', mesh=mesh)
                    plot(sol_p, title='sol_p', mesh=mesh)
                    err_p.vector()[:] = p1.vector()
                    sol_interp = interpolate(sol_p, P)
                    err_p.vector()[:] -= sol_interp.vector()
                    #plot(sol_p - p1, title='p1 - sol_p', mesh=mesh)
                    plot(err_p, title='p1 - sol_p', mesh=mesh)
                    #r = Expression('x[0]', degree=1, cell=triangle)
                    #divu1 = 1 / r * (r * u1[0]).dx(0) + u1[1].dx(1)
                    divu1.assign(project(u1[0].dx(0) + u1[1].dx(1), P))
                    plot(divu1, title='div(u1)')
                    interactive()
    return errors
Beispiel #53
0
def average(u):
    """Computes the average value of a function u over its domain.
    """
    return assemble(u * dx) / assemble(1.0 * dx(u.function_space().mesh()))
Beispiel #54
0
    def add_fields(self):
        Field.start_recording()

        params = self.params.copy_recursive()
        if not self.params.debug:
            params["save"] = False
            params["plot"] = False
        params.pop("debug")
        params.pop("use_timeaverage")
        params.pop("finalize")
        T0, T1 = self.params.start_time, self.params.end_time
        assert T0 != Field.default_params().start_time
        assert T1 != Field.default_params().end_time
        if self.params.use_timeaverage:
            u = TimeAverage("Velocity", params=params)
            velocity = u.name
        else:
            velocity = "Velocity"
        

        uneck = SubFunction(velocity, self.neck, params=params, label="neck")

        A = assemble(Constant(1)*dx(domain=self.neck))
        Qin = Dot(ConstantField(self.necknormal), uneck, params=params)

        t = Threshold(Qin, ConstantField(0), dict(threshold_by="above"))
        t.params.update(params)
        t.name = "threshold_neck"

        Ain = A*DomainAvg(t)
        Ain.name = "Ain"
        Ain.params.update(params)
        Qin = A*DomainAvg(Dot(Qin,t, params=params))
        Qin.name = "Qin"
        Qin.params.update(params)
        
        Qpa = 0
        for i, (plane, n) in enumerate(self.pa_planes):
            upa = SubFunction(velocity, plane, params=params, label="pa_%d" %i)
            
            Ai = assemble(Constant(1)*dx(domain=plane))
            Q = Ai*DomainAvg(Dot(ConstantField(n), upa, params=params))
            Q.name = "Qpa%d" %i
            Q.params.update(params)
            Qpa += Magnitude(Q)
            Qpa.params.update(params)
        Qpa.name = "Sum_Qpa"
        f = (Qin/Qpa)/(Ain/A)

        if not self.params.use_timeaverage:
            f = TimeAverage(f.name, params=params)
        
        self.valuename = f.name
        
        self.Qin = Qin.name
        self.Qpa = Qpa.name
        self.Ain = Ain.name
        self.A = A
        

        fields = Field.stop_recording()

        return fields
Beispiel #55
0
def _average(u):
    '''Computes the average value of a function u over its domain.
    '''
    return assemble(u * dx) \
        / assemble(1.0 * dx(u.function_space().mesh()))
Beispiel #56
0
def test_boussinesq(with_voltage, target_time=1.0e-2, show=False):
    """Simple boussinesq test; no Maxwell involved.
    """
    problem = problems.Crucible()

    # Solve construct initial state without Lorentz force and Joule heat.
    m = problem.subdomain_materials[problem.wpi]
    k_wpi = m.thermal_conductivity
    cp_wpi = m.specific_heat_capacity
    rho_wpi = m.density
    mu_wpi = m.dynamic_viscosity

    g = Constant((0.0, -9.80665, 0.0))
    submesh_workpiece = problem.W.mesh()
    ds_workpiece = Measure("ds", subdomain_data=problem.wp_boundaries)
    u0, p0, theta0 = _construct_initial_state(
        submesh_workpiece,
        problem.W_element,
        problem.P_element,
        problem.Q_element,
        k_wpi,
        cp_wpi,
        rho_wpi,
        mu_wpi,
        Constant(0.0),
        problem.u_bcs,
        problem.p_bcs,
        problem.theta_bcs_d,
        problem.theta_bcs_n,
        dx(submesh_workpiece),
        ds_workpiece,
        g,
        extra_force=None,
    )

    if with_voltage:
        voltages = [
            38.0 * numpy.exp(-1j * 2 * pi * 2 * 70.0 / 360.0),
            38.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0),
            38.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0),
            25.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0),
            25.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0),
        ]
        lorentz, joule, _ = get_lorentz_joule(problem, voltages, show=show)
    else:
        lorentz = None
        joule = Constant(0.0)

    u1, _, theta1 = _compute_boussinesq(
        problem,
        u0,
        p0,
        theta0,
        lorentz=lorentz,
        joule=joule,
        target_time=target_time,
        show=show,
    )

    if with_voltage:
        # p is only defined up to a constant
        ref = 0.001069306823450495
        assert abs(norm(u1, "L2") - ref) < 1.0e-3 * ref
        ref = 86.96271240592199
        assert abs(norm(theta1, "L2") - ref) < 1.0e-3 * ref
    else:
        ref = 0.001069283700624996
        assert abs(norm(u1, "L2") - ref) < 1.0e-3 * ref
        ref = 86.96274092197706
        assert abs(norm(theta1, "L2") - ref) < 1.0e-3 * ref

    return
Beispiel #57
0
def _compute_boussinesq(
    problem, u0, p0, theta0, lorentz, joule, target_time=0.1, show=False
):
    # Define a facet measure on the boundaries. See discussion on
    # <https://bitbucket.org/fenics-project/dolfin/issue/249/facet-specification-doesnt-work-on-ds>.
    ds_workpiece = Measure("ds", subdomain_data=problem.wp_boundaries)

    submesh_workpiece = problem.W.mesh()

    # Start time, time step.
    t = 0.0
    dt = 1.0e-3
    dt_max = 1.0e-1

    # Standard gravity, <https://en.wikipedia.org/wiki/Standard_gravity>.
    grav = 9.80665
    assert problem.W.num_sub_spaces() == 3
    g = Constant((0.0, -grav, 0.0))

    # Compute a few mesh characteristics.
    wpi_area = assemble(1.0 * dx(submesh_workpiece))
    # mesh.hmax() is a local function; get the global hmax.
    hmax_workpiece = MPI.max(submesh_workpiece.mpi_comm(), submesh_workpiece.hmax())

    # Take the maximum length in x-direction as characteristic length of the
    # domain.
    coords = submesh_workpiece.coordinates()
    char_length = max(coords[:, 0]) - min(coords[:, 0])

    # Prepare some parameters for the Navier-Stokes simulation in the workpiece
    m = problem.subdomain_materials[problem.wpi]
    k_wpi = m.thermal_conductivity
    cp_wpi = m.specific_heat_capacity
    rho_wpi = m.density
    mu_wpi = m.dynamic_viscosity

    theta_average = average(theta0)

    # show_total_force = True
    # if show_total_force:
    #     f = rho_wpi(theta0) * g
    #     if lorentz:
    #         f += as_vector((lorentz[0], lorentz[1], 0.0))
    #     tri = plot(f, mesh=submesh_workpiece, title='Total external force')
    #     plt.colorbar(tri)
    #     plt.show()

    with XDMFFile(submesh_workpiece.mpi_comm(), "all.xdmf") as outfile:
        outfile.parameters["flush_output"] = True
        outfile.parameters["rewrite_function_mesh"] = False

        _store(outfile, u0, p0, theta0, t)
        if show:
            _plot(p0, theta0)
            plt.show()

        successful_steps = 0
        failed_steps = 0
        while t < target_time + DOLFIN_EPS:
            info(
                "Successful steps: {}    (failed: {}, total: {})".format(
                    successful_steps, failed_steps, successful_steps + failed_steps
                )
            )
            with Message("Time step {:e} -> {:e}...".format(t, t + dt)):
                # Do one heat time step.
                with Message("Computing heat..."):
                    # Redefine the heat problem with the new u0.
                    heat_problem = cyl_heat.Heat(
                        problem.Q,
                        kappa=k_wpi,
                        rho=rho_wpi(theta_average),
                        cp=cp_wpi,
                        convection=u0,
                        source=joule,
                        dirichlet_bcs=problem.theta_bcs_d,
                        neumann_bcs=problem.theta_bcs_n,
                        my_dx=dx(submesh_workpiece),
                        my_ds=ds_workpiece,
                    )

                    # For time-stepping in buoyancy-driven flows, see
                    #
                    # Numerical solution of buoyancy-driven flows;
                    # Einar Rossebø Christensen;
                    # Master's thesis;
                    # <http://www.diva-portal.org/smash/get/diva2:348831/FULLTEXT01.pdf>.
                    #
                    # Similar to the present approach, one first solves for
                    # velocity and pressure, then for temperature.
                    #
                    heat_stepper = parabolic.ImplicitEuler(heat_problem)

                    ns_stepper = cyl_ns.IPCS(time_step_method="backward euler")
                    theta1 = heat_stepper.step(theta0, t, dt)

                theta0_average = average(theta0)
                try:
                    # Do one Navier-Stokes time step.
                    with Message("Computing flux and pressure..."):
                        # Include proper temperature-dependence here to account
                        # for the Boussinesq effect.
                        f0 = rho_wpi(theta0) * g
                        f1 = rho_wpi(theta1) * g
                        if lorentz is not None:
                            f = as_vector((lorentz[0], lorentz[1], 0.0))
                            f0 += f
                            f1 += f
                        u1, p1 = ns_stepper.step(
                            Constant(dt),
                            {0: u0},
                            p0,
                            problem.W,
                            problem.P,
                            problem.u_bcs,
                            problem.p_bcs,
                            # Make constant TODO
                            Constant(rho_wpi(theta0_average)),
                            Constant(mu_wpi(theta0_average)),
                            f={0: f0, 1: f1},
                            tol=1.0e-10,
                            my_dx=dx(submesh_workpiece),
                        )
                except RuntimeError as e:
                    info(e.args[0])
                    info(
                        "Navier--Stokes solver failed to converge. "
                        "Decrease time step from {:e} to {:e} and try again.".format(
                            dt, 0.5 * dt
                        )
                    )
                    dt *= 0.5
                    failed_steps += 1
                    continue
                successful_steps += 1

                # Assignments and plotting.
                theta0.assign(theta1)
                u0.assign(u1)
                p0.assign(p1)

                _store(outfile, u0, p0, theta0, t + dt)
                if show:
                    _plot(p0, theta0)
                    plt.show()

                t += dt
                with Message("Diagnostics..."):
                    # Print some general info on the flow in the crucible.
                    umax = get_umax(u0)
                    _print_diagnostics(
                        theta0,
                        umax,
                        submesh_workpiece,
                        wpi_area,
                        problem.subdomain_materials,
                        problem.wpi,
                        rho_wpi,
                        mu_wpi,
                        char_length,
                        grav,
                    )
                    info("")
                with Message("Step size adaptation..."):
                    # Some smooth step-size adaption.
                    target_dt = 0.2 * hmax_workpiece / umax
                    info("previous dt: {:e}".format(dt))
                    info("target dt: {:e}".format(target_dt))
                    # agg is the aggressiveness factor. The distance between
                    # the current step size and the target step size is reduced
                    # by |1-agg|. Hence, if agg==1 then dt_next==target_dt.
                    # Otherwise target_dt is approached more slowly.
                    agg = 0.5
                    dt = min(
                        dt_max,
                        # At most double the step size from step to step.
                        dt * min(2.0, 1.0 + agg * (target_dt - dt) / dt),
                    )
                    info("new dt:    {:e}".format(dt))
                    info("")
                info("")
    return u0, p0, theta0
Beispiel #58
0
def compute_time_errors(problem, MethodClass, mesh_sizes, Dt):

    mesh_generator, solution, f, mu, rho, cell_type = problem()

    # Compute the problem
    errors = {
        "u": numpy.empty((len(mesh_sizes), len(Dt))),
        "p": numpy.empty((len(mesh_sizes), len(Dt))),
    }
    for k, mesh_size in enumerate(mesh_sizes):
        info("")
        info("")
        with Message("Computing for mesh size {}...".format(mesh_size)):
            mesh = mesh_generator(mesh_size)

            # Define all expression with `domain`, see
            # <https://bitbucket.org/fenics-project/ufl/issues/96>.
            #
            # Translate data into FEniCS expressions.
            sol_u = Expression(
                (ccode(solution["u"]["value"][0]), ccode(solution["u"]["value"][1])),
                degree=_truncate_degree(solution["u"]["degree"]),
                t=0.0,
                domain=mesh,
            )
            sol_p = Expression(
                ccode(solution["p"]["value"]),
                degree=_truncate_degree(solution["p"]["degree"]),
                t=0.0,
                domain=mesh,
            )

            fenics_rhs0 = Expression(
                (ccode(f["value"][0]), ccode(f["value"][1])),
                degree=_truncate_degree(f["degree"]),
                t=0.0,
                mu=mu,
                rho=rho,
                domain=mesh,
            )
            # Deep-copy expression to be able to provide f0, f1 for the
            # Dirichlet boundary conditions later on.
            fenics_rhs1 = Expression(
                fenics_rhs0.cppcode,
                degree=_truncate_degree(f["degree"]),
                t=0.0,
                mu=mu,
                rho=rho,
                domain=mesh,
            )
            # Create initial states.
            W = VectorFunctionSpace(mesh, "CG", 2)
            P = FunctionSpace(mesh, "CG", 1)
            p0 = Expression(
                sol_p.cppcode,
                degree=_truncate_degree(solution["p"]["degree"]),
                t=0.0,
                domain=mesh,
            )

            mesh_area = assemble(1.0 * dx(mesh))
            method = MethodClass(
                time_step_method="backward euler",
                # time_step_method='crank-nicolson',
                # stabilization=None
                # stabilization='SUPG'
            )
            u1 = Function(W)
            p1 = Function(P)
            err_p = Function(P)
            divu1 = Function(P)
            for j, dt in enumerate(Dt):
                # Prepare previous states for multistepping.
                u = {
                    0: Expression(
                        sol_u.cppcode,
                        degree=_truncate_degree(solution["u"]["degree"]),
                        t=0.0,
                        cell=cell_type,
                    )
                }
                sol_u.t = dt
                u_bcs = [DirichletBC(W, sol_u, "on_boundary")]
                sol_p.t = dt
                # p_bcs = [DirichletBC(P, sol_p, 'on_boundary')]
                p_bcs = []
                fenics_rhs0.t = 0.0
                fenics_rhs1.t = dt
                u1, p1 = method.step(
                    Constant(dt),
                    u,
                    p0,
                    W,
                    P,
                    u_bcs,
                    p_bcs,
                    Constant(rho),
                    Constant(mu),
                    f={0: fenics_rhs0, 1: fenics_rhs1},
                    verbose=False,
                    tol=1.0e-10,
                )

                sol_u.t = dt
                sol_p.t = dt
                errors["u"][k][j] = errornorm(sol_u, u1)
                # The pressure is only determined up to a constant which makes
                # it a bit harder to define what the error is. For our
                # purposes, choose an alpha_0\in\R such that
                #
                #    alpha0 = argmin ||e - alpha||^2
                #
                # with  e := sol_p - p.
                # This alpha0 is unique and explicitly given by
                #
                #     alpha0 = 1/(2|Omega|) \int (e + e*)
                #            = 1/|Omega| \int Re(e),
                #
                # i.e., the mean error in \Omega.
                alpha = +assemble(sol_p * dx(mesh)) - assemble(p1 * dx(mesh))
                alpha /= mesh_area
                # We would like to perform
                #     p1 += alpha.
                # To avoid creating a temporary function every time, assume
                # that p1 lives in a function space where the coefficients
                # represent actual function values. This is true for CG
                # elements, for example. In that case, we can just add any
                # number to the vector of p1.
                p1.vector()[:] += alpha
                errors["p"][k][j] = errornorm(sol_p, p1)

                show_plots = False
                if show_plots:
                    plot(p1, title="p1", mesh=mesh)
                    plot(sol_p, title="sol_p", mesh=mesh)
                    err_p.vector()[:] = p1.vector()
                    sol_interp = interpolate(sol_p, P)
                    err_p.vector()[:] -= sol_interp.vector()
                    # plot(sol_p - p1, title='p1 - sol_p', mesh=mesh)
                    plot(err_p, title="p1 - sol_p", mesh=mesh)
                    # r = SpatialCoordinate(mesh)[0]
                    # divu1 = 1 / r * (r * u1[0]).dx(0) + u1[1].dx(1)
                    divu1.assign(project(u1[0].dx(0) + u1[1].dx(1), P))
                    plot(divu1, title="div(u1)")
    return errors