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 export3d_grid_msh(gid, fname, periodic_pairs=[]): """Exports 3D grid to fluent msh ascii format. :param gid: 3D grid file identifier or list of identifiers :param str grid: filename for output :param list periodic_pairs: ``[periodic-0, shadow-0, periodic-point-0, shadow-point-0, periodic-1, shadow-1, periodic-point-1, ...]`` Each periodic pair is defined by four values: * ``periodic`` - boundary identifier for periodic surface * ``shadow`` - boundary identifier for shadow surface * ``periodic-point`` - point in [x, y, z] format on periodic contour * ``shadow-point`` - point in [x, y, z] format on shadow contour Given points will be projected to closest vertex on the boundaries of respective subsurfaces. Periodic and shadow subsurfaces should be singly connected and topologically equivalent with respect to given points. For surface 2D topology definition periodic/shadow surfaces are taken with outside/inside normals respectively. """ icheck(0, UListOr1(Grid3D())) icheck(1, String()) icheck(2, CompoundList(ZType(), ZType(), Point3D(), Point3D())) cb = flow.interface.ask_for_callback() grid = _grid3_from_id(gid) bt = flow.receiver.get_zone_types() fluent_export.grid3(fname, grid, bt, periodic_pairs, cb)
def create_spline_contour(pnts, bnds=0, nedges=100): """ Creates singly connected contour as a parametric cubic spline. :param list-of-list-of-floats pnts: sequence of points. If coordinates of first and last points are equal then resulting contour will be closed. :param single-or-list-of-boundary-identifiers bnds: boundary type for each contour segment bounded by **pnts** or single identifier for the whole contour. :param int nedges: number of line segments of resulting contour. Should be equal or greater than the number of sections defined by **pnts**. :returns: contour identifier """ icheck(0, List(Point2D(), minlen=3)) icheck(1, ListOr1(ZType(), llen=len(pnts) - 1)) icheck(2, UInt(minv=len(pnts) - 1)) b = bnds if isinstance(bnds, list) else [bnds] c = com.contcom.CreateSpline({"points": pnts, "bnds": b, "nedges": nedges}) flow.exec_command(c) return c.added_contours2()[0]
def add_triangle_grid(p0, p1, p2, nedge, bnd=0): """Creates structured grid in triangle area :param list-of-floats p0: :param list-of-floats p1: :param list-of-floats p2: triangle vertices in [x, y] format :param int nedge: partition of triangle edges :param int-or-list-of-int bnd: boundary types for outer contour :return: identifier of newly created grid Resulting grid will contain quadrangle cells everywhere except area near ``p0``-``p2`` edge where triangle cells will be built. """ icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Point2D(noteq=[p0, p1])) icheck(3, UInt(minv=1)) icheck(4, ListOr1(ZType(), llen=3)) bnd = bnd[:3] if isinstance(bnd, list) else [bnd, bnd, bnd] c = com.gridcom.AddTriGrid({ "vertices": [p0, p1, p2], "nedge": nedge, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def add_rect_contour(p0, p1, bnd=0): """Adds four point closed rectangular contour. :param list-of-floats p0: :param list-of-floats p1: bottom left and top right coordinates of the contour :param bnd: single or list of 4 boundary identifiers (bottom, right, top, left) for contour segments. With the default value no boundary types will be set. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Point2D(grthan=p0)) icheck(2, ListOr1(ZType(), llen=4)) if isinstance(bnd, list): b = bnd[0:4] else: b = [bnd, bnd, bnd, bnd] c = com.contcom.AddRectCont({"p0": p0, "p1": p1, "bnds": b}) flow.exec_command(c) return c.added_contours2()[0]
def add_circ_contour(p0, rad, n_arc, bnd=0): """Adds circle contour from given center and radius. :param list-of-floats p0: circle center in [x, y] format :param float rad: circle radius :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, UInt(minv=3)) icheck(3, ZType()) c = com.contcom.AddCircCont({ "p0": p0, "rad": rad, "na": n_arc, "bnd": bnd }) flow.exec_command(c) return c.added_contours2()[0]
def set_btypes(obj, bt, segm=None): icheck(0, AObject()) icheck(1, ZType()) icheck(2, NoneOr(List(UInt()))) if segm is None: generalfun.set_boundary_type(obj, bt) else: generalfun.set_boundary_type(obj, bdict={bt: segm})
def add_unf_ring_grid(p0, radinner, radouter, na, nr, coef=1.0, bnd=0): """Builds ring grid :param list-of-floats p0: center coordinates as [x, y] :param float radinner: :param float radouter: inner and outer radii :param int na: :param int nr: arc and radius partition respectively :param float coef: refinement coefficient: * ``coef = 1``: equidistant radius division * ``coef > 1``: refinement towards center of circle * ``0 < coef < 1``: refinement towards outer arc :param int-or-list-of-int bnd: boundary types for inner and outer ring boundaries :return: created grid identifier """ if radinner > radouter: radinner, radouter = radouter, radinner icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, Float(grthan=0.0)) icheck(3, UInt(minv=3)) icheck(4, UInt(minv=1)) icheck(5, Float(grthan=0.0)) icheck(6, ListOr1(ZType(), llen=2)) bnd = bnd[:2] if isinstance(bnd, list) else [bnd, bnd] c = com.gridcom.AddUnfRingGrid({ "p0": p0, "radinner": radinner, "radouter": radouter, "na": na, "nr": nr, "coef": coef, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def add_circ_contour3(p0, p1, curv, n_arc, bnd=0): """Adds circle contour from given arc points and curvature. :param list-of-floats p0: :param list-of-floats p1: circle arc points in [x, y] format :param float curv: circle curvature. Equals ``1.0/radius``. :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. With the default value no boundary types will be set. :return: Contour identifier In the resulting circle ``p0``-``p1`` arc with counterclockwise direction will be shorter then ``p1``-``p0`` arc. """ from hybmeshpack.basic.geom import angle_3pnt icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Float(grthan=0.0)) icheck(3, UInt(minv=3)) icheck(4, ZType()) p0, p1, curv = map(float, p0), map(float, p1), float(curv) xa, ya = p1[0] - p0[0], p1[1] - p0[1] r = abs(1.0 / curv) a, b, c = -2.0 * xa, -2.0 * ya, xa * xa + ya * ya s = a * a + b * b x0, y0 = -a * c / s, -b * c / s d = r * r - c * c / s mult = math.sqrt(d / s) cx1 = x0 + b * mult cy1 = y0 - a * mult cx2 = x0 - b * mult cy2 = y0 + a * mult a1 = angle_3pnt((0.0, 0.0), (cx1, cx2), (xa, ya)) if (a1 < math.pi): cx, cy = cx1, cy1 else: cx, cy = cx2, cy2 return add_circ_contour([cx + p0[0], cy + p0[1]], r, n_arc, bnd)
def add_boundary_type(index, name="boundary1"): """ Register boundary type name. :param int index: index of boundary (>0) :param str name: user defined name of the boundary :returns: integer boundary identifier If boundary with ``index`` already exists it will be overwritten. Name of the boundary should be unique, if name already exists it will be changed automatically. """ icheck(0, ZType()) icheck(1, String()) c = com.contcom.EditBoundaryType({"index": index, "name": name}) flow.exec_command(c) return index
def create_contour(pnts, bnds=0): """ Create singly connected contour from sequence of points. :param list-of-list-of-floats pnts: sequence of points. If coordinates of first and last points are equal then contour is considered closed. :param single-or-list-of-boundary-identifiers bnds: boundary type for each contour segment or single identifier for the whole contour. :returns: contour identifier Example: >>> hmscript.create_contour([[0, 0], [1, 0], [1, 1], [0, 0]], [b1, b2, b3]) """ icheck(0, List(Point2D(), minlen=2)) icheck(1, ListOr1(ZType())) b = bnds if isinstance(bnds, list) else [bnds] c = com.contcom.CreateContour({"points": pnts, "bnds": b}) flow.exec_command(c) return c.added_contours2()[0]
def stripe(cont, partition, tip='no', bnd=0): """ Build a structured grid to the both sides of contour line :param cont: closed or open contour identifier :param ascending-list-of-double partition: partition perpendicular to source contour :param str tip: stripe endings meshing algorithm * ``"no"`` - no grid at endings * ``"radial"`` - radial grid at endings :param float-or-list-of-floats bnd: boundary types for input grid. List of four values provides respective values for bottom, left, right, top sides of resulting grid with respect to contour direction. :return: grid identifier Horizontal partition is taken from contour partition. Vertical partition is given by user with ``partition`` list parameter. If it starts with non zero value then grid will not contain contour nodes as its vertices. Use :func:`partition_segment` to define non-equidistant **partition** with any desired refinement if needed. """ icheck(0, ACont2D()) icheck(1, IncList(Float(grthan=0.0))) icheck(2, OneOf('no', 'radial')) icheck(3, ListOr1(ZType(), llen=4)) bnd = bnd[:4] if isinstance(bnd, list) else [bnd, bnd, bnd, bnd] arg = {"source": cont, "partition": partition, "tip": tip, "bnd": bnd} c = com.gridcom.StripeGrid(arg) flow.exec_command(c) return c.added_grids2()[0]
def add_circ_contour2(p0, p1, p2, n_arc, bnd=0): """Adds circle contour from given arc points. :param list-of-floats p0: :param list-of-floats p1: :param list-of-floats p2: circle arc points as [x, y] format :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. With the default value no boundary types will be set. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Point2D(noteq=[p0, p1])) icheck(3, UInt(minv=3)) icheck(4, ZType()) p0, p1, p2 = map(float, p0), map(float, p1), map(float, p2) xb, yb = p1[0] - p0[0], p1[1] - p0[1] xc, yc = p2[0] - p0[0], p2[1] - p0[1] A11, A12 = 2.0 * xb, 2.0 * yb A21, A22 = 2.0 * xc, 2.0 * yc B1, B2 = xb * xb + yb * yb, xc * xc + yc * yc d = A11 * A22 - A12 * A21 I11, I12, I21, I22 = A22 / d, -A12 / d, -A21 / d, A11 / d cx = I11 * B1 + I12 * B2 cy = I21 * B1 + I22 * B2 rad = math.sqrt((cx - xb) * (cx - xb) + (cy - yb) * (cy - yb)) return add_circ_contour([cx + p0[0], cy + p0[1]], rad, n_arc, bnd)
def set_boundary_type(obj, btps=None, bfun=None, bdict=None): """ Mark geometrical object with boundary types. :param obj: geometric object identifier :param btps: single identifier for the whole object or list of identifiers for each boundary segment. :param bfun: function which returns boundary type taking segment coordinates and old boundary type as arguments. :param bdict: {btype: [list-of-segment indicies]} dictionary which maps boundary type with object segments indicies Only one of **btps**, **bfun**, **bdict** arguments should be defined. **bfun** signature is: * ``(x0, y0, x1, y1, bt) -> btype`` for 2D objects, where *x0, y0, x1, y1* are edge end point coordinates, bt - old boundary type * ``(xc, yc, zc, bt) -> btype`` for 3D objects, where *xc, yc, zc* - approximate face center coordinates, bt - old boundary type If **obj** is a grid then only boundary segments will be passed to **bfun** function and **btps** list entries will be associated with boundary segments only. However **bdict** entries should contain global edge or face indicies. Example: .. literalinclude:: ../../testing/py/fromdoc/ex_setbtype.py :start-after: START OF EXAMPLE :end-before: END OF EXAMPLE """ icheck(0, AObject()) icheck(1, NoneOr(ListOr1(ZType()))) icheck(3, NoneOr(Dict(ZType(), List(UInt())))) t = flow.receiver.whatis(obj) if t in ['g2', 'c2']: icheck(2, NoneOr(Func(narg=5))) else: icheck(2, NoneOr(Func(narg=4))) if [btps, bfun, bdict].count(None) != 2: raise InvalidArgument("One of [btps, bfun, bdict] should be not None") args = {'name': obj, 'whole': None, 'btypes': {}} if isinstance(btps, int): args['whole'] = btps elif bdict is not None: args['btypes'] = bdict else: g = flow.receiver.get_object(obj) if t == 'g2': if btps is not None: _setbt_args_g2g3btps(g, btps, args['btypes']) if bfun is not None: _setbt_args_g2bfun(g, bfun, args['btypes']) if t == 'g3': if btps is not None: _setbt_args_g2g3btps(g, btps, args['btypes']) if bfun is not None: _setbt_args_g3bfun(g, bfun, args['btypes']) if t == 'c2': if btps is not None: _setbt_args_c2s3btps(g, btps, args['btypes']) if bfun is not None: _setbt_args_c2bfun(g, bfun, args['btypes']) if t == 's3': if btps is not None: _setbt_args_c2s3btps(g, btps, args['btypes']) if bfun is not None: _setbt_args_s3bfun(g, bfun, args['btypes']) c = com.objcom.SetBType(args) flow.exec_command(c)
def add_unf_circ_grid(p0, rad=1.0, na=8, nr=4, coef=1.0, is_trian=True, custom_rads=[], custom_arcs=[], bnd=0): """Builds circular grid. :param list-of-floats p0: center coordinate as [x, y] :param float rad: radius :param int na: :param int nr: partitions of arc and radius respectively :param float coef: refinement coefficient: * ``coef = 1``: equidistant radius division * ``coef > 1``: refinement towards center of circle * ``0 < coef < 1``: refinement towards outer arc :param bool is_trian: True if center cell should be triangulated :param float-or-list-of-floats custom_rads: user defined radious partition :param float-or-list-of-floats custom_arcs: user defined arc partition :param int bnd: boundary type for outer contour :returns: created grid identifier Creates a radial grid with the center in **p0**. If **custom_rads** is given as a single value it will be used as a constant step along radial axis hence **nr** and **coef** arguments will be ignored. If it is given as a list of increasing values starting from zero then it is parsed as explicit radius partition. Hence the last entry of this list will be the radius of the resulting grid and **rad** parameter will also be ignored. If **custom_arcs** is given as a single value it shows the constant step along outer arc and **na** will be ignored. If it is an increasing list of floats, it shows partition of outer arc. It can be given in degrees or radians or any other relative units. Program treats **custom_arcs[-1]**-**custom_arcs[0]** difference as a full circle length and normalizes all other entries to this length. First and last entries of this array provides the same arc segment (last = first + 2*pi) hence to get partition of n segments you should define n+1 entries. Use :func:`partition_segment` to conveniently define **custom\_** fields if needed. """ icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, UInt(minv=3)) icheck(3, UInt(minv=1)) icheck(4, Float(grthan=0.0)) icheck(5, Bool()) icheck(6, Or(Float(grthan=0.0), IncList(Float()))) icheck(7, Or(Float(grthan=0.0), IncList(Float()))) icheck(8, ZType()) custom_rads = custom_rads if isinstance(custom_rads, list)\ else [custom_rads] custom_arcs = custom_arcs if isinstance(custom_arcs, list)\ else [custom_arcs] c = com.gridcom.AddUnfCircGrid({ "p0": p0, "rad": rad, "na": na, "nr": nr, "coef": coef, "is_trian": is_trian, "custom_r": custom_rads, "custom_a": custom_arcs, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def add_unf_rect_grid(p0=[0, 0], p1=[1, 1], nx=3, ny=3, custom_x=[], custom_y=[], bnd=0): """Builds rectangular grid. :param list-of-floats p0: :param list-of-floats p1: bottom left, top right points in [x, y] format. :param int nx: :param int ny: partition in x and y directions. :param float-or-list-of-floats custom_x: :param float-or-list-of-floats custom_y: custom x and y coordinates :param int-or-list-of-int: boundary types for bottom, right, top, left rectangle sides :returns: created grid identifier Builds a grid in a rectangular area formed by points **p0** and **p1**. **nx** and **ny** provide grid partition in x and y direction. If **custom_x**/**custom_y** is given by a single float value than it shows a step size in respective direction, hence values given by **nx**/**ny** parameters will be omitted. If **custom_x**/**custom_y** is given by a list of increasing floats it explicitly shows the partition in respective direction. In the latter case the respective **p0**, **p1** coordinates will also be ignored. Use :func:`partition_segment` to conveniently define **custom\_** fields if needed. """ icheck(0, Point2D()) icheck(1, Point2D(grthan=p0)) icheck(2, UInt(minv=1)) icheck(3, UInt(minv=1)) icheck(4, Or(Float(grthan=0.), IncList(Float()))) icheck(5, Or(Float(grthan=0.), IncList(Float()))) icheck(6, ListOr1(ZType(), llen=4)) bnd = bnd[:4] if isinstance(bnd, list) else [bnd, bnd, bnd, bnd] custom_x = custom_x if isinstance(custom_x, list) else [custom_x] custom_y = custom_y if isinstance(custom_y, list) else [custom_y] c = com.gridcom.AddUnfRectGrid({ "p0": p0, "p1": p1, "nx": nx, "ny": ny, "custom_x": custom_x, "custom_y": custom_y, "bnds": bnd }) flow.exec_command(c) return c.added_grids2()[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]
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]