Beispiel #1
0
def space_from_string(space_string: str, mesh: df.Mesh,
                      dim: int) -> df.FunctionSpace:
    """
    Constructed a finite elements space from a string
    representation of the space

    Arguments
    ---------
    space_string : str
        A string on the form {familiy}_{degree} which
        determines the space. Example 'Lagrange_1'.
    mesh : dolfin.Mesh
        The mesh
    dim : int
        1 for scalar space, 3 for vector space.
    """
    family, degree = space_string.split("_")

    if dim == 3:
        V = df.FunctionSpace(
            mesh,
            df.VectorElement(
                family=family,
                cell=mesh.ufl_cell(),
                degree=int(degree),
                quad_scheme="default",
            ),
        )
    elif dim == 1:
        V = df.FunctionSpace(
            mesh,
            df.FiniteElement(
                family=family,
                cell=mesh.ufl_cell(),
                degree=int(degree),
                quad_scheme="default",
            ),
        )
    else:
        raise df.error("Cannot create function space of dimension {dim}")

    return V
Beispiel #2
0
def project_gradients(
    mesh: df.Mesh,
    scalar_solutions: Dict[str, df.Function],
    fiber_space: str = "CG_1",
) -> Dict[str, np.ndarray]:
    """
    Calculate the gradients using projections

    Arguments
    ---------
    mesh : dolfin.Mesh
        The mesh
    fiber_space : str
        A string on the form {familiy}_{degree} which
        determines for what space the fibers should be calculated for.
    scalar_solutions: dict
        A dictionary with the scalar solutions that you
        want to compute the gradients of.
    """
    Vv = utils.space_from_string(fiber_space, mesh, dim=3)
    V = utils.space_from_string(fiber_space, mesh, dim=1)

    data = {}
    V_cg = df.FunctionSpace(mesh,
                            df.VectorElement("Lagrange", mesh.ufl_cell(), 1))
    for case, scalar_solution in scalar_solutions.items():

        scalar_solution_int = df.interpolate(scalar_solution, V)

        if case != "lv_rv":
            gradient_cg = df.project(df.grad(scalar_solution),
                                     V_cg,
                                     solver_type="cg")
            gradient = df.interpolate(gradient_cg, Vv)

            # Add gradient data
            data[case + "_gradient"] = gradient.vector().get_local()

        # Add scalar data
        if case != "apex":
            data[case + "_scalar"] = scalar_solution_int.vector().get_local()

    # Return data
    return data
Beispiel #3
0
                                        height=1.0,
                                        degree=3)

        # Generate particles
        x = RandomCircle(Point(x0, y0), r).generate([pres, pres])
        s = np.zeros((len(x), 1), dtype=np.float_)

        # Initialize particles with position x and scalar property s at the mesh
        p = particles(x, [s], mesh)
        property_idx = 1  # Scalar quantity is stored at slot 1

        # Initialize advection class, use RK3 scheme
        ap = advect_rk3(p, V, uh, "open")

        # Define the variational (projection problem)
        W_e = FiniteElement("DG", mesh.ufl_cell(), k)
        T_e = FiniteElement("DG", mesh.ufl_cell(), 0)
        Wbar_e = FiniteElement("DGT", mesh.ufl_cell(), k)

        W = FunctionSpace(mesh, W_e)
        T = FunctionSpace(mesh, T_e)
        Wbar = FunctionSpace(mesh, Wbar_e)

        psi_h, psi0_h = Function(W), Function(W)
        lambda_h = Function(T)
        psibar_h = Function(Wbar)

        # Boundary conditions
        bc = DirichletBC(Wbar, Constant(0.0), "on_boundary")

        # Initialize forms
Beispiel #4
0
class Ball_in_tube(object):
    def __init__(self):
        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, _, cell_data, _ = meshes.ball_in_tube_cyl.generate()
        # 2018.1
        # self.mesh = Mesh(
        #     dolfin.mpi_comm_world(), dolfin.cpp.mesh.CellType.Type_triangle,
        #     points[:, :2], cells['triangle']
        #     )
        with TemporaryDirectory() as temp_dir:
            tmp_filename = os.path.join(temp_dir, "test.xml")
            meshio.write_points_cells(
                tmp_filename,
                points,
                cells,
                cell_data=cell_data,
                file_format="dolfin-xml",
            )
            self.mesh = Mesh(tmp_filename)

        V0_element = FiniteElement("CG", self.mesh.ufl_cell(), 2)
        V1_element = FiniteElement("B", self.mesh.ufl_cell(), 3)
        self.W = FunctionSpace(self.mesh, V0_element * V1_element)

        self.P = FunctionSpace(self.mesh, "CG", 1)

        # Define mesh and boundaries.
        class LeftBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] < GMSH_EPS

        left_boundary = LeftBoundary()

        class RightBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] > 1.0 - GMSH_EPS

        right_boundary = RightBoundary()

        class LowerBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[1] < GMSH_EPS

        lower_boundary = LowerBoundary()

        # class UpperBoundary(SubDomain):
        #     # pylint: disable=no-self-use
        #     def inside(self, x, on_boundary):
        #         return on_boundary and x[1] > 5.0-GMSH_EPS

        class CoilBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                # One has to pay a little bit of attention when defining the
                # coil boundary; it's easy to miss the edges closest to x[0]=0.
                return (
                    on_boundary
                    and x[1] > 1.0 - GMSH_EPS
                    and x[1] < 2.0 + GMSH_EPS
                    and x[0] < 1.0 - GMSH_EPS
                )

        coil_boundary = CoilBoundary()

        self.u_bcs = [
            DirichletBC(self.W, (0.0, 0.0), right_boundary),
            DirichletBC(self.W.sub(0), 0.0, left_boundary),
            DirichletBC(self.W, (0.0, 0.0), lower_boundary),
            DirichletBC(self.W, (0.0, 0.0), coil_boundary),
        ]
        self.p_bcs = []
        # self.p_bcs = [DirichletBC(Q, 0.0, upper_boundary)]
        return
Beispiel #5
0
def save_files_visualization(visualization_folder, dvp_, t, save_deg, mesh,
                             **namespace):
    # Files for storing results
    if not "d_file" in namespace.keys():
        d_file = XDMFFile(
            MPI.comm_world,
            str(visualization_folder.joinpath("displacement.xdmf")))
        v_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("velocity.xdmf")))
        p_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("pressure.xdmf")))
        for tmp_t in [d_file, v_file, p_file]:
            tmp_t.parameters["flush_output"] = True
            tmp_t.parameters["rewrite_function_mesh"] = False

        if save_deg > 1:
            mesh_viz = Mesh(mesh)  # copy the mesh

            for i in range(save_deg - 1):
                mesh_viz = refine(mesh_viz)  # refine the mesh

            dve_viz = VectorElement('CG', mesh_viz.ufl_cell(), 1)
            pe_viz = FiniteElement('CG', mesh_viz.ufl_cell(), 1)
            FSdv_viz = FunctionSpace(
                mesh_viz, dve_viz)  # Visualisation FunctionSpace for d and v
            FSp_viz = FunctionSpace(
                mesh_viz, pe_viz)  # Visualisation FunctionSpace for p

            return_dict = dict(v_file=v_file,
                               d_file=d_file,
                               p_file=p_file,
                               FSdv_viz=FSdv_viz,
                               FSp_viz=FSp_viz)

        else:
            return_dict = dict(v_file=v_file, d_file=d_file, p_file=p_file)

        namespace.update(return_dict)

    else:
        return_dict = {}

    # Split function
    d = dvp_["n"].sub(0, deepcopy=True)
    v = dvp_["n"].sub(1, deepcopy=True)
    p = dvp_["n"].sub(2, deepcopy=True)

    if save_deg > 1:
        d = project(d, namespace["FSdv_viz"])
        v = project(v, namespace["FSdv_viz"])
        p = project(p, namespace["FSp_viz"])

    # Name function
    d.rename("Displacement", "d")
    v.rename("Velocity", "v")
    p.rename("Pressure", "p")

    # Write results
    namespace["d_file"].write(d, t)
    namespace["v_file"].write(v, t)
    namespace["p_file"].write(p, t)

    return return_dict
Beispiel #6
0

if __name__ == "__main__":

    xlim = 0.0, 3.0
    ylim = 0.0, 0.0127
    WAid = 12
    INid = 13
    BND_ids = WAid, INid
    meszf = 0.001  # mesh element size factor

    Domain, Facets = Generate_PBRpygmsh(xlim,
                                        ylim,
                                        BND_ids,
                                        meszf,
                                        folder='pygmeshio_test')

    mesh_D = Mesh()
    with XDMFFile(Domain) as infile:
        infile.read(mesh_D)

    mesh_F = Mesh()
    with XDMFFile(Facets) as infile:
        infile.read(mesh_F)

    print('num_cells   :', mesh_D.num_cells())
    print('num_vertices:', mesh_D.num_vertices())
    print('cell_type   :', mesh_D.ufl_cell())
    #print('num_facets:', mesh_F.num_facets())
    #print('num_edges:', mesh_F.num_edges())
Beispiel #7
0
class Ball_in_tube(object):
    def __init__(self):
        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, _, cell_data, _ = meshes.ball_in_tube_cyl.generate()
        # 2018.1
        # self.mesh = Mesh(
        #     dolfin.mpi_comm_world(), dolfin.cpp.mesh.CellType.Type_triangle,
        #     points[:, :2], cells['triangle']
        #     )
        with TemporaryDirectory() as temp_dir:
            tmp_filename = os.path.join(temp_dir, "test.xml")
            meshio.write_points_cells(
                tmp_filename,
                points,
                cells,
                cell_data=cell_data,
                file_format="dolfin-xml",
            )
            self.mesh = Mesh(tmp_filename)

        V0_element = FiniteElement("CG", self.mesh.ufl_cell(), 2)
        V1_element = FiniteElement("B", self.mesh.ufl_cell(), 3)
        self.W = FunctionSpace(self.mesh, V0_element * V1_element)

        self.P = FunctionSpace(self.mesh, "CG", 1)

        # Define mesh and boundaries.
        class LeftBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] < GMSH_EPS

        left_boundary = LeftBoundary()

        class RightBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] > 1.0 - GMSH_EPS

        right_boundary = RightBoundary()

        class LowerBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[1] < GMSH_EPS

        lower_boundary = LowerBoundary()

        # class UpperBoundary(SubDomain):
        #     # pylint: disable=no-self-use
        #     def inside(self, x, on_boundary):
        #         return on_boundary and x[1] > 5.0-GMSH_EPS

        class CoilBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                # One has to pay a little bit of attention when defining the
                # coil boundary; it's easy to miss the edges closest to x[0]=0.
                return (on_boundary and x[1] > 1.0 - GMSH_EPS
                        and x[1] < 2.0 + GMSH_EPS and x[0] < 1.0 - GMSH_EPS)

        coil_boundary = CoilBoundary()

        self.u_bcs = [
            DirichletBC(self.W, (0.0, 0.0), right_boundary),
            DirichletBC(self.W.sub(0), 0.0, left_boundary),
            DirichletBC(self.W, (0.0, 0.0), lower_boundary),
            DirichletBC(self.W, (0.0, 0.0), coil_boundary),
        ]
        self.p_bcs = []
        # self.p_bcs = [DirichletBC(Q, 0.0, upper_boundary)]
        return
Beispiel #8
0
def save_files_visualization(visualization_folder, dvp_, t, save_deg, v_deg, p_deg, mesh, domains, **namespace):
    # Files for storing results
    if not "d_file" in namespace.keys():
        d_file = XDMFFile(MPI.comm_world, str(visualization_folder.joinpath("displacement.xdmf")))
        v_file = XDMFFile(MPI.comm_world, str(visualization_folder.joinpath("velocity.xdmf")))
        p_file = XDMFFile(MPI.comm_world, str(visualization_folder.joinpath("pressure.xdmf")))
        for tmp_t in [d_file, v_file, p_file]:
            tmp_t.parameters["flush_output"] = True
            tmp_t.parameters["rewrite_function_mesh"] = False

        if save_deg > 1:
          
            # Create function space for d, v and p
            dve = VectorElement('CG', mesh.ufl_cell(), v_deg)
            pe = FiniteElement('CG', mesh.ufl_cell(), p_deg)
            FSdv = FunctionSpace(mesh, dve)   # Higher degree FunctionSpace for d and v
            FSp= FunctionSpace(mesh, pe)     # Higher degree FunctionSpace for p

            # Copy mesh
            mesh_viz = Mesh(mesh)

            for i in range(save_deg-1):
                mesh_viz = refine(mesh_viz)  # refine the mesh
                domains_viz = adapt(domains,mesh_viz)  # refine the domains (so we can output domain IDs of refined mesh)

            # Create visualization function space for d, v and p
            dve_viz = VectorElement('CG', mesh_viz.ufl_cell(), 1)
            pe_viz = FiniteElement('CG', mesh_viz.ufl_cell(), 1)
            FSdv_viz = FunctionSpace(mesh_viz, dve_viz)   # Visualisation FunctionSpace for d and v
            FSp_viz = FunctionSpace(mesh_viz, pe_viz)     # Visualisation FunctionSpace for p

            # Create lower-order function for visualization on refined mesh
            d_viz = Function(FSdv_viz)
            v_viz = Function(FSdv_viz)
            p_viz = Function(FSp_viz)
    
            # Create a transfer matrix between higher degree and lower degree (visualization) function spaces
            dv_trans = PETScDMCollection.create_transfer_matrix(FSdv,FSdv_viz)
            p_trans = PETScDMCollection.create_transfer_matrix(FSp,FSp_viz)

            return_dict = dict(v_file=v_file, d_file=d_file, p_file=p_file, d_viz=d_viz,v_viz=v_viz, p_viz=p_viz, 
                dv_trans=dv_trans, p_trans=p_trans, mesh_viz=mesh_viz, domains_viz=domains_viz)

        else:
            return_dict = dict(v_file=v_file, d_file=d_file, p_file=p_file)

        namespace.update(return_dict)

    else:
        return_dict = {}

    # Split function
    d = dvp_["n"].sub(0, deepcopy=True)
    v = dvp_["n"].sub(1, deepcopy=True)
    p = dvp_["n"].sub(2, deepcopy=True)

    if save_deg > 1: # To save higher-order nodes

        # Interpolate by using the transfer matrix between higher degree and lower degree (visualization) function spaces
        namespace["d_viz"].vector()[:] = namespace["dv_trans"]*d.vector()
        namespace["v_viz"].vector()[:] = namespace["dv_trans"]*v.vector()
        namespace["p_viz"].vector()[:] = namespace["p_trans"]*p.vector()

        write_solution(namespace["d_viz"], namespace["v_viz"], namespace["p_viz"], 
            namespace["d_file"], namespace["v_file"], namespace["p_file"], t) # Write results

    else: # To save only the corner nodes

        write_solution(d, v, p, namespace["d_file"], namespace["v_file"], namespace["p_file"], t) # Write results

    return return_dict
Beispiel #9
0
meshio.write(os.path.join(Wri_path, "md_.xdmf"), triangle_mesh)
meshio.xdmf.write(os.path.join(Wri_path, "mf_.xdmf"), line_mesh)

# Reading mesh data stored in .xdmf files.
mesh = Mesh()
with XDMFFile(os.path.join(Wri_path, "md_.xdmf")) as infile:
    infile.read(mesh)
mvc = MeshValueCollection("size_t", mesh, 1)

with XDMFFile(os.path.join(Wri_path, "mf_.xdmf")) as infile:
    infile.read(mvc, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

# Define function spaces for PDEs variational formulation.
P1 = FiniteElement('P', mesh.ufl_cell(),
                   1)  # Lagrange 1-order polynomials family
element = MixedElement([P1, P1, P1, P1])
V = FunctionSpace(mesh, element)  # Test functions
function_space = FunctionSpace(mesh, P1)

# Splitting test and trial functions
v_A, v_B, v_C, v_T = TestFunctions(V)
u = Function(V)
u_n = Function(V)
u_A, u_B, u_C, u_T = split(u)

# Retrieve boundaries marks for Robin boundary conditions.
ds_in = Measure("ds", domain=mesh, subdomain_data=mf, subdomain_id=1)
ds_wall = Measure("ds", domain=mesh, subdomain_data=mf, subdomain_id=2)
"""Initial values (t == 0.0)"""
Beispiel #10
0
            if 4 * i >= local_range[0] and 4 * i + 3 < local_range[1]:
                local_p[4 * i - local_range[0]] = math.pow(10, row[0])
                local_p[4 * i + 1 - local_range[0]] = 0.
                local_p[4 * i + 2 - local_range[0]] = 0.
                local_p[4 * i + 3 - local_range[0]] = math.pow(10, row[0])
    p.vector().set_local(local_p)
    p.vector().apply("insert")


mesh = Mesh("data/biot_2mat.xml")
subdomains = MeshFunction("size_t", mesh, "data/biot_2mat_physical_region.xml")
boundaries = MeshFunction("size_t", mesh, "data/biot_2mat_facet_region.xml")

for discretization in ("DG", "EG"):
    # Block function space
    V_element = VectorElement("CG", mesh.ufl_cell(), 2)
    if discretization == "DG":
        Q_element = FiniteElement("DG", mesh.ufl_cell(), 1)
        W_element = BlockElement(V_element, Q_element)
    elif discretization == "EG":
        Q_element = FiniteElement("CG", mesh.ufl_cell(), 1)
        D_element = FiniteElement("DG", mesh.ufl_cell(), 0)
        EG_element = Q_element + D_element
        W_element = BlockElement(V_element, EG_element)
    else:
        raise RuntimeError("Invalid discretization")
    W = BlockFunctionSpace(mesh, W_element)

    PM = FunctionSpace(mesh, "DG", 0)
    TM = TensorFunctionSpace(mesh, "DG", 0)
Beispiel #11
0
def save_files_visualization(visualization_folder, dvp_, t, save_deg, mesh,
                             **namespace):
    # Files for storing results
    if not "d_file" in namespace.keys():
        d_file = XDMFFile(
            MPI.comm_world,
            str(visualization_folder.joinpath("displacement.xdmf")))
        v_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("velocity.xdmf")))
        p_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("pressure.xdmf")))
        for tmp_t in [d_file, v_file, p_file]:
            tmp_t.parameters["flush_output"] = True
            tmp_t.parameters["rewrite_function_mesh"] = False

        if save_deg > 1:
            # Import fenicstools
            import warnings
            try:
                with warnings.catch_warnings(record=True) as w:
                    from fenicstools import interpolate_nonmatching_mesh_any
            except ModuleNotFoundError:
                raise ModuleNotFoundError("For save_deg > 1 to work please install fenics tools with:\n" + \
                                          "pip install git+https://github.com/mikaem/fenicstools")

            # Copy mesh
            mesh_viz = Mesh(mesh)

            for i in range(save_deg - 1):
                mesh_viz = refine(mesh_viz)  # refine the mesh

            dve_viz = VectorElement('CG', mesh_viz.ufl_cell(), 1)
            pe_viz = FiniteElement('CG', mesh_viz.ufl_cell(), 1)
            FSdv_viz = FunctionSpace(
                mesh_viz, dve_viz)  # Visualisation FunctionSpace for d and v
            FSp_viz = FunctionSpace(
                mesh_viz, pe_viz)  # Visualisation FunctionSpace for p

            return_dict = dict(
                v_file=v_file,
                d_file=d_file,
                p_file=p_file,
                FSdv_viz=FSdv_viz,
                FSp_viz=FSp_viz,
                save_deg_interpolator=interpolate_nonmatching_mesh_any)
        else:
            return_dict = dict(v_file=v_file, d_file=d_file, p_file=p_file)

        namespace.update(return_dict)

    else:
        return_dict = {}

    # Split function
    d = dvp_["n"].sub(0, deepcopy=True)
    v = dvp_["n"].sub(1, deepcopy=True)
    p = dvp_["n"].sub(2, deepcopy=True)

    # New functions mimicing higher-order visualization fies
    if save_deg > 1:
        d = namespace["save_deg_interpolator"](d, namespace["FSdv_viz"])
        v = namespace["save_deg_interpolator"](v, namespace["FSdv_viz"])
        p = namespace["save_deg_interpolator"](p, namespace["FSp_viz"])

    # Name function
    d.rename("Displacement", "d")
    v.rename("Velocity", "v")
    p.rename("Pressure", "p")

    # Write results
    namespace["d_file"].write(d, t)
    namespace["v_file"].write(v, t)
    namespace["p_file"].write(p, t)

    return return_dict
Beispiel #12
0
class CavityProblemSetup():
    def __init__(self, parameters, mesh_name, facet_name):
        """
        Create the required function spaces, functions and boundary conditions
        for a channel flow problem
        """
        self.mesh = Mesh()
        with XDMFFile(mesh_name) as infile:
            infile.read(self.mesh)

        mvc = MeshValueCollection("size_t", self.mesh,
                                  self.mesh.topology().dim() - 1)
        with XDMFFile(facet_name) as infile:
            infile.read(mvc, "name_to_read")
        mf = self.mf = cpp.mesh.MeshFunctionSizet(self.mesh, mvc)
        self.bc_dict = {"bottom": 1, "right": 2, "top": 3, "left": 4}

        T_init = Constant(parameters["initial temperature [°C]"])
        self.t_amb = Constant(parameters["ambient temperature [°C]"])
        self.t_feeder = Constant(parameters["temperature feeder [°C]"])
        self.k_top = Constant(parameters["thermal conductivity top [W/(m K)]"])
        self.k_lft = Constant(
            parameters["thermal conductivity left [W/(m K)]"])
        self.k_btm = Constant(
            parameters["thermal conductivity bottom [W/(m K)]"])
        self.k_rgt = Constant(
            parameters["thermal conductivity right [W/(m K)]"])
        self.U_m = Constant(parameters["mean velocity lid [m/s]"])
        g = parameters["gravity [m/s²]"]
        self.g = Constant((0.0, -g))
        self.dt = Constant(parameters["dt [s]"])
        self.D = Constant(parameters["Diffusivity [-]"])

        self.V = V = VectorFunctionSpace(self.mesh, 'P', 2)
        self.Q = Q = FunctionSpace(self.mesh, 'P', 1)
        self.T = T = FunctionSpace(self.mesh, 'P', 1)

        self.ds_ = Measure("ds", domain=self.mesh, subdomain_data=mf)
        self.vu, self.vp, self.vt = (TestFunction(V), TestFunction(Q),
                                     TestFunction(T))
        self.u_, self.p_, self.t_ = Function(V), Function(Q), Function(T)
        self.mu, self.rho = Function(T), Function(T)
        self.u_1, self.p_1, self.t_1, self.rho_1 = (Function(V), Function(Q),
                                                    Function(T), Function(T))
        self.u, self.p, self.t = (TrialFunction(V), TrialFunction(Q),
                                  TrialFunction(T))

        # boundary conditions
        self.no_slip = Constant((0., 0))
        self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"),
                                  m=self.U_m,
                                  degree=2)
        bc0 = DirichletBC(V, self.topflow, mf, self.bc_dict["top"])
        bc1 = DirichletBC(V, self.no_slip, mf, self.bc_dict["left"])
        bc2 = DirichletBC(V, self.no_slip, mf, self.bc_dict["bottom"])
        bc3 = DirichletBC(V, self.no_slip, mf, self.bc_dict["right"])
        # bc4 = df.DirichletBC(Q, df.Constant(0), top)
        # bc3 = df.DirichletBC(T, df.Constant(800), top)
        self.bcu = [bc0, bc1, bc2, bc3]
        self.bcp = [DirichletBC(Q, Constant(0), mf, self.bc_dict["top"])]
        self.bcp = []
        self.bct = []
        # self.bct = [DirichletBC(T, Constant(self.t_feeder), mf,
        #                         self.bc_dict["top"])]

        self.robin_boundary_terms = (
            self.k_btm * (self.t - self.t_amb) * self.vt * self.ds_(1) +
            self.k_rgt * (self.t - self.t_amb) * self.vt * self.ds_(2)
            # + self.k_top*(self.t - self.t_feeder)*self.vt*self.ds_(3)
            + self.k_lft * (self.t - self.t_amb) * self.vt * self.ds_(4))
        print("k, T", self.k_btm.values(), self.t_feeder.values())
        print("k, T", self.k_rgt.values(), self.t_amb.values())
        # print("k, T", self.k_top.values(), self.t_amb.values())
        print("k, T", self.k_lft.values(), self.t_amb.values())

        # set initial values
        # TODO: find a better solution
        x, y = T.tabulate_dof_coordinates().T
        self.u_1.vector().vec().array[:] = 1e-6
        # self.u_k.vector().vec().array[:] = 1e-6
        self.p_.vector().vec(
        ).array[:] = -self.rho.vector().vec().array * g * y
        self.p_1.vector().vec(
        ).array[:] = -self.rho.vector().vec().array * g * y
        self.t_1.vector().vec().array = T_init
        self.t_.assign(self.t_1)
        return

    def stokes(self):
        P2 = VectorElement("CG", self.mesh.ufl_cell(), 2)
        P1 = FiniteElement("CG", self.mesh.ufl_cell(), 1)
        TH = P2 * P1
        VQ = FunctionSpace(self.mesh, TH)
        mf = self.mf
        self.no_slip = Constant((0., 0))
        self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"),
                                  m=self.U_m,
                                  degree=2)
        bc0 = DirichletBC(VQ.sub(0), self.topflow, mf, self.bc_dict["top"])
        bc1 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["left"])
        bc2 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["bottom"])
        bc3 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["right"])
        # bc4 = DirichletBC(VQ.sub(1), Constant(0), mf, self.bc_dict["top"])
        bcs = [bc0, bc1, bc2, bc3]

        vup = TestFunction(VQ)
        up = TrialFunction(VQ)
        # the solution will be in here:
        up_ = Function(VQ)

        u, p = split(up)  # Trial
        vu, vp = split(vup)  # Test
        u_, p_ = split(up_)  # Function holding the solution
        F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \
            - inner(vp, div(u))*dx + dot(self.g*self.rho, vu)*dx
        solve(lhs(F) == rhs(F), up_, bcs=bcs)
        self.u_.assign(project(u_, self.V))
        self.p_.assign(project(p_, self.Q))
        return

    def initial_condition_from_file(self, path_u, path_p):
        f_in = XDMFFile(path_u)
        f_in.read_checkpoint(self.u_, "f", 0)
        f_in = XDMFFile(path_p)
        f_in.read_checkpoint(self.p_, "f", 0)
        return

    def get_rho(self):
        return self.rho.vector().vec().array

    def set_rho(self, rho):
        self.rho.vector().vec().array[:] = rho

    def get_mu(self):
        return self.mu.vector().vec().array

    def set_mu(self, mu):
        self.mu.vector().vec().array[:] = mu

    def get_t(self):
        return self.t_.vector().vec().array

    def set_t(self, t):
        self.t_.vector().vec().array[:] = t

    def get_dt(self):
        return self.dt.values()

    def set_dt(self, dt):
        self.dt.assign(dt)

    def get_D(self):
        return self.D.values()

    def set_D(self, D):
        self.D.assign(D)

    def get_t_amb(self):
        return self.t_amb.values()

    def set_t_amb(self, t_amb):
        self.t_amb.assign(t_amb)

    def plot(self):
        cmap = mpl.cm.inferno
        cmap_r = mpl.cm.inferno_r
        u, p, t, m, r = self.u_, self.p_, self.t_, self.mu, self.rho
        mesh = self.mesh
        w0 = u.compute_vertex_values(mesh)
        w0.shape = (2, -1)
        magnitude = np.linalg.norm(w0, axis=0)
        x, y = np.split(mesh.coordinates(), 2, 1)
        u, v = np.split(w0, 2, 0)
        x, y, u, v = x.ravel(), y.ravel(), u.ravel(), v.ravel()
        tri = mesh.cells()
        pressure = p.compute_vertex_values(mesh)
        temperature = t.compute_vertex_values(mesh)
        viscosity = m.compute_vertex_values(mesh)
        density = r.compute_vertex_values(mesh)

        fig = plt.figure(figsize=(12, 8))
        ax1 = plt.subplot(121)
        ax2 = plt.subplot(243, sharex=ax1, sharey=ax1)
        ax3 = plt.subplot(244, sharex=ax1, sharey=ax1)
        ax4 = plt.subplot(247, sharex=ax1, sharey=ax1)
        ax5 = plt.subplot(248, sharex=ax1, sharey=ax1)
        ax1.plot(x, y, "k.", ms=.5)
        not0 = magnitude > 1e-6
        if np.sum(not0) > 0:
            ax1.quiver(x[not0], y[not0], u[not0], v[not0], magnitude[not0])
        c2 = ax2.tricontourf(x, y, tri, pressure, levels=40, cmap=cmap)
        c3 = ax3.tricontourf(x, y, tri, temperature, levels=40, cmap=cmap)
        c4 = ax4.tricontourf(
            x,
            y,
            tri,
            viscosity,
            levels=40,
            # vmin=self.mu(800, .1), vmax=self.mu(600, .1),
            cmap=cmap_r)
        c5 = ax5.tricontourf(
            x,
            y,
            tri,
            density,
            levels=40,
            # vmin=self.rho(800.), vmax=self.rho(600.),
            cmap=cmap_r)
        plt.colorbar(c2, ax=ax2)
        plt.colorbar(c3, ax=ax3, ticks=[temperature.min(), temperature.max()])
        plt.colorbar(c4, ax=ax4, ticks=[viscosity.min(), viscosity.max()])
        plt.colorbar(c5, ax=ax5, ticks=[density.min(), density.max()])
        ax1.set_aspect("equal")
        ax2.set_aspect("equal")
        ax3.set_aspect("equal")
        ax4.set_aspect("equal")
        ax5.set_aspect("equal")
        ax1.set_title("velocity\n{:.4f} ... {:.5f} m/s".format(
            magnitude.min(), magnitude.max()))
        ax2.set_title("pressure")
        ax3.set_title("temperature")
        ax4.set_title("viscosity")
        ax5.set_title("density")
        ax1.set_xlim([-.1, 1.1])
        ax1.set_ylim([-.1, 1.1])
        # plt.tight_layout()
        return fig, (ax1, ax2)