Ejemplo n.º 1
0
/*
 * interpolate the solutions found in r2 onto those found in r1
*/
void interp( int r1, int r2)
{
    register int ie1, ie2;
    register int i,j, in, fnd;
    int *done;
    struct tms before, after;

    times(&before);

    /*initialize the done array*/
    done = salloc( int, nn );
    for(ie1 = 0; ie1 < nn; ie1++) done[ie1] = FALSE;

    /*
     This has to be done in a somewhat cludgey fashion,
     because the region structure has not been built yet for r1
    */

    /*step over all the elements in the first region*/
    ie1 = 0;
    while( done_tri(ie1) ) {

	/*if this triangle is in the region*/
	if ( reg_tri(ie1) == r1 ) {
	    for(i = 0; i < num_vert(ie1); i++) {
		in = vert_tri(ie1, i);
		if ( done[in] ) continue;

		/*now look in the second region for triangles...*/
		done[in] = TRUE;

		fnd = FALSE;
		for(j = 0; !fnd && j < num_tri_reg(r2); j++) {
		    ie2 = tri_reg(r2,j);

		    if ( pt_in_tri(cord_arr(pt_nd(in)), ie2 ) ) {
			fnd = TRUE;

			if ( mode == TWOD ) {
			    interp_2d(in, ie2);
			}
			else if (mode == ONED) {
			    interp_1d(in, ie2);
			}
		    }
		}
		if ( !fnd ) panic("node not in any triangle");
	    }
	}
	next_tri(ie1);
    }
    free(done);
    times(&after);
    print_time("total interpolation time", &before, &after);
}
Ejemplo n.º 2
0
Interpolator_D2 test_Heston_PDE_solution(int CONFIG_sizeDiscretization_y)
{	
	std::cout << "Model and Product Direction_Parameters" << std::endl;

	//! Heston Direction_Parameters
	double kappa = Heston_params_kappa;
	double theta = Heston_params_theta;
	double sigma = Heston_params_sigma;
	double rho   = Heston_params_rho;
	double r     = Heston_params_r;

	//! Product Direction_Parameters
	double K = Option_params_K;
	double T = Option_params_T; 

	//! FD param
	double S_max = CONFIG_S_max;  // S_max = 2*K is not efficient! 
	double v_max = CONFIG_v_max;

	//! resume: the biggest error is the time! 
	int sizeDiscretization_t = CONFIG_sizeDiscretization_t + 1;  
	int sizeDiscretization_x = CONFIG_sizeDiscretization_x + 1; 
	int sizeDiscretization_y = CONFIG_sizeDiscretization_y + 1;

 //   //! ma model
	//MaModel ma_model(Ma_params_alpha,Ma_params_sigma,Ma_params_rho);
	//Ma_Model_discret ma_model_discret(ma_model);

	//! Range and discretization
	Range range_t(0.0,  T);        
	Range range_x(0.0,  S_max);   
	Range range_y(0.0,  v_max);  


	//! non-uniform 
		//! direction t
	int t_discretization_size = 1;
	std::vector<bool>   if_nonuniform_t(t_discretization_size);//              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    std::vector<bool>   if_shift_t(t_discretization_size); //                  = OPTIMIZATION_if_shfit_grid_x;
	std::vector<double> t_nonuniform_center_c(t_discretization_size);//        = K; 
	std::vector<double> t_nonuniform_scale_param_c(t_discretization_size);//   = K/5.0; 
	std::vector<double> t_shifting_center(t_discretization_size); //            = K;

	if_nonuniform_t[0]              = OPTIMIZATION_if_nonuniform_sinh_grid_t;
    if_shift_t[0]                   = OPTIMIZATION_if_shfit_grid_t;
	t_nonuniform_center_c[0]        = 0.0; 
	t_nonuniform_scale_param_c[0]   = OPTIMIZATION_nonuniform_t_sinh_scale_param; //1.0/500.0; 
	t_shifting_center[0]            = -999999.9;

	if(if_fwd_PDE == true)
	{
		////! add second time
  //     	if_nonuniform_t.push_back(false);             //           = true;//OPTIMIZATION_if_nonuniform_sinh_grid_t;
		//if_shift_t.push_back(false)    ;              // = OPTIMIZATION_if_shfit_grid_t;
		//t_nonuniform_center_c.push_back(0.0);		  //        = 0.0; 
		//t_nonuniform_scale_param_c.push_back(1.0/50); //   = 1.0/25.0; 
		//t_shifting_center.push_back(-99999.9);        //            = -999999.9;
	}

		//! direction x
	int x_discretization_size = 1;
	std::vector<bool>   if_nonuniform_x(x_discretization_size);//              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    std::vector<bool>   if_shift_x(x_discretization_size); //                  = OPTIMIZATION_if_shfit_grid_x;
	std::vector<double> x_nonuniform_center_c(x_discretization_size);//        = K; 
	std::vector<double> x_nonuniform_scale_param_c(x_discretization_size);//   = K/5.0; 
	std::vector<double> x_shifting_center(x_discretization_size); //            = K;

	if_nonuniform_x[0]              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    if_shift_x[0]                   = OPTIMIZATION_if_shfit_grid_x;
	x_nonuniform_center_c[0]        = K; 
	x_nonuniform_scale_param_c[0]   = K/5.0; 
	x_shifting_center[0]            = K;

	if(if_fwd_PDE == true)
	{
		x_nonuniform_center_c[0]      = fwd_PDE_S0; 
		x_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_x_sinh_scale_param; 
		x_shifting_center[0]          = fwd_PDE_S0;
	}

		//! direction y
	int y_discretization_size = 1;
	std::vector<bool>   if_nonuniform_y(y_discretization_size);		    
    std::vector<bool>   if_shift_y(y_discretization_size);				
	std::vector<double> y_nonuniform_center_c(y_discretization_size);   
	std::vector<double> y_nonuniform_scale_param_c(y_discretization_size); 
	std::vector<double> y_shifting_center(y_discretization_size);          

	if_nonuniform_y[0]		      = OPTIMIZATION_if_nonuniform_sinh_grid_y;
    if_shift_y[0]				  = OPTIMIZATION_if_shfit_grid_y; //! for Fwd PDE
	y_nonuniform_center_c[0]      = 0.0;     
	y_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_y_sinh_scale_param;  // V_max/500 is the experienced choice! 
	y_shifting_center[0]          = -99999.9;

	if(if_fwd_PDE == true)
	{
		//! first dimension: 
		if_nonuniform_y[0]			  = OPTIMIZATION_if_nonuniform_sinh_grid_y; // OPTIMIZATION_if_nonuniform_sinh_grid_y;
		if_shift_y[0]				  = OPTIMIZATION_if_shfit_grid_y; // OPTIMIZATION_if_shfit_grid_y; //! for Fwd PDE
		y_nonuniform_center_c[0]      = 0.0;//Heston_params_theta;     
		y_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_y_sinh_scale_param; // OPTIMIZATION_nonuniform_y_sinh_scale_param; //1.0/10000.0;  // V_max/500 is the experienced choice! 
		y_shifting_center[0]          = fwd_PDE_v0;

		////! second dimension:
		//if_nonuniform_y.push_back(false);
		//if_shift_y.push_back(true);					                  
		//y_nonuniform_center_c.push_back(fwd_PDE_v0);			      
		//y_nonuniform_scale_param_c.push_back(1.0/*OPTIMIZATION_nonuniform_y_sinh_scale_param*/);
		//y_shifting_center.push_back(fwd_PDE_v0); 

		////! third
		//if_nonuniform_y.push_back(false);
		//if_shift_y.push_back(true);					                  
		//y_nonuniform_center_c.push_back(Heston_params_theta);			      
		//y_nonuniform_scale_param_c.push_back(1.0/5000.0);
		//y_shifting_center.push_back(fwd_PDE_v0);
	}

	Discretization discret( range_t, sizeDiscretization_t,  
							range_x, sizeDiscretization_x,  
							range_y, sizeDiscretization_y,
							if_nonuniform_t,  t_nonuniform_center_c,  t_nonuniform_scale_param_c,
							if_shift_t,    t_shifting_center,
							if_nonuniform_x,  x_nonuniform_center_c,  x_nonuniform_scale_param_c,
							if_shift_x,    x_shifting_center,
							if_nonuniform_y,  y_nonuniform_center_c,  y_nonuniform_scale_param_c,
							if_shift_y,    y_shifting_center);  


	//! Heston Model
	HestonModel model(r,sigma,kappa,theta,rho);
	//Heston_Model_discret heston_model_discret(model);
	//! Heston discret Model
	PDE_Model_Heston heston_model_discret(model,discret);


    //! Term Structure, Payoff 	&&  Boundary Condition
	//! Don't want to use this one, it will make error in the code ! 
	//! Because Heston model calls directly r() of Heston model :) 
	Term_Structure* cts  = NULL; //new Const_Term_Structure(-999999);  
	PayoffYuan* payoff   = new Put(K);

	//! Backward PDE
	//BoundaryCondition_Heston_Put bc(cts, payoff, model, discret);
	//! Forward PDE
	BoundaryCondition_D2_density_CONSTPTR bc (new BoundaryCondition_D2_density (model, discret,fwd_PDE_S0,fwd_PDE_v0, cts, payoff ));

	//! --------------------------------------------------
	//! 
    //!           Test PDE solver 
	//! 
	//! ---------------------------------------------------
	//! new Scheme class 
	Scheme_ADI* scheme_new_ptr = NULL;
	if(scheme_type ==1)
	{
		scheme_new_ptr= new Scheme_Yanenko(
			discret,
			heston_model_discret,
			bc
			);
	}
	else if(scheme_type ==2)
	{
		scheme_new_ptr = new Scheme_Douglas(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta
			);
	}
	else if (scheme_type == 3)
	{
		scheme_new_ptr = new Scheme_CS(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta,
			scheme_douglas_lambda
			);
	}
	else if(scheme_type == 4)
	{
		scheme_new_ptr = new Scheme_MCS(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta,
			scheme_douglas_lambda
			);
	}
	else if(scheme_type == 5)
	{
		scheme_new_ptr = new Scheme_HV(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta
			);
	}
	else
	{
	    throw ("Error in Test_PDE.cpp, scheme_type  does not take valid value");
	}

	PDE_ADI_Solver   pde_solver(*scheme_new_ptr);

	//! --------------------------------------------------
	//! 
    //!           Test PDE solver extrapolation
	//! 
	//! ---------------------------------------------------
	//PDE_ADI_Extrapolation_Solver pde_extrapolation_solver( scheme_type,
	//													   discret,
	//													   heston_model_discret,
	//													   // --- For constructing: stupid bc (Bad Bad design !!!)
	//													   cts, 
	//													   payoff,
	//													   model,
	//													   // ----
	//													   scheme_douglas_theta, 
	//													   scheme_douglas_lambda);

	clock_t t1 = clock();
	//if(DEBUG_test_PDE_solver_extrapolation == true)
	//{
	//	pde_extrapolation_solver.solve_PDE();
	//}
	//else
	{
 		pde_solver.solve_PDE();	
	}
	clock_t t2 = clock();
	cout << "time = " << (double)(t2-t1)/CLOCKS_PER_SEC << " seconds"<< endl;

	////! Fwd PDE
	////! find initial dirac point
	//int dirac_x_index = -1;
	//int dirac_y_index = -1;
	//vector<double> discret_x_tilde = discret.get_discret_x_tilde();
	//vector<double> discret_y_tilde = discret.get_discret_y_tilde();
	//for(unsigned int i=0; i<discret_x_tilde.size(); ++i)
	//{
	//	double x = discret_x_tilde[i];
	//	if(fabs(x-fwd_PDE_S0)<0.000000001)
	//	{
	//		dirac_x_index = i;  
	//		break;
	//	}
	//}
	//for(unsigned int j=0; j<discret_y_tilde.size(); ++j)
	//{
	//	double y = discret_y_tilde[j];
 //       if(fabs(y-fwd_PDE_v0)<0.000000001)
	//	{
	//		dirac_y_index = j;
	//		break;
	//	}
	//}

	//
	//double inital_proba = 1.0/4
	//	                  *( discret.get_delta_x(dirac_x_index)+discret.get_delta_x(dirac_x_index+1) )
	//					  *( discret.get_delta_y(dirac_y_index)+discret.get_delta_y(dirac_y_index+1) );
	//cout << "inital_proba  = " << inital_proba  << endl;

	double inital_proba = 1.0;

	//! check sum of probability:
	Matrix Fwd_PDE_result (pde_solver.get_result());
	Fwd_PDE_result /= inital_proba;

	double sum_proba          = 0.0;
	double sum_proba_positive = 0.0;
	double sum_proba_negative = 0.0;
	for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
	{
		int index_i = i+1;
		for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
		{
			int index_j = j+1;
            double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
			double coeff   = 1.0/4
		                    *( discret.get_delta_x(i)+discret.get_delta_x(i+1) )
						    *( discret.get_delta_y(j)+discret.get_delta_y(j+1) );

			double proba   = coeff*density;  
			if(density>0.0)
			{
				sum_proba_positive += coeff*density;  
			}
			else
			{
			   sum_proba_negative  += coeff*density;  
			}
		}
	}
	sum_proba = sum_proba_positive + sum_proba_negative;
	cout << " ---- |||| ---- |||| Sum_Proba          = " << sum_proba << endl;  //<< ",  sum_proba_positive = " << sum_proba_positive << " + " << "sum_proba_negative = " << sum_proba_negative << endl;
	cout << " ---- |||| ---- |||| Sum_Proba_positive = " << sum_proba_positive << endl;
	cout << " ---- |||| ---- |||| Sum_Proba_negative = " << sum_proba_negative << endl;
	cout << " ---- |||| ---- |||| Sum_total_error    = " << fabs(sum_proba_positive - 1) + fabs(sum_proba_negative) << endl;


	//! analytical price
	int num_K = 17;
	double step = 0.05;
	//double K_start = Option_params_K*(num_K-1)/

	vector<double> v_K(num_K);
	vector<double> v_analytical_price(num_K);

	cout << "strike vector: "<< endl;
	cout << Option_params_K << endl;
	v_K[0] = Option_params_K;
	for(unsigned int i=1; i<v_K.size()-1; i+=2)
	{
		v_K[i]   =  Option_params_K *(1+i*step);
		v_K[i+1] =  Option_params_K *(1-i*step);
		cout << v_K[i] << endl;
		cout << v_K[i+1] << endl;
	}

	for(unsigned int i=0; i<v_K.size(); ++i)
	{
		Heston_analytical_pricer pricer_ana(v_K[i]);
		v_analytical_price[i] = pricer_ana.heston_put(fwd_PDE_S0,fwd_PDE_v0, 1024*10);

	}

	vector<double> v_numerical_price(num_K);
	//! first numerical integration price
	for(unsigned int kk=0; kk<v_K.size()-1; ++kk)
	{
		    double KK = v_K[kk];
			double sum_price          = 0.0;
			double sum_price_positive = 0.0;
			double sum_price_negative = 0.0;
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				double x = discret.get_discret_x(index_i);
				if(x<KK)
					payoff = KK - x;
				else
					payoff = 0.0;

				for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					int index_j = j+1;
					double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
					double coeff   = 1.0/4
									*( discret.get_delta_x(i)+discret.get_delta_x(i+1) )
									*( discret.get_delta_y(j)+discret.get_delta_y(j+1) );

					double proba   = coeff*density;  
					if(density>0.0)
					{
						sum_price_positive += coeff*density*payoff;  
					}
					else
					{
					   sum_price_negative  += coeff*density*payoff;  
					}
				}
			}
			sum_price_positive *= exp(-Option_params_T*Heston_params_r);
			sum_price_negative *= exp(-Option_params_T*Heston_params_r);
			sum_price = sum_price_positive + sum_price_negative;
			v_numerical_price[kk] = sum_price;
			cout << "1st numerical price = " << sum_price << endl;
			//cout << "price_numerical_positive  = " << sum_price_positive << endl;
			//cout << "price_numerical_negative  = " << sum_price_negative << endl;


			//!second numerical integration price
			vector<double> x_grid(discret.get_discret_x_tilde());
			vector<double> y_grid(discret.get_discret_y_tilde());

			vector<double> x_value(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> y_value(discret.get_sizeDiscret_y_tilde(),0.0);

			for(int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				//double x = discret.get_discret_x(index_i);
				//if(x<KK)
				//	payoff = KK - x;
				//else
				//	payoff = 0.0;

				for(int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					 int index_j = j+1;
					 y_value[j] = Fwd_PDE_result[index_i][index_j];
				}
				Interpolator interp_y(y_grid,y_value);
				x_value[i] = interp_y.calculate_integral_approximation()*payoff;
			}
			Interpolator interp_x(x_grid,x_value);
			double second_analytical_price = interp_x.calculate_integral_approximation();
			//second_analytical_price *= exp(-Option_params_T*Heston_params_r);
			cout << "2nd numerical price = " << second_analytical_price << endl;
			

			//! third numerical integration price
			double third_sum_price          = 0.0;
			vector<double> v_sum_x(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> v_sum_x_positive(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> v_sum_x_negative(discret.get_sizeDiscret_x_tilde(),0.0);
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				//double x = discret.get_discret_x(index_i);
				//if(x<KK)
				//	payoff = KK - x;
				//else
				//	payoff = 0.0;
				double sum_x          = 0.0;
				double sum_x_positive = 0.0;
				double sum_x_negative = 0.0;
				for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					int index_j = j+1;
					double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
					double coeff   = ( discret.get_delta_y(j)+discret.get_delta_y(j+1) )/2;

					double proba   = coeff*density;  
					if(density>0.0)
					{
						sum_x_positive += coeff*density*payoff;  
					}
					else
					{
					   sum_x_negative  += coeff*density*payoff;  
					}
					sum_x = sum_x_positive + sum_x_negative;
				}
				v_sum_x_positive[i] = sum_x_positive;
				v_sum_x_negative[i] = sum_x_negative;
				v_sum_x[i]          = sum_x;
			}

			double hehe = 0.0;
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				double interval = ( discret.get_delta_x(i)+discret.get_delta_x(i+1) )/2.0;
				hehe += v_sum_x[i]*interval;
			}
			cout << "3rd numerical price = " << hehe << endl;
	}
	Interpolator_D2 interp_2d(discret.get_discret_x(), discret.get_discret_y(), Fwd_PDE_result);

			////sum_price_positive *= exp(-Option_params_T*Heston_params_r);
			////sum_price_negative *= exp(-Option_params_T*Heston_params_r);
			//sum_price = sum_price_positive + sum_price_negative;
			//cout << "price_numerical  = " << sum_price << endl;
			//cout << "price_numerical_positive  = " << sum_price_positive << endl;
			//cout << "price_numerical_negative  = " << sum_price_negative << endl;
	


	//! Print one price
	if(DEBUG_PDE_error_print_to_screen == true)
	{
		cout.precision(15); 

		int S_index = 25;
		int v_index = 10;

		double S_check = discret.get_discret_x(S_index);
		double v_check = discret.get_discret_y(v_index);

		//Matrix PDE_result       = pde_solver.get_result();
		Matrix PDE_result(1,1,0);
		//if(DEBUG_test_PDE_solver_extrapolation == true)
		//{
		//	PDE_result = pde_extrapolation_solver.get_result();
		//}
		//else
		{
		    PDE_result = pde_solver.get_result();
		}

		Heston_analytical_pricer analytical_pricer;
		vector<double> discret_x;
		discret_x.push_back(S_check);
		
		cout << "PDE's price for So=" << S_check << ", v=" << v_check <<  "   =   " << PDE_result[S_index][v_index] << endl;

		vector<double> discret_y;
		discret_y.push_back(v_check);
		Matrix analytical_price = analytical_pricer.heston_put_v(discret_x,discret_y, 1024*100);
		cout.precision(15); 
		cout << "analytical formula's price = " << analytical_price[0][0]<< endl;
	}

	if (DEBUG_PDE_error_print_to_file == true)
	{
		std::stringstream ss;
		ss << CONFIG_sizeDiscretization_y;
		string s = ss.str();
		std::string PDE_error_output_file_name = DEBUG_output_path + s + "PDE_error.csv";

		//! get PDE result
		//Matrix PDE_result       = pde_solver.get_result();
		//Matrix PDE_result(1,1,0);
		//if(DEBUG_test_PDE_solver_extrapolation == true)
		//{
		//	PDE_result = pde_extrapolation_solver.get_result();
		//}
		//else
		//{
		//    PDE_result = pde_solver.get_result();
		//}

		Matrix PDE_result = Fwd_PDE_result;

		//! get analytical result 
		Heston_analytical_pricer analytical_pricer;

		vector<double> discret_x(discret.get_discret_x());
		vector<double> discret_y(discret.get_discret_y());

		//! Backward PDE
		//double Error_S_min = 0.5 * Option_params_K;
		//double Error_S_max = 1.5 * Option_params_K;
		//double Error_v_min = 0;
		//double Error_v_max = 1.0;

		//! Fwd PDE
		double Error_S_min = 0;
		double Error_S_max = S_max; // 1.5 * Option_params_K;
		double Error_v_min = 0;
		double Error_v_max = v_max; //1.0;


		vector<double> x_vector_value;  //! For analytical price
		vector<int>    x_vector_index;  
		vector<double> y_vector_value;  //! For PDE price (index) 
		vector<int>    y_vector_index;   

		for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
		{
			double x = discret_x[i];
		    if(x>=Error_S_min-0.000000001 && x <= Error_S_max+0.000000001)
			{
				x_vector_value.push_back(x);
				x_vector_index.push_back(i);
			}
		}

		for(unsigned int i=0; i<discret_y.size(); ++i)
		{
			double y = discret_y[i];
		    if(y>=Error_v_min-0.000000001 && y <= Error_v_max+0.000000001)
			{
				y_vector_value.push_back(y);
				y_vector_index.push_back(i);
			}
		}
		
		Matrix analytical_price(1,1,0.0);
		if(DEBUG_PDE_test_PDE_vs_analytical == true)
		{
			analytical_price  = analytical_pricer.heston_put_v(x_vector_value,y_vector_value);
		}
		Matrix PDE_error((int)x_vector_value.size(), (int)y_vector_value.size(),-9999.0);  
		for(unsigned int i=0; i<x_vector_value.size(); ++i)
		{
			for(unsigned int j=0; j<y_vector_value.size(); ++j)
			{
			    if(DEBUG_PDE_test_PDE_vs_analytical == true)
				{
				    PDE_error[i][j] = PDE_result[x_vector_index[i]][y_vector_index[j]] - analytical_price [i][j];
				}
				else if (DEBUG_PDE_test_only_PDE == true)
				{
				    PDE_error[i][j] = PDE_result[i][j];
				}
			}
		}
		print_result(PDE_error_output_file_name , x_vector_value, y_vector_value, PDE_error);

		//! find max error
		if(DEBUG_PDE_test_PDE_vs_analytical == true)
		{
			double max_error_value   = 0.0;
			int    max_error_index_S = 0;
			int    max_error_index_v = 0;
			for(unsigned int i=0; i<x_vector_value.size(); ++i)
			{
				for(unsigned int j=0; j<y_vector_value.size(); ++j)
				{
					if(abs(PDE_error[i][j]) > abs(max_error_value))
					{
						max_error_value = PDE_error[i][j];
						max_error_index_S = i;
						max_error_index_v = j;
					}
				}
			}
			//!!!!! I donot know why but Error !!!!  -- Max error = 17
			cout << "---- ---- ---- ---- Max_error_value is at (" << x_vector_value[max_error_index_S]<< ","<< y_vector_value[max_error_index_v] << ")   = " <<  max_error_value  << endl;
		}
	}

	for(unsigned int i=0; i<v_K.size(); ++i)
	{
		cout << "v_K[" << i << "] = "<< v_K[i] << " 's price: " << v_analytical_price[i] << " ~ " << v_numerical_price[i] << endl;
	}

	delete cts;
	delete payoff;
	//delete scheme_ptr;
	delete scheme_new_ptr;

	return interp_2d;
}