Example #1
0
	def __init__(self, x0, y0, z0, R, n):
		class SphereSurface(SubDomain):
			def inside(self, x, on_boundary):
				return on_boundary
		class X_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x0)
		class Y_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y0)
		class Z_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z0)
		self.geometry = Sphere(Point(x0, y0, z0), R, segments=n) - Box(Point(x0 + R, y0, z0 - R), Point(x0 - R, y0 - R, z0 + R)) - Box(Point(x0 - R, y0 + R, z0), Point(x0 + R, y0, z0 - R)) - Box(Point(x0, y0, z0), Point(x0 - R, y0 + R, z0 + R))
		self.mesh = generate_mesh(self.geometry, n)
		self.domains = MeshFunction("size_t", self.mesh, self.mesh.topology().dim())
		self.domains.set_all(0)
		self.dx = Measure('dx', domain=self.mesh, subdomain_data=self.domains)
		self.boundaries = MeshFunction("size_t", self.mesh, self.mesh.topology().dim()-1)
		self.boundaries.set_all(0)
		self.sphereSurface = SphereSurface()
		self.sphereSurface.mark(self.boundaries, 1)
		self.x_symmetric = X_Symmetric()
		self.x_symmetric.mark(self.boundaries, 2)
		self.y_symmetric = Y_Symmetric()
		self.y_symmetric.mark(self.boundaries, 3)
		self.z_symmetric = Z_Symmetric()
		self.z_symmetric.mark(self.boundaries, 4)
		self.ds = Measure('ds', domain=self.mesh, subdomain_data=self.boundaries)
		self.dS = Measure('dS', domain=self.mesh, subdomain_data=self.boundaries)
Example #2
0
  def dP(self, domain = "all"):
    """
    Convenience wrapper for integral-point 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

    *Returns*
      :class:`dolfin:Measure`
        the measure
    """
    if not self.mesh_has_domains(): return Measure('dP', self.mesh)

    if not self._dP.has_key(domain):
      v = TestFunction(self.FunctionSpace())
      values = assemble(v*self.dx(domain)).array()
      # TODO improve this?
      markers = ((np.sign(np.ceil(values) - 0.5) + 1.0) / 2.0).astype(np.uint64)

      vertex_domains = MeshFunction('size_t', self.mesh, 0)
      vertex_domains.array()[:] = markers

      self._dP[domain] = Measure('dP', self.mesh)[vertex_domains](1)

    return self._dP[domain]
Example #3
0
 def mesh_generator(n):
     mesh = UnitSquareMesh(n, n, "left/right")
     dim = mesh.topology().dim()
     domains = MeshFunction("size_t", mesh, dim)
     domains.set_all(0)
     dx = Measure("dx", subdomain_data=domains)
     boundaries = MeshFunction("size_t", mesh, dim - 1)
     boundaries.set_all(0)
     ds = Measure("ds", subdomain_data=boundaries)
     return mesh, dx, ds
    def create_mesh(self, parameters):
        from dolfin import Point, XDMFFile
        import hashlib

        d = {
            'rad': parameters['geometry']['rad'],
            'h': parameters['geometry']['meshsize']
        }
        # fname = 'coinforall'
        # fname = 'coin'
        fname = 'coinforall_small'
        meshfile = "meshes/%s-%s.xml" % (fname, self.signature)

        if os.path.isfile(meshfile):
            print("Meshfile %s exists" % meshfile)

        else:
            print("Create meshfile, meshsize {}".format(
                parameters['geometry']['meshsize']))
            nel = int(parameters['geometry']['rad'] /
                      parameters['geometry']['meshsize'])

            # geom = mshr.Circle(Point(0., 0.), parameters['geometry']['rad'])
            # mesh = mshr.generate_mesh(geom, nel)
            mesh_template = open('scripts/coin_template.geo')

            src = Template(mesh_template.read())
            geofile = src.substitute(d)

            if MPI.rank(MPI.comm_world) == 0:
                with open("scripts/coin-%s" % self.signature + ".geo",
                          'w') as f:
                    f.write(geofile)

        form_compiler_parameters = {
            "representation": "uflacs",
            "quadrature_degree": 2,
            "optimize": True,
            "cpp_optimize": True,
        }

        mesh = Mesh("meshes/{}.xml".format(fname))
        self.domains = MeshFunction(
            'size_t', mesh, 'meshes/{}_physical_region.xml'.format(fname))
        self.ds = Measure("exterior_facet", domain=mesh)
        self.dS = Measure("interior_facet", domain=mesh)
        self.dx = Measure("dx",
                          metadata=form_compiler_parameters,
                          subdomain_data=self.domains)
        # self.dx = Measure("dx", subdomain_data=self.domains)
        plt.colorbar(plot(self.domains))
        plt.savefig('domains.pdf')
        return mesh
Example #5
0
    def recompute_dJ(self):
        """
        Create gradient expression for deformation algorithm
        """
        # FIXME: probably only works with one obstacle
        # Recalculate barycenter and volume of obstacle
        self.geometric_quantities()
        self.integrand_list = []
        dJ = 0
        solver.dJ_form = []
        for i in range(1, self.N):
            # Integrand of gradient
            x = SpatialCoordinate(self.multimesh.part(i))
            u_i = self.u.part(i)
            dJ_stokes = -inner(grad(u_i), grad(u_i))
            dJ_vol = -Constant(2 * self.vfac) * (self.Vol - self.Vol0)
            dJ_bar = Constant(2 * self.bfac) / self.Vol * (
                (self.bx - x[0]) * self.bxoff + (self.by - x[1]) * self.byoff)
            integrand = dJ_stokes + dJ_vol + dJ_bar
            dDeform = Measure("ds", subdomain_data=self.mfs[i])
            from femorph import VolumeNormal
            n = VolumeNormal(self.multimesh.part(i))
            s = TestFunction(self.S[i])

            self.integrand_list.append(n * integrand)

            dJ = inner(s, n) * integrand * dDeform(self.move_dict[i]["Deform"])
            self.dJ_form.append(dJ)
Example #6
0
 def update_multimesh(self, step):
     move_norm = []
     hmins = []
     move_max = []
     for i in range(1, self.N):
         s_move = self.deformation[i - 1].copy(True)
         s_move.vector()[:] *= step
         # Approximate geodesic distance
         dDeform = Measure("ds", subdomain_data=self.mfs[i])
         n_i = FacetNormal(self.multimesh.part(i))
         geo_dist_i = inner(s_move, s_move)*\
                      dDeform(self.move_dict[i]["Deform"])
         move_norm.append(assemble(geo_dist_i))
         # move_max.append(project(sqrt(s_move[0]**2 + s_move[1]**2),
         #                         FunctionSpace(self.multimesh.part(i),"CG",1)
         #                         ).vector().max())
         # hmins.append(self.multimesh.part(i).hmin())
         ALE.move(self.multimesh.part(i), s_move)
     # Compute L2 norm of movement
     self.move_norm = sqrt(sum(move_norm))
     # self.move_max = max(move_max)
     # print(hmins, move_max)
     self.multimesh.build()
     for key in self.cover_points.keys():
         self.multimesh.auto_cover(key, self.cover_points[key])
 def _csd_normalization_factor(self, csd):
     old_a = csd.a
     csd.a = 1
     try:
         return 1.0 / assemble(csd * Measure("dx", self._mesh))
     finally:
         csd.a = old_a
    def initial_conditions(self):
        "Return initial conditions for v and s as a dolfin.GenericFunction."

        n = self.num_states() # (Maximal) Number of states in MultiCellModel
        VS = VectorFunctionSpace(self.mesh(), "DG", 0, n+1)
        vs = Function(VS)

        markers = self.markers()
        u = TrialFunction(VS)
        v = TestFunction(VS)

        dy = Measure("dx", domain=self.mesh(), subdomain_data=markers)

        # Define projection into multiverse
        a = inner(u, v)*dy()

        Ls = list()
        for (k, model) in enumerate(self.models()):
            ic = model.initial_conditions() # Extract initial conditions
            n_k = model.num_states() # Extract number of local states
            i_k = self.keys()[k] # Extract domain index of cell model k
            L_k = sum(ic[j]*v[j]*dy(i_k) for j in range(n_k))
            Ls.append(L_k)
        L = sum(Ls)
        solve(a == L, vs)
        return vs
Example #9
0
    def assign_initial_conditions(self, function):
        function_space = function.function_space()
        markers = self.markers()

        u = TrialFunction(function_space)
        v = TestFunction(function_space)

        dy = Measure("dx", domain=self.mesh(), subdomain_data=markers)

        # Define projection into multiverse
        a = inner(u, v) * dy()

        Ls = list()
        for k, model in enumerate(self.models()):
            ic = model.initial_conditions()  # Extract initial conditions
            n_k = model.num_states()  # Extract number of local states
            i_k = self.keys()[k]  # Extract domain index of cell model k
            L_k = sum(ic[j] * v[j] * dy(i_k)
                      for j in range(n_k + 1))  # include v and s
            Ls.append(L_k)
        L = sum(Ls)
        # solve(a == L, function)       # really inaccurate

        params = df.KrylovSolver.default_parameters()
        params["absolute_tolerance"] = 1e-14
        params["relative_tolerance"] = 1e-14
        params["nonzero_initial_guess"] = True
        solver = df.KrylovSolver()
        solver.update_parameters(params)
        A, b = df.assemble_system(a, L)
        solver.set_operator(A)
        solver.solve(function.vector(), b)
Example #10
0
 def __init__(self, V, subdomains, expression_type, basis_generation):
     self.V = V
     # Parametrized function to be interpolated
     mock_problem = MockProblem(V)
     f = ParametrizedExpression(
         mock_problem,
         "exp( - 2*pow(x[0]-mu[0], 2) - 2*pow(x[1]-mu[1], 2) )",
         mu=(0., 0.),
         element=V.ufl_element())
     # Subdomain measure
     dx = Measure("dx")(subdomain_data=subdomains)(1)
     #
     folder_prefix = os.path.join("test_eim_approximation_04_tempdir",
                                  expression_type, basis_generation)
     assert expression_type in ("Vector", "Matrix")
     if expression_type == "Vector":
         v = TestFunction(V)
         form = f * v * dx
         # Call Parent constructor
         EIMApproximation.__init__(self, mock_problem,
                                   ParametrizedTensorFactory(form),
                                   folder_prefix, basis_generation)
     elif expression_type == "Matrix":
         u = TrialFunction(V)
         v = TestFunction(V)
         form = f * u * v * dx
         # Call Parent constructor
         EIMApproximation.__init__(self, mock_problem,
                                   ParametrizedTensorFactory(form),
                                   folder_prefix, basis_generation)
     else:  # impossible to arrive here anyway thanks to the assert
         raise AssertionError("Invalid expression_type")
Example #11
0
	def __init__(self, x0, x1, y0, y1, z0, z1, n, unstructured=False):
		class Left(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x0)
		class Right(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x1)
		class Back(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y0)
		class Front(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y1)
		class Bottom(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z0)
		class Top(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z1)
		if unstructured:
			self.geometry = Box(Point(x0, y0, z0), Point(x1, y1, z1))
			self.mesh = generate_mesh(self.geometry, n)
		else:
			nx = int(round(n**(1./3.)*(x1 - x0)))
			ny = int(round(n**(1./3.)*(y1 - y0)))
			nz = int(round(n**(1./3.)*(z1 - z0)))
			self.mesh = BoxMesh(Point(x0, y0, z0), Point(x1, y1, z1), nx, ny, nz)
		self.domains = MeshFunction("size_t", self.mesh, self.mesh.topology().dim())
		self.domains.set_all(0)
		self.dx = Measure('dx', domain=self.mesh, subdomain_data=self.domains)
		self.boundaries = MeshFunction("size_t", self.mesh, self.mesh.topology().dim()-1)
		self.boundaries.set_all(0)
		self.left = Left()
		self.left.mark(self.boundaries, 1)
		self.right = Right()
		self.right.mark(self.boundaries, 2)
		self.front = Front()
		self.front.mark(self.boundaries, 3)
		self.back = Back()
		self.back.mark(self.boundaries, 4)
		self.bottom = Bottom()
		self.bottom.mark(self.boundaries, 5)
		self.top = Top()
		self.top.mark(self.boundaries, 6)
		self.ds = Measure('ds', domain=self.mesh, subdomain_data=self.boundaries)
		self.dS = Measure('dS', domain=self.mesh, subdomain_data=self.boundaries)
Example #12
0
    def calculate_volumes(self):
        dx = Measure('dx', domain=self.mesh1)
        a = Constant(1.0) * dx
        V1 = assemble(a)

        dx = Measure('dx', domain=self.mesh2)
        a = Constant(1.0) * dx
        V2 = assemble(a)

        dx = Measure('dx', domain=self.overlap_mesh)
        a = Constant(1.0) * dx
        VO = assemble(a)

        dx = Measure('dx', domain=self.mesh)
        a = Constant(1.0) * dx
        V = assemble(a)

        return V, V1, V2, VO
Example #13
0
    def calculate_areas(self):
        dx = Measure('dx', domain=self.mesh1)
        a = Constant(1.0) * dx
        A1 = assemble(a)

        dx = Measure('dx', domain=self.mesh2)
        a = Constant(1.0) * dx
        A2 = assemble(a)

        dx = Measure('dx', domain=self.overlap_mesh)
        a = Constant(1.0) * dx
        AO = assemble(a)

        dx = Measure('dx', domain=self.mesh)
        a = Constant(1.0) * dx
        A = assemble(a)

        return A, A1, A2, AO
Example #14
0
    def initialize(self,
                   coupling_subdomain,
                   mesh,
                   read_field,
                   write_field,
                   u_n,
                   dimension=2,
                   t=0,
                   n=0,
                   coupling_marker=0):
        """Initializes remaining attributes. Called once, from the solver.

        :param read_field: function applied on the read field
        :param write_field: function applied on the write field
        """
        print("Begin initializating the fenics adapter...")

        self._fenics_dimensions = dimension

        self.set_coupling_mesh(mesh, coupling_subdomain)
        self.set_read_field(read_field)
        self.set_write_field(write_field)
        self._precice_tau = self._interface.initialize()

        self._function_type = self.function_type(write_field)

        print('is action required')
        if self._interface.is_action_required(
                precice.action_write_initial_data()):
            self.write_block_data()

        self._interface.initialize_data()

        print('read available')
        if self._interface.is_read_data_available():
            self.read_block_data()
#            if self.function_type(read_field) is FunctionType.SCALAR:
#                self._interface.read_block_scalar_data(self._read_data_id, self._n_vertices, self._vertex_ids, self._read_data)
#            elif self.function_type(read_field) is FunctionType.VECTOR:
#                self._interface.read_block_vector_data(self._read_data_id, self._n_vertices, self._vertex_ids, self._read_data.ravel())
#            else:
#                raise Exception("Rank of function space is neither 0 nor 1")

        if self._interface.is_action_required(
                precice.action_write_iteration_checkpoint()):
            self._u_cp = u_n.copy(deepcopy=True)
            self._t_cp = t
            self._n_cp = n
            self._interface.fulfilled_action(
                precice.action_write_iteration_checkpoint())

        #create an integration domain for the coupled boundary
        self.dss = Measure('ds', domain=mesh, subdomain_data=coupling_marker)
        print("initialization successful")

        return self._precice_tau
Example #15
0
def main_slice_fem(mesh, subdomains, boundaries, src_pos, snk_pos):
    sigma_ROI = Constant(params.sigma_roi)
    sigma_SLICE = Constant(params.sigma_slice)
    sigma_SALINE = Constant(params.sigma_saline)
    sigma_AIR = Constant(0.)

    V = FunctionSpace(mesh, "CG", 2)
    v = TestFunction(V)
    u = TrialFunction(V)

    phi = Function(V)
    dx = Measure("dx")(subdomain_data=subdomains)
    ds = Measure("ds")(subdomain_data=boundaries)
    a = inner(sigma_ROI * grad(u), grad(v))*dx(params.roivol) + \
        inner(sigma_SLICE * grad(u), grad(v))*dx(params.slicevol) + \
        inner(sigma_SALINE * grad(u), grad(v))*dx(params.salinevol)
    L = Constant(0) * v * dx
    A = assemble(a)
    b = assemble(L)

    x_pos, y_pos, z_pos = src_pos
    point = Point(x_pos, y_pos, z_pos)
    delta = PointSource(V, point, 1.)
    delta.apply(b)

    x_pos, y_pos, z_pos = snk_pos
    point1 = Point(x_pos, y_pos, z_pos)
    delta1 = PointSource(V, point1, -1.)
    delta1.apply(b)

    solver = KrylovSolver("cg", "ilu")
    solver.parameters["maximum_iterations"] = 1000
    solver.parameters["absolute_tolerance"] = 1E-8
    solver.parameters["monitor_convergence"] = True

    info(solver.parameters, True)
    #    set_log_level(PROGRESS) does not work in fenics 2018.1.0
    solver.solve(A, phi.vector(), b)

    ele_pos_list = params.ele_coords
    vals = extract_pots(phi, ele_pos_list)
    # np.save(os.path.join('results', save_as), vals)
    return vals
Example #16
0
def rhs_with_markerwise_field(g, mesh, v):
    if g is None:
        dz = dx
        rhs = 0.0       # Do make constant
    elif isinstance(g, Markerwise):
        markers = g.markers()
        dz = Measure("dx", domain=mesh, subdomain_data=markers)
        rhs = sum([g*v*dz(i) for (i, g) in zip(g.keys(), g.values())])
    else:
        dz = dx
        rhs = g*v*dz()
    return dz, rhs
Example #17
0
def CladdingR_solver(FC_mesh, FC_facets, FC_fs, FC_info, D_post, R_path):

    FC_fi, FC_fo = FC_fs
    h, Tfc_inner, Tb, FC_Tave = FC_info

    # Reading mesh data stored in .xdmf files.
    mesh = Mesh()
    with XDMFFile(FC_mesh) as infile:
        infile.read(mesh)

    mvc = MeshValueCollection("size_t", mesh, 1)
    with XDMFFile(FC_facets) as infile:
        infile.read(mvc, "name_to_read")
    mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)
    #File("Circle_facet.pvd").write(mf)

    # Mesh data
    print('CladdingRod_mesh data\n', 'Number of cells: ', mesh.num_cells(),
          '\n Number of nodes: ', mesh.num_vertices())

    # Define variational problem
    V = FunctionSpace(mesh, 'P', 1)
    u = Function(V)
    v = TestFunction(V)

    # Define boundary conditions base on pygmsh mesh mark
    bc = DirichletBC(V, Constant(Tfc_inner), mf, FC_fi)
    ds = Measure("ds", domain=mesh, subdomain_data=mf, subdomain_id=FC_fo)

    # Variational formulation
    # Klbda_ZrO2 = 18/1000  # W/(m K) --> Nuclear reactor original source
    # Klbda_ZrO2 = Constant(K_ZrO2(FC_Tave))
    F = K_ZrO2(u) * dot(grad(u), grad(v)) * dx + h * (u - Tb) * v * ds

    # Compute solution
    du = TrialFunction(V)
    Gain = derivative(F, u, du)
    solve(F==0, u, bc, J=Gain, \
          solver_parameters={"newton_solver": {"linear_solver": "lu",
                                               "relative_tolerance": 1e-9}}, \
          form_compiler_parameters={"cpp_optimize": True,
                                    "representation": "uflacs",
                                    "quadrature_degree" : 2}
          )  # mumps

    # Save solution
    if D_post:
        fU_out = XDMFFile(os.path.join(R_path, 'FuelCladding', 'u.xdmf'))
        fU_out.write_checkpoint(u, "T", 0, XDMFFile.Encoding.HDF5, False)
        fU_out.close()
Example #18
0
def _init_measure(measure="default",
                  cell_domains=None,
                  facet_domains=None,
                  indicator=None):
    assert cell_domains is None or facet_domains is None, "You can't specify both cell_domains or facet_domains"

    if cell_domains is not None:
        assert isinstance(cell_domains, (MeshFunctionSizet, MeshFunctionInt))

    if facet_domains is not None:
        assert isinstance(facet_domains, (MeshFunctionSizet, MeshFunctionInt))

    if (cell_domains and indicator is not None):
        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            dI = Measure("cell")(subdomain_data=cell_domains)(indicator)
        else:
            dI = Measure("cell")[cell_domains](indicator)
    elif (facet_domains and indicator is not None):
        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            dI = Measure("exterior_facet")(
                subdomain_data=facet_domains)(indicator)
        else:
            dI = Measure("exterior_facet")[facet_domains](indicator)
    elif measure == "default":
        if indicator is not None:
            cbc_warning(
                "Indicator specified, but no domains. Will dompute average over entire domain."
            )
        dI = dx()
    elif isinstance(measure, Measure):
        dI = measure
    else:
        raise TypeError(
            "Unable to create a domain measure from provided domains or measure."
        )

    return dI
Example #19
0
 def assemble_lui_stiffness(self, g, f, mesh, robin_boundary):
     V = FunctionSpace(mesh, "Lagrange", self.p)
     u = TrialFunction(V)
     v = TestFunction(V)
     n = FacetNormal(mesh)
     robin = MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
     robin_boundary.mark(robin, 1)
     ds = Measure('ds', subdomain_data=robin)
     a = inner(grad(u), grad(v)) * dx
     b = (1 - g) * (inner(grad(u), n)) * v * ds(1)
     c = f * u * v * ds(1)
     k = lhs(a + b - c)
     K = PETScMatrix()
     assemble(k, tensor=K)
     return K, V
Example #20
0
def test_stationary_solve(show=False):

    problem = problems.Crucible()

    boundaries = problem.wp_boundaries

    average_temp = 1551.0

    material = problem.subdomain_materials[problem.wpi]
    rho = material.density(average_temp)
    cp = material.specific_heat_capacity
    kappa = material.thermal_conductivity

    my_ds = Measure("ds")(subdomain_data=boundaries)

    convection = None
    heat = maelstrom.heat.Heat(
        problem.Q,
        kappa,
        rho,
        cp,
        convection,
        source=Constant(0.0),
        dirichlet_bcs=problem.theta_bcs_d,
        neumann_bcs=problem.theta_bcs_n,
        robin_bcs=problem.theta_bcs_r,
        my_dx=dx,
        my_ds=my_ds,
    )
    theta_reference = heat.solve_stationary()
    theta_reference.rename("theta", "temperature")

    if show:
        # with XDMFFile('temperature.xdmf') as f:
        #     f.parameters['flush_output'] = True
        #     f.parameters['rewrite_function_mesh'] = False
        #     f.write(theta_reference)
        tri = plot(theta_reference)
        plt.colorbar(tri)
        plt.show()

    assert abs(maelstrom.helpers.average(theta_reference) - 1551.0) < 1.0e-1

    return theta_reference
Example #21
0
 def generate_H1_deformation(self):
     self.deformation = []
     for i in range(1, self.N):
         S_i = VectorFunctionSpace(self.multimesh.part(i), "CG", 1)
         u_i, v_i = TrialFunction(S_i), TestFunction(S_i)
         d_free = Measure("ds",
                          domain=self.multimesh.part(i),
                          subdomain_data=self.mfs[i],
                          subdomain_id=self.move_dict[i]["Deform"])
         plot(-self.integrand_list[i - 1])
         plt.show()
         a_i = inner(u_i, v_i) * dx + 0.01 * inner(grad(u_i),
                                                   grad(v_i)) * dx
         n_i = FacetNormal(self.multimesh.part(i))
         l_i = inner(v_i, -self.integrand_list[i - 1]) * d_free
         s_i = Function(S_i)
         solve(a_i == l_i, s_i)
         plot(s_i)
         plt.show()
         self.deformation.append(s_i)
Example #22
0
    def big_error_norms(self, u, overlap_subdomain):
        V = FunctionSpace(self.mesh, "Lagrange", self.p)

        uu = Function(V)
        uu.vector()[:] = u.vector()
        # uu.vector()[:] = u.vector()

        overlap_marker = MeshFunction('size_t', self.mesh,
                                      self.mesh.topology().dim())
        overlap_subdomain.mark(overlap_marker, 1)

        dxo = Measure('dx', subdomain_data=overlap_marker)

        error = (uu**2) * dxo
        semi_error = inner(grad(uu), grad(uu)) * dxo

        L2 = assemble(error)
        H1 = L2 + assemble(semi_error)
        SH = H1 - L2

        return L2, H1, SH
Example #23
0
 def __init__(self, w_sim, h_sim, w_wg, h_wg, res):
     # Create mesh with two domains, waveguide + cladding
     self.res = res
     domain = Rectangle(Point(-w_sim / 2, -h_sim / 2),
                        Point(w_sim / 2, h_sim / 2))
     domain.set_subdomain(
         1,
         Rectangle(Point(-w_sim / 2, -h_sim / 2),
                   Point(w_sim / 2, h_sim / 2)))
     domain.set_subdomain(
         2, Rectangle(Point(-w_wg / 2, -h_wg / 2),
                      Point(w_wg / 2, h_wg / 2)))
     self.mesh = generate_mesh(domain, self.res)
     self.mesh.init()
     # Initialize mesh function for interior domains
     self.waveguide = Waveguide(w_wg, h_wg)
     self.domains = MeshFunction("size_t", self.mesh, 2)
     self.domains.set_all(0)
     self.waveguide.mark(self.domains, 1)
     # Define new measures associated with the interior domains
     self.dx = Measure("dx")(subdomain_data=self.domains)
Example #24
0
    def recompute_dJ(self):
        """
        Create gradient expression for deformation algorithm
        """

        # Recalculate barycenter and volume of obstacle
        self.compute_volume_bary()

        # Integrand of gradient
        x = SpatialCoordinate(mesh)
        dJ_stokes = -inner(grad(self.u), grad(self.u))
        dJ_vol = - Constant(2*self.vfac)*(self.Vol-self.Vol0)
        dJ_bar = Constant(2*self.bfac)/self.Vol*((self.bx-x[0])*self.bx_off
                                                 + (self.by-x[1])*self.by_off)
        self.integrand = dJ_stokes + dJ_vol + dJ_bar
        dDeform = Measure("ds", subdomain_data=self.mf)
        from femorph import VolumeNormal
        n = VolumeNormal(mesh)
        s = TestFunction(self.S)
        dJ = 0
        # Sum up over all moving boundaries
        for marker in self.move_dict["Deform"]:
            dJ += inner(s,n)*self.integrand*dDeform(marker)
        self.dJ_form = dJ
Example #25
0
 def create_integration_subdomains(self):
     self._dx = Measure("dx")(subdomain_data=self._subdomains)
     self._ds = Measure("ds")(subdomain_data=self._boundaries)
Example #26
0
    def __init__(self):

        GMSH_EPS = 1.0e-15

        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, point_data, cell_data, _ = meshes.crucible_with_coils.generate(
        )

        # Convert the cell data to 'uint' so we can pick a size_t MeshFunction
        # below as usual.
        for k0 in cell_data:
            for k1 in cell_data[k0]:
                cell_data[k0][k1] = numpy.array(cell_data[k0][k1],
                                                dtype=numpy.dtype("uint"))

        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)
            self.subdomains = MeshFunction(
                "size_t", self.mesh,
                os.path.join(temp_dir, "test_gmsh:physical.xml"))

        self.subdomain_materials = {
            1: my_materials.porcelain,
            2: materials.argon,
            3: materials.gallium_arsenide_solid,
            4: materials.gallium_arsenide_liquid,
            27: materials.air,
        }

        # coils
        for k in range(5, 27):
            self.subdomain_materials[k] = my_materials.ek90

        # Define the subdomains which together form a single coil.
        self.coil_domains = [
            [5, 6, 7, 8, 9],
            [10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19],
            [20, 21, 22, 23],
            [24, 25, 26],
        ]

        self.wpi = 4

        self.submesh_workpiece = SubMesh(self.mesh, self.subdomains, self.wpi)

        # http://fenicsproject.org/qa/2026/submesh-workaround-for-parallel-computation
        # submesh_parallel_bug_fixed = False
        # if submesh_parallel_bug_fixed:
        #     submesh_workpiece = SubMesh(self.mesh, self.subdomains, self.wpi)
        # else:
        #     # To get the mesh in parallel, we need to read it in from a file.
        #     # Writing out can only happen in serial mode, though. :/
        #     base = os.path.join(current_path,
        #                         '../../meshes/2d/crucible-with-coils-submesh'
        #                         )
        #     filename = base + '.xml'
        #     if not os.path.isfile(filename):
        #         warnings.warn(
        #             'Submesh file \'{}\' does not exist. Creating... '.format(
        #             filename
        #             ))
        #         if MPI.size(mpi_comm_world()) > 1:
        #             raise RuntimeError(
        #                 'Can only write submesh in serial mode.'
        #                 )
        #         submesh_workpiece = \
        #             SubMesh(self.mesh, self.subdomains, self.wpi)
        #         output_stream = File(filename)
        #         output_stream << submesh_workpiece
        #     # Read the mesh
        #     submesh_workpiece = Mesh(filename)

        coords = self.submesh_workpiece.coordinates()
        ymin = min(coords[:, 1])
        ymax = max(coords[:, 1])

        # Find the top right point.
        k = numpy.argmax(numpy.sum(coords, 1))
        topright = coords[k, :]

        # Initialize mesh function for boundary domains
        class Left(SubDomain):
            def inside(self, x, on_boundary):
                # Explicitly exclude the lowest and the highest point of the
                # symmetry axis.
                # It is necessary for the consistency of the pressure-Poisson
                # system in the Navier-Stokes solver that the velocity is
                # exactly 0 at the boundary r>0. Hence, at the corner points
                # (r=0, melt-crucible, melt-crystal) we must enforce u=0
                # already and cannot have a component in z-direction.
                return (on_boundary and x[0] < GMSH_EPS
                        and x[1] < ymax - GMSH_EPS and x[1] > ymin + GMSH_EPS)

        class Crucible(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and (
                    (x[0] > GMSH_EPS and x[1] < ymax - GMSH_EPS) or
                    (x[0] > topright[0] - GMSH_EPS
                     and x[1] > topright[1] - GMSH_EPS) or
                    (x[0] < GMSH_EPS and x[1] < ymin + GMSH_EPS))

        # At the top right part (boundary melt--gas), slip is allowed, so only
        # n.u=0 is enforced. Very weirdly, the PPE is consistent if and only if
        # the end points of UpperRight are in UpperRight. This contrasts
        # Left(), where the end points must NOT belong to Left().  Judging from
        # the experiments, these settings do the right thing.
        # TODO try to better understand the PPE system/dolfin's boundary
        # settings
        class Upper(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[1] > ymax - GMSH_EPS

        class UpperRight(SubDomain):
            def inside(self, x, on_boundary):
                return (on_boundary and x[1] > ymax - GMSH_EPS
                        and x[0] > 0.038 - GMSH_EPS)

        # The crystal boundary is taken to reach up to 0.038 where the
        # Dirichlet boundary data is about the melting point of the crystal,
        # 1511K. This setting gives pretty acceptable results when there is no
        # convection except the one induced by buoyancy. Is there is any more
        # stirring going on, though, the end point of the crystal with its
        # fixed temperature of 1511K might be the hottest point globally. This
        # looks rather unphysical.
        # TODO check out alternatives
        class UpperLeft(SubDomain):
            def inside(self, x, on_boundary):
                return (on_boundary and x[1] > ymax - GMSH_EPS
                        and x[0] < 0.038 + GMSH_EPS)

        left = Left()
        crucible = Crucible()
        upper_left = UpperLeft()
        upper_right = UpperRight()

        self.wp_boundaries = MeshFunction(
            "size_t",
            self.submesh_workpiece,
            self.submesh_workpiece.topology().dim() - 1,
        )
        self.wp_boundaries.set_all(0)
        left.mark(self.wp_boundaries, 1)
        crucible.mark(self.wp_boundaries, 2)
        upper_right.mark(self.wp_boundaries, 3)
        upper_left.mark(self.wp_boundaries, 4)

        if DEBUG:
            from dolfin import plot, interactive

            plot(self.wp_boundaries, title="Boundaries")
            interactive()

        submesh_boundary_indices = {
            "left": 1,
            "crucible": 2,
            "upper right": 3,
            "upper left": 4,
        }

        # Boundary conditions for the velocity.
        #
        # [1] Incompressible flow and the finite element method; volume two;
        #     Isothermal Laminar Flow;
        #     P.M. Gresho, R.L. Sani;
        #
        # For the choice of function space, [1] says:
        #     "In 2D, the triangular elements P_2^+P_1 and P_2^+P_{-1} are very
        #      good [...]. [...] If you wish to avoid bubble functions on
        #      triangular elements, P_2P_1 is not bad, and P_2(P_1+P_0) is even
        #      better [...]."
        #
        # It turns out that adding the bubble space significantly hampers the
        # convergence of the Stokes solver and also considerably increases the
        # time it takes to construct the Jacobian matrix of the Navier--Stokes
        # problem if no optimization is applied.
        V_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(), 2)
        with_bubbles = False
        if with_bubbles:
            V_element += FiniteElement("B", self.submesh_workpiece.ufl_cell(),
                                       2)
        self.W_element = MixedElement(3 * [V_element])
        self.W = FunctionSpace(self.submesh_workpiece, self.W_element)

        rot0 = Expression(("0.0", "0.0", "-2*pi*x[0] * 5.0/60.0"), degree=1)
        # rot0 = (0.0, 0.0, 0.0)
        rot1 = Expression(("0.0", "0.0", "2*pi*x[0] * 5.0/60.0"), degree=1)
        self.u_bcs = [
            DirichletBC(self.W, rot0, crucible),
            DirichletBC(self.W.sub(0), 0.0, left),
            DirichletBC(self.W.sub(2), 0.0, left),
            # Make sure that u[2] is 0 at r=0.
            DirichletBC(self.W, rot1, upper_left),
            DirichletBC(self.W.sub(1), 0.0, upper_right),
        ]
        self.p_bcs = []

        self.P_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(),
                                       1)
        self.P = FunctionSpace(self.submesh_workpiece, self.P_element)

        self.Q_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(),
                                       2)
        self.Q = FunctionSpace(self.submesh_workpiece, self.Q_element)

        # Dirichlet.
        # This is a bit of a tough call since the boundary conditions need to
        # be read from a Tecplot file here.
        filename = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                "data/crucible-boundary.dat")
        data = tecplot_reader.read(filename)
        RZ = numpy.c_[data["ZONE T"]["node data"]["r"],
                      data["ZONE T"]["node data"]["z"]]
        T_vals = data["ZONE T"]["node data"]["temp. [K]"]

        class TecplotDirichletBC(Expression):
            def eval(self, value, x):
                # Find on which edge x sits, and raise exception if it doesn't.
                edge_found = False
                for edge in data["ZONE T"]["element data"]:
                    # Given a point X and an edge X0--X1,
                    #
                    #     (1 - theta) X0 + theta X1,
                    #
                    # the minimum distance is assumed for
                    #
                    #    argmin_theta ||(1-theta) X0  + theta X1 - X||^2
                    #    = <X1 - X0, X - X0> / ||X1 - X0||^2.
                    #
                    # If the distance is 0 and 0<=theta<=1, we found the edge.
                    #
                    # Note that edges are 1-based in Tecplot.
                    X0 = RZ[edge[0] - 1]
                    X1 = RZ[edge[1] - 1]
                    theta = numpy.dot(X1 - X0, x - X0) / numpy.dot(
                        X1 - X0, X1 - X0)
                    diff = (1.0 - theta) * X0 + theta * X1 - x
                    if (numpy.dot(diff, diff) < 1.0e-10 and 0.0 <= theta
                            and theta <= 1.0):
                        # Linear interpolation of the temperature value.
                        value[0] = (1.0 - theta) * T_vals[
                            edge[0] - 1] + theta * T_vals[edge[1] - 1]
                        edge_found = True
                        break
                # This class is supposed to be used for Dirichlet boundary
                # conditions. For some reason, FEniCS also evaluates
                # DirichletBC objects at coordinates which do not sit on the
                # boundary, see
                # <http://fenicsproject.org/qa/1033/dirichletbc-expressions-evaluated-away-from-the-boundary>.
                # The assigned values have no meaning though, so not assigning
                # values[0] here is okay.
                #
                # from matplotlib import pyplot as pp
                # pp.plot(x[0], x[1], 'xg')
                if not edge_found:
                    value[0] = 0.0
                    if False:
                        warnings.warn(
                            "Coordinate ({:e}, {:e}) doesn't sit on edge.".
                            format(x[0], x[1]))
                    # pp.plot(RZ[:, 0], RZ[:, 1], '.k')
                    # pp.plot(x[0], x[1], 'xr')
                    # pp.show()
                    # raise RuntimeError('Input coordinate '
                    #                    '{} is not on boundary.'.format(x))
                return

        tecplot_dbc = TecplotDirichletBC(degree=5)
        self.theta_bcs_d = [DirichletBC(self.Q, tecplot_dbc, upper_left)]
        self.theta_bcs_d_strict = [
            DirichletBC(self.Q, tecplot_dbc, upper_right),
            DirichletBC(self.Q, tecplot_dbc, crucible),
            DirichletBC(self.Q, tecplot_dbc, upper_left),
        ]

        # Neumann
        dTdr_vals = data["ZONE T"]["node data"]["dTempdx [K/m]"]
        dTdz_vals = data["ZONE T"]["node data"]["dTempdz [K/m]"]

        class TecplotNeumannBC(Expression):
            def eval(self, value, x):
                # Same problem as above: This expression is not only evaluated
                # at boundaries.
                for edge in data["ZONE T"]["element data"]:
                    X0 = RZ[edge[0] - 1]
                    X1 = RZ[edge[1] - 1]
                    theta = numpy.dot(X1 - X0, x - X0) / numpy.dot(
                        X1 - X0, X1 - X0)
                    dist = numpy.linalg.norm((1 - theta) * X0 + theta * X1 - x)
                    if dist < 1.0e-5 and 0.0 <= theta and theta <= 1.0:
                        value[0] = (1 - theta) * dTdr_vals[
                            edge[0] - 1] + theta * dTdr_vals[edge[1] - 1]
                        value[1] = (1 - theta) * dTdz_vals[
                            edge[0] - 1] + theta * dTdz_vals[edge[1] - 1]
                        break
                return

            def value_shape(self):
                return (2, )

        tecplot_nbc = TecplotNeumannBC(degree=5)
        n = FacetNormal(self.Q.mesh())
        self.theta_bcs_n = {
            submesh_boundary_indices["upper right"]: dot(n, tecplot_nbc),
            submesh_boundary_indices["crucible"]: dot(n, tecplot_nbc),
        }
        self.theta_bcs_r = {}

        # It seems that the boundary conditions from above are inconsistent in
        # that solving with Dirichlet overall and mixed Dirichlet-Neumann give
        # different results; the value *cannot* correspond to one solution.
        # From looking at the solutions, the pure Dirichlet setting appears
        # correct, so extract the Neumann values directly from that solution.

        # Pick fixed coefficients roughly at the temperature that we expect.
        # This could be made less magic by having the coefficients depend on
        # theta and solving the quasilinear equation.
        temp_estimate = 1550.0

        # Get material parameters
        wp_material = self.subdomain_materials[self.wpi]
        if isinstance(wp_material.specific_heat_capacity, float):
            cp = wp_material.specific_heat_capacity
        else:
            cp = wp_material.specific_heat_capacity(temp_estimate)
        if isinstance(wp_material.density, float):
            rho = wp_material.density
        else:
            rho = wp_material.density(temp_estimate)
        if isinstance(wp_material.thermal_conductivity, float):
            k = wp_material.thermal_conductivity
        else:
            k = wp_material.thermal_conductivity(temp_estimate)

        reference_problem = cyl_heat.Heat(
            self.Q,
            convection=None,
            kappa=k,
            rho=rho,
            cp=cp,
            source=Constant(0.0),
            dirichlet_bcs=self.theta_bcs_d_strict,
        )
        theta_reference = reference_problem.solve_stationary()
        theta_reference.rename("theta", "temperature (Dirichlet)")

        # Create equivalent boundary conditions from theta_ref. This
        # makes sure that the potentially expensive Expression evaluation in
        # theta_bcs_* is replaced by something reasonably cheap.
        self.theta_bcs_d = [
            DirichletBC(bc.function_space(), theta_reference,
                        bc.domain_args[0]) for bc in self.theta_bcs_d
        ]
        # Adapt Neumann conditions.
        n = FacetNormal(self.Q.mesh())
        self.theta_bcs_n = {
            k: dot(n, grad(theta_reference))
            # k: Constant(1000.0)
            for k in self.theta_bcs_n
        }

        if DEBUG:
            # Solve the heat equation with the mixed Dirichlet-Neumann
            # boundary conditions and compare it to the Dirichlet-only
            # solution.
            theta_new = Function(self.Q,
                                 name="temperature (Neumann + Dirichlet)")
            from dolfin import Measure

            ds_workpiece = Measure("ds", subdomain_data=self.wp_boundaries)

            heat = cyl_heat.Heat(
                self.Q,
                convection=None,
                kappa=k,
                rho=rho,
                cp=cp,
                source=Constant(0.0),
                dirichlet_bcs=self.theta_bcs_d,
                neumann_bcs=self.theta_bcs_n,
                robin_bcs=self.theta_bcs_r,
                my_ds=ds_workpiece,
            )
            theta_new = heat.solve_stationary()
            theta_new.rename("theta", "temperature (Neumann + Dirichlet)")

            from dolfin import plot, interactive, errornorm

            print("||theta_new - theta_ref|| = {:e}".format(
                errornorm(theta_new, theta_reference)))
            plot(theta_reference)
            plot(theta_new)
            plot(theta_reference - theta_new, title="theta_ref - theta_new")
            interactive()

        self.background_temp = 1400.0

        # self.omega = 2 * pi * 10.0e3
        self.omega = 2 * pi * 300.0

        return
Example #27
0
                    TestFunction, FunctionSpace)
import matplotlib.pyplot as plt
import subprocess, os
import numpy as np

ratios = []
exponents = [2, 3, 3.5, 4.0, 4.5, 5.0, 5.5]
for hein in exponents[-1:]:
    subprocess.call(
        ['gmsh -3 -clscale 0.075 -setnumber Hein %d tile_1_hein.geo' % hein],
        shell=True)

    outputs = convert('tile_1_hein.msh', 'tile_1_hein.h5')
    mesh, surfaces, volumes = outputs

    dx = Measure('dx', domain=mesh, subdomain_data=volumes)

    intra = assemble(1 * dx(1))
    extra = assemble(1 * dx(0))
    ratios.append(extra / (intra + extra))
    print('Extracellular volume %.2f' % ratios[-1])

    # Now want to get ratio of cell surface area to its volume
    # Want to keep track of port areas - these are boundary integrals
    ds = Measure('ds', domain=mesh, subdomain_data=surfaces)
    dS = Measure('dS', domain=mesh, subdomain_data=surfaces)

    area_no_port = assemble(1 * dS(1))
    area_port = assemble(1 * ds(1))

    volume = intra
k = 1

# Directory for output
outdir_base = './../../results/MovingMesh/'

mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), nx, ny)
n = FacetNormal(mesh)

outfile = File(mesh.mpi_comm(), outdir_base+"psi_h.pvd")

V = VectorFunctionSpace(mesh, 'DG', 2)
Vcg = VectorFunctionSpace(mesh, 'CG', 1)

boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1)
boundaries.set_all(0)
ds = Measure('ds', domain=mesh, subdomain_data=boundaries)

# Create function spaces
Q_E_Rho = FiniteElement("DG", mesh.ufl_cell(), k)
T_1 = FunctionSpace(mesh, 'DG', 0)
Qbar_E = FiniteElement("DGT", mesh.ufl_cell(), k)

Q_Rho = FunctionSpace(mesh, Q_E_Rho)
Qbar = FunctionSpace(mesh, Qbar_E)

phih, phih0 = Function(Q_Rho), Function(Q_Rho)
phibar = Function(Qbar)

# Advective velocity
# Swirling deformation advection (see LeVeque)
ux = 'pow(sin(pi*x[0]), 2) * sin(2*pi*x[1])'
Example #29
0
 def create_integration_subdomains(self):
     self._dx = Measure("dx")(subdomain_data=self._subdomains)
def transport_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 d_0, d_1, d_t,
                 vel_c, p_con, A_0, Temp, c_extrapolate):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet"  # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    C_cg = FiniteElement("CG", mesh.ufl_cell(), 1)
    C_dg = FiniteElement("DG", mesh.ufl_cell(), 0)
    mini = C_cg + C_dg
    C = FunctionSpace(mesh, mini)
    C = BlockFunctionSpace([C])
    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc / fc
    h_avg = (vc('+') + vc('-')) / (2 * avg(fc))

    penalty1 = Constant(1.0)

    tau = Function(PM)
    tau = tau_cal(tau, phi, -0.5)

    tuning_para = 0.25

    vel_norm = (dot(vel_c, n) + abs(dot(vel_c, n))) / 2.0

    cell_size = CellDiameter(mesh)
    vnorm = sqrt(dot(vel_c, vel_c))

    I = Identity(mesh.topology().dim())
    d_eff = Function(TM)
    d_eff = diff_coeff_cal_rev(d_eff, d_0, tau,
                               phi) + tuning_para * cell_size * vnorm * I

    monitor_dt = dt

    # Define variational problem
    dc, = BlockTrialFunction(C)
    dc_dot, = BlockTrialFunction(C)
    psic, = BlockTestFunction(C)
    block_c = BlockFunction(C)
    c, = block_split(block_c)
    block_c_dot = BlockFunction(C)
    c_dot, = block_split(block_c_dot)

    theta = -1.0

    a_time = phi * rho * inner(c_dot, psic) * dx

    a_dif = dot(rho*d_eff*grad(c),grad(psic))*dx \
        - dot(avg_w(rho*d_eff*grad(c),weight_e(rho*d_eff,n)), jump(psic, n))*dS \
        + theta*dot(avg_w(rho*d_eff*grad(psic),weight_e(rho*d_eff,n)), jump(c, n))*dS \
        + penalty1/h_avg*k_e(rho*d_eff,n)*dot(jump(c, n), jump(psic, n))*dS

    a_adv = -dot(rho*vel_c*c,grad(psic))*dx \
        + dot(jump(psic), rho('+')*vel_norm('+')*c('+') - rho('-')*vel_norm('-')*c('-') )*dS \
        + dot(psic, rho*vel_norm*c)*ds(3)

    R_c = R_c_cal(c_extrapolate, p_con, Temp)
    c_D1 = Constant(0.5)
    rhs_c = R_c * A_s_cal(phi, phi_0, A_0) * psic * dx - dot(
        rho * phi * vel_c, n) * c_D1 * psic * ds(1)

    r_u = [a_dif + a_adv]
    j_u = block_derivative(r_u, [c], [dc])

    r_u_dot = [a_time]
    j_u_dot = block_derivative(r_u_dot, [c_dot], [dc_dot])
    r = [r_u_dot[0] + r_u[0] - rhs_c]

    # this part is not applied.
    exact_solution_expression1 = Expression("1.0",
                                            t=0,
                                            element=C[0].ufl_element())

    def bc(t):
        p5 = DirichletBC(C.sub(0),
                         exact_solution_expression1,
                         boundaries,
                         1,
                         method="geometric")
        return BlockDirichletBC([p5])

    # Define problem wrapper
    class ProblemWrapper(object):
        def set_time(self, t):
            pass

        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            return r

        def jacobian_eval(self, t, solution, solution_dot,
                          solution_dot_coefficient):
            return [[
                Constant(solution_dot_coefficient) * j_u_dot[0, 0] + j_u[0, 0]
            ]]

        # Define boundary condition
        def bc_eval(self, t):
            pass

        # Define initial condition
        def ic_eval(self):
            return solution0

        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            pass

    problem_wrapper = ProblemWrapper()
    (solution, solution_dot) = (block_c, block_c_dot)
    solver = TimeStepping(problem_wrapper, solution, solution_dot)
    solver.set_parameters({
        "initial_time": t_start,
        "time_step_size": dt,
        "monitor": {
            "time_step_size": monitor_dt,
        },
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "report": True
    })
    export_solution = solver.solve()

    return export_solution, T