コード例 #1
0
ファイル: grdecl.py プロジェクト: opnumten/Splipy
    def to_ifem(self, p, ngeom, ntexture, method='full', irange=[None,None], jrange=[None,None]):
        translate = {
            'emodulus25'    : 'stiffness',
            'kx'            : 'permx',
            'ky'            : 'permy',
            'kz'            : 'permz',
            'poissonratio25': 'poisson'}

        h5_filename = 'textures.h5'
        h5_file = h5py.File(h5_filename, 'w')
        vol, textures = self.texture(p, ngeom, ntexture, method, irange, jrange)

        # augment dataset with missing information
        if 'kx' in textures and not 'ky' in textures:
            textures['ky'] = textures['kx']

        # print information to png-images and hdf5-files
        print(r'<porotexturematerial>')
        for name, data in textures.items():
            # translate to more IFEM-friendly terminology
            if name in translate: name = translate[name]

            h5_file.create_dataset(name, data=data, compression='gzip')
            a, b = min(data.flat), max(data.flat)
            img  = ((data - a) / (b - a) * 255).astype(np.uint8)
            n    = data.shape
            img  = img.reshape(n[0], n[1]*n[2])
            print('  <property file="{}.png" min="{}" max="{}" name="{}" nx="{}" ny="{}" nz="{}"/>'.format(name, a,b, name, n[0], n[1], n[2]))
            cv2.imwrite(name+'.png', img)
        print(r'</porotexturematerial>')
        h5_file.close()
        print(f'Written {h5_filename}')

        with G2('geom.g2') as myfile:
            myfile.write(vol)
コード例 #2
0
    def test_write_and_read_multipatch_surface(self):
        # write teapot to file and test if its there
        teapot = SurfaceFactory.teapot()
        with G2('teapot.g2') as myfile:
            myfile.write(teapot)
        self.assertTrue(os.path.isfile('teapot.g2'))

        # read the written file and compare that it's the same thing
        with G2('teapot.g2') as myfile:
            read_teapot = myfile.read()
        self.assertEqual(len(read_teapot), 32)
        for i in range(32):
            self.assertTrue(np.all(teapot[i].shape == read_teapot[i].shape))

        # clean up after us
        os.remove('teapot.g2')
コード例 #3
0
    def test_read_elementary_curves(self):
        with G2(THIS_DIR + '/geometries/elementary_curves.g2') as myfile:
            my_curves = myfile.read()

        self.assertEqual(len(my_curves), 3)

        # check circle (r=3, center=(1,0,0), xaxis=(1,1,0)
        circle = my_curves[0]
        t = np.linspace(circle.start(0), circle.end(0), 25)
        x = circle(t)
        self.assertTrue(np.allclose((x[:,0]-1)**2 + x[:,1]**2 + x[:,2]**2, 3**2))
        self.assertTrue(np.allclose(circle[0], [3/np.sqrt(2)+1,3/np.sqrt(2),0,1]))

        # check ellipse (r1=3, r2=5, center=(1,0,0), xaxis(0,1,0)
        ellipse = my_curves[1]
        t = np.linspace(ellipse.start(0), ellipse.end(0), 25)
        x = ellipse(t)
        self.assertTrue(np.allclose(ellipse[0], [1,3,0,1]))
        self.assertTrue(np.allclose(ellipse[2], [-4,0,0,1]))

        # check line piece (p1=(1,0,0), direction=(0,6,0), length=4 (times direction))
        line = my_curves[2]
        self.assertAlmostEqual(line.length(), 24)
        self.assertFalse(line.rational)
        self.assertTrue(np.allclose(line[0], [1,0,0]))
コード例 #4
0
    def test_write_and_read_surface(self):
        # write disc to file and test if its there
        disc = SurfaceFactory.disc(type='square')
        with G2('disc.g2') as myfile:
            myfile.write(disc)
        self.assertTrue(os.path.isfile('disc.g2'))

        # read the written file and compare that it's the same thing
        with G2('disc.g2') as myfile:
            read_disc = myfile.read()
        self.assertEqual(len(read_disc), 1)
        read_disc = read_disc[0]
        self.assertTrue(np.all(disc.shape == read_disc.shape))

        # clean up after us
        os.remove('disc.g2')
コード例 #5
0
    def write(self, fn, order=4):
        pids, patches = {}, []
        for i, (name, patch) in enumerate(self.items()):
            pids[name] = i
            diff = [o - order for o in patch.order()]
            patches.append(patch.lower_order(*diff))

        with G2(fn + '.g2') as f:
            f.write(patches)

        dom = xml.Element('geometry')
        dom.attrib['dim'] = str(patches[0].pardim)
        xml.SubElement(dom, 'patchfile').text = fn + '.g2'

        topology = xml.SubElement(dom, 'topology')
        for (master, medge), (slave, sedge, rev,
                              periodic) in self.masters.items():
            mid = pids[master] + 1
            sid = pids[slave] + 1
            if mid > sid:
                mid, sid = sid, mid
                medge, sedge = sedge, medge
            xml.SubElement(topology, 'connection').attrib.update({
                'master':
                str(mid),
                'midx':
                str(medge),
                'slave':
                str(sid),
                'sidx':
                str(sedge),
                'reverse':
                'true' if rev else 'false',
                'periodic':
                'true' if periodic else 'false',
            })
        for patch, direction in self.periodics:
            pid = pids[patch] + 1
            xml.SubElement(topology, 'periodic').attrib.update({
                'patch':
                str(pid),
                'dir':
                str(direction),
            })

        topsets = xml.SubElement(dom, 'topologysets')
        for name, kinds in self.boundaries.items():
            for kind, items in kinds.items():
                topset = xml.SubElement(topsets, 'set')
                topset.attrib.update({'name': name, 'type': kind})
                for patch, number in items:
                    item = xml.SubElement(topset, 'item')
                    item.attrib['patch'] = str(pids[patch] + 1)
                    item.text = str(number)

        xml.ElementTree(dom).write(fn + '.xinp',
                                   encoding='utf-8',
                                   xml_declaration=True,
                                   pretty_print=True,
                                   standalone=False)
コード例 #6
0
    def test_read_elementary_surfaces(self):
        with G2(THIS_DIR + '/geometries/elementary_surfaces.g2') as myfile:
            my_surfaces = myfile.read()

        self.assertEqual(len(my_surfaces), 4)

        # check cylinder ( center=(1,0,0), x-axis=(0,1,0), radius=2)
        cylinder = my_surfaces[0]
        self.assertTrue(cylinder.rational)
        self.assertTrue(np.allclose(cylinder[0,0], [1,2,0,1]))

        # check sphere ( radius=1.5, center=(4,0,0), z-axis=(0,1,1))
        sphere = my_surfaces[1]
        self.assertTrue(sphere.rational)
        self.assertTrue(np.allclose(sphere[0,-1], [4,3/np.sqrt(8),3/np.sqrt(8), 1])) # north pole

        # check disc ( radius=2.5, center=(6,0,0), x-axis=(0,0,-1 ), normal=(1,0,0)
        disc = my_surfaces[2]
        self.assertTrue(disc.rational)
        self.assertTrue(np.allclose(disc[ 0,0], [6,0,0,1]))    # center
        self.assertTrue(np.allclose(disc[-1,0], [6,0,-2.5,1])) # center+x_axis

        # check torus ( ...)
        torus = my_surfaces[3]
        self.assertTrue(torus.rational)
コード例 #7
0
ファイル: g2_test.py プロジェクト: yukoba/Splipy
 def test_read_doublespaced(self):
     with G2(THIS_DIR + '/test_geometries/lshape.g2'
             ) as myfile:  # controlpoints are separated by two spaces
         one_surf = myfile.read()
     self.assertEqual(len(one_surf), 1)
     self.assertEqual(one_surf[0].shape[0], 3)
     self.assertEqual(one_surf[0].shape[1], 2)
コード例 #8
0
    def test_write_and_read_volume(self):
        # write sphere to file and test if its there
        sphere = VolumeFactory.sphere(type='square')
        with G2('sphere.g2') as myfile:
            myfile.write(sphere)
        self.assertTrue(os.path.isfile('sphere.g2'))

        # read the written file and compare that it's the same thing
        with G2('sphere.g2') as myfile:
            read_sphere = myfile.read()
        self.assertEqual(len(read_sphere), 1)
        read_sphere = read_sphere[0]
        self.assertTrue(np.all(sphere.shape == read_sphere.shape))
        self.assertTrue(sphere.rational == read_sphere.rational)

        # clean up after us
        os.remove('sphere.g2')
コード例 #9
0
ファイル: SplineModel.py プロジェクト: juampatronics/Splipy
    def write(self, filename):
        lines = [
            "<?xml version='1.0' encoding='utf-8' standalone='no'?>",
            "<topology>",
        ]

        for connection in self.connections():
                lines.append('  <connection master="{}" slave="{}" midx="{}" sidx="{}" orient="{}"/>'.format(
                    connection.master,
                    connection.slave,
                    connection.midx,
                    connection.sidx,
                    connection.orient,
                ))

        lines.extend(["</topology>"])

        with open(filename + '-topology.xinp', 'wb') as f:
            f.write('\n'.join(lines).encode('utf-8') + b'\n')

        lines = [
            "<?xml version='1.0' encoding='utf-8' standalone='no'?>",
            "<topologysets>",
        ]

        names = sorted({
            node.name for node in self.model.catalogue.nodes(self.model.pardim - 1)
            if node.name is not None
        })

        for name in names:
            entries = {}
            for node in self.model.catalogue.nodes(self.model.pardim - 1):
                if node.name != name:
                    continue
                parent = node.owner
                sub_idx = next(idx for idx, sub in enumerate(parent.lower_nodes[self.model.pardim - 1]) if sub is node)
                entries.setdefault(self.node_ids[parent], set()).add(sub_idx)
            if entries:
                kind = {2: 'face', 1: 'edge', 0: 'vertex'}[self.model.pardim - 1]
                lines.append('  <set name="{}" type="{}">'.format(name, kind))
                for node_id, sub_ids in entries.items():
                    lines.append('    <item patch="{}">{}</item>'.format(
                        node_id + 1,
                        ' '.join(str(i+1) for i in sorted(sub_ids))
                    ))
                lines.append('  </set>')

        lines.extend(["</topologysets>"])

        with open(filename + '-topologysets.xinp', 'wb') as f:
            f.write('\n'.join(lines).encode('utf-8') + b'\n')

        with G2(filename + '.g2') as f:
            f.write([n.obj for n in self.nodes])
コード例 #10
0
    def test_from_step(self):
        # quite large nasty g2 file which contains cylinders, planes, trimming etc

        with G2(THIS_DIR + '/geometries/winglet_from_step.g2') as myfile:
            my_surfaces = myfile.read()
            trim_curves = myfile.trimming_curves

        # we only test that we are able to parse this file. No claims as to the
        # correctness of this parsing
        self.assertEqual(len(my_surfaces), 19)
        self.assertEqual(len(trim_curves), 122)
コード例 #11
0
 def test_edge_curves_finitestrain_lshape(self):
     # Create an L-shape geometry with an interior 270-degree angle at the origin (u=.5, v=1)
     c1 = CurveFactory.polygon([[-1, 1], [-1, -1], [1, -1]])
     c2 = CurveFactory.polygon([[1, -1], [1, 0]])
     c3 = CurveFactory.polygon([[1, 0], [0, 0], [0, 1]])
     c4 = CurveFactory.polygon([[0, 1], [-1, 1]])
     c1.refine(2).raise_order(1)
     c2.refine(2).raise_order(1)
     surf = SurfaceFactory.edge_curves([c1, c2, c3, c4],
                                       type='finitestrain')
     from splipy.io import G2
     with G2('out.g2') as myfile:
         myfile.write(surf)
     # the quickest way to check for self-intersecting geometry here is that
     # the normal is pointing the wrong way: down z-axis instead of up
     surf.reparam().set_dimension(3)
     self.assertTrue(surf.normal(0.5, 0.98)[2] > 0.0)
     # also check that no controlpoints leak away into the first quadrant
     self.assertFalse(
         np.any(np.logical_and(surf[:, :, 0] > 1e-10,
                               surf[:, :, 1] > 1e-10)))
コード例 #12
0
ファイル: poisson.py プロジェクト: TheBB/aroma
def ifem_solve(root, mu, i):
    with open('case.xinp') as f:
        template = Template(f.read())
    with open(root / 'case.xinp', 'w') as f:
        f.write(template.render(geometry='square.g2', **mu))

    patch = Surface()
    patch.set_dimension(3)
    with G2(str(root / 'square.g2')) as g2:
        g2.write(patch)
        try:
            g2.fstream.close()
        except:
            pass

    result = run([
        '/home/eivind/repos/IFEM/Apps/Poisson/build/bin/Poisson', 'case.xinp',
        '-adap', '-hdf5'
    ],
                 cwd=root,
                 stdout=PIPE,
                 stderr=PIPE)
    result.check_returncode()

    with h5py.File(root / 'case.hdf5', 'r') as h5:
        final = str(len(h5) - 1)
        group = h5[final]['Poisson-1']
        patchbytes = group['basis']['1'][:].tobytes()
        geompatch = lr.LRSplineSurface(patchbytes)
        coeffs = group['fields']['u']['1'][:]
        solpatch = geompatch.clone()
        solpatch.controlpoints = coeffs.reshape(len(solpatch), -1)

        with open(f'poisson-mesh-single-{i}.ps', 'wb') as f:
            geompatch.write_postscript(f)

        return geompatch, solpatch
コード例 #13
0
 def test_read_rational_surf(self):
     with G2(THIS_DIR + '/geometries/torus.g2') as myfile:
         surf = myfile.read()
     self.assertEqual(len(surf), 1)
     surf = surf[0]
     self.assertTrue(surf.rational)
コード例 #14
0
ファイル: write.py プロジェクト: yukoba/Splipy
# Examples on how to write geometries to file
#
# Author:    Kjetil Andre Johannessen
# Institute: Norwegian University of Science and Technology (NTNU)
# Date:      March 2016
#

from sys import path
path.append('../')
from splipy.io import G2, STL
import splipy.surface_factory as surfaces

# create a NURBS torus
torus = surfaces.torus(minor_r=1, major_r=4)


# STL files are tessellated linear triangles. View with i.e. meshlab
with STL('torus.stl') as my_file:
    my_file.write(torus, n=(50, 150)) # specify resolution of 50x150 evaluation pts


# G2 files are native GoTools (http://www.sintef.no/projectweb/geometry-toolkits/gotools/)
with G2('torus.g2') as my_file:
    my_file.write(torus)
コード例 #15
0
def export(polygon,
           project,
           manager,
           boundary_mode='exterior',
           rotation_mode='none',
           coords='utm33n',
           resolution=None,
           maxpts=None,
           format='png',
           structured=False,
           colormap='Terrain',
           invert=False,
           texture=False,
           zero_sea_level=True,
           filename=None,
           directory=None,
           axis_align=False):

    # Sanitize parameters
    image_mode = is_image_format(format)
    if not supports_texture(format):
        texture = False
    if not supports_structured_choice(format):
        structured = is_structured_format(format)

    if format == 'tiff' and coords != 'utm33n':
        raise ValueError(
            'GeoTIFF output for other formats than UTM33N is not supported')

    manager.report_max(4 if texture else 3)

    manager.report_message('Generating geometry')
    if structured:
        (in_x, in_y), (out_x, out_y), trf = polygon.generate_meshgrid(
            boundary_mode,
            rotation_mode,
            in_coords=project.coords,
            out_coords=coords,
            resolution=resolution,
            maxpts=maxpts,
            axis_align=axis_align,
        )
    else:
        (in_x, in_y), (out_x, out_y), tri = polygon.generate_triangulation(
            in_coords=project.coords,
            out_coords=coords,
            resolution=resolution,
        )
    manager.increment_progress()

    if texture:
        manager.report_message('Generating texture coordinates')
        left = np.min(out_x)
        right = np.max(out_x)
        down = np.min(out_y)
        up = np.max(out_y)
        uvcoords = np.stack([(out_x - left) / (right - left),
                             (out_y - down) / (up - down)],
                            axis=out_x.ndim)
        manager.increment_progress()

    manager.report_message('Generating data')
    data = polygon.interpolate(project, in_x, in_y)
    if not zero_sea_level:
        data -= np.min(data)
    manager.increment_progress()

    manager.report_message('Saving file')
    if filename is None:
        filename = hashlib.sha256(data.data).hexdigest() + '.' + format
        filename = Path(directory) / filename

    if image_mode:
        array_to_image(data, format, filename, cmap=colormap, invert=invert)
    elif format == 'g2':
        from splipy import Surface, BSplineBasis
        from splipy.io import G2
        cpts = np.stack([out_x, out_y, data[..., 0]], axis=2)
        knots = [[0.0] + list(map(float, range(n))) + [float(n - 1)]
                 for n in data.shape[:2]]
        bases = [BSplineBasis(order=2, knots=kts) for kts in knots]
        srf = Surface(*bases, cpts, raw=True)
        with G2(filename) as g2:
            g2.write(srf)
    elif format == 'stl':
        from stl.mesh import Mesh as STLMesh
        mesh = STLMesh(np.zeros(tri.shape[0], STLMesh.dtype))
        mesh.vectors[:, :, 0] = out_x[tri]
        mesh.vectors[:, :, 1] = out_y[tri]
        mesh.vectors[:, :, 2] = data[tri, 0]
        mesh.save(filename)
    elif format in ('vtk', 'vtu', 'vts'):
        import vtk
        import vtk.util.numpy_support as vtknp

        pointsarray = np.stack([out_x.flat, out_y.flat, data.flat], axis=1)
        points = vtk.vtkPoints()
        points.SetData(vtknp.numpy_to_vtk(pointsarray))

        if structured:
            grid = vtk.vtkStructuredGrid()
            grid.SetDimensions(*out_x.shape[::-1], 1)
        else:
            ncells = len(tri)
            cellarray = np.concatenate(
                [3 * np.ones((ncells, 1), dtype=int), tri], axis=1)
            cells = vtk.vtkCellArray()
            cells.SetCells(ncells,
                           vtknp.numpy_to_vtkIdTypeArray(cellarray.ravel()))
            grid = vtk.vtkUnstructuredGrid()
            grid.SetCells(vtk.VTK_TRIANGLE, cells)

        grid.SetPoints(points)

        if texture:
            grid.GetPointData().SetTCoords(
                vtknp.numpy_to_vtk(uvcoords.reshape(-1, 2)))

        if format == 'vts':
            writer = vtk.vtkXMLStructuredGridWriter()
        elif format == 'vtu':
            writer = vtk.vtkXMLUnstructuredGridWriter()
        else:
            writer = vtk.vtkStructuredGridWriter(
            ) if structured else vtk.vtkUnstructuredGridWriter()

        writer.SetFileName(filename)
        writer.SetInputData(grid)
        writer.Write()
    elif format == 'tiff':
        import tifffile
        tifffile.imwrite(
            filename,
            data[:, ::-1].T,
            extratags=[
                # GeoKeyDirectoryTag
                (
                    34735,
                    'h',
                    28,
                    (
                        1,
                        1,
                        1,
                        6,  # Version and number of geo keys
                        1024,
                        0,
                        1,
                        1,  # GTModelTypeGeoKey (2D projected CRS)
                        1025,
                        0,
                        1,
                        1,  # GTRasterTypeGeoKey (pixels denote areas)
                        2048,
                        0,
                        1,
                        4258,  # GeodeticCRSGeoKey (ETRS89)
                        2050,
                        0,
                        1,
                        6258,  # GeodeticDatumGeoKey (ETRS89)
                        2051,
                        0,
                        1,
                        8901,  # PrimeMeridianGeoKey (Greenwich)
                        3072,
                        0,
                        1,
                        25833,  # ProjectedCRSGeoKey (ETRS89: UTM33N)
                    ),
                    True),
                # ModelTransformationTag
                (34264, 'd', 16, tuple(trf.flat), True),
            ])

    manager.increment_progress()

    return filename
コード例 #16
0
    def test_orient(self):
        connections = [
            [
                IFEMConnection(1, 2, 2, 1, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 4, 3, 0),
                IFEMConnection(2, 6, 6, 5, 0),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 1, 3),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 3, 3, 1),
                IFEMConnection(2, 6, 5, 5, 1),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 2, 2),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 3, 3, 2),
                IFEMConnection(2, 6, 6, 5, 3),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 2, 1),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 4, 3, 3),
                IFEMConnection(2, 6, 5, 5, 2),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 3, 1),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 2, 3, 1),
                IFEMConnection(2, 6, 5, 5, 4),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 5, 5),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 3, 3, 4),
                IFEMConnection(2, 6, 2, 5, 5),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 2, 4, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 6, 5, 0),
                IFEMConnection(2, 4, 2, 3, 2),
                IFEMConnection(2, 6, 6, 5, 6),
                IFEMConnection(3, 4, 2, 1, 0),
                IFEMConnection(3, 7, 6, 5, 0),
                IFEMConnection(4, 8, 6, 5, 0),
                IFEMConnection(5, 6, 2, 1, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 2, 1, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 1, 1),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 6, 4),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 4, 1, 1),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 5, 4),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 1, 0),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 4, 1, 4),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 6, 0),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 3, 1),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 2, 1, 6),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 3, 5),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 1, 5),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 5, 1, 4),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 1, 7),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 4, 5),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 5, 1, 1),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 1, 2),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 5, 5),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 3, 1, 0),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 5, 7),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 2, 2),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 3, 1, 5),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 3, 6),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 2, 4),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 6, 1, 5),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
            [
                IFEMConnection(1, 2, 6, 5, 0),
                IFEMConnection(1, 3, 4, 3, 0),
                IFEMConnection(1, 5, 2, 1, 0),
                IFEMConnection(2, 4, 4, 4, 7),
                IFEMConnection(2, 6, 2, 1, 0),
                IFEMConnection(3, 4, 6, 2, 7),
                IFEMConnection(3, 7, 2, 1, 0),
                IFEMConnection(4, 8, 5, 1, 7),
                IFEMConnection(5, 7, 4, 3, 0),
                IFEMConnection(5, 6, 6, 5, 0),
                IFEMConnection(6, 8, 4, 3, 0),
                IFEMConnection(7, 8, 6, 5, 0)
            ],
        ]

        for i, ref_topo in enumerate(connections):
            model = SplineModel(3, 3)
            with G2(THIS_DIR +
                    '/geometries/cube-8-orient{}.g2'.format(i)) as myfile:
                model.add(myfile.read())

            writer = IFEMWriter(model)
            my_topo = list(writer.connections())

            my_topo = sorted(my_topo, key=lambda c: c.slave)
            my_topo = sorted(my_topo, key=lambda c: c.master)
            ref_topo = sorted(ref_topo, key=lambda c: c.slave)
            ref_topo = sorted(ref_topo, key=lambda c: c.master)

            for my_con, ref_con in zip(my_topo, ref_topo):
                assert my_con == ref_con
            assert len(my_topo) == len(ref_topo)