def write_hgrid_ll(self, fname, input_epsg=26910, output_epsg=4269):
        """ Write a hgrid.ll, lat-long mesh file, of the current mesh.

            Parameters
            ----------
            fname: str
                the output file name
            input_epsg: int, optional
                input EPSG. default value is 26310, NAD83/UTM10N.
            output_epsg: int, optional
                output EPSG. default value is 4269, NAD83
        """
        inSpatialRef = osgeo.osr.SpatialReference()
        inSpatialRef.ImportFromEPSG(input_epsg)
        outSpatialRef = osgeo.osr.SpatialReference()
        outSpatialRef.ImportFromEPSG(output_epsg)
        coordTransform = osgeo.osr.CoordinateTransformation(
            inSpatialRef, outSpatialRef)

        new_mesh = SchismMesh()
        new_mesh._nodes = np.copy(self.mesh.nodes)
        new_mesh._elems = np.copy(self.mesh._elems)

        point = osgeo.ogr.Geometry(osgeo.ogr.wkbPoint)
        for i, node in enumerate(self.mesh.nodes):
            point.AddPoint(node[0], node[1])
            point.Transform(coordTransform)
            new_mesh.nodes[i, 0] = point.GetX()
            new_mesh.nodes[i, 1] = point.GetY()
        write_mesh(new_mesh, fname)
def main():
    """ main function for CLI
    """
    parser = create_arg_parser()
    args = parser.parse_args()
    fpath_mesh_in = args.meshinput
    if not os.path.exists(fpath_mesh_in):
        raise ValueError('The given input file not found')
    fpath_mesh_out = args.meshoutput
    skewness = args.skewness
    if skewness is not None:
        if skewness < 0.:
            raise ValueError('Skewness must be bigger than zero')
    minangle = args.minangle
    maxangle = args.maxangle
    if minangle is not None:
        minangle = np.pi * minangle / 180.
    if maxangle is not None:
        maxangle = np.pi * maxangle / 180.
    if skewness is None and minangle is None and maxangle is None:
        raise ValueError('No splitting criteria are given')

    mesh = schism_mesh.read_mesh(fpath_mesh_in)
    elems_to_split = sets.Set()
    n_elems_ori = mesh.n_elems()
    if skewness is not None:
        for elem_i, elem in enumerate(mesh.elems):
            if len(elem) == 4:
                # split
                skew = calculate_skewness(mesh.nodes[elem])
                if skew > skewness:
                    # split
                    elems_to_split.add(elem_i)
    if minangle is not None or maxangle is not None:
        for elem_i, elem in enumerate(mesh.elems):
            if len(elem) == 4:
                angles = calculate_internal_angles(mesh.nodes[elem])
                if minangle is not None:
                    angle_min = angles.min()
                    if angle_min < minangle:
                        elems_to_split.add(elem_i)
                if maxangle is not None:
                    angle_max = angles.max()
                    if angle_max > maxangle:
                        elems_to_split.add(elem_i)

    print("Found %d quad element(s) to spilt." % len(elems_to_split))

    if len(elems_to_split) < 1:
        print("No element to split.")
        return

    print("Start splitting...")
    split_quad(mesh, elems_to_split)
    print("Writing output file...")
    schism_mesh.write_mesh(mesh, fpath_mesh_out)
    if args.prop is not None:
        fpath_prop = args.prop
        write_prop(elems_to_split, n_elems_ori, fpath_prop)
    print("Done.")
Exemple #3
0
def cut_mesh(fpath_gr3_in, lines, fpath_gr3_out, cut_side='left'):
    """ Remove elements of a mesh in one side of cutting polyline segments.
        A mesh is read in from a gr3, and a result mesh is written in another
        gr3 file.
        A user needs to be careful that line segments forms a closed division.
        Otherwise, all elements would be deleted.

        Parameters
        ----------
        fpath_gr3_in
            Filename of the input grid in gr3
        lines: array-like
            An array of coordinates of line segments specifying the location
            of cuts
        fpath_gr3_out
            Filename of the output grid in gr3
        cut_side: str, optional
            If cut_side is 'left,' which is default, the left side of cutting
            lines when one sees the second point from the first point of a line
            will be removed.
            If this value is 'right,' the right side will be removed.
    """
    s = read_mesh(fpath_gr3_in)
    lines = np.array(lines).reshape(-1, 4)
    print("{} line(s) to cut found".format(lines.shape[0]))
    if cut_side == 'right':
        # Switch ordering
        lines = np.hstack((lines[:, 2:], lines[:, :2]))
    s.trim_to_left_of_mesh(lines)

    write_mesh(s, fpath_gr3_out)
Exemple #4
0
def main():
    """ Just a main function
    """
    parser = create_arg_parser()
    args = parser.parse_args()
    mesh = read_mesh(args.hgrid, args.vgrid)
    print(mesh.vmesh.n_vert_levels())
    n_levels = mesh.vmesh.n_vert_levels() - np.array(mesh.vmesh.kbps)
    write_mesh(mesh, args.output, node_attr=n_levels)
Exemple #5
0
 def test_schism_mesh_gr3_writer(self):
     fpath_mesh = self.fpath_mesh
     mesh = read_mesh(fpath_mesh)
     fpath_mesh_out = os.path.join(os.path.dirname(__file__),
                                   "testdata/meshout.gr3")
     write_mesh(mesh, fpath_mesh_out, write_boundary=True)
     meshout = read_mesh(fpath_mesh_out)
     self.assertEqual(meshout.n_nodes(), 112)
     self.assertEqual(meshout.n_elems(), 135)
     self.assertEqual(meshout.n_boundaries(), 3)
     if os.path.exists(fpath_mesh_out):
         os.remove(fpath_mesh_out)
Exemple #6
0
def grid_opt_with_args(args):
    """ Optimize grid with arguments parsed by argparse
    """
    with open(args.optparam) as f:
        opt_param = schism_yaml.load(f)
    mesh = read_mesh(args.filename, nodestring_option='land')
    with open(args.demfile, 'r') as f:
        demfiles = schism_yaml.load(f)
        # dir = os.path.dirname(args.demfile)
        # demfiles_full = [os.path.join(dir, fname) for fname in demfiles]
    logger = init_logger()
    kwargs = {
        'mesh': mesh,
        'demfiles': demfiles,  # demfiles_full,
        'na_fill': args.na_fill,
        'logger': logger
    }
    optimizer = GridOptimizer(**kwargs)
    optimized = optimizer.optimize(opt_param)
    fpath_output = args.optfile
    write_mesh(mesh, fpath_output, node_attr=-optimized)
Exemple #7
0
def vgrid_gen(hgrid,
              vgrid_out,
              eta,
              minmaxlayerfile,
              ngen,
              maxiter,
              theta,
              b,
              hc,
              dx2fac=20.0,
              curvewgt=100.0,
              foldwgt=20.,
              foldfrac=0.35,
              archive_nlayer=None,
              nlayer_gr3=None):
    from numlayer import tabu_numlayer
    from lsc2 import default_num_layers
    from vgrid_opt2 import *

    print("Reading the mesh ")
    mesh = read_mesh(hgrid)
    h0 = mesh.nodes[:, 2]
    depth = eta + h0

    if archive_nlayer == 'out':
        print("Reading the polygons...")
        polygons = read_polygons(minmaxlayerfile)
        minlayer = np.ones_like(h0, dtype='int')
        #minlayer[:] = 8 # todo need polygons
        maxlayer = np.ones_like(h0, dtype='int') * 10000
        dztarget = np.full_like(h0, 100., dtype='d')
        #maxlayer[:] = 31
        print("Assign min/max layers to nodes based on polygons...")
        for polygon in polygons:
            box = [polygon.bounds[i] for i in (0, 2, 1, 3)]
            candidates = mesh.find_nodes_in_box(box)
            n_layers_min = int(polygon.prop['minlayer'])
            n_layers_max = int(polygon.prop['maxlayer'])
            dz0 = float(polygon.prop['dz_target'])
            for node_i in candidates:
                if polygon.intersects(mesh.nodes[node_i, :2]):
                    minlayer[node_i] = n_layers_min
                    maxlayer[node_i] = n_layers_max
                    dztarget[node_i] = dz0

        if np.any(np.isnan(minlayer)):
            print(np.where(np.isnan(minlayer)))
            raise ValueError('Nan value in minlayer')
        print("Creating vertical grid...")
        #meshsmooth = read_mesh("hgrid_depth_smooth.gr3")
        hsmooth = mesh.nodes[:, 2]
        etazero = 0.
        assert len(hsmooth) == len(h0)
        # todo: was eta and h0
        dztarget = dztarget * 0 + 1.
        dztarget = 0.6 + 0.4 * (hsmooth - 12.) / (22. - 12.)
        dztarget = np.minimum(1.0, dztarget)
        dztarget = np.maximum(0.65, dztarget)
        #dztarget2 = np.minimum(1.3,0.65+0.65*(2.-hsmooth))
        #dztarget[hsmooth<2.] = dztarget2[hsmooth<2.]
        nlayer_default = default_num_layers(eta, hsmooth, minlayer, maxlayer,
                                            dztarget)
        #print nlayer_default
        #nlayer = deap_numlayer(depth,mesh.edges,nlayer_default,minlayer,ngen)
        nlayer = tabu_numlayer(depth, mesh.edges, nlayer_default, minlayer,
                               maxlayer, ngen)
        print depth.shape
        print nlayer.shape

        if archive_nlayer == "out":
            print "writing out number of layers"
            write_mesh(mesh,
                       nlayer_gr3.replace(".gr3", "_default.gr3"),
                       node_attr=nlayer_default)
            write_mesh(mesh, nlayer_gr3, node_attr=nlayer)
            write_mesh(mesh,
                       nlayer_gr3.replace(".gr3", "_dztarget.gr3"),
                       node_attr=dztarget)
    elif archive_nlayer == "in":
        nlayer_mesh = read_mesh(nlayer_gr3)
        dztarget = read_mesh(nlayer_gr3.replace(".gr3",
                                                "_dztarget.gr3")).nodes[:, 2]
        nlayer = nlayer_mesh.nodes[:, 2].astype('i')
        if long(nlayer_mesh.n_nodes()) != long(mesh.n_nodes()):
            raise ValueError(
                "NLayer gr3 file (%s)\nhas %s nodes, hgrid file (%s) has %s" %
                (nlayer_gr3, nlayer_mesh.n_nodes(), hgrid, mesh.n_nodes()))
        #print("Reading the polygons for dz_target...")
        #polygons = read_polygons(minmaxlayerfile)
        #dztarget = np.full_like(h0, np.nan, dtype='d')
        #maxlayer[:] = 31
        #print("Assign dz_target to nodes based on polygons...")
        #for polygon in polygons:
        #    box = [polygon.bounds[i] for i in (0, 2, 1, 3)]
        #    candidates = mesh.find_nodes_in_box(box)
        #    dz0 = float(polygon.prop['dz_target'])
        #    for node_i in candidates:
        #        if polygon.intersects(mesh.nodes[node_i, :2]):
        #            dztarget[node_i] = dz0

    else:
        raise ValueError("archive_nlayer must be one of 'out', 'in' or None")

    #np.savez("savevar.npz",nlayer,nlayer_default,depth,h0)
    sigma, nlayer_revised = gen_sigma(nlayer,
                                      dztarget,
                                      eta,
                                      h0,
                                      theta,
                                      b,
                                      hc,
                                      mesh=mesh)
    print "sigma shape"
    print sigma.shape
    nlayer = nlayer_revised
    nlevel = nlayer + 1

    #fsigma = flip_sigma(sigma)
    #print fsigma[0,:]
    vmesh = SchismLocalVerticalMesh(flip_sigma(sigma))
    vgrid0 = vgrid_out.replace(".in", "_int.in")
    write_vmesh(vmesh, vgrid0)

    #   Gradient based stuff

    nodes = mesh.nodes
    edges = mesh.edges
    x = nodes[:, 0:2]  # x positions for xsect. These have no analog in 3D
    sidelen2 = np.sum((x[edges[:, 1], :] - x[edges[:, 0], :])**2., axis=1)

    #nodemasked = (depth < 0.75) #| (nlayer <= 2)
    #todo hardwire was 0.75
    nodemasked = (depth < 0.75)  #| (nlayer <= 2)
    sidemasked = nodemasked[edges[:, 0]] | nodemasked[edges[:, 1]]
    gradmat = gradient_matrix(mesh, sidelen2, sidemasked)

    print "Nodes excluded: %s" % np.sum(nodemasked)
    print "Sides excluded: %s" % np.sum(sidemasked)

    zcor = vmesh.build_z(mesh, eta)[:, ::-1]

    # todo: test this
    #zcor[depth < 0., :] = np.nan

    # todo: why is kbps-1 so common? What does it mean and why the funny offset

    nvlevel = (vmesh.n_vert_levels() - vmesh.kbps)
    #nvlevel[depth<0] = 0

    nlayer, ndx = index_interior(zcor, nodemasked, nvlevel)
    xvar = zcor[ndx >= 0].flatten()
    xvarbase = xvar.copy()
    zcorold = zcor.copy()
    zmin = np.nanmin(zcorold, axis=1)
    deptharr = np.tile(zmin, (zcorold.shape[1], 1)).T
    zcorold = np.where(np.isnan(zcorold), deptharr, zcorold)

    do_opt = False
    if do_opt:
        curvewgt = np.zeros_like(zcorold) + curvewgt
        #todo: hardwire
        #bigcurvewgt = 4
        #for iii in range(zcor.shape[0]):
        #    nlev = nlayer[iii]+1
        #    curvewgt[iii,0:nlev]+=np.maximum(np.linspace(bigcurvewgt-nlev,bigcurvewgt-nlev,nlev),1)

        # todo
        ata = laplace2(mesh, nodemasked, sidemasked)
        href_hess, grad_hess, laplace_hess = hess_base(
            xvar, zcorold, mesh, nlayer, ndx, eta, depth, gradmat, sidelen2,
            nodemasked, sidemasked, ata, dx2fac, curvewgt, foldwgt, foldfrac)

        zcor1 = mesh_opt(zcorold, mesh, nlayer, ndx, eta, depth, gradmat,
                         sidelen2, nodemasked, sidemasked, ata, dx2fac,
                         curvewgt, foldwgt, foldfrac, href_hess, grad_hess,
                         laplace_hess)

    else:
        zcor1 = zcorold

    sigma1 = z_sigma(zcor1)
    nlevel = nlayer + 1
    for i in range(len(depth)):
        nlev = nlevel[i]
        if depth[i] <= 0:
            sigma1[i, 0:nlev] = np.linspace(0, -1.0, nlev)
        sigma1[i, nlev:] = np.nan

    vmesh1 = SchismLocalVerticalMesh(flip_sigma(sigma1))
    print("Writing vgrid.in output file...")
    write_vmesh(vmesh1, vgrid_out)
    print "Done"
def vgrid_gen(hgrid,
              vgrid_out,
              eta,
              minmaxlayerfile,
              archive_nlayer=None,
              nlayer_gr3=None):
    from lsc2 import default_num_layers

    meshfun = BilinearMeshDensity()

    dummydepth = np.linspace(0, 14, 15)
    dummyk = np.linspace(0, 14, 15)
    dummyout = meshfun.depth(dummyk, dummydepth, 0.)

    print("Reading the mesh ")
    mesh = read_mesh(hgrid)
    h0 = mesh.nodes[:, 2]

    places_on = np.array(
        [[626573.490000, 4260349.590000], [626635.000000, 4260391.7]],
        dtype='d')
    dists_on = np.min(scipy.spatial.distance.cdist(mesh.nodes[:, 0:2],
                                                   places_on),
                      axis=1)
    print(np.where(dists_on < 100))

    depth = eta + h0

    print("Reading the polygons...")
    polygons = read_polygons(minmaxlayerfile)
    minlayer = np.ones_like(h0, dtype='int')
    #minlayer[:] = 8 # todo need polygons
    maxlayer = np.ones_like(h0, dtype='int') * 10000
    dztarget = np.full_like(h0, 100., dtype='d')
    print("Assign min/max layers to nodes based on polygons...")
    for polygon in polygons:
        box = [polygon.bounds[i] for i in (0, 2, 1, 3)]
        candidates = mesh.find_nodes_in_box(box)
        n_layers_min = int(polygon.prop['minlayer'])
        n_layers_max = int(polygon.prop['maxlayer'])
        dz0 = float(polygon.prop['dz_target'])
        for node_i in candidates:
            if polygon.intersects(mesh.nodes[node_i, :2]):
                minlayer[node_i] = n_layers_min
                maxlayer[node_i] = n_layers_max
                dztarget[node_i] = dz0

    if np.any(np.isnan(minlayer)):
        print((np.where(np.isnan(minlayer))))
        raise ValueError('Nan value in minlayer')

    if archive_nlayer == 'out':

        dztarget = 0.
        #todo: these will ruin the code
        if fix_minmax:
            minlayer = minlayer * 0 + fixed_min
            maxlayer = maxlayer * 0 + fixed_max  #np.max(maxlayer)

        xdummy = 0.
        nlayer_default = default_num_layers(xdummy, eta, h0, minlayer,
                                            maxlayer, dztarget, meshfun)
        nlayer = nlayer_default

        if archive_nlayer == "out":
            print("writing out number of layers")
            write_mesh(mesh,
                       nlayer_gr3.replace(".gr3", "_default.gr3"),
                       node_attr=nlayer_default)
            write_mesh(mesh, nlayer_gr3, node_attr=nlayer)
            #write_mesh(mesh,nlayer_gr3.replace(".gr3","_dztarget.gr3"),node_attr=dztarget)
    elif archive_nlayer == "in":
        nlayer_mesh = read_mesh(nlayer_gr3)
        #dztarget=read_mesh(nlayer_gr3.replace(".gr3","_dztarget.gr3")).nodes[:,2]
        nlayer = nlayer_mesh.nodes[:, 2].astype('i')
        if int(nlayer_mesh.n_nodes()) != int(mesh.n_nodes()):
            raise ValueError(
                "NLayer gr3 file (%s)\nhas %s nodes, hgrid file (%s) has %s" %
                (nlayer_gr3, nlayer_mesh.n_nodes(), hgrid, mesh.n_nodes()))
    else:
        raise ValueError("archive_nlayer must be one of 'out', 'in' or None")

    # inclusion of minlayer and maxlayer has to do with experiment regenerating # layers after smoothing
    # this will ruin code generally, and if the experiment goes well we need to make sure this is available when archive_nlayer="in"
    if fix_minmax:
        minlayer = nlayer * 0 + fixed_min
        maxlayer = nlayer * 0 + fixed_max  #np.max(maxlayer)

    sigma2, nlayer_revised = gen_sigma(nlayer, minlayer, maxlayer, eta, h0,
                                       mesh, meshfun)
    print("Returned nlayer revised: {}".format(np.max(nlayer_revised)))
    nlayer = nlayer_revised
    nlevel = nlayer + 1

    vmesh = SchismLocalVerticalMesh(flip_sigma(sigma2))
    #vgrid0 = vgrid_out.replace(".in", "_int.in")
    #write_vmesh(vmesh, vgrid0)
    #vmesh1 = SchismLocalVerticalMesh(flip_sigma(sigma1))
    print("Writing vgrid.in output file...")
    write_vmesh(vmesh, vgrid_out)
    print("Done")
def convert_mesh(args):
    mesh = read_mesh(args.input)
    write_mesh(mesh, args.output, proj4=args.proj4)