From 733d2a22eff275888c0ec7d4d94a18f4471f19f0 Mon Sep 17 00:00:00 2001 From: keston Date: Thu, 29 Jan 2026 10:40:31 -0500 Subject: [PATCH 01/44] Added software for Non global mesh generation using jigsaw --- .../BuildBoundaryPSLGfunction.m | 348 ++++++++++++++ .../FilterRoutinesNM.py | 425 ++++++++++++++++++ .../MakeBoundaryForcingNodes.m | 92 ++++ .../MakeCoastalBoundariesGSHHS.m | 137 ++++++ .../MakeCoastalBoundariesOSM.m | 171 +++++++ .../MakeDfun_mshfile.m | 308 +++++++++++++ .../MergePslgsOSMxGSSHS.m | 64 +++ .../PostProcessGrid.m | 326 ++++++++++++++ .../RWPS.ng.NoFiltrsOpts.py | 256 +++++++++++ .../matlab/BoundaryShape2msh.m | 69 +++ .../RWPSMeshtoolkit/matlab/BoundingBox.m | 11 + .../RWPSMeshtoolkit/matlab/BoxSmoothTopo.m | 33 ++ .../matlab/BuildBoundaryPSLGfunction.m | 348 ++++++++++++++ .../RWPSMeshtoolkit/matlab/CombineMesh.m | 18 + .../RWPSMeshtoolkit/matlab/ComputeAdjacency.m | 3 + .../matlab/ComputeLengthScaleX.m | 31 ++ .../matlab/ComputeLengthScale_wgs84.m | 32 ++ .../matlab/ComputeLengthScale_wgs84_MEL.m | 31 ++ .../matlab/ConnectDisjointMesh.m | 139 ++++++ .../matlab/ConnectDisjointPSLGs.m | 54 +++ .../matlab/ConnectDisjointPSLGsN.m | 54 +++ .../RWPSMeshtoolkit/matlab/DistanceToCoast.m | 54 +++ .../matlab/DistanceToCoast_v0.m | 39 ++ .../RWPSMeshtoolkit/matlab/Ele2Nodes.m | 15 + unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m | 12 + .../RWPSMeshtoolkit/matlab/FindOuterBnd.m | 133 ++++++ .../matlab/FindOuterBndNoPSLG.m | 32 ++ .../RWPSMeshtoolkit/matlab/FindOuterBndV0.m | 129 ++++++ .../RWPSMeshtoolkit/matlab/FindOuterBndWW3.m | 35 ++ .../RWPSMeshtoolkit/matlab/FindPointsAx.m | 4 + .../matlab/FixOuterBndSandPoints.m | 44 ++ .../RWPSMeshtoolkit/matlab/HandEditMesh.m | 58 +++ .../RWPSMeshtoolkit/matlab/InterpCoastline.m | 28 ++ .../RWPSMeshtoolkit/matlab/InterpCoastline1.m | 38 ++ .../MakeCoastalBoundariesMixedCoastGlobal.m | 206 +++++++++ .../RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m | 308 +++++++++++++ .../matlab/MergePslgsOSMxGSSHS.m | 64 +++ .../matlab/PlotMeshResSCRIPT.m | 64 +++ .../RWPSMeshtoolkit/matlab/RemoveMeshParts.m | 80 ++++ .../matlab/RemoveMissingIslands.m | 80 ++++ .../matlab/RemoveMissingIslandsEle.m | 93 ++++ .../matlab/RemoveMissingIslandsEle2.m | 112 +++++ .../matlab/RemoveMissingIslandsPoint.m | 93 ++++ .../RWPSMeshtoolkit/matlab/RemoveSandPoints.m | 65 +++ .../matlab/RemoveSandPointsWW3.m | 53 +++ .../matlab/SmoothSubSampleCoastlineFast.m | 19 + .../RWPSMeshtoolkit/matlab/SubsetMesh.m | 22 + .../RWPSMeshtoolkit/matlab/WriteWW3Mesh.m | 73 +++ .../matlab/WriteWW3MeshNoJig.m | 74 +++ .../RWPSMeshtoolkit/matlab/WriteWW3MeshX.m | 68 +++ unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m | 99 ++++ .../RWPSMeshtoolkit/matlab/edges2chains.m | 87 ++++ .../RWPSMeshtoolkit/matlab/joinpslg.m | 68 +++ unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m | 5 + unst_msh_gen/RWPSMeshtoolkit/matlab/l.m | 6 + .../RWPSMeshtoolkit/matlab/loadmshWW3.m | 157 +++++++ .../RWPSMeshtoolkit/matlab/patch_global.m | 7 + .../RWPSMeshtoolkit/matlab/pslg2geom.m | 8 + .../matlab/remove_dead_nodes.m | 21 + .../RWPSMeshtoolkit/matlab/submeshFast.m | 17 + .../RWPSMeshtoolkit/matlab/submeshFastEle.m | 9 + .../matlab/submeshFastPlusEle.m | 17 + .../RWPSMeshtoolkit/matlab/subpslgFast.m | 25 ++ .../RWPSMeshtoolkit/matlab/topo2msh.m | 21 + .../ComputeDistanceToCoast.py | 143 ++++++ .../ComputeDistanceToCoastConv.py | 176 ++++++++ .../FindUSadjacentGSHHSpoints.py | 99 ++++ .../ComputeDistanceToCoast/ReadWriteCoast.py | 63 +++ .../SmoothAndInterpCoastline.py | 17 + .../SmoothAndSubsampleCoastline.py | 278 ++++++++++++ .../SmoothAndSubsampleCoastlineP.py | 94 ++++ 71 files changed, 6462 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast_v0.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBnd.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndWW3.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FixOuterBndSandPoints.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/HandEditMesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline1.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MakeCoastalBoundariesMixedCoastGlobal.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/PlotMeshResSCRIPT.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/l.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m new file mode 100644 index 0000000..fe69089 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m @@ -0,0 +1,348 @@ +function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +%CoastLineFile = 'GlobalCoastlineOSM.shp' +%CoastLineFile = 'GlobalCoastlineGSHHS.shp' +%lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +%run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) + +S=shaperead(CoastLineFile) +FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] +isplot=0; + +%load GlobalCoastlineOSM.mat + + +%The overall objective of this project is to develop and implement into operations +% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, +% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, +% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the +% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. + +%Blon=[129.91 10.71]; +%Blat=[-30.42 79.99]; +Blon=[lonWest, lonEast]; +Blat=[latSouth,latNorth]; + + +N=length(S); +N1=N; +for k=1:N + if mod(k,1000)==0,k/N,end + lon=S(k).X(1:end-1);%remove trailing nan + lat=S(k).Y(1:end-1); + ns(k)=length(lon); + jWest=find(lon<90); + if(length(jWest)==ns(k)); + S(k).X=[lon+360,NaN]; + end + if and(0length(jWest)),%make translated copy + display(['duplicating coastal segment: ',int2str(k), ', nseg=',int2str(ns(k))]) + N1=N1+1; + S(N1).X=[lon+360,NaN]; + S(N1).Y=[lat,NaN]; + ns(N1)=length(lon); + end +end +N=length(S); +[tmp,j]=sort(-ns); +S=S(j);% sort to descending in length +ns=ns(j);% sort to descending in length + +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; + +%Make Bounding rectangle +Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +clear pslg +sxp=[];syp=[ ]; +xc=[];yc=[]; +N=length(S); +pslg.x=[]; +pslg.y=[]; +pslg.edges=[]; +nc=0; + +minedeges=4 +minarea=1 + +earth=referenceSphere('Earth'); +DXM=10^10;%DXM=1 +mdx=inf+ones(N,1); +for k=1:N + isinbox(k)=0; + x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) + y=S(k).Y(1:end-1); + mx=mean(x); + my=mean(y); + if length(x)>minedeges, + ji=find( insidepoly( x,y,Bx,By ) ); + if length(ji)>2 + [xi, yi,ii] = polyxpoly(x, y, Bx, By); + xc=[xc;xi(:)]; + yc=[yc;yi(:)]; + if ~isempty(xi) %modify ob + sxp=[sxp,x(1)];syp=[syp,y(1)]; + [iia,jja]=sort(ii(:,1));%sort to ascending order along segments + xia=xi(jja); + yia=yi(jja); + iis=ii(jja,1);%sorted into ascending order along segments + if ~insidepoly( x(1),y(1),Bx,By )% segment origonates outside box + nseg=length(xia); + for j=1:2:nseg-1, + xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; + ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + mdx(k)=max(dx); + + if max(dx) island entirely inside bounding box + xs=[x(1:end-1)]; + ys=[y(1:end-1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + if and(length(xs)>2,max(dx)3, ar> + if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end +end + +%OK - now revisit outer boundary! +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%restart script from here if needed +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%clear +%close all +eval(['load ',FileOutMatlab]); +%load pslgOSM.mat +%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +%make outer bound +n=length(pslg.x); +%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes +%pslg.y=[pslg.y,By(3:4)]; +pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes +pslg.y=[pslg.y,By(2:4)]; + +nc=length(pslg.chains);%add northwest and north east box corner chains +pslg.chains(nc+1).nodes=n+1; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+2; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+3; +nc=length(pslg.chains); + +xx =153.0400 %south east corner of Austrilia +yy = Blat(1) %check that these are the endpoints described for j0, j1!! +[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end + +xx = 288.3143%check that these are the endpoints described for j0, j1!! +yy = Blat(1) %south west corner of S. America +[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end + +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=[j0,j1]; +nc=length(pslg.chains); + +for k=1:nc + if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end + spx(k)=pslg.x(pslg.chains(k).nodes(1)); + spy(k)=pslg.y(pslg.chains(k).nodes(1)); + epx(k)=pslg.x(pslg.chains(k).nodes(end)); + epy(k)=pslg.y(pslg.chains(k).nodes(end)); + end + +%make boundary order index along boundary for start points +SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges +c=0*spy; +Deps1=10^-10 +j=find(abs(spy-By(1))v); +[mm,m]=min(c(j)); +l=j(m); +epi=[epi,pslg.chains(l).nodes]; +obc=[obc,l]; +n=0; +%while(epi(end)~=epi(1)) +while isempty( find(epi(2:end)==epi(1)) ) + v=d(l); + j=find(c>v); + [mm,m]=min(c(j)); + l=j(m) + epi=[epi,pslg.chains(l).nodes]; + obc=[obc,l]; + if isplot==1, plot(pslg.x(epi),pslg.y(epi),'r.-');pause(.001);end +end +j=find(epi(2:end)==epi(1)); +epi=epi(1:(j+1)); +%vvvvvvvvvvv Add fixed grid points on open boundary +% to prevent "curved" boundaries due to projection details +xob=pslg.x(epi); +yob=pslg.y(epi); +dob=abs([xob(2:end)-xob(1:end-1)]+i*[yob(2:end)-yob(1:end-1)]); +dob=[dob,abs([xob(end)-xob(1)]+i*[yob(1)-yob(end)])]; +nb=length(xob); +dmin=1;%node spacing around boundary +epit=epi; +for k=1:nb-1 + d=abs([xob(k+1)-xob(k)]+i*[yob(k+1)-yob(k)]); + if d>dmin + npl=round(d/dmin)-1; + dx=xob(k+1)-xob(k); + dy=yob(k+1)-yob(k); + xp=xob(k)+dx*[1:npl-1]/npl; + yp=yob(k)+dy*[1:npl-1]/npl; + np=length(xp); + n=length(pslg.x); + pslg.x=[pslg.x,xp]; + pslg.y=[pslg.y,yp]; + NewEdges=[[epi(k),n+1];[[n+1:n+np-1]',[n+2:n+np]'];[n+np,epi(k+1)]]; + %pslg.edges=[pslg.edges;NewEdges]; + j=find(epi(k)==epit ); + epit=[epit(1:j),n+1:n+np,epit(j+1:end)]; + end +end +epi=epit; +% to prevent "curved" boundaries due to projection details +%^^^^^^^^^^^^ Add fixed grid points on open boundary + + +% add edges in obc +epiv=epi(:); +NOE=length(epiv) +OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; +pslg.edges=[pslg.edges;OutterEdges]; + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +nodelist=[]; +for k=1:nc + if mod(k,100)==0,disp(['Finding interior chains compleate: ',num2str(k/nc)]);,end + if pslg.chains(k).nodes(1)==pslg.chains(k).nodes(end) + n=pslg.chains(k).nodes(1); + [inpoly,onpoly]=insidepoly( pslg.x(n), pslg.y(n),xob,yob); + if and(inpoly==1,onpoly==0) + nodelist=union(nodelist,pslg.chains(k).nodes); + end + end +end + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi']); + +nodelistXB=union(nodelist,epi); +pslgb=subpslgFast(pslg,nodelistXB); + +%remove "random" duplicate nodes +%z=pslgb.x+i*pslgb.y; +%[zu,j,k]=unique(z); +%pslgc=subpslgFast(pslgb,j); +pslgc=pslgb + +%remove duplicate edges +pslgc.edgesS=sort(pslgc.edges')'; +pslgc.edgesSU=unique(pslgc.edgesS,'rows') +pslgc.edges=pslgc.edgesSU; + +pslg=pslgc + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%save PSLG to jigsaw .msh format +geom=pslg2geom(pslg) +savemsh(FileOutJigsaw,geom) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py new file mode 100644 index 0000000..1a7a733 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py @@ -0,0 +1,425 @@ + +# The DEM file used below can be found at: +# https://github.com/dengwirda/dem/releases/tag/v0.1.1 +import os +import argparse +import configparser +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator +from scipy.sparse import csr_matrix +from scipy.sparse.csgraph import connected_components + +#from spacing import * + +def parse_input_args(): + parser = argparse.ArgumentParser(description='Create a mask file with multiple methods.') + parser.add_argument('--config', type=str, required=True, help='Path to the configuration file.') + args = parser.parse_args() + return args + +def load_configuration(config_path): + config = configparser.ConfigParser() + config.read(config_path) + + # Creating a dictionary and populating it with configuration settings + configurations = { + 'mesh_file': config.get('MeshSettings', 'mesh_file', fallback=''), + 'ww3_mesh_file':config.get('MeshSettings', 'WW3_mesh_file', fallback=''), + 'hfun_hmax': float(config.get('MeshSettings', 'hfun_hmax', fallback='100')), + 'black_sea': config.getint('CommandLineArgs', 'black_sea', fallback=3), + 'mask_file': config.get('CommandLineArgs', 'mask_file', fallback=''), + 'hmax': float(config.get('Spacing', 'hmax', fallback='100.0')), + 'hshr': float(config.get('Spacing', 'hshr', fallback='100')), + 'nwav': int(config.get('Spacing', 'nwav', fallback='400')), + 'hmin': float(config.get('Spacing', 'hmin', fallback='100.0')), + 'dhdx': float(config.get('Spacing', 'dhdx', fallback='0.05')), + 'dem_file': config.get('DataFiles', 'dem_file', fallback='') + } + return configurations + +ISOLATED = 30000. # min surface area [km^2] + +# just global objects, to keep things simple... +geom = jigsawpy.jigsaw_msh_t() +spac = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +opts = jigsawpy.jigsaw_jig_t() + + + +def inject_dem(): + +# args = parse_input_args() +# configurations = load_configuration(args.config) + +#-- remap a DEM on to the vertices of the mesh + + print("*inject-dem...") + + # Load the DEM file from the config + #dem_file = configurations['dem_file'] + #data = nc.Dataset(dem_file,"r") + + data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") + + xlon = np.asarray(data["lon"][:]) + ylat = np.asarray(data["lat"][:]) + elev = np.asarray(data["bed_elevation"][:]) + \ + np.asarray(data["ice_thickness"][:]) + + xmid = 0.5 * (xlon[:-1:] + xlon[1::]) + ymid = 0.5 * (ylat[:-1:] + ylat[1::]) + + ffun = RegularGridInterpolator( + (ymid, xmid), elev, + bounds_error=False, fill_value=None) + + vert = mesh.point["coord"] + + mids =(vert[mesh.tria3["index"][:, 0], :] + + vert[mesh.tria3["index"][:, 1], :] + + vert[mesh.tria3["index"][:, 2], :] + ) / 3.0 + + vsph = jigsawpy.R3toS2(geom.radii, vert) + vsph*= 180. / np.pi + + mesh.value = ffun((vsph[:, 1], vsph[:, 0])) + + msph = jigsawpy.R3toS2(geom.radii, mids) + msph*= 180. / np.pi + + mesh.vmids = ffun((msph[:, 1], msph[:, 0])) + + # save lon-lat at cell centres + mesh.smids = np.zeros( + (mesh.tria3.size, 2), dtype=np.float64) + mesh.smids[:, 0] = msph[:, 0] + mesh.smids[:, 1] = msph[:, 1] + + +def tri_to_tri(tria): + +#-- return tria-to-tria adj. as a sparse graph + + # non-unique edges in tris + edge = np.empty((0, 2), dtype=np.int32) + tris = np.empty((0), dtype=np.int32) + edge = np.concatenate((edge, + tria[:, (0, 1)]), axis=0) + tris = np.concatenate((tris, + np.arange(0, tria.shape[0]))) + + edge = np.concatenate((edge, + tria[:, (1, 2)]), axis=0) + tris = np.concatenate((tris, + np.arange(0, tria.shape[0]))) + + edge = np.concatenate((edge, + tria[:, (2, 0)]), axis=0) + tris = np.concatenate((tris, + np.arange(0, tria.shape[0]))) + + # which edges match to which? + edge = np.sort(edge, axis=1) + imap = np.argsort(edge[:, 1], kind="stable") + edge = edge[imap, :] + tris = tris[imap] + imap = np.argsort(edge[:, 0], kind="stable") + edge = edge[imap, :] + tris = tris[imap] + + diff = edge[1::, :] - edge[:-1:, :] + + same = np.argwhere(np.logical_and.reduce(( + diff[:, 0] == 0, + diff[:, 1] == 0))).ravel() + + # tris[same] and tris[same+1] share + rows = np.concatenate(( + tris[same], tris[same+1])) + cols = np.concatenate(( + tris[same+1], tris[same])) + data = np.ones(rows.size, dtype=np.int8) + + # ith tri is adj. to tri in ith row + return csr_matrix((data, (rows, cols))) + + +def filter_dry(mesh, mask): + +#-- require dry cells > 1 dry edge, and large + + print("*filter-dry...") + + filt = np.logical_not(mask) + tris = np.argwhere(filt).ravel() + + conn = tri_to_tri(mesh.tria3["index"][filt, :]) + + # require dry to be adj. >=1 dry cell + isol = np.sum(conn, axis=1) <= 1 + isol = np.ravel(isol) +#KWS COMMENT BELOW + + # delete groups of dry if too small + nprt, part = connected_components( + conn, directed=False, return_labels=True) + + tris = np.argwhere(filt).ravel() + for iprt in range(nprt): + itri = np.argwhere(part == iprt) + if (itri.size <= 2): mask[tris[itri]] = True + +#KWS COMMENT ABOVE + + # otherwise mark isolated cell as ocn + mask[tris[isol]] = True + + return mask + + +def filter_wet(mesh, mask): + +#-- require wet cells > 1 wet edge, and large + + print("*filter-wet...") + + tris = np.argwhere(mask).ravel() + + conn = tri_to_tri(mesh.tria3["index"][mask, :]) + + # require wet to be adj. >=1 wet cell + isol = np.sum(conn, axis=1) <= 1 + isol = np.ravel(isol) + + # delete groups of wet if too small + nprt, part = connected_components( + conn, directed=False, return_labels=True) + + area = jigsawpy.trivol2( + mesh.point["coord"], + mesh.tria3["index"][mask, :]) + + for iprt in range(nprt): + itri = np.argwhere(part == iprt) + asum = np.sum(area[itri]) + #print(asum) + if asum < ISOLATED: mask[tris[itri]] = False + + # otherwise mark isolated cell as dry + mask[tris[isol]] = False + + return mask + + +def filter_ocn(): + +# args = parse_input_args() +# configurations = load_configuration(args.config) + +#-- use the remapped elev. to keep ocean cells + + print("*filter-ocn...") +#KWS not sure what this is +# elev =(mesh.value[mesh.tria3["index"][:, 0]] +# + mesh.value[mesh.tria3["index"][:, 1]] +# + mesh.value[mesh.tria3["index"][:, 2]] +# + mesh.vmids) / 4.0 + elev =(mesh.value[mesh.tria3["index"][:, 0]] + + mesh.value[mesh.tria3["index"][:, 1]] + + mesh.value[mesh.tria3["index"][:, 2]] + ) / 3.0 + # Define the Caspian Sea region + caspian_lat_min = 34.5 + caspian_lat_max = 50.0 + caspian_lon_min = 44.5 + caspian_lon_max = 55.5 + + # Define the black Sea region + blacksea_lat_min = 40 + blacksea_lat_max = 47.25 + blacksea_lon_min = 26.15 + blacksea_lon_max = 41.5 + + # Define the additional region1 + additional_lat_min = 39.95 + additional_lat_max = 40.6 + additional_lon_min = 26 + additional_lon_max = 26.8 + + # Define the additional region2 + additional_lat_min2 = 40.3 + additional_lat_max2 = 40.6 + additional_lon_min2 = 26.8 + additional_lon_max2 = 30 + + # Define the additional region3 + additional_lat_min3 = 40.6 + additional_lat_max3 = 41.25 + additional_lon_min3 = 28.9 + additional_lon_max3 = 29.1 + + """ +# Print the elevations in the additional region + additional_elev = elev[np.logical_and.reduce(( + mesh.smids[:, 1] >= additional_lat_min, + mesh.smids[:, 1] <= additional_lat_max, + mesh.smids[:, 0] >= additional_lon_min, + mesh.smids[:, 0] <= additional_lon_max + ))] + print("Elevations in the additional region:") + print(additional_elev) + +# Print the elevations in the additional region2 + additional_elev2 = elev[np.logical_and.reduce(( + mesh.smids[:, 1] >= additional_lat_min2, + mesh.smids[:, 1] <= additional_lat_max2, + mesh.smids[:, 0] >= additional_lon_min2, + mesh.smids[:, 0] <= additional_lon_max2 + ))] + print("Elevations in the additional region2:") + print(additional_elev2) + +# Print the elevations in the additional region3 + additional_elev3 = elev[np.logical_and.reduce(( + mesh.smids[:, 1] >= additional_lat_min3, + mesh.smids[:, 1] <= additional_lat_max3, + mesh.smids[:, 0] >= additional_lon_min3, + mesh.smids[:, 0] <= additional_lon_max3 + ))] + print("Elevations in the additional region3:") + print(additional_elev3) + + """ + + # zssh, to cull elev. against + surf = np.zeros(elev.shape, dtype=np.float32) + # Update the surf array to include both regions + # Define the Caspian Sea region + caspian_region = np.logical_and.reduce(( + mesh.smids[:, 1] >= caspian_lat_min, + mesh.smids[:, 1] <= caspian_lat_max, + mesh.smids[:, 0] >= caspian_lon_min, + mesh.smids[:, 0] <= caspian_lon_max + )) + + blacksea_region = np.logical_and.reduce(( + mesh.smids[:, 1] >= blacksea_lat_min, + mesh.smids[:, 1] <= blacksea_lat_max, + mesh.smids[:, 0] >= blacksea_lon_min, + mesh.smids[:, 0] <= blacksea_lon_max + )) + + keep = elev <= surf # only keep tri with wet elev + + + + # iterate on dry cells until none "isolated" + #KWS remove filter dry for Non Global mesh +# if (False): +# knum = np.count_nonzero(keep) +# while (True): +# keep = filter_dry(mesh, keep) +# if (np.count_nonzero(keep) == knum): break +# knum = np.count_nonzero(keep) +# mesh.tria3 = mesh.tria3[keep] + + # iterate on wet cells until none "isolated" + keep = np.ones(mesh.tria3.size, dtype=bool) + knum = np.count_nonzero(keep) + while (True): + keep = filter_wet(mesh, keep) + if (np.count_nonzero(keep) == knum): break + knum = np.count_nonzero(keep) + + mesh.tria3 = mesh.tria3[keep] + + # delete unused vertices and reindex + ifwd = np.unique(mesh.tria3["index"].ravel()) + + irev = np.zeros(mesh.point.size, dtype=np.int32) + irev[ifwd] = np.arange(ifwd.size, dtype=np.int32) + + mesh.point = mesh.point[ifwd] + mesh.value = mesh.value[ifwd] + mesh.tria3["index"] = irev[mesh.tria3["index"]] + return mesh + +def write_gmsh_mesh(filename, node_data, tri): + num_nodes = node_data.shape[0] + + # Write the mesh to the file + with open(filename, 'w') as fileID: + fileID.write("$MeshFormat\n") + fileID.write("2 0 8\n") + fileID.write("$EndMeshFormat\n") + fileID.write("$Nodes\n") + fileID.write(str(num_nodes) + "\n") + + for i in range(num_nodes): + fileID.write( + f"{i + 1} {node_data[i, 0]:5.5f} {node_data[i, 1]:5.5f} {node_data[i, 2]:5.5f}\n" + ) + + fileID.write("$EndNodes\n") + fileID.write("$Elements\n") + num_elements = len(tri) + fileID.write(str(num_elements) + "\n") + + m = 0 + for i in range(len(tri)): + m += 1 + fileID.write(f"{m} 2 3 0 {i+1} 0 {tri[i][0]} {tri[i][1]} {tri[i][2]}\n") + + fileID.write("$EndElements\n") + +def interp_bathymetry_v0(): + + +#-- remap a DEM on to the vertices of the mesh + + print("*interp-batyhmetry...") + + # Load the DEM file from the config + dem_file = "../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc" + + data = nc.Dataset(dem_file,"r") + + xlon = np.asarray(data["lon"][:]) + ylat = np.asarray(data["lat"][:]) + elev = np.asarray(data["bed_elevation"][:]) + \ + np.asarray(data["ice_thickness"][:]) + + xmid = 0.5 * (xlon[:-1:] + xlon[1::]) + ymid = 0.5 * (ylat[:-1:] + ylat[1::]) + + ffun = RegularGridInterpolator((ymid, xmid), elev,bounds_error=False, fill_value=None) + + vert = mesh.point["coord"] + hdown = ffun( (vert[:, 1], vert[:, 0]) ) + + vert[:,2]=hdown + mesh.point["coord"][:,2]=vert[:,2] + return mesh + + +def interp_bat(): + +#-- remap a DEM on to the vertices of the mesh + + print("*interp-batyhmetry...") + + ffun = RegularGridInterpolator((topo.ygrid, topo.xgrid),topo.value,bounds_error=False, fill_value=None) + vert = mesh.point["coord"] + hdown = ffun( (vert[:, 1], vert[:, 0]) ) + mesh.value=hdown + return mesh + +def do_nothing( ): + print("the end") + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m new file mode 100644 index 0000000..2d4b424 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m @@ -0,0 +1,92 @@ +function MakeBoundaryForcingNodes(dx,CheckGFS) +if nargin<2,CheckGFS=0;end + +Blon=[129.91 10.71]; +Blon(1)=Blon(1)-360; +Blat=[-30.42 79.99]; +g=loadmshWW3('RWPS.OSMxGSHHS.GMU.txt.WW3.msh'); + +jb=unique(g.bnd); + +xb=g.x(jb); +yb=g.y(jb); + +%x=Blon(1)-dx:dx:Blon(2)+dx; +%y=Blat(1)-dx:dx:Blat(2)+dx; +x=Blon(1):dx:Blon(2); +y=Blat(1):dx:Blat(2); +if x(end)~=Blon(2), + x=[x,Blon(2)]; +end +if y(end)~=Blat(2), + y=[y,Blat(2)]; +end + + +Xs=x; +Ys=zeros(size(Xs))+min(Blat); +Xn=x(end:-1:1); +Yn=zeros(size(Xs))+max(Blat); + +Ye=y +Xe=zeros(size(Ye))+max(Blon); +Yw=y(end:-1:1); +Xw=zeros(size(Yw))+min(Blon); + +X=[Xs,Xe,Xn,Xw]; +Y=[Ys,Ye,Yn,Yw]; +whos X Y +clear m i; +for k=1:length(X); + m(k)=min(abs(X(k)+i*Y(k)-xb-i*yb)); +end + +j=find(m<2*dx); +Xp=X(j); +Yp=Y(j); +Xpp=Xp; +jW=find(Xpp<0); +Xpp(jW)=Xpp(jW)+360; + +filename = ['BoundaryDX',int2str(round(1/dx)),'thDeg.RWPS.txt'] +fileID = fopen(filename, 'w'); +fprintf(fileID, '%6f %6f\n',[Xpp(:),Yp(:)]'); +fclose(fileID); + +figure; +x=g.x;y=g.y;z=g.z;e=g.e; +clf;ph=patch(x(e'),y(e'),z(e'));shading interp;colormap('jet');colorbar; caxis([0,5000]);axis equal +hold on +plot(Xp,Yp,'k.-'); +plot(xb,yb,'r.') + +if CheckGFS, + Xpp=Xpp(:); + Yp=Yp(:); + xb=Xpp; + yb=Yp; + g=loadmshWW3('/mnt/sda/keston/meshes/uglo_15km.msh'); + x=g.x;y=g.y;z=g.z;e=g.e; + + clf;patch_global(x,y,z,e');shading interp; + cm=colormap('jet');colormap(flip(cm));colorbar; caxis([0,5000]);axis equal + + zb=scattered_interp2_noext(g.x,g.y,g.z,g.e,xb,yb) + j=find(isnan(zb )) + + nb=length(xb); + k=setdiff(1:nb,j) + hold on; + phg=plot(xb(k),yb(k),'w.'); + phb=plot(xb(j),yb(j),'ko',xb(j),yb(j),'kx'); + set(phb(1),'MarkerSize',13);set(phb(2),'MarkerSize',13); + title([int2str(round(1/dx)),'th degree spacing. White dot RWPS bound in GFS mesh, Black-Circle points out of GFS mesh ']); + kprint(['BoundaryDX',int2str(round(1/dx)),'thDeg.RWPS.jpg']) + InGFS=k; + OutGFS=j + + filename = ['BoundaryDX',int2str(round(1/dx)),'thDeg.RWPS.InGFS.txt'] + fileID = fopen(filename, 'w'); + fprintf(fileID, '%6f %6f\n',[Xpp(k),Yp(k)]'); + fclose(fileID); +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m new file mode 100644 index 0000000..bfc3680 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m @@ -0,0 +1,137 @@ +function MakeCoastalBoundariesGSHHS + +% make coastlines for mesh generation. +%Islands smaller than a threshold area are excluded. +%Narrow islands(some attols) with less than critical area are included if +%perimeter is longer than minPerimeter. Global and Pacific values are treated differently +%Coastline is smoothed and subsampled to usefull scale for mesh generation in RWPS +%various smoothings of coastlines + + +clear +isplot=0 +deg2km=111.132954 +deg2rad=pi/180 + + +%Pacific +minareaP=1;% square km +minPerimeterP=3;% km + +minareaG=1;% square km +minPerimeterG=10;% km + +geom.mshID='EUCLIDEAN-MESH' +geom.fileV = 3 +%filter out small islands +PacLon=[-140,140] +PacLat=[-20,40]; + +earth=referenceSphere('Earth') + +gcfl='../RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' +S = shaperead(gcfl); +N=length(S); +isisland=zeros(N,1); +for k=1:N + ns(k)=length(S(k).X(1:end-1)); + if and( S(k).X(end-1)==S(k).X(1) , S(k).Y(end-1)==S(k).Y(1) ) + isisland(k)=1; + end +end +if sum(isisland)==N + disp(['All features in ',gcfl,' are closed islands']) +else + disp([int2str(sum(isisland)),' features in ',gcfl,... + ' are closed islands. out of:',int2str(N),' total features']) +end + +%S0=S;%??? +n=0; +for k=1:N + x=S(k).X(1:end-1); + y=S(k).Y(1:end-1); +% [xs,ys]=SmoothSubSampleCoastlineFast(x,y,100.,75); + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,50.,10);%500 m coastline + if length(xs)>2, + n=n+1; + S0(n).X=[xs(:);NaN]'; + S0(n).Y=[ys(:);NaN]'; + S0(n).X0=S(n).X; + S0(n).Y0=S(n).Y; + S0(n).area = areaint(ys,xs,earth) / 10^6; + S0(n).perim=sum( deg2km*abs( cos(deg2rad*mean(ys))*( xs(2:end)-xs(1:end-1) ) + i*(ys(2:end)-ys(1:end-1)) ) ); + S0(n).Geometry=S(k).Geometry; + end + + if mod(k,1000)==0, + disp(['progress a:', num2str( sum(ns(1:k))/sum(ns) )]); + disp(['progress b:', num2str( k/N )]); + end +end + +N=length(S0) +for k=1:N + ns0(k)=length(S0(k).X(1:end-1)); +end +S=S0; + +save -v7.3 GlobalCoastlineGSHHS.mat S ns0 +%filter out small islands +js=[154,53]; +jsp=[154,53]; +clear A P +for n=1:length(S), + xp=mean(S(n).X(1:end-1)); + yp=mean(S(n).Y(1:end-1)); + if and( or(xpPacLon(2)), and(yp>PacLat(1),ypminarea, + js=[js,n]; + end + %if isempty(S(n).perim),S(n).perim=0;end + P(n)=S(n).perim; + if S(n).perim>minperim, + jsp=[jsp,n]; % perimeter criteria for narrow Atolls + end + Amin(n)=minarea; + Pmin(n)=minperim; + if mod(n,1000)==0, + disp(['progress ', num2str( n/ length(S) )]); + end + +end + +close all +if isplot + figure; + for k=1:length(js) + n=js(k); + xs=S(n).X(1:end-1); + ys=S(n).Y(1:end-1); + plot(xs,ys,'k-');hold on + end + pindx=setdiff(jsp,js) % narrow attols + for k=1:length(pindx) + n=pindx(k); + xs=S(n).X(1:end-1); + ys=S(n).Y(1:end-1); + plot(xs,ys,'r.-'); + end +end +jsg=union(js,jsp); + +%js=find(A>minarea); +S=S(jsg); +save -v7.3 GlobalCoastlineGSHHS.mat S +S=rmfield(S,'X0') +S=rmfield(S,'Y0') + +BoundaryShape2msh(S,'GlobalCoastlineGSHHS.msh'); +shapewrite(S, 'GlobalCoastlineGSHHS.shp'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m new file mode 100644 index 0000000..6ef687d --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m @@ -0,0 +1,171 @@ +function MakeCoastalBoundariesOSM +%Islands smaller than a threshold area are excluded. +%Narrow islands(some atolls) with less than critical area are included if +%perimeter is longer than minPerimeter. Global and Pacific values are treated differently +%Coastline is smoothed and subsampled to usefull scale for mesh generation in RWPS +%various smoothings of coastlines + + +clear +isplot=0 +deg2km=111.132954 +deg2rad=pi/180 + + +%Pacific +minareaP=1;% square km +minPerimeterP=3;% km + +minareaG=1;% square km +minPerimeterG=10;% km + +geom.mshID='EUCLIDEAN-MESH' +geom.fileV = 3 +%filter out small islands +PacLon=[-140,140] +PacLat=[-20,40]; + +earth=referenceSphere('Earth') + +%gcfl='/mnt/sda/keston/RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' +gcfl='../RWPS/Data/openstreetmap_land/land_polygons.shp' +S = shaperead(gcfl); +N=length(S); +isisland=zeros(N,1); +for k=1:N + ns(k)=length(S(k).X(1:end-1)); + if and( S(k).X(end-1)==S(k).X(1) , S(k).Y(end-1)==S(k).Y(1) ) + isisland(k)=1; + end +end +if sum(isisland)==N + disp(['All features in ',gcfl,' are closed islands']) +else + disp([int2str(sum(isisland)),' features in ',gcfl,... + ' are closed islands. out of:',int2str(N),' total features']) +end + +for k=1:N + x=S(k).BoundingBox(:,1); + y=S(k).BoundingBox(:,2); + x0(k)=mean(x); + y0(k)=mean(y); + dx(k)=abs(x(1)-x(2)); + dy(k)=abs(y(1)-y(2)); +end +A=[dx.*cos(deg2rad*y0/180)*deg2km].*[dy*deg2km]; +k=find(A>.500*.500); +S=S(k); +ns=ns(k); +N=length(S); +[ss,k]=sort(-ns); +S=S(k); +ns=ns(k); +N=length(S); +n=0; + +for k=1:N + x=S(k).X(1:end-2);%unique* points + y=S(k).Y(1:end-2); + zz=x+i*y; + [zzu,j]=unique(zz);%find unique points before end + j=sort(j); + if length(zzu)1); + if length(j)>0 + ji=1:j(1); + xs=xs(ji);ys=ys(ji); + end + + if length(xs)>2, + n=n+1; + S0(n).X=[xs(:);NaN]'; + S0(n).Y=[ys(:);NaN]'; + S0(n).X0=S(n).X; + S0(n).Y0=S(n).Y; + S0(n).area = areaint(ys,xs,earth) / 10^6; + S0(n).perim=sum( deg2km*abs( cos(deg2rad*mean(ys))*( xs(2:end)-xs(1:end-1) ) + i*(ys(2:end)-ys(1:end-1)) ) ); + S0(n).Geometry=S(k).Geometry; + end + if mod(k,1000)==0, + disp(['progress a:', num2str( sum(ns(1:k)) / sum(ns) ), ', progress b:', num2str( k/N )]); + end +end + +N=length(S0) +for k=1:N + ns0(k)=length(S0(k).X(1:end-1)); +end +S=S0; + +save -v7.3 GlobalCoastlineOSM.mat S ns0 +%filter out small islands +js=[ ]; +jsp=[ ]; +clear A P +for n=1:length(S), + xp=mean(S(n).X(1:end-1)); + yp=mean(S(n).Y(1:end-1)); + if and( or(xpPacLon(2)), and(yp>PacLat(1),ypminarea, + js=[js,n]; + end + %if isempty(S(n).perim),S(n).perim=0;end + P(n)=S(n).perim; + if S(n).perim>minperim, + jsp=[jsp,n]; % perimeter criteria for narrow Atolls + end + Amin(n)=minarea; + Pmin(n)=minperim; + if mod(n,1000)==0, + disp(['progress ', num2str( n/ length(S) )]); + end + +end + +if isplot + + close all + figure; + for k=1:length(js) + n=js(k); + xs=S(n).X(1:end-1); + ys=S(n).Y(1:end-1); + plot(xs,ys,'k-');hold on + end + pindx=setdiff(jsp,js) % narrow attols + for k=1:length(pindx) + n=pindx(k); + xs=S(n).X(1:end-1); + ys=S(n).Y(1:end-1); + plot(xs,ys,'r.-'); + end +end + +jsg=union(js,jsp); + +%js=find(A>minarea); +S=S(jsg); +save -v7.3 GlobalCoastlineOSM.mat S +S=rmfield(S,'X0') +S=rmfield(S,'Y0') + +BoundaryShape2msh(S,'GlobalCoastlineOSM.msh'); +shapewrite(S, 'GlobalCoastlineOSM.shp'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m new file mode 100644 index 0000000..7482382 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m @@ -0,0 +1,308 @@ +%This script creates a "Distance to Coast file" using a us coastline file +%and custom specification of + +clear +close all +isplot=0 + +%Input files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%PSLGfile='GlobalCoastlineOSM.PSLG.msh' +PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' +%Global Bathymetry file (netcdf) +GlobalTopoFile='../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%Shape file with US coastline +uscl='../RWPS/Data/us_coastline/tl_2023_us_coastline.shp' + +%Output files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Output "distance to coast" grided jigsaw .msh file +DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] +%Output bathymetry on same grid as DFunOutFile +TopoFile=['Topo.',DFunOutFile]; +%Temporary matlab file +FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] + + +US=shaperead(uscl); +NUS=length(US) +xus=[]; +yus=[]; +x0=[] +y0=[]; +interpDist=100. %meters +SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist +% then subsample soothed coastline every SmoothN points to create smaller +% coastline data set. i.e. remove small scale variation +for k=1:NUS + x=US(k).X(1:end-1); + y=US(k).Y(1:end-1); + x0=[x0,x]; + y0=[y0,y]; +% xs=x;ys=y; %1.5 mil points + if length(x)>3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; +xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; + +if isplot, + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +p.x=p.point.coord(:,1)-360; +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +j=find(xus>90); +xus(j)=xus(j)-360; + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; +yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; +j=find(xx>90); +xx(j)=xx(j)-360; +plot(xx,yy,'c.'); + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m new file mode 100644 index 0000000..cade447 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m @@ -0,0 +1,64 @@ + + +%OSMmsh='./PSLGboundary1kmP_NewOrleans.OSM.msh' +%GSHHGmsh='./PSLGboundary1kmP_NewOrleansB.msh' +isplot=0 +OSMmsh='./GlobalCoastlineOSM.PSLG.msh' +GSHHGmsh='./GlobalCoastlineGSHHS.PSLG.msh' +p0=loadmsh(OSMmsh) +p1=loadmsh(GSHHGmsh) + +p0.x=p0.point.coord(:,1); +p0.y=p0.point.coord(:,2); +p0.edges=p0.edge2.index(:,1:2); + + +p1.x=p1.point.coord(:,1); +p1.y=p1.point.coord(:,2); +p1.edges=p1.edge2.index(:,1:2); + +axAS = [183.0293 191.6089 -24.5496 -11.9295] +axPalau =[ 130.8368 141.8230 3.9914 10.1256] +axSP =[ 211.0219 220.1817 -18.9565 -13.8421] +axCP =[ 151.1962 152.3336 6.9451 7.5801] +axGOM =[ 290.8507 291.1934 43.7119 43.9032] +axCar =[ 272.0041 272.7733 17.1417 17.5712] +axCarB =[ 272.9356 274.2177 16.0475 16.7634]; + +AX=[axAS;axPalau;axSP;axCP;axGOM;axCar;axCarB] +[nax,four]=size(AX) + +if isplot, + close all + clf; + plot(p0.x,p0.y,'b.',p1.x,p1.y,'r.'); + axis equal; + hold on + for k=1:nax + ax=AX(k,:); + BoundingBox(ax(1:2),ax(3:4),'c'); + end +end + +p=p1;%gshhs baseline +for k=1:nax + j0=FindPointsAx(AX(k,:),p0.x,p0.y); + j=FindPointsAx(AX(k,:),p.x,p.y); + p0a=subpslgFast(p0,j0); + nn=length(p.x); + k=setdiff(1:nn,j); + p=subpslgFast(p,k);%remove gshhs features in box + p0a=subpslgFast(p0,j0);%get OSM features in box + p=joinpslg(p,p0a);%add OSM features to remaining gshhs +end + +pslg=p; +save pslgOSMxGSHHS.BOXES.mat pslg + +geom=pslg2geom(pslg) + +savemsh('PSLGboundaryOSMxGSHHS.BOXES.msh',geom) + +hold on; +plot(p.x,p.y,'k.'); +title('red-gshhs, blue- OSM, black- final') diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m new file mode 100644 index 0000000..24ac5a7 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -0,0 +1,326 @@ + +outdir='RWPSMeshOSMxGSHHS.BoxesFiles/' +pslgfile='PSLGboundaryOSMxGSHHS1kmBOXES.msh' +jigsawout='RWPS.F.LLH' + +%g=loadmsh('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.msh') +g=loadmsh([outdir,jigsawout,'.msh']); + +%remove sand points on boundary +%RemoveSandPoints('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.msh','PSLGboundaryOSMxGSHHS1kmBOXES.msh',... +% 'RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.msh','RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh');%ileOutJigsawMesh,FileOutWW3) +RemoveSandPoints([outdir,jigsawout,'.msh'],pslgfile,[outdir,jigsawout,'.NSP.msh'],[outdir,jigsawout,'.NSP.WW3.msh']); + +%Add Lakes to Mesh +%g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); +g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); + +gS=loadmshWW3('../RWPSLakes/Sebago.NWPS.WW3.msh'); +gS.x=gS.x-360; +gW=loadmshWW3('../RWPSLakes/Winnipesaukee.NWPS.WW3.msh') +gW.x=gW.x-360; +gO=loadmshWW3('../RWPSLakes/Okeechobee.NWPS.WW3.msh') +gO.x=gO.x-360; + +g=CombineMesh(g,gO); +g=CombineMesh(g,gS); +g=CombineMesh(g,gW); + +x=g.x;y=g.y;z=g.z;e=g.e; +LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + +clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; +caxis([0,12]) +colormap(flip(cm)); + +WriteWW3MeshX(g,'RWPS.WW3a.lakes.msh'); + + +%clear +g=loadmshWW3('RWPS.WW3a.lakes.msh') +%Remove key islands remaining in mesh +%load PSLGboundary1kmP_NewOrleans.mat +%p=loadmsh('PSLGboundaryOSMxGSHHS1kmBOXES.msh') +p=loadmsh(pslgfile); + +p.x=p.point.coord(:,1); +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +p.x=p.x-360; +x=g.x;y=g.y;z=g.z;e=g.e; +clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;axis equal; +hold on +plot(p.x,p.y,'k.') + +MinBndDist=1000; +gnew=g; + +%go through all longitude and remove nodes +dx=1; +%close all +n=1; +if 1, + for xx=(ceil(min(g.x))+2*dx):dx:(floor(max(g.x))-2*dx) + ax11=[xx-dx,xx+dx,min(g.y)+dx,max(g.y)-dx] + N(n)=length(gnew.x); + gnew=RemoveMissingIslandsEle(gnew,ax11,p,MinBndDist,0); + n=n+1; + n/243 + length(gnew.x) + figure(3);clf;plot(N,'ko-');pause(.001) + end +end + + +g=gnew +save NoPacIslAll.mat g pslgfile p + + + + +clear +load NoPacIslAll.mat + +x=g.x;y=g.y;z=g.z;e=g.e; +LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + +clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; +caxis([0,12]) +colormap(flip(cm)); +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(pslgfile); +p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); +hold on; +plot(p.x,p.y,'k.'); +g0=g; +gnew=g +axAS =[ -179.6738 -159.5513 -18.4086 -7.1731] +%gnew=RemoveMissingIslandsEle(gnew,axAS,p,MinBndDist); +axis(axAS);pause(5) + +axTofol =[ -197.5575 -196.5479 4.8724 5.7902] +axis(axTofol);pause(5) + +axPA = [-177.6646 -175.5927 -0.2906 1.3435] +%gnew=RemoveMissingIslandsEle(gnew,axPA,p,MinBndDist); +axis(axPA);pause(5) + +axJA =[ -172.1141 -165.7656 14.1706 19.1777] +%gnew=RemoveMissingIslandsEle(gnew,axJA,p,MinBndDist); +axis(axJA);pause(5) + +axMWI =[ -179.5965 -176.0019 27.0046 29.8397] +%gnew=RemoveMissingIslandsEle(gnew,axMWI,p,MinBndDist); +axis(axMWI);pause(5) + +axTin=[-215.1401 -213.4623 14.3922 15.7155] +%gnew=RemoveMissingIslandsEle(gnew,axTin,p,MinBndDist); +axis(axTin);pause(5) + +axNNMI =[ -215.9834 -213.8052 19.3525 21.0704]; +%gnew=RemoveMissingIslandsEle(gnew,axNNMI,p,MinBndDist); +axis(axNNMI);pause(5) + +axNNMI1=[-214.8924 -213.6875 14.6480 15.5983]; +%gnew=RemoveMissingIslandsEle(gnew,axNNMI1,p,MinBndDist); +axis(axNNMI1);pause(5) + +axMaj =[ -177.2629 -175.7651 -0.1340 1.0474] +%gnew=RemoveMissingIslandsEle(gnew,axMaj,p,MinBndDist); +axis(axMaj);pause(5) + +axHI =[ -179.1073 -153.7595 11.4935 31.4855] +%gnew=RemoveMissingIslandsEle(gnew,axHI,p,MinBndDist); +axis(axHI);pause(5) + +axChuuk =[ -198.1190 -196.0417 4.7967 5.8354] +%gnew=RemoveMissingIslandsEle(gnew,axChuuk,p,MinBndDist); +axis(axChuuk);pause(5) + +WriteWW3MeshX(gnew,'RWPS.WW3b.lakes.msh') %Fails + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%fix new orleans +clear +g=loadmshWW3('RWPS.WW3b.lakes.msh') +x=g.x;y=g.y;z=g.z;e=g.e; +LS=ComputeLengthScale_wgs84_MEL(x,y,e); +LSn=Ele2Nodes(x,y,e,LS); +clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; +colormap(flip(cm)); +caxis([0,12]); + +S=shaperead('../NewOrleansCoast/mz03mr26_LIX.shp') +hold on +for k=1:length(S),plot(S(k).X,S(k).Y,'k');end + +axNOZ =[ -91.6701 -87.7499 28.7284 30.9173] +axis(axNOZ) +gnew=g; +%if nescesary run: +display('enter 1 if you want to edit the mesh around New Orleans' ) +gnew=RemoveMeshParts(g,axNOZ,S,[0,50]); + +WriteWW3MeshX(gnew,'RWPS.WW3c.lakes.msh') +%confirm no introduction of sand points +g=RemoveSandPointsWW3(gnew,'RWPS.WW3d.lakes.msh') +WriteWW3MeshX(g,'RWPS.WW3d.lakes.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Fix boundary warping from projection in mesh generation +clear +g=loadmshWW3('RWPS.WW3d.lakes.msh') +Blon=[129.91 10.71] +Blat=[-30.42 79.99] +Blon(1)=Blon(1)-360 +x=g.x;y=g.y;z=g.z;e=g.e; +jb=g.bnd; + +clf; +plot(g.x(jb),g.y(jb),'k.');hold on +js=find(g.y(jb)max(Blat)); +g.y(jb(js))=max(Blat); +plot(g.x(jb(js)),g.y(jb(js)),'r.') + +dx=.5; +js=find(and( g.x(jb)>min(Blon),g.x(jb)max(Blon)-dx )); +g.x(jb(js))=max(Blon); +plot(g.x(jb(js)),g.y(jb(js)),'r.') +WriteWW3MeshX(g,'RWPS.WW3e.lakes.msh') +%confirm no introduction of sand points +g0=RemoveSandPointsWW3(g,'RWPS.WW3f.lakes.msh') + +WriteWW3MeshX(g0,'RWPS.WW3g.lakes.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Some Plotting + + + +clear +g=loadmshWW3('RWPS.WW3g.lakes.msh')%RWPS.PIXAllLnwps.PP.WW3c.msh'); +x=g.x;y=g.y;z=g.z;e=g.e; +LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); +clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; +jb=g.bnd; +hold on; +plot(g.x(jb),g.y(jb),'k.');hold on + + +f=z; +clf;patch(x(e'),y(e'),f(e'));cm=colormap('jet');shading interp;axis equal; +colormap(flip(cm)); +caxis([0,6000]); +kprint('Bathy.jpg'); + +clf; + caxis([0,6000]); +colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + %hcb.Label.String='(km)' + set(gca,'visible','off') +kprint('BathyColorbarH.jpg'); + +clf; +colorbar; +colormap(flip(cm)); +caxis([0,6000]); +kprint('BathyColorbarV.jpg'); + + +LS=ComputeLengthScale_wgs84_MEL(x,y,e); +LSn=Ele2Nodes(x,y,e,LS); + +clf;patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; +colormap(flip(cm)); +caxis([0,12]); +kprint('Lengthscale.jpg'); + + +axCAR =[ -85.4065 -61.7227 8.8200 26.8661] +ax=axCAR +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('Caribean.jpg') + + +axAK =[ -192.1450 -152.2804 47.2479 77.6231] +ax=axAK +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('Alaska.jpg') + +axHI =[ -179.5950 -152.9066 13.8641 34.1996] +ax=axHI +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('Hawaii.jpg') + + +axMI =[ -220.2161 -208.6314 12.5003 21.3274]; +ax=axMI +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('MarianaIslands.jpg') + +axAS =[ -173.3623 -168.3684 -16.4846 -12.0090] +ax=axAS +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('AmericanSamoa.jpg') + + +axMicro =[ -210.3818 -185.8701 -3.7494 15.5832] +ax=axMicro +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('Micronesia.jpg') + +axWMicro =[ -226.6896 -214.3594 5.3753 15.1002] +ax=axWMicro +axis(ax);daspect([1,cos(pi*ax(3)/180),1]) +kprint('WestMicronesia.jpg') + + +figure; +clf; + caxis([0,12]); +colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(km)' + set(gca,'visible','off') +kprint('LengthScaleColorbarH.jpg'); + +clf + caxis([0,12]); +colormap(flip(cm)); + + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(km)' + set(gca,'visible','off') +kprint('LengthScaleColorbarV.jpg'); + + +clf +caxis([0,6000]); +colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(m)' + set(gca,'visible','off') +kprint('BathyColorbarH.jpg'); + +clf + caxis([0,6000]); +colormap(flip(cm)); + + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(m)' + set(gca,'visible','off') +kprint('BathyColorbarV.jpg'); +qi= \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py new file mode 100644 index 0000000..6b5c853 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py @@ -0,0 +1,256 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- +PSLGFile="GlobalCoastlineOSM.PSLG.msh" +DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" +TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" + +PSLGFile="PSLGboundaryGSHHS.msh" +DistanceToCoastFile="GlobalCoastlineGSHHS.PSLG.msh" +TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" + +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="Topo.DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" + +# directory to write output files to +OutDir='testOSMxGSHHS.BOXES/' + +ww3_mesh_file='RWPS.OSMxGSHHS.BOXES.msh' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=10000. +d1=320000. - d0 +beta=1000. +Smin=0.5 +Smax=10. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "aust.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m new file mode 100644 index 0000000..11ab45a --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m @@ -0,0 +1,69 @@ +function geom=BoundaryShape2msh(S,flout) +% make coastlines for various smoothings of coastlines + +%from example 6 aust.msh + +%geom = +% point: [1×1 struct] +% edge2: [1×1 struct] +% mshID: 'EUCLIDEAN-MESH' +% fileV: 3 + +%geom.point.coord(1:10,:) +% 146.2929 -39.0150 0 +% 146.2937 -39.0192 0 +% 146.2846 -39.0242 0 + +%geom.edge2.index(1:10,:) +% 1 2 0 +% 1 27577 0 +% 2 3 0 + +%1km +clear geom +geom.mshID='EUCLIDEAN-MESH' +geom.fileV = 3 +if isstr(S) + S = shaperead(S); +end + +N=length(S); +x0=[]; +y0=[]; +edge0=[]; +for k=1:N + if mod(k,100)==0,k/N,end + x=S(k).X(1:end-1); + y=S(k).Y(1:end-1); + if ~isempty(x) + isisland=0; + if and( x(1)==x(end),y(1)==y(end) ) + isisland=1; + end + if length(x)>1, + if ~isisland, + n0=length(x0); + x0=[x0;x(:)]; + y0=[y0;y(:)]; + n1=length(x0); + edge0=[edge0;[ n0+1:n1-1;n0+2:n1]' ]; + else + n0=length(x0); + x=x(1:end-1); + y=y(1:end-1); + x0=[x0;x(:)]; + y0=[y0;y(:)]; + n1=length(x0); + edge0=[edge0;[ n0+1:n1-1;n0+2:n1]';[n1,n0+1]]; + end + end + end +end + +[ne,two]=size(edge0); +nn=length(x0); +geom.edge2.index=[edge0,zeros(ne,1)]; +geom.point.coord=[x0(:),y0(:),zeros(nn,1)]; + +savemsh(flout,geom); + \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m new file mode 100644 index 0000000..d9386b8 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m @@ -0,0 +1,11 @@ +function h=BoundingBox(x,y,c); +if nargin<3,c='k';end +x0=min(min(x)); +y0=min(min(y)); +x1=max(max(x)); +y1=max(max(y)); + +hold on; +h=plot([x0,x1,x1,x1,x0,x0],... + [y0,y0,y1,y1,y1,y0],c); + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m new file mode 100644 index 0000000..3831582 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m @@ -0,0 +1,33 @@ +function topo=BoxSmoothTopo(fl,k) + +lon=ncread(fl,'lon'); +lat=ncread(fl,'lat'); +z=ncread(fl,'bed_elevation'); + +lon=[lon(1:end-1)+lon(2:end)]/2; +lat=[lat(1:end-1)+lat(2:end)]/2; +if k==0, + topo.point.coord{:,1}=lon; + topo.point.coord{:,2}=lat;%fix to centers later + topo.value=double(z'); + + topo.mshID='ELLIPSOID-GRID' + topo.fileV=3; + +else + + n=2*k+1; + w=ones(n,n)/n/n; + [nx,ny] = size(z) + zw=conv2(z,w,'same'); + zw=zw(k+1:n:nx-k,k+1:n:ny-k); + lonw=lon(k+1:n:nx-k); + latw=lat(k+1:n:ny-k); + + topo.point.coord{:,1}=lonw; + topo.point.coord{:,2}=latw;%fix to centers later + topo.value=double(zw'); + + topo.mshID='ELLIPSOID-GRID' + topo.fileV=3; +end \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m new file mode 100644 index 0000000..fe69089 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -0,0 +1,348 @@ +function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +%CoastLineFile = 'GlobalCoastlineOSM.shp' +%CoastLineFile = 'GlobalCoastlineGSHHS.shp' +%lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +%run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) + +S=shaperead(CoastLineFile) +FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] +isplot=0; + +%load GlobalCoastlineOSM.mat + + +%The overall objective of this project is to develop and implement into operations +% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, +% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, +% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the +% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. + +%Blon=[129.91 10.71]; +%Blat=[-30.42 79.99]; +Blon=[lonWest, lonEast]; +Blat=[latSouth,latNorth]; + + +N=length(S); +N1=N; +for k=1:N + if mod(k,1000)==0,k/N,end + lon=S(k).X(1:end-1);%remove trailing nan + lat=S(k).Y(1:end-1); + ns(k)=length(lon); + jWest=find(lon<90); + if(length(jWest)==ns(k)); + S(k).X=[lon+360,NaN]; + end + if and(0length(jWest)),%make translated copy + display(['duplicating coastal segment: ',int2str(k), ', nseg=',int2str(ns(k))]) + N1=N1+1; + S(N1).X=[lon+360,NaN]; + S(N1).Y=[lat,NaN]; + ns(N1)=length(lon); + end +end +N=length(S); +[tmp,j]=sort(-ns); +S=S(j);% sort to descending in length +ns=ns(j);% sort to descending in length + +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; + +%Make Bounding rectangle +Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +clear pslg +sxp=[];syp=[ ]; +xc=[];yc=[]; +N=length(S); +pslg.x=[]; +pslg.y=[]; +pslg.edges=[]; +nc=0; + +minedeges=4 +minarea=1 + +earth=referenceSphere('Earth'); +DXM=10^10;%DXM=1 +mdx=inf+ones(N,1); +for k=1:N + isinbox(k)=0; + x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) + y=S(k).Y(1:end-1); + mx=mean(x); + my=mean(y); + if length(x)>minedeges, + ji=find( insidepoly( x,y,Bx,By ) ); + if length(ji)>2 + [xi, yi,ii] = polyxpoly(x, y, Bx, By); + xc=[xc;xi(:)]; + yc=[yc;yi(:)]; + if ~isempty(xi) %modify ob + sxp=[sxp,x(1)];syp=[syp,y(1)]; + [iia,jja]=sort(ii(:,1));%sort to ascending order along segments + xia=xi(jja); + yia=yi(jja); + iis=ii(jja,1);%sorted into ascending order along segments + if ~insidepoly( x(1),y(1),Bx,By )% segment origonates outside box + nseg=length(xia); + for j=1:2:nseg-1, + xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; + ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + mdx(k)=max(dx); + + if max(dx) island entirely inside bounding box + xs=[x(1:end-1)]; + ys=[y(1:end-1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + if and(length(xs)>2,max(dx)3, ar> + if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end +end + +%OK - now revisit outer boundary! +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%restart script from here if needed +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%clear +%close all +eval(['load ',FileOutMatlab]); +%load pslgOSM.mat +%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +%make outer bound +n=length(pslg.x); +%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes +%pslg.y=[pslg.y,By(3:4)]; +pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes +pslg.y=[pslg.y,By(2:4)]; + +nc=length(pslg.chains);%add northwest and north east box corner chains +pslg.chains(nc+1).nodes=n+1; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+2; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+3; +nc=length(pslg.chains); + +xx =153.0400 %south east corner of Austrilia +yy = Blat(1) %check that these are the endpoints described for j0, j1!! +[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end + +xx = 288.3143%check that these are the endpoints described for j0, j1!! +yy = Blat(1) %south west corner of S. America +[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end + +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=[j0,j1]; +nc=length(pslg.chains); + +for k=1:nc + if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end + spx(k)=pslg.x(pslg.chains(k).nodes(1)); + spy(k)=pslg.y(pslg.chains(k).nodes(1)); + epx(k)=pslg.x(pslg.chains(k).nodes(end)); + epy(k)=pslg.y(pslg.chains(k).nodes(end)); + end + +%make boundary order index along boundary for start points +SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges +c=0*spy; +Deps1=10^-10 +j=find(abs(spy-By(1))v); +[mm,m]=min(c(j)); +l=j(m); +epi=[epi,pslg.chains(l).nodes]; +obc=[obc,l]; +n=0; +%while(epi(end)~=epi(1)) +while isempty( find(epi(2:end)==epi(1)) ) + v=d(l); + j=find(c>v); + [mm,m]=min(c(j)); + l=j(m) + epi=[epi,pslg.chains(l).nodes]; + obc=[obc,l]; + if isplot==1, plot(pslg.x(epi),pslg.y(epi),'r.-');pause(.001);end +end +j=find(epi(2:end)==epi(1)); +epi=epi(1:(j+1)); +%vvvvvvvvvvv Add fixed grid points on open boundary +% to prevent "curved" boundaries due to projection details +xob=pslg.x(epi); +yob=pslg.y(epi); +dob=abs([xob(2:end)-xob(1:end-1)]+i*[yob(2:end)-yob(1:end-1)]); +dob=[dob,abs([xob(end)-xob(1)]+i*[yob(1)-yob(end)])]; +nb=length(xob); +dmin=1;%node spacing around boundary +epit=epi; +for k=1:nb-1 + d=abs([xob(k+1)-xob(k)]+i*[yob(k+1)-yob(k)]); + if d>dmin + npl=round(d/dmin)-1; + dx=xob(k+1)-xob(k); + dy=yob(k+1)-yob(k); + xp=xob(k)+dx*[1:npl-1]/npl; + yp=yob(k)+dy*[1:npl-1]/npl; + np=length(xp); + n=length(pslg.x); + pslg.x=[pslg.x,xp]; + pslg.y=[pslg.y,yp]; + NewEdges=[[epi(k),n+1];[[n+1:n+np-1]',[n+2:n+np]'];[n+np,epi(k+1)]]; + %pslg.edges=[pslg.edges;NewEdges]; + j=find(epi(k)==epit ); + epit=[epit(1:j),n+1:n+np,epit(j+1:end)]; + end +end +epi=epit; +% to prevent "curved" boundaries due to projection details +%^^^^^^^^^^^^ Add fixed grid points on open boundary + + +% add edges in obc +epiv=epi(:); +NOE=length(epiv) +OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; +pslg.edges=[pslg.edges;OutterEdges]; + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +nodelist=[]; +for k=1:nc + if mod(k,100)==0,disp(['Finding interior chains compleate: ',num2str(k/nc)]);,end + if pslg.chains(k).nodes(1)==pslg.chains(k).nodes(end) + n=pslg.chains(k).nodes(1); + [inpoly,onpoly]=insidepoly( pslg.x(n), pslg.y(n),xob,yob); + if and(inpoly==1,onpoly==0) + nodelist=union(nodelist,pslg.chains(k).nodes); + end + end +end + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi']); + +nodelistXB=union(nodelist,epi); +pslgb=subpslgFast(pslg,nodelistXB); + +%remove "random" duplicate nodes +%z=pslgb.x+i*pslgb.y; +%[zu,j,k]=unique(z); +%pslgc=subpslgFast(pslgb,j); +pslgc=pslgb + +%remove duplicate edges +pslgc.edgesS=sort(pslgc.edges')'; +pslgc.edgesSU=unique(pslgc.edgesS,'rows') +pslgc.edges=pslgc.edgesSU; + +pslg=pslgc + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%save PSLG to jigsaw .msh format +geom=pslg2geom(pslg) +savemsh(FileOutJigsaw,geom) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m new file mode 100644 index 0000000..3c67bf1 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m @@ -0,0 +1,18 @@ +function g=CombineMesh(g0,g1); + +nn=length(g0.x); +g.x=[g0.x(:);g1.x(:)]; +g.y=[g0.y(:);g1.y(:)]; +g.z=[g0.z(:);g1.z(:)]; +g.e=[g0.e;nn+g1.e]; + +if isfield(g0,'bnd') + if isfield(g1,'bnd') + g.bnd=[g0.bnd;g1.bnd+nn]; + else + g.bnd=g0.bnd + end +else + g.bnd=[]; +end + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m new file mode 100644 index 0000000..87d53a8 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m @@ -0,0 +1,3 @@ + +function Ac=ComputeAdjacency(e) +[Ac,GR] = groupcounts(e(:)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m new file mode 100644 index 0000000..1a60a73 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m @@ -0,0 +1,31 @@ +function a=ComputeLengthScaleX(x,y,e) +%function ComputeLengthScale(x,y,e) +% Input: +% x -lon [nn x 1] +% y -lat [nn x 1] +% e -element list[ ne x 3] +% +% Output: +% lengthscale [ne x 1] lengthscale of element in m based on +EqTrC=4/sqrt(3); +[ne,three]=size(e) +lengthscale=zeros(1,ne); +%parfor k=1:ne +wgs84 = wgs84Ellipsoid("km"); +n=length(x); +xp=x; +yp=y; +xp(n+1)=NaN; +yp(n+1)=NaN; +[ne,three]=size(e) +eP=[e(:,1:3),n+1+zeros(ne,1)]; +Xp=xp(eP)'; +Yp=yp(eP)'; +t0=now +clear a +a = areaint(Yp(:),Xp(:),wgs84); +t1=now; +60*24*(t1-t0) +et=60*24*(t1-t0); +disp([' total time : ',num2str(et),' min']); +lengthscale=sqrt(a*EqTrC); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m new file mode 100644 index 0000000..a0856a4 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m @@ -0,0 +1,32 @@ +function lengthscale_wgs84=ComputeLengthScale_wgs84_area(x,y,e) +%function ComputeLengthScale(x,y,e) +% Input: +% x -lon [nn x 1] +% y -lat [nn x 1] +% e -element list[ ne x 3] +% +% Output: +% lengthscale [ne x 1] lengthscale of element in m based on +% element area assuming equilateral + +EqTrC=4/sqrt(3); +[ne,three]=size(e) +lengthscale=zeros(1,ne); +wgs84 = wgs84Ellipsoid("km"); +n=length(x); +xp=x; +yp=y; +xp(n+1)=NaN; +yp(n+1)=NaN; +[ne,three]=size(e) +eP=[e(:,1:3),n+1+zeros(ne,1)]; +Xp=xp(eP)'; +Yp=yp(eP)'; +t0=now +clear a +a = areaint(Yp(:),Xp(:),wgs84); +t1=now; +60*24*(t1-t0) +et=60*24*(t1-t0); +disp([' total time : ',num2str(et),' min']); +lengthscale_wgs84=sqrt(a*EqTrC); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m new file mode 100644 index 0000000..9643cf9 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m @@ -0,0 +1,31 @@ +function lengthscale_wgs84_MEL=ComputeLengthScale_wgs84_MEL(x,y,e) +%function ComputeLengthScale(x,y,e) +% Input: +% x -lon [nn x 1] +% y -lat [nn x 1] +% e -element list[ ne x 3] +% +% Output: +% lengthscale [ne x 1] lengthscale of element in km, +% defined by mean side length +mthd=1 + +x1=x(e(:,1));y1=y(e(:,1)); +x2=x(e(:,2));y2=y(e(:,2)); +x3=x(e(:,3));y3=y(e(:,3)); + +if mthd==1 + wgs84 = wgs84Ellipsoid("km"); + D3 = distance([y1,x1],[y2,x2],wgs84); + D1 = distance([y2,x2],[y3,x3],wgs84); + D2 = distance([y3,x3],[y1,x1],wgs84); + lengthscale_wgs84_MEL=[D1+D2+D3]/3;% mean edge length + % lengthscale_wgs84_MEL=min(min(D1,D2),D3);% shortest edge +else + R=6378.100 %radius of earth in km + D03 = distance([y1,x1],[y2,x2],'degrees'); + D01 = distance([y2,x2],[y3,x3],'degrees'); + D02 = distance([y3,x3],[y1,x1],'degrees'); + D0=[D01+D02+D03]/3; + lengthscale_wgs84_MEL=R*sin(D0*pi/180); +end \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m new file mode 100644 index 0000000..8c4f861 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m @@ -0,0 +1,139 @@ +function gx=ConnectDisjointMesh(g,g0,flout,N) +%function ConnectDisjointPSLGs(flin1,flin2,flout) +% Join 2 PSLGs together with shortest lines. +% flin1= PSLG saved in jigsaw "geom" format (big pslg) +% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) +% flout= where to save joined PSLG +Smin=500; + +g=loadmsh('RWPSMeshFilesPIXNO/RWPS.F.LLH.msh') +g.x=g.point.coord(:,1);g.y=g.point.coord(:,2);g.z=g.point.coord(:,3);g.e=g.tria3.index(:,1:3); +g0=loadmsh('../RWPSLakes/RWPS.Sebago.msh') +g0.x=g0.point.coord(:,1);g0.y=g0.point.coord(:,2);g0.z=g0.point.coord(:,3);g0.e=g0.tria3.index(:,1:3); + + +bnd=detbndy(g.e); +bndu=unique(bnd); + +xb=g.x(bndu); +yb=g.y(bndu); + +bnd0=detbndy(g0.e); +bndu0=unique(bnd0); +xb0=g0.x(bndu0); +yb0=g0.y(bndu0); + + +lon2m=111320. +lat2m=110574. +clear D J +for k=1:length(bndu0) + [D(k),J(k)]=min(abs( lon2m*cos(pi*yb0(k)/180).*(xb0(k)-xb) + i*lat2m*[yb0(k)-yb] ) ); +end +[D0,k0]=min(D);%closest node lake +k=J(k0);%closest node global + +Nseg=round(D0/Smin) +n0=bndu0(k0) +n=bndu(k) + +j0=find(bnd0(:,1)==n0); +m0=bnd0(j0,2); +j=find(bnd(:,1)==n); +m=bnd(j,2); + +xng=g.x(n); +yng=g.y(n); +xng=g.x(n); +yng=g.y(n); +xp=g.x(n)+(g0.x(n0)-g.x(n))*(1:Nseg-1)/(Nseg); +yp=g.y(n)+(g0.y(n0)-g.y(n))*(1:Nseg-1)/(Nseg); + +xq=g.x(m)+(g0.x(m0)-g.x(m))*(1:Nseg-1)/(Nseg); +yq=g.y(m)+(g0.y(m0)-g.y(m))*(1:Nseg-1)/(Nseg); +clf;plot(xb,yb,'k.',xb0,yb0,'b.',xp,yp,'r.',xq,yq,'c.') + +g1.x=[g.x(:);g0.x(:)]; +g1.y=[g.y(:);g0.y(:)]; +g1.e=[g.e;length(g.x)+g0.e]; + +Nj=length(g1.x); +[NE,three]=size(g1.e); +g1.x=[g1.x(:);xp]; +g1.y=[g1.y(:);yp]; +Np=length(g1.x); +g1.x=[g1.x(:);xq]; +g1.y=[g1.y(:);yq]; +Nq=length(g1.x); + + + + + +[ils,jls]=find(ps.edges==ks); +ksN=ps.edges(ils,:); +ksNu=unique(ksN); +ksNux=setdiff(ksNu,ks); +[ne,two]=size(ps.edges); +ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node + +[ilg,jlg]=find(pg.edges==kg); +kgN=pg.edges(ilg,:); +kgNu=unique(kgN); +kgNux=setdiff(kgNu,kg); +[ne,two]=size(pg.edges); +pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node + + +for k=1:length(bndu0) + D(k)=min(abs) + + +pg=loadmsh(flin1) +pg.x=pg.point.coord(:,1); +pg.y=pg.point.coord(:,2); +pg.edges=pg.edge2.index(:,1:2); + +ps=loadmsh(flin2); +ps.x=ps.point.coord(:,1)+360; +ps.y=ps.point.coord(:,2); +ps.edges=ps.edge2.index(:,1:2); + +lon2m=111320. +lat2m=110574. +clear D +for k=1:length(ps.x) + D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); +end +[ms,ks]=min(D); +[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); +%find neighbors of ks + +[ils,jls]=find(ps.edges==ks); +ksN=ps.edges(ils,:); +ksNu=unique(ksN); +ksNux=setdiff(ksNu,ks); +[ne,two]=size(ps.edges); +ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node + +[ilg,jlg]=find(pg.edges==kg); +kgN=pg.edges(ilg,:); +kgNu=unique(kgN); +kgNux=setdiff(kgNu,kg); +[ne,two]=size(pg.edges); +pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node + +nn=length(pg.x); +p=joinpslg(pg,ps); +[ne,two]=size(p.edges); +p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; +p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; + +clf +plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') +hold on; +je=ne+1:ne+2; +plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); + +geom=pslg2geom(p) +savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m new file mode 100644 index 0000000..abf979b --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m @@ -0,0 +1,54 @@ +function ConnectDisjointPSLGs(flin1,flin2,flout) +%function ConnectDisjointPSLGs(flin1,flin2,flout) +% Join 2 PSLGs together with shortest lines. +% flin1= PSLG saved in jigsaw "geom" format (big pslg) +% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) +% flout= where to save joined PSLG +pg=loadmsh(flin1) +pg.x=pg.point.coord(:,1); +pg.y=pg.point.coord(:,2); +pg.edges=pg.edge2.index(:,1:2); + +ps=loadmsh(flin2); +ps.x=ps.point.coord(:,1)+360; +ps.y=ps.point.coord(:,2); +ps.edges=ps.edge2.index(:,1:2); + +lon2m=111320. +lat2m=110574. +clear D +for k=1:length(ps.x) + D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); +end +[ms,ks]=min(D); +[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); +%find neighbors of ks + +[ils,jls]=find(ps.edges==ks); +ksN=ps.edges(ils,:); +ksNu=unique(ksN); +ksNux=setdiff(ksNu,ks); +[ne,two]=size(ps.edges); +ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node + +[ilg,jlg]=find(pg.edges==kg); +kgN=pg.edges(ilg,:); +kgNu=unique(kgN); +kgNux=setdiff(kgNu,kg); +[ne,two]=size(pg.edges); +pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node + +nn=length(pg.x); +p=joinpslg(pg,ps); +[ne,two]=size(p.edges); +p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; +p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; + +clf +plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') +hold on; +je=ne+1:ne+2; +plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); + +geom=pslg2geom(p) +savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m new file mode 100644 index 0000000..b873af1 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m @@ -0,0 +1,54 @@ +function ConnectDisjointPSLGs(flin1,flin2,flout,N) +%function ConnectDisjointPSLGs(flin1,flin2,flout) +% Join 2 PSLGs together with shortest lines. +% flin1= PSLG saved in jigsaw "geom" format (big pslg) +% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) +% flout= where to save joined PSLG +pg=loadmsh(flin1) +pg.x=pg.point.coord(:,1); +pg.y=pg.point.coord(:,2); +pg.edges=pg.edge2.index(:,1:2); + +ps=loadmsh(flin2); +ps.x=ps.point.coord(:,1)+360; +ps.y=ps.point.coord(:,2); +ps.edges=ps.edge2.index(:,1:2); + +lon2m=111320. +lat2m=110574. +clear D +for k=1:length(ps.x) + D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); +end +[ms,ks]=min(D); +[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); +%find neighbors of ks + +[ils,jls]=find(ps.edges==ks); +ksN=ps.edges(ils,:); +ksNu=unique(ksN); +ksNux=setdiff(ksNu,ks); +[ne,two]=size(ps.edges); +ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node + +[ilg,jlg]=find(pg.edges==kg); +kgN=pg.edges(ilg,:); +kgNu=unique(kgN); +kgNux=setdiff(kgNu,kg); +[ne,two]=size(pg.edges); +pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node + +nn=length(pg.x); +p=joinpslg(pg,ps); +[ne,two]=size(p.edges); +p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; +p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; + +clf +plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') +hold on; +je=ne+1:ne+2; +plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); + +geom=pslg2geom(p) +savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m new file mode 100644 index 0000000..0e22328 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m @@ -0,0 +1,54 @@ +function D=DistanceToCoast(lon,lat,lonP,latP) +%function D=DistanceToCoast(lon,lat,lonP,latP) +% Computes grided distance to pointset on Globe +% +% Computes shortest distance to pointset [lonP,latP] from coordinates of +% lat by lon grid in m. +% +% inputs: +% lon - [nx,1] lon coordinates for output matrix +% lat - [ny,1] lon coordinates for output matrix +% lonP - [nn,1] longitude coordiantes of point set +% latP - [nn,1] latitude coordiantes of point set +% +% outputs: +% D - [ny, nx] units meters +% D(j,k)= minimumt Distance from point lat(j), lon(k) to pointset (lonP,latP) +% +clear d0 +lat2m=single(110574.) +lon=single(lon); +lat=single(lat); +nx=length(lon) +ny=length(lat) +clear ld1 ld2 D; +t0=now; +LambdaBox=10;%only use points within 5 degrees lat for 10x+ speed up +latP=latP(:); +lonP=lonP(:); +for j=1:ny % this loop takes ~16 hours + t00=now; + j/ny + lon2m=single(111320.*cos(lat(j)*pi/180)); + jbox=find(abs(lat(j)-latP)sum(A(jin)), + disp(['outer boundary is: ',int2str(obj)]) + plot(x(c(obj).nodes),y(c(obj).nodes),'r.-'); +end +hold on +for k=1:length(jin) + j=jin(k); + plot(x(c(j).nodes),y(c(j).nodes),'k-') +end + +figure;ph=patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar +hold on;plot(x(c(obj).nodes),y(c(obj).nodes),'k.-'); +n=c(obj).nodes; + +%g=loadmsh('output/RWPS.F.LLH.msh') +%p=loadmsh('PSLGboundary5km_shifted.msh'); +x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); +xp=p.point.coord(:,1);yp=p.point.coord(:,2);fp=p.point.coord(:,3); + +%remove corners from boundary where they exist +eps=5000;% +eps=500;% +figure;plot(xp,yp,'k.',max(xp),min(yp),'ro',min(xp),min(yp),'ro',max(xp),max(yp),'ro',min(xp),max(yp),'ro'); +wgs84 = wgs84Ellipsoid("m"); +DSW=distance( [min(yp),min(xp)],[yp,xp],wgs84); +DSE=distance( [min(yp),max(xp)],[yp,xp],wgs84); +DNW=distance( [max(yp),min(xp)],[yp,xp],wgs84); +DNE=distance( [max(yp),max(xp)],[yp,xp],wgs84); + +jSW=find(DSWepsD); % points 3 km or more from coastline point +noo=n(joo); +figure;plot(xp-360,yp,'y.',x(n),y(n),'k.-',x(noo),y(noo),'r.') + +xmax=max(xpp)-dx +xmin=min(xpp)+dx +ymax=max(yp)-dx +ymin=min(yp)+dx + +jX=find(and( x>xmin,xymin,y1 + if(ComputeBndy) + bnd=detbndy(e);%find boundary elements including islands + jb=unique(bnd(:)) + OpenBndNodes=intersect(jb,jc); + end +end \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m new file mode 100644 index 0000000..c3c694f --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m @@ -0,0 +1,129 @@ +function OpenBndNodes=FindOuterBnd(g) + + + +e=g.tria3.index(:,1:3); +x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); + +bnd=detbndy(e); +c=edges2chains(bnd); +for k=1:length(c) + k + xc(k)=mean(x(c(k).nodes)); + yc(k)=mean(y(c(k).nodes)); + A(k)=areaint(x(c(k).nodes),y(c(k).nodes)); +end + +[m,k]=max(A); +jin=setdiff(1:length(A),k) +obj=k; +if A(obj)>sum(A(jin)), + disp(['outer boundary is: ',int2str(obj)]) + plot(x(c(obj).nodes),y(c(obj).nodes),'r.-'); +end +hold on +for k=1:length(jin) + j=jin(k); + plot(x(c(j).nodes),y(c(j).nodes),'k-') +end + +figure;ph=patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar +hold on;plot(x(c(obj).nodes),y(c(obj).nodes),'k.-'); +n=c(obj).nodes; + +g=loadmsh('output/RWPS.F.LLH.msh') +p=loadmsh('PSLGboundary5km_shifted.msh'); +x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); +xp=p.point.coord(:,1);yp=p.point.coord(:,2);fp=p.point.coord(:,3); + +%remove corners from boundary where they exist +eps=5000;% +figure;plot(xp,yp,'k.',max(xp),min(yp),'ro',min(xp),min(yp),'ro',max(xp),max(yp),'ro',min(xp),max(yp),'ro'); +wgs84 = wgs84Ellipsoid("m"); +DSW=distance( [min(yp),min(xp)],[yp,xp],wgs84); +DSE=distance( [min(yp),max(xp)],[yp,xp],wgs84); +DNW=distance( [max(yp),min(xp)],[yp,xp],wgs84); +DNE=distance( [max(yp),max(xp)],[yp,xp],wgs84); + +jSW=find(DSWepsD); % points 3 km or more from coastline point +noo=n(joo); +figure;plot(xp-360,yp,'y.',x(n),y(n),'k.-',x(noo),y(noo),'r.') + +xmax=max(xpp)-dx +xmin=min(xpp)+dx +ymax=max(yp)-dx +ymin=min(yp)+dx + +jX=find(and( x>xmin,xymin,y1 + if(ComputeBndy) + bnd=detbndy(e);%find boundary elements including islands + jb=unique(bnd(:)) + OpenBndNodes=intersect(jb,jc); + end +end \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m new file mode 100644 index 0000000..fb4fecf --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m @@ -0,0 +1,4 @@ +function j=FindPointsAx(ax,x,y); +jx=find(and(x>ax(1),xax(3),yax(1),g.xax(3),g.yax(1),p.xax(3),p.ydmin); +z=z(j); +d=d(j); +if length(d)3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; +xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; + +if isplot, + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +p.x=p.point.coord(:,1)-360; +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +j=find(xus>90); +xus(j)=xus(j)-360; + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; +yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; +j=find(xx>90); +xx(j)=xx(j)-360; +plot(xx,yy,'c.'); + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m new file mode 100644 index 0000000..cade447 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m @@ -0,0 +1,64 @@ + + +%OSMmsh='./PSLGboundary1kmP_NewOrleans.OSM.msh' +%GSHHGmsh='./PSLGboundary1kmP_NewOrleansB.msh' +isplot=0 +OSMmsh='./GlobalCoastlineOSM.PSLG.msh' +GSHHGmsh='./GlobalCoastlineGSHHS.PSLG.msh' +p0=loadmsh(OSMmsh) +p1=loadmsh(GSHHGmsh) + +p0.x=p0.point.coord(:,1); +p0.y=p0.point.coord(:,2); +p0.edges=p0.edge2.index(:,1:2); + + +p1.x=p1.point.coord(:,1); +p1.y=p1.point.coord(:,2); +p1.edges=p1.edge2.index(:,1:2); + +axAS = [183.0293 191.6089 -24.5496 -11.9295] +axPalau =[ 130.8368 141.8230 3.9914 10.1256] +axSP =[ 211.0219 220.1817 -18.9565 -13.8421] +axCP =[ 151.1962 152.3336 6.9451 7.5801] +axGOM =[ 290.8507 291.1934 43.7119 43.9032] +axCar =[ 272.0041 272.7733 17.1417 17.5712] +axCarB =[ 272.9356 274.2177 16.0475 16.7634]; + +AX=[axAS;axPalau;axSP;axCP;axGOM;axCar;axCarB] +[nax,four]=size(AX) + +if isplot, + close all + clf; + plot(p0.x,p0.y,'b.',p1.x,p1.y,'r.'); + axis equal; + hold on + for k=1:nax + ax=AX(k,:); + BoundingBox(ax(1:2),ax(3:4),'c'); + end +end + +p=p1;%gshhs baseline +for k=1:nax + j0=FindPointsAx(AX(k,:),p0.x,p0.y); + j=FindPointsAx(AX(k,:),p.x,p.y); + p0a=subpslgFast(p0,j0); + nn=length(p.x); + k=setdiff(1:nn,j); + p=subpslgFast(p,k);%remove gshhs features in box + p0a=subpslgFast(p0,j0);%get OSM features in box + p=joinpslg(p,p0a);%add OSM features to remaining gshhs +end + +pslg=p; +save pslgOSMxGSHHS.BOXES.mat pslg + +geom=pslg2geom(pslg) + +savemsh('PSLGboundaryOSMxGSHHS.BOXES.msh',geom) + +hold on; +plot(p.x,p.y,'k.'); +title('red-gshhs, blue- OSM, black- final') diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/PlotMeshResSCRIPT.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/PlotMeshResSCRIPT.m new file mode 100644 index 0000000..177b8df --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/PlotMeshResSCRIPT.m @@ -0,0 +1,64 @@ + + +mesh= loadmsh('mesh_mixed_coastline_planar_ocean.msh'); +Elm=compute_area_Ell(mesh) +h=PatchGlobalE(mesh,Elm/1000); + + caxis([0,20]); + colorbar + axis([-180,180,-80,80]); + title('edge length (km)'); + colormap(jet(20)) + kprint('EdgeLengthGlobal.jpg') +hold on + +if(0) + S=shaperead('GlobalCoastline1kmUSto15km.shp'); + N=length(S); + xt=[]; + yt=[]; + for k=1:N + x=S(k).X; + y=S(k).Y; + xt=[xt;x(:)]; + yt=[yt;y(:)]; + if mod(k,1000)==0,k/N,end + end + clear S + save -v7.3 CoastVec1kmUSto15km.mat xt yt +else + load CoastVec1kmUSto15km.mat +end +nms={'CapeCod', 'MidAtlantic', 'OlympicP','Hawaii','Spain'} +flon = [-70.6,-75,-123.5,-155.6 -2.2] ; +flat = [41.6,38.7,47.6, 20, 41.4]; +title('edge length (km)') +dx=[.25,.5,.5,.5,5] +jnan=find(isnan(xt+yt)); +lx=[10,20,20,20,50] +cx=[1.5,1.5,1,1.5,30] +for k=1:5, + dx0=dx(k) + ax=[flon(k)-dx0,flon(k)+dx0,flat(k)-dx0,flat(k)+dx0]; + axis(ax); + set(h,'EdgeAlpha',.1); set(h,'EdgeColor','k'); + legx=ax(1)+dx0/10; + legy=ax(4)-dx0/10; + [ux,uy,zn]=ll2utm(legy,legx); + [legy5,legx5]=utm2ll(ux+lx(k)*1000,uy,zn); + hl=plot([legx,legx5],[legy,legy5],'ro-') + ht=text([legx+legx5]/2,legy-.05,[int2str(lx(k)),' km']) + jx=find(and( xtax(1))); + jy=find(and( ytax(3))); + j=intersect(jx,jy); + j=union(j,jnan); + + hold on + plot(xt(j),yt(j),'k-'); + title([nms{k},' edge length (km)']); + caxis([0,cx(k)]); + colormap(jet(20)); + daspect([1,cos(flat(k)*pi/180),1]) + kprint([nms{k},'EdgeLengthGlobal.jpg']); +end + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m new file mode 100644 index 0000000..5902e9f --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m @@ -0,0 +1,80 @@ +function gnew=RemoveMeshParts(g,ax,S,ca); +%function gnew=HandEditMesh(g,ax,p); +% Remove parts of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. The +% frame work is intended to expand to moving nodes, removing elements, etc +%This wont touch nodes within MinBndDist (m) of existing boundary + +jx=find(and(g.x>ax(1),g.xax(3),g.yx0;g0.x(:)'y0;g0.y(:)'0, + hold on;plot(x(deadnodes),y(deadnodes),'ko',x(deadnodes),y(deadnodes),'kx'); + title('Yo! nodes now exist with no elements! Fix with remove_dead_nodes'); +end + +set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); +axis(ax) +whos jg rmi +max(rmi) +jb=jg(rmi); +nn=length(g.x); +gnew=submeshFast(g,setdiff(1:nn,jb)); + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m new file mode 100644 index 0000000..6ce6bb9 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m @@ -0,0 +1,80 @@ +function gnew=RemoveMissingIslands(g,ax,p,MinBndDist,isplot); +%function gnew=HandEditMesh(g,ax,p); +% Remove parts of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. The +% frame work is intended to expand to moving nodes, removing elements, etc +%This wont touch nodes within MinBndDist (m) of existing boundary +if nargin<4 + MinBndDist=1000; +end +if nargin <5, + isplot=0; +end +jx=find(and(g.x>ax(1),g.xax(3),g.yax(1),p.xax(3),p.y2, + if n(1)==n(end), + jins=find(inside(x,y,p0.x(n),p0.y(n))); + jb0=[jb0;jins(:)]; + end + end +end + +lat2m=110574.; +lon2m=111320.; + +jb0X=[]; +for k=1:length(jb0); + n=jb0(k); + + d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... + i*lat2m*( y(n)-yb ) )); + if d>MinBndDist,jb0X=[jb0X,n];end +end +jb0=jb0X; + +if isplot, + hold on + plot(x(jb0),y(jb0),'ro'); +end + nn=length(x); +jg0=setdiff(1:nn,jb0); +g1=submeshFast(g0,jg0); + +if isplot, + figure; + x=g1.x;y=g1.y;z=g1.z;e=g1.e; + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; + hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); + set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); +end +jb=jg(jb0); +nn=length(g.x); +gnew=submeshFast(g,setdiff(1:nn,jb)); + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m new file mode 100644 index 0000000..45d69f4 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m @@ -0,0 +1,93 @@ +function gnew=RemoveMissingIslandsEle(g,ax,p,MinBndDist,isplot); + +% Remove parts of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. The +% frame work is intended to expand to moving nodes, removing elements, etc +%This wont touch nodes within MinBndDist (m) of existing boundary +if nargin<4 + MinBndDist=1000; +end +if nargin <5, + isplot=0; +end +jx=find(and(g.x>ax(1),g.xax(3),g.yax(1),p.xax(3),p.y2, + if n(1)==n(end), + %jins=find(inside(x,y,p0.x(n),p0.y(n))); + jins=find(inside(x,y,p0.x(n),p0.y(n))==1); + jb0=[jb0;jins(:)]; + IsClosed(k)=1; + hold on;plot(p0.x(n),p0.y(n),'gx-') + end + end +end + +lat2m=110574.; +lon2m=111320.; + +jb0X=[]; +for k=1:length(jb0); + n=jb0(k); + + d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... + i*lat2m*( y(n)-yb ) )); + if d>MinBndDist,jb0X=[jb0X,n];end +end +jb0=jb0X; + +if isplot, + hold on + plot(x(jb0),y(jb0),'ro'); +end + +[g1,kr0]=submeshFastEle(g0,jb0); + +if isplot, + figure(2); + x=g1.x;y=g1.y;z=g1.z;e=g1.e; + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; + hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); + set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); +end +%jb=jg(jb0); +kr1=intersect(kr0,jb0);% kr0 can have boundary nodes not intended for removal!! +if isplot, + figure(2); + XE=g0.x(kr1); + YE=g0.y(kr1); + plot(XE,YE,'md') + figure(1);hold on;plot(XE,YE,'md') +end +jb=jg(kr1); +nn=length(g.x); +gnew=submeshFast(g,setdiff(1:nn,jb)); %only removes nodes + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m new file mode 100644 index 0000000..6067f0b --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m @@ -0,0 +1,112 @@ +function gnew=RemoveMissingIslandsEle2(g,ax,p,MinBndDist,isplot); +%function gnew=HandEditMesh(g,ax,p); +% Remove parts of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. The +% frame work is intended to expand to moving nodes, removing elements, etc +%This wont touch nodes within MinBndDist (m) of existing boundary +if nargin<4 + MinBndDist=1000; +end +if nargin <5, + isplot=0; +end + +xc=mean(g.x(g.e')); +yc=mean(g.y(g.e')); + +jx=find(and(xc>ax(1),xcax(3),ycax(1),p.xax(3),p.y2, + if n(1)==n(end), + jins=find(inside(xc(jg),yc(jg),p0.x(n),p0.y(n))); + nin=g.e(jg(jins),:); + X=g.x(nin); + Y=g.y(nin); + jnins=find( sum(inside(X,Y,p0.x(n),p0.y(n) )')==3); + jb0=[jb0;jnins(:)]; + end + end +end + + + + + +g0=submeshFast(g,jg); +bnd=detbndy(g0.e); +jbnd=unique(bnd(:)); + +xb=g0.x(jbnd); +yb=g0.y(jbnd); + +jx=find(and(p.x>ax(1),p.xax(3),p.y2, + if n(1)==n(end), + jins=find(inside(x,y,p0.x(n),p0.y(n))); + jb0=[jb0;jins(:)]; + end + end +end + +lat2m=110574.; +lon2m=111320.; + +jb0X=[]; +for k=1:length(jb0); + n=jb0(k); + + d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... + i*lat2m*( y(n)-yb ) )); + if d>MinBndDist,jb0X=[jb0X,n];end +end +jb0=jb0X; + +if isplot, + hold on + plot(x(jb0),y(jb0),'ro'); +end + +[g1,kr0]=submeshFastEle(g0,jb0); + +if isplot, + figure; + x=g1.x;y=g1.y;z=g1.z;e=g1.e; + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; + hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); + set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); +end +%jb=jg(jb0); +jb=jg(kr0); +nn=length(g.x); +gnew=submeshFast(g,setdiff(1:nn,jb)); %only removes nodes + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m new file mode 100644 index 0000000..a887737 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m @@ -0,0 +1,93 @@ +function gnew=RemoveMissingIslandsPoint(g,ax,p,MinBndDist); +%function gnew=HandEditMesh(g,ax,p); +% Remove parts of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. The +% frame work is intended to expand to moving nodes, removing elements, etc +%This wont touch nodes within MinBndDist (m) of existing boundary +if nargin<4 + MinBndDist=1000; +end + +jx=find(and(g.x>ax(1),g.xax(3),g.yax(1),p.xax(3),p.y2, + dx=p.x(n(1:end-1))-p.x(n(2:end)); + dy=p.y(n(1:end-1))-p.y(n(2:end)); + d=abs( lon2m*dx*cos(pi*mean(p.y(n))/180)+i*lat2m*(dy) ); + P=sum(d)/1000;%perimeter length of feature + mx=mean(p0.x(n)); + my=mean(p0.y(n)); + [m,jc]=min(abs(g0.x-mx+i*[g0.y-my] )); + P + LSn(jc) + + if LSn(jc)*6 < P, %if "new island" smaller than feature- cut it + hold on;plot(mx,my,'ro',g0.x(jc),g0.y(jc),'cx'); + jb0=[jb0;jc]; + else + hold on;plot(mx,my,'r.',g0.x(jc),g0.y(jc),'rx'); + end + end +end +jc +jb0 +lat2m=110574. +lon2m=111320. + +jb0X=[]; +for k=1:length(jb0); + n=jb0(k); + + d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... + i*lat2m*( y(n)-yb ) )); + if d>=MinBndDist,jb0X=[jb0X,n];end +end +jb0=jb0X + +hold on +plot(x(jb0),y(jb0),'ro'); +xjb0=x(jb0); +yjb0=y(jb0); +nn=length(x); +jg0=setdiff(1:nn,jb0); +g1=submeshFast(g0,jg0); + +figure; +x=g1.x;y=g1.y;z=g1.z;e=g1.e; +clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; +hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-') +set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); +plot(xjb0,yjb0,'r.'); + +jb=jg(jb0); +nn=length(g.x); +gnew=submeshFast(g,setdiff(1:nn,jb)); + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m new file mode 100644 index 0000000..fddeac0 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m @@ -0,0 +1,65 @@ +function RemoveSandPoints(FileInJigsawMesh,FileInJigsawPSLG,FileOutJigsawMesh,FileOutWW3) + +%g=loadmsh('output/RWPS.F.LLH.msh'); +%g=loadmsh('../RWPSMeshTest/output.1km.10km/RWPS.F.LLH.msh'); +g=loadmsh(FileInJigsawMesh) + +close all; +count=0; +IsValidBoundary=0 +while ~IsValidBoundary, + e=g.tria3.index(:,1:3); + x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); + bnd=detbndy(e); + bndn=unique(bnd(:)); + clear n1 n2 + for k=1:length(bndn); + j1=find(bndn(k)==bnd(:,1)); + j2=find(bndn(k)==bnd(:,2)); + n1(k)=length(j1); + n2(k)=length(j2); + end + + nb=n1+n2; + unique(nb)% 2 or 4 + + j4=find(nb==4) + if isempty(j4) + IsValidBoundary=1 + end + + figure; + clf;patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar; + hold on + phsp=plot(x(bndn(j4)),y(bndn(j4)),'ro'); + title(['iteration : ',int2str(count)]) + if ~IsValidBoundary, + count=count+1; + bb=bndn(j4) + bbu=unique(bb) + display(['number of bad boundary points= ',int2str(length(bbu))]) + display(['iteration number : ',int2str(count)]) + nn=length(x); + %jgn=setdiff([1:nn],bbu(:)'); + + jgnBnd=setdiff([1:nn],bbu(:)'); + g.x=x(:);g.y=y(:);g.z=f(:);g.e=e; + hBnd=submeshFast(g,jgnBnd);%can orphan nodes + jgnInt=unique(hBnd.e(:));%nodes still in an element + h=submeshFast(hBnd,jgnInt); + + [ne,three]=size(h.e) + nn=length(h.x) + g0=g;%put back into jigsaw format + g0=rmfield(g0,"tria3") + g0=rmfield(g0,"point") + ep=[h.e,zeros(ne,1)]; + g0.tria3.index=ep; + g0.point.coord=[h.x(:),h.y(:),h.z(:),zeros(nn,1)]; + g0.value=-h.z; + g=g0; + end +end + +savemsh(FileOutJigsawMesh,g); +WriteWW3Mesh(FileOutJigsawMesh,FileInJigsawPSLG,FileOutWW3); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m new file mode 100644 index 0000000..5813112 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m @@ -0,0 +1,53 @@ +function g=RemoveSandPointsWW3(g,FileOutWW3) + +close all; +count=0; +IsValidBoundary=0 +while ~IsValidBoundary, + x=g.x;y=g.y;f=g.z;e=g.e; + bnd=detbndy(e); + bndn=unique(bnd(:)); + clear n1 n2 + for k=1:length(bndn); + j1=find(bndn(k)==bnd(:,1)); + j2=find(bndn(k)==bnd(:,2)); + n1(k)=length(j1); + n2(k)=length(j2); + end + + nb=n1+n2; + unique(nb)% 2 or 4 + + j4=find(nb==4) + if isempty(j4) + IsValidBoundary=1 + end + + figure; + clf;patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar; + hold on + plot(x(bndn(j4)),y(bndn(j4)),'ro'); + title(['iteration : ',int2str(count)]) + if ~IsValidBoundary, + count=count+1; + bb=bndn(j4) + bbu=unique(bb) + display(['number of bad boundary points= ',int2str(length(bbu))]) + display(['iteration number : ',int2str(count)]) + nn=length(x); + %jgn=setdiff([1:nn],bbu(:)'); + + jgnBnd=setdiff([1:nn],bbu(:)'); + g.x=x(:);g.y=y(:);g.z=f(:);g.e=e; + hBnd=submeshFast(g,jgnBnd);%can orphan nodes + jgnInt=unique(hBnd.e(:));%nodes still in an element + h=submeshFast(hBnd,jgnInt); + [ne,three]=size(h.e) + nn=length(h.x) + g=h; + end +end + +if nargin >1, + WriteWW3MeshX(g,FileOutWW3); +end \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m new file mode 100644 index 0000000..ea462df --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m @@ -0,0 +1,19 @@ +function [xss,yss]=SmoothSubSampleCoastlineFast(x,y,DI,lambda); +%function [xs,ys]=SmoothSubSampleCoastline(x,y,dsmooth,lambda); +%Sub sample coastline at dsmooth (m) distance. Boxcar smooth coastline to +% dsmooth*lambda distance +itz=0; +[xi,yi]=InterpCoastline1(x,y,DI,itz); +gamma=2*lambda+1; +ic=lambda+1; +W=ones(1,gamma)/gamma; +xs=conv(xi,W,'same'); +ys=conv(yi,W,'same'); +xss=xs(ic:lambda:end-ic); +yss=ys(ic:lambda:end-ic); +if and(x(1)==x(end),y(1)==y(end)) + if length(xss)>0, + xss=[xss,xss(1)]; + yss=[yss,yss(1)]; + end +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m new file mode 100644 index 0000000..9044665 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m @@ -0,0 +1,22 @@ +function omesh=SubsetMesh(mesh,j) +%function omesh=SubsetMesh(mesh,j) +omesh.point.coord=mesh.point.coord(j,:); +e=mesh.tria3.index(:,1:3); + +[n1,four]=size(mesh.point.coord); +[n0,four]=size(omesh.point.coord); + +%S=sparse(n1,n0); +%S(1:n0,j)=1; +[A,B]=ismember(1:n1,j); +e0=B(e);%map to kept nodes and 0 for missing nodes +e0i=e0; +e0i(find(e0>0))=1;%index of nodes (1) in or (0) out +ke=find(sum(e0i')==3); +e0=e0(ke,:); + +omesh.tria3.index(:,1:3)=e0; +[ne,three]=size(omesh.tria3.index); +omesh.tria3.index(:,4)=zeros(ne,1); + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m new file mode 100644 index 0000000..308ab39 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m @@ -0,0 +1,73 @@ + +function WriteWW3Mesh(mshFileInJigsawFormat,pslgFilelInJigsawFormat,WW3FileOut) +%If Outer edges aren't curved too much don't need PSLG +%OpenBndNodes=FindOuterBnd(mshFileInJigsawFormat,pslgFilelInJigsawFormat); + +OpenBndNodes=FindOuterBndNoPSLG(mshFileInJigsawFormat); + +g=loadmsh(mshFileInJigsawFormat) + +x=g.point.coord(:,1);y=g.point.coord(:,2);z=g.point.coord(:,3); +e=g.tria3.index(:,1:3); + +nn=length(x) +[ne,three]=size(e) +nb=length(OpenBndNodes); + +fp=fopen(WW3FileOut,'w'); +fprintf(fp,'$MeshFormat\n') +fprintf(fp,'2 0 8\n') +fprintf(fp,'$EndMeshFormat\n') +fprintf(fp,'$Nodes\n') +fprintf(fp,'%i\n',nn) + +A=[[1:nn]' x(:),y(:),z(:)]; + +fprintf(fp,'%i %f %f %f\n',A') + +fprintf(fp,'$EndNodes\n') +fprintf(fp,'$Elements\n') +fprintf(fp,'%i\n',ne+nb) + +B=[[1:nb]', 15*ones(nb,1) ,2*ones(nb,1),zeros(nb,1),zeros(nb,1),OpenBndNodes(:)]; + +fprintf(fp,'%i %i %i %i %i %i\n',B') + +C=[ nb+[1:ne]',2*ones(ne,1) ,3*ones(ne,1),zeros(ne,1),[1:ne]',zeros(ne,1),e]; +fprintf(fp,'%i %i %i %i %i %i %i %i %i\n',C') +fprintf(fp,'$EndElements\n') +fclose(fp); + + + +%76 2 3 0 1 0 77 76 1 +%$MeshFormat +%2 0 8 +%$EndMeshFormat +%$Nodes +%3070 +%1 -72.0576782709 40.9902316949 4.2878041267 +%2 -72.0521937363 40.9713426805 13.8250312805 +%3 -72.0469687227 40.9523807323 20.9117679596 + +%3068 -72.585996 40.813074 1.747097373 +%3069 -72.586352 40.818835 1.5 +%3070 -72.589697 40.813418 1.5 +%$EndNodes +%$Elements +%5855 +%1 15 2 0 0 75 +%2 15 2 0 0 74 +%3 15 2 0 0 73 + +%73 15 2 0 0 3 +%74 15 2 0 0 2 +%75 15 2 0 0 1 +%76 2 3 0 1 0 77 76 1 +%77 2 3 0 2 0 76 2 1 +%78 2 3 0 3 0 78 2 76 + +%5854 2 3 0 5779 0 3065 3069 3067 +%5855 2 3 0 5780 0 3068 3067 3070 +%$EndElements + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m new file mode 100644 index 0000000..2b61004 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m @@ -0,0 +1,74 @@ + +function WriteWW3MeshNoJig(g,WW3FileOut) + +%OpenBndNodes=FindOuterBnd(mshFileInJigsawFormat,pslgFilelInJigsawFormat); + +%g=loadmsh(mshFileInJigsawFormat) + +%x=g.point.coord(:,1);y=g.point.coord(:,2);z=g.point.coord(:,3); +%e=g.tria3.index(:,1:3); + +x=g.x;y=g.y;z=g.z;e=g.e; +OpenBndNodes=g.bnd; + +nn=length(x) +[ne,three]=size(e) +nb=length(OpenBndNodes); + +fp=fopen(WW3FileOut,'w'); +fprintf(fp,'$MeshFormat\n') +fprintf(fp,'2 0 8\n') +fprintf(fp,'$EndMeshFormat\n') +fprintf(fp,'$Nodes\n') +fprintf(fp,'%i\n',nn) + +A=[[1:nn]' x(:),y(:),z(:)]; + +fprintf(fp,'%i %f %f %f\n',A') + +fprintf(fp,'$EndNodes\n') +fprintf(fp,'$Elements\n') +fprintf(fp,'%i\n',ne+nb) + +B=[[1:nb]', 15*ones(nb,1) ,2*ones(nb,1),zeros(nb,1),zeros(nb,1),OpenBndNodes(:)]; + +fprintf(fp,'%i %i %i %i %i %i\n',B') + +C=[ nb+[1:ne]',2*ones(ne,1) ,3*ones(ne,1),zeros(ne,1),[1:ne]',zeros(ne,1),e]; +fprintf(fp,'%i %i %i %i %i %i %i %i %i\n',C') +fprintf(fp,'$EndElements\n') +fclose(fp); + + + +%76 2 3 0 1 0 77 76 1 +%$MeshFormat +%2 0 8 +%$EndMeshFormat +%$Nodes +%3070 +%1 -72.0576782709 40.9902316949 4.2878041267 +%2 -72.0521937363 40.9713426805 13.8250312805 +%3 -72.0469687227 40.9523807323 20.9117679596 + +%3068 -72.585996 40.813074 1.747097373 +%3069 -72.586352 40.818835 1.5 +%3070 -72.589697 40.813418 1.5 +%$EndNodes +%$Elements +%5855 +%1 15 2 0 0 75 +%2 15 2 0 0 74 +%3 15 2 0 0 73 + +%73 15 2 0 0 3 +%74 15 2 0 0 2 +%75 15 2 0 0 1 +%76 2 3 0 1 0 77 76 1 +%77 2 3 0 2 0 76 2 1 +%78 2 3 0 3 0 78 2 76 + +%5854 2 3 0 5779 0 3065 3069 3067 +%5855 2 3 0 5780 0 3068 3067 3070 +%$EndElements + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m new file mode 100644 index 0000000..b4b03b8 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m @@ -0,0 +1,68 @@ + +function WriteWW3MeshX(g,WW3FileOut) + +OpenBndNodes=FindOuterBndWW3(g,0) + +x=g.x;y=g.y;z=g.z;e=g.e; + +nn=length(x) +[ne,three]=size(e) +nb=length(OpenBndNodes); + +fp=fopen(WW3FileOut,'w'); +fprintf(fp,'$MeshFormat\n') +fprintf(fp,'2 0 8\n') +fprintf(fp,'$EndMeshFormat\n') +fprintf(fp,'$Nodes\n') +fprintf(fp,'%i\n',nn) + +A=[[1:nn]' x(:),y(:),z(:)]; + +fprintf(fp,'%i %f %f %f\n',A') + +fprintf(fp,'$EndNodes\n') +fprintf(fp,'$Elements\n') +fprintf(fp,'%i\n',ne+nb) + +B=[[1:nb]', 15*ones(nb,1) ,2*ones(nb,1),zeros(nb,1),zeros(nb,1),OpenBndNodes(:)]; + +fprintf(fp,'%i %i %i %i %i %i\n',B') + +C=[ nb+[1:ne]',2*ones(ne,1) ,3*ones(ne,1),zeros(ne,1),[1:ne]',zeros(ne,1),e]; +fprintf(fp,'%i %i %i %i %i %i %i %i %i\n',C') +fprintf(fp,'$EndElements\n') +fclose(fp); + + + +%76 2 3 0 1 0 77 76 1 +%$MeshFormat +%2 0 8 +%$EndMeshFormat +%$Nodes +%3070 +%1 -72.0576782709 40.9902316949 4.2878041267 +%2 -72.0521937363 40.9713426805 13.8250312805 +%3 -72.0469687227 40.9523807323 20.9117679596 + +%3068 -72.585996 40.813074 1.747097373 +%3069 -72.586352 40.818835 1.5 +%3070 -72.589697 40.813418 1.5 +%$EndNodes +%$Elements +%5855 +%1 15 2 0 0 75 +%2 15 2 0 0 74 +%3 15 2 0 0 73 + +%73 15 2 0 0 3 +%74 15 2 0 0 2 +%75 15 2 0 0 1 +%76 2 3 0 1 0 77 76 1 +%77 2 3 0 2 0 76 2 1 +%78 2 3 0 3 0 78 2 76 + +%5854 2 3 0 5779 0 3065 3069 3067 +%5855 2 3 0 5780 0 3068 3067 3070 +%$EndElements + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m new file mode 100644 index 0000000..55c3f10 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m @@ -0,0 +1,99 @@ +% DETBNDY compute a boundary segment list for a FEM domain +% +% DETBNDY bnd=detbndy(e); +% This function computes a boundary for the FEM domain +% described a file containing element connectivity list (e). +% It uses sparse matrix techniques to determine the element +% edges on the boundary of the FEM domain. +% +% Input: ele - element list; 3 (.tri) or 4 (.ele) columns wide +% Output: bnd - a 2-column list of boundary-node numbers, returned +% to the local workspace +% +% The output boundary list are pairs of node numbers, not +% coordinates, describing the edges of elements on the +% exterior of the domain, including islands. The segments +% are not connected. +% +% Call as: bnd=detbndy(e); +% +% Written by : Brian O. Blanton at The University of North Carolina +% at Chapel Hill, Mar 1995. +% +function bnd=detbndy(in) + +% DEFINE ERROR STRINGS +err1=['Only one input argument to DETBNDY. Type "help detbndy"']; +err2=['Element list passed to DETBNDY does not have 3 or 4 columns']; +err3=str2mat(['??? Error using ==> detbndy'],... + ['DETBNDY must have one output argument.'],... + ['Call as: >> bnd=detbndy(in);'],... + [' ']); +% check argument list +if nargin~=1 + error(err1); +end + +if nargout~=1 + disp(err3); + return +end + + +% Check size of element list +[nelems,ncol]=size(in); +if ncol < 3 | ncol > 4 + error(err2); + return +elseif ncol==4 + in=in(:,2:4); +end + +% Form (i,j) connection list from .ele element list +% +i=[in(:,1);in(:,2);in(:,3)]; +j=[in(:,2);in(:,3);in(:,1)]; + +% Form the sparse adjacency matrix and add transpose. +% +n = max(max(i),max(j)); +A = sparse(i,j,-1,n,n); +A = A + A'; + +% Consider only the upper part of A, since A is symmetric +% +A=A.*triu(A); + +% The boundary segments are A's with value == 1 +% +B=A==1; + +% Extract the row,col from B for the boundary list. +% +[ib,jb,s]=find(B); +bnd=[ib(:),jb(:)]; + +% Output .bnd list +% +%res=input('Output .bnd boundary list (y/n) ? [n] ','s'); +%if strcmp(res,'y') +% fname=input('Enter .bnd filename [bnd.dat] ','s'); +% if isempty(fname),fname='bnd.dat';,end +% fp=fopen(fname,'w'); +% for i=1:length(bnd) +% fprintf(fp,'%d %d\n', bnd(i,1),bnd(i,2)); +% end +%end +% +% Brian O. Blanton +% Curriculum in Marine Sciences +% 15-1A Venable Hall +% CB# 3300 +% University of North Carolina +% Chapel Hill, NC +% 27599-3300 +% +% 919-962-4466 +% blanton@marine.unc.edu +% + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m new file mode 100644 index 0000000..130e187 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m @@ -0,0 +1,87 @@ +function chains=edges2chains(edges); +%edges2chains::decompose list of edges into all maximal chains and cycles(non edge repeating paths) +%%take a Nx2 adjacency list and decompose it into all maximum cylcles and chains with provided no +%vertex has order greater than 2. +%function chains=edges2chains(edges); +% +%Inputs: +% edges:(Nedgesx2) integer adjacency list defining edges in graph. +% +%Outputs: +% chains:list of structures defining maximal paths. +% chains(k).nodes:n_k length integer list of nodes in chain k. +% +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +%Keston Smith & Ata Bilgili May 2001 +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + +if ~isempty(edges) + edges=[min(edges')',max(edges')']; + [i,j]=sort(edges(:,1)); + + edges=[edges(j,1),edges(j,2)]; + + [N,NN]=size(edges); + chains=[]; + n=0; + while ~isempty(edges) + chain=edges(1,1); + j=edges(1,2); + edges=edges(2:end,:); + %while ~isempty(j), + while length(j)==1, + chain=[chain,j(:)']; + %whos edges j + k1=find(edges(:,1)==j); + k2=find(edges(:,2)==j); + if ~isempty(k1), + j=edges(k1,2); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k1),:); + elseif ~isempty(k2), + j=edges(k2,1); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k2),:); + else + j=[]; + end + end + j=chain(1); + k1=find(edges(:,1)==j); + k2=find(edges(:,2)==j); + if ~isempty(k1), + j=edges(k1,2); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k1),:); + elseif ~isempty(k2), + j=edges(k2,1); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k2),:); + else + j=[]; + end +% while ~isempty(j), + while length(j)==1, + + chain=[j,chain]; + k1=find(edges(:,1)==j); + k2=find(edges(:,2)==j); + if ~isempty(k1), + j=edges(k1,2); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k1),:); + elseif ~isempty(k2), + j=edges(k2,1); + [N,M]=size(edges); + edges=edges(setdiff(1:N,k2),:); + else + j=[]; + end + end + n=n+1; + chains(n).nodes=chain; + end +else + chains(1).nodes=[]; +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m new file mode 100644 index 0000000..f27ef84 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m @@ -0,0 +1,68 @@ +function pslg=joinpslg(pslg1,pslg2,mergeDist); +%mergepslg::join two pslgs together. +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +%Keston Smith 2022 +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +pslg1.x=pslg1.x(:)'; +pslg1.y=pslg1.y(:)'; +pslg2.x=pslg2.x(:)'; +pslg2.y=pslg2.y(:)'; + + +np1=max(max(pslg1.edges)); +%pslg1,pslg2,np1 +if ~isempty(np1), + pslg.edges=[pslg1.edges;pslg2.edges+np1]; +else + pslg.edges=[pslg1.edges;pslg2.edges]; + +end +pslg.x=[pslg1.x,pslg2.x]; +pslg.y=[pslg1.y,pslg2.y]; +holes.x=[];holes.y=[]; +if isfield(pslg1,'holes') + holes.x=[holes.x(:);pslg1.holes.x(:)]; + holes.y=[holes.y(:);pslg1.holes.y(:)]; +end +if isfield(pslg2,'holes') + holes.x=[holes.x(:);pslg2.holes.x(:)]; + holes.y=[holes.y(:);pslg2.holes.y(:)]; +end +pslg.holes=holes; + +zones.x=[];zones.y=[]; +if isfield(pslg1,'zones') + zones.x=[zones.x(:);pslg1.zones.x(:)]; + zones.y=[zones.y(:);pslg1.zones.y(:)]; +end +if isfield(pslg2,'zones') + zones.x=[zones.x(:);pslg2.zones.x(:)]; + zones.y=[zones.y(:);pslg2.zones.y(:)]; +end +pslg.zones=zones; + +if isfield(pslg1,'chains') + pslg.chains=pslg1.chains; +end + +if isfield(pslg2,'chains') + nc=length(pslg.chains); + nc2=length(pslg2.chains); + np=length(pslg.x); + for k=1:nc2 + pslg.chains(nc+k).nodes=n+pslg2.chains(k).nodes; + end +end + +%z=round((pslg.x+i*pslg.y)/MergeDist); +if nargin>2 + z=pslg.x+i*pslg.y; + n=length(pslg.x); + for k=1:n-1, + d=abs(z(k)-z(k+1:n)); + j=find(d k ); +% h.e(j)=h.e(j)-1; +%end + +for k=1:length(ki) + j=find(g.e > ki(k) ); + h.e(j)=h.e(j)-1; +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m new file mode 100644 index 0000000..d635ca4 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m @@ -0,0 +1,17 @@ +function h=submeshFast(g,jGoodNodes) + +jGoodNodes=jGoodNodes(:)';%row format + +nn=length(g.x) +[ne,three]=size(g.e) + +jGoodNodes=sort(jGoodNodes); +h.x=g.x(jGoodNodes); +h.y=g.y(jGoodNodes); +h.z=g.z(jGoodNodes); + +A=ismember(g.e,jGoodNodes); +k=find(sum(A')==3)'; +e=g.e(k,:); +[kk,M]=ismember(1:nn,jGoodNodes); +h.e=M(e); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m new file mode 100644 index 0000000..1d900ec --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m @@ -0,0 +1,9 @@ +function [h,k]=submeshFastEle(g,jBadNodes) + +[ne,three]=size(g.e); +A=ismember(g.e,jBadNodes); +k=find(sum(A')==3)';%elements with nodes lying entirely within feature + +elist=setdiff(1:ne,k); +g.e=g.e(elist,:);%remove elements entirely within feature; +[h,k]=remove_dead_nodes(g);%remove nodes no longer in any elements diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m new file mode 100644 index 0000000..8c21dfa --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m @@ -0,0 +1,17 @@ +function h=submeshFast(g,jGoodNodes,jGoodEles) + +jGoodNodes=jGoodNodes(:)';%row format + +nn=length(g.x) +[ne,three]=size(g.e) + +jGoodNodes=sort(jGoodNodes); +h.x=g.x(jGoodNodes); +h.y=g.y(jGoodNodes); +h.z=g.z(jGoodNodes); + +A=ismember(g.e,jGoodNodes); +k=find(sum(A')==3)'; +e=g.e(k,:); +[kk,M]=ismember(1:nn,jGoodNodes); +h.e=M(e); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m new file mode 100644 index 0000000..b86ffdf --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m @@ -0,0 +1,25 @@ +function h=subpslgFast(g,jGoodNodes) +%function h=subpslgFast(g,jGoodNodes) +% +%Make the subset Planer Staight Line Graph(PSLG) consisting only of nodes +% with indexes in jGoodNodes (only edges consisting spanning nodes in +% jGoodNodes are preserved). +% +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +%Keston Smith 2022 +%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +jGoodNodes=jGoodNodes(:)';%row format + +nn=length(g.x); +[ne,two]=size(g.edges); + +jGoodNodes=sort(jGoodNodes); +h.x=g.x(jGoodNodes); +h.y=g.y(jGoodNodes); + +A=ismember(g.edges,jGoodNodes); +k=find(sum(A')==2)'; +edges=g.edges(k,:); +[kk,M]=ismember(1:nn,jGoodNodes); +h.edges=M(edges); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m new file mode 100644 index 0000000..910ff61 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m @@ -0,0 +1,21 @@ +function topo=topo2msh(fl,flout) + +x=ncread(fl,'lon'); +y=ncread(fl,'lat'); +z=ncread(fl,'bed_elevation'); +x=[x(2:end)+x(1:end-1)]/2; +y=[y(2:end)+y(1:end-1)]/2; + +%z = reshape( z,length(y), length(x)); +topo.point.coord{:,1}=x(:); +topo.point.coord{:,2}=y(:); +topo.value=z; + +topo.mshID='ELLIPSOID-GRID' +topo.fileV=3; + +nargin +if nargin>2 + savemsh(flout,topo); +end + \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py new file mode 100644 index 0000000..c0d91a0 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py @@ -0,0 +1,143 @@ +import os +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd +import time +from SmoothAndSubsampleCoastline import * + +MakePlots=False + +if MakePlots: + import plotly.express as px + import plotly.graph_objects as go + +#(positive integer)Subsample bathymetry coordinates to Nsubsamble +Nsubsample=2 #86 hours + +Nsubsample=5 #3.75 hours + +flout="DistToUSCoast.msh" +CoastInput=1 +if CoastInput==0: + fl="../RWPS/Data/us_coastline/tl_2023_us_coastline.shp" + #gdf = gpd.read_file("../RWPS/Data/us_coastline/tl_2023_us_coastline.shp") + dxS=5000. #(positive real)Smooth coastline to dxS meters length scale + dxI=2500. #(positive real)Interpolate smoothed coastline to dxI meters + points=SmoothAndSubsampleCoastline(fl,dxS,dxI) + lonUS=points[:,0] + latUS=points[:,1] + +if CoastInput==1: # Use precomputed smoothed & subsampled coast points from FindUSadjacentGSHHSpoints.py + fl="./USCoastPointsWithGSHHSandBanks.txt" + points=np.loadtxt(fl, delimiter=' ') + lonUS=points[1,:] + latUS=points[0,:] + +#gdf = gpd.read_file(fl) +j=np.where( np.abs(lonUS+latUS)>= 0 ) # remove NaN's +lonUS=lonUS[j] +latUS=latUS[j] + +np.savetxt('CoastPoints.txt', (lonUS, latUS), delimiter=' ') + +print("number of coastline points = " + str(lonUS.size)) +print("This number has a strong effect on run time") + +# load topo file to build distance function on the grid of +data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") +xlon = np.asarray(data["lon"][:]) +ylat = np.asarray(data["lat"][:]) +#elev = np.asarray(data["bed_elevation"][:]) + np.asarray(data["ice_thickness"][:]) + +if MakePlots: + fig = px.scatter(x=xlon, y=ylat) + fig.show(renderer='browser') + +xmid = 0.5 * (xlon[:-1:] + xlon[1::]) +ymid = 0.5 * (ylat[:-1:] + ylat[1::]) + +xmid=xmid[0 :: Nsubsample] +ymid=ymid[0 :: Nsubsample] + +nx=xmid.size +ny=ymid.size +npoints=lonUS.size + +D=np.zeros((ny,nx),dtype=np.single) +lat2m=np.single(110574.) +i=complex(0,1) + +t0=time.time() +D=np.zeros((ny,nx),dtype=np.single) +lat2m=np.single(110574.) +i=complex(0,1) +DLON=np.mod( np.array([xmid] * npoints) - np.array([lonUS] * nx).T, 360. ) +for k in range(0,ny-1): + print( str(k) + " of " + str(ny)+" percent:"+str(100*k/ny) ) + lon2m=np.single(111320.*np.cos(ylat[k]*np.pi/180.)) + DLAT=(ymid[k]-latUS) + DLATnx=np.array([DLAT] * nx).T + ldE=np.min ( np.abs( DLON*lon2m + i*DLATnx*lat2m ), axis=0 )#Distance to east + ldW=np.min ( np.abs( (360. - DLON)*lon2m + i*DLATnx*lat2m ), axis=0 )#Distance to west + ld=np.array([ldE,ldW]) + D[k,:]=np.min(ld,axis=0) # min of east, west distances + t1=time.time() + tps=(t1-t0)/max(k,1) + tre=tps*(ny-k) + print("estimated hours remaining: "+ str( tre /3600. ) ) + +#output to jigsaw .msh format +dist = jigsawpy.jigsaw_msh_t() +dist.mshID = "ellipsoid-grid" +dist.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) +dist.xgrid = xmid +dist.ygrid = ymid +dist.value = D +jigsawpy.savemsh(flout, dist) + + +#make some simple plots for sanity check +if MakePlots: + fig = px.imshow(D) + fig.show(renderer='browser') + + fig1 = go.Figure(data=go.Heatmap(z=D/1000,x=xmid,y=ymid)) + + fig1.update_layout( + title=dict(text='Distance to US coastline (km)'), + xaxis_nticks=36) + fig1.show(renderer='browser') + fig1.add_trace( + go.Scatter( + x=lonUS, + y=latUS, + mode='markers', + showlegend=False) + ) + fig1.show(renderer='browser') + +if MakePlots: + + fig2 = px.imshow(D/1000,labels=dict(x="longitude", y="latitude", color="distance"), + x=xmid, + y=ymid + ) + + fig2.update_layout( title=dict(text='Distance to US coastline (km)') ) + fig2.show(renderer='browser') + fig2.show(renderer='browser') + fig2.add_trace( + go.Scatter( + x=lonUS, + y=latUS, + mode='markers', + showlegend=False) + ) + fig2.show(renderer='browser') + + + fig = px.scatter(x=lonUS, y=latUS) + fig.add_trace(px.scatter(x=lonUS[1], y=latUS[1], mode='markers', marker=dict(color='red'), name='Second Trace')) + #fig.add_trace(go.Scatter(x=x2, y=y2, mode='markers', marker=dict(color='red'), name='Second Trace')) + fig.show(renderer='browser') diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py new file mode 100644 index 0000000..7346229 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py @@ -0,0 +1,176 @@ +import os +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd +import time +from SmoothAndSubsampleCoastline import * + +#for 2D convolution +from scipy import signal +from scipy import datasets + +MakePlots=False + +if MakePlots: + import plotly.express as px + import plotly.graph_objects as go + +#(positive integer)Subsample bathymetry coordinates to Nsubsamble +Nsubsample=2 # ~86 hours + +Nsubsample=5 # ~3.75 hours +Nsubsample=10# ~1. hours +Nsubsample=20# ~1. hours + + +flout="DistToUSCoast.msh" +CoastInput=1 +if CoastInput==0: + fl="../RWPS/Data/us_coastline/tl_2023_us_coastline.shp" + #gdf = gpd.read_file("../RWPS/Data/us_coastline/tl_2023_us_coastline.shp") + dxS=5000. #(positive real)Smooth coastline to dxS meters length scale + dxI=2500. #(positive real)Interpolate smoothed coastline to dxI meters + points=SmoothAndSubsampleCoastline(fl,dxS,dxI) + lonUS=points[:,0] + latUS=points[:,1] + +if CoastInput==1: # Use precomputed smoothed & subsampled coast points from FindUSadjacentGSHHSpoints.py + fl="./USCoastPointsWithGSHHSandBanks.txt" + points=np.loadtxt(fl, delimiter=' ') + lonUS=points[1,:] + latUS=points[0,:] + +#gdf = gpd.read_file(fl) +j=np.where( np.abs(lonUS+latUS)>= 0 ) # remove NaN's +lonUS=lonUS[j] +latUS=latUS[j] + +np.savetxt('CoastPoints.txt', (lonUS, latUS), delimiter=' ') + +print("number of coastline points = " + str(lonUS.size)) +print("This number has a strong effect on run time") + +# load topo file to build distance function on the grid of +data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") +xlon = np.asarray(data["lon"][:]) +ylat = np.asarray(data["lat"][:]) +#elev = np.asarray(data["bed_elevation"][:]) + np.asarray(data["ice_thickness"][:]) + +if MakePlots: + fig = px.scatter(x=xlon, y=ylat) + fig.show(renderer='browser') + +xmid = 0.5 * (xlon[:-1:] + xlon[1::]) +ymid = 0.5 * (ylat[:-1:] + ylat[1::]) + +xmid=xmid[0 :: Nsubsample] +ymid=ymid[0 :: Nsubsample] + +nx=xmid.size +ny=ymid.size +npoints=lonUS.size + +D=np.zeros((ny,nx),dtype=np.single) +lat2m=np.single(110574.) +i=complex(0,1) + +t0=time.time() +D=np.zeros((ny,nx),dtype=np.single) +lat2m=np.single(110574.) +i=complex(0,1) +DLON=np.mod( np.array([xmid] * npoints) - np.array([lonUS] * nx).T, 360. ) +for k in range(0,ny-1): + print( str(k) + " of " + str(ny)+" percent:"+str(100*k/ny) ) + lon2m=np.single(111320.*np.cos(ylat[k]*np.pi/180.)) + DLAT=(ymid[k]-latUS) + DLATnx=np.array([DLAT] * nx).T + ldE=np.min ( np.abs( DLON*lon2m + i*DLATnx*lat2m ), axis=0 )#Distance to east + ldW=np.min ( np.abs( (360. - DLON)*lon2m + i*DLATnx*lat2m ), axis=0 )#Distance to west + ld=np.array([ldE,ldW]) + D[k,:]=np.min(ld,axis=0) # min of east, west distances + t1=time.time() + tps=(t1-t0)/max(k,1) + tre=tps*(ny-k) + print("estimated hours remaining: "+ str( tre /3600. ) ) + +#output to jigsaw .msh format +dist = jigsawpy.jigsaw_msh_t() +dist.mshID = "ellipsoid-grid" +dist.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) +dist.xgrid = xmid +dist.ygrid = ymid +dist.value = D +jigsawpy.savemsh(flout, dist) + +#Average output to resolution of DistToCoast +# load topo file to build distance function on the grid of +data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") +xlon = np.asarray(data["lon"][:]) +ylat = np.asarray(data["lat"][:]) +elev = np.asarray(data["bed_elevation"][:]) + np.asarray(data["ice_thickness"][:]) +W=np.ones((Nsubsample,Nsubsample))/(Nsubsample**2) + +#eW = signal.convolve2d(elev,W, boundary='symm', mode='same') +eW = signal.convolve2d(elev,W, mode='same') + +xmid = 0.5 * (xlon[:-1:] + xlon[1::]) +ymid = 0.5 * (ylat[:-1:] + ylat[1::]) +xmid=xmid[0 :: Nsubsample] +ymid=ymid[0 :: Nsubsample] +eW=eW[0 :: Nsubsample,0 :: Nsubsample] +topofl="TopographyFor"+flout +#output to jigsaw .msh format +topo = jigsawpy.jigsaw_msh_t() +topo.mshID = "ellipsoid-grid" +topo.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) +topo.xgrid = xmid +topo.ygrid = ymid +topo.value = eW +jigsawpy.savemsh(topofl, topo) + +#make some simple plots for sanity check +if MakePlots: + fig = px.imshow(D) + fig.show(renderer='browser') + + fig1 = go.Figure(data=go.Heatmap(z=D/1000,x=xmid,y=ymid)) + + fig1.update_layout( + title=dict(text='Distance to US coastline (km)'), + xaxis_nticks=36) + fig1.show(renderer='browser') + fig1.add_trace( + go.Scatter( + x=lonUS, + y=latUS, + mode='markers', + showlegend=False) + ) + fig1.show(renderer='browser') + + +if MakePlots: + + fig2 = px.imshow(D/1000,labels=dict(x="longitude", y="latitude", color="distance"), + x=xmid, + y=ymid + ) + + fig2.update_layout( title=dict(text='Distance to US coastline (km)') ) + fig2.show(renderer='browser') + fig2.show(renderer='browser') + fig2.add_trace( + go.Scatter( + x=lonUS, + y=latUS, + mode='markers', + showlegend=False) + ) + fig2.show(renderer='browser') + + + fig = px.scatter(x=lonUS, y=latUS) + fig.add_trace(px.scatter(x=lonUS[1], y=latUS[1], mode='markers', marker=dict(color='red'), name='Second Trace')) + #fig.add_trace(go.Scatter(x=x2, y=y2, mode='markers', marker=dict(color='red'), name='Second Trace')) + fig.show(renderer='browser') diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py new file mode 100644 index 0000000..75d3b4c --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py @@ -0,0 +1,99 @@ +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd +import time + +from SmoothAndSubsampleCoastline import * + +#compute points in the higher resolution GSHHS global coastline that are near the us coastline, +#defined in tigerline + +#https://catalog.data.gov/dataset/tiger-line-shapefile-2019-nation-u-s-coastline-national-shapefile +#https://www.soest.hawaii.edu/pwessel/gshhg/ + +flUS="../RWPS/Data/us_coastline/tl_2023_us_coastline.shp" +GlobalCoastLineFile='../RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' + +dxS=5000. #(positive real)Smooth coastline to dxS meters length scale +dxI=2500. #(positive real)Interpolate smoothed coastline to dxI meters +pointsUS=SmoothAndSubsampleCoastline(flUS,dxS,dxI) + +lonUS=pointsUS[:,0] +latUS=pointsUS[:,1] +#gdf = gpd.read_file(fl) +j=np.where( np.abs(lonUS+latUS)>= 0 ) # remove NaN's +lonUS=lonUS[j] +latUS=latUS[j] + +pointsGlobal=SmoothAndSubsampleCoastline(GlobalCoastLineFile,dxS,dxI) +lonGlobal=pointsGlobal[:,0] +latGlobal=pointsGlobal[:,1] + +np.savetxt('GlobalCoastPoints.txt', (latGlobal, lonGlobal), delimiter=' ') + +j=np.where( np.abs(lonUS+latUS)>= 0 ) # remove NaN's +lonUS=lonUS[j] +latUS=latUS[j] + +j=np.where( np.abs(lonGlobal+latGlobal)>= 0 ) # remove NaN's +lonGlobal=lonGlobal[j] +latGlobal=latGlobal[j] + +npGlobal=lonGlobal.size + + +t0=time.time() +D=np.zeros((npGlobal),dtype=np.single) +lat2m=np.single(110574.) +i=complex(0,1) +for k in range(0,npGlobal-1): + lon2m=np.single(111320.*np.cos(latGlobal[k]*np.pi/180.)) + DLON=np.mod( lonGlobal[k] - lonUS , 360. ) + DLAT= latGlobal[k] - latUS + ldE=np.min ( np.abs( DLON*lon2m + i*DLAT*lat2m ) )#Distance to east + ldW=np.min ( np.abs( (360. - DLON)*lon2m + i*DLAT*lat2m ) )#Distance to west + D[k]=min(ldE,ldW) # min of east, west distances + t1=time.time() + tps=(t1-t0)/max(k,1) + tre=tps*(npGlobal-k) + if np.mod(k,10000)==0: + print( str(k) + " of " + str(npGlobal)+" percent:"+str(100*k/npGlobal) ) +# print("estimated hours remaining: "+ str( tre /3600. ) ) + print("estimated minutes remaining: "+ str( tre /60. ) ) + +np.savetxt('USCoastPoints.txt', (latUS, lonUS), delimiter=' ') + +thrsh=111000. +j=np.where( D <= thrsh ) # remove NaN's +np.savetxt('USCoastPointsFromGSHHS.txt', (latGlobal[j], lonGlobal[j]), delimiter=' ') + +lonUSX=np.append(lonUS,lonGlobal[j]) +latUSX=np.append(latUS,latGlobal[j]) +np.savetxt('USCoastPointsWithGSHHS.txt', (latUSX, lonUSX), delimiter=' ') + + +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#add points to off shore banks we want to refine here we have Georges Bank(GB) +#and banks around the Bahamas(FB) as well as Penguin bank of Molakai, HI. +#This artificially increases resolution for these features +lonFB=[ -78.6485, -78.6999, -78.3401, -76.4383, -79.9849] +latFB=[ 27.0490, 25.4556, 23.6567, 22.9114, 23.7338] +#lonFB= [ -79.9909, -78.1963, -78.3957] +#latFB= [23.7978, 26.8928, 24.1530] +lonUSX=np.append(lonUSX,lonFB) +latUSX=np.append(latUSX,latFB) +lonGB=[ -67.4977, -68.0673] +latGB=[ 41.6880, 41.1443] +#lonGB = -67.4517 +#latGB = 41.3567 +lonUSX=np.append(lonUSX,lonGB) +latUSX=np.append(latUSX,latGB) +#penguin bank HI 50m deep- probably not important in waves +lonPB =[ -157.6623, -157.5066] +latPB=[ 20.9413, 21.0486] +lonUSX=np.append(lonUSX,lonPB) +latUSX=np.append(latUSX,latPB) + +np.savetxt('USCoastPointsWithGSHHSandBanks.txt', (latUSX, lonUSX), delimiter=' ') + diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py new file mode 100644 index 0000000..b01a95c --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py @@ -0,0 +1,63 @@ + +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd + +def ReadWriteCoast(fl): + + gdf = gpd.read_file(fl) + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + for k in range(0, n-1): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + xss=np.append(xss,xp[:]) + yss=np.append(yss,yp[:]) + + #x,y = seg.coords.xy + #xp=numpy_array = np.array(x) + #yp=numpy_array = np.array(y) + ymp=np.mean(yp) + dx=xp[:-1:] - xp[1::] + dy=yp[:-1:] - yp[1::] + lat2m=110574. + lon2m=111320.*np.cos(ymp*np.pi/180.) + d=np.sqrt( (dx*lon2m)**2 + (dy*lat2m)**2 ) + d=np.append(0,np.cumsum(d)) + nd=d.size-1 + npoints=int(np.ceil(d[nd]/dxS)) + di=np.linspace(d[0],d[nd],npoints) + ni=di.size + xi=np.zeros((ni,), dtype=np.single) + yi=np.zeros((ni,), dtype=np.single) + for j in range(0,ni): + ks=np.where( (d-di[j])**2 < dxS**2 ) + xi[j]=np.mean(xp[ks]) + yi[j]=np.mean(yp[ks]) + xss=np.append(xss,xi[:]) + yss=np.append(yss,yi[:]) + if MakePlots: + xo=np.append(xo,xp[:]) + yo=np.append(yo,yp[:]) + + n=xss.size + point=np.zeros((n,2), dtype=np.single) + np.savetxt('CoastPoints.txt', (yss, xss), delimiter=' ') + + + point[:,0] = xss[:] + point[:,1] = yss[:] + return point diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py new file mode 100644 index 0000000..63d0f4f --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py @@ -0,0 +1,17 @@ +import geopandas as gpd +import time +from SmoothAndSubsampleCoastline import * + +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd + + +fl='../RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' + #gdf = gpd.read_file("../RWPS/Data/us_coastline/tl_2023_us_coastline.shp") +dxS=10000. #(positive real)Smooth coastline to dxS meters length scale +dxI=5000. #(positive real)Interpolate smoothed coastline to dxI meters +edges=SmoothAndSubsampleCoastlineGeom(fl,dxS,dxI,100) +lonUS=points[:,0] +latUS=points[:,1] diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py new file mode 100644 index 0000000..f191884 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py @@ -0,0 +1,278 @@ + +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd + +MakePlots=False + +if MakePlots: + import plotly.express as px + import plotly.graph_objects as go + + +def SmoothAndSubsampleCoastline(fl,dxS,dxI): + + gdf = gpd.read_file(fl) + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + for k in range(1, n): + if np.mod(k,1000)==0: + print("Loading Coastline: "+str(k)+" of "+str(n) ) + try: + seg=gdf.geometry[k-1] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + N[k-1]=xp.size + except: + print("Error reading segment # "+str(k)) + N[k-1]=0 + + k = np.argmax(N) + m = np.max(N) + + print("smoothing "+str(n)+" coast segments. longest segment at "+str(k)+" of length "+str(m)) + #gdfS=gdf + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + if MakePlots: + xo=np.array([], dtype=np.single) + yo=np.array([], dtype=np.single) + + for k in range(0, n-1): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + + ymp=np.mean(yp) + dx=xp[:-1:] - xp[1::] + dy=yp[:-1:] - yp[1::] + lat2m=110574. + lon2m=111320.*np.cos(ymp*np.pi/180.) + d=np.sqrt( (dx*lon2m)**2 + (dy*lat2m)**2 ) + d=np.append(0,np.cumsum(d)) + nd=d.size-1 + npoints=int(np.ceil(d[nd]/dxS)) + di=np.linspace(d[0],d[nd],npoints) + ni=di.size + xi=np.zeros((ni,), dtype=np.single) + yi=np.zeros((ni,), dtype=np.single) + for j in range(0,ni): + ks=np.where( (d-di[j])**2 < dxS**2 ) + xi[j]=np.mean(xp[ks]) + yi[j]=np.mean(yp[ks]) + xss=np.append(xss,xi[:]) + yss=np.append(yss,yi[:]) + if MakePlots: + xo=np.append(xo,xp[:]) + yo=np.append(yo,yp[:]) + + n=xss.size + point=np.zeros((n,2), dtype=np.single) + + point[:,0] = xss[:] + point[:,1] = yss[:] + if MakePlots: + + xo=xo[0 :: 100] + yo=yo[0 :: 100] + fig = go.Figure() + fig.add_trace(go.Scatter(x=xss, y=yss,mode='markers',name='smoothed'))#,color='blue')) + # go.Scatter can't handle more than ~1 mm points- so this may not work + fig.add_trace(go.Scatter(x=xo , y=yo ,mode='markers',name='origonal'))#,color='red')) + fig.show() + + return point + + +def SmoothAndSubsampleCoastlineGeom(fl,dxS,dxI,Nseg): + + gdf = gpd.read_file(fl) + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + #gdfS=gdf + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + edges=np.array((-1,-1)) + edges = np.expand_dims(edges, axis=1) + + nn=0 + +# for k in range(0, n-1): + for k in range(0, Nseg): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + jj=xp.size + if jj > 2: + ymp=np.mean(yp) + dx=xp[:-1:] - xp[1::] + dy=yp[:-1:] - yp[1::] + lat2m=110574. + lon2m=111320.*np.cos(ymp*np.pi/180.) + d=np.sqrt( (dx*lon2m)**2 + (dy*lat2m)**2 ) + d=np.append(0,np.cumsum(d)) + nd=d.size-1 + npoints=int(np.ceil(d[nd]/dxS)) + di=np.linspace(d[0],d[nd],npoints) + ni=di.size + xi=np.zeros((ni,), dtype=np.single) + yi=np.zeros((ni,), dtype=np.single) + for j in range(0,ni): + ks=np.where( (d-di[j])**2 < dxS**2 ) + xi[j]=np.mean(xp[ks]) + yi[j]=np.mean(yp[ks]) + xss=np.append(xss,xi[:]) + yss=np.append(yss,yi[:]) + + mm=xi.size + l=np.arange(mm-1) + v=np.vstack((l,1+l)) + c=np.array((mm-1,0)) + cc = np.expand_dims(c, axis=1) + vc=np.hstack((v,cc) ) + edges=np.hstack((edges,vc+nn)) + nn=nn+mm + + + geom = jigsawpy.jigsaw_msh_t() + + n=xss.size + point=np.zeros((n,2), dtype=np.single) + + point[:,0] = xss[:] + point[:,1] = yss[:] + + return edges + + +def SmoothAndSubsampleCoastlineShp(flin,flout,dxS,dxI): + + gdf = gpd.read_file(flin) + gdfout=gdf + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + for k in range(1, n): + if np.mod(k,1000)==0: + print("Loading Coastline: "+str(k)+" of "+str(n) ) + try: + seg=gdf.geometry[k-1] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + N[k-1]=xp.size + except: + print("Error reading segment # "+str(k)) + N[k-1]=0 + + k = np.argmax(N) + m = np.max(N) + + print("smoothing "+str(n)+" coast segments. longest segment at "+str(k)+" of length "+str(m)) + #gdfS=gdf + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + if MakePlots: + xo=np.array([], dtype=np.single) + yo=np.array([], dtype=np.single) + + for k in range(0, n-1): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + ymp=np.mean(yp) + + dx=xp[:-1:] - xp[1::] + dy=yp[:-1:] - yp[1::] + lat2m=110574. + lon2m=111320.*np.cos(ymp*np.pi/180.) + d=np.sqrt( (dx*lon2m)**2 + (dy*lat2m)**2 ) + d=np.append(0,np.cumsum(d)) + nd=d.size-1 + npoints=int(np.ceil(d[nd]/dxS)) + di=np.linspace(d[0],d[nd],npoints) + ni=di.size + xi=np.zeros((ni,), dtype=np.single) + yi=np.zeros((ni,), dtype=np.single) + for j in range(0,ni): + ks=np.where( (d-di[j])**2 < dxS**2 ) + xi[j]=np.mean(xp[ks]) + yi[j]=np.mean(yp[ks]) + + if MakePlots: + xo=xo[0 :: 100] + yo=yo[0 :: 100] + fig = go.Figure() + fig.add_trace(go.Scatter(x=xss, y=yss,mode='markers',name='smoothed'))#,color='blue')) + # go.Scatter can't handle more than ~1 mm points- so this may not work + fig.add_trace(go.Scatter(x=xo , y=yo ,mode='markers',name='origonal'))#,color='red')) + fig.show() + + return point + +def ReadWriteCoast(fl): + + gdf = gpd.read_file(fl) + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + for k in range(0, n-1): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + if seg.geom_type=='LineString': + x,y = seg.coords.xy + if seg.geom_type=='Polygon': + bnd=seg.boundary + x,y = bnd.coords.xy + xp= np.array(x) + yp= np.array(y) + xss=np.append(xss,xp[:]) + yss=np.append(yss,yp[:]) + + n=xss.size + point=np.zeros((n,2), dtype=np.single) + np.savetxt('CoastPoints.txt', (yss, xss), delimiter=' ') + + point[:,0] = xss[:] + point[:,1] = yss[:] + return point diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py new file mode 100644 index 0000000..6355b23 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py @@ -0,0 +1,94 @@ + +import numpy as np +import netCDF4 as nc +import jigsawpy +import geopandas as gpd + +MakePlots=False +MakePlots=True + +if MakePlots: + import plotly.express as px + import plotly.graph_objects as go + + +def SmoothAndSubsampleCoastlineP(fl,dxS,dxI): + + gdf = gpd.read_file(fl) + shp = gdf.shape + n=shp[0] + N=np.zeros((n,), dtype=int) + for k in range(1, n): + if np.mod(k,1000)==0: + print("Loading Coastline: "+str(k)+" of "+str(n) ) + try: + seg=gdf.geometry[k-1] + bnd=seg.boundary + x,y = bnd.coords.xy + N[k-1]=x.size + except: + print("Error reading segment # "+str(k)) + N[k-1]=0 + + k = np.argmax(N) + m = np.max(N) + + print("smoothing "+str(n)+" coast segments. longest segment at "+str(k)+" of length "+str(m)) + #gdfS=gdf + xss=np.array([], dtype=np.single) + yss=np.array([], dtype=np.single) + + if MakePlots: + xo=np.array([], dtype=np.single) + yo=np.array([], dtype=np.single) + + for k in range(0, n-1): + if np.mod(k,100)==0: + print(str(k)+" "+str(n)) + seg=gdf.geometry[k] + bnd=seg.boundary + x,y = bnd.coords.xy + xp=numpy_array = np.array(x) + yp=numpy_array = np.array(y) + ymp=np.mean(yp) + dx=xp[:-1:] - xp[1::] + dy=yp[:-1:] - yp[1::] + lat2m=110574. + lon2m=111320.*np.cos(ymp*np.pi/180.) + d=np.sqrt( (dx*lon2m)**2 + (dy*lat2m)**2 ) + d=np.append(0,np.cumsum(d)) + nd=d.size-1 + npoints=int(np.ceil(d[nd]/dxS)) + di=np.linspace(d[0],d[nd],npoints) + ni=di.size + xi=np.zeros((ni,), dtype=np.single) + yi=np.zeros((ni,), dtype=np.single) + for j in range(0,ni): + ks=np.where( (d-di[j])**2 < dxS**2 ) + xi[j]=np.mean(xp[ks]) + yi[j]=np.mean(yp[ks]) + xss=np.append(xss,xi[:]) + yss=np.append(yss,yi[:]) + if MakePlots: + xo=np.append(xo,xp[:]) + yo=np.append(yo,yp[:]) + + n=xss.size + point=np.zeros((n,2), dtype=np.single) + + point[:,0] = xss[:] + point[:,1] = yss[:] + if MakePlots: +# fig = px.scatter(x=xss, y=yss, mode='markers', marker=dict(color='blue'), name='smoothed + subsampled coastline') +# fig = px.scatter(x=xss, y=yss) +# fig.add_trace(go.Scatter(x=xo, y=yo, mode='markers', marker=dict(color='red'), name='input coastline')) +# fig.show(renderer='browser') + xo=xo[0 :: 100] + yo=yo[0 :: 100] + fig = go.Figure() + fig.add_trace(go.Scatter(x=xss, y=yss,mode='markers',name='smoothed'))#,color='blue')) + # go.Scatter can't handle more than ~1 mm points- so this may not work + fig.add_trace(go.Scatter(x=xo , y=yo ,mode='markers',name='origonal'))#,color='red')) + fig.show() + + return point From 88420ed06a575c7774dc5a5c151b067eb30aa69a Mon Sep 17 00:00:00 2001 From: keston Date: Fri, 30 Jan 2026 15:01:16 -0500 Subject: [PATCH 02/44] clarifying edits and performance improvement --- .../RWPSMeshGenScript.py | 256 ++++++++++++++++++ .../matlab/RemoveMissingIslandsEle.m | 9 +- .../matlab/SmoothSubSampleCoastlineFast.m | 3 +- .../RWPSMeshtoolkit/matlab/edges2chainsG.m | 13 + 4 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py new file mode 100644 index 0000000..aa436c9 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py @@ -0,0 +1,256 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- +PSLGFile="GlobalCoastlineOSM.PSLG.msh" +DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" +TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" + +PSLGFile="PSLGboundaryGSHHS.msh" +DistanceToCoastFile="GlobalCoastlineGSHHS.PSLG.msh" +TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" + +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="Topo.DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" + +# directory to write output files to +OutDir='testOSMxGSHHS.BOXES/' + +ww3_mesh_file='RWPS.OSMxGSHHS.BOXES.msh' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=10000. +d1=320000. - d0 +beta=1000. +Smin=0.5 +Smax=10. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "jcfg.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m index 45d69f4..0b85002 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m @@ -27,7 +27,9 @@ p0=subpslgFast(p,jp); x=g0.x;y=g0.y;z=g0.z;e=g0.e; -chains=edges2chains(p0.edges); +chains=edges2chainsG(p0.edges); +%chains=edges2chains(p0.edges); + if isplot, figure(1);clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); @@ -42,7 +44,10 @@ if length(n)>2, if n(1)==n(end), %jins=find(inside(x,y,p0.x(n),p0.y(n))); - jins=find(inside(x,y,p0.x(n),p0.y(n))==1); + %jins=find(inside(x,y,p0.x(n),p0.y(n))==1); + [inP,onP]=insidepoly(x,y,p0.x(n),p0.y(n)); + jins=find(or(inP,onP)); + jb0=[jb0;jins(:)]; IsClosed(k)=1; hold on;plot(p0.x(n),p0.y(n),'gx-') diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m index ea462df..e59f7b2 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m @@ -3,7 +3,8 @@ %Sub sample coastline at dsmooth (m) distance. Boxcar smooth coastline to % dsmooth*lambda distance itz=0; -[xi,yi]=InterpCoastline1(x,y,DI,itz); +[xi,yi]=InterpCoastline(x,y,DI,itz); +%[xi,yi]=InterpCoastline1(x,y,DI,itz);%Creates problems with long gamma=2*lambda+1; ic=lambda+1; W=ones(1,gamma)/gamma; diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m new file mode 100644 index 0000000..992c4f9 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m @@ -0,0 +1,13 @@ +function chains=edges2chainsG(edges); + +G=graph(edges(:,1),edges(:,2)); +cycles = allcycles(G); +cc=0; +for k=1:length(cycles), + n=cycles{k}; + if length(n)>2, + n=[n(:);n(1)]; + cc=cc+1; + chains(cc).nodes=n; + end +end From 98b6c4732a56fe92ca47752018357071c32f3ee0 Mon Sep 17 00:00:00 2001 From: keston Date: Mon, 2 Feb 2026 09:56:16 -0500 Subject: [PATCH 03/44] some parameter changes and plot supresion in Post processing script --- .../PostProcessGrid.m | 387 +++++++++--------- .../RWPSMeshtoolkit/matlab/WriteWW3MeshX.m | 2 +- 2 files changed, 205 insertions(+), 184 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 24ac5a7..1413030 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -1,4 +1,5 @@ +isplot=0; outdir='RWPSMeshOSMxGSHHS.BoxesFiles/' pslgfile='PSLGboundaryOSMxGSHHS1kmBOXES.msh' jigsawout='RWPS.F.LLH' @@ -15,11 +16,11 @@ %g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); -gS=loadmshWW3('../RWPSLakes/Sebago.NWPS.WW3.msh'); +gS=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Sebago.NWPS.WW3.msh'); gS.x=gS.x-360; -gW=loadmshWW3('../RWPSLakes/Winnipesaukee.NWPS.WW3.msh') +gW=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes//RWPSLakes/Winnipesaukee.NWPS.WW3.msh') gW.x=gW.x-360; -gO=loadmshWW3('../RWPSLakes/Okeechobee.NWPS.WW3.msh') +gO=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes//RWPSLakes/Okeechobee.NWPS.WW3.msh') gO.x=gO.x-360; g=CombineMesh(g,gO); @@ -27,20 +28,21 @@ g=CombineMesh(g,gW); x=g.x;y=g.y;z=g.z;e=g.e; -LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); -clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; -caxis([0,12]) -colormap(flip(cm)); +if isplot, + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + caxis([0,12]) + colormap(flip(cm)); +end WriteWW3MeshX(g,'RWPS.WW3a.lakes.msh'); %clear g=loadmshWW3('RWPS.WW3a.lakes.msh') -%Remove key islands remaining in mesh -%load PSLGboundary1kmP_NewOrleans.mat -%p=loadmsh('PSLGboundaryOSMxGSHHS1kmBOXES.msh') +%Remove key islands remaining in mesh that are present in the PSLG file + p=loadmsh(pslgfile); p.x=p.point.coord(:,1); @@ -48,151 +50,168 @@ p.edges=p.edge2.index(:,1:2); p.x=p.x-360; x=g.x;y=g.y;z=g.z;e=g.e; -clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;axis equal; -hold on -plot(p.x,p.y,'k.') + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;axis equal; + hold on + plot(p.x,p.y,'k.') +end MinBndDist=1000; gnew=g; %go through all longitude and remove nodes -dx=1; +dx=2; +dxb=10 %close all -n=1; -if 1, - for xx=(ceil(min(g.x))+2*dx):dx:(floor(max(g.x))-2*dx) - ax11=[xx-dx,xx+dx,min(g.y)+dx,max(g.y)-dx] +RemoveIsl=1; +n=1 +if RemoveIsl, + for xx=(ceil(min(g.x))+dxb):dx:(floor(max(g.x))-dxb) + ax11=[xx-dx,xx+dx,min(g.y)+dxb,max(g.y)-dxb] N(n)=length(gnew.x); + AX(n,:)=ax11; gnew=RemoveMissingIslandsEle(gnew,ax11,p,MinBndDist,0); n=n+1; n/243 length(gnew.x) - figure(3);clf;plot(N,'ko-');pause(.001) + %figure(3);clf;plot(N,'ko-');pause(.001) end +% figure(3);clf;plot(AX(:,1),N,'ko-'); end g=gnew -save NoPacIslAll.mat g pslgfile p - +g=RemoveSandPointsWW3(g,'RWPS.WW3a1.lakes.msh') - - -clear -load NoPacIslAll.mat +p=loadmsh(pslgfile); +p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); x=g.x;y=g.y;z=g.z;e=g.e; -LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); +if isplot, + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + caxis([0,12]) + colormap(flip(cm)); + hold on; + plot(p.x,p.y,'k.'); +end -clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; -caxis([0,12]) -colormap(flip(cm)); -%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); p=loadmsh(pslgfile); p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); -hold on; -plot(p.x,p.y,'k.'); + g0=g; gnew=g -axAS =[ -179.6738 -159.5513 -18.4086 -7.1731] -%gnew=RemoveMissingIslandsEle(gnew,axAS,p,MinBndDist); -axis(axAS);pause(5) +if isplot + axAS =[ -179.6738 -159.5513 -18.4086 -7.1731] + axis(axAS);pause(5) -axTofol =[ -197.5575 -196.5479 4.8724 5.7902] -axis(axTofol);pause(5) + axTofol =[ -197.5575 -196.5479 4.8724 5.7902] + axis(axTofol);pause(5) -axPA = [-177.6646 -175.5927 -0.2906 1.3435] -%gnew=RemoveMissingIslandsEle(gnew,axPA,p,MinBndDist); -axis(axPA);pause(5) + axPA = [-177.6646 -175.5927 -0.2906 1.3435] + axis(axPA);pause(5) -axJA =[ -172.1141 -165.7656 14.1706 19.1777] -%gnew=RemoveMissingIslandsEle(gnew,axJA,p,MinBndDist); -axis(axJA);pause(5) + axJA =[ -172.1141 -165.7656 14.1706 19.1777] + axis(axJA);pause(5) -axMWI =[ -179.5965 -176.0019 27.0046 29.8397] -%gnew=RemoveMissingIslandsEle(gnew,axMWI,p,MinBndDist); -axis(axMWI);pause(5) + axMWI =[ -179.5965 -176.0019 27.0046 29.8397] + axis(axMWI);pause(5) -axTin=[-215.1401 -213.4623 14.3922 15.7155] -%gnew=RemoveMissingIslandsEle(gnew,axTin,p,MinBndDist); -axis(axTin);pause(5) + axTin=[-215.1401 -213.4623 14.3922 15.7155] + axis(axTin);pause(5) -axNNMI =[ -215.9834 -213.8052 19.3525 21.0704]; -%gnew=RemoveMissingIslandsEle(gnew,axNNMI,p,MinBndDist); -axis(axNNMI);pause(5) + axNNMI =[ -215.9834 -213.8052 19.3525 21.0704]; + axis(axNNMI);pause(5) -axNNMI1=[-214.8924 -213.6875 14.6480 15.5983]; -%gnew=RemoveMissingIslandsEle(gnew,axNNMI1,p,MinBndDist); -axis(axNNMI1);pause(5) + axNNMI1=[-214.8924 -213.6875 14.6480 15.5983]; + axis(axNNMI1);pause(5) -axMaj =[ -177.2629 -175.7651 -0.1340 1.0474] -%gnew=RemoveMissingIslandsEle(gnew,axMaj,p,MinBndDist); -axis(axMaj);pause(5) + axMaj =[ -177.2629 -175.7651 -0.1340 1.0474] + axis(axMaj);pause(5) -axHI =[ -179.1073 -153.7595 11.4935 31.4855] -%gnew=RemoveMissingIslandsEle(gnew,axHI,p,MinBndDist); -axis(axHI);pause(5) + axHI =[ -179.1073 -153.7595 11.4935 31.4855] + axis(axHI);pause(5) -axChuuk =[ -198.1190 -196.0417 4.7967 5.8354] -%gnew=RemoveMissingIslandsEle(gnew,axChuuk,p,MinBndDist); -axis(axChuuk);pause(5) + axChuuk =[ -198.1190 -196.0417 4.7967 5.8354] + axis(axChuuk);pause(5) +end -WriteWW3MeshX(gnew,'RWPS.WW3b.lakes.msh') %Fails +WriteWW3MeshX(gnew,'RWPS.WW3b.lakes.msh') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %fix new orleans clear g=loadmshWW3('RWPS.WW3b.lakes.msh') -x=g.x;y=g.y;z=g.z;e=g.e; -LS=ComputeLengthScale_wgs84_MEL(x,y,e); -LSn=Ele2Nodes(x,y,e,LS); -clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; -colormap(flip(cm)); -caxis([0,12]); - -S=shaperead('../NewOrleansCoast/mz03mr26_LIX.shp') -hold on -for k=1:length(S),plot(S(k).X,S(k).Y,'k');end - -axNOZ =[ -91.6701 -87.7499 28.7284 30.9173] -axis(axNOZ) -gnew=g; -%if nescesary run: -display('enter 1 if you want to edit the mesh around New Orleans' ) -gnew=RemoveMeshParts(g,axNOZ,S,[0,50]); - +%Examine and Hand Edit Mesh around new orleans to relect changes if nescesary +%Should not be nescesary with +if isplot, + x=g.x;y=g.y;z=g.z;e=g.e; + LS=ComputeLengthScale_wgs84_MEL(x,y,e); + LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,12]); + % Shape file of new marine zones in New Orleans + S=shaperead('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/mz03mr26_LIX.shp') + hold on + for k=1:length(S),plot(S(k).X,S(k).Y,'k');end + + axNOZ =[ -91.6701 -87.7499 28.7284 30.9173] + axis(axNOZ) + gnew=g; + eno=input('Enter 1 if you want to edit the mesh around New Orleans:' ) + if eno, + gnew=RemoveMeshParts(g,axNOZ,S,[0,50]); + else + gnew=g; + end +else + gnew=g;% no edit +end + WriteWW3MeshX(gnew,'RWPS.WW3c.lakes.msh') %confirm no introduction of sand points g=RemoveSandPointsWW3(gnew,'RWPS.WW3d.lakes.msh') -WriteWW3MeshX(g,'RWPS.WW3d.lakes.msh') +%WriteWW3MeshX(g,'RWPS.WW3d.lakes.msh') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Fix boundary warping from projection in mesh generation clear +close all g=loadmshWW3('RWPS.WW3d.lakes.msh') +g0=g; + Blon=[129.91 10.71] Blat=[-30.42 79.99] Blon(1)=Blon(1)-360 x=g.x;y=g.y;z=g.z;e=g.e; jb=g.bnd; - -clf; -plot(g.x(jb),g.y(jb),'k.');hold on +bnd0=detbndy(g.e) + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e')); + cm=colormap('jet');shading interp;hold on + colormap(flip(cm)); + axis equal;hold on + plot(g.x(jb),g.y(jb),'k.');hold on +end js=find(g.y(jb)max(Blat)); g.y(jb(js))=max(Blat); -plot(g.x(jb(js)),g.y(jb(js)),'r.') +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end -dx=.5; +%dx=degree latitude delta to discriminate land points near boundary from open ocean boundary +dx=.05; js=find(and( g.x(jb)>min(Blon),g.x(jb)max(Blon)-dx )); g.x(jb(js))=max(Blon); -plot(g.x(jb(js)),g.y(jb(js)),'r.') +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end WriteWW3MeshX(g,'RWPS.WW3e.lakes.msh') %confirm no introduction of sand points g0=RemoveSandPointsWW3(g,'RWPS.WW3f.lakes.msh') @@ -201,126 +220,128 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Some Plotting +if isplot, + g=g0; + clear + g=loadmshWW3('RWPS.WW3g.lakes.msh')%RWPS.PIXAllLnwps.PP.WW3c.msh'); + x=g.x;y=g.y;z=g.z;e=g.e; + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + jb=g.bnd; + hold on; + plot(g.x(jb),g.y(jb),'k.');hold on -clear -g=loadmshWW3('RWPS.WW3g.lakes.msh')%RWPS.PIXAllLnwps.PP.WW3c.msh'); -x=g.x;y=g.y;z=g.z;e=g.e; -LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); -clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; -jb=g.bnd; -hold on; -plot(g.x(jb),g.y(jb),'k.');hold on + f=z; + clf;patch(x(e'),y(e'),f(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,6000]); + kprint('Bathy.jpg'); + + clf; + caxis([0,6000]); + colormap(flip(cm)); -f=z; -clf;patch(x(e'),y(e'),f(e'));cm=colormap('jet');shading interp;axis equal; -colormap(flip(cm)); -caxis([0,6000]); -kprint('Bathy.jpg'); + hcb=colorbar('h','position',[.1,.075,.8,.025]) + %hcb.Label.String='(km)' + set(gca,'visible','off') + kprint('BathyColorbarH.jpg'); -clf; + clf; + colorbar; + colormap(flip(cm)); caxis([0,6000]); -colormap(flip(cm)); + kprint('BathyColorbarV.jpg'); - hcb=colorbar('h','position',[.1,.075,.8,.025]) - %hcb.Label.String='(km)' - set(gca,'visible','off') -kprint('BathyColorbarH.jpg'); -clf; -colorbar; -colormap(flip(cm)); -caxis([0,6000]); -kprint('BathyColorbarV.jpg'); + LS=ComputeLengthScale_wgs84_MEL(x,y,e); + LSn=Ele2Nodes(x,y,e,LS); + clf;patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,12]); + kprint('Lengthscale.jpg'); -LS=ComputeLengthScale_wgs84_MEL(x,y,e); -LSn=Ele2Nodes(x,y,e,LS); -clf;patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; -colormap(flip(cm)); -caxis([0,12]); -kprint('Lengthscale.jpg'); + axCAR =[ -85.4065 -61.7227 8.8200 26.8661] + ax=axCAR + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Caribean.jpg') -axCAR =[ -85.4065 -61.7227 8.8200 26.8661] -ax=axCAR -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('Caribean.jpg') + axAK =[ -192.1450 -152.2804 47.2479 77.6231] + ax=axAK + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Alaska.jpg') + axHI =[ -179.5950 -152.9066 13.8641 34.1996] + ax=axHI + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Hawaii.jpg') -axAK =[ -192.1450 -152.2804 47.2479 77.6231] -ax=axAK -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('Alaska.jpg') -axHI =[ -179.5950 -152.9066 13.8641 34.1996] -ax=axHI -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('Hawaii.jpg') + axMI =[ -220.2161 -208.6314 12.5003 21.3274]; + ax=axMI + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('MarianaIslands.jpg') + axAS =[ -173.3623 -168.3684 -16.4846 -12.0090] + ax=axAS + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('AmericanSamoa.jpg') -axMI =[ -220.2161 -208.6314 12.5003 21.3274]; -ax=axMI -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('MarianaIslands.jpg') -axAS =[ -173.3623 -168.3684 -16.4846 -12.0090] -ax=axAS -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('AmericanSamoa.jpg') + axMicro =[ -210.3818 -185.8701 -3.7494 15.5832] + ax=axMicro + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Micronesia.jpg') + axWMicro =[ -226.6896 -214.3594 5.3753 15.1002] + ax=axWMicro + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('WestMicronesia.jpg') -axMicro =[ -210.3818 -185.8701 -3.7494 15.5832] -ax=axMicro -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('Micronesia.jpg') -axWMicro =[ -226.6896 -214.3594 5.3753 15.1002] -ax=axWMicro -axis(ax);daspect([1,cos(pi*ax(3)/180),1]) -kprint('WestMicronesia.jpg') + figure; + clf; + caxis([0,12]); + colormap(flip(cm)); + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(km)' + set(gca,'visible','off') + kprint('LengthScaleColorbarH.jpg'); -figure; -clf; - caxis([0,12]); -colormap(flip(cm)); + clf + caxis([0,12]); + colormap(flip(cm)); - hcb=colorbar('h','position',[.1,.075,.8,.025]) - hcb.Label.String='(km)' - set(gca,'visible','off') -kprint('LengthScaleColorbarH.jpg'); + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(km)' + set(gca,'visible','off') + kprint('LengthScaleColorbarV.jpg'); -clf - caxis([0,12]); -colormap(flip(cm)); - % hcb=colorbar('v','position',[.1,.075,.8,.025]) - vcb=colorbar('v','position',[.075,.1,.025,.8]) - vcb.Label.String='(km)' - set(gca,'visible','off') -kprint('LengthScaleColorbarV.jpg'); + clf + caxis([0,6000]); + colormap(flip(cm)); + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(m)' + set(gca,'visible','off') + kprint('BathyColorbarH.jpg'); -clf -caxis([0,6000]); -colormap(flip(cm)); + clf + caxis([0,6000]); + colormap(flip(cm)); - hcb=colorbar('h','position',[.1,.075,.8,.025]) - hcb.Label.String='(m)' - set(gca,'visible','off') -kprint('BathyColorbarH.jpg'); + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(m)' + set(gca,'visible','off') + kprint('BathyColorbarV.jpg'); -clf - caxis([0,6000]); -colormap(flip(cm)); - - % hcb=colorbar('v','position',[.1,.075,.8,.025]) - vcb=colorbar('v','position',[.075,.1,.025,.8]) - vcb.Label.String='(m)' - set(gca,'visible','off') -kprint('BathyColorbarV.jpg'); -qi= \ No newline at end of file +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m index b4b03b8..81ac7ab 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m @@ -1,7 +1,7 @@ function WriteWW3MeshX(g,WW3FileOut) -OpenBndNodes=FindOuterBndWW3(g,0) +OpenBndNodes=FindOuterBndWW3(g,1) x=g.x;y=g.y;z=g.z;e=g.e; From f688015fe5403712324ece25cf6b98edc1b8c8ab Mon Sep 17 00:00:00 2001 From: keston Date: Mon, 2 Feb 2026 10:54:07 -0500 Subject: [PATCH 04/44] Some additional comments and edited paths in scripts to run on Ursa --- .../BuildBoundaryPSLGwGSHHS.m | 354 ++++++++++++++++++ .../BuildBoundaryPSLGwOSM.m | 351 +++++++++++++++++ .../MakeCoastalBoundariesGSHHS.m | 9 +- .../MakeCoastalBoundariesOSM.m | 8 +- .../MeshGenTemplateDirectory/MakeDfunGSHHS.m | 312 +++++++++++++++ .../MeshGenTemplateDirectory/MakeDfunOSM.m | 309 +++++++++++++++ .../MakeDfunOSMxGSHHS.m | 309 +++++++++++++++ .../PostProcessGrid.m | 45 ++- 8 files changed, 1686 insertions(+), 11 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m new file mode 100644 index 0000000..09951fc --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m @@ -0,0 +1,354 @@ +% Script to build PSLG based on Global Self-consistent, Hierarchical, High-resolution Geography Database (GSHHG). +% Data available at https://www.ngdc.noaa.gov/mgg/shorelines/shorelines.html +% Before running this script run script MakeCoastalBoundariesGSHHS.m to smooth curves in GSHHS data to reflect +% desired coastal resolution in final mesh. + +CoastLineFile = 'GlobalCoastlineGSHHS.shp' +lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; + +S=shaperead(CoastLineFile) +FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] +isplot=0; + +%load GlobalCoastlineOSM.mat + + +%The overall objective of this project is to develop and implement into operations +% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, +% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, +% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the +% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. + +%Blon=[129.91 10.71]; +%Blat=[-30.42 79.99]; +Blon=[lonWest, lonEast]; +Blat=[latSouth,latNorth]; + + +N=length(S); +N1=N; +for k=1:N + if mod(k,1000)==0,k/N,end + lon=S(k).X(1:end-1);%remove trailing nan + lat=S(k).Y(1:end-1); + ns(k)=length(lon); + jWest=find(lon<90); + if(length(jWest)==ns(k)); + S(k).X=[lon+360,NaN]; + end + if and(0length(jWest)),%make translated copy + display(['duplicating coastal segment: ',int2str(k), ', nseg=',int2str(ns(k))]) + N1=N1+1; + S(N1).X=[lon+360,NaN]; + S(N1).Y=[lat,NaN]; + ns(N1)=length(lon); + end +end +N=length(S); +[tmp,j]=sort(-ns); +S=S(j);% sort to descending in length +ns=ns(j);% sort to descending in length + +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; + +%Make Bounding rectangle +Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +clear pslg +sxp=[];syp=[ ]; +xc=[];yc=[]; +N=length(S); +pslg.x=[]; +pslg.y=[]; +pslg.edges=[]; +nc=0; + + +minedeges=4 % minimum number of edges in land bounadry feature to include +minarea=1 % minimum area for islands to be included in boundary (not used in this version) + +%Loop below finds intersection of boanary rectangle with coastline segments to create outer boandary + + +earth=referenceSphere('Earth'); +DXM=10^10;%DXM=1 +mdx=inf+ones(N,1); +for k=1:N + isinbox(k)=0; + x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) + y=S(k).Y(1:end-1); + mx=mean(x); + my=mean(y); + if length(x)>minedeges, + ji=find( insidepoly( x,y,Bx,By ) ); + if length(ji)>2 + [xi, yi,ii] = polyxpoly(x, y, Bx, By); + xc=[xc;xi(:)]; + yc=[yc;yi(:)]; + if ~isempty(xi) %modify ob + sxp=[sxp,x(1)];syp=[syp,y(1)]; + [iia,jja]=sort(ii(:,1));%sort to ascending order along segments + xia=xi(jja); + yia=yi(jja); + iis=ii(jja,1);%sorted into ascending order along segments + if ~insidepoly( x(1),y(1),Bx,By )% segment origonates outside box + nseg=length(xia); + for j=1:2:nseg-1, + xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; + ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + mdx(k)=max(dx); + + if max(dx) island entirely inside bounding box + xs=[x(1:end-1)]; + ys=[y(1:end-1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + if and(length(xs)>2,max(dx)3, ar> + if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end +end + +%OK - now revisit outer boundary! +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%restart script from here if needed +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%clear +%close all +eval(['load ',FileOutMatlab]); +%load pslgOSM.mat +%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +%make outer bound +n=length(pslg.x); +%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes +%pslg.y=[pslg.y,By(3:4)]; +pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes +pslg.y=[pslg.y,By(2:4)]; + +nc=length(pslg.chains);%add northwest and north east box corner chains +pslg.chains(nc+1).nodes=n+1; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+2; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+3; +nc=length(pslg.chains); + +xx =153.0400 %south east corner of Austrilia +yy = Blat(1) %check that these are the endpoints described for j0, j1!! +[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end + +xx = 288.3143%check that these are the endpoints described for j0, j1!! +yy = Blat(1) %south west corner of S. America +[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end + +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=[j0,j1]; +nc=length(pslg.chains); + +for k=1:nc + if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end + spx(k)=pslg.x(pslg.chains(k).nodes(1)); + spy(k)=pslg.y(pslg.chains(k).nodes(1)); + epx(k)=pslg.x(pslg.chains(k).nodes(end)); + epy(k)=pslg.y(pslg.chains(k).nodes(end)); + end + +%make boundary order index along boundary for start points +SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges +c=0*spy; +Deps1=10^-10 +j=find(abs(spy-By(1))v); +[mm,m]=min(c(j)); +l=j(m); +epi=[epi,pslg.chains(l).nodes]; +obc=[obc,l]; +n=0; +%while(epi(end)~=epi(1)) +while isempty( find(epi(2:end)==epi(1)) ) + v=d(l); + j=find(c>v); + [mm,m]=min(c(j)); + l=j(m) + epi=[epi,pslg.chains(l).nodes]; + obc=[obc,l]; + if isplot==1, plot(pslg.x(epi),pslg.y(epi),'r.-');pause(.001);end +end +j=find(epi(2:end)==epi(1)); +epi=epi(1:(j+1)); +%vvvvvvvvvvv Add fixed grid points on open boundary +% to prevent "curved" boundaries due to projection details +xob=pslg.x(epi); +yob=pslg.y(epi); +dob=abs([xob(2:end)-xob(1:end-1)]+i*[yob(2:end)-yob(1:end-1)]); +dob=[dob,abs([xob(end)-xob(1)]+i*[yob(1)-yob(end)])]; +nb=length(xob); +dmin=1;%node spacing around boundary +epit=epi; +for k=1:nb-1 + d=abs([xob(k+1)-xob(k)]+i*[yob(k+1)-yob(k)]); + if d>dmin + npl=round(d/dmin)-1; + dx=xob(k+1)-xob(k); + dy=yob(k+1)-yob(k); + xp=xob(k)+dx*[1:npl-1]/npl; + yp=yob(k)+dy*[1:npl-1]/npl; + np=length(xp); + n=length(pslg.x); + pslg.x=[pslg.x,xp]; + pslg.y=[pslg.y,yp]; + NewEdges=[[epi(k),n+1];[[n+1:n+np-1]',[n+2:n+np]'];[n+np,epi(k+1)]]; + %pslg.edges=[pslg.edges;NewEdges]; + j=find(epi(k)==epit ); + epit=[epit(1:j),n+1:n+np,epit(j+1:end)]; + end +end +epi=epit; +% to prevent "curved" boundaries due to projection details +%^^^^^^^^^^^^ Add fixed grid points on open boundary + + +% add edges in obc +epiv=epi(:); +NOE=length(epiv) +OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; +pslg.edges=[pslg.edges;OutterEdges]; + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +nodelist=[]; +for k=1:nc + if mod(k,100)==0,disp(['Finding interior chains compleate: ',num2str(k/nc)]);,end + if pslg.chains(k).nodes(1)==pslg.chains(k).nodes(end) + n=pslg.chains(k).nodes(1); + [inpoly,onpoly]=insidepoly( pslg.x(n), pslg.y(n),xob,yob); + if and(inpoly==1,onpoly==0) + nodelist=union(nodelist,pslg.chains(k).nodes); + end + end +end + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi']); + +nodelistXB=union(nodelist,epi); +pslgb=subpslgFast(pslg,nodelistXB); + +%remove "random" duplicate nodes +%z=pslgb.x+i*pslgb.y; +%[zu,j,k]=unique(z); +%pslgc=subpslgFast(pslgb,j); +pslgc=pslgb + +%remove duplicate edges +pslgc.edgesS=sort(pslgc.edges')'; +pslgc.edgesSU=unique(pslgc.edgesS,'rows') +pslgc.edges=pslgc.edgesSU; + +pslg=pslgc + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%save PSLG to jigsaw .msh format +geom=pslg2geom(pslg) +savemsh(FileOutJigsaw,geom) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m new file mode 100644 index 0000000..c5015fa --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m @@ -0,0 +1,351 @@ +% Script to build PSLG based on Open Street Map(OSM) ocastline database +% https://osmdata.openstreetmap.de/download/land-polygons-complete-4326.zip +% Before running this script run script MakeCoastalBoundariesOSM.m to smooth curves in GSHHS data to reflect +% desired coastal resolution in final mesh. + +CoastLineFile = 'GlobalCoastlineOSM.shp' +lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; + +S=shaperead(CoastLineFile) +FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] +isplot=0; + +%load GlobalCoastlineOSM.mat + + +%The overall objective of this project is to develop and implement into operations +% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, +% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, +% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the +% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. + +Blon=[lonWest, lonEast]; +Blat=[latSouth,latNorth]; + + +N=length(S); +N1=N; +for k=1:N + if mod(k,1000)==0,k/N,end + lon=S(k).X(1:end-1);%remove trailing nan + lat=S(k).Y(1:end-1); + ns(k)=length(lon); + jWest=find(lon<90); + if(length(jWest)==ns(k)); + S(k).X=[lon+360,NaN]; + end + if and(0length(jWest)),%make translated copy + display(['duplicating coastal segment: ',int2str(k), ', nseg=',int2str(ns(k))]) + N1=N1+1; + S(N1).X=[lon+360,NaN]; + S(N1).Y=[lat,NaN]; + ns(N1)=length(lon); + end +end +N=length(S); +[tmp,j]=sort(-ns); +S=S(j);% sort to descending in length +ns=ns(j);% sort to descending in length + +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; + +%Make Bounding rectangle +Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +clear pslg +sxp=[];syp=[ ]; +xc=[];yc=[]; +N=length(S); +pslg.x=[]; +pslg.y=[]; +pslg.edges=[]; +nc=0; + + +minedeges=4 % minimum number of edges in land bounadry feature to include +minarea=1 % minimum area for islands to be included in boundary (not used in this version) + +%Loop below finds intersection of boanary rectangle with coastline segments to create outer boandary + +earth=referenceSphere('Earth'); +DXM=10^10;%DXM=1 +mdx=inf+ones(N,1); +for k=1:N + isinbox(k)=0; + x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) + y=S(k).Y(1:end-1); + mx=mean(x); + my=mean(y); + if length(x)>minedeges, + ji=find( insidepoly( x,y,Bx,By ) ); + if length(ji)>2 + [xi, yi,ii] = polyxpoly(x, y, Bx, By); + xc=[xc;xi(:)]; + yc=[yc;yi(:)]; + if ~isempty(xi) %modify ob + sxp=[sxp,x(1)];syp=[syp,y(1)]; + [iia,jja]=sort(ii(:,1));%sort to ascending order along segments + xia=xi(jja); + yia=yi(jja); + iis=ii(jja,1);%sorted into ascending order along segments + if ~insidepoly( x(1),y(1),Bx,By )% segment origonates outside box + nseg=length(xia); + for j=1:2:nseg-1, + xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; + ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + mdx(k)=max(dx); + + if max(dx) island entirely inside bounding box + xs=[x(1:end-1)]; + ys=[y(1:end-1)]; + dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); + if and(length(xs)>2,max(dx)3, ar> + if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end +end + +%OK - now revisit outer boundary! +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%restart script from here if needed +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%clear +%close all +eval(['load ',FileOutMatlab]); +%load pslgOSM.mat +%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] + +%make outer bound +n=length(pslg.x); +%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes +%pslg.y=[pslg.y,By(3:4)]; +pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes +pslg.y=[pslg.y,By(2:4)]; + +nc=length(pslg.chains);%add northwest and north east box corner chains +pslg.chains(nc+1).nodes=n+1; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+2; +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=n+3; +nc=length(pslg.chains); + +xx =153.0400 %south east corner of Austrilia +yy = Blat(1) %check that these are the endpoints described for j0, j1!! +[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end + +xx = 288.3143%check that these are the endpoints described for j0, j1!! +yy = Blat(1) %south west corner of S. America +[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) +if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end + +nc=length(pslg.chains); +pslg.chains(nc+1).nodes=[j0,j1]; +nc=length(pslg.chains); + +for k=1:nc + if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end + spx(k)=pslg.x(pslg.chains(k).nodes(1)); + spy(k)=pslg.y(pslg.chains(k).nodes(1)); + epx(k)=pslg.x(pslg.chains(k).nodes(end)); + epy(k)=pslg.y(pslg.chains(k).nodes(end)); + end + +%make boundary order index along boundary for start points +SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges +c=0*spy; +Deps1=10^-10 +j=find(abs(spy-By(1))v); +[mm,m]=min(c(j)); +l=j(m); +epi=[epi,pslg.chains(l).nodes]; +obc=[obc,l]; +n=0; +%while(epi(end)~=epi(1)) +while isempty( find(epi(2:end)==epi(1)) ) + v=d(l); + j=find(c>v); + [mm,m]=min(c(j)); + l=j(m) + epi=[epi,pslg.chains(l).nodes]; + obc=[obc,l]; + if isplot==1, plot(pslg.x(epi),pslg.y(epi),'r.-');pause(.001);end +end +j=find(epi(2:end)==epi(1)); +epi=epi(1:(j+1)); +%vvvvvvvvvvv Add fixed grid points on open boundary +% to prevent "curved" boundaries due to projection details +xob=pslg.x(epi); +yob=pslg.y(epi); +dob=abs([xob(2:end)-xob(1:end-1)]+i*[yob(2:end)-yob(1:end-1)]); +dob=[dob,abs([xob(end)-xob(1)]+i*[yob(1)-yob(end)])]; +nb=length(xob); +dmin=1;%node spacing around boundary +epit=epi; +for k=1:nb-1 + d=abs([xob(k+1)-xob(k)]+i*[yob(k+1)-yob(k)]); + if d>dmin + npl=round(d/dmin)-1; + dx=xob(k+1)-xob(k); + dy=yob(k+1)-yob(k); + xp=xob(k)+dx*[1:npl-1]/npl; + yp=yob(k)+dy*[1:npl-1]/npl; + np=length(xp); + n=length(pslg.x); + pslg.x=[pslg.x,xp]; + pslg.y=[pslg.y,yp]; + NewEdges=[[epi(k),n+1];[[n+1:n+np-1]',[n+2:n+np]'];[n+np,epi(k+1)]]; + %pslg.edges=[pslg.edges;NewEdges]; + j=find(epi(k)==epit ); + epit=[epit(1:j),n+1:n+np,epit(j+1:end)]; + end +end +epi=epit; +% to prevent "curved" boundaries due to projection details +%^^^^^^^^^^^^ Add fixed grid points on open boundary + + +% add edges in obc +epiv=epi(:); +NOE=length(epiv) +OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; +pslg.edges=[pslg.edges;OutterEdges]; + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +nodelist=[]; +for k=1:nc + if mod(k,100)==0,disp(['Finding interior chains compleate: ',num2str(k/nc)]);,end + if pslg.chains(k).nodes(1)==pslg.chains(k).nodes(end) + n=pslg.chains(k).nodes(1); + [inpoly,onpoly]=insidepoly( pslg.x(n), pslg.y(n),xob,yob); + if and(inpoly==1,onpoly==0) + nodelist=union(nodelist,pslg.chains(k).nodes); + end + end +end + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi']); + +nodelistXB=union(nodelist,epi); +pslgb=subpslgFast(pslg,nodelistXB); + +%remove "random" duplicate nodes +%z=pslgb.x+i*pslgb.y; +%[zu,j,k]=unique(z); +%pslgc=subpslgFast(pslgb,j); +pslgc=pslgb + +%remove duplicate edges +pslgc.edgesS=sort(pslgc.edges')'; +pslgc.edgesSU=unique(pslgc.edgesS,'rows') +pslgc.edges=pslgc.edgesSU; + +pslg=pslgc + +eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); + +%save PSLG to jigsaw .msh format +geom=pslg2geom(pslg) +savemsh(FileOutJigsaw,geom) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m index bfc3680..4141fbe 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m @@ -1,5 +1,8 @@ function MakeCoastalBoundariesGSHHS +% Script to use Global Self-consistent, Hierarchical, High-resolution Geography Database (GSHHG) to create global land boundaries +% Data available at https://www.ngdc.noaa.gov/mgg/shorelines/shorelines.html + % make coastlines for mesh generation. %Islands smaller than a threshold area are excluded. %Narrow islands(some attols) with less than critical area are included if @@ -9,6 +12,7 @@ clear + isplot=0 deg2km=111.132954 deg2rad=pi/180 @@ -23,13 +27,14 @@ geom.mshID='EUCLIDEAN-MESH' geom.fileV = 3 -%filter out small islands + +%Use different island filtering with in Pacific rectangle: PacLon=[-140,140] PacLat=[-20,40]; earth=referenceSphere('Earth') -gcfl='../RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' +gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' S = shaperead(gcfl); N=length(S); isisland=zeros(N,1); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m index 6ef687d..2f32daf 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m @@ -1,4 +1,8 @@ function MakeCoastalBoundariesOSM + +% Script to use Open Street Map(OSM) coastline to create global land boundaries +% https://osmdata.openstreetmap.de/download/land-polygons-complete-4326.zip + %Islands smaller than a threshold area are excluded. %Narrow islands(some atolls) with less than critical area are included if %perimeter is longer than minPerimeter. Global and Pacific values are treated differently @@ -27,8 +31,8 @@ earth=referenceSphere('Earth') -%gcfl='/mnt/sda/keston/RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' -gcfl='../RWPS/Data/openstreetmap_land/land_polygons.shp' +gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/openstreetmap_land/land_polygons.shp' + S = shaperead(gcfl); N=length(S); isisland=zeros(N,1); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m new file mode 100644 index 0000000..ba1c40b --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m @@ -0,0 +1,312 @@ +%This script creates a "Distance to Coast file" using a US coastline file +% and custom specification of other designated points. The PSLG intended for creation of the boundary +% is used as well as a global bathymetry file and US coastline shapefile. + +clear +close all +isplot=0 + +%Input files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%PSLGfile='GlobalCoastlineOSM.PSLG.msh' +%PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' + +%Coastline Boundary file +PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%Global Bathymetry file (netcdf) +GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%Shape file with US coastline +uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' + +%Output files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Output "distance to coast" grided jigsaw .msh file +DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] +%Output bathymetry on same grid as DFunOutFile +TopoFile=['Topo.',DFunOutFile]; +%Temporary matlab file +FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] + + +US=shaperead(uscl); +NUS=length(US) +xus=[]; +yus=[]; +x0=[] +y0=[]; +interpDist=100. %meters +SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist +% then subsample soothed coastline every SmoothN points to create smaller +% coastline data set. i.e. remove small scale variation +for k=1:NUS + x=US(k).X(1:end-1); + y=US(k).Y(1:end-1); + x0=[x0,x]; + y0=[y0,y]; +% xs=x;ys=y; %1.5 mil points + if length(x)>3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; +xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; + +if isplot, + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +p.x=p.point.coord(:,1)-360; +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +j=find(xus>90); +xus(j)=xus(j)-360; + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; +yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; +j=find(xx>90); +xx(j)=xx(j)-360; +plot(xx,yy,'c.'); + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m new file mode 100644 index 0000000..8df6408 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m @@ -0,0 +1,309 @@ +%This script creates a "Distance to Coast file" using a US coastline file +% and custom specification of other designated points. The PSLG intended for creation of the boundary +% is used as well as a global bathymetry file and US coastline shapefile. + +clear +close all +isplot=0 + +%Input files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%Coastline Boundary file +PSLGfile='GlobalCoastlineOSM.PSLG.msh' +%Global Bathymetry file (netcdf) +GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%Shape file with US coastline +uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' + +%Output files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Output "distance to coast" grided jigsaw .msh file +DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] +%Output bathymetry on same grid as DFunOutFile +TopoFile=['Topo.',DFunOutFile]; +%Temporary matlab file +FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] + + +US=shaperead(uscl); +NUS=length(US) +xus=[]; +yus=[]; +x0=[] +y0=[]; +interpDist=100. %meters +SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist +% then subsample soothed coastline every SmoothN points to create smaller +% coastline data set. i.e. remove small scale variation +for k=1:NUS + x=US(k).X(1:end-1); + y=US(k).Y(1:end-1); + x0=[x0,x]; + y0=[y0,y]; +% xs=x;ys=y; %1.5 mil points + if length(x)>3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; +xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; + +if isplot, + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +p.x=p.point.coord(:,1)-360; +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +j=find(xus>90); +xus(j)=xus(j)-360; + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; +yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; +j=find(xx>90); +xx(j)=xx(j)-360; +plot(xx,yy,'c.'); + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m new file mode 100644 index 0000000..8513a3d --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m @@ -0,0 +1,309 @@ +%This script creates a "Distance to Coast file" using a US coastline file +% and custom specification of other designated points. The PSLG intended for creation of the boundary +% is used as well as a global bathymetry file and US coastline shapefile. + +clear +close all +isplot=0 + +%Input files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%Coastline Boundary file +PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' +%Global Bathymetry file (netcdf) +GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%Shape file with US coastline +uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' + +%Output files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Output "distance to coast" grided jigsaw .msh file +DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] +%Output bathymetry on same grid as DFunOutFile +TopoFile=['Topo.',DFunOutFile]; +%Temporary matlab file +FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] + + +US=shaperead(uscl); +NUS=length(US) +xus=[]; +yus=[]; +x0=[] +y0=[]; +interpDist=100. %meters +SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist +% then subsample soothed coastline every SmoothN points to create smaller +% coastline data set. i.e. remove small scale variation +for k=1:NUS + x=US(k).X(1:end-1); + y=US(k).Y(1:end-1); + x0=[x0,x]; + y0=[y0,y]; +% xs=x;ys=y; %1.5 mil points + if length(x)>3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +Blon=lon; +xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; + +if isplot, + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +p.x=p.point.coord(:,1)-360; +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +j=find(xus>90); +xus(j)=xus(j)-360; + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; +yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; +j=find(xx>90); +xx(j)=xx(j)-360; +plot(xx,yy,'c.'); + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=180+(lon(j)+180); +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 1413030..2672cfe 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -1,17 +1,34 @@ +%script to handle all post jigsaw mesh editing. +%Post processing steps are as follows +% (A) Remove sand points +% (B) Merge inland lakes --> 'RWPS.WW3a.lakes.msh' +% (C) Remove islands that jigsaw has meshed over +% (D) Remove sand points that can be created (rarely) with island removal --> 'RWPS.WW3a1.lakes.msh' +% INACTIVE (E) Examine Pacific island resolution and make changes to island editing if needed --> 'RWPS.WW3b.lakes.msh' +% INACTIVE (F) Examine mesh near New Orleans where boundary has been merged to reflect new marine zones --> 'RWPS.WW3c.lakes.msh' +% INACTIVE (G) Remove sand points that can be created (rarely) with New Orleans editing --> 'RWPS.WW3d.lakes.msh' +% (H) Stretch open ocean boundary nodes back to origonal specified boundary rectangle --> 'RWPS.WW3e.lakes.msh' +% this is an artificat of the projection used in jigsaw +% (I) Remove sand points that can be created (Should not matter) with boundary node stretching --> 'RWPS.WW3f.lakes.msh' +% (J) Write final WW3 mesh --> 'RWPS.WW3g.lakes.msh' +% this is the mesh to run WW3 on. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: isplot=0; outdir='RWPSMeshOSMxGSHHS.BoxesFiles/' pslgfile='PSLGboundaryOSMxGSHHS1kmBOXES.msh' jigsawout='RWPS.F.LLH' -%g=loadmsh('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.msh') +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% g=loadmsh([outdir,jigsawout,'.msh']); %remove sand points on boundary -%RemoveSandPoints('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.msh','PSLGboundaryOSMxGSHHS1kmBOXES.msh',... -% 'RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.msh','RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh');%ileOutJigsawMesh,FileOutWW3) + RemoveSandPoints([outdir,jigsawout,'.msh'],pslgfile,[outdir,jigsawout,'.NSP.msh'],[outdir,jigsawout,'.NSP.WW3.msh']); +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (B) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %Add Lakes to Mesh %g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); @@ -39,6 +56,8 @@ WriteWW3MeshX(g,'RWPS.WW3a.lakes.msh'); +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (C) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %clear g=loadmshWW3('RWPS.WW3a.lakes.msh') %Remove key islands remaining in mesh that are present in the PSLG file @@ -82,8 +101,13 @@ g=gnew + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (D) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + g=RemoveSandPointsWW3(g,'RWPS.WW3a1.lakes.msh') +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (E) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + p=loadmsh(pslgfile); p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); @@ -140,7 +164,8 @@ WriteWW3MeshX(gnew,'RWPS.WW3b.lakes.msh') -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (F) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %fix new orleans clear g=loadmshWW3('RWPS.WW3b.lakes.msh') @@ -172,11 +197,13 @@ end WriteWW3MeshX(gnew,'RWPS.WW3c.lakes.msh') + %confirm no introduction of sand points +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (G) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% g=RemoveSandPointsWW3(gnew,'RWPS.WW3d.lakes.msh') -%WriteWW3MeshX(g,'RWPS.WW3d.lakes.msh') -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (H) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Fix boundary warping from projection in mesh generation clear close all @@ -213,12 +240,16 @@ g.x(jb(js))=max(Blon); if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end WriteWW3MeshX(g,'RWPS.WW3e.lakes.msh') + %confirm no introduction of sand points +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (I) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% g0=RemoveSandPointsWW3(g,'RWPS.WW3f.lakes.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (J) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% WriteWW3MeshX(g0,'RWPS.WW3g.lakes.msh') -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Some Plotting if isplot, g=g0; From d37b024b04fd58f0f3260cb6635099259a5d9f93 Mon Sep 17 00:00:00 2001 From: keston Date: Mon, 2 Feb 2026 11:29:57 -0500 Subject: [PATCH 05/44] added scripts for merging OSM and GSHHS PSLGs based on geographic region --- .../MergePslgsOSMxGSSHS.m | 43 ++++++----- .../MergePslgsOSMxGSSHS_14N230W.m | 77 +++++++++++++++++++ 2 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m index cade447..cd787cb 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m @@ -1,10 +1,7 @@ -%OSMmsh='./PSLGboundary1kmP_NewOrleans.OSM.msh' -%GSHHGmsh='./PSLGboundary1kmP_NewOrleansB.msh' -isplot=0 -OSMmsh='./GlobalCoastlineOSM.PSLG.msh' -GSHHGmsh='./GlobalCoastlineGSHHS.PSLG.msh' +OSMmsh='./PSLGboundary1kmP_NewOrleans.OSM.msh' +GSHHGmsh='./PSLGboundary1kmP_NewOrleansB.msh' p0=loadmsh(OSMmsh) p1=loadmsh(GSHHGmsh) @@ -17,29 +14,35 @@ p1.y=p1.point.coord(:,2); p1.edges=p1.edge2.index(:,1:2); +close all +clf; +plot(p0.x,p0.y,'b.',p1.x,p1.y,'r.'); +axis equal; +hold on axAS = [183.0293 191.6089 -24.5496 -11.9295] +BoundingBox(axAS(1:2),axAS(3:4),'c') + axPalau =[ 130.8368 141.8230 3.9914 10.1256] +BoundingBox(axPalau(1:2),axPalau(3:4),'c') + axSP =[ 211.0219 220.1817 -18.9565 -13.8421] +BoundingBox(axSP(1:2),axSP(3:4),'c') + axCP =[ 151.1962 152.3336 6.9451 7.5801] +BoundingBox(axCP(1:2),axCP(3:4),'c') + axGOM =[ 290.8507 291.1934 43.7119 43.9032] +BoundingBox(axGOM(1:2),axGOM(3:4),'c') + axCar =[ 272.0041 272.7733 17.1417 17.5712] +BoundingBox(axCar(1:2),axCar(3:4),'c'); + axCarB =[ 272.9356 274.2177 16.0475 16.7634]; +BoundingBox(axCarB(1:2),axCarB(3:4),'c'); AX=[axAS;axPalau;axSP;axCP;axGOM;axCar;axCarB] -[nax,four]=size(AX) - -if isplot, - close all - clf; - plot(p0.x,p0.y,'b.',p1.x,p1.y,'r.'); - axis equal; - hold on - for k=1:nax - ax=AX(k,:); - BoundingBox(ax(1:2),ax(3:4),'c'); - end -end +[nax,four]=size(AX); p=p1;%gshhs baseline for k=1:nax j0=FindPointsAx(AX(k,:),p0.x,p0.y); @@ -53,11 +56,11 @@ end pslg=p; -save pslgOSMxGSHHS.BOXES.mat pslg +save pslgOSMxGSHHS1kmBOXES.mat pslg geom=pslg2geom(pslg) -savemsh('PSLGboundaryOSMxGSHHS.BOXES.msh',geom) +savemsh('PSLGboundaryOSMxGSHHS1kmBOXES.msh',geom) hold on; plot(p.x,p.y,'k.'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m new file mode 100644 index 0000000..e5067d4 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m @@ -0,0 +1,77 @@ + + +OSMmsh='../RWPSmeshtrial.OSM/PSLGboundary1kmP_NewOrleans.msh' +GSHHGmsh='../RWPSmeshtrial.PIXX.AP1km/PSLGboundary1kmP_NewOrleans.msh' +p0=loadmsh(OSMmsh) +p1=loadmsh(GSHHGmsh) + +p0.x=p0.point.coord(:,1); +p0.y=p0.point.coord(:,2); +p0.edges=p0.edge2.index(:,1:2); + + +p1.x=p1.point.coord(:,1); +p1.y=p1.point.coord(:,2); +p1.edges=p1.edge2.index(:,1:2); + +close all +plot(p0.x,p0.y,'b.',p1.x,p1.y,'r.') + +yc=14.5 +xc=230 +jx0=find(p0.xyc ) +nb=find(p.y(j)xc ) +nb=find(p.x(j) Date: Mon, 2 Feb 2026 16:42:44 +0000 Subject: [PATCH 06/44] added jobcards for matlab and python scripts for Ursa --- .../FilterRoutinesNM.py | 4 +-- .../RWPSMeshGenScript.py | 7 +++- .../MeshGenTemplateDirectory/jigsaw.ursa.job | 32 +++++++++++++++++++ .../jobcard.matlab.postjigsaw | 16 ++++++++++ .../jobcard.matlab.prejigsaw | 16 ++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py index 1a7a733..6daaf82 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py @@ -64,8 +64,8 @@ def inject_dem(): #dem_file = configurations['dem_file'] #data = nc.Dataset(dem_file,"r") - data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") - +# data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") + data = nc.Dataset("/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") xlon = np.asarray(data["lon"][:]) ylat = np.asarray(data["lat"][:]) elev = np.asarray(data["bed_elevation"][:]) + \ diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py index aa436c9..d047e99 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py @@ -10,14 +10,19 @@ from scipy.interpolate import RegularGridInterpolator #-------------------Input Files---------------------------------------- + +""" +#GSHHS coastline PSLGFile="GlobalCoastlineOSM.PSLG.msh" DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" +#OSM coastline PSLGFile="PSLGboundaryGSHHS.msh" DistanceToCoastFile="GlobalCoastlineGSHHS.PSLG.msh" TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" - +""" +# GSHHS except identified problem spots (i.e. American Samoa) where OSM is used #jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline PSLGFile="PSLGboundaryOSMxGSHHS.BOXES.msh" #jigsaw gridded .msh format Distance to taget poings diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job new file mode 100644 index 0000000..441aae6 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job @@ -0,0 +1,32 @@ +#!/bin/bash +#SBATCH --job-name=jigsaw_py_RWPSng # Job name +#SBATCH --mail-type=END # Mail events (BEGIN, END, FAIL, ALL) +#SBATCH --mail-user=keston.smith@noaa.gov # Where to send mail +##SBATCH --ntasks=144 # Number of MPI ranks +#SBATCH --mem-per-cpu=256000mb # Memory per processor +#SBATCH --time=08:00:00 # Time limit hrs:min:sec +#SBATCH --output=mpi_test_%j.log # Standard output/error +#SBATCH --exclusive=user +#SBATCH --error=%j.err +##SBATCH --partition=marine-cpu +#SBATCH --account=marine-cpu +#SBATCH --nodes=1 +#SBATCH --ntasks=1 + + + +module purge +module use ../../global-workflowA/sorc/ufs_model.fd/modulefiles/ +module load ufs_ursa.intel +module load stack-oneapi/2024.2.1 +module load python/3.11 +module load cmake/3.27.9 + +module load py-numpy/1.26.4 +module load ufs_ursa.intel +module load py-netcdf4/1.7.1.post2 + +source ../../UrsaMeshgenEnv/jigsawenv/bin/activate +pip list -v + +python3 RWPS.ng.NoFiltrsOpts.py > NonGlobalMeshGen.out.txt diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw new file mode 100644 index 0000000..a630465 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw @@ -0,0 +1,16 @@ +#!/bin/sh +#SBATCH --nodes=1 +#SBATCH --ntasks=32 # Number of tasks/cores +#SBATCH --ntasks-per-node=32 +#SBATCH -q batch +#SBATCH -t 08:00:00 +#SBATCH -A marine-cpu +#SBATCH -J ml_test +#SBATCH -o ml_test.out + + +# Load the MATLAB module +module load matlab/R2024b # Specify the version you need + +# Run your MATLAB script without a graphical interface +matlab -nodisplay -nodesktop -r "run('./PostProcessGrid.m'); exit;" diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw new file mode 100644 index 0000000..00fe43d --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw @@ -0,0 +1,16 @@ +#!/bin/sh +#SBATCH --nodes=1 +#SBATCH --ntasks=32 # Number of tasks/cores +#SBATCH --ntasks-per-node=32 +#SBATCH -q batch +#SBATCH -t 08:00:00 +#SBATCH -A marine-cpu +#SBATCH -J ml_test +#SBATCH -o ml_test.out + + +# Load the MATLAB module +module load matlab/R2024b # Specify the version you need + +# Run your MATLAB script without a graphical interface +matlab -nodisplay -nodesktop -r "run('./GenGHHSMesh.m'); exit;" From 3d37fff617d3180c76243ca7d3ffcbc02f473853 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Mon, 2 Feb 2026 16:45:45 +0000 Subject: [PATCH 07/44] added jobcards for matlab and python scripts for Ursa and fixed file path --- .../RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job index 441aae6..4cbb45e 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job @@ -29,4 +29,4 @@ module load py-netcdf4/1.7.1.post2 source ../../UrsaMeshgenEnv/jigsawenv/bin/activate pip list -v -python3 RWPS.ng.NoFiltrsOpts.py > NonGlobalMeshGen.out.txt +python3 RWPSMeshGenScript.py > NonGlobalMeshGen.out.txt From feafe6c47b8195e5f8476c0de536c3745f664ebf Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Mon, 2 Feb 2026 17:14:33 +0000 Subject: [PATCH 08/44] fixed path for python environment --- .../MeshGenTemplateDirectory/jigsaw.ursa.job | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job index 4cbb45e..6a3ddff 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job @@ -16,7 +16,7 @@ module purge -module use ../../global-workflowA/sorc/ufs_model.fd/modulefiles/ +module use /scratch3/NCEPDEV/climate/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles/ module load ufs_ursa.intel module load stack-oneapi/2024.2.1 module load python/3.11 @@ -26,7 +26,7 @@ module load py-numpy/1.26.4 module load ufs_ursa.intel module load py-netcdf4/1.7.1.post2 -source ../../UrsaMeshgenEnv/jigsawenv/bin/activate +source /scratch3/NCEPDEV/climate/Keston.Smith/UrsaMeshgenEnv/jigsawenv/bin/activate pip list -v -python3 RWPSMeshGenScript.py > NonGlobalMeshGen.out.txt +python3 RWPSMeshGenScript.NewOrleans.py > NonGlobalMeshGen.out.txt From 145a8851ad8867a7b8cb061d9e19064576f405ad Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Mon, 2 Feb 2026 18:14:29 +0000 Subject: [PATCH 09/44] simplified path specification for matlab scripts --- .../MeshGenTemplateDirectory/PostProcessGrid.m | 12 ++++++++---- .../MeshGenTemplateDirectory/PreProcessCoastline.m | 13 +++++++++++++ .../MeshGenTemplateDirectory/SetPath.m | 4 ++++ .../jobcard.matlab.postjigsaw | 4 ++-- .../jobcard.matlab.prejigsaw | 6 +++--- 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 2672cfe..21bbad3 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -1,4 +1,8 @@ +addpath ../matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + %script to handle all post jigsaw mesh editing. %Post processing steps are as follows % (A) Remove sand points @@ -16,8 +20,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: isplot=0; -outdir='RWPSMeshOSMxGSHHS.BoxesFiles/' -pslgfile='PSLGboundaryOSMxGSHHS1kmBOXES.msh' +outdir='RWPSWithNewOrleans/' +pslgfile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS1kmBOXES.msh' jigsawout='RWPS.F.LLH' %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -35,9 +39,9 @@ gS=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Sebago.NWPS.WW3.msh'); gS.x=gS.x-360; -gW=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes//RWPSLakes/Winnipesaukee.NWPS.WW3.msh') +gW=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Winnipesaukee.NWPS.WW3.msh') gW.x=gW.x-360; -gO=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes//RWPSLakes/Okeechobee.NWPS.WW3.msh') +gO=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Okeechobee.NWPS.WW3.msh') gO.x=gO.x-360; g=CombineMesh(g,gO); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m new file mode 100644 index 0000000..84c7bd5 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m @@ -0,0 +1,13 @@ + +%addpath ../matlab +%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab +%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + +SetPath + +MakeCoastalBoundariesGSHHS +BuildBoundaryPSLGwGSHHS +MakeDfunGSHHS + + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m new file mode 100644 index 0000000..50d757f --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m @@ -0,0 +1,4 @@ +addpath ../matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw index a630465..5499005 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw @@ -5,8 +5,8 @@ #SBATCH -q batch #SBATCH -t 08:00:00 #SBATCH -A marine-cpu -#SBATCH -J ml_test -#SBATCH -o ml_test.out +#SBATCH -J MeshPostProcess +#SBATCH -o MeshPostProcess.out # Load the MATLAB module diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw index 00fe43d..9227942 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw @@ -5,12 +5,12 @@ #SBATCH -q batch #SBATCH -t 08:00:00 #SBATCH -A marine-cpu -#SBATCH -J ml_test -#SBATCH -o ml_test.out +#SBATCH -J MeshPreProcess +#SBATCH -o MeshPreProcess.out # Load the MATLAB module module load matlab/R2024b # Specify the version you need # Run your MATLAB script without a graphical interface -matlab -nodisplay -nodesktop -r "run('./GenGHHSMesh.m'); exit;" +matlab -nodisplay -nodesktop -r "run('./PreProcessCoastline.m'); exit;" From 1e588c913239af5d5081dba89dd6e978ac3752bb Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Mon, 2 Feb 2026 18:42:25 +0000 Subject: [PATCH 10/44] added README file pointing to online documentation --- unst_msh_gen/RWPSMeshtoolkit/README.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/README.txt diff --git a/unst_msh_gen/RWPSMeshtoolkit/README.txt b/unst_msh_gen/RWPSMeshtoolkit/README.txt new file mode 100644 index 0000000..d6b55dc --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/README.txt @@ -0,0 +1,5 @@ +Documentation currently in slideshow format at: + +https://docs.google.com/presentation/d/1P7M8eI6AkELXyCL1E4VQZSmJUk0EUZ344zdyeifffn8 + +Text documentation will be added later. From 5f014b2d3ebdfdba0d2e44047cf16e455bee325b Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Tue, 3 Feb 2026 12:39:16 +0000 Subject: [PATCH 11/44] cleared some unused statements --- .../MeshGenTemplateDirectory/PostProcessGrid.m | 10 +++++----- .../MeshGenTemplateDirectory/PreProcessCoastline.m | 3 --- .../MeshGenTemplateDirectory/jigsaw.ursa.job | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 21bbad3..1ec1bc7 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -20,7 +20,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: isplot=0; -outdir='RWPSWithNewOrleans/' +outdir='testOSMxGSHHS.BOXES/' pslgfile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS1kmBOXES.msh' jigsawout='RWPS.F.LLH' @@ -62,7 +62,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (C) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%clear +%%clear g=loadmshWW3('RWPS.WW3a.lakes.msh') %Remove key islands remaining in mesh that are present in the PSLG file @@ -171,7 +171,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (F) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %fix new orleans -clear +%clear g=loadmshWW3('RWPS.WW3b.lakes.msh') %Examine and Hand Edit Mesh around new orleans to relect changes if nescesary %Should not be nescesary with @@ -209,7 +209,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (H) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Fix boundary warping from projection in mesh generation -clear +%clear close all g=loadmshWW3('RWPS.WW3d.lakes.msh') g0=g; @@ -259,7 +259,7 @@ g=g0; - clear + %clear g=loadmshWW3('RWPS.WW3g.lakes.msh')%RWPS.PIXAllLnwps.PP.WW3c.msh'); x=g.x;y=g.y;z=g.z;e=g.e; LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m index 84c7bd5..7986015 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m @@ -1,7 +1,4 @@ -%addpath ../matlab -%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab -%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly SetPath diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job index 6a3ddff..ae23550 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job @@ -29,4 +29,4 @@ module load py-netcdf4/1.7.1.post2 source /scratch3/NCEPDEV/climate/Keston.Smith/UrsaMeshgenEnv/jigsawenv/bin/activate pip list -v -python3 RWPSMeshGenScript.NewOrleans.py > NonGlobalMeshGen.out.txt +python3 RWPSMeshGenScript.py > NonGlobalMeshGen.out.txt From bb2308092e351cd72e292f05ec58c4056a2380d1 Mon Sep 17 00:00:00 2001 From: keston Date: Tue, 3 Feb 2026 11:39:50 -0500 Subject: [PATCH 12/44] added bathymetry interpolation routines to archive --- .../InterpolateBathymetry/AddBathyToMesh.py | 37 + .../FiniteElementMeshRoutines.py | 228 +++ .../InterpolateBathymetry/GaussMarkov.py | 134 ++ .../InterpolateCRM.partscat.py | 335 ++++ .../KnitOutputBackTogether.py | 41 + .../MakeCommonNetCDFFileFormat.py | 437 +++++ .../SmoothSubsampleCMEMS.py | 116 ++ .../SmoothSubsampleNetCDFFiles.py | 135 ++ .../meshes/HawaiiTest.msh | 1689 +++++++++++++++++ 9 files changed, 3152 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleCMEMS.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/meshes/HawaiiTest.msh diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py new file mode 100644 index 0000000..89c6704 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py @@ -0,0 +1,37 @@ + +# +# Function for taking bathymetry field in a text file and replacing bathymetry +# from a WW3 .msh files with the values from the file specified on the command +# line: +# +# $python3 AddBathyToMesh.py MyBathy.txt +# +# creates a new WW3 mesh with bathymetry from MyBathy.txt +# +# + +import FiniteElementMeshRoutines as FE +import numpy as np +import sys + +mshnm="HawaiiTest" +mesh="meshes/"+mshnm+".msh" + +flin=sys.argv[1] +flout=flin+".WW3.msh" + +x, y, z0, e, bnd = FE.loadWW3Mesh(mesh) + +zmin=1. +nn=len(x) +z=np.zeros(nn) +f=open(flin, 'r') +for k in range(nn): + line=f.readline() + #print(str(k)+" "+line) + z[k]=float(line.strip()) + z[k]=-z[k] + z[k]=max(z[k],zmin) +f.close +FE.WriteWW3Mesh(flout,x,y,z,e,bnd) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py new file mode 100644 index 0000000..993760e --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py @@ -0,0 +1,228 @@ +# +# Functions for reading and writing WW3 meshes, calculating element +# area, and estimateing mesh length scale. +# +# x and y are length nn node coordinates +# e is a (Number-of-Elements by 3) element array +# bnd is a length nb list of open ocean boundary nodes +# Note:(nodes are assumed to be indexed from 1,2,...,nn within e +# and bnd) +# +# loadWW3MeshCoords(fl): read mesh nodes and elements from file +# +# loadWW3Mesh(fl): read mesh nodes, elements, and open boundary nodes +# from WW3 .msh file +# +# WriteWW3Mesh(flo,x,y,z,e,bnd): write WW3 .msh file +# +# lengthscale(x, y, e): compute length scale for each element +# +# ElementArea(x, y, e): compute area for each element +# +# ComputeNodeLengthScale(x,y,e): estimate length scale at each node +# + +import numpy as np +import math +#from geopy import distance +import re + +# Simple distance approximation in kilometers for calculating element +# area and lengthscale. +deg2km=111.132954 +deg2rad=np.pi/180. +def Distance(x0,y0,x1,y1): + d=np.sqrt( + ( deg2km*np.cos(deg2rad*(y0+y1)/2 )*(x1-x0) )**2 + + ( deg2km*(y1-y0))**2 ) + return d + +def loadWW3MeshCoords(fl): + f=open(fl, 'r') + header = f.readline() + header = f.readline() + header = f.readline() + header = f.readline() + header = f.readline() # number of nodes + nn = re.findall(r'\d+', header) + nn=int(nn[0]) + print(nn) + xi=np.zeros(nn) + yi=np.zeros(nn) + k=0 + for i in range(nn): + A = f.readline() + values = A.split(" ") + if len(values)>4: + xi[k]=values[2] + yi[k]=values[4] + else: + xi[k]=values[1] + yi[k]=values[2] + k=k+1 + print("number of nodes read: "+str(k)) + header = f.readline() + header = f.readline() + header = f.readline() # number of elements + ne=int(header) + print("ne=",str(ne)) + ei=np.zeros((ne,3), dtype=int) + k=0 + for i in range(ne): + A = f.readline() + values = A.split(" ") + #need to factor bnd nodes + if len(values)>15: + ei[k,0]=int(values[12]) + ei[k,1]=int(values[14]) + ei[k,2]=int(values[16]) + k=k+1 + elif len(values)>7: + ei[k,0]=int(values[6]) + ei[k,1]=int(values[7]) + ei[k,2]=int(values[8]) + k=k+1 + print("number of elements read: "+str(k)) + return xi, yi, ei + + +def loadWW3Mesh(fl): + f=open(fl, 'r') + header = f.readline() + header = f.readline() + header = f.readline() + header = f.readline() + header = f.readline() # number of nodes + nn=int(header) + print("nn = "+str(nn)) + xi=np.zeros(nn) + yi=np.zeros(nn) + zi=np.zeros(nn) + k=0 + for i in range(nn): + A = f.readline() + values = A.split(" ") + if len(values)>4: + xi[k]=values[2] + yi[k]=values[4] + zi[k]=values[6] + else: + xi[k]=values[1] + yi[k]=values[2] + zi[k]=values[3] + k=k+1 + print("number of nodes read: "+str(k)) + header = f.readline() + header = f.readline() + header = f.readline() # number of elements + ne=int(header)#includes boundary nodes and actual elements + print("ne="+str(ne)+" -includes boundary nodes") + nbnd=0 + bnd=[] + eix=np.zeros((ne,3), dtype=int) + k=0 + for i in range(ne): + A = f.readline() + values = A.split(" ") + if len(values) == 6: + if int(values[2])==2: + bnd.append(int(values[5])) + nbnd=nbnd+1 + if len(values)>15: + eix[k,0]=int(values[12]) + eix[k,1]=int(values[14]) + eix[k,2]=int(values[16]) + k=k+1 + elif len(values)>7: + eix[k,0]=int(values[6]) + eix[k,1]=int(values[7]) + eix[k,2]=int(values[8]) + k=k+1 + ei=eix[range(k),:] + print("number of open boundary nodes read: "+str(nbnd)) + print("number of elements read: "+str(k)) + return xi, yi, zi, ei, bnd + +def WriteWW3Mesh(flo,x,y,z,e,bnd): + f=open(flo, 'w') + f.write("$MeshFormat\n") + f.write("2 0 8\n") + f.write("$EndMeshFormat\n") + f.write("$Nodes\n") + nn=len(x) + f.write(str(nn)+"\n") + for k in range(nn): + f.write(f"{k+1:8d} {x[k]:6f} {y[k]:6f} {z[k]:5f} \n") + ne=e.shape[0] + nbnd=len(bnd) + f.write("$EndNodes\n") + f.write("$Elements\n") + f.write(str(ne+nbnd)+"\n") + for k in range(nbnd): + f.write(str(k+1)+" 15 2 0 0 " + str(bnd[k])+"\n") + for k in range(ne): + f.write(str(nbnd+k+1)+" 2 3 0 "+str(k+1)+" 0 "+str(e[k,0])+" "+str(e[k,1])+" "+str(e[k,2])+"\n") + f.write("$EndElements\n") + f.close + +# compute length scale for each element e +def lengthscale(x, y, e): + ne=e.shape[0] + lengthscaleE=np.zeros(ne) + for k in range(ne): + if k % 10000 ==0: + print(k) + x1=x[e[k,0]-1] + y1=y[e[k,0]-1] + x2=x[e[k,1]-1] + y2=y[e[k,1]-1] + x3=x[e[k,2]-1] + y3=y[e[k,2]-1] + D3=Distance(x1,y1,x2,y2) + D1=Distance(x2,y2,x3,y3) + D2=Distance(x3,y3,x1,y1) + lengthscaleE[k]=(D1+D2+D3)/3 + # mean edge length + return lengthscaleE + +# compute area for each element e +def ElementArea(x, y, e): + ne=e.shape[0] + AreaE=np.zeros(ne) + for k in range(ne): + if k % 10000 ==0: + print(k) + x1=x[e[k,0]-1]; + y1=y[e[k,0]-1]; + x2=x[e[k,1]-1]; + y2=y[e[k,1]-1]; + x3=x[e[k,2]-1]; + y3=y[e[k,2]-1]; + D3=Distance(x1,y1,x2,y2) + D1=Distance(x2,y2,x3,y3) + D2=Distance(x3,y3,x1,y1) + S=(D1+D2+D3)/2 + A=np.sqrt(S * (S - D1) * (S - D2) * (S - D3)) + AreaE[k]=A + return AreaE + +# approximate mesh lengthscale at mesh nodes. +# lengthscale is the weighted average (by area) of surrounding elements +def ComputeNodeLengthScale(x,y,e): + nn=np.max(e[:]) + print("ComputeNodeLengthScale nn="+str(nn)) + areaE=ElementArea(x, y, e) + LengthScaleE=lengthscale(x, y, e) + + ne=e.shape[0] + areaT=np.zeros(nn) + lsN=np.zeros(nn) + for k in range(ne): + for j in range(3): + i=e[k,j]-1 + lsN[i]=lsN[i]+LengthScaleE[k]*areaE[k] + areaT[i]=areaT[i]+areaE[k] + for k in range(nn): + lsN[k]=lsN[k]/areaT[k] + return lsN + diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py new file mode 100644 index 0000000..a854337 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py @@ -0,0 +1,134 @@ + +# +# Functions for Gauss Markov smoothing of bathymetry data. +# +# Common input variables: +# x,y,z are length nx vectors of observed depth (z) at point (x,y) +# xi,yi is the points for z to be intepolated to. +# +# InverseDistance : weighted inverse distance (squared) estimator +# +# GaussMarkovUnkMean : Gauss Markov smoothing with unkown mean (like ordinary kriging) +# +# GaussMarkov : Gauss Markov smoothing with kown mean (like simple kriging) +# Choices for mean are : +# "Zero" = 0 +# "Mean" = sample mean of z +# "Median" = sample median of z +# "Nearest" = value of z for closest point to (xi, yi) +# +# Two covariance functions are implemented: +# covmod="Exp" for exponential decay covariance as a function of distance or +# covmod="Sph" for spherical decay (finite suport) +# +# LengthScale is the (specified/ known) length scale in km at (xi, yi). +# LengthScale is intended to be proportional to mesh lengthscake at (xi, yi). +# + +import numpy as np + +#covmod="Sph" +covmod="Exp" +CovExp=2 # Exponent in covariance funtion, used if covmod="Exp", +IDExp=2 # exponent used in inverse distance estimator + +deg2km=111.132954 +deg2rad=np.pi/180 + +def InverseDistance(x,y,z,xi,yi): + d=DistanceV(x,y,xi,yi) + w=1.0/(d**IDExp) + zi=np.dot( z, w )/np.sum( w ) + return zi + +def GaussMarkov(x,y,z,xi,yi,LengthScale,Vobs,V,MeanTyp,CompErr): + nx=len(x) + f = np.zeros(nx) + C = np.zeros((nx,nx)) + for j in range(nx): + d = DistanceV(x,y,x[j],y[j]) + C[j,range(nx)]=CovarianceDistance(d,covmod,LengthScale,V) + C[j,j]=C[j,j] + Vobs + d = DistanceV(x,y,xi,yi) + f = CovarianceDistance(d,covmod,LengthScale,V) + detC = np.linalg.det(C) + if np.isclose(detC, 0): + zi=float("inf") + print("Cov matrix is nearly singular. Check for double input points, etc.") + if not CompErr: + return zi + else: + erri=float("inf") + return zi, erri + else: + match MeanTyp: + case "Zero": # simple kriging type + mu=0. + case "Mean": + mu=np.mean(z) # regional mean + case "Median": + mu=np.median(z) # regional median + case "Nearest": # nearest value + mu=z[np.argmax(f)] # max correlate(monotone)<==>closest point for process mean + case _: + mu=0. + w = np.linalg.solve(C, f) + zi=mu+np.dot(w,z-np.array(mu)) + if not CompErr: + return zi + else: + erri=np.sqrt( V - np.dot(f,w)) + return zi, erri + +def GaussMarkovUnkMean(x,y,z,xi,yi,LengthScale,Vobs,V,CompErr): + nx=len(x) + f = np.zeros(nx+1) + C = np.zeros((nx+1,nx+1)) + for j in range(nx): + d = DistanceV(x,y,x[j],y[j]) + C[j,range(nx)]=CovarianceDistance(d,covmod,LengthScale,V) + C[j,j]=C[j,j] + Vobs + C[nx,j]=1. + C[j,nx]=1. + d = DistanceV(x,y,xi,yi) + f[range(nx)] = CovarianceDistance(d,covmod,LengthScale,V) + C[nx,nx]=0 + f[nx]=1 + detC = np.linalg.det(C) + if np.isclose(detC, 0): + zi=float("inf") + w=zi+f + print("Cov matrix is likely singular.") + else: + w = np.linalg.solve(C, f) + zi= np.dot(w[range(nx)],z) + if not CompErr: + return zi + else: + erri=np.sqrt( V + np.dot( w[0:nx], np.matmul(C[0:nx,0:nx],w[0:nx])) -2.* np.dot(w[0:nx],f[0:nx]) ) + return zi, erri + +def DistanceV(x,y,x0,y0): #distance between list x,y and point x0,y0 + n=len(x) + d=np.zeros(n) + d=np.sqrt( + ( deg2km*np.cos( deg2rad*y0 )*(x-x0) )**2 + + ( deg2km*(y-y0))**2 ) + return d + +#from geopy import distance +def Distance(x0,y0,x1,y1): +# d = distance.great_circle(y0,x0,y1,x1).km + d=np.sqrt( + ( deg2km*np.cos(deg2rad*(y0+y1)/2 )*(x1-x0) )**2 + + ( deg2km*(y1-y0))**2 ) + return d + +def CovarianceDistance(d,model,ls,v): + if model == "Exp": + c = v*np.exp(- (d/ls )**CovExp ) + if model == "Sph": + c = v*( 1. - 1.5*(d/ls) + .5*((d/ls)**3) ) + c[np.where(d>ls)]=0. + return c + diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py new file mode 100644 index 0000000..41452e4 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py @@ -0,0 +1,335 @@ +import os +import argparse +import time +import numpy as np +import netCDF4 as nc +import csv + +#import jigsawpy +import sys +from scipy.interpolate import RegularGridInterpolator +import re +#import ComputeMeshToMeshInterpWeights as mshint +import math +#from geopy import distance +import itertools +#from geopy.distance import haversine +#from pykrige.ok import OrdinaryKriging + +import FiniteElementMeshRoutines as FE +import GaussMarkov as GM + +import gc + +TextOutput = False +BathyDir="/mnt/sda/keston/CoastalReliefModel/" +flnms=[ + "cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.PointValues500m.nc", + "crm_vol1_2023.nc.S250m.VB.nc", + "crm_vol2_2023.nc.S250m.VB.nc", + "crm_vol3_2023.nc.S250m.VB.nc", + "crm_vol4_2023.nc.S250m.VB.nc", + "crm_vol5_2023.nc.S250m.VB.nc", + "crm_vol7_2024.nc.S250m.VB.nc", + "crm_vol9_2023.nc.S250m.VB.nc", + "crm_vol10_2023.nc.S250m.VB.nc", + "crm_vol6_2023.nc.S250m.VB.nc", + "crm_vol8_2023.nc.S250m.VB.nc", + "crm_southak.CRMformat.nc", + "hurl_bathy_60m_nwhi.CRMformat.nc.S250m.VB.nc", + "PIX/ngdc_bathy_10m_wake.CRM.nc", + "PIX/pibhmc_bathy_20m_jarvis.CRM.nc", + "PIX/pibhmc_bathy_20m_johnston.CRM.nc", + "PIX/pibhmc_bathy_20m_kingman.CRM.nc", + "PIX/pibhmc_bathy_40m_baker.CRM.nc", + "PIX/pibhmc_bathy_40m_howland.CRM.nc", + "PIX/pibhmc_bathy_40m_palmyra.CRM.nc", + "PIX/pibhmc_bathy_40m_rose.CRM.nc", + "PIX/pibhmc_bathy_40m_swains.CRM.nc", + "PIX/pibhmc_bathy_40m_vailuluu.CRM.nc", + "PIX/pibhmc_bathy_5m_palmyra.CRM.nc", + "PIX/sopac_bathy_50m_majuro_reef.CRM.nc", + "PIX/ngdc_bathy_180m_mariana.CRM.nc", + "ngdc_bathy_90m_amsamoa.crm.nc", + "RTopo_2_0_4_GEBCO_v2023_60sec_pixel.CRMformat.nc" + ] +######################################################## +#set filetype to +# 0 : for gridded local data and +# 1 : for gridded global data and +# 2 : for scattered global data +nf=len(flnms) +filetype=np.zeros(nf, dtype=int) +filetype[0]=2 +filetype[nf-1]=1 +######################################################## + +Zmin=-11000. #deepest legit ocean depth value in case of mask fail +# nescesarry for data sets "crm_vol6_2023.nc.S250m.nc" and "crm_vol8_2023.nc.S250m.nc" +Zmax=0. # maximum value to include in interpolation - zero out land values or ignore land +Dmin=5./1000.# 5 meter minimum distance between observation points in km, prevent singularity +lambdaLL=.025 # set deg lat, lon search width for overlapping regions +#use Approximately NxTarget**2 points per data set, +#each linear system is approx 2*(NxTarget**2) +NxTarget=20 # N=20 ~ 10 grid points in each cardinal direction used in interpolating +NpointsMax=1000 +xlist=[] +ylist=[] +n=0 +nxl=np.zeros(len(flnms)) +nyl=np.zeros(len(flnms)) +xmax=np.zeros(len(flnms)) +xmin=np.zeros(len(flnms)) +ymax=np.zeros(len(flnms)) +ymin=np.zeros(len(flnms)) +for fl in flnms: +# print(f"'{fl}' has a length of {len(fl)}") +# if n>0: + data = nc.Dataset(BathyDir+fl,"r") + x=np.array(data["lon"][:]) + x=x%360 + y=np.array(data["lat"][:]) + xlist.append(list(x)) + ylist.append(list(y)) + nxl[n]=len(x) + nyl[n]=len(y) + #setup quick lookup table for file exlusion + xmax[n]=np.max(x)+lambdaLL*2 + xmin[n]=np.min(x)-lambdaLL*2 + ymax[n]=np.max(y)+lambdaLL*2 + ymin[n]=np.min(y)-lambdaLL*2 + n=n+1 + +def ZeroPadIntStr(N,K): + ZPNs=str(N).zfill(K) + return ZPNs + +mshnm="HawaiiTest" +mesh="meshes/"+mshnm+".msh" +OutDir=mshnm+".files/" + +xi, yi, ei = FE.loadWW3MeshCoords(mesh) + +lsN=FE.ComputeNodeLengthScale(xi,yi,ei) + +print(np.min(lsN)) +print(np.mean(lsN)) +print(np.max(lsN)) + +N=int(sys.argv[1]) + +fln=OutDir+'NodeList.'+str(N)+'.txt' +floutID=OutDir+'InvDist.'+str(N)+'.txt' +floutGMM=OutDir+'GMM.'+str(N)+'.txt' +floutGMN=OutDir+'GMN.'+str(N)+'.txt' +floutGM0=OutDir+'GM0.'+str(N)+'.txt' +floutGMU=OutDir+'GMU.'+str(N)+'.txt' +floutClosest=OutDir+'ClosestValue.'+str(N)+'.txt' +floutNpts=OutDir+'NDataPoints.'+str(N)+'.txt' +floutLLS=OutDir+'LengthScale.'+str(N)+'.txt' +floutGMUerr= OutDir+'GMU.std.'+str(N)+'.txt' +floutGMNerr= OutDir+'GMN.std.'+str(N)+'.txt' +#read in nodes to interpolate to +f=open(fln,"r") +header = f.readline() +nn =int( f.readline()) + +#make local node set to interpolate to +xil=np.zeros(nn) +yil=np.zeros(nn) +LSl=np.zeros(nn) +for k in range(nn): + j = int(f.readline()) + xil[k]=xi[j] + yil[k]=yi[j] + LSl[k]=lsN[j] + +#del xi yi ei lsN #clear global mesh variables +#gc.collect() + +nn=len(xil) + +#set search width for each data set based on expected +#number of points to interpolate +SearchWidth=np.zeros(nf) +for j in range(nf): + x=np.array(xlist[j][:]) + dx=np.abs(x[1]-x[0]) + SearchWidth[j]=dx*float(NxTarget)/2. + print("search width(deg Lat lon) for file: "+flnms[j]+" = ",str(SearchWidth[j])) + +SearchWidth[0]=.05 +SearchWidth[nf-1]=.75*SearchWidth[nf-1] # smaller number for global bathy set + +# Initialize estimate fields and posterioir estimates +NumPoints=np.zeros(nn) +ziID=np.zeros(nn) +ziGMU=np.zeros(nn) +stdiGMU=np.zeros(nn) +ziGMN=np.zeros(nn) +stdiGMN=np.zeros(nn) +#ziGMM=np.zeros(nn) +#ziGM0=np.zeros(nn) +ziClosest=np.zeros(nn) +LocalLengthScale=np.zeros(nn) + +t0 = time.time() +fl=flnms[0] +data = nc.Dataset(fl,"r") +x0=data["lon"][:] +x0=x0%360 +y0=data["lat"][:] +z0=data["z"][:] +#z0=float(z0.data) +for n in range(nn): + xp=xil[n]%360 + yp=yil[n] + +# LSp=2.*LSl[n] #probably better choice for spherical covarianve function + LSp=1.*LSl[n] #choice for exponential covarianve function +# LSp=0.25*LSl[n] +# LSp=LSl[n] #Local length scale for interpolation + LocalLengthScale[n]=LSp + xs=[] + ys=[] + zs=[] + si=0 + for j in range(nf): + if filetype[j] <2 : #gridded data + if all([ xp < xmax[j],xp > xmin[j],yp < ymax[j],yp > ymin[j]]): + x=np.array(xlist[j][:]) + y=np.array(ylist[j][:]) + fl=flnms[j] + if TextOutput: + print(fl) + jx=np.array(np.where( np.abs(xp-x) < SearchWidth[j] )) + jx=list(itertools.chain.from_iterable(jx)) + jy=np.array(np.where( np.abs(yp-y) < SearchWidth[j] )) + jy=list(itertools.chain.from_iterable(jy)) + data = nc.Dataset(BathyDir+fl,"r") + for kx in jx: + for ky in jy: + if kx and ky: # not empty + z=data["z"][ky,kx] + if not z.mask: + IncludePoint=True + if len(xs)>0: #BEGIN -check for near duplicate points - causes singularity in GMS + d=GM.DistanceV(xs,ys,x[kx],y[ky]) + if np.min(d) Zmax:#exclude land values(should be optional) + # IncludePoint=False + if IncludePoint: # first point + zd=min(zd,Zmax) # trunkate interpolant to Zmax<=0 + xs.append(x[kx]) + ys.append(y[ky]) + zs.append(zd) + else: # global scattered data, filetype[j] == 2 + fl=flnms[j] + j=np.array( np.where( np.array(np.abs(xp-x0) < SearchWidth[j] ) & np.array(np.abs(yp-y0) < SearchWidth[j] ) ) ) + j=list(itertools.chain.from_iterable(j)) + j=np.array(j).flatten() + if j.size>0: + j=np.array(j).flatten() + x=x0[j] + y=y0[j] + zd=z0[j] + jp=np.where( zd <= 0.) + x=x[jp] + y=y[jp] + zd=zd[jp] + if TextOutput: + print("number of points from "+fl+" is " +str(len(zd)) ) + xs.extend(x) + ys.extend(y) + zs.extend(zd) + if TextOutput: + if n % 1 == 0: + print("interpolating to:"+str(yp)+":"+str(xp)) + t1 = time.time() + time_per_iter = (t1 - t0) / (n + 1) + time_remaining = (nn - n) * time_per_iter / 60 + print("Progress: "+str(n+1)+" of "+ str(nn)) + print(f"Time remaining: {time_remaining:.2f} minutes") + print(f"Average time per node: {time_per_iter:.2f} seconds") + print("node: "+str(n)+" uses "+str(len(xs))+" data points") + + Npoints=len(xs) + NumPoints[n]=Npoints + + #limit total number of points in interpolation (shouldn't come into effect much in practice) + if Npoints > NpointsMax: + if TextOutput: + print("node "+str(n)+" has "+str(Npoints)+" data points. taking nearest: "+str(NpointsMax)) + xsp=np.zeros(NpointsMax) + ysp=xsp + zsp=xsp + D=GM.Distance(xs,ys,xp,yp) + for k in range(NpointsMax): + ki=np.argmin(D) + xsp[k]=xs[ki] + ysp[k]=ys[ki] + zsp[k]=zs[ki] + D[ki]=float('inf') + xs=xsp + ys=ysp + zs=zsp + +##### Specify priori error statistics here############################# +# Here some simple error statistics are given: These can be made dataset +# depent, depth dependent etc. +# Assumptions regarding observation standard error: + ObsErr= max(1. , np.mean(np.abs(zs))/100. ) # 1 percent of local mean depth (m) + VarObs=ObsErr**2 #(m^2) +#Specify assumptions regarding background variance: + VarBG=10.*VarObs #(m^2) +##### Done specify priori error statistics ############################ + + +##### Different depth estimators ###################################### + if TextOutput: + print("Number of obs = " +str(len(zs)) ) + print("std obs= " + str(np.sqrt(VarObs)) + " (m), std BG= " + str(np.sqrt(VarBG))+" (m)" ) + +# Inverse distance estimator + ziID[n]=GM.InverseDistance(xs,ys,zs,xp,yp) + +# Gauss-Markov smoothing with unkown mean (like ordinary kriging) + ziGMU[n], stdiGMU[n]=GM.GaussMarkovUnkMean(xs, ys, zs, xp, yp,LSp, VarObs,VarBG,True) + if TextOutput: + print("GMU: est= "+str(ziGMU[n])+", err= "+str(stdiGMU[n])) + +# Gauss-Markov smoothing with known mean (like simple kriging). Assumed mean is closest observation + ziGMN[n], stdiGMN[n]=GM.GaussMarkov(xs, ys, zs, xp, yp, LSp, VarObs,VarBG,"Nearest",True) #gives good results to eye + if TextOutput: + print("GMN: est= "+str(ziGMN[n])+", err= "+str(stdiGMN[n])) + +# Gauss-Markov smoothing with known mean (like simple kriging). Assumed mean is sample mean +# ziGMM[n]=GM.GaussMarkov(xs, ys, zs, xp, yp, LSp, VarObs,VarBG,"Mean",False) + +# Gauss-Markov smoothing with known mean (like simple kriging). Assumed mean is 0 +# ziGM0[n]=GM.GaussMarkov(xs, ys, zs, xp, yp, LSp, VarObs,VarBG,"Zero",False) + +# Nearest neighbor estimator + D=GM.DistanceV(xs,ys,xp,yp) + jc=np.argmin(D) + ziClosest[n]=zs[jc] + + +np.savetxt(floutID , ziID , fmt='%.6f', delimiter='\n') +np.savetxt(floutGMN, ziGMN, fmt='%.6f', delimiter='\n') +np.savetxt(floutGMNerr, stdiGMN, fmt='%.6f', delimiter='\n') +#np.savetxt(floutGMM, ziGMM, fmt='%.6f', delimiter='\n') +#np.savetxt(floutGM0, ziGM0, fmt='%.6f', delimiter='\n') +np.savetxt(floutGMU, ziGMU, fmt='%.6f', delimiter='\n') +np.savetxt(floutGMUerr, stdiGMU, fmt='%.6f', delimiter='\n') +np.savetxt(floutClosest, ziClosest, fmt='%.6f', delimiter='\n') +np.savetxt(floutNpts, NumPoints, fmt='%i', delimiter='\n') +np.savetxt(floutLLS, LocalLengthScale, fmt='%.6f', delimiter='\n') + + diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py new file mode 100644 index 0000000..99b9100 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py @@ -0,0 +1,41 @@ + +# +# This script takes the files generated in parallel from InterpolateCRM.partscat.py +# It should be called at the end of +# $ sbatch jobcardInterpBathy2Mesh +# when all independent interpolation problems are finished +# + +import numpy as np +import FiniteElementMeshRoutines as FE +import sys + +mshnm="HawaiiTest" +mesh="meshes/"+mshnm+".msh" +OutDir=mshnm+".files/" + +Nparts=int(sys.argv[1]) +Prefix=sys.argv[2] +xi, yi, ei = FE.loadWW3MeshCoords(mesh) +nn=len(xi) +NodeList=[] +si=np.zeros(nn) +for n in range(Nparts): + fli=OutDir+'NodeList.'+str(n)+'.txt' + fpi=open(fli, 'r') + fls=OutDir+Prefix+"."+str(n)+".txt" + fps=open(fls, 'r') + print("reading nodelist from: "+fli+", reading values from: "+fls) + header = fpi.readline() + nn0=int(fpi.readline()) + for k in range(nn0): + j = int(fpi.readline()) + value=float(fps.readline()) + si[j] = value +fps.close +fpi.close + +#write full field file with interpolated values +flout=mshnm+"."+Prefix+".txt" +np.savetxt(flout , si, fmt='%.6f',delimiter='\n') + diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py new file mode 100644 index 0000000..fe0941a --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py @@ -0,0 +1,437 @@ + +# This is a script to put all gridded bathymetry datasets into the same format. +# The output files should follow the same format as the 2023 version of the +# Coastal Relief Model (CRM) available at +# https://www.ncei.noaa.gov/products/coastal-relief-model +# Makes files with same variable names, latitude/longitude conventions, and masking. +# +# To run the full script you will need the following files: +# +# crm_vol6.nc +# crm_vol8.nc +# crm_southak.nc +# pibhmc_bathy_60m_guam.nc +# ngdc_bathy_90m_amsamoa.nc +# hurl_bathy_60m_nwhi.nc +# RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc +# +# Sources for these files are within the script in comments. + +import numpy as np +import netCDF4 as nc +import math +import subprocess + +# Example 1: Basic command execution +# This will run 'ls -l' and print the output to the console. +subprocess.run(["ls", "-l"]) + +#[0->7] variables(dimensions): |S1 crs(), float64 lat(lat), float64 lon(lon), float32 z(lat, lon) +#[8->9]variables(dimensions): float64 x(x), float64 y(y), float32 z(y, x) +#[10]variables(dimensions): float64 lon(num_lon), float64 lat(num_lat), int16 bed_elevation(num_row, num_col) + +Zmin=-12000 # deepest valid value (m) - used to backup masking errors + +# from https://www.ncei.noaa.gov/products/coastal-relief-model +flTemplate="crm_vol1_2023.nc" +dataT = nc.Dataset(flTemplate,"r") +print(dataT) + + +""" +# from https://pae-paha.pacioos.hawaii.edu/erddap/info/srtm30plus_v11_bathy/index.html +flin="srtm30plus_v11_bathy.nc" +flout="srtm30plus_v11_bathy.CRMformat.nc" +data0 = nc.Dataset(flin,"r") +x=np.asarray(data0["lon"][:]) +y=np.asarray(data0["lat"][:]) +z=np.asarray(data0["elev"][:,:]) +#z=float(z) +j=np.where(np.isnan(z)) +z[j]=-99999 +j=np.where(z7] variables(dimensions): |S1 crs(), float64 lat(lat), float64 lon(lon), float32 z(lat, lon) +#[8->9]variables(dimensions): float64 x(x), float64 y(y), float32 z(y, x) +#[10]variables(dimensions): float64 lon(num_lon), float64 lat(num_lat), int16 bed_elevation(num_row, num_col) + +flnms=[ + "crm_vol1_2023.nc",#dx= 0.00027, 3600/deg + "crm_vol2_2023.nc", + "crm_vol3_2023.nc", + "crm_vol4_2023.nc", + "crm_vol5_2023.nc", + "crm_vol7_2024.nc", + "crm_vol9_2023.nc", + "crm_vol10_2023.nc", #problem with mask values + "crm_vol6_2023.nc",#dx= 0.0008 cut to 3 x 3 + "crm_vol8_2023.nc",#dx= 0.0008,1200 / deg + "hurl_bathy_60m_nwhi.CRMformat.nc", + "pibhmc_bathy_60m_guam.crm.nc", + "ngdc_bathy_90m_amsamoa.crm.nc" + ] + +count=0 +filval=-99999 +for fl in flnms: + count=count+1 + + Nsubsample=9 + Nstart=4 + if (fl=="crm_vol6_2023.nc"or fl=="crm_vol8_2023.nc" ): + Nsubsample=3 + Nstart=1 + if fl == "hurl_bathy_60m_nwhi.CRMformat.nc": + Nsubsample=5 + Nstart=2 + if (fl == "pibhmc_bathy_60m_guam.crm.nc" or "ngdc_bathy_90m_amsamoa.crm.nc"): + Nsubsample=3 + Nstart=1 + + data0 = nc.Dataset(fl,"r") + x=np.asarray(data0["lon"][:]) + y=np.asarray(data0["lat"][:]) + if fl == "crm_socal_1as_vers2.nc": + z=np.asarray(data0["Band1"][:]) + z=z.astype(np.float32) + else: + z=np.asarray(data0["z"][:]) + nx=len(x) + ny=len(y) + dx=x[1]-x[0] + dy=y[1]-y[0] + print(fl) + print(z.shape) + print("org. dx= "+str(dx)) + print(1.0/dx) + print("org. dy= "+str(dy)) + print(1.0/dy) + if ( (fl == "crm_vol10_2023.nc") or (fl == "crm_socal_1as_vers2.nc") ) : # This file has an un recognized fill value + print("fixing bad fill value in: "+fl) + jb=np.where(z==-9999) + z[jb]= -float("inf") + + W=np.ones((Nsubsample,Nsubsample))/(Nsubsample**2) + z = signal.convolve2d(z,W, mode='same') + x=x[Nstart :: Nsubsample] + y=y[Nstart :: Nsubsample] + z=z[Nstart :: Nsubsample,Nstart :: Nsubsample] + nx=len(x) + ny=len(y) +# flout=fl+'.S250m.nc' + flout=fl+'.S250m.VB.nc' + # This file has an un recognized fill value +# if fl == "crm_vol10_2023.nc": + if ( (fl == "crm_vol10_2023.nc") or (fl == "crm_socal_1as_vers2.nc") ) : # This file has an un recognized fill value + print("patching correct fill values in: "+flout) + jb=np.where(z Date: Tue, 3 Feb 2026 11:49:24 -0500 Subject: [PATCH 13/44] added missing file, DivideMeshNodes.py --- .../InterpolateBathymetry/DivideMeshNodes.py | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py new file mode 100644 index 0000000..900e1ce --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py @@ -0,0 +1,132 @@ + +# +# This script partitions the nodes in mshnm into NP parts and writes a script to +# interpolate bathymetry data to the nodes in NP parallel parts +# call: +# +# $ python3 DivideMeshNodes.py 100 +# +# to create jobcard: jobcardInterpBathy2Mesh, which is then run: +# +# $ sbatch jobcardInterpBathy2Mesh +# +# to interpolate the bathymetry in 100 parallel tasks +# +# This script should be run after the bathymetry data sets specified in +# InterpolateCRM.partscat.py are present +# + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc +import math +import sys +from scipy.interpolate import RegularGridInterpolator +#import re +import FiniteElementMeshRoutines as FE +import random + +mshnm="HawaiiTest" +mesh="meshes/"+mshnm+".msh" +OutDir=mshnm+".files/" + +jobcard="jobcardInterpBathy2Mesh" + + +def WriteInterpJobscript(fl,N, ComputeNodes): + with open(fl, 'w') as f: + #yi[k]=float(values[4]) + f.write("#!/bin/bash \n") + f.write("#SBATCH --job-name=CRM_interp_masterscript \n") +# f.write("#SBATCH --ntasks="+str(N)+" \n") + f.write("#SBATCH --ntasks=1 \n") # ntasks per interpolation + f.write("#SBATCH --time=08:00:00 \n") + f.write("#SBATCH --output=mpi_test_%j.log \n") + f.write("#SBATCH --error=%j.err \n") + f.write("#SBATCH --account=marine-cpu \n") + f.write("#SBATCH --nodes="+str(ComputeNodes)+" \n") + f.write("#SBATCH --ntasks-per-core=1"+" \n") + f.write("#SBATCH --array=0-"+str(N-1)+" \n") + + f.write(" \n") + + f.write("module purge \n") + #f.write("module use /scratch4/NCEPDEV/marine/Ali.Salimi/Hera_Data/HR4-OPT/FromJessica/Keston/ICunstructuredRuns15km-implicit-450s/global-workflow/sorc/ufs_model.fd/modulefiles \n") + f.write("module use /scratch4/NCEPDEV/marine/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles \n") + f.write("module load ufs_ursa.intel \n") + f.write("module load py-scipy/1.14.1 \n") + f.write("module load py-netcdf4/1.7.1.post2 \n") + f.write("pip list \n") + f.write("srun python3 InterpolateCRM.partscat.py $SLURM_ARRAY_TASK_ID > InterpJob.$SLURM_ARRAY_TASK_ID.out \n") + f.write("wait \n") + f.write("## Run this after the full job array is compleate.\n") + f.write("## Patch randomly shuffled fields in orgigonal order.\n") + + f.write("python3 KnitOutputBackTogether.py "+str(N)+" GMN\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" GMU\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" InvDist\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" NDataPoints\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" ClosestValue\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" LengthScale\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" GMU.std\n") + f.write("python3 KnitOutputBackTogether.py "+str(N)+" GMN.std\n") + #f.write("python3 KnitOutputBackTogether.py "+str(N)+" GMM\n") + #f.write("python3 KnitOutputBackTogether.py "+str(N)+" GM0\n") + + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +fl="meshes/"+mshnm+".msh" + +xi, yi, ei =FE.loadWW3MeshCoords(fl) + +#tmp +lsE=FE.lengthscale(xi, yi, ei) +areaE=FE.ElementArea(xi, yi, ei) +lsN=FE.ComputeNodeLengthScale(lsE, areaE, ei) +np.savetxt("LengthScaleNodes.txt", lsN, fmt='%.6f', delimiter='\n') + +# randomly sort nodes for roughly equal jobs size +# nodes within CRM envelope use far more compute than +# open ocean nodes with fewer points used in interpolation + +nn=len(xi) +Nodes = list(range( nn )) +random.shuffle(Nodes) # randomize order of nodes for equitable job load + +Nparts=int(sys.argv[1]) + +nn=xi.shape[0] +NodesPerProc=math.ceil(nn/Nparts) +print(str(NodesPerProc)+ " " + str(nn)) +a = range(nn) + +NodeList = [] +for i in range(0, len(a), NodesPerProc): # Slice list in steps of n + NodeList.append(a[i:i + NodesPerProc]) + +print("NodeList") +print(NodeList) +for k in range(Nparts): + flo=OutDir+'NodeList.'+str(k)+'.txt' + f=open(flo, 'w') + f.write("List of nodes for job "+str(k) + "\n") + List=NodeList[k] + n=len(List) + f.write(str(n) + "\n") + for j in range(n): + #f.write(str(List[j]) + '\n') # sequential order of nodes, output can be cat > back together + f.write(str(Nodes[List[j]]) + '\n') # random order of nodes + f.close + +#write jobcard to do interpolation +WriteInterpJobscript(jobcard,Nparts,1) From c66d48f1b18576b82a60d35090c49a96aa70ffe8 Mon Sep 17 00:00:00 2001 From: keston Date: Tue, 3 Feb 2026 12:02:52 -0500 Subject: [PATCH 14/44] added README.txt to InterpolateBathymetry --- .../InterpolateBathymetry/README.txt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt new file mode 100644 index 0000000..258345f --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt @@ -0,0 +1,48 @@ +These are subroutines to interpolate bathymetry data to a unstructured +meshes with triangular elements. The interpolation uses Gauss Markov +smoothing with variable lengthscale proportional to the mesh lengthscale. +The interpolation is computed in parallel across a user determined +number of mesh divisions. The program uses an arbitrary number of +bathymetry data files. It was designed to use a low resolution file +with global coverage as well as local high resolution gridded bathymetry, +and global scattered high resolution bathymetry data, such as global +Satellite Derived Bathymetry (SDB). Bathymetry data sets need to be +downloaded and preprocessed to use a common format. + +To interpolate bathymetry to a mesh: + + (0) Download bathymetry data to be used (notes are in + MakeCommonNetCDFFileFormat.py) + + (1) python3 MakeCommonNetCDFFileFormat.py + + (2) python3 SmoothSubsampleNetCDFFiles.py + + (3) python3 SmoothSubsampleCMEMS.py + + (4) python3 DivideMeshNodes.py NP + NP=number of interpolation jobs to run in parallel + + (5) sbatch jobcardInterpBathy2Mesh + Runs interpolation job in parallel in slurm environmant + + (6) python3 AddBathyToMesh.py HawaiiTest.GMU.txt + creates HawaiiTest.GMU.txt.WW3.msh, a WW3 .msh mesh format + +to change the mesh interpolated to : + +$sed -i 's/HawaiiTest/MyMesh/g' *.py + +and copy MyMesh.msh file to the +WW3-tools/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/meshes/ +directory + + +AddBathyToMesh.py +FiniteElementMeshRoutines.py +GaussMarkov.py +InterpolateCRM.partscat.py +KnitOutputBackTogether.py +MakeCommonNetCDFFileFormat.py +SmoothSubsampleCMEMS.py +SmoothSubsampleNetCDFFiles.py From ee3ae59b648e132f750039621e13d14e564dce53 Mon Sep 17 00:00:00 2001 From: keston Date: Tue, 3 Feb 2026 12:32:09 -0500 Subject: [PATCH 15/44] documentation added within InterpolateCRM.partscat.py --- .../InterpolateCRM.partscat.py | 69 +++++++++++++------ 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py index 41452e4..8e72d5d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py @@ -1,16 +1,29 @@ +###################################################################### +# This is the main interpolation engine. This script reads in a list +# of nodes created by DivideMeshNodes.py and interpolates bathymetry +# from a list of bathymetry data files to the nodes in the assigned +# list. The intent is to run this in NPart parallel jobs for a +# partition of mesh nodes into NPart sets. +# +# The user is responsible for specifing the bathymetry data sets +# in list "flnms" as well as the type of data each of these files +# in list "filetype". filetype[k] = 0 gridded local data, 1 gridded +# global data and 2 for scattered data. +# +# The user should define there observational error model and bacground +# process statistical model. +# import os import argparse import time import numpy as np import netCDF4 as nc -import csv #import jigsawpy import sys from scipy.interpolate import RegularGridInterpolator -import re -#import ComputeMeshToMeshInterpWeights as mshint import math + #from geopy import distance import itertools #from geopy.distance import haversine @@ -19,10 +32,17 @@ import FiniteElementMeshRoutines as FE import GaussMarkov as GM -import gc - +# TextOutput = True # prints lots of information durring interpolation (may cause slowdown) TextOutput = False + +# directory containg all of the bahymetry data files specified in flnms BathyDir="/mnt/sda/keston/CoastalReliefModel/" + +######################################################## +# processed netcdf bathymetry files with variables: +# lon, lat and z. Specify corresponding file type, gridded or scattered, +# in list "filetype" below. +######################################################## flnms=[ "cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.PointValues500m.nc", "crm_vol1_2023.nc.S250m.VB.nc", @@ -54,10 +74,13 @@ "RTopo_2_0_4_GEBCO_v2023_60sec_pixel.CRMformat.nc" ] ######################################################## -#set filetype to + +######################################################## +# Set filetype corresponding to files in flnms # 0 : for gridded local data and # 1 : for gridded global data and # 2 : for scattered global data +######################################################## nf=len(flnms) filetype=np.zeros(nf, dtype=int) filetype[0]=2 @@ -144,13 +167,10 @@ def ZeroPadIntStr(N,K): yil[k]=yi[j] LSl[k]=lsN[j] -#del xi yi ei lsN #clear global mesh variables -#gc.collect() - nn=len(xil) -#set search width for each data set based on expected -#number of points to interpolate +# set search width for each data set based on expected +# number of points to interpolate SearchWidth=np.zeros(nf) for j in range(nf): x=np.array(xlist[j][:]) @@ -173,22 +193,29 @@ def ZeroPadIntStr(N,K): ziClosest=np.zeros(nn) LocalLengthScale=np.zeros(nn) -t0 = time.time() +###################################################################### +# For each scattered data set, read in the scattered data here to +# one dimensional arrays x0, y0, and z0. This should be looped to +# accumulate all of the scatted datasets together. The only scattered +# data set used here is +# "cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.PointValues500m.nc", +# so this is simply loaded here. +###################################################################### fl=flnms[0] data = nc.Dataset(fl,"r") x0=data["lon"][:] x0=x0%360 y0=data["lat"][:] z0=data["z"][:] -#z0=float(z0.data) +###################################################################### + +t0 = time.time() for n in range(nn): xp=xil[n]%360 yp=yil[n] - +# Set local length scale to use in Gauss Markov smoothing at node n # LSp=2.*LSl[n] #probably better choice for spherical covarianve function LSp=1.*LSl[n] #choice for exponential covarianve function -# LSp=0.25*LSl[n] -# LSp=LSl[n] #Local length scale for interpolation LocalLengthScale[n]=LSp xs=[] ys=[] @@ -261,7 +288,7 @@ def ZeroPadIntStr(N,K): Npoints=len(xs) NumPoints[n]=Npoints - + #limit total number of points in interpolation (shouldn't come into effect much in practice) if Npoints > NpointsMax: if TextOutput: @@ -282,12 +309,12 @@ def ZeroPadIntStr(N,K): ##### Specify priori error statistics here############################# # Here some simple error statistics are given: These can be made dataset -# depent, depth dependent etc. +# dependent, depth dependent, etc. # Assumptions regarding observation standard error: ObsErr= max(1. , np.mean(np.abs(zs))/100. ) # 1 percent of local mean depth (m) VarObs=ObsErr**2 #(m^2) #Specify assumptions regarding background variance: - VarBG=10.*VarObs #(m^2) + VarBG=10.*VarObs #(m^2) Background variance = 10 observation error variance ##### Done specify priori error statistics ############################ @@ -305,7 +332,7 @@ def ZeroPadIntStr(N,K): print("GMU: est= "+str(ziGMU[n])+", err= "+str(stdiGMU[n])) # Gauss-Markov smoothing with known mean (like simple kriging). Assumed mean is closest observation - ziGMN[n], stdiGMN[n]=GM.GaussMarkov(xs, ys, zs, xp, yp, LSp, VarObs,VarBG,"Nearest",True) #gives good results to eye + ziGMN[n], stdiGMN[n]=GM.GaussMarkov(xs, ys, zs, xp, yp, LSp, VarObs,VarBG,"Nearest",True) if TextOutput: print("GMN: est= "+str(ziGMN[n])+", err= "+str(stdiGMN[n])) @@ -320,7 +347,7 @@ def ZeroPadIntStr(N,K): jc=np.argmin(D) ziClosest[n]=zs[jc] - +###### Output estimates and other statistics to text files ########### np.savetxt(floutID , ziID , fmt='%.6f', delimiter='\n') np.savetxt(floutGMN, ziGMN, fmt='%.6f', delimiter='\n') np.savetxt(floutGMNerr, stdiGMN, fmt='%.6f', delimiter='\n') From 9e61f509e6ded32950176585052df93bfb16d27c Mon Sep 17 00:00:00 2001 From: keston Date: Tue, 3 Feb 2026 14:19:54 -0500 Subject: [PATCH 16/44] Added start of script to download all bathymetry file. Incompleate due to NCEI system (CRM) under maintanence --- .../DownloadBathyData.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py new file mode 100644 index 0000000..0ee7ef9 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py @@ -0,0 +1,90 @@ + + + "crm_vol1_2023.nc.S250m.VB.nc", + "crm_vol2_2023.nc.S250m.VB.nc", + "crm_vol3_2023.nc.S250m.VB.nc", + "crm_vol4_2023.nc.S250m.VB.nc", + "crm_vol5_2023.nc.S250m.VB.nc", + "crm_vol7_2024.nc.S250m.VB.nc", + "crm_vol9_2023.nc.S250m.VB.nc", + "crm_vol10_2023.nc.S250m.VB.nc", + "crm_vol6_2023.nc.S250m.VB.nc", + "crm_vol8_2023.nc.S250m.VB.nc", + "crm_southak.CRMformat.nc", + + + "PIX/ngdc_bathy_10m_wake.CRM.nc", + "PIX/pibhmc_bathy_20m_jarvis.CRM.nc", + "PIX/pibhmc_bathy_20m_johnston.CRM.nc", + + + + "PIX/pibhmc_bathy_20m_kingman.CRM.nc", + "PIX/pibhmc_bathy_40m_baker.CRM.nc", + "PIX/pibhmc_bathy_40m_howland.CRM.nc", + "PIX/pibhmc_bathy_40m_palmyra.CRM.nc", + "PIX/pibhmc_bathy_40m_rose.CRM.nc", + "PIX/pibhmc_bathy_40m_swains.CRM.nc", + "PIX/pibhmc_bathy_40m_vailuluu.CRM.nc", + + "PIX/pibhmc_bathy_5m_palmyra.CRM.nc", + "PIX/sopac_bathy_50m_majuro_reef.CRM.nc", + "PIX/ngdc_bathy_180m_mariana.CRM.nc", + + "RTopo_2_0_4_GEBCO_v2023_60sec_pixel.CRMformat.nc" + + + +# American Samoa +wget --output-document ngdc_bathy_90m_amsamoa.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_90m_amsamoa?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +# Mariana islands +wget --output-document ngdc_bathy_180m_mariana.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_180m_mariana?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +#North Western Hawiian islands +wget --output-document hurl_bathy_60m_nwhi.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/hurl_bathy_60m_nwhi?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +#US Minor outlying islands +#Wake island +wget --output-document ngdc_bathy_10m_wake.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_10m_wake?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_jarvis.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_jarvis?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_johnston.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_johnston?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_kingman.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_kingman?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_baker.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_baker?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_howland.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_howland?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_rose.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_rose?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_vailuluu.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_vailuluu?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_swains.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_swains?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_5m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_5m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document sopac_bathy_50m_majuro_reef.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/sopac_bathy_50m_majuro_reef?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + + +#For Coastal Relief Model: +#Please note: Due to scheduled maintenance, many NCEI systems will be unavailable February 3, 11:00 AM ET - February 11, 8:00 PM ET. We apologize for any inconvenience. More details. + +https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 + +wget --output-document cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.nc https://s3.waw3-1.cloudferro.com/mdl-native-17/native/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/cmems_obs-sdb_glo_phy_wk_my_100m-l4-s2_static_202511/cmems_obs-sdb_glo_phy-wk_my-oa-100m-l4-s2_static.nc + +#https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 +#cmems url- not for wget + +# 60 second Global Bathymetry +wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.zip + + +wget https://github.com/dengwirda/dem/releases/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip +wget https://github.com/dengwirda/dem/releases/expanded_assets/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip + From d39b4de81d4a97fc8549b10edf6a84dffac88c8c Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 04:12:20 +0000 Subject: [PATCH 17/44] made RWPSMeshGenScript file inputs consistent with PreProcessCoastline outputs --- .../RWPSMeshGenScript.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py index d047e99..4dadb86 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py @@ -12,15 +12,20 @@ #-------------------Input Files---------------------------------------- """ -#GSHHS coastline +#OSM coastline PSLGFile="GlobalCoastlineOSM.PSLG.msh" DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" +""" -#OSM coastline -PSLGFile="PSLGboundaryGSHHS.msh" -DistanceToCoastFile="GlobalCoastlineGSHHS.PSLG.msh" +#GSSH coastline +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format topography on same grid as distance TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" + """ # GSHHS except identified problem spots (i.e. American Samoa) where OSM is used #jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline @@ -29,11 +34,12 @@ DistanceToCoastFile="DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" #jigsaw gridded .msh format topography on same grid as distance TopographyFile="Topo.DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" +""" # directory to write output files to -OutDir='testOSMxGSHHS.BOXES/' +OutDir='testGSHHS/' -ww3_mesh_file='RWPS.OSMxGSHHS.BOXES.msh' +ww3_mesh_file='RWPS.GSHHS.WW3.msh' #-------------------Paramter Inputs------------------------------------ #parameters for specifying resolution From af159ce42e049af9b1b8b630cdb7bd9a808bf94f Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 04:20:25 +0000 Subject: [PATCH 18/44] made PostProcessGrid inputs consistent with RWPSMeshGenScript and PreProcessCoastline --- .../MeshGenTemplateDirectory/PostProcessGrid.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 1ec1bc7..1afb822 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -20,8 +20,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: isplot=0; -outdir='testOSMxGSHHS.BOXES/' -pslgfile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS1kmBOXES.msh' +outdir='testGSHHS/' +pslgfile='GlobalCoastlineGSHHS.PSLG.msh' jigsawout='RWPS.F.LLH' %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% From 57a397f3fef827053e0378d1a55448fb96fa914c Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 04:50:05 +0000 Subject: [PATCH 19/44] fixed path issue for unstrutured dataset --- .../InterpolateCRM.partscat.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py index 8e72d5d..ee39ffb 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py @@ -32,11 +32,17 @@ import FiniteElementMeshRoutines as FE import GaussMarkov as GM +# Name of mesh to interpolate bathymetry to +mshnm="HawaiiTest" + +mesh="meshes/"+mshnm+".msh" +OutDir=mshnm+".files/" + # TextOutput = True # prints lots of information durring interpolation (may cause slowdown) TextOutput = False # directory containg all of the bahymetry data files specified in flnms -BathyDir="/mnt/sda/keston/CoastalReliefModel/" +BathyDir="/scratch3/NCEPDEV/climate/Keston.Smith/CoastalReliefModel/" ######################################################## # processed netcdf bathymetry files with variables: @@ -127,9 +133,6 @@ def ZeroPadIntStr(N,K): ZPNs=str(N).zfill(K) return ZPNs -mshnm="HawaiiTest" -mesh="meshes/"+mshnm+".msh" -OutDir=mshnm+".files/" xi, yi, ei = FE.loadWW3MeshCoords(mesh) @@ -202,7 +205,7 @@ def ZeroPadIntStr(N,K): # so this is simply loaded here. ###################################################################### fl=flnms[0] -data = nc.Dataset(fl,"r") +data = nc.Dataset(BathyDir+fl,"r") x0=data["lon"][:] x0=x0%360 y0=data["lat"][:] From 2d319775fb5df1248e1e86b12e25c28cc2480735 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 04:56:38 +0000 Subject: [PATCH 20/44] comments clarifing output file definitions --- .../InterpolateBathymetry/InterpolateCRM.partscat.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py index ee39ffb..ff51dd1 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py @@ -351,15 +351,21 @@ def ZeroPadIntStr(N,K): ziClosest[n]=zs[jc] ###### Output estimates and other statistics to text files ########### +#Inverse distance output np.savetxt(floutID , ziID , fmt='%.6f', delimiter='\n') +#Gauss Markov smoothing with known mean output np.savetxt(floutGMN, ziGMN, fmt='%.6f', delimiter='\n') +#Std error (m) for Gauss Markov smoothing with known mean output np.savetxt(floutGMNerr, stdiGMN, fmt='%.6f', delimiter='\n') -#np.savetxt(floutGMM, ziGMM, fmt='%.6f', delimiter='\n') -#np.savetxt(floutGM0, ziGM0, fmt='%.6f', delimiter='\n') +#Gauss Markov smoothing with unknown mean output np.savetxt(floutGMU, ziGMU, fmt='%.6f', delimiter='\n') +#Std error (m) for Gauss Markov smoothing with unknown mean output np.savetxt(floutGMUerr, stdiGMU, fmt='%.6f', delimiter='\n') +#Nearest neighbor estimate np.savetxt(floutClosest, ziClosest, fmt='%.6f', delimiter='\n') +#Number of bathymetry observations used for each node np.savetxt(floutNpts, NumPoints, fmt='%i', delimiter='\n') +#Mesh length scale approcimation at nodes np.savetxt(floutLLS, LocalLengthScale, fmt='%.6f', delimiter='\n') From c7de8ed532afbcfe4f2db66ed7a4b0b2f8fbd062 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 14:51:09 +0000 Subject: [PATCH 21/44] Added python scripts and postprocessing for generating mesh with modified New Orleans Coast --- .../PostProcessGrid.OSMxGSHHS.NewOrl.m | 382 ++++++++++++++++++ .../RWPSMeshGenScript.OSMxGSSHS.NewOrl.py | 265 ++++++++++++ ...jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl | 16 + 3 files changed, 663 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m new file mode 100644 index 0000000..39ec8a0 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m @@ -0,0 +1,382 @@ + +addpath ../matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab +addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + +%script to handle all post jigsaw mesh editing. +%Post processing steps are as follows +% (A) Remove sand points +% (B) Merge inland lakes --> 'RWPS.WW3a.lakes.msh' +% (C) Remove islands that jigsaw has meshed over +% (D) Remove sand points that can be created (rarely) with island removal --> 'RWPS.WW3a1.lakes.msh' +% INACTIVE (E) Examine Pacific island resolution and make changes to island editing if needed --> 'RWPS.WW3b.lakes.msh' +% INACTIVE (F) Examine mesh near New Orleans where boundary has been merged to reflect new marine zones --> 'RWPS.WW3c.lakes.msh' +% INACTIVE (G) Remove sand points that can be created (rarely) with New Orleans editing --> 'RWPS.WW3d.lakes.msh' +% (H) Stretch open ocean boundary nodes back to origonal specified boundary rectangle --> 'RWPS.WW3e.lakes.msh' +% this is an artificat of the projection used in jigsaw +% (I) Remove sand points that can be created (Should not matter) with boundary node stretching --> 'RWPS.WW3f.lakes.msh' +% (J) Write final WW3 mesh --> 'RWPS.WW3g.lakes.msh' +% this is the mesh to run WW3 on. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: +isplot=0; +outdir='RWPS.OSMxGSHHS.NewOrl/' +pslgfile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS1kmBOXES.msh' +jigsawout='RWPS.F.LLH' + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +g=loadmsh([outdir,jigsawout,'.msh']); + +%remove sand points on boundary + +RemoveSandPoints([outdir,jigsawout,'.msh'],pslgfile,[outdir,jigsawout,'.NSP.msh'],[outdir,jigsawout,'.NSP.WW3.msh']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (B) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%Add Lakes to Mesh +%g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); +g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); + +gS=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Sebago.NWPS.WW3.msh'); +gS.x=gS.x-360; +gW=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Winnipesaukee.NWPS.WW3.msh') +gW.x=gW.x-360; +gO=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Okeechobee.NWPS.WW3.msh') +gO.x=gO.x-360; + +g=CombineMesh(g,gO); +g=CombineMesh(g,gS); +g=CombineMesh(g,gW); + +x=g.x;y=g.y;z=g.z;e=g.e; + +if isplot, + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + caxis([0,12]) + colormap(flip(cm)); +end + +WriteWW3MeshX(g,'RWPS.WW3a.lakes.msh'); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (C) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%clear +g=loadmshWW3('RWPS.WW3a.lakes.msh') +%Remove key islands remaining in mesh that are present in the PSLG file + +p=loadmsh(pslgfile); + +p.x=p.point.coord(:,1); +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +p.x=p.x-360; +x=g.x;y=g.y;z=g.z;e=g.e; + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;axis equal; + hold on + plot(p.x,p.y,'k.') +end + +MinBndDist=1000; +gnew=g; + +%go through all longitude and remove nodes +dx=2; +dxb=10 +%close all +RemoveIsl=1; +n=1 +if RemoveIsl, + for xx=(ceil(min(g.x))+dxb):dx:(floor(max(g.x))-dxb) + ax11=[xx-dx,xx+dx,min(g.y)+dxb,max(g.y)-dxb] + N(n)=length(gnew.x); + AX(n,:)=ax11; + gnew=RemoveMissingIslandsEle(gnew,ax11,p,MinBndDist,0); + n=n+1; + n/243 + length(gnew.x) + %figure(3);clf;plot(N,'ko-');pause(.001) + end +% figure(3);clf;plot(AX(:,1),N,'ko-'); +end + + +g=gnew + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (D) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +g=RemoveSandPointsWW3(g,'RWPS.WW3a1.lakes.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (E) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +p=loadmsh(pslgfile); +p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); + +x=g.x;y=g.y;z=g.z;e=g.e; +if isplot, + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + caxis([0,12]) + colormap(flip(cm)); + hold on; + plot(p.x,p.y,'k.'); +end + +p=loadmsh(pslgfile); +p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); + +g0=g; +gnew=g +if isplot + axAS =[ -179.6738 -159.5513 -18.4086 -7.1731] + axis(axAS);pause(5) + + axTofol =[ -197.5575 -196.5479 4.8724 5.7902] + axis(axTofol);pause(5) + + axPA = [-177.6646 -175.5927 -0.2906 1.3435] + axis(axPA);pause(5) + + axJA =[ -172.1141 -165.7656 14.1706 19.1777] + axis(axJA);pause(5) + + axMWI =[ -179.5965 -176.0019 27.0046 29.8397] + axis(axMWI);pause(5) + + axTin=[-215.1401 -213.4623 14.3922 15.7155] + axis(axTin);pause(5) + + axNNMI =[ -215.9834 -213.8052 19.3525 21.0704]; + axis(axNNMI);pause(5) + + axNNMI1=[-214.8924 -213.6875 14.6480 15.5983]; + axis(axNNMI1);pause(5) + + axMaj =[ -177.2629 -175.7651 -0.1340 1.0474] + axis(axMaj);pause(5) + + axHI =[ -179.1073 -153.7595 11.4935 31.4855] + axis(axHI);pause(5) + + axChuuk =[ -198.1190 -196.0417 4.7967 5.8354] + axis(axChuuk);pause(5) +end + +WriteWW3MeshX(gnew,'RWPS.WW3b.lakes.msh') + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (F) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%fix new orleans +%clear +g=loadmshWW3('RWPS.WW3b.lakes.msh') +%Examine and Hand Edit Mesh around new orleans to relect changes if nescesary +%Should not be nescesary with +if isplot, + x=g.x;y=g.y;z=g.z;e=g.e; + LS=ComputeLengthScale_wgs84_MEL(x,y,e); + LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,12]); + % Shape file of new marine zones in New Orleans + S=shaperead('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/mz03mr26_LIX.shp') + hold on + for k=1:length(S),plot(S(k).X,S(k).Y,'k');end + + axNOZ =[ -91.6701 -87.7499 28.7284 30.9173] + axis(axNOZ) + gnew=g; + eno=input('Enter 1 if you want to edit the mesh around New Orleans:' ) + if eno, + gnew=RemoveMeshParts(g,axNOZ,S,[0,50]); + else + gnew=g; + end +else + gnew=g;% no edit +end + +WriteWW3MeshX(gnew,'RWPS.WW3c.lakes.msh') + +%confirm no introduction of sand points +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (G) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +g=RemoveSandPointsWW3(gnew,'RWPS.WW3d.lakes.msh') + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (H) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Fix boundary warping from projection in mesh generation +%clear +close all +g=loadmshWW3('RWPS.WW3d.lakes.msh') +g0=g; + +Blon=[129.91 10.71] +Blat=[-30.42 79.99] +Blon(1)=Blon(1)-360 +x=g.x;y=g.y;z=g.z;e=g.e; +jb=g.bnd; +bnd0=detbndy(g.e) + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e')); + cm=colormap('jet');shading interp;hold on + colormap(flip(cm)); + axis equal;hold on + plot(g.x(jb),g.y(jb),'k.');hold on +end +js=find(g.y(jb)max(Blat)); +g.y(jb(js))=max(Blat); +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end + +%dx=degree latitude delta to discriminate land points near boundary from open ocean boundary +dx=.05; +js=find(and( g.x(jb)>min(Blon),g.x(jb)max(Blon)-dx )); +g.x(jb(js))=max(Blon); +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end +WriteWW3MeshX(g,'RWPS.WW3e.lakes.msh') + +%confirm no introduction of sand points +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (I) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +g0=RemoveSandPointsWW3(g,'RWPS.WW3f.lakes.msh') + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (J) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +WriteWW3MeshX(g0,'RWPS.WW3g.lakes.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Some Plotting +if isplot, + g=g0; + + + %clear + g=loadmshWW3('RWPS.WW3g.lakes.msh')%RWPS.PIXAllLnwps.PP.WW3c.msh'); + x=g.x;y=g.y;z=g.z;e=g.e; + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + jb=g.bnd; + hold on; + plot(g.x(jb),g.y(jb),'k.');hold on + + + f=z; + clf;patch(x(e'),y(e'),f(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,6000]); + kprint('Bathy.jpg'); + + clf; + caxis([0,6000]); + colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + %hcb.Label.String='(km)' + set(gca,'visible','off') + kprint('BathyColorbarH.jpg'); + + clf; + colorbar; + colormap(flip(cm)); + caxis([0,6000]); + kprint('BathyColorbarV.jpg'); + + + LS=ComputeLengthScale_wgs84_MEL(x,y,e); + LSn=Ele2Nodes(x,y,e,LS); + + clf;patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + colormap(flip(cm)); + caxis([0,12]); + kprint('Lengthscale.jpg'); + + + axCAR =[ -85.4065 -61.7227 8.8200 26.8661] + ax=axCAR + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Caribean.jpg') + + + axAK =[ -192.1450 -152.2804 47.2479 77.6231] + ax=axAK + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Alaska.jpg') + + axHI =[ -179.5950 -152.9066 13.8641 34.1996] + ax=axHI + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Hawaii.jpg') + + + axMI =[ -220.2161 -208.6314 12.5003 21.3274]; + ax=axMI + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('MarianaIslands.jpg') + + axAS =[ -173.3623 -168.3684 -16.4846 -12.0090] + ax=axAS + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('AmericanSamoa.jpg') + + + axMicro =[ -210.3818 -185.8701 -3.7494 15.5832] + ax=axMicro + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('Micronesia.jpg') + + axWMicro =[ -226.6896 -214.3594 5.3753 15.1002] + ax=axWMicro + axis(ax);daspect([1,cos(pi*ax(3)/180),1]) + kprint('WestMicronesia.jpg') + + + figure; + clf; + caxis([0,12]); + colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(km)' + set(gca,'visible','off') + kprint('LengthScaleColorbarH.jpg'); + + clf + caxis([0,12]); + colormap(flip(cm)); + + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(km)' + set(gca,'visible','off') + kprint('LengthScaleColorbarV.jpg'); + + + clf + caxis([0,6000]); + colormap(flip(cm)); + + hcb=colorbar('h','position',[.1,.075,.8,.025]) + hcb.Label.String='(m)' + set(gca,'visible','off') + kprint('BathyColorbarH.jpg'); + + clf + caxis([0,6000]); + colormap(flip(cm)); + + % hcb=colorbar('v','position',[.1,.075,.8,.025]) + vcb=colorbar('v','position',[.075,.1,.025,.8]) + vcb.Label.String='(m)' + set(gca,'visible','off') + kprint('BathyColorbarV.jpg'); + +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py new file mode 100644 index 0000000..db08dc2 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py @@ -0,0 +1,265 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- + +""" +#OSM coastline +PSLGFile="GlobalCoastlineOSM.PSLG.msh" +DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" +TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" + +#GSSH coastline +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" +""" + +# GSHHS except identified problem spots (i.e. American Samoa) where OSM is used +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS1kmBOXES.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/DistToUScoast_shifted.OSMxGSHHS.Boxes.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/Topo_shifted.OSMxGSHHS.Boxes.msh" + +# directory to write output files to +OutDir='RWPS.OSMxGSHHS.NewOrl/' + +ww3_mesh_file='RWPS.GSHHSxGSHHS.NewOrl.WW3.msh' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=10000. +d1=320000. - d0 +beta=1000. +Smin=0.5 +Smax=10. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "jcfg.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl new file mode 100644 index 0000000..2f0d59d --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl @@ -0,0 +1,16 @@ +#!/bin/sh +#SBATCH --nodes=1 +#SBATCH --ntasks=32 # Number of tasks/cores +#SBATCH --ntasks-per-node=32 +#SBATCH -q batch +#SBATCH -t 08:00:00 +#SBATCH -A marine-cpu +#SBATCH -J MeshPostProcess +#SBATCH -o MeshPostProcess.out + + +# Load the MATLAB module +module load matlab/R2024b # Specify the version you need + +# Run your MATLAB script without a graphical interface +matlab -nodisplay -nodesktop -r "run('./PostProcessGrid.OSMxGSHHS.NewOrl.m'); exit;" From 3ffc5386fefaa69895ea60a74d0822751802a4cc Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 14:52:09 +0000 Subject: [PATCH 22/44] Added Ursa jobcards for generating mesh with modified New Orleans Coast --- .../jigsaw.ursa.NewOrl.job | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job new file mode 100644 index 0000000..7c94ed0 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job @@ -0,0 +1,32 @@ +#!/bin/bash +#SBATCH --job-name=jigsaw_py_RWPSng # Job name +#SBATCH --mail-type=END # Mail events (BEGIN, END, FAIL, ALL) +#SBATCH --mail-user=keston.smith@noaa.gov # Where to send mail +##SBATCH --ntasks=144 # Number of MPI ranks +#SBATCH --mem-per-cpu=256000mb # Memory per processor +#SBATCH --time=08:00:00 # Time limit hrs:min:sec +#SBATCH --output=mpi_test_%j.log # Standard output/error +#SBATCH --exclusive=user +#SBATCH --error=%j.err +##SBATCH --partition=marine-cpu +#SBATCH --account=marine-cpu +#SBATCH --nodes=1 +#SBATCH --ntasks=1 + + + +module purge +module use /scratch3/NCEPDEV/climate/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles/ +module load ufs_ursa.intel +module load stack-oneapi/2024.2.1 +module load python/3.11 +module load cmake/3.27.9 + +module load py-numpy/1.26.4 +module load ufs_ursa.intel +module load py-netcdf4/1.7.1.post2 + +source /scratch3/NCEPDEV/climate/Keston.Smith/UrsaMeshgenEnv/jigsawenv/bin/activate +pip list -v + +python3 RWPSMeshGenScript.OSMxGSSHS.NewOrl.py > NonGlobalMeshGen.OSMxGSSHS.NewOrl.out.txt From 95697c727f021554cea150e5043be55880e0052e Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 15:50:58 +0000 Subject: [PATCH 23/44] Fixed file matlab name for OSMxGSHHS.NewOrl post processing --- ...id.OSMxGSHHS.NewOrl.m => PostProcessGrid_OSMxGSHHS_NewOrl.m} | 0 .../jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/{PostProcessGrid.OSMxGSHHS.NewOrl.m => PostProcessGrid_OSMxGSHHS_NewOrl.m} (100%) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.OSMxGSHHS.NewOrl.m rename to unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl index 2f0d59d..f110bbd 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl @@ -13,4 +13,4 @@ module load matlab/R2024b # Specify the version you need # Run your MATLAB script without a graphical interface -matlab -nodisplay -nodesktop -r "run('./PostProcessGrid.OSMxGSHHS.NewOrl.m'); exit;" +matlab -nodisplay -nodesktop -r "run('./PostProcessGrid_OSMxGSHHS_NewOrl.m'); exit;" From 1cd904f2105a888834ba022e9915fe3bddda3f69 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 16:02:01 +0000 Subject: [PATCH 24/44] removed some unescesary files in unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory --- .../BuildBoundaryPSLGfunction.m | 348 ------------------ .../MakeDfun_mshfile.m | 308 ---------------- 2 files changed, 656 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m deleted file mode 100644 index fe69089..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGfunction.m +++ /dev/null @@ -1,348 +0,0 @@ -function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) -%CoastLineFile = 'GlobalCoastlineOSM.shp' -%CoastLineFile = 'GlobalCoastlineGSHHS.shp' -%lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; -%run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) - -S=shaperead(CoastLineFile) -FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] -FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] -isplot=0; - -%load GlobalCoastlineOSM.mat - - -%The overall objective of this project is to develop and implement into operations -% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, -% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, -% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the -% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. - -%Blon=[129.91 10.71]; -%Blat=[-30.42 79.99]; -Blon=[lonWest, lonEast]; -Blat=[latSouth,latNorth]; - - -N=length(S); -N1=N; -for k=1:N - if mod(k,1000)==0,k/N,end - lon=S(k).X(1:end-1);%remove trailing nan - lat=S(k).Y(1:end-1); - ns(k)=length(lon); - jWest=find(lon<90); - if(length(jWest)==ns(k)); - S(k).X=[lon+360,NaN]; - end - if and(0length(jWest)),%make translated copy - display(['duplicating coastal segment: ',int2str(k), ', nseg=',int2str(ns(k))]) - N1=N1+1; - S(N1).X=[lon+360,NaN]; - S(N1).Y=[lat,NaN]; - ns(N1)=length(lon); - end -end -N=length(S); -[tmp,j]=sort(-ns); -S=S(j);% sort to descending in length -ns=ns(j);% sort to descending in length - -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); -Blon=lon; - -%Make Bounding rectangle -Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] -By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] - -clear pslg -sxp=[];syp=[ ]; -xc=[];yc=[]; -N=length(S); -pslg.x=[]; -pslg.y=[]; -pslg.edges=[]; -nc=0; - -minedeges=4 -minarea=1 - -earth=referenceSphere('Earth'); -DXM=10^10;%DXM=1 -mdx=inf+ones(N,1); -for k=1:N - isinbox(k)=0; - x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) - y=S(k).Y(1:end-1); - mx=mean(x); - my=mean(y); - if length(x)>minedeges, - ji=find( insidepoly( x,y,Bx,By ) ); - if length(ji)>2 - [xi, yi,ii] = polyxpoly(x, y, Bx, By); - xc=[xc;xi(:)]; - yc=[yc;yi(:)]; - if ~isempty(xi) %modify ob - sxp=[sxp,x(1)];syp=[syp,y(1)]; - [iia,jja]=sort(ii(:,1));%sort to ascending order along segments - xia=xi(jja); - yia=yi(jja); - iis=ii(jja,1);%sorted into ascending order along segments - if ~insidepoly( x(1),y(1),Bx,By )% segment origonates outside box - nseg=length(xia); - for j=1:2:nseg-1, - xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; - ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; - dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); - mdx(k)=max(dx); - - if max(dx) island entirely inside bounding box - xs=[x(1:end-1)]; - ys=[y(1:end-1)]; - dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); - if and(length(xs)>2,max(dx)3, ar> - if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end -end - -%OK - now revisit outer boundary! -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%restart script from here if needed -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%clear -%close all -eval(['load ',FileOutMatlab]); -%load pslgOSM.mat -%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] -%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] - -%make outer bound -n=length(pslg.x); -%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes -%pslg.y=[pslg.y,By(3:4)]; -pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes -pslg.y=[pslg.y,By(2:4)]; - -nc=length(pslg.chains);%add northwest and north east box corner chains -pslg.chains(nc+1).nodes=n+1; -nc=length(pslg.chains); -pslg.chains(nc+1).nodes=n+2; -nc=length(pslg.chains); -pslg.chains(nc+1).nodes=n+3; -nc=length(pslg.chains); - -xx =153.0400 %south east corner of Austrilia -yy = Blat(1) %check that these are the endpoints described for j0, j1!! -[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) -if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end - -xx = 288.3143%check that these are the endpoints described for j0, j1!! -yy = Blat(1) %south west corner of S. America -[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) -if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end - -nc=length(pslg.chains); -pslg.chains(nc+1).nodes=[j0,j1]; -nc=length(pslg.chains); - -for k=1:nc - if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end - spx(k)=pslg.x(pslg.chains(k).nodes(1)); - spy(k)=pslg.y(pslg.chains(k).nodes(1)); - epx(k)=pslg.x(pslg.chains(k).nodes(end)); - epy(k)=pslg.y(pslg.chains(k).nodes(end)); - end - -%make boundary order index along boundary for start points -SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges -c=0*spy; -Deps1=10^-10 -j=find(abs(spy-By(1))v); -[mm,m]=min(c(j)); -l=j(m); -epi=[epi,pslg.chains(l).nodes]; -obc=[obc,l]; -n=0; -%while(epi(end)~=epi(1)) -while isempty( find(epi(2:end)==epi(1)) ) - v=d(l); - j=find(c>v); - [mm,m]=min(c(j)); - l=j(m) - epi=[epi,pslg.chains(l).nodes]; - obc=[obc,l]; - if isplot==1, plot(pslg.x(epi),pslg.y(epi),'r.-');pause(.001);end -end -j=find(epi(2:end)==epi(1)); -epi=epi(1:(j+1)); -%vvvvvvvvvvv Add fixed grid points on open boundary -% to prevent "curved" boundaries due to projection details -xob=pslg.x(epi); -yob=pslg.y(epi); -dob=abs([xob(2:end)-xob(1:end-1)]+i*[yob(2:end)-yob(1:end-1)]); -dob=[dob,abs([xob(end)-xob(1)]+i*[yob(1)-yob(end)])]; -nb=length(xob); -dmin=1;%node spacing around boundary -epit=epi; -for k=1:nb-1 - d=abs([xob(k+1)-xob(k)]+i*[yob(k+1)-yob(k)]); - if d>dmin - npl=round(d/dmin)-1; - dx=xob(k+1)-xob(k); - dy=yob(k+1)-yob(k); - xp=xob(k)+dx*[1:npl-1]/npl; - yp=yob(k)+dy*[1:npl-1]/npl; - np=length(xp); - n=length(pslg.x); - pslg.x=[pslg.x,xp]; - pslg.y=[pslg.y,yp]; - NewEdges=[[epi(k),n+1];[[n+1:n+np-1]',[n+2:n+np]'];[n+np,epi(k+1)]]; - %pslg.edges=[pslg.edges;NewEdges]; - j=find(epi(k)==epit ); - epit=[epit(1:j),n+1:n+np,epit(j+1:end)]; - end -end -epi=epit; -% to prevent "curved" boundaries due to projection details -%^^^^^^^^^^^^ Add fixed grid points on open boundary - - -% add edges in obc -epiv=epi(:); -NOE=length(epiv) -OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; -pslg.edges=[pslg.edges;OutterEdges]; - -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); - -nodelist=[]; -for k=1:nc - if mod(k,100)==0,disp(['Finding interior chains compleate: ',num2str(k/nc)]);,end - if pslg.chains(k).nodes(1)==pslg.chains(k).nodes(end) - n=pslg.chains(k).nodes(1); - [inpoly,onpoly]=insidepoly( pslg.x(n), pslg.y(n),xob,yob); - if and(inpoly==1,onpoly==0) - nodelist=union(nodelist,pslg.chains(k).nodes); - end - end -end - -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi']); - -nodelistXB=union(nodelist,epi); -pslgb=subpslgFast(pslg,nodelistXB); - -%remove "random" duplicate nodes -%z=pslgb.x+i*pslgb.y; -%[zu,j,k]=unique(z); -%pslgc=subpslgFast(pslgb,j); -pslgc=pslgb - -%remove duplicate edges -pslgc.edgesS=sort(pslgc.edges')'; -pslgc.edgesSU=unique(pslgc.edgesS,'rows') -pslgc.edges=pslgc.edgesSU; - -pslg=pslgc - -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); - -%save PSLG to jigsaw .msh format -geom=pslg2geom(pslg) -savemsh(FileOutJigsaw,geom) - diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m deleted file mode 100644 index 7482382..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfun_mshfile.m +++ /dev/null @@ -1,308 +0,0 @@ -%This script creates a "Distance to Coast file" using a us coastline file -%and custom specification of - -clear -close all -isplot=0 - -%Input files -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' -%PSLGfile='GlobalCoastlineOSM.PSLG.msh' -PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' -%Global Bathymetry file (netcdf) -GlobalTopoFile='../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' -%Shape file with US coastline -uscl='../RWPS/Data/us_coastline/tl_2023_us_coastline.shp' - -%Output files -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Output "distance to coast" grided jigsaw .msh file -DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] -%Output bathymetry on same grid as DFunOutFile -TopoFile=['Topo.',DFunOutFile]; -%Temporary matlab file -FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] - - -US=shaperead(uscl); -NUS=length(US) -xus=[]; -yus=[]; -x0=[] -y0=[]; -interpDist=100. %meters -SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist -% then subsample soothed coastline every SmoothN points to create smaller -% coastline data set. i.e. remove small scale variation -for k=1:NUS - x=US(k).X(1:end-1); - y=US(k).Y(1:end-1); - x0=[x0,x]; - y0=[y0,y]; -% xs=x;ys=y; %1.5 mil points - if length(x)>3 - [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); - xus=[xus,xs]; - yus=[yus,ys]; - end -end -n0=length(xus); -%Now add Pacific Territories and COFA points -%------------------------------------------------------------------------ -%NWS Pacific Region, via the Compact of Free Association, -% %oversees operations of 5 Weather Service Offices (WSO) across -% Micronesia in the Republic of Palau, Federated States of Micronesia -% and the Republic of the Marshall Islands. WFO Guam provides routine -% forecasts as well as WWA services for these areas. -Eric Lau -%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island - -%Wake Island -coord=[19.2796,166.6499];%E -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Palau -coord=[7.4942, 134.5690] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Yap:9.5557° N, 138.1399° E -coord=[9.5557, 138.1399] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Chuuk: 7°25′N 151°47′E -coord=[7.374227, 151.754606]%E -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pohnpei › Coordinates: 6.8519° N, 158.2147° E -coord=[6.8519, 158.2147] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Majuro › Coordinates7.0667° N, 171.2667° E -coord=[7.0667, 171.2667] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pago Pago › Coordinates: 14.2732° S, 170.7030° W -coord=[-14.2732, -170.7030]% SW -xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Kosrae › Coordinates :5.3096° N, 162.9815° E -coord=[5.3096, 162.9815] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%------------------------------------------------------------------------ - -%Marshall Islands -%Majuro -coord=[7.0667, 171.2667] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Ebeye -coord=[8.7815, 167.7373] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Micronesia -%Kolonia, -coord=[6.9636, 158.2102] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pohnpei, -coord=[6.8519, 158.2147] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Chuuk-Weno -coord=[7.4523, 151.8422] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Tofol -coord=[5.3256, 163.0086] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Colonia -between Palau and Guam -coord=[9.5164,138.1222] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -n1=length(xus); -%------------------------------------------------------------------------ -%Points from Curt -%Howland Island -Baker -coord=[0.8113, -176.6183]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Johnston atoll -coord=[16.7295, -169.5336]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Palmyra -coord=[5.8885, -162.0787]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Jarvis Island -coord=[0.3744, -159.9967]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Baker Island -%0.1936° N, 176.4769° W -coord=[0.1936,-176.4769 ]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%------------------------------------------------------------------------ - coord=[18.4101, -75.0115 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: - %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg - %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). - %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. - %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. - - %Kwajalein Atoll - 9.1898° N, 167.4243° E - %Enewetak Atoll - 11.4654° N, 162.1890° E - %Bikini Atoll - 11.6065° N, 165.3768° E - - %Kwajalein Atoll - 9.1898° N, 167.4243° E - coord=[9.1898, 167.4243 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %Enewetak Atoll - 11.4654° N, 162.1890° E - coord=[ 11.4654, 162.1890]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %Bikini Atoll - 11.6065° N, 165.3768° E - coord=[11.6065, 165.3768 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - -Blon=[129.91 10.71]; -Blat=[-30.42 79.99]; -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); -Blon=lon; -xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; - -if isplot, - clf; - plot(xusp(1:n0) ,yus(1:n0),'k.',... - xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... - xusp(n1+1:end),yus(n1+1:end),'rx'); - hold on - BoundingBox(Blon-360,Blat,'r'); - grid on; - title('Updated RWPS high res target points'); - kprint('RWPSHighResPointsX.jpg'); -end -topo=BoxSmoothTopo(GlobalTopoFile,2); - -lon = topo.point.coord{:,1}; -lat = topo.point.coord{:,2}; - -%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); -p=loadmsh(PSLGfile); - -p.x=p.point.coord(:,1)-360; -p.y=p.point.coord(:,2); -p.edges=p.edge2.index(:,1:2); -plot(p.x,p.y,'g.'); - -%Remove near boundary points- Not land targets of resolution -dx=1; -j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); -j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); -plot(p.x,p.y,'y.'); - -j=find(xus>90); -xus(j)=xus(j)-360; - -%This loop Takes a few min:Find PSLG points near us coastline -deg2km=111.132954 -np=length(p.x); -NP=10000; - -clear d; -nus=length(xus); -for k=1:NP:np - j=k:min(np,k+NP); - x=p.x(j); - y=p.y(j); - d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); - %if mod(k,1000)==0,k/np,end - k/np -end - -dmin=100; -%dmin=50; -j=find(d90); -xus(j)=xus(j)-360; -Blon=[129.91-360, 10.71]; -Blat=[-30.42, 79.99]; -if isplot, - plot(p.x,p.y,'k.'); - hold on - BoundingBox(Blon,Blat,'k'); - th=title('PSLG defining boundary'); - set(th,'FontSize',22); - kprint('PSLG.jpg') - - plot(xus,yus,'r.'); - th=title('PSLG with US coasline data points(red)'); - set(th,'FontSize',22); - kprint('PSLGwUSpoints.jpg') - - j=find(d<100); - plot(p.x(j),p.y(j),'c.'); - th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); - set(th,'FontSize',22); - kprint('PSLGwUSpointsPSLGnear.jpg') -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%add points to off shore banks we want to refine here we have Georges Bank -%and banks around the Bahamas. - -xFB= [ -79.9909 -78.1963 -78.3957] -yFB= [23.7978 26.8928 24.1530] -xGB = -67.4517 -yGB = 41.3567 - -xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; -yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; -j=find(xx>90); -xx(j)=xx(j)-360; -plot(xx,yy,'c.'); - -D=DistanceToCoast(lon,lat,xx,yy); - -eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Make .msh files for jigsaw - -topo=BoxSmoothTopo(GlobalTopoFile,2); - -Dfun=topo; - -lon=Dfun.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); -j0=setdiff(1:length(lon),j);j0=j0(:); -lon=lon([j0(:);j(:)]); -D1=[D(:,j0),D(:,j)]; -Dfun.point.coord{:,1}=lon; -Dfun.value=D1; - -Dmax=20004000%max distance between two points on earth -D1(find(D1>Dmax))=Dmax; -Dfun.value=D1; - -figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); -shading interp;colorbar;colormap('jet') -savemsh(DFunOutFile,Dfun); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% save smoothed topo at same resolution as Distance function -topo=BoxSmoothTopo(GlobalTopoFile,2); - -D=topo.value; -lon=topo.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); -j0=setdiff(1:length(lon),j);j0=j0(:); -lon=lon([j0(:);j(:)]); -D1=[D(:,j0),D(:,j)]; -topo.point.coord{:,1}=lon; -topo.value=D1; - -figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); -shading interp;colorbar;colormap('jet') -savemsh(TopoFile,topo); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% From 3d542a30656f81f1c090ea1e574e2cf0ee7ab935 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 16:58:42 +0000 Subject: [PATCH 25/44] added script to download all needed bathymetry data --- .../DownloadBathyData.py | 90 -------------- .../jobcard.DowloadBathyData | 111 ++++++++++++++++++ 2 files changed, 111 insertions(+), 90 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py deleted file mode 100644 index 0ee7ef9..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DownloadBathyData.py +++ /dev/null @@ -1,90 +0,0 @@ - - - "crm_vol1_2023.nc.S250m.VB.nc", - "crm_vol2_2023.nc.S250m.VB.nc", - "crm_vol3_2023.nc.S250m.VB.nc", - "crm_vol4_2023.nc.S250m.VB.nc", - "crm_vol5_2023.nc.S250m.VB.nc", - "crm_vol7_2024.nc.S250m.VB.nc", - "crm_vol9_2023.nc.S250m.VB.nc", - "crm_vol10_2023.nc.S250m.VB.nc", - "crm_vol6_2023.nc.S250m.VB.nc", - "crm_vol8_2023.nc.S250m.VB.nc", - "crm_southak.CRMformat.nc", - - - "PIX/ngdc_bathy_10m_wake.CRM.nc", - "PIX/pibhmc_bathy_20m_jarvis.CRM.nc", - "PIX/pibhmc_bathy_20m_johnston.CRM.nc", - - - - "PIX/pibhmc_bathy_20m_kingman.CRM.nc", - "PIX/pibhmc_bathy_40m_baker.CRM.nc", - "PIX/pibhmc_bathy_40m_howland.CRM.nc", - "PIX/pibhmc_bathy_40m_palmyra.CRM.nc", - "PIX/pibhmc_bathy_40m_rose.CRM.nc", - "PIX/pibhmc_bathy_40m_swains.CRM.nc", - "PIX/pibhmc_bathy_40m_vailuluu.CRM.nc", - - "PIX/pibhmc_bathy_5m_palmyra.CRM.nc", - "PIX/sopac_bathy_50m_majuro_reef.CRM.nc", - "PIX/ngdc_bathy_180m_mariana.CRM.nc", - - "RTopo_2_0_4_GEBCO_v2023_60sec_pixel.CRMformat.nc" - - - -# American Samoa -wget --output-document ngdc_bathy_90m_amsamoa.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_90m_amsamoa?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -# Mariana islands -wget --output-document ngdc_bathy_180m_mariana.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_180m_mariana?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -#North Western Hawiian islands -wget --output-document hurl_bathy_60m_nwhi.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/hurl_bathy_60m_nwhi?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -#US Minor outlying islands -#Wake island -wget --output-document ngdc_bathy_10m_wake.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_10m_wake?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_jarvis.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_jarvis?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_johnston.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_johnston?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_kingman.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_kingman?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_baker.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_baker?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_howland.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_howland?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_rose.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_rose?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_vailuluu.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_vailuluu?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_swains.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_swains?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_5m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_5m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document sopac_bathy_50m_majuro_reef.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/sopac_bathy_50m_majuro_reef?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - - -#For Coastal Relief Model: -#Please note: Due to scheduled maintenance, many NCEI systems will be unavailable February 3, 11:00 AM ET - February 11, 8:00 PM ET. We apologize for any inconvenience. More details. - -https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 - -wget --output-document cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.nc https://s3.waw3-1.cloudferro.com/mdl-native-17/native/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/cmems_obs-sdb_glo_phy_wk_my_100m-l4-s2_static_202511/cmems_obs-sdb_glo_phy-wk_my-oa-100m-l4-s2_static.nc - -#https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 -#cmems url- not for wget - -# 60 second Global Bathymetry -wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.zip - - -wget https://github.com/dengwirda/dem/releases/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip -wget https://github.com/dengwirda/dem/releases/expanded_assets/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip - diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData new file mode 100644 index 0000000..c510ca7 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData @@ -0,0 +1,111 @@ +#!/bin/bash +#SBATCH --job-name=download_data # Job name +#SBATCH --output=download_data_%j.out # Standard output and error log +#SBATCH --error=download_data_%j.err # Standard error log +#SBATCH --account=marine-cpu +#SBATCH --nodes=1 # Run on 1 node +#SBATCH --ntasks=1 # Run a single task +#SBATCH --time=08:00:00 # Time limit hrs:min:sec + +############################################################################################################# + +# Script to download global and regional bathymetry files: +# You will need ~ 20 GB free space + +echo "Downloading bathymetry data" + +############################################################################################################# +######################## Download main Coastal Relief Moesl (CRM) files ##################################### +############################################################################################################# +# see: https://www.ncei.noaa.gov/products/coastal-relief-model +############################################################################################################# +#Northeast Atlantic +wget --output-document crm_vol1_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol1_2023.nc +#Southeast Atlantic +wget --output-document crm_vol2_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol2_2023.nc +# Florida and East Gulf of America +wget --output-document crm_vol3_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol3_2023.nc +# Central GOA +wget --output-document crm_vol4_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol4_2023.nc +# Western GOA +wget --output-document crm_vol5_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol5_2023.nc +#Central Pacific +wget --output-document crm_vol7_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol7_2023.nc +#Northwest Pacific +wget --output-document crm_vol8_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol8_2023.nc +#Puerto Rico +wget --output-document crm_vol9_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol9_2023.nc +#Hawaii +wget --output-document crm_vol10_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol10_2023.nc +#Other CRM files +# Southern California +wget --output-document crm_vol6.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_vol6.nc +# Southern Alaska +wget --output-document crm_southak.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_southak.nc +############################################################################################################# + +echo "Done Coastal Relief Model (CRM) Download" + +############################################################################################################# +######################## Download regional files in Pacific ################################################# +############################################################################################################# +# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html +############################################################################################################# +# American Samoa +wget --output-document ngdc_bathy_90m_amsamoa.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_90m_amsamoa?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +# Mariana islands +wget --output-document ngdc_bathy_180m_mariana.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_180m_mariana?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +#North Western Hawiian islands +wget --output-document hurl_bathy_60m_nwhi.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/hurl_bathy_60m_nwhi?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +############################################################################################################# + +echo "Done regional files in Pacific Download" + +############################################################################################################# +######################## Download small scale bathymetry for US Minor outlying islands in Pacific ########### +############################################################################################################# +# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html +############################################################################################################# +wget --output-document ngdc_bathy_10m_wake.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_10m_wake?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_jarvis.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_jarvis?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_johnston.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_johnston?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_kingman.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_kingman?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_baker.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_baker?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_howland.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_howland?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_rose.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_rose?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_vailuluu.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_vailuluu?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_swains.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_swains?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_5m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_5m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document sopac_bathy_50m_majuro_reef.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/sopac_bathy_50m_majuro_reef?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +############################################################################################################# + +echo "Done small scale bathymetry for US Minor outlying islands in Pacific download" + +############################################################################################################# +######################## Global SDB [~0m to ~30m] depth from copernicus ##################################### +############################################################################################################# +# see: https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 +############################################################################################################# +wget --output-document cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.nc https://s3.waw3-1.cloudferro.com/mdl-native-17/native/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/cmems_obs-sdb_glo_phy_wk_my_100m-l4-s2_static_202511/cmems_obs-sdb_glo_phy-wk_my-oa-100m-l4-s2_static.nc +############################################################################################################# + +echo "Done Global SDB download" + +############################################################################################################# +######################## 60 second Global Bathymetry######################################################### +wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip +############################################################################################################# + +echo "Done Global Bathymetry download" From 85a0ca56865d2bd9acf86fa8ac71c8c4af549c70 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 17:13:35 +0000 Subject: [PATCH 26/44] added script to download all needed bathymetry data (again) --- .../InterpolateBathymetry/jobcard.DowloadBathyData | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData index c510ca7..cea2df8 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData @@ -4,7 +4,7 @@ #SBATCH --error=download_data_%j.err # Standard error log #SBATCH --account=marine-cpu #SBATCH --nodes=1 # Run on 1 node -#SBATCH --ntasks=1 # Run a single task +###SBATCH --ntasks=1 # Run a single task #SBATCH --time=08:00:00 # Time limit hrs:min:sec ############################################################################################################# From ca1f4ef806d33b477581741b1ea8e29959a08b20 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 18:33:13 +0000 Subject: [PATCH 27/44] added shell script to download all bathymetry data used in RWPS --- .../InterpolateBathymetry/DowloadBathyData.sh | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh new file mode 100755 index 0000000..0355532 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh @@ -0,0 +1,103 @@ +#!/bin/bash +############################################################################################################# + +# Script to download global and regional bathymetry files: +# You will need ~ 20 GB free space + +echo "Downloading bathymetry data" + +############################################################################################################# +######################## Download main Coastal Relief Moesl (CRM) files ##################################### +############################################################################################################# +# see: https://www.ncei.noaa.gov/products/coastal-relief-model +############################################################################################################# +#Northeast Atlantic +wget --output-document crm_vol1_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol1_2023.nc +#Southeast Atlantic +wget --output-document crm_vol2_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol2_2023.nc +# Florida and East Gulf of America +wget --output-document crm_vol3_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol3_2023.nc +# Central GOA +wget --output-document crm_vol4_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol4_2023.nc +# Western GOA +wget --output-document crm_vol5_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol5_2023.nc +#Central Pacific +wget --output-document crm_vol7_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol7_2023.nc +#Northwest Pacific +wget --output-document crm_vol8_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol8_2023.nc +#Puerto Rico +wget --output-document crm_vol9_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol9_2023.nc +#Hawaii +wget --output-document crm_vol10_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol10_2023.nc +#Other CRM files +# Southern California +wget --output-document crm_vol6.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_vol6.nc +# Southern Alaska +wget --output-document crm_southak.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_southak.nc +############################################################################################################# + +echo "Done Coastal Relief Model (CRM) Download" + +############################################################################################################# +######################## Download regional files in Pacific ################################################# +############################################################################################################# +# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html +############################################################################################################# +# American Samoa +wget --output-document ngdc_bathy_90m_amsamoa.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_90m_amsamoa?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +# Mariana islands +wget --output-document ngdc_bathy_180m_mariana.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_180m_mariana?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +#North Western Hawiian islands +wget --output-document hurl_bathy_60m_nwhi.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/hurl_bathy_60m_nwhi?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +############################################################################################################# + +echo "Done regional files in Pacific Download" + +############################################################################################################# +######################## Download small scale bathymetry for US Minor outlying islands in Pacific ########### +############################################################################################################# +# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html +############################################################################################################# +wget --output-document ngdc_bathy_10m_wake.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_10m_wake?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_jarvis.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_jarvis?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_johnston.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_johnston?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_20m_kingman.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_kingman?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_baker.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_baker?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_howland.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_howland?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_rose.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_rose?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_vailuluu.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_vailuluu?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_40m_swains.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_swains?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document pibhmc_bathy_5m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_5m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true + +wget --output-document sopac_bathy_50m_majuro_reef.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/sopac_bathy_50m_majuro_reef?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true +############################################################################################################# + +echo "Done small scale bathymetry for US Minor outlying islands in Pacific download" + +############################################################################################################# +######################## Global SDB [~0m to ~30m] depth from copernicus ##################################### +############################################################################################################# +# see: https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 +############################################################################################################# +wget --output-document cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.nc https://s3.waw3-1.cloudferro.com/mdl-native-17/native/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/cmems_obs-sdb_glo_phy_wk_my_100m-l4-s2_static_202511/cmems_obs-sdb_glo_phy-wk_my-oa-100m-l4-s2_static.nc +############################################################################################################# + +echo "Done Global SDB download" + +############################################################################################################# +######################## 60 second Global Bathymetry######################################################### +wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip +############################################################################################################# + +echo "Done Global Bathymetry download" From 990718752676d535cfd6e6bedd1454a3359b1a6a Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 18:34:36 +0000 Subject: [PATCH 28/44] removed slurm jobcard for downloading data (replaced with shell script) --- .../jobcard.DowloadBathyData | 111 ------------------ 1 file changed, 111 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData deleted file mode 100644 index cea2df8..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/jobcard.DowloadBathyData +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash -#SBATCH --job-name=download_data # Job name -#SBATCH --output=download_data_%j.out # Standard output and error log -#SBATCH --error=download_data_%j.err # Standard error log -#SBATCH --account=marine-cpu -#SBATCH --nodes=1 # Run on 1 node -###SBATCH --ntasks=1 # Run a single task -#SBATCH --time=08:00:00 # Time limit hrs:min:sec - -############################################################################################################# - -# Script to download global and regional bathymetry files: -# You will need ~ 20 GB free space - -echo "Downloading bathymetry data" - -############################################################################################################# -######################## Download main Coastal Relief Moesl (CRM) files ##################################### -############################################################################################################# -# see: https://www.ncei.noaa.gov/products/coastal-relief-model -############################################################################################################# -#Northeast Atlantic -wget --output-document crm_vol1_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol1_2023.nc -#Southeast Atlantic -wget --output-document crm_vol2_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol2_2023.nc -# Florida and East Gulf of America -wget --output-document crm_vol3_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol3_2023.nc -# Central GOA -wget --output-document crm_vol4_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol4_2023.nc -# Western GOA -wget --output-document crm_vol5_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol5_2023.nc -#Central Pacific -wget --output-document crm_vol7_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol7_2023.nc -#Northwest Pacific -wget --output-document crm_vol8_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol8_2023.nc -#Puerto Rico -wget --output-document crm_vol9_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol9_2023.nc -#Hawaii -wget --output-document crm_vol10_2023.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/cudem/crm_vol10_2023.nc -#Other CRM files -# Southern California -wget --output-document crm_vol6.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_vol6.nc -# Southern Alaska -wget --output-document crm_southak.nc https://www.ngdc.noaa.gov/thredds/fileServer/crm/crm_southak.nc -############################################################################################################# - -echo "Done Coastal Relief Model (CRM) Download" - -############################################################################################################# -######################## Download regional files in Pacific ################################################# -############################################################################################################# -# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html -############################################################################################################# -# American Samoa -wget --output-document ngdc_bathy_90m_amsamoa.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_90m_amsamoa?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true -# Mariana islands -wget --output-document ngdc_bathy_180m_mariana.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_180m_mariana?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true -#North Western Hawiian islands -wget --output-document hurl_bathy_60m_nwhi.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/hurl_bathy_60m_nwhi?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true -############################################################################################################# - -echo "Done regional files in Pacific Download" - -############################################################################################################# -######################## Download small scale bathymetry for US Minor outlying islands in Pacific ########### -############################################################################################################# -# see: https://pae-paha.pacioos.hawaii.edu/thredds/bathymetry.html -############################################################################################################# -wget --output-document ngdc_bathy_10m_wake.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/ngdc_bathy_10m_wake?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_jarvis.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_jarvis?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_johnston.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_johnston?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_20m_kingman.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_20m_kingman?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_baker.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_baker?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_howland.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_howland?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_rose.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_rose?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_vailuluu.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_vailuluu?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_40m_swains.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_40m_swains?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document pibhmc_bathy_5m_palmyra.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/pibhmc_bathy_5m_palmyra?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true - -wget --output-document sopac_bathy_50m_majuro_reef.nc https://pae-paha.pacioos.hawaii.edu/thredds/ncss/sopac_bathy_50m_majuro_reef?var=elev&disableLLSubset=on&disableProjSubset=on&horizStride=1&addLatLon=true -############################################################################################################# - -echo "Done small scale bathymetry for US Minor outlying islands in Pacific download" - -############################################################################################################# -######################## Global SDB [~0m to ~30m] depth from copernicus ##################################### -############################################################################################################# -# see: https://data.marine.copernicus.eu/product/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/files?subdataset=cmems_obs-sdb_glo_phy_comp_my_100m-l4-s2_static_202511 -############################################################################################################# -wget --output-document cmems_obs-sdb_glo_phy-comp_my-oa-100m-l4-s2_static.nc https://s3.waw3-1.cloudferro.com/mdl-native-17/native/BATHYMETRY_GLO_PHY_COASTAL_L4_MY_016_001/cmems_obs-sdb_glo_phy_wk_my_100m-l4-s2_static_202511/cmems_obs-sdb_glo_phy-wk_my-oa-100m-l4-s2_static.nc -############################################################################################################# - -echo "Done Global SDB download" - -############################################################################################################# -######################## 60 second Global Bathymetry######################################################### -wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip -############################################################################################################# - -echo "Done Global Bathymetry download" From f929a4a39d3f8655c04681f01fcd7c2f0ac156a1 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 18:54:48 +0000 Subject: [PATCH 29/44] changed final mesh name for defat --- .../MeshGenTemplateDirectory/PostProcessGrid.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 1afb822..208948b 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -24,6 +24,7 @@ pslgfile='GlobalCoastlineGSHHS.PSLG.msh' jigsawout='RWPS.F.LLH' +WW3FileOut='RWPS.GSHHS.WW3.msh' %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% g=loadmsh([outdir,jigsawout,'.msh']); @@ -251,8 +252,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (J) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -WriteWW3MeshX(g0,'RWPS.WW3g.lakes.msh') - +%WriteWW3MeshX(g0,'RWPS.WW3g.lakes.msh') +WriteWW3MeshX(g0,WW3FileOut); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Some Plotting if isplot, From e047186094f1a5e2442ec7b89b386cb658fb9d74 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 4 Feb 2026 19:19:21 +0000 Subject: [PATCH 30/44] fixed error in python env path --- .../InterpolateBathymetry/DivideMeshNodes.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py index 900e1ce..48ceecd 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py +++ b/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py @@ -15,6 +15,16 @@ # This script should be run after the bathymetry data sets specified in # InterpolateCRM.partscat.py are present # +""" +Ursa environment + +module purge +module use /scratch3/NCEPDEV/climate/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles +module load ufs_ursa.intel +module load py-scipy/1.14.1 +module load py-netcdf4/1.7.1.post2 +pip list +""" import os import argparse @@ -53,8 +63,7 @@ def WriteInterpJobscript(fl,N, ComputeNodes): f.write(" \n") f.write("module purge \n") - #f.write("module use /scratch4/NCEPDEV/marine/Ali.Salimi/Hera_Data/HR4-OPT/FromJessica/Keston/ICunstructuredRuns15km-implicit-450s/global-workflow/sorc/ufs_model.fd/modulefiles \n") - f.write("module use /scratch4/NCEPDEV/marine/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles \n") + f.write("module use /scratch3/NCEPDEV/climate/Keston.Smith/global-workflowA/sorc/ufs_model.fd/modulefiles \n") f.write("module load ufs_ursa.intel \n") f.write("module load py-scipy/1.14.1 \n") f.write("module load py-netcdf4/1.7.1.post2 \n") From 00dabf5fcb628443a4d8976997cc285f9179d66b Mon Sep 17 00:00:00 2001 From: keston Date: Thu, 5 Feb 2026 11:01:32 -0500 Subject: [PATCH 31/44] removed some unused files in unst_msh_gen/RWPSMeshtoolkit/matlab/ and added some headers to remaing files --- .../RWPSMeshtoolkit/matlab/BoundingBox.m | 3 + .../RWPSMeshtoolkit/matlab/BoxSmoothTopo.m | 8 +- .../matlab/BuildBoundaryPSLGfunction.m | 8 + .../RWPSMeshtoolkit/matlab/ComputeAdjacency.m | 7 +- .../matlab/ConnectDisjointPSLGs.m | 54 ----- .../matlab/ConnectDisjointPSLGsN.m | 54 ----- .../matlab/DistanceToCoast_v0.m | 39 ---- .../RWPSMeshtoolkit/matlab/FindOuterBndV0.m | 129 ----------- .../RWPSMeshtoolkit/matlab/FindPointsAx.m | 12 +- .../matlab/FixOuterBndSandPoints.m | 44 ---- .../RWPSMeshtoolkit/matlab/InterpCoastline1.m | 38 ---- .../MakeCoastalBoundariesMixedCoastGlobal.m | 206 ------------------ .../RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m | 16 +- .../matlab/MergePslgsOSMxGSSHS.m | 5 +- .../matlab/PlotMeshResSCRIPT.m | 64 ------ .../RWPSMeshtoolkit/matlab/RemoveMeshParts.m | 1 + .../matlab/RemoveMissingIslands.m | 8 +- .../matlab/RemoveMissingIslandsEle.m | 7 +- .../matlab/RemoveMissingIslandsEle2.m | 112 ---------- .../matlab/RemoveMissingIslandsPoint.m | 8 +- .../matlab/WriteWW3MeshNoJig.m | 74 ------- .../RWPSMeshtoolkit/matlab/edges2chainsG.m | 4 + unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m | 3 +- .../RWPSMeshtoolkit/matlab/loadmshWW3.m | 21 +- .../RWPSMeshtoolkit/matlab/patch_global.m | 5 +- .../RWPSMeshtoolkit/matlab/pslg2geom.m | 9 + .../matlab/remove_dead_nodes.m | 16 +- .../matlab/submeshFastPlusEle.m | 17 -- 28 files changed, 106 insertions(+), 866 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast_v0.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FixOuterBndSandPoints.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline1.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MakeCoastalBoundariesMixedCoastGlobal.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/PlotMeshResSCRIPT.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m index d9386b8..f0af7dc 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m @@ -1,4 +1,7 @@ function h=BoundingBox(x,y,c); +%function h=BoundingBox(x,y,c); +% draw bounding rectanble around points x, y in color c + if nargin<3,c='k';end x0=min(min(x)); y0=min(min(y)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m index 3831582..1b27db9 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m @@ -1,5 +1,9 @@ function topo=BoxSmoothTopo(fl,k) - +%function topo=BoxSmoothTopo(fl,k) +% Apply 2D Boxcar smoothing and sub sampling of bathymetry in file fl. +% retuns topo a gridded jigsaw structure. + + lon=ncread(fl,'lon'); lat=ncread(fl,'lat'); z=ncread(fl,'bed_elevation'); @@ -30,4 +34,4 @@ topo.mshID='ELLIPSOID-GRID' topo.fileV=3; -end \ No newline at end of file +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index fe69089..6be5d87 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -1,4 +1,12 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +%function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +% This is a function format of what is probably better written as a script. for examples see: +% +% unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m or: +% unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m +% + + %CoastLineFile = 'GlobalCoastlineOSM.shp' %CoastLineFile = 'GlobalCoastlineGSHHS.shp' %lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m index 87d53a8..96536cc 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m @@ -1,3 +1,8 @@ - function Ac=ComputeAdjacency(e) +% function Ac=ComputeAdjacency(e) +% Compute number of adjacencent elements for each node in mesh with element list e +% +% input: e (ne x 3) element list (ne : number of elements in mesh) +% outout: Ac (nn x 1) number of elements adjacent to each node (nn : number of nodes in mesh) + [Ac,GR] = groupcounts(e(:)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m deleted file mode 100644 index abf979b..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGs.m +++ /dev/null @@ -1,54 +0,0 @@ -function ConnectDisjointPSLGs(flin1,flin2,flout) -%function ConnectDisjointPSLGs(flin1,flin2,flout) -% Join 2 PSLGs together with shortest lines. -% flin1= PSLG saved in jigsaw "geom" format (big pslg) -% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) -% flout= where to save joined PSLG -pg=loadmsh(flin1) -pg.x=pg.point.coord(:,1); -pg.y=pg.point.coord(:,2); -pg.edges=pg.edge2.index(:,1:2); - -ps=loadmsh(flin2); -ps.x=ps.point.coord(:,1)+360; -ps.y=ps.point.coord(:,2); -ps.edges=ps.edge2.index(:,1:2); - -lon2m=111320. -lat2m=110574. -clear D -for k=1:length(ps.x) - D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); -end -[ms,ks]=min(D); -[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); -%find neighbors of ks - -[ils,jls]=find(ps.edges==ks); -ksN=ps.edges(ils,:); -ksNu=unique(ksN); -ksNux=setdiff(ksNu,ks); -[ne,two]=size(ps.edges); -ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node - -[ilg,jlg]=find(pg.edges==kg); -kgN=pg.edges(ilg,:); -kgNu=unique(kgN); -kgNux=setdiff(kgNu,kg); -[ne,two]=size(pg.edges); -pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node - -nn=length(pg.x); -p=joinpslg(pg,ps); -[ne,two]=size(p.edges); -p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; -p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; - -clf -plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') -hold on; -je=ne+1:ne+2; -plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); - -geom=pslg2geom(p) -savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m deleted file mode 100644 index b873af1..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointPSLGsN.m +++ /dev/null @@ -1,54 +0,0 @@ -function ConnectDisjointPSLGs(flin1,flin2,flout,N) -%function ConnectDisjointPSLGs(flin1,flin2,flout) -% Join 2 PSLGs together with shortest lines. -% flin1= PSLG saved in jigsaw "geom" format (big pslg) -% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) -% flout= where to save joined PSLG -pg=loadmsh(flin1) -pg.x=pg.point.coord(:,1); -pg.y=pg.point.coord(:,2); -pg.edges=pg.edge2.index(:,1:2); - -ps=loadmsh(flin2); -ps.x=ps.point.coord(:,1)+360; -ps.y=ps.point.coord(:,2); -ps.edges=ps.edge2.index(:,1:2); - -lon2m=111320. -lat2m=110574. -clear D -for k=1:length(ps.x) - D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); -end -[ms,ks]=min(D); -[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); -%find neighbors of ks - -[ils,jls]=find(ps.edges==ks); -ksN=ps.edges(ils,:); -ksNu=unique(ksN); -ksNux=setdiff(ksNu,ks); -[ne,two]=size(ps.edges); -ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node - -[ilg,jlg]=find(pg.edges==kg); -kgN=pg.edges(ilg,:); -kgNu=unique(kgN); -kgNux=setdiff(kgNu,kg); -[ne,two]=size(pg.edges); -pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node - -nn=length(pg.x); -p=joinpslg(pg,ps); -[ne,two]=size(p.edges); -p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; -p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; - -clf -plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') -hold on; -je=ne+1:ne+2; -plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); - -geom=pslg2geom(p) -savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast_v0.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast_v0.m deleted file mode 100644 index f027f00..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast_v0.m +++ /dev/null @@ -1,39 +0,0 @@ -function D=DistanceToCoast_v0(lon,lat,lonP,latP) -%function D=DistanceToCoast(lon,lat,lonP,latP) -% Computes grided distance to pointset on Globe -% -% Computes shortest distance to pointset [lonP,latP] from coordinates of -% lat by lon grid in m. -% -% inputs: -% lon - [nx,1] lon coordinates for output matrix -% lat - [ny,1] lon coordinates for output matrix -% lonP - [nn,1] longitude coordiantes of point set -% latP - [nn,1] latitude coordiantes of point set -% -% outputs: -% D - [ny, nx] units meters -% D(j,k)= minimumt Distance from point lat(j), lon(k) to pointset (lonP,latP) -% -clear d0 -lat2m=single(110574.) -lon=single(lon); -lat=single(lat); -nx=length(lon) -ny=length(lat) -clear ld1 ld2 D; -t0=now; -latP=latP(:); -lonP=lonP(:); -for j=1:ny % this loop takes ~16 hours - j/ny - lon2m=single(111320.*cos(lat(j)*pi/180)); - DLON= mod(lon(:)'-lonP(:),360) ;% large matrix - ld1=min ( abs( [ DLON ]*lon2m + i*[ones(1,nx)*lat(j) - latP(:)]*lat2m ) ); - ld2=min ( abs( [360 - DLON ]*lon2m + i*[ones(1,nx)*lat(j) - latP(:)]*lat2m ) ); 360-ld1; - D(j,:)=min( [ ld1(:),ld2(:) ]' ); % take shortes distance of east or west distance - t1=now; - est=(ny-j)*[(t1-t0)/j]; - disp(['etimated time remaing: ' ,num2str(est*24),' hrs']); -end - diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m deleted file mode 100644 index c3c694f..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndV0.m +++ /dev/null @@ -1,129 +0,0 @@ -function OpenBndNodes=FindOuterBnd(g) - - - -e=g.tria3.index(:,1:3); -x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); - -bnd=detbndy(e); -c=edges2chains(bnd); -for k=1:length(c) - k - xc(k)=mean(x(c(k).nodes)); - yc(k)=mean(y(c(k).nodes)); - A(k)=areaint(x(c(k).nodes),y(c(k).nodes)); -end - -[m,k]=max(A); -jin=setdiff(1:length(A),k) -obj=k; -if A(obj)>sum(A(jin)), - disp(['outer boundary is: ',int2str(obj)]) - plot(x(c(obj).nodes),y(c(obj).nodes),'r.-'); -end -hold on -for k=1:length(jin) - j=jin(k); - plot(x(c(j).nodes),y(c(j).nodes),'k-') -end - -figure;ph=patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar -hold on;plot(x(c(obj).nodes),y(c(obj).nodes),'k.-'); -n=c(obj).nodes; - -g=loadmsh('output/RWPS.F.LLH.msh') -p=loadmsh('PSLGboundary5km_shifted.msh'); -x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); -xp=p.point.coord(:,1);yp=p.point.coord(:,2);fp=p.point.coord(:,3); - -%remove corners from boundary where they exist -eps=5000;% -figure;plot(xp,yp,'k.',max(xp),min(yp),'ro',min(xp),min(yp),'ro',max(xp),max(yp),'ro',min(xp),max(yp),'ro'); -wgs84 = wgs84Ellipsoid("m"); -DSW=distance( [min(yp),min(xp)],[yp,xp],wgs84); -DSE=distance( [min(yp),max(xp)],[yp,xp],wgs84); -DNW=distance( [max(yp),min(xp)],[yp,xp],wgs84); -DNE=distance( [max(yp),max(xp)],[yp,xp],wgs84); - -jSW=find(DSWepsD); % points 3 km or more from coastline point -noo=n(joo); -figure;plot(xp-360,yp,'y.',x(n),y(n),'k.-',x(noo),y(noo),'r.') - -xmax=max(xpp)-dx -xmin=min(xpp)+dx -ymax=max(yp)-dx -ymin=min(yp)+dx - -jX=find(and( x>xmin,xymin,y>ax=axis % get current figure axis +% >>j=FindPointsAx(ax,g.x,g.y); +% >>g_local=submeshFast(g,j) +% +% to return mesh structure contained within current figure axis + jx=find(and(x>ax(1),xax(3),ydmin); -z=z(j); -d=d(j); -if length(d)ax(1))); - jy=find(and( ytax(3))); - j=intersect(jx,jy); - j=union(j,jnan); - - hold on - plot(xt(j),yt(j),'k-'); - title([nms{k},' edge length (km)']); - caxis([0,cx(k)]); - colormap(jet(20)); - daspect([1,cos(flat(k)*pi/180),1]) - kprint([nms{k},'EdgeLengthGlobal.jpg']); -end - diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m index 5902e9f..9724182 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m @@ -1,4 +1,5 @@ function gnew=RemoveMeshParts(g,ax,S,ca); + %function gnew=HandEditMesh(g,ax,p); % Remove parts of mesh, g inside closed curves defined in pslg % p. The action is preformed only within the axis ax. The diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m index 6ce6bb9..6d89936 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m @@ -1,9 +1,9 @@ function gnew=RemoveMissingIslands(g,ax,p,MinBndDist,isplot); -%function gnew=HandEditMesh(g,ax,p); -% Remove parts of mesh, g inside closed curves defined in pslg -% p. The action is preformed only within the axis ax. The -% frame work is intended to expand to moving nodes, removing elements, etc +%function gnew=RemoveMissingIslands(g,ax,p,MinBndDist,isplot); +% Remove nodes of mesh, g inside closed curves defined in pslg +% p. The action is preformed only within the axis ax. %This wont touch nodes within MinBndDist (m) of existing boundary + if nargin<4 MinBndDist=1000; end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m index 0b85002..68f0d79 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m @@ -1,9 +1,10 @@ function gnew=RemoveMissingIslandsEle(g,ax,p,MinBndDist,isplot); % Remove parts of mesh, g inside closed curves defined in pslg -% p. The action is preformed only within the axis ax. The -% frame work is intended to expand to moving nodes, removing elements, etc -%This wont touch nodes within MinBndDist (m) of existing boundary +% p. Only nodes for which all adjoining elements are inside closed curve are removed. +% The action is preformed only within the axis ax. +% This wont touch nodes within MinBndDist (m) of existing boundary + if nargin<4 MinBndDist=1000; end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m deleted file mode 100644 index 6067f0b..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle2.m +++ /dev/null @@ -1,112 +0,0 @@ -function gnew=RemoveMissingIslandsEle2(g,ax,p,MinBndDist,isplot); -%function gnew=HandEditMesh(g,ax,p); -% Remove parts of mesh, g inside closed curves defined in pslg -% p. The action is preformed only within the axis ax. The -% frame work is intended to expand to moving nodes, removing elements, etc -%This wont touch nodes within MinBndDist (m) of existing boundary -if nargin<4 - MinBndDist=1000; -end -if nargin <5, - isplot=0; -end - -xc=mean(g.x(g.e')); -yc=mean(g.y(g.e')); - -jx=find(and(xc>ax(1),xcax(3),ycax(1),p.xax(3),p.y2, - if n(1)==n(end), - jins=find(inside(xc(jg),yc(jg),p0.x(n),p0.y(n))); - nin=g.e(jg(jins),:); - X=g.x(nin); - Y=g.y(nin); - jnins=find( sum(inside(X,Y,p0.x(n),p0.y(n) )')==3); - jb0=[jb0;jnins(:)]; - end - end -end - - - - - -g0=submeshFast(g,jg); -bnd=detbndy(g0.e); -jbnd=unique(bnd(:)); - -xb=g0.x(jbnd); -yb=g0.y(jbnd); - -jx=find(and(p.x>ax(1),p.xax(3),p.y2, - if n(1)==n(end), - jins=find(inside(x,y,p0.x(n),p0.y(n))); - jb0=[jb0;jins(:)]; - end - end -end - -lat2m=110574.; -lon2m=111320.; - -jb0X=[]; -for k=1:length(jb0); - n=jb0(k); - - d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... - i*lat2m*( y(n)-yb ) )); - if d>MinBndDist,jb0X=[jb0X,n];end -end -jb0=jb0X; - -if isplot, - hold on - plot(x(jb0),y(jb0),'ro'); -end - -[g1,kr0]=submeshFastEle(g0,jb0); - -if isplot, - figure; - x=g1.x;y=g1.y;z=g1.z;e=g1.e; - clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; - hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); - set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); -end -%jb=jg(jb0); -jb=jg(kr0); -nn=length(g.x); -gnew=submeshFast(g,setdiff(1:nn,jb)); %only removes nodes - - diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m index a887737..e94e68e 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m @@ -1,9 +1,7 @@ function gnew=RemoveMissingIslandsPoint(g,ax,p,MinBndDist); -%function gnew=HandEditMesh(g,ax,p); -% Remove parts of mesh, g inside closed curves defined in pslg -% p. The action is preformed only within the axis ax. The -% frame work is intended to expand to moving nodes, removing elements, etc -%This wont touch nodes within MinBndDist (m) of existing boundary +% function gnew=RemoveMissingIslandsPoint(g,ax,p,MinBndDist); +% Not in current use. This will be removed upon further review + if nargin<4 MinBndDist=1000; end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m deleted file mode 100644 index 2b61004..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshNoJig.m +++ /dev/null @@ -1,74 +0,0 @@ - -function WriteWW3MeshNoJig(g,WW3FileOut) - -%OpenBndNodes=FindOuterBnd(mshFileInJigsawFormat,pslgFilelInJigsawFormat); - -%g=loadmsh(mshFileInJigsawFormat) - -%x=g.point.coord(:,1);y=g.point.coord(:,2);z=g.point.coord(:,3); -%e=g.tria3.index(:,1:3); - -x=g.x;y=g.y;z=g.z;e=g.e; -OpenBndNodes=g.bnd; - -nn=length(x) -[ne,three]=size(e) -nb=length(OpenBndNodes); - -fp=fopen(WW3FileOut,'w'); -fprintf(fp,'$MeshFormat\n') -fprintf(fp,'2 0 8\n') -fprintf(fp,'$EndMeshFormat\n') -fprintf(fp,'$Nodes\n') -fprintf(fp,'%i\n',nn) - -A=[[1:nn]' x(:),y(:),z(:)]; - -fprintf(fp,'%i %f %f %f\n',A') - -fprintf(fp,'$EndNodes\n') -fprintf(fp,'$Elements\n') -fprintf(fp,'%i\n',ne+nb) - -B=[[1:nb]', 15*ones(nb,1) ,2*ones(nb,1),zeros(nb,1),zeros(nb,1),OpenBndNodes(:)]; - -fprintf(fp,'%i %i %i %i %i %i\n',B') - -C=[ nb+[1:ne]',2*ones(ne,1) ,3*ones(ne,1),zeros(ne,1),[1:ne]',zeros(ne,1),e]; -fprintf(fp,'%i %i %i %i %i %i %i %i %i\n',C') -fprintf(fp,'$EndElements\n') -fclose(fp); - - - -%76 2 3 0 1 0 77 76 1 -%$MeshFormat -%2 0 8 -%$EndMeshFormat -%$Nodes -%3070 -%1 -72.0576782709 40.9902316949 4.2878041267 -%2 -72.0521937363 40.9713426805 13.8250312805 -%3 -72.0469687227 40.9523807323 20.9117679596 - -%3068 -72.585996 40.813074 1.747097373 -%3069 -72.586352 40.818835 1.5 -%3070 -72.589697 40.813418 1.5 -%$EndNodes -%$Elements -%5855 -%1 15 2 0 0 75 -%2 15 2 0 0 74 -%3 15 2 0 0 73 - -%73 15 2 0 0 3 -%74 15 2 0 0 2 -%75 15 2 0 0 1 -%76 2 3 0 1 0 77 76 1 -%77 2 3 0 2 0 76 2 1 -%78 2 3 0 3 0 78 2 76 - -%5854 2 3 0 5779 0 3065 3069 3067 -%5855 2 3 0 5780 0 3068 3067 3070 -%$EndElements - diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m index 992c4f9..f2720c4 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m @@ -1,4 +1,8 @@ function chains=edges2chainsG(edges); +%function chains=edges2chainsG(edges); +% This performs similair function to edges2chains, how ever it uses matlabs graph theory library +% and only returns closed cycles rather than cycles and open ended chains. +% G=graph(edges(:,1),edges(:,2)); cycles = allcycles(G); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m index 083d8a3..c1105c0 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m @@ -1,5 +1,6 @@ function kprint(fl); -%eval(['print -djpeg ',fl]); +% function kprint(fl); +% prints and trims (using convert) current figure h=gcf; saveas(h, fl); system(['convert -trim ',fl,' ',fl]); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m index 79f7612..571305f 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m @@ -1,4 +1,23 @@ -function g=read_msh(fl) +function g=loadmshWW3(fl) +% function g=loadmshWW3(fl) +% +% load WW3 .msh format mesh see: +% https://polar.ncep.noaa.gov/waves/wavewatch/manual.v5.16.pdf +% +% mesh structure g has fields: +% +% x: longitute +% y: latitude +% z: bathymetric depth +% e: (ne x 3) element list +% etype: element type +% ntags: +% PhsEnty: +% EleNum: +% ElemUnk: +% bnd: open ocean boundary nodes +% BndType: +% BndGeom: %$MeshFormat %2 0 8 diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m index 3c822d6..0302f6e 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m @@ -1,7 +1,10 @@ function ph=patch_global(lon,lat,f,e) +%function ph=patch_global(lon,lat,f,e) +% make a patch graphic object showing field f structure for mesh fith coordinates lon,lat and element matrix e. +% elements crossing dateline are eliminated in the plot dx=max(lon(e))-min(lon(e)); j=find(dx<270); ep=e(:,j); - ph=patch(lon(ep),lat(ep),f(ep)); \ No newline at end of file + ph=patch(lon(ep),lat(ep),f(ep)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m index a982609..b541487 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m @@ -1,4 +1,13 @@ function geom=pslg2geom(pslg) +%function geom=pslg2geom(pslg) +% convert Planar Straight Line Graph (pslg) structure with fields +% +% pslg.x : (nn x 1) x coordinates of nodes +% pslg.y : (nn x 1 )y coordinates of nodes +% pslg.edges : (nedges x 2) list of edges between nodes +% +% to jigsaw geometry structure containing the same information +% geom.MSHID=3 geom.mshID= 'EUCLIDEAN-MESH' diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m index 0866b31..1b1dcb7 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m @@ -1,5 +1,14 @@ function [h,ki]=remove_dead_nodes(g) - +%function [h,ki]=remove_dead_nodes(g) +% +% remove nodes from mesh structure g that are not present in any elements +% the new mesh structure is returned as h +% +% g.x : longitute +% g.y : latitude +% g.z : bathymetric depth +% g.e : (ne x 3) element list +% ju=sort(unique(g.e(:))); k=1:length(g.x); @@ -10,11 +19,6 @@ h.e=g.e; -%for k=ki -% j=find(g.e > k ); -% h.e(j)=h.e(j)-1; -%end - for k=1:length(ki) j=find(g.e > ki(k) ); h.e(j)=h.e(j)-1; diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m deleted file mode 100644 index 8c21dfa..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastPlusEle.m +++ /dev/null @@ -1,17 +0,0 @@ -function h=submeshFast(g,jGoodNodes,jGoodEles) - -jGoodNodes=jGoodNodes(:)';%row format - -nn=length(g.x) -[ne,three]=size(g.e) - -jGoodNodes=sort(jGoodNodes); -h.x=g.x(jGoodNodes); -h.y=g.y(jGoodNodes); -h.z=g.z(jGoodNodes); - -A=ismember(g.e,jGoodNodes); -k=find(sum(A')==3)'; -e=g.e(k,:); -[kk,M]=ismember(1:nn,jGoodNodes); -h.e=M(e); From d213d1abb7f17ca19495aa098bd9536e1aab004e Mon Sep 17 00:00:00 2001 From: keston Date: Thu, 5 Feb 2026 14:02:11 -0500 Subject: [PATCH 32/44] further headers for funcions in unst_msh_gen/RWPSMeshtoolkit/matlab --- .../matlab/ComputeLengthScaleX.m | 31 ------------------- .../RWPSMeshtoolkit/matlab/Ele2Nodes.m | 12 ++++++- unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m | 14 +++++++-- 3 files changed, 23 insertions(+), 34 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m deleted file mode 100644 index 1a60a73..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScaleX.m +++ /dev/null @@ -1,31 +0,0 @@ -function a=ComputeLengthScaleX(x,y,e) -%function ComputeLengthScale(x,y,e) -% Input: -% x -lon [nn x 1] -% y -lat [nn x 1] -% e -element list[ ne x 3] -% -% Output: -% lengthscale [ne x 1] lengthscale of element in m based on -EqTrC=4/sqrt(3); -[ne,three]=size(e) -lengthscale=zeros(1,ne); -%parfor k=1:ne -wgs84 = wgs84Ellipsoid("km"); -n=length(x); -xp=x; -yp=y; -xp(n+1)=NaN; -yp(n+1)=NaN; -[ne,three]=size(e) -eP=[e(:,1:3),n+1+zeros(ne,1)]; -Xp=xp(eP)'; -Yp=yp(eP)'; -t0=now -clear a -a = areaint(Yp(:),Xp(:),wgs84); -t1=now; -60*24*(t1-t0) -et=60*24*(t1-t0); -disp([' total time : ',num2str(et),' min']); -lengthscale=sqrt(a*EqTrC); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m index 57a6495..d01243d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m @@ -1,5 +1,15 @@ function Fnode = Ele2Nodes(lon,lat,e,Fele) -%crude compute element Area +%function Fnode = Ele2Nodes(lon,lat,e,Fele) +% Approximate element averages for field supported on elements +% at nodes. Uses average weighted by elment areas +% inputs: +% lon : (nn x 1) longitude coordinates of nodes +% lat : (nn x 1) latitude coordinates of nodes +% e : (ne x 3) element matrix +% Fele : (ne x 1) field average on elements +% output: +% Fnode : (nn x 1) approximation of Fele at nodes +% A=EleArea(lon,lat,e); nn=length(lon); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m index eeea3b7..3a64ecd 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m @@ -1,9 +1,19 @@ function A = EleArea(lon,lat,e) -%crude compute element Area +%function A = EleArea(lon,lat,e) +%Approximate element Area +% +% inputs: +% lon : (nn x 1) longitude coordinates of mesh nodes +% lat : (nn x 1) latitude coordinates of mesh nodes +% e : (ne x 3) element matrix +% +% output: +% A : (ne x 1) aproximate area of each element in m^2 +% X=lon(e); Y=lat(e); mY=mean(Y')'; -lat2m=111111.; +lat2m=110574.; lon2m=lat2m.*cos(pi*mY/180.); D3=abs( lon2m.*(X(:,2)-X(:,1)) + lat2m*i*( Y(:,2)-Y(:,1) )); D2=abs( lon2m.*(X(:,3)-X(:,1)) + lat2m*i*( Y(:,3)-Y(:,1) )); From 5bd30cd3e099bc556ca9fc88e162fb1d7c1f4aa2 Mon Sep 17 00:00:00 2001 From: keston Date: Thu, 5 Feb 2026 14:15:52 -0500 Subject: [PATCH 33/44] filled in further headers in matlab functions --- .../RWPSMeshtoolkit/matlab/FindOuterBnd.m | 133 ------------------ .../RWPSMeshtoolkit/matlab/WriteWW3Mesh.m | 14 +- .../RWPSMeshtoolkit/matlab/WriteWW3MeshX.m | 11 +- 3 files changed, 21 insertions(+), 137 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBnd.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBnd.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBnd.m deleted file mode 100644 index e129ec3..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBnd.m +++ /dev/null @@ -1,133 +0,0 @@ -function OpenBndNodes=FindOuterBnd(meshflin,pslgflin) - - -g=loadmsh(meshflin) -p=loadmsh(pslgflin) - - -e=g.tria3.index(:,1:3); -x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); - -bnd=detbndy(e);%find boundary elements(line segments) -c=edges2chains(bnd);%find closed chains in boundary elements(these are islands or ) -for k=1:length(c)%compute area of each closed chain - k - xc(k)=mean(x(c(k).nodes)); - yc(k)=mean(y(c(k).nodes)); - A(k)=areaint(x(c(k).nodes),y(c(k).nodes)); -end - -[m,k]=max(A); -jin=setdiff(1:length(A),k) -obj=k; -if A(obj)>sum(A(jin)), - disp(['outer boundary is: ',int2str(obj)]) - plot(x(c(obj).nodes),y(c(obj).nodes),'r.-'); -end -hold on -for k=1:length(jin) - j=jin(k); - plot(x(c(j).nodes),y(c(j).nodes),'k-') -end - -figure;ph=patch(x(e'),y(e'),f(e'));shading interp;colormap('jet');colorbar -hold on;plot(x(c(obj).nodes),y(c(obj).nodes),'k.-'); -n=c(obj).nodes; - -%g=loadmsh('output/RWPS.F.LLH.msh') -%p=loadmsh('PSLGboundary5km_shifted.msh'); -x=g.point.coord(:,1);y=g.point.coord(:,2);f=g.point.coord(:,3); -xp=p.point.coord(:,1);yp=p.point.coord(:,2);fp=p.point.coord(:,3); - -%remove corners from boundary where they exist -eps=5000;% -eps=500;% -figure;plot(xp,yp,'k.',max(xp),min(yp),'ro',min(xp),min(yp),'ro',max(xp),max(yp),'ro',min(xp),max(yp),'ro'); -wgs84 = wgs84Ellipsoid("m"); -DSW=distance( [min(yp),min(xp)],[yp,xp],wgs84); -DSE=distance( [min(yp),max(xp)],[yp,xp],wgs84); -DNW=distance( [max(yp),min(xp)],[yp,xp],wgs84); -DNE=distance( [max(yp),max(xp)],[yp,xp],wgs84); - -jSW=find(DSWepsD); % points 3 km or more from coastline point -noo=n(joo); -figure;plot(xp-360,yp,'y.',x(n),y(n),'k.-',x(noo),y(noo),'r.') - -xmax=max(xpp)-dx -xmin=min(xpp)+dx -ymax=max(yp)-dx -ymin=min(yp)+dx - -jX=find(and( x>xmin,xymin,y Date: Thu, 5 Feb 2026 16:49:26 -0500 Subject: [PATCH 34/44] filled in more headers for matlab functions --- .../matlab/BoundaryShape2msh.m | 30 ++-- .../RWPSMeshtoolkit/matlab/BoundingBox.m | 3 +- .../RWPSMeshtoolkit/matlab/BoxSmoothTopo.m | 18 ++- .../RWPSMeshtoolkit/matlab/CombineMesh.m | 2 + .../matlab/ConnectDisjointMesh.m | 139 ------------------ unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m | 2 +- .../matlab/FindOuterBndNoPSLG.m | 17 ++- .../RWPSMeshtoolkit/matlab/FindOuterBndWW3.m | 16 +- .../RWPSMeshtoolkit/matlab/HandEditMesh.m | 7 +- .../RWPSMeshtoolkit/matlab/InterpCoastline.m | 13 +- .../matlab/SmoothSubSampleCoastlineFast.m | 16 +- .../RWPSMeshtoolkit/matlab/edges2chainsG.m | 3 +- .../RWPSMeshtoolkit/matlab/joinpslg.m | 10 +- 13 files changed, 95 insertions(+), 181 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m index 11ab45a..d82f132 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m @@ -1,25 +1,13 @@ function geom=BoundaryShape2msh(S,flout) -% make coastlines for various smoothings of coastlines +% function geom=BoundaryShape2msh(S,flout) +% make coastline read from a shape file into a jigsaw format mesh file. +% inputs: +% S: shapefile structure, i.e. S=shaperead('us_coastline.shp'); +% flout: file to write jigsaw format .msh file representing S +% outputs: +% geom : jigsaw structure representing S +% -%from example 6 aust.msh - -%geom = -% point: [1×1 struct] -% edge2: [1×1 struct] -% mshID: 'EUCLIDEAN-MESH' -% fileV: 3 - -%geom.point.coord(1:10,:) -% 146.2929 -39.0150 0 -% 146.2937 -39.0192 0 -% 146.2846 -39.0242 0 - -%geom.edge2.index(1:10,:) -% 1 2 0 -% 1 27577 0 -% 2 3 0 - -%1km clear geom geom.mshID='EUCLIDEAN-MESH' geom.fileV = 3 @@ -66,4 +54,4 @@ geom.point.coord=[x0(:),y0(:),zeros(nn,1)]; savemsh(flout,geom); - \ No newline at end of file + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m index f0af7dc..63c301a 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m @@ -1,6 +1,7 @@ function h=BoundingBox(x,y,c); %function h=BoundingBox(x,y,c); -% draw bounding rectanble around points x, y in color c +% draw a bounding rectanble around points x, y in color c. +% Note, x and y can be different lengths here. if nargin<3,c='k';end x0=min(min(x)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m index 1b27db9..33001fc 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m @@ -1,7 +1,21 @@ function topo=BoxSmoothTopo(fl,k) %function topo=BoxSmoothTopo(fl,k) -% Apply 2D Boxcar smoothing and sub sampling of bathymetry in file fl. -% retuns topo a gridded jigsaw structure. +% Apply 2D boxcar smoothing and sub sampling of bathymetry in file fl. +% jigsaw can sometimes run into memory problems with large stuctures +% of this type when generating non-global meshes. Retuns topo, a +% gridded jigsaw structure. +% inputs: +% fl : filename pointing to a netcdf bathymetry file with variables +% lon : length (nx+1) longitude of grid +% lat : length (ny+1) latitude of grid +% bed_elevation : ( nx by ny) average bathymetric depth in cell +% k : integer to resample the bathymetry at.The smoothing is carried +% out using a 2 D Boxcar smoother (square average) with sides of +% length (2 k + 1) and resampled every k points +% output: +% topo : jigsaw format girdded data representing the smoothed resampled +% data. +% lon=ncread(fl,'lon'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m index 3c67bf1..0caf722 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m @@ -1,4 +1,6 @@ function g=CombineMesh(g0,g1); +% function g=CombineMesh(g0,g1); +% Combine 2 non intersecting mesh structures g0 and g1 to get their union g. nn=length(g0.x); g.x=[g0.x(:);g1.x(:)]; diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m deleted file mode 100644 index 8c4f861..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/ConnectDisjointMesh.m +++ /dev/null @@ -1,139 +0,0 @@ -function gx=ConnectDisjointMesh(g,g0,flout,N) -%function ConnectDisjointPSLGs(flin1,flin2,flout) -% Join 2 PSLGs together with shortest lines. -% flin1= PSLG saved in jigsaw "geom" format (big pslg) -% flin2= PSLG saved in jigsaw "geom" format (little(pslg)) -% flout= where to save joined PSLG -Smin=500; - -g=loadmsh('RWPSMeshFilesPIXNO/RWPS.F.LLH.msh') -g.x=g.point.coord(:,1);g.y=g.point.coord(:,2);g.z=g.point.coord(:,3);g.e=g.tria3.index(:,1:3); -g0=loadmsh('../RWPSLakes/RWPS.Sebago.msh') -g0.x=g0.point.coord(:,1);g0.y=g0.point.coord(:,2);g0.z=g0.point.coord(:,3);g0.e=g0.tria3.index(:,1:3); - - -bnd=detbndy(g.e); -bndu=unique(bnd); - -xb=g.x(bndu); -yb=g.y(bndu); - -bnd0=detbndy(g0.e); -bndu0=unique(bnd0); -xb0=g0.x(bndu0); -yb0=g0.y(bndu0); - - -lon2m=111320. -lat2m=110574. -clear D J -for k=1:length(bndu0) - [D(k),J(k)]=min(abs( lon2m*cos(pi*yb0(k)/180).*(xb0(k)-xb) + i*lat2m*[yb0(k)-yb] ) ); -end -[D0,k0]=min(D);%closest node lake -k=J(k0);%closest node global - -Nseg=round(D0/Smin) -n0=bndu0(k0) -n=bndu(k) - -j0=find(bnd0(:,1)==n0); -m0=bnd0(j0,2); -j=find(bnd(:,1)==n); -m=bnd(j,2); - -xng=g.x(n); -yng=g.y(n); -xng=g.x(n); -yng=g.y(n); -xp=g.x(n)+(g0.x(n0)-g.x(n))*(1:Nseg-1)/(Nseg); -yp=g.y(n)+(g0.y(n0)-g.y(n))*(1:Nseg-1)/(Nseg); - -xq=g.x(m)+(g0.x(m0)-g.x(m))*(1:Nseg-1)/(Nseg); -yq=g.y(m)+(g0.y(m0)-g.y(m))*(1:Nseg-1)/(Nseg); -clf;plot(xb,yb,'k.',xb0,yb0,'b.',xp,yp,'r.',xq,yq,'c.') - -g1.x=[g.x(:);g0.x(:)]; -g1.y=[g.y(:);g0.y(:)]; -g1.e=[g.e;length(g.x)+g0.e]; - -Nj=length(g1.x); -[NE,three]=size(g1.e); -g1.x=[g1.x(:);xp]; -g1.y=[g1.y(:);yp]; -Np=length(g1.x); -g1.x=[g1.x(:);xq]; -g1.y=[g1.y(:);yq]; -Nq=length(g1.x); - - - - - -[ils,jls]=find(ps.edges==ks); -ksN=ps.edges(ils,:); -ksNu=unique(ksN); -ksNux=setdiff(ksNu,ks); -[ne,two]=size(ps.edges); -ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node - -[ilg,jlg]=find(pg.edges==kg); -kgN=pg.edges(ilg,:); -kgNu=unique(kgN); -kgNux=setdiff(kgNu,kg); -[ne,two]=size(pg.edges); -pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node - - -for k=1:length(bndu0) - D(k)=min(abs) - - -pg=loadmsh(flin1) -pg.x=pg.point.coord(:,1); -pg.y=pg.point.coord(:,2); -pg.edges=pg.edge2.index(:,1:2); - -ps=loadmsh(flin2); -ps.x=ps.point.coord(:,1)+360; -ps.y=ps.point.coord(:,2); -ps.edges=ps.edge2.index(:,1:2); - -lon2m=111320. -lat2m=110574. -clear D -for k=1:length(ps.x) - D(k)=min(abs( lon2m*cos(pi*ps.y(k)/180).*(ps.x(k)-pg.x) + i*lat2m*[ps.y(k)-pg.y] ) ); -end -[ms,ks]=min(D); -[mg,kg]=min(abs( lon2m*cos(pi*ps.y(ks)/180).*(ps.x(ks)-pg.x) + i*lat2m*[ps.y(ks)-pg.y] ) ); -%find neighbors of ks - -[ils,jls]=find(ps.edges==ks); -ksN=ps.edges(ils,:); -ksNu=unique(ksN); -ksNux=setdiff(ksNu,ks); -[ne,two]=size(ps.edges); -ps.edges=ps.edges(setdiff(1:ne,ils),:);%remove edges to close node - -[ilg,jlg]=find(pg.edges==kg); -kgN=pg.edges(ilg,:); -kgNu=unique(kgN); -kgNux=setdiff(kgNu,kg); -[ne,two]=size(pg.edges); -pg.edges=pg.edges(setdiff(1:ne,ilg),:);%remove edges to close node - -nn=length(pg.x); -p=joinpslg(pg,ps); -[ne,two]=size(p.edges); -p.edges(ne+1,:)=[nn+ksNux(1),kgNux(1)]; -p.edges(ne+2,:)=[nn+ksNux(2),kgNux(2)]; - -clf -plot(pg.x,pg.y,'k.',ps.x,ps.y,'b.') -hold on; -je=ne+1:ne+2; -plot(p.x(p.edges(je,:)'), p.y(p.edges(je,:)'),'go-'); - -geom=pslg2geom(p) -savemsh(flout,geom) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m index 3a64ecd..1e9930c 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m @@ -14,7 +14,7 @@ Y=lat(e); mY=mean(Y')'; lat2m=110574.; -lon2m=lat2m.*cos(pi*mY/180.); +lon2m=111320.*cos(pi*mY/180.); D3=abs( lon2m.*(X(:,2)-X(:,1)) + lat2m*i*( Y(:,2)-Y(:,1) )); D2=abs( lon2m.*(X(:,3)-X(:,1)) + lat2m*i*( Y(:,3)-Y(:,1) )); D1=abs( lon2m.*(X(:,3)-X(:,2)) + lat2m*i*( Y(:,3)-Y(:,2) )); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m index 799bf20..3dcbbe6 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m @@ -1,4 +1,18 @@ function OpenBndNodes=FindOuterBndNoPSLG(meshflin,ComputeBndy) +% function OpenBndNodes=FindOuterBndNoPSLG(meshflin,ComputeBndy) +% find the open boundary nodes from jigsaw format .msh file +% representing an unstructured mesh, and find the estimated +% open ocean boundary nodes assuming the mesh is on an oriented +% rectangle. +% +% inputs: +% meshflin : jigsaw format .msh file representing an unstructured mesh +% ComputeBndy : ComputeBndy =1 in all cases +% output: +% OpenBndNodes : list of open ocean boundary nodes numbers +% + +Dmin=1000; %critical distance in meters to find boundary nodes g=loadmsh(meshflin) @@ -18,7 +32,6 @@ DIE=abs(DIE); D=min(DIE'); -Dmin=1000; jc=find(Dax(1),g.x Date: Fri, 6 Feb 2026 09:39:42 -0500 Subject: [PATCH 35/44] finished adding headers to files in unst_msh_gen/RWPSMeshtoolkit/matlab/ --- .../RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m | 310 ------------------ .../RWPSMeshtoolkit/matlab/RemoveMeshParts.m | 17 +- .../matlab/RemoveMissingIslands.m | 16 +- .../matlab/RemoveMissingIslandsEle.m | 24 +- .../RWPSMeshtoolkit/matlab/RemoveSandPoints.m | 16 + .../matlab/RemoveSandPointsWW3.m | 22 +- .../RWPSMeshtoolkit/matlab/SubsetMesh.m | 22 -- unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m | 3 +- unst_msh_gen/RWPSMeshtoolkit/matlab/l.m | 4 +- .../RWPSMeshtoolkit/matlab/loadmshWW3.m | 10 - .../RWPSMeshtoolkit/matlab/patch_global.m | 2 +- .../matlab/remove_dead_nodes.m | 16 +- .../RWPSMeshtoolkit/matlab/submeshFast.m | 15 + .../RWPSMeshtoolkit/matlab/submeshFastEle.m | 16 + .../RWPSMeshtoolkit/matlab/subpslgFast.m | 10 + .../RWPSMeshtoolkit/matlab/topo2msh.m | 13 +- 16 files changed, 154 insertions(+), 362 deletions(-) delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m delete mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m deleted file mode 100644 index 3d2abcf..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDfun_mshfile.m +++ /dev/null @@ -1,310 +0,0 @@ -%This script creates a "Distance to Coast file" using a us coastline file -%and custom specification of other points. - -clear -close all -isplot=0 - -%Input files -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Jigsaw .msh format file with PSLG geometry: -PSLGfile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/JigsawFormatFiles/PSLGboundaryOSMxGSHHS.BOXES.msh' % mesh boundary PSLG file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Global Bathymetry file (netcdf) -GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' % global topography file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Shapefile with US coastline -uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' % us coastline file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%Output files -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Output "distance to coast" grided jigsaw .msh file -DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] -%Output bathymetry on same grid as DFunOutFile -TopoFile=['Topo.',DFunOutFile]; -%Temporary matlab file -FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] - - -US=shaperead(uscl); -NUS=length(US) -xus=[]; -yus=[]; -x0=[] -y0=[]; -interpDist=100. %meters -SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist -% then subsample soothed coastline every SmoothN points to create smaller -% coastline data set. i.e. remove small scale variation -for k=1:NUS - x=US(k).X(1:end-1); - y=US(k).Y(1:end-1); - x0=[x0,x]; - y0=[y0,y]; -% xs=x;ys=y; %1.5 mil points - if length(x)>3 - [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); - xus=[xus,xs]; - yus=[yus,ys]; - end -end -n0=length(xus); -%Now add Pacific Territories and COFA points -%------------------------------------------------------------------------ -%NWS Pacific Region, via the Compact of Free Association, -% %oversees operations of 5 Weather Service Offices (WSO) across -% Micronesia in the Republic of Palau, Federated States of Micronesia -% and the Republic of the Marshall Islands. WFO Guam provides routine -% forecasts as well as WWA services for these areas. -Eric Lau -%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island - -%Wake Island -coord=[19.2796,166.6499];%E -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Palau -coord=[7.4942, 134.5690] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Yap:9.5557° N, 138.1399° E -coord=[9.5557, 138.1399] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Chuuk: 7°25′N 151°47′E -coord=[7.374227, 151.754606]%E -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pohnpei › Coordinates: 6.8519° N, 158.2147° E -coord=[6.8519, 158.2147] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Majuro › Coordinates7.0667° N, 171.2667° E -coord=[7.0667, 171.2667] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pago Pago › Coordinates: 14.2732° S, 170.7030° W -coord=[-14.2732, -170.7030]% SW -xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Kosrae › Coordinates :5.3096° N, 162.9815° E -coord=[5.3096, 162.9815] -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%------------------------------------------------------------------------ - -%Marshall Islands -%Majuro -coord=[7.0667, 171.2667] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Ebeye -coord=[8.7815, 167.7373] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Micronesia -%Kolonia, -coord=[6.9636, 158.2102] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Pohnpei, -coord=[6.8519, 158.2147] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Chuuk-Weno -coord=[7.4523, 151.8422] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -% Tofol -coord=[5.3256, 163.0086] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Colonia -between Palau and Guam -coord=[9.5164,138.1222] -%xus=[xus,coord(2)];yus=[yus,coord(1)]; -n1=length(xus); -%------------------------------------------------------------------------ -%Points from Curt -%Howland Island -Baker -coord=[0.8113, -176.6183]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Johnston atoll -coord=[16.7295, -169.5336]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Palmyra -coord=[5.8885, -162.0787]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Jarvis Island -coord=[0.3744, -159.9967]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%Baker Island -%0.1936° N, 176.4769° W -coord=[0.1936,-176.4769 ]%W -xus=[xus,coord(2)];yus=[yus,coord(1)]; -%------------------------------------------------------------------------ - coord=[18.4101, -75.0115 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: - %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg - %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). - %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. - %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. - - %Kwajalein Atoll - 9.1898° N, 167.4243° E - %Enewetak Atoll - 11.4654° N, 162.1890° E - %Bikini Atoll - 11.6065° N, 165.3768° E - - %Kwajalein Atoll - 9.1898° N, 167.4243° E - coord=[9.1898, 167.4243 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %Enewetak Atoll - 11.4654° N, 162.1890° E - coord=[ 11.4654, 162.1890]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - %Bikini Atoll - 11.6065° N, 165.3768° E - coord=[11.6065, 165.3768 ]%W - xus=[xus,coord(2)];yus=[yus,coord(1)]; - -Blon=[129.91 10.71]; -Blat=[-30.42 79.99]; -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); -Blon=lon; -xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; - -if isplot, - clf; - plot(xusp(1:n0) ,yus(1:n0),'k.',... - xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... - xusp(n1+1:end),yus(n1+1:end),'rx'); - hold on - BoundingBox(Blon-360,Blat,'r'); - grid on; - title('Updated RWPS high res target points'); - kprint('RWPSHighResPointsX.jpg'); -end -topo=BoxSmoothTopo(GlobalTopoFile,2); - -lon = topo.point.coord{:,1}; -lat = topo.point.coord{:,2}; - -%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); -p=loadmsh(PSLGfile); - -p.x=p.point.coord(:,1)-360; -p.y=p.point.coord(:,2); -p.edges=p.edge2.index(:,1:2); -plot(p.x,p.y,'g.'); - -%Remove near boundary points- Not land targets of resolution -dx=1; -j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); -j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); -plot(p.x,p.y,'y.'); - -j=find(xus>90); -xus(j)=xus(j)-360; - -%This loop Takes a few min:Find PSLG points near us coastline -deg2km=111.132954 -np=length(p.x); -NP=10000; - -clear d; -nus=length(xus); -for k=1:NP:np - j=k:min(np,k+NP); - x=p.x(j); - y=p.y(j); - d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); - %if mod(k,1000)==0,k/np,end - k/np -end - -dmin=100; -%dmin=50; -j=find(d90); -xus(j)=xus(j)-360; -Blon=[129.91-360, 10.71]; -Blat=[-30.42, 79.99]; -if isplot, - plot(p.x,p.y,'k.'); - hold on - BoundingBox(Blon,Blat,'k'); - th=title('PSLG defining boundary'); - set(th,'FontSize',22); - kprint('PSLG.jpg') - - plot(xus,yus,'r.'); - th=title('PSLG with US coasline data points(red)'); - set(th,'FontSize',22); - kprint('PSLGwUSpoints.jpg') - - j=find(d<100); - plot(p.x(j),p.y(j),'c.'); - th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); - set(th,'FontSize',22); - kprint('PSLGwUSpointsPSLGnear.jpg') -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%add points to off shore banks we want to refine here we have Georges Bank -%and banks around the Bahamas. - -xFB= [ -79.9909 -78.1963 -78.3957] -yFB= [23.7978 26.8928 24.1530] -xGB = -67.4517 -yGB = 41.3567 - -xx=[xUSsl(:);xus(:);xFB(:);xGB(:)]'; -yy=[yUSsl(:);yus(:);yFB(:);yGB(:)]'; -j=find(xx>90); -xx(j)=xx(j)-360; -plot(xx,yy,'c.'); - -D=DistanceToCoast(lon,lat,xx,yy); - -eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Make .msh files for jigsaw - -topo=BoxSmoothTopo(GlobalTopoFile,2); - -Dfun=topo; - -lon=Dfun.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); -j0=setdiff(1:length(lon),j);j0=j0(:); -lon=lon([j0(:);j(:)]); -D1=[D(:,j0),D(:,j)]; -Dfun.point.coord{:,1}=lon; -Dfun.value=D1; - -Dmax=20004000%max distance between two points on earth -D1(find(D1>Dmax))=Dmax; -Dfun.value=D1; - -figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); -shading interp;colorbar;colormap('jet') -savemsh(DFunOutFile,Dfun); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% save smoothed topo at same resolution as Distance function -topo=BoxSmoothTopo(GlobalTopoFile,2); - -D=topo.value; -lon=topo.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); -j0=setdiff(1:length(lon),j);j0=j0(:); -lon=lon([j0(:);j(:)]); -D1=[D(:,j0),D(:,j)]; -topo.point.coord{:,1}=lon; -topo.value=D1; - -figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); -shading interp;colorbar;colormap('jet') -savemsh(TopoFile,topo); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m index 9724182..f879286 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m @@ -1,10 +1,19 @@ function gnew=RemoveMeshParts(g,ax,S,ca); %function gnew=HandEditMesh(g,ax,p); -% Remove parts of mesh, g inside closed curves defined in pslg -% p. The action is preformed only within the axis ax. The -% frame work is intended to expand to moving nodes, removing elements, etc -%This wont touch nodes within MinBndDist (m) of existing boundary +% Graphical interface to remove parts of mesh, g inside axis, where ax=[xmin, xmax,ymin, ymax]. +% The frame work is intended to expand to moving nodes, removing elements, etc +% +% inputs: +% g : FE mesh structure with fields +% g.x : longitute +% g.y : latitude +% g.z : bathymetric depth +% g.e : (ne x 3) element list +% ax : output of axis for figure, i.e. ax=axis or prespecified as ax=[xmin, xmax,ymin, ymax] +% S : structure output from S=shaperead(CoastLineFile) etc. +% ca : [1,2] caxis for colorfield based on g.z ca=[min(g.z),max(g.z)] +% jx=find(and(g.x>ax(1),g.xax(3),g.y1, WriteWW3MeshX(g,FileOutWW3); -end \ No newline at end of file +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m deleted file mode 100644 index 9044665..0000000 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/SubsetMesh.m +++ /dev/null @@ -1,22 +0,0 @@ -function omesh=SubsetMesh(mesh,j) -%function omesh=SubsetMesh(mesh,j) -omesh.point.coord=mesh.point.coord(j,:); -e=mesh.tria3.index(:,1:3); - -[n1,four]=size(mesh.point.coord); -[n0,four]=size(omesh.point.coord); - -%S=sparse(n1,n0); -%S(1:n0,j)=1; -[A,B]=ismember(1:n1,j); -e0=B(e);%map to kept nodes and 0 for missing nodes -e0i=e0; -e0i(find(e0>0))=1;%index of nodes (1) in or (0) out -ke=find(sum(e0i')==3); -e0=e0(ke,:); - -omesh.tria3.index(:,1:3)=e0; -[ne,three]=size(omesh.tria3.index); -omesh.tria3.index(:,4)=zeros(ne,1); - - diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m index c1105c0..d515ce3 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m @@ -1,6 +1,7 @@ function kprint(fl); % function kprint(fl); -% prints and trims (using convert) current figure +% prints and trims (using convert) current figure to file name fl +% i.e. kprint('MyGraphicFile.jpg') h=gcf; saveas(h, fl); system(['convert -trim ',fl,' ',fl]); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/l.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/l.m index 497aca0..f3fe200 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/l.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/l.m @@ -1,6 +1,8 @@ function l(x) +%function l(str) +% just a shortcut for ls str -lrth from the matlab prompt if nargin<1 ls -lrth else eval(['ls ',x,' -lrth']) -end \ No newline at end of file +end diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m index 571305f..e86c43d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m @@ -19,16 +19,6 @@ % BndType: % BndGeom: -%$MeshFormat -%2 0 8 -%$EndMeshFormat -%$Nodes -%16160 -%1 -97.85953778 22.71682524 2.50000000 -%2 -97.78561621 22.17578432 2.50000000 -%3 -97.62163399 21.55885326 30.14750695 -%4 -97.81115063 24.09775399 2.50000000 - fp=fopen(fl,'r') str=fgetl(fp); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m index 0302f6e..12be5e0 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m @@ -1,6 +1,6 @@ function ph=patch_global(lon,lat,f,e) %function ph=patch_global(lon,lat,f,e) -% make a patch graphic object showing field f structure for mesh fith coordinates lon,lat and element matrix e. +% script to make a patch graphic object showing field f structure for mesh with coordinates lon,lat and element matrix e. % elements crossing dateline are eliminated in the plot dx=max(lon(e))-min(lon(e)); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m index 1b1dcb7..1d96db8 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m @@ -1,14 +1,18 @@ function [h,ki]=remove_dead_nodes(g) %function [h,ki]=remove_dead_nodes(g) % -% remove nodes from mesh structure g that are not present in any elements +% Primitive function to remove nodes from mesh structure g that are not present in any elements % the new mesh structure is returned as h +% input: +% g : FE mesh structure with fields +% g.x : longitute +% g.y : latitude +% g.z : bathymetric depth +% g.e : (ne x 3) element list % -% g.x : longitute -% g.y : latitude -% g.z : bathymetric depth -% g.e : (ne x 3) element list -% +% outputs: +% h : FE mesh structure with no nodes that aren't in elements +% ki : list of nodes in g that are now in h so that h.x=g.x(ki), etc. ju=sort(unique(g.e(:))); k=1:length(g.x); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m index d635ca4..09c3ab1 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m @@ -1,4 +1,19 @@ function h=submeshFast(g,jGoodNodes) +% +% Make the subset of unstructured mesh g consisting only of nodes +% with indexes in jGoodNodes (and only elements consisting entirely +% of nodes in jGoodNodes are preserved). +% input: +% g : FE mesh structure with fields +% g.x : longitute +% g.y : latitude +% g.z : bathymetric depth +% g.e : (ne x 3) element list +% jGoodNodes : list of nodes to keep +% +% output: +% h : portion of FE mesh structure,g spanned by nodes jGoodNodes +% jGoodNodes=jGoodNodes(:)';%row format diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m index 1d900ec..a75a722 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m @@ -1,4 +1,20 @@ function [h,k]=submeshFastEle(g,jBadNodes) +% +% Make the subset of unstructured mesh g consisting only of +% elements with no nodes in jBadNodes +% +% input: +% g : FE mesh structure with fields +% g.x : longitute +% g.y : latitude +% g.z : bathymetric depth +% g.e : (ne x 3) element list +% jBadNodes : list of nodes to throw out +% +% output: +% h : portion of FE mesh structure with no elements made entirely of +% nodes in list jBadNodes +% [ne,three]=size(g.e); A=ismember(g.e,jBadNodes); diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m index b86ffdf..d6c56f7 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m @@ -4,6 +4,16 @@ %Make the subset Planer Staight Line Graph(PSLG) consisting only of nodes % with indexes in jGoodNodes (only edges consisting spanning nodes in % jGoodNodes are preserved). +% inputs: +% g: a Planar Straight Line Graph (pslg) structure with fields +% g.x : (n x 1) x coordinates of points in pslg +% g.y : (n x 1 )y coordinates of points in pslg +% g.edges : (nedges x 2) list of edges between points +% jGoodNodes: list of points to preserve in out put h (only edges +% consisting points in jGoodNodes are preserved in h +% outputs: +% h: subset PSLG of g consisiting only of points jGoodNodes and edges +% spanning points in jGoodNodes % %XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX %Keston Smith 2022 diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m index 910ff61..487b16b 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m @@ -1,4 +1,15 @@ function topo=topo2msh(fl,flout) +% convert bathymetry in netcdf file fl to jigsaw m.msh format +% Retuns topo, a gridded jigsaw structure. +% inputs: +% fl : filename pointing to a netcdf bathymetry file with variables +% lon : length (nx+1) longitude of grid +% lat : length (ny+1) latitude of grid +% bed_elevation : ( nx by ny) average bathymetric depth in cell +% flout : jigsaw .msh file to write topo to. +% output: +% topo : jigsaw format girdded data representing the data in fl +% x=ncread(fl,'lon'); y=ncread(fl,'lat'); @@ -18,4 +29,4 @@ if nargin>2 savemsh(flout,topo); end - \ No newline at end of file + From 46676c4c58fc02cb5347f5d373976e4798cd8db8 Mon Sep 17 00:00:00 2001 From: keston Date: Fri, 6 Feb 2026 14:34:13 -0500 Subject: [PATCH 36/44] Added function to generate outer boundary from arbitrary rectangle and coastline data --- .../matlab/BuildBoundaryPSLGfunction.m | 255 +++++++++++------- .../matlab/RemoveMissingIslandsEle.m | 145 +++++----- 2 files changed, 232 insertions(+), 168 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index 6be5d87..2584bd3 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -1,37 +1,38 @@ -function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) -%function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) -% This is a function format of what is probably better written as a script. for examples see: +function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth,FileOutJigsaw) +% BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth,FileOutJigsaw[optional]) +% Build a boundary Planer Straight Line Graph (PSLG) from a coastline .msh file and +% Bounded oriented lat lon rectangle. +% inputs: +% CoastLineFile : shapefile describing an appropriately smoothed coastline +% for example one created with scripts: MakeCoastalBoundariesGSHHS.m +% in unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ +% lonWest : bounding west longitude +% lonEast : bounding east longitude +% latSouth : bounding south latitude +% latNorth : bounding north latitude +% FileOutJigsaw : file name to output jigsaw format .msh file % -% unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m or: -% unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m +% NOTE: If the south west corner (lonWest,latSouth ) is not in the grid (i.e. on land) then the next +% crossing point,moving to the east along the south boundary, should be into +% the intended connected part of the mesh. This has to do with finding and outer boundary in the PSLG +% and could be adjusted near line 271 if needed. % - - -%CoastLineFile = 'GlobalCoastlineOSM.shp' -%CoastLineFile = 'GlobalCoastlineGSHHS.shp' -%lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; -%run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +% CoastLineFile = 'GlobalCoastlineOSM.shp' +% CoastLineFile = 'GlobalCoastlineGSHHS.shp' +% lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +% or : ax=axis;lonWest=ax(1),lonEast=ax(2),latSouth=ax(3),latNorth=ax(4) +% run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) S=shaperead(CoastLineFile) -FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +if nargin<6 + FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] +end FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] isplot=0; -%load GlobalCoastlineOSM.mat - - -%The overall objective of this project is to develop and implement into operations -% a Regional Wave Prediction System (RWPS) that fulfills the needs of NWS marine coastal, -% offshore, and high seas areas of responsibility. The domain of the RWPS will cover the Atlantic, -% Pacific, and Arctic oceans equal to the bounds of the Oceanic Domain as developed for the -% National Blend of Models (NBM). For reference the NBM Oceanic Domain has corner points of LL - 30.42S - 129.91E UR - 79.99N - 10.71E. - -%Blon=[129.91 10.71]; -%Blat=[-30.42 79.99]; Blon=[lonWest, lonEast]; Blat=[latSouth,latNorth]; - N=length(S); N1=N; for k=1:N @@ -59,14 +60,29 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); Blon=lon; -%Make Bounding rectangle -Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] -By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] - +CornerX=[min(Blon),max(Blon),max(Blon),min(Blon)]; +CornerY=[min(Blat),min(Blat),max(Blat),max(Blat)]; + +%Make closed bounding rectangle +Bx=[CornerX,CornerX(1)]; +By=[CornerY,CornerY(1)]; clear pslg + + +N=length(S); +IsCornerIn=ones(1,4); + +for k=1:N + x=S(k).X(1:end);% remove trailing nan (-1) and endpoint==startpoint (-2) + y=S(k).Y(1:end); + [isin,ison]=insidepoly(CornerX,CornerY,x,y) ; + IsCornerIn=IsCornerIn-isin; + if mod(k,1000)==0,disp(['Checking boundary corners for land part compleate: ',num2str(k/N)]);,end +end +display(['IsCornerIn?, [SW,SE,NE,NW] = ',int2str(IsCornerIn)]) + sxp=[];syp=[ ]; xc=[];yc=[]; -N=length(S); pslg.x=[]; pslg.y=[]; pslg.edges=[]; @@ -76,10 +92,10 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor minarea=1 earth=referenceSphere('Earth'); -DXM=10^10;%DXM=1 -mdx=inf+ones(N,1); +% Loop handles all intersections of coastline with bounding rectangle boundaries +% elliminates portion outside of the rectangle, adds intersection points and +% creates all "chains" of nodes in this structure/ for k=1:N - isinbox(k)=0; x=S(k).X(1:end-1);% remove trailing nan (-1) and endpoint==startpoint (-2) y=S(k).Y(1:end-1); mx=mean(x); @@ -102,20 +118,17 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor xs=[xia(j),x( iis(j)+1:iis(j+1) ),xia(j+1)]; ys=[yia(j),y( iis(j)+1:iis(j+1) ),yia(j+1)]; dx=abs(xs(2:end)-xs(1:end-1) +i*[ys(2:end)-ys(1:end-1)] ); - mdx(k)=max(dx); - - if max(dx)2,max(dx)2,%no degenerate islands n0=length(pslg.x); pslg.x=[pslg.x,xs]; pslg.y=[pslg.y,ys]; @@ -174,7 +183,7 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor pslg.chains(nc).index=k; pslg.chains(nc).BI=0; end - end + end end end % if n>3, ar> if mod(k,1000)==0,disp(['Land segments compleate: ',num2str(k/N)]);,end @@ -184,45 +193,90 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%restart script from here if needed +% Intermission +% restart script from here if needed %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%clear -%close all + eval(['load ',FileOutMatlab]); -%load pslgOSM.mat -%%Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] -%%By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; +Blon=lon; +%Make Bounding rectangle +Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] +By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] -%make outer bound +nc=length(pslg.chains); n=length(pslg.x); -%pslg.x=[pslg.x,Bx(3:4)];%add northwest and north east box corner nodes -%pslg.y=[pslg.y,By(3:4)]; -pslg.x=[pslg.x,Bx(2:4)];%add northwest and north east box corner nodes -pslg.y=[pslg.y,By(2:4)]; -nc=length(pslg.chains);%add northwest and north east box corner chains -pslg.chains(nc+1).nodes=n+1; -nc=length(pslg.chains); -pslg.chains(nc+1).nodes=n+2; +%IsInSW=0;IsInSE=1;IsInNE=1;IsInNW=1; +%IsCornerIn=[IsInSW,IsInSE,IsInNE,IsInNW]; + +%Define ordered corners within mesh from south-west counter clockwise +% to north-west. +CornerX=[min(Blon),max(Blon),max(Blon),min(Blon)]; +CornerY=[min(Blat),min(Blat),max(Blat),max(Blat)]; + + +n=length(pslg.x); +%add southeast, northwest and northeast box corner nodes +pslg.x=[pslg.x,CornerX]; +pslg.y=[pslg.y,CornerY]; nc=length(pslg.chains); -pslg.chains(nc+1).nodes=n+3; +cc=0; +for k=1:4 + if IsCornerIn(k), + cc=cc+1; + pslg.x(n+cc)=CornerX(k); + pslg.y(n+cc)=CornerY(k); + pslg.chains(nc+cc).nodes=n+cc;%chain pointing to self + pslg.chains(nc+cc).BI=1;%chain on bndy + end +end nc=length(pslg.chains); +n=length(pslg.x); + +%find end points of chains on boundary +xbn=[]; +ybn=[]; +chn=[];nb=[]; +figure; +for k=1:nc, + if pslg.chains(k).BI==1, + nb=[nb;pslg.chains(k).nodes(1),pslg.chains(k).nodes(end)]; + %chn=[chn;[k,k]]; + chn=[chn;k]; + xbn=[xbn;[pslg.x( pslg.chains(k).nodes(1)), pslg.x( pslg.chains(k).nodes(end))]]; + ybn=[ybn;[pslg.y( pslg.chains(k).nodes(1)), pslg.y( pslg.chains(k).nodes(end))]]; + plot(pslg.x( pslg.chains(k).nodes), pslg.y( pslg.chains(k).nodes)); + hold on + end +end +plot(xbn,ybn,'ro') + +Deps1=10^-10; %tolerance for finding boundary points +%traverse south edge from west to east +[jS,cS]=find(abs(ybn-min(By)) < Deps1); +xS=[]; +yS=[]; +for k=1:length(jS), + xS=[xS,xbn(jS(k),cS(k))]; + yS=[yS,xbn(jS(k),cS(k))]; + if cS(k)==1, + nS(k)=pslg.chains( chn(jS(k)) ) .nodes(1) + else + nS(k)=pslg.chains( chn(jS(k)) ) .nodes(end) + end +end -xx =153.0400 %south east corner of Austrilia -yy = Blat(1) %check that these are the endpoints described for j0, j1!! -[m0,j0]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) -if isplot,plot(xx,yy,'ro',pslg.x(j0),pslg.y(j0),'bx');end +[xx,mm]=mink(xS,2);%Find two western most intersections on South boundary -xx = 288.3143%check that these are the endpoints described for j0, j1!! -yy = Blat(1) %south west corner of S. America -[m1,j1]=min(abs(pslg.x+i*pslg.y-xx-i*yy)) -if isplot,plot(xx,yy,'ro',pslg.x(j1),pslg.y(j1),'bx');end +j0=nS(mm(1)); +j1=nS(mm(2)); nc=length(pslg.chains); pslg.chains(nc+1).nodes=[j0,j1]; +pslg.chains(nc+1).BI=1; nc=length(pslg.chains); - for k=1:nc if mod(k,100)==0,disp(['Labeling chains compleate: ',num2str(k/nc)]);end spx(k)=pslg.x(pslg.chains(k).nodes(1)); @@ -234,7 +288,6 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor %make boundary order index along boundary for start points SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges c=0*spy; -Deps1=10^-10 j=find(abs(spy-By(1))ax(1),g.xax(3),g.yax(1),p.xax(3),p.yax(1),p.xax(3),p.y2, - if n(1)==n(end), - %jins=find(inside(x,y,p0.x(n),p0.y(n))); - %jins=find(inside(x,y,p0.x(n),p0.y(n))==1); - [inP,onP]=insidepoly(x,y,p0.x(n),p0.y(n)); - jins=find(or(inP,onP)); + nc=length(chains); + jb0=[]; + for k=1:nc + IsClosed(k)=0; + n=chains(k).nodes; + if length(n)>2, + if n(1)==n(end), + %jins=find(inside(x,y,p0.x(n),p0.y(n))); + %jins=find(inside(x,y,p0.x(n),p0.y(n))==1); + [inP,onP]=insidepoly(x,y,p0.x(n),p0.y(n)); + jins=find(or(inP,onP)); - jb0=[jb0;jins(:)]; - IsClosed(k)=1; - hold on;plot(p0.x(n),p0.y(n),'gx-') + jb0=[jb0;jins(:)]; + IsClosed(k)=1; + hold on;plot(p0.x(n),p0.y(n),'gx-') + end + end end - end -end -lat2m=110574.; -lon2m=111320.; + lat2m=110574.; + lon2m=111320.; -jb0X=[]; -for k=1:length(jb0); - n=jb0(k); + jb0X=[]; + for k=1:length(jb0); + n=jb0(k); - d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... - i*lat2m*( y(n)-yb ) )); - if d>MinBndDist,jb0X=[jb0X,n];end -end -jb0=jb0X; + d=min(abs( lon2m*( x(n)-xb )*cos(pi*y(n)/180) + ... + i*lat2m*( y(n)-yb ) )); + if d>MinBndDist,jb0X=[jb0X,n];end + end + jb0=jb0X; -if isplot, - hold on - plot(x(jb0),y(jb0),'ro'); -end + if isplot, + hold on + plot(x(jb0),y(jb0),'ro'); + end -[g1,kr0]=submeshFastEle(g0,jb0); + [g1,kr0]=submeshFastEle(g0,jb0); -if isplot, - figure(2); - x=g1.x;y=g1.y;z=g1.z;e=g1.e; - clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; - hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); - set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); -end -%jb=jg(jb0); -kr1=intersect(kr0,jb0);% kr0 can have boundary nodes not intended for removal!! -if isplot, - figure(2); - XE=g0.x(kr1); - YE=g0.y(kr1); - plot(XE,YE,'md') - figure(1);hold on;plot(XE,YE,'md') + if isplot, + figure(2); + x=g1.x;y=g1.y;z=g1.z;e=g1.e; + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;colorbar;axis equal; + hold on;plot(p0.x(p0.edges'),p0.y(p0.edges'),'k.-'); + set(ph,'EdgeColor','w');set(ph,'EdgeAlpha',.2); + end + %jb=jg(jb0); + kr1=intersect(kr0,jb0);% kr0 can have boundary nodes not intended for removal!! + if isplot, + figure(2); + XE=g0.x(kr1); + YE=g0.y(kr1); + plot(XE,YE,'md') + figure(1);hold on;plot(XE,YE,'md') + end + jb=jg(kr1); + nn=length(g.x); + gnew=submeshFast(g,setdiff(1:nn,jb)); %only removes nodes + else + gnew=g; + end +else + gnew=g; end -jb=jg(kr1); -nn=length(g.x); -gnew=submeshFast(g,setdiff(1:nn,jb)); %only removes nodes - From 7b1405f868c014ed75e18241e04e79f4e2f04605 Mon Sep 17 00:00:00 2001 From: keston Date: Fri, 6 Feb 2026 16:07:24 -0500 Subject: [PATCH 37/44] Added shell script to download coastline shapefiles used in RWPS mesh generation --- .../DownloadShapeFiles.sh | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh new file mode 100644 index 0000000..353546a --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Script to downoad files used in mesh generation for RWPS +echo "Downloading coastline shapefiles for boundary definition" + +############################################################################################################# +######################## Download Coastline Shape Files #################################################### +############################################################################################################# + +#US coastline data +echo "Downloading US coastline" +wget --output-document tl_2023_us_coastline.zip https://www2.census.gov/geo/tiger/TIGER2023/COASTLINE/tl_2023_us_coastline.zip + +echo "Downloading Global Self-consistent, Hierarchical, High-resolution Shorelines (GSHHS)" +#GSHHG global coastline data +wget --output-document gshhg-shp-2.3.7.zip http://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip + +echo "Downloading OpenStreetMap shoreline (OSM)" +#OSM global coastline data +wget --output-document land-polygons-complete-4326.zip https://osmdata.openstreetmap.de/download/land-polygons-complete-4326.zip + +############################################################################################################# +######################## 60 second Global Bathymetry######################################################### + +echo "Downloading global bathymetry" +wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip + +############################################################################################################# From 7df5eb3632e17435362b995b06ca9107b64a0253 Mon Sep 17 00:00:00 2001 From: keston Date: Fri, 6 Feb 2026 16:09:53 -0500 Subject: [PATCH 38/44] added generic function for generating boundary PSLG from coastline data and rectangle coordinates --- .../matlab/BuildBoundaryPSLGfunction.m | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index 2584bd3..992577c 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -19,8 +19,8 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor % % CoastLineFile = 'GlobalCoastlineOSM.shp' % CoastLineFile = 'GlobalCoastlineGSHHS.shp' -% lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; -% or : ax=axis;lonWest=ax(1),lonEast=ax(2),latSouth=ax(3),latNorth=ax(4) +% set:>> lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +% or :>> ax=axis;lonWest=ax(1),lonEast=ax(2),latSouth=ax(3),latNorth=ax(4) % run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) S=shaperead(CoastLineFile) @@ -57,9 +57,11 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor S=S(j);% sort to descending in length ns=ns(j);% sort to descending in length -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; Blon=lon; +%Define ordered corners within mesh from south-west counter clockwise +% to north-west. CornerX=[min(Blon),max(Blon),max(Blon),min(Blon)]; CornerY=[min(Blat),min(Blat),max(Blat),max(Blat)]; @@ -190,7 +192,8 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor end %OK - now revisit outer boundary! -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); +eval(['save -v7.3 ',FileOutMatlab]); + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Intermission @@ -199,25 +202,10 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor eval(['load ',FileOutMatlab]); -lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; -Blon=lon; -%Make Bounding rectangle -Bx=[Blon(1),Blon(2),Blon(2),Blon(1),Blon(1)] -By=[Blat(1),Blat(1),Blat(2),Blat(2),Blat(1)] nc=length(pslg.chains); n=length(pslg.x); -%IsInSW=0;IsInSE=1;IsInNE=1;IsInNW=1; -%IsCornerIn=[IsInSW,IsInSE,IsInNE,IsInNW]; - -%Define ordered corners within mesh from south-west counter clockwise -% to north-west. -CornerX=[min(Blon),max(Blon),max(Blon),min(Blon)]; -CornerY=[min(Blat),min(Blat),max(Blat),max(Blat)]; - - -n=length(pslg.x); %add southeast, northwest and northeast box corner nodes pslg.x=[pslg.x,CornerX]; pslg.y=[pslg.y,CornerY]; @@ -369,7 +357,7 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor OutterEdges=[epiv(1:NOE-1),epiv(2:NOE)]; pslg.edges=[pslg.edges;OutterEdges]; -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); +eval(['save -v7.3 ',FileOutMatlab]); nodelist=[]; chn=[]; @@ -385,7 +373,7 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor end end -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot nodelist epi chn']); +eval(['save -v7.3 ',FileOutMatlab]); pslg.chains=pslg.chains(chn); nc=length(pslg.chains); @@ -398,6 +386,7 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor %z=pslgb.x+i*pslgb.y; %[zu,j,k]=unique(z); %pslgc=subpslgFast(pslgb,j); + pslgc=pslgb %remove duplicate edges @@ -407,7 +396,7 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor pslg=pslgc -eval(['save -v7.3 ',FileOutMatlab,' pslg Blon Blat isplot']); +eval(['save -v7.3 ',FileOutMatlab]); %save PSLG to jigsaw .msh format geom=pslg2geom(pslg) From c549d984e7d57897f5fd1919bef5befa4743a353 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Tue, 10 Feb 2026 13:39:28 +0000 Subject: [PATCH 39/44] Simplified files path specification by adding input paths to SetPath.m rather than hardcoding in various scripts --- .../MeshGenTemplateDirectory/MakeDfunOSM.m | 11 ++++++--- .../MakeDfunOSMxGSHHS.m | 4 +++- .../PostProcessGrid.m | 10 ++++---- .../PreProcessCoastline.m | 4 ++-- .../MeshGenTemplateDirectory/SetPath.m | 23 +++++++++++++++++++ .../matlab/BuildBoundaryPSLGfunction.m | 22 +++++++++++++----- 6 files changed, 58 insertions(+), 16 deletions(-) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m index 8df6408..99e209d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m @@ -2,7 +2,8 @@ % and custom specification of other designated points. The PSLG intended for creation of the boundary % is used as well as a global bathymetry file and US coastline shapefile. -clear +%clear +SetPath close all isplot=0 @@ -12,9 +13,13 @@ %Coastline Boundary file PSLGfile='GlobalCoastlineOSM.PSLG.msh' %Global Bathymetry file (netcdf) -GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc' +%GlobalTopoFile='../Data/Bathymetry/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc' +GlobalTopoFile, %set as a global variable in SetPath %Shape file with US coastline -uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' +%uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' +uscl, %set as a global variable in SetPath %Output files %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m index 8513a3d..da931c0 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m @@ -12,7 +12,9 @@ %Coastline Boundary file PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' %Global Bathymetry file (netcdf) -GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc' +GlobalTopoFile='../Data/Bathymetry/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc' %Shape file with US coastline uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index 208948b..c6bcd8b 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -1,7 +1,6 @@ -addpath ../matlab -addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab -addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + +SetPath %script to handle all post jigsaw mesh editing. %Post processing steps are as follows @@ -21,10 +20,13 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: isplot=0; outdir='testGSHHS/' -pslgfile='GlobalCoastlineGSHHS.PSLG.msh' +%pslgfile='GlobalCoastlineGSHHS.PSLG.msh' +pslgfile=PSLGfile, %global variable filename set in SetPath + jigsawout='RWPS.F.LLH' WW3FileOut='RWPS.GSHHS.WW3.msh' + %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% g=loadmsh([outdir,jigsawout,'.msh']); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m index 7986015..1b9898f 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m @@ -2,8 +2,8 @@ SetPath -MakeCoastalBoundariesGSHHS -BuildBoundaryPSLGwGSHHS +%MakeCoastalBoundariesGSHHS +%BuildBoundaryPSLGwGSHHS MakeDfunGSHHS diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m index 50d757f..faa4b74 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m @@ -1,4 +1,27 @@ + addpath ../matlab addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly + +% set global variables defining paths to different data sets +global GlobalTopoFile uscl gcfl gcflGSHHS gcflOSM PSLGfile + +% Global coverage "low" resolution bathymetry file +GlobalTopoFile='../Data/Bathymetry/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc' + +% US coastline file or shapefile defining coastal points for high resolution +uscl='../Data/us_coastline/tl_2023_us_coastline.shp' + +%Global coverage coastline file from () +gcflGSHHS='../Data/GSHHS_shp/f/GSHHS_f_L1.shp' + +%Global coverage coastline file from OpenStreetMap +gcflOSM='../Data/openstreetmap_land/land-polygons-complete-4326/land_polygons.shp' + +%which Global coverage coastline file is to be used +gcfl=gcflGSHHS + +%Output file from BuildBoundaryPSLGwGSHHS and input to MakeDfunGSHHS +PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index 992577c..e5c71a8 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -23,6 +23,10 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor % or :>> ax=axis;lonWest=ax(1),lonEast=ax(2),latSouth=ax(3),latNorth=ax(4) % run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +%Note: One could eliminate the path in the input and use +%SetPath +%CoastLineFile='GlobalCoastline.msh' + S=shaperead(CoastLineFile) if nargin<6 FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] @@ -273,16 +277,22 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor epy(k)=pslg.y(pslg.chains(k).nodes(end)); end -%make boundary order index along boundary for start points -SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges + +%The function c runs from lowest on the South West corner of the mesh, +%increasing moving east along the South bounding line. It then increases +%moving North along the East Boundary, then increases moving West Along the +% North Boundary before increaing moving South along the West Boundary. + +%make boundary order index along boundary for start points of outer boundary segments +SN=10.*[max(abs(pslg.x))+max(abs(pslg.y))];%large number to seperate edges S,E, N, W boundaries c=0*spy; -j=find(abs(spy-By(1)) Date: Wed, 11 Feb 2026 08:17:54 -0500 Subject: [PATCH 40/44] Added function LonCon to remove longitude transform from scripts. Changed from insidepoly toolbox to inpoly2 to simplify download and improve support. --- .../BuildBoundaryPSLGwGSHHS.m | 2 +- .../BuildBoundaryPSLGwOSM.m | 2 +- .../DownloadShapeFiles.sh | 22 ++ .../ExtraPointsOfIntrest.m | 117 ++++++++++ .../FilterRoutinesNM.py | 3 +- .../MeshGenTemplateDirectory/LonCon.m | 10 + .../MakeCoastalBoundariesGSHHS.m | 7 +- .../MakeCoastalBoundariesOSM.m | 9 +- .../MeshGenTemplateDirectory/MakeDfunGSHHS.m | 6 +- .../MeshGenTemplateDirectory/MakeDfunOSM.m | 19 +- .../MakeDfunOSMxGSHHS.m | 6 +- .../MakeDistanceToCoastRWPS.m | 219 ++++++++++++++++++ .../MeshGenTemplateDirectory/MakeRWPSMesh.m | 9 + .../PostProcessGrid.m | 37 +-- .../MeshGenTemplateDirectory/SetPath.m | 7 +- .../matlab/BuildBoundaryPSLGfunction.m | 40 ++-- .../RWPSMeshtoolkit/matlab/DistanceToCoast.m | 4 + .../RWPSMeshtoolkit/matlab/GetMatlabLibs.sh | 8 + .../matlab/MakeDistanceToCoastData.m | 128 ++++++++++ .../RWPSMeshtoolkit/matlab/insidepoly.m | 15 ++ 20 files changed, 612 insertions(+), 58 deletions(-) mode change 100644 => 100755 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m create mode 100755 unst_msh_gen/RWPSMeshtoolkit/matlab/GetMatlabLibs.sh create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDistanceToCoastData.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/matlab/insidepoly.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m index 09951fc..5f2645b 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m @@ -50,7 +50,7 @@ S=S(j);% sort to descending in length ns=ns(j);% sort to descending in length -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; Blon=lon; %Make Bounding rectangle diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m index c5015fa..2699eea 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m @@ -48,7 +48,7 @@ S=S(j);% sort to descending in length ns=ns(j);% sort to descending in length -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; Blon=lon; %Make Bounding rectangle diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh old mode 100644 new mode 100755 index 353546a..af193a2 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh @@ -26,3 +26,25 @@ echo "Downloading global bathymetry" wget https://github.com/dengwirda/dem/releases/download/v0.1.1/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip ############################################################################################################# + +mkdir ../Data +mkdir ../Data/us_coastline/ +unzip tl_2023_us_coastline.zip +mv tl_2023_us_coastline.* ../Data/us_coastline/ +echo "US coastline data moved to ../Data/us_coastline/" + +unzip gshhg-shp-2.3.7.zip +mv GSHHS_shp/ ../Data/ +mv WDBII_shp ../Data/ +mv gshhg-shp-2.3.7.zip ../Data +echo "GSHHS global coastline data moved to ../Data/GSHHS_shp/" + +unzip land-polygons-complete-4326.zip +mkdir ../Data/openstreetmap_land +mv land-polygons-complete-* ../Data/openstreetmap_land/ +echo "OSM global coastline data moved to ../Data/openstreetmap_land/" + +unzip RTopo_2_0_4_GEBCO_v2024_60sec_pixel.zip +mkdir ../Data/Bathymetry +mv RTopo_2_0_4_GEBCO_v* ../Data/Bathymetry/ +echo "Global bathymetry data moved to ../Data/Bathymetry/" diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m new file mode 100644 index 0000000..e4c3c18 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m @@ -0,0 +1,117 @@ +function [xus,yus]=ExtraPointsOfIntrest +xus=[]; +yus=[]; + +%Now add Pacific Territories and COFA points +%------------------------------------------------------------------------ +%NWS Pacific Region, via the Compact of Free Association, +% %oversees operations of 5 Weather Service Offices (WSO) across +% Micronesia in the Republic of Palau, Federated States of Micronesia +% and the Republic of the Marshall Islands. WFO Guam provides routine +% forecasts as well as WWA services for these areas. -Eric Lau +%Palau,Yap, Chuuk, Pohnpei, Majuro, Pago Pago, Wake island + +%Wake Island +coord=[19.2796,166.6499];%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palau +coord=[7.4942, 134.5690] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Yap:9.5557° N, 138.1399° E +coord=[9.5557, 138.1399] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Chuuk: 7°25′N 151°47′E +coord=[7.374227, 151.754606]%E +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei › Coordinates: 6.8519° N, 158.2147° E +coord=[6.8519, 158.2147] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Majuro › Coordinates7.0667° N, 171.2667° E +coord=[7.0667, 171.2667] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pago Pago › Coordinates: 14.2732° S, 170.7030° W +coord=[-14.2732, -170.7030]% SW +xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Kosrae › Coordinates :5.3096° N, 162.9815° E +coord=[5.3096, 162.9815] +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + +%Marshall Islands +%Majuro +coord=[7.0667, 171.2667] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Ebeye +coord=[8.7815, 167.7373] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Micronesia +%Kolonia, +coord=[6.9636, 158.2102] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Pohnpei, +coord=[6.8519, 158.2147] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Chuuk-Weno +coord=[7.4523, 151.8422] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +% Tofol +coord=[5.3256, 163.0086] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Colonia -between Palau and Guam +coord=[9.5164,138.1222] +%xus=[xus,coord(2)];yus=[yus,coord(1)]; +n1=length(xus); +%------------------------------------------------------------------------ +%Points from Curt +%Howland Island -Baker +coord=[0.8113, -176.6183]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Johnston atoll +coord=[16.7295, -169.5336]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Palmyra +coord=[5.8885, -162.0787]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Jarvis Island +coord=[0.3744, -159.9967]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%Baker Island +%0.1936° N, 176.4769° W +coord=[0.1936,-176.4769 ]%W +xus=[xus,coord(2)];yus=[yus,coord(1)]; +%------------------------------------------------------------------------ + coord=[18.4101, -75.0115 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %If your team is going to the effort to add resolution for Majuro in RMI, I would strongly suggest doing the same for these atolls in RMI: + %1. Kwajalein Atoll, which is home to part of the Ronald Regard Ballistic Missile Test Site (https://home.army.mil/kwajalein/index.php) and the underprediction of wave heights by NWS' WaveWatchIII model in January 2024, which I discussed on our last call, is what led to significant damage at the base, per: https://www.youtube.com/shorts/jH-pGoQDdcg + %2. Enewetak Atoll, which is the home of the Runit Dome (https://en.wikipedia.org/wiki/Runit_Island), is threatened by wave-driven overwash that has serious implications for the US Department of State, Department of Defense/War, and Department of the Interior via the Intergovernmental Compact of Free Association (https://www.doi.gov/oia/compacts-of-free-association). + %3. Bikini Atoll, for similar reasons as Enewetak, although the radionuclides are all over the place and not all dumped in one location. + %I would note that most of the atolls drop off at a 70-80 degree slope from approximately 30 m depth (which is generally less than 1000 m from shore) to over 1000 m depth, so there is not a need for a large region of increasing resolution to capture a broad continental shelf as characterizes CONUS. + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + %Enewetak Atoll - 11.4654° N, 162.1890° E + %Bikini Atoll - 11.6065° N, 165.3768° E + + %Kwajalein Atoll - 9.1898° N, 167.4243° E + coord=[9.1898, 167.4243 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Enewetak Atoll - 11.4654° N, 162.1890° E + coord=[ 11.4654, 162.1890]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + %Bikini Atoll - 11.6065° N, 165.3768° E + coord=[11.6065, 165.3768 ]%W + xus=[xus,coord(2)];yus=[yus,coord(1)]; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%add points to off shore banks we want to refine here we have Georges Bank +%and banks around the Bahamas. + +xFB= [ -79.9909 -78.1963 -78.3957] +yFB= [23.7978 26.8928 24.1530] +xGB = -67.4517 +yGB = 41.3567 + +xus=[xus(:);xFB(:);xGB(:)]'; +yus=[yus(:);yFB(:);yGB(:)]'; + +xus=LonCon(xus); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py index 6daaf82..5a230ae 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py @@ -65,7 +65,8 @@ def inject_dem(): #data = nc.Dataset(dem_file,"r") # data = nc.Dataset("../RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") - data = nc.Dataset("/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") +# data = nc.Dataset("/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc","r") + data = nc.Dataset("../Data/Bathymetry/RTopo_2_0_4_GEBCO_v2024_60sec_pixel.nc","r") xlon = np.asarray(data["lon"][:]) ylat = np.asarray(data["lat"][:]) elev = np.asarray(data["bed_elevation"][:]) + \ diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m new file mode 100644 index 0000000..3a1b6ac --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m @@ -0,0 +1,10 @@ +function lon=LonCon(lon) +% function lon=LonCon(lon) +% Transform longitude to match longitude convention you want to use +% here. This is used to avoid discontinuity at the international; +% dateline etc. + + +%lon=lon; +j=find(lon<90);lon(j)=lon(j)+360; % RWPS +%j=find(lon>180);lon(j)=lon(j)-360;% \ No newline at end of file diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m index 4141fbe..3dce92d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m @@ -11,8 +11,7 @@ %various smoothings of coastlines -clear - +SetPath isplot=0 deg2km=111.132954 deg2rad=pi/180 @@ -34,7 +33,7 @@ earth=referenceSphere('Earth') -gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' +%gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/GlobalCoast/GSHHS_shp/f/GSHHS_f_L1.shp' S = shaperead(gcfl); N=length(S); isisland=zeros(N,1); @@ -138,5 +137,5 @@ S=rmfield(S,'X0') S=rmfield(S,'Y0') -BoundaryShape2msh(S,'GlobalCoastlineGSHHS.msh'); +%BoundaryShape2msh(S,'GlobalCoastlineGSHHS.msh'); shapewrite(S, 'GlobalCoastlineGSHHS.shp'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m index 2f32daf..8dc6c24 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m @@ -9,8 +9,7 @@ %Coastline is smoothed and subsampled to usefull scale for mesh generation in RWPS %various smoothings of coastlines - -clear +SetPath isplot=0 deg2km=111.132954 deg2rad=pi/180 @@ -31,7 +30,7 @@ earth=referenceSphere('Earth') -gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/openstreetmap_land/land_polygons.shp' +%gcfl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/openstreetmap_land/land_polygons.shp' S = shaperead(gcfl); N=length(S); @@ -70,6 +69,7 @@ for k=1:N x=S(k).X(1:end-2);%unique* points + x=LonCon(x); y=S(k).Y(1:end-2); zz=x+i*y; [zzu,j]=unique(zz);%find unique points before end @@ -82,7 +82,6 @@ y=[y,y(1)]; [xs,ys]=SmoothSubSampleCoastlineFast(x,y,50.,10);%500 m coastline - zs=xs+i*ys; dz=abs(zs(2:end)-zs(1:end-1)); j=find(dz>1); @@ -171,5 +170,5 @@ S=rmfield(S,'X0') S=rmfield(S,'Y0') -BoundaryShape2msh(S,'GlobalCoastlineOSM.msh'); +%BoundaryShape2msh(S,'GlobalCoastlineOSM.msh'); shapewrite(S, 'GlobalCoastlineOSM.shp'); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m index ba1c40b..f04d0eb 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m @@ -154,7 +154,7 @@ Blon=[129.91 10.71]; Blat=[-30.42 79.99]; -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; Blon=lon; xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; @@ -277,7 +277,7 @@ Dfun=topo; lon=Dfun.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; @@ -298,7 +298,7 @@ D=topo.value; lon=topo.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m index 99e209d..b665fa0 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m @@ -156,17 +156,16 @@ Blon=[129.91 10.71]; Blat=[-30.42 79.99]; -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); -Blon=lon; -xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; +Blon=LonCon(Blon) +xusp=LonCon(xus); if isplot, clf; plot(xusp(1:n0) ,yus(1:n0),'k.',... xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... xusp(n1+1:end),yus(n1+1:end),'rx'); hold on - BoundingBox(Blon-360,Blat,'r'); + BoundingBox(Blon,Blat,'r'); grid on; title('Updated RWPS high res target points'); kprint('RWPSHighResPointsX.jpg'); @@ -179,7 +178,8 @@ %p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); p=loadmsh(PSLGfile); -p.x=p.point.coord(:,1)-360; +%p.x=p.point.coord(:,1)-360; +p.x=LonCon(p.x); p.y=p.point.coord(:,2); p.edges=p.edge2.index(:,1:2); plot(p.x,p.y,'g.'); @@ -192,8 +192,9 @@ j=find(p.y>min(p.y)+dx);p=subpslgFast(p,j); plot(p.x,p.y,'y.'); -j=find(xus>90); -xus(j)=xus(j)-360; +%j=find(xus>90); +%xus(j)=xus(j)-360; +xus=LonCon(xus) %This loop Takes a few min:Find PSLG points near us coastline deg2km=111.132954 @@ -279,7 +280,7 @@ Dfun=topo; lon=Dfun.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; @@ -300,7 +301,7 @@ D=topo.value; lon=topo.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m index da931c0..68bf254 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m @@ -153,7 +153,7 @@ Blon=[129.91 10.71]; Blat=[-30.42 79.99]; -lon=Blon;j=find(lon<90);lon(j)=180+(lon(j)+180); +lon=Blon;j=find(lon<90);lon(j)=lon(j)+360; Blon=lon; xusp=xus;j=find(xus>0);xusp(j)=xus(j)-360; @@ -276,7 +276,7 @@ Dfun=topo; lon=Dfun.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; @@ -297,7 +297,7 @@ D=topo.value; lon=topo.point.coord{:,1}; -j=find(lon<90);lon(j)=180+(lon(j)+180); +j=find(lon<90);lon(j)=lon(j)+360; j0=setdiff(1:length(lon),j);j0=j0(:); lon=lon([j0(:);j(:)]); D1=[D(:,j0),D(:,j)]; diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m new file mode 100644 index 0000000..662ddb5 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m @@ -0,0 +1,219 @@ +%This script creates a "Distance to Coast file" using a US coastline file +% and custom specification of other designated points. The PSLG intended for creation of the boundary +% is used as well as a global bathymetry file and US coastline shapefile. + +SetPath +isplot=0 + +%Input files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%PSLGfile='GlobalCoastlineOSM.PSLG.msh' +%PSLGfile='PSLGboundaryOSMxGSHHS.BOXES.msh' + +%Coastline Boundary file +%PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%Global Bathymetry file (netcdf) +%GlobalTopoFile='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/RTopo_2_0_4_GEBCO_v2023_60sec_pixel.nc' +%Shape file with US coastline +%uscl='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/Data/us_coastline/tl_2023_us_coastline.shp' + +%Output files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Output "distance to coast" grided jigsaw .msh file +DFunOutFile=['DFun.',PSLGfile(1:end-4),'.msh'] +%Output bathymetry on same grid as DFunOutFile +TopoFile=['Topo.',DFunOutFile]; +%Temporary matlab file +FileOutMatlab=[PSLGfile(1:end-4),'.MakeDistance.mat'] + + +US=shaperead(uscl); +NUS=length(US) +xus=[]; +yus=[]; +x0=[] +y0=[]; +interpDist=100. %meters +SmoothN=25;% box car smooth coastline at width 2(*SmoothN+1)*interpDist +% then subsample soothed coastline every SmoothN points to create smaller +% coastline data set. i.e. remove small scale variation +for k=1:NUS + x=US(k).X(1:end-1); + y=US(k).Y(1:end-1); + x0=[x0,x]; + y0=[y0,y]; +% xs=x;ys=y; %1.5 mil points + if length(x)>3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end +n0=length(xus); + +[xpi,ypi]=ExtraPointsOfIntrest + +xus=[xus(:)',xpi(:)'] +yus=[yus(:)',ypi(:)'] + +Blon=[129.91 10.71]; +Blat=[-30.42 79.99]; +Blon=LonCon(Blon) + + +if isplot, + xusp=LonCon(xus); + clf; + plot(xusp(1:n0) ,yus(1:n0),'k.',... + xusp(n0+1:n1) ,yus(n0+1:n1),'co', ... + xusp(n1+1:end),yus(n1+1:end),'rx'); + hold on + BoundingBox(Blon-360,Blat,'r'); + grid on; + title('Updated RWPS high res target points'); + kprint('RWPSHighResPointsX.jpg'); +end +topo=BoxSmoothTopo(GlobalTopoFile,2); + +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +%p=loadmsh('PSLGboundaryOSMxGSHHS1km.msh'); +p=loadmsh(PSLGfile); + +%p.x=p.point.coord(:,1)-360; +p.x=p.point.coord(:,1); +p.y=p.point.coord(:,2); +p.x=LonCon(p.x); +p.edges=p.edge2.index(:,1:2); +plot(p.x,p.y,'g.'); + +%Remove near boundary points- Not land targets of resolution +dx=1; +j=find(p.xmin(p.x)+dx);p=subpslgFast(p,j); +j=find(p.ymin(p.y)+dx);p=subpslgFast(p,j); +plot(p.x,p.y,'y.'); + +%j=find(xus>90); +%xus(j)=xus(j)-360; + +xus=LonCon(xus); +p.x=LonCon(p.x); +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +t0=now; +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + if mod(k,1)==0, + t1=now; + est=(np-k)*[(t1-t0)/k]; + disp(['Computing PSLG distance to coast, etimated time remaing: ' ,num2str(est*24*60),' miniutes']); + end +end + +dmin=100; +%dmin=50; +j=find(d90); +xus(j)=xus(j)-360; +Blon=[129.91-360, 10.71]; +Blat=[-30.42, 79.99]; +if isplot, + plot(p.x,p.y,'k.'); + hold on + BoundingBox(Blon,Blat,'k'); + th=title('PSLG defining boundary'); + set(th,'FontSize',22); + kprint('PSLG.jpg') + + plot(xus,yus,'r.'); + th=title('PSLG with US coasline data points(red)'); + set(th,'FontSize',22); + kprint('PSLGwUSpoints.jpg') + + j=find(d<100); + plot(p.x(j),p.y(j),'c.'); + th=title('PSLG with US coasline data points and PSLG points near us (cyan)'); + set(th,'FontSize',22); + kprint('PSLGwUSpointsPSLGnear.jpg') +end + + + +xx=[xUSsl(:);xus(:)]'; +yy=[yUSsl(:);yus(:)]'; +xx=LonCon(xx); +plot(xx,yy,'c.'); + +save tmp.mat + +D=DistanceToCoast(lon,lat,xx,yy); + +eval(['save -v7.3 ',FileOutMatlab, ' lon lat D xx yy xus yus xUSsl yUSsl']) ; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Make .msh files for jigsaw + +topo=BoxSmoothTopo(GlobalTopoFile,2); + +Dfun=topo; + +lon=Dfun.point.coord{:,1}; +j=find(lon<90);lon(j)=lon(j)+360; +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +Dfun.point.coord{:,1}=lon; +Dfun.value=D1; + +Dmax=20004000%max distance between two points on earth +D1(find(D1>Dmax))=Dmax; +Dfun.value=D1; + +figure;clf;pcolor(Dfun.point.coord{:,1},Dfun.point.coord{:,2},exp(-Dfun.value/320000)); +shading interp;colorbar;colormap('jet') +savemsh(DFunOutFile,Dfun); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% save smoothed topo at same resolution as Distance function +topo=BoxSmoothTopo(GlobalTopoFile,2); + +D=topo.value; +lon=topo.point.coord{:,1}; +j=find(lon<90);lon(j)=lon(j)+360; +j0=setdiff(1:length(lon),j);j0=j0(:); +lon=lon([j0(:);j(:)]); +D1=[D(:,j0),D(:,j)]; +topo.point.coord{:,1}=lon; +topo.value=D1; + +figure;clf;pcolor(topo.point.coord{:,1},topo.point.coord{:,2},topo.value); +shading interp;colorbar;colormap('jet') +savemsh(TopoFile,topo); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m new file mode 100644 index 0000000..f57e345 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m @@ -0,0 +1,9 @@ + +SetPath +lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +CoastLineFile = 'GlobalCoastlineGSHHS.shp' +BuildBoundaryPSLGfunctionLC(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +[xpi,ypi]=ExtraPointsOfIntrest; +TargetShap=uscl; +DX=.1; +MakeDistanceToCoastData(DX,TargetShape,xpi,ypi) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index c6bcd8b..a816697 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -18,8 +18,10 @@ % this is the mesh to run WW3 on. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: + +SetPath isplot=0; -outdir='testGSHHS/' +outdir='RWPS.1/' %pslgfile='GlobalCoastlineGSHHS.PSLG.msh' pslgfile=PSLGfile, %global variable filename set in SetPath @@ -39,13 +41,18 @@ %Add Lakes to Mesh %g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); - -gS=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Sebago.NWPS.WW3.msh'); -gS.x=gS.x-360; -gW=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Winnipesaukee.NWPS.WW3.msh') -gW.x=gW.x-360; -gO=loadmshWW3('/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/Okeechobee.NWPS.WW3.msh') -gO.x=gO.x-360; +g.x=LonCon(g.x); +LakeDir='/mnt/sda/keston/RWPSLakes/' +%LakeDir='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/' +gS=loadmshWW3([LakeDir,'Sebago.NWPS.WW3.msh']); +%gS.x=gS.x-360; +gS.x=LonCon(gS.x); +gW=loadmshWW3([LakeDir,'Winnipesaukee.NWPS.WW3.msh']) +%gW.x=gW.x-360; +gW.x=LonCon(gW.x); +gO=loadmshWW3([LakeDir,'Okeechobee.NWPS.WW3.msh']) +%gO.x=gO.x-360; +gO.x=LonCon(gO.x); g=CombineMesh(g,gO); g=CombineMesh(g,gS); @@ -74,7 +81,8 @@ p.x=p.point.coord(:,1); p.y=p.point.coord(:,2); p.edges=p.edge2.index(:,1:2); -p.x=p.x-360; +%p.x=p.x-360; +p.x=LonCon(p.x); x=g.x;y=g.y;z=g.z;e=g.e; if isplot, @@ -116,8 +124,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (E) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% p=loadmsh(pslgfile); -p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); - +p.x=p.point.coord(:,1);p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); +p.x=LonCon(p.x); x=g.x;y=g.y;z=g.z;e=g.e; if isplot, LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); @@ -129,7 +137,9 @@ end p=loadmsh(pslgfile); -p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); +%p.x=p.point.coord(:,1);p.x=p.x-360;p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); +p.x=p.point.coord(:,1);p.y=p.point.coord(:,2);p.edges=p.edge2.index(:,1:2); +p.x=LonCon(p.x); g0=g; gnew=g @@ -219,7 +229,8 @@ Blon=[129.91 10.71] Blat=[-30.42 79.99] -Blon(1)=Blon(1)-360 +%Blon(1)=Blon(1)-360 +Blon=LonCon(Blon); x=g.x;y=g.y;z=g.z;e=g.e; jb=g.bnd; bnd0=detbndy(g.e) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m index faa4b74..51764ab 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m @@ -1,7 +1,10 @@ addpath ../matlab -addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab -addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly +addpath ../matlab/jigsaw-matlab +addpath ../matlab/inpoly + +%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab +%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly % set global variables defining paths to different data sets diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index e5c71a8..1d3ffce 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -1,4 +1,4 @@ -function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth,FileOutJigsaw) +function BuildBoundaryPSLGfunctionLC(CoastLineFile,lonWest,lonEast,latSouth,latNorth,FileOutJigsaw) % BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth,FileOutJigsaw[optional]) % Build a boundary Planer Straight Line Graph (PSLG) from a coastline .msh file and % Bounded oriented lat lon rectangle. @@ -23,6 +23,8 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor % or :>> ax=axis;lonWest=ax(1),lonEast=ax(2),latSouth=ax(3),latNorth=ax(4) % run:>> BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +% >>west=-127,east=-121,south=45.5,north=50 +% >>BuildBoundaryPSLGfunction('GlobalCoastlineOSM.shp',west,east,south,north) %Note: One could eliminate the path in the input and use %SetPath %CoastLineFile='GlobalCoastline.msh' @@ -44,14 +46,18 @@ function BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNor lon=S(k).X(1:end-1);%remove trailing nan lat=S(k).Y(1:end-1); ns(k)=length(lon); - jWest=find(lon<90); - if(length(jWest)==ns(k)); - S(k).X=[lon+360,NaN]; + + lonp=LonCon(lon); + mvp=sum(lon~=lonp);%find how many points change due to LonCon in this segment + if(mvp==ns(k));% if all move then just move boundary + S(k).X=[LonCon(lon),NaN]; end - if and(0length(jWest)),%make translated copy + if and(mvp>0,mvp3 + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,interpDist,SmoothN); + xus=[xus,xs]; + yus=[yus,ys]; + end +end + +whos x0 xus + +xus=[xus(:)',xtrgt(:)']; +yus=[yus(:)',ytrgt(:)']; + +n0=length(xus); + +p=loadmsh(PSLGfile); +p.x=p.point.coord(:,1); +p.x=LonCon(p.x); + +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); + +xg=min(p.x-DX):DX:max(p.x+DX); +yg=min(p.y-DX):DX:max(p.y+DX); +nx=length(xg); +ny=length(yg); +XG=ones(ny,1)*[xg(:)']; +YG=yg(:)*ones(1,nx); + +topo=BoxSmoothTopo(GlobalTopoFile,0); +lon = topo.point.coord{:,1}; +lat = topo.point.coord{:,2}; + +localtopo=topo; +localtopo.point.coord{:,1}=xg(:); +localtopo.point.coord{:,2}=yg(:); +localtopo.value=interp2(topo.point.coord{:,1},topo.point.coord{:,2},topo.value,XG,YG); + +%This loop Takes a few min:Find PSLG points near us coastline +deg2km=111.132954 +np=length(p.x); +NP=10000; + +clear d; +nus=length(xus); +for k=1:NP:np + j=k:min(np,k+NP); + x=p.x(j); + y=p.y(j); + d(j)=min(deg2km*abs([x(:)-xus(:)'].*[cos(pi*y(:)/180)*ones(1,nus)]+i*[y(:)-yus(:)'])'); + %if mod(k,1000)==0,k/np,end + k/np +end + +%dmin=10; +dmin=50; +j=find(d1, + onpoly0=0*inpoly; +end +%INPOLY2 compute "points-in-polygon" queries. +% [STAT] = INPOLY2(VERT,NODE,EDGE) returns the "inside/ou- +% tside" status for a set of vertices VERT and a polygon +% {NODE,EDGE} embedded in a two-dimensional plane. General +% non-convex and multiply-connected polygonal regions can +% be handled. VERT is an N-by-2 array of XY coordinates to +% be tested. STAT is an associated N-by-1 logical array, +% with STAT(II) = TRUE if VERT(II,:) is an interior point. From 6011692408ee351305930752dc1814c4ee927f86 Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 11 Feb 2026 15:58:32 +0000 Subject: [PATCH 41/44] Added sample scripts for local mesh generation. fixed lake meshfile path on ursa --- .../MeshGenTemplateDirectory/MakeRWPSMesh.m | 7 +- .../PostProcessGrid.NWcoastal.m | 145 ++++++++++ .../PostProcessGrid.m | 9 +- .../PreProcessCoastline.m | 16 +- .../PreProcessCoastline_NWCoastalMesh.m | 12 + .../RWPSMeshGenScript.GSHHS.py | 267 ++++++++++++++++++ .../MeshGenTemplateDirectory/jigsaw.ursa.job | 5 +- 7 files changed, 449 insertions(+), 12 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m index f57e345..96c60b7 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m @@ -2,8 +2,9 @@ SetPath lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; CoastLineFile = 'GlobalCoastlineGSHHS.shp' -BuildBoundaryPSLGfunctionLC(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) [xpi,ypi]=ExtraPointsOfIntrest; TargetShap=uscl; -DX=.1; -MakeDistanceToCoastData(DX,TargetShape,xpi,ypi) +%DX=.1; +%MakeDistanceToCoastData(DX,TargetShape,xpi,ypi) +MakeDistanceToCoastRWPS diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m new file mode 100644 index 0000000..88b4860 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m @@ -0,0 +1,145 @@ + + +SetPath + +%script to handle all post jigsaw mesh editing. +%Post processing steps are as follows +% (A) Remove sand points +% (B) Merge inland lakes --> 'RWPS.WW3a.lakes.msh' +% (C) Remove islands that jigsaw has meshed over +% (D) Remove sand points that can be created (rarely) with island removal --> 'RWPS.WW3a1.lakes.msh' +% INACTIVE (E) Examine Pacific island resolution and make changes to island editing if needed --> 'RWPS.WW3b.lakes.msh' +% INACTIVE (F) Examine mesh near New Orleans where boundary has been merged to reflect new marine zones --> 'RWPS.WW3c.lakes.msh' +% INACTIVE (G) Remove sand points that can be created (rarely) with New Orleans editing --> 'RWPS.WW3d.lakes.msh' +% (H) Stretch open ocean boundary nodes back to origonal specified boundary rectangle --> 'RWPS.WW3e.lakes.msh' +% this is an artificat of the projection used in jigsaw +% (I) Remove sand points that can be created (Should not matter) with boundary node stretching --> 'RWPS.WW3f.lakes.msh' +% (J) Write final WW3 mesh --> 'RWPS.WW3g.lakes.msh' +% this is the mesh to run WW3 on. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Input file from jigsaw and boundary file used in it's creation: + +SetPath +isplot=0; +outdir='NWcoastral/' +pslgfile=PSLGfile, %global variable filename set in SetPath + +jigsawout='RWPS.F.LLH' + +WW3FileOut='NWcoastal.WW3.msh' + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (A) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +g=loadmsh([outdir,jigsawout,'.msh']); + +%remove sand points on boundary + +RemoveSandPoints([outdir,jigsawout,'.msh'],pslgfile,[outdir,jigsawout,'.NSP.msh'],[outdir,jigsawout,'.NSP.WW3.msh']); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (B) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); +g.x=LonCon(g.x); + +if isplot, + LS=ComputeLengthScale_wgs84_MEL(x,y,e);LSn=Ele2Nodes(x,y,e,LS); + clf;ph=patch(x(e'),y(e'),LSn(e'));cm=colormap('jet');shading interp;axis equal; + caxis([0,12]) + colormap(flip(cm)); +end + +WriteWW3MeshX(g,'RWPS.WW3a.msh'); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (C) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%clear +g=loadmshWW3('RWPS.WW3a.msh') +%Remove key islands remaining in mesh that are present in the PSLG file + +p=loadmsh(pslgfile); + +p.x=p.point.coord(:,1); +p.y=p.point.coord(:,2); +p.edges=p.edge2.index(:,1:2); +p.x=LonCon(p.x); +x=g.x;y=g.y;z=g.z;e=g.e; + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e'));cm=colormap('jet');shading interp;axis equal; + hold on + plot(p.x,p.y,'k.') +end + +MinBndDist=1000; +gnew=g; + +%go through all longitude and remove nodes +dx=2; +dxb=10 +%close all +RemoveIsl=1; +n=1 +if RemoveIsl, + for xx=(ceil(min(g.x))+dxb):dx:(floor(max(g.x))-dxb) + ax11=[xx-dx,xx+dx,min(g.y)+dxb,max(g.y)-dxb] + N(n)=length(gnew.x); + AX(n,:)=ax11; + gnew=RemoveMissingIslandsEle(gnew,ax11,p,MinBndDist,0); + n=n+1; + length(gnew.x) + %figure(3);clf;plot(N,'ko-');pause(.001) + end +end + +g=gnew + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (D) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +g=RemoveSandPointsWW3(g,'RWPS.WW3a1.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (H) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Fix boundary warping from projection in mesh generation +%clear +close all +g=loadmshWW3('RWPS.WW3a1.msh') +g0=g; + +Blon=[round(min(g.x)),round(max(g.x))] +Blat=[round(min(g.y)),round(max(g.y))] +Blon=LonCon(Blon); + +x=g.x;y=g.y;z=g.z;e=g.e; +jb=g.bnd; +bnd0=detbndy(g.e) + +if isplot, + clf;ph=patch(x(e'),y(e'),z(e')); + cm=colormap('jet');shading interp;hold on + colormap(flip(cm)); + axis equal;hold on + plot(g.x(jb),g.y(jb),'k.');hold on +end +js=find(g.y(jb)max(Blat)); +g.y(jb(js))=max(Blat); +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end + +%dx=degree latitude delta to discriminate land points near boundary from open ocean boundary +dx=.05; +js=find(and( g.x(jb)>min(Blon),g.x(jb)max(Blon)-dx )); +g.x(jb(js))=max(Blon); +if isplot,plot(g.x(jb(js)),g.y(jb(js)),'r.');end +WriteWW3MeshX(g,'RWPS.WW3b.msh') + +%confirm no introduction of sand points +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (I) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +g0=RemoveSandPointsWW3(g,'RWPS.WW3c.msh') + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% STEP (J) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +WriteWW3MeshX(g0,WW3FileOut); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m index a816697..cf28f27 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m @@ -42,16 +42,15 @@ %g=loadmshWW3('RWPSMeshOSMxGSHHS.BoxesFiles/RWPS.F.LLH.NSP.WW3.msh'); g=loadmshWW3( [outdir,jigsawout,'.NSP.WW3.msh']); g.x=LonCon(g.x); -LakeDir='/mnt/sda/keston/RWPSLakes/' -%LakeDir='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/' + +%LakeDir='/mnt/sda/keston/RWPSLakes/' +LakeDir='/scratch3/NCEPDEV/climate/Keston.Smith/RWPS/RWPSLakes/' + gS=loadmshWW3([LakeDir,'Sebago.NWPS.WW3.msh']); -%gS.x=gS.x-360; gS.x=LonCon(gS.x); gW=loadmshWW3([LakeDir,'Winnipesaukee.NWPS.WW3.msh']) -%gW.x=gW.x-360; gW.x=LonCon(gW.x); gO=loadmshWW3([LakeDir,'Okeechobee.NWPS.WW3.msh']) -%gO.x=gO.x-360; gO.x=LonCon(gO.x); g=CombineMesh(g,gO); diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m index 1b9898f..9af823d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m @@ -2,9 +2,21 @@ SetPath -%MakeCoastalBoundariesGSHHS +MakeCoastalBoundariesGSHHS %BuildBoundaryPSLGwGSHHS -MakeDfunGSHHS +%MakeDfunGSHHS +SetPath +lonWest=129.91;lonEast=10.71;latSouth=-30.42;latNorth=79.99; +CoastLineFile = 'GlobalCoastlineGSHHS.shp' +BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) + +%TargetShap=uscl; %Shapefile with points of interest +%DX=.1; %lat/lon grid resolution for jigsaw inputs +%[xpi,ypi]=ExtraPointsOfIntrest; %Define points of interest for distance function not in TargetShape file +%MakeDistanceToCoastData(DX,TargetShape,xpi,ypi) %use for local meshes that don't span the international dateline + +%use this for RWPS to deal with international dateline discontinuity. +MakeDistanceToCoastRWPS diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m new file mode 100644 index 0000000..77ee015 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m @@ -0,0 +1,12 @@ + +SetPath + +MakeCoastalBoundariesOSM.m +lonWest=-128;lonEast=-121; +latSouth=45;latNorth=51; +CoastLineFile = 'GlobalCoastlineOSM.shp' +BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +%[xpi,ypi]=ExtraPointsOfIntrest; +TargetShap=uscl; +DX=.0125; +MakeDistanceToCoastData(DX,TargetShape,[],[]) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py new file mode 100644 index 0000000..e96fa91 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py @@ -0,0 +1,267 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- + +""" +#OSM coastline +PSLGFile="GlobalCoastlineOSM.PSLG.msh" +DistanceToCoastFile="DFun.GlobalCoastlineOSM.PSLG.msh" +TopographyFile="Topo.DFun.GlobalCoastlineOSM.PSLG.msh" +""" + +#GSSH coastline +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="DFun.GlobalCoastlineGSHHS.PSLG.msh" + +""" +# GSHHS except identified problem spots (i.e. American Samoa) where OSM is used +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="Topo.DFun.PSLGboundaryOSMxGSHHS.BOXES.msh" +""" + +# directory to write output files to +OutDir='testRWPS.GSHHS/' + +ww3_mesh_file='RWPS.GSHHS.WW3.msh' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=10000. +d1=320000. - d0 +beta=1000. +Smin=0.5 +Smax=10. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "jcfg.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job index ae23550..29b97c1 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job @@ -6,7 +6,7 @@ #SBATCH --mem-per-cpu=256000mb # Memory per processor #SBATCH --time=08:00:00 # Time limit hrs:min:sec #SBATCH --output=mpi_test_%j.log # Standard output/error -#SBATCH --exclusive=user +##SBATCH --exclusive=user #SBATCH --error=%j.err ##SBATCH --partition=marine-cpu #SBATCH --account=marine-cpu @@ -29,4 +29,5 @@ module load py-netcdf4/1.7.1.post2 source /scratch3/NCEPDEV/climate/Keston.Smith/UrsaMeshgenEnv/jigsawenv/bin/activate pip list -v -python3 RWPSMeshGenScript.py > NonGlobalMeshGen.out.txt +##python3 RWPSMeshGenScript.py > NonGlobalMeshGen.out.txt +python3 RWPSMeshGenScript.GSHHS.py > RWPSMeshGenScript.GSHHS.out From ceb89f1c0de0739d909327c14090ebd1c8f6466c Mon Sep 17 00:00:00 2001 From: kestonsmith-noaa Date: Wed, 11 Feb 2026 16:09:21 +0000 Subject: [PATCH 42/44] Added paths for local mesh generation example to SetPath --- ...ProcessGrid.NWcoastal.m => PostProcessGrid_NWcoastal.m} | 0 .../RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) rename unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/{PostProcessGrid.NWcoastal.m => PostProcessGrid_NWcoastal.m} (100%) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.NWcoastal.m rename to unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m index 51764ab..177c17f 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m @@ -3,9 +3,6 @@ addpath ../matlab/jigsaw-matlab addpath ../matlab/inpoly -%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/jigsaw-matlab -%addpath /scratch3/NCEPDEV/climate/Keston.Smith/MeshGenMatlabLibs/InsidePoly - % set global variables defining paths to different data sets global GlobalTopoFile uscl gcfl gcflGSHHS gcflOSM PSLGfile @@ -28,3 +25,7 @@ %Output file from BuildBoundaryPSLGwGSHHS and input to MakeDfunGSHHS PSLGfile='GlobalCoastlineGSHHS.PSLG.msh' +%For NWcoastal mesh uncomment the following lines +%gcfl=gcflOSM +%PSLGfile='NWcoastal.PSLG.msh' + From b77a507ee119ca48b20195dbca3343520c5795bb Mon Sep 17 00:00:00 2001 From: keston Date: Wed, 11 Feb 2026 13:29:11 -0500 Subject: [PATCH 43/44] changes related to update of OSM coastline data. Fixed typo in file name, and added all nescesarry files for local mesh example --- .../DownloadShapeFiles.sh | 3 +- .../MakeCoastalBoundariesOSM.m | 51 ++-- .../MeshGenScript.NWcoastal.py | 248 ++++++++++++++++++ .../PostProcessGrid_NWcoastal.m | 2 +- .../PreProcessCoastline_NWCoastalMesh.m | 8 +- .../RWPSMeshGenScript.NWcoastal.py | 248 ++++++++++++++++++ .../matlab/BuildBoundaryPSLGfunction.m | 4 +- .../RWPSMeshtoolkit/matlab/InterpCoastline.m | 5 +- 8 files changed, 540 insertions(+), 29 deletions(-) create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py create mode 100644 unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh index af193a2..668d9eb 100755 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh @@ -13,7 +13,8 @@ wget --output-document tl_2023_us_coastline.zip https://www2.census.gov/geo/tige echo "Downloading Global Self-consistent, Hierarchical, High-resolution Shorelines (GSHHS)" #GSHHG global coastline data -wget --output-document gshhg-shp-2.3.7.zip http://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip +#wget --output-document gshhg-shp-2.3.7.zip http://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip +wget --output-document gshhg-shp-2.3.7.zip https://www.ngdc.noaa.gov/mgg/shorelines/data/gshhg/latest/gshhg-shp-2.3.7.zip echo "Downloading OpenStreetMap shoreline (OSM)" #OSM global coastline data diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m index 8dc6c24..aa2539d 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m @@ -69,8 +69,13 @@ for k=1:N x=S(k).X(1:end-2);%unique* points - x=LonCon(x); y=S(k).Y(1:end-2); +%deal with "messy" OpenStreetMap coasts + jb=find(isnan(x+y)); + if ~isempty(jb) + x=x(1:[min(jb)-1]); + y=y(1:[min(jb)-1]);%truncate coastline at first discontinuity + end zz=x+i*y; [zzu,j]=unique(zz);%find unique points before end j=sort(j); @@ -78,28 +83,32 @@ x=x(j); y=y(j); end - x=[x,x(1)];%close loop - y=[y,y(1)]; - [xs,ys]=SmoothSubSampleCoastlineFast(x,y,50.,10);%500 m coastline - - zs=xs+i*ys; - dz=abs(zs(2:end)-zs(1:end-1)); - j=find(dz>1); - if length(j)>0 - ji=1:j(1); - xs=xs(ji);ys=ys(ji); - end + + if length(x)>2 + x=[x,x(1)];%close loop + y=[y,y(1)]; + [xs,ys]=SmoothSubSampleCoastlineFast(x,y,50.,10);%500 m coastline + + zs=xs+i*ys; + dz=abs(zs(2:end)-zs(1:end-1)); + j=find(dz>1); + if length(j)>0 + ji=1:j(1); + xs=xs(ji);ys=ys(ji); + end - if length(xs)>2, - n=n+1; - S0(n).X=[xs(:);NaN]'; - S0(n).Y=[ys(:);NaN]'; - S0(n).X0=S(n).X; - S0(n).Y0=S(n).Y; - S0(n).area = areaint(ys,xs,earth) / 10^6; - S0(n).perim=sum( deg2km*abs( cos(deg2rad*mean(ys))*( xs(2:end)-xs(1:end-1) ) + i*(ys(2:end)-ys(1:end-1)) ) ); - S0(n).Geometry=S(k).Geometry; + if length(xs)>2, + n=n+1; + S0(n).X=[xs(:);NaN]'; + S0(n).Y=[ys(:);NaN]'; + S0(n).X0=S(n).X; + S0(n).Y0=S(n).Y; + S0(n).area = areaint(ys,xs,earth) / 10^6; + S0(n).perim=sum( deg2km*abs( cos(deg2rad*mean(ys))*( xs(2:end)-xs(1:end-1) ) + i*(ys(2:end)-ys(1:end-1)) ) ); + S0(n).Geometry=S(k).Geometry; + end end + if mod(k,1000)==0, disp(['progress a:', num2str( sum(ns(1:k)) / sum(ns) ), ', progress b:', num2str( k/N )]); end diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py new file mode 100644 index 0000000..55a6cd8 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py @@ -0,0 +1,248 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- + +#GSSH coastline +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="NWcoastal.PSLG.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.NWcoastal.PSLG.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="Topo.DFun.NWcoastal.PSLG.msh" + +# directory to write output files to +OutDir='NWcoastal/' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=10000. +d1=320000. - d0 +beta=1000. +Smin=0.5 +Smax=10. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "jcfg.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m index 88b4860..26c8472 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m @@ -21,7 +21,7 @@ SetPath isplot=0; -outdir='NWcoastral/' +outdir='NWcoastal/' pslgfile=PSLGfile, %global variable filename set in SetPath jigsawout='RWPS.F.LLH' diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m index 77ee015..574d7d2 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m @@ -1,12 +1,12 @@ SetPath -MakeCoastalBoundariesOSM.m +MakeCoastalBoundariesOSM lonWest=-128;lonEast=-121; latSouth=45;latNorth=51; CoastLineFile = 'GlobalCoastlineOSM.shp' -BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth) +BuildBoundaryPSLGfunction(CoastLineFile,lonWest,lonEast,latSouth,latNorth,PSLGfile) %[xpi,ypi]=ExtraPointsOfIntrest; -TargetShap=uscl; +TargetShape=uscl;% US coastline as target for distance DX=.0125; -MakeDistanceToCoastData(DX,TargetShape,[],[]) +MakeDistanceToCoastData(DX,uscl,[],[]) diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py new file mode 100644 index 0000000..a54a248 --- /dev/null +++ b/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py @@ -0,0 +1,248 @@ + +import os +import argparse +import time +import numpy as np +import netCDF4 as nc + +import jigsawpy + +from scipy.interpolate import RegularGridInterpolator + +#-------------------Input Files---------------------------------------- + +#GSSH coastline +#jigsaw .msh format Planer Straight Line Graph defining mesh outer boundary and coastline +PSLGFile="NWcoastal.PSLG.msh" +#jigsaw gridded .msh format Distance to taget poings +DistanceToCoastFile="DFun.NWcoastal.PSLG.msh" +#jigsaw gridded .msh format topography on same grid as distance +TopographyFile="Topo.DFun.NWcoastal.PSLG.msh" + +# directory to write output files to +OutDir='NWcoastal/' + +#-------------------Paramter Inputs------------------------------------ +#parameters for specifying resolution +d0=25000. +d1=320000. - d0 +beta=250. +Smin=0.25 +Smax=7. + +#-------------------Main Program--------------------------------------- + +# Create the output directory------------------------------------------ +try: + os.mkdir(OutDir) + print(f"Directory '{OutDir}' created successfully.") +except FileExistsError: + print(f"Directory '{OutDir}' already exists. Proceeding ...") +except PermissionError: + print(f"Permission denied: Unable to create '{OutDir}'.") + +# Setup jigsaw structures---------------------------------------------- +opts = jigsawpy.jigsaw_jig_t() +topo = jigsawpy.jigsaw_msh_t() #topographic database +dist = jigsawpy.jigsaw_msh_t() #distance to US coastline in meters +geom = jigsawpy.jigsaw_msh_t() +mesh = jigsawpy.jigsaw_msh_t() +meshR3 = jigsawpy.jigsaw_msh_t() +hmat = jigsawpy.jigsaw_msh_t() +proj = jigsawpy.jigsaw_prj_t() + +opts.geom_file = "geom.msh" +opts.jcfg_file = "jcfg.jig" +opts.mesh_file = "mesh.msh" +opts.hfun_file = "spac.msh" + +# load input data------------------------------------------------------ +jigsawpy.loadmsh(PSLGFile, geom) +jigsawpy.loadmsh(DistanceToCoastFile, dist) +jigsawpy.loadmsh(TopographyFile, topo) + +# truncate data to bounding rectangle of input PSLG-------------------- +xmin = np.min( geom.point["coord"][:, 0]) +ymin = np.min( geom.point["coord"][:, 1]) +xmax = np.max( geom.point["coord"][:, 0]) +ymax = np.max( geom.point["coord"][:, 1]) + +tv = topo.value +dv = dist.value + +xmsk = np.logical_and( topo.xgrid > xmin , topo.xgrid < xmax ) +ymsk = np.logical_and( topo.ygrid > ymin , topo.ygrid < ymax ) + +tv = tv[:, xmsk] +tv = tv[ymsk, :] +dv = dv[:, xmsk] +dv = dv[ymsk, :] + +# define spatial resolution shape function----------------------------- +W=np.exp(- (np.abs(dv-d0) / d1) - (np.abs(tv) / beta) ) +W[ np.where(dv < d0 ) ] = 1. + +# build resolution specification gridded data structure, hmat---------- +hmat=topo +hmat.value=Smax - (Smax - Smin)*W + +hmat.mshID = "ellipsoid-grid" +hmat.radii = np.full( +3, +6371.0, dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +hmat.xgrid = hmat.xgrid[xmsk] * np.pi / 180. +hmat.ygrid = hmat.ygrid[ymsk] * np.pi / 180. + +hmat.value = np.maximum(hmat.value, Smin)#should not be nescesary +hmat.value = np.minimum(hmat.value, Smax) + +hmat.slope = np.full( hmat.value.shape, +0.1500 , dtype=jigsawpy.jigsaw_msh_t.REALS_t) + +#------------------------------------ do stereographic proj. +geom.point["coord"][:, :] *= np.pi / 180. + +proj.prjID = 'stereographic' +proj.radii = +6.371E+003 +proj.xbase = +0.500 * (xmin + xmax) * np.pi / 180. +proj.ybase = +0.500 * (ymin + ymax) * np.pi / 180. + +jigsawpy.savemsh(OutDir+"HFUN.msh", hmat) + +jigsawpy.project(geom, proj, "fwd") +jigsawpy.project(hmat, proj, "fwd") + +jigsawpy.savemsh(opts.geom_file, geom) +jigsawpy.savemsh(opts.hfun_file, hmat) + +# save hmat------------------------------------------------------------ +jigsawpy.savemsh(OutDir+"HFUNproj0.msh", hmat) + +#smooth hmat +jigsawpy.cmd.marche(opts, hmat) + +# save smoothed hmat--------------------------------------------------- +jigsawpy.savemsh(OutDir+"HFUNproj1.msh", hmat) + +# make mesh using JIGSAW----------------------------------------------- +opts.hfun_scal = "absolute" +opts.hfun_hmax = float("inf") # null HFUN limits +opts.hfun_hmin = float(+0.00) +#opts.hfun_hmax = 1.25*Smax # Unintended effects, better off null +#opts.hfun_hmin = .5*Smin + +opts.mesh_dims = +2 # 2-dim. simplexes +opts.mesh_eps1 = +1. + +#opts.mesh_top1 = "true" !!!No convergece + + +ttic = time.time() + +jigsawpy.cmd.jigsaw(opts, mesh) + +ttoc = time.time() + +print("CPUSEC =", (ttoc - ttic)) + +# save mesh in JIGSAW native projection based on input PSLG------------ +jigsawpy.savemsh(OutDir+"/RWPS.PROJ.msh",mesh) + +# compute costa functions and save +cost = jigsawpy.triscr2(mesh.point["coord"],mesh.tria3["index"]) +np.savetxt(OutDir+"TriScr2.txt",cost,"%f") +print("TRISCR =", np.min(cost), np.mean(cost)) + +cost = jigsawpy.pwrscr2(mesh.point["coord"], mesh.power, mesh.tria3["index"]) +np.savetxt(OutDir+"PwrScr2.txt",cost,"%f") +print("PWRSCR =", np.min(cost), np.mean(cost)) + +tbad = jigsawpy.centre2(mesh.point["coord"],mesh.power,mesh.tria3["index"]) +print("OBTUSE =",+np.count_nonzero(np.logical_not(tbad))) + + +# project mesh nodes to radian lat, lon +jigsawpy.project(mesh, proj, "inv") # This used to work +#jigsawpy.savemsh("RWPS.radian.msh",mesh) + +# transform mesh nodes to degree lat, lon +mesh.point["coord"][:, :] = mesh.point["coord"][:, :]*180. / np.pi + +# save mesh in degree lat, lon system +jigsawpy.savemsh(OutDir+"RWPS.LL.msh",mesh) + +# create jigsaw R3 mesh on global surface and save to +S2=mesh.point["coord"][:,[0,1]] +S2=S2*np.pi/180. + +R3=jigsawpy.S2toR3(mesh.radii,S2) +#np.savetxt("R3.txt",R3," %f ") # save 3D nodes + +meshR3 = jigsawpy.jigsaw_msh_t() +mesh.mshID = 'ellipsoid-mesh' +meshR3.tria3=mesh.tria3 +meshR3.ndims=3 +#make 3D coordinates +nd=R3.shape +meshR3.vert3 = np.zeros(nd[0], dtype=mesh.VERT3_t) +meshR3.vert3["coord"] = R3 +jigsawpy.savemsh(OutDir+"RWPS.R3.msh",meshR3) + + +# Now apply filters and output in WW3 form +# import FilterRoutines.py + +from FilterRoutinesNM import * + +#replace mesh with R3 mesh, mesh->mesh R3 +jigsawpy.loadmsh(OutDir+"RWPS.R3.msh", mesh) # uncomment if starting here + +opts.geom_file = "geom.msh" #saves the geometry info for jigsaw +opts.jcfg_file = "opts.jig" #jigsaw ctlr file + + +geom.mshID = "ellipsoid-mesh" +geom.radii = np.full(3, 6.371E+003, dtype=geom.REALS_t) + +jigsawpy.savemsh(opts.geom_file, geom) + +inject_dem() +filter_ocn() + +jigsawpy.savemsh(OutDir+"RWPS.F.R3.msh", mesh) + +# viz. in eg. paraview +jigsawpy.savevtk(OutDir+"test.vtk", mesh) + +# convert to lon lat +point = mesh.point["coord"] +point = jigsawpy.R3toS2(geom.radii, point) +point*= 180. / np.pi + +depth = np.reshape(-1*mesh.value, (mesh.value.size, 1)) +depth[depth <= 0] = 2 +point = np.hstack((point, depth)) # append elev. as 3rd coord. +cells = [("triangle", mesh.tria3["index"])] +tri_data=cells[0][1]+1 + +#put coordinates in non standard format to avoid international date line +lon=point[:,0] +lon[np.where(lon>90)]=lon[np.where(lon>90)]-360 +point[:,0]=lon + +write_gmsh_mesh(OutDir+"RWPS.ww3", point, tri_data) + +mesh.point["coord"]=point +jigsawpy.savemsh(OutDir+"RWPS.F.LLH.msh", mesh) + + +#write final mesh in jigsaw .msh format +meshR2 = jigsawpy.jigsaw_msh_t() +#make 2D coordinates +nd=point.shape +meshR2.ndims=2 +meshR2.vert2 = np.zeros(nd[0], dtype=mesh.VERT2_t) +meshR2.vert2["coord"] = point[:,[0,1]] +meshR2.tria3=mesh.tria3 +meshR2.mshID=mesh.mshID + +jigsawpy.savemsh(OutDir+"RWPS.F.LL.msh", meshR2) + diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m index 1d3ffce..cef964a 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m @@ -31,7 +31,9 @@ function BuildBoundaryPSLGfunctionLC(CoastLineFile,lonWest,lonEast,latSouth,latN S=shaperead(CoastLineFile) if nargin<6 - FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] + SetPath + FileOutJigsaw=PSLGfile + %FileOutJigsaw=[CoastLineFile(1:end-4),'.PSLG.msh'] end FileOutMatlab=[CoastLineFile(1:end-4),'.PSLGtmp.mat'] isplot=0; diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m b/unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m index 156b97f..bf38c35 100644 --- a/unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m +++ b/unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m @@ -28,7 +28,10 @@ d=[0,cumsum(d)];%distance di=d(1):dsmooth:d(end); if itz,z(j)=NaN;end -zi=interp1(d,z,di); +%zi=interp1(d,z,di); +[du,ju]=unique(d); +ju=sort(ju); +zi=interp1(d(ju),z(ju),di);%degenerate cases in OSM Antarctica if isisland zi=[zi,zi(1)]; end From 24bb96785aa783fe819c1a5ad0a5260bd2d6ea0d Mon Sep 17 00:00:00 2001 From: keston Date: Thu, 12 Feb 2026 15:52:48 -0500 Subject: [PATCH 44/44] renamed RWPSMeshtoolkit as regional, within unst_msh_gen --- .../InterpolateBathymetry/AddBathyToMesh.py | 0 .../InterpolateBathymetry/DivideMeshNodes.py | 0 .../InterpolateBathymetry/DowloadBathyData.sh | 0 .../InterpolateBathymetry/FiniteElementMeshRoutines.py | 0 .../InterpolateBathymetry/GaussMarkov.py | 0 .../InterpolateBathymetry/InterpolateCRM.partscat.py | 0 .../InterpolateBathymetry/KnitOutputBackTogether.py | 0 .../InterpolateBathymetry/MakeCommonNetCDFFileFormat.py | 0 .../InterpolateBathymetry/README.txt | 0 .../InterpolateBathymetry/SmoothSubsampleCMEMS.py | 0 .../InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py | 0 .../InterpolateBathymetry/meshes/HawaiiTest.msh | 0 .../MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m | 0 .../MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m | 0 .../MeshGenTemplateDirectory/DownloadShapeFiles.sh | 0 .../MeshGenTemplateDirectory/ExtraPointsOfIntrest.m | 0 .../MeshGenTemplateDirectory/FilterRoutinesNM.py | 0 .../MeshGenTemplateDirectory/LonCon.m | 0 .../MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m | 0 .../MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m | 0 .../MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m | 0 .../MeshGenTemplateDirectory/MakeDfunGSHHS.m | 0 .../MeshGenTemplateDirectory/MakeDfunOSM.m | 0 .../MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m | 0 .../MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m | 0 .../MeshGenTemplateDirectory/MakeRWPSMesh.m | 0 .../MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m | 0 .../MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m | 0 .../MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py | 0 .../MeshGenTemplateDirectory/PostProcessGrid.m | 0 .../MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m | 0 .../MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m | 0 .../MeshGenTemplateDirectory/PreProcessCoastline.m | 0 .../MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m | 0 .../MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py | 0 .../MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py | 0 .../MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py | 0 .../RWPSMeshGenScript.OSMxGSSHS.NewOrl.py | 0 .../MeshGenTemplateDirectory/RWPSMeshGenScript.py | 0 .../MeshGenTemplateDirectory/SetPath.m | 0 .../MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job | 0 .../MeshGenTemplateDirectory/jigsaw.ursa.job | 0 .../MeshGenTemplateDirectory/jobcard.matlab.postjigsaw | 0 .../jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl | 0 .../MeshGenTemplateDirectory/jobcard.matlab.prejigsaw | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/README.txt | 0 .../{RWPSMeshtoolkit => regional}/matlab/BoundaryShape2msh.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BoundingBox.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BoxSmoothTopo.m | 0 .../matlab/BuildBoundaryPSLGfunction.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/CombineMesh.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/ComputeAdjacency.m | 0 .../matlab/ComputeLengthScale_wgs84.m | 0 .../matlab/ComputeLengthScale_wgs84_MEL.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/DistanceToCoast.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/Ele2Nodes.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/EleArea.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/FindOuterBndNoPSLG.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/FindOuterBndWW3.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/FindPointsAx.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/GetMatlabLibs.sh | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/HandEditMesh.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/InterpCoastline.m | 0 .../matlab/MakeDistanceToCoastData.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/MergePslgsOSMxGSSHS.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/RemoveMeshParts.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/RemoveMissingIslands.m | 0 .../matlab/RemoveMissingIslandsEle.m | 0 .../matlab/RemoveMissingIslandsPoint.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/RemoveSandPoints.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/RemoveSandPointsWW3.m | 0 .../matlab/SmoothSubSampleCoastlineFast.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/WriteWW3Mesh.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/WriteWW3MeshX.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/detbndy.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/edges2chains.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/edges2chainsG.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/insidepoly.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/joinpslg.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/kprint.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/l.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/loadmshWW3.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/patch_global.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/pslg2geom.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/remove_dead_nodes.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/submeshFast.m | 0 .../{RWPSMeshtoolkit => regional}/matlab/submeshFastEle.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/subpslgFast.m | 0 unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/topo2msh.m | 0 .../python/ComputeDistanceToCoast/ComputeDistanceToCoast.py | 0 .../python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py | 0 .../python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py | 0 .../python/ComputeDistanceToCoast/ReadWriteCoast.py | 0 .../python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py | 0 .../python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py | 0 .../python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py | 0 96 files changed, 0 insertions(+), 0 deletions(-) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/AddBathyToMesh.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/DivideMeshNodes.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/DowloadBathyData.sh (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/FiniteElementMeshRoutines.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/GaussMarkov.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/InterpolateCRM.partscat.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/KnitOutputBackTogether.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/README.txt (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/SmoothSubsampleCMEMS.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/InterpolateBathymetry/meshes/HawaiiTest.msh (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/DownloadShapeFiles.sh (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/FilterRoutinesNM.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/LonCon.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeDfunGSHHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeDfunOSM.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MakeRWPSMesh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/PostProcessGrid.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/PreProcessCoastline.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/RWPSMeshGenScript.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/SetPath.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/jigsaw.ursa.job (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/README.txt (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BoundaryShape2msh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BoundingBox.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BoxSmoothTopo.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/BuildBoundaryPSLGfunction.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/CombineMesh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/ComputeAdjacency.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/ComputeLengthScale_wgs84.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/ComputeLengthScale_wgs84_MEL.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/DistanceToCoast.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/Ele2Nodes.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/EleArea.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/FindOuterBndNoPSLG.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/FindOuterBndWW3.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/FindPointsAx.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/GetMatlabLibs.sh (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/HandEditMesh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/InterpCoastline.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/MakeDistanceToCoastData.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/MergePslgsOSMxGSSHS.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveMeshParts.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveMissingIslands.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveMissingIslandsEle.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveMissingIslandsPoint.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveSandPoints.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/RemoveSandPointsWW3.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/SmoothSubSampleCoastlineFast.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/WriteWW3Mesh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/WriteWW3MeshX.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/detbndy.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/edges2chains.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/edges2chainsG.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/insidepoly.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/joinpslg.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/kprint.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/l.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/loadmshWW3.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/patch_global.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/pslg2geom.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/remove_dead_nodes.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/submeshFast.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/submeshFastEle.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/subpslgFast.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/matlab/topo2msh.m (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/ReadWriteCoast.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py (100%) rename unst_msh_gen/{RWPSMeshtoolkit => regional}/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py (100%) diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py b/unst_msh_gen/regional/InterpolateBathymetry/AddBathyToMesh.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/AddBathyToMesh.py rename to unst_msh_gen/regional/InterpolateBathymetry/AddBathyToMesh.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py b/unst_msh_gen/regional/InterpolateBathymetry/DivideMeshNodes.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DivideMeshNodes.py rename to unst_msh_gen/regional/InterpolateBathymetry/DivideMeshNodes.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh b/unst_msh_gen/regional/InterpolateBathymetry/DowloadBathyData.sh similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/DowloadBathyData.sh rename to unst_msh_gen/regional/InterpolateBathymetry/DowloadBathyData.sh diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py b/unst_msh_gen/regional/InterpolateBathymetry/FiniteElementMeshRoutines.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/FiniteElementMeshRoutines.py rename to unst_msh_gen/regional/InterpolateBathymetry/FiniteElementMeshRoutines.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py b/unst_msh_gen/regional/InterpolateBathymetry/GaussMarkov.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/GaussMarkov.py rename to unst_msh_gen/regional/InterpolateBathymetry/GaussMarkov.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py b/unst_msh_gen/regional/InterpolateBathymetry/InterpolateCRM.partscat.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/InterpolateCRM.partscat.py rename to unst_msh_gen/regional/InterpolateBathymetry/InterpolateCRM.partscat.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py b/unst_msh_gen/regional/InterpolateBathymetry/KnitOutputBackTogether.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/KnitOutputBackTogether.py rename to unst_msh_gen/regional/InterpolateBathymetry/KnitOutputBackTogether.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py b/unst_msh_gen/regional/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py rename to unst_msh_gen/regional/InterpolateBathymetry/MakeCommonNetCDFFileFormat.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt b/unst_msh_gen/regional/InterpolateBathymetry/README.txt similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/README.txt rename to unst_msh_gen/regional/InterpolateBathymetry/README.txt diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleCMEMS.py b/unst_msh_gen/regional/InterpolateBathymetry/SmoothSubsampleCMEMS.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleCMEMS.py rename to unst_msh_gen/regional/InterpolateBathymetry/SmoothSubsampleCMEMS.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py b/unst_msh_gen/regional/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py rename to unst_msh_gen/regional/InterpolateBathymetry/SmoothSubsampleNetCDFFiles.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/meshes/HawaiiTest.msh b/unst_msh_gen/regional/InterpolateBathymetry/meshes/HawaiiTest.msh similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/InterpolateBathymetry/meshes/HawaiiTest.msh rename to unst_msh_gen/regional/InterpolateBathymetry/meshes/HawaiiTest.msh diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/BuildBoundaryPSLGwGSHHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/BuildBoundaryPSLGwOSM.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh b/unst_msh_gen/regional/MeshGenTemplateDirectory/DownloadShapeFiles.sh similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/DownloadShapeFiles.sh rename to unst_msh_gen/regional/MeshGenTemplateDirectory/DownloadShapeFiles.sh diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/ExtraPointsOfIntrest.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/FilterRoutinesNM.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/FilterRoutinesNM.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/FilterRoutinesNM.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/LonCon.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/LonCon.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/LonCon.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeBoundaryForcingNodes.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeCoastalBoundariesGSHHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeCoastalBoundariesOSM.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunGSHHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunGSHHS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunGSHHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunOSM.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSM.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunOSM.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDfunOSMxGSHHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeDistanceToCoastRWPS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MakeRWPSMesh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MakeRWPSMesh.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MakeRWPSMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MergePslgsOSMxGSSHS_14N230W.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/MeshGenScript.NWcoastal.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid_NWcoastal.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/PostProcessGrid_OSMxGSHHS_NewOrl.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/PreProcessCoastline.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/PreProcessCoastline.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/PreProcessCoastline_NWCoastalMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/RWPS.ng.NoFiltrsOpts.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.GSHHS.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.NWcoastal.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.OSMxGSSHS.NewOrl.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py b/unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/RWPSMeshGenScript.py rename to unst_msh_gen/regional/MeshGenTemplateDirectory/RWPSMeshGenScript.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m b/unst_msh_gen/regional/MeshGenTemplateDirectory/SetPath.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/SetPath.m rename to unst_msh_gen/regional/MeshGenTemplateDirectory/SetPath.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job b/unst_msh_gen/regional/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job rename to unst_msh_gen/regional/MeshGenTemplateDirectory/jigsaw.ursa.NewOrl.job diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job b/unst_msh_gen/regional/MeshGenTemplateDirectory/jigsaw.ursa.job similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jigsaw.ursa.job rename to unst_msh_gen/regional/MeshGenTemplateDirectory/jigsaw.ursa.job diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw b/unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw rename to unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl b/unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl rename to unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.postjigsaw.OSMxGSHHS.NewOrl diff --git a/unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw b/unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw rename to unst_msh_gen/regional/MeshGenTemplateDirectory/jobcard.matlab.prejigsaw diff --git a/unst_msh_gen/RWPSMeshtoolkit/README.txt b/unst_msh_gen/regional/README.txt similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/README.txt rename to unst_msh_gen/regional/README.txt diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m b/unst_msh_gen/regional/matlab/BoundaryShape2msh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/BoundaryShape2msh.m rename to unst_msh_gen/regional/matlab/BoundaryShape2msh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m b/unst_msh_gen/regional/matlab/BoundingBox.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/BoundingBox.m rename to unst_msh_gen/regional/matlab/BoundingBox.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m b/unst_msh_gen/regional/matlab/BoxSmoothTopo.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/BoxSmoothTopo.m rename to unst_msh_gen/regional/matlab/BoxSmoothTopo.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m b/unst_msh_gen/regional/matlab/BuildBoundaryPSLGfunction.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/BuildBoundaryPSLGfunction.m rename to unst_msh_gen/regional/matlab/BuildBoundaryPSLGfunction.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m b/unst_msh_gen/regional/matlab/CombineMesh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/CombineMesh.m rename to unst_msh_gen/regional/matlab/CombineMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m b/unst_msh_gen/regional/matlab/ComputeAdjacency.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeAdjacency.m rename to unst_msh_gen/regional/matlab/ComputeAdjacency.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m b/unst_msh_gen/regional/matlab/ComputeLengthScale_wgs84.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84.m rename to unst_msh_gen/regional/matlab/ComputeLengthScale_wgs84.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m b/unst_msh_gen/regional/matlab/ComputeLengthScale_wgs84_MEL.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/ComputeLengthScale_wgs84_MEL.m rename to unst_msh_gen/regional/matlab/ComputeLengthScale_wgs84_MEL.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m b/unst_msh_gen/regional/matlab/DistanceToCoast.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/DistanceToCoast.m rename to unst_msh_gen/regional/matlab/DistanceToCoast.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m b/unst_msh_gen/regional/matlab/Ele2Nodes.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/Ele2Nodes.m rename to unst_msh_gen/regional/matlab/Ele2Nodes.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m b/unst_msh_gen/regional/matlab/EleArea.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/EleArea.m rename to unst_msh_gen/regional/matlab/EleArea.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m b/unst_msh_gen/regional/matlab/FindOuterBndNoPSLG.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndNoPSLG.m rename to unst_msh_gen/regional/matlab/FindOuterBndNoPSLG.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndWW3.m b/unst_msh_gen/regional/matlab/FindOuterBndWW3.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/FindOuterBndWW3.m rename to unst_msh_gen/regional/matlab/FindOuterBndWW3.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m b/unst_msh_gen/regional/matlab/FindPointsAx.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/FindPointsAx.m rename to unst_msh_gen/regional/matlab/FindPointsAx.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/GetMatlabLibs.sh b/unst_msh_gen/regional/matlab/GetMatlabLibs.sh similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/GetMatlabLibs.sh rename to unst_msh_gen/regional/matlab/GetMatlabLibs.sh diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/HandEditMesh.m b/unst_msh_gen/regional/matlab/HandEditMesh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/HandEditMesh.m rename to unst_msh_gen/regional/matlab/HandEditMesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m b/unst_msh_gen/regional/matlab/InterpCoastline.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/InterpCoastline.m rename to unst_msh_gen/regional/matlab/InterpCoastline.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDistanceToCoastData.m b/unst_msh_gen/regional/matlab/MakeDistanceToCoastData.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/MakeDistanceToCoastData.m rename to unst_msh_gen/regional/matlab/MakeDistanceToCoastData.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m b/unst_msh_gen/regional/matlab/MergePslgsOSMxGSSHS.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/MergePslgsOSMxGSSHS.m rename to unst_msh_gen/regional/matlab/MergePslgsOSMxGSSHS.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m b/unst_msh_gen/regional/matlab/RemoveMeshParts.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMeshParts.m rename to unst_msh_gen/regional/matlab/RemoveMeshParts.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m b/unst_msh_gen/regional/matlab/RemoveMissingIslands.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslands.m rename to unst_msh_gen/regional/matlab/RemoveMissingIslands.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m b/unst_msh_gen/regional/matlab/RemoveMissingIslandsEle.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsEle.m rename to unst_msh_gen/regional/matlab/RemoveMissingIslandsEle.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m b/unst_msh_gen/regional/matlab/RemoveMissingIslandsPoint.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveMissingIslandsPoint.m rename to unst_msh_gen/regional/matlab/RemoveMissingIslandsPoint.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m b/unst_msh_gen/regional/matlab/RemoveSandPoints.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPoints.m rename to unst_msh_gen/regional/matlab/RemoveSandPoints.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m b/unst_msh_gen/regional/matlab/RemoveSandPointsWW3.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/RemoveSandPointsWW3.m rename to unst_msh_gen/regional/matlab/RemoveSandPointsWW3.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m b/unst_msh_gen/regional/matlab/SmoothSubSampleCoastlineFast.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/SmoothSubSampleCoastlineFast.m rename to unst_msh_gen/regional/matlab/SmoothSubSampleCoastlineFast.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m b/unst_msh_gen/regional/matlab/WriteWW3Mesh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3Mesh.m rename to unst_msh_gen/regional/matlab/WriteWW3Mesh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m b/unst_msh_gen/regional/matlab/WriteWW3MeshX.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/WriteWW3MeshX.m rename to unst_msh_gen/regional/matlab/WriteWW3MeshX.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m b/unst_msh_gen/regional/matlab/detbndy.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/detbndy.m rename to unst_msh_gen/regional/matlab/detbndy.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m b/unst_msh_gen/regional/matlab/edges2chains.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chains.m rename to unst_msh_gen/regional/matlab/edges2chains.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m b/unst_msh_gen/regional/matlab/edges2chainsG.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/edges2chainsG.m rename to unst_msh_gen/regional/matlab/edges2chainsG.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/insidepoly.m b/unst_msh_gen/regional/matlab/insidepoly.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/insidepoly.m rename to unst_msh_gen/regional/matlab/insidepoly.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m b/unst_msh_gen/regional/matlab/joinpslg.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/joinpslg.m rename to unst_msh_gen/regional/matlab/joinpslg.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m b/unst_msh_gen/regional/matlab/kprint.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/kprint.m rename to unst_msh_gen/regional/matlab/kprint.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/l.m b/unst_msh_gen/regional/matlab/l.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/l.m rename to unst_msh_gen/regional/matlab/l.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m b/unst_msh_gen/regional/matlab/loadmshWW3.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/loadmshWW3.m rename to unst_msh_gen/regional/matlab/loadmshWW3.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m b/unst_msh_gen/regional/matlab/patch_global.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/patch_global.m rename to unst_msh_gen/regional/matlab/patch_global.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m b/unst_msh_gen/regional/matlab/pslg2geom.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/pslg2geom.m rename to unst_msh_gen/regional/matlab/pslg2geom.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m b/unst_msh_gen/regional/matlab/remove_dead_nodes.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/remove_dead_nodes.m rename to unst_msh_gen/regional/matlab/remove_dead_nodes.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m b/unst_msh_gen/regional/matlab/submeshFast.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFast.m rename to unst_msh_gen/regional/matlab/submeshFast.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m b/unst_msh_gen/regional/matlab/submeshFastEle.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/submeshFastEle.m rename to unst_msh_gen/regional/matlab/submeshFastEle.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m b/unst_msh_gen/regional/matlab/subpslgFast.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/subpslgFast.m rename to unst_msh_gen/regional/matlab/subpslgFast.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m b/unst_msh_gen/regional/matlab/topo2msh.m similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/matlab/topo2msh.m rename to unst_msh_gen/regional/matlab/topo2msh.m diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/ComputeDistanceToCoast.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/ComputeDistanceToCoastConv.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/FindUSadjacentGSHHSpoints.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/ReadWriteCoast.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/ReadWriteCoast.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/ReadWriteCoast.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndInterpCoastline.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastline.py diff --git a/unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py b/unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py similarity index 100% rename from unst_msh_gen/RWPSMeshtoolkit/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py rename to unst_msh_gen/regional/python/ComputeDistanceToCoast/SmoothAndSubsampleCoastlineP.py