Esempio n. 1
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]
Esempio n. 2
0
def matched_partition(cont, step, influence, ref_conts=[], ref_pts=[],
                      angle0=30., power=3.):
    """ Makes a contour partition with respect to other
        contours partitions and given reference points

        :param cont: target contour.

        :param float step: default contour step size.

        :param float influence: influence radius of size conditions.

        :param ref_conts: list of contours which segmentation will
          be treated as target segmentation conditions.

        :param ref_pts: reference points given as
           ``[step0, [x0, y0], step1, [x1, y1], ...]`` list.

        :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 positive-float power: shows power of weight
           calculation function. As this parameter increases
           size transitions along contour become less smooth and more
           sensible to size conditions.

        See :ref:`matchedcontmeshing` for details.
    """
    icheck(0, ACont2D())
    icheck(1, Float(grthan=0.0))
    icheck(2, Float(grthan=0.0))
    icheck(3, UList(ACont2D()))
    icheck(4, CompoundList(Float(grthan=0.0), Point2D()))
    icheck(5, Float(within=[-1., 180., '[]']))
    icheck(6, Float(grthan=0.0))

    if not isinstance(ref_conts, list):
        ref_conts = [ref_conts]

    rp = []
    for i in range(len(ref_pts) / 2):
        rp.append(ref_pts[2 * i])
        rp.extend(ref_pts[2 * i + 1])

    args = {"base": cont,
            "cconts": ref_conts,
            "cpts": rp,
            "step": step,
            "infdist": influence,
            "angle0": angle0,
            "power": power
            }
    c = com.contcom.MatchedPartition(args)
    flow.exec_command(c)
    return c.added_contours2()[0]
Esempio n. 3
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]
Esempio n. 4
0
def pebi_fill(domain, constr=[], pts=[]):
    """Builds perpendicular bisector cells in given domain.

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

    :param constr: single or list of contours representing
        meshing 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

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

    Routine can produce concave cells (as a result of bad size
    control or near the concave domain boundary vertices).
    Use :func:`heal_grid` routine with ``convex_cells`` option to fix this.

    See details in :ref:`unstructured-meshing`.
    """
    icheck(0, UListOr1(ACont2D()))
    icheck(1, UListOr1(ACont2D()))
    icheck(2, CompoundList(Float(grthan=0.0), Point2D()))
    return _triquad(domain, constr, pts, 'pebi')
Esempio n. 5
0
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()
Esempio n. 6
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]
Esempio n. 7
0
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
Esempio n. 8
0
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]
Esempio n. 9
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])
Esempio n. 10
0
def scale_geom(objs, xpc=100., ypc=100., zpc=100., refp=[0.0, 0.0, 0.0]):
    """ Scales objects

    :param objs: identifier or list of identifiers of scaling objects

    :param float xpc:

    :param float ypc:

    :param float zpc: percentages of scaling in x, y and z directions

    :param list-of-float refp: reference point as ``[x, y, z]`` which stays
       fixed after transformation

    :returns: None

    if **objs** contains only 2d objects **zpc** is ignored and could be
    ommitted, **refp** could by given as ``[x, y]``.
    """
    icheck(0, UListOr1(AObject()))
    icheck(1, Float(grthan=0.))
    icheck(2, Float(grthan=0.))
    icheck(3, Float(grthan=0.))
    icheck(4, APoint())
    # for backward compatibility check if zpc was omitted
    if isinstance(zpc, list):
        refp = zpc
        zpc = 100.
    if len(refp) == 2:
        refp = [refp[0], refp[1], 0.]

    ob = objs if isinstance(objs, list) else [objs]
    c = com.objcom.ScaleGeom({
        "names": ob,
        "xpc": xpc,
        "ypc": ypc,
        "zpc": zpc,
        "p0": refp
    })
    flow.exec_command(c)
Esempio n. 11
0
def move_geom(objs, dx, dy, dz=0.):
    """ Moves a list of objects

    :param objs: identifier or list of identifiers of moving objects

    :param float dx:

    :param float dy:

    :param float dz: shifts in x, y and z direction. Z moves take place only
       for 3d objects

    :returns: None
    """
    icheck(0, UListOr1(AObject()))
    icheck(1, Float())
    icheck(2, Float())
    icheck(3, Float())

    ob = objs if isinstance(objs, list) else [objs]
    c = com.objcom.MoveGeom({"names": ob, "dx": dx, "dy": dy, "dz": dz})
    flow.exec_command(c)
Esempio n. 12
0
def partition_segment(start, end, hstart, hend, hinternal=[]):
    """ Makes a partition of numeric segment by given
    recommended step sizes at different locations.

    :param float start:

    :param float end: start and end points of numeric segment.

    :param float hstart:

    :param float hend: recommended step at the beginning and at the
       end of numeric segments

    :param list-of-floats hinternal: possible internal recommended steps
       given as [segment value0, step0, segment value1, step1, ...]

    :returns: increasing float list representing
       partitioned segment [start, ..(internal steps).., end]

    This is a helper function which runs iterative procedure
    to adopt partition of the segment to user defined step size
    recommendations. It could be used for example to
    explicitly define partition in :func:`add_unf_rect_grid`,
    :func:`add_unf_circ_grid` with given `custom\_\*` options or
    vertical partition of boundary grid in :func:`build_boundary_grid`.

    Example:
      Shows division of [1, 2] segment from approximately 0.1
      step size at the beginning to approximately 0.5 step size at
      the end

      .. code-block:: python

         print hm.partition_segment(1, 2, 0.1, 0.5)
         >>> [1.0, 1.1238348, 1.309012, 1.585923, 2.0]

      Shows division of [1, 2] segment with approximate 0.1
      step sizes at its end points and 0.4 step size at the center.

      .. code-block:: python

         print hm.partition_segment(1, 2, 0.1, 0.1, [1.5, 0.4])
         >>> [1.0, 1.1082238, 1.3278488, 1.672151, 1.891776, 2.0]
    """
    icheck(0, Float())
    icheck(1, Float(grthan=start))
    icheck(2, Float(grthan=0.))
    icheck(3, Float(grthan=0.))
    icheck(4, CompoundList(Float(within=[start, end, '()']),
                           Float(grthan=0.0)))

    from hybmeshpack.hmcore import c2 as c2core
    return c2core.segment_partition(start, end, hstart, hend, hinternal)
Esempio n. 13
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)
Esempio n. 14
0
def rotate_geom(objs, angle, pc=[0.0, 0.0]):
    """ Rotates group of 2d objects

    :param objs: identifier or list of identifiers of rotating 2d objects

    :param float angle: degree of rotation. Positive angle corresponds to
       counterclockwise rotation

    :param list-of-float pc: center of rotation

    :returns: None
    """
    icheck(0, UListOr1(ACont2D()))
    icheck(1, Float())
    icheck(2, Point2D())
    ob = objs if isinstance(objs, list) else [objs]
    c = com.objcom.RotateGeom({"names": ob, "angle": angle, "p0": pc})
    flow.exec_command(c)
Esempio n. 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]
Esempio n. 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')
Esempio n. 17
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]
Esempio n. 18
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]
Esempio n. 19
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]
Esempio n. 20
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]
Esempio n. 21
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]
Esempio n. 22
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]