o Gg3B@sddlTGdddZGdddZddZd8dd Zd d Zd d Zd9ddZGdddZddZ d:ddZ d;d d!Z dd&d'Zd(d)Zd8d*d+Zd,d-Zd?d.d/Zd0d1Zd@d2d3ZdAd5d6Zed7krs dSdS)B)*c@s^eZdZd^ddZ  d_dd Zd d Zd`ddZddZddZd^ddZ daddZ dbddZ ddZ ddZ dbdd Zdbd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zdbd+d,Zdcd-d.Zd^d/d0Zddd1d2Zded4d5Zdfd8d9Zdgd;d<Zdhd@dAZdidCdDZdjdGdHZdkdJdKZdldNdOZdPdQZ dRdSZ!dmdTdUZ"dmdVdWZ#dmdXdYZ$dZd[Z%d\d]Z&dS)n schism_gridNcCsj|durn+|ds|dr||n|ds|dr)t|jj|_ntd|||_dS)z Initialize to empty instance if fname is not provided; otherwise, read from three supported file format NZgr3.llz.pklz.npzz#hgrid file format {} not recognized) endswith read_hgridloadzhgrid__dict__copy Exceptionformat source_fileselffnamerL/lfs/h1/ops/prod/packages/stofs.v2.1.16/ush/stofs_3d_atl/pysh/schism_file.py__init__s  zschism_grid.__init__r皙?bothTc!Ks|durd}|dur d}|durt}|dkrs|jdk}|jdk}|dk|dkBr|j|ddf}t||dddff}|j|}|j|}t|tt|dgtf}t ||j }t|tt|dgtf}t ||j }|j|ddf}t||dddff}|j|}|j|}t|tt|dgtf}t ||j }t|tt|dgtf}t ||j }|dkr|dkrd}t t ||ft ||f||d}nP|d vr$t |j||Bddft|j|df|j|d dfff}|dur|j }n t||jkr|j|d }nt||jkr!td |j| durBt|}t||t||}}||krA|d }n| \}}| durMd} t| ds[t||t| } tt|dkrq|t||jdd}||t|t|dkr|dkrt|j|j||f|||d|}|d krt|j|j||f|||d|}n.|dkrt|j|j||f| |||d|}|d krt|j|j||f| |||d|}tj j!|||d|r|dkrt"|}||_#| durt| ds |$t||t| n|$| |dkr$t t ||ft ||f||d}||_%| dur2t&|| d| dur=t&|| dt'()dvrqt*j+j,-}t.dd|D}d|vr_t/|_0d|vrh|1d|vrq|2|S|dkr?t|j|jf|j} t.ddt3| |jD} |durt|ds|4|j5}n t||jkr|j6|d }nt||jkrtd |j|dur| |} ||}| durt|t|g} |dkrt'j7j8| f|||dd |}n)t'j7j8| f|||| dd!|}|rt"|}||_#| dur|$| |!| |9||:||_%| dur2t&|| d| dur=t&|| d|SdS)"a plot grid with default color value (grid depth) method=0: using tricontourf; method=1: using PolyCollection (old method) fmt=0: plot grid only; fmt=1: plot filled contours; fmt=2: plot contour lines value: color value size(np,or ne) mask: size(ne); only plot elements (mask=True)) ec: color of grid line; fc: element color; lw: grid line width levels=100: number of colors for depths; levels=array([v1,v2,...]): depths for plot ticks=[v1,v2,...]: colorbar ticks; ticks=10: number of ticks clim=[vmin,vmax]: value range for plot/colorbar cb=False: not add colorbar NNonerk)lwcolorrrvaluezvalue has wrong size: {}gư>3__len__axis绽|=)vminvmaxextend)levelsr&r'r()r&r')xlim)ylimZqt5aggqtaggcSg|]}|qSrZiconText.0irrr oz)schism_grid.plot_grid..bpquerybndcSs<g|]\}}|dkrt|dkr|ddddfn|qS)rrrNlen)r1si34rrrr3w<dpeF)r edgecolor facecolor antialiased)rr?arrayclimrA);gcar<elnodec_xyonessumnanreshapesizeplotr_dpr:neinterp_elem_to_nodenpsysexitr shapeisnanminmaxhasattrlinspaceintabs tricontourf tricontourcmScalarMappableset_climcolorbarhc set_tickshgsetpmpl get_backendlowergcfcanvastoolbaractionsrB schism_bpfiler5query_pt create_bndzip compute_ctrr>interp_node_to_elem collectionsPolyCollectionadd_collectionautoscale_view)!raxmethodfmtr maskecfcrr)ticksr*r+rCr(cbargsfp3fp4trix3y3quadx4y4rffpnr&r'rdacsatsZxy4rrr plot_grids   *((*(( $ >  $,,,..   *        zschism_grid.plot_gridcK|jdi|S)z' alias for plot_grid() Nr)rrrrrrrNzschism_grid.plotr?cKs|dkrt|t|dkr|d}t|ds|g}t|jD] }t|d|j|f}q"t| d}|dk}|j |}|j |} t ||<t | |<g} t|j D]$}|j|dkrgt| d|j|f} qSt| d|j||j|df} qSt|  d} | dk}|j | } |j | } t | |<t | |<t|| |dfd|i|} t| | |dfd|i|}| |g|_td vrtjj}td d |D}d |vrt|_d |vr|d|vr|dSdSdS)z plot schims grid boundary gd.plot_bnd(): plot bnd gd.plot_bnd(c='rb'): open bnd in red,land bnd in blue Nrrnobr8r\rrr,cSr.rr/r0rrrr3r4z(schism_grid.plot_bnd..r5r6r7)scar:rZ compute_bndarangerrOiobnrBastyperGrHrKnlbislandilbnrNZhbrhrirjrkrlrmrnror5rprq)rcrryrsindor2rbx1by1sindlbx2by2Zhb1Zhb2rrrrrplot_bnds6"  zschism_grid.plot_bndcsT||_t|d}||tdddd\|_|_tdddd|jDdj \|_ |_ |_ t d|j|jkrKdSd dd|jd|j|jD}td d|Dd}|dddf|_|ddddfd|_d}|t d |j|jkrdSd|j|jtd|_dg|_g|_t|jD]0}|jtd|jtfd dt|jd Dd|jd qt|j|_t|jdd|_t |jdkr|jd|_td|_dg|_g|_g|_t|jD]\}dd}|jt|dd}|jtfddt|jd Dd|jd t |dkrjt|d}|jd d|jd d kr{d}|j|q&t|j|_t|j|_t|jdd|_t |jdkr|jd|_dSdS)Nrrrrr\cSg|] }|ddqS)rrsplitr0rrrr3z*schism_grid.read_hgrid..floatcSg|]}|qSrstriprr0rrrr3cSs(g|]}t|dkr |ng|dqS)-1r9r0rrrr3(rc0g|]}td|ddqSrrr\rrr1rlinesnrrr30r8Odtype=crrrrrrrr3r)r open readlinescloserBrrrQrSTrGrHrPr:r<rE compute_sider\rrnobnrrappendrnlbnrr)rrrfidfdatar2slineZibtyperrrrs6&4(0> *4.*"(&zschism_grid.read_hgridcCs2t|}t||jkrtd|jt||S)z9 read schism prop, and return the values zcheck dimension: ne={}, prop={})read_schism_propr:rQrTrUr )rrZevirrr read_props&zschism_grid.read_propcCsl|dur|jn|}|jdk}|}t|j}||j|ddfjdd||<||j|jdd||<|S)zf interpolate node values to element values default is self.dp => self.dpe Nrrr#)rPr<zerosrQrEmean)rr rPrrr>rrrrts "zschism_grid.interp_node_to_elemrc Cs|t|ds ||durt|ds||dur|jn|}||j}|dkrS|jdk}|jdd}tt|dkrId||<|jdd|}n ||jdd|}|dkrh|d||jdk<|jdd}|d kr}|d||jdk<|jdd}|dkrt |j |jd |j |j|j d |j dddf} d| |}d||jdk<|jdd}||jdd|}|S) a interpolate element values to nodes if value not given, dpe is used fmt=0: simple avarage; fmt=1: inverse distance (power=p) fmt=2: maximum of surrounding nodal values fmt=3: minimum of surrounding nodal values nneNr>rr8rr#rr?)rZ compute_nnersr>inerJrWrXrYr]xctryctrrGrH) rr r{pv0vswtwvdistrrrrR s  **<:zschism_grid.interp_elem_to_nodecCst|dr |dkr |t|dr|dkr|t|dr#|dkr)|jddt|dr2|dkr6|t|dr?|dkrE|d Sd S) aw compute all geometry information of hgrid by invoking: functions: compute_ctr(),compute_area(),compute_side(fmt=2),compute_nne(),compute_ic3() attrs: (xctr,yctr,dpe),(area),(ns,isidenode,isdel,xcj,ycj,dps,distj),(nne,mnei,indel,ine),(ic3,elside) fmt=0: skip if already attrs are already available; fmt=1: recompute all attrs r>rareadpsrr{ric3N)rZrs compute_arearr compute_ic3)rr{rrr compute_all(s "zschism_grid.compute_allcCst|ds|jdk}|}td|jg\|_|_|_|j|j|ddfj dd|j|<|j|j|ddfj dd|j|<|j |j|ddfj dd|j|<|j |j|ddfj dd|j|<|j |j|ddfj dd|j|<|j |j|ddfj dd|j|<|jS)zE compute element center information: (xctr,yctr,dpe) rrNrr#) rZr<rrQrrr>rGrErrHrP)rrrrrrrs5s *&&&&&&zschism_grid.compute_ctrc Cs:|jdddfdk}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf} ||||<||| |<||||||||||| |||||d|_|jS)Nr8rrrr)rErGrHr) rfpx1y1x2y2rrrrrrrrCs000HFzschism_grid.compute_areacCst|ds |t|ds||jdddfdk}|}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf}|j|jdddf} |j|jdddf} |j|jdddf} |j|jdddf} |j|jdddf} |j|jdddf}|j|jdddf}||| |<||||<||||<||| || |||d}| |||| || |d}||| | | || ||d||_| |||| | ||| d||_t |jd|jd|_ ||| |||| |||||||||| |d||}| || |||||| || || |||||d||}t |d|d}|j||d|j|<|j||d|j|<|j ||d|j |<|j |j|d |_ |j |j|d |_ |j |j |d |_|j |j |jfS) aP Compute gradient of gd.dp on each element first, then transfer to nodes with the following options "see details in interp_elem_to_node()": fmt=0: simple avarage; fmt=1: inverse distance; fmt=2: maximum of surrounding nodal values. The default is (0) simple average rr>Nr8rrrr)r r{)rZrrsrErGrHrPZdpedxZdpedysqrtZdpedxyrRZdpdxZdpdyZdpdxy)rr{rrrrv1rrv2rrv3rrv4a1a2Zdpedx2Zdpedy2Zdpedxy2rrrcompute_gradientLs. HHHH$$$..TTzschism_grid.compute_gradientc Cs^|jdk}|j|df|j|df<g}g}tdD])}|t|jdd|ddf|jdd|ddff|t|jqt|j}t| gd t |dg}t |dd dddfdk}||}||}d |j|df<t |dd j}t|dd |dd d d \}}} t ||_|dkr|jS|dvr-t|} || } || |_|| } t|jd } ttt ||}||| | |<| | } t| | f|_| | k| dk}t|j||j|<|dkr%t|j|j|jf|jjdd j\|_|_|_tt |j|jdd d t |j|jdd dddf|_|j|j|jfSdS)z compute side information of schism's hgrid fmt=0: compute ns (# of sides) only fmt=1: compute (ns,isidenode,isdel) fmt=2: compute (ns,isidenode,isdel), and (xcj,ycj,dps,distj) rrr8rNrr)rrrr#rT) return_indexreturn_inverserr\) r<rErrrFrQrBrravel transposerLr:diffsortuniquensargsort isidenoderIr setdiff1disdelfliplrrGrHrPrZxcjZycjrr]Zdistj)rr{rZsisZsier2rZusissindsindrZsindasindsZse1Zse2rfpsrrrrws&* P.:2  *2 0>zschism_grid.compute_sidecCsdtdt|drt|ds|jdd|jdddfdk}|j|}|j|dddf}t|}t|d }t|j |d kd}t|j |d kd}t d D]t}|d kr|j ||d f} |j ||df}||df|k||df| k} t ||| ||| <qT|j ||f} |j |||dd f||<|j |||df||<|dddf|k|dddf| k} t || || <qTt t|dddft |} t|d } d} g}g}t| dkrF|t| dkdddf}|| |df}||g}d| | |<d| | |< || |df}d| | |<||kr'n||q| d} |t||t|t| dkst|}t|d d}tt|}||||}}t|dsit|_g}g}|j}t|D]\}}|||t|t|qtt|}t|}||_||_t| d |_| |_||_||_|j||_|j ||_ t | D]F}|j|j|}t||!kdd}|j|t|d|j|||d|j|g}t"|j||j |dkrd|j|<nqt|ds0d|_#tg|_$tgg|_%t|j}|j|_&|j||_'|j||_(|j||_dSdS)z. compute boundary information zcomputing grid boundariesrrrrNr8rr\rrTrrbndinfor))printrZrrrr:rIrnonzeror<rrErdictrrrJrrBflipudrzdatar enumerater(tileriprnbnbnibnrGrHrXsignarrrrrr)rrZisnbenbsi2rrr2i1rrZifbrrr Zid0idibnirrrSmpxi0sidrrrrsH >: $:F:4  $ 2 2,* (4. &0zschism_grid.compute_bndcKr)z/ alias for compute_node_ball() Nr)compute_node_ballrrrrrrzschism_grid.compute_nnec Cstt|jddgj}|j}|dk}||||}}t|}||||}}t|ddd\}}|_|j |_ t |j |j g d |_t|j D]}|j|k}|||}|||j||f<qOtddt|j|jDd d |_|jS) aL compute nodal ball information: nne,mnei,indel,ine where: nne: number of elements in nodal ball mnei: maximum number of elements in nodal ball indel: indices for each nodal ball ine: indices for each nodal ball, but in maxtrix " shape=[np,max(nne)]" rrrT)r return_countsr\cSs g|] \}}t|d|qSN)rBr1r2rrrrr3 z1schism_grid.compute_node_ball..rr)rrrQrrrErrrrYmneirIrSrrrBrrindel) relemnoderZunoderr2Zfpesinderrrrs$ "8"zschism_grid.compute_node_ballcCs0t|ds |jddtt|jddgj}|j}|dk}||||}}t|}||||}}t |dd\}}t |j dg d  |_ |j}t|D]e}t|j|kd }|j|} |||} || } |j| j\} } t|D]>}|d| |d| }}|j||f| k|j||f| k|j||f| k|j||f| kB}| ||j |||f<qzqTd|j |jd kdf<t |j dg d  |_t|j }t|D]0}|j|j d d |f}|d d d f|k}||df|j||f<||d f|j||f<qd|j|j dk<|j|j fS) za compute element-to-side table, where elside: element-to-side table rrrrr8Trrr\rrN)rZrrrrrrrrrrIrQrZelsider<rYrrrEr)rsiderrZuelemrZm34r2rr<rsdn1n2rid1id2Zfpkieesrrrrrs($2 ( H" ,2 zschism_grid.compute_ic3cCs,t|}t|dgd }t|dg}|dkrt|d }t|}t|ds.|t||t|j |j f}| |||\} } } t| dkr`|| ||| <| ||| <| ||| <||dk} || || }}t|dkrt|ds~| t|j D]E} |j|| f}| |||\} } } t| dkr|| ||| <| ||| <| ||| <||dk} || || }}t|dkrnqt|dkrXt|ds|t||t|j|jf}|dddf||<d ||df<t|jD]Z} |j|| f}| |||\} } } t| dkr,|| ||| <| ||| <| ||| <| |jd krN||dk|j|| d fdk} || || }}t|dkrWnqt|dkd}||||d k}t|dkr|j||d d \||<||<||<n |d kr|jjdd}t||j||j|d d }|dk} |j|| || <t|j d kd}t| d}t|dkrt|dkr|j|jtgd }t|||j||j|d d }|dk} ||| ||| <|j|| ||| <|dk}t|dkri|j||j\}}}|j||j\}}}||j\}}tt|||ft|||f}tt|||ft|||f}tt|||ft|||f}t||||d |||f||<t|dkrt||t|j|jf}|dddf||<d ||df<|||fS) aL compute acor coodinate for points pxy[npt,2] usage: ie,ip,acor=compute_acor(c_[xi,yi]), where xi and yi are array of coordinates outputs: ie[npt],ip[npt,3],acor[npt,3] ie: the element number ip: the nodal indices of the ie acor: the area coordinate fmt=0: (default) faster method by searching the neighbors of elements and nodes fmt=1: slower method using point-wise comparison Note: for interpolation of few pts on a large grid, fmt=1 can be faster than fmt=0 rr\rrr8rrNrrrrrr)r:rIrrrrZrsnear_ptsrFrr inside_elemrr<rYrrrGrHrrr inside_grid compute_acorrErinside_polygonrBrJr )rpxyr{nptpippacorpiesindprrsipZsacorrr2r'Zsindnsind4Zsind2Zpie2rrrrrrrrGrHA1A2Arrrr- sP( 04 $4:$6D&2 , 82:<D@ zschism_grid.compute_acorcCs\|dur|jn|}t||jkr|j|d}|j||ddd\}}|j||jddS)a interpolate to get value at pxy pxy: c_[x,y] value=None: gd.dp is used; value: array of [np,] or [ne,] fmt=0: (default) faster method by searching the neighbors of elements and nodes fmt=1: slower method using point-wise comparison Note: for interpolation of few pts on a large grid, fmt=1 can be faster than fmt=0 Nrrrr#)rPr:rQrRr-rJ)rr/r r{vir1r2rrrinterpVs zschism_grid.interpcKsv|durdtj|jd}|ds|ds|dr*|j|fi|dSt}||_t ||fi|dS)a save hgrid as (*.npz, *.pkl, *.gr3, *.ll or *.ic) examples: 1). gd.save('grid.npz') or gd.save('grid') 2). gd.save('grid.pkl') 3). gd.save('hgrid.gr3') or gd.save('hgrid.ll') or gd.save('temp.ic',value=5) Nz{}.npzrz.gr3rz.ic) r ospathsplitextr r write_hgridrrsavez)rrrr;rrrsavehs "zschism_grid.savec Cs|dur|j}nt|dr|}nt|j|}|dkrd}t|d}|d||d|j|jt|jD]} |d| d|j | |j | || q;|dkrt|jD]F} |j | d kr|d j| d|j | g|j | ddfdR|j | d kr|d j| d|j | g|j | ddfdRq\|dkr|dur|j |d |dur|t|dWddSWddS1swYdS)aL write *.gr3 file fname: file name value: depth value to be outputted value=const: uniform value in space value=dp[np]: specify depth value value=None: grid's default depth self.dp is used fmt=0: not output grid boundary info.; fmt=1: output grid boundary info. elnode=1: output grid connectivity; elnode=0: not output grid connectivity bndfile=filepath: if bndfile is not None, append it at the end of file Info: annotation of the gr3 file Nr"rw+z !grd info:{} {} {} z{:.z{} = number of land boundaries z){} = Total number of land boundary nodes rz-{} {} = Number of nodes for land boundary {} z/{} {} = Number of nodes for island boundary {} cSrIrJrKrrrrr3rL)rZrrrDr rr\rJrrrFrrrrrr)rrrbidr2ZnlnrrrrEs,&(zschism_grid.write_bnd schism.prop{:8.5f}cCs|durt|ds ||j}nt|dr|}nt|j|}d|vr+|d}d|d|j}ttd|jd|gd d j }t |d }| |j | |dS) a write schism prop file. fname: file name value: prop value; 1). if value=None, self.dpe is outputed. 2). value=const 3). value=array[gd.ne] fmt: output format of prop value Nr>r"dr\z{:d} z rrrrB)rZrsr>r rIrQrrBrangerrrFr rr)rrr r{Zpvifstrfvalrrrr write_props   *zschism_grid.write_prop hgrid.2dmc Csg}|dt|jD]:}|j|dkr,|dj|dg|j|ddfdR|j|dkrF|dj|dg|j|dRq t|jD]}|d|d|j||j||j |qLt |d }| || dS) z9 convert grid to *.2dm format and save zMESH2D rzE3T {} {} {} {} 1 rNrzE4Q {} {} {} {} {} 1 zND {} {:.8f} {:.8f} {:.8f} rB) rrrQr<r rErSrGrHrPrrFr)rrrr2rrrrgrd2smss<4. zschism_grid.grd2sms<xnew.gr3cCst|ds ||||j}|j|j|ddf}|j|j|ddf}tdD]}t|ddd}|} t|dd} |dd|f} |dd| f} |dd| f} |dd|f}|dd| f}|dd| f}t| | d||t| | d||}t| | d||t| | d||}t| | d||t| | d||}t|dt dd}t|dt dd}t|dt dd}t |||f}|j dd|j dd}|d kr|}q*t ||f}q*t |ddd f|ddd f|dddf|ddd f}|j}t|j}t|jt|dgd fd |_t|D]n}|j|}|j|ddf}||d kr{t|gd df|j|ddf<d |j|<t|gddf|j||ddf<q7t|gddf|j|ddf<d |j|<t|gddf|j||ddf<q7|||_t|jt|d fd |_|jd |_||dS)z 1). split the quads that have angle (angle_max), add append the connectivity in the end 2). output a new grid "fname" index_bad_quadNrrrhr#rrrr\)rrrr)rrr)rrr)rrr)rZ check_quadsrZrGrErHrmodanglepirFrYrXsignrQr:rOrIrr r<r?)r angle_min angle_maxrqindrGrHr2r%r&id3rrrrrrrra3aAir9flagrQZneaindZndsrrr split_quadss>0 $00000BD"  ,*,* zschism_grid.split_quads bad_quad.bpcCst|jdkd}|j|j|ddf}|j|j|ddf}g}tdD]e}t|ddd} |} t|dd} |dd| f} |dd| f} |dd| f}|dd| f}|dd| f}|dd| f}t| | d||t|| d||}||dt q't |j }t|dd}tdD]1}|dkr|dd|f|k|dd|f|kB}q||dd|f|kB|dd|f|kB}q|t|d|_ t |ds||j|j }|j|j }t}t||_||_||_t|j|_||dS) z 1). check the quality of quads, violation when internal angle < angle_min, or >angle_max 2). the locations of bad quads are saved in file "fname" rrNrrr[r\r)rr<rGrErHrr^r_rr`rBrrZrZrsrrror:nstarz write_bpfile)rrbrcrrdrGrHrgr2r%r&rerrrrrrairqxiqyisbprrrr]s$0 $000 *.6zschism_grid.check_quadsr cGsdt|ds |t|ds||j|j}|j|j}|t||dg|R||ddS)NrZr.)rms)rZr]rsrrZrrrN)rrrvrrqrrrrrplot_bad_quads9s zschism_grid.plot_bad_quads epsg:4326c Cs<|dus|dur|j}|j}t||||||d\}}||gS)a transform the projection of schism grid's coordinates Inputs: prj0: projection name of schism grid prj1: target projection name; default is 'epsg:4326' x,y: values of grid coordiantes; default is (gd.x, gd.y) lon0,lat0: lon&lat of cpp projection center; needed only if 'cpp' in [prj0,prj1] if ("ll"=>"cpp") and (lon0 or lat0 is not provided): lon0=mean(x); lat0=mean(y) N)prj0prj1rGrHlon0lat0)rGrHproj) rryrzrGrHr{r|rrrrrr}Ds zschism_grid.projskew_element.bpc!Cst|ds ||jdk}|j|j|ddf}|j|j|ddf}|j|}|j|}|j|} g} t dD]q} | } | dd} | dd}|dd| f}|dd| f}|dd|f}|dd| f}|dd| f}|dd|f}t t ||d||t ||d||dt }t ||kd}t|dkr| |q;t| } t| dkr|| }|| }| | }| }ntg}tg}tg}tg}|jd k}|j|j|ddf}|j|j|ddf}|j|}|j|}|j|} g} t d D]s} | } | dd } | dd }|dd| f}|dd| f}|dd|f}|dd| f}|dd| f}|dd|f}t t ||d||t ||d||dt }t ||kd}t|dkr|| |q t| } t| dkr|| }|| }| | }| }ntg}tg}tg}tg}|durt||f|_t||f|_t||f}t} t|j| _|j| _|j| _|| _| ||dkrtg||d SdS) a 1) check schism grid's skewness with angle<=angle_min 2) the locations of skew elements are (xskew,yskew), and also save in file "fname" Inputs: angle_min: skew element if one of element's internal angles is smaller than angle_min fname=None: not save skew_element.bp; fname!=None: save skew_element.bp fmt=1: return indices of skew elements r>rNrrrr[rrr\)rZrsr<rGrErHrrr>rr]r_r`rr:r(rBr rOZxskewZyskewrormrnror)!rrbrr{rrGrHrrZzctrrr2r%r&rerrrrrrrpsindiZXS3ZYS3ZZS3Zsind3ZXS4ZYS4ZZS4r6Zzskewrsrrrcheck_skew_elemsRsF X 00< " X 00<  (2 zschism_grid.check_skew_elemscCsg}g}g}t|jdD]}|dkr5|j|ddf}|j|j\}} } |j|j\} } } |j\}}|dkrs||j|dk}t|d}|j||ddtgdf}|j|j\}} } |j|j\} } } ||j\}}t t || | ft | | | f}t t || | ft || | f}t t ||| ft | || f}t t || |ft | | |f}|dk|dk|dk}||||}||||}t |t j st|g}|dkr|t|d|dkr|||||||t ||d||fqt|t|t|fS)z check whether pts are inside elements, then compute area coordinates for pts in elements pxy: c_[x,y] ie: array of element indices corresponding to each pt rrNrrrr))rr<rYrErGrrHrrBr rF isinstancerSndarrayr()rr/r'rr1r2r2rrrrrrrxiyirfprrA0r7r8ZA3Zac1Zac2rrrr+s H T<<8,zschism_grid.inside_elemcCst|}t|}t|ds|t|jds|t|jjD]1}|jj|}t|||j||j |dk}|jj |dkrE||n||}t|dkrRnq!t | d}d||<|S)z check whether pts are inside grid usage: sind=gd.inside_grid(pxy) sind=0: outside; sind=1: inside rrrrr\) r:rrZrrrr r.rGrHrrr)rr/r0r4r2Zfpbrrrrrr,s,"zschism_grid.inside_gridcCst|_d|j_tgggj}t|jD]!}|j|}t|j ||j |f}t |dt dd}t ||f}qt|jD],}|j|}t|j ||j |f}|j|dkrYt|}t |dt dd}t ||f}q;||j_t||j_t||jdS)NPOLYLINErr#r)rZshp_bndtyperBrrrrrFrGrHinsertrKrOrrrclose_data_loopxy get_prj_fileprjwrite_shapefile_data)rrrrr2rjxyirrrwrite_shapefile_bnds    zschism_grid.write_shapefile_bndcCs\t|_d|j_t|j|jf|j_dg|j_t|j d|j_ t ||j_ t ||jdS)NPOINTZid_noder)rZshp_noderrFrGrHrattnamerrSattvaluerrrrrrrrrwrite_shapefile_nodes  z schism_grid.write_shapefile_nodecCs<t|_d|j_|j}|dddfdk}||df||df<t|}tdD]9}t|j|dd|f|j|dd|ff}|dkrQ|dddddf}q't||dddddff}q't |gd}t |j  d|j_ t|j D] }|||jj |<qwdg|j_t|j d|j_t||j_t||jdS) NPOLYGONr8rr)rrrrZid_elemr)rZshp_elemrrErrrFrGrHrrrQrrrrrrr)rrrrErr2rrrrrwrite_shapefile_elements". 0   z#schism_grid.write_shapefile_elementcsfdd}fddfddfddtjjd ur*tjj}t d d |D}d |vrJ|t |d kd d ntjj d }t ds[t _jg_g_g_d _g_d _g_d _g_g_|j|tjd S)z: create open and land boundaries for grid cstjd_tdstds"fddjD_tjj }t dd|D}|t |dkdd}| sF| tjdS) Nbutton_press_eventrhb0c s@g|]}tjt||dfjt||dfdddqS)rbr)r)rNrGrOrHr0rrrr3s@zCschism_grid.create_bnd..connect_actions..cSr.rr/r0rrrr3r4Panr)rkrl mpl_connectcidbndrZrr rrmrnrBr isCheckedtriggerdrawrrac)ronclickrrrconnect_actionss  8z/schism_grid.create_bnd..connect_actionsc s>t|j}t|j}|j}|j}|dkr|dkr|||dkr*|dkr*|||dkr|dkrjddkrAtddSjjkrj d}t j |j dkdd}jd_t j ||dj |df}j|tj|j|d}j|j_tjdd _td d jD_ttjttj } jt| _tgjfd d | Ddd _td d jD_t tdjtdt| f_tj j!tjj"#} tdd | D} | t | dkdd} | $r| %tj&dSdSdS)Nrrrz!open boundary needs to be definedr8rg-rrcSg|]}t|qSrr9r0rrrr3r4z;schism_grid.create_bnd..onclick..csg|]}j|qSr)r r0rrrr3cSrrr9r0rrrr3r4cSr.rr/r0rrrr3r4r)'r\dblclickbuttonxdataydatar0rrrrMrr ptrOrrrNrGrHhlbrBrrrrrr:rrrrkrlmpl_disconnectrrmrnrrr) spdlkbtnbxbyrMpidrrrrrr)radd_pt remove_ptrrrrs$  *<$.668z'schism_grid.create_bnd..onclickc sttj|dj|}t||kdd}j|}j|}tj||kdd}j dkrgj d}tj|j dkdd}j ddkrZ||krZdSj ddkrg||krgdS|j vrt j||dj|d|fj|<j |j |j d_ tj|j|d} j | j ddkr׈jd_j|||d} j | tj| j| d} j | j dkrj ddkr||krjd_j|||d} j | tj| j| d} j | j dkr`||kr`jd_t j||dj|df} j | tjt | j|dfjt | j|dfd} j | tjdS) Nrrr8rrrozr-r)squeezer]rGrHrrXrrr r0rMrrOrrNhprrhobrrrrkrlr) rGrHdistprrrMrZbid0Zpid0rrrr)rrrrrs&8. *8$$.$&.$<Hz&schism_grid.create_bnd..add_ptcs&jdkrdSjd}tj|jdkdd}jddjjjjd_jddkrZjddjj d_ j j j ksrj j krjddkrjdkrj ddj j j d_ tjdS)Nrr8rr)r0rMrr rrremovepoprrrrrrrkrlr)rGrHrMrrrrr#s*<@02z)schism_grid.create_bnd..remove_ptNcSr.rr/r0rrrr34r4z*schism_grid.create_bnd..r7rr)rh_pylab_helpersGcf get_activerrkrlrmrnrBr addActionrZrrrrrrrrrr0rrM triggeredconnectr)rrrrZabnr)rrrrrrrqs  0B zschism_grid.create_bndcszfdd}fddtjj}tdd|D}d|vr-|t|dkddntjjd}|j|d S) z1 add function for querying depth cstjd_dS)Nr)rkrlrcidqueryrrrrrrCsz-schism_grid.query_pt..connect_actionscst|j}t|j}|j}|j}|dkr|dkrtjj}t dd|D}|t |dkdd}t |dr|j j dkrAdStt|j j|d|j j|}t ||kdd} t|j j| |j j| f\} } } j| | } td| dSdS|dkr|dkrt||f\} } } j| | } td | dS|dkr|d krtjjdSdSdS) NrrcSr.rr/r0rrrr3Ir4z9schism_grid.query_pt..onclick..r5rzquery: bp depth= {}rzquery: depth= {}r)r\rrrrrkrlrmrnrBrrZr5rmrr]rGrHrXr-rFrPrJrr rr)rrrrrrrrrrr3r1r2pzirrrrFs 8 <:*z%schism_grid.query_pt..onclickcSr.rr/r0rrrr3Ur4z(schism_grid.query_pt..r6rN) rkrlrmrnrBrrrr)rrrrabprrrrp?s   0zschism_grid.query_ptr)NrrNNNNrNNNNNrT)rrN)NrrrNr)NrrNN)rHN)rNNrO)rU)rWrXrY)rWrXrl)rrt)rxNNNN)r~rrrx)'__name__ __module__ __qualname__rrrNrrrrtrRrrsrrrrrrrr-r;rAr?rErTrVrkr]rwr}rr+r,rrrrqrprrrrrsP   (+    +$6  J   '   5 " 3    _rc@sneZdZddZddZdddZdd Zd d Zdd d ZdddZ dddZ dddZ ddZ ddZ dS) rocCsBd|_tg|_tg|_tg|_g|_g|_g|_|dSr) rmrBrGrHrnstationrhteditrrrrr[s$ zschism_bpfile.__init__cC|j|dddSNrr) read_bpfilerrrrread_reg`zschism_bpfile.read_regrcsddt|dD}ddt|dddD}|dkrkt|dd|_|jdkr0dSdd tfd d|dd|jD}|dddft|_|dddft|_|ddd ft|_ n@|dkrt|dd|_|jdkrdSt t|d dgd }|dddf|_|dddf|_t |j|_ nt d t||jkrt||_dStddt|jD|_dS)NcSrrrr0rrrr3erz-schism_bpfile.read_bpfile..rcSs&g|]}d|vr|ddqS)!r8rr0rrrr3fs&rrrcSs0t|dkr|Sg|dd|dddS)Nrrr9)rGrrrjrz+schism_bpfile.read_bpfile..csg|]}|qSrr)r1liner~rrr3kr4rrz unknow formatcSsg|]}d|qS){}rKr0rrrr3~r)rrr\rmrBrrrGrHrnrrrTrUr:rr)rrr{rstationsdatarrrrcs* $ zschism_bpfile.read_bpfilecCs.|dr|j|dddS|j|dddS)zo If fname.endswith('reg'), save points as ACE/gredit *.reg file. Otherwise, save as *.bp file z.regrrrN)rrorrrrrAs zschism_bpfile.savecCrr)rorrrr write_regrzschism_bpfile.write_regc Cs t|d}t|dr|d|j|dkr |d|j|dkr-|d|jdd t|jD}t|d rGt|j|jkrG|j}t|jD]2}|dkrk|d |d|j ||j ||j ||||dkr~|d |j ||j |qL| d S)z^ fmt=0: write ACE/gredit *.bp file fmt=1: write ACE/gredit *.reg file rBnotezACE/gredit: {}rzbpfile in ACE/gredit format {} rz#Region in ACE/gredit format 1 {} 1 cSsg|]}|dqSrrr0rrrr3r4z.schism_bpfile.write_bpfile..rz"{:.connect_actions..rz>double click: left=add pt, right=remove pt; middle=finish editzsingle click: middle=move pt)rkrlrcidmovecidpressrmr:rrrmrnrBrrrrrr)ronmoverrrrs 8  z+schism_bpfile.edit..connect_actionscsT|jdur$t|j}t|j}|j}|j}|dkr&|dkr(||dSdSdSdS)Nrr)rr\rrr)rrrrr)move_ptrrrs  z"schism_bpfile.edit..onmovecst|j}t|j}|j}|j}|dkr|dkr|||dkr*|dkr*|||dkrn|dkrptjjtjj tjj }t dd|D}|t |dkdd}|rf|tjdSdSdS)NrrrcSr.rr/r0rrrr3r4z7schism_bpfile.edit..onclick..rr)r\rrrrrkrlrrrrmrnrBrrrr)rrrrrrrr)rrrrrrs 8z#schism_bpfile.edit..onclickc s&jd_gjdj_tj|f_tj|f_tjdf_tjdkrZjdd}j d}| }| }| }| }|}|} | } nd}d}d}d }d }d } d} t||||||d } j| t||jd| || d } j | tjdS)Nrrgrr8rru@r normalr markersizerrrfontsize fontweight)rmrr rOrGrHrnr:rr get_color get_markerget_markersize get_linestyle get_fontsizeget_fontweightrNrrrkrlr) rGrHrrrmkrvrfsfwr~rrrrrrs$0  &z"schism_bpfile.edit..add_ptc sjdkrdSttj|dj|}t||kdd}d}d}d}d}d}d} d} t|jD]u} | jd krYjd d j d  jd =j d =q7j| d } j| d } | j| <| j| <d | d j | <j| d j |  t | | ||||d }|j| <t| | j | | || d }|j | <q7jdd _jdd _jdd _j dd _ jd _tjdS)Nrrrrurrrrrr8rrr)rmrr]rGrHrrXrrrrr rrNrrnrkrlr)rGrHrrrrrvrr r r~r2rrrrrrrrs8 ( &Lz%schism_bpfile.edit..remove_ptc sttj|dj|}t||kdd}d}d}d}d}d}d} d} |j|<|j|<j|dj|t ||||||d } | j|<t ||j || || d } | j|<t j dS) Nrrrrurrrrrr)rr]rGrHrrXrrrrNrrrkrlr) rrrrrrrvrr r r~rrrrrrs8 $z#schism_bpfile.edit..move_ptcSr.rr/r0rrrr3r4z&schism_bpfile.edit..r5rr8)rhrrrrkrlrmrnrBrrrZr5r:rrrrr disconnectrr)rrrrrZnhpr2r)rrrrrrrrs&    0    $ zschism_bpfile.editrr)NrruNTr)rrrrrrrArrorrrr-rrrrrroZs     rocCt}|||Sr)rr)rrrrrread_schism_hgrid-s r cCst}|j||d|S)zM read schism *bp (fmt=0) or *.reg (fmt=1) file created by ACE/gredit r)ror)rr{r5rrrread_schism_bpfile2srcCsFt|}|jdkr|dddf}|S|dddfdddf}|S)zH read schism *.prop file (element based), and return the values rNr)loadtxtndim)rZpdatapvaluerrrr:s rcCs t|ddS)z6 read schism *.reg file created by ACE/gredit rr)r)rrrrread_schism_regBs rgridruc Csd|}d|}d|}t}tj|r>t|}tj|r/t|}|j|j|_|_ |dkr;| | ||_ tj|rIt ||_t|ds\t|ds\td||t|||S)z read and save path/{hgrid.gr3,hgrid.ll,vgrid.in} fname: save name path: directory whether grids exist fmt=0: not save grid's full geometry; fmt=1: save z {}/hgrid.gr3z {}/hgrid.llz {}/vgrid.inrrvgridznot found: {}, {})r rr<r=existsr rGrHlonlatrrrread_schism_vgridrrZrTrUr@) rr=r{gnameZgname_llZvnamerrZgdlrrrsave_schism_gridHs && rc@s0eZdZddZddZd ddZd d d ZdS) schism_vgridcCsdSrrrrrrr\szschism_vgrid.__init__c Cst|d}|}|t|dd|_t|dd|_|jdkr|dd}t|d d}| dkrtdd|D|_ t |j |_ t|j |jg |_t|D]\}}t|dd d|j||j |df<qa|jS| d}|d|_ t ||_ td d|ddDj d|_|jd k}d |j|<|jS|jdkrE|ddd \|_|_t|j|_t|j|_g|_d}t|jD]}|d}|j||dqt|j d|_g|_|d}|j|jd|_t||dd  d\|_|_|_t|jD]}|d}|j||dq&t|j d|_|jS) NrrrrrcSs g|] }t|ddqSr)r\rr0rrrr3hrz+schism_vgrid.read_vgrid..r\cSr)rNrr0rrrr3nrr8r)rrrr\rrivcornvrtrBrrXkbpr:rSrIsigmarrkzh_srztotrrZnsigh_ctheta_btheta_f) rrrrrr2rZfpmZirecrrr read_vgrid_s:4 "  4$ 8 . zschism_vgrid.read_vgridrNc Cs|jdkr#|dkrt|j||||jdS|dkr!t|||||dSdS|jdkrEt|j|||d|d|d\}}|dkr=|S|dkrG||gSdSdS)a compute schism zcor (ivcor=1) dp: depth at nodes (dim=[np] or [1]) eta: surface elevation (dim=[np] or [1]) fmt: output format of zcor fmt=0: bottom depths byeond kbp are extended fmt=1: bottom depths byeond kbp are nan method=1 and ivcor=1: used for computing zcor for subset of nodes (need sigma,kbp) method=1 and ivcor=2: return zcor and kbp ifix=1 and ivcor=2: using traditional sigma in shallow if error raise rr)etar{rr)r'r{rvdrzifixN)r compute_zcorrr) rrPr'r{rzrrr)zcorrrrr*s   zschism_vgrid.compute_zcorvgrid.inc s |jdkr|j|j|j|jf\}}}}t|ddt ||||dkrjt |D] }d||d||f<q1dd|d |d}j|d d |d |j }fd d t |Dn1|dkrt t ||D]%\}\}}dd||d j|d|dg||dRqudS|jdkrt|ddd|j|j|jt |jD]\}} d|d| qˆd|j|j|jt |jD]\}} d|d| qdStd|jdS)z write schism vertical grid fmt=0: write vgrid.in in latest format of ivcor=1 (one line per lelvel) fmt=1: write vgrid.in in old format of ivcor=1 (one line per node) rrBz"1 !average # of layers={} {} riNz z {:10d} z{:8d}z {:10.6f}cs,g|]\}}j|dg|RqSr)rDr rrrRrrr3s,z,schism_vgrid.write_vgrid..z {:9d} {:3d}z {:11.6f}rz 2 !ivcor z"{} {} {} !nvrt, kz, h_s Z levels rCz)S levels {} {} {} !h_c, theta_b, theta_f z {} {:9.6f} zunknow ivcor={})rrrSrr rrrDr rrrrrrrr r!r"r#r$r%rTrU) rrr{rrSrrr2rZzlevelZslevelrr.r write_vgrids* $$"(,  ** zschism_vgrid.write_vgrid)rrrNNr)r,r)rrrrr&r*r/rrrrr[s  %rcCr )z' read schism vgrid information )rr&)rr(rrrrsrNrc Cs|dkrj|jd} t|dst| |}t|dst| |}|dur,tdd|D}||} | dddf||dddf} | dk} || dddf | | <|dkrht| D] } t| | d|| f<q[| S|dkrqt|ds|d} t|g}nt|} t|dst| |}t|j| gt} d|jt |j |j t |j |jt |j |j dt |j ddt |j d}| }||jk}|j||<||jk}|j dddf||dddf||dddf||dddf| |jdd|f<||j ||j|j t |j k}t|dkrh|dkr.td |j|dkrg||dddf||dddf||dddf|j dddf| |jdd|f<n<||dddfd|j dddf|j|j dddf|dddf|||j| |jdd|f<t| d  }|jd|||jk<||jk} t| d}|D]z} td|jdD] }||  |j|k||  |j|dkr||| <nq|| d krtd n|| dks || |jdkrtd || |j||  | || | f<t|| d|jdD] }|j|| || f<q/q| j} ||_|dkrat| D]} | | || f| | d|| f<qM|dkrh| S|dkrs| |gSdSdS)a# compute schism zcor (ivcor=1) sigma: sigma cooridinate (dim=[np,nvrt]) dp: depth at nodes (dim=[np] or [1]) eta: surface elevation (dim=[np] or [1]) fmt: output format of zcor fmt=0: bottom depths byeond kbp are extended fmt=1: bottom depths byeond kbp are nan kbp: index of bottom layer (not necessary, just to speed up if provided for ivcor=1) method=1 and ivcor=2: return zcor and kbp ifix=1 and ivcor=2: using traditional sigma in shallow if error raise rrr"NcSs(g|]}tt|ddkddqS)rr%rr8)rr]r0rrrr3rz compute_zcor..rrzPls choose a larger h_c: {}r\r8z$can not find a bottom level for nodezimpossible kbp,kz: {}, {})rVrZrIrBrrKr:rr$sinhr%rtanhr r!r#r rJrTrUr rrr"rr)rrPr'r{rrr(rzr)rShwr+fpzr2csZhmodrrZfpcrrrrrr*sn $"   "8 `&rx$. "   $1r*r,rr.r?cCst}|||_|_|dkrOt|dr$t|||d |_|_|_n d|g| |_|_|_||||_|_ |_ t dd|d|j|_ | |dStddS)a+ create schism vertical grid: fname: name of the grid nvrt: number of vertical layers ivcor=2: SZ grid zlevels: 1). Z levels or 2). single number for h_s h_c, theta_b, theta_f: strench constants for sigma grid ivcor=1: LCS^2 grid rr"r8rrz ivcor=1 option not available yetN)rrrrZr:r r"r!r#r$r%r[rr/rTrU)rrrZzlevelsr#r$r%r(rrrcreate_schism_vgrids  "r7c3 Cs&t|drt|dr||j }t|j|jf}nt|tjr4t|tjr4|j dkr3|dddf}nt dt |}|j d} t|dsLt d|j} ||j } |j||d\} } }| | |djdd } t| ddd f| dgj}||k}||||<t| ddd f| dgj}||k}||||<d}t|tjrd d|ggndt ||g\}}}d d |D}dd |D}|durtt|}|durtt|}t|d}t|d}g}d}g}tt|||D]\}\}}}t||jkd }t||jkd }t|| kd }||d krkt |dkr(|d ||<t |d kr.cSrrr9r0rrrr3Gr4r\z=need "pind" for np/ne in {}th variable: dims={}, np={}, ne={}z8need "zind" for nvrt in {}th variable: dims={}, nvrt={} rr)'rZr*rPrFrGrHrrSrrrTrUr:rVrr-rJrrrKrIrBrrrrrrQr rrrrrrr expand_dimsrrXr)3rr(r/ZpzvaluespindZzindr{r0nzrr+r3r1r2zmr3ZilstnvardimsndimsZtindw0Zpvaluesr2r dsrr4rZsindkrZtw0rrrZdsnrrrrz1z2Zratzrizrrratrrrrrinterp_schism_3d's  ,04,  4($:&,  (" ,"    00&0 $rFcCstd|dd\}}d||}t}tt|dd|_ |dkrD|j dd\|_ |_ |_ |_ |_|_|j dd|_|Std |S) z get global information about schism run (ne,ns,np,nvrt,nproc,ntracers,ntrs) dirpath: run directory or outputs directory fmt=0: default is 0; fmt(!=0) are for eariler schism versions rr)dirpathr{z{}/local_to_global_{}rr\Nrz fmt unknown)srankr rrBrreadlinerrrinforrQrSrnprocZntracersZntrsrTrU)rGr{Zrstrbdirrrrrrgetglobs "& rMcCsd}d}tjd|rtj|}d|}tjd|r/tjd|}d|}tjd|rCtj|}d|}tjd |rZtjd|}d|}|d kr`|S|d krh||gSdS) z return string of schism rank number ('0032', or '000032') dirpath: run directory, or RUN*/outputs fmt=0: return rank string; fmt=1: return rank string and the location dir. Nz{}/local_to_global_0000z{:04}z{}/outputs/local_to_global_0000z {}/outputs/z{}/local_to_global_000000z{:06}z!{}/outputs/local_to_global_000000rr)r<r=rr abspath)rankrGr{rLZstr_rankrrrrHs(.(.rHc Cst|ddd}t}t|d}t||d}t|||d}tdd|d|dDdddfdd|_td d||d||dDdddfdd|_td d|||d |||d Ddddfdd|_ t |||d t |D]%}|| }t |dkrqt|d|krt|d|kr|}nqtd d|||d|||dDd} | dddfd} | ddddfdd} |||| | f\|_ |_|_|_|_|S) z+ read schism partition information rrNrrcSrrrr0rrrr3rz/read_schism_local_to_global..r\cSrrrr0rrrr3rcSrrrr0rrrr3rrcSs<g|]}t|dkr|n g|dqS)r~r)r:rrr0rrrr3r=)rrrr\rrBrZielgZiplgZislgrr:rrQrSrr<rE) rrrrQrSrr2rndslinesr<rErrrread_schism_local_to_globals<6>F(44"rScCst|d}dd|D}|dd|D}i}|D]>}d|vr,|d|d}|d\}}|}|}|dkrW|d d d drWd |vrSt |nt |}|||<q|S) z read schism parameters from param.nml/param.in/cosine.in fmt=0: return all field as string; fmt=1: return field as float if possible rcSr.r)rr0rrrr3r4z%read_schism_param..cSs8g|]}d|vr|dkr|ddkr|ddkr|qS)rrNrr&rr0rrrr3s8rNrr-rurN) rrrfindrrlstripreplaceisdigitrr\)rr{rrparamrkeyivalirrrread_schism_params$  r]c Cslt|}t|d!}tt|D]}|d|||||qWddS1s/wYdS)NrBz {:10}= {:} )sortedkeysrrQr:rDr )rrZZpkeysrr2rrrwrite_schism_params   "r`c CsJt|d}|}|tdd|Dd}tdd|Dd}t||f}t|dddf}||}tdd|Dd }t|dddf}||}t} |jd| _ |jd| _ |ddd dfd | _ |ddd dfj \| _ | _| _d t| j d| _|ddd fd k} d | j| <|dur| || S)z 1). read SMS *2dm grid, and return grid object 2). if grd!=None, save grid as *gr3 format e.g. gd=sms2gr3('hgrid.2dm','hgrid.gr3') rcSs2g|]}|drg|dddqS)ZE3Trr8r startswithrrr0rrrr3s2zsms2grd..r\cS*g|]}|dr|ddqS)ZE4Qrr8rar0rrrr3*NrcSrc)NDrNrar0rrrr3rdrrrr8r)rrrrBrrOrrrVrQrSrErrGrHrPrIr<r?) smsgrdrrZE3ZE4ZE34rrerrrrrsms2grds(<4rhcCsBt|tr t|}nt|tr|}ntd|||dS)z convert schism hgrid to SMS *.2dm format usage: 1). grd2sms('hgrid.gr3','hgrid.2dm') 2). grd2sms(gd,'hgrid.2dm'), or gd.grd2sms('hgrid.2dm') note gd=read_schism_hgrid('hgrid.gr3') zunknow format of grd: {}N)rstrr rrTrUr rV)rgrfrrrrrV s  rVc Cs|jdd\}}t|} |jddkr|dddfnt| } tj||} t} | t| j| _ | _ ||| | _ | _ | _ t| jdt| j dgfd| _dt| j d| _t| ||||||d} | S)a create schism grid from scatter pts xyz: c_[x,y] or c_[x,y,z] angle_min: remove element with internal_angle < angle_min area_max: remove element with element_area > area_max side_min: remove element with side_length < side_min side_max: remove element with side_length > side_max reg_in: ACE/xgredit region file. remove elements in region if reg_in is provided reg_out: ACE/xgredit region file. remove elements outside of region if reg_out is provided Nrrrrr\)rbarea_maxside_minside_maxreg_inreg_out)rr:rVrrhr Triangulationr trianglesrSrQrGrHrPrFrIrrEr<delete_schism_grid_element) xyzrbrjrkrlrmrnrGrHrSrntrrrrrscatter_to_schism_grid!s &*:rtr~c)CsFgg}} |jdk} |jdk} td|jgd\} } }t|j}tdD]}|d| | <|dd| | <|dd|| <|d| | <|dd| | <|dd|| <|j|j|| f}|j|j|| f}|j|j||f}|j|j|| f}|j|j|| f}|j|j||f}tt ||d||t ||d||dt }| |t|d||d|}| |q%t |j }t | } |jdd}| jd d}| jd d}|||d urt||kd nt g}|d urt|j|kd nt g}|d urt||kd nt g}|d ur)t||kd nt g}t||||fd} |d urbt| d krbt|dd }!tt|j| |j| f|!j|!jdk}"| |"} |d urt|dd }!ttt|j|jf|!j|!jd kd }#t| |#f} tt|j| }$tt|jt|j|$}%t|%d kr|g}&|%D]<}'|j |'}(|d kr||(}|& |(t|t|kd d |dkr||(}|& |(t|t|kd d qt!t|$t |&f}$t|$|j|$|j|$|_|_|_|j|$|j|$|j|$|j"|$f\|_|_|_|_"|S) ag delete schism grid's elements grd: schism_grid object angle_min: remove element with internal_angle < angle_min area_max: remove element with element_area > area_max side_min: remove element with side_length < side_min side_max: remove element with side_length > side_max reg_in: ACE/xgredit region file. remove elements in region if reg_in is provided reg_out: ACE/xgredit region file. remove elements outside of region if reg_out is provided method=0: use side_max for dangling pts; method=1: use angle_min for dangling pts rrr\rrrr[r#rNr)#r<rIrQrrrGrErHr]r_r`rrBrrXrYrrsrrrOr:rr.rFrrrrSrrrrrr>))rrbrjrkrlrmrnrzanglessidesrrr%r&rerr2rrrrrrrpsiZmangleZsideminZsidemaxZfangleZfareaZ fside_maxZ fside_minr4r5rrrZipsrrZiesrrrrq:sH$ ,,<<F($ $"" 0  4  44&4rq__main__r)rrur)rrNrNrr)r,rrr5rrr6)NNr)rur)rrurr)NNNNNN)r~NNNNNr)pylibrror rrrrrrr*r7rFrMrHrSr]r`rhrVrtrqrrrrrsD^T  Y  V  o     =