def make_model(coor, yr, month, day, period=46, dt=900 ,opt='SUNTANS', images_dir=os.getcwd()+"/images"): ''' Run multiple GNOME; yr,month,day---oil spill start time; period---oil spill simulation duration; dt--oil spill time step in second ''' print "initializing the model" base_dir=os.getcwd() #start_time = datetime(2014,8,21,0) start_time = datetime(yr,month,day,0) model = Model(start_time = start_time, duration = timedelta(hours=period), time_step =dt, uncertain = False, ) mapfile = os.path.join(base_dir, './coast.bna') print "adding the map" gnome_map = MapFromBNA(mapfile, refloat_halflife=6) # hours print "adding renderer" model.outputters += Renderer(mapfile, images_dir, size=(1800, 1600)) print "adding a wind mover from a time-series" ## this is wind wind_file=get_datafile(os.path.join(base_dir, 'wind.WND')) wind = Wind(filename=wind_file) w_mover = WindMover(wind) model.movers += w_mover print "adding a current mover:" ## this is currents curr_file = get_datafile(os.path.join(base_dir, 'current_'+opt+'.txt')) model.movers += GridCurrentMover(curr_file) #model.movers += RandomMover(1000) ## ## Add some spills (sources of elements) ## print "adding 13 points in a cluster that has some small initial separation as the source of spill" for i in range(len(coor)): xcoor,ycoor=nctools.utmToLatLng(15,coor[i][0],coor[i][1],northernHemisphere=True) model.spills += point_line_release_spill(num_elements=1, start_position = (ycoor,xcoor, 0.0), release_time = start_time, ) print "adding netcdf output" netcdf_output_file = os.path.join(base_dir,'GNOME_'+opt+'.nc') scripting.remove_netcdf(netcdf_output_file) model.outputters += NetCDFOutput(netcdf_output_file, which_data='all') return model
def duplicate(starttime,endtime,dt): """ Traverse the SUNTANS boundary grid to locate the points that ROMS result enters and run GNOME """ print "Trying to duplicate the oil spill particles at the SUNTANS boundary!!\n" base_dir = os.path.dirname(__file__) try: ncfile=Dataset(base_dir+'/CoarseTri/rundata/'+'GalvCoarse_0000.nc','r') except IOError: print 'No SUNTANS output available' mark=ncfile.variables['mark'][:] xe=ncfile.variables['xe'][:] ye=ncfile.variables['ye'][:] tide=[] #tide boundary mark river=[] #river boundary mark for ii in mark: if ii==3: tide.append(ii) if ii==2: river.append(ii) tide_index=[] for ind,mk in enumerate(mark): if mk==3: tide_index.append(ind) ###########Output the cooridinate of SUNTANS open boundary points######### open_boundary=[] for kk in tide_index: open_boundary.append([xe[kk],ye[kk]]) boundary=[] for i in range(len(open_boundary)): boundary.append(nctools.utmToLatLng(15,open_boundary[i][0],open_boundary[i][1])) ###########ROMS output############ roms_spill=spill_locations('GNOME_ROMS.nc') ################################## cbp=[] ###cbp is cross SUNTANS boundary point SUN13=[] for nn in range(len(roms_spill)): particle=roms_spill[nn] for i in range(len(particle)): find=False for j in range(len(boundary)): if abs(boundary[j][0]-particle[i][0])<0.0035 \ and abs(boundary[j][1]-particle[i][1])<0.0035: SUN13.append([boundary[j][0],boundary[j][1]]) find=True break if find==True: cbp.append(i) ###cbp is cross SUNTANS boundary point break if SUN13==[]: print '#########\n ROMS output particles will not cross SUNTANS boundary!! \n#########' print '#########\n check the Google map for details!! \n#########' raise RuntimeError('adjust initial locations and time period for GNOME run \ or you can change to mode 1 and rerun') else: print '#########\n %s particles generating at SUNTANS boundary!! \n#########'%str(len(SUN13)) timeformat='%Y-%m-%d' SUN_starttime=datetime.strptime(starttime,timeformat)+timedelta(math.floor(min(cbp)/(24*3600./dt))+1) SUN_starttime=SUN_starttime.strftime(timeformat) ##SUNTANS starttime before particle cross ROMS boundary diff=datetime.strptime(endtime,timeformat)-datetime.strptime(SUN_starttime,timeformat) period=diff.days*24 ####running SUNTANS from the SUN_starttime to endtime hydro_wrapper.runSUNTANS(SUN_starttime, endtime) ####generating input of GNOME from SUNTANS output infile=base_dir+'/CoarseTri/rundata/'+'GalvCoarse_0000.nc' outfile=base_dir+'/GNOME/'+'txsuntans.nc' Tx_SUNTANS(infile,outfile) coor=[] for i in range(len(SUN13)): coor.append(utm.from_latlon(SUN13[i][0],SUN13[i][1])[0:2]) yr=int(SUN_starttime[0:4]); #month=int(SUN_starttime[5:7].lstrip("0").replace("0", " ")) month=int(SUN_starttime[5:7].lstrip('0')) #day=int(SUN_starttime[8:].lstrip("0").replace("0", " ")) day=int(SUN_starttime[8:].lstrip('0')) row1='NetCDF Files' row2='[File] ./txsuntans.nc' f=open(os.getcwd()+'/GNOME/'+'current_SUNTANS.txt','w') f.write(row1+'\n') f.write(row2+'\n') f.close() work_dir=os.getcwd() os.chdir(work_dir+'/GNOME/') scripting.make_images_dir() pdb.set_trace() model = make_model(coor,yr,month,day,period,dt,images_dir=os.getcwd()+"/images") wdd=[0.01,0.04] model.full_run(wdd,logger=True) os.chdir(work_dir)
def Tx_SUNTANS(infile,outfile): """ step 1: interpolate the data from SUNTANS output to GNOME input Input: infile='GalvCoarse_0000.nc' outfile='txsuntans_example.nc' """ ''' Sample script to retrieve data from unstructured grid netcdf "file" (can be OPeNDAP url), generate necessary grid topology (boundary info), and write GNOME compatible output. The boundary file is saved to the data files directory so it only needs to be generated once (unless you are subsetting the grid). To process multiple files (urls) either a) pass the filenames/urls in as a list -- this creates a netcdf4 MFDataset and is a good option for not too many files (all output is written to one nc file for GNOME in this case) b) add a file list loop -- in this case put it after the grid topo vars are loaded (as this only has to be done once). See NGOFS_multifile_example.py ''' data_files_dir=os.path.dirname(__file__) # specify local file or opendap url data_file = os.path.join(data_files_dir,infile) # the utools class requires a mapping of specific model variable names (values) # to common names (keys) so that the class methods can work with FVCOM, SELFE, # and ADCIRC which have different variable names # (This seemed easier than finding them by CF long_names etc) #!!!!!!!!txsuntans output on server does not include eles_surrounding_ele info #I have it saved as a netcdf file included in libgoods data_files directory var_map = { 'time':'time',\ 'u_velocity':'uc', \ 'v_velocity':'vc', \ 'nodes_surrounding_ele':'cells',\ 'eles_surrounding_ele':'nbe',\ 'edge_node_connectivity':'edges',\ } # class instantiation creates a netCDF Dataset object as an attribute txsuntans = nctools.ugrid(data_file) # get longitude, latitude, and time variables print 'Downloading data dimensions' txsuntans.get_dimensions(var_map) # UTM coordinates -- calculate lat/lon x = txsuntans.Dataset.variables['xp'][:] y = txsuntans.Dataset.variables['yp'][:] lon = np.ones_like(x); lat = np.ones_like(x) for ii in range(len(x)): lat[ii], lon[ii] = nctools.utmToLatLng(15,x[ii],y[ii]) txsuntans.data['lon'] = lon txsuntans.data['lat'] = lat txsuntans.atts['lon'] = {'long_name': 'longitude'} txsuntans.atts['lat'] = {'long_name': 'latitude'} # get grid topo variables (nbe, nv) print 'Downloading grid topo variables' txsuntans.get_grid_topo(var_map) edge_types = txsuntans.Dataset.variables['mark'][:].tolist() #"0 - computational; 1 - closed; 2 flux BC; 3 - stage BC; 4 - other BC; 5 - interproc; 6 - ghost #Based on personal communication we use 1,2, and 3 bound_id, bound_type = zip(*[(i,x) for i,x in enumerate(edge_types) if x>0 and x<4]) bound_segs = txsuntans.data['edges'][bound_id,:] + 1 #Node numbering starts at 0, GNOME expects it to start at 1 -- adjust nv and bnd bound_type_gnome = (np.array(bound_type)<=2).choose(1,0) txsuntans.order_boundary(bound_segs.tolist(),list(bound_type_gnome)) txsuntans.atts['bnd'] = {'long_name':'Boundary segment information required for GNOME model'} #Node numbering starts at 0, GNOME expects it to start at 1 -- adjust nv and bnd txsuntans.data['nv'] = txsuntans.data['nv'] + 1 ## GNOME needs to know whether the elements are ordered clockwise (FVCOM) or counter-clockwise (SELFE) txsuntans.atts['nbe']['order'] = 'ccw' ''' !!!!!!!!!!!!!All the stuff above here only has to be done once -- if you want to process multiple files, I'd put a loop here and just keep overwriting txsuntans.data['u'] and ['v'] and incrementing the output file name Also need to change txsuntans.data['time'] appropriately ''' # get the data print 'Loading u/v' txsuntans.get_data(var_map,zindex=0) print 'Writing to GNOME file' txsuntans.write_unstruc_grid(os.path.join(data_files_dir, outfile)) txsuntans.Dataset.close()
def mul_GNOME_inputs(number,yr,month,day,hr,period): ''' Transform multiple SELFE combined binary outputs into GNOME's inputs in NetCDF format; number is SELFE number; Oil spill starting time: yr,month,day,hr; month is based on 30 days Oil spill simulation time period: period (hours) ''' data_file = os.path.join(base_dir,'169_hvel.nc') var_map = { 'longitude':'lon', \ 'latitude':'lat', \ 'time':'', \ 'u_velocity':'u', \ 'v_velocity':'v', \ 'nodes_surrounding_ele':'ele',\ 'eles_surrounding_ele':'',\ } txselfe = utools.ugrid(data_file) print 'Downloading data dimensions' x = txselfe.Dataset.variables['x'][:] y = txselfe.Dataset.variables['y'][:] lon = np.ones_like(x); lat = np.ones_like(x) for ii in range(len(x)): lat[ii], lon[ii] = nctools.utmToLatLng(14,x[ii],y[ii]) txselfe.data['lon'] = lon txselfe.data['lat'] = lat txselfe.atts['lon'] = {'long_name': 'longitude'} txselfe.atts['lat'] = {'long_name': 'latitude'} # get grid topo variables (nbe, nv) print 'Downloading grid topo variables' try: txselfe.get_grid_topo(var_map) except KeyError: #model output on server doesn't have nbe txselfe.build_face_face_connectivity() # GNOME requires boundary info -- this file can be read form data_files directory # if saved or generated print 'Loading/generating boundary segments' bndry_file = os.path.join(base_dir, 'txselfe.bry') try: txselfe.read_bndry_file(bndry_file) except IOError: txselfe.write_bndry_file('txselfe',bndry_file) txselfe.read_bndry_file(bndry_file) txselfe.data['nbe'] = txselfe.data['nbe'] txselfe.data['nv'] = txselfe.data['nv'] # GNOME needs to know whether the elements are ordered clockwise (FVCOM) or counter-clockwise (SELFE) txselfe.atts['nbe']['order'] = 'ccw' # get the SELFE data print 'Loading u/v' # specify SELFE output path for n in range(number): shutil.copy(base_dir+'/txselfe.bry',base_dir+'/'+str(n+1)+'/GNOME') selfe = pyselfe_v1.Dataset(base_dir+'/'+str(n+1)+'/outputs/169_hvel.64') for j in range(period): model_time = dt.datetime(yr,month+j/720,day+(j/24)%30,hr+j%24,0,0) t_units = 'hours since 2012-01-01 00:00:00' txselfe.data['time'] = [date2num(model_time,t_units),] txselfe.atts['time'] = {'units':t_units} num_nodes = len(txselfe.data['lon']) txselfe.data['u'] = np.ones([1,num_nodes],) txselfe.data['v'] = np.ones([1,num_nodes],) txselfe.atts['u'] = {'long_name':'eastward_velocity','units':'m/s'} txselfe.atts['v'] = {'long_name':'northward_velocity','units':'m/s'} [t, t_iter, eta, dp, mdata] = selfe.read_time_series('hvel.64', nfiles=1, sfile=169+j, datadir=base_dir+'/'+str(n+1)+'/outputs/') for i in range(num_nodes): txselfe.data['u'][0][i]=mdata[0,i,5,0] txselfe.data['v'][0][i]=mdata[0,i,5,1] print 'Writing to GNOME file' txselfe.write_unstruc_grid(os.path.join(base_dir, str(n+1)+'/GNOME/'+str(169+j)+'_hvel.nc'))