def skewness(gid, threshold=0.7): """Reports equiangular skewness coefficient (in [0, 1]) of grid cells :param gid: grid identifier :param float threshold: cells with skewness greater than this value are considered bad and will be reported. Set it to -1 to get skewness for each cell. :returns: dictionary with keys:: {'ok': bool, # True if no bad_cells were found 'max_skew': float, # maximum skew value in grid 'max_skew_cell': int, # index of cell with maximum skew 'bad_cells': [list-of-int], # list of bad cell indicies 'bad_skew': [list-of-float] # list of bad cell skew values } Respective `bad_cells` and `bad_skew` lists entries correspond to the same cells. """ icheck(0, Grid2D()) icheck(1, Float()) skew = flow.receiver.get_grid2(gid).skewness(threshold) if (len(skew) == 0): raise Exception("Failed to calculate skewness") skew['ok'] = (len(skew['bad_cells']) == 0) return skew
def export_grid_msh(gid, fname, periodic_pairs=[]): """Exports grid to fluent msh format. :param gid: 2d grid file identifier or list of identifiers. :param str fname: output filename :param list periodic_pairs: ``[b-periodic0, b-shadow0, is_reversed0, b-periodic1, b-shadow1, is_reversed1, ...]`` list defining periodic boundaries. Each periodic condition is defined by three values: * ``b-periodic`` - boundary identifier for periodic contour segment * ``b-shadow`` - boundary identifier for shadow contour segment * ``is_reversed`` - boolean which defines whether shadow contour segment should be reversed so that first point of periodic segment be equivalent to last point of shadow segment Periodic and shadow boundary segments should be singly connected and topologically equivalent. :returns: None Only grids with triangle/quadrangle cells could be exported. """ icheck(0, UListOr1(Grid2D())) icheck(1, String()) icheck(2, CompoundList(ZType(), ZType(), Bool())) cb = flow.interface.ask_for_callback() grid = _grid2_from_id(gid) bt = flow.receiver.get_zone_types() fluent_export.grid2(fname, grid, bt, periodic_pairs, cb)
def export_grid_vtk(gid, fname): """ Exports 2d grid to vtk format :param gid: single or list of 2d grid identifiers :param str fname: output filename :returns: None """ icheck(0, UListOr1(Grid2D())) icheck(1, String()) grid = _grid2_from_id(gid) cb = flow.interface.ask_for_callback() vtk_export.grid2(fname, grid, cb)
def grid_bnd_to_contour(gid, simplify=True): """ Extracts grid boundary to user contour. :param gid: grid identifier :param bool simplify: if true deletes all non-significant points. Otherwise resulting contour will contain all boundary grid edges. :returns: contour identifier """ icheck(0, Grid2D()) icheck(1, Bool()) c = com.contcom.GridBndToContour({"grid_name": gid, "simplify": simplify}) flow.exec_command(c) return c.added_contours2()[0]
def tab_grid2(obj, what): """ Returns plain table for the given grid. :param str obj: grid identifier :param str what: table name :returns: plain ctypes array representing requested table. Possible **what** values are: * ``'vert'`` - vertex coordinates table, * ``'edge_vert'`` - edge-vertex connectivity: indices of first and last vertices for each edge, * ``'edge_cell'`` - edge-cell connectivity: indices of left and right cell for each edge. If this is a boundary edge ``-1`` is used to mark boundary edge side, * ``'cell_dim'`` - number of vertices in each cell, * ``'cell_edge'`` - cell-edge connectivity: counterclockwise ordered edge indices for each cell. * ``'cell_vert'`` - cell-vertex connectivity: counterclockwise ordered vertex indices for each cell. * ``'bnd'`` - list of boundary edges indices, * ``'bt'`` - boundary types for all edges including internal ones, * ``'bnd_bt'`` - (boundary edge, boundary feature) pairs In case of grids with variable cell dimensions ``'cell_edge'`` and ``'cell_vert'`` tables require additional ``'cell_dim'`` table to subdive returned plain array by certain cells. """ icheck(0, Grid2D()) icheck( 1, OneOf( 'vert', 'edge_vert', 'edge_cell', 'cell_dim', 'cell_edge', 'cell_vert', 'bnd', 'bt', 'bnd_bt', )) return flow.receiver.get_grid2(obj).raw_data(what)
def export_grid_hmg(gid, fname, fmt='ascii', afields=[]): """Exports 2d grid to hybmesh native format. :param gid: single or list of grid identifiers :param str fname: output filename :param str fmt: output data format: * ``'ascii'`` - all fields will be saved as text fields, * ``'bin'`` - all fields will be saved in binary section, * ``'fbin'`` - only floating point fields will be saved in binary section. :param list-of-str afields: additional data which should be placed to output file. :returns: None To save additional data into grid file :ref:`user defined fields <udef-fields>` place any of these strings into **afields** list: * ``'cell-vertices'`` -- cell vertex connectivity. All vertices will be written in counterclockwise direction; * ``'cell-edges'`` -- cell edge connectivity. All edges will be written in counterclockwise direction. See :ref:`grid2d-file` for format description. """ if fmt == "binary": fmt = "bin" if fmt == "fbinary": fmt = "fbin" icheck(0, UListOr1(Grid2D())) icheck(1, String()) icheck(2, OneOf('ascii', 'bin', 'fbin')) icheck(3, UList(OneOf('cell-vertices', 'cell-edges'))) names = gid if isinstance(gid, list) else [gid] grids = map(flow.receiver.get_grid2, names) cb = flow.interface.ask_for_callback() native_export.grid2_tofile(fname, grids, names, fmt, afields, cb)
def export_grid_tecplot(gid, fname): """Exports grid to tecplot ascii format. :param gid: grid identifier or list of identifiers :param fname: output filename :returns: None All cells will be saved as FEPolygon elements. Boundary segments with same boundary type will be converted to separate zones. """ icheck(0, UListOr1(Grid2D())) icheck(1, String()) cb = flow.interface.ask_for_callback() grid = _grid2_from_id(gid) bt = flow.receiver.get_zone_types() tecplot_export.grid2(fname, grid, bt, cb)
def export_grid_gmsh(gid, fname): """ Exports grid to gmsh ascii format. :param gid: single or list of grid identifiers :param fname: output filename :returns: None Only grids with triangle/quadrangle cells could be exported. Boundary edges will be exported as Elements of "Line" type. All boundary types which present in grid will be exported as Physical Groups with an id identical to boundary index and a respective Physical Name. """ icheck(0, UListOr1(Grid2D())) icheck(1, String()) cb = flow.interface.ask_for_callback() grid = _grid2_from_id(gid) bt = flow.receiver.get_zone_types() gmsh_export.grid2(fname, grid, bt, cb)
def info_grid(gid): """Get grid structure information :param gid: grid identifier :returns: dictionary which represents total number of nodes/cells/edges and number of cells of each type:: {'Nnodes': int, 'Ncells': int, 'Nedges': int, 'cell_types': {int: int} # cell dimension: number of such cells } """ icheck(0, Grid2D()) grid = flow.receiver.get_grid2(gid) ret = {} ret['Nnodes'] = grid.n_vertices() ret['Ncells'] = grid.n_cells() ret['Nedges'] = grid.n_edges() ret['cell_types'] = grid.cell_types_info() return ret
def extrude_grid(obj, zcoords, bottombc=0, topbc=0, sidebc=None): """ Creates 3D grid by extrusion of 2D grid along z-axis :param obj: 2d grid identifier :param list-of-floats zcoords: increasing vector of z values which will be used to create 3d points :param bottombc: :param topbc: values which define boundary features of 3d grid at ``z=min(zcoords)`` and ``z=max(zcoords)`` surfaces respectively. Could be either a single boundary identifier for a whole surface or a function: ``(float x, float y, int cell_index)->bindex`` which takes central cell point x, y coordinates and cell index as arguments and returns boundary type (see example below). :param sidebc: defines boundary features for side surfaces. * If None than boundary types will be taken from corresponding edges of 2D grid * If single boundary identifier then whole side surface will have same boundary type :returns: 3D grid identifier Use :func:`partition_segment` to define non-equidistant **zcoords** with any desired refinement. Example: .. literalinclude:: ../../testing/py/fromdoc/ex_extrude.py :start-after: vvvvvvvvvvvvvvvvvvvvvvvv :end-before: ^^^^^^^^^^^^^^^^^^^^^^^^ """ icheck(0, Grid2D()) icheck(1, IncList(Float())) icheck(2, Or(ZType(), Func(nargs=3))) icheck(3, Or(ZType(), Func(nargs=3))) icheck(4, NoneOr(ZType())) # calculate boundary types if not isinstance(bottombc, int) or not isinstance(topbc, int): grid = flow.receiver.get_grid2(obj) cc_pnt = grid.raw_data('cell_center') if isinstance(bottombc, int): bbot = [bottombc] elif callable(bottombc): it = iter(cc_pnt) bbot = [bottombc(p[0], p[1], i) for i, p in enumerate(zip(it, it))] if isinstance(topbc, int): btop = [topbc] elif callable(topbc): it = iter(cc_pnt) btop = [topbc(p[0], p[1], i) for i, p in enumerate(zip(it, it))] if sidebc is None: bside = None elif isinstance(sidebc, int): bside = sidebc c = com.grid3dcom.ExtrudeZ({ "base": obj, "zvals": copy.deepcopy(zcoords), "bside": bside, "btop": btop, "bbot": bbot }) flow.exec_command(c) return c.added_grids3()[0]
def revolve_grid(obj, p1, p2, n_phi=None, phi=None, btype1=0, btype2=0, merge_central=False): """ Creates 3D grid by revolution of 2D grid around a vector :param obj: 2d grid identifier :param p1: :param p2: points in [x, y] format which define vector of rotation :param int n_phi: partition along circular coordinate. If this parameter is defined then [0, 360] range will be divided into equal parts and full revolution solid will be build. :param list-of-floats phi: increasing vector defining custom partition of angular range. This parameter will be processed if **n_phi** is None. If the last value of **phi** is not equal to first one plus 360 degree than incomplete revolution solid will be built. :param btype1: :param btype2: boundary identifiers for surfaces which will be build as a result of incomplete rotation at end values of **phi** vector. :param bool merge_central: if rotation vector coincides with boundary edges of input grid then this parameter defines whether central cells derived from the revolution of respective boundary cells should be merged into one complex finite volume (True) or left as they are (False). :returns: 3D grid identifier All points of input grid should lie to the one side of rotation vector. Use :func:`partition_segment` to define non-equidistant **phi** with any desired refinement if needed. """ icheck(0, Grid2D()) icheck(1, Point2D()) icheck(2, Point2D(noteq=p1)) icheck(3, NoneOr(UInt(minv=3))) icheck(4, NoneOr(IncList(Float()))) icheck(5, ZType()) icheck(6, ZType()) icheck(7, Bool()) # calculate phi's if n_phi is None: inp_phi = copy.deepcopy(phi) else: inp_phi = [] for i in range(n_phi + 1): inp_phi.append(360. * i / n_phi) c = com.grid3dcom.Revolve({ "base": obj, "p1": p1, "p2": p2, "phi": inp_phi, "bt1": btype1, "bt2": btype2, "center_tri": not merge_central }) flow.exec_command(c) return c.added_grids3()[0]