#include"../kernel/Assemble_Base.h"
#include"../solver/Solver_Base.h"

#include<string>
#include <fstream>
#include <iostream>
#include <iomanip>

void OpticsFEM_2D_EigenMode::Test_OutputMatrix()
{
	if (_mIsReal)
	{
		std::ofstream outAi, outAj, outAv, outBi, outBj, outBv;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv.open("Av.txt", std::ios::out | std::ios::trunc);
		outBi.open("Bi.txt", std::ios::out | std::ios::trunc);
		outBj.open("Bj.txt", std::ios::out | std::ios::trunc);
		outBv.open("Bv.txt", std::ios::out | std::ios::trunc);
		outAi << std::fixed; outAj << std::fixed; outAv << std::scientific;
		outBi << std::fixed; outBj << std::fixed; outBv << std::scientific;

		Eigen::SparseMatrix<double> tempA = Eigen::SparseMatrix<double>(_mA_real);
		Eigen::SparseMatrix<double> tempB = Eigen::SparseMatrix<double>(_mB_real);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<double>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv << std::setprecision(12) << it.value() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv << std::endl;

		for (int k = 0; k < tempB.outerSize(); k++)
			for (Eigen::SparseMatrix<double>::InnerIterator it(tempB, k); it; ++it)
			{
				outBv << std::setprecision(12) << it.value() << " ";
				outBi << std::setprecision(12) << it.row() + 1 << " ";
				outBj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outBi << std::endl;
		outBj << std::endl;
		outBv << std::endl;

		outAi.close();
		outAj.close();
		outAv.close();
		outBi.close();
		outBj.close();
		outBv.close();
	}
	else
	{
		std::ofstream outAi, outAj, outAv_real, outAv_imag, outBi, outBj, outBv_real, outBv_imag, outPi, outPj, outPv_real, outPv_imag;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv_real.open("Av_real.txt", std::ios::out | std::ios::trunc);
		outAv_imag.open("Av_imag.txt", std::ios::out | std::ios::trunc);
		outBi.open("Bi.txt", std::ios::out | std::ios::trunc);
		outBj.open("Bj.txt", std::ios::out | std::ios::trunc);
		outBv_real.open("Bv_real.txt", std::ios::out | std::ios::trunc);
		outBv_imag.open("Bv_imag.txt", std::ios::out | std::ios::trunc);
		outPi.open("Pi.txt", std::ios::out | std::ios::trunc);
		outPj.open("Pj.txt", std::ios::out | std::ios::trunc);
		outPv_real.open("Pv_real.txt", std::ios::out | std::ios::trunc);
		outPv_imag.open("Pv_imag.txt", std::ios::out | std::ios::trunc);

		outAi << std::fixed; outAj << std::fixed; outAv_real << std::scientific;
		outBi << std::fixed; outBj << std::fixed; outBv_real << std::scientific;
		outPi << std::fixed; outPj << std::fixed; outPv_real << std::scientific;
		outAv_imag << std::scientific; outBv_imag << std::scientific; outPv_imag << std::scientific;

		Eigen::SparseMatrix<complex<double>> tempA = Eigen::SparseMatrix<complex<double>>(_mA_complex);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv_real << std::setprecision(12) << it.value().real() << " ";
				outAv_imag << std::setprecision(12) << it.value().imag() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv_real << std::endl;
		outAv_imag << std::endl;

		Eigen::SparseMatrix<complex<double>> tempB = Eigen::SparseMatrix<complex<double>>(_mB_complex);
		for (int k = 0; k < tempB.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempB, k); it; ++it)
			{
				outBv_real << std::setprecision(12) << it.value().real() << " ";
				outBv_imag << std::setprecision(12) << it.value().imag() << " ";
				outBi << std::setprecision(12) << it.row() + 1 << " ";
				outBj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outBi << std::endl;
		outBj << std::endl;
		outBv_real << std::endl;
		outBv_imag << std::endl;

		Eigen::SparseMatrix<complex<double>> tempP = Eigen::SparseMatrix<complex<double>>(_mP_complex);
		for (int k = 0; k < tempP.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempP, k); it; ++it)
			{
				outPv_real << std::setprecision(12) << it.value().real() << " ";
				outPv_imag << std::setprecision(12) << it.value().imag() << " ";
				outPi << std::setprecision(12) << it.row() + 1 << " ";
				outPj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outPi << std::endl;
		outPj << std::endl;
		outPv_real << std::endl;
		outPv_imag << std::endl;

		outAi.close();
		outAj.close();
		outAv_real.close();
		outAv_imag.close();
		outBi.close();
		outBj.close();
		outBv_real.close();
		outBv_imag.close();
		outPi.close();
		outPj.close();
		outPv_real.close();
		outPv_imag.close();
	}
}

void OpticsFEM_2D_EigenFreq::Test_OutputMatrix()
{
	if (_mIsReal)
	{
		std::ofstream outAi, outAj, outAv, outBi, outBj, outBv;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv.open("Av.txt", std::ios::out | std::ios::trunc);
		outBi.open("Bi.txt", std::ios::out | std::ios::trunc);
		outBj.open("Bj.txt", std::ios::out | std::ios::trunc);
		outBv.open("Bv.txt", std::ios::out | std::ios::trunc);
		outAi << std::fixed; outAj << std::fixed; outAv << std::scientific;
		outBi << std::fixed; outBj << std::fixed; outBv << std::scientific;

		Eigen::SparseMatrix<double> tempA = Eigen::SparseMatrix<double>(_mA_real);
		Eigen::SparseMatrix<double> tempB = Eigen::SparseMatrix<double>(_mB_real);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<double>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv << std::setprecision(12) << it.value() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv << std::endl;

		for (int k = 0; k < tempB.outerSize(); k++)
			for (Eigen::SparseMatrix<double>::InnerIterator it(tempB, k); it; ++it)
			{
				outBv << std::setprecision(12) << it.value() << " ";
				outBi << std::setprecision(12) << it.row() + 1 << " ";
				outBj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outBi << std::endl;
		outBj << std::endl;
		outBv << std::endl;

		outAi.close();
		outAj.close();
		outAv.close();
		outBi.close();
		outBj.close();
		outBv.close();
	}
	else
	{
		std::ofstream outAi, outAj, outAv_real, outAv_imag, outBi, outBj, outBv_real, outBv_imag, outPi, outPj, outPv_real, outPv_imag;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv_real.open("Av_real.txt", std::ios::out | std::ios::trunc);
		outAv_imag.open("Av_imag.txt", std::ios::out | std::ios::trunc);
		outBi.open("Bi.txt", std::ios::out | std::ios::trunc);
		outBj.open("Bj.txt", std::ios::out | std::ios::trunc);
		outBv_real.open("Bv_real.txt", std::ios::out | std::ios::trunc);
		outBv_imag.open("Bv_imag.txt", std::ios::out | std::ios::trunc);
		outPi.open("Pi.txt", std::ios::out | std::ios::trunc);
		outPj.open("Pj.txt", std::ios::out | std::ios::trunc);
		outPv_real.open("Pv_real.txt", std::ios::out | std::ios::trunc);
		outPv_imag.open("Pv_imag.txt", std::ios::out | std::ios::trunc);

		outAi << std::fixed; outAj << std::fixed; outAv_real << std::scientific;
		outBi << std::fixed; outBj << std::fixed; outBv_real << std::scientific;
		outPi << std::fixed; outPj << std::fixed; outPv_real << std::scientific;
		outAv_imag << std::scientific; outBv_imag << std::scientific; outPv_imag << std::scientific;

		Eigen::SparseMatrix<complex<double>> tempA = Eigen::SparseMatrix<complex<double>>(_mA_complex);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv_real << std::setprecision(12) << it.value().real() << " ";
				outAv_imag << std::setprecision(12) << it.value().imag() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv_real << std::endl;
		outAv_imag << std::endl;

		Eigen::SparseMatrix<complex<double>> tempB = Eigen::SparseMatrix<complex<double>>(_mB_complex);
		for (int k = 0; k < tempB.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempB, k); it; ++it)
			{
				outBv_real << std::setprecision(12) << it.value().real() << " ";
				outBv_imag << std::setprecision(12) << it.value().imag() << " ";
				outBi << std::setprecision(12) << it.row() + 1 << " ";
				outBj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outBi << std::endl;
		outBj << std::endl;
		outBv_real << std::endl;
		outBv_imag << std::endl;

		Eigen::SparseMatrix<complex<double>> tempP = Eigen::SparseMatrix<complex<double>>(_mP_complex);
		for (int k = 0; k < tempP.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempP, k); it; ++it)
			{
				outPv_real << std::setprecision(12) << it.value().real() << " ";
				outPv_imag << std::setprecision(12) << it.value().imag() << " ";
				outPi << std::setprecision(12) << it.row() + 1 << " ";
				outPj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outPi << std::endl;
		outPj << std::endl;
		outPv_real << std::endl;
		outPv_imag << std::endl;

		outAi.close();
		outAj.close();
		outAv_real.close();
		outAv_imag.close();
		outBi.close();
		outBj.close();
		outBv_real.close();
		outBv_imag.close();
		outPi.close();
		outPj.close();
		outPv_real.close();
		outPv_imag.close();
	}
}

void OpticsFEM_2D_Scatter::Test_OutputMatrix()
{
	if(_mIsReal)
	{
		std::ofstream outAi, outAj, outAv, outBv, outX;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv.open("Av.txt", std::ios::out | std::ios::trunc);
		outBv.open("Bv.txt", std::ios::out | std::ios::trunc);
		outX.open("X.txt", std::ios::out | std::ios::trunc);
		outAi << std::fixed; outAj << std::fixed; outAv << std::scientific; outBv << std::scientific; outX << std::scientific;

		Eigen::SparseMatrix<double> tempA = Eigen::SparseMatrix<double>(_mA_real);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<double>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv << std::setprecision(12) << it.value() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv << std::endl;

		for (int k = 0; k < _mB_real.rows(); k++)
		{
			outBv << std::setprecision(12) << _mB_real(k) << endl;
			outX << std::setprecision(12) << _mX(k).real() << endl;
		}
			
		outAi.close();
		outAj.close();
		outAv.close();
		outBv.close();
		outX.close();
	}
	else
	{
		std::ofstream outAi, outAj, outAv_real, outAv_imag, outBv_real, outBv_imag,outX_real,outX_imag;
		outAi.open("Ai.txt", std::ios::out | std::ios::trunc);
		outAj.open("Aj.txt", std::ios::out | std::ios::trunc);
		outAv_real.open("Av_real.txt", std::ios::out | std::ios::trunc);
		outAv_imag.open("Av_imag.txt", std::ios::out | std::ios::trunc);
		outBv_real.open("Bv_real.txt", std::ios::out | std::ios::trunc);
		outBv_imag.open("Bv_imag.txt", std::ios::out | std::ios::trunc);
		outX_real.open("X_real.txt", std::ios::out | std::ios::trunc);
		outX_imag.open("X_imag.txt", std::ios::out | std::ios::trunc);
		outAi << std::fixed; outAj << std::fixed; outAv_real << std::scientific; 
		outAv_imag << std::scientific; outBv_real << std::scientific; outBv_imag << std::scientific;
		outX_real << std::scientific; outX_imag << std::scientific;
		Eigen::SparseMatrix<complex<double>> tempA = Eigen::SparseMatrix<complex<double>>(_mA_complex);

		for (int k = 0; k < tempA.outerSize(); k++)
			for (Eigen::SparseMatrix<complex<double>>::InnerIterator it(tempA, k); it; ++it)
			{
				outAv_real << std::setprecision(12) << it.value().real() << " ";
				outAv_imag << std::setprecision(12) << it.value().imag() << " ";
				outAi << std::setprecision(12) << it.row() + 1 << " ";
				outAj << std::setprecision(12) << it.col() + 1 << " ";
			}
		outAi << std::endl;
		outAj << std::endl;
		outAv_real << std::endl;
		outAv_imag << std::endl;

		for (int k = 0; k < _mB_complex.rows(); k++)
		{
			outBv_real << std::setprecision(12) << _mB_complex(k).real() << endl;
			outBv_imag << std::setprecision(12) << _mB_complex(k).imag() << endl;
			outX_real << std::setprecision(12) << _mX(k).real() << endl;
			outX_imag << std::setprecision(12) << _mX(k).imag() << endl;
		}
			
		outAi.close();
		outAj.close();
		outAv_real.close();
		outAv_imag.close();
		outBv_real.close();
		outBv_imag.close();
		outX_real.close();
		outX_imag.close();
	}
}


void Solver_LdaDom::Test_OutputX(Eigen::VectorXcd* x)
{
	std::ofstream outX;
	outX.open("X.txt", std::ios::out | std::ios::trunc);
	outX << std::fixed; 
	
	for(int i=0;i<x[0].rows();i++)
		outX<<std::setprecision(12) << x[0](i).real()<<" "<<x[0](i).imag()<<endl;

	outX.close();
}
