示例#1
0
def construct_sleeve_geometry(
    t_wall=None,
    t_gap=None,
    t_sleeve=None,
    L_wall=None,
    L_sleeve=None,
    refinement_parameter=16,
):
    #
    # Define the domain as a polygon
    mesh = Mesh()
    domain = Polygon([
        dolfin.Point(0.0, 0.0),
        dolfin.Point(L_wall, 0.0),
        dolfin.Point(L_wall, t_wall),
        dolfin.Point((L_wall - L_sleeve), t_wall),
        dolfin.Point((L_wall - L_sleeve), (t_wall + t_gap)),
        dolfin.Point(L_wall, (t_wall + t_gap)),
        dolfin.Point(L_wall, (t_sleeve + t_wall + t_gap)),
        dolfin.Point((L_wall - L_sleeve), (t_sleeve + t_wall + t_gap)),
        dolfin.Point((L_wall - L_sleeve - t_sleeve - t_gap), t_wall),
        dolfin.Point(0.0, t_wall),
    ], )
    #
    # Define weld region
    weld_subdomain = Polygon([
        dolfin.Point((L_wall - L_sleeve - t_sleeve - t_gap), t_wall),
        dolfin.Point((L_wall - L_sleeve), t_wall),
        dolfin.Point((L_wall - L_sleeve), (t_wall + t_sleeve + t_gap)),
    ])
    domain.set_subdomain(1, weld_subdomain)
    #
    # Mesh
    mesh = generate_mesh(domain, refinement_parameter)
    #
    # Refine in the weld
    cell_markers = CellFunction("bool", mesh)
    cell_markers.set_all(False)
    c = is_in_weld_region(
        t_wall=t_wall,
        t_gap=t_gap,
        t_sleeve=t_sleeve,
        L_wall=L_wall,
        L_sleeve=L_sleeve,
    )

    class MyDomain(SubDomain):
        def inside(self, x, on_boundary):
            return c(x)

    my_domain = MyDomain()
    my_domain.mark(cell_markers, True)
    mesh = refine(mesh, cell_markers)

    #
    # Define the upper and lower boundaries
    class Upper(SubDomain):
        def inside(self, x, on_boundary):
            #
            # Define relevant points
            xb1 = (L_wall - L_sleeve - t_sleeve - t_gap)
            xb2 = (L_wall - L_sleeve)
            yb1 = t_wall
            yb2 = (t_wall + t_sleeve + t_gap)
            #
            # Define params for assessing if on a line between points
            dx_line = xb2 - xb1
            dy_line = yb2 - yb1
            dx = x[0] - xb1
            dy = x[1] - yb1
            zero = dx * dy_line - dx_line * dy
            #
            is_upper_region_one = x[0] <= xb1 and near(x[1], yb1)
            is_upper_region_two = x[0] >= xb1 and x[0] <= xb2 and near(zero, 0)
            is_upper_region_three = x[0] >= xb2 and near(x[1], yb2)
            #
            return is_upper_region_one or is_upper_region_two or is_upper_region_three

    class Lower(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0)

    #
    # Set boundaries
    upper = Upper()
    lower = Lower()
    boundaries = FacetFunction("size_t", mesh)
    boundaries.set_all(0)
    upper.mark(boundaries, 1)
    lower.mark(boundaries, 2)
    #
    return (mesh, boundaries)
示例#2
0
 def get_circle():
     filename = inspect.getframeinfo(inspect.currentframe()).filename
     home = os.path.dirname(os.path.abspath(filename))
     mesh = Mesh(home + '/test/circle.xml')
     mesh.coordinates()[:, 2] /= 1000.0
     return mesh
示例#3
0
# This script illustrates how the Xd-1d mesh could be makde from 1d
from dolfin import Mesh, MeshFunction, Timer
from mesh_around_1d import mesh_around_1d
from meshconvert import convert2xml
import subprocess, os
import numpy as np

timer = Timer('Meshing')
timer.start()

path = 'vasc_mesh.xml.gz'
geo, _ = mesh_around_1d(path, size=1.)

data = MeshFunction('int', Mesh(path), 'widths.xml.gz')

out = subprocess.check_output(['gmsh', '--version'], stderr=subprocess.STDOUT)
assert out.split('.')[0] == '3', 'Gmsh 3+ is required'

ccall = 'gmsh -3 -optimize %s' % geo
subprocess.call(ccall, shell=True)

# Convert
xml_file = 'vasc_GMSH.xml'
msh_file = 'vacs_GMSH.msh'
convert2xml(msh_file, xml_file)

# Throw away the line function as it is expensive to store all the edges
meshXd = Mesh(xml_file)
# Make sure that the assumption of correspondence hold
assert np.linalg.norm(mesh.coordinates() -
                      meshXd.coordinates()[:mesh.num_vertices()]) < 1E-13
示例#4
0
        beta = (rk2.dot(zk2)) / (rk.dot(zk))
        y1 = beta * pk
        pk = (zk2 + y1).copy()
        rk = rk2.copy()
        zk = zk2.copy()

        res4 = residual(Ah, bh, xk)
        print('residual after', ite + 1, 'iterations of CG is:', res4 / r0)
    return xk


# ===============================================================
# Read the meshes.
Vspace = []

mesh = Mesh("./level_1.xml")
V = VectorFunctionSpace(mesh, 'P', 1)
Vspace.append(V)

mesh1 = Mesh("./level_2.xml")
V1 = VectorFunctionSpace(mesh1, 'P', 1)
Vspace.append(V1)

mesh2 = Mesh("./level_3.xml")
V2 = VectorFunctionSpace(mesh2, 'P', 1)
Vspace.append(V2)

mesh3 = Mesh("./level_4.xml")
V3 = VectorFunctionSpace(mesh3, 'P', 1)
Vspace.append(V3)
示例#5
0
 def get_greenland_2D_1H():
     filename = inspect.getframeinfo(inspect.currentframe()).filename
     home = os.path.dirname(os.path.abspath(filename))
     mesh = Mesh(home + '/greenland/greenland_2D_1H_mesh.xml')
     return mesh
示例#6
0
def create_submesh(mesh, markers, marker):
    "This function allows for a SubMesh-equivalent to be created in parallel"
    # Build mesh
    submesh = Mesh()
    mesh_editor = MeshEditor()
    mesh_editor.open(submesh,
                     mesh.ufl_cell().cellname(),
                     mesh.ufl_cell().topological_dimension(),
                     mesh.ufl_cell().geometric_dimension())

    # Return empty mesh if no matching markers
    if MPI.sum(mpi_comm_world(), int(marker in markers.array())) == 0:
        cbc_warning(
            "Unable to find matching markers in meshfunction. Submesh is empty."
        )
        mesh_editor.close()
        return submesh

    base_cell_indices = np.where(markers.array() == marker)[0]
    base_cells = mesh.cells()[base_cell_indices]
    base_vertex_indices = np.unique(base_cells.flatten())

    base_global_vertex_indices = sorted(
        [mesh.topology().global_indices(0)[vi] for vi in base_vertex_indices])

    gi = mesh.topology().global_indices(0)
    shared_local_indices = set(base_vertex_indices).intersection(
        set(mesh.topology().shared_entities(0).keys()))
    shared_global_indices = [gi[vi] for vi in shared_local_indices]

    unshared_global_indices = list(
        set(base_global_vertex_indices) - set(shared_global_indices))
    unshared_vertices_dist = distribution(len(unshared_global_indices))

    # Number unshared vertices on separate process
    idx = sum(unshared_vertices_dist[:MPI.rank(mpi_comm_world())])
    base_to_sub_global_indices = {}
    for gi in unshared_global_indices:
        base_to_sub_global_indices[gi] = idx
        idx += 1

    # Gather all shared process on process 0 and assign global index
    all_shared_global_indices = gather(shared_global_indices,
                                       on_process=0,
                                       flatten=True)
    all_shared_global_indices = np.unique(all_shared_global_indices)

    shared_base_to_sub_global_indices = {}
    idx = int(
        MPI.max(mpi_comm_world(),
                float(max(base_to_sub_global_indices.values() + [-1e16]))) + 1)
    if MPI.rank(mpi_comm_world()) == 0:
        for gi in all_shared_global_indices:
            shared_base_to_sub_global_indices[int(gi)] = idx
            idx += 1

    # Broadcast global numbering of all shared vertices
    shared_base_to_sub_global_indices = dict(
        zip(broadcast(shared_base_to_sub_global_indices.keys(), 0),
            broadcast(shared_base_to_sub_global_indices.values(), 0)))

    # Join shared and unshared numbering in one dict
    base_to_sub_global_indices = dict(
        base_to_sub_global_indices.items() +
        shared_base_to_sub_global_indices.items())

    # Create mapping of local indices
    base_to_sub_local_indices = dict(
        zip(base_vertex_indices, range(len(base_vertex_indices))))

    # Define sub-cells
    sub_cells = [None] * len(base_cells)
    for i, c in enumerate(base_cells):
        sub_cells[i] = [base_to_sub_local_indices[j] for j in c]

    # Store vertices as sub_vertices[local_index] = (global_index, coordinates)
    sub_vertices = {}
    for base_local, sub_local in base_to_sub_local_indices.items():
        sub_vertices[sub_local] = (base_to_sub_global_indices[
            mesh.topology().global_indices(0)[base_local]],
                                   mesh.coordinates()[base_local])

    ## Done with base mesh

    # Distribute meshdata on (if any) empty processes
    sub_cells, sub_vertices = distribute_meshdata(sub_cells, sub_vertices)
    global_cell_distribution = distribution(len(sub_cells))
    #global_vertex_distribution = distribution(len(sub_vertices))

    global_num_cells = MPI.sum(mpi_comm_world(), len(sub_cells))
    global_num_vertices = sum(unshared_vertices_dist) + MPI.sum(
        mpi_comm_world(), len(all_shared_global_indices))

    mesh_editor.init_vertices(len(sub_vertices))
    #mesh_editor.init_cells(len(sub_cells))
    mesh_editor.init_cells_global(len(sub_cells), global_num_cells)
    global_index_start = sum(
        global_cell_distribution[:MPI.rank(mesh.mpi_comm())])

    for index, cell in enumerate(sub_cells):
        if LooseVersion(dolfin_version()) >= LooseVersion("1.6.0"):
            mesh_editor.add_cell(index, *cell)
        else:
            mesh_editor.add_cell(int(index), global_index_start + index,
                                 np.array(cell, dtype=np.uintp))

    for local_index, (global_index, coordinates) in sub_vertices.items():
        #print coordinates
        mesh_editor.add_vertex_global(int(local_index), int(global_index),
                                      coordinates)

    mesh_editor.close()

    submesh.topology().init(0, len(sub_vertices), global_num_vertices)
    submesh.topology().init(mesh.ufl_cell().topological_dimension(),
                            len(sub_cells), global_num_cells)

    # FIXME: Set up shared entities
    # What damage does this do?
    submesh.topology().shared_entities(0)[0] = []
    # The code below sets up shared vertices, but lacks shared facets.
    # It is considered incomplete, and therefore commented out
    '''
    #submesh.topology().shared_entities(0)[0] = []
    from dolfin import compile_extension_module
    cpp_code = """
    void set_shared_entities(Mesh& mesh, std::size_t idx, const Array<std::size_t>& other_processes)
    {
        std::set<unsigned int> set_other_processes;
        for (std::size_t i=0; i<other_processes.size(); i++)
        {
            set_other_processes.insert(other_processes[i]);
            //std::cout << idx << " --> " << other_processes[i] << std::endl;
        }
        //std::cout << idx << " --> " << set_other_processes[0] << std::endl;
        mesh.topology().shared_entities(0)[idx] = set_other_processes;
    }
    """

    set_shared_entities = compile_extension_module(cpp_code).set_shared_entities
    base_se = mesh.topology().shared_entities(0)
    se = submesh.topology().shared_entities(0)

    for li in shared_local_indices:
        arr = np.array(base_se[li], dtype=np.uintp)
        sub_li = base_to_sub_local_indices[li]
        set_shared_entities(submesh, base_to_sub_local_indices[li], arr)
    '''
    return submesh
示例#7
0
def convert(ifilename, handler):
    """ Convert from Abaqus.

    The Abaqus format first defines a node block, then there should be a number
    of elements containing these nodes.
    """

    # Dictionary of nodes (maps node id to coordinates)
    nodes = {}

    # Dictionary of elements (maps cell id to list of cell nodes)
    elems = {}

    # Lists of nodes for given name (key)
    node_sets = {}

    # Lists of cells for given name (key)
    cell_sets = {}

    # Lists of surfaces for given name (key) in the format:
    # {'SS1': [set(['SS1_S1', 'S1']), set(['SS1_S4', 'S4'])]},
    # where SS1 is the name of the surface, SS1_S1 is the name of the
    # cell list whose first face is to be selected, ...
    surface_sets = {}

    # Open file Abaqus file
    csv_file = csv.reader(open(ifilename, 'rb'),
                          delimiter=',',
                          skipinitialspace=True)

    node_set_name = None
    generate = None

    # Set intial state state
    state = State.Init

    # Read data from input file
    for l in csv_file:

        # Sanity check
        if (len(l) == 0): print "Ooops, zero length."

        if l[0].startswith('**'):  # Pass over comments
            continue
        elif l[0].startswith('*'):  # Have a keyword
            state = State.Unknown

            if l[0].lower() == "*heading":
                state = State.ReadHeading

            elif l[0].lower() == "*part":
                part_name = _read_part_name(l)

            elif l[0].lower() == "*end part":
                state = State.Invalid

            elif l[0].lower() == "*node":
                node_set_name = _create_node_list_entry(node_sets, l)
                state = State.ReadNodes

            elif l[0].lower() == "*element":
                cell_type, cell_set_name = _read_element_keywords(cell_sets, l)
                state = State.ReadCells

            elif l[0].lower() == "*nset":
                node_set_name, generate = _read_nset_keywords(node_sets, l)
                state = State.ReadNodeSet

            elif l[0].lower() == "*elset":
                cell_set_name, generate = _read_elset_keywords(cell_sets, l)
                if generate:
                    print "WARNING: generation of *elsets not tested."
                state = State.ReadCellSet

            elif l[0].lower() == "*surface":
                surface_set_name, generate = _read_surface_keywords(
                    surface_sets, l)
                state = State.ReadSurfaceSet

            else:
                print "WARNING: unrecognised Abaqus input keyword:", l[0]
                state = State.Unknown

        else:

            if state == State.ReadHeading:
                model_name = _read_heading(l)

            elif state == State.ReadNodes:
                node_id = int(l[0]) - 1
                coords = [float(c) for c in l[1:]]
                nodes[node_id] = coords
                if node_set_name is not None:
                    node_sets[node_set_name].add(node_id)

            elif state == State.ReadCells:
                cell_id = int(l[0]) - 1
                cell_connectivity = [int(v) - 1 for v in l[1:]]
                elems[cell_id] = cell_connectivity
                if cell_set_name is not None:
                    cell_sets[cell_set_name].add(cell_id)

            elif state == State.ReadNodeSet:

                try:
                    if generate:
                        n0, n1, increment = l
                        node_range = range(
                            int(n0) - 1,
                            int(n1) - 1, int(increment))
                        node_range.append(int(n1) - 1)
                        node_sets[node_set_name].update(node_range)
                    else:
                        # Strip empty term at end of list, if present
                        if l[-1] == '': l.pop(-1)
                        node_range = [int(n) - 1 for n in l]
                        node_sets[node_set_name].update(node_range)
                except:
                    print "WARNING: Non-integer node sets not yet supported."

            elif state == State.ReadCellSet:
                try:
                    if generate:
                        n0, n1, increment = l
                        cell_range = range(
                            int(n0) - 1,
                            int(n1) - 1, int(increment))
                        cell_range.append(int(n1) - 1)
                        cell_sets[cell_set_name].update(cell_range)
                    else:
                        # Strip empty term at end of list, if present
                        if l[-1] == '': l.pop(-1)
                        cell_range = [int(n) - 1 for n in l]
                        cell_sets[cell_set_name].update(cell_range)
                except:
                    print "WARNING: Non-integer element sets not yet supported."

            elif state == State.ReadSurfaceSet:
                # Strip empty term at end of list, if present
                if l[-1] == '': l.pop(-1)
                surface_sets[surface_set_name].update([tuple(l)])

            elif state == State.Invalid:  # part
                raise StandardError("Inavlid Abaqus parser state..")

    # Close CSV object
    del csv_file

    # Write data to XML file
    # Note that vertices/cells must be consecutively numbered, which
    # isn't necessarily the case in Abaqus. Therefore we enumerate and
    # translate original IDs to sequence indexes if gaps are present.

    # FIXME
    handler.set_mesh_type("tetrahedron", 3)

    process_facets = len(surface_sets) > 0
    if process_facets:
        try:
            from dolfin import MeshEditor, Mesh
        except ImportError:
            _error(
                "DOLFIN must be installed to handle Abaqus boundary regions")

        mesh = Mesh()
        mesh_editor = MeshEditor()
        mesh_editor.open(mesh, 3, 3)

    node_ids_order = {}
    # Check for gaps in vertex numbering
    node_ids = nodes.keys()
    if len(node_ids) > 0:
        vertex_gap = (min(node_ids) != 0 or max(node_ids) != len(node_ids) - 1)
        for x, y in enumerate(node_ids):
            node_ids_order[y] = x  # Maps Abaqus IDs to Dolfin IDs
    else:
        vertex_gap = True

    # Check for gaps in cell numbering
    elemids = elems.keys()
    if len(elemids) > 0:
        cell_gap = (min(elemids) != 0 or max(elemids) != len(elemids) - 1)
    else:
        cell_gap = True

    # Write vertices to XML file
    handler.start_vertices(len(nodes))
    if process_facets:
        mesh_editor.init_vertices_global(len(nodes), len(nodes))

    if not vertex_gap:

        for v_id, v_coords in nodes.items():
            handler.add_vertex(v_id, v_coords)
            if process_facets:
                mesh_editor.add_vertex(v_id, np.array(v_coords,
                                                      dtype=np.float_))

    else:

        for idx, (v_id, v_coords) in enumerate(nodes.items()):
            handler.add_vertex(idx, v_coords)
            if process_facets:
                mesh_editor.add_vertex(idx, np.array(v_coords,
                                                     dtype=np.float_))

    handler.end_vertices()

    # Write cells to XML file
    handler.start_cells(len(elems))
    if process_facets:
        mesh_editor.init_cells_global(len(elems), len(elems))

    if not vertex_gap and not cell_gap:

        for c_index, c_data in elems.items():
            for v_id in c_data:
                if not (0 <= v_id < len(nodes)):
                    handler.error(
                        "Element %s references non-existent node %s" %
                        (c_index, v_id))
            handler.add_cell(c_index, c_data)

            if process_facets:
                c_data_tmp = np.array(c_data)
                c_data_tmp.sort()
                mesh_editor.add_cell(c_index,
                                     np.array(c_data_tmp, dtype=np.uintp))

    elif not vertex_gap and cell_gap:

        for idx, (c_index, c_data) in enumerate(elems.items()):
            for v_id in c_data:
                if not (0 <= v_id < len(nodes)):
                    handler.error(
                        "Element %s references non-existent node %s" %
                        (c_index, v_id))
            handler.add_cell(idx, c_data)

            if process_facets:
                c_data_tmp = np.array(c_data)
                c_data_tmp.sort()
                mesh_editor.add_cell(idx, np.array(c_data_tmp, dtype=np.uintp))

    else:

        for idx, (c_id, c_data) in enumerate(elems.items()):
            c_nodes = []
            for v_id in c_data:
                try:
                    c_nodes.append(node_ids_order[v_id])
                except ValueError:
                    handler.error(
                        "Element %s references non-existent node %s" %
                        (c_id, v_id))
            handler.add_cell(idx, c_nodes)

            if process_facets:
                c_nodes.sort()
                mesh_editor.add_cell(idx, np.array(c_nodes, dtype=np.uintp))

    handler.end_cells()

    # Write MeshValueCollections to XML file
    handler.start_domains()

    # Build a abaqus node ID -> dolfin cell ID map (which is not unique but that is irrelevant here)
    #                           and its local entity.
    if len(node_sets.items()) > 0:
        node_cell_map = {}
        for c_dolfin_index, (c_index, c_data) in enumerate(elems.items()):
            c_data_tmp = np.array(c_data)
            c_data_tmp.sort()
            for local_entity, n_index in enumerate(c_data_tmp):
                node_cell_map[n_index] = (c_dolfin_index, local_entity)

    # Write vertex/node sets
    dim = 0
    for value, (name, node_set) in enumerate(node_sets.items()):
        handler.start_mesh_value_collection(name, dim, len(node_set), "uint")

        for node in node_set:
            try:
                cell, local_entity = node_cell_map[node]
                handler.add_entity_mesh_value_collection(
                    dim, cell, value, local_entity=local_entity)
            except KeyError:
                print "Warning: Boundary references non-existent node %s" % node
        handler.end_mesh_value_collection()

    # Write cell/element sets
    dim = 3
    for name, s in cell_sets.items():
        handler.start_mesh_value_collection(name, dim, len(s), "uint")
        for cell in s:
            handler.add_entity_mesh_value_collection(dim, cell, 0)
        handler.end_mesh_value_collection()

    # Write surface sets
    if process_facets:
        dim = 2
        nodes_facet_map = _nodes_facet_map(mesh)

        data = [int(0)] * mesh.num_facets()
        S1 = [0, 1, 2]
        S2 = [0, 3, 1]
        S3 = [1, 3, 2]
        S4 = [2, 3, 0]
        node_selector = {
            'S1': S1,
            'S2': S2,
            'S3': S3,
            'S4': S4,
        }

        for index, (name, s) in enumerate(surface_sets.items()):
            cell_face_list = []
            for cell_set_name, face_index in s:
                cell_face_list += [(cell, face_index)
                                   for cell in cell_sets[cell_set_name]]

            for cell, face in cell_face_list:
                cell_nodes = elems[cell]
                # Extract the face nodes
                face_nodes = [cell_nodes[i] for i in node_selector[face]]
                dolfin_face_nodes = [node_ids_order[n] for n in face_nodes]
                dolfin_face_nodes.sort()
                # Convert the face_nodes to dolfin IDs
                face_id = nodes_facet_map[tuple(dolfin_face_nodes)]
                data[face_id] = index + 1

        # Create and initialise the mesh function
        handler.start_meshfunction("facet_region", dim, mesh.num_facets())
        for index, physical_region in enumerate(data):
            handler.add_entity_meshfunction(index, physical_region)
        handler.end_meshfunction()

    handler.end_domains()
示例#8
0
    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


if __name__ == '__main__':
    print('Loading meshes')
    mesh = Mesh(os.path.join("mesh", "slice_saline_model.xml"))
    subdomains = MeshFunction(
        "size_t", mesh,
        os.path.join("mesh", "slice_saline_model_physical_region.xml"))
    boundaries = MeshFunction(
        "size_t", mesh,
        os.path.join("mesh", "slice_saline_model_facet_region.xml"))
    for dipole in params.dipole_list:
        print('Now computing FEM for dipole: ', dipole['name'])
        src_pos = dipole['src_pos']
        snk_pos = dipole['snk_pos']
        print('Done loading meshes')
        fem_20 = main_slice_fem(mesh, subdomains, boundaries, src_pos, snk_pos)
        print('Done 4Shell-FEM-20')
        f = open(os.path.join('Numerical_' + dipole['name'] + '.npz'), 'wb')
        np.savez(f, fem_20=fem_20)
def test_eim_approximation_04(expression_type, basis_generation):
    """
    This test is an extension of test 03.
    The aim of this script is to test that integration of a subdomain is correctly handled by DEIM.
    * EIM: not applicable, as there is no difference with respect to test 03.
    * DEIM: the integral in form definitions is now restricted to a subdomain.
    """
    class MockProblem(ParametrizedProblem):
        def __init__(self, V, **kwargs):
            ParametrizedProblem.__init__(self, "")
            self.V = V

        def name(self):
            return "MockProblem_04_" + expression_type + "_" + basis_generation

    class ParametrizedFunctionApproximation(EIMApproximation):
        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")

    # 1. Create the mesh for this test
    mesh = Mesh("../../../tutorials/01_thermal_block/data/thermal_block.xml")
    subdomains = MeshFunction(
        "size_t", mesh,
        "../../../tutorials/01_thermal_block/data/thermal_block_physical_region.xml"
    )

    # 2. Create Finite Element space (Lagrange P1)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # 3. Allocate an object of the ParametrizedFunctionApproximation class
    parametrized_function_approximation = ParametrizedFunctionApproximation(
        V, subdomains, expression_type, basis_generation)
    mu_range = [(-1.0, 1.0), (-1.0, 1.0)]
    parametrized_function_approximation.set_mu_range(mu_range)

    # 4. Prepare reduction with EIM
    parametrized_function_reduction_method = EIMApproximationReductionMethod(
        parametrized_function_approximation)
    parametrized_function_reduction_method.set_Nmax(20)
    parametrized_function_reduction_method.set_tolerance(0.)

    # 5. Perform the offline phase
    parametrized_function_reduction_method.initialize_training_set(
        100, sampling=EquispacedDistribution())
    reduced_parametrized_function_approximation = parametrized_function_reduction_method.offline(
    )

    # 6. Perform an online solve
    online_mu = (-1., -1.)
    reduced_parametrized_function_approximation.set_mu(online_mu)
    reduced_parametrized_function_approximation.solve()

    # 7. Perform an error analysis
    parametrized_function_reduction_method.initialize_testing_set(100)
    parametrized_function_reduction_method.error_analysis()
k = 1

# Magnitude solid body rotation .
Uh = np.pi

# Timestepping
Tend = 2.0
dt = Constant(0.02)
num_steps = np.rint(Tend / float(dt))

# Output directory
store_step = 5
outdir = "./../../results/SlottedDisk_l2/"

# Mesh
mesh = Mesh("./../../meshes/circle_0.xml")
mesh = refine(refine(refine(mesh)))

outfile = XDMFFile(mesh.mpi_comm(), outdir + "psi_h.xdmf")

# Particle output
fname_list = [outdir + "xp.pickle", outdir + "rhop.pickle"]
property_list = [0, 1]

# Set slotted disk
psi0_expr = SlottedDisk(radius=rdisk,
                        center=[xc, yc],
                        width=rwidth,
                        depth=0.0,
                        degree=3,
                        lb=lb,
示例#11
0
def _main():
    args = _parse_cmd_arguments()

    content = np.load(args.infile)

    data = content.item()["data"]
    n = content.item()["n"]

    # # plot statistics
    # axes0 = problem.get_ellipse_axes(alpha0).T.flatten()
    # plt.plot(axes0, label='axes lengths before')
    # axes1 = problem.get_ellipse_axes(out.x).T.flatten()
    # plt.plot(axes1, label='axes lengths opt')
    # plt.legend()
    # plt.grid()

    # Plot unperturbed MacAdam
    # colorio.plot_luo_rigg(
    #     ellipse_scaling=1,
    colorio.save_macadam("macadam-native.png",
                         ellipse_scaling=10,
                         plot_rgb_triangle=False,
                         n=n)

    points, cells = meshzoo.triangle(corners=np.array([[0.0, 0.0, 0.0],
                                                       [1.0, 0.0, 0.0],
                                                       [0.0, 1.0, 0.0]]),
                                     n=n)

    # https://bitbucket.org/fenics-project/dolfin/issues/845/initialize-mesh-from-vertices
    editor = MeshEditor()
    mesh = Mesh()
    editor.open(mesh, "triangle", 2, 2)
    editor.init_vertices(points.shape[0])
    editor.init_cells(cells.shape[0])
    for k, point in enumerate(points):
        editor.add_vertex(k, point[:2])
    for k, cell in enumerate(cells):
        editor.add_cell(k, cell)
    editor.close()

    V = FunctionSpace(mesh, "CG", 1)

    def get_u(alpha):
        n = V.dim()
        ax = alpha[:n]
        ay = alpha[n:]

        ux = Function(V)
        ux.vector().set_local(ax)
        ux.vector().apply("")

        uy = Function(V)
        uy.vector().set_local(ay)
        uy.vector().apply("")
        return ux, uy

    # Plot perturbed MacAdam
    def transform(XY, data=data):
        is_solo = len(XY.shape) == 1
        if is_solo:
            XY = np.array([XY]).T
        # print(XY)
        ux, uy = get_u(data)
        out = np.array([[ux(x, y) for x, y in XY.T],
                        [uy(x, y) for x, y in XY.T]])
        if is_solo:
            out = out[..., 0]
        return out

    # colorio.plot_luo_rigg(
    #     ellipse_scaling=1,
    plt.figure()
    colorio.plot_macadam(
        ellipse_scaling=10,
        # xy_to_2d=problem.pade2d.eval,
        xy_to_2d=transform,
        plot_rgb_triangle=False,
        mesh_resolution=n,
    )
    # plt.xlim(-0.2, 0.9)
    # plt.ylim(+0.0, 0.7)
    plt.savefig(f"macadam-{n:03d}.png")
    return
示例#12
0
    def __init__(self):
        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, _, cell_data, _ = meshes.ball_in_tube_cyl.generate()
        # 2018.1
        # self.mesh = Mesh(
        #     dolfin.mpi_comm_world(), dolfin.cpp.mesh.CellType.Type_triangle,
        #     points[:, :2], cells['triangle']
        #     )
        with TemporaryDirectory() as temp_dir:
            tmp_filename = os.path.join(temp_dir, "test.xml")
            meshio.write_points_cells(
                tmp_filename,
                points,
                cells,
                cell_data=cell_data,
                file_format="dolfin-xml",
            )
            self.mesh = Mesh(tmp_filename)

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

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

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

        left_boundary = LeftBoundary()

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

        right_boundary = RightBoundary()

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

        lower_boundary = LowerBoundary()

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

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

        coil_boundary = CoilBoundary()

        self.u_bcs = [
            DirichletBC(self.W, (0.0, 0.0), right_boundary),
            DirichletBC(self.W.sub(0), 0.0, left_boundary),
            DirichletBC(self.W, (0.0, 0.0), lower_boundary),
            DirichletBC(self.W, (0.0, 0.0), coil_boundary),
        ]
        self.p_bcs = []
        # self.p_bcs = [DirichletBC(Q, 0.0, upper_boundary)]
        return
示例#13
0
def fluent2xml(ifilename, ofilename):
    """Converting from ANSYS Fluent format (.msh) to FEniCS xml format
    The fluent mesh (the .msh file) is basically stored as a list of vertices, and then a 
    list of faces for each zone of the mesh, the interior and the boundaries."""

    # Use regular expressions to identify sections and tokens found in a fluent file
    re_dimline = re.compile(r"\(2\s(\d)\)")
    re_comment = re.compile(r"\(0\s.*")
    re_zone_init = re.compile(r"\(10\s\(0\s(\w+)\s(\w+)\s(\d+)\s(\d+)\)\)")
    re_zone = re.compile(r"\(10\s\((\w+)\s(\w+)\s(\w+)\s(\d+)\s(\d)\)(\(|)")
    re_face_init = re.compile(r"\(13(\s*)\(0\s+(\w+)\s+(\w+)\s+(0|0 0)\)\)")
    re_face = re.compile(
        r"\(13(\s*)\((\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\)(\s*)(\(|)")
    re_periodic = re.compile(r"\(18.*\((\w+)\s+(\w+)\s+(\w+)\s+(\w+)\).*\(")
    re_pfaces = re.compile(r"((^\s)|)(\w+)(\s*)(\w+)")
    re_cells_init = re.compile(
        r"\(12(\s*)\(0(\s+)(\w+)(\s+)(\w+)(\s+)(0|0 0)\)\)")
    re_cells = re.compile(r"\(12.*\((\w+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(\d+)\)\)")
    re_cells2 = re.compile(
        r"\(12(\s*)\((\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\)(\s*)(\(|)")
    re_zones = re.compile(
        r"\((45|39)\s+\((\d+)\s+(\S+)\s+(\S+).*\)\((.*|[0-9]+[\.]*[0-9]*)\)\)")
    re_parthesis = re.compile(r"(^\s*\)(\s*)|^\s*\)\)(\s*)|^\s*\(\s*)")

    # Declare som maps that will be built when reading in the lists of vertices and faces:
    cell_map = {}  # Maps cell id with vertices
    boundary_cells = {
    }  # List of cells attached to a boundary facet. Key is zone id
    zones = {}  # zone information (not really used yet)

    def read_periodic(ifile, periodic_dx):
        """Scan past periodic section. Periodicity is computed by FEniCS."""
        while 1:
            line = ifile.readline()
            a = re.search(re_pfaces, line)
            if a:
                continue
            break

    def read_zone_vertices(dim, Nmin, Nmax, ifile, editor):
        """Scan ifile for vertices and add to mesh_editor."""
        # First line could be either just "(" or a regular vertex.
        # Check for initial paranthesis. If paranthesis then read a new line, else reset
        pos = ifile.tell()
        line = ifile.readline()
        if not re.search(re_parthesis, line):
            ifile.seek(pos)  # reset
        # read Nmax-Nmin vertices
        for i in range(Nmin, Nmax + 1):
            line = ifile.readline()
            vertex = [eval(x) for x in line.split()]
            if dim == 2:
                editor.add_vertex(i - Nmin, vertex[0], vertex[1])
            else:
                editor.add_vertex(i - Nmin, vertex[0], vertex[1], vertex[2])

    def read_faces(zone_id, Nmin, Nmax, bc_type, face, ifile):
        """Read all faces and create cell_map + boundary maps."""
        pos = ifile.tell()  # current position
        line = ifile.readline()
        if not re.search(
                re_parthesis, line
        ):  # check for initial paranthesis. If paranthesis then read a new line, else reset
            ifile.seek(pos)

        # read Nmax-Nmin faces
        for i in range(Nmin, Nmax + 1):
            line = ifile.readline()
            ln = line.split()
            if face == 0:
                nd = int(ln[0], 16)  # Number of vertices
                nds = [int(x, 16) for x in ln[1:(nd + 1)]]
                cells = [int(x, 16) for x in ln[(nd + 1):]]
            else:
                nd = face
                nds = [int(x, 16) for x in ln[:nd]]
                cells = [int(x, 16) for x in ln[nd:]]

            if min(cells) == 0:  # A boundary zone
                if zone_id in boundary_cells:
                    boundary_cells[zone_id][max(cells)] = array(nds)
                else:
                    boundary_cells[zone_id] = {max(cells): array(nds)}

            for c in cells:
                if c > 0:
                    if not c in cell_map:
                        cell_map[c] = copy(nds)
                    else:
                        cell_map[c] = list(Set(cell_map[c] + nds))

    def scan_fluent_mesh(ifile, mesh, editor):
        """Scan fluent mesh and generate maps."""
        dim = 0
        one = 0
        while 1:
            line = ifile.readline()
            if len(line) == 0:
                print 'Finished reading file\n'
                break

            if dim == 0:  # Dimension usually comes first
                a = re.search(re_dimline, line)
                if a:
                    print 'Reading dimensions\n'
                    dim = int(a.group(1))
                    editor.open(mesh, dim, dim)
                    continue

            if one == 0:  # The total number of vertices
                a = re.search(re_zone_init, line)
                if a:
                    print 'Reading zone info\n'
                    one, num_vertices, dummy1, dummy2 = int(a.group(1)), \
                        int(a.group(2), 16), int(a.group(3), 16), int(a.group(4))
                    editor.init_vertices(num_vertices)
                    continue

            a = re.search(re_zone, line)  # Vertices
            if a:
                zone_id, first_id, last_id = int(a.group(1), 16), \
                    int(a.group(2), 16), int(a.group(3), 16)
                print 'Reading ', last_id - first_id + 1, ' vertices in zone ', zone_id + 1, '\n'
                read_zone_vertices(dim, first_id, last_id, ifile, editor)
                continue

            a = re.search(re_zones, line)  # Zone info
            if a:
                print 'Reading zone info ', line
                dummy, zone_id, zone_type, zone_name, radius =  \
                        int(a.group(1)), int(a.group(2)),  a.group(3), \
                        a.group(4), a.group(5)
                zones[zone_id] = [zone_type, zone_name, radius]
                continue

            a = re.search(re_cells_init,
                          line)  # Get total number of cells/elements
            if a:
                print 'Reading cell info ', line
                first_id, tot_num_cells = int(a.group(3),
                                              16), int(a.group(5), 16)
                editor.init_cells(tot_num_cells)
                continue

            a = re.search(re_cells, line)  # Get the cell info.
            if a:
                zone_id, first_id, last_id, bc_type, element_type = \
                    int(a.group(1)), int(a.group(2), 16), int(a.group(3), 16), \
                    int(a.group(4), 16), int(a.group(5), 16)
                print 'Found ', last_id - first_id + 1, ' cells in zone ', zone_id, '\n'
                if last_id == 0:
                    raise TypeError("Zero elements!")
                continue

            a = re.search(re_cells2, line)  # Get the cell info.
            if a:
                raise TypeError(
                    "Wrong cell type. Can only handle one single cell type")

            a = re.search(re_face_init, line)
            if a:
                print 'Reading total number of faces\n', line
                continue

            a = re.search(re_face, line)
            if a:
                print 'Reading faces ', line
                zone_id, first_id, last_id, bc_type, face_type = \
                    int(a.group(2), 16), int(a.group(3), 16), int(a.group(4), 16), \
                    int(a.group(5), 16), int(a.group(6), 16)
                read_faces(zone_id, first_id, last_id, bc_type, face_type,
                           ifile)
                continue

            a = re.search(re_periodic, line)
            if a:
                print 'Scanning past periodic connectivity\n', line
                read_periodic(ifile, periodic_dx)
                continue

            if any([re.search(st, line) for st in (re_parthesis, re_comment)]) or \
                                                                not line.strip():
                continue

            # Should not make it here
            raise IOError('Something went wrong reading fluent mesh.')

    def write_fenics_file(ofile, mesh, editor):

        dim = mesh.geometry().dim()
        for i in range(1, len(cell_map) + 1):
            if dim == 2:
                editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1,
                                cell_map[i][2] - 1)
            else:
                editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1,
                                cell_map[i][2] - 1, cell_map[i][3] - 1)

        mesh.order()
        # Set MeshValueCollections from info in  boundary_cell
        #mvc = mesh.domains().markers(dim-1)
        md = mesh.domains()
        for zone, cells in boundary_cells.iteritems():
            for cell, nds in cells.iteritems():
                dolfin_cell = Cell(mesh, cell - 1)
                vertices_of_cell = dolfin_cell.entities(0)
                vertices_of_face = nds - 1
                for jj, ff in enumerate(facets(dolfin_cell)):
                    facet_vertices = ff.entities(0)
                    if all(map(lambda x: x in vertices_of_face,
                               facet_vertices)):
                        local_index = jj
                        break
                #mvc.set_value(cell-1, local_index, zone)
                md.set_marker((ff.index(), zone), dim - 1)

        ofile << mesh
        from dolfin import plot
        plot(mesh, interactive=True)
        print 'Finished writing FEniCS mesh\n'

    ifile = open(ifilename, "r")
    ofile = File(ofilename)
    mesh = Mesh()
    editor = MeshEditor()
    scan_fluent_mesh(ifile, mesh, editor)
    write_fenics_file(ofile, mesh, editor)
    ifile.close()
示例#14
0
def test(path, type='mf'):
    '''Evolve the tile in (n, n) pattern checking volume/surface properties'''

    comm = mpi_comm_world()
    h5 = HDF5File(comm, path, 'r')
    tile = Mesh()
    h5.read(tile, 'mesh', False)

    init_container = lambda type, dim: (
        MeshFunction('size_t', tile, dim, 0)
        if type == 'mf' else MeshValueCollection('size_t', tile, dim))

    for n in (2, 4):
        data = {}
        checks = {}
        for dim, name in zip((2, 3), ('surfaces', 'volumes')):
            # Get the collection
            collection = init_container(type, dim)
            h5.read(collection, name)

            if type == 'mvc': collection = as_meshf(collection)

            # Data to evolve
            tile.init(dim, 0)
            e2v = tile.topology()(dim, 0)
            # Only want to evolve tag 1 (interfaces) for the facets.
            data[(dim, 1)] = np.array(
                [e2v(e.index()) for e in SubsetIterator(collection, 1)],
                dtype='uintp')

            if dim == 2:
                check = lambda m, f: assemble(
                    FacetArea(m) * ds(domain=m,
                                      subdomain_data=f,
                                      subdomain_id=1) + avg(FacetArea(m)) *
                    dS(domain=m, subdomain_data=f, subdomain_id=1))
            else:
                check = lambda m, f: assemble(
                    CellVolume(m) * dx(
                        domain=m, subdomain_data=f, subdomain_id=1))

            checks[
                dim] = lambda m, f, t=tile, c=collection, n=n, check=check: abs(
                    check(m, f) - n**2 * check(t, c)) / (n**2 * check(t, c))

        t = Timer('x')
        mesh, mesh_data = TileMesh(tile, (n, n), mesh_data=data)
        info('\tTiling took %g s. Ncells %d, nvertices %d, \n' %
             (t.stop(), mesh.num_vertices(), mesh.num_cells()))

        foos = mf_from_data(mesh, mesh_data)
        # Mesh Functions
        from_mf = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        mvcs = mvc_from_data(mesh, mesh_data)
        foos = as_meshf(mvcs)
        # Mesh ValueCollections
        from_mvc = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        assert np.linalg.norm(from_mf - from_mvc) < 1E-13
        # I ignore shared facets so there is bound to be some error in facets
        # Volume should match well
        print from_mf
示例#15
0
            },
            'neumann': {
                'values': [[0., -1e5]],
                'regions': [2],
                'types': ['cauchy']
            }
        }
    }
}

# First solve the inverse elastostatics problem.
problem = fm.SolidMechanicsProblem(config)
solver = fm.SolidMechanicsSolver(problem,
                                 fname_disp="results/unloaded_config.pvd")
solver.full_solve()

# Move the mesh using dolfin's ALE functionality
from dolfin import ALE, Mesh
ALE.move(problem.mesh, problem.displacement)
mesh_copy = Mesh(problem.mesh)

# Only need to change relevant entries in config
config['mesh']['mesh_file'] = mesh_copy
config['formulation']['inverse'] = False

# Solve a 'forward' problem.
problem = fm.SolidMechanicsProblem(config)
solver = fm.SolidMechanicsSolver(problem,
                                 fname_disp="results/loaded_config.pvd")
solver.full_solve()
    def create_mesh(self, parameters):
        from dolfin import Point, XDMFFile
        import hashlib

        d = {
            'rad': parameters['geometry']['rad'],
            'rad2': parameters['geometry']['rad2'],
            'meshsize': parameters['geometry']['meshsize']
        }
        fname = 'circle'
        meshfile = "meshes/%s-%s.xml" % (fname, self.signature)

        if os.path.isfile(meshfile):
            # already existing mesh
            print("Meshfile %s exists" % meshfile)

        else:
            # mesh_template = open('scripts/sandwich_pert.template.geo' )
            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.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)

                # cmd = 'gmsh scripts/coin-{}.geo -2 -o meshes/coin-{}.msh'.format(self.signature, self.signature)
                # print(check_output([cmd], shell=True))  # run in shell mode in case you are not run in terminal

                # cmd = 'dolfin-convert -i gmsh meshes/coin-{}.msh meshes/coin-{}.xml'.format(self.signature, self.signature)
                # Popen([cmd], stdout=PIPE, shell=True).communicate()

            # mesh_xdmf = XDMFFile("meshes/%s-%s.xdmf"%(fname, self.signature))
            # mesh_xdmf.write(mesh)

        form_compiler_parameters = {
            "representation": "uflacs",
            "quadrature_degree": 2,
            "optimize": True,
            "cpp_optimize": True,
        }
        # import pdb; pdb.set_trace()

        mesh = Mesh("meshes/coin.xml")
        self.domains = MeshFunction('size_t', mesh,
                                    'meshes/coin_physical_region.xml')
        # dx = dx(subdomain_data=domains)
        # plt.figure()
        # plot(self.domains)
        # visuals.setspines0()
        # plt.savefig(os.path.join(self.outdir,'domains-{}.pdf'
        # .format(hashlib.md5(str(d).encode('utf-8')).hexdigest())))
        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)

        return mesh
示例#17
0
__date__ = "2014-04-10"
__copyright__ = "Copyright (C) 2014 " + __author__
__license__ = "GNU Lesser GPL version 3 or any later version"

from dolfin import Mesh, AutoSubDomain, near
import os

if not os.path.isfile("mesh/cylinder.xml"):
    try:
        os.system("gmsh mesh/cylinder.geo -2 -o mesh/cylinder.msh")
        os.system("dolfin-convert mesh/cylinder.msh mesh/cylinder.xml")
        os.system("rm mesh/cylinder.msh")
    except RuntimeError:
        raise "Gmsh is required to run this demo"

mesh = Mesh("mesh/cylinder.xml")

H = 0.41
L = 2.2
D = 0.1
center = 0.2
cases = {1: {'Um': 0.3, 'Re': 20.0}, 2: {'Um': 1.5, 'Re': 100.0}}

# Specify boundary conditions
Inlet = AutoSubDomain(lambda x, on_bnd: on_bnd and x[0] < 1e-8)
Wall = AutoSubDomain(lambda x, on_bnd: on_bnd and near(x[1] * (H - x[1]), 0))
Cyl = AutoSubDomain(lambda x, on_bnd: on_bnd and x[0] > 1e-6 and x[0] < 1 and
                    x[1] < 3 * H / 4 and x[1] > H / 4)
Outlet = AutoSubDomain(lambda x, on_bnd: on_bnd and x[0] > L - 1e-8)

示例#18
0
    # Protecting self
    assert not(set(('geo', '.geo')) & set(args.cleanup))
    
    try:
        msh_file, h5_file = args.io[:2]
    except ValueError:
        msh_file = args.io[0]

        root, ext = os.path.splitext(msh_file)
        h5_file = '.'.join([root, 'h5'])

    assert convert(msh_file, h5_file, args.save_mvc)

    if args.save_pvd:
        h5 = HDF5File(mpi_comm_world(), h5_file, 'r')
        mesh = Mesh()
        h5.read(mesh, 'mesh', False)

        surfaces = MeshFunction('size_t', mesh, mesh.topology().dim()-1, 0)
        volumes = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

        if not args.save_mvc:
            h5.read(surfaces, 'surfaces')
            h5.read(volumes, 'volumes')
        # The data is mesh value collections
        else:
            from tiling_cpp import fill_mf_from_mvc

            surfaces_mvc = MeshValueCollection('size_t', mesh, mesh.topology().dim()-1)
            h5.read(surfaces_mvc, 'surfaces')
            fill_mf_from_mvc(surfaces_mvc, surfaces)
示例#19
0
def mesh_AcuteSquare(n=0):
    mbasename = 'AcuteSquareMesh2'
    mesh = Mesh(mbasename + '_%d.xml' % n)
    return mesh
示例#20
0
def get_mesh(geo_name, mesh_name = "mesh/mesh.xml"):

    from dolfin import Mesh
    return Mesh("/".join([DATADIR, geo_name, mesh_name]))
示例#21
0
def gmsh2xml(ifilename, handler):
    """Convert between .gmsh v2.0 format (http://www.geuz.org/gmsh/) and .xml,
    parser implemented as a state machine:

        0 = read 'MeshFormat'
        1 = read  mesh format data
        2 = read 'EndMeshFormat'
        3 = read 'Nodes'
        4 = read  number of vertices
        5 = read  vertices
        6 = read 'EndNodes'
        7 = read 'Elements'
        8 = read  number of cells
        9 = read  cells
        10 = done

    Afterwards, extract physical region numbers if they are defined in
    the mesh file as a mesh function.

    """

    print("Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format")

    # The dimension of the gmsh element types supported here as well as the dolfin cell types for each dimension
    gmsh_dim = {15: 0, 1: 1, 2: 2, 4: 3}
    cell_type_for_dim = {1: "interval", 2: "triangle", 3: "tetrahedron" }
    # the gmsh element types supported for conversion
    supported_gmsh_element_types = [1, 2, 4, 15]

    # Open files
    ifile = open(ifilename, "r")

    # Scan file for cell type
    cell_type = None
    highest_dim = 0
    line = ifile.readline()
    while line:

        # Remove newline
        line = line.rstrip("\n\r")

        # Read dimension
        if line.find("$Elements") == 0:

            line = ifile.readline()
            num_elements = int(line)
            if num_elements == 0:
                _error("No elements found in gmsh file.")
            line = ifile.readline()

            # Now iterate through elements to find largest dimension.  Gmsh
            # format might include elements of lower dimensions in the element list.
            # We also need to count number of elements of correct dimensions.
            # Also determine which vertices are not used.
            dim_count = {0: 0, 1: 0, 2: 0, 3: 0}
            vertices_used_for_dim = {0: [], 1: [], 2: [], 3: []}
            # Array used to store gmsh tags for 1D (type 1/line), 2D (type 2/triangular) elements and 3D (type 4/tet) elements
            tags_for_dim = {0: [], 1: [], 2: [], 3: []}

            while line.find("$EndElements") == -1:
                element = line.split()
                elem_type = int(element[1])
                num_tags = int(element[2])
                if elem_type in supported_gmsh_element_types:
                    dim = gmsh_dim[elem_type]
                    if highest_dim < dim:
                        highest_dim = dim
                    node_num_list = [int(node) for node in element[3 + num_tags:]]
                    vertices_used_for_dim[dim].extend(node_num_list)
                    if num_tags > 0:
                        tags_for_dim[dim].append(tuple(int(tag) for tag in element[3:3+num_tags]))
                    dim_count[dim] += 1
                else:
                    #TODO: output a warning here. "gmsh element type %d not supported" % elem_type
                    pass
                line = ifile.readline()
        else:
            # Read next line
            line = ifile.readline()

    # Check that we got the cell type and set num_cells_counted
    if highest_dim == 0:
        _error("Unable to find cells of supported type.")

    num_cells_counted = dim_count[highest_dim]
    vertex_set = set(vertices_used_for_dim[highest_dim])
    vertices_used_for_dim[highest_dim] = None

    vertex_dict = {}
    for n,v in enumerate(vertex_set):
        vertex_dict[v] = n

    # Step to beginning of file
    ifile.seek(0)

    # Set mesh type
    handler.set_mesh_type(cell_type_for_dim[highest_dim], highest_dim)

    # Initialise node list (gmsh does not export all vertexes in order)
    nodelist = {}

    # Current state
    state = 0

    # Write data
    num_vertices_read = 0
    num_cells_read = 0

    # Only import the dolfin objects if facet markings exist
    process_facets = False
    if len(tags_for_dim[highest_dim-1]) > 0:
        # first construct the mesh
        try:
            from dolfin import MeshEditor, Mesh
        except ImportError:
            _error("DOLFIN must be installed to handle Gmsh boundary regions")
        mesh = Mesh()
        mesh_editor = MeshEditor ()
        mesh_editor.open( mesh, highest_dim, highest_dim )
        process_facets = True
    else:
        # TODO: Output a warning or an error here
        me = None

    while state != 10:

        # Read next line
        line = ifile.readline()
        if not line: break

        # Skip comments
        if line[0] == '#':
            continue

        # Remove newline
        line = line.rstrip("\n\r")

        if state == 0:
            if line == "$MeshFormat":
                state = 1
        elif state == 1:
            (version, file_type, data_size) = line.split()
            state = 2
        elif state == 2:
            if line == "$EndMeshFormat":
                state = 3
        elif state == 3:
            if line == "$Nodes":
                state = 4
        elif state == 4:
            num_vertices = len(vertex_dict)
            handler.start_vertices(num_vertices)
            if process_facets:
                mesh_editor.init_vertices_global(num_vertices, num_vertices)
            state = 5
        elif state == 5:
            (node_no, x, y, z) = line.split()
            node_no = int(node_no)
            x,y,z = [float(xx) for xx in (x,y,z)]
            if node_no in vertex_dict:
                node_no = vertex_dict[node_no]
            else:
                continue
            nodelist[int(node_no)] = num_vertices_read
            handler.add_vertex(num_vertices_read, [x, y, z])
            if process_facets:
                if highest_dim == 1:
                    coords = numpy.array([x])
                elif highest_dim == 2:
                    coords = numpy.array([x, y])
                elif highest_dim == 3:
                    coords = numpy.array([x, y, z])
                mesh_editor.add_vertex(num_vertices_read, coords)

            num_vertices_read +=1

            if num_vertices == num_vertices_read:
                handler.end_vertices()
                state = 6
        elif state == 6:
            if line == "$EndNodes":
                state = 7
        elif state == 7:
            if line == "$Elements":
                state = 8
        elif state == 8:
            handler.start_cells(num_cells_counted)
            if process_facets:
                mesh_editor.init_cells_global(num_cells_counted, num_cells_counted)

            state = 9
        elif state == 9:
            element = line.split()
            elem_type = int(element[1])
            num_tags  = int(element[2])
            if elem_type in supported_gmsh_element_types:
                dim = gmsh_dim[elem_type]
            else:
                dim = 0
            if dim == highest_dim:
                node_num_list = [vertex_dict[int(node)] for node in element[3 + num_tags:]]
                for node in node_num_list:
                    if not node in nodelist:
                        _error("Vertex %d of %s %d not previously defined." %
                              (node, cell_type_for_dim[dim], num_cells_read))
                cell_nodes = [nodelist[n] for n in node_num_list]
                handler.add_cell(num_cells_read, cell_nodes)

                if process_facets:
                    cell_nodes = numpy.array([nodelist[n] for n in node_num_list], dtype=numpy.uintp)
                    mesh_editor.add_cell(num_cells_read, cell_nodes)

                num_cells_read +=1

            if num_cells_counted == num_cells_read:
                handler.end_cells()
                if process_facets:
                    mesh_editor.close()
                state = 10
        elif state == 10:
            break

    # Write mesh function based on the Physical Regions defined by
    # gmsh, but only if they are not all zero. All zero physical
    # regions indicate that no physical regions were defined.
    if highest_dim not in [1,2,3]:
        _error("Gmsh tags not supported for dimension %i. Probably a bug" % dim)

    tags = tags_for_dim[highest_dim]
    physical_regions = tuple(tag[0] for tag in tags)
    if not all(tag == 0 for tag in physical_regions):
        handler.start_meshfunction("physical_region", dim, num_cells_counted)
        for i, physical_region in enumerate(physical_regions):
            handler.add_entity_meshfunction(i, physical_region)
        handler.end_meshfunction()

    # Now process the facet markers
    tags = tags_for_dim[highest_dim-1]
    if (len(tags) > 0) and (mesh is not None):
        physical_regions = tuple(tag[0] for tag in tags)
        if not all(tag == 0 for tag in physical_regions):
            mesh.init(highest_dim-1,0)

            # Get the facet-node connectivity information (reshape as a row of node indices per facet)
            if highest_dim==1:
              # for 1d meshes the mesh topology returns the vertex to vertex map, which isn't what we want
              # as facets are vertices
              facets_as_nodes = numpy.array([[i] for i in range(mesh.num_facets())])
            else:
              facets_as_nodes = mesh.topology()(highest_dim-1,0)().reshape ( mesh.num_facets(), highest_dim )

            # Build the reverse map
            nodes_as_facets = {}
            for facet in range(mesh.num_facets()):
              nodes_as_facets[tuple(facets_as_nodes[facet,:])] = facet

            data = [int(0*k) for k in range(mesh.num_facets()) ]
            for i, physical_region in enumerate(physical_regions):
                nodes = [n-1 for n in vertices_used_for_dim[highest_dim-1][highest_dim*i:(highest_dim*i+highest_dim)]]
                nodes.sort()

                if physical_region != 0:
                    try:
                        index = nodes_as_facets[tuple(nodes)]
                        data[index] = physical_region
                    except IndexError:
                        raise Exception ( "The facet (%d) was not found to mark: %s" % (i, nodes) )

            # Create and initialise the mesh function
            handler.start_meshfunction("facet_region", highest_dim-1, mesh.num_facets() )
            for index, physical_region in enumerate ( data ):
                handler.add_entity_meshfunction(index, physical_region)
            handler.end_meshfunction()

    # Check that we got all data
    if state == 10:
        print("Conversion done")
    else:
       _error("Missing data, unable to convert \n\ Did you use version 2.0 of the gmsh file format?")

    # Close files
    ifile.close()
示例#22
0

if __name__ == "__main__":

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

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

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

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

    print('num_cells   :', mesh_D.num_cells())
    print('num_vertices:', mesh_D.num_vertices())
    print('cell_type   :', mesh_D.ufl_cell())
    #print('num_facets:', mesh_F.num_facets())
    #print('num_edges:', mesh_F.num_edges())
示例#23
0
def get_1d_matrices(mesh_, N, root=''):
    '''Given mesh construct 1d matrices for GEVP.'''
    if not isinstance(N, (int, float)):
        assert root
        return all([get_1d_matrices(mesh_, n, root) == 0 for n in N])

    mesh_dir = '../plate-beam/py/fem_new/meshes'

    # Zig zag mesh
    if mesh_ == 'nonuniform':
        mesh = 'Pb_zig_zag_bif'
        mesh2d = '%s/%s_%d.xml.gz' % (mesh_dir, mesh, N)
        # mesh1d = '%s/%s_%d_facet_region.xml.gz' % (mesh_dir, mesh, N)
        mesh2d = Mesh(mesh2d)
        # Constructing facet function can be too expensive so here's and
        # alternative
        # mesh1d = get_marked_facets(mesh1d)
    # Structured meshes
    elif mesh_ == 'uniform':
        mesh = mesh_
        N = int(N)
        mesh2d = UnitSquareMesh(N, N)
        # mesh1d = EdgeFunction('size_t', mesh2d, 0)
        # Beam at y = 0.5
        # CompiledSubDomain('near(x[1], 0.5, 1E-10)').mark(mesh1d, 1)

        # Use the above here as well
        # from dolfin import SubsetIterator
        # mesh1d = [e.index() for e in SubsetIterator(mesh1d, 1)]
    mesh1d = '%s/%s_%d_edgelist' % (mesh_dir, mesh, N)
    mesh1d = map(int, np.loadtxt(mesh1d))

    print FunctionSpace(mesh2d, 'CG', 1).dim()

    # Extract 1d
    import sys
    sys.setrecursionlimit(20000)
    mesh = interval_mesh_from_edge_f(mesh2d, mesh1d, 1)[0].pop()

    # Assemble
    V = FunctionSpace(mesh, 'CG', 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    bc = DirichletBC(V, Constant(0), 'on_boundary')

    a = inner(grad(u), grad(v)) * dx
    m = inner(u, v) * dx
    L = inner(Constant(0), v) * dx

    A, _ = assemble_system(a, L, bc)
    M, _ = assemble_system(m, L, bc)

    A, M = A.array(), M.array()

    if root:
        dA = np.diagonal(A, 0)
        uA = np.r_[np.diagonal(A, 1), 0]
        A = np.c_[dA, uA]

        dM = np.diagonal(M, 0)
        uM = np.r_[np.diagonal(M, 1), 0]
        M = np.c_[dM, uM]

        header = 'main and upper diagonals of A, M'
        f = '_'.join([mesh_, str(N)])
        import os
        f = os.path.join(root, f)
        np.savetxt(f, np.c_[A, M], header=header)
        return 0
    else:
        return A, M
示例#24
0
            #                         ).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])


if __name__ == "__main__":
    meshes = []
    for i in range(2):
        mesh_i = Mesh()
        with XDMFFile("meshes/multimesh_%d.xdmf" % i) as infile:
            infile.read(mesh_i)
        meshes.append(mesh_i)
    mfs = []
    for i in range(2):
        mvc = MeshValueCollection("size_t", meshes[i], 1)
        with XDMFFile("meshes/mf_%d.xdmf" % i) as infile:
            infile.read(mvc, "name_to_read")
        mfs.append(cpp.mesh.MeshFunctionSizet(meshes[i], mvc))

    cover = {0: Point(0.5, 0.5)}
    from create_meshes import (inflow, outflow, walls, inner_marker,
                               outer_marker, L, H)
    bc_dict = {
        0: {
示例#25
0
 def get_antarctica_coarse():
     filename = inspect.getframeinfo(inspect.currentframe()).filename
     home = os.path.dirname(os.path.abspath(filename))
     mesh = Mesh(home + '/antarctica/antarctica_50H_5l.xml')
     mesh.coordinates()[:, 2] /= 1000.0
     return mesh
示例#26
0
    def test_convert_triangle(
            self):  # Disabled because it fails, see FIXME below

        # test no. 1
        from dolfin import Mesh, MPI

        fname = os.path.join(os.path.dirname(__file__), "data", "triangle")
        dfname = fname + ".xml"

        # Read triangle file and convert to a dolfin xml mesh file
        meshconvert.triangle2xml(fname, dfname)

        # Read in dolfin mesh and check number of cells and vertices
        mesh = Mesh(dfname)
        self.assertEqual(mesh.num_vertices(), 96)
        self.assertEqual(mesh.num_cells(), 159)

        # Clean up
        os.unlink(dfname)

        # test no. 2
        from dolfin import MPI, Mesh, MeshFunction, \
                           edges, Edge, faces, Face, \
                           SubsetIterator, facets

        fname = os.path.join(os.path.dirname(__file__), "data",
                             "test_Triangle_3")
        dfname = fname + ".xml"
        dfname0 = fname + ".attr0.xml"

        # Read triangle file and convert to a dolfin xml mesh file
        meshconvert.triangle2xml(fname, dfname)

        # Read in dolfin mesh and check number of cells and vertices
        mesh = Mesh(dfname)
        mesh.init()
        mfun = MeshFunction('double', mesh, dfname0)
        self.assertEqual(mesh.num_vertices(), 58)
        self.assertEqual(mesh.num_cells(), 58)

        # Create a size_t MeshFunction and assign the values based on the
        # converted Meshfunction
        cf = MeshFunction("size_t", mesh, mesh.topology().dim())
        cf.array()[mfun.array() == 10.0] = 0
        cf.array()[mfun.array() == -10.0] = 1

        # Meassure total area of cells with 1 and 2 marker
        add = lambda x, y: x + y
        area0 = reduce(add, (Face(mesh, cell.index()).area() \
                             for cell in SubsetIterator(cf, 0)), 0.0)
        area1 = reduce(add, (Face(mesh, cell.index()).area() \
                             for cell in SubsetIterator(cf, 1)), 0.0)
        total_area = reduce(add, (face.area() for face in faces(mesh)), 0.0)

        # Check that all cells in the two domains are either above or below y=0
        self.assertTrue(
            all(cell.midpoint().y() < 0 for cell in SubsetIterator(cf, 0)))
        self.assertTrue(
            all(cell.midpoint().y() > 0 for cell in SubsetIterator(cf, 1)))

        # Check that the areas add up
        self.assertAlmostEqual(area0 + area1, total_area)

        # Measure the edge length of the two edge domains
        #edge_markers = mesh.domains().facet_domains()
        edge_markers = mesh.domains().markers(mesh.topology().dim() - 1)
        self.assertTrue(edge_markers is not None)
        #length0 = reduce(add, (Edge(mesh, e.index()).length() \
        #                    for e in SubsetIterator(edge_markers, 0)), 0.0)
        length0, length1 = 0.0, 0.0
        for item in list(edge_markers.items()):
            if item[1] == 0:
                e = Edge(mesh, int(item[0]))
                length0 += Edge(mesh, int(item[0])).length()
            elif item[1] == 1:
                length1 += Edge(mesh, int(item[0])).length()

        # Total length of all edges and total length of boundary edges
        total_length = reduce(add, (e.length() for e in edges(mesh)), 0.0)
        boundary_length = reduce(add, (Edge(mesh, f.index()).length() \
                          for f in facets(mesh) if f.exterior()), 0.0)

        # Check that the edges add up
        self.assertAlmostEqual(length0 + length1, total_length)
        self.assertAlmostEqual(length1, boundary_length)

        # Clean up
        os.unlink(dfname)
        os.unlink(dfname0)
示例#27
0
 def get_greenland_detailed():
     filename = inspect.getframeinfo(inspect.currentframe()).filename
     home = os.path.dirname(os.path.abspath(filename))
     mesh = Mesh(home + '/greenland/greenland_detailed_mesh.xml')
     mesh.coordinates()[:, 2] /= 100000.0
     return mesh
k = 1

# Magnitude solid body rotation .
Uh = np.pi

# Timestepping
Tend = 2.
dt = Constant(0.02)
num_steps = np.rint(Tend / float(dt))

# Output directory
store_step = 1
outdir = './../../results/SlottedDisk_Rotation_AddDelete/'

# Mesh
mesh = Mesh('./../../meshes/circle_0.xml')
mesh = refine(mesh)
mesh = refine(mesh)
mesh = refine(mesh)

outfile = XDMFFile(mesh.mpi_comm(), outdir + "psi_h.xdmf")

# Set slotted disk
psi0_expr = SlottedDisk(radius=rdisk,
                        center=[xc, yc],
                        width=rwidth,
                        depth=0.,
                        degree=3,
                        lb=lb,
                        ub=ub)
示例#29
0
def save_files_visualization(visualization_folder, dvp_, t, save_deg, mesh,
                             **namespace):
    # Files for storing results
    if not "d_file" in namespace.keys():
        d_file = XDMFFile(
            MPI.comm_world,
            str(visualization_folder.joinpath("displacement.xdmf")))
        v_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("velocity.xdmf")))
        p_file = XDMFFile(MPI.comm_world,
                          str(visualization_folder.joinpath("pressure.xdmf")))
        for tmp_t in [d_file, v_file, p_file]:
            tmp_t.parameters["flush_output"] = True
            tmp_t.parameters["rewrite_function_mesh"] = False

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

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

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

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

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

        namespace.update(return_dict)

    else:
        return_dict = {}

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

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

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

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

    return return_dict
示例#30
0
def mesh_around_1d(mesh, size=1, scale=10, padding=0.05):
    '''
    From a 1d in xd (X > 1) mesh (in XML format) produce a Xd mesh where
    the 1d structure is embedded. Mesh size close to strucure should 
    be size(given as multiple of hmin(), elsewhere scale * size. Padding 
    controls size of the bounding box.
    '''
    dot = mesh.find('.')
    root, ext = mesh[:dot], mesh[dot:]
    assert ext == '.xml' or ext == '.xml.gz', ext

    mesh = Mesh(mesh)
    gdim = mesh.geometry().dim()
    assert gdim > 1 and mesh.topology().dim() == 1

    x = mesh.coordinates()
    mesh.init(1, 0)

    # Compute fall back mesh size:
    assert size > 0
    size = mesh.hmin() * size

    # Don't allow zero padding - collision of lines with bdry segfaults
    # too ofter so we prevent it
    assert padding > 0
    # Finally scale better be positive
    assert scale > 0

    point = (lambda xi: tuple(xi) + (0, ))\
            if gdim == 2 else (lambda xi: tuple(xi))

    geo = '.'.join([root, 'geo'])
    with open(geo, 'w') as outfile:
        # Setup
        outfile.write('SetFactory("OpenCASCADE");\n')
        outfile.write('size = %g;\n' % size)
        outfile.write('SIZE = %g;\n' % (size * scale))

        # Points
        fmt = 'Point(%d) = {%.16f, %.16f, %.16f, size};\n'
        for i, xi in enumerate(x, 1):
            outfile.write(fmt % ((i, ) + point(xi)))
        # Lines
        fmt = 'Line(%d) = {%d, %d};\n'
        for i, cell in enumerate(cells(mesh), 1):
            outfile.write(fmt % ((i, ) + tuple(cell.entities(0) + 1)))

        # BBox
        xmin, xmax = x.min(0), x.max(0)
        padding = (xmax - xmin) * padding / 2.
        xmin -= padding
        xmax += padding
        dx = xmax - xmin

        if gdim == 2 or dx[-1] < 1E-14:  # All points are on a plane
            rect = 'Rectangle(1) = {%g, %g, %g, %g, %g};\n' % (
                xmin[0], xmin[1], 0 if gdim == 2 else xmin[2], dx[0], dx[1])
            outfile.write(rect)
            bbox = 'Surface'
        else:
            box = 'Box(1) = {%g, %g, %g, %g, %g, %g};\n' % (
                xmin[0], xmin[1], xmin[2], dx[0], dx[1], dx[2])
            outfile.write(box)
            bbox = 'Volume'

        # Crack
        for line in xrange(1, mesh.num_cells() + 1):
            outfile.write('Line{%d} In %s{1};\n' % (line, bbox))

        # Add Physical volume/surface
        outfile.write('Physical %s(1) = {1};\n' % bbox)

        # Add Physical surface/line
        lines = ', '.join(
            map(lambda v: '%d' % v, xrange(1,
                                           mesh.num_cells() + 1)))
        outfile.write('Physical Line(1) = {%s};\n' % lines)
    return geo, gdim