📄 utils.f90
字号:
! SEM2DPACK version 2.2.11 -- A Spectral Element Method for 2D wave propagation and fracture dynamics,! with emphasis on computational seismology and earthquake source dynamics.! ! Copyright (C) 2003-2007 Jean-Paul Ampuero! All Rights Reserved! ! Jean-Paul Ampuero! ! ETH Zurich (Swiss Federal Institute of Technology)! Institute of Geophysics! Seismology and Geodynamics Group! ETH H鰊ggerberg HPP O 13.1! CH-8093 Z黵ich! Switzerland! ! ampuero@erdw.ethz.ch! +41 44 633 2197 (office)! +41 44 633 1065 (fax)! ! http://www.sg.geophys.ethz.ch/geodynamics/ampuero/! ! ! This software is freely available for scientific research purposes. ! If you use this software in writing scientific papers include proper ! attributions to its author, Jean-Paul Ampuero.! ! This program is free software; you can redistribute it and/or! modify it under the terms of the GNU General Public License! as published by the Free Software Foundation; either version 2! of the License, or (at your option) any later version.! ! This program is distributed in the hope that it will be useful,! but WITHOUT ANY WARRANTY; without even the implied warranty of! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the! GNU General Public License for more details.! ! You should have received a copy of the GNU General Public License! along with this program; if not, write to the Free Software! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.! ! This is a set of basic tools, adapted from different open sourcesmodule utils implicit none private public :: invert2,drank,dsort,hunt,sub2ind,sub2ind_b,spline,splintcontains!----------------------------------------------------------------------!-- inversion of a 2 x 2 matrix function invert2(A) result(B) use stdio, only : IO_abort double precision, intent(in) :: A(2,2) double precision :: B(2,2) double precision :: determinant determinant = A(1,1)*A(2,2) - A(1,2)*A(2,1) if (determinant <= 0d0) call IO_abort('SE_InverseJacobian: undefined Jacobian') B(1,1) = A(2,2) B(2,1) = - A(2,1) B(1,2) = - A(1,2) B(2,2) = A(1,1) B = B/determinant end function invert2!=====================================================================! subscript (i,j) to index (iglob)! numbering conventions :! i=1:n ! j=1:p! iglob = 1:integer function sub2ind(i,j,n) integer, intent(in) :: i,j,n sub2ind = (j-1)*n + iend function sub2ind!--------------------------------------------------------------------- ! returns 0 if out of boxinteger function sub2ind_b(i,j,n,p) integer, intent(in) :: i,j,n,p if (i<=n .and. i>=1 .and. j<=p .and. j>=1) then sub2ind_b= (j-1)*n + i else sub2ind_b=0 endifend function sub2ind_b!-----------------------------------------------------------------------!From Michel Olagnon's ORDERPACK 2.0!http://www.fortran-2000.com/rank/index.html!!Subroutine D_mrgrnk (XDONT, IRNGT)Subroutine drank(XDONT, IRNGT)! __________________________________________________________! MRGRNK = Merge-sort ranking of an array! For performance reasons, the first 2 passes are taken! out of the standard loop, and use dedicated coding.! __________________________________________________________! __________________________________________________________! Real (kind=kdp), Dimension (:), Intent (In) :: XDONT double precision, Dimension (:), Intent (In) :: XDONT !jpampuero Integer, Dimension (:), Intent (Out) :: IRNGT! __________________________________________________________! Real (kind=kdp) :: XVALA, XVALB double precision :: XVALA, XVALB !jpampuero! Integer, Dimension (SIZE(IRNGT)) :: JWRKT Integer :: LMTNA, LMTNC, IRNG1, IRNG2 Integer :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB! NVAL = Min (SIZE(XDONT), SIZE(IRNGT)) Select Case (NVAL) Case (:0) Return Case (1) IRNGT (1) = 1 Return Case Default Continue End Select!! Fill-in the index array, creating ordered couples! Do IIND = 2, NVAL, 2 If (XDONT(IIND-1) <= XDONT(IIND)) Then IRNGT (IIND-1) = IIND - 1 IRNGT (IIND) = IIND Else IRNGT (IIND-1) = IIND IRNGT (IIND) = IIND - 1 End If End Do If (Modulo(NVAL, 2) /= 0) Then IRNGT (NVAL) = NVAL End If!! We will now have ordered subsets A - B - A - B - ...! and merge A and B couples into C - C - ...! LMTNA = 2 LMTNC = 4!! First iteration. The length of the ordered subsets goes from 2 to 4! Do If (NVAL <= 2) Exit!! Loop on merges of A and B into C! Do IWRKD = 0, NVAL - 1, 4 If ((IWRKD+4) > NVAL) Then If ((IWRKD+2) >= NVAL) Exit!! 1 2 3! If (XDONT(IRNGT(IWRKD+2)) <= XDONT(IRNGT(IWRKD+3))) Exit!! 1 3 2! If (XDONT(IRNGT(IWRKD+1)) <= XDONT(IRNGT(IWRKD+3))) Then IRNG2 = IRNGT (IWRKD+2) IRNGT (IWRKD+2) = IRNGT (IWRKD+3) IRNGT (IWRKD+3) = IRNG2!! 3 1 2! Else IRNG1 = IRNGT (IWRKD+1) IRNGT (IWRKD+1) = IRNGT (IWRKD+3) IRNGT (IWRKD+3) = IRNGT (IWRKD+2) IRNGT (IWRKD+2) = IRNG1 End If Exit End If!! 1 2 3 4! If (XDONT(IRNGT(IWRKD+2)) <= XDONT(IRNGT(IWRKD+3))) Cycle!! 1 3 x x! If (XDONT(IRNGT(IWRKD+1)) <= XDONT(IRNGT(IWRKD+3))) Then IRNG2 = IRNGT (IWRKD+2) IRNGT (IWRKD+2) = IRNGT (IWRKD+3) If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD+4))) Then! 1 3 2 4 IRNGT (IWRKD+3) = IRNG2 Else! 1 3 4 2 IRNGT (IWRKD+3) = IRNGT (IWRKD+4) IRNGT (IWRKD+4) = IRNG2 End If!! 3 x x x! Else IRNG1 = IRNGT (IWRKD+1) IRNG2 = IRNGT (IWRKD+2) IRNGT (IWRKD+1) = IRNGT (IWRKD+3) If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD+4))) Then IRNGT (IWRKD+2) = IRNG1 If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD+4))) Then! 3 1 2 4 IRNGT (IWRKD+3) = IRNG2 Else! 3 1 4 2 IRNGT (IWRKD+3) = IRNGT (IWRKD+4) IRNGT (IWRKD+4) = IRNG2 End If Else! 3 4 1 2 IRNGT (IWRKD+2) = IRNGT (IWRKD+4) IRNGT (IWRKD+3) = IRNG1 IRNGT (IWRKD+4) = IRNG2 End If End If End Do!! The Cs become As and Bs! LMTNA = 4 Exit End Do!! Iteration loop. Each time, the length of the ordered subsets! is doubled.! Do If (LMTNA >= NVAL) Exit IWRKF = 0 LMTNC = 2 * LMTNC!! Loop on merges of A and B into C! Do IWRK = IWRKF IWRKD = IWRKF + 1 JINDA = IWRKF + LMTNA IWRKF = IWRKF + LMTNC If (IWRKF >= NVAL) Then If (JINDA >= NVAL) Exit IWRKF = NVAL End If IINDA = 1 IINDB = JINDA + 1!! Shortcut for the case when the max of A is smaller! than the min of B. This line may be activated when the! initial set is already close to sorted.!! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE!! One steps in the C subset, that we build in the final rank array!! Make a copy of the rank array for the merge iteration! JWRKT (1:LMTNA) = IRNGT (IWRKD:JINDA)! XVALA = XDONT (JWRKT(IINDA)) XVALB = XDONT (IRNGT(IINDB))! Do IWRK = IWRK + 1!! We still have unprocessed values in both A and B! If (XVALA > XVALB) Then IRNGT (IWRK) = IRNGT (IINDB) IINDB = IINDB + 1 If (IINDB > IWRKF) Then! Only A still with unprocessed values IRNGT (IWRK+1:IWRKF) = JWRKT (IINDA:LMTNA) Exit End If XVALB = XDONT (IRNGT(IINDB)) Else IRNGT (IWRK) = JWRKT (IINDA) IINDA = IINDA + 1 If (IINDA > LMTNA) Exit! Only B still with unprocessed values XVALA = XDONT (JWRKT(IINDA)) End If! End Do End Do!! The Cs become As and Bs! LMTNA = 2 * LMTNA End Do! Return!!End Subroutine D_mrgrnkEnd Subroutine drank!-----------------------------------------------------------------------! DSORT adapted from SLATEC! Converted to f90 using f2f.perl! Modified: + to be used always with DY! + only increasing order! + no checks / error messages! Jean-Paul Ampuero dim oct 19 17:15:29 EDT 2003! ECK DSORT! SUBROUTINE DSORT (DX, DY, N, KFLAG) SUBROUTINE DSORT (DX, DY)!***BEGIN PROLOGUE DSORT!***PURPOSE Sort an array and optionally make the same interchanges in! an auxiliary array. The array may be sorted in increasing! or decreasing order. A slightly modified QUICKSORT! algorithm is used.!***LIBRARY SLATEC!***CATEGORY N6A2B!***TYPE DOUBLE PRECISION (SSORT-S, DSORT-D, ISORT-I)!***KEYWORDS SINGLETON QUICKSORT, SORT, SORTING!***AUTHOR Jones, R. E., (SNLA)! Wisniewski, J. A., (SNLA)!***DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -