public LMatrices BuildDerivativesNonUniform(double[] S, double[] V, double[] T) { // Build the first- and second-order derivatives for the "L" operator matrix // for the Weighted method // Requires a uniform grid for S and V // INPUTS // S = vector for uniform stock price grid // V = vector for uniform volatility grid // T = vector for uniform maturity grid // thet = parameter for the weighted scheme // OUTPUTS // Matrices of dimnension N x N (N=NS+NV) // derS = Matrix for first-order derivative dU/dS // derSS = Matrix for second-order derivative dU2/dS2 // derV1 = Matrix for first-order derivative dU/dV, kappa*theta portion // derV2 = Matrix for first-order derivative dU/dV, -kappa*V portion // derVV = Matrix for first-order derivative dU2/dV2 // derSV = Matrix for first-order derivative dU2/dSdV // R = Matrix for r*S(v,t) portion of the PDE Interpolation BDU = new Interpolation(); // Length of stock price, volatility, and maturity int NS = S.Length; int NV = V.Length; int NT = T.Length; double Smin = S[0]; double Smax = S[NS - 1]; double Vmin = V[0]; double Vmax = V[NV - 1]; double Tmin = T[0]; double Tmax = T[NT - 1]; // Preliminary quantities // Size of the U(t) vector and L matrix int N = NS * NV; // The vectors for S and V, stacked double[] Si = new double[N]; double[] Vi = new double[N]; int k = 0; for (int v = 0; v <= NV - 1; v++) { for (int s = 0; s <= NS - 1; s++) { Si[k] = S[s]; Vi[k] = V[v]; k += 1; } } // Identification of the boundary points int[] VminB = new int[N]; int[] VmaxB = new int[N]; int[] SminB = new int[N]; int[] SmaxB = new int[N]; // Vmin and Vmax for (int v = 0; v <= NS - 2; v++) { VminB[v] = 1; } for (int v = N - NS + 1; v <= N - 2; v++) { VmaxB[v] = 1; } VmaxB[N - 1] = 1; // Smin and Smax k = 0; for (int v = 0; v <= NV - 1; v++) { for (int s = 0; s <= NS - 1; s++) { if (s == 0) { SminB[k] = 1; } else if (s == NS - 1) { SmaxB[k] = 1; } k += 1; } } SminB[0] = 0; SmaxB[NS - 1] = 0; SmaxB[N - 1] = 0; // Identification of the non-boundary points int[] NB = new int[N]; for (k = 0; k <= N - 1; k++) { if (SminB[k] == 0 & SmaxB[k] == 0 & VminB[k] == 0 & VmaxB[k] == 0) { NB[k] = 1; } } NB[NS - 1] = 1; // Forward, backward and central differences for S int[] Cs = new int[N]; int[] Fs = new int[N]; int[] Bs = new int[N]; k = 0; for (int v = 0; v <= NV - 2; v++) { for (int s = 0; s <= NS - 1; s++) { if (s == 1) { Fs[k] = 1; } else if (s == NS - 2) { Bs[k] = 1; } else if (s >= 2 & s <= NS - 3) { Cs[k] = 1; } k += 1; } } Fs[1] = 0; Bs[NS - 2] = 0; for (k = 2; k <= NS - 3; k++) { Cs[k] = 0; } // Forward, backward and central differences for V int[] Cv = new int[N]; int[] Fv = new int[N]; int[] Bv = new int[N]; for (k = NS + 1; k <= 2 * NS - 2; k++) { Fv[k] = 1; } for (k = (NV - 2) * NS + 1; k <= (NV - 1) * NS - 2; k++) { Bv[k] = 1; } k = 0; for (int v = 0; v <= NV - 3; v++) { for (int s = 0; s <= NS - 1; s++) { if (s >= 1 & s <= NS - 2) { Cv[k] = 1; } k += 1; } } for (k = 0; k <= 2 * NS - 1; k++) { Cv[k] = 0; } // Central difference for SV-derivatives int[] Csv = new int[N]; k = 0; for (int v = 0; v <= NV - 2; v++) { for (int s = 0; s <= NS - 1; s++) { if (s >= 1 & s <= NS - 2) { Csv[k] = 1; } k += 1; } } for (k = 0; k <= NS - 1; k++) { Csv[k] = 0; } // for(k=0;k<=N-1;k++) // Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}",SminB[k],SmaxB[k],VminB[k],VmaxB[k],NB[k],Fs[k],Bs[k],Cs[k],Fv[k],Bv[k],Cv[k],Csv[k]); // Create the matrices for the derivatives double[,] derS = new double[N, N]; double[,] derSS = new double[N, N]; double[,] derV1 = new double[N, N]; double[,] derV2 = new double[N, N]; double[,] derVV = new double[N, N]; double[,] derSV = new double[N, N]; double[,] R = new double[N, N]; for (int i = 0; i <= N - 1; i++) { for (int j = 0; j <= N - 1; j++) { if (i == j) { R[i, j] = 1.0; } } } int M; int[] I; double ds, dv; // Create the matrices for the derivatives // NON BOUNDARY POINTS ---------------------------------- I = BDU.Find(Cs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Central differences ds = Si[I[k]] - Si[I[k] - 1]; derS[I[k], I[k] - 1] = -0.5 / ds * Si[I[k]]; // U(s-1,v) derSS[I[k], I[k] - 1] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-1,v) ds = Si[I[k] + 1] - Si[I[k]]; derS[I[k], I[k] + 1] = 0.5 / ds * Si[I[k]]; // U(s+1,v) derSS[I[k], I[k] + 1] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+1,v) ds = (Si[I[k] + 1] - Si[I[k] - 1]) / 2.0; derS[I[k], I[k]] = 0.0; // U(s,v) derSS[I[k], I[k]] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) } I = BDU.Find(Fs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Forward differences ds = (Si[I[k] + 1] - Si[I[k] - 1]) / 2.0; derS[I[k], I[k]] = -1.5 / ds * Si[I[k]]; // U(s,v) derSS[I[k], I[k]] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) ds = Si[I[k] + 1] - Si[I[k]]; derS[I[k], I[k] + 1] = 2.0 / ds * Si[I[k]]; // U(s+1,v) derSS[I[k], I[k] + 1] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+1,v) ds = (Si[I[k] + 2] - Si[I[k]]) / 2.0; derS[I[k], I[k] + 2] = -1.0 / ds * Si[I[k]]; // U(s+2,v) derSS[I[k], I[k] + 2] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+2,v) } I = BDU.Find(Bs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Backward differences ds = (Si[I[k]] - Si[I[k] - 2]) / 2.0; derS[I[k], I[k] - 2] = -0.5 / ds * Si[I[k]]; // U(s-2,v) derSS[I[k], I[k] - 2] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-2,v) ds = (Si[I[k]] - Si[I[k] - 1]); derS[I[k], I[k] - 1] = -2.0 / ds * Si[I[k]]; // U(s-1,v) derSS[I[k], I[k] - 1] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-1,v) ds = (Si[I[k] + 1] - Si[I[k] - 1]) / 2.0; derSS[I[k], I[k]] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) derS[I[k], I[k]] = 1.5 / ds * Si[I[k]]; // U(s,v) } // Create the matrix for V-derivatives I = BDU.Find(Cv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Central differences dv = Vi[I[k]] - Vi[I[k] - NS]; derV1[I[k], I[k] - NS] = -0.5 / dv; // U(s,v-1) derV2[I[k], I[k] - NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k] - NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-1) dv = Vi[I[k] + NS] - Vi[I[k]]; derV1[I[k], I[k] + NS] = 0.5 / dv; // U(s,v+1) derV2[I[k], I[k] + NS] = 0.5 / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] + NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+1) dv = (Vi[I[k] + NS] - Vi[I[k] - NS]) / 2.0; derVV[I[k], I[k]] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v) derV1[I[k], I[k]] = 0.0; // U(s,v) derV2[I[k], I[k]] = 0.0; // U(s,v) } I = BDU.Find(Fv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Forward differences dv = (Vi[I[k] + NS] - Vi[I[k] - NS]) / 2.0; derV1[I[k], I[k]] = -1.5 / dv; // U(s,v) derV2[I[k], I[k]] = -1.5 / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k]] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v) dv = Vi[I[k] + NS] - Vi[I[k]]; derV1[I[k], I[k] + NS] = 2.0 / dv; // U(s,v+1) derV2[I[k], I[k] + NS] = 2.0 / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] + NS] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v+1) dv = (Vi[I[k] + 2 * NS] - Vi[I[k]]) / 2.0; derV1[I[k], I[k] + 2 * NS] = -1.0 / dv; // U(s,v+2) derV2[I[k], I[k] + 2 * NS] = -1.0 / dv * Vi[I[k]]; // U(s,v+2) derVV[I[k], I[k] + 2 * NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+2) } I = BDU.Find(Bv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Backward differences dv = (Vi[I[k]] - Vi[I[k] - 2 * NS]) / 2.0; derV1[I[k], I[k] - 2 * NS] = -0.5 / dv; // U(s,v-2) derV2[I[k], I[k] - 2 * NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-2) derVV[I[k], I[k] - 2 * NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-2) dv = Vi[I[k]] - Vi[I[k] - NS]; derV1[I[k], I[k] - NS] = -2.0 / dv; // U(s,v-1) derV2[I[k], I[k] - NS] = -2.0 / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k] - NS] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v-1) dv = (Vi[I[k] + NS] - Vi[I[k] - NS]) / 2.0; derV1[I[k], I[k]] = 1.5 / dv; // U(s,v) derV2[I[k], I[k]] = 1.5 / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k]] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v) } // Create the matrix for SV-derivatives - simplified version /* I = Find(Csv); * M = I.Length; * for(k=0;k<=M-1;k++) * { * dv = (Vi[I[k]+NS] - Vi[I[k]-NS])/2.0; * ds = (Si[I[k]+1] - Si[I[k]-1])/2.0; * derSV[I[k],I[k]+NS+1] = 1.0/(4.0*ds*dv) * Vi[I[k]]*Si[I[k]]; // U(s+1,v+1) * derSV[I[k],I[k]+NS-1] = -1.0/(4.0*ds*dv) * Vi[I[k]]*Si[I[k]]; // U(s-1,v+1) * derSV[I[k],I[k]-NS-1] = 1.0/(4.0*ds*dv) * Vi[I[k]]*Si[I[k]]; // U(s-1,v-1) * derSV[I[k],I[k]-NS+1] = -1.0/(4.0*ds*dv) * Vi[I[k]]*Si[I[k]]; // U(s+1,v-1) * } */ // Create the matrix for SV-derivatives I = BDU.Find(Csv); M = I.Length; double a1, a2, a3, a4, a5, a6, a7, a8, a9, ds1, dv1; for (k = 0; k <= M - 1; k++) { ds = Si[I[k]] - Si[I[k] - 1]; if (I[k] + 1 <= NS) { ds1 = Si[I[k + 1]] - S[I[k]]; // Correct for off-grid point } else { ds1 = ds; } dv = Vi[I[k]] - Vi[I[k] - NS]; dv1 = Vi[I[k] + NS] - Vi[I[k]]; a1 = ds1 / ds / (ds + ds1) * dv1 / dv / (dv + dv1); a2 = -ds1 / ds / (ds + ds1) * (dv1 - dv) / dv / dv1; a3 = -ds1 / ds / (ds + ds1) * dv / dv1 / (dv + dv1); a4 = (ds1 - ds) / ds / ds1 * (-dv1) / dv / (dv + dv1); a5 = (ds1 - ds) / ds / ds1 * (dv1 - dv) / dv1 / dv; a6 = (ds1 - ds) / ds / ds1 * dv / dv1 / (dv + dv1); a7 = ds / ds / (ds + ds1) * (-dv1) / dv / (dv + dv1); a8 = ds / ds1 / (ds + ds1) * (dv1 - dv) / dv / dv1; a9 = ds / ds1 / (ds1 + ds) * dv / dv1 / (dv + dv1); derSV[I[k], I[k] - NS - 1] = a1 * Vi[I[k]] * Si[I[k]]; // U(s-1,v-1) derSV[I[k], I[k] - 1] = a2 * Vi[I[k]] * Si[I[k]]; // U(s-1,v) derSV[I[k], I[k] + NS - 1] = a3 * Vi[I[k]] * Si[I[k]]; // U(s-1,v+1) derSV[I[k], I[k] - NS] = a4 * Vi[I[k]] * Si[I[k]]; // U(s,v-1) derSV[I[k], I[k]] = a5 * Vi[I[k]] * Si[I[k]]; // U(s,v) derSV[I[k], I[k] + NS] = a6 * Vi[I[k]] * Si[I[k]]; // U(s,v+1) derSV[I[k], I[k] - NS + 1] = a7 * Vi[I[k]] * Si[I[k]]; // U(s+1,v-1) derSV[I[k], I[k] + 1] = a8 * Vi[I[k]] * Si[I[k]]; // U(s+1,v) derSV[I[k], I[k] + NS + 1] = a9 * Vi[I[k]] * Si[I[k]]; // U(s+1,v+1) } // BOUNDARY POINTS ---------------------------------- // Boundary for Smin I = BDU.Find(SminB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = 0.0; derSS[I[k], I[k]] = 0.0; derV1[I[k], I[k]] = 0.0; derV2[I[k], I[k]] = 0.0; derVV[I[k], I[k]] = 0.0; derSV[I[k], I[k]] = 0.0; R[I[k], I[k]] = 0.0; } // Boundary condition for Smax I = BDU.Find(SmaxB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = Si[I[k]]; derSS[I[k], I[k]] = 0.0; derSV[I[k], I[k]] = 0.0; // Central difference derV1[I[k], I[k]] = 0; // U(s,v) derV2[I[k], I[k]] = 0.0; // U(s,v) dv = Vi[I[k]] - Vi[I[k] - NS]; derV1[I[k], I[k] - NS] = -0.5 / dv; // U(s,v-1) derV2[I[k], I[k] - NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k] - NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-1) dv = Vi[I[k] + NS] - Vi[I[k]]; derV1[I[k], I[k] + NS] = 0.5 / dv; // U(s,v+1) derV2[I[k], I[k] + NS] = 0.5 / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] + NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+1) dv = (Vi[I[k] + NS] - Vi[I[k] - NS]) / 2.0; derVV[I[k], I[k]] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v) } // Boundary condition for Vmax. Only the LS submatrix is non-zero I = BDU.Find(VmaxB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = Si[I[k]]; } // Boundary condition for Vmin // First row ds = Si[1] - Si[0]; derS[0, 0] = -1.5 / ds * Si[0]; // U(s,v) derS[0, 1] = 2.0 / ds * Si[0]; // U(s+1,v) derS[0, 2] = -1.0 / ds * Si[0]; // U(s+2,v) dv = Vi[2 * NS] - Vi[NS]; derV1[0, 0] = -1.5 / dv; // U(s,v) derV1[0, NS] = 2.0 / dv; // U(s,v+1) derV1[0, 2 * NS] = -1.0 / dv; // U(s,v+2) // Last row ds = Si[N - 2] - Si[N - 3]; derS[N - 2, N - 4] = -0.5 / ds * Si[N - 2]; // U(s-2,v) derS[N - 2, N - 3] = -2.0 / ds * Si[N - 2]; // U(s-1,v) derS[N - 2, N - 2] = 1.5 / ds * Si[N - 2]; // U(s,v) dv = Vi[2 * NS] - Vi[NS]; derV1[NS - 2, NS - 2 + 2 * NS] = -0.5 / dv * Vi[NS - 2]; // U(s,v+2) derV1[NS - 2, NS - 2 + NS] = 2.0 / dv * Vi[NS - 2]; // U(s,v+1) derV1[NS - 2, NS - 2] = -1.5 / dv * Vi[NS - 2]; // U(s,v) // Other rows for (int i = 1; i <= NS - 3; i++) { ds = Si[i] - Si[i - 1]; derS[i, i - 1] = -0.5 / ds * Si[i]; // U(s-1,v) derS[i, i] = 0.0; // U(s,v) derS[i, i + 1] = 0.5 / ds * Si[i]; // U(s+1,v) dv = Vi[2 * NS] - Vi[NS]; derV1[i, i] = -1.5 / dv; // U(s,v) derV1[i, i + NS] = 2.0 / dv; // U(s,v+1) derV1[i, i + 2 * NS] = -1.0 / dv; // U(s,v+2) } // Output the sub-matrices LMatrices LMat; LMat.derS = derS; LMat.derSS = derSS; LMat.derV1 = derV1; LMat.derV2 = derV2; LMat.derVV = derVV; LMat.derSV = derSV; LMat.R = R; return(LMat); }
public LMatrices BuildDerivatives(double[] S, double[] V, double[] T) { // Build the first- and second-order derivatives for the "L" operator matrix // for the Weighted method // INPUTS // S = vector for uniform stock price grid // V = vector for uniform volatility grid // T = vector for uniform maturity grid // thet = parameter for the weighted scheme // OUTPUTS // Matrices of dimnension N x N (N=NS+NV) // derS = Matrix for first-order derivative dU/dS // derSS = Matrix for second-order derivative dU2/dS2 // derV1 = Matrix for first-order derivative dU/dV, kappa*theta portion // derV2 = Matrix for first-order derivative dU/dV, -kappa*V portion // derVV = Matrix for first-order derivative dU2/dV2 // derSV = Matrix for first-order derivative dU2/dSdV // R = Matrix for r*S(v,t) portion of the PDE Interpolation IP = new Interpolation(); // Length of stock price, volatility, and maturity int NS = S.Length; int NV = V.Length; int NT = T.Length; double Smin = S[0]; double Smax = S[NS - 1]; double Vmin = V[0]; double Vmax = V[NV - 1]; double Tmin = T[0]; double Tmax = T[NT - 1]; // Increment for Stock Price, Volatility, and Maturity double ds = (Smax - Smin) / Convert.ToDouble(NS - 1); double dv = (Vmax - Vmin) / Convert.ToDouble(NV - 1); double dt = (Tmax - Tmin) / Convert.ToDouble(NT - 1); // Preliminary quantities // Size of the U(t) vector and L matrix int N = NS * NV; // The vectors for S and V, stacked double[] Si = new double[N]; double[] Vi = new double[N]; int k = 0; for (int v = 0; v <= NV - 1; v++) { for (int s = 0; s <= NS - 1; s++) { Si[k] = S[s]; Vi[k] = V[v]; k += 1; } } // Identification of the boundary points int[] VminB = new int[N]; int[] VmaxB = new int[N]; int[] SminB = new int[N]; int[] SmaxB = new int[N]; // Vmin and Vmax for (int v = 0; v <= NS - 2; v++) { VminB[v] = 1; } for (int v = N - NS + 1; v <= N - 2; v++) { VmaxB[v] = 1; } VmaxB[N - 1] = 1; // Smin and Smax k = 0; for (int v = 0; v <= NV - 1; v++) { for (int s = 0; s <= NS - 1; s++) { if (s == 0) { SminB[k] = 1; } else if (s == NS - 1) { SmaxB[k] = 1; } k += 1; } } SminB[0] = 0; SmaxB[NS - 1] = 0; SmaxB[N - 1] = 0; // Identification of the non-boundary points int[] NB = new int[N]; for (k = 0; k <= N - 1; k++) { if (SminB[k] == 0 & SmaxB[k] == 0 & VminB[k] == 0 & VmaxB[k] == 0) { NB[k] = 1; } } // Forward, backward and central differences for S int[] Cs = new int[N]; int[] Fs = new int[N]; int[] Bs = new int[N]; k = 0; for (int v = 0; v <= NV - 2; v++) { for (int s = 0; s <= NS - 1; s++) { if (s == 1) { Fs[k] = 1; } else if (s == NS - 2) { Bs[k] = 1; } else if (s >= 2 & s <= NS - 3) { Cs[k] = 1; } k += 1; } } Fs[1] = 0; Bs[NS - 2] = 0; for (k = 2; k <= NS - 3; k++) { Cs[k] = 0; } // Forward, backward and central differences for V int[] Cv = new int[N]; int[] Fv = new int[N]; int[] Bv = new int[N]; for (k = NS + 1; k <= 2 * NS - 2; k++) { Fv[k] = 1; } for (k = (NV - 2) * NS + 1; k <= (NV - 1) * NS - 2; k++) { Bv[k] = 1; } k = 0; for (int v = 0; v <= NV - 3; v++) { for (int s = 0; s <= NS - 1; s++) { if (s >= 1 & s <= NS - 2) { Cv[k] = 1; } k += 1; } } for (k = 0; k <= 2 * NS - 1; k++) { Cv[k] = 0; } // Central difference for SV-derivatives int[] Csv = new int[N]; k = 0; for (int v = 0; v <= NV - 2; v++) { for (int s = 0; s <= NS - 1; s++) { if (s >= 1 & s <= NS - 2) { Csv[k] = 1; } k += 1; } } for (k = 0; k <= NS - 1; k++) { Csv[k] = 0; } // Create the matrices for the derivatives double[,] derS = new double[N, N]; double[,] derSS = new double[N, N]; double[,] derV1 = new double[N, N]; double[,] derV2 = new double[N, N]; double[,] derVV = new double[N, N]; double[,] derSV = new double[N, N]; double[,] R = new double[N, N]; for (int i = 0; i <= N - 1; i++) { for (int j = 0; j <= N - 1; j++) { if (i == j) { R[i, j] = 1.0; } } } int M; int[] I; // Create the matrices for the derivatives // NON BOUNDARY POINTS ---------------------------------- I = IP.Find(Cs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Central differences derS[I[k], I[k] - 1] = -0.5 / ds * Si[I[k]]; // U(s-1,v) derS[I[k], I[k]] = 0.0; // U(s,v) derS[I[k], I[k] + 1] = 0.5 / ds * Si[I[k]]; // U(s+1,v) derSS[I[k], I[k] - 1] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-1,v) derSS[I[k], I[k]] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) derSS[I[k], I[k] + 1] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+1,v) } I = IP.Find(Fs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Forward differences derS[I[k], I[k]] = -1.5 / ds * Si[I[k]]; // U(s,v) derS[I[k], I[k] + 1] = 2.0 / ds * Si[I[k]]; // U(s+1,v) derS[I[k], I[k] + 2] = -1.0 / ds * Si[I[k]]; // U(s+2,v) derSS[I[k], I[k]] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) derSS[I[k], I[k] + 1] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+1,v) derSS[I[k], I[k] + 2] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s+2,v) } I = IP.Find(Bs); M = I.Length; for (k = 0; k <= M - 1; k++) { // Backward differences derS[I[k], I[k] - 2] = -0.5 / ds * Si[I[k]]; // U(s-2,v) derS[I[k], I[k] - 1] = -2.0 / ds * Si[I[k]]; // U(s-1,v) derS[I[k], I[k]] = 1.5 / ds * Si[I[k]]; // U(s,v) derSS[I[k], I[k] - 2] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-2,v) derSS[I[k], I[k] - 1] = -2.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s-1,v) derSS[I[k], I[k]] = 1.0 / ds / ds * Vi[I[k]] * Si[I[k]] * Si[I[k]]; // U(s,v) } // Create the matrix for V-derivatives I = IP.Find(Cv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Central differences derV1[I[k], I[k] - NS] = -0.5 / dv; // U(s,v-1) derV1[I[k], I[k]] = 0.0; // U(s,v) derV1[I[k], I[k] + NS] = 0.5 / dv; // U(s,v+1) derV2[I[k], I[k] - NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-1) derV2[I[k], I[k]] = 0.0; // U(s,v) derV2[I[k], I[k] + NS] = 0.5 / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] - NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k]] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k] + NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+1) } I = IP.Find(Fv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Forward differences derV1[I[k], I[k]] = -1.5 / dv; // U(s,v) derV1[I[k], I[k] + NS] = 2.0 / dv; // U(s,v+1) derV1[I[k], I[k] + 2 * NS] = -1.0 / dv; // U(s,v+2) derV2[I[k], I[k]] = -1.5 / dv * Vi[I[k]]; // U(s,v) derV2[I[k], I[k] + NS] = 2.0 / dv * Vi[I[k]]; // U(s,v+1) derV2[I[k], I[k] + 2 * NS] = -1.0 / dv * Vi[I[k]]; // U(s,v+2) derVV[I[k], I[k]] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k] + NS] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] + 2 * NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+2) } I = IP.Find(Bv); M = I.Length; for (k = 0; k <= M - 1; k++) { // Backward differences derV1[I[k], I[k] - 2 * NS] = -0.5 / dv; // U(s,v-2) derV1[I[k], I[k] - NS] = -2.0 / dv; // U(s,v-1) derV1[I[k], I[k]] = 1.5 / dv; // U(s,v) derV2[I[k], I[k] - 2 * NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-2) derV2[I[k], I[k] - NS] = -2.0 / dv * Vi[I[k]]; // U(s,v-1) derV2[I[k], I[k]] = 1.5 / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k] - 2 * NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-2) derVV[I[k], I[k] - NS] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k]] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v) } // Create the matrix for SV-derivatives I = IP.Find(Csv); M = I.Length; for (k = 0; k <= M - 1; k++) { derSV[I[k], I[k] + NS + 1] = 1.0 / (4.0 * ds * dv) * Vi[I[k]] * Si[I[k]]; // U(s+1,v+1) derSV[I[k], I[k] + NS - 1] = -1.0 / (4.0 * ds * dv) * Vi[I[k]] * Si[I[k]]; // U(s-1,v+1) derSV[I[k], I[k] - NS - 1] = 1.0 / (4.0 * ds * dv) * Vi[I[k]] * Si[I[k]]; // U(s-1,v-1) derSV[I[k], I[k] - NS + 1] = -1.0 / (4.0 * ds * dv) * Vi[I[k]] * Si[I[k]]; // U(s+1,v-1) } // BOUNDARY POINTS ---------------------------------- // Boundary for Smin I = IP.Find(SminB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = 0.0; derSS[I[k], I[k]] = 0.0; derV1[I[k], I[k]] = 0.0; derV2[I[k], I[k]] = 0.0; derVV[I[k], I[k]] = 0.0; derSV[I[k], I[k]] = 0.0; R[I[k], I[k]] = 0.0; } // Boundary condition for Smax I = IP.Find(SmaxB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = Si[I[k]]; derSS[I[k], I[k]] = 0.0; derSV[I[k], I[k]] = 0.0; // Central difference derV1[I[k], I[k] - NS] = -0.5 / dv; // U(s,v-1) derV1[I[k], I[k]] = 0; // U(s,v) derV1[I[k], I[k] + NS] = 0.5 / dv; // U(s,v+1) derV2[I[k], I[k] - NS] = -0.5 / dv * Vi[I[k]]; // U(s,v-1) derV2[I[k], I[k]] = 0.0; // U(s,v) derV2[I[k], I[k] + NS] = 0.5 / dv * Vi[I[k]]; // U(s,v+1) derVV[I[k], I[k] - NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v-1) derVV[I[k], I[k]] = -2.0 / dv / dv * Vi[I[k]]; // U(s,v) derVV[I[k], I[k] + NS] = 1.0 / dv / dv * Vi[I[k]]; // U(s,v+1) } // Boundary condition for Vmax. Only the LS submatrix is non-zero. I = IP.Find(VmaxB); M = I.Length; for (k = 0; k <= M - 1; k++) { derS[I[k], I[k]] = Si[I[k]]; } // Boundary condition for Vmin // First row derS[0, 0] = -1.5 / ds * Si[0]; // U(s,v) derS[0, 1] = 2.0 / ds * Si[0]; // U(s+1,v) derS[0, 2] = -1.0 / ds * Si[0]; // U(s+2,v) derV1[0, 0] = -1.5 / dv; // U(s,v) derV1[0, NS] = 2.0 / dv; // U(s,v+1) derV1[0, 2 * NS] = -1.0 / dv; // U(s,v+2) // Last row derS[N - 2, N - 4] = -0.5 / ds * Si[N - 2]; // U(s-2,v) derS[N - 2, N - 3] = -2.0 / ds * Si[N - 2]; // U(s-1,v) derS[N - 2, N - 2] = 1.5 / ds * Si[N - 2]; // U(s,v) derV1[NS - 2, NS - 2 + 2 * NS] = -0.5 / dv * Vi[NS - 2]; // U(s,v+2) derV1[NS - 2, NS - 2 + NS] = 2.0 / dv * Vi[NS - 2]; // U(s,v+1) derV1[NS - 2, NS - 2] = -1.5 / dv * Vi[NS - 2]; // U(s,v) // Other rows for (int i = 1; i <= NS - 3; i++) { derS[i, i - 1] = -0.5 / ds * Si[i]; // U(s-1,v) derS[i, i] = 0.0; // U(s,v) derS[i, i + 1] = 0.5 / ds * Si[i]; // U(s+1,v) derV1[i, i] = -1.5 / dv; // U(s,v) derV1[i, i + NS] = 2.0 / dv; // U(s,v+1) derV1[i, i + 2 * NS] = -1.0 / dv; // U(s,v+2) } // Output the sub-matrices LMatrices LMat; LMat.derS = derS; LMat.derSS = derSS; LMat.derV1 = derV1; LMat.derV2 = derV2; LMat.derVV = derVV; LMat.derSV = derSV; LMat.R = R; return(LMat); }