Télécharger pragmg.eso

Retour à la liste

Numérotation des lignes :

pragmg
  1. C PRAGMG SOURCE GOUNAND 25/03/24 21:15:08 12216
  2. SUBROUTINE PRAGMG(KMORS,KTYP,KNOD,KISA,KS2B,MATRIK,MAPREC,LRES,
  3. $ LNMV,INCX,ITER,INMV,
  4. $ RESID,KPREC,
  5. $ NREST,ICALRS,IDDOT,IMVEC,KTIME,LTIME,IMPR,IRET)
  6. IMPLICIT REAL*8 (A-H,O-Z)
  7. IMPLICIT INTEGER (I-N)
  8. C***********************************************************************
  9. C NOM : PRAGMG
  10. C DESCRIPTION :
  11. C Préparation de la résolution d'un système linéaire Ax=b
  12. C par une méthode Multigrille Algébrique
  13. C
  14. C LANGAGE : ESOPE
  15. C AUTEUR : Stéphane GOUNAND (CEA/DRN/DMT/SEMT/TTMF)
  16. C mél : gounand@semt2.smts.cea.fr
  17. C REFERENCE (bibtex-like) :
  18. C***********************************************************************
  19. C***********************************************************************
  20. C VERSION : v1, 17/06/08, version initiale
  21. C HISTORIQUE : 17/06/08 : Crétation
  22. C HISTORIQUE :
  23. C***********************************************************************
  24. C Prière de PRENDRE LE TEMPS de compléter les commentaires
  25. C en cas de modification de ce sous-programme afin de faciliter
  26. C la maintenance !
  27. C***********************************************************************
  28. *
  29. * .. Includes et pointeurs associés ..
  30. *
  31. -INC PPARAM
  32. -INC CCOPTIO
  33. -INC CCREEL
  34. -INC SMLREEL
  35. INTEGER JG
  36. POINTEUR LRES.MLREEL
  37. -INC SMLENTI
  38. POINTEUR LNMV.MLENTI
  39. POINTEUR KTYP.MLENTI
  40. POINTEUR KNOD.MLENTI
  41. POINTEUR IBLOCK.MLENTI
  42. POINTEUR IPERM.MLENTI
  43. POINTEUR JPERM.MLENTI
  44. POINTEUR MAPREC.MATRIK
  45. POINTEUR KMORS.PMORS
  46. POINTEUR KISA.IZA
  47. POINTEUR AMORS.PMORS
  48. POINTEUR AISA.IZA
  49. POINTEUR KS2B.IZA,RES.IZA
  50. POINTEUR INCX.IZA,INCDX.IZA
  51. POINTEUR INVDIA.IZA
  52. POINTEUR ILUM.PMORS
  53. POINTEUR ILUI.IZA
  54. -INC SMTABLE
  55. POINTEUR KTIME.MTABLE
  56. CHARACTER*8 CHARI
  57. LOGICAL LTIME,LOGII,LBLOCK
  58. * .. Parameters
  59. * This is a breakdown tolerance for BiCGSTAB-type method
  60. REAL*8 BRTOL
  61. *STAT-INC SMSTAT
  62. * .. Scalar Arguments ..
  63. INTEGER ITER, KPREC, IMPR, IRET
  64. INTEGER ICNT
  65. REAL*8 RESID,TOL,BNRM2,RNRM2,XFACT
  66. * ..
  67. * Vars reqd for STOPTEST2
  68. * REAL*8 TOL, BNRM2
  69. * ..
  70. * .. External subroutines ..
  71. * EXTERNAL STOPTEST2
  72. INTEGER NBVA,NJA,NTT,NTTPRE
  73. REAL*8 GNRM2
  74. EXTERNAL GNRM2
  75. * ..
  76. * .. Executable Statements ..
  77. *
  78. * WRITE(IOIMP,*) 'Debut de pragmg'
  79. IRET = 0
  80.  
  81. IVALI=0
  82. XVALI=0.D0
  83. LOGII=.FALSE.
  84. IRETI=0
  85. IAT =0
  86. XVALR=0.D0
  87. IRETR=0
  88. IST =0
  89. *
  90. * On récupère les paramètres
  91. *
  92. *
  93. SEGACT MATRIK
  94. SEGACT KMORS
  95. NTT =KMORS.IA(/1)-1
  96. NJA =KMORS.JA(/1)
  97. SEGACT KISA
  98. NBVA=KISA.A(/1)
  99. SEGACT KS2B
  100. SEGINI,RES=KS2B
  101. SEGACT INCX*MOD
  102. nbva=INCX.A(/1)
  103. SEGINI INCDX
  104. C
  105. C Initialisation de l'historique de convergence
  106. C
  107. JG=ITER+1
  108. SEGINI LNMV
  109. SEGINI LRES
  110. *
  111. * Autres paramètres
  112. *
  113. IJOB=0
  114. IF (IMPR.GT.2) THEN
  115. IPRINT=IOIMP
  116. ELSE
  117. IPRINT=-1
  118. ENDIF
  119. TOL=RESID
  120. ICNT=0
  121. *
  122. * AGMG ne fait que du résidu relatif d'où les petits ajustements
  123. * suivants.
  124. *
  125. * res = b - AX
  126. CALL GMOMV(IMVEC,'N',-1.D0,KMORS,KISA,INCX,1.D0,RES)
  127. BNRM2=GNRM2(KS2B)
  128. RNRM2=GNRM2(RES)
  129. IF (ICALRS.EQ.1) BNRM2=RNRM2
  130. IF (BNRM2.LT.XPETIT) BNRM2=1.D0
  131. RESID=RNRM2 / BNRM2
  132. LRES.PROG(ICNT+1)=RESID
  133. LNMV.LECT(ICNT+1)=1
  134. *
  135. IF (RESID.LE.TOL) THEN
  136. ITER=0
  137. GOTO 30
  138. ENDIF
  139. *
  140. IF (ICALRS.EQ.0) THEN
  141. XFACT=1.D0/RESID
  142. TOL=TOL*XFACT
  143. ENDIF
  144. *
  145. * To use the standard AGMG library, you should make sure that it
  146. * is compiled with same compiler and options than Castem's and that
  147. * the sequential example furnished with AGMG works.
  148. * Then it is sufficient to put agmg_seq.o and agmg.o in the
  149. * current directory and use essai for linking.
  150. *
  151. * No interface to the parallel version of agmg for now
  152. *
  153. WRITE(IOIMP,*) '***********************************'
  154. WRITE(IOIMP,*) ' '
  155. WRITE(IOIMP,*) 'Please uncomment the CALL AGMG(...',
  156. $ ' in the pragmg.eso subroutine if you wish to use'
  157. WRITE(IOIMP,*) 'the AGMG library by Y. Notay'
  158. WRITE(IOIMP,*) ' '
  159. WRITE(IOIMP,*) '***********************************'
  160. * 251 2
  161. *Tentative d'utilisation d'une option non implémentée
  162. CALL ERREUR(251)
  163. IRET=-1
  164. GOTO 9999
  165. *********************************************************************
  166. *
  167. * AGMG v3.3.7_block call (standard sequential version)
  168. *
  169. * 1) Trouver le nombre de blocs
  170. c$$$ NBLOCK=0
  171. c$$$ segact ktyp
  172. c$$$ ntt=ktyp.lect(/1)
  173. c$$$ if (nrest.lt.0) then
  174. c$$$ segact knod
  175. c$$$ ntt2=knod.lect(/1)
  176. c$$$ if (ntt2.ne.ntt) THEN
  177. c$$$ call erreur(5)
  178. c$$$ goto 9999
  179. c$$$ endif
  180. c$$$ endif
  181. c$$$ jg=ntt
  182. c$$$ segini iperm
  183. c$$$ segini jperm
  184. c$$$ nja=kisa.a(/1)
  185. c$$$ DO i=1,ntt
  186. c$$$ jblock=ktyp.lect(i)
  187. c$$$ if (jblock.gt.nblock) nblock=jblock
  188. c$$$ enddo
  189. c$$$ if (impr.gt.2) then
  190. c$$$ write(ioimp,*) 'Nb d''inconnues=',ntt
  191. c$$$ write(ioimp,*) 'Nb de termes=',kmors.ja(/1)
  192. c$$$ write(ioimp,*) 'Nb de termes 2=',nja
  193. c$$$ write(ioimp,*) 'Nb de blocs detectes nblock=',nblock
  194. c$$$ endif
  195. c$$$ JG=NBLOCK+1
  196. c$$$ SEGINI IBLOCK
  197. c$$$ lblock=nblock.gt.1
  198. c$$$ 187 FORMAT (5X,10I8)
  199. c$$$ if (lblock) then
  200. c$$$*
  201. c$$$* 2) Trouver le nombre d'inconnus par blocs
  202. c$$$ DO i=1,ktyp.lect(/1)
  203. c$$$ jblock=ktyp.lect(i)
  204. c$$$ iblock.lect(jblock)=iblock.lect(jblock)+1
  205. c$$$ enddo
  206. c$$$ if (impr.gt.2) then
  207. c$$$ write(ioimp,*) 'Nb inconnues par blocs'
  208. c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1))
  209. c$$$ endif
  210. c$$$* 3) D'où le segment de repérage
  211. c$$$ do i=nblock,1,-1
  212. c$$$ iblock.lect(i+1)=iblock.lect(i)
  213. c$$$ enddo
  214. c$$$ if (impr.gt.2) then
  215. c$$$ write(ioimp,*) 'Segment de repérage tmp'
  216. c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1))
  217. c$$$ endif
  218. c$$$ iblock.lect(1)=1
  219. c$$$ do i=1,nblock
  220. c$$$ iblock.lect(i+1)=iblock.lect(i+1)+iblock.lect(i)
  221. c$$$ enddo
  222. c$$$ if (impr.gt.2) then
  223. c$$$ write(ioimp,*) 'Segment de repérage'
  224. c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1))
  225. c$$$ endif
  226. c$$$* 4) Construction des permutations
  227. c$$$ ntt=kmors.ia(/1)-1
  228. c$$$ if (impr.gt.2) then
  229. c$$$ write(ioimp,*) 'Nb d''inconnues 2 ntt=',ntt
  230. c$$$ endif
  231. c$$$ ktt=1
  232. c$$$ do kblock=1,nblock
  233. c$$$ do itt=1,ntt
  234. c$$$ jblock=ktyp.lect(itt)
  235. c$$$ if (kblock.eq.jblock) then
  236. c$$$ iperm.lect(itt)=ktt
  237. c$$$ jperm.lect(ktt)=itt
  238. c$$$ ktt=ktt+1
  239. c$$$ endif
  240. c$$$ enddo
  241. c$$$ enddo
  242. c$$$* write(ioimp,*) 'Permutation i'
  243. c$$$* write(ioimp,187) (iperm.lect(I),I=1,iperm.lect(/1))
  244. c$$$* write(ioimp,*) 'Permutation j'
  245. c$$$* write(ioimp,187) (jperm.lect(I),I=1,jperm.lect(/1))
  246. c$$$*
  247. c$$$* 5) Permutation de la matrice et du second membre
  248. c$$$*
  249. c$$$ SEGINI,AMORS=KMORS
  250. c$$$ SEGINI,AISA=KISA
  251. c$$$* SEGINI,AMORS
  252. c$$$* SEGINI,AISA
  253. c$$$* write(ioimp,*) 'Avant permutation'
  254. c$$$* CALL ECMORS(AMORS,AISA,3)
  255. c$$$ job=1
  256. c$$$ CALL DPERM(ntt,kisa.a,kmors.ja,kmors.ia,
  257. c$$$ $ aisa.a,amors.ja,amors.ia,iperm.lect,jperm.lect,job)
  258. c$$$ CALL DVPERM(ntt,res.a,iperm.lect)
  259. c$$$ if (nrest.lt.0) CALL IVPERM(ntt,knod.lect,iperm.lect)
  260. c$$$* write(ioimp,*) 'Apres permutation'
  261. c$$$* CALL ECMORS(AMORS,AISA,3)
  262. c$$$ else
  263. c$$$ iblock.lect(1)=1
  264. c$$$ iblock.lect(2)=ntt+1
  265. c$$$ if (impr.gt.2) then
  266. c$$$ write(ioimp,*) 'Segment de repérage'
  267. c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1))
  268. c$$$ endif
  269. c$$$* Pas de permutation
  270. c$$$ SEGINI,AMORS=KMORS
  271. c$$$ SEGINI,AISA=KISA
  272. c$$$ endif
  273. c$$$*
  274. c$$$* Changement automatique du signe des lignes de la matrice
  275. c$$$* et du second membre si le terme diagonal est négatif.
  276. c$$$*
  277. c$$$* SEGACT,AMORS*mod
  278. c$$$* segact,AISA*mod
  279. c$$$ DO I=1,NTT
  280. c$$$ IFOUND=0
  281. c$$$ DO J=AMORS.IA(I),(AMORS.IA(I+1)-1)
  282. c$$$* WRITE(IOIMP,*) 'I,J=',I,J
  283. c$$$* WRITE(IOIMP,*) 'JA(J)=',AMORS.JA(J)
  284. c$$$ IF (AMORS.JA(J).EQ.I) THEN
  285. c$$$* WRITE(IOIMP,*) 'AISA.A(J)=',AISA.A(J)
  286. c$$$ IF (AISA.A(J).GT.XZERO) THEN
  287. c$$$ IFOUND=1
  288. c$$$ ELSEIF (AISA.A(J).LT.XZERO) THEN
  289. c$$$ IFOUND=-1
  290. c$$$ ENDIF
  291. c$$$ GOTO 10
  292. c$$$ ENDIF
  293. c$$$ ENDDO
  294. c$$$ 10 CONTINUE
  295. c$$$* WRITE(IOIMP,*) 'IFOUND=',IFOUND
  296. c$$$ IF (IFOUND.EQ.0) THEN
  297. c$$$ WRITE(IOIMP,*) 'The ',I
  298. c$$$ $ ,'th diagonal term of the matrix is nil'
  299. c$$$ IRET=-3
  300. c$$$ GOTO 9999
  301. c$$$ ELSEIF (IFOUND.EQ.-1) THEN
  302. c$$$ RES.A(I)=-1.D0*RES.A(I)
  303. c$$$ DO J=AMORS.IA(I),(AMORS.IA(I+1)-1)
  304. c$$$ AISA.A(J)=-1.D0*AISA.A(J)
  305. c$$$ ENDDO
  306. c$$$ ENDIF
  307. c$$$ ENDDO
  308. c$$$* WRITE(IOIMP,*) '4'
  309. c$$$* CALL ECMORS(AMORS,AISA,3)
  310. c$$$
  311. c$$$
  312. c$$$ ITR2=ITER-1
  313. c$$$ instance=0
  314. c$$$ IF (NREST.GE.0) then
  315. c$$$* IPRINT=-978
  316. c$$$ CALL DAGMG(NTT,AISA.A,AMORS.JA,AMORS.IA,RES.A,INCDX.A,
  317. c$$$ $ IJOB,IPRINT,NREST,ITR2,TOL,NBLOCK,IBLOCK.LECT)
  318. c$$$ ELSE
  319. c$$$ IF (.NOT.lblock) THEN
  320. c$$$ write(ioimp,*) 'The AGMG Stokes solver needs blocks'
  321. c$$$ moterr(1:8)='pragmg'
  322. c$$$ call erreur(1127)
  323. c$$$ return
  324. c$$$ ENDIF
  325. c$$$ NRESTA=ABS(NREST)
  326. c$$$ if (nresta.GT.1) then
  327. c$$$ nddl1=iblock.lect(2)-iblock.lect(1)
  328. c$$$ do i=2,nblock
  329. c$$$ nddl=iblock.lect(i+1)-iblock.lect(i)
  330. c$$$ if (nddl.ne.nddl1) then
  331. c$$$ write(ioimp,*) 'Le bloc ',i,' de taille =',nddl
  332. c$$$ write(ioimp,*) 'na pas la meme taille que le bloc 1 ='
  333. c$$$ $ ,nddl1
  334. c$$$ moterr(1:8)='pragmg'
  335. c$$$ call erreur(1127)
  336. c$$$ return
  337. c$$$ endif
  338. c$$$ enddo
  339. c$$$*
  340. c$$$* Vérif que les inconnues sont dans le même ordre à l'intérieur de
  341. c$$$* chaque bloc
  342. c$$$*
  343. c$$$ do i=2,nblock
  344. c$$$ nddl=iblock.lect(i+1)-iblock.lect(i)
  345. c$$$ ideb=iblock.lect(i)
  346. c$$$ do iddl=1,nddl
  347. c$$$ inod1=knod.lect(iddl)
  348. c$$$ inodi=knod.lect(ideb+iddl-1)
  349. c$$$ if (inodi.ne.inod1) then
  350. c$$$ write(ioimp,*) 'Dans le bloc ',i,' le ddl ',iddl
  351. c$$$ $ ,' porte sur le noeud inodi=',inodi
  352. c$$$ write(ioimp,*) 'Dans le bloc ',1,' le ddl ',iddl
  353. c$$$ $ ,' porte sur le noeud inod1=',inod1
  354. c$$$ write(ioimp,*) 'inod1 != inodi est une erreur !'
  355. c$$$ moterr(1:8)='pragmg'
  356. c$$$ call erreur(1127)
  357. c$$$ return
  358. c$$$ endif
  359. c$$$ enddo
  360. c$$$ enddo
  361. c$$$
  362. c$$$ call DAGMG_STOKES_INTPARAM('smoothtype',-51,instance)
  363. c$$$ call DAGMG_STOKES_INTPARAM('pointcoarsening',1,instance)
  364. c$$$ call DAGMG_STOKES_INTPARAM('Ltransform',1,instance)
  365. c$$$ endif
  366. c$$$ CALL DAGMG_STOKES(NTT,AISA.A,AMORS.JA,AMORS.IA,RES.A,INCDX.A,
  367. c$$$ $ IJOB,IPRINT,NREST,ITR2,TOL,NBLOCK,IBLOCK.LECT)
  368. c$$$
  369. c$$$ ENDIF
  370. c$$$ CALL dagmg_status(istat,instance)
  371. c$$$ CALL dagmg_niter(itr2,instance)
  372. c$$$
  373. c$$$ if (lblock) then
  374. c$$$ CALL DVPERM(ntt,incdx.a,jperm.lect)
  375. c$$$ endif
  376. c$$$ SEGSUP IBLOCK
  377. c$$$ segsup iperm
  378. c$$$ segsup jperm
  379. c$$$
  380. c$$$
  381. c$$$
  382. c$$$* X = X_0 + \delta X
  383. c$$$ CALL GAXPY(1.D0,INCDX,INCX)
  384. c$$$* Résidu final
  385. c$$$ CALL GCOPY(KS2B,RES)
  386. c$$$ CALL GMOMV(IMVEC,'N',-1.D0,KMORS,KISA,INCX,1.D0,RES)
  387. c$$$ RNRM2=GNRM2(RES)
  388. c$$$ RESID=RNRM2/BNRM2
  389. c$$$*
  390. c$$$ IF (istat.NE.0) THEN
  391. c$$$ IRET=1
  392. c$$$ ELSE
  393. c$$$ IRET=0
  394. c$$$ ENDIF
  395. c$$$ ITER=ITR2
  396. c$$$*
  397. c$$$ ICNT=ICNT+1
  398. c$$$ LRES.PROG(ICNT+1)=RESID
  399. c$$$ LNMV.LECT(ICNT+1)=1+ITER
  400. c$$$ INMV=1+ITER
  401. *
  402. * End of AGMG call (standard sequential version)
  403. *
  404. *********************************************************************
  405. *
  406. IF (LTIME) THEN
  407. CHARI='MGAGGREG'
  408. CALL ECCTAB(KTIME,'MOT ',IVALI,XVALI,CHARI,LOGII,IRETI,
  409. $ 'ENTIER ',IAT,XVALR,CHARR,LOGIR,IRETR)
  410. CHARI='MGSOLUTI'
  411. CALL ECCTAB(KTIME,'MOT ',IVALI,XVALI,CHARI,LOGII,IRETI,
  412. $ 'ENTIER ',IST,XVALR,CHARR,LOGIR,IRETR)
  413. ENDIF
  414. *
  415. C
  416. C Désactivation
  417. C
  418. 30 CONTINUE
  419. JG=ICNT+1
  420. SEGADJ LRES
  421. SEGDES LRES
  422. SEGADJ LNMV
  423. SEGDES LNMV
  424. SEGSUP INCDX
  425. SEGDES INCX
  426. SEGDES KS2B
  427. SEGSUP RES
  428. SEGSUP AISA
  429. * SEGSUP ATYP
  430. SEGSUP AMORS
  431. SEGDES KISA
  432. SEGDES KTYP
  433. if (nrest.lt.0) SEGDES KNOD
  434. SEGDES KMORS
  435. SEGDES MATRIK
  436. C
  437. C A breakdown has occured in the CGS method
  438. C
  439. IF (IRET.LT.0) GOTO 9999
  440. *
  441. * Normal termination
  442. *
  443. RETURN
  444. *
  445. * Format handling
  446. *
  447. * 1002 FORMAT(10(1X,1PE11.4))
  448. *
  449. * Error handling
  450. *
  451. 9999 CONTINUE
  452. WRITE(IOIMP,*) 'An error was detected in pragmg.eso'
  453. RETURN
  454. *
  455. * End of PRAGMG
  456. *
  457. END
  458.  
  459.  

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