Télécharger dsapps.eso

Retour à la liste

Numérotation des lignes :

dsapps
  1. C DSAPPS SOURCE FANDEUR 22/05/02 21:15:14 11359
  2. c-----------------------------------------------------------------------
  3. c\BeginDoc
  4. c
  5. c\Name: dsapps
  6. c
  7. c\Description:
  8. c Given the Arnoldi factorization
  9. c
  10. c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
  11. c
  12. c apply NP shifts implicitly resulting in
  13. c
  14. c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
  15. c
  16. c where Q is an orthogonal matrix of order KEV+NP. Q is the product of
  17. c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi
  18. c factorization becomes:
  19. c
  20. c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
  21. c
  22. c\Usage:
  23. c call dsapps
  24. c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD )
  25. c
  26. c\Arguments
  27. c N Integer. (INPUT)
  28. c Problem size, i.e. dimension of matrix A.
  29. c
  30. c KEV Integer. (INPUT)
  31. c INPUT: KEV+NP is the size of the input matrix H.
  32. c OUTPUT: KEV is the size of the updated matrix HNEW.
  33. c
  34. c NP Integer. (INPUT)
  35. c Number of implicit shifts to be applied.
  36. c
  37. c SHIFT Double precision array of length NP. (INPUT)
  38. c The shifts to be applied.
  39. c
  40. c V REAL*8 N by (KEV+NP) array. (INPUT/OUTPUT)
  41. c INPUT: V contains the current KEV+NP Arnoldi vectors.
  42. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors
  43. c are in the first KEV columns of V.
  44. c
  45. c LDV Integer. (INPUT)
  46. c Leading dimension of V exactly as declared in the calling
  47. c program.
  48. c
  49. c H REAL*8 (KEV+NP) by 2 array. (INPUT/OUTPUT)
  50. c INPUT: H contains the symmetric tridiagonal matrix of the
  51. c Arnoldi factorization with the subdiagonal in the 1st column
  52. c starting at H(2,1) and the main diagonal in the 2nd column.
  53. c OUTPUT: H contains the updated tridiagonal matrix in the
  54. c KEV leading submatrix.
  55. c
  56. c LDH Integer. (INPUT)
  57. c Leading dimension of H exactly as declared in the calling
  58. c program.
  59. c
  60. c RESID Double precision array of length (N). (INPUT/OUTPUT)
  61. c INPUT: RESID contains the the residual vector r_{k+p}.
  62. c OUTPUT: RESID is the updated residual vector rnew_{k}.
  63. c
  64. c Q REAL*8 KEV+NP by KEV+NP work array. (WORKSPACE)
  65. c Work array used to accumulate the rotations during the bulge
  66. c chase sweep.
  67. c
  68. c LDQ Integer. (INPUT)
  69. c Leading dimension of Q exactly as declared in the calling
  70. c program.
  71. c
  72. c WORKD Double precision work array of length 2*N. (WORKSPACE)
  73. c Distributed array used in the application of the accumulated
  74. c orthogonal matrix Q.
  75. c
  76. c\EndDoc
  77. c
  78. c-----------------------------------------------------------------------
  79. c
  80. c\BeginLib
  81. c
  82. c\Local variables:
  83. c xxxxxx real
  84. c
  85. c\References:
  86. c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
  87. c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
  88. c pp 357-385.
  89. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
  90. c Restarted Arnoldi Iteration", Rice University Technical Report
  91. c TR95-13, Department of Computational and Applied Mathematics.
  92. c
  93. c\Routines called:
  94. c ivout ARPACK utility routine that prints integers.
  95. c arscnd ARPACK utility routine for timing. -> deleted by BP in 2020
  96. c dvout ARPACK utility routine that prints vectors.
  97. c dlamch LAPACK routine that determines machine constants.
  98. c dlartg LAPACK Givens rotation construction routine.
  99. c dlacpy LAPACK matrix copy routine.
  100. c dlaset LAPACK matrix initialization routine.
  101. c dgemv Level 2 BLAS routine for matrix vector multiplication.
  102. c daxpy Level 1 BLAS that computes a vector triad.
  103. c dcopy Level 1 BLAS that copies one vector to another.
  104. c dscal Level 1 BLAS that scales a vector.
  105. c
  106. c\Author
  107. c Danny Sorensen Phuong Vu
  108. c Richard Lehoucq CRPC / Rice University
  109. c Dept. of Computational & Houston, Texas
  110. c Applied Mathematics
  111. c Rice University
  112. c Houston, Texas
  113. c
  114. c\Revision history:
  115. c 12/16/93: Version ' 2.4'
  116. c
  117. c\SCCS Information: @(#)
  118. c FILE: sapps.F SID: 2.6 DATE OF SID: 3/28/97 RELEASE: 2
  119. c
  120. c\Remarks
  121. c 1. In this version, each shift is applied to all the subblocks of
  122. c the tridiagonal matrix H and not just to the submatrix that it
  123. c comes from. This routine assumes that the subdiagonal elements
  124. c of H that are stored in h(1:kev+np,1) are nonegative upon input
  125. c and enforce this condition upon output. This version incorporates
  126. c deflation. See code for documentation.
  127. c
  128. c\EndLib
  129. c
  130. c-----------------------------------------------------------------------
  131. c
  132. subroutine dsapps
  133. & ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd )
  134. c
  135. c %----------------------------------------------------%
  136. c | Include files for debugging and timing information |
  137. c -INC TARTRAK
  138. c %----------------------------------------------------%
  139. c
  140. c
  141. c %------------------%
  142. c | Scalar Arguments |
  143. c %------------------%
  144. c
  145. integer kev, ldh, ldq, ldv, n, np
  146. c
  147. c %-----------------%
  148. c | Array Arguments |
  149. c %-----------------%
  150. c
  151. REAL*8
  152. & h(ldh,2), q(ldq,kev+np), resid(n), shift(np),
  153. & v(ldv,kev+np), workd(2*n)
  154. c
  155. c %------------%
  156. c | Parameters |
  157. c %------------%
  158. c
  159. REAL*8
  160. & one, zero
  161. parameter (one = 1.0D+0, zero = 0.0D+0)
  162. c
  163. c %---------------%
  164. c | Local Scalars |
  165. c %---------------%
  166. c
  167. integer i, iend, istart, itop, j, jj, kplusp, msglvl
  168. parameter (msglvl=0)
  169. logical first
  170. REAL*8
  171. & a1, a2, a3, a4, big, c, epsmch, f, g, r, s
  172. save epsmch, first
  173. c
  174. c
  175. c %----------------------%
  176. c | External Subroutines |
  177. c %----------------------%
  178. c
  179. external daxpy, dcopy, dscal, dlacpy,
  180. c
  181. c %--------------------%
  182. c | External Functions |
  183. c %--------------------%
  184. c
  185. REAL*8
  186. external dlamch
  187. c
  188. c %----------------------%
  189. **c | Intrinsics Functions |
  190. **c %----------------------%
  191. **c
  192. ** intrinsic abs
  193. **c
  194. **c %----------------%
  195. **c | Data statments |
  196. **c %----------------%
  197. **c
  198. data first / .true. /
  199. **c
  200. **c %-----------------------%
  201. **c | Executable Statements |
  202. c %-----------------------%
  203. c
  204. if (first) then
  205. epsmch = dlamch('Epsilon-Machine')
  206. first = .false.
  207. end if
  208. itop = 1
  209. c
  210. c %-------------------------------%
  211. c | Initialize timing statistics |
  212. c | & message level for debugging |
  213. c %-------------------------------%
  214. c
  215. * call arscnd (t0)
  216. c msglvl = msapps
  217. c
  218. kplusp = kev + np
  219. c
  220. c %----------------------------------------------%
  221. c | Initialize Q to the identity matrix of order |
  222. c | kplusp used to accumulate the rotations. |
  223. c %----------------------------------------------%
  224. c
  225. call dlaset ('All', kplusp, kplusp, zero, one, q, ldq)
  226. c
  227. c %----------------------------------------------%
  228. c | Quick return if there are no shifts to apply |
  229. c %----------------------------------------------%
  230. c
  231. if (np .eq. 0) go to 9000
  232. c
  233. c %----------------------------------------------------------%
  234. c | Apply the np shifts implicitly. Apply each shift to the |
  235. c | whole matrix and not just to the submatrix from which it |
  236. c | comes. |
  237. c %----------------------------------------------------------%
  238. c
  239. do 90 jj = 1, np
  240. c
  241. istart = itop
  242. c
  243. c %----------------------------------------------------------%
  244. c | Check for splitting and deflation. Currently we consider |
  245. c | an off-diagonal element h(i+1,1) negligible if |
  246. c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) |
  247. c | for i=1:KEV+NP-1. |
  248. c | If above condition tests true then we set h(i+1,1) = 0. |
  249. c | Note that h(1:KEV+NP,1) are assumed to be non negative. |
  250. c %----------------------------------------------------------%
  251. c
  252. 20 continue
  253. c
  254. c %------------------------------------------------%
  255. c | The following loop exits early if we encounter |
  256. c | a negligible off diagonal element. |
  257. c %------------------------------------------------%
  258. c
  259. do 30 i = istart, kplusp-1
  260. big = abs(h(i,2)) + abs(h(i+1,2))
  261. if (h(i+1,1) .le. epsmch*big) then
  262. if (msglvl .gt. 0) then
  263. call ivout ( 1, i, ndigit,
  264. & '_sapps: deflation at row/column no.')
  265. call ivout ( 1, jj, ndigit,
  266. & '_sapps: occured before shift number.')
  267. call dvout ( 1, h(i+1,1), ndigit,
  268. & '_sapps: the corresponding off diagonal element')
  269. end if
  270. h(i+1,1) = zero
  271. iend = i
  272. go to 40
  273. end if
  274. 30 continue
  275. iend = kplusp
  276. 40 continue
  277. c
  278. if (istart .lt. iend) then
  279. c
  280. c %--------------------------------------------------------%
  281. c | Construct the plane rotation G'(istart,istart+1,theta) |
  282. c | that attempts to drive h(istart+1,1) to zero. |
  283. c %--------------------------------------------------------%
  284. c
  285. f = h(istart,2) - shift(jj)
  286. g = h(istart+1,1)
  287. call dlartg (f, g, c, s, r)
  288. c
  289. c %-------------------------------------------------------%
  290. c | Apply rotation to the left and right of H; |
  291. c | H <- G' * H * G, where G = G(istart,istart+1,theta). |
  292. c | This will create a "bulge". |
  293. c %-------------------------------------------------------%
  294. c
  295. a1 = c*h(istart,2) + s*h(istart+1,1)
  296. a2 = c*h(istart+1,1) + s*h(istart+1,2)
  297. a4 = c*h(istart+1,2) - s*h(istart+1,1)
  298. a3 = c*h(istart+1,1) - s*h(istart,2)
  299. h(istart,2) = c*a1 + s*a2
  300. h(istart+1,2) = c*a4 - s*a3
  301. h(istart+1,1) = c*a3 + s*a4
  302. c
  303. c %----------------------------------------------------%
  304. c | Accumulate the rotation in the matrix Q; Q <- Q*G |
  305. c %----------------------------------------------------%
  306. c
  307. do 60 j = 1, min(istart+jj,kplusp)
  308. a1 = c*q(j,istart) + s*q(j,istart+1)
  309. q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1)
  310. q(j,istart) = a1
  311. 60 continue
  312. c
  313. c
  314. c %----------------------------------------------%
  315. c | The following loop chases the bulge created. |
  316. c | Note that the previous rotation may also be |
  317. c | done within the following loop. But it is |
  318. c | kept separate to make the distinction among |
  319. c | the bulge chasing sweeps and the first plane |
  320. c | rotation designed to drive h(istart+1,1) to |
  321. c | zero. |
  322. c %----------------------------------------------%
  323. c
  324. do 70 i = istart+1, iend-1
  325. c
  326. c %----------------------------------------------%
  327. c | Construct the plane rotation G'(i,i+1,theta) |
  328. c | that zeros the i-th bulge that was created |
  329. c | by G(i-1,i,theta). g represents the bulge. |
  330. c %----------------------------------------------%
  331. c
  332. f = h(i,1)
  333. g = s*h(i+1,1)
  334. c
  335. c %----------------------------------%
  336. c | Final update with G(i-1,i,theta) |
  337. c %----------------------------------%
  338. c
  339. h(i+1,1) = c*h(i+1,1)
  340. call dlartg (f, g, c, s, r)
  341. c
  342. c %-------------------------------------------%
  343. c | The following ensures that h(1:iend-1,1), |
  344. c | the first iend-2 off diagonal of elements |
  345. c | H, remain non negative. |
  346. c %-------------------------------------------%
  347. c
  348. if (r .lt. zero) then
  349. r = -r
  350. c = -c
  351. s = -s
  352. end if
  353. c
  354. c %--------------------------------------------%
  355. c | Apply rotation to the left and right of H; |
  356. c | H <- G * H * G', where G = G(i,i+1,theta) |
  357. c %--------------------------------------------%
  358. c
  359. h(i,1) = r
  360. c
  361. a1 = c*h(i,2) + s*h(i+1,1)
  362. a2 = c*h(i+1,1) + s*h(i+1,2)
  363. a3 = c*h(i+1,1) - s*h(i,2)
  364. a4 = c*h(i+1,2) - s*h(i+1,1)
  365. c
  366. h(i,2) = c*a1 + s*a2
  367. h(i+1,2) = c*a4 - s*a3
  368. h(i+1,1) = c*a3 + s*a4
  369. c
  370. c %----------------------------------------------------%
  371. c | Accumulate the rotation in the matrix Q; Q <- Q*G |
  372. c %----------------------------------------------------%
  373. c
  374. do 50 j = 1, min( i+jj, kplusp )
  375. a1 = c*q(j,i) + s*q(j,i+1)
  376. q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
  377. q(j,i) = a1
  378. 50 continue
  379. c
  380. 70 continue
  381. c
  382. end if
  383. c
  384. c %--------------------------%
  385. c | Update the block pointer |
  386. c %--------------------------%
  387. c
  388. istart = iend + 1
  389. c
  390. c %------------------------------------------%
  391. c | Make sure that h(iend,1) is non-negative |
  392. c | If not then set h(iend,1) <-- -h(iend,1) |
  393. c | and negate the last column of Q. |
  394. c | We have effectively carried out a |
  395. c | similarity on transformation H |
  396. c %------------------------------------------%
  397. c
  398. if (h(iend,1) .lt. zero) then
  399. h(iend,1) = -h(iend,1)
  400. call dscal(kplusp, -one, q(1,iend), 1)
  401. end if
  402. c
  403. c %--------------------------------------------------------%
  404. c | Apply the same shift to the next block if there is any |
  405. c %--------------------------------------------------------%
  406. c
  407. if (iend .lt. kplusp) go to 20
  408. c
  409. c %-----------------------------------------------------%
  410. c | Check if we can increase the the start of the block |
  411. c %-----------------------------------------------------%
  412. c
  413. do 80 i = itop, kplusp-1
  414. if (h(i+1,1) .gt. zero) go to 90
  415. itop = itop + 1
  416. 80 continue
  417. c
  418. c %-----------------------------------%
  419. c | Finished applying the jj-th shift |
  420. c %-----------------------------------%
  421. c
  422. 90 continue
  423. c
  424. c %------------------------------------------%
  425. c | All shifts have been applied. Check for |
  426. c | more possible deflation that might occur |
  427. c | after the last shift is applied. |
  428. c %------------------------------------------%
  429. c
  430. do 100 i = itop, kplusp-1
  431. big = abs(h(i,2)) + abs(h(i+1,2))
  432. if (h(i+1,1) .le. epsmch*big) then
  433. if (msglvl .gt. 0) then
  434. call ivout ( 1, i, ndigit,
  435. & '_sapps: deflation at row/column no.')
  436. call dvout ( 1, h(i+1,1), ndigit,
  437. & '_sapps: the corresponding off diagonal element')
  438. end if
  439. h(i+1,1) = zero
  440. end if
  441. 100 continue
  442. c
  443. c %-------------------------------------------------%
  444. c | Compute the (kev+1)-st column of (V*Q) and |
  445. c | temporarily store the result in WORKD(N+1:2*N). |
  446. c | This is not necessary if h(kev+1,1) = 0. |
  447. c %-------------------------------------------------%
  448. c
  449. if ( h(kev+1,1) .gt. zero )
  450. & call dgemv ('N', n, kplusp, one, v, ldv,
  451. & q(1,kev+1), 1, zero, workd(n+1), 1)
  452. c
  453. c %-------------------------------------------------------%
  454. c | Compute column 1 to kev of (V*Q) in backward order |
  455. c | taking advantage that Q is an upper triangular matrix |
  456. c | with lower bandwidth np. |
  457. c | Place results in v(:,kplusp-kev:kplusp) temporarily. |
  458. c %-------------------------------------------------------%
  459. c
  460. do 130 i = 1, kev
  461. call dgemv ('N', n, kplusp-i+1, one, v, ldv,
  462. & q(1,kev-i+1), 1, zero, workd, 1)
  463. call dcopy (n, workd, 1, v(1,kplusp-i+1), 1)
  464. 130 continue
  465. c
  466. c %-------------------------------------------------%
  467. c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
  468. c %-------------------------------------------------%
  469. c
  470. call dlacpy ('All', n, kev, v(1,np+1), ldv, v, ldv)
  471. c
  472. c %--------------------------------------------%
  473. c | Copy the (kev+1)-st column of (V*Q) in the |
  474. c | appropriate place if h(kev+1,1) .ne. zero. |
  475. c %--------------------------------------------%
  476. c
  477. if ( h(kev+1,1) .gt. zero )
  478. & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1)
  479. c
  480. c %-------------------------------------%
  481. c | Update the residual vector: |
  482. c | r <- sigmak*r + betak*v(:,kev+1) |
  483. c | where |
  484. c | sigmak = (e_{kev+p}'*Q)*e_{kev} |
  485. c | betak = e_{kev+1}'*H*e_{kev} |
  486. c %-------------------------------------%
  487. c
  488. call dscal (n, q(kplusp,kev), resid, 1)
  489. if (h(kev+1,1) .gt. zero)
  490. & call daxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1)
  491. c
  492. c if (msglvl .gt. 1) then
  493. c call dvout ( 1, q(kplusp,kev), ndigit,
  494. c & '_sapps: sigmak of the updated residual vector')
  495. c call dvout ( 1, h(kev+1,1), ndigit,
  496. c & '_sapps: betak of the updated residual vector')
  497. c call dvout ( kev, h(1,2), ndigit,
  498. c & '_sapps: updated main diagonal of H for next iteration')
  499. c if (kev .gt. 1) then
  500. c call dvout ( kev-1, h(2,1), ndigit,
  501. c & '_sapps: updated sub diagonal of H for next iteration')
  502. c end if
  503. c end if
  504. c
  505. * call arscnd (t1)
  506. c tsapps = tsapps + (t1 - t0)
  507. c
  508. 9000 continue
  509. c return
  510. c
  511. c %---------------%
  512. c | End of dsapps |
  513. c %---------------%
  514. c
  515. end
  516.  
  517.  
  518.  
  519.  
  520.  

© Cast3M 2003 - Tous droits réservés.
Mentions légales