예제 #1
0
파일: c2oper.py 프로젝트: cescjf/HybMesh
def simplify_contour(cont, simplify=True, angle=0., separate=False):
    """ Separates and simplify user contour

    :param cont: source contour or grid identifier

    :param bool simplify: do simplification, i.e. make all
       segments non-collinear
       Collinear segments will not be splitted if they have different
       boundary types.

    :param degree angle: maximum allowed angle between simplified segments
       (deg, >=0).

    :param bool separate: assemble list of singly connected contours from
       multiply connected source contour

    :returns: list of created contours ids

    """
    icheck(0, ACont2D())
    icheck(1, Bool())
    icheck(2, Float(within=[0., 180., '[]']))
    icheck(3, Bool())

    c = com.contcom.SimplifyContours({"names": [cont],
                                      "simplify": simplify,
                                      "angle": angle,
                                      "separate": separate})
    flow.exec_command(c)
    return c.added_contours2()
예제 #2
0
파일: c2oper.py 프로젝트: cescjf/HybMesh
def clip_domain(dom1, dom2, operation, simplify=True):
    """ Executes domain clipping procedure

    :param dom1:

    :param dom2: contour identifiers

    :param  str operatrion: operation code

       * ``"union"``
       * ``"difference"``
       * ``"intersection"``
       * ``"xor"``

    :param bool simplify: whether to keep all source points (False) or
       return simplified contour

    :returns: created contour identifier or None if resulting domain is empty
    """
    icheck(0, ACont2D())
    icheck(1, ACont2D())
    icheck(2, OneOf("union", "difference", "intersection", "xor"))
    icheck(3, Bool())

    c = com.contcom.ClipDomain({"c1": dom1, "c2": dom2, "oper": operation,
                                "simplify": simplify})
    flow.exec_command(c)
    if len(c.added_contours2()) > 0:
        return c.added_contours2()[0]
    else:
        return None
예제 #3
0
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)
예제 #4
0
def add_unf_hex_grid(area, cell_radius, strict=False):
    """ Builds grid with regular hexagonal cells

    :param area: defines meshing area. If given as ``[[x, y], radius]``
       then represents hexagonal area; if ``[[x0, y0], [x1, y1]]`` then
       it is a rectangle defined by bottom-left and top-right points.

    :param float cell_radius: radius of hexagonal cell.

    :param bool strict: forces grid stretch
      to guarantee that all outer rectangle corners lie in the
      centers of cells.

    See details in :ref:`hexgrid`
    """
    icheck(0, List(Any()))
    icheck(
        0,
        CompoundList(Point2D(),
                     Or(Float(grthan=0.0), Point2D(grthan=area[0])),
                     llen=2))
    icheck(1, Float(grthan=0.))
    icheck(2, Bool())

    simpar = [area[0][0], area[0][1]]
    if isinstance(area[1], list):
        simpar.append(area[1][0])
        simpar.append(area[1][1])
    else:
        simpar.append(area[1])
    args = {"area": simpar, "crad": cell_radius, "strict": strict}
    c = com.gridcom.AddUnfHexGrid(args)
    flow.exec_command(c)
    return c.added_grids2()[0]
예제 #5
0
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]
예제 #6
0
파일: c2oper.py 프로젝트: cescjf/HybMesh
def connect_subcontours(sources, fix=[], close="no", shiftnext=True):
    """ Connects sequence of open contours into a single contour
    even if neighboring contours have no equal end points

    :param sources: list of open contour identifiers

    :param list-of-int fix: indicies of **sources** contours
        which could not be shifted or stretched.

    :param str close: last connection algorithm:
        ``no``, ``yes`` or ``force``

    :param bool shiftnext: if True then each next contour will be
        shifted to the end point of previous one, otherwise
        both contours will be stretched to match average end point.

    To connect given contours this procedure implements stretching
    and shifting of those ones not listed in **fix** list.
    If two adjacent source contours are marked as fixed but have no
    common end points an exception will be raised.

    If **close** is ``yes`` then last contour of **sources** will
    be connected with the first one with algorithm depending on
    **fix** and **shiftnext** options.

    If **close** is ``no``
    then ending contours will be left as they are. In that case resulting
    contour will be open until first and last points are exactly equal.

    **close** = ``force`` algorithm works like **close** = ``no`` but
    creates a section which explicitly connects first and last contours
    by a straight line.
    """
    icheck(0, UList(Cont2D()))
    icheck(1, UList(UInt(maxv=len(sources) - 1), maxlen=len(sources)))
    icheck(2, OneOf('no', 'yes', 'force'))
    icheck(3, Bool())

    args = {}
    args['src'] = sources
    args['fix'] = copy.deepcopy(fix)
    args['close'] = close
    args['shiftnext'] = shiftnext
    c = com.contcom.ConnectSubcontours(args)
    flow.exec_command(c)
    return c.added_contours2()[0]
예제 #7
0
def grid3_bnd_to_surface(gid, separate=False):
    """ Returns surface object built out of grid boundary

    :param gid: 3D grid identifier

    :param bool separate: whether grid surface should be separated
       into singly connected set of surfaces

    :returns: grid identifier if **separate** is False or
       list of grid identifiers otherwise

    """
    icheck(0, Grid3D())
    icheck(1, Bool())

    c = com.surfcom.Grid3BndToSurface({"grid_name": gid, "separate": separate})
    flow.exec_command(c)
    if separate:
        return c.added_surfaces3()
    else:
        return c.added_surfaces3()[0]
예제 #8
0
파일: c2oper.py 프로젝트: cescjf/HybMesh
def partition_contour(cont, algo, step=1., angle0=30., keep_bnd=False,
                      nedges=None, crosses=[], keep_pts=[],
                      start=None, end=None):
    """ Makes connected contour partition

    :param cont: Contour or grid identifier

    :param str algo: Partition algorithm:

       * ``'const'``: partition with defined constant step
       * ``'ref_points'``: partition with step function given by a
         set of values refered to basic points
       * ``'ref_weights'``: partition with step function given by a
         set of values refered to local contour [0, 1] coordinate
       * ``'ref_lengths'``: partition with step function given by a
         set of values refered to local contour length coordinate

    :param step: For ``algo='const'`` a float number defining
       partition step;

       For ``algo='ref_points'`` - list of step values and point coordinates
       given as
       ``[ step_0, [x_0, y_0], step_1, [x_1, y_1], ....]``.

       For ``algo='ref_weights'`` - list of step values and point normalized
       1d coordinates given as
       ``[ step_0, w_0, step_1, w_1, ....]``.

       For ``algo='ref_lengths'`` - list of step values and point 1d
       coordinates given as
       ``[ step_0, s_0, step_1, s_1, ....]``. Negative ``s_i`` shows
       length coordinate started from end point in reversed direction.


    :param float angle0: existing contour vertices which provide
       turns outside of ``[180 - angle0, 180 + angle0]`` degrees range
       will be preserved regardless of other options

    :param bool keep_bnd: if that is True than vertices which have different
       boundary features on their right and left sides will be preserved

    :param int nedges: if this parameter is not None then it provides
       exact number of edges in the resulting contour. To satisfy this
       condition **step** value will be multiplied by an appropriate factor.
       If it can not be satisfied (due to other restrictions)
       then an exception will be raised.

    :param crosses: represents set of contour which cross points with
       target contour will be present in resulting contour.

    :param keep_pts: list of points as ``[[x1, y1], [x2, y2], ...]`` list
       which should present in output partition.

    :param start:

    :param end: start and end points which define processing segment

    :returns: new contour identifier

    Points set defined by user for ``algo='ref_points'`` algorithm
    will not present in resulting contour (as well as points defined
    implicitly by other ``'ref_'`` algorithms). It just shows locations
    where step size of given length should be applied. If any point
    of this set is not located on the input contour then it will be
    projected to it.

    For constant stepping any contour including multiply connected ones
    could be passed. For ``ref_`` stepping only singly connected
    contours (open or closed) are allowed.

    If **start** and **end** points are defined then only segment between
    these points will be parted. Note that all closed contours are treated
    in counterclockwise direction. Given start/end points will be
    projected to closest contour vertices.

    ``ref_weights``, ``ref_lengths`` partition methods
    require definition of **start** point
    (To process whole contour ``end`` point could be omitted).

    Example:

      .. literalinclude:: ../../testing/py/fromdoc/ex_partcontour.py
          :start-after: vvvvvvvvvvvvvvvvvvvvvvvv
          :end-before: ^^^^^^^^^^^^^^^^^^^^^^^^

    See also: :ref:`simplecontmeshing`
    """
    if nedges <= 0:
        nedges = None
    icheck(0, ACont2D())
    icheck(1, OneOf("const", "ref_points", "ref_weights", "ref_lengths"))
    if algo == "const":
        icheck(2, Float(grthan=0.0))
    elif algo == "ref_points":
        icheck(2, CompoundList(Float(grthan=0.0),
                               Point2D(), minlen=2))
    elif algo == "ref_weights":
        icheck(2, CompoundList(Float(grthan=0.0),
                               Float(within=[-1, 1, '[]']), minlen=2))
    elif algo == "ref_lengths":
        icheck(2, CompoundList(Float(grthan=0.0), Float(), minlen=2))
    icheck(3, Float())
    icheck(4, Bool())
    icheck(5, NoneOr(UInt(minv=1)))
    icheck(6, List(ACont2D()))
    icheck(7, List(Point2D()))
    icheck(8, NoneOr(Point2D()))
    icheck(9, NoneOr(Point2D()))
    if start is None and algo in ['ref_weights', 'ref_lengths']:
        raise InvalidArgument("Define start point for %s partition" % algo)

    # prepare arguments for command
    if algo == "const":
        plain_step = [step]
    elif algo == "ref_points":
        plain_step = []
        for i in range(len(step) / 2):
            plain_step.append(step[2 * i])
            plain_step.extend(step[2 * i + 1])
    elif algo in ["ref_weights", "ref_lengths"]:
        plain_step = copy.deepcopy(step)
    sp, ep = None, None
    if start is not None:
        sp = [start[0], start[1]]
    if end is not None:
        ep = [end[0], end[1]]
    kp = []
    if keep_pts is not None:
        for p in keep_pts:
            kp.append([p[0], p[1]])

    args = {"algo": algo,
            "step": plain_step,
            "angle0": angle0,
            "keepbnd": keep_bnd,
            "base": cont,
            "nedges": nedges,
            "crosses": crosses,
            "start": sp,
            "end": ep,
            "keep_pts": kp}
    # call
    c = com.contcom.PartitionContour(args)
    flow.exec_command(c)
    return c.added_contours2()[0]
예제 #9
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]
예제 #10
0
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]
예제 #11
0
def add_custom_rect_grid(algo,
                         left,
                         bottom,
                         right=None,
                         top=None,
                         hermite_tfi_w=[1.0, 1.0, 1.0, 1.0],
                         return_invalid=False):
    """ Creates rectangular grid on the basis of four curvilinear contours
    using contour vertices for partition.
    See details in :ref:`custom_rect_grid`.

    :param str algo: Algorithms of building:

       * ``'linear'`` - connects respective points of opposite
         contours by straight lines.
       * ``'linear_tfi'`` - linear transfinite interpolation
       * ``'hermite_tfi'`` - hermite transfinite interpolation
       * ``'inverse_laplace'`` -
       * ``'direct_laplace'`` - connects points using solution of
         laplace equation with Dirichlet boundary conditions;
       * ``'orthogonal'`` - builds orthogonal grid based on **left** and
         **bottom** partition.
         Partitions of **right** and **top** are ignored.

    :param left:

    :param bottom:

    :param right:

    :param top: identifiers of curvilinear domain sides.
       **right** and **top** could be ``None``. If so right and top
       boundaries will be created by translation of **left** and **bottom**.

    :param list-of-floats hermite_tfi_w:
       perpendicularity weights
       for **left**, **bottom**, **right**, **top** contours respectively
       for **algo** = ``'hermite_tfi'``

    :param bool return_invalid: if this flag is on
       then the procedure will return a grid even if it is not valid
       (has self-intersections). Such grids could be exported to
       simple formats (like vtk or tecplot) in order to detect
       bad regions and give user a hint of how to adopt
       input data to gain an acceptable result.

       .. warning:: Never use invalid grids for further operations.

    :return: new grid identifier

    """
    icheck(
        0,
        OneOf('linear', 'linear_tfi', 'hermite_tfi', 'inverse_laplace',
              'direct_laplace', 'orthogonal'))
    icheck(1, Cont2D())
    icheck(2, Cont2D())
    icheck(3, NoneOr(Cont2D()))
    icheck(4, NoneOr(Cont2D()))
    icheck(5, List(Float(), llen=4))
    icheck(6, Bool())

    # call
    args = {
        'algo': algo,
        'left': left,
        'right': right,
        'bot': bottom,
        'top': top,
        'her_w': hermite_tfi_w,
        'return_invalid': return_invalid
    }
    c = com.gridcom.AddCustomRectGrid(args)
    flow.exec_command(c)
    return c.added_grids2()[0]
예제 #12
0
파일: o2info.py 프로젝트: cescjf/HybMesh
def get_point(obj,
              ind=None,
              vclosest=None,
              eclosest=None,
              cclosest=None,
              only_contour=True):
    """ Returns object point

    :param obj: grid or contour identifier

    :param int ind: index of point

    :param vclosest:

    :param eclosest:

    :param cclosest: point as [x, y] list

    :param bool only_contour: If that is true then if **objs** is a grid
       then respective grid contour will be used

    :returns: point as [x, y] list

    Only one of **ind**, **vclosest**, **eclosest**, **cclosest**
    arguments should be defined.

    If **ind** is defined then returns point at given index.

    If **vvlosest** point is defined then returns object vertex closest to
    this point.

    If **eclosest** point is defined then returns point owned by an
    object edge closest to input point.

    If **cclosest** point is defined then returns non straight line
    object contour vertex closest to input point.
    """
    icheck(0, ACont2D())
    icheck(1, NoneOr(UInt()))
    icheck(2, NoneOr(Point2D()))
    icheck(3, NoneOr(Point2D()))
    icheck(4, NoneOr(Point2D()))
    icheck(5, Bool())
    if ind is None and vclosest is None and eclosest is None and\
            cclosest is None:
        raise InvalidArgument("Define point location")

    try:
        tar = flow.receiver.get_contour2(obj)
    except KeyError:
        tar = flow.receiver.get_grid2(obj)
        if only_contour or cclosest is not None:
            tar = tar.contour()
    if cclosest is not None:
        tar = tar.deepcopy()
        c2core.simplify(tar.cdata, 0, False)
        vclosest = cclosest

    if vclosest is not None:
        return tar.closest_points([vclosest], "vertex")[0]
    elif eclosest is not None:
        return tar.closest_points([eclosest], "edge")[0]
    elif ind is not None:
        return tar.point_at(ind)