Advertisement
Miki76

Untitled

Apr 7th, 2016
381
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 122.68 KB | None | 0 0
  1. ! MT2D package for OCCAM 3.0
  2. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  3. !
  4. ! Revision History:
  5. ! Oct 2006 David Myer - move to F90, allocated memory, cmdline params,
  6. ! modules, and general code reorg. From mathematical perspective
  7. ! this version includes options for model value limits and
  8. ! diagonal penalties. PW2D derivatives now returned with respect
  9. ! to linear conductivity. (Version 3.0)
  10. ! Dec-13-2005, Kerry Key
  11. ! Modified to use different regularization options :
  12. ! July 25, 2001 - (Catherine deGroot-Hedlin)
  13. ! alteration to fordiv, PW's new adjoint method,
  14. ! which returns derviatives with respect to log(resistivity)
  15. ! Feb 23, 1994 revision to allow for impedance data - cdh -
  16. ! January 1993 Steven Constable's re-write of Catherine deGroot-Hedlin's
  17. ! thesis code under Geotools sponsorship (Version 1.01)
  18. !
  19. ! REFERENCES: CONSTABLE, PARKER & CONSTABLE, 1987: GEOPHYSICS 52, 289-300.
  20. ! DEGROOT-HEDLIN & CONSTABLE, 1990: GEOPHYSICS 55, 1613-1624.
  21. ! CONSTABLE, 1991: GEOPHYS. J. INT. 106, 387-388.
  22. ! CONSTABLE, 1992: OCCAM DISTRIBUTION NOTES.
  23. ! Myer et al., 2007: OCCAM 3.0 release notes.
  24. !
  25. ! See http://marineemlab.ucsd.edu/Projects/Occam/
  26. !
  27. !-----------------------------------------------------------------------
  28. SUBROUTINE OBJMAT(IRUF, model, DEL, nPTerms, bHaveLink, linkpr)
  29. !-----------------------------------------------------------------------
  30.  
  31. ! OCCAM MT2D 3.0 Package
  32. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  33. ! Subroutine Revision 3.0, November 2006
  34. ! Dec-13-2005, Kerry Key
  35. ! Modified to use different regularization options 3-2XX:
  36. ! Subroutine Revision 1.01, 13 Jan 1993
  37. !
  38. ! CONSTRUCTS PENALTY MATRIX (DEL) FOR 2DMT CASE.
  39. ! WE USE A SIMPLE PENALTY MEASURE FOR THE TIME BEING WHICH ASSUMES BLOCK
  40. ! HEIGHT INCREASES EXPONENTIALLY WITH DEPTH. LATER WE CAN USE ACTUAL
  41. ! DIMENSIONS OF THE COMMON EDGES OF THE BRICKS TO WORK OUT THE PENALTY
  42. ! MEASURE.
  43.  
  44. ! ON INPUT:
  45.  
  46. ! IRUF valid values:
  47. ! 1 1ST DERIVATIVE ROUGHNESS
  48. ! 2 2nd Deriv is NOT supported in the 2D occam
  49. ! 3 1st Deriv + PARAMETER ASPECT RATIO WEIGHTING
  50. ! 4 1st Deriv + DEPTH WEIGHTED SMOOTHING (LOG10(DEPTH))
  51. ! 1XX HORIZONTALLY BIASED, XX IS FACTOR WEIGHT APPLIED
  52. ! TO HORIZ ROUGHNESS, VERT REMAINS AS FIRST DIFFERENCES
  53. ! 2XX VERTICALLY BIASED, XX IS FACTOR WEIGHT APPLIED
  54. ! TO VERT ROUGHNESS, HORIZ REMAINS AS FIRST DIFFERENCES
  55. ! nPTerms = (INTEGER) NUMBER OF NON-ZERO ROWS IN PENALTY MATRIX
  56. ! ON OUTPUT:
  57. ! DEL() = (REAL) PENALTY MATRIX
  58. ! linkpr = brick #s of pairs of bricks linked in the penalty matrix.
  59. ! Used in deltdel to calculate (DEL)Transpose * DEL using
  60. ! essentially sparse matrix methods.
  61. !-----------------------------------------------------------------------
  62. USE Occam_Mod
  63. USE Fwd_mod
  64.  
  65. IMPLICIT NONE
  66.  
  67. ! ARGUMENTS:
  68. INTEGER, intent(in) :: IRUF
  69. real, intent(in) :: model(nParams)
  70. REAL, intent(out) :: DEL(nPTerms,nParams)
  71. INTEGER, intent(in) :: nPTerms ! # of penalty terms (for dim of DEL & linkpr)
  72. logical, intent(in) :: bHaveLink ! true if linkpr was passed. NB: intrinsic fctn present() doesn't appear to work.
  73. INTEGER, OPTIONAL, intent(out) :: linkpr(nPTerms,2) ! DGM Oct 2006 - not always needed. Quite large!
  74.  
  75. ! LOCAL VARIABLES
  76. INTEGER I, J, K, nPen
  77. logical :: bChkPair, bExceptUsed(nExep)
  78. REAL PENALT
  79. ! bExceptUsed() = A TABLE TO INDICATE WHETHER PENALTY 'EXCEPTIONS' ARE MOD-
  80. ! IFICATIONS OF THE DEFAULT PENALTIES OR ADDITIONS TO THE PENALTY
  81. ! MATRIX
  82. ! PENALT = WEIGHTING OF PENALTY
  83.  
  84. !------------------------------------------------
  85. ! Init working variables
  86. DEL = 0.0 ! Array math
  87. nPen = 0
  88. PENALT = 0 ! Oct 2006 - was not initialized - if IRUF 0 or 2, wld be random.
  89. bExceptUsed = .false.
  90.  
  91. ! Count the horizontal & vertical penalty blocks
  92. do i = 1,NBRICK
  93. ! Look for blocks connected to block i
  94. ! NB: ICORN's 2nd index: 1=top, 2=left, 3=bottom, 4=right
  95. do j = 1,NBRICK
  96. bChkPair = .false.
  97.  
  98. ! Horizontal or Diagonal
  99. if (ICORN(i,4) == ICORN(j,2)) then
  100. if (ICORN(i,1) == ICORN(j,1)) then ! Horizontal
  101. nPen = nPen + 1
  102. bChkPair = .true.
  103.  
  104. IF (IRUF .EQ. 1) then ! FIRST DIFFERENCE ONLY
  105. PENALT = 1.0
  106. ELSEIF (IRUF .EQ. 3) then ! ASPECT RATIO WEIGHTING
  107. PENALT = 2.*THICK(I)/(WIDTH(I)+WIDTH(J))
  108. ELSEIF (IRUF .EQ. 4) then ! DEPTH WEIGHTED
  109. PENALT = log10( sum( DLZ(1:ICORN(I,1)) ) )
  110. elseif (IRUF >= 100 .and. IRUF <= 199) then ! 1XX HORIZONTALLY BIASED
  111. PENALT = MOD(IRUF,100)
  112. elseif (IRUF >= 200 .and. IRUF <= 299) then ! 2XX VERTICALLY BIASED
  113. PENALT = 1.0
  114. ENDIF
  115.  
  116. elseif (gbAddDiags) then ! if we care about diagonals
  117. if ( ICORN(i,1) == ICORN(j,3) & ! diag up
  118. .or. ICORN(i,3) == ICORN(j,1) ) then ! diag down
  119. bChkPair = .true.
  120. nPen = nPen + 1
  121.  
  122. IF (IRUF .EQ. 1) then ! first difference only:
  123. PENALT = 1.0
  124. ELSEIF (IRUF .EQ. 3) then ! Aspect ratio weighting
  125. PENALT = 2.*THICK(I)/(WIDTH(I)+WIDTH(J))
  126. ELSEIF (IRUF .EQ. 4) then ! DEPTH WEIGHTED
  127. PENALT = log10( sum( DLZ(1:ICORN(I,1)) ) )
  128. elseif (IRUF >= 100 .and. IRUF <= 199) then ! 1XX HORIZONTALLY BIASED
  129. PENALT = 1.0
  130. elseif (IRUF >= 200 .and. IRUF <= 299) then ! 2XX VERTICALLY BIASED
  131. PENALT = 1.0
  132. ENDIF
  133. endif
  134. endif
  135. elseif ( (ICORN(i,3) == ICORN(j,1)) & ! Vertical?
  136. .AND. &
  137. ((ICORN(i,2) == ICORN(j,2)).OR.(ICORN(i,4) == ICORN(j,4))) &
  138. ) then
  139. bChkPair = .true.
  140. nPen = nPen + 1
  141.  
  142. IF (IRUF .EQ. 1) then ! first difference only:
  143. PENALT = 1.0
  144. ELSEIF (IRUF .EQ. 3) then ! Aspect ratio weighting
  145. PENALT = 2.*THICK(I)/(WIDTH(I)+WIDTH(J))
  146. ELSEIF (IRUF .EQ. 4) then ! DEPTH WEIGHTED
  147. PENALT = log10( sum( DLZ(1:ICORN(I,1)) ) )
  148. elseif (IRUF >= 100 .and. IRUF <= 199) then ! 1XX HORIZONTALLY BIASED
  149. PENALT = 1.0
  150. elseif (IRUF >= 200 .and. IRUF <= 299) then ! 2XX VERTICALLY BIASED
  151. PENALT = MOD(IRUF,200)
  152. ENDIF
  153. endif
  154.  
  155. ! If we found a linkage between blocks i and j...
  156. if (bChkPair) then
  157. ! Is an exception applied to this pair? If so, modify the penalty
  158. do k = 1, NEXEP
  159. if ( ((IJEXEP(k,1) == i) .AND. (IJEXEP(k,2) == j)) &
  160. .OR. &
  161. ((IJEXEP(k,1) == j) .AND. (IJEXEP(k,2) == i)) &
  162. ) then
  163. bExceptUsed(k) = .true.
  164. PENALT = PENALT*ABS(EXPEN(K))
  165. exit
  166. endif
  167. enddo
  168.  
  169. ! Record the penalty in the DEL matrix & the relationship in linkpr
  170. DEL(nPen, I) = -1. * PENALT
  171. DEL(nPen, J) = 1. * PENALT
  172. if (bHaveLink) then ! didn't work: (present(linkpr)) then
  173. linkpr(nPen,1)=i
  174. linkpr(nPen,2)=j
  175. endif
  176. endif
  177.  
  178. enddo
  179. enddo
  180.  
  181. ! Any exceptions in the array that were not used to modify bricks
  182. ! that would normally get penalties are used to link bricks that
  183. ! are not normally linked. Add the linkages to the DEL array now.
  184. DO I = 1, NEXEP
  185. IF (.not. bExceptUsed(I)) THEN
  186. nPen = nPen + 1
  187. PENALT = ABS(EXPEN(I))
  188. DEL(nPen, IJEXEP(I,1)) = -1.*PENALT
  189. DEL(nPen, IJEXEP(I,2)) = 1.*PENALT
  190. if (bHaveLink) then ! didn't work: (present(linkpr)) then
  191. linkpr(nPen,1) = ijexep(i,1)
  192. linkpr(nPen,2) = ijexep(i,2)
  193. endif
  194. END IF
  195. enddo
  196.  
  197. ! SET THE PREJUDICE WEIGHTS (i.e. block on itself)
  198. ! Change the weighting so that as the blocks get taller but
  199. ! no wider, structures are not abnormally elongated.
  200. PREWTS(1:NBRICK) = PREWT(1:NBRICK) !kwk * WIDTH(1:NBRICK) / THICK(1:NBRICK)
  201.  
  202. ! Copy over the weights for the free static shifts too.
  203. PREWTS(NBRICK+1:nParams) = PREWT(NBRICK+1:nParams)
  204.  
  205. return
  206. end subroutine objmat
  207.  
  208. !-----------------------------------------------------------------------
  209. INTEGER FUNCTION CountPenaltyTerms( iRuf ) result(nTerms)
  210. !-----------------------------------------------------------------------
  211. ! OCCAM MT2D 3.0 Package
  212. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  213. ! Subroutine Revision 3.0, November 2006
  214. ! DGM Oct 2006 - # of penalty terms may change depending on whether the
  215. ! roughness type requested does just horiz & vert or also diagonal.
  216. use Occam_mod
  217. use Fwd_mod
  218. implicit none
  219.  
  220. ! Parameters
  221. integer, intent(in) :: iRuf
  222.  
  223. ! Local vars
  224. integer :: i, j, k
  225. logical :: bChkPair, bExceptUsed(nExep)
  226.  
  227. ! Init various working variables
  228. nTerms = 0
  229. bExceptUsed = .false.
  230.  
  231. ! Count the horizontal & vertical penalty blocks
  232. do i = 1,NBRICK
  233. ! Look for blocks connected to block i
  234. ! NB: ICORN's 2nd index: 1=top, 2=left, 3=bottom, 4=right
  235. do j = 1,NBRICK
  236. bChkPair = .false.
  237.  
  238. ! Horizontal or Diagonal
  239. if (ICORN(i,4) == ICORN(j,2)) then
  240. if (ICORN(i,1) == ICORN(j,1)) then ! Horizontal
  241. nTerms = nTerms + 1
  242. bChkPair = .true.
  243. elseif (gbAddDiags) then ! if we care about diagonals
  244. if ( ICORN(i,1) == ICORN(j,3) & ! diag up
  245. .or. ICORN(i,3) == ICORN(j,1) ) then ! diag down
  246. nTerms = nTerms + 1
  247. bChkPair = .true.
  248. endif
  249. endif
  250. elseif ( (ICORN(i,3) == ICORN(j,1)) & ! Vertical?
  251. .AND. &
  252. ((ICORN(i,2) == ICORN(j,2)).OR.(ICORN(i,4) == ICORN(j,4))) &
  253. ) then
  254. nTerms = nTerms + 1
  255. bChkPair = .true.
  256. endif
  257.  
  258. ! Is an exception applied to this pair?
  259. if (bChkPair) then
  260. do k = 1, NEXEP
  261. if ( ((IJEXEP(k,1) == i) .AND. (IJEXEP(k,2) == j)) &
  262. .OR. &
  263. ((IJEXEP(k,1) == j) .AND. (IJEXEP(k,2) == i)) &
  264. ) then
  265. bExceptUsed(k) = .true.
  266. exit
  267. endif
  268. enddo
  269. endif
  270.  
  271. enddo
  272. enddo
  273.  
  274. ! Count exceptions that were not applied above. This allows you
  275. ! to use the exceptions to create penalties between blocks that
  276. ! otherwise would not have penalties (i.e. disconnected blocks)
  277. do i = 1, NEXEP
  278. if (.not. bExceptUsed(i)) then
  279. nTerms = nTerms + 1
  280. endif
  281. enddo
  282.  
  283. return
  284. end FUNCTION CountPenaltyTerms
  285.  
  286.  
  287.  
  288. !-----------------------------------------------------------------------
  289. subroutine inputd(datfil)
  290. !-----------------------------------------------------------------------
  291. !
  292. ! OCCAM MT2D 3.0 Package
  293. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  294. ! Subroutine Revision 3.0, November 2006
  295. ! revision to allow for Zrot value of input data - cdh -March 29, 1999
  296. ! revision to allow for impedance data - cdh -February 23, 1994
  297. ! Subroutine Revision 1.02, 13 Jan 1993
  298. !
  299. ! inputd opens the data file datfil and reads in the data array
  300. !
  301. ! includes:
  302. USE Occam_Mod
  303. USE Fwd_mod
  304. IMPLICIT NONE
  305.  
  306. ! arguments:
  307. character(*) datfil
  308.  
  309. ! local variables
  310. logical iffte, ifftm
  311. ! flags to indicate which modes are required
  312. integer lerr, i, j, nAllocErr
  313. ! error flag, loop index and handy integer
  314. character(80) string
  315. ! string buffer
  316. integer idcode
  317. ! idcode= function that performs the equivalent of a free-format internal
  318. ! read for an integer
  319. !
  320. ! parameters:
  321. integer iof
  322. parameter (iof = 15)
  323. ! iof = io unit number for file operations
  324. !----------------------------------------------------------
  325. ! open data file
  326. open (iof, file=datfil, status='old', iostat=lerr)
  327. if (lerr .ne. 0) then
  328. write(*,*) ' Error opening data file'
  329. stop
  330. end if
  331.  
  332. ! read stuff
  333. read(iof,'(18x,a)', end=198, err=199) string
  334. if (string(1:16) .ne. 'OCCAM2MTDATA_1.0') call filerr( &
  335. & ' Data file not supported',iof)
  336. read(iof,'(18x,a)', end=198, err=199) string
  337.  
  338. ! # of receivers
  339. read(iof,'(18x,a)', end=198, err=199) string
  340. nrc = idcode(string, iof)
  341. write(*,*) '# Receivers: ', nrc
  342.  
  343. ! Allocate things dependent on # rcvrs
  344. allocate( nrl(nrc) &
  345. , sitloc(nrc) &
  346. , isx1(2*nrc) & ! Static shift stuff
  347. , isx3(2*nrc) &
  348. , isfx(2*nrc) &
  349. , shift(2*nrc) &
  350. , cSiteName(nrc) &
  351. , stat=nAllocErr )
  352. if (nAllocErr .ne. 0) then
  353. write(*,*) 'Out of memory. Try reducing the model size.'
  354. stop
  355. endif
  356.  
  357. ! Read the receiver names.
  358. do i = 1, nrc
  359. read(iof,'(a)', end=198, err=199) cSiteName(i)
  360. enddo
  361. read(iof,'(a)', end=198, err=199) string
  362.  
  363. ! Rcvr locations
  364. read(iof,*, end=198, err=199) (sitloc(i), i=1,nrc)
  365.  
  366. ! # of Frequencies
  367. read(iof,'(18x,a)', end=198, err=199) string
  368. nfre = idcode(string, iof)
  369.  
  370. ! Allocate freq related vars
  371. allocate( frek(nfre) &
  372. , stat=nAllocErr )
  373. if (nAllocErr .ne. 0) then
  374. write(*,*) 'Out of memory. Try reducing the model size'
  375. stop
  376. endif
  377.  
  378. ! Read frequency list
  379. read(iof,*, end=198, err=199) (frek(i), i=1,nfre)
  380.  
  381. ! # of data
  382. read(iof,'(18x,a)', end=198, err=199) string
  383. ndata = idcode(string, iof)
  384.  
  385. ! Allocate vars related to # of data
  386. allocate( d(ndata) &
  387. , sd(ndata) &
  388. , dp(ndata,cnDataParams) &
  389. , stat=nAllocErr )
  390. if (nAllocErr .ne. 0) then
  391. write(*,*) 'Out of memory. Try reducing the model size'
  392. stop
  393. endif
  394.  
  395. ! Read the data
  396. read(iof,'(a)', end=198, err=199) string ! header line
  397. read(iof,*, end=198, err=199) &
  398. (dp(i,1), dp(i,2), dp(i,3), d(i), sd(i), i=1,ndata)
  399. dp(:,4) = 0 ! init the extra column for rotation (not used at the moment)
  400.  
  401. ! set idx, the mode definition for PW2DI
  402. iffte = .false.
  403. ifftm = .false.
  404. do 20 i = 1, ndata
  405. j = int(dp(i,3)+0.01)
  406. select case (j)
  407. case (1, 2, 3, 4, 9, 13, 14) ! See Fwd_mod for list of valid values
  408. iffte = .true.
  409. case (5, 6, 7, 8, 10, 15, 16)
  410. ifftm = .true.
  411. case (11, 12, 17, 18)
  412. iffte = .true.
  413. ifftm = .true.
  414. case default
  415. write(*,*) ' Invalid data type: ', j
  416. stop
  417. end select
  418. 20 continue
  419.  
  420. if ((iffte .and. ifftm)) then
  421. idx = 1
  422. else if (iffte) then
  423. idx = 2
  424. else if (ifftm) then
  425. idx = 3
  426. end if
  427.  
  428. if (idebug .ge. 1) then
  429. write(*,*) '# Data: ', ndata
  430. end if
  431.  
  432. ! initially set nd for occam as number of MT data
  433. ! May be modified later to account for static shift parameters
  434. nd = ndata
  435.  
  436. return
  437.  
  438. 198 call filerr (' Data file ended prematurely', iof)
  439. 199 call filerr (' Error reading data file', iof)
  440. !
  441. end
  442. !
  443. !-----------------------------------------------------------------------
  444. subroutine inputm(modfil)
  445. !----------------------------------------------------------------------
  446. !
  447. ! OCCAM MT2D 3.0 Package
  448. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  449. ! Subroutine Revision 3.0, November 2006
  450. ! Subroutine Revision 1.04, 14 Jan 1993
  451. !
  452. ! inputm() opens and reads the model file modfil, opens and reads the
  453. ! mesh and static shift files pointed at by modfil, and sets up the
  454. ! environments needed by OCCAM and PW2DI.
  455. !
  456. ! Note: inputm() assumes that inputd() has already been called
  457. !
  458. ! on input:
  459. ! modfil = (character) model file name
  460. ! on output:
  461. ! incredible amounts of stuff in common blocks (see include files)
  462. ! calls:
  463. ! filerr
  464. !
  465. USE Occam_Mod
  466. USE Fwd_mod
  467. IMPLICIT NONE
  468.  
  469. !
  470. ! arguments:
  471. character(*) modfil
  472. !
  473. ! local variables:
  474. INTEGER, ALLOCATABLE:: IRZ(:), IRY(:,:), IRINDX(:,:)
  475. INTEGER, ALLOCATABLE:: LOCEXP(:,:), ICONB(:)
  476.  
  477. integer lerr, i, l, j
  478. integer nsites, lidx, lfre, nexec, nAllocErr
  479. integer ii, jj, inz1, inz2, iny1, iny2
  480. integer nprej, nColMax
  481. ! irz() = no of vert. FEs in each row
  482. ! iry() = no of horiz FEs in each col for each row
  483. ! irindx() = layer/column to parameter pointers. 0 if fixed block
  484. ! lerr = iostat from file operations
  485. ! i,l,j = loop counters
  486. ! nsites = no of sites read from file. Ignored after input by OCCAM
  487. ! lidx = type of modelling; should be 0 for OCCAM
  488. ! lfre = number of frequencies read from file. Ignored by OCCAM
  489. ! nexec = type of action required - not used by inversion process.
  490. ! ii, jj = index counters for regularization bricks
  491. ! inz1, inz2 = top and bottom edges of bricks defined by FE mesh
  492. ! iny1, iny2 = left and right edges .. ditto ..
  493. ! locexp() = brick layer/col indices of exeption pairs
  494. ! nprej = number of entries in model prejudice
  495. ! iconb() = flag to indicate nodes on conductivity boundaries
  496. real dummy, tesum, tmsum, sserr
  497. real temp1,temp2
  498. ! dummy = dummy variable to read frequencies into
  499. ! tesum = sum of logs of TE free static shifts
  500. ! tmsum = sum of logs of TM free static shifts
  501. ! sserr = error term to use in conjuction with static shift constraint
  502.  
  503. character(1), allocatable :: apt(:,:,:)
  504. ! apt() = character array to store 4 resistivity codes for each element
  505.  
  506. character(80) mshfil, mshtyp, string, ssfile, prfile
  507. ! mshfil = mesh file name
  508. ! mshtyp = mesh type
  509. ! string = string buffer for free format reads
  510. ! ssfile = static shift file name
  511. ! prfile = file containing model prejudice and weights
  512. !
  513. logical iffree
  514. ! iffree = flag to indicate free element in regularization brick
  515. integer idcode
  516. ! idcode = function to perform the equivalent of a free-format internal
  517. ! read for an integer
  518. real rdcode
  519. ! rdcode = function to perform the equivalent of a free-format internal
  520. ! read for a real
  521. !
  522. ! parameters:
  523. integer iof
  524. parameter (iof = 15)
  525. ! iof = io unit number for file operations
  526. !
  527. !-----------------------------------------------------------------------
  528.  
  529. !
  530. ! Allocate arrays needed:
  531. !
  532. allocate( thick(nParams) &
  533. , width(nParams) &
  534. , y(nParams+cnMaxFixedRes) & ! + for all possible fixed resistivities (0-9,A-Z)
  535. , icorn(nParams,4) & ! 4 sides: 1=top, 2=left, 3=bottom, 4=right
  536. , laprm(nParams) &
  537. , prewt(nParams) &
  538. , stat=nAllocErr )
  539.  
  540. if (nAllocErr .ne. 0) then
  541. write(*,*) 'Out of memory. Too many free parameters (', nParams, ')'
  542. stop
  543. endif
  544.  
  545.  
  546.  
  547. !ccccccccccccccccccc model file reading cccccccccccccccccccccccccccccccc
  548. !
  549. open (iof, file=modfil, status='old', iostat=lerr)
  550. if (lerr .ne. 0) then
  551. write(*,*) ' Error opening model file'
  552. stop
  553. end if
  554.  
  555. ! read character descriptors
  556. read (iof,'(18x,a)', end=198, err=199) string
  557. if (string(1:15) .ne. 'OCCAM2MTMOD_1.0') call filerr( &
  558. & ' Model file not supported',iof)
  559. read (iof,'(18x,a)', end=198, err=199) string
  560. read (iof,'(18x,a)', end=198, err=199) string
  561. read (iof,'(18x,a)', end=198, err=199) mshfil
  562. read (iof,'(18x,a)', end=198, err=199) mshtyp
  563. read (iof,'(18x,a)', end=198, err=199) ssfile
  564. read (iof,'(18x,a)', end=198, err=199) prfile
  565.  
  566.  
  567. ! read in the binding offset and number of layers
  568. read (iof,'(18x,a)', end=198, err=199) string
  569. boffs = rdcode(string, iof)
  570. read (iof,'(18x,a)', end=198, err=199) string
  571. nlay = idcode(string, iof)
  572. write(*,*)nlay
  573.  
  574. ! Allocate vars related to the # of layers
  575. Allocate( irz(nlay) &
  576. , nrcol(nlay) &
  577. , stat=nAllocErr )
  578. if (nAllocErr .ne. 0) then
  579. write(*,*) 'Out of memory. Try reducing the model size.'
  580. stop
  581. endif
  582.  
  583. ! Don't know how many cols there are. So pre-read through the layers
  584. ! and keep the max #. Then allocate local vars to hold the data, and
  585. ! re-read through the layer data.
  586. do i = 1,nlay
  587. read (iof,*,end=198,err=199) irz(i), nrcol(i)
  588. write(*,*)irz(i), nrcol(i)
  589. read (iof,*,end=198,err=199) (ii, j=1,nrcol(i)) ! discard these for now
  590. enddo
  591. close(iof)
  592. open (iof, file=modfil, status='old', iostat=lerr)
  593. if (lerr .ne. 0) then
  594. write(*,*) ' Error opening model file (2nd pass)'
  595. stop
  596. end if
  597. do i = 1,9
  598. read (iof,*,end=198,err=199) string
  599. write(*,*)string
  600. enddo
  601.  
  602. nColMax = maxval(nrcol)
  603. Allocate( iry(nlay,nColMax), irindx(nlay,nColMax) &
  604. , stat=nAllocErr )
  605. if (nAllocErr .ne. 0) then
  606. write(*,*) 'Out of memory. Try reducing the model size.'
  607. stop
  608. endif
  609.  
  610. ! read in regularization mesh description
  611. do i = 1,nlay
  612. read (iof,*, end=198, err=199) irz(i),nrcol(i)
  613. read (iof,*, end=198, err=199) (iry(i,j), j=1,nrcol(i))
  614. enddo
  615.  
  616. ! read in exceptions to penalty matrix
  617. read (iof,'(18x,a)', end=198, err=199) string
  618. nexep = idcode(string, iof)
  619.  
  620. ! Allocate vars related to the # of exceptions
  621. Allocate( locexp(abs(nexep),4) & ! (local) exception bricks: row1,col1, row2,col2
  622. , ijexep(abs(nexep),2) & ! (kept) exceptions: brick#1, brick#2
  623. , expen(abs(nexep)) & ! (kept) exception expense value
  624. , stat=nAllocErr )
  625. if (nAllocErr .ne. 0) then
  626. write(*,*) 'Out of memory. Try reducing the model size.'
  627. stop
  628. endif
  629.  
  630. ! If # exceptions is positive, then use a scheme where the regularization
  631. ! row & column numbers are used to identify the blocks.
  632. ! An expen(i) value of zero means no penalty for those two blocks to be
  633. ! different.
  634. if (nexep .gt. 0) then
  635. do i = 1,nexep
  636. read (iof,*, end=198, err=199) (locexp(i,j),j=1,4),expen(i)
  637. end do
  638. ! If exception # is negative, use actual brick numbers.
  639. else if (nexep .lt. 0) then
  640. do i = 1,-nexep
  641. read (iof,*, end=198, err=199) (ijexep(i,j),j=1,2),expen(i)
  642. end do
  643. end if
  644.  
  645. ! we are done with the model file
  646. close (iof)
  647.  
  648. !cccccccccccccccccccc mesh file reading cccccccccccccccccccccccccccccccc
  649. !
  650. if (mshtyp(1:4) .ne. 'PW2D') call filerr( &
  651. & ' Mesh type not supported', iof)
  652. open (iof, file=mshfil, status='old', iostat=lerr)
  653. if (lerr .ne. 0) then
  654. write(*,*) ' Error opening mesh file'
  655. stop
  656. end if
  657.  
  658. ! read in mesh sizes, etc...
  659. read (iof,'(a)', end=198, err=199) string
  660. read (iof,*, end=188, err=189) lidx,nodey,nodez,nrfix,lfre,nexec
  661. ! errors:
  662. if (lidx .ne. 0) call filerr(' Mesh file not OCCAM file', iof)
  663. if (nrfix .ge. cnMaxFixedRes) call filerr('Too many fixed resistivities',iof)
  664.  
  665. ! Allocate things related to node values
  666. Allocate( iconb(nodeY) &
  667. , yy(nodeY), dly(nodeY) &
  668. , zz(nodeZ + cnAirLayers) &
  669. , dlz(nodeZ + cnAirLayers) &
  670. , npt(nodeZ + cnAirLayers,4,nodeY) &
  671. , apt(nodeZ,4,nodeY) & ! local var doesn't need air layers
  672. , stat=nAllocErr )
  673. if (nAllocErr .ne. 0) then
  674. write(*,*) 'Out of memory. Try reducing the model size.'
  675. stop
  676. endif
  677.  
  678. ! input values for fixed resistivities, if any
  679. if (nrfix .ge. 1) then
  680. read (iof,*, end=188, err=189) (y(i), i = 2,nrfix+1)
  681. end if
  682. ! input frequencies, if any (these are ignored)
  683. if (lfre .ge. 1) then
  684. read (iof,*, end=188, err=189) (dummy, i=1,lfre)
  685. end if
  686. ! input the element widths and heights
  687. read (iof,*, end=188, err=189) (dly(i), i = 1,nodey-1)
  688. read (iof,*, end=188, err=189) (dlz(i), i = 1,nodez-1)
  689. ! input site information, if any (these are ignored)
  690. read (iof,*, end=188, err=189) nsites, (dummy, i = 1,nsites)
  691. ! input the resistivity codes
  692. do i = 1, nodez-1
  693. do l = 1,4
  694. read (iof,'(1000a1)',end=188,err=189) (apt(i,l,j), j=1,nodey-1)
  695. enddo
  696. enddo
  697.  
  698. ! We are done with the mesh file
  699. close (iof)
  700.  
  701. !ccccccccccccccccccc statics file reading cccccccccccccccccccccccccccccc
  702. !
  703. if (ssfile(1:4) .eq. 'none' .or. ssfile(1:4) .eq. 'NONE') then
  704. iscon = 0
  705. nsb = 0
  706. else
  707. open (iof, file=ssfile, status='old', iostat=lerr)
  708. if (lerr .ne. 0) then
  709. write(*,*) ' Error opening static shift file'
  710. stop
  711. end if
  712. ! Read the stuff in it.
  713. read (iof,'(18x,a)', end=208, err=209) string
  714. if (string(1:17) .ne. 'OCCAM2MTSHIFT_1.0') call filerr( &
  715. & ' Static shift file not supported', iof)
  716. read (iof,'(18x,a)', end=208, err=209) string
  717. read (iof,'(18x,a)', end=208, err=209) string
  718. read (iof,'(18x,a)', end=208, err=209) string
  719. iscon = idcode(string, iof)
  720. read (iof,'(18x,a)', end=208, err=209) string
  721. sserr = rdcode(string, iof)
  722. read (iof,'(18x,a)', end=208, err=209) string
  723. nsb = idcode(string, iof)
  724. read (iof,'(a)', end=208, err=209) string
  725. do i = 1,nsb
  726. read (iof,*,end=208,err=209) isx1(i),isx3(i),shift(i),isfx(i)
  727. enddo
  728. close (iof)
  729. end if
  730.  
  731. !ccccccccccccccccccc prejudice file reading cccccccccccccccccccccccccccc
  732. !
  733. ! no prejudice: zero out the model pejudice and associated weights
  734. premod = 1.0
  735. prewt = 0
  736. if (prfile(1:4) .eq. 'none' .or. prfile(1:4) .eq. 'NONE') then
  737. nprej = 0
  738.  
  739. else
  740. ! read the prejudice file
  741. open (iof, file=prfile, status='old', iostat=lerr)
  742.  
  743. if (lerr .ne. 0) then
  744. write(*,*) ' Error opening model prejudice file'
  745. stop
  746. else
  747. write(*,*) 'Reading in prejudice file: ',prfile
  748. end if
  749. ! Read the stuff in it.
  750. read (iof,'(18x,a)', end=218, err=219) string
  751. !KWK 01-24-2006:
  752. ! old style prejudice file, needs full prejudice model
  753. if (string(1:16) .eq. 'OCCAM2MTPREJ_1.0') then
  754. read (iof,'(18x,a)', end=218, err=219) string
  755. read (iof,'(18x,a)', end=218, err=219) string
  756. nprej = idcode(string, iof)
  757. if (nprej .gt. nParams) then
  758. call filerr(' Too much prejudice', iof)
  759. endif
  760. read (iof,*,end=218,err=219) (premod(i), i=1,nprej)
  761. read (iof,*,end=218,err=219) (prewt(i), i=1,nprej)
  762. close (iof)
  763. elseif (string(1:16) .eq. 'OCCAM2MTPREJ_2.0') then
  764. !KWK new version just lists parameter number, premod and weight
  765. ! for any parameters to be prejudiced
  766. write(*,*) 'Prejudice file format: OCCAM2MTPREJ_2.0'
  767. read (iof,'(18x,a)', end=218, err=219) string
  768. nprej = idcode(string, iof)
  769. if (nprej .gt. nParams) then
  770. call filerr(' Too much prejudice', iof)
  771. endif
  772. ! read in prejudiced parameters line by line
  773. !KWK: still need to clean up the error messages
  774. write(*,*) 'Prejudiced parameters: ', nprej
  775. do i = 1,nprej
  776. read (iof,*,end=218,err=219) j,temp1,temp2
  777. if (j.gt.nParams) then
  778. write(*,*) 'prejudice for parameter:??',j
  779. call filerr(' Too much prejudice', iof)
  780. endif
  781. premod(j) = temp1
  782. prewt(j) = temp2
  783. ! write(*,*) '#,premod,prewt: ',j,premod(j),prewt(j)
  784. enddo
  785. close (iof)
  786. else
  787. call filerr(' Model prejudice file not supported', iof)
  788. endif
  789.  
  790. end if
  791.  
  792.  
  793. !
  794. !ccccccccccccccc set up mesh and penalty matrix info ccccccccccccccccccc
  795. !
  796.  
  797.  
  798. ! npt() runs from 0 (0) to 35 (Z), '?' is flagged as -99, to be overwritten
  799. ! from the parameter array later.
  800. do j = 1,nodey-1
  801. do l = 1,4
  802. do i = 1,nodez-1
  803. npt(i,l,j) = ichar(apt(i,l,j)) - 48
  804. if (npt(i,l,j) .eq. 15) npt(i,l,j) = -99 ! sends ? to 99
  805. if (npt(i,l,j) .eq. 42) npt(i,l,j) = -1 !sends Z to seawater
  806. if (npt(i,l,j) .gt. 9) npt(i,l,j) = npt(i,l,j) - 7 !sends A-Z to 10-35
  807. enddo
  808. enddo
  809. enddo
  810. !
  811. ! Set up the free parameter part of npt() and also laprm().
  812. ! The following block of code finds the outline of every parameter brick,
  813. ! and if any part of it is free, adds it to npt() and laprm().
  814. ! This block of code also computes the widths and thickness of the bricks,
  815. ! which will be needed later during the computation of the penalty matrix.
  816. !
  817. ! initialize the number of parameters and the top edge of bricks
  818. nprm = 0
  819. inz1 = 1
  820. ! for every layer in the reg. mesh
  821. do i = 1,nlay
  822. ! find the bottom edge of bricks and initialize the right edge of first brick
  823. inz2 = inz1 + irz(i) - 1
  824. iny1 = 1
  825. ! for every brick in that layer
  826. do j = 1,nrcol(i)
  827. ! set irindx() assuming that this brick is fixed (will be tested later)
  828. irindx(i,j) = 0
  829. ! find the right edge of brick
  830. iny2 = iny1 + abs(iry(i,j)) - 1
  831. ! test to see if the brick is free
  832. iffree = .false.
  833. do ii = inz1,inz2
  834. do jj = iny1, iny2
  835. do l = 1,4
  836. if (apt(ii,l,jj) .eq. '?') iffree = .true.
  837. enddo
  838. enddo
  839. enddo
  840. if (iffree) then
  841. ! it is a free param: incr count and set a new element of laprm
  842. nprm = nprm + 1
  843. laprm(nprm) = nprm + nrfix
  844.  
  845. ! set irindx() to point to the new parameter
  846. irindx(i,j) = nprm
  847.  
  848. ! find the thickness of the brick
  849. thick(nprm) = 0.0
  850. do ii = inz1, inz2
  851. thick(nprm) = thick(nprm) + dlz(ii)
  852. enddo
  853.  
  854. ! find the width of the brick
  855. width(nprm) = 0.0
  856. do jj = iny1, iny2
  857. width(nprm) = width(nprm) + dly(jj)
  858. enddo
  859.  
  860. ! record the FE nodes for the four corners of the block (top, left, bottom, right)
  861. icorn(nprm,1) = inz1
  862. icorn(nprm,2) = iny1
  863. icorn(nprm,3) = inz2+1
  864. icorn(nprm,4) = iny2+1
  865.  
  866. ! over the entire brick, including sub-triangles,
  867. ! test to see if triangular element is free and set npt() if it is
  868. do ii = inz1,inz2
  869. do jj = iny1, iny2
  870. do l = 1,4
  871. if (apt(ii,l,jj) .eq. '?') then
  872. npt(ii,l,jj) = nprm + nrfix
  873. end if
  874. enddo
  875. enddo
  876. enddo
  877. end if
  878. ! increment the left edge of brick
  879. iny1 = iny2 + 1
  880. enddo
  881. ! increment the top edge of bricks
  882. inz1 = inz2 + 1
  883. enddo
  884. !
  885. ! copy nprm into nbrick to give routines the number of parameters
  886. ! which are actually resistivity bricks (c.f. static shifts)
  887. nbrick = nprm
  888. !
  889. ! Now, the bricks on the edges of the mesh and the bottom of the mesh will have
  890. ! widths and thicknesses that are too large to use in regularization penalty. Set
  891. ! them equal to their inside neighbours. The indexing in this code is the same as
  892. ! above.
  893. do i = 1,nlay
  894. do j = 1, nrcol(i)
  895. ii = irindx(i,j)
  896. if (ii .gt. 0) then
  897. ! DGM Oct 2006 - if the row is one block wide, don't do the width adjustments!
  898. if (nrcol(i) > 1) then
  899. if (j .eq. 1) width(ii) = width(ii+1)
  900. if (j .eq. nrcol(i)) width(ii) = width(ii-1)
  901. endif
  902.  
  903. ! DGM Oct 2006 - the line below assumed the last two rows had the same
  904. ! number of columns ... which was probably BOGUS.
  905. ! So now I enforce the assumption.
  906. if (i .eq. nlay) then
  907. if(nrcol(i) == nrcol(i-1)) thick(ii) = thick(ii-nrcol(i))
  908. endif
  909. end if
  910. enddo
  911. enddo
  912. !
  913. ! search the penalty exceptions list to find the block numbers
  914. !
  915. if (nexep .gt. 0) then
  916. ! print*, 'Exceptions between blocks'
  917. do i = 1,nexep
  918. ijexep(i,1) = irindx(locexp(i,1),locexp(i,2))
  919. ijexep(i,2) = irindx(locexp(i,3),locexp(i,4))
  920. if ((ijexep(i,1).le.0) .and. (ijexep(i,2).le.0)) call filerr( &
  921. & ' Penalty requested for two fixed blocks; use prejudice file',0)
  922. ! print*, ijexep(i,1), ijexep(i,2)
  923. end do
  924. else
  925. nexep = -nexep
  926. end if
  927.  
  928. write(*,*) '# Exceptions: ', nexep
  929.  
  930. ! search the penalty exceptions list to find the block numbers
  931. ! do 97 i = 1,nexep
  932. ! ijexep(i,1) = irindx(locexp(i,1),locexp(i,2))
  933. ! ijexep(i,2) = irindx(locexp(i,3),locexp(i,4))
  934. ! if ((ijexep(i,1).le.0) .and. (ijexep(i,2).le.0)) call filerr(
  935. ! * ' Penalty requested for two fixed blocks; use prejudice file',0)
  936. !97 continue
  937. !c
  938. !ccccccccccccccccccc set up receiver locations ccccccccccccccccccccccccc
  939. !
  940. ! first find the position of the right edge of the left terminating layer:
  941. dummy = 0.0
  942. do i = 1, abs(iry(1,1))
  943. dummy = dummy + dly(i)
  944. enddo
  945. ! now find cumulative positions of all nodes (borrowing an array
  946. ! used for similar thing in PW2DI), zero out iconb()
  947. yy(1) = boffs - dummy
  948. iconb(1) = 0
  949. do i = 1,nodey-1
  950. iconb(i+1) = 0
  951. yy(i+1) = yy(i) + dly(i)
  952. enddo
  953. ! find the node locations for surface conductivity boundaries
  954. !kk l = 1
  955. !kk do 103 i = 1, nrcol(1)
  956. !kk l = l + iry(1,i)
  957. !kk iconb(l) = 1
  958. !kk103 continue
  959. ! now find the nodes closest to the station locations, avoiding conductivity
  960. ! boundaries
  961. do 110 i = 1, nrc
  962. do 105 j = 2,nodey
  963. if (yy(j) .ge. sitloc(i)) then
  964. if (yy(j)-sitloc(i) .le. sitloc(i)-yy(j-1)) then
  965. nrl(i) = j
  966. if (iconb(j) .eq. 1) nrl(i) = j-1
  967. else
  968. nrl(i) = j-1
  969. if (iconb(j-1) .eq. 1) nrl(i) = j
  970. end if
  971. goto 110
  972. end if
  973. 105 continue
  974. 110 continue
  975. if (idebug .ge. 1) then
  976. write(*,*) ' '
  977. write(*,*) 'station position node number actual position'
  978. do i = 1, nrc
  979. write(*,'(4X,f10.0,10X,i5,11X,f10.0)') sitloc(i), nrl(i), yy(nrl(i))
  980. enddo
  981. write(*,*) ' '
  982. end if
  983. ! now check to see if two stations occupy the same location
  984. !kk who cares!
  985. !kk do 115 i = 1, nrc
  986. !kk do 114 j = 1, nrc
  987. !kk if ((nrl(i) .eq. nrl(j)) .and. (i.ne.j)) then
  988. !kk call filerr(' Two stations on same node', 0)
  989. !kk end if
  990. !kk114 continue
  991. !kk115 continue
  992.  
  993. !ccccccccccccccccccc set up static shift arrays cccccccccccccccccccccccc
  994. !
  995. ! Examine the statics blocks, allocate new parameters and set up the
  996. ! data constriants
  997. nfss = 0
  998. tesum = 0.0
  999. tmsum = 0.0
  1000. if (nsb .eq. 0) iscon = 0
  1001. do 140 i = 1,nsb
  1002. if (isfx(i) .ne. 0) then
  1003. ! this static shift is a free parameter: add one more to the list
  1004. nfss = nfss + 1
  1005. if (nbrick + nfss .gt. nParams) call filerr( &
  1006. & ' No room for free statics in parameter array',0)
  1007. isfx(i) = nbrick + nfss
  1008. ! add a term to the constraint sums
  1009. if (isx3(i) .eq. 1) then
  1010. tesum = tesum + shift(i)
  1011. else if (isx3(i) .eq. 5) then
  1012. tmsum = tmsum + shift(i)
  1013. else
  1014. call filerr(' Can only apply statics to resistivities',0)
  1015. end if
  1016. end if
  1017. 140 continue
  1018. !
  1019. ! Set up the statics constraint
  1020. if (iscon.eq.0) then
  1021. ! no constraint: do nothing
  1022. continue
  1023. else if (iscon .eq. 1) then
  1024. ! constraint is to sum both TE and TM shifts together to whatever was the
  1025. ! sum in the statics file
  1026. nd = ndata + 1
  1027. call Realloc_dp_d_sd
  1028. dp(ndata+1,3) = -1
  1029. d(ndata+1) = tesum + tmsum
  1030. sd(ndata+1) = sserr
  1031. else if (iscon .eq. 2) then
  1032. ! constraint is to sum both TE and TM shifts separately to whatever was the
  1033. ! sum in the statics file
  1034. nd = ndata + 2
  1035. call Realloc_dp_d_sd
  1036. dp(ndata+1,3) = -2
  1037. dp(ndata+2,3) = -3
  1038. d(ndata+1) = tesum
  1039. d(ndata+2) = tmsum
  1040. sd(ndata+1) = sserr
  1041. sd(ndata+2) = sserr
  1042. else
  1043. call filerr ( &
  1044. & ' Statics constraints type greater than 2 not supported', 0)
  1045. end if
  1046. !
  1047. !nParams = nbrick + nfss
  1048. if (nParams .ne. nbrick + nfss) then
  1049. if (iscon == 0) then
  1050. call filerr( 'Model file error: # params <> # free bricks', 0 )
  1051. else
  1052. call filerr( 'Model or Static Shift error: # params <> # free bricks + # static shift params', 0 )
  1053. endif
  1054. endif
  1055.  
  1056.  
  1057. !cccccccccccccccccccccc clean up and leave cccccccccccccccccccccccccccc
  1058. !
  1059. ! Allocate things related to the number of data (and potentially
  1060. ! extra elements for statics).
  1061. ! Use nd instead of ndata because it will reflect the extra elements.
  1062. allocate( dm(nd) &
  1063. , dwk1(nd) &
  1064. , dwk3(nd) &
  1065. , dwk4(nd) &
  1066. , stat=nAllocErr )
  1067. if (nAllocErr .ne. 0) then
  1068. write(*,*) 'Out of memory. Try reducing the model size'
  1069. stop
  1070. endif
  1071.  
  1072. ! We should have read the iteration file already and set nParams. Test for
  1073. ! consistency with nbrick and nfss
  1074. if (nParams .ne. nbrick+nfss) &
  1075. & call filerr (' Model file and nParams do not match', 0)
  1076.  
  1077.  
  1078. if (abs(idebug) .ge. 1) then
  1079. write(*,*) nodey, ' x ', nodez, ' FE mesh read'
  1080. write(*,*) nParams, ' model parameters defined'
  1081. end if
  1082.  
  1083. return
  1084.  
  1085. 188 call filerr (' Mesh file ended prematurely', iof)
  1086. 189 call filerr (' Error reading mesh file', iof)
  1087. 198 call filerr (' Model file ended prematurely', iof)
  1088. 199 call filerr (' Error reading model file', iof)
  1089. 208 call filerr (' Statics file ended prematurely', iof)
  1090. 209 call filerr (' Error reading statics file', iof)
  1091. 218 call filerr (' Prejudice file ended prematurely', iof)
  1092. 219 call filerr (' Error reading prejudice file', iof)
  1093. !
  1094. end
  1095.  
  1096. !-----------------------------------------------------------------------
  1097. subroutine Realloc_dp_d_sd
  1098. !-----------------------------------------------------------------------
  1099. ! OCCAM MT2D 3.0 Package
  1100. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  1101. ! Subroutine Revision 3.0, November 2006
  1102. ! When statics params are included in the inversion, they
  1103. ! *may* add one or two new rows to 'nd' so that nd = ndata + 1 or 2.
  1104. ! Various data arrays have to be reallocated to accommodate this.
  1105. use Occam_mod
  1106. use Fwd_mod
  1107. implicit none
  1108.  
  1109. ! Local vars to hold existing values during the realloc.
  1110. real, dimension(:), allocatable :: d_old, sd_old
  1111. real, dimension(:,:), allocatable :: dp_old
  1112. integer :: nDim, nAllocErr
  1113.  
  1114. nDim = size(d,1)
  1115.  
  1116. ! Allocate buffers to hold the old & copy the values
  1117. allocate( d_old(nDim), sd_old(nDim), dp(nDim,cnDataParams) &
  1118. , stat=nAllocErr )
  1119. if (nAllocErr .ne. 0) then
  1120. write(*,*) 'Out of memory. Try reducing the model size.'
  1121. stop
  1122. endif
  1123.  
  1124. d_old = d
  1125. sd_old = sd
  1126. dp_old = dp
  1127.  
  1128. ! Reallocate the targets & copy the data back over
  1129. deallocate( d, sd, dp )
  1130. allocate( d(nd), sd(nd), dp(nd,cnDataParams) &
  1131. , stat=nAllocErr )
  1132. if (nAllocErr .ne. 0) then
  1133. write(*,*) 'Out of memory. Try reducing the model size.'
  1134. stop
  1135. endif
  1136.  
  1137. d(:nDim) = d_old
  1138. sd(:nDim) = sd_old
  1139. dp(:nDim,:) = dp_old
  1140.  
  1141. ! release our local buffers
  1142. deallocate( d_old, sd_old, dp_old )
  1143.  
  1144. return
  1145. end subroutine Realloc_dp_d_sd
  1146.  
  1147.  
  1148. !-----------------------------------------------------------------------
  1149. subroutine FwdCalc( bDoPartials, np, nd, pm, dp, dm, d, wj )
  1150. !-----------------------------------------------------------------------
  1151. ! OCCAM MT2D 3.0 Package
  1152. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  1153. ! Subroutine Revision 3.0, November 2006
  1154. ! DGM Oct 2006: Routine combined from old formod & fordiv routines which
  1155. ! were identical except for addition of 'wj' handling (jacobian) in
  1156. ! fordiv. Parameter 'wj' is now optional: reqd only if (bDoPartials).
  1157. ! Notes from previous function headers:
  1158. ! revision to allow for impedance data - cdh -Feb 23, 1994
  1159. ! Impedances are broken up into real and imaginary
  1160. ! parts so that all data can be treated as real
  1161. ! allows for multiplication by decomposition matrix
  1162. ! KWK Feb 23,2006 input d(nd) to compare for 360 degree phase wraps
  1163.  
  1164. ! includes:
  1165. Use Occam_mod, only: idebug
  1166. USE Fwd_mod
  1167.  
  1168. IMPLICIT NONE
  1169.  
  1170. ! arguments:
  1171. logical, intent(in) :: bDoPartials
  1172. integer :: np, nd ! # parameters, # data
  1173. real, intent(in) :: pm(np) ! input model parameters
  1174. real, intent(in) :: dp(nd,4) ! 4 cols: see defn in module
  1175. real, intent(out) :: dm(nd) ! output data: apparent resistivity, phase, etc....
  1176. real, intent(in) :: d(nd) ! original input data
  1177. real, optional :: wj(nd,np) ! output jacobians
  1178.  
  1179. ! local variables
  1180. real :: tesum, tmsum, p0, pm360, pp360, e10
  1181. ! tesum = sum of logs of TE free static shifts
  1182. ! tmsum = sum of logs of TM free static shifts
  1183. integer :: i, j, nres, itype, isite, ifreq
  1184. ! i,j = loop counters
  1185. ! nres = number of resistivities in y() array
  1186. ! itype, isite, ifreq = integer versions of dp() entries
  1187. real :: nRMin, nRMax
  1188. ! nRMin/ax - used for tracking input to PW2DI. If the range is too large,
  1189. ! the forward model will choke big time.
  1190.  
  1191. !------------------------------------------------
  1192.  
  1193.  
  1194. ! total number of resistivities = fixed resistivities + free res'ties
  1195. ! (but not air)
  1196. nres = nrfix + nbrick
  1197. tesum = 0.0
  1198. tmsum = 0.0
  1199. e10 = alog(10.) ! 1/log10(e)
  1200.  
  1201. ! Make sure that the model params are converted into resistivities.
  1202. ! Input resistivities should be placed into array 'y'
  1203. y(1) = 1/3.25 ! init the "water" entry. Fixed resistivities set in inputd()
  1204. forall( i=1:nbrick ) y(nrfix+1+i) = 10.**pm(i)
  1205.  
  1206. ! copy across any static shifts in the free parameters
  1207. if (nfss .gt. 0) then
  1208. do j = 1,nsb
  1209. if (isfx(j) .ne. 0) shift(j) = pm(isfx(j))
  1210. enddo
  1211. end if
  1212.  
  1213. ! As an info step, look at the range of the min & max resistivities that
  1214. ! are being passed to the forward model. If this range is too large
  1215. ! the forward model will fail or produce unstable results.
  1216. if (abs(idebug) >= 1) then
  1217. nRMax = maxval( y(nrfix+2:nrfix+1+nbrick) )
  1218. nRMin = minval( y(nrfix+2:nrfix+1+nbrick) )
  1219. write(*,*) ' '
  1220. write(*,*) ' Fwd model resistivity range:', nRMin, ' ', nRMax
  1221. if (nRMax > 10e7) then
  1222. write(*,*) '!!WARNING!! RESISTIVITIES TOO HIGH. FORWARD MODEL MIGHT FAIL!'
  1223. write(*,*) 'Moving resistivity back down to finite range!'
  1224. where (y>10e7) y = 10e7
  1225. nRMax = maxval( y(nrfix+2:nrfix+1+nbrick) )
  1226. nRMin = minval( y(nrfix+2:nrfix+1+nbrick) )
  1227. write(*,*) ' Fwd model resistivity range:', nRMin, ' ', nRMax
  1228. endif
  1229. if (nRMin < 10e-7) then
  1230. write(*,*) '!!WARNING!! RESISTIVITIES TOO LOW. FORWARD MODEL MIGHT FAIL!'
  1231. write(*,*) 'Moving resistivity back up to finite range!'
  1232. where (y<10e-7) y = 10e-7
  1233. nRMax = maxval( y(nrfix+2:nrfix+1+nbrick) )
  1234. nRMin = minval( y(nrfix+2:nrfix+1+nbrick) )
  1235. write(*,*) ' Fwd model resistivity range:', nRMin, ' ', nRMax
  1236. endif
  1237.  
  1238. endif
  1239.  
  1240. ! compute the MT response
  1241. if (bDoPartials) then
  1242. call PW2DI(nres, 2) ! 2 = Compute resp + compute jacobian
  1243. else
  1244. call PW2DI(nres, 1) ! 1 = Compute response
  1245. endif
  1246.  
  1247. ! For every datum:
  1248. ! Note: As of Oct 2006, derivatives from PW2DI are NOT wrt
  1249. ! log10(resistivity). They need to be converted to log space.
  1250. do i = 1, ndata
  1251.  
  1252. ! strip off data from dp(:,4)
  1253. ! dp(:,1) = site number
  1254. ! dp(:,2) = frequency number
  1255. ! dp(:,3) = data type (see defn of dp in module)
  1256. ! dp(:,4) = input strike angle
  1257. isite = int(dp(i,1)+0.1)
  1258. ifreq = int(dp(i,2)+0.1)
  1259. itype = int(dp(i,3)+0.1)
  1260.  
  1261. select case (iType)
  1262. case (1) ! TE Resistivity (log10)
  1263. dm(i) = alog10(rhte(isite,ifreq))
  1264. if (bDoPartials) then
  1265. ! from drho_a/dsigma_m to dlog10rho_a/dlog10rho_m
  1266. forall( j=1:nbrick ) wj(i,j) = -rted(j,iSite,iFreq) / rhte(iSite,iFreq) / y(j+1)
  1267. endif
  1268.  
  1269. case (9) ! TE Resistivity (linear)
  1270. dm(i) = rhte(isite,ifreq)
  1271. if (bDoPartials) then
  1272. wj(i,1:nbrick) = rted(1:nbrick,iSite,iFreq)
  1273. endif
  1274.  
  1275. case (2) ! TE Phase
  1276. dm(i) = phte(isite,ifreq)
  1277.  
  1278. ! KWK Feb 23, 2006, phase shifting:
  1279. p0 = abs(dm(i) - d(i))
  1280. pm360 = abs(dm(i) - 360. -d(i))
  1281. pp360 = abs(dm(i) + 360. -d(i))
  1282.  
  1283. if (pm360.lt.p0) then ! +- 360 degrees if misfit is better
  1284. dm(i) = dm(i) - 360.
  1285. elseif (pp360.lt.p0) then
  1286. dm(i) = dm(i) + 360.
  1287. endif
  1288.  
  1289.  
  1290. if (bDoPartials) then
  1291. wj(i,1:nbrick) = pted(1:nbrick,iSite,iFreq)
  1292. endif
  1293.  
  1294. case (3) ! real(tipper)
  1295. dm(i) = real(kzte(isite,ifreq))
  1296. if (bDoPartials) then
  1297. wj(i,1:nbrick) = real(kted(1:nbrick,iSite,iFreq))
  1298. endif
  1299.  
  1300. case (4) ! imag(tipper)
  1301. dm(i) = aimag(kzte(isite,ifreq))
  1302. if (bDoPartials) then
  1303. wj(i,1:nbrick) = aimag(kted(1:nbrick,iSite,iFreq))
  1304. endif
  1305.  
  1306. case (5) ! TM resistivity (log10)
  1307. dm(i) = alog10(rhtm(isite,ifreq))
  1308. if (bDoPartials) then
  1309. ! from drho_a/dsigma_m to dlog10rho_a/dlog10rho_m
  1310. forall( j=1:nbrick ) wj(i,j) = -rtmd(j,iSite,iFreq) / rhtm(iSite,iFreq) / y(j+1)
  1311. endif
  1312.  
  1313. case (10) ! TM resistivity (linear)
  1314. dm(i) = rhtm(isite,ifreq)
  1315. if (bDoPartials) then
  1316. wj(i,1:nbrick) = rtmd(1:nbrick,iSite,iFreq)
  1317. endif
  1318.  
  1319. case (6) ! TM phase
  1320. dm(i) = phtm(isite,ifreq)
  1321.  
  1322. ! KWK Feb 23, 2006, phase shifting:
  1323. p0 = abs(dm(i) - d(i))
  1324. pm360 = abs(dm(i) - 360. -d(i))
  1325. pp360 = abs(dm(i) + 360. -d(i))
  1326. if (pm360.lt.p0) then ! +- 360 degrees if misfit is better
  1327. dm(i) = dm(i) - 360.
  1328. elseif (pp360.lt.p0) then
  1329. dm(i) = dm(i) + 360.
  1330. endif
  1331.  
  1332. if (bDoPartials) then
  1333. wj(i,1:nbrick) = ptmd(1:nbrick,iSite,iFreq)
  1334. endif
  1335.  
  1336.  
  1337. case (11, 12, 17, 18) ! real(Zxx), imag(Zxx), ... Zyy
  1338. dm(i) = 0.
  1339. if (bDoPartials) &
  1340. wj(i,1:nbrick) = 0
  1341.  
  1342. case (13) ! real(Zxy)
  1343. dm(i) = real(zimpe(isite,ifreq))
  1344. if (bDoPartials) then
  1345. wj(i,1:nbrick) = real(zimped(1:nbrick,iSite,iFreq))
  1346. endif
  1347.  
  1348. case (14) ! imag(Zxy)
  1349. dm(i) = aimag(zimpe(isite,ifreq))
  1350. if (bDoPartials) then
  1351. wj(i,1:nbrick) = aimag(zimped(1:nbrick,iSite,iFreq))
  1352. endif
  1353.  
  1354. case (15) ! real(Zyx)
  1355. dm(i) = real(zimpm(isite,ifreq))
  1356. if (bDoPartials) then
  1357. wj(i,1:nbrick) = real(zimpmd(1:nbrick,iSite,iFreq))
  1358. endif
  1359.  
  1360. case (16) ! imag(Zyx)
  1361. dm(i) = aimag(zimpm(isite,ifreq))
  1362. if (bDoPartials) then
  1363. wj(i,1:nbrick) = aimag(zimpmd(1:nbrick,iSite,iFreq))
  1364. endif
  1365.  
  1366. case default
  1367. write(*,*) 'Unknown Data type:', iType
  1368. write(*,*) 'Need to implement this type in FwdCalc(). Stopping.'
  1369. stop
  1370. end select
  1371.  
  1372. ! Convert from d.../dsigma_m to d.../dlog10rho_m. The conversion is the same
  1373. ! for almost all derivatives because only the denominator of the derivative
  1374. ! (which doesn't depend on the data type) is being converted:
  1375. ! dG/dlog10rho_m = dG/dsigma_m * dsigma_m/drho_m * drho_m/dlog10rho_m
  1376. ! <want> <have> <conversion factors>
  1377. ! Similar with bounded constraints where denom is not dlog10rho_m but some
  1378. ! other function of rho_m.
  1379. if (bDoPartials) then
  1380. ! TE & TM log10 resistivity are done in the case above because
  1381. ! their transformations are slightly different.
  1382. if (iType .ne. 1 .and. iType .ne. 5) then
  1383. forall( j=1:nbrick )
  1384. wj(i,j) = -1*wj(i,j)*e10 / y(j+1)
  1385. end forall
  1386. endif
  1387. endif
  1388.  
  1389. ! Handle the static shifts
  1390. if (bDoPartials) then
  1391. ! Zero out any additional columns of the Jacobian matrix associated
  1392. ! with free static shifts (there might not be a free shift for this
  1393. ! datum)
  1394. do j = 1, nfss
  1395. wj(i,nbrick+j) = 0.0
  1396. enddo
  1397. endif
  1398.  
  1399. ! Search the static shifts to see if one applies to this datum:
  1400. do j = 1, nsb
  1401. if ((isx1(j).eq.isite) .and. (isx3(j).eq.itype)) then
  1402. ! apply the static shift
  1403. dm(i) = dm(i) + shift(j)
  1404.  
  1405. ! If this shift is a free parameter set the augmentation of WJ to 1.0
  1406. if (bDoPartials .and. isfx(j) .ne. 0) wj(i,isfx(j)) = 1.0
  1407. end if
  1408. enddo
  1409.  
  1410. enddo ! all data
  1411.  
  1412. ! Now compute the sums used in the static shift constraint
  1413. do j = 1, nsb
  1414. if (isfx(j) .ne. 0) then
  1415. ! compute the sum of shifts for the shift constrains
  1416. if (isx3(j) .eq. 1) then
  1417. tesum = tesum + shift(j)
  1418. else if (isx3(j) .eq. 5) then
  1419. tmsum = tmsum + shift(j)
  1420. end if
  1421. end if
  1422. enddo
  1423.  
  1424. ! Now add rows to the Jacobian matrix for static shift
  1425. ! constraints and create the synthetic constraint data
  1426. select case (iscon)
  1427. case (0) ! no constraint: do nothing
  1428. continue
  1429.  
  1430. case (1) ! constraint is to sum both TE and TM shifts together
  1431. dm(ndata+1) = tesum + tmsum
  1432.  
  1433. if (bDoPartials) then
  1434. ! zero out those cols of wj associated with model resistivities
  1435. wj(nData+1,1:nBrick) = 0.0
  1436.  
  1437. ! set those cols of wj associated with free static shifts
  1438. ! to all ones for TE + TM summing
  1439. do j = 1, nfss
  1440. wj(ndata+1,nbrick+j) = 1.0
  1441. enddo
  1442. endif
  1443.  
  1444. case (2) ! constraint is to sum both TE and TM shifts separately
  1445. dm(ndata+1) = tesum
  1446. dm(ndata+2) = tmsum
  1447.  
  1448. if (bDoPartials) then
  1449. ! zero out those cols of wj associated with model resistivities
  1450. wj(ndata+1:ndata+2,1:nBrick) = 0.0
  1451.  
  1452. ! set those cols of wj associated with free static shifts
  1453. ! (need to test for either TE or TM sum)
  1454. do j = 1, nsb
  1455. if (isfx(j) .ne. 0) then
  1456. if (isx3(j) .eq. 1) then ! TE constraint
  1457. wj(ndata+1,isfx(j)) = 1.0
  1458. wj(ndata+2,isfx(j)) = 0.0
  1459. else if (isx3(j) .eq. 5) then ! TM constraint
  1460. wj(ndata+1,isfx(j)) = 0.0
  1461. wj(ndata+2,isfx(j)) = 1.0
  1462. end if
  1463. end if
  1464. enddo
  1465. endif
  1466. end select
  1467.  
  1468. return
  1469. end subroutine FwdCalc
  1470.  
  1471.  
  1472. !-----------------------------------------------------------------------
  1473. subroutine OutFwd( cFile )
  1474. !-----------------------------------------------------------------------
  1475. ! OCCAM MT2D 3.0 Package
  1476. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  1477. ! Subroutine Revision 3.0, November 2006
  1478. use Occam_Mod
  1479. use Fwd_mod
  1480. implicit none
  1481.  
  1482. ! Arguments
  1483. character(*), intent(in) :: cFile
  1484.  
  1485. ! Local vars
  1486. integer :: i, j
  1487.  
  1488. open( unit=42, file=cFile )
  1489. write(42,'(A)') 'FORMAT: OCCAM2MTDATA_1.0 '
  1490. write(42,'(A)') 'TITLE: Forward model response from Occam2D'
  1491. write(42,'(A,I4)') 'SITES: ', nRc
  1492. write(42,'(A)') (trim(cSiteName(i)), i=1,nRc)
  1493. write(42,'(A)') 'OFFSETS (M):'
  1494. write(42,'(G14.6)') (SitLoc(i), i=1, nRc)
  1495. write(42,'(A,I4)') 'FREQUENCIES: ', nFre
  1496. write(42,'(G14.6)') (frek(i), i=1, nFre)
  1497. write(42,'(A,I4)') 'DATA BLOCKS: ', nd
  1498. write(42,'(A)') 'SITE FREQ TYPE DATUM ERROR'
  1499. do i=1,nd
  1500. write(42,'(3I6,2(2X,G14.6))') (INT(DP(i,j)), j=1,3),DM(i),SD(i)
  1501. enddo
  1502.  
  1503. close(42)
  1504.  
  1505. return
  1506. end subroutine OutFwd
  1507.  
  1508.  
  1509. ! **********************************************************************
  1510. SUBROUTINE PW2DI(NRES,NEXEC)
  1511. ! **********************************************************************
  1512. ! OCCAM MT2D 3.0 Package
  1513. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  1514. ! Subroutine Revision 3.0, November 2006
  1515. ! Original code written by Phil Wannamaker.
  1516. ! July 25, 2001 - alteration to FwdCalc, PW's new adjoint method
  1517. ! used, which returns derviatives with respect to log(resistivity)
  1518. ! Additions & edits by Catherine DeGroot-Hedlin, Kerry Key, & David Myer.
  1519. !
  1520. !========================== INCLUDE FILES ==============================
  1521. !
  1522. use Occam_Mod
  1523. USE Fwd_mod
  1524.  
  1525.  
  1526. IMPLICIT NONE
  1527.  
  1528. !
  1529. !============================ INTERFACE ================================
  1530. !
  1531. ! WRITTEN BY: P. WANNAMAKER, UURI.
  1532. !
  1533. ! DESCRIPTION:
  1534. !
  1535. ! FOR THE FORWARD PROBLEM AND JACOBIANS,
  1536. ! FINITE ELEMENTS ARE USED WITH LINEAR BASIS FUNCTIONS. TOPO-
  1537. ! GRAPHIC OR BATHYMETRIC VARIATIONS ACROSS THE PROFILE CAN BE
  1538. ! INCLUDED AS WELL (WANNAMAKER ET AL, 1986, GEOPHYSICS). MKS
  1539. ! UNITS AND EXP(+JWT) TIME DEPENDENCE ARE ASSUMED. THE + COORD-
  1540. ! INATE DIRECTIONS FOR THE PROBLEM ARE X- NORTH, Y-EAST, Z-DOWN.
  1541. ! STRIKE DIRECTION IS ASSUMED N-S. ORIGIN IS AT A USER-SPECIFIED
  1542. ! NODAL COLUMN AT THE HIGHEST TOPOGRAPHIC POINT. A SECONDARY
  1543. ! FIELD FORMULATION OF THE FINITE ELEMENT EQUATIONS HAS BEEN
  1544. ! UTILIZED HERE TO IMPROVE ACCURACY (WANNAMAKER ET AL, 1987, GEOP.
  1545. ! J. ROY. ASTR. SOC.). THE LAYERED HOST FOR THE INHOMOGENEITY BY
  1546. ! CONVENTION IS TAKEN TO BE THAT WITH THE HIGHER RESISTIVITY IN
  1547. ! THE UPPERMOST LAYER. IN THIS VERSION, THE PARAMETER JACOBIANS
  1548. ! ARE COMPUTED BY TAKING ADVANTAGE OF RECIPROCITY. THERE IS A
  1549. ! REPORT DOCUMENTATION BY WANNAMAKER (1990) DESCRIBING THE METHOD.
  1550. !
  1551. ! ROUTINES NEEDED: PW2DI, PARFLD, COAMP, ZLFLD, GAUSS, AUXFLD,
  1552. ! BNORM, DERIV, APPARMT, addair, RECIJAC, PARJAC,
  1553. ! GAUSSD, AUXADJ, APPRMTJ, DRVADJ
  1554. !
  1555. ! ON INPUTS:
  1556. ! NRES - NO. OF UNIQUE RESISTIVITY MEDIA IN THE MESH
  1557. ! (INCLUDES ANY SEAWATER BUT NOT THE AIR)
  1558. ! NFRE - NO. OF FREQUENCIES TO BE MODELED
  1559. ! NEXEC - IF .EQ. 0, JUST PRINT INPUT PARAMETERS AND MESH
  1560. ! TO CHECK CORRECTNESS
  1561. ! - IF .EQ. 1, COMPUTE RESPONSE
  1562. ! - IF .EQ. 2, INVERT DATA
  1563. ! Y - ARRAY OF RESISTIVITIES OF MEDIA MAKING UP THE MESH;
  1564. ! LAST VALUE IS THAT OF ANY SEAWATER.
  1565. ! FREK - ARRAY OF FREQUENCIES
  1566. ! NRL - SITE LOCATIONS BY FE MESH NODE NUMBER
  1567. !
  1568. ! /BLKI/ IDX - PARAMETER DEFINING MODE OF PROBLEM TO BE SOLVED
  1569. ! - IF .EQ. 1, SOLVE BOTH TE AND TM
  1570. ! - IF .EQ. 2, SOLVE TE ONLY
  1571. ! - IF .EQ. 3, SOLVE TM ONLY
  1572. ! /BLKI/ NODEY - NO. OF NODES IN THE Y-DIRECTION OF THE FINITE
  1573. ! ELEMENT MESH
  1574. ! /BLKI/ NODEZ - NO. OF NODES IN THE Z-DIRECTION OF THE FINITE
  1575. ! ELEMENT MESH
  1576. ! /BLKI/ NPRM - NO. OF POLYGONAL MEDIA OF INVERSION MODEL
  1577. ! /BLKI/ LAPRM - INTEGER LABELS OF EACH INVERSION MEDIUM
  1578. ! /BLKD/ DLY - ARRAY OF ELEMENT COLUMN WIDTHS
  1579. ! /BLKD/ DLZ - ARRAY OF ELEMENT ROW HEIGHTS
  1580. ! /BLKE/ NPT - INTEGER LABELS FOR EACH TRIANGULAR ELEMENT OF EACH
  1581. ! RECTANGULAR ELEMENT OF THE MESH. THESE LABELS ARE
  1582. ! ASSIGNED THE VALUES IN THE RESISTIVITY ARRAY Y.
  1583. ! LABEL 0 IS RESERVED FOR AIR AND LABEL -1 IS RESERVED
  1584. ! FOR SEAWATER. TRIANGULAR ELEMENT LABELING ORDER IS
  1585. ! TOP, LEFT, BOTTOM AND RIGHT.
  1586. !
  1587. !============== PARAMETER AND LOCAL VARIABLE DECLARATIONS ==============
  1588. !
  1589. ! ---- PASS PARAMETERS
  1590. INTEGER NRES,NEXEC
  1591. !
  1592. ! ---- LOCAL VARIABLES
  1593. INTEGER lidx,NODEY1,MAIR,NODEZ1
  1594. INTEGER I,J,K,L,M,III,NYRB
  1595. real conds(0:NRES+1)
  1596. !
  1597. !
  1598. !=======================================================================
  1599.  
  1600. ! Make sure the things we need are allocated. If already allocated
  1601. ! this call will do no harm. Make sure that there are enough extra
  1602. ! Z nodes to account for the air layers added (them removed) by the
  1603. ! calls to AddAir().
  1604. call Fwd_Allocate( NRC, NRES, nParams, nfre, nlay, nodey, nodez + cnAirLayers)
  1605.  
  1606. NODEY1 = NODEY - 1
  1607. !
  1608. ! ---- DEFINE LOCATION OF Y=0 AT CENTER OF MESH
  1609. YY(1) = 0.0
  1610. DO 20 I = 2,NODEY
  1611. YY(I) = YY(I-1) + DLY(I-1)
  1612. 20 CONTINUE
  1613. !
  1614. DO 30 I = 1,NODEY
  1615. YY(I) = YY(I) - YY(NODEY)/2.
  1616. 30 CONTINUE
  1617. !
  1618. ! add the air layer if necessary
  1619. lidx = idx
  1620. call addair(lidx, mair) ! if TE involved, will extra air layers and modify nodez
  1621.  
  1622. NODEZ1 = NODEZ - 1
  1623. NTR = MAIR + 1
  1624. !
  1625. ! ---- CHANGE FROM RESISTIVITIES INPUT TO CONDUCTIVITIES AND
  1626. ! ASSOCIATE CONDUCTIVITIES WITH THE MESH INPUT CODE
  1627. conds(1) = 1.0E-18 ! air conductivity
  1628. conds(0) = 3.25 ! seawater conductivity
  1629. DO 90 I = 2,NRES+1
  1630. conds(i) = 1./Y(I)
  1631. 90 CONTINUE
  1632. !
  1633. ! ISEA=NRES+1
  1634. ISEA = -1 !Changed by Kerry, Aug 17, 2001
  1635. ! conds(ISEA+1) = 1./Y(NRES+1)
  1636. DO 100 J = 1,NODEZ1
  1637. DO 101 L = 1,NODEY1
  1638. DO 102 M = 1,4
  1639. K = NPT(J,M,L)
  1640. SIG(J,M,L) = conds(K+1) ! K=0 is air, K=-1 is seawater
  1641. 102 CONTINUE
  1642. 101 CONTINUE
  1643. 100 CONTINUE
  1644. !
  1645. ! ---- POSITION THE DATUM (HIGHEST TOPOGRAPHIC POINT)
  1646. L = NTR
  1647. ZZ(L) = 0.
  1648. DO 110 I = NTR,NODEZ1
  1649. ZZ(L+1) = ZZ(L) + DLZ(I)
  1650. L = L + 1
  1651. 110 CONTINUE
  1652. !
  1653. IF(MAIR .NE. 0)THEN
  1654. L = NTR
  1655. DO 130 III = 1,MAIR
  1656. I = MAIR + 1 - III
  1657. ZZ(L-1) = ZZ(L) - DLZ(I)
  1658. L = L - 1
  1659. 130 CONTINUE
  1660. END IF
  1661. !
  1662. ! ---- SPECIFY NODAL ROW DEPRESSIONS OF TOPO/BATH SURFACE.
  1663. DO 140 I = 2,NODEY1
  1664. NTAO(I) = 0
  1665. DO 141 J = NTR,NODEZ1
  1666. IF(NPT(J,4,I-1) .EQ. 0 .AND. NPT(J,2,I) .EQ. 0 )GO TO 142
  1667. IF(NPT(J,4,I-1) .EQ. ISEA .AND. NPT(J,2,I) .EQ. ISEA)GO TO 142
  1668. GO TO 140
  1669. 142 CONTINUE
  1670. NTAO(I) = J - MAIR
  1671. 141 CONTINUE
  1672. 140 CONTINUE
  1673. NTAO(1) = NTAO(2)
  1674. NTAO(NODEY) = NTAO(NODEY1)
  1675. ! write(*,*),'ntao',(NTAO(i),i=1,nodey)
  1676. !
  1677. ! ---- DISCERN BOUNDARY LAYERING PARAMETERS FROM INPUT MESH
  1678. NYRB = 1
  1679. DO 150 I = 1,2
  1680. IF(I .EQ. 2)NYRB = NODEY1
  1681. NOLA(I) = 1
  1682. NZZB(I) = NTR
  1683. DO 160 J = NTR,NODEZ1-1
  1684. !
  1685. ! ---- PATCH TO PREVENT ARRAY OVERRUN
  1686. IF (NOLA(I) .GE. nLay)GOTO 160
  1687. IF(NPT(J,1,NYRB) .EQ. 0)THEN
  1688. NZZB(I) = J + 1
  1689. ELSE
  1690. RLR(NOLA(I),I) = 1./SIG(J,2*I,NYRB)
  1691. IF(NPT(J,2*I,NYRB) .NE. NPT(J+1,2*I,NYRB))THEN
  1692. DLR(NOLA(I),I) = ZZ(J+1) - ZZ(NZZB(I))
  1693. NOLA(I) = NOLA(I) + 1
  1694. END IF
  1695. END IF
  1696. 160 CONTINUE
  1697. RLR(NOLA(I),I) = 1./SIG(NODEZ1,2*I,NYRB)
  1698. 150 CONTINUE
  1699. ! calling new version of PARFLD, etc
  1700. !
  1701. NDX = IDX
  1702. NMODE = 1
  1703. IF(NDX .EQ. 1) NMODE = 2
  1704. if (abs(idebug) >= 1) write(*,'(" Freq #: ",$)') ! suppress CR
  1705. DO 180 LFRQ = 1,NFRE
  1706. if (abs(idebug) >= 1) write(*,'(I3,$)') LFRQ ! suppress CR
  1707. !
  1708. DO 200 IMD = 1,NMODE
  1709. !
  1710. ! ---- FORM AND SOLVE GLOBAL SYSTEM OF EQUATIONS
  1711. CALL PARFLD
  1712. !
  1713. ! ---- CALCULATE AUXILIARY FIELDS, REAL AND IMAGINARY,
  1714. ! AND APPARENT RESISTIVITY AND PHASE AND TIPPER
  1715. !
  1716. CALL APPARMT
  1717. !
  1718. ! CALCULATE DATA-PARAMETER JACOBIAN IF INVERSION IS SELECTED.
  1719. !
  1720. IF(NEXEC .EQ. 2)THEN
  1721. CALL RECIJAC(NRES)
  1722. END IF
  1723. !
  1724. 200 CONTINUE
  1725. 180 CONTINUE
  1726. if (abs(idebug) >= 1) write (*,*) ' ' ! force CR at end of line
  1727. IDX=NDX
  1728. !
  1729. ! remove the air layer if necessary
  1730. call addair(0, mair) ! if TE involved, will remove extra air layers added above
  1731.  
  1732. RETURN
  1733. END SUBROUTINE PW2DI
  1734.  
  1735. !
  1736. !-----------------------------------------------------------------------
  1737. subroutine addair(lidx, mair)
  1738. !-----------------------------------------------------------------------
  1739. !
  1740. ! OCCAM MT2D 3.0 Package
  1741. ! Steven Constable, Kerry Key, David Myer IGPP/SIO La Jolla CA 92093-0225
  1742. ! Subroutine Revision 3.0, November 2006
  1743. ! Subroutine Revision 1.01, 13 Jan 1993
  1744. !
  1745. ! addair adds or removes an air layer of 10 nodes
  1746. ! from the FE mesh (nodez, dlz(), npt() in common blocks)
  1747. ! if a TE mode calculation is being done. Much of this code has been
  1748. ! abstracted from Phil Wannamaker's PW2DI
  1749. !
  1750. ! on input:
  1751. ! lidx = flag for direction and action (local version of one in PW2DI):
  1752. ! = 1 or 2 causes addition of air layer
  1753. ! = 3 sets mair = 0 and does nothing else
  1754. ! = otherwise removes air layer
  1755. ! mair = unchanged from any previous call to addair
  1756. !
  1757. ! on ouput:
  1758. ! mair = number of air layers, 0 for TM, 10 for TE
  1759. ! /blki/nodez, /blkd/dlz() and /blke/npt() are modified for TE calculation
  1760. !
  1761. ! calls:
  1762. ! no other routines
  1763. !
  1764. !-----------------------------------------------------------------------
  1765. ! includes:
  1766. USE Fwd_mod
  1767.  
  1768. IMPLICIT NONE
  1769.  
  1770. !
  1771. ! arguments
  1772. integer lidx, mair
  1773. ! local variables
  1774. REAL DZF,XA,XB,FXA,FXM,XM
  1775. integer i,j,l,m
  1776.  
  1777. !-----------------------------------------------------------------------
  1778. if (lidx .eq. 3) then
  1779. MAIR = 0
  1780. go to 9999
  1781. else if (lidx.eq.1 .or. lidx.eq.2) then
  1782. !
  1783. MAIR = cnAirLayers
  1784. NODEZ = NODEZ + MAIR
  1785. !
  1786. ! make room in dlz() and npt() for air layers (push things down mair elements)
  1787. do j = nodez-mair-1, 1, -1
  1788. dlz(j+mair) = dlz(j)
  1789. do l = 1, nodey-1
  1790. do m = 1,4
  1791. npt(j+mair,m,l) = npt(j,m,l)
  1792. enddo
  1793. enddo
  1794. enddo
  1795. !
  1796. ! compute the thickness of the elements in the air layer
  1797. ! TOTAL AIR THICKNESS IS ONE-HALF MESH WIDTH, I.E.,
  1798. ! YY(NODEY) ABOVE. ELEMENT ROW JUST ABOVE SURFACE
  1799. ! EQUALS THAT JUST BELOW AND ROW THICKNESSES INCREASE
  1800. ! EXPONENTIALLY UPWARD. IN ALL, THERE ARE MAIR ELEMENT
  1801. ! ROWS OF AIR.
  1802. DZF = YY(NODEY)/DLZ(MAIR + 1)
  1803. XA = 1.
  1804. XB = DZF**0.25
  1805. DO 40 I = 1,50
  1806. XM = (XA + XB)/2.
  1807. IF((XM-XA)/XM .LT. 1.0E-04)GO TO 41
  1808. FXA = 1.
  1809. FXM = 1.
  1810. DO 42 J = 1,MAIR-1
  1811. FXA = 1. + XA*FXA
  1812. FXM = 1. + XM*FXM
  1813. 42 CONTINUE
  1814. FXA = FXA - DZF
  1815. FXM = FXM - DZF
  1816. !
  1817. IF(SIGN(1.,FXA)*SIGN(1.,FXM) .LE. 0)THEN
  1818. XB = XM
  1819. ELSE
  1820. XA = XM
  1821. END IF
  1822. 41 CONTINUE
  1823. 40 CONTINUE
  1824. !
  1825. DLZ(MAIR) = DLZ(MAIR + 1)
  1826. DO 43 I = 1,MAIR-1
  1827. J = MAIR - I
  1828. DLZ(J) = XM*DLZ(J+1)
  1829. 43 CONTINUE
  1830. !
  1831. ! fill the air layer lookup table with 0 (air)
  1832. DO j = 1,MAIR
  1833. DO l = 1,NODEY-1
  1834. DO m = 1,4
  1835. NPT(j,m,l) = 0
  1836. enddo
  1837. enddo
  1838. enddo
  1839. !
  1840. else
  1841. ! remove air layers in dlz() and npt() (push things up mair elements)
  1842. if (mair .ne. 0) then
  1843. do j = 1, nodez-mair-1
  1844. dlz(j) = dlz(j+mair)
  1845. do l = 1, nodey-1
  1846. do m = 1,4
  1847. npt(j,m,l) = npt(j+mair,m,l)
  1848. enddo
  1849. enddo
  1850. enddo
  1851. nodez = nodez - mair
  1852. end if
  1853. end if
  1854.  
  1855. 9999 continue
  1856. return
  1857. end subroutine addair
  1858.  
  1859. !-----------------------------------------------------------------------
  1860. SUBROUTINE PARFLD
  1861. !-----------------------------------------------------------------------
  1862. ! OCCAM MT2D 3.0 Package
  1863. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  1864. ! Original code written by Phil Wannamaker.
  1865. !
  1866. ! THIS ROUTINE COMPUTES THE GLOBAL FINITE ELEMENT SYSTEM TO GIVE
  1867. ! THE FIELD PARALLEL TO STRIKE. TASKS PERFORMED INCLUDE THE
  1868. ! PRIMARY FIELDS FOR THE SOURCE VECTOR AND AT EACH NODAL COLUMN,
  1869. ! LOADING THE MATRIX ELEMENTS INTO THE GLOBAL SYSTEM, INCORPORA-
  1870. ! TING ANY DIRICHLET BOUNDARY CONDITIONS, AND SOLVING THE SYSTEM.
  1871. !
  1872. USE Fwd_mod
  1873.  
  1874. IMPLICIT NONE
  1875.  
  1876. COMPLEX CP(4),CP12,CP23,CP34,CP14,CP1234,A11,A12,A13,A15,A22, &
  1877. &A24,A25,A33,A34,A35,A44,A45,A55,E11,G11,C11,H11,E22,H22,C22, &
  1878. &E33,G33,E44,A55I,ZLFLD,FSE,FSH
  1879. COMPLEX CK(4),CK12,CK13,CK14,CK23,CK24,CK34
  1880. COMPLEX FP1(nodeZ),FP2(nodeZ),FP3(nodeZ),FP4(nodeZ),DJ1,DJ2,DJ3,DJ4, &
  1881. & DSS1,DSS2,DSS3,DSS4,FP5(nodeZ),FP6(nodeZ),FP7(nodeZ),FP8(nodeZ),SM1, &
  1882. & SM2,SM3,SM4,SM5,RU1,RU2,RU3,RU4,RU5,RC1,RC2,RC3,RC4
  1883. ! miscellaneous stuff that needs to be defined
  1884. integer i,nodey1,nodez1,nband,nban1,nlyr,nlyr1,lzp,j,jm1,k,l1,l, &
  1885. & m,l2,l3,l4,nji,iyn,it,ib
  1886. real pi,rad,w,wu,we,ra,zap,rhal,phal,rhar,phar,zt,z1,z2,z3,z5,z6,&
  1887. & z7,z8,zl,dlzy,dlyz,a,b,c,c4,dy4
  1888.  
  1889. IF(NDX .EQ. 1)IDX = 2
  1890. IF(IMD .EQ. 2)IDX = 3
  1891. IF(IDX .EQ. 2)THEN
  1892. NTQ = 1
  1893. NDZ = NODEZ
  1894. NDZ1 = NDZ - 1
  1895. DO 10 I = 1,NODEY
  1896. NTA(I) = NTAO(I) + NTR + NDZ*(I-1)
  1897. ! WRITE(*,*),'NTA(I),TE MODE: ', NTA(I)
  1898. 10 CONTINUE
  1899. ELSE IF(IDX .EQ. 3)THEN
  1900. NTQ = NTR
  1901. NDZ = NODEZ - NTR + 1
  1902. NDZ1 = NDZ - 1
  1903. DO 15 I = 1,NODEY
  1904. NTA(I) = NTAO(I) + 1 + NDZ*(I-1)
  1905. ! WRITE(*,*),'NTA(I),TM MODE: ', NTA(I)
  1906. 15 CONTINUE
  1907. ! write(*,*),'nta: ',(nta(i),i=1,nodey)
  1908. END IF
  1909. NODEY1 = NODEY - 1
  1910. NODEZ1 = NODEZ - 1
  1911. NBAND = NDZ + 2
  1912. NNODE = NODEY*NDZ
  1913. NBAN1 = NBAND - 1
  1914. !
  1915. ! COMPUTE APPARENT RESISTIVITIES AND IMPEDANCE PHASES FOR LEFT
  1916. ! AND RIGHT SIDE LAYER SEQUENCES.
  1917. !
  1918. PI = 3.1415927
  1919. RAD = 180./PI
  1920. W = 2.*PI*FREK(LFRQ)
  1921. WU = W*PI*4.E-07
  1922. WE = W*8.85433E-12
  1923. RA = 1.0E+18
  1924. NLYR = NOLA(1)
  1925. NLYR1 = NLYR - 1
  1926. IF (NLYR .EQ. 1) GO TO 20
  1927. DO 30 I = 1,NLYR1
  1928. DDP(I) = DLR(I,1)
  1929. RL(I) = RLR(I,1)
  1930. 30 CONTINUE
  1931. 20 CONTINUE
  1932. RL(NLYR) = RLR(NLYR,1)
  1933. CALL COAMP(WU,WE,NLYR)
  1934. IF(IMD .EQ. 1) THEN
  1935. ZAP = 0.
  1936. IF(NPT(NZZB(1),1,1) .EQ. ISEA)ZAP = DDP(1)
  1937. FSE = ZLFLD(WU,ZAP,1,NLYR)
  1938. FSH = ZLFLD(WU,ZAP,2,NLYR)
  1939. RHAL = CABS(FSE/FSH)**2/WU
  1940. PHAL = RAD*ATAN2(AIMAG(FSE/FSH),REAL(FSE/FSH))
  1941. END IF
  1942. !
  1943. NLYR = NOLA(2)
  1944. NLYR1 = NLYR - 1
  1945. IF(NLYR .EQ. 1)GO TO 40
  1946. DO 50 I = 1,NLYR1
  1947. DDP(I) = DLR(I,2)
  1948. RL(I) = RLR(I,2)
  1949. 50 CONTINUE
  1950. 40 CONTINUE
  1951. RL(NLYR) = RLR(NLYR,2)
  1952. CALL COAMP(WU,WE,NLYR)
  1953. IF (IMD .EQ. 1) THEN
  1954. ZAP = 0.
  1955. IF(NPT(NZZB(2),1,NODEY1) .EQ. ISEA)ZAP = DDP(1)
  1956. FSE = ZLFLD(WU,ZAP,1,NLYR)
  1957. FSH = ZLFLD(WU,ZAP,2,NLYR)
  1958. RHAR = CABS(FSE/FSH)**2/WU
  1959. PHAR = RAD*ATAN2(AIMAG(FSE/FSH),REAL(FSE/FSH))
  1960. END IF
  1961. !
  1962. ! THIS SECTION CALCULATES THE PRIMARY E- OR H-FIELDS FOR THE TE
  1963. ! AND TM PROBLEMS. FIELDS IN THE LAYERED HOST ARE CALCULATED FOR
  1964. ! AN INCIDENT E-FIELD AMPLITUDE OF (1.,0.) AT THE EARTH'S SURFACE
  1965. ! (NOT AT THE TOP OF THE MESH) POLARIZED IN THE +X DIRECTION FOR
  1966. ! THE TE MODE AND IN THE +Y DIRECTION FOR THE TM MODE.
  1967. ! ZLFLD(Z,1) IS FOR E AND ZLFLD(Z,2) IS FOR H.
  1968. !
  1969. LSID = 1
  1970. IF(RLR(1,1) .LT. RLR(1,2))LSID = 2 !WHICH SIDE IS HOST
  1971. !
  1972. NLYR = NOLA(LSID)
  1973. NLYR1 = NLYR - 1
  1974. IF(NLYR .EQ. 1)GO TO 60
  1975. DO 70 I = 1,NLYR1
  1976. DDP(I) = DLR(I,LSID)
  1977. RL(I) = RLR(I,LSID)
  1978. 70 CONTINUE
  1979. 60 CONTINUE
  1980. RL(NLYR) = RLR(NLYR,LSID)
  1981. CALL COAMP(WU,WE,NLYR)
  1982. DO 80 I = NTQ,NODEZ1
  1983. ZT = ZZ(I) - ZZ(NZZB(LSID))
  1984. Z1 = ZT + DLZ(I)/6.
  1985. Z2 = ZT + DLZ(I)/2.
  1986. Z3 = ZT + DLZ(I)*(5./6.)
  1987. LZP = 0
  1988. IF(Z2 .GE. 0.)LZP = 1
  1989. IF(NLYR .EQ. 1)GO TO 100
  1990. DO 110 J = 2,NLYR
  1991. JM1 = J - 1
  1992. IF(Z2 .GT. DDP(JM1))LZP = J
  1993. 110 CONTINUE
  1994. 100 CONTINUE
  1995. IF(LZP .EQ. 0)GO TO 120
  1996. SIGH(I) = CMPLX(1./RL(LZP),WE)
  1997. ! write(*,*) 'RL(LZP): ', RL(LZP)
  1998. GO TO 130
  1999. 120 CONTINUE
  2000. SIGH(I) = CMPLX(1./RA,WE)
  2001. ! write(*,*) 'RA: ', RA
  2002. 130 CONTINUE
  2003. IF(IDX .EQ. 3)GO TO 140
  2004. FP1(I) = ZLFLD(WU,Z1,1,NLYR)
  2005. FP2(I) = ZLFLD(WU,Z2,1,NLYR)
  2006. FP3(I) = ZLFLD(WU,Z3,1,NLYR)
  2007. FP4(I) = FP2(I)
  2008. GO TO 90
  2009. 140 CONTINUE
  2010. FP1(I) = -ZLFLD(WU,Z1,2,NLYR)
  2011. FP2(I) = -ZLFLD(WU,Z2,2,NLYR)
  2012. FP3(I) = -ZLFLD(WU,Z3,2,NLYR)
  2013. FP4(I) = FP2(I)
  2014. Z5 = ZT
  2015. Z6 = ZT + DLZ(I)/4.
  2016. Z7 = ZT + DLZ(I)*(3./4.)
  2017. Z8 = ZT + DLZ(I)
  2018. FP5(I) = ZLFLD(WU,Z5,1,NLYR)
  2019. FP6(I) = ZLFLD(WU,Z6,1,NLYR)
  2020. FP7(I) = ZLFLD(WU,Z7,1,NLYR)
  2021. FP8(I) = ZLFLD(WU,Z8,1,NLYR)
  2022. 90 CONTINUE
  2023. 80 CONTINUE
  2024. DO 150 I = NTQ,NODEZ
  2025. ZL = ZZ(I) - ZZ(NZZB(LSID))
  2026. IF(IDX .EQ. 2)THEN
  2027. FPA(I) = ZLFLD(WU,ZL,1,NLYR)
  2028. FPB(I) = ZLFLD(WU,ZL,2,NLYR)
  2029. ELSE
  2030. FPA(I) = -ZLFLD(WU,ZL,2,NLYR)
  2031. FPB(I) = ZLFLD(WU,ZL,1,NLYR)
  2032. END IF
  2033. 150 CONTINUE
  2034. !
  2035. ! THIS SECTION CALCULATES A 4 X 4 ELEMENT MATRIX FOR RECTANGULAR
  2036. ! ELEMENT MADE UP OF 4 TRIANGULAR ELEMENTS. THE 5 X 5 MATRIX IS
  2037. ! OBTAINED FROM PROPER COMBINATION OF THE FOUR 3 X 3 TRIANGULAR
  2038. ! ELEMENT MATRICIES AND REDUCED TO A 4 X 4 MATRIX THROUGH STATIC
  2039. ! CONDENSATION. THIS ELIMINATES THE DEGREE OF FREEDOM ASSOCIATED
  2040. ! WITH THE INTERNAL NODE OF THE RECTANGLE, THUS REDUCING THE
  2041. ! SIZE OF THE GLOBAL SYSTEM MATRIX.
  2042. !
  2043. DO 160 I = 1,NNODE
  2044. RM(I) = (0.,0.)
  2045. 160 CONTINUE
  2046. DO 170 K = 1,NBAND
  2047. DO 180 I = 1,NNODE
  2048. S(K,I) = (0.,0.)
  2049. 180 CONTINUE
  2050. 170 CONTINUE
  2051. !
  2052. L1 = 0
  2053. DO 190 L = 1,NODEY1
  2054. L1 = L1 + 1
  2055. DO 200 M = NTQ,NODEZ1
  2056. DLZY = DLZ(M)/(2.*DLY(L))
  2057. DLYZ = DLY(L)/(2.*DLZ(M))
  2058. A = -(DLZY + DLYZ)/2.
  2059. B = (DLZY - DLYZ)/2.
  2060. C = DLY(L)*DLZ(M)/48.
  2061. C4 = C*4.
  2062. DY4 = DLY(L)/4.
  2063. !
  2064. ! CALCULATE THE APPROPRIATE COEFFICIENTS OF THE HELMHOLTZ
  2065. ! EQUATION FOR INSERTION INTO THE ELEMENT MATRICIES
  2066. ! ACCORDING TO WHETHER THE TE OR TM MODE IS BEING SOLVED.
  2067. !
  2068. IF(IDX .EQ. 2)THEN
  2069. DO 210 I = 1,4
  2070. CK(I) = 1./CMPLX(0.,WU)
  2071. CP(I) = -CMPLX(SIG(M,I,L),WE)
  2072. 210 CONTINUE
  2073. ELSE
  2074. DO 220 I = 1,4
  2075. CK(I) = 1./CMPLX(SIG(M,I,L),WE)
  2076. CP(I) = -CMPLX(0.,WU)
  2077. 220 CONTINUE
  2078. END IF
  2079. CK12 = CK(1) + CK(2)
  2080. CK13 = CK(1) + CK(3)
  2081. CK14 = CK(1) + CK(4)
  2082. CK23 = CK(2) + CK(3)
  2083. CK24 = CK(2) + CK(4)
  2084. CK34 = CK(3) + CK(4)
  2085. CP12 = CP(1) + CP(2)
  2086. CP23 = CP(2) + CP(3)
  2087. CP34 = CP(3) + CP(4)
  2088. CP14 = CP(1) + CP(4)
  2089. CP1234 = CP12 + CP34
  2090. !
  2091. ! THESE ARE THE ELEMENTS OF THE 5 X 5 MATRIX
  2092. !
  2093. A11 = A*CK12 + 2.*C*CP12
  2094. A12 = -B*CK(2) + C*CP(2)
  2095. A13 = B*CK(1) + C*CP(1)
  2096. A15 = DLYZ*CK(1) + DLZY*CK(2) + C*CP12
  2097. A22 = A*CK23 + 2.*C*CP23
  2098. A24 = B*CK(3) + C*CP(3)
  2099. A25 = DLYZ*CK(3) + DLZY*CK(2) + C*CP23
  2100. A33 = A*CK14 + 2.*C*CP14
  2101. A34 = -B*CK(4) + C*CP(4)
  2102. A35 = DLYZ*CK(1) + DLZY*CK(4) + C*CP14
  2103. A44 = A*CK34 + 2.*C*CP34
  2104. A45 = DLYZ*CK(3) + DLZY*CK(4) + C*CP34
  2105. A55 = 2.*(C*CP1234 - DLYZ*CK13 - DLZY*CK24)
  2106. !
  2107. ! THESE ARE THE ELEMENTS OF THE 5 X 1 SOURCE VECTOR
  2108. !
  2109. DJ1 = (CMPLX(SIG(M,1,L),WE) - SIGH(M))*FP1(M)
  2110. DJ2 = (CMPLX(SIG(M,2,L),WE) - SIGH(M))*FP2(M)
  2111. DJ3 = (CMPLX(SIG(M,3,L),WE) - SIGH(M))*FP3(M)
  2112. DJ4 = (CMPLX(SIG(M,4,L),WE) - SIGH(M))*FP4(M)
  2113. SM1 = (0.,0.)
  2114. SM2 = (0.,0.)
  2115. SM3 = (0.,0.)
  2116. SM4 = (0.,0.)
  2117. SM5 = (0.,0.)
  2118. IF(IDX .EQ. 2)GO TO 230
  2119. DSS1 = 1. - SIGH(M)/CMPLX(SIG(M,1,L),WE)
  2120. DSS2 = 1. - SIGH(M)/CMPLX(SIG(M,2,L),WE)
  2121. DSS3 = 1. - SIGH(M)/CMPLX(SIG(M,3,L),WE)
  2122. DSS4 = 1. - SIGH(M)/CMPLX(SIG(M,4,L),WE)
  2123. DJ1 = CMPLX(0.,WU)*DSS1*FP1(M)
  2124. DJ2 = CMPLX(0.,WU)*DSS2*FP2(M)
  2125. DJ3 = CMPLX(0.,WU)*DSS3*FP3(M)
  2126. DJ4 = CMPLX(0.,WU)*DSS4*FP4(M)
  2127. SM1 = DSS1*(2.*FP5(M) - FP6(M)) + DSS2*FP6(M)
  2128. SM2 = -DSS2*FP7(M) - DSS3*(2.*FP8(M) - FP7(M))
  2129. SM3 = DSS1*(2.*FP5(M) - FP6(M)) + DSS4*FP6(M)
  2130. SM4 = -DSS3*(2.*FP8(M) - FP7(M)) - DSS4*FP7(M)
  2131. SM5 = -FP6(M)*(2.*DSS1 - DSS2 - DSS4) &
  2132. & - FP7(M)*(DSS2 - 2.*DSS3 + DSS4)
  2133. 230 CONTINUE
  2134. RU1 = C4*(DJ1 + DJ2) + DY4*SM1
  2135. RU2 = C4*(DJ2 + DJ3) + DY4*SM2
  2136. RU3 = C4*(DJ1 + DJ4) + DY4*SM3
  2137. RU4 = C4*(DJ3 + DJ4) + DY4*SM4
  2138. RU5 = C4*(DJ1 + DJ2 + DJ3 + DJ4) + DY4*SM5
  2139. !
  2140. ! ELEMENTS OF THE 4 X 4 CONDENSED MATRIX AND SOURCE
  2141. !
  2142. A55I = 1./A55
  2143. AA55(1,M,L) = A15*A55I
  2144. AA55(2,M,L) = A25*A55I
  2145. AA55(3,M,L) = A35*A55I
  2146. AA55(4,M,L) = A45*A55I
  2147. E11 = A11 - A15*AA55(1,M,L)
  2148. G11 = A12 - A15*AA55(2,M,L)
  2149. C11 = A13 - A15*AA55(3,M,L)
  2150. H11 = -A15*AA55(4,M,L)
  2151. E22 = A22 - A25*AA55(2,M,L)
  2152. H22 = -A25*AA55(3,M,L)
  2153. C22 = A24 - A25*AA55(4,M,L)
  2154. E33 = A33 - A35*AA55(3,M,L)
  2155. G33 = A34 - A35*AA55(4,M,L)
  2156. E44 = A44 - A45*AA55(4,M,L)
  2157. RC1 = RU1 - A15*(RU5/A55)
  2158. RC2 = RU2 - A25*(RU5/A55)
  2159. RC3 = RU3 - A35*(RU5/A55)
  2160. RC4 = RU4 - A45*(RU5/A55)
  2161. !
  2162. ! THIS SECTION LOADS ELEMENT MATRICIES INTO GLOBAL MATRIX
  2163. !
  2164. S(1,L1) = S(1,L1) + E11
  2165. S(2,L1) = S(2,L1) + G11
  2166. S(NBAN1,L1) = S(NBAN1,L1) + C11
  2167. S(NBAND,L1) = S(NBAND,L1) + H11
  2168. L2 = L1 + 1
  2169. S(1,L2) = S(1,L2) + E22
  2170. S(NDZ,L2) = S(NDZ,L2) + H22
  2171. S(NBAN1,L2) = S(NBAN1,L2) + C22
  2172. L3 = L1 + NDZ
  2173. S(1,L3) = S(1,L3) + E33
  2174. S(2,L3) = S(2,L3) + G33
  2175. L4 = L3 + 1
  2176. S(1,L4) = S(1,L4) + E44
  2177. RM(L1) = RM(L1) + RC1
  2178. RM(L2) = RM(L2) + RC2
  2179. RM(L3) = RM(L3) + RC3
  2180. RM(L4) = RM(L4) + RC4
  2181. L1 = L1 + 1
  2182. 200 CONTINUE
  2183. 190 CONTINUE
  2184. !
  2185. ! INCORPORATE BOUNDARY CONDITIONS INTO GLOBAL EQUATION SYSTEM.
  2186. ! METHOD 1 OF HUEBNER (1983, P. 52) IS USED, REDUCING UNDERFLOWS.
  2187. ! ZERO CONDITIONS ARE USED AT THE MESH TOP FOR THE TM MODE AND AT
  2188. ! THE MESH BOTTOM FOR THE TE MODE. NEUMANN CONDITIONS ELSEWHERE.
  2189. !
  2190. NJI = NNODE - NDZ + 1
  2191. IYN = 1
  2192. DO 240 IT = 1,NJI,NDZ
  2193. IF(IDX .EQ. 3)THEN
  2194. S(1,IT) = (1.,0.)
  2195. IF(IYN .EQ. 1)GO TO 250
  2196. S(2,IT-1) = (0.,0.)
  2197. S(NDZ,IT-NDZ+1) = (0.,0.)
  2198. S(NBAN1,IT-NDZ) = (0.,0.)
  2199. IF(IYN .EQ. 2)GO TO 250
  2200. S(NBAND,IT-NBAN1) = (0.,0.)
  2201. 250 CONTINUE
  2202. S(2,IT) = (0.,0.)
  2203. S(NDZ,IT) = (0.,0.)
  2204. S(NBAN1,IT) = (0.,0.)
  2205. S(NBAND,IT) = (0.,0.)
  2206. RM(IT) = (0.,0.)
  2207. END IF
  2208. IF(IDX .EQ. 2)THEN
  2209. IB = IT + NDZ1
  2210. S(1,IB) = (1.,0.)
  2211. IF(IYN .EQ. NODEY)GO TO 260
  2212. S(2,IB) = (0.,0.)
  2213. S(NDZ,IB) = (0.,0.)
  2214. S(NBAN1,IB) = (0.,0.)
  2215. IF(IYN .EQ. NODEY1)GO TO 260
  2216. S(NBAND,IB) = (0.,0.)
  2217. 260 CONTINUE
  2218. S(2,IB-1) = (0.,0.)
  2219. S(NDZ,IB-NDZ+1) = (0.,0.)
  2220. IF(IYN .EQ. 1)GO TO 270
  2221. S(NBAN1,IB-NDZ) = (0.,0.)
  2222. S(NBAND,IB-NBAN1) = (0.,0.)
  2223. 270 CONTINUE
  2224. RM(IB) = (0.,0.)
  2225. END IF
  2226. IYN = IYN + 1
  2227. 240 CONTINUE
  2228. !
  2229. ! SOLVE THE GLOBAL SYSTEM USING GAUSSIAN ELIMINATION
  2230. !
  2231. CALL GAUSS(NNODE,NBAND)
  2232.  
  2233. RETURN
  2234. END SUBROUTINE PARFLD
  2235.  
  2236. !-----------------------------------------------------------------------
  2237. SUBROUTINE COAMP(WM,WP,NLYR)
  2238. !-----------------------------------------------------------------------
  2239. ! OCCAM MT2D 3.0 Package
  2240. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2241. ! Original code written by Phil Wannamaker.
  2242. ! SUBROUTINE TO COMPUTE AMPLITUDE AND REFLECTION COEFFICIENTS FOR
  2243. ! ELECTRIC FIELDS PROPAGATING IN LAYERED EARTH. COEFFICIENTS ARE
  2244. ! PASSED TO FUNCTION ZLFLD IN COMMON BLOCK BLKP.
  2245. !
  2246.  
  2247. USE Fwd_mod
  2248.  
  2249. IMPLICIT NONE
  2250.  
  2251. COMPLEX AEXI,HTN(nLay-1),A2EX(nLay-1),CNUM,DEN,TL1
  2252. integer nlyr,nlyr1,i,j,k,kk1
  2253. real wm,wp,ra
  2254.  
  2255. RA = 1.0E+30
  2256. KL10 = CSQRT(-CMPLX(0.,WM)*CMPLX(1./RA,WP))
  2257. DO 10 I = 1,NLYR
  2258. KL1(I) = CSQRT(-CMPLX(0.,WM)*CMPLX(1./RL(I),WP))
  2259. 10 CONTINUE
  2260. IF(NLYR .GT. 1)THEN
  2261. NLYR1 = NLYR - 1
  2262. HL(1) = DDP(1)
  2263. IF(NLYR1 .EQ. 1)GO TO 30
  2264. DO 40 I = 2,NLYR1
  2265. HL(I) = DDP(I) - DDP(I-1)
  2266. 40 CONTINUE
  2267. 30 CONTINUE
  2268. DO 50 J = 1,NLYR1
  2269. ARG(J) = (0.,1.)*KL1(J)*HL(J)
  2270. IF(REAL(ARG(J)) .GT. 100.)GO TO 60
  2271. AEX(J) = CEXP(-ARG(J))
  2272. GO TO 70
  2273. 60 CONTINUE
  2274. AEX(J) = (0.,0.)
  2275. 70 CONTINUE
  2276. IF(REAL(ARG(J)) .GT. 40.)GO TO 80
  2277. AEXI = 1./AEX(J)
  2278. HTN(J) = (AEXI - AEX(J))/(AEXI + AEX(J))
  2279. GO TO 81
  2280. 80 CONTINUE
  2281. HTN(J) = (1.,0.)
  2282. 81 CONTINUE
  2283. A2EX(J) = AEX(J)*AEX(J)
  2284. 50 CONTINUE
  2285. ZLA = WM/KL1(NLYR)
  2286. DO 90 I = 1,NLYR1
  2287. J = NLYR - I + 1
  2288. ZL1 = WM/KL1(J-1)
  2289. RFC(J) = (ZLA - ZL1)/(ZLA + ZL1)
  2290. ZLA = ZL1*(ZLA + ZL1*HTN(J-1))/(ZL1 + ZLA*HTN(J-1))
  2291. 90 CONTINUE
  2292. ZL1 = WM/KL10
  2293. COA(1) = (2.*ZLA/(ZLA + ZL1))/(1. + RFC(2)*A2EX(1))
  2294. TL1 = COA(1)*(1. + RFC(2)*A2EX(1))
  2295. RFC(1) = TL1 - 1.
  2296. IF(NLYR1 .EQ. 1)GO TO 100
  2297. DO 110 K = 2,NLYR1
  2298. KK1 = K - 1
  2299. DEN = 1. + RFC(K+1)*A2EX(K)
  2300. CNUM = (1. + RFC(K))*AEX(KK1)
  2301. COA(K) = COA(KK1)*CNUM/DEN
  2302. 110 CONTINUE
  2303. 100 CONTINUE
  2304. COA(NLYR) = COA(NLYR1)*AEX(NLYR1)*(1. + RFC(NLYR))
  2305. GO TO 120
  2306. ELSE
  2307. COA(1) = 2.*KL10/(KL1(1) + KL10)
  2308. TL1 = COA(1)
  2309. RFC(1) = (KL10 - KL1(1))/(KL10 + KL1(1))
  2310. END IF
  2311. 120 CONTINUE
  2312.  
  2313. RETURN
  2314. END SUBROUTINE COAMP
  2315.  
  2316. !-----------------------------------------------------------------------
  2317. COMPLEX FUNCTION ZLFLD(WM,Z,IFL,NLYR)
  2318. !-----------------------------------------------------------------------
  2319. ! OCCAM MT2D 3.0 Package
  2320. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2321. ! Original code written by Phil Wannamaker.
  2322. ! FUNCTION COMPUTES ELECTRIC (IFL .EQ. 1) OR MAGNETIC (IFL .EQ.
  2323. ! 2) FIELD AT A DEPTH Z DUE TO UNIT-AMPLITUDE, DOWNGOING ELECTRIC
  2324. ! VECTOR AT SURFACE. REFLECTION AND TRANSMISSION COEFFICIENTS
  2325. ! FOR THE LAYERING ARE PASSED FROM COAMP IN COMMON BLOCK BLKP.
  2326. !
  2327. USE Fwd_mod
  2328.  
  2329. IMPLICIT NONE
  2330.  
  2331. COMPLEX K1WC,AR,AE,AEI,AR1,AR2
  2332. integer ifl,nlyr,lzp,lzp1,i,im1
  2333. real wm,z,zd1,zd2
  2334.  
  2335. IF(Z .LT. 0.)THEN
  2336. AR = (0.,1.)*KL10*Z
  2337. IF(IFL .EQ. 1)ZLFLD = CEXP(-AR)*(1.+RFC(1)*CEXP(2.*AR))
  2338. ! IF(IFL .EQ. 1)ZLFLD = CMPLX(CDEXP(DCMPLX(-AR))*
  2339. ! & (1.+RFC(1)*CDEXP(DCMPLX(2.*AR))))
  2340. IF(IFL .EQ. 2)ZLFLD = (KL10/WM)*CEXP(-AR)* &
  2341. & (1.-RFC(1)*CEXP(2.*AR))
  2342. ! IF(IFL .EQ. 2)ZLFLD = CMPLX((KL10/WM)*CDEXP(DCMPLX(-AR))*
  2343. ! & (1.-RFC(1)*CDEXP(DCMPLX(2.*AR))))
  2344. GO TO 10
  2345. ELSE
  2346. IF(NLYR .GT. 1)THEN
  2347. LZP = 1
  2348. DO 30 I = 2,NLYR
  2349. IM1 = I - 1
  2350. IF(Z .GT. DDP(IM1))LZP = I
  2351. 30 CONTINUE
  2352. K1WC = (KL1(LZP)/WM)*COA(LZP)
  2353. IF(LZP .EQ. NLYR)GO TO 40
  2354. IF(REAL(ARG(LZP)) .GT. 40.)GO TO 50
  2355. AR = (0.,1.)*KL1(LZP)*(Z-DDP(LZP))
  2356. AE = CEXP(-AR)
  2357. IF(IFL .EQ. 1)ZLFLD = COA(LZP)*(AE + RFC(LZP+1)/AE)*AEX(LZP)
  2358. IF(IFL .EQ. 2)ZLFLD = K1WC*(AE - RFC(LZP+1)/AE)*AEX(LZP)
  2359. GO TO 10
  2360. 50 CONTINUE
  2361. IF(LZP .EQ. 1)GO TO 60
  2362. LZP1 = LZP - 1
  2363. ZD1 = Z - DDP(LZP1)
  2364. ZD2 = Z - 2.*DDP(LZP) + DDP(LZP1)
  2365. GO TO 70
  2366. 60 CONTINUE
  2367. ZD1 = Z
  2368. ZD2 = Z - 2.*DDP(LZP)
  2369. 70 CONTINUE
  2370. AR1 = (0.,1.)*KL1(LZP)*ZD1
  2371. AE = (0.,0.)
  2372. AEI = (0.,0.)
  2373. IF(REAL(AR1) .GT. 100.)GO TO 80
  2374. AE = CEXP(-AR1)
  2375. AR2 = (0.,1.)*KL1(LZP)*ZD2
  2376. IF(REAL(AR2) .LT. -100.)GO TO 80
  2377. AEI = CEXP(AR2)
  2378. 80 CONTINUE
  2379. IF(IFL .EQ. 1)ZLFLD = COA(LZP)*(AE + RFC(LZP+1)*AEI)
  2380. IF(IFL .EQ. 2)ZLFLD = K1WC*(AE - RFC(LZP+1)*AEI)
  2381. GO TO 10
  2382. 40 CONTINUE
  2383. AR = (0.,1.)*KL1(LZP)*(Z-DDP(LZP-1))
  2384. IF(REAL(AR) .GT. 100.)GO TO 90
  2385. IF(IFL .EQ. 1)ZLFLD = COA(LZP)*CEXP(-AR)
  2386. IF(IFL .EQ. 2)ZLFLD = K1WC*CEXP(-AR)
  2387. GO TO 10
  2388. 90 CONTINUE
  2389. ZLFLD = (0.,0.)
  2390. GO TO 10
  2391. ELSE
  2392. AR = (0.,1.)*KL1(1)*Z
  2393. IF(REAL(AR) .GT. 100.)GO TO 100
  2394. IF(IFL .EQ. 1)ZLFLD = COA(1)*CEXP(-AR)
  2395. IF(IFL .EQ. 2)ZLFLD = (KL1(1)/WM)*COA(1)*CEXP(-AR)
  2396. GO TO 10
  2397. 100 CONTINUE
  2398. ZLFLD = (0.,0.)
  2399. GO TO 10
  2400. END IF
  2401. END IF
  2402. 10 CONTINUE
  2403.  
  2404. RETURN
  2405. END FUNCTION ZLFLD
  2406.  
  2407. !-----------------------------------------------------------------------
  2408. SUBROUTINE GAUSS(NNODE,NBAND)
  2409. !-----------------------------------------------------------------------
  2410. ! OCCAM MT2D 3.0 Package
  2411. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2412. ! Original code written by Phil Wannamaker.
  2413. ! ROUTINE TO REDUCE FINITE ELEMENT MATRIX. GAUSSIAN ELIMINATION
  2414. ! WITHOUT PIVOTING BUT SPECIALIZED TO BANDED SYMMETRIC MATRICES
  2415. ! IS USED. WRITTEN BY L. RIJO, 1977. SUBSCRIPTING REVERSED IN
  2416. ! MATRIX S TO IMPROVE RUN-TIME, BY P. LUGAO, 1994. ARITHMETIC IF
  2417. ! STATEMENTS REPLACED BY P. WANNAMAKER, 1994.
  2418. !
  2419. USE Fwd_mod, NNODE_dont => NNODE
  2420. IMPLICIT NONE
  2421.  
  2422. COMPLEX D
  2423. COMPLEX(8) C
  2424. INTEGER NNODE,NBAND,N,NBLIM,L,I,J,K,M
  2425.  
  2426. DO 10 N = 1,NNODE
  2427. NBLIM = NBAND
  2428. IF(N .GT. NNODE-NBAND+1)NBLIM = NNODE - N + 1
  2429. IF(NBLIM .LT. 2)GO TO 10
  2430. DO 20 L = 2,NBLIM
  2431. I = N + L - 1
  2432. C = S(L,N)/S(1,N)
  2433. J = 0
  2434. DO 40 K = L,NBAND
  2435. J = J + 1
  2436. S(J,I) = S(J,I) - C*S(K,N)
  2437. 40 CONTINUE
  2438. S(L,N) = C
  2439. 20 CONTINUE
  2440. 10 CONTINUE
  2441. !
  2442. ! FORWARD REDUCTION OF SOURCES
  2443. !
  2444. DO 50 N = 1,NNODE
  2445. NBLIM = NBAND
  2446. IF(N .GT. NNODE-NBAND+1)NBLIM = NNODE - N + 1
  2447. IF(NBLIM .LT. 2)GO TO 70
  2448. DO 60 L = 2,NBLIM
  2449. I = N + L - 1
  2450. C = S(L,N)
  2451. RM(I) = RM(I) - RM(N)*C
  2452. 60 CONTINUE
  2453. 70 CONTINUE
  2454. D = 1./S(1,N)
  2455. RM(N) = RM(N)*D
  2456. 50 CONTINUE
  2457. !
  2458. ! BACK SUBSTITUTION OF SOURCES
  2459. !
  2460. DO 80 M = 2,NNODE
  2461. N = NNODE + 1 - M
  2462. NBLIM = NBAND
  2463. IF(N .GT. NNODE-NBAND+1)NBLIM = NNODE - N + 1
  2464. IF(NBLIM .LT. 2)GO TO 80
  2465. DO 90 L = 2,NBLIM
  2466. K = N + L - 1
  2467. C = S(L,N)
  2468. RM(N) = RM(N) - RM(K)*C
  2469. 90 CONTINUE
  2470. 80 CONTINUE
  2471.  
  2472. RETURN
  2473. END SUBROUTINE GAUSS
  2474.  
  2475. !-----------------------------------------------------------------------
  2476. SUBROUTINE APPARMT
  2477. !-----------------------------------------------------------------------
  2478. ! OCCAM MT2D 3.0 Package
  2479. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2480. ! Original code written by Phil Wannamaker.
  2481. ! CALCULATE AUXILIARY FIELDS, REAL AND IMAGINARY, AND APPARENT
  2482. ! RESISTIVITY, IMPEDANCE PHASE AND TIPPER. AUXILIARY FIELDS
  2483. ! RETURNED FROM CALL TO AUXFLD.
  2484. !
  2485. USE Fwd_mod
  2486.  
  2487. IMPLICIT NONE
  2488.  
  2489. COMPLEX FT,PF,HF,VF,TP,ZIMP
  2490. ! miscellaneous stuff
  2491. integer nzzn,in,i,nto,iii
  2492. real pi,rad,w,wu
  2493.  
  2494. PI = 3.1415927
  2495. RAD = 180./PI
  2496. W = 2.*PI*FREK(LFRQ)
  2497. WU = W*PI*4.E-07
  2498. NZZN = NTAO(1) + NTR
  2499. !ccKERRY: WRITE OUT X FIELD FOR ENTIRE MODEL:
  2500. IF (loutfields) THEN
  2501. write(*,*)'loutfields is true...'
  2502. IF(IDX .EQ. 2)THEN
  2503. WRITE(*,*) 'WRITING OUT TE ELECTRIC FIELD FOR ENTIRE MODEL...'
  2504. WRITE(UNITTE,*) (nodey*nodez)
  2505. WRITE(UNITTE,'(E11.4,1x,E11.4)') (RM(iii),iii=1,nodey*nodez)
  2506. WRITE(UNITTE,*) (nodez)
  2507. WRITE(UNITTE,'(E11.4,1x,E11.4)') (FPA(iii),iii=1,nodez)
  2508. ELSE
  2509. WRITE(*,*)'WRITING OUT TM MAGNETIC FIELD FOR ENTIRE MODEL...'
  2510. WRITE(UNITTM,*)(nodey*nodez)
  2511. WRITE(UNITTM,'(E11.4,1x,E11.4)')(RM(iii),iii=1,nodey*nodez)
  2512. WRITE(UNITTM,*)(nodez)
  2513. WRITE(UNITTM,'(E11.4,1x,E11.4)')(FPA(iii),iii=1,nodez)
  2514. END IF
  2515. END IF
  2516. !ccKERRY END
  2517. DO 10 IN = 1,NRC
  2518. AFN(IN) = (0.,0.)
  2519. AFT(IN) = (0.,0.)
  2520. I = NRL(IN)
  2521. CALL AUXFLD(I,IN)
  2522. NTO = NTAO(I) + NTR
  2523. FT = RM(NTA(I)) + FPA(NTO)
  2524. PF = FT/FPA(NZZN)
  2525. HF = AFT(IN)/FPB(NZZN)
  2526. VF = AFN(IN)/FPB(NZZN)
  2527. TP = VF/HF
  2528. IF(IDX .EQ. 2)THEN
  2529. ZIMP = FT/AFT(IN)
  2530. zimpe(in,lfrq)=zimp
  2531. RHTE(IN,LFRQ) = CABS(ZIMP)**2/WU
  2532. ! write(*,*)'RHTE(IN,LFRQ): ',RHTE(IN,LFRQ)
  2533. PHTE(IN,LFRQ) = RAD*ATAN2(AIMAG(ZIMP),REAL(ZIMP))
  2534. KZTE(IN,LFRQ) = TP
  2535. ELSE
  2536. ZIMP = AFT(IN)/FT
  2537. zimpm(in,lfrq)=zimp
  2538. RHTM(IN,LFRQ) = CABS(ZIMP)**2/WU
  2539. PHTM(IN,LFRQ) = RAD*ATAN2(-AIMAG(ZIMP),-REAL(ZIMP))
  2540. TZTM(IN,LFRQ) = TP
  2541. END IF
  2542. ! write(*,*) 'FT: ', FT
  2543. 10 CONTINUE
  2544.  
  2545. RETURN
  2546. END SUBROUTINE APPARMT
  2547.  
  2548. !-----------------------------------------------------------------------
  2549. SUBROUTINE AUXFLD(I,IN)
  2550. !-----------------------------------------------------------------------
  2551. ! OCCAM MT2D 3.0 Package
  2552. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2553. ! Original code written by Phil Wannamaker.
  2554. ! CALCULATE THE TOTAL FIELD NORMAL TO THE SLOPE AND THE TOTAL
  2555. ! FIELD PARALLEL TO THE SLOPE AND TRANSVERSE TO STRIKE. THIS IS
  2556. ! DONE THROUGH THREE-POINT DIFFERENCE APPROXIMATIONS TO MAXWELL'S
  2557. ! EQUATIONS IN SUBROUTINE DERIV. AUXILIARY FIELDS ARE RETURNED
  2558. ! TO MAIN IN ARRAYS AFN (NORMAL FIELD) AND AFT (TRANSVERSE
  2559. ! FIELD). FOR THE TE MODE , THE TRANSVERSE H-FIELD IS COMPUTED
  2560. ! IN A HORIZONTAL DIRECTION. SIMILAR PROCEDURES ARE CARRIED OUT
  2561. ! FOR THE AUXILIARY JACOBIAN QUANTITIES IN AFND AND AFTD.
  2562. !
  2563. USE Fwd_mod
  2564.  
  2565. IMPLICIT NONE
  2566.  
  2567. COMPLEX DERIV,DV,DH,UC
  2568. DIMENSION IR(8)
  2569. INTEGER I,IN,IR,NT,NCL,NCL1,NRW,NRW1,IH,IV,NPL,NPR,NPL1,NPR1,IH1,&
  2570. & IH2,IH3,IV1,IV2,IV3,IY1,IY2,IZ1,IZ2,ISB,NCSH,NHS,MSH,NTZ
  2571. REAL PI,W,WU,WE,AN,SIGU
  2572.  
  2573. PI = 3.1415927
  2574. W = 2.*PI*FREK(LFRQ)
  2575. WU = W*PI*4.E-07
  2576. WE = W*8.85433E-12
  2577. !
  2578. ! DEFINE NODAL ROW AND COLUMN LOCATIONS OF FIELDPOINT
  2579. !
  2580. NT = NTA(I)
  2581. NCL = I
  2582. NCL1 = NCL - 1
  2583. NRW = NTAO(I) + NTR
  2584. NRW1 = NRW - 1
  2585. !
  2586. ! COMPUTE SHIFT IN INDICES OF NODAL FIELDS ALONG STRIKE USED FOR
  2587. ! DETERMINING AUXILIARY FIELDS. NODES USED ARE KEPT WITHIN THE
  2588. ! EARTH. FOR BATHYMETRY, NODES ARE SHIFTED BY TWO INTO SEAWATER.
  2589. !
  2590. IH = 0
  2591. IV = -1
  2592. AN = 0.
  2593. NPL = 0
  2594. NPR = 0
  2595. IF(I .NE. 1)NPL = NPT(NRW,1,NCL1)
  2596. IF(I .NE. NODEY)NPR = NPT(NRW,1,NCL)
  2597. ! write(*,*),'NPL,NPR: ',NPL,NPR
  2598. NPARF(IN) = NPT(NRW,2,NCL) !RESIS. LABEL UNDER RECEIVER
  2599. IF(NPR .EQ. 0 .OR. NPR .EQ. ISEA)NPARF(IN) = NPT(NRW,4,NCL1)
  2600. NPL1 = 0
  2601. NPR1 = 0
  2602. IF(NRW .NE. 1)THEN
  2603. NPL1 = NPT(NRW1,3,NCL1)
  2604. NPR1 = NPT(NRW1,3,NCL)
  2605. ! write(*,*),'NPL1,NPR1: ',NPL1,NPR1
  2606. END IF
  2607. IF(I .EQ. 1 .OR. I .EQ. NODEY)GO TO 30
  2608. CALL BNORM(NCL,NRW,NCL1,NRW1,AN,IR) !SLOPE AT RECEIVER
  2609. IF(NPL .EQ. 0)IH = 1 !HORIZONTAL SHIFT TO
  2610. IF(NPR .EQ. 0)IH = -1 !AVOID AIR OR SEA
  2611. IF(NPL .EQ. 0 .AND. NPR .EQ. 0)IH = 0
  2612. IF(NRW .NE. 1)THEN !SEAFLOOR SHIFTS
  2613. IF(NPL1 .EQ. ISEA)IH = -1
  2614. IF(NPR1 .EQ. ISEA)IH = 1
  2615. IF(NPL1 .EQ. ISEA .AND. NPR1 .EQ. ISEA)IH = 0
  2616. IF(NPL1 .EQ. ISEA .OR. NPR1 .EQ. ISEA)IV = 1
  2617. END IF
  2618. GO TO 40
  2619. 30 CONTINUE
  2620. IF(I .EQ. 1 .OR. I .EQ. 2)THEN
  2621. IH = 1
  2622. IF(NRW .NE. 1 .AND. NPR1 .EQ. ISEA)IV = 1
  2623. END IF
  2624. IF(I .EQ. NODEY .OR. I .EQ. NODEY-1)THEN
  2625. IH = -1
  2626. IF(NRW .NE. 1 .AND. NPL1 .EQ. ISEA)IV = 1
  2627. END IF
  2628. AN = 0.
  2629. 40 CONTINUE
  2630. ! IF(IV .EQ. 1)AN = 0. !ASSUME SEAFLOOR LOCALLY FLAT
  2631. !kwk commented out for seafloor use slope
  2632. !kwk IF(IDX .EQ. 2)AN = 0. !TE HORIZ. & VERT.
  2633. IF(IV .EQ. 1)NPARF(IN) = -1 !NO E-PRIM. TERM IN SEA
  2634. !
  2635. ! INDICES FOR FIELDPOINT LOCATIONS AND ELEMENT DIMENSIONS
  2636. !
  2637. IH1 = NT + NDZ*(IH - 1)
  2638. IH2 = NT + NDZ*IH
  2639. IH3 = NT + NDZ*(IH + 1)
  2640. IV1 = NT - IV - 1
  2641. IV2 = NT - IV
  2642. IV3 = NT - IV + 1
  2643. IY1 = NCL1 + IH
  2644. IY2 = NCL + IH
  2645. IZ1 = NRW1 - IV
  2646. IZ2 = NRW - IV
  2647. ISB = IZ1 + (1 + IV)/2
  2648. ! write(*,*)'ih1,ih2,ih3,iv1,iv2,iv3: ',ih1,ih2,ih3,iv1,iv2,iv3
  2649. !
  2650. ! COMPUTE VERTICAL AND HORIZONTAL FIELD DERIVATIVES (DV AND DH).
  2651. ! AVOID JUMPS IN SIG OR SIGH ONE NODE AWAY WITH 1ST-ORDER DIFF'S.
  2652. !
  2653. ! DGM Jan 20, 2006 - added warning messages below.
  2654. !
  2655. ! IV = -1 for land, +1 for sea
  2656. ! ISB = the row that the site is at the bottom of (for sea)
  2657. ! IZ1 = the row above the row containing the site.
  2658. ! I,NCL = the column to the right of the site (the site sits above its left side)
  2659. ! NPT is the parameter number in the regularization grid. This number
  2660. ! will be 0=air, -1=water, or >0 for a real parameter.
  2661.  
  2662. NCSH = 1
  2663. IF(LSID .EQ. 2)NCSH = NODEY-1
  2664. DV = -IV*(RM(IV2) - RM(IV1))/DLZ(ISB) !DEFAULT 1ST-ORDER
  2665. ! write(*,*) 'IZ1: ', IZ1
  2666. IF(IZ1 .LT. 1) THEN
  2667. write(*,*) 'WARNING: Site ', IN, ' using linear derivative ' &
  2668. & , 'because it is at the top of the model.'
  2669. GO TO 50
  2670. END IF
  2671. ! write(*,*) 'I, NODEY', I, NODEY
  2672. IF(I .LT. NODEY) THEN
  2673. ! write(*,*) '(I<NodeY) ISB,NCL,IV,NPT...', ISB, NCL, IV
  2674. ! & , NPT(ISB,2,NCL), NPT(ISB-IV,2,NCL)
  2675. IF(NPT(ISB,2,NCL) .NE. NPT(ISB-IV,2,NCL)) THEN
  2676. IF (IV .gt. 0) THEN ! Land site
  2677. write(*,*) 'WARNING: Site ', IN, ' using linear derivative ' &
  2678. & , 'because triangle #2 on two blocks below are in different ' &
  2679. & , 'model blocks. Chg model.'
  2680. ELSE ! Sea site
  2681. write(*,*) 'WARNING: Site ', IN, ' using linear derivative ' &
  2682. & , 'because triangle #2 on two blocks above are in different ' &
  2683. & , 'model blocks. Chg model.'
  2684. END IF
  2685. GO TO 50
  2686. END IF
  2687. END IF
  2688. IF(I .GT. 1) THEN
  2689. ! write(*,*) '(I>1) ISB,NCL,IV,NPT etc', ISB, NCL, IV
  2690. ! & , NPT(ISB,4,NCL-1), NPT(ISB-IV,4,NCL-1)
  2691. IF(NPT(ISB,4,NCL-1) .NE. NPT(ISB-IV,4,NCL-1)) THEN
  2692. IF (IV .gt. 0) THEN ! Land site
  2693. write(*,*) 'WARNING: Site ', IN, ' using linear derivative ' &
  2694. & , 'because triangle #4 on two blocks below are in different ' &
  2695. & , 'model blocks. Chg model.'
  2696. ELSE ! Sea site
  2697. write(*,*) 'WARNING: Site ', IN, ' using linear derivative ' &
  2698. & , 'because triangle #4 on two blocks above are in different ' &
  2699. & , 'model blocks. Chg model.'
  2700. END IF
  2701. GO TO 50
  2702. END IF
  2703. END IF
  2704. ! write(*,*) 'ISB,NCSH,IV,NPT...', ISB,NCSH,IV
  2705. ! & , NPT(ISB,3,NCSH), NPT(ISB-IV,1,NCSH)
  2706.  
  2707. ! DGM Jan 20, 2006
  2708. ! The logic below is looking at the parameters on the very left of
  2709. ! the model because that is where the 1D response is calculated ... maybe.
  2710. ! Or maybe that's just left-overs from some old process...
  2711. ! The purpose of the last condition is to avoid a change in the
  2712. ! background conductivity model.
  2713. ! This IF doesn't work for models with bathymetry where the lefthand
  2714. ! side of the model is higher than some of the sites. In the case
  2715. ! where a site is deeper than the lefthand side AND the two blocks
  2716. ! above the site are in different regularization blocks, then this
  2717. ! IF is triggered and the parabolic derivative is skipped. This
  2718. ! causes the occam inversion to diverge.
  2719. ! IF(NPT(ISB,3,NCSH) .NE. NPT(ISB-IV,1,NCSH)) THEN
  2720. ! write(*,*) 'WARNING: Site ', IN, ' using linear derivative '
  2721. ! GO TO 50 !AVOID SIGH
  2722. ! END IF
  2723.  
  2724. DV = DERIV(RM(IV1),RM(IV2),RM(IV3),DLZ(IZ1),DLZ(IZ2),IV)
  2725. ! write(*,*) 'RM(IV1),RM(IV2),RM(IV3),DLZ(IZ1),DLZ(IZ2),IV: '
  2726. ! & ,RM(IV1),RM(IV2),RM(IV3),DLZ(IZ1),DLZ(IZ2),IV
  2727. 50 CONTINUE
  2728. DH = (0.,0.)
  2729. IF(I .EQ. 1 .OR. I .EQ. NODEY)GO TO 52
  2730. IF(IH .NE. 0)THEN
  2731. NHS = 1
  2732. MSH = 1
  2733. IF(IH .EQ. 1)NHS = 0
  2734. IF(IH .EQ. 1)MSH = -1
  2735. IF(NPT(ISB,2+IV,NCL-NHS) .NE. NPT(ISB,2+IV,NCL+1-3*NHS))THEN
  2736. NTZ = NT + NDZ*(1-2*NHS)
  2737. DH = MSH*(RM(NT) - RM(NTZ))/DLY(NCL-NHS) !DEFAULT 1ST-ORDER
  2738. GO TO 52
  2739. END IF
  2740. END IF
  2741. DH = DERIV(RM(IH1),RM(IH2),RM(IH3),DLY(IY1),DLY(IY2),IH)
  2742. 52 CONTINUE
  2743. !
  2744. ! TE MODE AUXILIARY FIELDS
  2745. !
  2746. IF(IDX .EQ. 2)THEN
  2747. !kwk commented out for using seafloor slope
  2748. !kwk AN = 0.
  2749. UC = -CMPLX(0.,WU)
  2750. AFN(IN) = -(FPB(NRW) + DV/UC)*SIN(AN) - (DH/UC)*COS(AN)
  2751. AFT(IN) = (FPB(NRW) + DV/UC)*COS(AN) - (DH/UC)*SIN(AN)
  2752. CSIGU(IN) = UC !SAVED FOR PARJAC AND AUXADJ
  2753. !
  2754. ! TM MODE AUXILIARY FIELDS
  2755. !
  2756. ELSE
  2757. SIGU = SIG(ISB,2,NCL)
  2758. IF(I .EQ. NODEY) SIGU = SIG(ISB,4,NCL-1)
  2759. UC = CMPLX(SIGU,WE)
  2760. ! AN = 0.
  2761. AFN(IN) = (-(SIGH(ISB)*FPB(NRW) +DV)*SIN(AN) - DH*COS(AN))/UC
  2762. AFT(IN) = ((SIGH(ISB)*FPB(NRW) + DV)*COS(AN) - DH*SIN(AN))/UC
  2763. ! write(*,*) 'IN, AN, AFN, AFT: ',IN, AN, AFN(IN), AFT(IN)
  2764. ! write(*,*) 'SIGH(ISB), FPB(NRW), DV, UC: ', SIGH(ISB), FPB(NRW),
  2765. ! & DV, UC
  2766. CSIGU(IN) = UC !SAVED FOR PARJAC AND AUXADJ
  2767. END IF
  2768.  
  2769. RETURN
  2770. END SUBROUTINE AUXFLD
  2771.  
  2772. !-----------------------------------------------------------------------
  2773. SUBROUTINE BNORM(NCL,NRW,NCL1,NRW1,AN,IR)
  2774. !-----------------------------------------------------------------------
  2775. ! OCCAM MT2D 3.0 Package
  2776. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2777. ! Original code written by Phil Wannamaker.
  2778. ! CALCULATE DOWNWARD BISECTOR FROM FIELD NODE AT BREAK IN TOPO-
  2779. ! GRAPHY. AR, AL CLOCKWISE FROM UP, AN CLOCKWISE FROM DOWN.
  2780. !
  2781. USE Fwd_mod
  2782.  
  2783. IMPLICIT NONE
  2784.  
  2785. COMPLEX TAL,TAR
  2786. INTEGER NCL,NRW,NCL1,NRW1,IR,I
  2787. REAL AN,SM,AL,AR
  2788. DIMENSION IR(8)
  2789.  
  2790. ! IDENTIFY RESISTIVITY CODES OF TRIANGULAR ELEMENTS SURROUNDING
  2791. ! FIELD NODE. UPPERMOST LEFT OCTANT IS IR(1), RIGHT IS IR(8).
  2792. !
  2793. IR(3) = NPT(NRW,1,NCL1)
  2794. IR(4) = NPT(NRW,4,NCL1)
  2795. IR(5) = NPT(NRW,2,NCL)
  2796. IR(6) = NPT(NRW,1,NCL)
  2797. IF(NRW .EQ. 1)GO TO 10
  2798. IR(1) = NPT(NRW1,4,NCL1)
  2799. IR(2) = NPT(NRW1,3,NCL1)
  2800. IR(7) = NPT(NRW1,3,NCL)
  2801. IR(8) = NPT(NRW1,2,NCL)
  2802. GO TO 20
  2803. 10 CONTINUE
  2804. IR(1) = 0
  2805. IR(2) = 0
  2806. IR(7) = 0
  2807. IR(8) = 0
  2808. 20 CONTINUE
  2809. DO 40 I = 1,8
  2810. IF (IR(I) .EQ. ISEA) IR(I) = 0
  2811. 40 CONTINUE
  2812. !
  2813. ! DETERMINE SLOPE TO LEFT OF FIELD NODE
  2814. !
  2815. SM = 1.0E-05
  2816. TAL = 100.*CMPLX(1.,-SM)
  2817. IF (NRW .EQ. 1) GO TO 50
  2818. TAL = DLZ(NRW1)*CMPLX(1.,-SM)
  2819. IF (IR(1).EQ.0 .AND. IR(2).NE.0)TAL = CMPLX(DLZ(NRW1),-DLY(NCL1))
  2820. 50 CONTINUE
  2821. IF (IR(2).EQ.0 .AND. IR(3).NE.0)TAL = DLY(NCL1)*CMPLX(SM,-1.)
  2822. IF (IR(3).EQ.0 .AND. IR(4).NE.0)TAL = CMPLX(-DLZ(NRW),-DLY(NCL1))
  2823. IF (IR(4).EQ.0 .AND. IR(5).NE.0)TAL = DLZ(NRW)*CMPLX(-1.,-SM)
  2824. !
  2825. ! DETERMINE SLOPE TO RIGHT OF FIELD NODE
  2826. !
  2827. TAR = 100.*CMPLX(1.,SM)
  2828. IF (NRW .EQ. 1) GO TO 60
  2829. TAR = DLZ(NRW1)*CMPLX(1.,SM)
  2830. IF (IR(8).EQ.0 .AND. IR(7).NE.0)TAR = CMPLX(DLZ(NRW1),DLY(NCL))
  2831. 60 CONTINUE
  2832. IF (IR(7).EQ.0 .AND. IR(6).NE.0)TAR = DLY(NCL)*CMPLX(SM,1.)
  2833. IF (IR(6).EQ.0 .AND. IR(5).NE.0)TAR = CMPLX(-DLZ(NRW),DLY(NCL))
  2834. IF (IR(5).EQ.0 .AND. IR(4).NE.0)TAR = DLZ(NRW)*CMPLX(-1.,SM)
  2835. AL = ATAN2(AIMAG(TAL),REAL(TAL))
  2836. AR = ATAN2(AIMAG(TAR),REAL(TAR))
  2837. AN = (AL + AR)/2.
  2838. ! write(*,*),'BNORM SLOPE: ',AN*180/3.16
  2839.  
  2840. RETURN
  2841. END SUBROUTINE BNORM
  2842.  
  2843. !-----------------------------------------------------------------------
  2844. COMPLEX FUNCTION DERIV(R1,R2,R3,D1,D2,IF)
  2845. !-----------------------------------------------------------------------
  2846. ! OCCAM MT2D 3.0 Package
  2847. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2848. ! Original code written by Phil Wannamaker.
  2849. ! FUNCTION ESTIMATES DERIVATIVE AT LEFT END, MIDDLE OR RIGHT END
  2850. ! OF A COMPLEX THREE-POINT SEQUENCE BY FITTING THE PARABOLA
  2851. ! R = A + B*D + C*D**2. PARABOLA COEFFICIENTS ARE CALCULATED
  2852. ! FROM AMPLITUDES AND SEPARATIONS OF THE THREE POINTS.
  2853. !
  2854. IMPLICIT NONE
  2855. COMPLEX R1,R2,R3,B,C
  2856. INTEGER IF
  2857. REAL D1,D2,DEN
  2858.  
  2859. DEN = D1*D2*D2 + D1*D1*D2
  2860. ! A = R2
  2861. B = ((R3-R2)*D1*D1 - (R1-R2)*D2*D2)/DEN
  2862. C = ((R3-R2)*D1 + (R1-R2)*D2)/DEN
  2863. IF(IF)10,20,30
  2864. ! DERIVATIVE AT LEFT POINT
  2865. 10 CONTINUE
  2866. DERIV = B - 2.*C*D1
  2867. GO TO 40
  2868. ! DERIVATIVE AT MIDDLE POINT
  2869. 20 CONTINUE
  2870. DERIV = B
  2871. GO TO 40
  2872. ! DERIVATIVE AT RIGHT POINT
  2873. 30 CONTINUE
  2874. DERIV = B + 2.*C*D2
  2875. 40 CONTINUE
  2876.  
  2877. RETURN
  2878. END FUNCTION DERIV
  2879.  
  2880. !-----------------------------------------------------------------------
  2881. SUBROUTINE RECIJAC(NRES)
  2882. !-----------------------------------------------------------------------
  2883. ! OCCAM MT2D 3.0 Package
  2884. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2885. ! Original code written by Phil Wannamaker.
  2886. ! SUBROUTINE TO CALCULATE DATA-PARAMETER JACOBIANS USING
  2887. ! RECIPROCITY. PARALLEL FIELD QUANTITIES COMPUTED FOR TE MODE
  2888. ! ONLY BY LOADING UNIT SOURCES AT MT RECEIVER POINTS. TM MODE
  2889. ! JACOBIAN ALONG STRIKE IS ZERO. TRANSVERSE AND VERTICAL FIELD
  2890. ! QUANTITIES COMPUTED BY DEFINING A DISTRIBUTED SOURCE AT MT
  2891. ! FIELD POINT AND NEIGHBOURING POINTS FOR FIRST OR SECOND-ORDER
  2892. ! DIFFERENCING.
  2893. !
  2894. USE Fwd_mod
  2895.  
  2896. DO 10 KP = 1,NRES
  2897. DO 11 I = 1,NRC
  2898. FLDJ(I,KP) = (0.,0.)
  2899. FLDJH(I,KP) = (0.,0.)
  2900. FLDJV(I,KP) = (0.,0.)
  2901. 11 CONTINUE
  2902. 10 CONTINUE
  2903. !
  2904. ! ALONG-STRIKE COMPONENT COMPUTED BY LOADING ARRAY OF RECIPROCAL
  2905. ! SOURCES AT MT RECEIVERS AND SOLVING IN GAUSSD.
  2906. !
  2907. DO 15 JY = 1,NNODE
  2908. DO 16 IY = 1,NODEY
  2909. RJ(IY,JY) = (0.,0.)
  2910. 16 CONTINUE
  2911. 15 CONTINUE
  2912. IX = 0
  2913. DO 17 ILD = 1,NRC
  2914. I = NTA(NRL(ILD))
  2915. IF(IDX .EQ. 2 .OR. NPARF(ILD) .EQ. -1)RJ(ILD,I) = (1.,0.)
  2916. 17 CONTINUE
  2917. NBAND=NDZ+2
  2918. CALL GAUSSD(NNODE,NBAND,NRC)
  2919. CALL PARJAC(IX)
  2920. !
  2921. ! CALCULATE AUXILIARY FIELD JACOBIANS, USING DISTRIBUTED SOURCES.
  2922. ! FOR TE MODE, CALCULATE BOTH HORIZONTAL AND VERTICAL AUXILIARY
  2923. ! JACOBIANS. FOR TM MODE, CALCULATE ONLY JACOBIAN OF AUXILIARY
  2924. ! ELECTRIC FIELD ALONG SLOPE.
  2925. !
  2926. DO 20 IX = 1,2
  2927. DO 21 JY = 1,NNODE
  2928. DO 22 IY = 1,NODEY
  2929. RJ(IY,JY) = (0.,0.)
  2930. 22 CONTINUE
  2931. 21 CONTINUE
  2932. IF(IX .EQ. 2 .AND. IDX .EQ. 3)GO TO 20 !NO EZ
  2933. DO 23 ILD = 1,NRC
  2934. I = NRL(ILD)
  2935. CALL AUXADJ(I,ILD,IX) !DEFINE DISTRIBUTED SOURCE VECTORS
  2936. 23 CONTINUE
  2937. CALL GAUSSD(NNODE,NBAND,NRC)
  2938. CALL PARJAC(IX)
  2939. 20 CONTINUE
  2940. !
  2941. ! CONVERT E AND H-FIELD JACOBIANS TO THOSE OF LOG APP RHO, PHASE
  2942. ! AND TIPPER. JACOBIANS ARE WITH RESPECT TO LOG RHO.
  2943. !
  2944. CALL APPRMTJ
  2945.  
  2946. RETURN
  2947. END SUBROUTINE RECIJAC
  2948.  
  2949. !-----------------------------------------------------------------------
  2950. SUBROUTINE PARJAC(IX)
  2951. !-----------------------------------------------------------------------
  2952. ! OCCAM MT2D 3.0 Package
  2953. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  2954. ! Original code written by Phil Wannamaker.
  2955. ! THIS ROUTINE COMPUTES THE DERIVATIVE OF THE FIELD PARALLEL TO
  2956. ! STRIKE WITH RESPECT TO THE CONDUCTIVITY OF A POLYGONAL REGION
  2957. ! IN THE MESH USING RECIPROCITY. THIS IS ACCOMPLISHED FOLLOWING
  2958. ! SOLUTION OF UNIT OR DISTRIBUTED RECIPROCAL SOURCES BY WEIGHTING
  2959. ! WITH ELEMENT PROPERTIES AND TOTAL FIELDS.
  2960. !
  2961. USE Fwd_mod
  2962.  
  2963.  
  2964. COMPLEX CPD(4),CPD12,CPD23,CPD34,CPD14,CPD1T4,AD11,AD12,AD13,&
  2965. &AD15,AD22,AD24,AD25,AD33,AD34,AD35,AD44,AD45,AD55,ED11,GD11,&
  2966. &CD11,HD11,ED22,HD22,CD22,ED33,GD33,ED44,&
  2967. &FT1,FT2,FT3,FT4,RJC1,RJC2,RJC3,RJC4
  2968. COMPLEX DSIG,CKD(4),CKD12,CKD13,CKD14,CKD23,CKD24,CKD34
  2969.  
  2970. PI = 3.1415927
  2971. W = 2.*PI*FREK(LFRQ)
  2972. WE = W*8.85433E-12
  2973. !
  2974. ! LOOP OVER ELEMENTS, CONSTRUCTING DERIVATIVE SOURCE TERMS
  2975. !
  2976. NODEY1 = NODEY - 1
  2977. NODEZ1 = NODEZ - 1
  2978. L1 = 0
  2979. DO 140 L = 1,NODEY1
  2980. L1 = L1 + 1
  2981. DO 150 M = NTQ,NODEZ1
  2982. L2 = L1 + 1
  2983. L3 = L1 + NDZ
  2984. L4 = L3 + 1
  2985. !
  2986. ! CALCULATE THE APPROPRIATE COEFFICIENTS FOR INSERTION INTO
  2987. ! THE SOURCE. IF TRIANGLES WITHIN RECTANGULAR ELEMENT ARE NOT
  2988. ! ALL THE SAME, SUM THEIR CONTRIBUTIONS SEPARATELY (NPE = 4).
  2989. !
  2990. NPT1 = NPT(M,1,L)
  2991. NPE = 1
  2992. DO 120 IC = 2,4
  2993. IF(NPT(M,IC,L) .NE. NPT1)NPE = 4
  2994. 120 CONTINUE
  2995. IF(NPE .EQ. 1 .AND. NPT1 .EQ. 0)GO TO 131
  2996. DLZY = DLZ(M)/(2.*DLY(L))
  2997. DLYZ = DLY(L)/(2.*DLZ(M))
  2998. A = -(DLZY + DLYZ)/2.
  2999. B = (DLZY - DLYZ)/2.
  3000. C = DLY(L)*DLZ(M)/48.
  3001. !
  3002. ! CALCULATE THE APPROPRIATE COEFFICIENTS FOR INSERTION INTO
  3003. ! SOURCE VECTOR ACCORDING TO WHETHER TE OR TM MODE SOLVED.
  3004. !
  3005. DO 130 IE = 1,NPE
  3006. NPTE = NPT(M,IE,L)
  3007. IF(NPE .EQ. 1)THEN !HOMOGENEOUS RECTANGLE
  3008. IF(IDX .EQ. 2)THEN !TE MODE
  3009. DO 132 I = 1,4
  3010. CKD(I) = CMPLX(0.,0.)
  3011. CPD(I) = CMPLX(1.,0.)
  3012. 132 CONTINUE
  3013. ELSE !TM MODE
  3014. DO 133 I = 1,4
  3015. DSIG = 1./CMPLX(SIG(M,I,L),WE)
  3016. CKD(I)= DSIG*DSIG
  3017. CPD(I) = CMPLX(0.,0.)
  3018. 133 CONTINUE
  3019. END IF
  3020. ELSE !INHOMOGENEOUS RECTANGLE
  3021. DO 135 I = 1,4
  3022. CKD(I) = 0.
  3023. CPD(I) = 0.
  3024. 135 CONTINUE
  3025. !
  3026. ! CALCULATE THE APPROPRIATE COEFFICIENTS FOR INSERTION INTO
  3027. ! SOURCE VECTOR ACCORDING TO WHETHER TE OR TM MODE SOLVED.
  3028.  
  3029. IF(IDX .EQ. 2)THEN
  3030. CKD(IE) = CMPLX(0.,0.)
  3031. CPD(IE) = CMPLX(1.,0.)
  3032. ELSE
  3033. DSIG = 1./CMPLX(SIG(M,IE,L),WE)
  3034. CKD(IE)= DSIG*DSIG
  3035. CPD(IE) = CMPLX(0.,0.)
  3036. END IF
  3037. END IF
  3038. CKD12 = CKD(1) + CKD(2)
  3039. CKD13 = CKD(1) + CKD(3)
  3040. CKD14 = CKD(1) + CKD(4)
  3041. CKD23 = CKD(2) + CKD(3)
  3042. CKD24 = CKD(2) + CKD(4)
  3043. CKD34 = CKD(3) + CKD(4)
  3044. CPD12 = CPD(1) + CPD(2)
  3045. CPD23 = CPD(2) + CPD(3)
  3046. CPD34 = CPD(3) + CPD(4)
  3047. CPD14 = CPD(1) + CPD(4)
  3048. CPD1T4 = CPD12 + CPD34
  3049. !
  3050. ! ELEMENTS OF THE 5 X 5 DIFFERENTIATED MATRIX
  3051. !
  3052. AD11 = A*CKD12 + 2.*C*CPD12
  3053. AD12 = -B*CKD(2) + C*CPD(2)
  3054. AD13 = B*CKD(1) + C*CPD(1)
  3055. AD15 = DLYZ*CKD(1) + DLZY*CKD(2) + C*CPD12
  3056. AD22 = A*CKD23 + 2.*C*CPD23
  3057. AD24 = B*CKD(3) + C*CPD(3)
  3058. AD25 = DLYZ*CKD(3) + DLZY*CKD(2) + C*CPD23
  3059. AD33 = A*CKD14 + 2.*C*CPD14
  3060. AD34 = -B*CKD(4) + C*CPD(4)
  3061. AD35 = DLYZ*CKD(1) + DLZY*CKD(4) + C*CPD14
  3062. AD44 = A*CKD34 + 2.*C*CPD34
  3063. AD45 = DLYZ*CKD(3) + DLZY*CKD(4) + C*CPD34
  3064. AD55 = 2.*(C*CPD1T4 - DLYZ*CKD13 - DLZY*CKD24)
  3065.  
  3066. ! ELEMENTS OF THE CONDENSED DIFFERENTIATED MATRIX
  3067.  
  3068. DO 170 IA = 1,4
  3069. AAD55(IA) = AD55*AA55(IA,M,L)
  3070. 170 CONTINUE
  3071. ED11 = AD11 - 2.*AD15*AA55(1,M,L) + AAD55(1)*AA55(1,M,L)
  3072. GD11 = AD12 - AD15*AA55(2,M,L) - AD25*AA55(1,M,L) &
  3073. & + AAD55(1)*AA55(2,M,L)
  3074. CD11 = AD13 - AD15*AA55(3,M,L) - AD35*AA55(1,M,L) &
  3075. & + AAD55(1)*AA55(3,M,L)
  3076. HD11 = - AD15*AA55(4,M,L) - AD45*AA55(1,M,L) &
  3077. & + AAD55(1)*AA55(4,M,L)
  3078. ED22 = AD22 - 2.*AD25*AA55(2,M,L) + AAD55(2)*AA55(2,M,L)
  3079. HD22 = - AD25*AA55(3,M,L) - AD35*AA55(2,M,L) &
  3080. & + AAD55(2)*AA55(3,M,L)
  3081. CD22 = AD24 - AD25*AA55(4,M,L) - AD45*AA55(2,M,L) &
  3082. & + AAD55(2)*AA55(4,M,L)
  3083. ED33 = AD33 - 2.*AD35*AA55(3,M,L) + AAD55(3)*AA55(3,M,L)
  3084. GD33 = AD34 - AD35*AA55(4,M,L) - AD45*AA55(3,M,L) &
  3085. & + AAD55(3)*AA55(4,M,L)
  3086. ED44 = AD44 - 2.*AD45*AA55(4,M,L) + AAD55(4)*AA55(4,M,L)
  3087. !
  3088. ! MULTIPLYING THE CONDENSED DIFFERENTIATED MATRIX BY THE TOTAL
  3089. ! FIELDS ALONG STRIKE AT THE CORNERS OF THE RECTANGULAR
  3090. ! ELEMENT YIELDS THE CONDENSED SOURCE. EVALUATION OF SOURCE TERMS
  3091. ! UTILIZES FIELDS FROM FORWARD PROBLEM AND RECIPROCITY.
  3092. !
  3093. ! DGM Oct 9, 2006 - NPTE may also equal -1 (seawater)
  3094. IF (NPTE .NE. 0 .and. NPTE .NE. ISEA) THEN
  3095. FT1 = RM(L1) + FPA(M)
  3096. FT2 = RM(L2) + FPA(M+1)
  3097. FT3 = RM(L3) + FPA(M)
  3098. FT4 = RM(L4) + FPA(M+1)
  3099. RJC1 = ED11*FT1 + GD11*FT2 + CD11*FT3 + HD11*FT4
  3100. RJC2 = GD11*FT1 + ED22*FT2 + HD22*FT3 + CD22*FT4
  3101. RJC3 = CD11*FT1 + HD22*FT2 + ED33*FT3 + GD33*FT4
  3102. RJC4 = HD11*FT1 + CD22*FT2 + GD33*FT3 + ED44*FT4
  3103. !
  3104. DO 107 KR = 1,NRC
  3105. !
  3106. IF(IX .EQ. 0)THEN !TE PARALLEL JACOBIAN
  3107. FLDJ(KR,NPTE) = FLDJ(KR,NPTE) + RJC1*RJ(KR,L1) &
  3108. & + RJC2*RJ(KR,L2) + RJC3*RJ(KR,L3) + RJC4*RJ(KR,L4)
  3109. ELSE IF(IX .EQ. 1)THEN !HORIZONTAL AUX. JACOBIAN
  3110. FLDJH(KR,NPTE) = FLDJH(KR,NPTE) + RJC1*RJ(KR,L1) &
  3111. & + RJC2*RJ(KR,L2) + RJC3*RJ(KR,L3) + RJC4*RJ(KR,L4)
  3112. ELSE IF(IX .EQ. 2)THEN !VERTICAL AUX. JACOBIAN
  3113. FLDJV(KR,NPTE) = FLDJV(KR,NPTE) + RJC1*RJ(KR,L1) &
  3114. & + RJC2*RJ(KR,L2) + RJC3*RJ(KR,L3) + RJC4*RJ(KR,L4)
  3115. END IF
  3116. !
  3117. 107 CONTINUE
  3118. END IF
  3119. 130 CONTINUE
  3120. 131 CONTINUE
  3121. L1 = L1 + 1
  3122. 150 CONTINUE
  3123. 140 CONTINUE
  3124. !
  3125. ! FOR TM MODE, ADD E-FIELD TO THE ALONG-SLOPE ELECTRIC JACOBIAN
  3126. ! WHEN RECEIVER POINT IS IN THE PARAMETER.
  3127. !
  3128. IF(IDX .EQ. 3 .AND. IX .EQ. 1) THEN
  3129. DO 177 KS = 1,NRC
  3130. IF(NPARF(KS) .GT. 0)THEN
  3131. FLDJH(KS,NPARF(KS)) = FLDJH(KS,NPARF(KS)) &
  3132. & - AFT(KS)/CSIGU(KS)
  3133. END IF
  3134. 177 CONTINUE
  3135. END IF
  3136.  
  3137. RETURN
  3138. END SUBROUTINE PARJAC
  3139.  
  3140. !-----------------------------------------------------------------------
  3141. SUBROUTINE GAUSSD(NNODE,NBAND,NSRC)
  3142. !-----------------------------------------------------------------------
  3143. ! OCCAM MT2D 3.0 Package
  3144. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  3145. ! Original code written by Phil Wannamaker.
  3146. use Fwd_mod, NNODE_dont => NNODE
  3147.  
  3148. COMPLEX C,D
  3149.  
  3150. DO 50 N = 1,NNODE
  3151. NBLIM = NBAND
  3152. IF(N .GT. NNODE-NBAND+1)NBLIM = NNODE - N + 1
  3153. IF(NBLIM .LT. 2)GO TO 70
  3154. DO 60 L = 2,NBLIM
  3155. C = S(L,N)
  3156. I = N + L - 1
  3157. DO 80 KP = 1,NSRC
  3158. RJ(KP,I) = RJ(KP,I) - C*RJ(KP,N)
  3159. 80 CONTINUE
  3160. 60 CONTINUE
  3161. 70 CONTINUE
  3162. D = 1./S(1,N)
  3163. DO 90 KP = 1,NSRC
  3164. RJ(KP,N) = RJ(KP,N)*D
  3165. 90 CONTINUE
  3166. 50 CONTINUE
  3167. !
  3168. DO 100 M = 2,NNODE
  3169. N = NNODE + 1 - M
  3170. NBLIM = NBAND
  3171. IF(N .GT. NNODE-NBAND+1)NBLIM = NNODE - N + 1
  3172. IF(NBLIM .LT. 2)GO TO 100
  3173. DO 110 L = 2,NBLIM
  3174. C = S(L,N)
  3175. K = N + L - 1
  3176. DO 120 KP = 1,NSRC
  3177. RJ(KP,N) = RJ(KP,N) - C*RJ(KP,K)
  3178. 120 CONTINUE
  3179. 110 CONTINUE
  3180. 100 CONTINUE
  3181.  
  3182. RETURN
  3183. END SUBROUTINE GAUSSD
  3184.  
  3185. !-----------------------------------------------------------------------
  3186. SUBROUTINE AUXADJ(I,ILD,IX)
  3187. !-----------------------------------------------------------------------
  3188. ! OCCAM MT2D 3.0 Package
  3189. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  3190. ! Original code written by Phil Wannamaker.
  3191. ! LOADS THE AUXILIARY FIELD JACOBIAN SOURCE VECTORS ACCORDING TO
  3192. ! RECIPROCITY. FOR EACH RECEIVER, SUBROUTINE DRVADJ COMPUTES
  3193. ! PARABOLA COEFFICIENTS A, B, AND C WHICH WILL BE LOADED INTO
  3194. ! SOURCE VECTOR RJ(,) TO BE SOLVED IN SUBROUTINE GAUSSD. COEFF-
  3195. ! ICIENT VALUES DEPEND UPON TOPOGRAPHIC SLOPE AND ELEMENT PROPER-
  3196. ! TIES. FOR TM MODE, PROJECTED VERTICAL AND HORIZONTAL DERIVA-
  3197. ! TIVES ARE ADDED TO GIVE E-FIELD ALONG SLOPE.
  3198. !
  3199. USE Fwd_mod
  3200.  
  3201. COMPLEX UC
  3202. DIMENSION IR(8)
  3203.  
  3204. ! DEFINE NODAL ROW AND COLUMN LOCATIONS OF FIELDPOINT
  3205. !
  3206. NT = NTA(I)
  3207. NCL = I
  3208. NCL1 = NCL - 1
  3209. NRW = NTAO(I) + NTR
  3210. NRW1 = NRW - 1
  3211. UC = CSIGU(ILD)
  3212. !
  3213. ! COMPUTE SHIFT IN INDICES OF NODAL FIELDS ALONG STRIKE USED FOR
  3214. ! DETERMINING AUXILIARY FIELDS. NODES USED ARE KEPT WITHIN THE
  3215. ! EARTH. FOR BATHYMETRY, NODES ARE SHIFTED BY TWO INTO SEAWATER.
  3216. !
  3217. IH = 0
  3218. IV = -1
  3219. AN = 0.
  3220. NPL = 0
  3221. NPR = 0
  3222. IF(I .NE. 1)NPL = NPT(NRW,1,NCL1)
  3223. IF(I .NE. NODEY)NPR = NPT(NRW,1,NCL)
  3224. NPL1 = 0
  3225. NPR1 = 0
  3226. IF(NRW .NE. 1)THEN
  3227. NPL1 = NPT(NRW1,3,NCL1)
  3228. NPR1 = NPT(NRW1,3,NCL)
  3229. END IF
  3230. IF(I .EQ. 1 .OR. I .EQ. NODEY)GO TO 30
  3231. CALL BNORM(NCL,NRW,NCL1,NRW1,AN,IR) !SLOPE AT RECEIVER
  3232. IF(NPL .EQ. 0)IH = 1 !HORIZONTAL SHIFT TO
  3233. IF(NPR .EQ. 0)IH = -1 !AVOID AIR OR SEA
  3234. IF(NPL .EQ. 0 .AND. NPR .EQ. 0)IH = 0
  3235. IF(NRW .NE. 1)THEN !SEAFLOOR SHIFTS
  3236. IF(NPL1 .EQ. ISEA)IH = -1
  3237. IF(NPR1 .EQ. ISEA)IH = 1
  3238. IF(NPL1 .EQ. ISEA .AND. NPR1 .EQ. ISEA)IH = 0
  3239. IF(NPL1 .EQ. ISEA .OR. NPR1 .EQ. ISEA)IV = 1
  3240. END IF
  3241. GO TO 40
  3242. 30 CONTINUE
  3243. IF(I .EQ. 1 .OR. I .EQ. 2)THEN
  3244. IH = 1
  3245. IF(NRW .NE. 1 .AND. NPR1 .EQ. ISEA)IV = 1
  3246. END IF
  3247. IF(I .EQ. NODEY .OR. I .EQ. NODEY-1)THEN
  3248. IH = -1
  3249. IF(NRW .NE. 1 .AND. NPL1 .EQ. ISEA)IV = 1
  3250. END IF
  3251. AN = 0.
  3252. 40 CONTINUE
  3253. ! IF(IV .EQ. 1)AN = 0. !ASSUME SEAFLOOR LOCALLY FLAT
  3254. !kwk commented out for using seafloor slope:
  3255. !kwk IF(IDX .EQ. 2)AN = 0. !TE HORIZ. & VERT.
  3256. !
  3257. ! INDICES FOR FIELDPOINT LOCATIONS AND ELEMENT DIMENSIONS
  3258. !
  3259. IH1 = NT + NDZ*(IH - 1)
  3260. IH2 = NT + NDZ*IH
  3261. IH3 = NT + NDZ*(IH + 1)
  3262. IV1 = NT - IV - 1
  3263. IV2 = NT - IV
  3264. IV3 = NT - IV + 1
  3265. IY1 = NCL1 + IH
  3266. IY2 = NCL + IH
  3267. IZ1 = NRW1 - IV
  3268. IZ2 = NRW - IV
  3269. ISB = IZ1 + (1 + IV)/2
  3270. !
  3271. IF(IX .EQ. 1)THEN !CROSS-STRIKE FIELD JACOBIAN
  3272. !
  3273. ! VERTICAL DERIVATIVE COEFFICIENTS A, B AND C FOR HORIZONTAL
  3274. ! AUXILIARY JACOBIAN.
  3275. !
  3276. A = -1./DLZ(IZ1) !AVOID JUMPS IN SIG ONE NODE
  3277. B = 1./DLZ(IZ1) !AWAY WITH 1ST-ORDER DIFF'S.
  3278. C = 0.
  3279. IF(IZ1 .LT. 1)GO TO 50
  3280. IF(I .LT. NODEY) THEN
  3281. IF(NPT(ISB,2,NCL) .NE. NPT(ISB-IV,2,NCL))GO TO 50
  3282. END IF
  3283. IF(I .GT. 1) THEN
  3284. IF(NPT(ISB,4,NCL-1) .NE. NPT(ISB-IV,4,NCL-1))GO TO 50
  3285. END IF
  3286. !
  3287. CALL DRVADJ(DLZ(IZ1),DLZ(IZ2),IV,A,B,C)
  3288. !
  3289. 50 CONTINUE
  3290. !
  3291. ! LOAD COEFFICIENTS A, B AND C INTO RHS VECTOR RJ, WEIGHTED BY
  3292. ! PROPERTY FACTOR FOR EITHER TE OR TM. FOR TM MODE, COEFFICIENT
  3293. ! W.R.T. RECEIVER IS ALWAYS ZERO DUE TO NO SECONDARY H-FIELD AT
  3294. ! SURFACE.
  3295. !
  3296. IF(IDX .EQ. 3 .AND. IV .EQ. -1)A = 0.
  3297. RJ(ILD,IV1) = COS(AN)*CMPLX(A,0.)/UC
  3298. RJ(ILD,IV2) = COS(AN)*CMPLX(B,0.)/UC
  3299. RJ(ILD,IV3) = COS(AN)*CMPLX(C,0.)/UC
  3300. END IF
  3301. !
  3302. ! HORIZONTAL DERIVATIVES FOR VERTICAL FIELD COMPONENTS. THESE
  3303. ! ARE DONE FOR THE TE MODE GENERALLY AND THE TM FOR TOPOGRAPHY.
  3304. !
  3305. NVGO = 0
  3306. IF(IX .EQ. 1 .AND. IDX .EQ. 3)NVGO = 1
  3307. IF(IX .EQ. 2 .AND. IDX .EQ. 2)NVGO = 1
  3308. IF(NVGO .EQ. 1)THEN
  3309. IF(IH .EQ. 1)THEN !FIRST-ORDER DEFAULTS
  3310. A = -1./DLY(IY1)
  3311. B = 1./DLY(IY1)
  3312. C = 0.
  3313. ELSE IF(IH .EQ. -1)THEN
  3314. A = 0.
  3315. B = -1./DLY(IY2)
  3316. C = 1./DLY(IY2)
  3317. END IF
  3318. IF(I .EQ. 1 .OR. I .EQ. NODEY)GO TO 51
  3319. IF(IH .NE. 0)THEN
  3320. NHS = 1
  3321. IF(IH .EQ. 1)NHS = 0
  3322. IF(NPT(ISB,2+IV,NCL-NHS) .NE. &
  3323. & NPT(ISB,2+IV,NCL+1-3*NHS))GO TO 51
  3324. END IF
  3325. !
  3326. CALL DRVADJ(DLY(IY1),DLY(IY2),IH,A,B,C)
  3327. !
  3328. 51 CONTINUE
  3329. !
  3330. ANM = AN
  3331. IF(IDX .EQ. 2)ANM = AN + 1.570796 !ADD PI/2 FOR TE
  3332. IF(IV .EQ. -1 .AND. IDX .EQ. 3)THEN
  3333. IF(IH .EQ. 1)A = 0.
  3334. IF(IH .EQ. 0)B = 0.
  3335. IF(IH .EQ. -1)C = 0.
  3336. END IF
  3337. !
  3338. IF(IH .EQ. 0)THEN
  3339. RJ(ILD,IH1) = -SIN(ANM)*CMPLX(A,0.)/UC
  3340. RJ(ILD,IH2) = RJ(ILD,IH2) - SIN(ANM)*CMPLX(B,0.)/UC
  3341. RJ(ILD,IH3) = -SIN(ANM)*CMPLX(C,0.)/UC
  3342. ELSE IF(IH .EQ. 1)THEN
  3343. RJ(ILD,IH1) = RJ(ILD,IH1) - SIN(ANM)*CMPLX(A,0.)/UC
  3344. RJ(ILD,IH2) = -SIN(ANM)*CMPLX(B,0.)/UC
  3345. RJ(ILD,IH3) = -SIN(ANM)*CMPLX(C,0.)/UC
  3346. ELSE IF(IH .EQ. -1)THEN
  3347. RJ(ILD,IH1) = -SIN(ANM)*CMPLX(A,0.)/UC
  3348. RJ(ILD,IH2) = -SIN(ANM)*CMPLX(B,0.)/UC
  3349. RJ(ILD,IH3) = RJ(ILD,IH3) - SIN(ANM)*CMPLX(C,0.)/UC
  3350. END IF
  3351. END IF
  3352.  
  3353. RETURN
  3354. END SUBROUTINE AUXADJ
  3355.  
  3356. !-----------------------------------------------------------------------
  3357. SUBROUTINE DRVADJ(D1,D2,IF,A,B,C)
  3358. !-----------------------------------------------------------------------
  3359. ! OCCAM MT2D 3.0 Package
  3360. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  3361. ! Original code written by Phil Wannamaker.
  3362. ! CALCULATE PARABOLA FITTING COEFFICIENTS A,B AND C WHICH
  3363. ! WILL GO INTO RHS VECTOR OF RECIPROCITY SOLUTION FOR THE
  3364. ! AUXILIARY FIELD JACOBIANS. PARABOLA COEFFICIENTS ARE
  3365. ! CALCULATED FROM SEPARATIONS OF THE THREE POINTS AT LEFT,
  3366. ! MIDDLE OR RIGHT END. FORM IS R = A*R1 + B*R2 + C*R3.
  3367. !
  3368. REAL A,B,C,D1,D2,DEN
  3369.  
  3370. DEN = D1*D2*D2 + D1*D1*D2
  3371. IF(IF)10,20,30
  3372. !
  3373. ! DERIVATIVE AT LEFT POINT (IF=-1)
  3374. !
  3375. 10 CONTINUE
  3376. A = (-D2*D2 - 2.*D1*D2)/DEN
  3377. B = (D2*D2 + D1*D1 + 2.*D1*D2)/DEN
  3378. C = -D1*D1/DEN
  3379. GO TO 40
  3380. !
  3381. ! DERIVATIVE AT MIDDLE POINT (IF=0)
  3382. !
  3383. 20 CONTINUE
  3384. A = -D2*D2/DEN
  3385. B = (D2*D2 - D1*D1)/DEN
  3386. C = D1*D1/DEN
  3387. GO TO 40
  3388. !
  3389. ! DERIVATIVE AT RIGHT POINT (IF=1)
  3390. !
  3391. 30 CONTINUE
  3392. A = D2*D2/DEN
  3393. B = -(D2*D2 + D1*D1 + 2.*D1*D2)/DEN
  3394. C = (D1*D1 + 2.*D1*D2)/DEN
  3395. 40 CONTINUE
  3396.  
  3397. RETURN
  3398. END SUBROUTINE DRVADJ
  3399.  
  3400. !-----------------------------------------------------------------------
  3401. SUBROUTINE APPRMTJ
  3402. !-----------------------------------------------------------------------
  3403. ! OCCAM MT2D 3.0 Package
  3404. ! Subroutine Revision 3.0, November 2006 (notional only to track future fixes)
  3405. ! Original code written by Phil Wannamaker.
  3406. ! CALCULATE JACOBIANS OF LOG APP. RES., IMPEDANCE PHASE AND TIPPER
  3407. ! FROM E AND H-FIELD JACOBIANS. FINAL QUANTITIES ARE WITH RESPECT
  3408. ! TO LOG RHO.
  3409. !
  3410. USE Fwd_mod
  3411.  
  3412. COMPLEX FT,ZIMP,FTD,TPD,ZIMPD
  3413.  
  3414. PI = 3.1415927
  3415. RAD = 180./PI
  3416. W = 2.*PI*FREK(LFRQ)
  3417. WU = W*PI*4.E-07
  3418. ELOG = 2.3025851
  3419. !
  3420. ! LOOP OVER RECEIVER NODES
  3421. !
  3422. DO 10 IN = 1,NRC
  3423. I = NRL(IN)
  3424. NTO = NTAO(I) + NTR
  3425. FT = RM(NTA(I)) + FPA(NTO) ! TOTAL PARALLEL FIELD
  3426. IF(IDX .EQ. 2)ZIMP = FT/AFT(IN) ! TE -> E(par)/H(aux)
  3427. IF(IDX .EQ. 3)ZIMP = AFT(IN)/FT ! TM -> E(aux)/H(par)
  3428. !
  3429. ! LOOP OVER PARAMETERS
  3430. !
  3431. DO 20 KP = 1,NPRM
  3432. PFC = -1./y(LAPRM(KP)+1)
  3433. FTD = FLDJ(IN,LAPRM(KP)) !PARALLEL FIELD JACOBIAN
  3434. AFTD(KP) = FLDJH(IN,LAPRM(KP)) !HORIZONTAL AUX. JACOBIAN
  3435. AFND(KP) = FLDJV(IN,LAPRM(KP)) !VERTICAL AUX. JACOBIAN
  3436.  
  3437. ! DGM Oct 2006 - modified to return the jacobians in non-log
  3438. ! space. The input is not in log, the output should
  3439. ! also be NOT in log. Let the caller figure it out.
  3440. ! These derivatives are wrt sigma_model (not sigma_apparent),
  3441. ! e.g. d-rho_apparent / d-sigma_model.
  3442. ! Also note: Phase is returned in degrees.
  3443. IF(IDX .EQ. 2)THEN !TE MODE
  3444. ZIMPD = (FTD - ZIMP*AFTD(KP))/AFT(IN)
  3445.  
  3446. ! Zxy
  3447. ! zimped(kp,in,lfrq) = ELOG*PFC*ZIMPD
  3448. zimped(kp,in,lfrq) = ZIMPD
  3449.  
  3450. ! TE Apparent Resistivity
  3451. ! RTED(KP,IN,LFRQ) = PFC*(2./WU)*(REAL(ZIMP)*REAL(ZIMPD) &
  3452. ! & + AIMAG(ZIMP)*AIMAG(ZIMPD))/RHTE(IN,LFRQ)
  3453. RTED(KP,IN,LFRQ) = (2./WU) &
  3454. * (REAL(ZIMP)*REAL(ZIMPD) + AIMAG(ZIMP)*AIMAG(ZIMPD))
  3455.  
  3456. ! TE Phase
  3457. AIOR = AIMAG(ZIMP)/REAL(ZIMP)
  3458. ! PTED(KP,IN,LFRQ) = ELOG*PFC*RAD*(1./(1. + AIOR*AIOR)) &
  3459. ! & *(AIMAG(ZIMPD) - REAL(ZIMPD)*AIOR)/REAL(ZIMP)
  3460. PTED(KP,IN,LFRQ) = RAD*(1./(1. + AIOR*AIOR)) &
  3461. *(AIMAG(ZIMPD) - REAL(ZIMPD)*AIOR)/REAL(ZIMP)
  3462.  
  3463. ! Tipper
  3464. ! TPD = ELOG*PFC*(AFND(KP) - KZTE(IN,LFRQ)*AFTD(KP))/AFT(IN)
  3465. TPD = (AFND(KP) - KZTE(IN,LFRQ)*AFTD(KP))/AFT(IN)
  3466. KTED(KP,IN,LFRQ) = TPD
  3467.  
  3468. ELSE !TM MODE
  3469. ZIMPD = (AFTD(KP) - ZIMP*FTD)/FT
  3470.  
  3471. ! Zyx
  3472. ! zimpmd(kp,in,lfrq) = ELOG*PFC*ZIMPD
  3473. zimpmd(kp,in,lfrq) = ZIMPD
  3474.  
  3475. ! TM Apparent Resistivity
  3476. ! RTMD(KP,IN,LFRQ) = PFC*(2./WU)*(REAL(ZIMP)*REAL(ZIMPD) &
  3477. ! & + AIMAG(ZIMP)*AIMAG(ZIMPD))/RHTM(IN,LFRQ)
  3478. RTMD(KP,IN,LFRQ) = (2./WU) &
  3479. * (REAL(ZIMP)*REAL(ZIMPD) + AIMAG(ZIMP)*AIMAG(ZIMPD))
  3480.  
  3481. ! TM Phase
  3482. AIOR = AIMAG(ZIMP)/REAL(ZIMP)
  3483. ! PTMD(KP,IN,LFRQ) = ELOG*PFC*RAD*(1./(1. + AIOR*AIOR)) &
  3484. ! & *(AIMAG(ZIMPD) - REAL(ZIMPD)*AIOR)/REAL(ZIMP)
  3485. PTMD(KP,IN,LFRQ) = RAD*(1./(1. + AIOR*AIOR)) &
  3486. *(AIMAG(ZIMPD) - REAL(ZIMPD)*AIOR)/REAL(ZIMP)
  3487.  
  3488. ! Tipper
  3489. ! TPD = ELOG*PFC*(AFND(KP) - TZTM(IN,LFRQ)*AFTD(KP))/AFT(IN)
  3490. TPD = (AFND(KP) - TZTM(IN,LFRQ)*AFTD(KP))/AFT(IN)
  3491. TTMD(KP,IN,LFRQ) = TPD
  3492.  
  3493. END IF
  3494. 20 CONTINUE
  3495. 10 CONTINUE
  3496.  
  3497. RETURN
  3498. END SUBROUTINE APPRMTJ
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement