#include #include #include #include #include "portmesh.h" #include "material.h" #include "bc.h" #include "tensor.h" #include "cvtr.h" #include "Constants.h" #include "tri.elem" #include "vtkwriter.h" portMesh::portMesh(){ faceCNT = 0; edgeCNT = 0; nodeCNT = 0; objCNT = 0; objMAP = 0; ndArray = 0; fcArray = 0; modeIMP = 0.; magE = 0.; impZ = 0.; globToLocMap_ = 0; } portMesh::~portMesh(){ delete [] fcArray; delete [] ndArray; delete [] objMAP; delete globToLocMap_; } void portMesh::writeMesh(Material *propMAT, fp_t freq){ FILE *foo; char meshName[180]; int i, j, k, objNum; tensor epsr, mur; node *nd; vtr vv, vv2D; sprintf(meshName, "%s.mesh", portName); foo = fopen(meshName, "w"); fprintf(foo, "%.20e %.20e %.20e\n", (coord.O.getx()), (coord.O.gety()), (coord.O.getz())); fprintf(foo, "%.20e %.20e %.20e\n", (coord.x_axis.getx()), (coord.x_axis.gety()), (coord.x_axis.getz())); fprintf(foo, "%.20e %.20e %.20e\n", (coord.y_axis.getx()), (coord.y_axis.gety()), (coord.y_axis.getz())); fprintf(foo, "1.0 \n"); fprintf(foo, "%d %d %d \n", objCNT, nodeCNT, faceCNT); for(i = 0; i < nodeCNT; i++){ nd = ndArray[i]; vv = nd->getCoord(); vv2D = coord.Transform(vv); fprintf(foo, "0 %.20e %.20e \n", (vv2D.getx()), (vv2D.gety())); } for(i = 0; i < faceCNT; i++){ objNum = fcArray[i]->gettetraPtr(0)->getobjNum(); fprintf(foo, "%d %d %d %d \n", getobjMAP(objNum) + 1, fcArray[i]->getNodePtr(0)->num2D, fcArray[i]->getNodePtr(1)->num2D, fcArray[i]->getNodePtr(2)->num2D); for(j = 0; j < 3; j++){ if(fcArray[i]->getEdge(j) == 0) fprintf(foo, " 1 "); else fprintf(foo, " 0 "); } fprintf(foo, "\n"); } for(i = 0; i < objCNT; i++){ objNum = objMAP[i]; epsr = propMAT[objNum].epsr; mur = propMAT[objNum].mur; epsr = coord.Transform(epsr); fprintf(foo, "%d \n", i + 1); for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++){ fprintf(foo, "%.20e ", (epsr.getEntry(j, k))); } fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++){ fprintf(foo, "%.20e ", (mur.getEntry(j, k))); } fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++){ fprintf(foo, "0.0 "); } fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++){ fprintf(foo, "0.0 "); } fprintf(foo, "\n"); } } fprintf(foo, "%d \n", vline.np); for(i = 0; i < vline.np; i++){ vv = vline.coord[i]; cout << vv.getx() << " " << vv.gety() << " " << vv.getz() << endl; vv2D = coord.Transform(vv); fprintf(foo, "%.20e %.20e \n", vv2D.getx(), vv2D.gety()); } fclose(foo); } void portMesh::writeMesh(Material* propMat){ int i, j, k; vtr vv, vv2D; char meshName[STRLEN]; memset(meshName, 0, STRLEN*sizeof(char)); sprintf(meshName, "%s.mesh", portName); FILE* foo = fopen(meshName, "w"); vtr& O = coord.getO(); vtr& xAxis = coord.getXAxis(); vtr& yAxis = coord.getYAxis(); fprintf(foo, "%.20e %.20e %.20e\n", (O.getx()), (O.gety()), (O.getz())); fprintf(foo, "%.20e %.20e %.20e\n", (xAxis.getx()), (xAxis.gety()), (xAxis.getz())); fprintf(foo, "%.20e %.20e %.20e\n", (yAxis.getx()), (yAxis.gety()), (yAxis.getz())); fprintf(foo, "1.0\n"); fprintf(foo, "%d %d %d \n", objCNT, nodeCNT, faceCNT); for(i = 0; i < nodeCNT; i++){ node* nd = ndArray[i]; vv = nd->getCoord(); vv2D = coord.Transform(vv); fprintf(foo, "0 %.20e %.20e\n", (vv2D.getx()), (vv2D.gety())); } int objNum = 0; for(i = 0; i < faceCNT; i++){ objNum = fcArray[i]->getTetra(0).getobjNum(); fprintf(foo, "%d %d %d %d\n", getobjMAP(objNum) + 1, globToLocMap_->find(fcArray[i]->getNode(0)->getid())->second, globToLocMap_->find(fcArray[i]->getNode(1)->getid())->second, globToLocMap_->find(fcArray[i]->getNode(2)->getid())->second); for(j = 0; j < 3; j++){ if(fcArray[i]->getEdge(j)->getbType() == pecType) fprintf(foo, " 1 "); else fprintf(foo, " 0 "); } fprintf(foo, "\n"); } tensor epsr; tensor mur; for(i = 0; i < objCNT; i++){ objNum = objMAP[i]; epsr = propMat[objNum].epsr; mur = propMat[objNum].mur; epsr = coord.Transform(epsr); fprintf(foo, "%d\n", i + 1); for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++) fprintf(foo, "%.20e ", (epsr.getEntry(j, k))); fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++) fprintf(foo, "%.20e ", (mur.getEntry(j, k))); fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++) fprintf(foo, "%.20e ", 0.0); fprintf(foo, "\n"); } for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++) fprintf(foo, "0.0 "); fprintf(foo, "\n"); } } fprintf(foo, "%d\n", vline.np); for(i = 0; i < vline.np; i++){ cout << vv.getx() << " " << vv.gety() << " " << vv.getz() << endl; vv = vline.coord[i]; vv2D = coord.Transform(vv); fprintf(foo, "%.20e %.20e\n", (vv2D.getx()), (vv2D.gety())); } fclose(foo); } void portMesh::makeObjMap(){ int i, tmpCNT, objNum; tmpCNT = 0; for(i = 0; i < faceCNT; i++){ objNum = fcArray[i]->gettetraPtr(0)->getobjNum(); tmpCNT = (tmpCNT > objNum) ? tmpCNT : objNum; } tmpCNT++; objMAP = new int[tmpCNT]; for(i = 0; i < faceCNT; i++){ objNum = fcArray[i]->gettetraPtr(0)->getobjNum(); insertOBJ(objNum); } } int portMesh::getobjMAP(int obj){ int i; for(i = 0; i < objCNT; i++){ if(objMAP[i] == obj) return i; } return -1; } void portMesh::insertOBJ(int obj){ int i; for(i = 0; i < objCNT; i++){ if(objMAP[i] == obj) return; } objMAP[objCNT] = obj; objCNT++; } void portMesh::setFaceCnt(int faceCnt){ faceCNT = faceCnt; fcArray = new face*[faceCNT]; memset(fcArray, 0, faceCNT * sizeof(face*)); } void portMesh::setNodeCnt(int nodeCnt){ nodeCNT = nodeCnt; ndArray = new node*[nodeCNT]; memset(ndArray, 0, nodeCNT * sizeof(node*)); } // Read from portnems.vpath the definition of the path which defines // the voltage integration forthe mode. This is necessary to do // de-embedding to 50 ohm transmission lines. ifthe file does not exist // then the S parameters will be expressed in terms of the intrinsic // impedances. // void portMesh::readVline(fp_t unit_conv){ FILE *foo; char vlineName[180]; int i, np; fp_t x, y, z; double x_,y_,z_; sprintf(vlineName, "%s.vpath", portName); if((foo = fopen(vlineName, "r")) == NULL){ vline.np = 0; vline.coord = 0; return; } fscanf(foo, "%d", &np); vline.np = np; vline.coord = new vtr[np]; for(i = 0; i < np; i++){ fscanf(foo, "%le", &x_); fscanf(foo, "%le", &y_); fscanf(foo, "%le", &z_); (vline.coord[i]).setvtr((fp_t)x_ * unit_conv, (fp_t)y_ * unit_conv, (fp_t)z_ * unit_conv); } fclose(foo); } void portMesh::readVline(fp_t unit_conv, fp_t& xoff, fp_t& yoff, fp_t& zoff){ FILE *foo; char vlineName[180]; int i, np; fp_t x, y, z; double x_,y_,z_; sprintf(vlineName, "%s.vpath", portName); if((foo = fopen(vlineName, "r")) == NULL){ vline.np = 0; vline.coord = 0; return; } fscanf(foo, "%d", &np); vline.np = np; vline.coord = new vtr[np]; for(i = 0; i < np; i++){ fscanf(foo, "%le", &x_); fscanf(foo, "%le", &y_); fscanf(foo, "%le", &z_); (vline.coord[i]).setvtr((fp_t)x_ * unit_conv + xoff, (fp_t)y_ * unit_conv + yoff, (fp_t)z_ * unit_conv + zoff); } fclose(foo); } // portMesh::makeRHS // foreach port, we assemble a right-hand-side to be used as the // excitation forthe computations of the entire scattering matrix // of the multiport microwave components. // void portMesh::makeRHS(fp_t freq, int dim, int *Part, portCounter pC){ // FILE *foo; // char solname[180], cc; // int i, j, k, tmpCNT, triMAP[8]; // vtr tmpVTR, nvtr[2]; // vtr hvtr[6], jvtr[6]; // cVtr tvtr; // fp_t jval[8], rhs, cval; // face *fc; // denseMat elemM(8, 8); // Material prop; // fp_t scaleF; // cval = -Uo; // portY.N = dim; // portY.entry = new fp_t[dim]; // sprintf(solname, "%s.1H1", portName); // if((foo = fopen(solname, "rb")) == NULL){ // printf("Could not open File %s \n", solname); // exit(1); // } // fread(&tmpCNT, sizeof(int ), 1, foo); // fread(&cc, sizeof(char ), 1, foo); // fread(&cc, sizeof(char ), 1, foo); // fread(&tmpCNT, sizeof(int ), 1, foo); // fread(&gamma, sizeof(fp_t ), 1, foo); // fread(&gamma, sizeof(fp_t ), 1, foo); // for(i = 0; i < 3; i++){ // fread(&tmpVTR, sizeof(vtr ), 1, foo); // } // fread(&modeIMP, sizeof(fp_t ), 1, foo); // // scaleF = modeIMP; // // scaleF = scaleF / impZ; // // scaleF = sqrt(scaleF); // scaleF = 1.0; // for(i = 0; i < 8; i++) // jval[i] = 0.0; // for(i = 0; i < faceCNT; i++){ // fc = fcArray[i]; // maketriMAP(fc, Part, triMAP, pC); // for(j = 0; j < 6; j++){ // fread(&tvtr, sizeof(cVtr ), 1, foo); // hvtr[j].setvtr(tvtr.x.real(), tvtr.y.real(), tvtr.z.real()); // hvtr[j] = hvtr[j] * scaleF; // jvtr[j].setvtr(hvtr[j].gety() * (-1.0), hvtr[j].getx(), 0.0); // } // fc->P2toH1(jvtr, jval, coord); // fc->makeElemMatrix(prop, coord, 8, &elemM); // for(j = 0; j < 8; j++){ // if(triMAP[j] < 0) // continue; // rhs = 0.0; // for(k = 0; k < 8; k++){ // rhs = rhs + jval[k] * elemM.getEntry(j, k); // } // portY.addentry(triMAP[j], rhs * cval); // } // } // fclose(foo); // } struct dbl_vtr{ double x,y,z; }; struct dbl_cvtr{ complex x,y,z; }; void portMesh::makeRHS_E(){ FILE *foo; char solname[StrOutput], cc; int i, j, tmpCNT, triMAP[8]; vtr nvtr[2]; dbl_vtr tmpVTR; vtr evtr[NumOfEdges]; dbl_cvtr tvtr; fp_t cval; face *fc; fp_t scaleF; double gamma_,modeIMP_; sprintf(solname, "%s.1E1", portName); if((foo = fopen(solname, "rb")) == NULL){ printf("Could not open File %s \n", solname); exit(1); } fread(&tmpCNT, sizeof(int), 1, foo); fread(&cc, sizeof(char), 1, foo); fread(&cc, sizeof(char), 1, foo); fread(&tmpCNT, sizeof(int), 1, foo); fread(&gamma_, sizeof(double), 1, foo); fread(&gamma_, sizeof(double), 1, foo); for(i = 0; i < NumOfUnitaryVectors; i++){ fread(&tmpVTR, sizeof(dbl_vtr), 1, foo); } fread(&modeIMP_, sizeof(double), 1, foo); gamma = (fp_t)gamma_; modeIMP = (fp_t)modeIMP_; scaleF = 1.0; for(j = 0; j < NumOfEdges; j++){ evtr[j].setvtr(0.0, 0.0, 0.0); } for(i = 0; i < faceCNT; i++){ fc = fcArray[i]; for(j = 0; j < 6; j++){ fread(&tvtr, sizeof(dbl_cvtr), 1, foo); evtr[j] = coord.x_axis * (fp_t)(tvtr.x.real()) + coord.y_axis * (fp_t)(tvtr.y.real()) + coord.z_axis * (fp_t)(tvtr.z.real()); evtr[j] = evtr[j] * scaleF; } fc->Set_WgSolverExcitation_E(evtr); } fclose(foo); } void portMesh::makeRHS_H(){ FILE *foo; char solname[180], cc; int i, j, tmpCNT, triMAP[8]; vtr nvtr[2]; dbl_vtr tmpVTR; vtr hvtr[6]; dbl_cvtr tvtr; fp_t cval; face *fc; fp_t scaleF; double gamma_,modeIMP_; sprintf(solname, "%s.1H1", portName); if((foo = fopen(solname, "rb")) == NULL){ printf("Could not open File %s \n", solname); exit(1); } fread(&tmpCNT, sizeof(int), 1, foo); fread(&cc, sizeof(char), 1, foo); fread(&cc, sizeof(char), 1, foo); fread(&tmpCNT, sizeof(int), 1, foo); fread(&gamma_, sizeof(double), 1, foo); fread(&gamma_, sizeof(double), 1, foo); for(i = 0; i < 3; i++) fread(&tmpVTR, sizeof(dbl_vtr), 1, foo); fread(&modeIMP_, sizeof(double ), 1, foo); gamma = (fp_t)gamma_; modeIMP = (fp_t)modeIMP_; scaleF = 1.0; for(j = 0; j < 6; j++){ hvtr[j].setvtr(0.0, 0.0, 0.0); } for(i = 0; i < faceCNT; i++){ fc = fcArray[i]; for(j = 0; j < 6; j++){ fread(&tvtr, sizeof(dbl_cvtr), 1, foo); hvtr[j] = coord.x_axis * (fp_t)(tvtr.x.real()) + coord.y_axis * (fp_t)(tvtr.y.real()) + coord.z_axis * (fp_t)(tvtr.z.real()); hvtr[j] = hvtr[j] * scaleF; } fc->Set_WgSolverExcitation_H(hvtr); } fclose(foo); } void portMesh::makeCoordSystem(){ vtr zAxis = findFaceNormal(*(fcArray[0])); zAxis = zAxis * (-1.0); //point inside tetr(0) // zAxis = zAxis *(1.0); // forSMT // forthe SMT example somehow the zAxis was (0,0,1) but from the geometry // it should be (0,0,-1). So I flip the sign to make the right direction coord.setz_axis(zAxis); // I always assume the zAxis is the portDirection node* vertexNode = 0; node* edgeNode = 0; findNodes(&vertexNode, &edgeNode); if(vertexNode == 0){ cerr << "ERROR: PortMesh::makeCoordSystem: " << "Could not find a vertex node forport " << portName << endl; exit(1); } if(edgeNode == 0){ cerr << "ERROR: PortMesh::makeCoordSystem: " << "Could not find an edge node forport " << portName << endl; exit(1); } vtr O = vertexNode->getCoord(); coord.setO(O); vtr xAxis = edgeNode->getCoord() - O; coord.setx_axis(xAxis); vtr yAxis = zAxis * xAxis; coord.sety_axis(yAxis); vtr PortDirection = coord.getZAxis(); cout << portName << endl; cout << "( " << PortDirection.getx() << ", " << PortDirection.gety() << ", " << PortDirection.getz() << " )" << endl; fp_t Port_Direction_mag = sqrt(PortDirection.getx() * PortDirection.getx() + PortDirection.gety() * PortDirection.gety() + PortDirection.getz() * PortDirection.getz()); fp_t px = PortDirection.getx()/Port_Direction_mag; fp_t py = PortDirection.gety()/Port_Direction_mag; fp_t pz = PortDirection.getz()/Port_Direction_mag; PortDirection_vtr.setvtr(px,py,pz); for(int i = 0; i < faceCNT; i++) fcArray[i]->getbcPtr()->set_PortDirection( PortDirection_vtr.getx(), PortDirection_vtr.gety(), PortDirection_vtr.getz()); } vtr portMesh::findFaceNormal(face& Face){ int i; vtr vv0 = Face.getNode(0)->getCoord(); vtr vv1 = Face.getNode(1)->getCoord(); vtr vv2 = Face.getNode(2)->getCoord(); vtr nvtr = (vv1 - vv0) * (vv2 - vv0); nvtr = nvtr * 0.5; tetra& Tetra = Face.getTetra(0); if(Tetra == 0){ cerr << "ERROR: DgGroup::findFaceNormal: " << "Port face does not have a correct tetra link." << endl; exit(1); }else{ vv0.setvtr(0., 0., 0.); for(i = 0; i < 4; i++){ vv0 = vv0 + Tetra.getNode(i)->getCoord(); } vv0 = vv0 * 0.25; vv0 = vv0 - vv1; if(dotP(vv0, nvtr) > 0.) nvtr = nvtr * (-1.); } nvtr = nvtr * (1.0 / nvtr.magnitude()); return nvtr; } void portMesh::findNodes(node** vNode, node** eNode){ int i, j; vtr vv1; vtr vv2; for(i = 0; i < faceCNT; i++){ bool foundVertex = false; bool foundEdge = false; node* vertexNode = 0; node* edgeNode = 0; for(j = 0; j < 3; j++){ node* Node = fcArray[i]->getNodePtr(j); if(Node->getPType() == VERTEX_NODE){ if(foundVertex == true){ if(foundEdge == true){ vv1 = edgeNode->getCoord() - vertexNode->getCoord(); vv2 = Node->getCoord() - vertexNode->getCoord(); if(vv2.magnitude() < vv1.magnitude()){ edgeNode = Node; } }else{ foundEdge = true; edgeNode = Node; } }else{ vertexNode = Node; foundVertex = true; } } if(Node->getPType() == EDGE_NODE){ foundEdge = 1; edgeNode = Node; } } if((foundVertex) && (foundEdge)){ *vNode = vertexNode; *eNode = edgeNode; return; } } } void portMesh::writeVtk(){ int i, j; char hFileName[STRLEN]; char eFileName[STRLEN]; FILE* fdE; FILE* fdH; char cc; int dummy; dbl_vtr dummyVtr; complex gamma_; double modeIMP_; sprintf(eFileName, "%s.1E1", portName); if((fdE = fopen(eFileName, "rb")) == 0){ cerr << "ERROR: PortMesh::makeRhs: " << "Could not open file " << eFileName << " forread." << endl; exit(1); } fread(&dummy, sizeof(int), 1, fdE); fread(&cc, sizeof(char), 1, fdE); fread(&cc, sizeof(char), 1, fdE); fread(&dummy, sizeof(int), 1, fdE); fread(&gamma_, sizeof(complex), 1, fdE); for(i = 0; i < 3; i++) fread(&dummyVtr, sizeof(dbl_vtr), 1, fdE); fread(&modeIMP_, sizeof(double), 1, fdE); sprintf(hFileName, "%s.1H1", portName); if((fdH = fopen(hFileName, "rb")) == 0){ cerr << "ERROR: PortMesh::makeRhs: " << "Could not open file " << hFileName << " forread." << endl; exit(1); } fread(&dummy, sizeof(int), 1, fdH); fread(&cc, sizeof(char), 1, fdH); fread(&cc, sizeof(char), 1, fdH); fread(&dummy, sizeof(int), 1, fdH); fread(&gamma_, sizeof(complex), 1, fdH); for(i = 0; i < 3; i++) fread(&dummyVtr, sizeof(dbl_vtr), 1, fdH); fread(&modeIMP_, sizeof(double), 1, fdH); // fill the port field with averaged values vtr* eField = new vtr[nodeCNT]; vtr* hField = new vtr[nodeCNT]; int* count = new int[nodeCNT]; memset(count, 0, nodeCNT*sizeof(int)); int index; dbl_cvtr evtr; dbl_cvtr hvtr; vtr tmpE; // change here vtr tmpH; for(i = 0; i < faceCNT; i++){ for(j = 0; j < SEC_ORDER_FACE_NODES; j++){ fread(&evtr, sizeof(dbl_cvtr), 1, fdE); fread(&hvtr, sizeof(dbl_cvtr), 1, fdH); if(j < 3){ index = globToLocMap_->find(fcArray[i]->getNode(j)->getid())->second; tmpE = coord.x_axis * (fp_t)(evtr.x.real()) + coord.y_axis * (fp_t)(evtr.y.real()) + coord.z_axis * (fp_t)(evtr.z.real()); tmpH = coord.x_axis * (fp_t)(hvtr.x.real()) + coord.y_axis * (fp_t)(hvtr.y.real()) + coord.z_axis * (fp_t)(hvtr.z.real()); eField[index] = eField[index] + tmpE; hField[index] = hField[index] + tmpH; (count[index])++; } } } fclose(fdE); fclose(fdH); for(i = 0; i < nodeCNT; i++){ eField[i] = eField[i] / static_cast(count[i]); hField[i] = hField[i] / static_cast(count[i]); } node** locNodeArray = new node*[nodeCNT]; for(i = 0; i < nodeCNT; i++){ node& Node = *(ndArray[i]); int index = globToLocMap_->find(Node.getid())->second; locNodeArray[index] = new node(index, Node.getPType(), Node.getSingOrder(), Node.getCoord().getx(), Node.getCoord().gety(), Node.getCoord().getz()); } face** locFaceArray = new face*[faceCNT]; for(i = 0; i < faceCNT; i++){ face& Face = *(fcArray[i]); locFaceArray[i] = new face(Face); locFaceArray[i]->setFace( locNodeArray[globToLocMap_->find(Face.getNode(0)->getid())->second], locNodeArray[globToLocMap_->find(Face.getNode(1)->getid())->second], locNodeArray[globToLocMap_->find(Face.getNode(2)->getid())->second]); } VtkWriter vtkWriter(1.); vtkWriter.writeTriUg(portName, nodeCNT, locNodeArray, faceCNT, locFaceArray, eField, hField, 1); for(i = 0; i < nodeCNT; i++) delete locNodeArray[i]; delete [] locNodeArray; for(i = 0; i < faceCNT; i++) delete locFaceArray[i]; delete [] locFaceArray; delete [] eField; delete [] hField; delete [] count; }