379 lines
11 KiB
C++
379 lines
11 KiB
C++
#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);
|
||
}
|
||
|