MODULE CalcConvolution;
IMPORT NbrInt, NbrRe, DataErrors, MathInt, MathRe, CalcFn;
PROCEDURE LogP( p, x: NbrRe.Real ): NbrRe.Real;
BEGIN
RETURN MathRe.Ln( x ) / MathRe.Ln( p )
END LogP;
PROCEDURE GetArrayDimension*( x, t: NbrRe.Real; n: NbrInt.Integer ): NbrInt.Integer;
BEGIN
RETURN NbrRe.Ceiling( n * x / t ) + 1
END GetArrayDimension;
PROCEDURE Solve*( k: CalcFn.ReArg; f: CalcFn.Re2Arg; x, t: NbrRe.Real; n, p: NbrInt.Integer;
VAR soln: ARRAY OF ARRAY OF NbrRe.Real );
VAR i, j, l, s, z, gamma, iBar, jj, mu, power, sigma: NbrInt.Integer; h, prod, sum, xi: NbrRe.Real;
kernel: POINTER TO ARRAY OF ARRAY OF NbrRe.Real;
laplaceArray: ARRAY 5 OF NbrRe.Real;
laplaceMatrix: ARRAY 8, 8 OF NbrRe.Real;
BEGIN
IF k # NIL THEN
IF f # NIL THEN
IF x > 0 THEN
IF t > 0 THEN
IF LEN( soln, 0 ) > NbrRe.Ceiling( n * x / t ) THEN
IF LEN( soln, 1 ) > 1 THEN
IF n < 4 THEN n := 4 END;
IF p < 2 THEN p := 2 END;
h := t / n; mu := NbrInt.Max( 1, NbrRe.Ceiling( LogP( p, x / t ) ) );
NEW( kernel, mu + 1, p * n + 1 );
FOR i := 1 TO p * n DO kernel[1, i] := k( h * (i - 0.5) ) END;
FOR j := 2 TO mu DO
FOR i := 1 TO (p - 1) * n DO kernel[j, i] := k( (t + h * (i - 0.5)) * MathInt.Power( p, j - 1 ) ) END
END;
FOR j := 4 TO 7 DO
FOR i := 1 TO j DO laplaceMatrix[i, j] := 1 END;
laplaceMatrix[1, j] := laplaceMatrix[1, j] + 703 / 5760;
laplaceMatrix[2, j] := laplaceMatrix[2, j] - 463 / 1920;
laplaceMatrix[3, j] := laplaceMatrix[3, j] + 101 / 640;
laplaceMatrix[4, j] := laplaceMatrix[4, j] - 223 / 5760;
laplaceMatrix[j, j] := laplaceMatrix[j, j] + 703 / 5760;
laplaceMatrix[j - 1, j] := laplaceMatrix[j - 1, j] - 463 / 1920;
laplaceMatrix[j - 2, j] := laplaceMatrix[j - 2, j] + 101 / 640;
laplaceMatrix[j - 3, j] := laplaceMatrix[j - 3, j] - 223 / 5760;
END;
laplaceArray[1] := 1 + 703 / 5760; laplaceArray[2] := 1 - 463 / 1920;
laplaceArray[3] := 1 + 101 / 640; laplaceArray[4] := 1 - 223 / 5760;
jj := NbrRe.Ceiling( x / h ); soln[0, 0] := 0; soln[0, 1] := 0;
IF mu = 1 THEN iBar := jj ELSE iBar := p * n END;
FOR i := 1 TO NbrInt.Min( 3, iBar ) DO
xi := i * h; soln[i, 0] := xi;
soln[i, 1] :=
i * h *
(13 * (k( 7 * xi / 8 ) * f( xi / 8, xi ) + k( xi / 8 ) * f( 7 * xi / 8, xi )) +
11 * (k( 5 * xi / 8 ) * f( 3 * xi / 8, xi ) + k( 3 * xi / 8 ) * f( 5 * xi / 8, xi ))) / 48
END;
FOR i := 4 TO NbrInt.Min( 7, iBar ) DO
xi := i * h; soln[i, 0] := xi; soln[i, 1] := 0;
FOR j := 1 TO i DO
prod := laplaceMatrix[j, i] * kernel[1, j] * f( (i - j + 0.5) * h, xi ); soln[i, 1] := soln[i, 1] + prod
END;
soln[i, 1] := h * soln[i, 1]
END;
FOR i := 8 TO iBar DO
xi := i * h; soln[i, 0] := xi; soln[i, 1] := 0;
FOR j := 1 TO 4 DO
prod := laplaceArray[j] * kernel[1, j] * f( (i - j + 0.5) * h, xi ); soln[i, 1] := soln[i, 1] + prod
END;
FOR j := 5 TO i - 4 DO prod := kernel[1, j] * f( (i - j + 0.5) * h, xi ); soln[i, 1] := soln[i, 1] + prod END;
FOR j := i - 3 TO i DO
prod := laplaceArray[i + 1 - j] * kernel[1, j] * f( (i - j + 0.5) * h, xi );
soln[i, 1] := soln[i, 1] + prod
END;
soln[i, 1] := h * soln[i, 1]
END;
FOR i := iBar + 1 TO jj DO
xi := i * h; soln[i, 0] := xi; soln[i, 1] := 0;
FOR j := 1 TO 4 DO
prod := laplaceArray[j] * kernel[1, j] * f( (i - j + 0.5) * h, xi ); soln[i, 1] := soln[i, 1] + prod
END;
FOR j := 5 TO p * n - 4 DO
prod := kernel[1, j] * f( (i - j + 0.5) * h, xi ); soln[i, 1] := soln[i, 1] + prod
END;
FOR j := p * n - 3 TO p * n DO
prod := laplaceArray[p * n + 1 - j] * kernel[1, j] * f( (i - j + 0.5) * h, xi );
soln[i, 1] := soln[i, 1] + prod
END;
sigma := NbrRe.Ceiling( LogP( p, i / n ) ) - 1;
FOR s := 1 TO sigma - 1 DO
sum := 0; power := MathInt.Power( p, s );
FOR j := 1 TO 4 DO
sum := sum + laplaceArray[j] * kernel[s + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
FOR j := 5 TO n * (p - 1) - 4 DO
sum := sum + kernel[s + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
FOR j := n * (p - 1) - 3 TO n * (p - 1) DO
sum :=
sum +
laplaceArray[n * (p - 1) + 1 - j] * kernel[s + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
soln[i, 1] := soln[i, 1] + power * sum
END;
soln[i, 1] := h * soln[i, 1];
power := MathInt.Power( p, sigma ); l := i - n * power;
IF l < 4 * power THEN
soln[i, 1] :=
soln[i, 1] +
l * h *
(13 * (k( (i - l / 8) * h ) * f( l * h / 8, xi ) + k( (i - 7 * l / 8) * h ) * f( 7 * l * h / 8, xi )) +
11 * (k( (i - 3 * l / 8) * h ) * f( 3 * l * h / 8, xi ) + k( (i - 5 * l / 8) * h ) * f( 5 * l * h / 8, xi ))) / 48
ELSE
sum := 0; gamma := NbrRe.Floor( l / power );
IF gamma < 8 THEN
FOR j := 1 TO gamma DO
sum :=
sum +
laplaceMatrix[j, gamma] * kernel[sigma + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
soln[i, 1] := soln[i, 1] + h * power * sum
ELSE
FOR j := 1 TO 4 DO
sum :=
sum + laplaceArray[j] * kernel[sigma + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
FOR j := 5 TO gamma - 4 DO
sum := sum + kernel[sigma + 1, j] * f( xi - (t + h * (j - 0.5)) * power, xi )
END;
FOR j := gamma - 3 TO gamma DO
sum :=
sum +
laplaceArray[gamma + 1 - j] * kernel[sigma + 1, j] *
f( xi - (t + h * (j - 0.5)) * power, xi )
END;
soln[i, 1] := soln[i, 1] + h * power * sum
END;
z := i - power * (n + gamma);
soln[i, 1] :=
soln[i, 1] +
h * z *
(13 * (k( (i - z / 8) * h ) * f( z * h / 8, xi ) + k( (i - 7 * z / 8) * h ) * f( 7 * z * h / 8, xi )) +
11 * (k( (i - 3 * z / 8) * h ) * f( 3 * z * h / 8, xi ) + k( (i - 5 * z / 8) * h ) * f( 5 * z * h / 8, xi ))) / 48
END
END
ELSE DataErrors.Error( "The second dimension of the solution array must be at least 2." )
END
ELSE DataErrors.IntError( LEN( soln, 0 ), "The solution array is too short." )
END
ELSE DataErrors.ReError( t, "The characteristic time is required to be positive." )
END
ELSE DataErrors.ReError( x, "The upper limit of integration is required to be positive." )
END
ELSE DataErrors.Error( "The supplied forcing function was NIL." )
END
ELSE DataErrors.Error( "The supplied kernel function was NIL." )
END
END Solve;
END CalcConvolution.