Ejemplo n.º 1
0
def SetupUnitMeshHelper(mesh, V=None, Vc=None):

    if V is None:
        V = df.FunctionSpace(mesh, 'CG', 1)
    if Vc is None:
        Vc = df.FunctionSpace(mesh, 'DG', 0)

    boundaries = dict()
    boundaries['left'] = df.CompiledSubDomain("near(x[0], 0.0) && on_boundary")
    boundaries['bottom'] = df.CompiledSubDomain(
        "near(x[1], 0.0) && on_boundary")
    boundaries['top'] = df.CompiledSubDomain("near(x[1], 1.0) && on_boundary")
    boundaries['right'] = df.CompiledSubDomain(
        "near(x[0], 1.0) && on_boundary")

    boundarymarkers = df.MeshFunction('size_t', mesh,
                                      mesh.topology().dim() - 1, 0)
    boundarymarkers.set_all(0)
    domainmarkers = df.MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

    boundaries['left'].mark(boundarymarkers, 1)
    boundaries['bottom'].mark(boundarymarkers, 2)
    boundaries['right'].mark(boundarymarkers, 3)
    boundaries['top'].mark(boundarymarkers, 4)

    ds = df.Measure('ds', domain=mesh, subdomain_data=boundarymarkers)
    dx = df.Measure('dx', domain=mesh, subdomain_data=domainmarkers)

    return boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc
Ejemplo n.º 2
0
def calTrueSol(para):
    nx, ny = para['mesh_N'][0], para['mesh_N'][1]
    mesh = fe.UnitSquareMesh(nx, ny)
    Vu = fe.FunctionSpace(mesh, 'P', para['P'])
    Vc = fe.FunctionSpace(mesh, 'P', para['P'])
    al = fe.Constant(para['alpha'])
    f = fe.Expression(para['f'], degree=5)
    q1 = fe.interpolate(fe.Expression(para['q1'], degree=5), Vc)
    q2 = fe.interpolate(fe.Expression(para['q2'], degree=5), Vc)
    q3 = fe.interpolate(fe.Expression(para['q3'], degree=5), Vc)
    theta = fe.interpolate(fe.Expression(para['q4'], degree=5), Vc)

    class BoundaryX0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 0.0)

    class BoundaryX1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 1.0)

    class BoundaryY0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 0.0)

    class BoundaryY1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 1.0)

    boundaries = fe.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(), BoundaryY1()
    bc0.mark(boundaries, 1)
    bc1.mark(boundaries, 2)
    bc2.mark(boundaries, 3)
    bc3.mark(boundaries, 4)

    domains = fe.MeshFunction("size_t", mesh, mesh.topology().dim())
    domains.set_all(0)

    bcD = fe.DirichletBC(Vu, theta, boundaries, 4)
    dx = fe.Measure('dx', domain=mesh, subdomain_data=domains)
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

    u_trial, u_test = fe.TrialFunction(Vu), fe.TestFunction(Vu)
    u = fe.Function(Vu)
    left = fe.inner(al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx
    right = f * u_test * dx + (q1 * u_test * ds(1) + q2 * u_test * ds(2) +
                               q3 * u_test * ds(3))

    left_m, right_m = fe.assemble_system(left, right, bcD)
    fe.solve(left_m, u.vector(), right_m)

    return u
Ejemplo n.º 3
0
 def get_measures(self):
     """
     Create the measurements from the generated subdomains and boundaries
     objects. The defined measurements are:
         - dx: Area measure.
         - ds: External boundaries measure.
         - dS: Internal boundaries measure.
     Returns
     -------
     None.
     """
     self.dx = fn.Measure('dx')(subdomain_data=self.subdomains)
     self.ds = fn.Measure('ds')(subdomain_data=self.boundaries)
     self.dS = fn.Measure('dS')(subdomain_data=self.boundaries)
Ejemplo n.º 4
0
 def set_boundaries(self):
     self.boundaries = fe.MeshFunction("size_t", self.mesh,
                                       self.mesh.topology().dim() - 1)
     self.boundaries.set_all(0)
     self.ds = fe.Measure("ds")(subdomain_data=self.boundaries)
     self.I = fe.Identity(self.mesh.topology().dim())
     self.normal = fe.FacetNormal(self.mesh)
Ejemplo n.º 5
0
    def readCellExpression(self,
                           group_value_dict,
                           value_type="scalar",
                           overlap=lambda x: x[0],
                           *args,
                           **kwargs):
        """
        Reads cell expression and returns it.
        """
        value_type_dictionary = {
            "scalar": ScalarCellExpressionFromXDMF,
            "vector2d": Vector2DCellExpressionFromXDMF,
            "vector3d": Vector3DCellExpressionFromXDMF
        }

        self.readMesh()
        xdmffile = fenics.XDMFFile(self.xdmffilename)
        cf = value_type_dictionary[value_type.lower()](group_value_dict,
                                                       overlap=overlap,
                                                       *args,
                                                       **kwargs)
        cf.init()
        for (key, value) in cf.group_value_dict.items():
            cf.markers[key] = fenics.MeshFunction("size_t", self.mesh,
                                                  self.mesh.topology().dim())
            xdmffile.read(cf.markers[key], key)
            cf.dx[key] = fenics.Measure("dx",
                                        domain=self.mesh,
                                        subdomain_data=cf.markers[key])
        xdmffile.close()
        return cf
Ejemplo n.º 6
0
    def _make_variational_problem(V):
        """
        Formulate the variational problem a(u, v) = L(v).

        Parameters
        ----------
        V: FEniCS.FunctionSpace

        Returns
        -------
        a, L: FEniCS.Expression
            Variational forms.
        """
        # Define trial and test functions
        u = F.TrialFunction(V)
        v = F.TestFunction(V)

        # Collect Neumann conditions
        ds = F.Measure("ds", domain=mesh, subdomain_data=boundary_markers)
        integrals_N = []
        for i in boundary_conditions:
            if isinstance(boundary_conditions[i], dict):
                if "Neumann" in boundary_conditions[i]:
                    if boundary_conditions[i]["Neumann"] != 0:
                        g = boundary_conditions[i]["Neumann"]
                        integrals_N.append(g[0] * v * ds(i))

        # Define variational problem
        a = F.inner(u, v) * F.dx + (DT**2) * (C**2) * F.inner(
            F.grad(u), F.grad(v)) * F.dx
        L = ((DT**2) * f[0] + 2 * u_nm1 -
             u_nm2) * v * F.dx + (DT**2) * (C**2) * sum(integrals_N)
        return a, L
Ejemplo n.º 7
0
    def get_measures(self):
        """
        Get measures of the domain given the required data.
        The defined measurements are:
            - dx: Area measure.
            - ds: External boundaries measure.
            - dS: Internal boundaries measure.
        Returns:

        """
        self.dx = fn.Measure('dx')(
            subdomain_data=self.subdomains)  # Area measure.
        self.ds = fn.Measure('ds')(
            subdomain_data=self.boundaries)  # External boundaries measures.
        self.dS = fn.Measure('dS')(
            subdomain_data=self.boundaries
        )  # Internal boundaries measures (interface boundary).
Ejemplo n.º 8
0
    def useSternLayerCellBC(self):
        """
        Interfaces at left hand side and right hand side, species-wise
        number conservation within interval."""
        self.boundary_conditions = []

        # Introduce a Lagrange multiplier per species anderson
        # rebuild discretization scheme (function spaces)
        self.constraints = 0
        self.K = self.M
        self.discretize()

        # Potential Dirichlet BC
        self.u0 = self.delta_u_scaled / 2.
        self.u1 = -self.delta_u_scaled / 2.

        boundary_markers = fn.MeshFunction('size_t', self.mesh,
                                           self.mesh.topology().dim() - 1)

        bx = [
            Boundary(x0=self.x0_scaled, tol=self.bctol),
            Boundary(x0=self.x1_scaled, tol=self.bctol)
        ]

        # Boundary.mark crashes the kernel if Boundary is internal class
        for i, b in enumerate(bx):
            b.mark(boundary_markers, i)

        boundary_conditions = {
            0: {
                'Robin': (1. / self.lambda_S_scaled, self.u0)
            },
            1: {
                'Robin': (1. / self.lambda_S_scaled, self.u1)
            },
        }

        ds = fn.Measure('ds',
                        domain=self.mesh,
                        subdomain_data=boundary_markers)

        integrals_R = []
        for i in boundary_conditions:
            if 'Robin' in boundary_conditions[i]:
                r, s = boundary_conditions[i]['Robin']
                integrals_R.append(r * (self.u - s) * self.v * ds(i))

        self.constraints += sum(integrals_R)

        # Number conservation constraints

        N0 = self.L_scaled * self.c_scaled  # total amount of species in cell
        for k in range(self.M):
            self.logger.info('{:>{lwidth}s} N0 = {:<8.4g}'.format(
                'Ion species {:02d} number conservation constraint'.format(k),
                N0[k],
                lwidth=self.label_width))
            self.applyNumberConservationConstraint(k, self.c_scaled[k])
Ejemplo n.º 9
0
    def eva(self):
        # construct solutions corresponding to the basis functions
        class BoundaryX0(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[0], 0.0)

        class BoundaryX1(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[0], 1.0)

        class BoundaryY0(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[1], 0.0)

        class BoundaryY1(fe.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and fe.near(x[1], 1.0)

        boundaries = fe.MeshFunction('size_t', self.mesh,
                                     self.mesh.topology().dim() - 1)
        boundaries.set_all(0)
        bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(
        ), BoundaryY1()
        bc0.mark(boundaries, 1)
        bc1.mark(boundaries, 2)
        bc2.mark(boundaries, 3)
        bc3.mark(boundaries, 4)

        domains = fe.MeshFunction("size_t", self.mesh,
                                  self.mesh.topology().dim())
        domains.set_all(0)

        dx = fe.Measure('dx', domain=self.mesh, subdomain_data=domains)
        ds = fe.Measure('ds', domain=self.mesh, subdomain_data=boundaries)

        u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu)
        left = fe.inner(fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx
        right = self.f * u_test * dx + (self.q1 * u_test * ds(1) +
                                        self.q2 * u_test * ds(2) +
                                        self.q3 * u_test * ds(3))
        bcD = fe.DirichletBC(self.Vu, self.theta, boundaries, 4)
        left_m, right_m = fe.assemble_system(left, right, bcD)
        fe.solve(left_m, self.u.vector(), right_m)
Ejemplo n.º 10
0
def BCsDefinition(Dimensions, Mesh, V, u_0, u_1, LoadCase, BCsType=False):

    # Define geometric spaces
    class LowerSide(fe.SubDomain):
        def inside(self, x, on_boundary):
            tol = 1E-14
            return on_boundary and fe.near(x[2], -Dimensions[2] / 2, tol)

    class UpperSide(fe.SubDomain):
        def inside(self, x, on_boundary):
            tol = 1E-14
            return on_boundary and fe.near(x[2], Dimensions[2] / 2, tol)

    # Define integration over subdpmains
    Domains_Facets = fe.MeshFunction('size_t', Mesh,
                                     Mesh.geometric_dimension() - 1)
    ds = fe.Measure('ds', domain=Mesh, subdomain_data=Domains_Facets)

    # Mark all domain facets with 0
    Domains_Facets.set_all(0)

    # Mark bottom facets with 1
    bottom = LowerSide()
    bottom.mark(Domains_Facets, 1)

    # Mark upper facets with 2
    upper = UpperSide()
    upper.mark(Domains_Facets, 2)

    # Apply boundary conditions
    if BCsType == 'Ideal':

        if LoadCase == 'SimpleShear':
            bcl = fe.DirichletBC(V, u_0, Domains_Facets, 1)
            bcu = fe.DirichletBC(V, u_1, Domains_Facets, 2)

        else:
            bcl = fe.DirichletBC(V.sub(2), u_0, Domains_Facets, 1)
            bcu = fe.DirichletBC(V.sub(2), u_1, Domains_Facets, 2)

    else:

        bcl = fe.DirichletBC(V, u_0, Domains_Facets, 1)
        bcu = fe.DirichletBC(V, u_1, Domains_Facets, 2)

    # Set of boundary conditions
    BoundaryConditions = [bcl, bcu]

    return [BoundaryConditions, ds]
Ejemplo n.º 11
0
def load_2d_muscle_geo(filename='../geo/muscle_2d.xml', L0=1e-2):

    mesh = fe.Mesh(filename)
    coords = mesh.coordinates()
    coords *= L0
    mesh.bounding_box_tree().build(mesh)

    # Define Boundaries
    bottom = fe.CompiledSubDomain("near(x[1], side, 0.01) && on_boundary", side=-20.0 * L0)
    top = fe.CompiledSubDomain("near(x[1], side, 0.01) && on_boundary", side=20.0 * L0)

    # Initialize mesh function for boundary domains
    boundaries = fe.MeshFunction('size_t', mesh, 2)
    boundaries.set_all(0)
    bottom.mark(boundaries, 1)
    top.mark(boundaries, 2)

    # Define new measures associated with the interior domains and
    # exterior boundaries

    dx = fe.Measure('dx', domain=mesh)
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

    return mesh, dx, ds, {"top": top, "bottom": bottom}
Ejemplo n.º 12
0
 def readFacetFunction(self, group_value_dict, *args, **kwargs):
     """
     Reads facet function and returns it.
     """
     self.readMesh()
     xdmffile = fenics.XDMFFile(self.xdmffilename)
     ff = FacetFunctionFromXDMF(group_value_dict, *args, **kwargs)
     ff.init()
     for (key, value) in ff.group_value_dict.items():
         ff.markers[key] = fenics.MeshFunction("size_t", self.mesh, self.mesh.topology().dim() - 1)
         xdmffile.read(ff.markers[key], key)
         ff.marked[key] = value.get("marked", 1)
         ff.ds[key] = fenics.Measure("ds", domain=self.mesh, subdomain_data=ff.markers[key])
         ff.bcs[key] = value
     xdmffile.close()
     return ff
Ejemplo n.º 13
0
 def run(self) -> None:
     mesh = self.mesh_creator.get_mesh()
     self.spaces.initialize(mesh=mesh)
     self.boundary_markers.mark_boundaries(mesh=mesh)
     bc = self.bc_creator.apply(
         vector_space=self.spaces.vector_space,
         boundary_markers=self.boundary_markers.value)
     ds = fenics.Measure('ds',
                         domain=mesh,
                         subdomain_data=self.boundary_markers.value)
     self.boundary_excitation.set_ds(ds=ds)
     self.fields.initialize(spaces=self.spaces)
     fem_solver = get_fem_solver(fem_solver=self.fem_solver_type,
                                 problem=self.problem,
                                 fields=self.fields,
                                 boundary_conditions=bc)
     self.time_step_builder.set(
         alpha_params=self.alpha_params,
         time_params=self.time_params,
         fem_solver=fem_solver,
         boundary_excitation=self.boundary_excitation,
         field_updates=self.field_updates,
         fields=self.fields,
         mesh=mesh,
         spaces=self.spaces)
     time_step = self.time_step_builder.build()
     mins = []
     maxs = []
     for (i, t) in enumerate(self.time_params.linear_time_space[1:]):
         # for i in range(3):
         print("Time: ", t)
         time_step.run(i)
         # v = fenics.elem_div(self.problem.constitutive_relation.get_new_value(self.fields.u_new), fenics.sym(fenics.grad(self.fields.u_new)))
         # x = fenics.project(v, self.spaces.tensor_space).vector()[:]
         # mins.append(min(x))
         # maxs.append(max(x))
         # # print('min: {}, max: {}, median, {}'.format(min(x), max(x), np.nanmedian(np.asarray(x))))
         # print(x)
         # print()
         # print(fenics.project(self.problem.constitutive_relation.get_new_value(self.fields.u_new), self.spaces.tensor_space).vector()[:])
         # print(fenics.project(fenics.sym(fenics.grad(self.fields.u_new)), self.spaces.tensor_space).vector()[:])
         if time_step.halt:
             break
     time_step.close()
     print('total: min: {}, max: {}'.format(min(mins), max(maxs)))
Ejemplo n.º 14
0
def wrapper2D(par, meshName, N_PN, boundaryFilePrefix, solutionFolder):
    #-------- load mesh --------
    mesh = fe.Mesh(meshName + '.xml')
    boundaryMarkers = fe.MeshFunction('size_t', mesh, meshName + '_facet_region.xml')
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaryMarkers)
    
    u = solvePN2nd(par, N_PN, mesh, boundaryFilePrefix, ds)
    #fe.plot(u[0])

    # first moment:     u0 = int_{4pi} I * b0 dOmega, b0 = sqrt(1 / 4 / pi)
    # radiative energy: phi = int_{4pi} I dOmega 
    radiativeEnergy = np.sqrt(4 * np.pi) * u[0].compute_vertex_values()
    createFolder(solutionFolder)
    sio.savemat('%sradiativeEnergy_P%d2nd_%s.mat'%(solutionFolder, N_PN, meshName.split('/')[-1]),
                    {'radiativeEnergy': radiativeEnergy, 'points': mesh.coordinates(),
                     'connectivityList': mesh.cells()})
    
    return u
Ejemplo n.º 15
0
 def readXDMFFile(self, xdmffilename, group_value_dict):
     xdmffile = fenics.XDMFFile(xdmffilename)
     self.group_value_dict = group_value_dict
     self.mesh = fenics.Mesh()
     xdmffile.read(self.mesh)
     self.markers = {}
     self.marked = {}
     self.ds = {}
     self.bcs = {}
     for (key, value) in self.group_value_dict.iteritems():
         # Fenics interface here: create facet function of type size_t (positive int) for every group
         # TODO: examine whether size_t is appropriate or this class could be generalized
         self.markers[key] = fenics.FacetFunction("size_t", self.mesh)
         xdmffile.read(self.markers[key], key)
         self.marked[key] = value.get("marked", 1)
         self.ds[key] = fenics.Measure("ds", domain=self.mesh, subdomain_data=self.markers[key])
         self.bcs[key] = value
     xdmffile.close()
Ejemplo n.º 16
0
	def avg_condition_number(mesh):
		"""Computes average mesh quality based on the condition number of the reference mapping.

		This quality criterion uses the condition number (in the Frobenius norm) of the
		(linear) mapping from the elements of the mesh to the reference element. Computes
		the average of the condition number over all elements.

		Parameters
		----------
		mesh : dolfin.cpp.mesh.Mesh
			The mesh, whose quality shall be computed.

		Returns
		-------
		float
			The average mesh quality based on the condition number.
		"""

		DG0 = fenics.FunctionSpace(mesh, 'DG', 0)
		jac = Jacobian(mesh)
		inv = JacobianInverse(mesh)

		options = [
				['ksp_type', 'preonly'],
				['pc_type', 'jacobi'],
				['pc_jacobi_type', 'diagonal'],
				['ksp_rtol', 1e-16],
				['ksp_atol', 1e-20],
				['ksp_max_it', 1000]
			]
		ksp = PETSc.KSP().create()
		_setup_petsc_options([ksp], [options])

		dx = fenics.Measure('dx', mesh)
		a = fenics.TrialFunction(DG0)*fenics.TestFunction(DG0)*dx
		L = fenics.sqrt(fenics.inner(jac, jac))*fenics.sqrt(fenics.inner(inv, inv))*fenics.TestFunction(DG0)*dx

		cond = fenics.Function(DG0)

		A, b = _assemble_petsc_system(a, L)
		_solve_linear_problem(ksp, A, b, cond.vector().vec(), options)
		cond.vector().apply('')

		return np.average(np.sqrt(mesh.geometric_dimension()) / cond.vector()[:])
Ejemplo n.º 17
0
def defineBoundaryMarkers1D(mesh, zMin, zMax):
    """For implementation details, see
    https://fenicsproject.org/olddocs/dolfin/1.3.0/python/demo/documented/subdomains-poisson/python/documentation.html
    https://fenicsproject.discourse.group/t/natural-boundary-conditions-without-facetfunction/228/3
    """
    
    boundaries = fe.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    class Left(fe.SubDomain):
        def inside(self, x, on_boundary):
            return fe.near(x[0], zMin)

    class Right(fe.SubDomain):
        def inside(self, x, on_boundary):
            return fe.near(x[0], zMax)
    
    left = Left()
    right = Right()
    left.mark(boundaries, 1)
    right.mark(boundaries, 2)
    ds = fe.Measure("ds", domain=mesh, subdomain_data=boundaries)
    
    return ds
Ejemplo n.º 18
0
        def readXDMFfile(self, xdmffilename, group_value_dict):
            """
            Initialization of CellExpressionXDMF by reading an XDMF file.

            @param: xdmffilename: path to xdmf file
            @param: group_value_dict: {"groupname":function(x)}

            function(x) is a function which is evaluated at the marked positions of the cells
            """
            xdmffile = fenics.XDMFFile(xdmffilename)
            self.group_value_dict = group_value_dict
            self.mesh = fenics.Mesh()
            xdmffile.read(self.mesh)
            self.markers = {}
            self.dx = {}
            for (key, value) in self.group_value_dict.iteritems():
                # Fenics interface here: create cell function of type int for every group
                # TODO: examine whether int is appropriate or this class could be generalized
                self.markers[key] = fenics.CellFunction("size_t", self.mesh)
                xdmffile.read(self.markers[key], key)
                self.dx[key] = fenics.Measure("dx", domain=self.mesh, subdomain_data=self.markers[key])
            xdmffile.close()
Ejemplo n.º 19
0
    def _build_function_space(self):
        class Exterior(fa.SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary

        self.exterior = Exterior()
        self.V = fa.FunctionSpace(self.mesh, 'P', 1)
        self.sub_domains = fa.MeshFunction("size_t", self.mesh,
                                           self.mesh.topology().dim() - 1)
        self.sub_domains.set_all(0)
        self.normal = fa.FacetNormal(self.mesh)
        self.ds = fa.Measure("ds")(subdomain_data=self.sub_domains)

        # self.source = fa.Expression(("cos(pi*x[0])*cos(pi*x[1])"),  degree=3)
        self.source = fa.Expression(("x[0]*x[0] + x[1]*x[1]"), degree=3)
        self.source = fa.interpolate(self.source, self.V)
        # self.source = fa.Constant(1.)

        self.bcs = []
        boundary_fn = fa.Constant(0.)
        boundary_bc = fa.DirichletBC(self.V, boundary_fn, self.exterior)
        self.bcs = self.bcs + [boundary_bc]
Ejemplo n.º 20
0
    def _assembly(V):
        """
        Assemble the matrices used in the linear system Au = b.
        Alternative representation of the variational form.
        Pre-calculate to speed up.
        """
        # Define trial and test functions
        u = F.TrialFunction(V)
        v = F.TestFunction(V)

        # Assemble
        a_M = F.inner(u, v) * F.dx
        a_K = F.inner(F.grad(u), F.grad(v)) * F.dx

        M = F.assemble(a_M)
        K = F.assemble(a_K)

        A = M + (dt**2) * (c**2) * K

        ds = F.Measure("ds", domain=mesh, subdomain_data=boundary_markers)
        M_ = F.assemble(u * v * ds(1))
        return M, K, A, M_
Ejemplo n.º 21
0
	def __init__(self, state_forms, bcs_list, cost_functional_form, states, controls, adjoints, config=None,
				 riesz_scalar_products=None, control_constraints=None, initial_guess=None, ksp_options=None,
				 adjoint_ksp_options=None, desired_weights=None):
		r"""This is used to generate all classes and functionalities. First ensures
		consistent input, afterwards, the solution algorithm is initialized.

		Parameters
		----------
		state_forms : ufl.form.Form or list[ufl.form.Form]
			The weak form of the state equation (user implemented). Can be either
			a single UFL form, or a (ordered) list of UFL forms.
		bcs_list : list[dolfin.fem.dirichletbc.DirichletBC] or list[list[dolfin.fem.dirichletbc.DirichletBC]] or dolfin.fem.dirichletbc.DirichletBC or None
			The list of DirichletBC objects describing Dirichlet (essential) boundary conditions.
			If this is ``None``, then no Dirichlet boundary conditions are imposed.
		cost_functional_form : ufl.form.Form or list[ufl.form.Form]
			UFL form of the cost functional.
		states : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The state variable(s), can either be a :py:class:`fenics.Function`, or a list of these.
		controls : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The control variable(s), can either be a :py:class:`fenics.Function`, or a list of these.
		adjoints : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The adjoint variable(s), can either be a :py:class:`fenics.Function`, or a (ordered) list of these.
		config : configparser.ConfigParser or None
			The config file for the problem, generated via :py:func:`cashocs.create_config`.
			Alternatively, this can also be ``None``, in which case the default configurations
			are used, except for the optimization algorithm. This has then to be specified
			in the :py:meth:`solve <cashocs.OptimalControlProblem.solve>` method. The
			default is ``None``.
		riesz_scalar_products : None or ufl.form.Form or list[ufl.form.Form], optional
			The scalar products of the control space. Can either be None, a single UFL form, or a
			(ordered) list of UFL forms. If ``None``, the :math:`L^2(\Omega)` product is used.
			(default is ``None``).
		control_constraints : None or list[dolfin.function.function.Function] or list[float] or list[list[dolfin.function.function.Function]] or list[list[float]], optional
			Box constraints posed on the control, ``None`` means that there are none (default is ``None``).
			The (inner) lists should contain two elements of the form ``[u_a, u_b]``, where ``u_a`` is the lower,
			and ``u_b`` the upper bound.
		initial_guess : list[dolfin.function.function.Function], optional
			List of functions that act as initial guess for the state variables, should be valid input for :py:func:`fenics.assign`.
			Defaults to ``None``, which means a zero initial guess.
		ksp_options : list[list[str]] or list[list[list[str]]] or None, optional
			A list of strings corresponding to command line options for PETSc,
			used to solve the state systems. If this is ``None``, then the direct solver
			mumps is used (default is ``None``).
		adjoint_ksp_options : list[list[str]] or list[list[list[str]]] or None
			A list of strings corresponding to command line options for PETSc,
			used to solve the adjoint systems. If this is ``None``, then the same options
			as for the state systems are used (default is ``None``).

		Examples
		--------
		Examples how to use this class can be found in the :ref:`tutorial <tutorial_index>`.
		"""

		OptimizationProblem.__init__(self, state_forms, bcs_list, cost_functional_form, states, adjoints, config, initial_guess, ksp_options, adjoint_ksp_options, desired_weights)
		### Overloading, such that we do not have to use lists for a single state and a single control
		### controls
		try:
			if type(controls) == list and len(controls) > 0:
				for i in range(len(controls)):
					if controls[i].__module__ == 'dolfin.function.function' and type(controls[i]).__name__ == 'Function':
						pass
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'controls have to be fenics Functions.')

				self.controls = controls

			elif controls.__module__ == 'dolfin.function.function' and type(controls).__name__ == 'Function':
				self.controls = [controls]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'Type of controls is wrong.')
		except:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'Type of controls is wrong.')

		self.control_dim = len(self.controls)

		### riesz_scalar_products
		if riesz_scalar_products is None:
			dx = fenics.Measure('dx', self.controls[0].function_space().mesh())
			self.riesz_scalar_products = [fenics.inner(fenics.TrialFunction(self.controls[i].function_space()), fenics.TestFunction(self.controls[i].function_space())) * dx
										  for i in range(len(self.controls))]
		else:
			try:
				if type(riesz_scalar_products)==list and len(riesz_scalar_products) > 0:
					for i in range(len(riesz_scalar_products)):
						if riesz_scalar_products[i].__module__== 'ufl.form' and type(riesz_scalar_products[i]).__name__== 'Form':
							pass
						else:
							raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')
					self.riesz_scalar_products = riesz_scalar_products
				elif riesz_scalar_products.__module__== 'ufl.form' and type(riesz_scalar_products).__name__== 'Form':
					self.riesz_scalar_products = [riesz_scalar_products]
				else:
					raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')
			except:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')

		### control_constraints
		if control_constraints is None:
			self.control_constraints = []
			for control in self.controls:
				u_a = fenics.Function(control.function_space())
				u_a.vector()[:] = float('-inf')
				u_b = fenics.Function(control.function_space())
				u_b.vector()[:] = float('inf')
				self.control_constraints.append([u_a, u_b])
		else:
			try:
				if type(control_constraints) == list and len(control_constraints) > 0:
					if type(control_constraints[0]) == list:
						for i in range(len(control_constraints)):
							if type(control_constraints[i]) == list and len(control_constraints[i]) == 2:
								for j in range(2):
									if type(control_constraints[i][j]) in [float, int]:
										pass
									elif control_constraints[i][j].__module__ == 'dolfin.function.function' and type(control_constraints[i][j]).__name__ == 'Function':
										pass
									else:
										raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')
								pass
							else:
								raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')
						self.control_constraints = control_constraints
					elif (type(control_constraints[0]) in [float, int] or (control_constraints[0].__module__ == 'dolfin.function.function' and type(control_constraints[0]).__name__=='Function')) \
						and (type(control_constraints[1]) in [float, int] or (control_constraints[1].__module__ == 'dolfin.function.function' and type(control_constraints[1]).__name__=='Function')):

						self.control_constraints = [control_constraints]
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')

			except:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')

		# recast floats into functions for compatibility
		temp_constraints = self.control_constraints[:]
		self.control_constraints = []
		for idx, pair in enumerate(temp_constraints):
			if type(pair[0]) in [float, int]:
				lower_bound = fenics.Function(self.controls[idx].function_space())
				lower_bound.vector()[:] = pair[0]
			elif pair[0].__module__ == 'dolfin.function.function' and type(pair[0]).__name__ == 'Function':
				lower_bound = pair[0]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Wrong type for the control constraints')

			if type(pair[1]) in [float, int]:
				upper_bound = fenics.Function(self.controls[idx].function_space())
				upper_bound.vector()[:] = pair[1]
			elif pair[1].__module__ == 'dolfin.function.function' and type(pair[1]).__name__ == 'Function':
				upper_bound = pair[1]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Wrong type for the control constraints')

			self.control_constraints.append([lower_bound, upper_bound])

		### Check whether the control constraints are feasible, and whether they are actually present
		self.require_control_constraints = [False for i in range(self.control_dim)]
		for idx, pair in enumerate(self.control_constraints):
			if not np.alltrue(pair[0].vector()[:] < pair[1].vector()[:]):
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
								 'The lower bound must always be smaller than the upper bound for the control_constraints.')

			if np.max(pair[0].vector()[:]) == float('-inf') and np.min(pair[1].vector()[:]) == float('inf'):
				# no control constraint for this component
				pass
			else:
				self.require_control_constraints[idx] = True
				
				control_element = self.controls[idx].ufl_element()
				if control_element.family() == 'Mixed':
					for j in range(control_element.value_size()):
						sub_elem = control_element.extract_component(j)[1]
						if sub_elem.family() == 'Real' or (sub_elem.family() == 'Lagrange' and sub_elem.degree() == 1) \
								or (sub_elem.family() == 'Discontinuous Lagrange' and sub_elem.degree() == 0):
							pass
						else:
							raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls',
									 'Control constraints are only implemented for linear Lagrange, constant Discontinuous Lagrange, and Real elements.')

				else:
					if control_element.family() == 'Real' or (control_element.family() == 'Lagrange' and control_element.degree() == 1) \
							or (control_element.family() == 'Discontinuous Lagrange' and control_element.degree() == 0):
						pass
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls',
									 'Control constraints are only implemented for linear Lagrange, constant Discontinuous Lagrange, and Real elements.')

		if not len(self.riesz_scalar_products) == self.control_dim:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'Length of controls does not match')
		if not len(self.control_constraints) == self.control_dim:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Length of controls does not match')
		### end overloading
		
		self.form_handler = ControlFormHandler(self.lagrangian, self.bcs_list, self.states, self.controls, self.adjoints, self.config,
											   self.riesz_scalar_products, self.control_constraints, self.ksp_options, self.adjoint_ksp_options,
											   self.require_control_constraints)

		self.state_spaces = self.form_handler.state_spaces
		self.control_spaces = self.form_handler.control_spaces
		self.adjoint_spaces = self.form_handler.adjoint_spaces

		self.projected_difference = [fenics.Function(V) for V in self.control_spaces]

		self.state_problem = StateProblem(self.form_handler, self.initial_guess)
		self.adjoint_problem = AdjointProblem(self.form_handler, self.state_problem)
		self.gradient_problem = GradientProblem(self.form_handler, self.state_problem, self.adjoint_problem)

		self.algorithm = _optimization_algorithm_configuration(self.config)

		self.reduced_cost_functional = ReducedCostFunctional(self.form_handler, self.state_problem)

		self.gradients = self.gradient_problem.gradients
		self.objective_value = 1.0
Ejemplo n.º 22
0
def strain(v):
    return fn.sym(fn.grad(v))


# boundary conditions
bdry = fn.MeshFunction("size_t", mesh, 1)

bdry.set_all(0)
FooT = fn.CompiledSubDomain(
    "(x[0] >= -0.2) && (x[0] <= 0.2) && near(x[1], 0.75) && on_boundary")
GammaU = fn.CompiledSubDomain(
    "( near(x[0], -0.5) || near(x[1], 0.0) ) && on_boundary")
GammaU.mark(bdry, 31)
FooT.mark(bdry, 32)
ds = fn.Measure("ds", subdomain_data=bdry)

bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31)
bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32)
bcs = [bcU, bcP]

# ********  Weak forms ********** #

PLeft =  2*mu*fn.inner(strain(u),strain(v)) * fn.dx \
         - fn.div(v) * phi * fn.dx \
         + (c0/alpha + 1.0/lmbda)* p * q * fn.dx \
         + kappa/(alpha*nu) * fn.dot(fn.grad(p),fn.grad(q)) * fn.dx \
         - 1.0/lmbda * phi * q * fn.dx \
         - fn.div(u) * psi * fn.dx \
         + 1.0/lmbda * psi * p * fn.dx \
         - 1.0/lmbda * phi * psi * fn.dx
Ejemplo n.º 23
0
    def __init__(self, lagrangian, bcs_list, states, adjoints, config,
                 ksp_options, adjoint_ksp_options):
        """Initializes the form handler.

		Parameters
		----------
		lagrangian : cashocs._forms.Lagrangian
			The lagrangian of the optimization problem.
		bcs_list : list[list[dolfin.fem.dirichletbc.DirichletBC]]
			The list of DirichletBCs for the state equation.
		states : list[dolfin.function.function.Function]
			The function that acts as the state variable.
		adjoints : list[dolfin.function.function.Function]
			The function that acts as the adjoint variable.
		config : configparser.ConfigParser
			The configparser object of the config file.
		ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			state systems.
		adjoint_ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			adjoint systems.
		"""

        # Initialize the attributes from the arguments
        self.lagrangian = lagrangian
        self.bcs_list = bcs_list
        self.states = states
        self.adjoints = adjoints
        self.config = config
        self.state_ksp_options = ksp_options
        self.adjoint_ksp_options = adjoint_ksp_options

        # Further initializations
        self.cost_functional_form = self.lagrangian.cost_functional_form
        self.state_forms = self.lagrangian.state_forms

        self.state_dim = len(self.states)

        self.state_spaces = [x.function_space() for x in self.states]
        self.adjoint_spaces = [x.function_space() for x in self.adjoints]

        # Test if state_spaces coincide with adjoint_spaces
        if self.state_spaces == self.adjoint_spaces:
            self.state_adjoint_equal_spaces = True
        else:
            self.state_adjoint_equal_spaces = False

        self.mesh = self.state_spaces[0].mesh()
        self.dx = fenics.Measure('dx', self.mesh)

        self.trial_functions_state = [
            fenics.TrialFunction(V) for V in self.state_spaces
        ]
        self.test_functions_state = [
            fenics.TestFunction(V) for V in self.state_spaces
        ]

        self.trial_functions_adjoint = [
            fenics.TrialFunction(V) for V in self.adjoint_spaces
        ]
        self.test_functions_adjoint = [
            fenics.TestFunction(V) for V in self.adjoint_spaces
        ]

        self.state_is_linear = self.config.getboolean('StateSystem',
                                                      'is_linear',
                                                      fallback=False)
        self.state_is_picard = self.config.getboolean('StateSystem',
                                                      'picard_iteration',
                                                      fallback=False)
        self.opt_algo = _optimization_algorithm_configuration(config)

        if self.opt_algo == 'pdas':
            self.inner_pdas = self.config.get('AlgoPDAS', 'inner_pdas')

        self.__compute_state_equations()
        self.__compute_adjoint_equations()
Ejemplo n.º 24
0
    def __init__(self, form_handler):
        """Initializes the regularization

		Parameters
		----------
		form_handler : cashocs._forms.ShapeFormHandler
			the corresponding shape form handler object
		"""

        self.form_handler = form_handler
        self.config = self.form_handler.config

        self.dx = fenics.Measure('dx', self.form_handler.mesh)
        self.ds = fenics.Measure('ds', self.form_handler.mesh)

        self.spatial_coordinate = fenics.SpatialCoordinate(
            self.form_handler.mesh)

        self.measure_hole = self.config.getboolean('Regularization',
                                                   'measure_hole',
                                                   fallback=False)
        if self.measure_hole:
            self.x_start = self.config.getfloat('Regularization',
                                                'x_start',
                                                fallback=0.0)
            self.x_end = self.config.getfloat('Regularization',
                                              'x_end',
                                              fallback=1.0)
            if not self.x_end >= self.x_start:
                raise ConfigError('Regularization', 'x_end',
                                  'x_end must not be smaller than x_start.')
            self.delta_x = self.x_end - self.x_start

            self.y_start = self.config.getfloat('Regularization',
                                                'y_start',
                                                fallback=0.0)
            self.y_end = self.config.getfloat('Regularization',
                                              'y_end',
                                              fallback=1.0)
            if not self.y_end >= self.y_start:
                raise ConfigError('Regularization', 'y_end',
                                  'y_end must not be smaller than y_start.')
            self.delta_y = self.y_end - self.y_start

            self.z_start = self.config.getfloat('Regularization',
                                                'z_start',
                                                fallback=0.0)
            self.z_end = self.config.getfloat('Regularization',
                                              'z_end',
                                              fallback=1.0)
            if not self.z_end >= self.z_start:
                raise ConfigError('Regularization', 'z_end',
                                  'z_end must not be smaller than z_start.')
            self.delta_z = self.z_end - self.z_start
            if self.form_handler.mesh.geometric_dimension() == 2:
                self.delta_z = 1.0

        self.mu_volume = self.config.getfloat('Regularization',
                                              'factor_volume',
                                              fallback=0.0)
        self.target_volume = self.config.getfloat('Regularization',
                                                  'target_volume',
                                                  fallback=0.0)
        if self.config.getboolean('Regularization',
                                  'use_initial_volume',
                                  fallback=False):
            if not self.measure_hole:
                self.target_volume = fenics.assemble(Constant(1) * self.dx)
            else:
                self.target_volume = self.delta_x * self.delta_y * self.delta_z - fenics.assemble(
                    Constant(1.0) * self.dx)

        self.mu_surface = self.config.getfloat('Regularization',
                                               'factor_surface',
                                               fallback=0.0)
        self.target_surface = self.config.getfloat('Regularization',
                                                   'target_surface',
                                                   fallback=0.0)
        if self.config.getboolean('Regularization',
                                  'use_initial_surface',
                                  fallback=False):
            self.target_surface = fenics.assemble(Constant(1) * self.ds)

        self.mu_barycenter = self.config.getfloat('Regularization',
                                                  'factor_barycenter',
                                                  fallback=0.0)
        self.target_barycenter_list = json.loads(
            self.config.get('Regularization',
                            'target_barycenter',
                            fallback='[0,0,0]'))

        if not type(self.target_barycenter_list) == list:
            raise ConfigError('Regularization', 'target_barycenter',
                              'This has to be a list.')

        if self.form_handler.mesh.geometric_dimension() == 2 and len(
                self.target_barycenter_list) == 2:
            self.target_barycenter_list.append(0.0)

        if self.config.getboolean('Regularization',
                                  'use_initial_barycenter',
                                  fallback=False):
            self.target_barycenter_list = [0.0, 0.0, 0.0]
            if not self.measure_hole:
                volume = fenics.assemble(Constant(1) * self.dx)
                self.target_barycenter_list[0] = fenics.assemble(
                    self.spatial_coordinate[0] * self.dx) / volume
                self.target_barycenter_list[1] = fenics.assemble(
                    self.spatial_coordinate[1] * self.dx) / volume
                if self.form_handler.mesh.geometric_dimension() == 3:
                    self.target_barycenter_list[2] = fenics.assemble(
                        self.spatial_coordinate[2] * self.dx) / volume
                else:
                    self.target_barycenter_list[2] = 0.0

            else:
                volume = self.delta_x * self.delta_y * self.delta_z - fenics.assemble(
                    Constant(1) * self.dx)
                self.target_barycenter_list[0] = (
                    0.5 * (pow(self.x_end, 2) - pow(self.x_start, 2)) *
                    self.delta_y * self.delta_z - fenics.assemble(
                        self.spatial_coordinate[0] * self.dx)) / volume
                self.target_barycenter_list[1] = (
                    0.5 * (pow(self.y_end, 2) - pow(self.y_start, 2)) *
                    self.delta_x * self.delta_z - fenics.assemble(
                        self.spatial_coordinate[1] * self.dx)) / volume
                if self.form_handler.mesh.geometric_dimension() == 3:
                    self.target_barycenter_list[2] = (
                        0.5 * (pow(self.z_end, 2) - pow(self.z_start, 2)) *
                        self.delta_x * self.delta_y - fenics.assemble(
                            self.spatial_coordinate[2] * self.dx)) / volume
                else:
                    self.target_barycenter_list[2] = 0.0

        if not (self.mu_volume >= 0.0 and self.mu_surface >= 0.0
                and self.mu_barycenter >= 0.0):
            raise ConfigError(
                'Regularization', 'mu_volume, mu_surface, or mu_barycenter',
                'All regularization constants have to be nonnegative.')

        if self.mu_volume > 0.0 or self.mu_surface > 0.0 or self.mu_barycenter > 0.0:
            self.has_regularization = True
        else:
            self.has_regularization = False

        # self.relative_scaling = self.config.getboolean('Regularization', 'relative_scaling')
        # if self.relative_scaling and self.has_regularization:
        # 	self.scale_weights()

        self.current_volume = fenics.Expression('val', degree=0, val=1.0)
        self.current_surface = fenics.Expression('val', degree=0, val=1.0)
        self.current_barycenter_x = fenics.Expression('val', degree=0, val=0.0)
        self.current_barycenter_y = fenics.Expression('val', degree=0, val=0.0)
        self.current_barycenter_z = fenics.Expression('val', degree=0, val=0.0)
Ejemplo n.º 25
0
def regular_box_mesh(n=10,
                     S_x=0.0,
                     S_y=0.0,
                     S_z=None,
                     E_x=1.0,
                     E_y=1.0,
                     E_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, with specified start (``S_``) and end points (``E_``).
	The resulting mesh uses ``n`` elements along the shortest direction
	and accordingly many along the longer ones. The resulting domain is

	.. math::
		\begin{alignedat}{2}
			&[S_x, E_x] \times [S_y, E_y] \quad &&\text{ in } 2D, \\
			&[S_x, E_x] \times [S_y, E_y] \times [S_z, E_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=S_x`.

	  - 2 corresponds to :math:`x=E_x`.

	  - 3 corresponds to :math:`y=S_y`.

	  - 4 corresponds to :math:`y=E_y`.

	  - 5 corresponds to :math:`z=S_z` (only in 3D).

	  - 6 corresponds to :math:`z=E_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	S_x : float
		Start of the x-interval.
	S_y : float
		Start of the y-interval.
	S_z : float or None, optional
		Start of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).
	E_x : float
		End of the x-interval.
	E_y : float
		End of the y-interval.
	E_z : float or None, optional
		End of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""

    n = int(n)

    if not n > 0:
        raise InputError('cashocs.geometry.regular_box_mesh', 'n',
                         'This needs to be positive.')

    if not S_x < E_x:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_x',
            'Incorrect input for the x-coordinate. S_x has to be smaller than E_x.'
        )
    if not S_y < E_y:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_y',
            'Incorrect input for the y-coordinate. S_y has to be smaller than E_y.'
        )
    if not ((S_z is None and E_z is None) or (S_z < E_z)):
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_z',
            'Incorrect input for the z-coordinate. S_z has to be smaller than E_z, or only one of them is specified.'
        )

    if S_z is None:
        lx = E_x - S_x
        ly = E_y - S_y
        sizes = [lx, ly]
        dim = 2
    else:
        lx = E_x - S_x
        ly = E_y - S_y
        lz = E_z - S_z
        sizes = [lx, ly, lz]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if S_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(S_x, S_y),
                                    fenics.Point(E_x, E_y), num_points[0],
                                    num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(S_x, S_y, S_z),
                              fenics.Point(E_x, E_y, E_z), num_points[0],
                              num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], sx, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sx=S_x)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], ex, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ex=E_x)
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], sy, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sy=S_y)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], ey, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ey=E_y)
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if S_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], sz, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         sz=S_z)
        z_max = fenics.CompiledSubDomain('on_boundary && near(x[2], ez, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         ez=E_z)
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

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

    return mesh, subdomains, boundaries, dx, ds, dS
Ejemplo n.º 26
0
############################### IMPORT MESH ##################################
#cprint("\nMESH PRE-PROCESSING", 'blue', attrs=['bold'])
# Import mesh and groups
#cprint("Creating gmsh mesh...", 'green')
subprocess.check_output("gmsh ./gmsh/beam.geo -3", shell=True)
#cprint("Converting mesh to DOLFIN format...", 'green')
subprocess.check_output('dolfin-convert ./gmsh/beam.msh mesh/beam.xml',
                        shell=True)
#cprint("Importing mesh in FEniCS...", 'green')
mesh = fe.Mesh('mesh/beam.xml')
#cprint("Generating boundaries and subdomains...", 'green')
subdomains = fe.MeshFunction("size_t", mesh, "mesh/beam_physical_region.xml")
boundaries = fe.MeshFunction("size_t", mesh, "mesh/beam_facet_region.xml")

# Redefine the integration measures
dxp = fe.Measure('dx', domain=mesh, subdomain_data=subdomains)
dsp = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

##################### FINITE ELEMENT SPACES ##################################
# Finite element spaces
W = fe.FunctionSpace(mesh, 'P', 1)
V = fe.VectorFunctionSpace(mesh, 'P', 1)
Z = fe.TensorFunctionSpace(mesh, 'P', 1)

# Finite element functions
du = fe.TrialFunction(V)
v = fe.TestFunction(V)
u = fe.Function(V)

######################### PROBLEM PARAMS ######################################
# Material properties
Ejemplo n.º 27
0
def regular_mesh(n=10, L_x=1.0, L_y=1.0, L_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, starting at the origin and having length specified
	in ``L_x``, ``L_y``, and ``L_z``. The resulting mesh uses ``n`` elements along the
	shortest direction and accordingly many along the longer ones.
	The resulting domain is

	.. math::
		\begin{alignedat}{2}
		&[0, L_x] \times [0, L_y] \quad &&\text{ in } 2D, \\
		&[0, L_x] \times [0, L_y] \times [0, L_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=0`.

	  - 2 corresponds to :math:`x=L_x`.

	  - 3 corresponds to :math:`y=0`.

	  - 4 corresponds to :math:`y=L_y`.

	  - 5 corresponds to :math:`z=0` (only in 3D).

	  - 6 corresponds to :math:`z=L_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	L_x : float
		Length in x-direction.
	L_y : float
		Length in y-direction.
	L_z : float or None, optional
		Length in z-direction, if this is ``None``, then the geometry
		will be two-dimensional (default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A :py:class:`fenics.MeshFunction` object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""
    if not n > 0:
        raise InputError('cashocs.geometry.regular_mesh', 'n',
                         'This needs to be positive.')
    if not L_x > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_x',
                         'L_x needs to be positive')
    if not L_y > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_y',
                         'L_y needs to be positive')
    if not (L_z is None or L_z > 0.0):
        raise InputError('cashocs.geometry.regular_mesh', 'L_z',
                         'L_z needs to be positive or None (for 2D mesh)')

    n = int(n)

    if L_z is None:
        sizes = [L_x, L_y]
        dim = 2
    else:
        sizes = [L_x, L_y, L_z]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if L_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(0, 0), fenics.Point(sizes),
                                    num_points[0], num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(0, 0, 0), fenics.Point(sizes),
                              num_points[0], num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[0])
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[1])
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if L_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], 0, tol)',
                                         tol=fenics.DOLFIN_EPS)
        z_max = fenics.CompiledSubDomain(
            'on_boundary && near(x[2], length, tol)',
            tol=fenics.DOLFIN_EPS,
            length=sizes[2])
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

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

    return mesh, subdomains, boundaries, dx, ds, dS
    def compute_static_deformation(self):

        assert self.mesh is not None

        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, 3)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, 2)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        # define function spaces
        V = fe.VectorFunctionSpace(self.mesh, "Lagrange", 1)
        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        d = self.mesh.geometry().dim()

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, d)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, d - 1)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        c_zero = fe.Constant((0, 0, 0))

        # define boundary conditions
        bc_bottom = fe.DirichletBC(V, c_zero, bottom)
        bc_top = fe.DirichletBC(V, c_zero, top)

        bcs = [bc_bottom]  # , bc_top]

        # define functions
        du = TrialFunction(V)
        v = TestFunction(V)
        u = Function(V)
        B = fe.Constant((0., 2.0, 0.))
        T = fe.Constant((0.0, 0.0, 0.0))

        d = u.geometric_dimension()
        I = fe.Identity(d)
        F = I + grad(u)
        C = F.T * F

        I_1 = tr(C)
        J = det(F)

        E, mu = 10., 0.3
        mu, lmbda = fe.Constant(E / (2 * (1 + mu))), fe.Constant(
            E * mu / ((1 + mu) * (1 - 2 * mu)))

        # stored energy (comp. neo-hookean model)
        psi = (mu / 2.) * (I_1 - 3) - mu * fe.ln(J) + (lmbda /
                                                       2.) * (fe.ln(J))**2

        dx = self.dx
        ds = self.ds

        Pi = psi * fe.dx - dot(B, u) * fe.dx - dot(T, u) * fe.ds

        F = fe.derivative(Pi, u, v)
        J = fe.derivative(F, u, du)

        fe.solve(F == 0, u, bcs, J=J)

        # save results
        self.u = u

        # write to disk
        output = fe.File("/tmp/static.pvd")
        output << u
Ejemplo n.º 29
0
def import_mesh(arg):
    """Imports a mesh file for use with CASHOCS / FEniCS.



	This function imports a mesh file that was generated by GMSH and converted to
	.xdmf with the command line function :ref:`cashocs-convert <cashocs_convert>`.
	If there are Physical quantities specified in the GMSH file, these are imported
	to the subdomains and boundaries output of this function and can also be directly
	accessed via the measures, e.g., with ``dx(1)``, ``ds(1)``, etc.

	Parameters
	----------
	arg : str or configparser.ConfigParser
		This is either a string, in which case it corresponds to the location
		of the mesh file in .xdmf file format, or a config file that
		has this path stored in its settings, under the section Mesh, as
		parameter ``mesh_file``.

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The imported (computational) mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A :py:class:`fenics.MeshFunction` object containing the subdomains,
		i.e., the Physical regions marked in the GMSH
		file.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries,
		i.e., the Physical regions marked in the GMSH
		file. Can, e.g., be used to set up boundary
		conditions.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to
		the subdomains (i.e. GMSH Physical region indices).
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to
		the boundaries (i.e. GMSH Physical region indices).
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding
		to boundaries (i.e. GMSH Physical region indices).
	"""

    start_time = time.time()
    print('Importing mesh to FEniCS')
    # Check for the file format

    if type(arg) == str:
        mesh_file = arg
        mesh_attribute = 'str'
    elif type(arg) == configparser.ConfigParser:
        mesh_attribute = 'config'
        ### overloading for remeshing
        if not arg.getboolean('Mesh', 'remesh', fallback=False):
            mesh_file = arg.get('Mesh', 'mesh_file')
        else:
            if not ('_cashocs_remesh_flag' in sys.argv):
                mesh_file = arg.get('Mesh', 'mesh_file')
            else:
                temp_dir = sys.argv[-1]
                with open(temp_dir + '/temp_dict.json', 'r') as file:
                    temp_dict = json.load(file)
                mesh_file = temp_dict['mesh_file']

    else:
        raise InputError(
            'cashocs.geometry.import_mesh', 'arg',
            'Not a valid argument for import_mesh. Has to be either a path to a mesh file (str) or a config.'
        )

    if mesh_file[-5:] == '.xdmf':
        file_string = mesh_file[:-5]
    else:
        raise InputError(
            'cashocs.geometry.import_mesh', 'arg',
            'Not a suitable mesh file format. Has to end in .xdmf.')

    mesh = fenics.Mesh()
    xdmf_file = fenics.XDMFFile(mesh.mpi_comm(), mesh_file)
    xdmf_file.read(mesh)
    xdmf_file.close()

    subdomains_mvc = fenics.MeshValueCollection('size_t', mesh,
                                                mesh.geometric_dimension())
    boundaries_mvc = fenics.MeshValueCollection('size_t', mesh,
                                                mesh.geometric_dimension() - 1)

    if os.path.isfile(file_string + '_subdomains.xdmf'):
        xdmf_subdomains = fenics.XDMFFile(mesh.mpi_comm(),
                                          file_string + '_subdomains.xdmf')
        xdmf_subdomains.read(subdomains_mvc, 'subdomains')
        xdmf_subdomains.close()
    if os.path.isfile(file_string + '_boundaries.xdmf'):
        xdmf_boundaries = fenics.XDMFFile(mesh.mpi_comm(),
                                          file_string + '_boundaries.xdmf')
        xdmf_boundaries.read(boundaries_mvc, 'boundaries')
        xdmf_boundaries.close()

    subdomains = fenics.MeshFunction('size_t', mesh, subdomains_mvc)
    boundaries = fenics.MeshFunction('size_t', mesh, boundaries_mvc)

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

    end_time = time.time()
    print('Done Importing Mesh. Elapsed Time: ' +
          format(end_time - start_time, '.3e') + ' s')
    print('')

    # Add an attribute to the mesh to show with what procedure it was generated
    mesh._cashocs_generator = mesh_attribute

    return mesh, subdomains, boundaries, dx, ds, dS
Ejemplo n.º 30
0
# section of boundary that is free
free_boundary = fn.CompiledSubDomain(
        "(near(x[1], mesh_height) || near(x[0], mesh_width/2)) && on_boundary",
        mesh_height=mesh_height, mesh_width=mesh_width)

# section of boundary that is a rigid wall
wall_boundary = fn.CompiledSubDomain(
        "(near(x[1], 0.0) || near(x[0], -mesh_width/2)) && on_boundary",
        mesh_width=mesh_width)

# mark boundaries
free_boundary.mark(mesh_boundary, 31)
wall_boundary.mark(mesh_boundary, 32)

# ds, for integrating
ds = fn.Measure("ds", subdomain_data=mesh_boundary)

# boundary conditions
bcU  = fn.DirichletBC(Hh.sub(0), u_g, mesh_boundary, 32)
bcP  = fn.DirichletBC(Hh.sub(2), p_g, mesh_boundary, 31)
boundary_conditions = [bcU, bcP]

# initial conditions - poroelasticity
u_old   = fn.interpolate(fn.Constant((0.0, 0.0)), Vhf)
phi_old = fn.interpolate(fn.Constant(0.0), Zhf)
p_old   = fn.interpolate(fn.Constant(0.0), Qhf)

# initial conditions - reaction-diffusion
E_old = fn.interpolate(fn.Constant(0.0),Mhf)
n_old = fn.interpolate(fn.Constant(0.0),Mhf)