source: CIVL/examples/fortran/nek5000/core/navier4.f

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100755
File size: 37.3 KB
Line 
1c-----------------------------------------------------------------------
2c
3c TO DO: Need to monitor dssum when using DG. (11/29/15, pff)
4c
5c Specifically - line 837 in navier4.f
6c - line 537 in hmholtz.f
7c
8c-----------------------------------------------------------------------
9 subroutine setrhs(p,h1,h2,h2inv)
10C
11C Project rhs onto best fit in the "E" norm.
12C
13 include 'SIZE'
14 include 'INPUT'
15 include 'MASS'
16 include 'SOLN'
17 include 'TSTEP'
18C
19 REAL P (LX2,LY2,LZ2,LELV)
20 REAL H1 (LX1,LY1,LZ1,LELV)
21 REAL H2 (LX1,LY1,LZ1,LELV)
22 REAL H2INV(LX1,LY1,LZ1,LELV)
23C
24 logical ifdump
25 save ifdump
26 data ifdump /.false./
27C
28 PARAMETER (LTOT2=LX2*LY2*LZ2*LELV)
29 COMMON /ORTHOV/ RHS(LTOT2,MXPREV)
30 COMMON /ORTHOX/ Pbar(LTOT2),Pnew(LTOT2)
31 COMMON /ORTHOS/ ALPHA(Mxprev), WORK(Mxprev), ALPHAN, DTLAST
32 COMMON /ORTHOI/ Nprev,Mprev
33 REAL ALPHA,WORK
34C
35C
36 integer icalld
37 save icalld
38 data icalld/0/
39C
40C First call, we have no vectors to orthogonalize against.
41 IF (ICALLD.EQ.0) THEN
42 icalld=icalld+1
43 Nprev=0
44 Mprev=param(93)
45 Mprev=min(Mprev,Mxprev)
46 endif
47C
48C Diag to see how much reduction in the residual is attained.
49C
50 NTOT2 = lx2*ly2*lz2*NELV
51 ALPHA1 = GLSC3(p,p,bm2inv,NTOT2)
52 if (alpha1.gt.0) ALPHA1 = sqrt(alpha1/volvm2)
53C
54C Update rhs's if E-matrix has changed
55C
56 CALL UPDRHSE(P,H1,H2,H2INV,ierr)
57 if (ierr.eq.1) Nprev=0
58C
59C Perform Gram-Schmidt for previous rhs's.
60C
61 DO 10 I=1,Nprev
62 ALPHA(i) = VLSC2(P,RHS(1,i),NTOT2)
63 10 CONTINUE
64C
65 IF (Nprev.GT.0) CALL gop(alpha,WORK,'+ ',Nprev)
66C
67 CALL RZERO(Pbar,NTOT2)
68 DO 20 I=1,Nprev
69 alphas = alpha(i)
70 CALL ADD2S2(Pbar,RHS(1,i),alphas,NTOT2)
71 20 CONTINUE
72C
73 if (Nprev.gt.0) then
74 INTETYPE = 1
75 CALL CDABDTP(Pnew,Pbar,H1,H2,H2INV,INTETYPE)
76 CALL SUB2 (P,Pnew,NTOT2)
77C ................................................................
78C Diag.
79 ALPHA2 = GLSC3(p,p,bm2inv,NTOT2)
80 if (alpha2.gt.0) ALPHA2 = sqrt(alpha2/volvm2)
81 ratio = alpha1/alpha2
82 n10=min(10,nprev)
83c IF (NIO.EQ.0) WRITE(6,11)ISTEP,Nprev,(ALPHA(I),I=1,N10)
84c IF (NIO.EQ.0) WRITE(6,12) ISTEP,nprev,ALPHA1,ALPHA2,ratio
85 11 FORMAT(2I5,' alpha:',1p10e12.4)
86 12 FORMAT(I6,i4,1p3e12.4,' alph12')
87C
88c if (alpha1.gt.0.001 .and. .not.ifdump) then
89c IF (NID.EQ.0) WRITE(6,*) 'alph1 large ... '
90c if (istep.gt.10) then
91c IF (NID.EQ.0) WRITE(6,*) ' ... dumping'
92c call prepost (.true.,' ')
93c ifdump = .true.
94c else
95c IF (NID.EQ.0) WRITE(6,*) ' ... doing nothing'
96c endif
97c endif
98c if (alpha1.gt.0.1.and.istep.gt.10) then
99c IF (NID.EQ.0) WRITE(6,*) 'alph1 too large ... aborting'
100c call prepost (.true.,' ')
101c call exitt
102c endif
103C ................................................................
104 endif
105C
106C
107 return
108 end
109c-----------------------------------------------------------------------
110 subroutine gensoln(p,h1,h2,h2inv)
111C
112C Reconstruct the solution to the original problem by adding back
113C the previous solutions
114C know the soln.
115C
116 include 'SIZE'
117 PARAMETER (LTOT2=LX2*LY2*LZ2*LELV)
118 COMMON /ORTHOV/ RHS(LTOT2,MXPREV)
119 COMMON /ORTHOX/ Pbar(LTOT2),Pnew(LTOT2)
120 COMMON /ORTHOS/ ALPHA(Mxprev), WORK(Mxprev), ALPHAN, DTLAST
121 COMMON /ORTHOI/ Nprev,Mprev
122 REAL ALPHA,WORK
123
124 REAL P (LX2,LY2,LZ2,LELV)
125 REAL H1 (LX1,LY1,LZ1,LELV)
126 REAL H2 (LX1,LY1,LZ1,LELV)
127 REAL H2INV(LX1,LY1,LZ1,LELV)
128C
129 NTOT2=lx2*ly2*lz2*NELV
130C
131C First, save current solution
132C
133 CALL COPY (Pnew,P,NTOT2)
134C
135C Reconstruct solution
136C
137 CALL ADD2(P,Pbar,NTOT2)
138C
139C Update the set of <p,rhs>
140C
141 CALL UPDTSET(P,H1,H2,H2INV,ierr)
142 if (ierr.eq.1) Nprev = 0
143c
144 return
145 end
146c-----------------------------------------------------------------------
147 subroutine updtset(p,h1,h2,h2inv,IERR)
148C
149C Update the set of rhs's and the corresponding p-set:
150C
151C . Standard case is to add P_new, and RHS_new = E*P_new
152C
153C . However, when Nprev=Mprev (max. allowed), we throw out
154C the old set, and set P_1 = P, RHS_1=E*P_1
155C
156C . Other schemes are possible, e.g., let's save a bunch of
157C old vectors, perhaps chosen wisely via P.O.D.
158C
159C
160 include 'SIZE'
161 include 'INPUT'
162 include 'MASS'
163 PARAMETER (LTOT2=LX2*LY2*LZ2*LELV)
164 COMMON /ORTHOV/ RHS(LTOT2,MXPREV)
165 COMMON /ORTHOX/ Pbar(LTOT2),Pnew(LTOT2)
166 COMMON /ORTHOS/ ALPHA(Mxprev), WORK(Mxprev), ALPHAN, DTLAST
167 COMMON /ORTHOI/ Nprev,Mprev
168
169 REAL ALPHA,WORK
170
171 REAL P (LX2,LY2,LZ2,LELV)
172 REAL H1 (LX1,LY1,LZ1,LELV)
173 REAL H2 (LX1,LY1,LZ1,LELV)
174 REAL H2INV(LX1,LY1,LZ1,LELV)
175C
176 NTOT2=lx2*ly2*lz2*NELV
177C
178 IF (Nprev.EQ.Mprev) THEN
179 CALL COPY(Pnew,P,NTOT2)
180 Nprev=0
181 endif
182C
183C Increment solution set
184 Nprev = Nprev+1
185C
186 CALL COPY (RHS(1,Nprev),Pnew,NTOT2)
187
188C Orthogonalize rhs against previous rhs and normalize
189
190 write(6,*) istep,nprev,' call econj2'
191 call econj (nprev,h1,h2,h2inv,ierr)
192C call echeck(nprev,h1,h2,h2inv,intetype)
193C
194c Save last sol'n
195 CALL COPY(Pnew,P,NTOT2)
196C
197 return
198 end
199c-----------------------------------------------------------------------
200 subroutine econj(kprev,h1,h2,h2inv,ierr)
201C
202C Orthogonalize the rhs wrt previous rhs's for which we already
203C know the soln.
204C
205 include 'SIZE'
206 include 'INPUT'
207 include 'MASS'
208 include 'SOLN'
209 include 'TSTEP'
210C
211 REAL H1 (LX1,LY1,LZ1,LELV)
212 REAL H2 (LX1,LY1,LZ1,LELV)
213 REAL H2INV(LX1,LY1,LZ1,LELV)
214C
215 PARAMETER (LTOT2=LX2*LY2*LZ2*LELV)
216 COMMON /ORTHOV/ RHS(LTOT2,MXPREV)
217 COMMON /ORTHOX/ Pbar(LTOT2),Pnew(LTOT2),Pbrr(ltot2)
218 COMMON /ORTHOS/ ALPHA(Mxprev), WORK(Mxprev), ALPHAN, DTLAST
219 COMMON /ORTHOI/ Nprev,Mprev
220 REAL ALPHA,WORK
221 real ALPHAd
222C
223C
224 ierr = 0
225 NTOT2 = lx2*ly2*lz2*NELV
226 INTETYPE=1
227C
228C Gram Schmidt, w re-orthogonalization
229C
230 npass=1
231 if (abs(param(105)).eq.2) npass=2
232 do ipass=1,npass
233c
234 CALL CDABDTP(Pbrr,RHS(1,Kprev),H1,H2,H2INV,INTETYPE)
235C
236C Compute part of the norm
237 Alphad = GLSC2(RHS(1,Kprev),Pbrr,NTOT2)
238C
239C Gram-Schmidt
240 Kprev1=Kprev-1
241 DO 10 I=1,Kprev1
242 ALPHA(I) = VLSC2(Pbrr,RHS(1,i),NTOT2)
243 10 CONTINUE
244 IF (Kprev1.GT.0) CALL gop(alpha,WORK,'+ ',Kprev1)
245C
246 DO 20 I=1,Kprev1
247 alpham = -alpha(i)
248 CALL ADD2S2(RHS(1,Kprev),RHS (1,i),alpham,NTOT2)
249 Alphad = Alphad - alpha(i)**2
250 20 CONTINUE
251 enddo
252C
253C .Normalize new element in P~
254C
255 if (ALPHAd.le.0.0) then
256 if (nio.eq.0)
257 $ write(6,*) 'ERROR: alphad .le. 0 in econj',alphad,Kprev
258 ierr = 1
259 return
260 endif
261 ALPHAd = 1.0/SQRT(ALPHAd)
262 ALPHAN = Alphad
263 CALL CMULT(RHS (1,Kprev),alphan,NTOT2)
264C
265 return
266 end
267c-----------------------------------------------------------------------
268 subroutine chkptol
269C--------------------------------------------------------------------
270C
271C Check pressure tolerance for transient case.
272C
273C pff 6/20/92
274C This routine has been modified for diagnostic purposes only.
275C It can be replaced with the standard nekton version.
276C
277C--------------------------------------------------------------------
278 include 'SIZE'
279 include 'SOLN'
280 include 'MASS'
281 include 'INPUT'
282 include 'TSTEP'
283 COMMON /CTOLPR/ DIVEX
284 COMMON /CPRINT/ IFPRINT
285 LOGICAL IFPRINT
286C
287 COMMON /SCRUZ/ DIVV (LX2,LY2,LZ2,LELV)
288 $ , BDIVV(LX2,LY2,LZ2,LELV)
289C
290 if (ifsplit) return
291 IF (param(102).eq.0.and.(TOLPDF.NE.0. .OR. ISTEP.LE.5)) return
292 five = 5.0
293 if (param(102).ne.0.0) five=param(102)
294C
295 NTOT2 = lx2*ly2*lz2*NELV
296 if (ifield.eq.1) then ! avo: sub arguments?
297 CALL OPDIV (BDIVV,VX,VY,VZ)
298 else
299 CALL OPDIV (BDIVV,BX,BY,BZ)
300 endif
301 CALL COL3 (DIVV,BDIVV,BM2INV,NTOT2)
302 DNORM = SQRT(GLSC2(DIVV,BDIVV,NTOT2)/VOLVM2)
303C
304 if (nio.eq.0) WRITE (6,*) istep,' DNORM, DIVEX',DNORM,DIVEX
305C
306c IF (istep.gt.10.and.DNORM.GT.(1.01*DIVEX).AND.DIVEX.GT.0.) then
307c if (DNORM.gt.1e-8) then
308c if (nid.eq.0) WRITE(6,*) 'DNORM-DIVEX div. ... aborting'
309c call prepost (.true.,' ')
310c call exitt
311c else
312c if (nid.eq.0) WRITE(6,*) 'DNORM-DIVEX div. ... small'
313c endif
314c endif
315C
316c IF (DNORM.GT.(1.2*DIVEX).AND.DIVEX.GT.0.) TOLPDF = 5.*DNORM
317 IF (istep.gt.5.and.tolpdf.eq.0.0.and.
318 $ DNORM.GT.(1.2*DIVEX).AND.DIVEX.GT.0.)
319 $ TOLPDF = FIVE*DNORM
320C
321 return
322 end
323 FUNCTION VLSC3(X,Y,B,N)
324C
325C local inner product, with weight
326C
327 DIMENSION X(1),Y(1),B(1)
328 REAL DT
329C
330 include 'OPCTR'
331C
332#ifdef TIMER
333C
334 if (isclld.eq.0) then
335 isclld=1
336 nrout=nrout+1
337 myrout=nrout
338 rname(myrout) = 'VLSC3 '
339 endif
340 isbcnt = 3*n
341 dct(myrout) = dct(myrout) + dfloat(isbcnt)
342 ncall(myrout) = ncall(myrout) + 1
343 dcount = dcount + dfloat(isbcnt)
344#endif
345C
346 DT = 0.0
347 DO 10 I=1,N
348 T = X(I)*Y(I)*B(I)
349 DT = DT+T
350 10 CONTINUE
351 T=DT
352 VLSC3 = T
353 return
354 end
355c-----------------------------------------------------------------------
356 subroutine updrhse(p,h1,h2,h2inv,ierr)
357C
358C Update rhs's if E-matrix has changed
359C
360C
361 include 'SIZE'
362 include 'INPUT'
363 include 'MASS'
364 include 'TSTEP'
365C
366 PARAMETER (LTOT2=LX2*LY2*LZ2*LELV)
367 COMMON /ORTHOV/ RHS(LTOT2,MXPREV)
368 COMMON /ORTHOX/ Pbar(LTOT2),Pnew(LTOT2)
369 COMMON /ORTHOS/ ALPHA(Mxprev), WORK(Mxprev), ALPHAN, DTLAST
370 COMMON /ORTHOI/ Nprev,Mprev
371 COMMON /ORTHOL/ IFNEWE
372 REAL ALPHA,WORK
373 LOGICAL IFNEWE
374C
375C
376 REAL P (LX2,LY2,LZ2,LELV)
377 REAL H1 (LX1,LY1,LZ1,LELV)
378 REAL H2 (LX1,LY1,LZ1,LELV)
379 REAL H2INV(LX1,LY1,LZ1,LELV)
380C
381 integer icalld
382 save icalld
383 data icalld/0/
384
385 ntot2=lx2*ly2*lz2*nelv
386
387
388C First, we have to decide if the E matrix has changed.
389
390
391 if (icalld.eq.0) then
392 icalld=1
393 dtlast=dt
394 endif
395
396 ifnewe=.false.
397 if (ifmvbd) then
398 ifnewe=.true.
399 call invers2(bm2inv,bm2,ntot2)
400 endif
401 if (dtlast.ne.dt) then
402 ifnewe=.true.
403 dtlast=dt
404 endif
405c if (ifnewe.and.nio.eq.0) write(6,*) istep,'reorthogo:',nprev
406
407
408C
409C Next, we reconstruct a new rhs set.
410C
411 if (ifnewe) then
412c
413c new idea...
414c if (nprev.gt.0) nprev=1
415c call copy(rhs,pnew,ntot2)
416c
417 Nprevt = Nprev
418 DO 100 Iprev=1,Nprevt
419C Orthogonalize this rhs w.r.t. previous rhs's
420 call econj (iprev,h1,h2,h2inv,ierr)
421 if (ierr.eq.1) then
422 if (nio.eq.0) write(6,*) istep,ierr,' econj error'
423 nprev = 0
424 return
425 endif
426 100 CONTINUE
427C
428 endif
429C
430 return
431 end
432c-----------------------------------------------------------------------
433 subroutine hconj(approx,k,h1,h2,vml,vmk,ws,name4,ierr)
434c
435c Orthonormalize the kth vector against vector set
436c
437 include 'SIZE'
438 include 'INPUT'
439 include 'MASS'
440 include 'SOLN'
441 include 'PARALLEL'
442 include 'TSTEP'
443c
444 parameter (lt=lx1*ly1*lz1*lelt)
445 real approx(lt,0:1),h1(1),h2(1),vml(1),vmk(1),ws(1)
446 character*4 name4
447c
448 ierr=0
449 ntot=lx1*ly1*lz1*nelfld(ifield)
450c
451 call axhelm (approx(1,0),approx(1,k),h1,h2,1,1)
452 call col2 (approx(1,0),vmk,ntot)
453c
454c Compute part of the norm (Note: a(0) already scaled by vml)
455c
456 alpha = glsc2(approx(1,0),approx(1,k),ntot)
457 alph1 = alpha
458c
459c Gram-Schmidt
460c
461 km1=k-1
462 do i=1,km1
463 ws(i) = vlsc2(approx(1,0),approx(1,i),ntot)
464 enddo
465 if (km1.gt.0) call gop(ws,ws(k),'+ ',km1)
466c
467 do i=1,km1
468 alpham = -ws(i)
469 call add2s2(approx(1,k),approx(1,i),alpham,ntot)
470 alpha = alpha - ws(i)**2
471 enddo
472c
473c .Normalize new element in approximation space
474c
475 eps = 1.e-7
476 if (wdsize.eq.8) eps = 1.e-15
477 ratio = alpha/alph1
478c
479 if (ratio.le.0) then
480 ierr=1
481 if (nio.eq.0) write(6,12) istep,name4,k,alpha,alph1
482 12 format(I6,1x,a4,' alpha b4 sqrt:',i4,1p2e12.4)
483 elseif (ratio.le.eps) then
484 ierr=2
485 if (nio.eq.0) write(6,12) istep,name4,k,alpha,alph1
486 else
487 ierr=0
488 alpha = 1.0/sqrt(alpha)
489 call cmult(approx(1,k),alpha,ntot)
490 endif
491c
492 if (ierr.ne.0) then
493 call axhelm (approx(1,0),approx(1,k),h1,h2,1,1)
494 call col2 (approx(1,0),vmk,ntot)
495c
496c Compute part of the norm (Note: a(0) already scaled by vml)
497c
498 alpha = glsc2(approx(1,0),approx(1,k),ntot)
499 if (nio.eq.0) write(6,12) istep,name4,k,alpha,alph1
500 if (alpha.le.0) then
501 ierr=3
502 if (nio.eq.0) write(6,12) istep,name4,k,alpha,alph1
503 return
504 endif
505 alpha = 1.0/sqrt(alpha)
506 call cmult(approx(1,k),alpha,ntot)
507 ierr = 0
508 endif
509c
510 return
511 end
512c-----------------------------------------------------------------------
513 subroutine hmhzpf(name,u,r,h1,h2,mask,mult,imesh,tli,maxit,isd,bi)
514 include 'SIZE'
515 include 'INPUT'
516 include 'MASS'
517 include 'FDMH1'
518 include 'CTIMER'
519c
520 CHARACTER*4 NAME
521 REAL U (LX1,LY1,LZ1,1)
522 REAL R (LX1,LY1,LZ1,1)
523 REAL H1 (LX1,LY1,LZ1,1)
524 REAL H2 (LX1,LY1,LZ1,1)
525 REAL MASK (LX1,LY1,LZ1,1)
526 REAL MULT (LX1,LY1,LZ1,1)
527 REAL bi (LX1,LY1,LZ1,1)
528 COMMON /CTMP0/ W1 (LX1,LY1,LZ1,LELT)
529 $ , W2 (LX1,LY1,LZ1,LELT)
530c
531 etime1=dnekclock()
532c
533 IF (IMESH.EQ.1) NTOT = lx1*ly1*lz1*NELV
534 IF (IMESH.EQ.2) NTOT = lx1*ly1*lz1*NELT
535c
536 tol = tli
537 if (param(22).ne.0) tol = abs(param(22))
538 CALL CHKTCG1 (TOL,R,H1,H2,MASK,MULT,IMESH,ISD)
539c
540c
541c Set flags for overlapping Schwarz preconditioner (pff 11/12/98)
542c
543 kfldfdm = -1
544c if (name.eq.'TEMP') kfldfdm = 0
545c if (name.eq.'VELX') kfldfdm = 1
546c if (name.eq.'VELY') kfldfdm = 2
547c if (name.eq.'VELZ') kfldfdm = 3
548 if (name.eq.'PRES') kfldfdm = ldim+1
549
550 if (ifdg) then
551 call cggo_dg (u,r,h1,h2,bi,mask,name,tol,maxit)
552 else
553 call cggo
554 $ (u,r,h1,h2,mask,mult,imesh,tol,maxit,isd,bi,name)
555 endif
556 thmhz=thmhz+(dnekclock()-etime1)
557c
558c
559 return
560 end
561c-----------------------------------------------------------------------
562 subroutine hsolve(name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd
563 $ ,approx,napprox,bi)
564c
565c Either std. Helmholtz solve, or a projection + Helmholtz solve
566c
567 include 'SIZE'
568 include 'TOTAL'
569 include 'CTIMER'
570c
571 CHARACTER*4 NAME
572 REAL U (LX1,LY1,LZ1,1)
573 REAL R (LX1,LY1,LZ1,1)
574 REAL H1 (LX1,LY1,LZ1,1)
575 REAL H2 (LX1,LY1,LZ1,1)
576 REAL vmk (LX1,LY1,LZ1,1)
577 REAL vml (LX1,LY1,LZ1,1)
578 REAL bi (LX1,LY1,LZ1,1)
579 REAL approx (1)
580 integer napprox(1)
581 common /ctmp2/ w1 (lx1,ly1,lz1,lelt)
582 common /ctmp3/ w2 (2+2*mxprev)
583
584 logical ifstdh
585 character*4 cname
586 character*6 name6
587
588 logical ifwt,ifvec
589
590 call chcopy(cname,name,4)
591 call capit (cname,4)
592
593 ifstdh = .true. ! default is no projection
594 if (ifprojfld(ifield)) then
595 ifstdh = .false.
596 endif
597
598 p945 = param(94)
599 if (cname.eq.'PRES') then
600 ifstdh = .false.
601 p945 = param(95)
602 endif
603
604 if (ifield.gt.ldimt_proj+1) ifstdh = .true.
605 if (param(93).eq.0) ifstdh = .true.
606 if (p945.eq.0) ifstdh = .true.
607 if (istep.lt.p945) ifstdh = .true.
608
609 if (ifstdh) then
610 call hmholtz(name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd)
611 else
612
613 n = lx1*ly1*lz1*nelfld(ifield)
614
615 call col2 (r,vmk,n)
616 call dssum (r,lx1,ly1,lz1)
617
618 call blank (name6,6)
619 call chcopy(name6,name,4)
620 ifwt = .true.
621 ifvec = .false.
622
623 call project1
624 $ (r,n,approx,napprox,h1,h2,vmk,vml,ifwt,ifvec,name6)
625
626 call hmhzpf (name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd,bi)
627
628 call project2
629 $ (u,n,approx,napprox,h1,h2,vmk,vml,ifwt,ifvec,name6)
630
631 endif
632
633 return
634 end
635c-----------------------------------------------------------------------
636 subroutine project1(b,n,rvar,ivar,h1,h2,msk,w,ifwt,ifvec,name6)
637
638c 1. Compute the projection of x onto X
639
640c 2. Re-orthogonalize the X basis set and corresponding B=A*X
641c vectors if A has changed.
642
643c Output: b = b - projection of b onto B
644
645c Input: n = length of field (or multifields, when ifvec=true)
646c rvar = real array of field values, including old h1,h2, etc.
647c ivar = integer array of pointers, etc.
648c h1 = current h1, for Axhelm(.,.,h1,h2,...)
649c h2 = current h2
650c msk = mask for Dirichlet BCs
651c w = weight for inner products (typ. w=vmult, tmult, etc.)
652c ifwt = use weighted inner products when ifwt=.true.
653c ifvec = are x and b vectors, or scalar fields?
654c name6 = discriminator for action of A*x
655
656c The idea here is to have one pair of projection routines for
657c constructing the new rhs (project1) and reconstructing the new
658c solution (x = xbar + dx) plus updating the approximation space.
659c The latter functions are done in project2.
660c
661c The approximation space X and corresponding right-hand sides,
662c B := A*X are stored in rvar, as well as h1old and h2old and a
663c couple of other auxiliary arrays.
664
665c In this new code, we retain both X and B=A*X and we re-orthogonalize
666c at each timestep (with no extra matrix-vector products, but O(nm)
667c work. The idea is to retain fresh vectors by injecting the most
668c recent solution and pushing the oldest off the stack, hopefully
669c keeping the number of vectors, m, small.
670
671
672 include 'SIZE' ! For nid/nio
673 include 'TSTEP' ! For istep
674 include 'CTIMER'
675
676 real b(n),rvar(n,1),h1(n),h2(n),w(n),msk(n)
677 integer ivar(1)
678 character*6 name6
679 logical ifwt,ifvec
680
681 etime0 = dnekclock()
682
683 nn = n
684 if (ifvec) nn = n*ldim
685
686 call proj_get_ivar
687 $ (m,mmx,ixb,ibb,ix,ib,ih1,ih2,ivar,n,ifvec,name6)
688
689 if (m.le.0) return
690
691 ireset=iproj_chk(rvar(ih1,1),rvar(ih2,1),h1,h2,n) ! Updated matrix?
692
693 bb4 = glsc3(b,w,b,n)
694 bb4 = sqrt(bb4)
695
696
697c Re-orthogonalize basis set w.r.t. new vectors if space has changed.
698
699 if (ireset.eq.1) then
700
701 do j=0,m-1 ! First, set B := A*X
702 jb = ib+j*nn !Iterate through xs and bs
703 jx = ix+j*nn
704 call proj_matvec (rvar(jb,1),rvar(jx,1),n,h1,h2,msk,name6)
705 enddo
706
707 if (nio.eq.0 .and. loglevel.gt.2)
708 $ write(6,'(13x,A)') 'Reorthogonalize Basis'
709
710 call proj_ortho_full
711 $ (rvar(ix,1),rvar(ib,1),n,m,w,ifwt,ifvec,name6)
712
713 ivar(2) = m ! Update number of saved vectors
714
715 endif
716
717c ixb is pointer to xbar, ibb is pointer to bbar := A*xbar
718
719 call project1_a(rvar(ixb,1),rvar(ibb,1),b,rvar(ix,1),rvar(ib,1)
720 $ ,n,m,w,ifwt,ifvec)
721
722 baf = glsc3(b,w,b,n)
723 baf = sqrt(baf)
724 ratio = bb4/baf
725
726 tproj = tproj + dnekclock() - etime0
727
728 if (nio.eq.0) write(6,1) istep,' Project ' // name6,
729 & baf,bb4,ratio,m,mmx
730 1 format(i11,a,6x,1p3e13.4,i4,i4)
731
732 return
733 end
734c-----------------------------------------------------------------------
735 subroutine project1_a(xbar,bbar,b,xx,bb,n,m,w,ifwt,ifvec)
736
737c xbar is best fit in xx, bbar = A*xbar
738c b <-- b - bbar
739
740 include 'SIZE'
741 include 'TSTEP'
742 include 'INPUT'
743 include 'PARALLEL'
744 parameter(lt=lx1*ly1*lz1*lelv)
745 real xbar(n),bbar(n),b(n),xx(n,m),bb(n,m),w(n)
746 logical ifwt,ifvec
747 integer e,eg
748 parameter(lxyz=lx1*ly1*lz1)
749 real tt(lxyz,lelt)
750
751 real work(mxprev),alpha(mxprev)
752
753 if (m.le.0) return
754
755 !First round of CGS
756 do k = 1, m
757 if(ifwt) then
758 alpha(k) = vlsc3(xx(1,k),w,b,n)
759 else
760 alpha(k) = vlsc2(xx(1,k),b,n)
761 endif
762 enddo
763 !First one outside loop to avoid zeroing xbar and bbar
764 call gop(alpha,work,'+ ',m)
765 call cmult2(xbar,xx(1,1),alpha(1),n)
766 call cmult2(bbar,bb(1,1),alpha(1),n)
767 call add2s2(b,bb(1,1),-alpha(1),n)
768 do k = 2,m
769 call add2s2(xbar,xx(1,k),alpha(k),n)
770 call add2s2(bbar,bb(1,k),alpha(k),n)
771 call add2s2(b,bb(1,k),-alpha(k),n)
772 enddo
773 !Second round of CGS
774 do k = 1, m
775 if(ifwt) then
776 alpha(k) = vlsc3(xx(1,k),w,b,n)
777 else
778 alpha(k) = vlsc2(xx(1,k),b,n)
779 endif
780 enddo
781 call gop(alpha,work,'+ ',m)
782 do k = 1,m
783 call add2s2(xbar,xx(1,k),alpha(k),n)
784 call add2s2(bbar,bb(1,k),alpha(k),n)
785 call add2s2(b,bb(1,k),-alpha(k),n)
786 enddo
787
788 return
789 end
790c-----------------------------------------------------------------------
791 function iproj_chk(h1old,h2old,h1,h2,n)
792 include 'SIZE'
793 include 'TOTAL'
794
795c Matrix has changed if h1/h2 differ from old values
796
797 real h1(n),h2(n),h1old(n),h2old(n)
798
799 iproj_chk = 0
800
801 if (ifmvbd) then
802 iproj_chk = 1
803 return
804 endif
805
806 dh1 = 0.
807 dh2 = 0.
808 do i=1,n
809 dh1 = max(dh1,abs(h1(i)-h1old(i)))
810 dh2 = max(dh2,abs(h2(i)-h2old(i)))
811 enddo
812 dh = max(dh1,dh2)
813 dh = glmax(dh,1) ! Max across all processors
814
815 if (dh.gt.0) then
816
817 call copy(h1old,h1,n) ! Save old h1 / h2 values
818 call copy(h2old,h2,n)
819
820 iproj_chk = 1 ! Force re-orthogonalization of basis
821
822 endif
823
824 return
825 end
826c-----------------------------------------------------------------------
827 subroutine proj_matvec(b,x,n,h1,h2,msk,name6)
828 include 'SIZE'
829 include 'TOTAL'
830 real b(n),x(n),h1(n),h2(n),msk(n)
831 character*6 name6
832
833c This is the default matvec for nekcem.
834
835c The code can later be updated to support different matvec
836c implementations, which would be discriminated by the character
837c string "name6"
838
839 isd = 1 ! This probably won't work for axisymmetric
840 imsh = 1
841 if (iftmsh(ifield)) imsh=2
842
843 call axhelm (b,x,h1,h2,imsh,isd) ! b = A x
844 call dssum (b,lx1,ly1,lz1)
845 call col2 (b,msk,n)
846
847 return
848 end
849c-----------------------------------------------------------------------
850 !O(nm) method for updating projection space
851 !See James Lotte's note or Nicholas Christensen's master's thesis
852 subroutine proj_ortho(xx,bb,n,m,w,ifwt,ifvec,name6)
853
854 include 'SIZE' ! nio
855 include 'TSTEP' ! istep
856 include 'PARALLEL' ! wdsize
857
858 real xx(n,1), bb(n,1), w(n)
859 character*6 name6
860 logical ifwt, ifvec
861 real tol, nrm, scl1, scl2, c, s
862 real work(mxprev), alpha(mxprev), beta(mxprev)
863 integer h
864
865 if(m.le.0) return !No vectors to ortho-normalize
866
867 ! AX = B
868 ! Calculate dx, db: dx = x-XX^Tb, db=b-BX^Tb
869
870 do k = 1, m !First round CGS
871 if(ifwt) then
872 alpha(k) = 0.5*(vlsc3(xx(1,k),w,bb(1,m),n)
873 $ + vlsc3(bb(1,k),w,xx(1,m),n))
874 else
875 alpha(k) = 0.5*(vlsc2(xx(1,k),bb(1,m),n)
876 $ + vlsc2(bb(1,k),xx(1,m),n))
877 endif
878 enddo
879 call gop(alpha,work,'+ ',m)
880 nrm = sqrt(alpha(m)) !Calculate A-norm of new vector
881 do k = 1,m-1
882 call add2s2(xx(1,m),xx(1,k),-alpha(k),n)
883 call add2s2(bb(1,m),bb(1,k),-alpha(k),n)
884 enddo
885
886 do k = 1, m-1 !Second round CGS
887 if(ifwt) then
888 beta(k) = 0.5*(vlsc3(xx(1,k),w,bb(1,m),n)
889 $ + vlsc3(bb(1,k),w,xx(1,m),n))
890 else
891 beta(k) = 0.5*(vlsc2(xx(1,k),bb(1,m),n)
892 $ + vlsc2(bb(1,k),xx(1,m),n))
893 endif
894 enddo
895 call gop(beta,work,'+ ',m-1)
896 do k = 1,m-1
897 call add2s2(xx(1,m),xx(1,k),-beta(k),n)
898 call add2s2(bb(1,m),bb(1,k),-beta(k),n)
899 !While we're at it,
900 !Sum weights from each round to get the total alpha
901 alpha(k) = alpha(k) + beta(k)
902 enddo
903
904 !Calculate A-norm of newest solution
905 if(ifwt) then
906 alpha(m) = glsc3(xx(1,m), w, bb(1,m), n)
907 else
908 alpha(m) = glsc2(xx(1,m), bb(1,m), n)
909 endif
910 alpha(m) = sqrt(alpha(m))
911 !dx and db now stored in last column of xx and bb
912
913c Set tolerance for linear independence
914 tol = 1.e-7
915 if (wdsize.eq.4) tol=1.e-3
916
917c Check for linear independence.
918 if(alpha(m).gt.tol*nrm) then !New vector is linearly independent
919
920 !Normalize dx and db
921 scl1 = 1.0/alpha(m)
922 call cmult(xx(1,m), scl1, n)
923 call cmult(bb(1,m), scl1, n)
924
925 !We want to throw away the oldest information
926 !The below propagates newest information to first vector.
927 !This will make the first vector a scalar
928 !multiple of x.
929 do k = m, 2, -1
930 h = k - 1
931 call givens_rotation(alpha(h),alpha(k),c,s,nrm)
932 alpha(h) = nrm
933 do i = 1, n !Apply rotation to xx and bb
934 scl1 = c*xx(i,h) + s*xx(i,k)
935 xx(i,k) = -s*xx(i,h) + c*xx(i,k)
936 xx(i,h) = scl1
937 scl2 = c*bb(i,h) + s*bb(i,k)
938 bb(i,k) = -s*bb(i,h) + c*bb(i,k)
939 bb(i,h) = scl2
940 enddo
941 enddo
942
943 else !New vector is not linearly independent, forget about it
944 k = m !location of rank deficient column
945
946 if (nio.eq.0 .and. loglevel.gt.2)
947 $ write(6,1) istep,k,m,name6,alpha(m),tol
948
949 1 format(i9,'proj_ortho: ',2i4,1x,a6,
950 $ ' Detect rank deficiency:',1p2e12.4)
951
952 m = m - 1 !Remove column
953 endif
954
955 return
956 end
957c-----------------------------------------------------------------------
958 !Function to switch between mgs and cgs2 full reorthogonalization
959 subroutine proj_ortho_full(xx,bb,n,m,w,ifwt,ifvec,name6)
960
961 include 'SIZE'
962
963 real xx(n,1),bb(n,1),w(n)
964 character*6 name6
965 logical ifwt,ifvec
966 integer flag(mxprev)
967
968 !call proj_ortho_full_mgs(xx,bb,n,m,w,ifwt,ifvec,name6)
969 call proj_ortho_full_cgs2(xx,bb,n,m,w,ifwt,ifvec,name6)
970
971 return
972 end
973c-----------------------------------------------------------------------
974c Full MGS reorthogonalization
975 subroutine proj_ortho_full_mgs(xx,bb,n,m,w,ifwt,ifvec,name6)
976
977 include 'SIZE' ! nio
978 include 'TSTEP' ! istep
979 include 'PARALLEL' ! wdsize
980
981 real xx(n,1),bb(n,1),w(n)
982 character*6 name6
983 logical ifwt,ifvec
984 integer flag(mxprev)
985 real normk,normp,alpha
986
987 if (m.le.0) return
988
989 if ( ifwt) alpha = glsc3(xx(1,m),w,bb(1,m),n)
990 if (.not. ifwt) alpha = glsc2(xx(1,m),bb(1,m),n)
991 if (alpha.eq.0) return
992
993 scale = 1./sqrt(alpha)
994 call cmult(xx(1,m),scale,n)
995 call cmult(bb(1,m),scale,n)
996 flag(m) = 1
997
998 do k=m-1,1,-1 ! Reorthogonalize, starting with latest solution
999
1000 if ( ifwt) normk = glsc3(xx(1,k),w,bb(1,k),n)
1001 if (.not. ifwt) normk = glsc2(xx(1,k),bb(1,k),n)
1002 normk=sqrt(normk)
1003
1004 do j=m,k+1,-1 ! Modified GS
1005 if(flag(j).eq.1) then
1006 alpha = 0.
1007 if (ifwt) then
1008 alpha = alpha + .5*(vlsc3(xx(1,j),w,bb(1,k),n)
1009 $ + vlsc3(bb(1,j),w,xx(1,k),n))
1010 else
1011 alpha = alpha + .5*(vlsc2(xx(1,j),bb(1,k),n)
1012 $ + vlsc2(bb(1,j),xx(1,k),n))
1013 endif
1014 scale = -glsum(alpha,1)
1015 call add2s2(xx(1,k),xx(1,j),scale,n)
1016 call add2s2(bb(1,k),bb(1,j),scale,n)
1017 endif
1018 enddo
1019 if ( ifwt) normp = glsc3(xx(1,k),w,bb(1,k),n)
1020 if (.not. ifwt) normp = glsc2(xx(1,k),bb(1,k),n)
1021 if (normp.gt.0.0) normp=sqrt(normp)
1022
1023 tol = 1.e-7
1024 if (wdsize.eq.4) tol=1.e-3
1025
1026 if (normp.gt.tol*normk) then ! linearly independent vectors
1027 scale = 1./normp
1028 call cmult(xx(1,k),scale,n)
1029 call cmult(bb(1,k),scale,n)
1030 flag(k) = 1
1031c if (nio.eq.0) write(6,2) istep,k,m,name6,normp,normk
1032c 2 format(i9,'proj_ortho: ',2i4,1x,a6,' project ok.'
1033c $ ,1p2e12.4)
1034 else
1035 flag(k) = 0
1036c if (nio.eq.0) write(6,1) istep,k,m,name6,normp,normk
1037c 1 format(i9,'proj_ortho: ',2i4,1x,a6,' Detect rank deficiency:'
1038c $ ,1p2e12.4)
1039 endif
1040
1041 enddo
1042
1043 k=0
1044 do j=1,m
1045 if (flag(j).eq.1) then
1046 k=k+1
1047 if (k.lt.j) then
1048 call copy(xx(1,k),xx(1,j),n)
1049 call copy(bb(1,k),bb(1,j),n)
1050 endif
1051 endif
1052 enddo
1053 m = k
1054
1055 return
1056 end
1057c-----------------------------------------------------------------------
1058 !CGS2 version of full reorthogonalization, possibly more stable in
1059 !certain instances. Much faster for large m.
1060 subroutine proj_ortho_full_cgs2(xx,bb,n,m,w,ifwt,ifvec,name6)
1061
1062 include 'SIZE' ! nio
1063 include 'TSTEP' ! istep
1064 include 'PARALLEL' ! wdsize
1065
1066 real xx(n,1),bb(n,1),w(n)
1067 character*6 name6
1068 logical ifwt,ifvec
1069 integer flag(mxprev)
1070 real normk,normp,alpha(mxprev),work(mxprev),scl1,tol
1071
1072 if (m.le.0) return
1073
1074 tol = 1.e-7
1075 if (wdsize.eq.4) tol=1.e-3
1076
1077 do i = 1, 2 !Do this twice for CGS2
1078
1079 do k = m, 1, -1
1080 do j = m, k, -1
1081 alpha(j) = 0.0
1082 if(ifwt) then
1083 alpha(j) = .5*(vlsc3(xx(1,j),w,bb(1,k),n)
1084 $ + vlsc3(bb(1,j),w,xx(1,k),n))
1085 else
1086 alpha(j) = .5*(vlsc2(xx(1,j),bb(1,k),n)
1087 $ + vlsc2(bb(1,j),xx(1,k),n))
1088 endif
1089 enddo
1090 call gop(alpha(k), work,'+ ',(m - k) + 1)
1091 do j = m, k+1, -1
1092 call add2s2(xx(1,k),xx(1,j),-alpha(j),n)
1093 call add2s2(bb(1,k),bb(1,j),-alpha(j),n)
1094 enddo
1095 normp = sqrt(alpha(k))
1096 if(ifwt) then
1097 normk = glsc3(xx(1,k),w,bb(1,k),n)
1098 else
1099 normk = glsc2(xx(1,k),bb(1,k),n)
1100 endif
1101 normk = sqrt(normk)
1102 if(normk.gt.tol*normp) then
1103 scl1 = 1.0/normk
1104 call cmult(xx(1,k), scl1, n)
1105 call cmult(bb(1,k), scl1, n)
1106 flag(k) = 1
1107 else
1108 flag(k) = 0
1109 endif
1110 enddo
1111
1112 enddo
1113
1114 k=0
1115 do j=1,m
1116 if (flag(j).eq.1) then
1117 k=k+1
1118 if (k.lt.j) then
1119 call copy(xx(1,k),xx(1,j),n)
1120 call copy(bb(1,k),bb(1,j),n)
1121 endif
1122 endif
1123 enddo
1124 m = k
1125
1126 return
1127 end
1128c-----------------------------------------------------------------------
1129 subroutine project2(x,n,rvar,ivar,h1,h2,msk,w,ifwt,ifvec,name6)
1130
1131 include 'CTIMER'
1132
1133 real x(n),b(n),rvar(n,1),h1(n),h2(n),w(n),msk(n)
1134 integer ivar(1)
1135 character*6 name6
1136 logical ifwt,ifvec
1137
1138 etime0 = dnekclock()
1139
1140 call proj_get_ivar(m,mmx,ixb,ibb,ix,ib,ih1,ih2,
1141 $ ivar,n,ifvec,name6)
1142
1143c ix is pointer to X, ib is pointer to B
1144c ixb is pointer to xbar, ibb is pointer to bbar := A*xbar
1145
1146 call project2_a(x,rvar(ixb,1),rvar(ix,1),rvar(ib,1)
1147 $ ,n,m,mmx,h1,h2,msk,w,ifwt,ifvec,name6)
1148
1149 ivar(2) = m ! Update number of saved vectors
1150
1151 tproj = tproj + dnekclock() - etime0
1152
1153 return
1154 end
1155c-----------------------------------------------------------------------
1156 subroutine project2_a(x,xbar,xx,bb,n,m,mmx,h1,h2,msk,w,ifwt,ifvec,
1157 $ name6)
1158
1159 include 'SIZE'
1160
1161 real x(n),xbar(n),xx(n,1),bb(n,1),h1(n),h2(n),w(n),msk(n)
1162 character*6 name6
1163 logical ifwt,ifvec
1164
1165 nn = n
1166 if (ifvec) nn=ldim*n
1167
1168 if (m.gt.0) call add2(x,xbar,n) ! Restore desired solution
1169
1170 !Uncomment this if using full reorthogonalization
1171c if (m.eq.mmx) then ! Push old vector off the stack
1172c do k=2,mmx
1173c call copy (xx(1,k-1),xx(1,k),nn)
1174c call copy (bb(1,k-1),bb(1,k),nn)
1175c enddo
1176c endif
1177
1178 m = min(m+1,mmx)
1179 !print *, "m", m
1180 call copy (xx(1,m),x,nn) ! Update (X,B)
1181 call proj_matvec (bb(1,m),xx(1,m),n,h1,h2,msk,name6)
1182 call proj_ortho (xx,bb,n,m,w,ifwt,ifvec,name6) !Update orthogonalization
1183 !Uncomment the if block above if using full reorthogonalization
1184c call proj_ortho_full (xx,bb,n,m,w,ifwt,ifvec,name6) !Fully reorthogonalize
1185
1186 return
1187 end
1188c-----------------------------------------------------------------------
1189 subroutine proj_get_ivar
1190 $ (m,mmx,ixb,ibb,ix,ib,ih1,ih2,ivar,n,ifvec,name6)
1191
1192 include 'SIZE'
1193 include 'TSTEP'
1194
1195 logical ifvec
1196 character*6 name6
1197
1198 integer ivar(10)
1199
1200 integer icalld
1201 save icalld
1202 data icalld/0/
1203
1204 m = ivar(2)
1205 mmx = (mxprev-4)/2 ! ivar=0 --> mxprev array
1206 ivar(1) = mmx
1207
1208 nn = n
1209 if (ifvec) nn = n*ldim ! Number of entries in a vector
1210
1211
1212 ih1 = 1
1213 ih2 = ih1 + n
1214 ixb = ih2 + n ! pointer to xbar
1215 ibb = ixb + nn ! " to bbar
1216 ix = ibb + nn ! " to X
1217 ib = ix + nn*mmx ! " to B
1218
1219 return
1220 end
1221c-----------------------------------------------------------------------
1222 subroutine laplacep(name,u,mask,mult,ifld,tol,maxi,approx,napprox)
1223c
1224c Solve Laplace's equation, with projection onto previous solutions.
1225c
1226c Boundary condition strategy:
1227c
1228c u = u0 + ub
1229c
1230c u0 = 0 on Dirichlet boundaries
1231c ub = u on Dirichlet boundaries
1232c
1233c _
1234c A ( u0 + ub ) = 0
1235c
1236c _ _
1237c A u0 = - A ub
1238c
1239c _ _
1240c MAM u0 = -M A ub, M is the mask
1241c
1242c _
1243c A u0 = -M A ub , Helmholtz solve with SPD matrix A
1244c
1245c u = u0+ub
1246c
1247 include 'SIZE'
1248 include 'TOTAL'
1249 include 'CTIMER'
1250c
1251 character*4 name
1252 real u(1),mask(1),mult(1),approx (1)
1253 integer napprox(1)
1254
1255 parameter (lt=lx1*ly1*lz1*lelt)
1256 common /scrvh/ h1(lt),h2(lt)
1257 common /scruz/ r (lt),ub(lt)
1258
1259 logical ifstdh
1260 character*4 cname
1261 character*6 name6
1262
1263 logical ifwt,ifvec
1264
1265 call chcopy(cname,name,4)
1266 call capit (cname,4)
1267
1268 call blank (name6,6)
1269 call chcopy(name6,name,4)
1270 ifwt = .true.
1271 ifvec = .false.
1272 isd = 1
1273 imsh = 1
1274 nel = nelfld(ifld)
1275
1276 n = lx1*ly1*lz1*nel
1277
1278 call copy (ub,u,n) ! ub = u on boundary
1279 call dsavg(ub) ! Make certain ub is in H1
1280 call rone (h1,n)
1281 call rzero(h2,n)
1282 ! _
1283 call axhelm (r,ub,h1,h2,1,1) ! r = A*ub
1284
1285 do i=1,n ! _
1286 r(i)=-r(i)*mask(i) ! r = -M*A*ub
1287 enddo
1288
1289 call dssum (r,lx1,ly1,lz1) ! dssum rhs
1290
1291 call project1
1292 $ (r,n,approx,napprox,h1,h2,mask,mult,ifwt,ifvec,name6)
1293
1294 if (nel.eq.nelv) then
1295 call hmhzpf (name,u,r,h1,h2,mask,mult,imsh,tol,maxi,isd,binvm1)
1296 else
1297 call hmhzpf (name,u,r,h1,h2,mask,mult,imsh,tol,maxi,isd,bintm1)
1298 endif
1299
1300 call project2
1301 $ (u,n,approx,napprox,h1,h2,mask,mult,ifwt,ifvec,name6)
1302
1303 call add2(u,ub,n)
1304
1305 return
1306 end
1307c-----------------------------------------------------------------------
1308 subroutine givens_rotation(a, b, c, s, r)
1309
1310 real a, b, c, s, r, h, d
1311
1312 if(b.ne.0.0) then
1313 h = hypot(a,b) !Can use library version or below implementation
1314 d = 1.0/h
1315 c = abs(a)*d
1316 s = sign(d,a)*b
1317 r = sign(1.0,a)*h
1318 else
1319 c = 1.0
1320 s = 0.0
1321 r = a
1322 endif
1323
1324 return
1325 end
1326c-----------------------------------------------------------------------
1327 ! Compilers with Fortran 2008 support should have a
1328 ! library implementation of this (gfortran and ifort do).
1329
1330 real function hypot(a, b) !Does not handle a = b = 0 case
1331
1332 real a, b, t, x, c, d, ix
1333
1334 c = abs(a)
1335 d = abs(b)
1336 x = max(c,d)
1337 ix = 1.0/x
1338 t = min(c,d)
1339 t = ix*t
1340
1341 hypot = x*sqrt(1.0+t*t)
1342
1343 return
1344 end
1345c-----------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.