Beispiel #1
0
def export3d_grid_hmg(gid, fname, fmt="ascii", afields=[]):
    """Exports 3d 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.

      To save additional data into grid file
      :ref:`user defined fields <udef-fields>`
      place any of these strings into **afields** list:

      * ``'face-vertices'`` - face vertex ordered connectivity,
      * ``'cell-faces'`` - cell face connectivity,
      * ``'cell-vertices'`` - cell vertex connectivity,
      * ``'linfem'`` - tries to write cells-vertex connectivity
        for cell types most widely used in linear fem solvers.
        Supported cell types are: tetrahedron (4 nodes), hexahedron (8),
        prism(6), pyramid(5).
        Record for each of those cells contains points in order prescribed
        by vtk file format. If a cell is not of one of those types
        then a zero length connectivity list will be written for it.

        .. figure:: vtk_cells3d.png
           :width: 500 px

      See :ref:`grid3d-file` for format description.
    """
    if fmt == "binary":
        fmt = "bin"
    if fmt == "fbinary":
        fmt = "fbin"
    icheck(0, UListOr1(Grid3D()))
    icheck(1, String())
    icheck(2, OneOf('ascii', 'bin', 'fbin'))
    icheck(
        3,
        UList(OneOf('face-vertices', 'cell-faces', 'cell-vertices', 'linfem')))
    names = gid if isinstance(gid, list) else [gid]
    grids = map(flow.receiver.get_grid3, names)
    cb = flow.interface.ask_for_callback()
    native_export.grid3_tofile(fname, grids, names, fmt, afields, cb)
Beispiel #2
0
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
Beispiel #3
0
def check_compatibility(vers, policy=1):
    """ Checks version compatibility. Notifies if current version
    of hymbesh is not fully compatible with input version.

    :param str vers: version in ``"0.1.2"`` format

    :param int policy: if versions are incompatible then:

       * 0 - do nothing (return False)
       * 1 - report warning to cout
       * 2 - raise ExecError

    :returns: False if versions are incompatible, True otherwise.

    """
    icheck(0, String())
    icheck(1, OneOf(1, 2, 3))

    versc = progdata.HybMeshVersion.current()
    versi = progdata.HybMeshVersion(vers)
    # last checked for 0.2.1 version
    ret = True
    if (versi > versc):
        ret = False
    if (versi < progdata.HybMeshVersion("0.2.1")):
        ret = False
    if not ret:
        message = "Current version of hybmesh %s is not " \
            "fully compatible with version %s" % (versc, vers)
        if policy == 1:
            print "WARNING:", message
        elif policy == 2:
            raise Exception(message)
    return ret
Beispiel #4
0
def export3d_surface_hmc(sid, fname, fmt="ascii"):
    """Exports 3d surface to hybmesh native format.

      :param sid: single or list of surface 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.

      See :ref:`surface3d-file` for format description.
    """
    if fmt == "binary":
        fmt = "bin"
    elif fmt == "fbinary":
        fmt = "fbin"
    icheck(0, UListOr1(ASurf3D()))
    icheck(1, String())
    icheck(2, OneOf('ascii', 'bin', 'fbin'))

    names = sid if isinstance(sid, list) else [sid]
    surfs = [_surf3_from_id(n) for n in names]
    cb = flow.interface.ask_for_callback()
    native_export.surf3_tofile(fname, surfs, names, fmt, cb)
Beispiel #5
0
def export_contour_hmc(cid, fname, fmt="ascii"):
    """Exports contours to native format.

      :param cid: contour identifier or list of 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.

      :returns: None

      See :ref:`contour2d-file` for format description.
    """
    if fmt == "binary":
        fmt = "bin"
    elif fmt == "fbinary":
        fmt = "fbin"
    icheck(0, UListOr1(ACont2D()))
    icheck(1, String())
    icheck(2, OneOf('ascii', 'bin', 'fbin'))

    names = cid if isinstance(cid, list) else [cid]
    conts = [_cont2_from_id(n) for n in names]
    cb = flow.interface.ask_for_callback()
    native_export.cont2_tofile(fname, conts, names, fmt, cb)
Beispiel #6
0
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)
Beispiel #7
0
def add_circ_rect_grid(p0, rad, step, sqrside=1.0, rcoef=1.0, algo="linear"):
    """ Creates quadrangular cell grid in a circular area.
    See details in :ref:`circrect_grid`.

    :param list-of-floats p0: center point of circle area in [x, y] format.

    :param positive-float rad: radius of circle area.

    :param positive-float step: approximate partition step of the outer
       boundary.

    :param positive-float sqrside: side of the inner square normalized by
       the circle radius. Values greater than 1.4 are not allowed.

    :param positive-float rcoef: radius direction refinement of
       the ring part of the grid.
       Values less then unity lead to refinement towards outer boundary.

    :param str algo: Algorithms of assembling the ring part of the grid.

       * ``'linear'`` - use weighted approach for each ray partition
       * ``'laplace'`` - use algebraic mapping for
         building each 45 degree sector.
       * ``'orthogonal_circ'`` - build orthogonal grid keeping
         uniform grid at outer circle
       * ``'orthogonal_rect'`` - build orthogonal grid keeping
         uniform grid at inner rectangle

    :return: new grid identifier

    """
    icheck(0, Point2D())
    icheck(1, Float(grthan=0.0))
    icheck(2, Float(grthan=0.0))
    icheck(3, Float(within=[0., 1.4, '[)']))
    icheck(4, Float(grthan=0.0))
    icheck(5, OneOf('linear', 'laplace', 'orthogonal_circ', 'orthogonal_rect'))

    # call
    args = {
        'algo': algo,
        'p0': p0,
        'rad': rad,
        'step': step,
        'sqrside': sqrside,
        'rcoef': rcoef
    }
    c = com.gridcom.AddCirc4Grid(args)
    flow.exec_command(c)
    return c.added_grids2()[0]
Beispiel #8
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)
Beispiel #9
0
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]
Beispiel #10
0
def build_boundary_grid1(cont,
                         partition,
                         direction,
                         pstart=None,
                         pend=None,
                         range_angles=[40, 125, 235, 275]):
    """Builds a singly-connected boundary grid near given contour.

    :param cont: source contour (or grid) identifier

    :param list-of-float partition: partition in perpendicular direction.

    :param str direction: 'left'/'right'

    :param pstart:

    :param pend: points in [x, y] format which define
      the exact segment of the contour for building grid.
      If both are None hence whole contour (or all subcontours) will be used.

    :param range_angles: list of 4 angle values (deg) which define algorithms
      for contour bends treatment.

    :returns: identifier of the newly created grid.

    This is a wrapper for a :func:`build_boundary_grid` with simplified
    interface. It allows to build a boundary grid with constant partition
    options using existing contour segmentation for horizontal stepping.
    """
    icheck(0, ACont2D())
    icheck(1, IncList(Float(), startfrom=0.0))
    icheck(2, OneOf('left', 'right'))
    icheck(3, NoneOr(Point2D()))
    icheck(4, NoneOr(Point2D(noteq=pstart)))
    icheck(5, IncList(Float(within=[0, 360, '[]'])))

    bo = BoundaryGridOptions(cont,
                             partition,
                             direction,
                             bnd_stepping='no',
                             range_angles=range_angles,
                             start_point=pstart,
                             end_point=pend)
    return build_boundary_grid([bo])
Beispiel #11
0
def tab_cont2(obj, what):
    """ Returns plain table for the given contour.

    :param str obj: contour 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,
    * ``'bt'`` - boundary features of each edge.

    """
    icheck(0, Cont2D())
    icheck(1, OneOf('vert', 'edge_vert', 'bt'))
    return flow.receiver.get_contour2(obj).raw_data(what)
Beispiel #12
0
def save_project(fname, fmt="ascii"):
    """Saves current command flow and data to HybMesh project file.

       :param str fname: file name

       :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.

       See :ref:`hmp-file` for description.
    """
    if fmt == "binary":
        fmt = "bin"
    elif fmt == "fbinary":
        fmt = "fbin"
    icheck(0, String())
    icheck(1, OneOf('ascii', 'bin', 'fbin'))

    flow_export.flow_and_framework_tofile(fname, flow, fmt)
Beispiel #13
0
def extract_subcontours(source, plist, project_to="vertex"):
    """ Extracts singly connected subcontours from given contour.

        :param source: source contour identifier

        :param list-of-list-of-float plist: consecutive list of
           subcontours end points

        :param str project_to: defines projection rule for **plist** entries

           * ``"line"`` projects to closest point on the source contour
           * ``"vertex"`` projects to closest contour vertex
           * ``"corner"`` projects to closest contour corner vertex

        :returns: list of new contours identifiers

        Length of **plist** should be equal or greater than two.
        First and last points in **plist** define first and last points
        of **source** segment to extract.
        All internal points define internal division
        of this segment. Hence number of resulting subcontours will equal
        number of points in **plist** minus one.

        For closed **source** contour first and last **plist** points
        could coincide. In that case the sum of resulting subcontours
        will be equal to **source**.
    """
    icheck(0, ACont2D())
    icheck(1, List(Point2D(), minlen=2))
    icheck(2, OneOf("line", "vertex", "corner"))

    c = com.contcom.ExtractSubcontours({
        'src': source,
        'plist': plist,
        'project_to': project_to
    })
    flow.exec_command(c)
    return c.added_contours2()
Beispiel #14
0
def export_all_hmd(fname, fmt="ascii"):
    """Exports all geometrical data to native format.

       :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.

       See :ref:`nativeformat` for description.
    """
    if fmt == "binary":
        fmt = "bin"
    elif fmt == "fbinary":
        fmt = "fbin"
    icheck(0, String())
    icheck(1, OneOf('ascii', 'bin', 'fbin'))

    cb = flow.interface.ask_for_callback()
    native_export.export_all_tofile(fname, flow.receiver, fmt, cb)
Beispiel #15
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]
Beispiel #16
0
def triangulate_domain(domain, constr=[], pts=[], fill='3'):
    """Builds constrained triangulation within given domain

    :param domain: single or list of closed contours
        representing bounding domain

    :param constr: single or list of contours representing
        triangulation constraints

    :param pts: set of points in ``[len0, [x0, y0], ...]``
        format where ``x, y`` are coordinates of internal vertices
        which should be embedded into the resulting grid,
        ``len`` - size of adjacent cells
    :param str fill: if '3' then triangulates area; '4' runs
        recombination algorithm to make mostly quadrangular mesh

    :return: grid identifier

    A contour tree will be built using all closed contours
    passed as **domain** parameter. Only the interior parts
    of this tree will be meshed. Contours passed by **domain**
    should not intersect each other, but could intersect **constr**
    contours.
    **constr** could contain any set of closed and open contours.

    See details in :ref:`unstructured-meshing`.
    """
    icheck(0, UListOr1(ACont2D()))
    icheck(1, UListOr1(ACont2D()))
    icheck(2, CompoundList(Float(grthan=0.0), Point2D()))
    icheck(3, OneOf('3', '4'))

    if fill == '3':
        return _triquad(domain, constr, pts, '3')
    elif fill == '4':
        return _triquad(domain, constr, pts, '4')
Beispiel #17
0
def stdout_verbosity(verb):
    icheck(0, OneOf(0, 1, 2, 3))
    flow.set_interface(flow.interface.reset(verb))
Beispiel #18
0
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]
Beispiel #19
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]