XIAN-FEM-2026June/3D opticsfem-master/kernel/Assemble_EigenFreq_Boundary...

379 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include"Assemble_Base.h"
#include"PBC_Util.h"
#include"Nedelec3D_Util.h"
#include"../common/util.h"
#include<iostream>
#include<vector>
#include<algorithm>
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<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();
});
///*???????*/
//std::sort(temp_P.begin(), temp_P.end(),
// [](const Eigen::Triplet<double>& a, const Eigen::Triplet<double>& 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<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());;
///*???????*/
//std::sort(tripleP_complex.begin(), tripleP_complex.end(),
//[](const Eigen::Triplet<complex<double>>& a, const Eigen::Triplet<complex<double>>& 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<int> allSrc;
std::vector<int> allDst;
std::vector<std::complex<double>> 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<int> 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<int> 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<int>(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);
}