// cviewDoc.cpp : implementation of the CcviewDoc class // #include "stdafx.h" #include #include #include "cv_problem.h" #include "femm.h" #include "xyplot.h" #include "cviewDoc.h" #include "cviewView.h" #include "MainFrm.h" #include "lua.h" #define AXISYMMETRIC 1 extern lua_State * lua; extern void *pcviewDoc; extern BOOL bLinehook; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CcviewDoc IMPLEMENT_DYNCREATE(CcviewDoc, CDocument) BEGIN_MESSAGE_MAP(CcviewDoc, CDocument) //{{AFX_MSG_MAP(CcviewDoc) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CcviewDoc construction/destruction double sqr(double x); CcviewDoc::CcviewDoc() { // set some default values for problem definition d_LineIntegralPoints=400; Depth=1/0.0254; Frequency=0; LengthUnits=0; ProblemType=FALSE; ProblemNote="Add comments here."; FirstDraw=-1; A_High=0.; A_Low=0.; A_lb=0.; A_ub=0.; extRo=extRi=extZo=0; Smooth=TRUE; NumList=NULL; ConList=NULL; bHasMask=FALSE; LengthConv=(double *)calloc(6,sizeof(double)); LengthConv[0]=0.0254; //inches LengthConv[1]=0.001; //millimeters LengthConv[2]=0.01; //centimeters LengthConv[3]=1.; //meters LengthConv[4]=2.54e-05; //mils LengthConv[5]=1.e-06; //micrometers Coords=FALSE; for(int i=0;i<9;i++) d_PlotBounds[i][0]=d_PlotBounds[i][1]= PlotBounds[i][0]=PlotBounds[i][1]=0; // determine path to bin directory BinDir=((CFemmApp *)AfxGetApp())->GetExecutablePath(); ScanPreferences(); // lua initialization stuff initalise_lua(); } CcviewDoc::~CcviewDoc() { int i; free(LengthConv); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } ProblemNote=v; q[0]=NULL; } // properties for axisymmetric external region if( _strnicmp(q,"[extzo]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extZo); q[0]=NULL; } if( _strnicmp(q,"[extro]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extRo); q[0]=NULL; } if( _strnicmp(q,"[extri]",7)==0){ v=StripKey(s); sscanf(v,"%lf",&extRi); q[0]=NULL; } // Point Properties if( _strnicmp(q,"",11)==0){ PProp.PointName="New Point Property"; PProp.V=0; PProp.qp=0; q[0]=NULL; } if( _strnicmp(q,"",11)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } PProp.PointName=v; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.V.re); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.V.im); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.qp.re); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&PProp.qp.im); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ nodeproplist.Add(PProp); q[0]=NULL; } // Boundary Properties; if( _strnicmp(q,"",11)==0){ BProp.BdryName="New Boundary"; BProp.BdryFormat=0; BProp.V; BProp.c0=0; BProp.c1=0; BProp.qs=0; BProp.InConductor=""; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } BProp.BdryName=v; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); sscanf(v,"%i",&BProp.BdryFormat); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.V.re); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.V.im); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.qs.re); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.qs.im); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c0.re); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c1.re); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c0.im); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&BProp.c1.im); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ lineproplist.Add(BProp); q[0]=NULL; } // Block Properties; if( _strnicmp(q,"",12)==0){ MProp.BlockName="New Material"; MProp.Kx=0; MProp.Ky=0; MProp.ex=0; MProp.ey=0; MProp.ox=0; MProp.oy=0; q[0]=NULL; } if( _strnicmp(q,"",10)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } MProp.BlockName=v; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.ox); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.oy); q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.ex.re); MProp.ex.im=0; q[0]=NULL; } if( _strnicmp(q,"",4)==0){ v=StripKey(s); sscanf(v,"%lf",&MProp.ey.re); MProp.ey.im=0; q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); double lt; sscanf(v,"%lf",<); lt=-atan(lt); MProp.ex=MProp.ex*exp(I*lt); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); double lt; sscanf(v,"%lf",<); lt=-atan(lt); MProp.ey=MProp.ey*exp(I*lt); q[0]=NULL; } if( _strnicmp(q,"",9)==0){ MProp.Kx=MProp.ox+I*2.*PI*Frequency*MProp.ex*eo; MProp.Ky=MProp.oy+I*2.*PI*Frequency*MProp.ey*eo; blockproplist.Add(MProp); q[0]=NULL; } // Circuit Properties if( _strnicmp(q,"",16)==0){ CProp.CircName="New Circuit"; CProp.V=0; CProp.q=0; CProp.CircType=0; q[0]=NULL; } if( _strnicmp(q,"",15)==0){ v=StripKey(s); k=(int) strlen(v); for(i=0;i0) for(i=k-1;i>=0;i--){ if(v[i]=='\"'){ v[i]=0; i=-1; } } CProp.CircName=v; q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.V.re); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.V.im); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.q.re); q[0]=NULL; } if( _strnicmp(q,"",5)==0){ v=StripKey(s); sscanf(v,"%lf",&CProp.q.im); q[0]=NULL; } if( _strnicmp(q,"",15)==0){ v=StripKey(s); sscanf(v,"%i",&CProp.CircType); q[0]=NULL; } if( _strnicmp(q,"",14)==0){ circproplist.Add(CProp); q[0]=NULL; } // Points list; if(_strnicmp(q,"[numpoints]",11)==0){ v=StripKey(s); sscanf(v,"%i",&k); for(i=0;i0) asegm.MaxSideLength=b; arclist.Add(asegm); } q[0]=NULL; } // read in list of holes; if(_strnicmp(q,"[numholes]",13)==0){ v=StripKey(s); sscanf(v,"%i",&k); if(k>0) { blk.BlockType=-1; blk.MaxArea=0; for(i=0;imeshelem[i].rsqr) meshelem[i].rsqr=b; } } // Find flux density in each element; for(i=0;iA_High) A_High=abs(meshnode[i].v); if (abs(meshnode[i].v)Re(A_ub)) A_ub.re=Re(meshnode[i].v); if (Re(meshnode[i].v)Im(A_ub)) A_ub.im=Im(meshnode[i].v); if (Im(meshnode[i].v)arg(u1)) { swa=ConList[i][k]; ConList[i][k]=ConList[i][k+1]; ConList[i][k+1]=swa; flg=TRUE; } } if(!flg) j=NumList[i]; } } // Postprocess to get smoothed nodal values of current for(i=0;id_PlotBounds[3][1]) d_PlotBounds[3][1]=b; if(bd_PlotBounds[4][1]) d_PlotBounds[4][1]=b; if(bd_PlotBounds[5][1]) d_PlotBounds[5][1]=b; if(bd_PlotBounds[6][1]) d_PlotBounds[6][1]=b; if(bd_PlotBounds[7][1]) d_PlotBounds[7][1]=b; if(bd_PlotBounds[8][1]) d_PlotBounds[8][1]=b; if(b=0) { if(meshelem[i].lbl!=k) { blocklist[meshelem[i].lbl].IsSelected=TRUE; if (!bMultiplyDefinedLabels) { CString msg; msg ="Some regions in the problem have been defined\n"; msg+="by more than one block label. These potentially\n"; msg+="problematic regions will appear as selected in\n"; msg+="the initial view."; MsgBox(msg); bMultiplyDefinedLabels=TRUE; } } } } FirstDraw=TRUE; return TRUE; } int CcviewDoc::InTriangle(double x, double y) { static int k; int j,hi,lo,sz; double z; sz=(int) meshelem.GetSize(); if((k<0) || (k>=sz)) k=0; // In most applications, the triangle we're looking // for is nearby the last one we found. Since the elements // are ordered in a banded structure, we want to check the // elements nearby the last one selected first. if (InTriangleTest(x,y,k)) return k; hi=k;lo=k; for(j=0;j=sz) hi=0; lo--; if(lo<0) lo=sz-1; z=(meshelem[hi].ctr.re-x)*(meshelem[hi].ctr.re-x) + (meshelem[hi].ctr.im-y)*(meshelem[hi].ctr.im-y); if(z<=meshelem[hi].rsqr) { if(InTriangleTest(x,y,hi)) { k=hi; return k; } } z=(meshelem[lo].ctr.re-x)*(meshelem[lo].ctr.re-x) + (meshelem[lo].ctr.im-y)*(meshelem[lo].ctr.im-y); if(z<=meshelem[lo].rsqr) { if(InTriangleTest(x,y,lo)) { k=lo; return k; } } } return (-1); } BOOL CcviewDoc::GetPointValues(double x, double y, CPointVals &u) { int k; k=InTriangle(x,y); if (k<0) return FALSE; GetPointValues(x,y,k,u); return TRUE; } BOOL CcviewDoc::GetPointValues(double x, double y, int k, CPointVals &u) { int i,n[3]; double a[3],b[3],c[3],da,ravg,aecf; for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; b[0]=meshnode[n[1]].y - meshnode[n[2]].y; b[1]=meshnode[n[2]].y - meshnode[n[0]].y; b[2]=meshnode[n[0]].y - meshnode[n[1]].y; c[0]=meshnode[n[2]].x - meshnode[n[1]].x; c[1]=meshnode[n[0]].x - meshnode[n[2]].x; c[2]=meshnode[n[1]].x - meshnode[n[0]].x; da=(b[0]*c[1]-b[1]*c[0]); ravg=LengthConv[LengthUnits]* (meshnode[n[0]].x + meshnode[n[1]].x + meshnode[n[2]].x)/3.; GetPointJ(x,y,u.Jx,u.Jy,meshelem[k]); u.v=0; u.Jx=0; u.Jy=0; for(i=0;i<3;i++){ // voltage u.v +=meshnode[n[i]].v*(a[i]+b[i]*x+c[i]*y)/(da); // total current density if(Smooth==TRUE) { u.Jx +=meshelem[k].jx[i]*(a[i]+b[i]*x+c[i]*y)/(da); u.Jy +=meshelem[k].jy[i]*(a[i]+b[i]*x+c[i]*y)/(da); } } if (Smooth==FALSE){ u.Jx=meshelem[k].Jx; u.Jx=meshelem[k].Jx; } // ac conductivity aecf=AECF(k,x+I*y); u.Kx=blockproplist[meshelem[k].blk].Kx/aecf; u.Ky=blockproplist[meshelem[k].blk].Ky/aecf; // electric field intensity u.Ex = u.Jx/(u.Kx); u.Ey = u.Jy/(u.Ky); // electrical permittivity u.ex = blockproplist[meshelem[k].blk].ex/aecf; u.ey = blockproplist[meshelem[k].blk].ey/aecf; // electric flux density u.Dx = u.Ex*u.ex*eo; u.Dy = u.Ey*u.ey*eo; // displacement current density u.Jdx = u.Dx*I*2.*PI*Frequency; u.Jdy = u.Dy*I*2.*PI*Frequency; // conductivity u.ox = blockproplist[meshelem[k].blk].ox/aecf; u.oy = blockproplist[meshelem[k].blk].oy/aecf; // conduction current density u.Jcx = u.Ex*u.ox; u.Jcy = u.Ey*u.oy; return TRUE; } void CcviewDoc::GetPointJ(double x, double y, CComplex &Jx, CComplex &Jy, CElement &elm) { // elm is a reference to the element that contains the point of interest. int i,n[3]; double da,a[3],b[3],c[3]; if(Smooth==FALSE){ Jx=elm.Jx; Jy=elm.Jy; return; } for(i=0;i<3;i++) n[i]=elm.p[i]; a[0]=meshnode[n[1]].x * meshnode[n[2]].y - meshnode[n[2]].x * meshnode[n[1]].y; a[1]=meshnode[n[2]].x * meshnode[n[0]].y - meshnode[n[0]].x * meshnode[n[2]].y; a[2]=meshnode[n[0]].x * meshnode[n[1]].y - meshnode[n[1]].x * meshnode[n[0]].y; b[0]=meshnode[n[1]].y - meshnode[n[2]].y; b[1]=meshnode[n[2]].y - meshnode[n[0]].y; b[2]=meshnode[n[0]].y - meshnode[n[1]].y; c[0]=meshnode[n[2]].x - meshnode[n[1]].x; c[1]=meshnode[n[0]].x - meshnode[n[2]].x; c[2]=meshnode[n[1]].x - meshnode[n[0]].x; da=(b[0]*c[1]-b[1]*c[0]); for(i=0,Jx=0,Jy=0;i<3;i++){ Jx+=(elm.jx[i]*(a[i]+b[i]*x+c[i]*y)/da); Jy+=(elm.jy[i]*(a[i]+b[i]*x+c[i]*y)/da); } } BOOL CcviewDoc::IsSameMaterial(int e1, int e2) { int b1,b2; b1=meshelem[e1].blk; b2=meshelem[e2].blk; // Are the same material trivially if they are the same block type if (b1==b2) return TRUE; // If the materials have the same Kx and Ky, we // can say that they are the same material; if ((blockproplist[b1].Kx==blockproplist[b2].Kx) && (blockproplist[b1].Ky==blockproplist[b2].Ky)) return TRUE; return FALSE; } void CcviewDoc::GetNodalJ(CComplex *xd, CComplex *yd, int N) { int i,j,k,n,m,p,eos,nos,qn; int lf,rt; double xi,yi,ii,xx,xy,yy,dx,dy,det; CComplex dv,iv,xv,yv,Ex,Ey; static int q[21]; CComplex kn; BOOL flag; for(i=0;i<3;i++) { j=meshelem[N].p[i]; lf=rt=-1; flag=FALSE; for(eos=0;eos2) nos=0; p=meshelem[n].p[nos]; // add this node to the list. We can have a max of 20 nodes, // which should never actually occur (usually about 6 to 8) if (qn<20) q[qn++]=p; // if this node has a fixed definition, get out of the loop; if((meshnode[j].Q!=-2) &&(meshnode[p].Q!=-2)){ lf=p; break; } m--; if(m<0) m=NumList[j]-1; } // catch some annoying special cases; if ((lf==rt) && (rt!=-1) && (meshnode[j].Q!=-2)) { // The node of interest is at the end of a conductor; not much to // do but punt; xd[i]=meshelem[N].Jx; yd[i]=meshelem[N].Jy; flag=TRUE; } else if ((rt!=-1) && (meshnode[j].Q!=-2) && (lf==-1)) { // Another instance of a node at the // end of a conductor; punt! xd[i]=meshelem[N].Jx; yd[i]=meshelem[N].Jy; flag=TRUE; } else if ((lf!=-1) && (meshnode[j].Q!=-2) && (rt==-1)) { // Another instance of a node at the // end of a conductor; punt! xd[i]=meshelem[N].Jx; yd[i]=meshelem[N].Jy; flag=TRUE; } else if((lf==-1) && (rt==-1) && (meshnode[j].Q!=-2)) { // The node of interest is an isolated charge. Again, not much to // do but punt; xd[i]=meshelem[N].Jx; yd[i]=meshelem[N].Jy; flag=TRUE; } else if((lf!=-1) && (rt!=-1) && (meshnode[j].Q!=-2)) { // The node of interest is on some boundary where the charge is fixed. // if the angle is shallow enough, we can just do the regular thing; // Otherwise, we punt. CComplex x,y; x=meshnode[lf].CC()-meshnode[j].CC(); x/=abs(x); y=meshnode[j].CC()-meshnode[rt].CC(); y/=abs(y); if(fabs(arg(x/y))>10.0001*PI/180.) { // if the angle is greater than 10 degrees, punt; xd[i]=meshelem[N].Jx; yd[i]=meshelem[N].Jy; flag=TRUE; } } if(flag==FALSE) { // The nominal case. // Fit a plane through the nodes in the list to solve for E. // Then, multiply by permittivity to get D. xi=yi=ii=xx=xy=yy=0; iv=0; xv=0; yv=0; q[qn++]=j; for(k=0;k0) { OnNewDocument(); SetPathName(pname,FALSE); OnOpenDocument(pname); } } int CcviewDoc::ClosestNode(double x, double y) { int i,j; double d0,d1; if(nodelist.GetSize()==0) return -1; j=0; d0=nodelist[0].GetDistance(x,y); for(i=0;iq[k]) && (k<(contour.GetSize()-1))) k++; u=(z-q[k-1])/(q[k]-q[k-1]); pt=contour[k-1]+u*(contour[k]-contour[k-1]); t=contour[k]-contour[k-1]; t/=abs(t); n = I*t; pt+=(n*1.e-06); if (elm<0) elm=InTriangle(pt.re,pt.im); else if (InTriangleTest(pt.re,pt.im,elm)==FALSE) { flag=FALSE; for(j=0;j<3;j++) for(m=0;m=0) flag=GetPointValues(pt.re,pt.im,elm,v); else flag=FALSE; p.M[i][0]=z; if(flag!=FALSE) { switch (PlotType) { case 0: p.M[i][1]=abs(v.v); p.M[i][2]=Re(v.v); p.M[i][3]=Im(v.v); break; case 1: p.M[i][1]=abs(abs(v.Jx)+I*abs(v.Jy)); break; case 2: yr=Re(v.Jx)+I*Re(v.Jy); yi=Im(v.Jx)+I*Im(v.Jy); p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); p.M[i][2]=Re(yr/n); p.M[i][3]=Re(yi/n); break; case 3: yr=Re(v.Jx)+I*Re(v.Jy); yi=Im(v.Jx)+I*Im(v.Jy); p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); p.M[i][2]=Re(yr/t); p.M[i][3]=Re(yi/t); break; case 4: p.M[i][1]=abs(abs(v.Jx/v.Kx)+I*abs(v.Jy/v.Ky)); break; case 5: yr=Re(v.Jx/v.Kx)+I*Re(v.Jy/v.Ky); yi=Im(v.Jx/v.Kx)+I*Im(v.Jy/v.Ky); p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); p.M[i][2]=Re(yr/n); p.M[i][3]=Re(yi/n); break; case 6: yr=Re(v.Jx/v.Kx)+I*Re(v.Jy/v.Ky); yi=Im(v.Jx/v.Kx)+I*Im(v.Jy/v.Ky); p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); p.M[i][2]=Re(yr/t); p.M[i][3]=Re(yi/t); break; case 7: p.M[i][1]=abs(abs(v.Jcx)+I*abs(v.Jcy)); break; case 8: yr=Re(v.Jcx)+I*Re(v.Jcy); yi=Im(v.Jcx)+I*Im(v.Jcy); p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); p.M[i][2]=Re(yr/n); p.M[i][3]=Re(yi/n); break; case 9: yr=Re(v.Jcx)+I*Re(v.Jcy); yi=Im(v.Jcx)+I*Im(v.Jcy); p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); p.M[i][2]=Re(yr/t); p.M[i][3]=Re(yi/t); break; case 10: p.M[i][1]=abs(abs(v.Jdx)+I*abs(v.Jdy)); break; case 11: yr=Re(v.Jdx)+I*Re(v.Jdy); yi=Im(v.Jdx)+I*Im(v.Jdy); p.M[i][1]=abs(Re(yr/n)+I*Re(yi/n)); p.M[i][2]=Re(yr/n); p.M[i][3]=Re(yi/n); break; case 12: yr=Re(v.Jdx)+I*Re(v.Jdy); yi=Im(v.Jdx)+I*Im(v.Jdy); p.M[i][1]=abs(Re(yr/t)+I*Re(yi/t)); p.M[i][2]=Re(yr/t); p.M[i][3]=Re(yi/t); break; default: p.M[i][1]=0; break; } } } free(q); } BOOL CcviewDoc::InTriangleTest(double x, double y, int i) { if ((i<0) || (i>=meshelem.GetSize())) return FALSE; int j,k; double z; for(j=0;j<3;j++) { k=j+1; if(k==3) k=0; // Case 1: p[k]>p[j] if (meshelem[i].p[k] > meshelem[i].p[j]) { z=(meshnode[meshelem[i].p[k]].x-meshnode[meshelem[i].p[j]].x)* (y-meshnode[meshelem[i].p[j]].y) - (meshnode[meshelem[i].p[k]].y-meshnode[meshelem[i].p[j]].y)* (x-meshnode[meshelem[i].p[j]].x); if(z<0) return FALSE; } //Case 2: p[k]0) return FALSE; } } return TRUE; } CPointVals::CPointVals() { v=0; // voltage Ex=0; Ey=0; // electric field intensity Dx=0; Dy=0; // electric flux density Jcx=0; Jcy=0; // conduction current density Jdx=0; Jdy=0; // displacement current density Jx=0; Jy=0; // ac current density Kx=0; Ky=0; // ac conductivity ox=0; oy=0; // dc conductivity ex=0; ey=0; // permittivity } CComplex CcviewDoc::Ctr(int i) { CComplex p,c; int j; for(j=0,c=0;j<3;j++){ p.Set(meshnode[meshelem[i].p[j]].x/3.,meshnode[meshelem[i].p[j]].y/3.); c+=p; } return c; } double CcviewDoc::ElmArea(int i) { int j,n[3]; double b0,b1,c0,c1; for(j=0;j<3;j++) n[j]=meshelem[i].p[j]; b0=meshnode[n[1]].y - meshnode[n[2]].y; b1=meshnode[n[2]].y - meshnode[n[0]].y; c0=meshnode[n[2]].x - meshnode[n[1]].x; c1=meshnode[n[0]].x - meshnode[n[2]].x; return (b0*c1-b1*c0)/2.; } double CcviewDoc::ElmArea(CElement *elm) { int j,n[3]; double b0,b1,c0,c1; for(j=0;j<3;j++) n[j]=elm->p[j]; b0=meshnode[n[1]].y - meshnode[n[2]].y; b1=meshnode[n[2]].y - meshnode[n[0]].y; c0=meshnode[n[2]].x - meshnode[n[1]].x; c1=meshnode[n[0]].x - meshnode[n[2]].x; return (b0*c1-b1*c0)/2.; } CComplex CcviewDoc::HenrotteVector(int k) { int i,n[3]; double b[3],c[3],da; CComplex v; for(i=0;i<3;i++) n[i]=meshelem[k].p[i]; b[0]=meshnode[n[1]].y - meshnode[n[2]].y; b[1]=meshnode[n[2]].y - meshnode[n[0]].y; b[2]=meshnode[n[0]].y - meshnode[n[1]].y; c[0]=meshnode[n[2]].x - meshnode[n[1]].x; c[1]=meshnode[n[0]].x - meshnode[n[2]].x; c[2]=meshnode[n[1]].x - meshnode[n[0]].x; da=(b[0]*c[1]-b[1]*c[0]); for(i=0,v=0;i<3;i++) v-=meshnode[n[i]].msk*(b[i]+I*c[i])/(da*LengthConv[LengthUnits]); // grad return v; } CComplex CcviewDoc::BlockIntegral(int inttype) { int i,k; CComplex c,y,z,Ex,Ey,B1,B2,F1,F2; double a,R,ex,ey,aecf; double r[3]; for(i=0,z=0;i=6) { a=ElmArea(i)*pow(LengthConv[LengthUnits],2.); if(ProblemType==1){ for(k=0;k<3;k++) r[k]=meshnode[meshelem[i].p[k]].x*LengthConv[LengthUnits]; R=(r[0]+r[1]+r[2])/3.; a*=(2.*PI*R); } else a*=Depth; B1=meshelem[i].Jx*eo/(blockproplist[meshelem[i].blk].Kx); B2=meshelem[i].Jy*eo/(blockproplist[meshelem[i].blk].Ky); c=HenrotteVector(i); switch(inttype){ case 6: // x (or r) direction Henrotte force, SS part. if(ProblemType!=0) break; y=(((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + 2.*Re(B1*conj(B2))*Im(c))/(2.*eo); if(Frequency!=0) y/=2.; y*=AECF(i); // correction for axisymmetric external region; z+=(a*y); break; case 7: // y (or z) direction Henrotte force, SS part. y=(((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + 2.*Re(B1*conj(B2))*Re(c))/(2.*eo); y*=AECF(i); // correction for axisymmetric external region; if(Frequency!=0) y/=2.; z+=(a*y); break; case 8: // x (or r) direction Henrotte force, 2x part. if(ProblemType!=0) break; z+=a*((((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*eo)) * AECF(i); break; case 9: // y (or z) direction Henrotte force, 2x part. z+= a*((((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*eo)) * AECF(i); break; case 10: // Henrotte torque, SS part. if(ProblemType!=0) break; F1 = (((B1*conj(B1)) - (B2*conj(B2)))*Re(c) + 2.*Re(B1*conj(B2))*Im(c))/(2.*eo); F2 = (((B2*conj(B2)) - (B1*conj(B1)))*Im(c) + 2.*Re(B1*conj(B2))*Re(c))/(2.*eo); for(c=0,k=0;k<3;k++) c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3.; y=Re(c)*F2 -Im(c)*F1; if(Frequency!=0) y/=2.; y*=AECF(i); z+=(a*y); break; case 11: // Henrotte torque, 2x part. if(ProblemType!=0) break; F1 = (((B1*B1) - (B2*B2))*Re(c) + 2.*B1*B2*Im(c))/(4.*eo); F2 = (((B2*B2) - (B1*B1))*Im(c) + 2.*B1*B2*Re(c))/(4.*eo); for(c=0,k=0;k<3;k++) c+=meshnode[meshelem[i].p[k]].CC()*LengthConv[LengthUnits]/3; z+=a*(Re(c)*F2 -Im(c)*F1)*AECF(i); break; default: break; } } } return z; } void CcviewDoc::LineIntegral(int inttype, CComplex *z) { // inttype Integral // 0 E.t // 1 J.n // 2 Contour length // 3 Average Voltage z[0]=0; z[1]=0; // inttype==0 => E.t if(inttype==0){ CPointVals u; int k; k=(int) contour.GetSize(); GetPointValues(contour[0].re,contour[0].im, u); z[0] = u.v; GetPointValues(contour[k-1].re,contour[k-1].im,u); z[0]-= u.v; } // inttype==1 => J.n if(inttype==1){ CComplex n,t,pt,Fn; CPointVals v; double dz,u,d; int i,j,k,m,elm; int NumPlotPoints=d_LineIntegralPoints; BOOL flag; z[0]=0; z[1]=0; z[2]; z[3]=0; for(k=1;k=0) flag=GetPointValues(pt.re,pt.im,elm,v); else flag=FALSE; if(flag==TRUE){ Fn = (v.Jx.re+I*v.Jy.re)/n + I*(v.Jx.im+I*v.Jy.im)/n; if (ProblemType==AXISYMMETRIC) d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); else d=Depth*LengthConv[LengthUnits]; z[0]+=(Fn*dz*d); z[1]+=dz*d; } } } z[1]=z[0]/z[1]; // Average J.n over the surface; } // inttype==2 => Contour Length if(inttype==2){ int i,k; k=(int) contour.GetSize(); for(i=0,z[0]=0;i Average Voltage if(inttype==3){ CComplex pt; CPointVals v; double dz,u,d; int i,j,k,m,elm; int NumPlotPoints=d_LineIntegralPoints; BOOL flag; z[0]=0; z[1]=0; for(k=1;k=0) flag=GetPointValues(pt.re,pt.im,elm,v); else flag=FALSE; if(flag==TRUE){ if (ProblemType==AXISYMMETRIC) d=2.*PI*pt.re*sq(LengthConv[LengthUnits]); else d=Depth*LengthConv[LengthUnits]; z[0]+=(v.v*dz*d); z[1]+=dz*d; } } } z[0]=z[0]/z[1]; // Average voltage over the surface; } // inttype==4 => Stress Tensor Force if(inttype==4){ CComplex n,t,pt,En,Dn,DE,dF1,dF2; CPointVals v; double dz,dza,u; int i,j,k,m,elm; int NumPlotPoints=d_LineIntegralPoints; BOOL flag; for(i=0;i<4;i++) z[i]=0; for(k=1;k=0) flag=GetPointValues(pt.re,pt.im,elm,v); else flag=FALSE; if(flag==TRUE){ En=n.re*v.Ex + n.im*v.Ey; Dn=n.re*v.Dx + n.im*v.Dy; DE = v.Dx*v.Ex + v.Dy*v.Ey; dF1 = v.Ex*Dn + v.Dx*En - n.re*DE; dF2 = v.Ey*Dn + v.Dy*En - n.im*DE; dza=dz*LengthConv[LengthUnits]; if(ProblemType==1){ dza*=2.*PI*pt.re*LengthConv[LengthUnits]; dF1=0; } else dza*=Depth; z[0]+=(dF1*dza/4.); z[1]+=(dF2*dza/4.); DE = v.Dx*v.Ex.Conj() +v.Dy*v.Ey.Conj(); if (ProblemType!=1) dF1 = v.Ex*Dn.Conj() + v.Dx*En.Conj() - n.re*DE; dF2= v.Ey*Dn.Conj() + v.Dy*En.Conj() - n.im*DE; z[2]+=(dF1*dza/4.); z[3]+=(dF2*dza/4.); } } } } // inttype==5 => Stress Tensor Torque if(inttype==5){ CComplex n,t,pt,En,Dn,DE,dF1,dF2,dT; CPointVals v; double dz,dza,u; int i,j,k,m,elm; int NumPlotPoints=d_LineIntegralPoints; BOOL flag; for(i=0;i<2;i++) z[i].Set(0,0); for(k=1;k=0) flag=GetPointValues(pt.re,pt.im,elm,v); else flag=FALSE; if(flag==TRUE) { En=n.re*v.Ex + n.im*v.Ey; Dn=n.re*v.Dx + n.im*v.Dy; DE = v.Dx*v.Ex + v.Dy*v.Ey; dF1 = v.Ex*Dn + v.Dx*En - n.re*DE; dF2 = v.Ey*Dn + v.Dy*En - n.im*DE; dT=pt.re*dF2 - dF1*pt.im; dza=dz*LengthConv[LengthUnits]*LengthConv[LengthUnits]; z[0]+=(dT*dza*Depth/4.); DE = v.Dx*v.Ex.Conj() +v.Dy*v.Ey.Conj(); dF1 = v.Ex*Dn.Conj() + v.Dx*En.Conj() - n.re*DE; dF2= v.Ey*Dn.Conj() + v.Dy*En.Conj() - n.im*DE; dT= pt.re*dF2 - dF1*pt.im ; z[1]+=(dT*dza*Depth/4.); } } } } return; } int CcviewDoc::ClosestArcSegment(double x, double y) { double d0,d1; int i,j; if(arclist.GetSize()==0) return -1; j=0; d0=ShortestDistanceFromArc(CComplex(x,y),arclist[0]); for(i=0;i0) && (z1.) t=1.; if (t<0.) t=0.; x[2]=x[0]+t*(x[1]-x[0]); y[2]=y[0]+t*(y[1]-y[0]); return sqrt((p-x[2])*(p-x[2]) + (q-y[2])*(q-y[2])); } BOOL CcviewDoc::ScanPreferences() { FILE *fp; CString fname; fname=BinDir+"cview.cfg"; fp=fopen(fname,"rt"); if (fp!=NULL) { BOOL flag=FALSE; char s[1024]; char q[1024]; char *v; // parse the file while (fgets(s,1024,fp)!=NULL) { sscanf(s,"%s",q); if( _strnicmp(q,"",20)==0) { v=StripKey(s); sscanf(v,"%i",&d_LineIntegralPoints); q[0]=NULL; } } fclose(fp); } else return FALSE; return TRUE; } void CcviewDoc::BendContour(double angle, double anglestep) { if (angle==0) return; if (anglestep==0) anglestep=1; int k,n; double d,tta,dtta,R; CComplex c,a0,a1; // check to see if there are at least enough // points to have made one line; k=(int) contour.GetSize()-1; if (k<1) return; // restrict the angle of the contour to 180 degrees; if ((angle<-180.) || (angle>180.)) return; n=(int) ceil(fabs(angle/anglestep)); tta=angle*PI/180.; dtta=tta/((double) n); // pop last point off of the contour; a1=contour[k]; contour.RemoveAt(k); a0=contour[k-1]; // compute location of arc center; // and radius of the circle that the // arc lives on. d=abs(a1-a0); R=d/(2.*sin(fabs(tta/2.))); if(tta>0) c=a0 + (R/d)*(a1-a0)*exp(I*(PI-tta)/2.); else c=a0+(R/d)*(a1-a0)*exp(-I*(PI+tta)/2.); // add the points on the contour for(k=1;k<=n;k++) contour.Add(c+(a0-c)*exp(k*I*dtta)); } double CcviewDoc::ShortestDistance(double p, double q, int segm) { double t,x[3],y[3]; x[0]=nodelist[linelist[segm].n0].x; y[0]=nodelist[linelist[segm].n0].y; x[1]=nodelist[linelist[segm].n1].x; y[1]=nodelist[linelist[segm].n1].y; t=((p-x[0])*(x[1]-x[0]) + (q-y[0])*(y[1]-y[0]))/ ((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])); if (t>1.) t=1.; if (t<0.) t=0.; x[2]=x[0]+t*(x[1]-x[0]); y[2]=y[0]+t*(y[1]-y[0]); return sqrt((p-x[2])*(p-x[2]) + (q-y[2])*(q-y[2])); } int CcviewDoc::ClosestSegment(double x, double y) { double d0,d1; int i,j; if(linelist.GetSize()==0) return -1; j=0; d0=ShortestDistance(x,y,0); for(i=0;i