! Copyright 2014 College of William and Mary ! ! Licensed under the Apache License, Version 2.0 (the "License"); ! you may not use this file except in compliance with the License. ! You may obtain a copy of the License at ! ! http://www.apache.org/licenses/LICENSE-2.0 ! ! Unless required by applicable law or agreed to in writing, software ! distributed under the License is distributed on an "AS IS" BASIS, ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ! See the License for the specific language governing permissions and ! limitations under the License. ! !**************************************************************************************** ! * ! Read in (x,y,z,time) from station.xyzt (z>=0 is distance from F.S.; time in sec) ! for 3D variables (surface values for 2D variables) DEFINED @ nodes or elem. Interpolation in time. ! Not working for lon/lat. ! Works for mixed tri/quad outputs, combined or uncombined nc outputs. ! Inputs: (1) nc files; ! (2) station.xyzt: make sure all times are after 1st record (to ensure interpolation in time); ! pad extra days before and after if necessary. ! z>=0 from surface. ! (3) screen inputs: varname; invalid value (for out of domain, dry etc) ! (4) vgrid.in: in this dir or ../ ! Outputs: fort.1[89]; fort.11 (fatal errors); fort.12: nonfatal errors. ! ! ifort -mcmodel=medium -CB -O2 -o read_output9_xyzt.exe ../UtilLib/extract_mod.f90 \ ! ../UtilLib/compute_zcor.f90 ../UtilLib/pt_in_poly_test.f90 read_output9_xyzt.f90 \ !-I$NETCDF/include -I$NETCDF_FORTRAN/include -L$NETCDF_FORTRAN/lib -L$NETCDF/lib -lnetcdf -lnetcdff !**************************************************************************************** ! program read_out use netcdf use extract_mod use compute_zcor use pt_in_poly_test character(len=30) :: file63,varname character(len=12) :: it_char integer,allocatable :: kbp(:),iday(:,:),irecord(:,:),node3(:,:),iep(:),irank_read(:) real,allocatable :: sigma(:),cs(:),ztot(:),times(:,:),out(:,:,:),out2(:,:,:), & &eta2(:),arco(:,:),ztmp(:),x00(:),y00(:),z00(:),t00(:),sigma_lcl(:,:),ztmp2(:,:), & &outvar(:,:,:) real*8,allocatable :: timeout(:) integer :: nodel(3) !,dimids(100),idims(100), & ! &start_2d(2),start_3d(3),start_4d(4), & ! &count_2d(2),count_3d(3),count_4d(4) dimension swild(3),out3(2,2),out4(2) !long int for large files !integer(kind=8) :: irec print*, 'Do you work on uncombined (0) or combined (1) nc?' read(*,*)icomb if(icomb/=0.and.icomb/=1) stop 'Unknown icomb' print*, 'Input variable name to read from (e.g. elev):' read(*,'(a30)')varname varname=adjustl(varname); len_var=len_trim(varname) ! Invliad number used for 3D variables: below bottom; dry spot; no parents print*, 'Input values to be used for invalid place:' read(*,*)rjunk open(10,file='station.xyzt',status='old') read(10,*) read(10,*) nxy allocate(x00(nxy),y00(nxy),z00(nxy),t00(nxy),stat=istat) if(istat/=0) stop 'Falied to allocate (1)' do i=1,nxy read(10,*)j,x00(i),y00(i),z00(i),t00(i) !z00>=0 from F.S.; t00 in sec if(z00(i)<0) then write(*,*)'Invalid z value:',i; stop endif enddo !i close(10) !... Header !Returned vars: ne,np,ns,nrec,[x y dp](np), !elnode,i34,nvrt,h0,dtout !If icomb=0, additonal vars: !nproc,iegl_rank,iplg,ielg,islg,np_lcl(:),ne_lcl(:),ns_lcl(:) if(icomb==0) then !uncombined call get_global_geo else call readheader(1) endif print*, 'After header:',ne,np,ns,nrec,i34(ne), & &elnode(1:i34(ne),ne),nvrt,h0,x(np),y(np),dp(np) !,start_time last_dim=max(np,ne,ns) allocate(timeout(nrec),out(3,nvrt,2),out2(2,nvrt,2),eta2(np),node3(nxy,3),arco(nxy,3), & &iep(nxy),iday(2,nxy),irecord(2,nxy),times(2,nxy),outvar(2,nvrt,last_dim),stat=istat) outvar=-huge(1.0) if(istat/=0) stop 'Failed to allocate (3)' ! Read in vgrid.in allocate(ztot(nvrt),sigma(nvrt),sigma_lcl(nvrt,np),kbp(np)) call get_vgrid_single('vgrid.in',np,nvrt,ivcor,kz,h_s,h_c,theta_b,theta_f,ztot,sigma,sigma_lcl,kbp) allocate(ztmp(nvrt),ztmp2(nvrt,3)) ! Calculate kbp00 if(ivcor==1) then kbp00=kbp else do i=1,np !Use large eta to get true bottom call zcor_SZ_single(dp(i),1.e8,h0,h_s,h_c,theta_b,theta_f,kz,nvrt,ztot,sigma, & &ztmp(:),idry2,kbp00(i)) enddo !i endif !ivcor !... Find parent element for (x00,y00) iep=0 ! arco=1./3 !initialize for pts without parents ! do l=1,nxy ! node3(l,1:3)=elnode(1:3,1) !initialize for pts without parents ! enddo !l do i=1,ne do l=1,nxy if(iep(l)/=0) cycle call pt_in_poly_single(i34(i),real(x(elnode(1:i34(i),i))), & &real(y(elnode(1:i34(i),i))),x00(l),y00(l),inside,arco(l,1:3),nodel) if(inside==1) then iep(l)=i !print*, 'Found:',l,arco(l,1:3),nodel node3(l,1:3)=elnode(nodel(1:3),i) endif !inside enddo !l; build pts ifl=0 !flag do l=1,nxy if(iep(l)==0) then ifl=1 exit endif enddo !l if(ifl==0) exit enddo !i=1,ne iabort=0 do j=1,nxy if(iep(j)<=0) then write(11,*)'Cannot find a parent for pt:',j,x00(j),y00(j) iabort=1 endif enddo !j if(iabort==1) stop 'check fort.11 for pts outside' !Mark ranks that need to be read in if(icomb==0) then allocate(irank_read(0:nproc-1)) irank_read=0 do j=1,nxy irank_read(iegl_rank(iep(j)))=1 write(99,*)'reading from rank #:',iegl_rank(iep(j)) enddo endif !icomb !... Compute stack and record # for each pt do i=1,nxy ! Check if time is before first record if(t00(i)nrec.or.irecord(2,i)>nrec) then write(11,*)'Record # overflow: ',i,irecord(:,i) stop endif if(t00(i)times(2,i)) then write(11,*)'Wrong time bounds:',i,t00(i),times(:,i),iday(:,i),irecord(:,i) stop endif enddo !i=1,nxy !... Time iteration do i=1,nxy loop1: do l=1,2 !2 times ! write(it_char,'(i12)')iday(l,i) ! it_char=adjustl(it_char); leng=len_trim(it_char) ! file63='schout_'//it_char(1:leng)//'.nc' ! iret=nf90_open(trim(adjustl(file63)),OR(NF90_NETCDF4,NF90_NOWRITE),ncid) ! !time is double ! iret=nf90_inq_varid(ncid,'time',itime_id) ! iret=nf90_get_var(ncid,itime_id,timeout,(/1/),(/nrec/)) if(icomb==0) then !uncombined call get_timeout(iday(l,i),nrec,timeout,icomb) else call get_timeout(iday(l,i),nrec,timeout) endif ! print*, 'time=',timeout,trim(adjustl(file63)) irec=irecord(l,i) if(icomb==0) then !uncombined do irank=0,nproc-1 if(irank_read(irank)>0) then call get_outvar(iday(l,i),irec,varname,np,last_dim,nvrt,outvar,i23d,ivs,eta2,irank) endif enddo !irank else call get_outvar(iday(l,i),irec,varname,np,last_dim,nvrt,outvar,i23d,ivs,eta2) endif !Get elev ! start_2d(1)=1; start_2d(2)=irec ! count_2d(1)=np; count_2d(2)=1 ! iret=nf90_get_var(ncid,ielev_id,eta2,start_2d,count_2d) ! ! iret=nf90_inq_varid(ncid,varname(1:len_var),ivarid1) ! if(iret/=nf90_NoErr) stop 'Var not found' ! iret=nf90_Inquire_Variable(ncid,ivarid1,ndims=ndims,dimids=dimids) ! if(ndims>100) stop 'increase dimension of dimids & idims' ! do ii=1,ndims ! iret=nf90_Inquire_Dimension(ncid,dimids(ii),len=idims(ii)) ! enddo !i ! npes=idims(ndims-1) !np|ne|ns ! if(npes/=np.and.npes/=ne) stop 'can only handle node- or elem-based' ! if(idims(ndims)/=nrec) stop 'last dim is not time' ! ! iret=nf90_get_att(ncid,ivarid1,'i23d',i23d) ! if(i23d<=0.or.i23d>6) stop 'wrong i23d' ! iret=nf90_get_att(ncid,ivarid1,'ivs',ivs) ! !print*, 'i23d:',i23d,ivs,idims(1:ndims) ! if(ivs==1) then !scalar ! if(mod(i23d-1,3)==0) then !2D ! start_2d(1)=1; start_2d(2)=irec ! count_2d(1)=npes; count_2d(2)=1 ! iret=nf90_get_var(ncid,ivarid1,outvar(1,1,1:npes),start_2d,count_2d) ! else !3D ! start_3d(1:2)=1; start_3d(3)=irec ! count_3d(2)=npes; count_3d(1)=nvrt; count_3d(3)=1 ! iret=nf90_get_var(ncid,ivarid1,outvar(1,:,1:npes),start_3d,count_3d) ! endif ! else !vector ! if(mod(i23d-1,3)==0) then !2D ! start_3d(1:2)=1; start_3d(3)=irec ! count_3d(2)=npes; count_3d(1)=2; count_3d(3)=1 ! iret=nf90_get_var(ncid,ivarid1,outvar(1:2,1,1:npes),start_3d,count_3d) ! else if(ndims-1==3) then !3D vector ! start_4d(1:3)=1; start_4d(4)=irec ! count_4d(3)=npes; count_4d(2)=nvrt; count_4d(1)=2; count_4d(4)=1 ! iret=nf90_get_var(ncid,ivarid1,outvar(:,:,1:npes),start_4d,count_4d) ! else ! stop 'Unknown type(2)' ! endif ! endif !ivs !Available now: outvar(2,nvrt,np|ne),eta2(np) !However, for uncombined nc, values in untouched ranks are junk !Debug ! write(98,*)i,l ! do j=1,np ! write(98,*)j,kbp00(j),outvar(1,:,j) ! enddo !j ! stop out2(l,:,:)=0 out3(l,:)=0 if(mod(i23d-1,3)==0) then !2D do j=1,3 !nodes nd=node3(i,j) do m=1,ivs if(i23d<=3) then !node out2(l,1,m)=out2(l,1,m)+arco(i,j)*outvar(m,1,nd) else if (i23d<=6) then !elem out2(l,1,m)=outvar(m,1,iep(i)) endif enddo !m enddo !j else !3D ! Do interpolation etal=0; dep=0; idry=0 do j=1,3 nd=node3(i,j) if(eta2(nd)+dp(nd)=ztmp(k).and.ztmp(nvrt)-z00(i)<=ztmp(k+1)) then k0=k rat=(ztmp(nvrt)-z00(i)-ztmp(k))/(ztmp(k+1)-ztmp(k)) exit endif enddo !k if(k0==0) then out3(:,:)=rjunk exit loop1 ! write(12,*)'Warning: failed to find a vertical level:',it,i else do m=1,ivs if(i23d<=3) then !node out3(l,m)=out2(l,k0,m)*(1-rat)+out2(l,k0+1,m)*rat else if (i23d<=6) then !elem out3(l,m)=out2(l,k0+1,m) !FV endif enddo !m endif endif !dry/wet endif !i23d enddo loop1 !l=1,2; 2 times ! Interpolate in time trat=(t00(i)-times(1,i))/(times(2,i)-times(1,i)) !must be [0,1] if(mod(i23d-1,3)==0) then if(iep(i)==0) then !no parents out4(1:ivs)=rjunk else out4(1:ivs)=out2(1,1,1:ivs)*(1-trat)+out2(2,1,1:ivs)*trat endif write(18,'(e16.8,1000(1x,f15.3))')t00(i)/86400,out4(1:ivs),x00(i),y00(i) else !3D if(iep(i)==0) then !no parents out4(1:ivs)=rjunk else out4(1:ivs)=out3(1,1:ivs)*(1-trat)+out3(2,1:ivs)*trat endif write(18,*)t00(i)/86400,out4(1),x00(i),y00(i),z00(i) !write(18,'(e16.8,1000(1x,f15.3))')t00(i)/86400,out4(1),x00(i),y00(i),z00(i) if(ivs==2) write(19,'(e16.8,1000(1x,f15.3))')t00(i)/86400,out4(2),x00(i),y00(i),z00(i) endif enddo !i=1,nxy print*, 'Finished!' stop end