#include"Assemble_Base.h" #include"PBC_Util.h" #include"Nedelec3D_Util.h" #include"../common/util.h" #include #include #include void OpticsFEM_2D_EigenFreq::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(); //??T????????? int numEle = 0; if (_mElectricType == 0) { numEle = _mMesh->GetNbrVertex(); } else if (_mElectricType == 1) { numEle = _mMesh->GetNbrEdge(); } NbrDstIndex = NbrDstIndex + numEle; Eigen::VectorXi dstIndex = Eigen::VectorXi::Zero(NbrDstIndex); Eigen::VectorXi srcIndex = Eigen::VectorXi::Zero(NbrDstIndex); Eigen::VectorXcd IndexPhi = Eigen::VectorXcd::Zero(NbrDstIndex); //??T?????????????? if (_mElectricType == 0) { for (int i = 0; i < numEle; i++) { dstIndex(i) = i; srcIndex(i) = i; IndexPhi(i) = 0.; } } else if (_mElectricType == 1) { for (int i = 0; i < numEle; i++) { dstIndex(i) = i + _mMesh->GetNbrVertex(); srcIndex(i) = i + _mMesh->GetNbrVertex(); IndexPhi(i) = 0.; } } for (int i = 0; i < nodeIndexOfPEC.rows(); i++) { int num = numEle; dstIndex(i + num) = nodeIndexOfPEC(i); srcIndex(i + num) = nodeIndexOfPEC(i); IndexPhi(i + num) = 0; } for (int i = 0; i < edgeIndexOfPEC.rows(); i++) { int num = nodeIndexOfPEC.rows() + numEle; 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() + numEle; 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() + numEle; 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> temp_P; for (int i = 0; i < dof; i++) // { temp_P.push_back(Eigen::Triplet(i, i, 1)); if (num < dstIndex.size()) //????PEC??PBC { if (i == dstIndex(num)) { temp_P.push_back(Eigen::Triplet(dstIndex(num), srcIndex(num), IndexPhi(num).real())); num++; } } } /*???P????????*/ std::sort(temp_P.begin(), temp_P.end(), [](const Eigen::Triplet& a, const Eigen::Triplet& b) { return a.col() < b.col(); }); ///*???????*/ //std::sort(temp_P.begin(), temp_P.end(), // [](const Eigen::Triplet& a, const Eigen::Triplet& b) { // return a.col() < b.col(); // }); // for (const auto& triplet : temp_P) { // std::cout << "(" << triplet.row() << ", " << triplet.col() << "): " << triplet.value() << std::endl; // } /*???dstIndex?????*/ std::vector> 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(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(dof, dof - dstIndex.rows()); _mP_real.setFromTriplets(tripleP_real.begin(), tripleP_real.end()); /*???????*/ //std::sort(tripleP_real.begin(), tripleP_real.end(), // [](const Eigen::Triplet& a, const Eigen::Triplet& 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>> temp_P_complex; for (int i = 0; i < dof; i++) // { temp_P_complex.push_back(Eigen::Triplet>(i, i, 1)); if (num < dstIndex.size()) //????PEC??PBC { if (i == dstIndex(num)) { temp_P_complex.push_back(Eigen::Triplet>(dstIndex(num), srcIndex(num), IndexPhi(num))); num++; } } } /*???P????????*/ std::sort(temp_P_complex.begin(), temp_P_complex.end(), [](const Eigen::Triplet>& a, const Eigen::Triplet>& b) { return a.col() < b.col(); }); /*???dstIndex?????*/ std::vector>> 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>(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, Eigen::RowMajor>(dof, dof - dstIndex.rows()); _mP_complex.setFromTriplets(tripleP_complex.begin(), tripleP_complex.end());; ///*???????*/ //std::sort(tripleP_complex.begin(), tripleP_complex.end(), //[](const Eigen::Triplet>& a, const Eigen::Triplet>& b) // { // return a.col() < b.col(); // }); //for (const auto& triplet : tripleP_complex) { // std::cout << "(" << triplet.row() << ", " << triplet.col() << "): " << triplet.value() << std::endl; //} } } void OpticsFEM_3D_EigenFreq::Assemble_PEC_PBC() { const int elementOrder = _mPhy->GetElementOrder(); std::vector allSrc; std::vector allDst; std::vector> allPhi; if (_mPhy->GetNbrPEC() > 0) { Eigen::VectorXi PECDomain = Eigen::VectorXi::Zero(_mPhy->GetNbrPEC()); for (int i = 0; i < _mPhy->GetNbrPEC(); i++) PECDomain(i) = _mPhy->GetPECDomain(i) + 1; // Reuse scatter PEC DOF collector via local duplicate of edge+face zeroing. // Edge DOFs (order1) or edge×2 + face×2 (order2). std::vector pecEdges; for (int i = 0; i < PECDomain.rows(); i++) { Eigen::VectorXi triIndices; _mMesh->GetTriIndicesOfDomain(PECDomain(i), triIndices); for (int t = 0; t < triIndices.size(); t++) { Eigen::Vector3i conn; _mMesh->GetCoonOfTri(triIndices(t), conn); const int numTet = conn(0); const int numFace = conn(1) + 1; int e[3] = { -1, -1, -1 }; if (numFace == 1) { e[0] = _mMesh->GetEdgeOfTet(numTet, 0); e[1] = _mMesh->GetEdgeOfTet(numTet, 1); e[2] = _mMesh->GetEdgeOfTet(numTet, 3); } else if (numFace == 2) { e[0] = _mMesh->GetEdgeOfTet(numTet, 0); e[1] = _mMesh->GetEdgeOfTet(numTet, 2); e[2] = _mMesh->GetEdgeOfTet(numTet, 4); } else if (numFace == 3) { e[0] = _mMesh->GetEdgeOfTet(numTet, 1); e[1] = _mMesh->GetEdgeOfTet(numTet, 2); e[2] = _mMesh->GetEdgeOfTet(numTet, 5); } else if (numFace == 4) { e[0] = _mMesh->GetEdgeOfTet(numTet, 3); e[1] = _mMesh->GetEdgeOfTet(numTet, 4); e[2] = _mMesh->GetEdgeOfTet(numTet, 5); } for (int k = 0; k < 3; k++) if (e[k] >= 0) pecEdges.push_back(e[k]); } } std::sort(pecEdges.begin(), pecEdges.end()); pecEdges.erase(std::unique(pecEdges.begin(), pecEdges.end()), pecEdges.end()); const int nE = _mMesh->GetNbrEdge(); const int nF = _mMesh->GetNbrFace(); for (int edgeId : pecEdges) { allSrc.push_back(Nedelec3D::edgeGlobalDof(edgeId, 0, nE)); allDst.push_back(Nedelec3D::edgeGlobalDof(edgeId, 0, nE)); allPhi.push_back(0.0); if (elementOrder == 2) { allSrc.push_back(Nedelec3D::edgeGlobalDof(edgeId, 1, nE)); allDst.push_back(Nedelec3D::edgeGlobalDof(edgeId, 1, nE)); allPhi.push_back(0.0); } } if (elementOrder == 2) { std::vector pecFaces; for (int i = 0; i < PECDomain.rows(); i++) { Eigen::VectorXi triIndices; _mMesh->GetTriIndicesOfDomain(PECDomain(i), triIndices); for (int t = 0; t < triIndices.size(); t++) { Eigen::Vector3i conn; _mMesh->GetCoonOfTri(triIndices(t), conn); pecFaces.push_back(_mMesh->GetFaceOfTet(conn(0), conn(1))); } } std::sort(pecFaces.begin(), pecFaces.end()); pecFaces.erase(std::unique(pecFaces.begin(), pecFaces.end()), pecFaces.end()); for (int faceId : pecFaces) { allSrc.push_back(Nedelec3D::faceGlobalDof(faceId, 0, nE, nF)); allDst.push_back(Nedelec3D::faceGlobalDof(faceId, 0, nE, nF)); allPhi.push_back(0.0); allSrc.push_back(Nedelec3D::faceGlobalDof(faceId, 1, nE, nF)); allDst.push_back(Nedelec3D::faceGlobalDof(faceId, 1, nE, nF)); allPhi.push_back(0.0); } } } if (_mPhy->GetNbrPBCGroups() > 0) { Eigen::VectorXi srcEdgeIndex; Eigen::VectorXi dstEdgeIndex; Eigen::VectorXcd edgePhi; if (collectMergedPbcConstraints(_mMesh, _mPhy, elementOrder, srcEdgeIndex, dstEdgeIndex, edgePhi)) { for (int i = 0; i < srcEdgeIndex.size(); i++) { allSrc.push_back(srcEdgeIndex(i)); allDst.push_back(dstEdgeIndex(i)); allPhi.push_back(edgePhi(i)); } } } const int nbr = static_cast(allSrc.size()); Eigen::VectorXi srcIndex(nbr); Eigen::VectorXi dstIndex(nbr); Eigen::VectorXcd indexPhi(nbr); for (int i = 0; i < nbr; i++) { srcIndex(i) = allSrc[i]; dstIndex(i) = allDst[i]; indexPhi(i) = allPhi[i]; } sortUniquePbcPairs(srcIndex, dstIndex, indexPhi); if (_mIsReal) buildPeriodicProjectionReal(_mDof, dstIndex, srcIndex, indexPhi, _mP_real); else buildPeriodicProjectionComplex(_mDof, dstIndex, srcIndex, indexPhi, _mP_complex); }