void nilss_solve(const std::vector<MatrixXd>& R, const std::vector<MatrixXd>& D, const std::vector<VectorXd>& b, const std::vector<VectorXd>& c, std::vector<VectorXd>& a) { int n = R.size(); assert(D.size() == n + 1); assert(b.size() == n); assert(c.size() == n + 1); std::unique_ptr<MatrixXd> kkt = assemble_kkt(R, D); std::unique_ptr<VectorXd> rhs = assemble_rhs(b, c); typedef SparseMatrix<double> SpMat; SpMat A(kkt->sparseView()); SparseLU<SparseMatrix<double>> solver; solver.analyzePattern(A); solver.factorize(A); VectorXd sol = solver.solve(*rhs); //VectorXd sol = kkt->partialPivLu().solve(*rhs); assert(sol.size() % (2 * n + 1) == 0); int m = sol.size() / (2 * n + 1); a.empty(); a.reserve(n + 1); for (int i = 0; i <= n; ++ i) { a.push_back(sol.segment(i * m, m)); } }
// Solve the stokes equation // F -> U X P void ProblemStructure::solveStokes() { Map<VectorXd> stokesSolnVector (geometry.getStokesData(), M * (N - 1) + (M - 1) * N + M * N); #ifndef USE_DENSE static SparseMatrix<double> stokesMatrix (3 * M * N - M - N, 3 * M * N - M - N); static SparseMatrix<double> forcingMatrix (3 * M * N - M - N, 2 * M * N - M - N); static SparseMatrix<double> boundaryMatrix (3 * M * N - M - N, 2 * M + 2 * N); static SparseLU<SparseMatrix<double>, COLAMDOrdering<int> > solver; #else /* Don't use this unless you hate your computer. */ static MatrixXd stokesMatrix (3 * M * N - M - N, 3 * M * N - M - N); static MatrixXd forcingMatrix (3 * M * N - M - N, 2 * M * N - M - N); static MatrixXd boundaryMatrix (3 * M * N - M - N, 2 * M + 2 * N); static PartialPivLU<MatrixXd> solver; #endif static bool initialized; double * viscosityData = geometry.getViscosityData(); if (!(initialized) || !(viscosityModel=="constant")) { #ifndef USE_DENSE SparseForms::makeStokesMatrix (stokesMatrix, M, N, h, viscosityData); stokesMatrix.makeCompressed(); SparseForms::makeForcingMatrix (forcingMatrix, M, N); forcingMatrix.makeCompressed(); SparseForms::makeBoundaryMatrix (boundaryMatrix, M, N, h, viscosityData); boundaryMatrix.makeCompressed(); solver.analyzePattern (stokesMatrix); solver.factorize (stokesMatrix); #else DenseForms::makeStokesMatrix (stokesMatrix, M, N, h, viscosityData); DenseForms::makeForcingMatrix (forcingMatrix, M, N); DenseForms::makeBoundaryMatrix (boundaryMatrix, M, N, h, viscosityData); solver.compute (stokesMatrix); #endif initialized = true; } stokesSolnVector = solver.solve (forcingMatrix * Map<VectorXd>(geometry.getForcingData(), 2 * M * N - M - N) + boundaryMatrix * Map<VectorXd>(geometry.getVelocityBoundaryData(), 2 * M + 2 * N)); Map<VectorXd> pressureVector (geometry.getPressureData(), M * N); double pressureMean = pressureVector.sum() / (M * N); pressureVector -= VectorXd::Constant (M * N, pressureMean); #ifdef DEBUG cout << "<Calculated Stokes Equation Solutions>" << endl; cout << "<U Velocity Data>" << endl; cout << DataWindow<double> (geometry.getUVelocityData(), N - 1, M).displayMatrix() << endl; cout << "<V Velocity Data>" << endl; cout << DataWindow<double> (geometry.getVVelocityData(), N, M - 1).displayMatrix() << endl; cout << "<Pressure Data>" << endl; cout << DataWindow<double> (geometry.getPressureData(), N, M).displayMatrix() << endl << endl; #endif }
int main(){ //Dati double T=1; // Scadenza double K=90; // Strike price double H=110; // Barriera up double S0=95; // Spot price double r=0.0367; // Tasso risk free // Parametri della parte continua double sigma=0.120381; // Volatilità // Parametri della parte salto double p=0.20761; // Parametro 1 Kou double lambda=0.330966; // Parametro 2 Kou double lambda_piu=9.65997; // Parametro 3 Kou double lambda_meno=3.13868; // Parametro 4 Kou // Discretizzazione int N=10; // Spazio int M=10; // Tempo // Griglie double dt=T/M; double Smin=0.5*S0*exp((r-sigma*sigma/2)*T-6*sigma*sqrt(T)); // Troncamento di x=log(S/S0) double xmin=log(Smin/S0); double xmax=log(H/S0); //x=linspace(xmin,xmax,N+1); double dx=(xmax-xmin)/N; VectorXd x(N+1); for (int i=0; i<N+1; ++i) { x(i)=xmin+i*dx; } double alpha, lambda2, Bmin, Bmax; integrale_Levy(alpha, lambda2, Bmin, Bmax, p, lambda, lambda_piu, lambda_meno, xmin, xmax, 2*N); cout<<"lambda "<<lambda<<" lambda2 "<<lambda2<<"\n"; SpMatrix M1(N-1,N-1); SpMatrix M2(N-1,N-1); SpMatrix FF(N-1,N-1); buildMatrix(M1, M2, FF, sigma, r, lambda2, alpha, N, dx, dt); VectorXd u(x.size()-2); for (int i=0; i<u.size(); ++i) { u(i)=payoff(x(i+1), K, S0); } double BC1_0=M1.coeffRef(1,0); double BC1_N=M1.coeffRef(0,1); double BC2_0=M2.coeffRef(1,0); double BC2_N=M2.coeffRef(0,1); for (int j=M-1; j>=0; --j) { cout<<j<<"\n"; // rhs VectorXd J(N-1); VectorXd z(u.size()+2); z(0)=(K-S0*exp(xmin))*exp(r*(T-(j+1)*dt)); for (int i=1; i<u.size(); ++i) { z(i)=u(i-1); } z(z.size()-1)=0; integrale2_Levy(J, Bmin, Bmax, x, z, N, K, S0, p, lambda, lambda_piu, lambda_meno); VectorXd rhs(N-1); rhs=FF*J; rhs(0)+=-BC1_0*(K-S0*exp(xmin))*exp(r*(T-(j-2)*dt))+BC2_0*(K-S0*exp(xmin))*exp(r*(T-(j-1)*dt)); // Solver SparseLU<SpMatrix> solver; M1.makeCompressed(); solver.analyzePattern(M1); solver.factorize(M1); u=solver.solve(M2*u+rhs); } VectorXd sol(u.size()+2); sol(0)=(K-S0*exp(xmin))*exp(r*T); for (int i=0; i<u.size(); ++i) { sol(i+1)=u(i); } sol(sol.size()-1)=0; VectorXd S(x.size()); VectorXd Put(sol.size()); for (int i=0; i<x.size(); ++i) { S(i)=S0*exp(x(i)); Put(i)=sol(i)*exp(-r*T); } double x_array[S.size()]; double u_array[Put.size()]; for (int i=0; i<x.size(); ++i) { x_array[i]=S(i); u_array[i]=Put(i); } gsl_interp_accel *my_accel_ptr = gsl_interp_accel_alloc (); gsl_spline *my_spline_ptr = gsl_spline_alloc (gsl_interp_cspline, x.size()); gsl_spline_init (my_spline_ptr, x_array, u_array, x.size()); double Prezzo=gsl_spline_eval(my_spline_ptr, S0 , my_accel_ptr); gsl_spline_free(my_spline_ptr); gsl_interp_accel_free(my_accel_ptr); cout<<"Prezzo="<<setprecision(8)<<Prezzo<<"\n"; return 0; }