-
Notifications
You must be signed in to change notification settings - Fork 2
/
lsdp3.for
1200 lines (1200 loc) · 38.8 KB
/
lsdp3.for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
c
subroutine cfode (meth, elco, tesco)
integer meth
integer i, ib, nq, nqm1, nqp1
double precision elco, tesco
double precision agamq, fnq, fnqm1, pc, pint, ragq,
1 rqfac, rq1fac, tsign, xpin
dimension elco(13,12), tesco(3,12)
c-----------------------------------------------------------------------
c cfode is called by the integrator routine to set coefficients
c needed there. the coefficients for the current method, as
c given by the value of meth, are set for all orders and saved.
c the maximum order assumed here is 12 if meth = 1 and 5 if meth = 2.
c (a smaller value of the maximum order is also allowed.)
c cfode is called once at the beginning of the problem,
c and is not called again unless and until meth is changed.
c
c the elco array contains the basic method coefficients.
c the coefficients el(i), 1 .le. i .le. nq+1, for the method of
c order nq are stored in elco(i,nq). they are given by a genetrating
c polynomial, i.e.,
c l(x) = el(1) + el(2)*x + ... + el(nq+1)*x**nq.
c for the implicit adams methods, l(x) is given by
c dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1), l(-1) = 0.
c for the bdf methods, l(x) is given by
c l(x) = (x+1)*(x+2)* ... *(x+nq)/k,
c where k = factorial(nq)*(1 + 1/2 + ... + 1/nq).
c
c the tesco array contains test constants used for the
c local error test and the selection of step size and/or order.
c at order nq, tesco(k,nq) is used for the selection of step
c size at order nq - 1 if k = 1, at order nq if k = 2, and at order
c nq + 1 if k = 3.
c-----------------------------------------------------------------------
dimension pc(12)
c
go to (100, 200), meth
c
100 elco(1,1) = 1.0d0
elco(2,1) = 1.0d0
tesco(1,1) = 0.0d0
tesco(2,1) = 2.0d0
tesco(1,2) = 1.0d0
tesco(3,12) = 0.0d0
pc(1) = 1.0d0
rqfac = 1.0d0
do 140 nq = 2,12
c-----------------------------------------------------------------------
c the pc array will contain the coefficients of the polynomial
c p(x) = (x+1)*(x+2)*...*(x+nq-1).
c initially, p(x) = 1.
c-----------------------------------------------------------------------
rq1fac = rqfac
rqfac = rqfac/dble(nq)
nqm1 = nq - 1
fnqm1 = dble(nqm1)
nqp1 = nq + 1
c form coefficients of p(x)*(x+nq-1). ----------------------------------
pc(nq) = 0.0d0
do 110 ib = 1,nqm1
i = nqp1 - ib
110 pc(i) = pc(i-1) + fnqm1*pc(i)
pc(1) = fnqm1*pc(1)
c compute integral, -1 to 0, of p(x) and x*p(x). -----------------------
pint = pc(1)
xpin = pc(1)/2.0d0
tsign = 1.0d0
do 120 i = 2,nq
tsign = -tsign
pint = pint + tsign*pc(i)/dble(i)
120 xpin = xpin + tsign*pc(i)/dble(i+1)
c store coefficients in elco and tesco. --------------------------------
elco(1,nq) = pint*rq1fac
elco(2,nq) = 1.0d0
do 130 i = 2,nq
130 elco(i+1,nq) = rq1fac*pc(i)/dble(i)
agamq = rqfac*xpin
ragq = 1.0d0/agamq
tesco(2,nq) = ragq
if (nq .lt. 12) tesco(1,nqp1) = ragq*rqfac/dble(nqp1)
tesco(3,nqm1) = ragq
140 continue
return
c
200 pc(1) = 1.0d0
rq1fac = 1.0d0
do 230 nq = 1,5
c-----------------------------------------------------------------------
c the pc array will contain the coefficients of the polynomial
c p(x) = (x+1)*(x+2)*...*(x+nq).
c initially, p(x) = 1.
c-----------------------------------------------------------------------
fnq = dble(nq)
nqp1 = nq + 1
c form coefficients of p(x)*(x+nq). ------------------------------------
pc(nqp1) = 0.0d0
do 210 ib = 1,nq
i = nq + 2 - ib
210 pc(i) = pc(i-1) + fnq*pc(i)
pc(1) = fnq*pc(1)
c store coefficients in elco and tesco. --------------------------------
do 220 i = 1,nqp1
220 elco(i,nq) = pc(i)/pc(2)
elco(2,nq) = 1.0d0
tesco(1,nq) = rq1fac
tesco(2,nq) = dble(nqp1)/elco(1,nq)
tesco(3,nq) = dble(nq+2)/elco(1,nq)
rq1fac = rq1fac/fnq
230 continue
return
c----------------------- end of subroutine cfode -----------------------
end
subroutine prepj (neq, y, yh, nyh, ewt, ftem, savf, wm, iwm,
1 f, jac)
external f, jac
c the following line is for use with microsoft compilers. --------------
external vnorm
integer neq, nyh, iwm
integer icf, ierpj, iersl, jcur, jstart, kflag, l, meth, miter,
2 maxord, maxcor, msbp, mxncf, n, nq, nst, nfe, nje, nqu
integer i, i1, i2, ier, ii, j, j1, jj, lenp,
1 mba, mband, meb1, meband, ml, ml3, mu
double precision y, yh, ewt, ftem, savf, wm
double precision ccmax, el0, h, hmin, hmxi, hu, rc, tn, uround
double precision con, di, fac, hl0, r, r0, srur, yi, yj, yjj,
1 vnorm
dimension neq(1), y(1), yh(nyh,1), ewt(1), ftem(1), savf(1),
1 wm(1), iwm(1)
common /ls0001/ ccmax, el0, h, hmin, hmxi, hu, rc, tn, uround,
4 icf, ierpj, iersl, jcur, jstart, kflag, l, meth, miter,
5 maxord, maxcor, msbp, mxncf, n, nq, nst, nfe, nje, nqu
c-----------------------------------------------------------------------
c prepj is called by stode to compute and process the matrix
c p = i - h*el(1)*j , where j is an approximation to the jacobian.
c here j is computed by the user-supplied routine jac if
c miter = 1 or 4, or by finite differencing if miter = 2, 3, or 5.
c if miter = 3, a diagonal approximation to j is used.
c j is stored in wm and replaced by p. if miter .ne. 3, p is then
c subjected to lu decomposition in preparation for later solution
c of linear systems with p as coefficient matrix. this is done
c by dgefa if miter = 1 or 2, and by dgbfa if miter = 4 or 5.
c
c in addition to variables described previously, communication
c with prepj uses the following..
c y = array containing predicted values on entry.
c ftem = work array of length n (acor in stode).
c savf = array containing f evaluated at predicted y.
c wm = real work space for matrices. on output it contains the
c inverse diagonal matrix if miter = 3 and the lu decomposition
c of p if miter is 1, 2 , 4, or 5.
c storage of matrix elements starts at wm(3).
c wm also contains the following matrix-related data..
c wm(1) = sqrt(uround), used in numerical jacobian increments.
c wm(2) = h*el0, saved for later use if miter = 3.
c iwm = integer work space containing pivot information, starting at
c iwm(21), if miter is 1, 2, 4, or 5. iwm also contains band
c parameters ml = iwm(1) and mu = iwm(2) if miter is 4 or 5.
c el0 = el(1) (input).
c ierpj = output error flag, = 0 if no trouble, .gt. 0 if
c p matrix found to be singular.
c jcur = output flag = 1 to indicate that the jacobian matrix
c (or approximation) is now current.
c this routine also uses the common variables el0, h, tn, uround,
c miter, n, nfe, and nje.
c-----------------------------------------------------------------------
nje = nje + 1
ierpj = 0
jcur = 1
hl0 = h*el0
go to (100, 200, 300, 400, 500), miter
c if miter = 1, call jac and multiply by scalar. -----------------------
100 lenp = n*n
do 110 i = 1,lenp
110 wm(i+2) = 0.0d0
call jac (neq, tn, y, 0, 0, wm(3), n)
con = -hl0
do 120 i = 1,lenp
120 wm(i+2) = wm(i+2)*con
go to 240
c if miter = 2, make n calls to f to approximate j. --------------------
200 fac = vnorm (n, savf, ewt)
r0 = 1000.0d0*dabs(h)*uround*dble(n)*fac
if (r0 .eq. 0.0d0) r0 = 1.0d0
srur = wm(1)
j1 = 2
do 230 j = 1,n
yj = y(j)
r = dmax1(srur*dabs(yj),r0/ewt(j))
y(j) = y(j) + r
fac = -hl0/r
call f (neq, tn, y, ftem)
do 220 i = 1,n
220 wm(i+j1) = (ftem(i) - savf(i))*fac
y(j) = yj
j1 = j1 + n
230 continue
nfe = nfe + n
c add identity matrix. -------------------------------------------------
240 j = 3
do 250 i = 1,n
wm(j) = wm(j) + 1.0d0
250 j = j + (n + 1)
c do lu decomposition on p. --------------------------------------------
call dgefa (wm(3), n, n, iwm(21), ier)
if (ier .ne. 0) ierpj = 1
return
c if miter = 3, construct a diagonal approximation to j and p. ---------
300 wm(2) = hl0
r = el0*0.1d0
do 310 i = 1,n
310 y(i) = y(i) + r*(h*savf(i) - yh(i,2))
call f (neq, tn, y, wm(3))
nfe = nfe + 1
do 320 i = 1,n
r0 = h*savf(i) - yh(i,2)
di = 0.1d0*r0 - h*(wm(i+2) - savf(i))
wm(i+2) = 1.0d0
if (dabs(r0) .lt. uround/ewt(i)) go to 320
if (dabs(di) .eq. 0.0d0) go to 330
wm(i+2) = 0.1d0*r0/di
320 continue
return
330 ierpj = 1
return
c if miter = 4, call jac and multiply by scalar. -----------------------
400 ml = iwm(1)
mu = iwm(2)
ml3 = ml + 3
mband = ml + mu + 1
meband = mband + ml
lenp = meband*n
do 410 i = 1,lenp
410 wm(i+2) = 0.0d0
call jac (neq, tn, y, ml, mu, wm(ml3), meband)
con = -hl0
do 420 i = 1,lenp
420 wm(i+2) = wm(i+2)*con
go to 570
c if miter = 5, make mband calls to f to approximate j. ----------------
500 ml = iwm(1)
mu = iwm(2)
mband = ml + mu + 1
mba = min0(mband,n)
meband = mband + ml
meb1 = meband - 1
srur = wm(1)
fac = vnorm (n, savf, ewt)
r0 = 1000.0d0*dabs(h)*uround*dble(n)*fac
if (r0 .eq. 0.0d0) r0 = 1.0d0
do 560 j = 1,mba
do 530 i = j,n,mband
yi = y(i)
r = dmax1(srur*dabs(yi),r0/ewt(i))
530 y(i) = y(i) + r
call f (neq, tn, y, ftem)
do 550 jj = j,n,mband
y(jj) = yh(jj,1)
yjj = y(jj)
r = dmax1(srur*dabs(yjj),r0/ewt(jj))
fac = -hl0/r
i1 = max0(jj-mu,1)
i2 = min0(jj+ml,n)
ii = jj*meb1 - ml + 2
do 540 i = i1,i2
540 wm(ii+i) = (ftem(i) - savf(i))*fac
550 continue
560 continue
nfe = nfe + mba
c add identity matrix. -------------------------------------------------
570 ii = mband + 2
do 580 i = 1,n
wm(ii) = wm(ii) + 1.0d0
580 ii = ii + meband
c do lu decomposition of p. --------------------------------------------
call dgbfa (wm(3), meband, n, ml, mu, iwm(21), ier)
if (ier .ne. 0) ierpj = 1
return
c----------------------- end of subroutine prepj -----------------------
end
subroutine solsy (wm, iwm, x, tem)
integer iwm
integer icf, ierpj, iersl, jcur, jstart, kflag, l, meth, miter,
2 maxord, maxcor, msbp, mxncf, n, nq, nst, nfe, nje, nqu
integer i, meband, ml, mu
double precision wm, x, tem
double precision ccmax, el0, h, hmin, hmxi, hu, rc, tn, uround
double precision di, hl0, phl0, r
dimension wm(1), iwm(1), x(1), tem(1)
common /ls0001/ ccmax, el0, h, hmin, hmxi, hu, rc, tn, uround,
4 icf, ierpj, iersl, jcur, jstart, kflag, l, meth, miter,
5 maxord, maxcor, msbp, mxncf, n, nq, nst, nfe, nje, nqu
c-----------------------------------------------------------------------
c this routine manages the solution of the linear system arising from
c a chord iteration. it is called if miter .ne. 0.
c if miter is 1 or 2, it calls dgesl to accomplish this.
c if miter = 3 it updates the coefficient h*el0 in the diagonal
c matrix, and then computes the solution.
c if miter is 4 or 5, it calls dgbsl.
c communication with solsy uses the following variables..
c wm = real work space containing the inverse diagonal matrix if
c miter = 3 and the lu decomposition of the matrix otherwise.
c storage of matrix elements starts at wm(3).
c wm also contains the following matrix-related data..
c wm(1) = sqrt(uround) (not used here),
c wm(2) = hl0, the previous value of h*el0, used if miter = 3.
c iwm = integer work space containing pivot information, starting at
c iwm(21), if miter is 1, 2, 4, or 5. iwm also contains band
c parameters ml = iwm(1) and mu = iwm(2) if miter is 4 or 5.
c x = the right-hand side vector on input, and the solution vector
c on output, of length n.
c tem = vector of work space of length n, not used in this version.
c iersl = output flag (in common). iersl = 0 if no trouble occurred.
c iersl = 1 if a singular matrix arose with miter = 3.
c this routine also uses the common variables el0, h, miter, and n.
c-----------------------------------------------------------------------
iersl = 0
go to (100, 100, 300, 400, 400), miter
100 call dgesl (wm(3), n, n, iwm(21), x, 0)
return
c
300 phl0 = wm(2)
hl0 = h*el0
wm(2) = hl0
if (hl0 .eq. phl0) go to 330
r = hl0/phl0
do 320 i = 1,n
di = 1.0d0 - r*(1.0d0 - 1.0d0/wm(i+2))
if (dabs(di) .eq. 0.0d0) go to 390
320 wm(i+2) = 1.0d0/di
330 do 340 i = 1,n
340 x(i) = wm(i+2)*x(i)
return
390 iersl = 1
return
c
400 ml = iwm(1)
mu = iwm(2)
meband = 2*ml + mu + 1
call dgbsl (wm(3), meband, n, ml, mu, iwm(21), x, 0)
return
c----------------------- end of subroutine solsy -----------------------
end
subroutine ewset (n, itol, rtol, atol, ycur, ewt)
c-----------------------------------------------------------------------
c this subroutine sets the error weight vector ewt according to
c ewt(i) = rtol(i)*abs(ycur(i)) + atol(i), i = 1,...,n,
c with the subscript on rtol and/or atol possibly replaced by 1 above,
c depending on the value of itol.
c-----------------------------------------------------------------------
integer n, itol
integer i
double precision rtol, atol, ycur, ewt
double precision atoli, rtoli
dimension rtol(1), atol(1), ycur(n), ewt(n)
rtoli = rtol(1)
atoli = atol(1)
do 10 i = 1,n
if (itol .ge. 3) rtoli = rtol(i)
if (itol .eq. 2 .or. itol .eq. 4) atoli = atol(i)
ewt(i) = rtoli*dabs(ycur(i)) + atoli
10 continue
return
c----------------------- end of subroutine ewset -----------------------
end
double precision function vnorm (n, v, w)
c-----------------------------------------------------------------------
c this function routine computes the weighted root-mean-square norm
c of the vector of length n contained in the array v, with weights
c contained in the array w of length n..
c vnorm = sqrt( (1/n) * sum( v(i)*w(i) )**2 )
c-----------------------------------------------------------------------
integer n, i
double precision v, w, sum
dimension v(n), w(n)
sum = 0.0d0
do 10 i = 1,n
10 sum = sum + (v(i)*w(i))**2
vnorm = dsqrt(sum/dble(n))
return
c----------------------- end of function vnorm -------------------------
end
subroutine dgefa(a,lda,n,ipvt,info)
integer lda,n,ipvt(1),info
double precision a(lda,1)
c
c dgefa factors a double precision matrix by gaussian elimination.
c
c dgefa is usually called by dgeco, but it can be called
c directly with a saving in time if rcond is not needed.
c (time for dgeco) = (1 + 9/n)*(time for dgefa) .
c
c on entry
c
c a double precision(lda, n)
c the matrix to be factored.
c
c lda integer
c the leading dimension of the array a .
c
c n integer
c the order of the matrix a .
c
c on return
c
c a an upper triangular matrix and the multipliers
c which were used to obtain it.
c the factorization can be written a = l*u where
c l is a product of permutation and unit lower
c triangular matrices and u is upper triangular.
c
c ipvt integer(n)
c an integer vector of pivot indices.
c
c info integer
c = 0 normal value.
c = k if u(k,k) .eq. 0.0 . this is not an error
c condition for this subroutine, but it does
c indicate that dgesl or dgedi will divide by zero
c if called. use rcond in dgeco for a reliable
c indication of singularity.
c
c linpack. this version dated 08/14/78 .
c cleve moler, university of new mexico, argonne national lab.
c
c subroutines and functions
c
c blas daxpy,dscal,idamax
c
c internal variables
c
double precision t
integer idamax,j,k,kp1,l,nm1
c
c
c gaussian elimination with partial pivoting
c
info = 0
nm1 = n - 1
if (nm1 .lt. 1) go to 70
do 60 k = 1, nm1
kp1 = k + 1
c
c find l = pivot index
c
l = idamax(n-k+1,a(k,k),1) + k - 1
ipvt(k) = l
c
c zero pivot implies this column already triangularized
c
if (a(l,k) .eq. 0.0d0) go to 40
c
c interchange if necessary
c
if (l .eq. k) go to 10
t = a(l,k)
a(l,k) = a(k,k)
a(k,k) = t
10 continue
c
c compute multipliers
c
t = -1.0d0/a(k,k)
call dscal(n-k,t,a(k+1,k),1)
c
c row elimination with column indexing
c
do 30 j = kp1, n
t = a(l,j)
if (l .eq. k) go to 20
a(l,j) = a(k,j)
a(k,j) = t
20 continue
call daxpy(n-k,t,a(k+1,k),1,a(k+1,j),1)
30 continue
go to 50
40 continue
info = k
50 continue
60 continue
70 continue
ipvt(n) = n
if (a(n,n) .eq. 0.0d0) info = n
return
end
subroutine dgesl(a,lda,n,ipvt,b,job)
integer lda,n,ipvt(1),job
double precision a(lda,1),b(1)
c
c dgesl solves the double precision system
c a * x = b or trans(a) * x = b
c using the factors computed by dgeco or dgefa.
c
c on entry
c
c a double precision(lda, n)
c the output from dgeco or dgefa.
c
c lda integer
c the leading dimension of the array a .
c
c n integer
c the order of the matrix a .
c
c ipvt integer(n)
c the pivot vector from dgeco or dgefa.
c
c b double precision(n)
c the right hand side vector.
c
c job integer
c = 0 to solve a*x = b ,
c = nonzero to solve trans(a)*x = b where
c trans(a) is the transpose.
c
c on return
c
c b the solution vector x .
c
c error condition
c
c a division by zero will occur if the input factor contains a
c zero on the diagonal. technically this indicates singularity
c but it is often caused by improper arguments or improper
c setting of lda . it will not occur if the subroutines are
c called correctly and if dgeco has set rcond .gt. 0.0
c or dgefa has set info .eq. 0 .
c
c to compute inverse(a) * c where c is a matrix
c with p columns
c call dgeco(a,lda,n,ipvt,rcond,z)
c if (rcond is too small) go to ...
c do 10 j = 1, p
c call dgesl(a,lda,n,ipvt,c(1,j),0)
c 10 continue
c
c linpack. this version dated 08/14/78 .
c cleve moler, university of new mexico, argonne national lab.
c
c subroutines and functions
c
c blas daxpy,ddot
c
c internal variables
c
double precision ddot,t
integer k,kb,l,nm1
c
nm1 = n - 1
if (job .ne. 0) go to 50
c
c job = 0 , solve a * x = b
c first solve l*y = b
c
if (nm1 .lt. 1) go to 30
do 20 k = 1, nm1
l = ipvt(k)
t = b(l)
if (l .eq. k) go to 10
b(l) = b(k)
b(k) = t
10 continue
call daxpy(n-k,t,a(k+1,k),1,b(k+1),1)
20 continue
30 continue
c
c now solve u*x = y
c
do 40 kb = 1, n
k = n + 1 - kb
b(k) = b(k)/a(k,k)
t = -b(k)
call daxpy(k-1,t,a(1,k),1,b(1),1)
40 continue
go to 100
50 continue
c
c job = nonzero, solve trans(a) * x = b
c first solve trans(u)*y = b
c
do 60 k = 1, n
t = ddot(k-1,a(1,k),1,b(1),1)
b(k) = (b(k) - t)/a(k,k)
60 continue
c
c now solve trans(l)*x = y
c
if (nm1 .lt. 1) go to 90
do 80 kb = 1, nm1
k = n - kb
b(k) = b(k) + ddot(n-k,a(k+1,k),1,b(k+1),1)
l = ipvt(k)
if (l .eq. k) go to 70
t = b(l)
b(l) = b(k)
b(k) = t
70 continue
80 continue
90 continue
100 continue
return
end
subroutine dgbfa(abd,lda,n,ml,mu,ipvt,info)
integer lda,n,ml,mu,ipvt(1),info
double precision abd(lda,1)
c
c dgbfa factors a double precision band matrix by elimination.
c
c dgbfa is usually called by dgbco, but it can be called
c directly with a saving in time if rcond is not needed.
c
c on entry
c
c abd double precision(lda, n)
c contains the matrix in band storage. the columns
c of the matrix are stored in the columns of abd and
c the diagonals of the matrix are stored in rows
c ml+1 through 2*ml+mu+1 of abd .
c see the comments below for details.
c
c lda integer
c the leading dimension of the array abd .
c lda must be .ge. 2*ml + mu + 1 .
c
c n integer
c the order of the original matrix.
c
c ml integer
c number of diagonals below the main diagonal.
c 0 .le. ml .lt. n .
c
c mu integer
c number of diagonals above the main diagonal.
c 0 .le. mu .lt. n .
c more efficient if ml .le. mu .
c on return
c
c abd an upper triangular matrix in band storage and
c the multipliers which were used to obtain it.
c the factorization can be written a = l*u where
c l is a product of permutation and unit lower
c triangular matrices and u is upper triangular.
c
c ipvt integer(n)
c an integer vector of pivot indices.
c
c info integer
c = 0 normal value.
c = k if u(k,k) .eq. 0.0 . this is not an error
c condition for this subroutine, but it does
c indicate that dgbsl will divide by zero if
c called. use rcond in dgbco for a reliable
c indication of singularity.
c
c band storage
c
c if a is a band matrix, the following program segment
c will set up the input.
c
c ml = (band width below the diagonal)
c mu = (band width above the diagonal)
c m = ml + mu + 1
c do 20 j = 1, n
c i1 = max0(1, j-mu)
c i2 = min0(n, j+ml)
c do 10 i = i1, i2
c k = i - j + m
c abd(k,j) = a(i,j)
c 10 continue
c 20 continue
c
c this uses rows ml+1 through 2*ml+mu+1 of abd .
c in addition, the first ml rows in abd are used for
c elements generated during the triangularization.
c the total number of rows needed in abd is 2*ml+mu+1 .
c the ml+mu by ml+mu upper left triangle and the
c ml by ml lower right triangle are not referenced.
c
c linpack. this version dated 08/14/78 .
c cleve moler, university of new mexico, argonne national lab.
c
c subroutines and functions
c
c blas daxpy,dscal,idamax
c fortran max0,min0
c
c internal variables
c
double precision t
integer i,idamax,i0,j,ju,jz,j0,j1,k,kp1,l,lm,m,mm,nm1
c
c
m = ml + mu + 1
info = 0
c
c zero initial fill-in columns
c
j0 = mu + 2
j1 = min0(n,m) - 1
if (j1 .lt. j0) go to 30
do 20 jz = j0, j1
i0 = m + 1 - jz
do 10 i = i0, ml
abd(i,jz) = 0.0d0
10 continue
20 continue
30 continue
jz = j1
ju = 0
c
c gaussian elimination with partial pivoting
c
nm1 = n - 1
if (nm1 .lt. 1) go to 130
do 120 k = 1, nm1
kp1 = k + 1
c
c zero next fill-in column
c
jz = jz + 1
if (jz .gt. n) go to 50
if (ml .lt. 1) go to 50
do 40 i = 1, ml
abd(i,jz) = 0.0d0
40 continue
50 continue
c
c find l = pivot index
c
lm = min0(ml,n-k)
l = idamax(lm+1,abd(m,k),1) + m - 1
ipvt(k) = l + k - m
c
c zero pivot implies this column already triangularized
c
if (abd(l,k) .eq. 0.0d0) go to 100
c
c interchange if necessary
c
if (l .eq. m) go to 60
t = abd(l,k)
abd(l,k) = abd(m,k)
abd(m,k) = t
60 continue
c
c compute multipliers
c
t = -1.0d0/abd(m,k)
call dscal(lm,t,abd(m+1,k),1)
c
c row elimination with column indexing
c
ju = min0(max0(ju,mu+ipvt(k)),n)
mm = m
if (ju .lt. kp1) go to 90
do 80 j = kp1, ju
l = l - 1
mm = mm - 1
t = abd(l,j)
if (l .eq. mm) go to 70
abd(l,j) = abd(mm,j)
abd(mm,j) = t
70 continue
call daxpy(lm,t,abd(m+1,k),1,abd(mm+1,j),1)
80 continue
90 continue
go to 110
100 continue
info = k
110 continue
120 continue
130 continue
ipvt(n) = n
if (abd(m,n) .eq. 0.0d0) info = n
return
end
subroutine dgbsl(abd,lda,n,ml,mu,ipvt,b,job)
integer lda,n,ml,mu,ipvt(1),job
double precision abd(lda,1),b(1)
c
c dgbsl solves the double precision band system
c a * x = b or trans(a) * x = b
c using the factors computed by dgbco or dgbfa.
c
c on entry
c
c abd double precision(lda, n)
c the output from dgbco or dgbfa.
c
c lda integer
c the leading dimension of the array abd .
c
c n integer
c the order of the original matrix.
c
c ml integer
c number of diagonals below the main diagonal.
c
c mu integer
c number of diagonals above the main diagonal.
c
c ipvt integer(n)
c the pivot vector from dgbco or dgbfa.
c
c b double precision(n)
c the right hand side vector.
c
c job integer
c = 0 to solve a*x = b ,
c = nonzero to solve trans(a)*x = b , where
c trans(a) is the transpose.
c
c on return
c
c b the solution vector x .
c
c error condition
c
c a division by zero will occur if the input factor contains a
c zero on the diagonal. technically this indicates singularity
c but it is often caused by improper arguments or improper
c setting of lda . it will not occur if the subroutines are
c called correctly and if dgbco has set rcond .gt. 0.0
c or dgbfa has set info .eq. 0 .
c
c to compute inverse(a) * c where c is a matrix
c with p columns
c call dgbco(abd,lda,n,ml,mu,ipvt,rcond,z)
c if (rcond is too small) go to ...
c do 10 j = 1, p
c call dgbsl(abd,lda,n,ml,mu,ipvt,c(1,j),0)
c 10 continue
c
c linpack. this version dated 08/14/78 .
c cleve moler, university of new mexico, argonne national lab.
c
c subroutines and functions
c
c blas daxpy,ddot
c fortran min0
c
c internal variables
c
double precision ddot,t
integer k,kb,l,la,lb,lm,m,nm1
c
m = mu + ml + 1
nm1 = n - 1
if (job .ne. 0) go to 50
c
c job = 0 , solve a * x = b
c first solve l*y = b
c
if (ml .eq. 0) go to 30
if (nm1 .lt. 1) go to 30
do 20 k = 1, nm1
lm = min0(ml,n-k)
l = ipvt(k)
t = b(l)
if (l .eq. k) go to 10
b(l) = b(k)
b(k) = t
10 continue
call daxpy(lm,t,abd(m+1,k),1,b(k+1),1)
20 continue
30 continue
c
c now solve u*x = y
c
do 40 kb = 1, n
k = n + 1 - kb
b(k) = b(k)/abd(m,k)
lm = min0(k,m) - 1
la = m - lm
lb = k - lm
t = -b(k)
call daxpy(lm,t,abd(la,k),1,b(lb),1)
40 continue
go to 100
50 continue
c
c job = nonzero, solve trans(a) * x = b
c first solve trans(u)*y = b
c
do 60 k = 1, n
lm = min0(k,m) - 1
la = m - lm
lb = k - lm
t = ddot(lm,abd(la,k),1,b(lb),1)
b(k) = (b(k) - t)/abd(m,k)
60 continue
c
c now solve trans(l)*x = y
c
if (ml .eq. 0) go to 90
if (nm1 .lt. 1) go to 90
do 80 kb = 1, nm1
k = n - kb
lm = min0(ml,n-k)
b(k) = b(k) + ddot(lm,abd(m+1,k),1,b(k+1),1)
l = ipvt(k)
if (l .eq. k) go to 70
t = b(l)
b(l) = b(k)
b(k) = t
70 continue
80 continue
90 continue
100 continue
return
end
subroutine daxpy(n,da,dx,incx,dy,incy)
c
c constant times a vector plus a vector.
c uses unrolled loops for increments equal to one.
c jack dongarra, linpack, 3/11/78.
c
double precision dx(1),dy(1),da
integer i,incx,incy,ix,iy,m,mp1,n
c
if(n.le.0)return
if (da .eq. 0.0d0) return
if(incx.eq.1.and.incy.eq.1)go to 20
c
c code for unequal increments or equal increments
c not equal to 1
c
ix = 1
iy = 1
if(incx.lt.0)ix = (-n+1)*incx + 1
if(incy.lt.0)iy = (-n+1)*incy + 1
do 10 i = 1,n
dy(iy) = dy(iy) + da*dx(ix)
ix = ix + incx
iy = iy + incy
10 continue
return
c
c code for both increments equal to 1
c
c
c clean-up loop
c
20 m = mod(n,4)
if( m .eq. 0 ) go to 40
do 30 i = 1,m
dy(i) = dy(i) + da*dx(i)
30 continue
if( n .lt. 4 ) return
40 mp1 = m + 1
do 50 i = mp1,n,4
dy(i) = dy(i) + da*dx(i)
dy(i + 1) = dy(i + 1) + da*dx(i + 1)
dy(i + 2) = dy(i + 2) + da*dx(i + 2)
dy(i + 3) = dy(i + 3) + da*dx(i + 3)
50 continue
return
end
subroutine dscal(n,da,dx,incx)
c
c scales a vector by a constant.
c uses unrolled loops for increment equal to one.
c jack dongarra, linpack, 3/11/78.
c
double precision da,dx(1)
integer i,incx,m,mp1,n,nincx
c
if(n.le.0)return
if(incx.eq.1)go to 20
c
c code for increment not equal to 1
c
nincx = n*incx
do 10 i = 1,nincx,incx
dx(i) = da*dx(i)
10 continue
return
c
c code for increment equal to 1
c
c
c clean-up loop
c
20 m = mod(n,5)
if( m .eq. 0 ) go to 40
do 30 i = 1,m
dx(i) = da*dx(i)
30 continue
if( n .lt. 5 ) return
40 mp1 = m + 1
do 50 i = mp1,n,5
dx(i) = da*dx(i)
dx(i + 1) = da*dx(i + 1)
dx(i + 2) = da*dx(i + 2)
dx(i + 3) = da*dx(i + 3)
dx(i + 4) = da*dx(i + 4)
50 continue
return
end
double precision function ddot(n,dx,incx,dy,incy)
c