LOTS OF PROGRAMS 2


Well, here is the Maple code for the harmonic stuff on the gasket:



> #This function returns a table R which contains the values of p and q as defined
#by Mike Usher for determining the values of n-harmonic extensions. The values
#a and b are values of inner products. The function basically implements the
#formula for determining extensions based on an iterative method involving inner
#products. See "Splines on Fractals" from more information (ie, don't ask me,
#I just work here...).

ps_n_qs:=proc(n)
local i,l,j,R,m;
R:=table();

R[p,0]:=2/5;
R[q,0]:=1/5;
R[a,0]:=2;
R[b,0]:=-1;

R[p,1]:=-3/25;
R[q,1]:=-7/75;
R[a,1]:=7/45;
R[b,1]:=4/45;

for i from 1 to n-1 do

R[a,i+1]:=(2/15)*(1/(5^(2*i)-6*5^(i-1) + 1/5)) * sum( (((4*5^i-4/15)*R[p,i+1-j]+(5^i+13/15)*R[q,i+1-j])*(R[a,j]+2*R[b,j])), j=1..i);
R[b,i+1]:=(2/15)*(1/(5^(2*i)-6*5^(i-1) + 1/5))*sum( (((3*5^i-13/15) * R[p,i+1-j] + (2*5^i-14/15) * R[q,i+1-j]) * (R[a,j] + 2*R[b,j])),j=1..i);

R[p,i+1]:=(-1/5)*((9/5)*(R[a,i+1] + 2*R[b,i+1]) + sum( ((4*R[p,i+1-m] + R[q,i+1-m])*R[a,m] + (3 * R[p,i+1-m] + 2*R[q,i+1-m]) * R[b,m]),m=1..i));
R[q,i+1]:=(-1/5)*((7/5)*(R[a,i+1] + 2*R[b,i+1]) + sum( ((2*R[p,i+1-m] + 3*R[q,i+1-m])*R[a,m] + (4 * R[p,i+1-m] + R[q,i+1-m]) * R[b,m]),m=1..i));


od;
R;
end;

> #As long as I'm here, why don't we just calculate this thing out to 5
#so that we can do sex-harmonic functions (Yeah, baby!)
R:=ps_n_qs(5);

> eval(R):

> #This function creates a n-harmonic function, using the values for harmonic extensions calculated
#in R. It uses the recursive method of calculating the n-harmonic extension based on Mike
#Usher's work. In order to understand how the recursion addressing works, I recommend you look
#at the documentation of make_points and gen_points in SG.mws, where I fully explain how the
#recursion works (in terms of the addressing). Basically, after that, this function
#is quite straightforward; it simply calculates the next level based on the values of the previous
#level, as well as the necessary laplacians. This procedure is called by the wrapper function
#n_harm.


nharm:=proc(T,R,n,m,add0,add1,add2,funcno)
local i,j;
if m <> 0 then
#print(funcno);
#print(add0,add1,add2);

if add1[nops(add1)-1..nops(add1)] = [0,1] then
#This loop is because we need to calculate up to n-1 laplacians of the function
#at this level as well...
for i from 0 to n-1 do
#the sums here determine the value at the next level based on the values of
#various laplacians and the such before. Again, see Mike Usher's work for a
#derivation of this formula.
T[[op(add1[1..nops(add1)-2]),0,0,1],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add1,funcno+n-1-i+j]) + R[q,j] * T[add2,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),0,1,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add1,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add0,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),0,0,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add1,funcno+n-1-i+j] ),j=0..i);


nharm(T,R,n,m-1,add0,[op(add1[1..nops(add1)-2]),0,0,1],[op(add1[1..nops(add1)-2]),0,0,2],funcno);
nharm(T,R,n,m-1,add1,[op(add1[1..nops(add1)-2]),0,1,2],[op(add1[1..nops(add1)-2]),0,0,1],funcno);
nharm(T,R,n,m-1,add2,[op(add1[1..nops(add1)-2]),0,0,2],[op(add1[1..nops(add1)-2]),0,1,2],funcno);
fi;
if add1[nops(add1)-1..nops(add1)] = [1,2] then
for i from 0 to n-1 do
T[[op(add1[1..nops(add1)-2]),1,1,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add1,funcno+n-1-i+j]) + R[q,j] * T[add2,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),1,0,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add1,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add0,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),1,0,1],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add1,funcno+n-1-i+j] ),j=0..i);
od;
nharm(T,R,n,m-1,add0,[op(add1[1..nops(add1)-2]),1,1,2],[op(add1[1..nops(add1)-2]),1,0,1],funcno);
nharm(T,R,n,m-1,add1,[op(add1[1..nops(add1)-2]),1,0,2],[op(add1[1..nops(add1)-2]),1,1,2],funcno);
nharm(T,R,n,m-1,add2,[op(add1[1..nops(add1)-2]),1,0,1],[op(add1[1..nops(add1)-2]),1,0,2],funcno);
fi;
if add1[nops(add1)-1..nops(add1)] = [0,2] then
for i from 0 to n-1 do
T[[op(add1[1..nops(add1)-2]),2,0,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add1,funcno+n-1-i+j]) + R[q,j] * T[add2,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),2,0,1],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add1,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add0,funcno+n-1-i+j] ),j=0..i);
T[[op(add1[1..nops(add1)-2]),2,1,2],funcno+n-1-i] := sum((1/(5^(j*(nops(add1)))))*(R[p,j] * (T[add0,funcno+n-1-i+j] + T[add2,funcno+n-1-i+j]) + R[q,j] * T[add1,funcno+n-1-i+j] ),j=0..i);
od;
nharm(T,R,n,m-1,add0,[op(add1[1..nops(add1)-2]),2,0,2],[op(add1[1..nops(add1)-2]),2,1,2],funcno);
nharm(T,R,n,m-1,add1,[op(add1[1..nops(add1)-2]),2,0,1],[op(add1[1..nops(add1)-2]),2,0,2],funcno);
nharm(T,R,n,m-1,add2,[op(add1[1..nops(add1)-2]),2,1,2],[op(add1[1..nops(add1)-2]),2,0,1],funcno);
fi;
fi;
end;


> #So this is basically a wrapper function around the function nharm. This function is
#necessary because nharm won't work until V1, due to idiosyncracies in the labeling system.
#This function basically computes the first n-harmonic extension, and then sends the rest out to
#nharm to compute. n stands for n-harmonic, and R is the table of harmonic extension values
#calculated using ps_and_qs. In order to make this function work, you have to put in the values
#of the function at the boundaries in funcno, as well as the values of the laplacians of the
#function in funcno+1, L^2 of the function in funcno+2... and so forth. This uniquely determines
#an n-harmonic function (ie, you need to specify boundary values of L^(0->n-1)). Notice that
#the algorithm developed required that the function as well as all of it's laplacians be
#defined out to all levels. This has the added bonus that while calculating the function, you have
#calculated the laplacian of it in funcno+1, L^2(f) in funcno+2... Fun, isn't it?

n_harm:=proc(T,R,n,m,add0,add1,add2,funcno)

local i,j;


for i from 0 to n-1 do
T[[0,1],funcno+n-1-i]:=sum((1/(5^(j*nops(add1))))*(R[p,j]*(T[add0,funcno+n-1-i+j]+T[add1,funcno+n-1-i+j])+R[q,j]*T[add2,funcno+n-1-i+j]),j=0..i);
T[[1,2],funcno+n-1-i]:=sum((1/(5^(j*1)))*(R[p,j]*(T[add1,funcno+n-1-i+j]+T[add2,funcno+n-1-i+j])+R[q,j]*T[add0,funcno+n-1-i+j]),j=0..i);
T[[0,2],funcno+n-1-i]:=sum((1/(5^(j*1)))*(R[p,j]*(T[add0,funcno+n-1-i+j]+T[add2,funcno+n-1-i+j])+R[q,j]*T[add1,funcno+n-1-i+j]),j=0..i);
od;


nharm(T,R,n,m-1,[0],[0,1],[0,2],funcno);
nharm(T,R,n,m-1,[1],[1,2],[0,1],funcno);
nharm(T,R,n,m-1,[2],[0,2],[1,2],funcno);



end;

> #This function recursively generates a harmonic function. It is a much simpler algorithm than
#the n-harmonic algorithm, so the addressing business is much more transparent here. Basically,
#it implements the 2/5, 2/5, 1/5 rule for generating the harmonic extension, and recursively
#generates values all the way down into the gasket. The recursion is a little bit complicated,
#because each step of the way, you need to know the orientation of the triangle in order to know
#what type of points are assigned what values. Basically, we used a rotational method of
#determining what the orientation is: we made it so that the 0th address always was a vertex of the
#previous triangle (ie, the 0th address of the first triangle is [1]...). This way, we always
#which address to assign to, based on the last digits of address 1 (if address 1 is [1,2], then
#we know the triangle is a 1 triangle. Thus, you know what addresses to assign what values.
#Anyway, it works. If you want a somewhat more transparent example, see make_points and gen_points
#in SG.mws. The recursion method used there is exactly the same as used here, and should be easily
#generalizable to other fractals (ie, pentagasket...).

harm:=proc(T,m,add0,add1,add2,funcno)
if m <> 0 then
#print(funcno);
#print(add0,add1,add2);

if add1[nops(add1)-1..nops(add1)] = [0,1] then
T[[op(add1[1..nops(add1)-2]),0,0,1],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add1,funcno] + 1/5 * T[add2,funcno];
T[[op(add1[1..nops(add1)-2]),0,1,2],funcno] := 2/5 * T[add1,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add0,funcno];
T[[op(add1[1..nops(add1)-2]),0,0,2],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add1,funcno];
harm(T,m-1,add0,[op(add1[1..nops(add1)-2]),0,0,1],[op(add1[1..nops(add1)-2]),0,0,2],funcno);
harm(T,m-1,add1,[op(add1[1..nops(add1)-2]),0,1,2],[op(add1[1..nops(add1)-2]),0,0,1],funcno);
harm(T,m-1,add2,[op(add1[1..nops(add1)-2]),0,0,2],[op(add1[1..nops(add1)-2]),0,1,2],funcno);
fi;
if add1[nops(add1)-1..nops(add1)] = [1,2] then
T[[op(add1[1..nops(add1)-2]),1,1,2],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add1,funcno] + 1/5 * T[add2,funcno];
T[[op(add1[1..nops(add1)-2]),1,0,2],funcno] := 2/5 * T[add1,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add0,funcno];
T[[op(add1[1..nops(add1)-2]),1,0,1],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add1,funcno];
harm(T,m-1,add0,[op(add1[1..nops(add1)-2]),1,1,2],[op(add1[1..nops(add1)-2]),1,0,1],funcno);
harm(T,m-1,add1,[op(add1[1..nops(add1)-2]),1,0,2],[op(add1[1..nops(add1)-2]),1,1,2],funcno);
harm(T,m-1,add2,[op(add1[1..nops(add1)-2]),1,0,1],[op(add1[1..nops(add1)-2]),1,0,2],funcno);
fi;
if add1[nops(add1)-1..nops(add1)] = [0,2] then
T[[op(add1[1..nops(add1)-2]),2,0,2],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add1,funcno] + 1/5 * T[add2,funcno];
T[[op(add1[1..nops(add1)-2]),2,0,1],funcno] := 2/5 * T[add1,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add0,funcno];
T[[op(add1[1..nops(add1)-2]),2,1,2],funcno] := 2/5 * T[add0,funcno] + 2/5 * T[add2,funcno] + 1/5 * T[add1,funcno];
harm(T,m-1,add0,[op(add1[1..nops(add1)-2]),2,0,2],[op(add1[1..nops(add1)-2]),2,1,2],funcno);
harm(T,m-1,add1,[op(add1[1..nops(add1)-2]),2,0,1],[op(add1[1..nops(add1)-2]),2,0,2],funcno);
harm(T,m-1,add2,[op(add1[1..nops(add1)-2]),2,1,2],[op(add1[1..nops(add1)-2]),2,0,1],funcno);
fi;
fi;
end;

> #This function is basically a wrapper for harm
#It generates a harmonic function with val0,val1,val2 on the boundaries.
#This function calculates the first harmonic extension, and then calls harm
#on the 3 parts to generate the rest of the harmonic function. It can't do it directly due
#to idiosyncracies in the nomenclature of the V0 points.

harmonic:=proc(T,m,val0,val1,val2,funcno)
T[[0],funcno]:=val0;
T[[1],funcno]:=val1;
T[[2],funcno]:=val2;

T[[0,1],funcno]:=2/5 * val0 + 2/5 * val1 + 1/5 * val2;
T[[0,2],funcno]:=2/5 * val0 + 2/5 * val2 + 1/5 * val1;
T[[1,2],funcno]:=2/5 * val1 + 2/5 * val2 + 1/5 * val0;

harm(T,m-1,[2],[0,2], [1,2], funcno);
harm(T,m-1,[0],[0,1], [0,2], funcno);
harm(T,m-1,[1],[1,2], [0,1], funcno);
end;



Previous page Next page
Back to Lots of Programs