#include"Assemble_Base.h"
#include"../common/util.h"

void OpticsFEM_2D_EigenMode::Assemble_PEC_PBC()
{
	//find PEC index
	Eigen::VectorXi PECDomain = Eigen::VectorXi::Zero(_mPhy->GetNbrPEC());
	for (int i = 0; i < _mPhy->GetNbrPEC(); i++)
		PECDomain(i) = _mPhy->GetPECDomain(i) + 1;
	Eigen::VectorXi nodeIndexOfPEC, edgeIndexOfPEC;
	_mMesh->GetIndexOfDomain(PECDomain, nodeIndexOfPEC, edgeIndexOfPEC);
	//find PBC index
	Eigen::VectorXi srcNodeIndex, dstNodeIndex, srcEdgeIndex, dstEdgeIndex;
	Eigen::VectorXcd nodePhi, edgePhi, PBCData;
	Eigen::MatrixXi PBC;
	PBC = Eigen::MatrixXi::Zero(_mPhy->GetNbrPBC(), 2);
	PBCData = Eigen::VectorXcd::Zero(_mPhy->GetNbrPBC());
	for (int i = 0; i < _mPhy->GetNbrPBC(); i++)
	{
		PBC(i, 0) = _mPhy->GetSrcDomain(i);
		PBC(i, 1) = _mPhy->GetDstDomain(i);
		PBCData(i) = _mPhy->GetPBCPhi(i);
	}
	_mMesh->GetIndexOfPBC(PBC, PBCData, srcNodeIndex, dstNodeIndex, nodePhi, srcEdgeIndex, dstEdgeIndex, edgePhi);

	//行 1:DOF
	//列 1：(DOF-NbrPEC-NbrDst)
	int NbrVertex = _mMesh->GetNbrVertex();
	int NbrDstIndex = nodeIndexOfPEC.rows() + edgeIndexOfPEC.rows() + dstNodeIndex.rows() + dstEdgeIndex.rows();

	Eigen::VectorXi dstIndex = Eigen::VectorXi::Zero(NbrDstIndex);
	Eigen::VectorXi srcIndex = Eigen::VectorXi::Zero(NbrDstIndex);
	Eigen::VectorXcd IndexPhi = Eigen::VectorXcd::Zero(NbrDstIndex);
	for (int i = 0; i < nodeIndexOfPEC.rows(); i++)
	{
		dstIndex(i) = nodeIndexOfPEC(i);
		srcIndex(i) = nodeIndexOfPEC(i);
		IndexPhi(i) = 0.;
	}
	for (int i = 0; i < edgeIndexOfPEC.rows(); i++)
	{
		int num = nodeIndexOfPEC.rows();
		dstIndex(i + num) = edgeIndexOfPEC(i) + NbrVertex;
		srcIndex(i + num) = edgeIndexOfPEC(i) + NbrVertex;
		IndexPhi(i + num) = 0.;
	}
	for (int i = 0; i < dstNodeIndex.rows(); i++)
	{
		int num = nodeIndexOfPEC.rows() + edgeIndexOfPEC.rows();
		dstIndex(i + num) = dstNodeIndex(i);
		srcIndex(i + num) = srcNodeIndex(i);
		IndexPhi(i + num) = nodePhi(i);
	}
	for (int i = 0; i < dstEdgeIndex.rows(); i++)
	{
		int num = nodeIndexOfPEC.rows() + edgeIndexOfPEC.rows() + dstNodeIndex.rows();
		dstIndex(i + num) = dstEdgeIndex(i) + NbrVertex;
		srcIndex(i + num) = srcEdgeIndex(i) + NbrVertex;
		IndexPhi(i + num) = edgePhi(i);
	}
	//排序
	Eigen::VectorXi tempIndex = Eigen::VectorXi::Zero(NbrDstIndex);
	for (int i = 0; i < NbrDstIndex; i++)
		tempIndex(i) = i;
	QuickSort(dstIndex, tempIndex, 0, NbrDstIndex - 1);

	//去重
	Unique(dstIndex, tempIndex);
	Eigen::VectorXcd tempIndexPhi = Eigen::VectorXcd::Zero(dstIndex.rows());
	Eigen::VectorXi tempSrcIndex = Eigen::VectorXi::Zero(dstIndex.rows());
	for (int i = 0; i < dstIndex.rows(); i++)
	{
		tempIndexPhi(i) = IndexPhi(tempIndex(i));
		tempSrcIndex(i) = srcIndex(tempIndex(i));
	}
	IndexPhi = tempIndexPhi;
	srcIndex = tempSrcIndex;

	//不同数目
	int dof = _mMesh->GetNbrEdge() + _mMesh->GetNbrVertex();
	int vdof = _mMesh->GetNbrEdge();
	int sdof = _mMesh->GetNbrVertex();

	//P矩阵
	int num = 0;
	if (_mIsReal)
	{
		std::vector<Eigen::Triplet<double>> temp_P;
		for (int i = 0; i < dof; i++) // 
		{
			temp_P.push_back(Eigen::Triplet<double>(i, i, 1));
			if (num < dstIndex.size()) //处理PEC或PBC
			{
				if (i == dstIndex(num))
				{
					temp_P.push_back(Eigen::Triplet<double>(dstIndex(num), srcIndex(num), IndexPhi(num).real()));
					num++;
				}
			}
		}
		/*临时P矩阵排序*/
		std::sort(temp_P.begin(), temp_P.end(),
			[](const Eigen::Triplet<double>& a, const Eigen::Triplet<double>& b)
			{
				return a.col() < b.col();
			});


		/*删除dstIndex对应列*/
		std::vector<Eigen::Triplet<double>> tripleP_real;
		num = 0;// 用于跟踪新矩阵的列索引
		int	DeleteIndex = 0;
		for (int i = 0; i < dof; i++)
		{
			DeleteIndex = 0;
			for (int j = 0; j < dstIndex.rows(); j++)
			{
				if (i == dstIndex[j])
				{
					DeleteIndex = 1;
				}
			}
			if (DeleteIndex != 1)
			{
				for (const auto& triplet : temp_P)
				{
					if (triplet.col() == i)
					{
						tripleP_real.push_back(Eigen::Triplet<double>(triplet.row(), triplet.col() - num, triplet.value()));
					}
				}
			}
			for (int j = 0; j < dstIndex.rows(); j++)
			{
				if (i == dstIndex[j])
				{
					num = num + 1;
				}
			}

		}
		_mP_real = Eigen::SparseMatrix<double, Eigen::RowMajor>(dof, dof - dstIndex.rows());
		_mP_real.setFromTriplets(tripleP_real.begin(), tripleP_real.end());

		///*排序后打印*/
		//std::sort(tripleP_real.begin(), tripleP_real.end(),
		//		[](const Eigen::Triplet<double>& a, const Eigen::Triplet<double>& b) {
		//			return a.col() < b.col();
		//		});
		//	for (const auto& triplet : tripleP_real) {
		//		std::cout << "(" << triplet.row() << ", " << triplet.col() << "): " << triplet.value() << std::endl;
		//	}
	}
	else
	{
		std::vector<Eigen::Triplet<complex<double>>> temp_P_complex;
		for (int i = 0; i < dof; i++) // 
		{
			temp_P_complex.push_back(Eigen::Triplet<complex<double>>(i, i, 1));
			if (num < dstIndex.size()) //处理PEC或PBC
			{
				if (i == dstIndex(num))
				{
					temp_P_complex.push_back(Eigen::Triplet<complex<double>>(dstIndex(num), srcIndex(num), IndexPhi(num)));
					num++;
				}
			}
		}
		/*临时P矩阵排序*/
		std::sort(temp_P_complex.begin(), temp_P_complex.end(),
			[](const Eigen::Triplet<complex<double>>& a, const Eigen::Triplet<complex<double>>& b)
			{
				return a.col() < b.col();
			});


		/*删除dstIndex对应列*/
		std::vector<Eigen::Triplet<complex<double>>> tripleP_complex;
		num = 0;// 用于跟踪新矩阵的列索引
		int	DeleteIndex = 0;
		for (int i = 0; i < dof; i++)
		{
			DeleteIndex = 0;
			for (int j = 0; j < dstIndex.rows(); j++)
			{
				if (i == dstIndex[j])
				{
					DeleteIndex = 1;
				}
			}
			if (DeleteIndex != 1)
			{
				for (const auto& triplet : temp_P_complex)
				{
					if (triplet.col() == i)
					{
						tripleP_complex.push_back(Eigen::Triplet<complex<double>>(triplet.row(), triplet.col() - num, triplet.value()));
					}
				}
			}
			for (int j = 0; j < dstIndex.rows(); j++)
			{
				if (i == dstIndex[j])
				{
					num = num + 1;
				}
			}

		}
		_mP_complex = Eigen::SparseMatrix<complex<double>, Eigen::RowMajor>(dof, dof - dstIndex.rows());
		_mP_complex.setFromTriplets(tripleP_complex.begin(), tripleP_complex.end());;
	}

}
