Structural knowledge and functional properties should be used by the symbolic
environment in order to improve the efficiency of the resulting compiled
code [21]. Optimisation can be used for more efficient evaluation of the
function and its Jacobian matrix in Newton's method, in much the same way as in
the Runge-Kutta example of section . For example, the
optimization process can resolve matrix symmetries.
Illustration of these issues is given by a simple example. Consider a Jacobian
matrix derived from a function of two variables .
In[1]:= f[x_,y_] := {x + y + 2 x Sin[y]^2, x + y + x^2 Sin[2 y]}; In[2]:= jac[f_List,vars_List] := Outer[D,f,vars]; In[3]:= matrix = jac[f[x,y],{x,y}]; In[4]:= matrix //MatrixForm Out[4]//MatrixForm= 2 1 + 2 Sin[y] 1 + 4 x Cos[y] Sin[y] 2 1 + 2 x Sin[2 y] 1 + 2 x Cos[2 y]
In fact this matrix turns out to be symmetric:
In[5]:= simpmat = Simplify[matrix]; In[6]:= simpmat //MatrixForm
Out[6]//MatrixForm= 2 - Cos[2 y] 1 + 2 x Sin[2 y] 2 1 + 2 x Sin[2 y] 1 + 2 x Cos[2 y]A considerable amount of computation can be saved if the property
In[7]:= FortranAssign[m, simpmat, AssignOptimize->True, OptimizePower->True,OptimizeTimes->False] Out[7]//OutputForm= o1=cos(2.d0*y) o2=sin(2.d0*y) o3=1.d0+2.d0*o2*x m(1,1)=2.d0-o1 m(1,2)=o3 m(2,1)=o3 m(2,2)=1.d0+2.d0*o1*x**2Notice that the matrix components are optimized, but the encapsulating lists themselves are not, since the default setting OptimizeNull->{List} has been used to ignore such objects. Also we use the option OptimizeTimes->False to ignore sub-expressions with head Times. Such operations do not yield additional optimizations in this example and ignoring them speeds up the optimization process.