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.")
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)
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)
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)
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)
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)