Above shows how
a heat flow operator transforms
the input qt to the output qt+1.
What we really want to do is completely different.
We want to define the input as the source function
and we want to define the output as some arbitrary subset
of qt, qt+1, qt+2, etc.
The adjoint we seek will carry us
from the specified subset of qt
back to an image of the sources st.
Defining (where deltaxx is the second difference operator)
reduces equation (3) to
![]() |
(5) |
![]() |
(6) |
![]() |
(7) |
The adjoint of H is H'.
We define the image of the sources by the recursion
![]() |
(8) |
![]() |
(9) |
As before, the computing methodology is to preload
and then use
C-style augmenting assignments
![]() |
(10) |
subroutine heatsteps( adj, sigma, ss, nx,nt, qq ) integer adj, nx,nt, it real sigma, ss( nx,nt), qq( nx,nt) temporary real tt( nx,nt) call adjnull( adj, 0, ss, nx*nt, qq, nx*nt) if( adj == 0) { call copy( nx*nt, ss, tt) do it= 2, nt call heatstep( 0,1, sigma, tt(1,it-1), nx, tt(1,it)) call copy( nx*nt, tt, qq) } else { call copy( nx*nt, qq, tt) do it= nt,2,-1 call heatstep( 1,1, sigma, tt(1,it-1), nx, tt(1,it)) call copy( nx*nt, tt, ss) } return; end
The problem with the above subroutine is that it wastes memory, assuming that we can store the temperature field over all space and time. A more realistic assumption is that we can store it over all space but only at two time levels. Moving the copy commands into the inner loops, we require memory for only the field at time t and time t+1.
subroutine heatsteps( adj, sigma, ss, nx,nt, qq ) integer adj, nx,nt, it real sigma, ss( nx,nt), qq( nx,nt) temporary real tt( nx) call adjnull( adj, 0, ss, nx*nt, qq, nx*nt) if( adj == 0) { call copy( nx, ss(1, 1), qq(1,1)) # load initial do it= 2, nt { call copy( nx, ss(1,it), tt) # load source call heatstep( 0,1, sigma, qq(1,it-1), nx, tt) call copy( nx, tt, qq(1,it)) # extract } } else { call copy( nx, qq(1,nt), ss(1,nt)) # load initial do it= nt-1,1,-1 { call copy( nx, qq(1,it), tt) # load call heatstep( 1,1, sigma, tt, nx, ss(1,it+1)) call copy( nx, tt, ss(1,it)) # extract source } } return; end
Notice that the input ss(,) and output qq(,) still fill all of time and space so they appear to be impractically large. What saves us is that in practice there will not be sources everywhere in time and space nor will there be recording of the thermal field everywhere either. Thus in practice the copy calls will be reduced to copying the application operator inputs and outputs which should be much smaller.