Exemple #1
0
def test():
    x1 = nm.fix( nm.random.rand( 5, 3 ) * 5 ) / 10
    x2 = nm.fix( nm.random.rand( 10, 3 ) * 5 ) / 10
    cmap = find_map( x1, x2 )
    conn1 = nm.array( [[range( 5 )], [range( 5 )]] ).squeeze()
    conn2 = nm.array( [[range( 10 )], [range( 10 )]] ).squeeze()
    conn2.shape = (4, 5)

    print x1
    print conn1
    print x2
    print conn2
    print cmap
    xx, conns = merge_mesh( x1, [conn1], x2, [conn2], cmap )
    print xx
    print conns
def compose_periodic_mesh(mesh_in, scale, repeat, eps, check_mvd=False):
    """
    Create a new mesh from a periodic mesh by scaling it and repeating
    along each axis,

    Parameters
    ----------
    mesh_in : Mesh instance
        The input periodic mesh.
    scale : float
        The scale parameter.
    repeat : array
        The number of repetitions of `mesh_in` along each axis.
    eps : float
        Tolerance for finding matching mesh vertices.
    check_mvd : bool
        If True, verify periodicity by checking approximate minimum
        vertex distance and minimum edge length.

    Returns
    -------
    mesh_out : Mesh instance
        The composed periodic mesh.
    """
    dim = mesh_in.dim
    bbox = mesh_in.get_bounding_box()
    mscale = bbox[1] - bbox[0]
    output('bbox:\n', bbox)

    centre0 = 0.5 * (bbox[1] + bbox[0])
    output('centre:\n', centre0)

    scale = float(scale)
    if repeat is None:
        repeat = [scale] * dim

    repeat = nm.asarray(repeat)

    # Normalize original coordinates.
    coor0 = (mesh_in.coors - centre0) / (mscale)

    aux = fix_double_nodes(coor0, mesh_in.ngroups, mesh_in.conns, eps)
    coor0, ngroups0, mesh_in.conns = aux
    
    if check_mvd:
        mes0 = get_min_edge_size(coor0, mesh_in.conns)
        mvd0 = get_min_vertex_distance(coor0, mes0)
        if mes0 > (mvd0 + eps):
            output('          original min. "edge" length: %.5e' % mes0)
            output('original approx. min. vertex distance: %.5e' % mvd0)
            output('-> still double nodes in input mesh!')
            output('try increasing eps')
            raise ValueError('cannot fix double nodes!')

    output('composing periodic mesh...')
    for indx in cycle(repeat):
        aindx = nm.array(indx, dtype=nm.float64)
        centre = 0.5 * (2.0 * aindx - repeat + 1.0)
        output(indx, centre)

        if aindx.sum() == 0:
            coor = coor0 + centre
            ngroups = ngroups0
            conns = mesh_in.conns
        else:
            coor1 = coor0 + centre
            ngroups1 = ngroups0
            conns1 = mesh_in.conns

            cmap = find_map(coor, coor1, eps=eps)
            if not cmap.size:
                raise ValueError('non-periodic mesh!')

            else:
                output(cmap.size / 2)

            coor, ngroups, conns = merge_mesh(coor, ngroups, conns,
                                              coor1, ngroups1, conns1,
                                              cmap, eps=eps)

    if check_mvd:
        mes = get_min_edge_size( coor, conns )
        mvd = get_min_vertex_distance( coor, mes0 )

        output('          original min. "edge" length: %.5e' % mes0)
        output('             final min. "edge" length: %.5e' % mes)
        output('original approx. min. vertex distance: %.5e' % mvd0)
        output('   final approx. min. vertex distance: %.5e' % mvd)
        if mvd < 0.99999 * mvd0:
            if mvd0 < (mes0 - eps):
                output('-> probably non-periodic input mesh!')
                output('   - adjacent sides were not connected!')
                output('   try increasing eps')
            else:
                output('-> input mesh might be periodic')
                output('   try increasing eps')
        else:
            output('-> input mesh looks periodic')
    else:
        output('non-periodic input mesh detection skipped!')

    # Renormalize.
    coor = (coor * mscale) / scale
    mesh_out = make_mesh(coor, ngroups, conns, mesh_in)
    output('...done')

    return mesh_out
Exemple #3
0
def main():

    parser = OptionParser( usage = usage, version = "%prog 42" )
    parser.add_option( "-s", "--scale", type = int, metavar = 'scale',
                       action = "store", dest = "scale",
                       default = 2, help = help['scale'] )
    parser.add_option( "-e", "--eps", type = float, metavar = 'eps',
                       action = "store", dest = "eps",
                       default = 1e-8, help = help['eps'] )
    parser.add_option( "-t", "--test",
                       action = "store_true", dest = "test",
                       default = False, help = help['test'] )
    parser.add_option( "-n", "--no-mvd",
                       action = "store_true", dest = "nomvd",
                       default = False, help = help['nomvd'] )
    (options, args) = parser.parse_args()

    if options.test:
        test()
        return

    if (len( args ) == 2):
        filename_in = args[0]
        filename_out = args[1]
    else:
        parser.print_help()
        return

    print 'scale:', options.scale
    print 'eps:', options.eps

    mesh_in = Mesh.from_file( filename_in )
    bbox = mesh_in.get_bounding_box()
    print 'bbox:\n', bbox
    mscale = bbox[1] - bbox[0]
    centre0 = 0.5 * (bbox[1] + bbox[0])
    print 'centre:\n', centre0

    scale = nm.array( options.scale, dtype = nm.float64 )

    # Normalize original coordinates.
    coor0 = (mesh_in.nod0[:,:-1] - centre0) / (mscale)
    dim = mesh_in.dim

    coor0, mesh_in.conns = fix_double_nodes( coor0, mesh_in.conns, options.eps )
    if not options.nomvd:
        mes0 = get_min_edge_size( coor0, mesh_in.conns )
        mvd0 = get_min_vertex_distance( coor0, mes0 )
        if mes0 > (mvd0 + options.eps):
            print '          original min. "edge" length: %.5e' % mes0
            print 'original approx. min. vertex distance: %.5e' % mvd0
            print '-> still double nodes in input mesh!'
            print 'try increasing eps...'
            raise ValueError

    for indx in cycle( [options.scale] * dim ):
        aindx = nm.array( indx, dtype = nm.float64 )
        centre = 0.5 * (2.0 * aindx - scale + 1.0)
        print indx, centre

        if aindx.sum() == 0:
            coor = coor0 + centre
            conns = mesh_in.conns
        else:
            coor1 = coor0 + centre
            conns1 = mesh_in.conns

            cmap = find_map( coor, coor1, eps = options.eps )
            if not cmap.size:
                print 'non-periodic mesh!'
#                raise ValueError
            else:
                print cmap.size / 2
            coor, conns = merge_mesh( coor, conns, coor1, conns1, cmap,
                                     eps = options.eps )

    if not options.nomvd:
        mes = get_min_edge_size( coor, conns )
        mvd = get_min_vertex_distance( coor, mes0 )

        print '          original min. "edge" length: %.5e' % mes0
        print '             final min. "edge" length: %.5e' % mes
        print 'original approx. min. vertex distance: %.5e' % mvd0
        print '   final approx. min. vertex distance: %.5e' % mvd
        if mvd < 0.99999 * mvd0:
            if mvd0 < (mes0 - options.eps):
                print '-> probably non-periodic input mesh!'
                print '   ... adjacent sides were not connected!'
                print '   try increasing eps...'
            else:
                print '-> input mesh might be periodic'
                print '   try increasing eps...'
        else:
            print '-> input mesh looks periodic'
    else:
        print 'non-periodic input mesh detection skipped!'

    print 'renormalizing...'
    coor = (coor * mscale) / scale
    print 'saving...'
    mesh_out = make_mesh( coor, conns, mesh_in )
    mesh_out.write( filename_out, io = 'auto' )
    print 'done.'