예제 #1
0
    def set_quad_grid(self, name, nodes, elements, color, line_width=5, opacity=1.):
        """
        Makes a CQUAD4 grid
        """
        self.create_alternate_vtk_grid(name, color=color, line_width=line_width,
                                       opacity=opacity, representation='wire')

        nnodes = nodes.shape[0]
        nquads = elements.shape[0]
        #print(nodes)
        if nnodes == 0:
            return
        if nquads == 0:
            return

        #print('adding quad_grid %s; nnodes=%s nquads=%s' % (name, nnodes, nquads))
        assert isinstance(nodes, np.ndarray), type(nodes)

        points = numpy_to_vtk_points(nodes)
        grid = self.alt_grids[name]
        grid.SetPoints(points)

        etype = 9  # vtk.vtkQuad().GetCellType()
        create_vtk_cells_of_constant_element_type(grid, elements, etype)

        self._add_alt_actors({name : self.alt_grids[name]})

        #if name in self.geometry_actors:
        self.geometry_actors[name].Modified()
예제 #2
0
    def _create_cart3d_free_edges(self, model, nodes, elements):
        """creates the free edges to help identify unclosed models"""
        free_edges_array = model.get_free_edges(elements)
        nfree_edges = len(free_edges_array)

        if nfree_edges:
            npoints = 2 * nfree_edges
            if 'free_edges' not in self.gui.alt_grids:
                self.gui.create_alternate_vtk_grid('free_edges',
                                                   color=PINK_FLOAT,
                                                   line_width=3,
                                                   opacity=1.0,
                                                   representation='surface')

            alt_grid = self.gui.alt_grids['free_edges']
            etype = 3  # vtk.vtkLine().GetCellType()
            elements2 = np.arange(0, npoints,
                                  dtype='int32').reshape(nfree_edges, 2)
            create_vtk_cells_of_constant_element_type(alt_grid, elements2,
                                                      etype)

            #alt_grid.Allocate(nfree_edges, 1000)
            free_edge_nodes = nodes[free_edges_array.ravel(), :]
            points = numpy_to_vtk_points(free_edge_nodes)
            alt_grid.SetPoints(points)

        else:
            # TODO: clear free edges
            pass

        if 'free_edges' in self.gui.alt_grids:
            self.gui._add_alt_actors(self.gui.alt_grids)
            self.gui.geometry_actors['free_edges'].Modified()
            if hasattr(self.gui.geometry_actors['free_edges'], 'Update'):
                self.gui.geometry_actors['free_edges'].Update()
예제 #3
0
    def load_stl_geometry(self, stl_filename, name='main', plot=True):
        #print("load_stl_geometry...")
        skip_reading = self.gui._remove_old_geometry(stl_filename)
        if skip_reading:
            return

        model = read_stl(stl_filename,
                         remove_elements_with_bad_normals=True,
                         log=self.gui.log,
                         debug=False)
        #self.model_type = model.model_type
        nodes = model.nodes
        elements = model.elements

        normals = model.get_normals(elements, stop_on_failure=False)
        areas = model.get_area(elements, stop_on_failure=False)
        #nnormals = model.get_normals_at_nodes(elements)
        self.gui.nnodes = nodes.shape[0]
        self.gui.nelements = elements.shape[0]

        self.gui.log.info('nnodes=%s nelements=%s' %
                          (self.gui.nnodes, self.gui.nelements))
        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        points = numpy_to_vtk_points(nodes)
        self.gui.nid_map = {}
        #elem.SetNumberOfPoints(nnodes)

        assert nodes is not None
        unused_nnodes = nodes.shape[0]
        xmax, ymax, zmax = nodes.max(axis=0)
        xmin, ymin, zmin = nodes.min(axis=0)
        self.gui.log.info('xmax=%s xmin=%s' % (xmax, xmin))
        self.gui.log.info('ymax=%s ymin=%s' % (ymax, ymin))
        self.gui.log.info('zmax=%s zmin=%s' % (zmax, zmin))
        dim_max = max(xmax - xmin, ymax - ymin, zmax - zmin)
        self.gui.create_global_axes(dim_max)

        etype = 5  # vtkTriangle().GetCellType()
        create_vtk_cells_of_constant_element_type(grid, elements, etype)

        grid.SetPoints(points)
        grid.Modified()
        if hasattr(grid, 'Update'):  # pragma: no cover
            grid.Update()

        # loadSTLResults - regions/loads
        self.gui.scalarBar.VisibilityOff()
        self.gui.scalarBar.Modified()

        cases = OrderedDict()
        self.gui.isubcase_name_map = {}
        ID = 1

        form, cases, node_ids, element_ids = self._fill_stl_case(
            cases, ID, elements, nodes, normals, areas)
        self.gui.node_ids = node_ids
        self.gui.element_ids = element_ids
        self.gui._finish_results_io2(form, cases)
예제 #4
0
    def load_bedge_geometry(self, bedge_filename, name='main', plot=True):
        #skip_reading = self.remove_old_openfoam_geometry(openfoam_filename)
        #if skip_reading:
        #    return

        self.gui.modelType = 'bedge'

        model = read_bedge(bedge_filename)
        self.gui.log.info('bedge_filename = %s' % bedge_filename)
        nnodes = model.nodes.shape[0]
        nbars = model.bars.shape[0]
        nelements = nbars

        nodes = model.nodes
        self.gui.nelements = nelements
        self.gui.nnodes = nnodes

        self.gui.log.debug("nNodes = %s" % self.gui.nnodes)
        self.gui.log.debug("nElements = %s" % self.gui.nelements)
        assert nelements > 0, nelements

        black = (0., 0., 0.)
        self.gui.create_alternate_vtk_grid('nodes',
                                           color=black,
                                           line_width=5,
                                           opacity=1.,
                                           point_size=3,
                                           representation='point')
        alt_grid = self.gui.alt_grids['nodes']
        alt_grid.Allocate(nnodes, 1000)

        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        points = numpy_to_vtk_points(nodes)

        mmax = np.amax(nodes, axis=0)
        mmin = np.amin(nodes, axis=0)
        unused_dim_max = (mmax - mmin).max()
        self.gui.log.info('max = %s' % mmax)
        self.gui.log.info('min = %s' % mmin)
        #print('dim_max =', dim_max)
        #self.update_axes_length(dim_max)

        etype = 1  # vtk.vtkVertex().GetCellType()
        #elements = np.arange(0, len(nodes), dtype='int32')
        #assert len(elements) == len(nodes)
        #create_vtk_cells_of_constant_element_type(alt_grid, elements, etype)
        for inode, unused_node in enumerate(nodes):
            elem = vtk.vtkVertex()
            elem.GetPointIds().SetId(0, inode)
            alt_grid.InsertNextCell(etype, elem.GetPointIds())

        bars = model.bars

        etype = 3  # vtkLine().GetCellType()
        create_vtk_cells_of_constant_element_type(grid, bars, etype)

        self.gui.nelements = nelements
        alt_grid.SetPoints(points)
        grid.SetPoints(points)
        grid.Modified()
        if hasattr(grid, 'Update'):  # pragma: no cover
            grid.Update()
        #print("updated grid")

        # loadBedgeResults - regions/loads
        #self.TurnTextOn()
        self.gui.scalarBar.VisibilityOn()
        self.gui.scalarBar.Modified()

        self.gui.isubcase_name_map = {1: ['AFLR BEDGE', '']}
        cases = OrderedDict()
        ID = 1

        self.gui._add_alt_actors(self.gui.alt_grids)
        form, cases = self._fill_bedge_case(bedge_filename, cases, ID, nnodes,
                                            nelements, model)
        if plot:
            self.gui._finish_results_io2(form, cases)
예제 #5
0
    def load_degen_geom_geometry(self,
                                 csv_filename,
                                 name='main',
                                 plot=True):  # pragma: no cover
        #key = self.case_keys[self.icase]
        #case = self.result_cases[key]

        skip_reading = self._remove_old_adb_geometry(csv_filename)
        if skip_reading:
            return

        model = DegenGeom(log=self.log, debug=False)
        self.model_type = 'vspaero'
        #self.model_type = model.model_type
        model.read_degen_geom(csv_filename)
        nodes = []
        elements = []
        inid = 0
        for name, comps in sorted(model.components.items()):
            self.log.debug('name = %r' % name)
            #print(comps)
            #print('------------')
            for comp in comps:
                self.log.info(comp)
                nnodes = comp.xyz.shape[0]
                nodes.append(comp.xyz)
                is_elem = np.linalg.norm(comp.elements, axis=1) > 0
                elements.append(comp.elements[is_elem] + inid)
                inid += nnodes

        if len(nodes) == 1:
            nodes = nodes[0]
            elements = elements[0]
        else:
            nodes = np.vstack(nodes)
            elements = np.vstack(elements)

        nnodes = nodes.shape[0]
        nelements = elements.shape[0]
        self.nnodes = nnodes
        self.nelements = nelements

        self.grid.Allocate(self.nelements, 1000)
        #vectorReselt.SetNumberOfComponents(3)
        self.nid_map = {}

        assert nodes is not None

        #print("nxyz_nodes=%s" % nxyz_nodes)
        mmax = amax(nodes, axis=0)

        mmin = amin(nodes, axis=0)
        dim_max = (mmax - mmin).max()
        self.create_global_axes(dim_max)

        points = numpy_to_vtk_points(nodes)
        #self.log.info('nxyz_nodes=%s nwake_nodes=%s total=%s' % (
        #nnodes, nwake_nodes, nxyz_nodes + nwake_nodes))
        #self.log.info('nxyz_elements=%s nwake_elements=%s total=%s' % (
        #nxyz_elements, nwake_elements, nxyz_elements + nwake_elements))

        elements -= 1
        etype = 9  # vtkQuad().GetCellType()
        create_vtk_cells_of_constant_element_type(self.grid, elements, etype)

        self.grid.SetPoints(points)
        self.grid.Modified()
        if hasattr(self.grid, 'Update'):
            self.grid.Update()
        #self.log_info("updated grid")

        # load results - regions/loads
        self.scalarBar.VisibilityOn()
        self.scalarBar.Modified()

        #mach = model.machs[0]
        #alpha = model.alphas[0]
        #beta = model.betas[0]
        #note = ':  Mach=%.2f, alpha=%.1f, beta=%.1f' % (mach, alpha, beta)
        note = 'name=%s' % name
        self.isubcase_name_map = {1: ['OpenVSP%s' % note, '']}
        cases = {}
        ID = 1

        form, cases = self._fill_degen_geom_case(cases, ID, model, nnodes,
                                                 nelements)
        self._finish_results_io2(form, cases)
예제 #6
0
    def load_tetgen_geometry(self, smesh_filename, name='main', plot=True):
        skip_reading = self.gui._remove_old_geometry(smesh_filename)
        if skip_reading:
            return

        model = Tetgen(log=self.gui.log, debug=False)

        base_filename, ext = os.path.splitext(smesh_filename)
        ext = ext.lower()
        node_filename = base_filename + '.node'
        ele_filename = base_filename + '.ele'
        if ext == '.smesh':
            dimension_flag = 2
        elif ext == '.ele':
            dimension_flag = 3
        else:
            raise RuntimeError('unsupported extension.  Use "smesh" or "ele".')
        model.read_tetgen(node_filename, smesh_filename, ele_filename,
                          dimension_flag)
        nodes = model.nodes
        tris = model.tris
        tets = model.tets
        nnodes = nodes.shape[0]

        self.gui.nnodes = nodes.shape[0]
        ntris = 0
        ntets = 0
        if dimension_flag == 2:
            ntris = tris.shape[0]
        elif dimension_flag == 3:
            ntets = tets.shape[0]
        else:
            raise RuntimeError()
        nelements = ntris + ntets
        self.gui.nelements = nelements

        #print("nnodes = ",self.gui.nnodes)
        #print("nelements = ", self.gui.nelements)

        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        assert nodes is not None
        points = numpy_to_vtk_points(nodes)
        self.gui.nid_map = {}

        #elements -= 1
        if dimension_flag == 2:
            etype = 5  # vtkTriangle().GetCellType()
            create_vtk_cells_of_constant_element_type(grid, tris, etype)
        elif dimension_flag == 3:
            etype = 10  # vtkTetra().GetCellType()
            create_vtk_cells_of_constant_element_type(grid, tets, etype)
        else:
            raise RuntimeError('dimension_flag=%r; expected=[2, 3]' %
                               dimension_flag)

        grid.SetPoints(points)
        grid.Modified()
        if hasattr(grid, 'Update'):  # pragma: no cover
            grid.Update()

        # loadTetgenResults - regions/loads
        self.gui.scalarBar.VisibilityOff()
        self.gui.scalarBar.Modified()

        form, cases, node_ids, element_ids = self._fill_tetgen_case(
            nnodes, nelements)
        self.gui.node_ids = node_ids
        self.gui.element_ids = element_ids
        self.gui._finish_results_io2(form, cases, reset_labels=True)
예제 #7
0
    def load_cart3d_geometry(self, cart3d_filename, name='main', plot=True):
        """
        The entry point for Cart3d geometry loading.

        Parameters
        ----------
        cart3d_filename : str
            the cart3d filename to load
        name : str
            the name of the "main" actor for the GUI
        plot : bool; default=True
            should the model be generated or should we wait until
            after the results are loaded
        """
        skip_reading = self._remove_old_cart3d_geometry(cart3d_filename)
        if skip_reading:
            return

        self.gui.eid_maps[name] = {}
        self.gui.nid_maps[name] = {}
        model = read_cart3d(cart3d_filename, log=self.gui.log, debug=False)
        self.gui.model_type = 'cart3d'
        nodes = model.nodes
        elements = model.elements
        regions = model.regions
        loads = model.loads

        self.gui.nnodes = model.npoints
        self.gui.nelements = model.nelements

        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        #if 0:
        #fraction = 1. / self.nnodes  # so you can color the nodes by ID
        #for nid, node in sorted(iteritems(nodes)):
        #self.grid_result.InsertNextValue(nid * fraction)

        assert nodes is not None
        #nnodes = nodes.shape[0]

        mmax = nodes.max(axis=0)
        mmin = nodes.min(axis=0)
        dim_max = (mmax - mmin).max()
        xmax, ymax, zmax = mmax
        xmin, ymin, zmin = mmin
        self.gui.log_info("xmin=%s xmax=%s dx=%s" % (xmin, xmax, xmax - xmin))
        self.gui.log_info("ymin=%s ymax=%s dy=%s" % (ymin, ymax, ymax - ymin))
        self.gui.log_info("zmin=%s zmax=%s dz=%s" % (zmin, zmax, zmax - zmin))
        self.gui.create_global_axes(dim_max)
        points = numpy_to_vtk_points(nodes)

        #assert elements.min() == 0, elements.min()

        etype = 5  # vtkTriangle().GetCellType()
        create_vtk_cells_of_constant_element_type(grid, elements, etype)

        grid.SetPoints(points)
        grid.Modified()
        if hasattr(grid, 'Update'):  # pragma: no cover
            grid.Update()
        self._create_cart3d_free_edges(model, nodes, elements)

        # loadCart3dResults - regions/loads
        self.gui.scalarBar.VisibilityOn()
        self.gui.scalarBar.Modified()

        assert loads is not None
        if 'Mach' in loads:
            avg_mach = mean(loads['Mach'])
            note = ':  avg(Mach)=%g' % avg_mach
        else:
            note = ''
        self.gui.isubcase_name_map = {1: ['Cart3d%s' % note, '']}
        cases = OrderedDict()
        ID = 1
        form, cases, icase, node_ids, element_ids, data_map_dict = _fill_cart3d_geometry_objects(
            cases, ID, nodes, elements, regions, model)
        self.data_map = data_map_dict

        mach, unused_alpha, unused_beta = self._create_box(
            cart3d_filename, ID, form, cases, icase, regions)
        #mach = None
        _fill_cart3d_results(cases, form, icase, ID, loads, model, mach)

        self.gui.node_ids = node_ids
        self.gui.element_ids = element_ids
        self.gui._finish_results_io2(form, cases)
예제 #8
0
    def load_usm3d_geometry(self, cogsg_filename, name='main', plot=True):
        skip_reading = self.parent._remove_old_geometry(cogsg_filename)
        if skip_reading:
            return

        self.parent.eid_maps[name] = {}
        self.parent.nid_maps[name] = {}
        model = Usm3d(log=self.parent.log, debug=False)

        base_filename, ext = os.path.splitext(cogsg_filename)
        #node_filename = base_filename + '.node'
        #ele_filename = base_filename + '.ele'
        if ext == '.cogsg':
            dimension_flag = 3
        #elif ext == '.ele':
        #dimension_flag = 3
        else:
            raise RuntimeError(
                'unsupported extension.  Use "cogsg" or "front".')

        read_loads = True
        nodes, tris_tets, tris, bcs, mapbc, loads, flo_filename = model.read_usm3d(
            base_filename, dimension_flag, read_loads=read_loads)
        del tris_tets
        nodes = model.nodes
        tris = model.tris
        tets = model.tets
        bcs = model.bcs
        mapbc = model.mapbc
        loads = model.loads

        self.parent.out_filename = None
        if flo_filename is not None:
            self.parent.out_filename = flo_filename

        bcmap_to_bc_name = model.bcmap_to_bc_name

        self.parent.nnodes = nodes.shape[0]
        ntris = 0
        ntets = 0
        if tris is not None:
            ntris = tris.shape[0]

        if dimension_flag == 2:
            pass
        elif dimension_flag == 3:
            ntets = tets.shape[0]
            ntets = 0
        else:
            raise RuntimeError()
        self.parent.nelements = ntris + ntets

        self.parent.log.debug("nnodes = %i" % self.parent.nnodes)
        self.parent.log.debug("nelements = %i" % self.parent.nelements)

        grid = self.parent.grid
        grid.Allocate(self.parent.nelements, 1000)

        self.parent.nid_map = {}
        self.parent.eid_map = {}

        assert nodes is not None
        unused_nnodes = nodes.shape[0]

        points = numpy_to_vtk_points(nodes)
        if ntris:
            self.parent.element_ids = np.arange(1, ntris + 1, dtype='int32')
            etype = 5  # vtkTriangle().GetCellType()
            create_vtk_cells_of_constant_element_type(grid, tris, etype)
        else:
            ntets = tets.shape[0]
            self.parent.element_ids = np.arange(1, ntets + 1, dtype='int32')

        if dimension_flag == 2:
            pass
        elif dimension_flag == 3:
            if ntets:
                etype = 10  # vtkTetra().GetCellType()
                assert tets.max() > 0, tets.min()
                create_vtk_cells_of_constant_element_type(grid, tets, etype)
        else:
            raise RuntimeError('dimension_flag=%r' % dimension_flag)

        grid.SetPoints(points)
        grid.Modified()
        if hasattr(grid, 'Update'):  # pragma: no cover
            grid.Update()

        # regions/loads
        self.parent.scalarBar.Modified()

        cases = OrderedDict()
        form = []
        form, cases = self._fill_usm3d_results(cases,
                                               form,
                                               bcs,
                                               mapbc,
                                               bcmap_to_bc_name,
                                               loads,
                                               is_geometry=True)
        self.parent._finish_results_io2(form, cases)
예제 #9
0
    def load_panair_geometry(self, panair_filename, name='main', plot=True):
        model_name = name
        self.gui.nid_map = {}
        #key = self.case_keys[self.icase]
        #case = self.result_cases[key]

        skip_reading = self.gui._remove_old_geometry(panair_filename)
        if skip_reading:
            return

        model = PanairGrid(log=self.gui.log, debug=self.gui.debug)
        self.gui.model_type = model.model_type
        model.read_panair(panair_filename)
        self.gui.geom_model = model
        # get_wakes=True shows explicit wakes
        #
        # TODO: bad for results...what about just not adding it to the patches/bcs?
        nodes, elements, regions, kt, cp_norm = model.get_points_elements_regions(
            get_wakes=True)

        self.gui.nnodes = len(nodes)
        self.gui.nelements = len(elements)

        #print("nnodes = ",self.nnodes)
        #print("nelements = ", self.nelements)

        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        points = vtk.vtkPoints()
        points.SetNumberOfPoints(self.gui.nnodes)

        assert len(nodes) > 0
        mmax = amax(nodes, axis=0)
        mmin = amin(nodes, axis=0)
        dim_max = (mmax - mmin).max()
        self.gui.create_global_axes(dim_max)
        points = numpy_to_vtk_points(nodes)

        assert len(elements) > 0
        elem = vtkQuad()
        quad_type = elem.GetCellType()
        create_vtk_cells_of_constant_element_type(grid, elements, quad_type)

        grid.SetPoints(points)
        grid.Modified()

        # loadPanairResults - regions/loads
        if plot:
            self.gui.scalar_bar_actor.VisibilityOn()
            self.gui.scalar_bar_actor.Modified()

        self.gui.isubcase_name_map = {1: ['Panair', '']}
        cases = OrderedDict()
        ID = 1

        loads = []
        form, cases, node_ids, element_ids = self._fill_panair_geometry_case(
            cases, ID, nodes, elements, regions, kt, cp_norm, loads)
        self.gui.node_ids = node_ids
        self.gui.element_ids = element_ids

        #if plot:
        self.gui._finish_results_io2(model_name, form, cases)
예제 #10
0
    def load_openfoam_geometry(self,
                               openfoam_filename,
                               mesh_3d,
                               name='main',
                               plot=True,
                               **kwargs):
        model_name = name
        #key = self.caseKeys[self.iCase]
        #case = self.resultCases[key]

        #skip_reading = self.remove_old_openfoam_geometry(openfoam_filename)
        skip_reading = self.gui._remove_old_geometry(openfoam_filename)
        if skip_reading:
            return
        log = self.gui.log
        reset_labels = True
        #self.log.info('self.modelType=%s' % self.modelType)
        log.info('mesh_3d = %s' % mesh_3d)
        if mesh_3d in ['hex', 'shell']:
            model = BlockMesh(log=log,
                              debug=False)  # log=self.log, debug=False
        elif mesh_3d == 'faces':
            model = BlockMesh(log=log,
                              debug=False)  # log=self.log, debug=False
            boundary = Boundary(log=log, debug=False)

        self.gui.modelType = 'openfoam'
        #self.modelType = model.modelType
        log.info('openfoam_filename = %s' % openfoam_filename)

        is_face_mesh = False
        if mesh_3d == 'hex':
            is_3d_blockmesh = True
            is_surface_blockmesh = False
            (nodes, hexas, quads, names,
             patches) = model.read_openfoam(openfoam_filename)
        elif mesh_3d == 'shell':
            is_3d_blockmesh = False
            is_surface_blockmesh = True
            (nodes, hexas, quads, names,
             patches) = model.read_openfoam(openfoam_filename)
        elif mesh_3d == 'faces':
            is_3d_blockmesh = False
            is_surface_blockmesh = False
            is_face_mesh = True
            #(nodes, hexas, quads, names, patches) = model.read_openfoam(openfoam_filename)
        else:
            raise RuntimeError(mesh_3d)

        tris = []

        if mesh_3d == 'hex':
            self.gui.nelements = len(hexas)
        elif mesh_3d == 'shell':
            self.gui.nelements = len(quads)
        elif mesh_3d == 'faces':
            dirname = os.path.dirname(openfoam_filename)
            point_filename = os.path.join(dirname, 'points')
            face_filename = os.path.join(dirname, 'faces')
            boundary_filename = os.path.join(dirname, 'boundary')
            check_path(face_filename, 'face_filename')
            check_path(point_filename, 'point_filename')
            check_path(boundary_filename, 'boundary_filename')

            hexas = None
            patches = None
            nodes, quads, names = boundary.read_openfoam(
                point_filename, face_filename, boundary_filename)
            self.gui.nelements = len(quads) + len(tris)
        else:
            raise RuntimeError(mesh_3d)

        self.gui.nnodes = len(nodes)
        log = self.gui.log
        log.debug("nnodes = %s" % self.gui.nnodes)
        log.debug("nelements = %s" % self.gui.nelements)

        grid = self.gui.grid
        grid.Allocate(self.gui.nelements, 1000)

        self.gui.nid_map = {}

        assert nodes is not None
        nnodes = nodes.shape[0]

        xmax, ymax, zmax = nodes.max(axis=0)
        xmin, ymin, zmin = nodes.min(axis=0)
        nodes -= np.array([xmin, ymin, zmin])
        log.info('xmax=%s xmin=%s' % (xmax, xmin))
        log.info('ymax=%s ymin=%s' % (ymax, ymin))
        log.info('zmax=%s zmin=%s' % (zmax, zmin))
        dim_max = max(xmax - xmin, ymax - ymin, zmax - zmin)

        #dim_max = (mmax - mmin).max()
        assert dim_max > 0

        # breaks the model without subracting off the delta
        #self.update_axes_length(dim_max)
        self.gui.create_global_axes(dim_max)

        #print('is_face_mesh=%s is_3d_blockmesh=%s is_surface_blockmesh=%s' % (
        #is_face_mesh, is_3d_blockmesh, is_surface_blockmesh))
        with open('points.bdf', 'w') as bdf_file:
            bdf_file.write('CEND\n')
            bdf_file.write('BEGIN BULK\n')

            unames = unique(names)
            for pid in unames:
                bdf_file.write('PSHELL,%i,1,0.1\n' % pid)
            bdf_file.write('MAT1,1,1.0e7,,0.3\n')

            if is_face_mesh:
                points = vtk.vtkPoints()
                points.SetNumberOfPoints(self.gui.nnodes)

                unodes = unique(quads)
                unodes.sort()
                # should stop plotting duplicate nodes
                for inode, node in enumerate(nodes):
                    if inode in unodes:
                        bdf_file.write('GRID,%i,,%s,%s,%s\n' % (
                            inode + 1,
                            node[0],
                            node[1],
                            node[2],
                        ))
                    points.InsertPoint(inode, node)
            else:
                points = numpy_to_vtk_points(nodes)

            #elements -= 1
            normals = None
            if is_3d_blockmesh:
                nelements = hexas.shape[0]
                cell_type_hexa8 = vtkHexahedron().GetCellType()
                create_vtk_cells_of_constant_element_type(
                    grid, hexas, cell_type_hexa8)

            elif is_surface_blockmesh:
                nelements = quads.shape[0]
                cell_type_quad4 = vtkQuad().GetCellType()
                create_vtk_cells_of_constant_element_type(
                    grid, quads, cell_type_quad4)

            elif is_face_mesh:
                elems = quads
                nelements = quads.shape[0]
                nnames = len(names)
                normals = zeros((nelements, 3), dtype='float32')
                if nnames != nelements:
                    msg = 'nnames=%s nelements=%s names.max=%s names.min=%s' % (
                        nnames, nelements, names.max(), names.min())
                    raise RuntimeError(msg)
                for eid, element in enumerate(elems):
                    ineg = where(element == -1)[0]

                    nnodes = 4
                    if ineg:
                        nnodes = ineg.max()

                    #pid = 1
                    pid = names[eid]
                    if nnodes == 3:  # triangle!
                        bdf_file.write('CTRIA3,%i,%i,%i,%i,%i\n' %
                                       (eid + 1, pid, element[0] + 1,
                                        element[1] + 1, element[2] + 1))
                        elem = vtkTriangle()
                        a = nodes[element[1], :] - nodes[element[0], :]
                        b = nodes[element[2], :] - nodes[element[0], :]
                        n = cross(a, b)
                        normals[eid, :] = n / norm(n)

                        elem.GetPointIds().SetId(0, element[0])
                        elem.GetPointIds().SetId(1, element[1])
                        elem.GetPointIds().SetId(2, element[2])
                        grid.InsertNextCell(elem.GetCellType(),
                                            elem.GetPointIds())
                    elif nnodes == 4:
                        bdf_file.write(
                            'CQUAD4,%i,%i,%i,%i,%i,%i\n' %
                            (eid + 1, pid, element[0] + 1, element[1] + 1,
                             element[2] + 1, element[3] + 1))
                        a = nodes[element[2], :] - nodes[element[0], :]
                        b = nodes[element[3], :] - nodes[element[1], :]
                        n = cross(a, b)
                        normals[eid, :] = n / norm(n)

                        elem = vtkQuad()
                        elem.GetPointIds().SetId(0, element[0])
                        elem.GetPointIds().SetId(1, element[1])
                        elem.GetPointIds().SetId(2, element[2])
                        elem.GetPointIds().SetId(3, element[3])
                        grid.InsertNextCell(elem.GetCellType(),
                                            elem.GetPointIds())
                    else:
                        raise RuntimeError('nnodes=%s' % nnodes)
            else:
                msg = 'is_surface_blockmesh=%s is_face_mesh=%s; pick one' % (
                    is_surface_blockmesh, is_face_mesh)
                raise RuntimeError(msg)
            bdf_file.write('ENDDATA\n')

        self.gui.nelements = nelements
        grid.SetPoints(points)
        grid.Modified()

        self.gui.scalar_bar_actor.VisibilityOn()
        self.gui.scalar_bar_actor.Modified()

        self.gui.isubcase_name_map = {0: ['OpenFoam BlockMeshDict', '']}
        cases = OrderedDict()
        ID = 1

        #print("nElements = ",nElements)
        if mesh_3d == 'hex':
            form, cases, node_ids, element_ids = self._fill_openfoam_case(
                cases, ID, nodes, nelements, patches, names, normals,
                is_surface_blockmesh)

        elif mesh_3d == 'shell':
            form, cases, node_ids, element_ids = self._fill_openfoam_case(
                cases, ID, nodes, nelements, patches, names, normals,
                is_surface_blockmesh)

        elif mesh_3d == 'faces':
            if len(names) == nelements:
                is_surface_blockmesh = True
            form, cases, node_ids, element_ids = self._fill_openfoam_case(
                cases, ID, nodes, nelements, patches, names, normals,
                is_surface_blockmesh)
        else:
            raise RuntimeError(mesh_3d)

        self.gui.node_ids = node_ids
        self.gui.element_ids = element_ids
        if plot:
            self.gui._finish_results_io2(model_name,
                                         form,
                                         cases,
                                         reset_labels=reset_labels)
        else:
            self.gui._set_results(form, cases)