示例#1
0
def _not_equal_nodes_build_tree(nodes_xyz, xyz_compare, tol, neq_max=4, msg=''):
    # type: (np.ndarray, np.ndarray, float, int, str) -> (Any, np.ndarray, np.ndarray)
    """
    helper function for `bdf_equivalence_nodes`

    Parameters
    ----------
    nodes_xyz : (Nnodes, 3) float ndarray
         the source points
    xyz_compare : (Ncompare, 3) float ndarray
         the xyz points to compare to
    tol : float
        the max spherical tolerance
    neq_max : int; default=4
        the number of close nodes
    msg : str; default=''
        error message

    Returns
    -------
    kdt : cKDTree()
        the kdtree object
    ieq : int ndarray
        The indices of nodes_xyz where the nodes in xyz_compare are close???
        neq_max = 1:
            (N, ) int ndarray
        neq_max > 1:
            (N, N) int ndarray
    slots : int ndarray
        The indices of nodes_xyz where the nodes in xyz_compare are close???
        neq_max = 1:
            (N, ) int ndarray
        neq_max > 1:
            (N, N) int ndarray
    msg : str; default=''
        error message

    """
    assert isinstance(xyz_compare, np.ndarray), type(xyz_compare)
    if nodes_xyz.shape[1] != xyz_compare.shape[1]:
        msgi = 'nodes_xyz.shape=%s xyz_compare.shape=%s%s' % (
            str(nodes_xyz.shape), str(xyz_compare.shape), msg)
        raise RuntimeError(msgi)
    kdt = _get_tree(nodes_xyz, msg=msg)
    # check the closest 10 nodes for equality
    deq, ieq = kdt.query(xyz_compare, k=neq_max, distance_upper_bound=tol)
    #print(deq)
    #print('ieq =', ieq)
    #print('neq_max = %s' % neq_max)

    # get the ids of the duplicate nodes
    nnodes = nodes_xyz.shape[0]
    if neq_max == 1:
        assert len(deq.shape) == 1, deq.shape
        slots = np.where(ieq < nnodes)
    else:
        assert len(deq.shape) == 2, deq.shape
        slots = np.where(ieq[:, :] < nnodes)
    #print('slots =', slots)
    return kdt, ieq, slots
示例#2
0
def _not_equal_nodes_build_tree(nodes_xyz, xyz_compare, tol, neq_max=4):
    """
    helper function for `bdf_equivalence_nodes`

    Parameters
    ----------
    nodes_xyz : (N, 3) float ndarray
         the source points
    xyz_compare : (N, 3) float ndarray
         the xyz points to compare to
    tol : float
        the max spherical tolerance
    neq_max : int; default=4
        the number of close nodes

    Returns
    -------
    kdt : cKDTree() or KDTree()
        the kdtree object
    ieq : int ndarray
        The indices of nodes_xyz where the nodes in xyz_compare are close???
        neq_max = 1:
            (N, ) int ndarray
        neq_max > 1:
            (N, N) int ndarray
    slots : int ndarray
        The indices of nodes_xyz where the nodes in xyz_compare are close???
        neq_max = 1:
            (N, ) int ndarray
        neq_max > 1:
            (N, N) int ndarray
    """
    assert isinstance(xyz_compare, np.ndarray), type(xyz_compare)
    if nodes_xyz.shape[1] != xyz_compare.shape[1]:
        msg = 'nodes_xyz.shape=%s xyz_compare.shape=%s' % (
            str(nodes_xyz.shape), str(xyz_compare.shape))
        raise RuntimeError(msg)

    kdt = _get_tree(nodes_xyz)
    # check the closest 10 nodes for equality
    deq, ieq = kdt.query(xyz_compare, k=neq_max, distance_upper_bound=tol)
    #print(deq)
    #print('ieq =', ieq)
    #print('neq_max = %s' % neq_max)

    # get the ids of the duplicate nodes
    nnodes = nodes_xyz.shape[0]
    if neq_max == 1:
        assert len(deq.shape) == 1, deq.shape
        slots = where(ieq < nnodes)
    else:
        assert len(deq.shape) == 2, deq.shape
        slots = where(ieq[:, :] < nnodes)
    #print('slots =', slots)
    return kdt, ieq, slots
示例#3
0
def pierce_shell_model(bdf_filename, xyz_points, tol=1.0):
    # type: (Union[BDF, str], Any, float) -> List[int], np.ndarray, List[List[int]]
    """
    Pierces a shell model with a <0., 0., 1.> vector.  In other words,
    models are pierced in the xy plane.

    Parameters
    ----------
    bdf_filename : str / BDF()
        the model to run
    xyz_points : (npoints, 3) float ndarray
        the xyz_points to pierce
    tol : float; default=1.0
        the pierce tolerance
        pick a value that is ~3x the max local element edge length

    Returns
    -------
    eids_pierce : List[int]
        int : The element ids that were pierced.
              If multiple elements are pierced, the one with the largest
              pierced z value will be returned.
        None : invalid pierce
    xyz_pierces_max : List[float ndarray, None]
        ndarray : pierce location
        None : invalid pierce
    node_ids : List[int ndarray, None]
        ndarray : pierced element's nodes
        None : invalid pierce
    """
    xyz_points = np.asarray(xyz_points)
    assert xyz_points.shape[1] == 3, xyz_points.shape
    xy_points = xyz_points[:, :2]
    assert xy_points.shape[1] == 2, xy_points.shape

    if isinstance(bdf_filename, BDF):
        model = bdf_filename
    else:
        model = read_bdf(bdf_filename)

    eids = []
    centroids = []
    etypes_to_skip = [
        'CHEXA',
        'CPENTA',
        'CTETRA',
        'CPYRAM',
        'CBUSH',
        'CBUSH1D',
        'CBUSH2D',
        'CBEAM',
        'CROD',
        'CONROD',
        'CELAS1',
        'CELAS2',
        'CELAS3',
        'CELAS4',
        'CDAMP1',
        'CDAMP2',
        'CDAMP3',
        'CDAMP4',
        'CDAMP5',
    ]
    for eid, elem in iteritems(model.elements):
        if elem.type in ['CQUAD4', 'CTRIA3']:
            centroid = elem.Centroid()
        elif elem.type in etypes_to_skip:
            continue
        else:
            print(elem.type)
            #raise NotImplementedError(elem)
            continue
        eids.append(eid)
        centroids.append(centroid)
    eids = np.array(eids, dtype='int32')
    assert len(eids) > 0, 'eids=%s\n' % eids
    centroids_xy = np.array(centroids, dtype='float64')[:, :2]

    #print('centroids:\n%s\n' % str(centroids_xy))
    assert centroids_xy.shape[1] == 2, centroids_xy.shape

    msg = 'which is required by pierce_shell_model'
    kdt = _get_tree(centroids_xy, msg=msg)
    results = kdt.query_ball_point(xy_points, tol)
    nresults = len(results)
    iresults = np.arange(nresults)
    #print(results)
    #print(iresults)

    direction = np.array([0., 0., 1.])
    ipoints = []
    eids_pierce = []
    xyz_pierces_max = []
    node_ids = []
    for i, xyz_point, eidsi in zip(count(), xyz_points, results):
        model.log.debug('eidsi = [%s]' %
                        ', '.join([str(eidii).rstrip('L') for eidii in eidsi]))
        if not eidsi:
            ipoints.append(i)
            eids_pierce.append(None)
            xyz_pierces_max.append(None)
            node_ids.append(None)
            model.log.warning(
                'skipping %s because it failed tolerancing (tol=%s)' %
                (xyz_point, tol))
            continue

        model.log.debug('xyz_point = %s' % xyz_point)
        eidsi2 = eids[eidsi]
        eids_newi = []
        piercesi = []
        zpiercesi = []
        for eid in eidsi2:
            elem = model.elements[eid]
            if elem.type == 'CQUAD4':
                v0 = elem.nodes_ref[0].get_position()
                v1 = elem.nodes_ref[1].get_position()
                v2 = elem.nodes_ref[2].get_position()
                v3 = elem.nodes_ref[3].get_position()
                xyz_pierce = quad_intersection(xyz_point, direction, v0, v1,
                                               v2, v3)
            elif elem.type == 'CTRIA3':
                v0 = elem.nodes_ref[0].get_position()
                v1 = elem.nodes_ref[1].get_position()
                v2 = elem.nodes_ref[2].get_position()
                xyz_pierce = triangle_intersection(xyz_point, direction, v0,
                                                   v1, v2)
            else:
                raise NotImplementedError(elem)

            if xyz_pierce is None:
                #model.log.warning('failed to pierce eid=%s' % eid)
                continue

            zpierce = xyz_pierce[2]
            model.log.debug('  eid=%s xyz_pierce=%s zpierce=%s' %
                            (eid, xyz_pierce, zpierce))
            eids_newi.append(eid)
            piercesi.append(xyz_pierce)
            zpiercesi.append(zpierce)

        if len(zpiercesi) == 0:
            ipoints.append(i)
            eids_pierce.append(None)
            xyz_pierces_max.append(None)
            node_ids.append(None)
            model.log.warning('skipping %s because no pierces found (tol=%s)' %
                              (xyz_point, tol))
            continue

        #print('zpiercesi = %s' % zpiercesi)
        zpiercesi_max = max(zpiercesi)
        ipierce_max = zpiercesi.index(zpiercesi_max)
        eid_max = eids_newi[ipierce_max]
        xyz_piercei_max = piercesi[ipierce_max]
        model.log.debug(
            'i=%s xyz_point=%s xyz_piercei_max=%s zpiercesi=%s zmax=%s eid_max=%s'
            %
            (i, xyz_point, xyz_piercei_max, zpiercesi, zpiercesi_max, eid_max))

        ipoints.append(i)
        eids_pierce.append(eid_max)
        xyz_pierces_max.append(xyz_piercei_max)
        #print(model.elements[eid_max])
        node_ids.append(model.elements[eid_max].node_ids)

    xyz_pierces_max = np.array(xyz_pierces_max)
    model.log.debug('ipoints=%s' % ipoints)
    model.log.info('eids_pierce=%s' % eids_pierce)
    model.log.info('xyz_pierces_max:\n%s' % xyz_pierces_max)
    model.log.info('node_ids=%s' % node_ids)

    return eids_pierce, xyz_pierces_max, node_ids