Path: blob/devel/elmerice/IceSheet/Tools/ConservativeInterpolation/MakeCDOGridDesc.F90
3206 views
!/*****************************************************************************/1! *2! * Elmer/Ice, a glaciological add-on to Elmer3! * http://elmerice.elmerfem.org4! *5! *6! * This program is free software; you can redistribute it and/or7! * modify it under the terms of the GNU General Public License8! * as published by the Free Software Foundation; either version 29! * of the License, or (at your option) any later version.10! *11! * This program is distributed in the hope that it will be useful,12! * but WITHOUT ANY WARRANTY; without even the implied warranty of13! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14! * GNU General Public License for more details.15! *16! * You should have received a copy of the GNU General Public License17! * along with this program (in file fem/GPL-2); if not, write to the18! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,19! * Boston, MA 02110-1301, USA.20! *21! *****************************************************************************/22! ******************************************************************************23! *24! * Authors: F. Gillet-Chaulet (IGE-France)25! * Web: http://elmerice.elmerfem.org26! * Original Date: 04/201927! *28! *****************************************************************************29!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!30! Write the grid description file for CDO (https://code.mpimet.mpg.de/projects/cdo)31! cf e.g. http://www.climate-cryosphere.org/wiki/index.php?title=Regridding_with_CDO32! Limitations: restricted to meshes with 303 elements33! Requires: fortrangis (http://fortrangis.sourceforge.net) with proj support34!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!35SUBROUTINE MakeCDOGridDesc( Model,Solver,dt,TransientSimulation )36USE DefUtils37USE fortranc38USE proj39IMPLICIT NONE4041TYPE(Model_t) :: Model42TYPE(Solver_t):: Solver43REAL(KIND=dp) :: dt44LOGICAL :: TransientSimulation4546TYPE(ValueList_t), POINTER :: SolverParams47INTEGER :: t,n,ne,i48TYPE(Element_t),POINTER :: Element49INTEGER, POINTER :: NodeIndexes(:)50REAL(KIND=dp),ALLOCATABLE :: LatLon(:,:),Corner(:,:,:)51REAL(KIND=dp) :: x(3),y(3),xg,yg,xt(3),yt(3)52INTEGER, parameter :: io=1253INTEGER :: nclock=054CHARACTER(len=100) :: Filename5556TYPE(pjuv_object) :: coordp,coordg57TYPE(pj_object) :: pj58CHARACTER(LEN=MAX_NAME_LEN) :: proj_string5960! Get projection definition61SolverParams => GetSolverParams()62proj_string = ListGetString(SolverParams,'projection',UnFoundFatal=.TRUE.)63pj = pj_init_plus(TRIM(proj_string)//CHAR(0))6465ne=GetNOFActive()66allocate(LatLon(ne,2),Corner(ne,3,2))6768DO t = 1,ne69Element => GetActiveElement(t)70NodeIndexes => Element % NodeIndexes7172IF (Element % TYPE % ElementCode.NE.303) &73CALL FATAL('MakeCDOGrid','Wrong element type')7475n = GetElementNOFNodes()76! element center77xg=SUM(Solver%Mesh%Nodes%x(NodeIndexes(1:n)))/n78yg=SUM(Solver%Mesh%Nodes%y(NodeIndexes(1:n)))/n7980! convert to lon,lat81coordp = pjuv_object(xg,yg)82coordg = pj_inv(coordp, pj)83LatLon(t,1)=coordg % v * pj_rad_to_deg84LatLon(t,2)=coordg % u * pj_rad_to_deg8586! element corners87x(1:n)=Solver%Mesh%Nodes%x(NodeIndexes(1:n))88y(1:n)=Solver%Mesh%Nodes%y(NodeIndexes(1:n))89! CDO requires anti-clokwise ordering90IF(IsClockwise(x,y,n)) THEN91nclock=nclock+192xt=x93yt=y94Do i=1,395x(4-i)=xt(i)96y(4-i)=yt(i)97End do98END IF99!convert corners to lon,lat100Do i=1,n101coordp = pjuv_object(x(i),y(i))102coordg = pj_inv(coordp, pj)103Corner(t,i,1)=coordg % v * pj_rad_to_deg104Corner(t,i,2)=coordg % u * pj_rad_to_deg105End do106107End do108109PRINT *,Model%Mesh%name110! write the grid description file111IF (ParEnv % Pes>1 ) THEN112write(FileName,'(a,a,i0,a)') TRIM(Model%Mesh%name),'_CDOGrid_',ParEnv%MyPe,'.txt'113ELSE114write(FileName,'(a,a)') TRIM(Model%Mesh%name),'_CDOGrid.txt'115END IF116117open(io,file=trim(Filename))118write(io,*) 'gridtype = unstructured'119write(io,*) 'gridsize = ',ne120write(io,*) 'nvertex = ',3121122write(io,*) 'xvals = ',LatLon(1,2)123Do t=2,ne124write(io,*) LatLon(t,2)125End do126write(io,*) 'xbounds = ',Corner(1,1:3,2)127Do t=2,ne128write(io,*) Corner(t,1:3,2)129End do130131write(io,*) 'yvals = ',LatLon(1,1)132Do t=2,ne133write(io,*) LatLon(t,1)134End do135write(io,*) 'ybounds = ',Corner(1,1:3,1)136Do t=2,ne137write(io,*) Corner(t,1:3,1)138End do139140141close(io)142143deallocate(LatLon,Corner)144145CONTAINS146! Are nodes given clockwise?147FUNCTION IsClockwise(x,y,n) RESULT(clokwise)148LOGICAL :: clokwise149REAL(KIND=dp) :: x(n),y(n)150INTEGER :: n151INTEGER :: i,ind2152REAL(KIND=dp) :: sarea153154sarea=0._dp155Do i=1,n-1156ind2=mod(i+1,n)157sarea=sarea+(x(ind2)-x(i))*(y(ind2)+y(i))158End do159clokwise=(sarea.GT.0)160161END FUNCTION IsClockwise162End163164165