A example umacr4.f is given below.
The name of the user macro is set to broyden. The macro
command itself is used to perform a given number of quasi-newton updates
to the solution vector without form-factoring an additional tangent matrix.
The command takes as options the keyword iter and the number of
iteration to be performed. The sequence of calls from the Macro prompt
would then be:
Macro> utan,,1
Macro> broy,iter,10
if one were interested in ten broyden iterations.
As these routines use the user memory allocation system. The needed ualloc file is also contained below.
c * * F E A P * * A Finite Element Analysis Program
c.... Copyright (c) 1984-1999: Robert L. Taylor
c-----[--.----+----.----+----.-----------------------------------------]
c Purpose: User interface for the
Broyden Quasi-Newton Method
c
c Call order: > utan,,1
c
> broy,iter,15
c Inputs:
c lct
- Command character parameters
c ctl(3)
- Command numerical parameters
c prt
- Flag, output if true
c Outputs:
c N.B. Users
are responsible for command actions. See
c
programmers manual for example.
c-----[--.----+----.----+----.-----------------------------------------]
implicit none
include 'cdata.h'
include 'iofile.h'
include 'pointer.h'
include 'umac1.h'
include 'upointer.h'
include 'comblk.h'
logical pcomp,prt,tlog,ualloc
character lct*15
integer numvec,vecs,i
real*8 ctl(3)
save
c Set command word
if(pcomp(uct,'mac4',4)) then
uct = 'broy'
numvec = 0
return
elseif(pcomp(lct,'iter',4)) then
vecs = min(max(int(ctl(1)),2),20) ! allow for a maximum of 20 vectors and min of one iteration (2 vecs)
if(numvec .lt. vecs) then
! Re-allocate to get more memory if necessary
numvec = vecs
tlog = ualloc(1,'VTIL',neq*numvec,2)
if(.not.tlog)
write(*,*) 'UALLOC ERROR - VTIL'
tlog = ualloc(2,'DELX',neq*numvec,2)
if(.not.tlog)
write(*,*) 'UALLOC ERROR - DELX'
endif
call pzero(hr(up(1)),neq*numvec)
call pzero(hr(up(2)),neq*numvec)
c Grab
delta-x from previous utang,,1 solve
do i = 1,neq
hr(up(2) + i - 1)
= hr(np(26) + i - 1)
end do
call broyden(hr(up(1)),hr(up(2)),vecs)
endif
end
subroutine broyden(vtil,delx,numvec)
implicit none
include 'cdata.h'
include 'fdata.h'
include 'hdatam.h'
include 'ndata.h'
include 'part0.h'
include 'pointer.h'
include 'print.h'
include 'prlod.h'
include 'comblk.h'
logical fa,tr
integer numvec,iter,k,pu,pr,fp(5),j
real*8 w,z,energy,rnorm,dot
real*8 vtil(neq,numvec),delx(neq,numvec)
real*8 v(neq)
save
pu = np(40)
pr = np(26)
fa = .false.
tr = .true.
c Iterate for the updates
do iter = 2,numvec
c Allow for history
updates
hflgu = tr
h3flgu = tr
c Get external load
vector
call pload(mr(np(31)),hr(pu),hr(np(30)),hr(pr),prop,tr,fa)
c Get total
negative residual in hr(pr)
call formfe(pu,pr,pr,pr,fa,tr,fa,fa,6,1,numel,1)
rnorm = sqrt(dot(hr(pr),hr(pr),neq))
write(*,*) 'Iter = ',iter,' Residual
= ',rnorm
c Set flags for
u-symm solve and solve with result found in hr(pr)
fp(1) = na
fp(2) = nau
fp(3) = nal
fp(4) = pr
fp(5) = np(20+npart)
call psolve(fp,fa,tr,tr,prnt)
do k=1,neq
v(k) = -hr(pr+k-1)
end do
if(iter.eq.2) then
c Broyden
update computation first one
w = dot(v,delx(1,iter-1),neq)
z = dot(delx(1,iter-1),delx(1,iter-1),neq)
z = -1.d0/(w+z)
do k = 1,neq
vtil(k,iter-1)
= v(k)*z
delx(k,iter)
= -(v(k) + w*vtil(k,iter-1))
end do
else
c
Broyden update computation generic form iter > 2
do j = 1,iter-2
w = dot(v,delx(1,j),neq)
do k = 1,neq
v(k) = v(k) + vtil(k,j)*w
end do
end do
w = dot(v,delx(1,iter-1),neq)
z = dot(delx(1,iter-1),delx(1,iter-1),neq)
z = -1.d0/(w+z)
do k = 1,neq
vtil(k,iter-1)
= v(k)*z
delx(k,iter)
= -(v(k) + w*vtil(k,iter-1))
end do
endif
c Actual update
of solution vector
call update(mr(np(31)),hr(np(30)),hr(pu),hr(np(42)),
&
delx(1,iter),fl(9),2)
end do
end
c User allocation routine that goes with
broyden macro
c$Id: ualloc.f,v 1.1 1999/03/21
07:53:57 sanjay Exp $
logical function ualloc(num,name,length,precis)
c * * F E A P * * A Finite Element Analysis Program
c.... Copyright (c) 1984-1999: Robert L. Taylor
c-----[--.----+----.----+----.-----------------------------------------]
c Purpose: Define, delete, or resize
a user dictionary entry.
c
Pointer defined for integer (single) and real
c
(double precision) arrays.
c
N.B. Currently limited to 200 names by dimension of
c
common blocks 'allotd','allotn','pointer','upointer'
c Inputs:
c num
- Entry number for array (see below)
c name
- Name of array (see
below)
c length
- Length of array defined: =0 for delete
c precis
- Precision of array: 1 = integers; 2 = reals
c Output:
c up(num)
- Pointer to first word of array in blank common
c-----[--.----+----.----+----.-----------------------------------------]
implicit none
include 'allotd.h'
logical usetmem
character name*(*)
integer i, num,length,precis
c Storage definitions for UALLOC variables
integer list
parameter (list = 2)
character names(list)*5
save
c Define and store names
data (names(i),i=1,list)/
& 'VTIL','DELX'/
c Short description of variables
c
'VTIL', ! 1: v-tilde array
in broyden method
c
'DELX', ! 2: array of old
incremental updates
c Do memory management operations
ualloc = usetmem(list,names,num,name,length,precis)
end