XIAN-FEM-2026June/opticsfem-master/kernel/Assemble_Scatter_2D_Boundar...

2164 lines
63 KiB
C++
Raw Permalink 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"../function/BF.h"
#include"../function/Gauss.h"
#include"../common/define.h"
#include "../parser/mpParser.h"
#include"../Eigen/Sparse"
#include"../Eigen/Dense"
#include<cmath>
using namespace Eigen;
void OpticsFEM_2D_Scatter::Assemble_SBC()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(ONEDIM, LINE, BF_LINEFUNC * 2);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(ONEDIM, LINE, u, v, w, wght);
//init of geo
Vector3d* vertex = new Vector3d[5];
Matrix3d Jac, InvJac;
Vector3d normal;
//init of basis function
BF BF_Lagrange, BF_Nedelec;
Vector3d* Et, ** Ez;
BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
Et = new Vector3d[NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
for (int i = 0; i < NbrGuassPoints; i++)
{
Ez[i] = new Vector3d[2];
}
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
Vector3cd* Einc;
complex<double>* EincPhi;
Einc = new Vector3cd[NbrGuassPoints];
EincPhi = new complex<double>[NbrGuassPoints];
//overloop of SBC
int NbrSBC = _mPhy->GetNbrSBC();
for (int n = 0; n < NbrSBC; n++)
{
//SBC data
int SBCDomain = _mPhy->GetSBCDomain(n) + 1;
int SBCType = _mPhy->GetSBCType(n);
string Eincx, Eincy, Eincz;
Vector3d kdir;
if (SBCType == 1)
{
_mPhy->GetSBDir(n, kdir);
_mPhy->GetEinc(n, Eincx, Eincy, Eincz);
}
VectorXi edgesIndex;
_mMesh->GetEdgesIndexOfDomain(SBCDomain, edgesIndex);
//overloop of edgesOfSBC
for (int m = 0; m < edgesIndex.rows(); m++)
{
//edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgesIndex(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
//coordinate of vertex,integration coordinate, and mapping
int MappingIndex[3];
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
index[0] = 1; index[1] = 2; index[2] = 1;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 1);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 0) + _mMesh->GetNbrVertex();
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
index[0] = 1; index[1] = 3; index[2] = 2;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 1) + _mMesh->GetNbrVertex();
}
else if (numEdge == 2)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
index[0] = 2; index[1] = 3; index[2] = 3;
MappingIndex[0] = _mMesh->GetTri(numEle, 1);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 2) + _mMesh->GetNbrVertex();
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0)!= vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//normal
_mMesh->GetNormOfEdges(_mMesh->GetDomainOfEdges(edgesIndex(m))-1, normal);
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < 2; j++)
{
BF_Lagrange.GetValueBF(index[j], v[i], w[i], 0.0, Ez[i][j]);
}
BF_Nedelec.GetValueBF(index[2], v[i], w[i], 0.0, Et[i]);
Et[i] = InvJac * Et[i];
}
//material
double n = _mMatLib->GetN(_mMesh->GetDomainOfTri(numEle));
complex<double> phySBC(0, k0 * n);
//submatrix
MatrixXcd Be;
Be = MatrixXcd::Zero(2, 2);
complex<double>Ae;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Be(i, j) = Be(i, j) + wght[k] * integCoe * phySBC * (normal.cross(Ez[k][i])).dot(normal.cross(Ez[k][j]));
}
for (int k = 0; k < NbrGuassPoints; k++)
{
Ae = Ae + wght[k] * integCoe * phySBC * (normal.cross(Et[k])).dot(normal.cross(Et[k]));
}
//store in triple
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
_mTripleA_complex.push_back(Triplet<complex<double>>(MappingIndex[i], MappingIndex[j], Be(i, j)));
}
_mTripleA_complex.push_back(Triplet<complex<double>>(MappingIndex[2], MappingIndex[2], Ae));
//inc
if (SBCType == 1)
{
//Einc
for (int i = 0; i < NbrGuassPoints; i++)
{
double tempX = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
double tempY = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
xx = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
yy = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
p.SetExpr(_T(Eincx));
Einc[i](0).real(p.Eval().GetFloat());
Einc[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincy));
Einc[i](1).real(p.Eval().GetFloat());
Einc[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincz));
Einc[i](2).real(p.Eval().GetFloat());
Einc[i](2).imag(p.Eval().GetImag());
complex<double> phi(0, -k0 * n * (kdir(0) * tempX + kdir(1) * tempY));
EincPhi[i] = exp(
phi);
}
//submatrix
complex<double> be[3];
for (int k = 0; k < NbrGuassPoints; k++)
{
be[0] = be[0] + wght[k] * integCoe * phySBC * /* EincPhi[k]* */ Ez[k][0].dot(normal.cross(Einc[k].cross(normal - kdir)));
be[1] = be[1] + wght[k] * integCoe * phySBC * /* EincPhi[k]* */ Ez[k][1].dot(normal.cross(Einc[k].cross(normal - kdir)));
be[2] = be[2] + wght[k] * integCoe * phySBC * /* EincPhi[k]* */Et[k].dot(normal.cross(Einc[k].cross(normal - kdir)));
}
//store in vector
for (int i = 0; i < 3; i++)
_mB_complex(MappingIndex[i]) = _mB_complex(MappingIndex[i]) + be[i];
}
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] Ez[i];
}
delete[] Ez, Et, Einc, EincPhi;
}
void OpticsFEM_2D_Scatter::Assemble_BELE()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(TWODIM, TRIANGLE, BF_LINEFUNC * 2);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(TWODIM, TRIANGLE, u, v, w, wght);
//init of geo
Vector3d* vertex = new Vector3d[5];
Matrix3d Jac, InvJac, TJac, JacS;
//init of basis function
BF BF_Lagrange, BF_Curl_Lagrange, BF_Nedelec, BF_Curl_Nedelec;
int sdof, vdof;
Vector3d** Et, ** curlEt, ** Ez, ** curlEz;
/*Vector3d** bEt, ** bcurlEt, ** bEz, ** bcurlEz;*/
sdof = BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
BF_Curl_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_LAGRANGE, BF_LINEFUNC);
vdof = BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
BF_Curl_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_NEDELEC, BF_LINEFUNC);
Et = new Vector3d * [NbrGuassPoints];
curlEt = new Vector3d * [NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
curlEz = new Vector3d * [NbrGuassPoints];
for (int i = 0; i < NbrGuassPoints; i++)
{
Et[i] = new Vector3d[vdof];
curlEt[i] = new Vector3d[vdof];
Ez[i] = new Vector3d[sdof];
curlEz[i] = new Vector3d[sdof];
}
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
Vector3cd* bEt, * bEz, * bcurlEt, * bcurlEz;
bEt = new Vector3cd[NbrGuassPoints];
bEz = new Vector3cd[NbrGuassPoints];
bcurlEt = new Vector3cd[NbrGuassPoints];
bcurlEz = new Vector3cd[NbrGuassPoints];
string Ebx, Eby, Ebz;
_mPhy->GetEb(Ebx, Eby, Ebz);
string curlEbx, curlEby, curlEbz;
_mPhy->GetCurlEb(curlEbx, curlEby, curlEbz);
//loop over tri
int NbrTri = _mMesh->GetNbrTri();
for (int n = 0; n < NbrTri; n++)
{
int domain = _mMesh->GetDomainOfTri(n);
Eigen::VectorXi BELE;
_mPhy->GetBELE(BELE);
if (std::find(BELE.begin(), BELE.end(), domain) == BELE.end())
{
continue;
}
//coordinate of vertex
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(n, i), vertex[i]);
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
JacS(0, 0) = InvJac(1, 1); JacS(0, 1) = -InvJac(1, 0); JacS(0, 2) = 0.;
JacS(1, 0) = -InvJac(0, 1); JacS(1, 1) = InvJac(0, 0); JacS(1, 2) = 0.;
JacS(2, 0) = 0.; JacS(2, 1) = 0.; JacS(2, 2) = 1.;
double DetJac = fabs(Jac.determinant());
TJac = Jac.transpose() / Jac.determinant();
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < sdof; j++)
{
BF_Lagrange.GetValueBF(j + 1, u[i], v[i], w[i], Ez[i][j]);
BF_Curl_Lagrange.GetValueBF(j + 1, u[i], v[i], w[i], curlEz[i][j]);
curlEz[i][j] = JacS * curlEz[i][j];
}
for (int j = 0; j < vdof; j++)
{
BF_Nedelec.GetValueBF(j + 1, u[i], v[i], w[i], Et[i][j]);
Et[i][j] = InvJac * Et[i][j];
BF_Curl_Nedelec.GetValueBF(j + 1, u[i], v[i], w[i], curlEt[i][j]);
curlEt[i][j] = TJac * curlEt[i][j];
}
}
//background field
for (int i = 0; i < NbrGuassPoints; i++)
{
xx = vertex[0][0] + Jac(0, 0) * u[i] + Jac(1, 0) * v[i];
yy = vertex[0][1] + Jac(0, 0) * u[i] + Jac(1, 1) * v[i];
p.SetExpr(_T(Ebx));
bEt[i](0).real(p.Eval().GetFloat());
bEt[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eby));
bEt[i](1).real(p.Eval().GetFloat());
bEt[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Ebz));
bEz[i](2).real(p.Eval().GetFloat());
bEz[i](2).imag(p.Eval().GetImag());
p.SetExpr(_T(curlEbx));
bcurlEz[i](0).real(p.Eval().GetFloat());
bcurlEz[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(curlEby));
bcurlEz[i](1).real(p.Eval().GetFloat());
bcurlEz[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(curlEbz));
bcurlEt[i](2).real(p.Eval().GetFloat());
bcurlEt[i](2).imag(p.Eval().GetImag());
}
//material
Matrix3cd epsr = _mMatLib->GetEpsr(domain);
Matrix3cd Mur = _mMatLib->GetMur(domain);
Matrix3cd invMur;
invMur = Mur.inverse();
//submatrix
MatrixXcd St, Sz, Tt, Tz;
St = MatrixXcd::Zero(vdof, vdof);
Sz = MatrixXcd::Zero(sdof, sdof);
Tt = MatrixXcd::Zero(vdof, vdof);
Tz = MatrixXcd::Zero(sdof, sdof);
for (int i = 0; i < sdof; i++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Sz(i, 0) = Sz(i, 0) + wght[k] * DetJac * curlEz[k][i].dot(invMur * bcurlEz[k]);
Tz(i, 0) = Tz(i, 0) + wght[k] * DetJac * k0 * k0 * Ez[k][i].dot(epsr * bEz[k]);
}
for (int i = 0; i < vdof; i++)
for (int k = 0; k < NbrGuassPoints; k++)
{
St(i, 0) = St(i, 0) + wght[k] * DetJac * curlEt[k][i].dot(invMur * bcurlEt[k]);
Tt(i, 0) = Tt(i, 0) + wght[k] * DetJac * k0 * k0 * Et[k][i].dot(epsr * bEt[k]);
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int i = 0; i < 3; i++)
{
MappingIndexS(i) = _mMesh->GetTri(n, i);
MappingIndexV(i) = _mMesh->GetEdgeOfTri(n, i) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[i]) = _mB_complex(MappingIndexS[i]) + Tz(i, 0) - Sz(i, 0);
_mB_complex(MappingIndexV[i]) = _mB_complex(MappingIndexV[i]) + Tt(i, 0) - St(i, 0);
}
}
//Line
//init of Gauss point
NbrGuassPoints = gauss.GetNbrGaussPoints(ONEDIM, LINE, BF_LINEFUNC * 4);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(ONEDIM, LINE, u, v, w, wght);
Eigen::VectorXi BELE;
_mPhy->GetBELE(BELE);
int NbrBELE = BELE.rows();
//find PML index
int NbrPML = _mPhy->GetNbrPML();
Eigen::VectorXi PMLEdge = Eigen::VectorXi::Zero(NbrPML);
for (int i = 0; i < NbrPML; i++)
PMLEdge(i) = _mPhy->GetPMLEdge(i) + 1;
Eigen::VectorXi edgeIndexOfPML, edgeNumOfPML;//edges<65><73><EFBFBD><EFBFBD> <20><>ӦELE<4C><45><EFBFBD><EFBFBD>
_mMesh->GetIndexOfDomain2(PMLEdge, edgeIndexOfPML, edgeNumOfPML);
//overloop of edgesOfBELE
for (int m = 0; m < edgeNumOfPML.rows(); m++)
{
//edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgeIndexOfPML(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
//coordinate of vertex,integration coordinate, and mapping
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
}
else if (numEdge == 2)
{
vertex[3] = vertex[1];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0) != vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//normal
Vector3d normal;
int edge = _mMesh->GetDomainOfEdges(edgeNumOfPML(m));
_mMesh->GetNormOfEdges(_mMesh->GetDomainOfEdges(edgeNumOfPML(m)) - 1, normal);
if (normal.isZero())
{
normal[0] = (vertex[3](0) + vertex[4](0)) / 2 - normal[0];
normal[1] = (vertex[3](1) + vertex[4](1)) / 2 - normal[1];
normal[2] = 0;
normal.normalize();
}
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < sdof; j++)
{
BF_Lagrange.GetValueBF(j + 1, v[i], w[i], 0.0, Ez[i][j]);
}
for (int j = 0; j < vdof; j++)
{
BF_Nedelec.GetValueBF(j + 1, v[i], w[i], 0.0, Et[i][j]);
Et[i][j] = InvJac * Et[i][j];
}
}
//back ground field
for (int i = 0; i < NbrGuassPoints; i++)
{
xx = vertex[0][0] + Jac(0, 0) * v[i] + Jac(1, 0) * w[i];
yy = vertex[0][1] + Jac(0, 0) * v[i] + Jac(1, 1) * w[i];
p.SetExpr(_T(curlEbx));
bcurlEz[i](0).real(p.Eval().GetFloat());
bcurlEz[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(curlEby));
bcurlEz[i](1).real(p.Eval().GetFloat());
bcurlEz[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(curlEbz));
bcurlEt[i](2).real(p.Eval().GetFloat());
bcurlEt[i](2).imag(p.Eval().GetImag());
}
//submatrix
MatrixXcd bz, bt;
bz = MatrixXcd::Zero(3, 1);
bt = MatrixXcd::Zero(3, 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < NbrGuassPoints; j++)
{
bz(i) = bz(i) - wght[j] * integCoe * Ez[j][i].dot(normal.cross(bcurlEz[j]));
bt(i) = bt(i) - wght[j] * integCoe * Et[j][i].dot(normal.cross(bcurlEt[j]));
}
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int i = 0; i < 3; i++)
{
MappingIndexS(i) = _mMesh->GetTri(numEle, i);
MappingIndexV(i) = _mMesh->GetEdgeOfTri(numEle, i) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[i]) = _mB_complex(MappingIndexS[i]) + bz(i);
_mB_complex(MappingIndexV[i]) = _mB_complex(MappingIndexV[i]) + bt(i);
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] Et[i], curlEt[i], Ez[i], curlEz[i];
}
delete[] Et, curlEt, Ez, curlEz, bEt, bcurlEt, bEz, bcurlEz;
}
void OpticsFEM_2D_Scatter::Assemble_MAG()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
//Line
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(ONEDIM, LINE, BF_LINEFUNC * 4);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(ONEDIM, LINE, u, v, w, wght);
//init of basis function
Vector3d* vertex = new Vector3d[5];
Matrix3d Jac, InvJac, TJac, JacS;
//init of basis function
BF BF_Lagrange, BF_Curl_Lagrange, BF_Nedelec, BF_Curl_Nedelec;
Vector3d** Et, ** Ez;
int sdof, vdof;
Et = new Vector3d * [NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
sdof = BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
vdof = BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
for (int i = 0; i < NbrGuassPoints; i++)
{
Et[i] = new Vector3d[vdof];
Ez[i] = new Vector3d[sdof];
}
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
Vector3cd * bcurlEt, * bcurlEz;
bcurlEt = new Vector3cd[NbrGuassPoints];
bcurlEz = new Vector3cd[NbrGuassPoints];
//find MAG index
int NbrMAG = _mPhy->GetNbrMAG();
string H0x, H0y, H0z;
Eigen::VectorXi MAGDomain = Eigen::VectorXi::Zero(1);
for (int n = 0; n < NbrMAG; n++)
{
_mPhy->GetH0(H0x, H0y, H0z, n);
MAGDomain(0) = _mPhy->GetMAGDomain(n) + 1;
Eigen::VectorXi edgeIndexOfMAG, edgeNumOfMAG;//edges<65><73><EFBFBD><EFBFBD> <20><>ӦMAG<41><47><EFBFBD><EFBFBD>
_mMesh->GetIndexOfDomain2(MAGDomain, edgeIndexOfMAG, edgeNumOfMAG);
//overloop of edgesOfMAG
for (int m = 0; m < edgeNumOfMAG.rows(); m++)
{
//edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgeIndexOfMAG(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
//coordinate of vertex,integration coordinate, and mapping
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
}
else if (numEdge == 2)
{
vertex[3] = vertex[1];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0) != vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//normal
Vector3d normal;
int edge = _mMesh->GetDomainOfEdges(edgeNumOfMAG(m));
_mMesh->GetNormOfEdges(_mMesh->GetDomainOfEdges(edgeNumOfMAG(m)) - 1, normal);
if (normal.isZero())
{
normal[0] = (vertex[3](0) + vertex[4](0)) / 2 - normal[0];
normal[1] = (vertex[3](1) + vertex[4](1)) / 2 - normal[1];
normal[2] = 0;
normal.normalize();
}
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < sdof; j++)
{
BF_Lagrange.GetValueBF(j + 1, v[i], w[i], 0.0, Ez[i][j]);
}
for (int j = 0; j < vdof; j++)
{
BF_Nedelec.GetValueBF(j + 1, v[i], w[i], 0.0, Et[i][j]);
Et[i][j] = InvJac * Et[i][j];
}
}
//back ground field
for (int i = 0; i < NbrGuassPoints; i++)
{
xx = vertex[0][0] + Jac(0, 0) * v[i] + Jac(1, 0) * w[i];
yy = vertex[0][1] + Jac(0, 1) * v[i] + Jac(1, 1) * w[i];
p.SetExpr(_T(H0x));
bcurlEz[i](0).real(p.Eval().GetFloat());
bcurlEz[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(H0y));
bcurlEz[i](1).real(p.Eval().GetFloat());
bcurlEz[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(H0z));
bcurlEt[i](2).real(p.Eval().GetFloat());
bcurlEt[i](2).imag(p.Eval().GetImag());
}
//submatrix
MatrixXcd bz, bt;
bz = MatrixXcd::Zero(3, 1);
bt = MatrixXcd::Zero(3, 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < NbrGuassPoints; j++)
{
bz(i) = bz(i) - complex<double>(0.0, 1.0) * k0 * wght[j] * integCoe * Ez[j][i].dot(normal.cross(bcurlEz[j]));
bt(i) = bt(i) - complex<double>(0.0, 1.0) * k0 * wght[j] * integCoe * Et[j][i].dot(normal.cross(bcurlEt[j]));
}
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int i = 0; i < 3; i++)
{
MappingIndexS(i) = _mMesh->GetTri(numEle, i);
MappingIndexV(i) = _mMesh->GetEdgeOfTri(numEle, i) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[i]) = _mB_complex(MappingIndexS[i]) + bz(i);
_mB_complex(MappingIndexV[i]) = _mB_complex(MappingIndexV[i]) + bt(i);
}
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] Et[i], Ez[i];
}
delete[] Et, Ez, bcurlEt, bcurlEz;
}
void OpticsFEM_2D_Scatter::Assemble_SCD()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
//Line
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(ONEDIM, LINE, BF_LINEFUNC * 4);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(ONEDIM, LINE, u, v, w, wght);
//init of basis function
Vector3d* vertex = new Vector3d[5];
Matrix3d Jac, InvJac, TJac, JacS;
//init of basis function
BF BF_Lagrange, BF_Curl_Lagrange, BF_Nedelec, BF_Curl_Nedelec;
Vector3d** Et, ** Ez;
int sdof, vdof;
Et = new Vector3d * [NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
sdof = BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
vdof = BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
for (int i = 0; i < NbrGuassPoints; i++)
{
Et[i] = new Vector3d[vdof];
Ez[i] = new Vector3d[sdof];
}
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
Vector3cd* bEt, * bEz;
bEt = new Vector3cd[NbrGuassPoints];
bEz = new Vector3cd[NbrGuassPoints];
//find SCD index
int NbrSCD = _mPhy->GetNbrSCD();
string J0x, J0y, J0z;
Eigen::VectorXi SCDDomain = Eigen::VectorXi::Zero(1);
for (int n = 0; n < NbrSCD; n++)
{
_mPhy->GetJ0(J0x, J0y, J0z, n);
SCDDomain(0) = _mPhy->GetSCDDomain(n) + 1;
Eigen::VectorXi edgeIndexOfSCD, edgeNumOfSCD;//edges<65><73><EFBFBD><EFBFBD> <20><>ӦSCD<43><44><EFBFBD><EFBFBD>
_mMesh->GetIndexOfDomain2(SCDDomain, edgeIndexOfSCD, edgeNumOfSCD);
//overloop of edgesOfSCD
for (int m = 0; m < edgeNumOfSCD.rows(); m++)
{
//edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgeIndexOfSCD(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
}
else if (numEdge == 2)
{
vertex[3] = vertex[1];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0) != vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < sdof; j++)
{
BF_Lagrange.GetValueBF(j + 1, v[i], w[i], 0.0, Ez[i][j]);
}
for (int j = 0; j < vdof; j++)
{
BF_Nedelec.GetValueBF(j + 1, v[i], w[i], 0.0, Et[i][j]);
Et[i][j] = InvJac * Et[i][j];
}
}
//back ground field
for (int i = 0; i < NbrGuassPoints; i++)
{
xx = vertex[0][0] + Jac(0, 0) * v[i] + Jac(1, 0) * w[i];
yy = vertex[0][1] + Jac(0, 1) * v[i] + Jac(1, 1) * w[i];
p.SetExpr(_T(J0x));
bEt[i](0).real(p.Eval().GetFloat());
bEt[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(J0y));
bEt[i](1).real(p.Eval().GetFloat());
bEt[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(J0z));
bEz[i](2).real(p.Eval().GetFloat());
bEz[i](2).imag(p.Eval().GetImag());
}
//submatrix
MatrixXcd bz, bt;
bz = MatrixXcd::Zero(3, 1);
bt = MatrixXcd::Zero(3, 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < NbrGuassPoints; j++)
{
bz(i) = bz(i) - complex<double>(0.0, 1.0) * sqrt(mu0 / epsilon0) * k0 * wght[j] * integCoe * Ez[j][i].dot(bEz[j]);
bt(i) = bt(i) - complex<double>(0.0, 1.0) * sqrt(mu0 / epsilon0) * k0 * wght[j] * integCoe * Et[j][i].dot(bEt[j]);
}
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int i = 0; i < 3; i++)
{
MappingIndexS(i) = _mMesh->GetTri(numEle, i);
MappingIndexV(i) = _mMesh->GetEdgeOfTri(numEle, i) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[i]) = _mB_complex(MappingIndexS[i]) + bz(i);
_mB_complex(MappingIndexV[i]) = _mB_complex(MappingIndexV[i]) + bt(i);
}
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] Et[i], Ez[i];
}
delete[] Et, Ez, bEt, bEz;
}
void OpticsFEM_2D_Scatter::Assemble_MPD()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
Eigen::MatrixXd m;
Eigen::VectorXi MPD;
_mPhy->GetMPD(MPD);
_mPhy->GetMPDData(m);
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(TWODIM, TRIANGLE, BF_LINEFUNC * 4);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(TWODIM, TRIANGLE, u, v, w, wght);
//init of geo
Vector3d* vertex = new Vector3d[3];
Matrix3d Jac, InvJac, TJac, JacS;
double xx, yy;
Vector3cd* bEt, * bEz;
bEt = new Vector3cd[NbrGuassPoints];
bEz = new Vector3cd[NbrGuassPoints];
//init of basis function
BF BF_Lagrange, BF_Curl_Lagrange, BF_Nedelec, BF_Curl_Nedelec;
int sdof, vdof;
Vector3d** curlEt, ** curlEz;
sdof = BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
BF_Curl_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_LAGRANGE, BF_LINEFUNC);
vdof = BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
BF_Curl_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_NEDELEC, BF_LINEFUNC);
curlEt = new Vector3d * [NbrGuassPoints];
curlEz = new Vector3d * [NbrGuassPoints];
for (int i = 0; i < NbrGuassPoints; i++)
{
curlEt[i] = new Vector3d[vdof];
curlEz[i] = new Vector3d[sdof];
}
//loop over tri
int NbrTri = _mMesh->GetNbrTri();
int NbrMPD = MPD.size();
int num = 0;
for (int i = 0; i < NbrMPD; i++)
{
for (int n = 0; n < NbrTri; n++)
{
bool found = false;
for (int j = 0; j < 3; j++)
{
if (MPD[i] == _mMesh->GetTri(n, j))
{
found = true;
break;
}
}
if (found) {
//coordinate of vertex
num = num + 1;
for (int j = 0; j < 3; j++)
_mMesh->GetVertex(_mMesh->GetTri(n, j), vertex[j]);
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
JacS(0, 0) = InvJac(1, 1); JacS(0, 1) = -InvJac(1, 0); JacS(0, 2) = 0.;
JacS(1, 0) = -InvJac(0, 1); JacS(1, 1) = InvJac(0, 0); JacS(1, 2) = 0.;
JacS(2, 0) = 0.; JacS(2, 1) = 0.; JacS(2, 2) = 1.;
double DetJac = fabs(Jac.determinant());
TJac = Jac.transpose() / Jac.determinant();
//basis function
for (int j = 0; j < NbrGuassPoints; j++)
{
for (int k = 0; k < sdof; k++)
{
BF_Curl_Lagrange.GetValueBF(k + 1, u[j], v[j], w[j], curlEz[j][k]);
curlEz[j][k] = JacS * curlEz[j][k];
}
for (int k = 0; k < vdof; k++)
{
BF_Curl_Nedelec.GetValueBF(k + 1, u[j], v[j], w[j], curlEt[j][k]);
curlEt[j][k] = TJac * curlEt[j][k];
}
}
//submatrix
Eigen::Vector3d m_current = m.row(i);
MatrixXcd Tt, Tz;
Tt = MatrixXcd::Zero(vdof, 1);
Tz = MatrixXcd::Zero(sdof, 1);
for (int j = 0; j < sdof; j++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Tz(j) = Tz(j) + complex<double>(0.0, -1.0) * sqrt(mu0 / epsilon0) * k0 * wght[k] * DetJac * curlEz[k][j].dot(m_current);
}
for (int j = 0; j < vdof; j++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Tt(j) = Tt(j) + complex<double>(0.0, -1.0) * sqrt(mu0 / epsilon0) * k0 * wght[k] * DetJac * curlEt[k][j].dot(m_current);
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int j = 0; j < 3; j++)
{
MappingIndexS(j) = _mMesh->GetTri(n, j);
MappingIndexV(j) = _mMesh->GetEdgeOfTri(n, j) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[j]) = _mB_complex(MappingIndexS[j]) + Tz(j);
_mB_complex(MappingIndexV[j]) = _mB_complex(MappingIndexV[j]) + Tt(j);
}
}
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] curlEt[i], curlEz[i];
}
delete[] bEt, bEz;
}
void OpticsFEM_2D_Scatter::Assemble_EPD()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
Eigen::MatrixXd p;
Eigen::VectorXi EPD;
_mPhy->GetEPD(EPD);
_mPhy->GetEPDData(p);
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
double* u, * v, * w, * wght;
NbrGuassPoints = gauss.GetNbrGaussPoints(TWODIM, TRIANGLE, BF_LINEFUNC * 4);
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(TWODIM, TRIANGLE, u, v, w, wght);
//init of geo
Vector3d* vertex = new Vector3d[3];
Matrix3d Jac, InvJac, TJac, JacS;
double xx, yy;
Vector3cd* bEt, * bEz;
bEt = new Vector3cd[NbrGuassPoints];
bEz = new Vector3cd[NbrGuassPoints];
//init of basis function
BF BF_Lagrange, BF_Curl_Lagrange, BF_Nedelec, BF_Curl_Nedelec;
int sdof, vdof;
Vector3d** Et, ** Ez;
sdof = BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
BF_Curl_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_LAGRANGE, BF_LINEFUNC);
vdof = BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
BF_Curl_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_CURL_NEDELEC, BF_LINEFUNC);
Et = new Vector3d * [NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
for (int i = 0; i < NbrGuassPoints; i++)
{
Et[i] = new Vector3d[vdof];
Ez[i] = new Vector3d[sdof];
}
//loop over tri
int NbrTri = _mMesh->GetNbrTri();
int NbrEPD = EPD.size();
int num = 0;
for (int i = 0; i < NbrEPD; i++)
{
for (int n = 0; n < NbrTri; n++)
{
bool found = false;
for (int j = 0; j < 3; j++)
{
if (EPD[i] == _mMesh->GetTri(n, j))
{
found = true;
break;
}
}
if (found) {
//coordinate of vertex
num = num + 1;
for (int j = 0; j < 3; j++)
_mMesh->GetVertex(_mMesh->GetTri(n, j), vertex[j]);
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
JacS(0, 0) = InvJac(1, 1); JacS(0, 1) = -InvJac(1, 0); JacS(0, 2) = 0.;
JacS(1, 0) = -InvJac(0, 1); JacS(1, 1) = InvJac(0, 0); JacS(1, 2) = 0.;
JacS(2, 0) = 0.; JacS(2, 1) = 0.; JacS(2, 2) = 1.;
double DetJac = fabs(Jac.determinant());
TJac = Jac.transpose() / Jac.determinant();
//basis function
for (int j = 0; j < NbrGuassPoints; j++)
{
for (int k = 0; k < sdof; k++)
{
BF_Lagrange.GetValueBF(k + 1, u[j], v[j], w[j], Ez[j][k]);
}
for (int k = 0; k < vdof; k++)
{
BF_Nedelec.GetValueBF(k + 1, u[j], v[j], w[j], Et[j][k]);
Et[j][k] = InvJac * Et[j][k];
}
}
//submatrix
Eigen::Vector3d p_current = p.row(i);
MatrixXcd Tt, Tz;
Tt = MatrixXcd::Zero(vdof, 1);
Tz = MatrixXcd::Zero(sdof, 1);
for (int j = 0; j < sdof; j++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Tz(j) = Tz(j) + complex<double>(0.0, -1.0) * sqrt(mu0/epsilon0) * k0 * wght[k] * DetJac * Ez[k][j].dot(p_current);
}
for (int j = 0; j < vdof; j++)
for (int k = 0; k < NbrGuassPoints; k++)
{
Tt(j) = Tt(j) + complex<double>(0.0, -1.0) * sqrt(mu0 / epsilon0) * k0 * wght[k] * DetJac * Et[k][j].dot(p_current);
}
//Mapping
VectorXi MappingIndexS = VectorXi::Zero(sdof);
VectorXi MappingIndexV = VectorXi::Zero(vdof);
for (int j = 0; j < 3; j++)
{
MappingIndexS(j) = _mMesh->GetTri(n, j);
MappingIndexV(j) = _mMesh->GetEdgeOfTri(n, j) + _mMesh->GetNbrVertex();
_mB_complex(MappingIndexS[j]) = _mB_complex(MappingIndexS[j]) + Tz(j);
_mB_complex(MappingIndexV[j]) = _mB_complex(MappingIndexV[j]) + Tt(j);
}
}
}
}
delete[] u, v, w, wght;
delete[] vertex;
for (int i = 0; i < NbrGuassPoints; i++)
{
delete[] Et[i], Ez[i];
}
delete[] bEt, bEz;
}
void OpticsFEM_2D_Scatter::Assemble_PEC_ELE()
{
//find PEC index
int NbrPEC = _mPhy->GetNbrPEC();
Eigen::VectorXi PECDomain = Eigen::VectorXi::Zero(NbrPEC);
for (int i = 0; i < NbrPEC; i++)
PECDomain(i) = _mPhy->GetPECDomain(i) + 1;
Eigen::VectorXi nodeIndexOfPEC, edgeIndexOfPEC;
_mMesh->GetIndexOfDomain(PECDomain, nodeIndexOfPEC, edgeIndexOfPEC);
//find ELE index
int NbrELE = _mPhy->GetNbrElE();
Eigen::VectorXi ELEDomain = Eigen::VectorXi::Zero(NbrELE);
for (int i = 0; i < NbrELE; i++)
ELEDomain(i) = _mPhy->GetELEDomain(i) + 1;
Eigen::VectorXi edgeIndexOfELE, edgeNumOfELE;//edges<65><73><EFBFBD><EFBFBD> <20><>ӦELE<4C><45><EFBFBD><EFBFBD>
_mMesh->GetIndexOfDomain2(ELEDomain, edgeIndexOfELE, edgeNumOfELE);
//init BCIndex BCValue
int NbrBC = edgeIndexOfPEC.rows() + nodeIndexOfPEC.rows() + edgeNumOfELE.rows() * 3; //<2F><><EFBFBD><EFBFBD>+һ<><D2BB><EFBFBD><EFBFBD>
Eigen::VectorXi BCIndex = Eigen::VectorXi::Zero(NbrBC);// 1:3 ELE 4:6 PEC
Eigen::VectorXcd BCValue = Eigen::VectorXcd::Zero(NbrBC);
//init of geo
Vector3d* vertex = new Vector3d[5];
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy, zz;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
p.DefineVar(_T("z"), mup::Variable(&zz));
Vector3cd E0;
//overloop edge of ELE
int bcOffset = 0;
int NbrVertex = _mMesh->GetNbrVertex();
for (int m = 0; m < NbrELE; m++)
{
Eigen::VectorXi ELEDomain = Eigen::VectorXi::Zero(NbrELE);
ELEDomain(0) = _mPhy->GetELEDomain(m) + 1;
Eigen::VectorXi edgeIndexOfELE, currentEdgeNum;//edges<65><73><EFBFBD><EFBFBD> <20><>ӦELE<4C><45><EFBFBD><EFBFBD>
_mMesh->GetIndexOfDomain2(ELEDomain, edgeIndexOfELE, currentEdgeNum);
string E0x, E0y, E0z;
_mPhy->GetE0(E0x, E0y, E0z,m);
for (int n = 0; n <currentEdgeNum.rows(); n++)
{
//edge data
Eigen::Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgeIndexOfELE(n), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
Eigen::Vector3d ee = Eigen::Vector3d::Zero();
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
ee(0) = vertex[1](0) - vertex[0](0);
ee(1) = vertex[1](1) - vertex[0](1);
BCIndex(n + bcOffset)= _mMesh->GetTri(numEle, 0);
BCIndex(n + bcOffset + edgeNumOfELE.rows()) = _mMesh->GetTri(numEle, 1);
BCIndex(n + bcOffset + edgeNumOfELE.rows() * 2) = _mMesh->GetEdgeOfTri(numEle, 0) + NbrVertex;
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
ee(0) = vertex[2](0) - vertex[0](0);
ee(1) = vertex[2](1) - vertex[0](1);
BCIndex(n + bcOffset) = _mMesh->GetTri(numEle, 0);
BCIndex(n + bcOffset + edgeNumOfELE.rows()) = _mMesh->GetTri(numEle, 2);
BCIndex(n + bcOffset + edgeNumOfELE.rows() * 2) = _mMesh->GetEdgeOfTri(numEle, 1) + NbrVertex;
}
else if (numEdge == 2)
{
vertex[3] = vertex[1];
vertex[4] = vertex[2];
ee(0) = vertex[2](0) - vertex[1](0);
ee(1) = vertex[2](1) - vertex[1](1);
BCIndex(n + bcOffset) = _mMesh->GetTri(numEle, 1);
BCIndex(n + bcOffset + edgeNumOfELE.rows()) = _mMesh->GetTri(numEle, 2);
BCIndex(n + bcOffset + edgeNumOfELE.rows() * 2) = _mMesh->GetEdgeOfTri(numEle, 2) + NbrVertex;
}
xx = (vertex[3](0) + vertex[4](0)) / 2;
yy = (vertex[3](1) + vertex[4](1)) / 2;
if (_mPhy->GetNbrBELE())
{
string Ebx, Eby, Ebz;
string ExFunc, EyFunc, EzFunc;
_mPhy->GetEb(Ebx, Eby, Ebz);
ExFunc = E0x + "-" + Ebx;
EyFunc = E0y + "-" + Eby;
EzFunc = E0z + "-" + Ebz;
p.SetExpr(_T(ExFunc));
E0(0).real(p.Eval().GetFloat());
E0(0).imag(p.Eval().GetImag());
p.SetExpr(_T(EyFunc));
E0(1).real(p.Eval().GetFloat());
E0(1).imag(p.Eval().GetImag());
xx = vertex[3](0); yy = vertex[4](0);
p.SetExpr(_T(EzFunc));
E0(2).real(p.Eval().GetFloat());
E0(2).imag(p.Eval().GetImag());
BCValue(n + bcOffset) = E0(2);
xx = vertex[4](0); yy = vertex[5](0);
p.SetExpr(_T(EzFunc));
E0(2).real(p.Eval().GetFloat());
E0(2).imag(p.Eval().GetImag());
BCValue(n + bcOffset + edgeNumOfELE.rows()) = E0(2);
}
else
{
p.SetExpr(_T(E0x));
E0(0).real(p.Eval().GetFloat());
E0(0).imag(p.Eval().GetImag());
p.SetExpr(_T(E0y));
E0(1).real(p.Eval().GetFloat());
E0(1).imag(p.Eval().GetImag());
xx = vertex[3](0); yy = vertex[4](0);
p.SetExpr(_T(E0z));
E0(2).real(p.Eval().GetFloat());
E0(2).imag(p.Eval().GetImag());
BCValue(n + bcOffset) = E0(2);
xx = vertex[4](0); yy = vertex[5](0);
p.SetExpr(_T(E0z));
E0(2).real(p.Eval().GetFloat());
E0(2).imag(p.Eval().GetImag());
BCValue(n + bcOffset + edgeNumOfELE.rows()) = E0(2);
}
BCValue(n + bcOffset + edgeNumOfELE.rows() * 2) = E0.dot(ee);
}
bcOffset += currentEdgeNum.rows();
}
delete[] vertex;
//store PEC data
for (int i = 0; i < nodeIndexOfPEC.rows(); i++)
{
BCIndex(i + bcOffset * 3) = nodeIndexOfPEC(i);
BCValue(i + bcOffset * 3) = 0.;
}
for (int i = 0; i < edgeIndexOfPEC.rows(); i++)
{
BCIndex(i + bcOffset * 3 + nodeIndexOfPEC.rows()) = edgeIndexOfPEC(i) + NbrVertex;
BCValue(i + bcOffset * 3 + nodeIndexOfPEC.rows()) = 0.;
}
//<2F><><EFBFBD><EFBFBD>
Eigen::VectorXi tempIndex = Eigen::VectorXi::Zero(NbrBC);
for (int i = 0; i < NbrBC; i++)
tempIndex(i) = i;
QuickSort(BCIndex, tempIndex, 0, NbrBC - 1);
//ȥ<><C8A5>
Unique(BCIndex, tempIndex);
Eigen::VectorXcd tempValue = Eigen::VectorXcd::Zero(BCIndex.rows());
for (int i = 0; i < BCIndex.rows(); i++)
tempValue(i) = BCValue(tempIndex(i));
BCValue = tempValue;
//<2F><><EFBFBD><EFBFBD>
if (_mIsReal)
{
Eigen::VectorXd tempValue;
for (int i = 0; i < BCValue.rows(); i++)
{
tempValue = Eigen::VectorXd::Zero(_mA_real.rows());
tempValue(BCIndex(i)) = 1.;
_mB_real = _mB_real - _mA_real * tempValue * BCValue(i).real();
}
Eigen::SparseMatrix<double, Eigen::RowMajor> P(_mA_real.rows(), _mA_real.rows());
std::vector<Eigen::Triplet<double>> tempTriple;
int num = 0;
for (int i = 0; i < _mA_real.rows(); i++)
{
if (num < BCIndex.rows())
{
if (i == BCIndex(num))
num++;
else
tempTriple.push_back(Eigen::Triplet<double>(i, i, 1.));
}
else
tempTriple.push_back(Eigen::Triplet<double>(i, i, 1.));
}
P.setFromTriplets(tempTriple.begin(), tempTriple.end());
_mA_real = P * _mA_real * P;
P.setZero();
tempTriple.clear();
for (int i = 0; i < BCIndex.rows(); i++)
{
tempTriple.push_back(Eigen::Triplet<double>(BCIndex(i), BCIndex(i), 1.));
_mB_real(BCIndex(i)) = BCValue(i).real();
}
P.setFromTriplets(tempTriple.begin(), tempTriple.end());
_mA_real = _mA_real + P;
}
else
{
Eigen::VectorXcd tempValue;
for (int i = 0; i < BCValue.rows(); i++)
{
tempValue = Eigen::VectorXcd::Zero(_mA_complex.rows());
tempValue(BCIndex(i)) = 1;
_mB_complex = _mB_complex - _mA_complex * tempValue * BCValue(i);
}
Eigen::SparseMatrix<complex<double>, Eigen::RowMajor> P(_mA_complex.rows(), _mA_complex.rows());
std::vector<Eigen::Triplet<complex<double>>> tempTriple;
int num = 0;
for (int i = 0; i < _mA_complex.rows(); i++)
{
if (num < BCIndex.rows())
{
if (i == BCIndex(num))
num++;
else
tempTriple.push_back(Eigen::Triplet<complex<double>>(i, i, 1.));
}
else
tempTriple.push_back(Eigen::Triplet<complex<double>>(i, i, 1.));
}
P.setFromTriplets(tempTriple.begin(), tempTriple.end());
_mA_complex = P * _mA_complex * P;
P.setZero();
tempTriple.clear();
for (int i = 0; i < BCIndex.rows(); i++)
{
tempTriple.push_back(Eigen::Triplet<complex<double>>(BCIndex(i), BCIndex(i), 1.));
_mB_complex(BCIndex(i)) = BCValue(i);
}
P.setFromTriplets(tempTriple.begin(), tempTriple.end());
_mA_complex = _mA_complex + P;
}
}
void OpticsFEM_2D_Scatter::Assemble_PBC()
{
//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);
//<2F><> 1:DOF
//<2F><> 1<><31>(DOF-NbrPEC-NbrDst)
int NbrVertex = _mMesh->GetNbrVertex();
int NbrDstIndex = 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 < dstNodeIndex.rows(); i++)
{
dstIndex(i) = dstNodeIndex(i);
srcIndex(i) = srcNodeIndex(i);
IndexPhi(i) = nodePhi(i);
}
for (int i = 0; i < dstEdgeIndex.rows(); i++)
{
int num = dstNodeIndex.rows();
dstIndex(i + num) = dstEdgeIndex(i) + NbrVertex;
srcIndex(i + num) = srcEdgeIndex(i) + NbrVertex;
IndexPhi(i + num) = edgePhi(i);
}
//<2F><><EFBFBD><EFBFBD>
Eigen::VectorXi tempIndex = Eigen::VectorXi::Zero(NbrDstIndex);
for (int i = 0; i < NbrDstIndex; i++)
tempIndex(i) = i;
QuickSort(dstIndex, tempIndex, 0, NbrDstIndex - 1);
//ȥ<><C8A5>
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;
//<2F><>ͬ<EFBFBD><CDAC>Ŀ
int dof = _mMesh->GetNbrEdge() + _mMesh->GetNbrVertex();
int vdof = _mMesh->GetNbrEdge();
int sdof = _mMesh->GetNbrVertex();
//P<><50><EFBFBD><EFBFBD>
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()) //<2F><><EFBFBD><EFBFBD>PBC
{
if (i == dstIndex(num))
{
temp_P.push_back(Eigen::Triplet<double>(dstIndex(num), srcIndex(num), IndexPhi(num).real()));
num++;
}
}
}
/*<2A><>ʱP<CAB1><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
std::sort(temp_P.begin(), temp_P.end(),
[](const Eigen::Triplet<double>& a, const Eigen::Triplet<double>& b)
{
return a.col() < b.col();
});
/*ɾ<><C9BE>dstIndex<65><78>Ӧ<EFBFBD><D3A6>*/
std::vector<Eigen::Triplet<double>> tripleP_real;
num = 0;// <20><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD>¾<EFBFBD><C2BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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());
}
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()) //<2F><><EFBFBD><EFBFBD>PEC<45><43>PBC
{
if (i == dstIndex(num))
{
temp_P_complex.push_back(Eigen::Triplet<complex<double>>(dstIndex(num), srcIndex(num), IndexPhi(num)));
num++;
}
}
}
/*<2A><>ʱP<CAB1><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
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();
});
/*ɾ<><C9BE>dstIndex<65><78>Ӧ<EFBFBD><D3A6>*/
std::vector<Eigen::Triplet<complex<double>>> tripleP_complex;
num = 0;// <20><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD>¾<EFBFBD><C2BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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());;
}
}
void OpticsFEM_2D_Scatter::Assemble_Port()
{
//physic
double k0 = 2 * Pi / _mSolver->GetLda0();
//init of Gauss point
Gauss gauss;
int NbrGuassPoints;
NbrGuassPoints = gauss.GetNbrGaussPoints(ONEDIM, LINE, BF_LINEFUNC * 4);
double* u, * v, * w, * wght;
u = new double[NbrGuassPoints];
v = new double[NbrGuassPoints];
w = new double[NbrGuassPoints];
wght = new double[NbrGuassPoints];
gauss.GetGaussPoints(ONEDIM, LINE, u, v, w, wght);
//init of geo
Vector3d* vertex = new Vector3d[5];
Matrix3d Jac, InvJac;
Vector3d normal;
//init of basis function
BF BF_Lagrange, BF_Nedelec;
Vector3d* Et, ** Ez;
BF_Lagrange.GetNbrBF(TWODIM, TRIANGLE, BF_LAGRANGE, BF_LINEFUNC);
BF_Nedelec.GetNbrBF(TWODIM, TRIANGLE, BF_NEDELEC, BF_LINEFUNC);
Et = new Vector3d[NbrGuassPoints];
Ez = new Vector3d * [NbrGuassPoints];
for (int i = 0; i < NbrGuassPoints; i++)
{
Ez[i] = new Vector3d[2];
}
//inite parser
mup::ParserX p(mup::pckALL_COMPLEX);
p.EnableAutoCreateVar(true);
mup::Value xx, yy;
p.DefineVar(_T("x"), mup::Variable(&xx));
p.DefineVar(_T("y"), mup::Variable(&yy));
Vector3cd* N0, * N2, * curlN0, * curlN1, * curlN2;
N0 = new Vector3cd[NbrGuassPoints];
N2 = new Vector3cd[NbrGuassPoints];
curlN0 = new Vector3cd[NbrGuassPoints];
curlN1 = new Vector3cd[NbrGuassPoints];
curlN2 = new Vector3cd[NbrGuassPoints];
int NbrPortinc = _mPhy->GetNbrPortinc();
for (int n = 0; n < NbrPortinc; n++)
{
int PortincDomain = _mPhy->GetPortincDomain(n) + 1;
Eigen::VectorXi edgesIndex;
_mMesh->GetEdgesIndexOfDomain(PortincDomain, edgesIndex);
string Eincx, Eincy, Eincz, Eoutx, Eouty, Eoutz, EincCurlx, EincCurly, EincCurlz, EoutCurlx, EoutCurly, EoutCurlz;
_mPhy->GetPortEinc(Eincx, Eincy, Eincz);
_mPhy->GetPortEout(Eoutx, Eouty, Eoutz);
_mPhy->GetPortEincCurl(EincCurlx, EincCurly, EincCurlz);
_mPhy->GetPortEoutCurl(EoutCurlx, EoutCurly, EoutCurlz);
//overloop of edgesOfPortinc
for (int m = 0; m < edgesIndex.rows(); m++)
{
// edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgesIndex(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
//coordinate of vertex,integration coordinate, and mapping
int MappingIndex[3];
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
index[0] = 1; index[1] = 2; index[2] = 1;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 1);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 0) + _mMesh->GetNbrVertex();
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
index[0] = 1; index[1] = 3; index[2] = 2;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 1) + _mMesh->GetNbrVertex();
}
else if (numEdge == 2)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
index[0] = 2; index[1] = 3; index[2] = 3;
MappingIndex[0] = _mMesh->GetTri(numEle, 1);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 2) + _mMesh->GetNbrVertex();
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0) != vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//normal
_mMesh->GetNormOfEdges(_mMesh->GetDomainOfEdges(edgesIndex(m)) - 1, normal);
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < 2; j++)
{
BF_Lagrange.GetValueBF(index[j], v[i], w[i], 0.0, Ez[i][j]);
}
BF_Nedelec.GetValueBF(index[2], v[i], w[i], 0.0, Et[i]);
Et[i] = InvJac * Et[i];
}
for (int i = 0; i < NbrGuassPoints; i++)
{
double tempX = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
double tempY = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
xx = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
yy = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
//<2F><><EFBFBD>䳡N0
p.SetExpr(_T(Eincx));
N0[i](0).real(p.Eval().GetFloat());
N0[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincy));
N0[i](1).real(p.Eval().GetFloat());
N0[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincz));
N0[i](2).real(p.Eval().GetFloat());
N0[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N2
p.SetExpr(_T(Eoutx));
N2[i](0).real(p.Eval().GetFloat());
N2[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincy));
N0[i](1).real(p.Eval().GetFloat());
N0[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincz));
N0[i](2).real(p.Eval().GetFloat());
N0[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N0<4E><30><EFBFBD><EFBFBD>
p.SetExpr(_T(EincCurlx));
curlN0[i](0).real(p.Eval().GetFloat());
curlN0[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(EincCurly));
curlN0[i](1).real(p.Eval().GetFloat());
curlN0[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(EincCurlz));
curlN0[i](2).real(p.Eval().GetFloat());
curlN0[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N1<4E><31><EFBFBD><EFBFBD>
curlN1[i](0) = std::conj(curlN0[i](0));
curlN1[i](1) = std::conj(curlN0[i](1));
curlN1[i](2) = std::conj(curlN0[i](2));
//<2F><><EFBFBD>䳡N2
p.SetExpr(_T(EoutCurlx));
curlN2[i](0).real(p.Eval().GetFloat());
curlN2[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(EoutCurly));
curlN2[i](1).real(p.Eval().GetFloat());
curlN2[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(EoutCurlz));
curlN2[i](2).real(p.Eval().GetFloat());
curlN2[i](2).imag(p.Eval().GetImag());
}
//material
int domain = _mMesh->GetDomainOfTri(n);
Matrix3cd epsr = _mMatLib->GetEpsr(domain);
Matrix3cd refra = epsr.cwiseSqrt();
//submatrix
MatrixXcd Se1, Ge1, be1;
Se1 = MatrixXcd::Zero(2, 1);
Ge1 = MatrixXcd::Zero(2, 1);
be1 = MatrixXcd::Zero(2, 1);
complex<double>Se2, Ge2, be2;
for (int i = 0; i < 2; i++)
{
for (int k = 0; k < NbrGuassPoints; k++)
{
be1(i, 0) = be1(i, 0) + wght[k] * integCoe * Ez[k][i].dot(curlN0[k].cross(refra * normal));
Se1(i, 0) = Se1(i, 0) + wght[k] * integCoe * Ez[k][i].dot(curlN1[k].cross(refra * normal));
Ge1(i, 0) = Ge1(i, 0) + wght[k] * integCoe * N0[k].dot(normal.cross(Ez[k][i].cross(normal)));
}
}
for (int k = 0; k < NbrGuassPoints; k++)
{
be2 = be2 + wght[k] * integCoe * Et[k].dot(curlN0[k].cross(refra * normal));
Se2 = Se2 + wght[k] * integCoe * Et[k].dot(curlN1[k].cross(refra * normal));
Ge2 = Ge2 + wght[k] * integCoe * N0[k].dot(normal.cross(Et[k].cross(normal)));
P1 = P1 + wght[k] * integCoe * N0[k].dot(normal.cross(N0[k].cross(normal)));
b1 = b1 + wght[k] * integCoe * N0[k].dot(normal.cross(N0[k].cross(normal)));
}
//<2F><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>
for (int i = 0; i < 2; i++)
{
_mPort_B_complex(MappingIndex[i]) = _mPort_B_complex(MappingIndex[i]) - be1(i, 0);
_mS_complex(MappingIndex[i]) = _mS_complex(MappingIndex[i]) + Se1(i, 0);
_mG1_complex(MappingIndex[i]) = _mG1_complex(MappingIndex[i]) + Ge1(i, 0);
}
_mPort_B_complex(MappingIndex[2]) = _mPort_B_complex(MappingIndex[2]) - be2;
_mS_complex(MappingIndex[2]) = _mS_complex(MappingIndex[2]) + Se2;
_mG1_complex(MappingIndex[2]) = _mG1_complex(MappingIndex[2]) + Ge2;
//<2F><><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD>
int PortoutDomain = _mPhy->GetPortoutDomain(n) + 1;
Eigen::VectorXi edgesIndex;
_mMesh->GetEdgesIndexOfDomain(PortoutDomain, edgesIndex);
for (int m = 0; m < edgesIndex.rows(); m++)
{
// edge data
Vector2i coonOfEdges;
_mMesh->GetCoonOfEdges(edgesIndex(m), coonOfEdges);
int numEle = coonOfEdges(0);
int numEdge = coonOfEdges(1);
//coordinate of vertex,integration coordinate, and mapping
int MappingIndex[3];
int index[3];
for (int i = 0; i < 3; i++)
_mMesh->GetVertex(_mMesh->GetTri(numEle, i), vertex[i]);
if (numEdge == 0)
{
vertex[3] = vertex[0];
vertex[4] = vertex[1];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = 0.0;
}
index[0] = 1; index[1] = 2; index[2] = 1;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 1);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 0) + _mMesh->GetNbrVertex();
}
else if (numEdge == 1)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = 0.0;
w[i] = (u[i] + 1.0) / 2.0;
}
index[0] = 1; index[1] = 3; index[2] = 2;
MappingIndex[0] = _mMesh->GetTri(numEle, 0);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 1) + _mMesh->GetNbrVertex();
}
else if (numEdge == 2)
{
vertex[3] = vertex[0];
vertex[4] = vertex[2];
for (int i = 0; i < NbrGuassPoints; i++)
{
v[i] = (u[i] + 1.0) / 2.0;
w[i] = (1.0 - u[i]) / 2.0;
}
index[0] = 2; index[1] = 3; index[2] = 3;
MappingIndex[0] = _mMesh->GetTri(numEle, 1);
MappingIndex[1] = _mMesh->GetTri(numEle, 2);
MappingIndex[2] = _mMesh->GetEdgeOfTri(numEle, 2) + _mMesh->GetNbrVertex();
}
//Jac
Jac(0, 0) = vertex[1](0) - vertex[0](0); Jac(0, 1) = vertex[1](1) - vertex[0](1); Jac(0, 2) = 0.;
Jac(1, 0) = vertex[2](0) - vertex[0](0); Jac(1, 1) = vertex[2](1) - vertex[0](1); Jac(1, 2) = 0.;
Jac(2, 0) = 0.; Jac(2, 1) = 0.; Jac(2, 2) = 1.;
InvJac = Jac.inverse();
//integration coe
double phi1 = vertex[4](1) - vertex[3](1);
double phi2 = vertex[3](0) - vertex[4](0);
double integCoe = 0;
if (vertex[3](0) != vertex[4](0))
{
integCoe = phi1 / phi2;
integCoe = fabs(sqrtf(1 + integCoe * integCoe) * phi2 / 2.0);
}
else
{
integCoe = abs(phi1) / 2.0;
}
//normal
_mMesh->GetNormOfEdges(_mMesh->GetDomainOfEdges(edgesIndex(m)) - 1, normal);
//basis function
for (int i = 0; i < NbrGuassPoints; i++)
{
for (int j = 0; j < 2; j++)
{
BF_Lagrange.GetValueBF(index[j], v[i], w[i], 0.0, Ez[i][j]);
}
BF_Nedelec.GetValueBF(index[2], v[i], w[i], 0.0, Et[i]);
Et[i] = InvJac * Et[i];
}
for (int i = 0; i < NbrGuassPoints; i++)
{
double tempX = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
double tempY = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
xx = Jac(0, 0) * v[i] + Jac(1, 0) * w[i] + vertex[0](0);
yy = Jac(0, 1) * v[i] + Jac(1, 1) * w[i] + vertex[0](1);
//<2F><><EFBFBD>䳡N0
p.SetExpr(_T(Eincx));
N0[i](0).real(p.Eval().GetFloat());
N0[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincy));
N0[i](1).real(p.Eval().GetFloat());
N0[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Eincz));
N0[i](2).real(p.Eval().GetFloat());
N0[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N2
p.SetExpr(_T(Eoutx));
N2[i](0).real(p.Eval().GetFloat());
N2[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(Eouty));
N2[i](1).real(p.Eval().GetFloat());
N2[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(Eoutz));
N2[i](2).real(p.Eval().GetFloat());
N2[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N0<4E><30><EFBFBD><EFBFBD>
p.SetExpr(_T(EincCurlx));
curlN0[i](0).real(p.Eval().GetFloat());
curlN0[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(EincCurly));
curlN0[i](1).real(p.Eval().GetFloat());
curlN0[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(EincCurlz));
curlN0[i](2).real(p.Eval().GetFloat());
curlN0[i](2).imag(p.Eval().GetImag());
//<2F><><EFBFBD>䳡N1<4E><31><EFBFBD><EFBFBD>
curlN1[i](0) = std::conj(curlN0[i](0));
curlN1[i](1) = std::conj(curlN0[i](1));
curlN1[i](2) = std::conj(curlN0[i](2));
//<2F><><EFBFBD>䳡N2
p.SetExpr(_T(EoutCurlx));
curlN2[i](0).real(p.Eval().GetFloat());
curlN2[i](0).imag(p.Eval().GetImag());
p.SetExpr(_T(EoutCurly));
curlN2[i](1).real(p.Eval().GetFloat());
curlN2[i](1).imag(p.Eval().GetImag());
p.SetExpr(_T(EoutCurlz));
curlN2[i](2).real(p.Eval().GetFloat());
curlN2[i](2).imag(p.Eval().GetImag());
}
//material
int domain = _mMesh->GetDomainOfTri(n);
Matrix3cd epsr = _mMatLib->GetEpsr(domain);
Matrix3cd refra = epsr.cwiseSqrt();
//submatrix
MatrixXcd Te1, Ge1;
Te1 = MatrixXcd::Zero(2, 1);
Ge1 = MatrixXcd::Zero(2, 1);
complex<double>P2;
for (int i = 0; i < 2; i++)
{
for (int k = 0; k < NbrGuassPoints; k++)
{
Te1(i, 0) = Te1(i, 0) + wght[k] * integCoe * Ez[k][i].dot(curlN2[k].cross(refra * normal));
Ge1(i, 0) = Ge1(i, 0) + wght[k] * integCoe * N2[k].dot(normal.cross(Ez[k][i].cross(normal)));
P2 = P2 + wght[k] * integCoe * N2[k].dot(normal.cross(N2[k].cross(normal)));
}
}
complex<double>Te2, Ge2;
for (int k = 0; k < NbrGuassPoints; k++)
{
Te2 = Te2 + wght[k] * integCoe * Et[k].dot(curlN2[k].cross(refra * normal));
Ge2 = Ge2 + wght[k] * integCoe * N2[k].dot(normal.cross(Et[k].cross(normal)));
}
//<2F><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>
for (int i = 0; i < 2; i++)
{
_mT_complex(MappingIndex[i]) = _mT_complex(MappingIndex[i]) + Te1(i, 0);
_mG2_complex(MappingIndex[i]) = _mG2_complex(MappingIndex[i]) + Ge1(i, 0);
}
_mT_complex(MappingIndex[2]) = _mT_complex(MappingIndex[2]) + Te2;
_mG2_complex(MappingIndex[2]) = _mG2_complex(MappingIndex[2]) + Ge2;
}
}
}
_mS_complex = _mP_complex.adjoint() * _mS_complex;
_mT_complex = _mP_complex.adjoint() * _mT_complex;
_mG1_complex = _mP_complex.adjoint() * _mG1_complex;
_mG2_complex = _mP_complex.adjoint() * _mG2_complex;
for (const auto& triplet : _mTripleA_complex)
{
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(triplet.row(), triplet.col(), triplet.value()));
/*std::cout << "col: " << triplet.col() << "row: " << triplet.row() << ", Value: " << triplet.value() << std::endl;*/
}
for (int k = 0; k < _mA_complex.outerSize(); k++)
{
for (Eigen::SparseMatrix<complex<double>, RowMajor>::InnerIterator it(_mA_complex, k); it; ++it)
{
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(it.row(), it.col(), it.value()));
}
}
for (int i = 0; i < _mS_complex.size(); i++) {
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(i, _mDof, _mS_complex[i]));
}
for (int i = 0; i < _mT_complex.size(); i++) {
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(i, _mDof + 1, _mT_complex[i]));
}
for (int i = 0; i < _mG1_complex.size(); i++) {
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(_mDof, i, _mG1_complex[i]));
}
for (int i = 0; i < _mG2_complex.size(); i++) {
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(_mDof + 1, i, _mG2_complex[i]));
}
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(_mDof, _mDof, -P1));
_mTriplePort_A_complex.push_back(Triplet<complex<double>>(_mDof + 1, _mDof + 1, -P2));
_mPort_B_complex(_mDof) = b1;
for (int k = 0; k < _mP_complex.outerSize(); k++)
{
for (Eigen::SparseMatrix<complex<double>, RowMajor>::InnerIterator it(_mP_complex, k); it; ++it)
{
_mPort_P_complex.coeffRef(it.row(), it.col()) = it.value();
}
}
}