#include"stdafx.h" #include #include #include "fkn.h" #include "fknDlg.h" #include "complex.h" #include "mesh.h" #include "spars.h" #include "FemmeDocCore.h" // #define NEWTON // since all node positions were converted to units of cm // the proper LengthConv is converts centimeters to meters #define LengthConv 0.01 double Power(double x, int y); void CFemmeDocCore::GetPrev2DB(int k, double &B1p, double &B2p) { int i,n[3]; double b[3],c[3],da; for(i=0;i<3;i++) n[i]=meshele[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]); B1p=0; B2p=0; for(i=0;i<3;i++) { B1p+=Aprev[n[i]]*c[i]/(da*LengthConv); B2p-=Aprev[n[i]]*b[i]/(da*LengthConv); } } BOOL CFemmeDocCore::Harmonic2D(CBigComplexLinProb &L) { int i,j,k,ww,s,pctr; CComplex Mx[3][3],My[3][3],Mxy[3][3]; CComplex Me[3][3],be[3]; // element matrices; double l[3],p[3],q[3]; // element shape parameters; int n[3]; // numbers of nodes for a particular element; double a,r,t,x,y,B,w,res,lastres,ds,Cduct; CComplex K,mu,dv,B1,B2,v[3],u[3],mu1,mu2,lag,halflag,deg45,Jv; CComplex **Mu,*V_old; double c=PI*4.e-05; double units[]={2.54,0.1,1.,100.,0.00254,1.e-04}; CElement *El; int Iter=0; BOOL LinearFlag=TRUE; BOOL bIncremental=FALSE; if (PrevSoln.GetLength()>0) bIncremental=TRUE; res=0; // #ifndef NEWTON CComplex murel,muinc; // #else; CComplex Mnh[3][3]; CComplex Mna[3][3]; CComplex Mns[3][3]; // #endif CComplex Mn[3][3]; deg45=1+I; w=Frequency*2.*PI; CComplex *CircInt1,*CircInt2,*CircInt3; // Can't handle LamType==1 or LamType==2 in AC problems. // Detect if this is being attempted. for(i=0;i0) { CircInt1=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); CircInt2=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); CircInt3=(CComplex *)calloc(NumCircProps,sizeof(CComplex)); for(i=0;i=0) if(labellist[meshele[i].lbl].InCircuit!=-1){ El=&meshele[i]; // get element area; for(k=0;k<3;k++) n[k]=El->p[k]; p[0]=meshnode[n[1]].y - meshnode[n[2]].y; p[1]=meshnode[n[2]].y - meshnode[n[0]].y; p[2]=meshnode[n[0]].y - meshnode[n[1]].y; q[0]=meshnode[n[2]].x - meshnode[n[1]].x; q[1]=meshnode[n[0]].x - meshnode[n[2]].x; q[2]=meshnode[n[1]].x - meshnode[n[0]].x; a=(p[0]*q[1]-p[1]*q[0])/2.; // r=(meshnode[n[0]].x+meshnode[n[1]].x+meshnode[n[2]].x)/3.; // if coils are wound, they act like they have // a zero "bulk" conductivity... Cduct=blockproplist[El->blk].Cduct; if (labellist[El->lbl].bIsWound) Cduct=0; // evaluate integrals; // total cross-section of circuit; CircInt1[labellist[El->lbl].InCircuit]+=a; // integral of conductivity over the circuit; CircInt2[labellist[El->lbl].InCircuit]+=a*Cduct; // integral of applied J over current; CircInt3[labellist[El->lbl].InCircuit]+= (blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji)*a*100.; } } for(i=0;iSetDlgItemText(IDC_FRAME1,"Matrix Construction"); TheView->m_prog1.SetPos(0); pctr=0; if(Iter>0) L.Wipe(); // first, tack in air gap element contributions for(i=0;ico) { ci=ci-co; co=0; } else{ ci=1-co+ci; co=1; } // build the element matrix for each quad element in the annulus (same for each element) // matrix for quad element derived from serendipity element MG[0][0] = (5*Power (-1 + ci,2)*Power (ci,4)*(K + Ki))/48.; MG[0][1] = -((-1 + ci)*Power (ci,3)*(5*(-1 + ci*(-5 + 4*ci))*K + (-5 + ci*(-19 + 14*ci))*Ki))/48.; MG[0][2] = ((-1 + ci)*Power (ci,2)*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; MG[0][3] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-2 + ci*(-3 + 4*ci))*K + (2 + ci*(-3 + 2*ci))*Ki))/48.; MG[0][4] = (Power (-1 + ci,3)*Power (ci,3)*(5*K - Ki))/48.; MG[0][5] = ((-1 + ci)*Power (ci,2)*(-1 + co)*Power (co,2)*(K - 5*Ki))/48.; MG[0][6] = -((-1 + ci)*Power (ci,2)*co*((-1 + co*(-5 + 4*co))*K + (5 + (19 - 14*co)*co)*Ki))/48.; MG[0][7] = ((-1 + ci)*Power (ci,2)*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; MG[0][8] = -((-1 + ci)*Power (ci,2)*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (-2 + (3 - 2*co)*co)*Ki))/48.; MG[0][9] = ((-1 + ci)*Power (ci,2)*Power (-1 + co,2)*co*(K + Ki))/48.; MG[1][1] = (Power (ci,2)*(5*Power (1 + (5 - 4*ci)*ci,2)*K + (5 + ci*(38 + ci*(49 + 4*ci*(-29 + 11*ci))))*Ki))/48.; MG[1][2] = (-5*ci*(-1 + 2*ci)*(-2 + 3*(-1 + ci)*ci)*(-1 + ci*(-5 + 4*ci))*K + ci*(10 + ci*(39 - ci*(50 + ci*(85 + 6*ci*(-23 + 8*ci)))))*Ki)/48.; MG[1][3] = ((-1 + ci)*ci*(5*(2 + ci*(13 + ci*(3 + 16*(-2 + ci)*ci)))*K + (-2 + 5*ci*(1 + ci*(3 + 4*(-2 + ci)*ci)))*Ki))/48.; MG[1][4] = -(Power (-1 + ci,2)*Power (ci,2)*(5*(-1 + ci*(-5 + 4*ci))*K + Ki + ci*(-1 + 2*ci)*Ki))/48.; MG[1][5] = -(ci*(-1 + co)*Power (co,2)*((-1 + ci*(-5 + 4*ci))*K + (5 + (19 - 14*ci)*ci)*Ki))/48.; MG[1][6] = (ci*co*((-1 + ci*(-5 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (-5 + ci*(-19 + 14*ci) - 19*co + ci*(-77 + 58*ci)*co + 2*(7 + (29 - 22*ci)*ci)*Power (co,2))*Ki))/48.; MG[1][7] = (-(ci*(-1 + ci*(-5 + 4*ci))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + ci*(-10 + co*(-1 + 3*(7 - 4*co)*co) + ci*(-38 + co + 99*Power (co,2) - 60*Power (co,3)) + Power (ci,2)*(28 + 2*co*(-1 + 3*co*(-13 + 8*co))))*Ki)/48.; MG[1][8] = (ci*(-1 + co)*((-1 + ci*(-5 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co) + Power (ci,2)*(4 + 2*(9 - 10*co)*co) + ci*(-2 + co*(-21 + 22*co)))*Ki))/48.; MG[1][9] = -(ci*Power (-1 + co,2)*co*((-1 + ci*(-5 + 4*ci))*K + (-1 + ci - 2*Power (ci,2))*Ki))/48.; MG[2][2] = (5*Power (-2 + ci + 9*Power (ci,2) - 6*Power (ci,3),2)*K + (20 + (-1 + ci)*ci*(-4 + 3*(-1 + ci)*ci*(-25 + 24*(-1 + ci)*ci)))*Ki)/48.; MG[2][3] = (-5*(4 + Power (ci,2)*(-33 + ci*(18 + ci*(65 + 6*ci*(-13 + 4*ci)))))*K + (4 + Power (ci,2)*(39 - ci*(30 + ci*(115 + 6*ci*(-25 + 8*ci)))))*Ki)/48.; MG[2][4] = (Power (-1 + ci,2)*ci*(5*(2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (-2 + ci*(-5 + 3*ci*(-5 + 4*ci)))*Ki))/48.; MG[2][5] = ((-1 + co)*Power (co,2)*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K - (10 + ci*(1 + 3*ci*(-7 + 4*ci)))*Ki))/48.; MG[2][6] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*co*(-1 + co*(-5 + 4*co))*K) + co*(-10 - 38*co + 28*Power (co,2) + Power (ci,2)*(21 + 99*co - 78*Power (co,2)) + ci*(-1 + co - 2*Power (co,2)) + 12*Power (ci,3)*(-1 + co*(-5 + 4*co)))*Ki)/48.; MG[2][7] = ((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K - (2*(10 + co) + 6*Power (co,2)*(-7 + 4*co) + 3*Power (ci,2)*(-14 + co*(5 + (55 - 36*co)*co)) + ci*(2 + co*(5 + 3*(5 - 4*co)*co)) + 12*Power (ci,3)*(2 + co*(-1 - 9*co + 6*Power (co,2))))*Ki)/48.; MG[2][8] = (-((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*(2 + co - 7*Power (co,2) + 4*Power (co,3))*K) + (-1 + co)*(4 + 2*ci*(5 + 3*(5 - 4*ci)*ci) + 3*(-2 + ci*(3 + (17 - 12*ci)*ci))*co + 2*(2 + ci*(-7 + 3*ci*(-11 + 8*ci)))*Power (co,2))*Ki)/48.; MG[2][9] = (Power (-1 + co,2)*co*((2 + ci*(-1 - 9*ci + 6*Power (ci,2)))*K + (2 + ci*(5 + 3*(5 - 4*ci)*ci))*Ki))/48.; MG[3][3] = (Power (-1 + ci,2)*(5*Power (2 + (3 - 4*ci)*ci,2)*K + (20 + ci*(36 + ci*(-35 - 60*ci + 44*Power (ci,2))))*Ki))/48.; MG[3][4] = -(Power (-1 + ci,3)*ci*(5*(-2 + ci*(-3 + 4*ci))*K + (-10 + ci*(-9 + 14*ci))*Ki))/48.; MG[3][5] = -((-1 + ci)*(-1 + co)*Power (co,2)*((-2 + ci*(-3 + 4*ci))*K + (-2 + (3 - 2*ci)*ci)*Ki))/48.; MG[3][6] = ((-1 + ci)*co*((-2 + ci*(-3 + 4*ci))*(-1 + co*(-5 + 4*co))*K + (2 + ci*(-3 + 2*ci) - 2*co + ci*(-21 + 22*ci)*co + 2*(2 + (9 - 10*ci)*ci)*Power (co,2))*Ki))/48.; MG[3][7] = (-((2 + ci - 7*Power (ci,2) + 4*Power (ci,3))*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K) + (-1 + ci)*(4 + 2*co*(5 + 3*(5 - 4*co)*co) + ci*(-6 + 3*co*(3 + (17 - 12*co)*co)) + 2*Power (ci,2)*(2 + co*(-7 + 3*co*(-11 + 8*co))))*Ki)/48.; MG[3][8] = ((-1 + ci)*(-1 + co)*((-2 + ci*(-3 + 4*ci))*(-2 + co*(-3 + 4*co))*K + (-20 + 3*ci*(1 + 2*co)*(-6 + 5*co) + 2*co*(-9 + 14*co) + Power (ci,2)*(28 + 30*co - 44*Power (co,2)))*Ki))/48.; MG[3][9] = -((-1 + ci)*Power (-1 + co,2)*co*((-2 + ci*(-3 + 4*ci))*K + (10 + (9 - 14*ci)*ci)*Ki))/48.; MG[4][4] = (5*Power (-1 + ci,4)*Power (ci,2)*(K + Ki))/48.; MG[4][5] = (Power (-1 + ci,2)*ci*(-1 + co)*Power (co,2)*(K + Ki))/48.; MG[4][6] = -(Power (-1 + ci,2)*ci*co*((-1 + co*(-5 + 4*co))*K + (-1 + co - 2*Power (co,2))*Ki))/48.; MG[4][7] = (Power (-1 + ci,2)*ci*((2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (2 + co*(5 + 3*(5 - 4*co)*co))*Ki))/48.; MG[4][8] = -(Power (-1 + ci,2)*ci*(-1 + co)*((-2 + co*(-3 + 4*co))*K + (10 + (9 - 14*co)*co)*Ki))/48.; MG[4][9] = (Power (-1 + ci,2)*ci*Power (-1 + co,2)*co*(K - 5*Ki))/48.; MG[5][5] = (5*Power (-1 + co,2)*Power (co,4)*(K + Ki))/48.; MG[5][6] = -((-1 + co)*Power (co,3)*(5*(-1 + co*(-5 + 4*co))*K + (-5 + co*(-19 + 14*co))*Ki))/48.; MG[5][7] = ((-1 + co)*Power (co,2)*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (10 + co*(1 + 3*co*(-7 + 4*co)))*Ki))/48.; MG[5][8] = -(Power (-1 + co,2)*Power (co,2)*(5*(-2 + co*(-3 + 4*co))*K + (2 + co*(-3 + 2*co))*Ki))/48.; MG[5][9] = (Power (-1 + co,3)*Power (co,3)*(5*K - Ki))/48.; MG[6][6] = (Power (co,2)*(5*Power (1 + (5 - 4*co)*co,2)*K + (5 + co*(38 + co*(49 + 4*co*(-29 + 11*co))))*Ki))/48.; MG[6][7] = (-5*co*(-1 + 2*co)*(-2 + 3*(-1 + co)*co)*(-1 + co*(-5 + 4*co))*K + co*(10 + co*(39 - co*(50 + co*(85 + 6*co*(-23 + 8*co)))))*Ki)/48.; MG[6][8] = ((-1 + co)*co*(5*(2 + co*(13 + co*(3 + 16*(-2 + co)*co)))*K + (-2 + 5*co*(1 + co*(3 + 4*(-2 + co)*co)))*Ki))/48.; MG[6][9] = -(Power (-1 + co,2)*Power (co,2)*(5*(-1 + co*(-5 + 4*co))*K + Ki + co*(-1 + 2*co)*Ki))/48.; MG[7][7] = (5*Power (-2 + co + 9*Power (co,2) - 6*Power (co,3),2)*K + (20 + (-1 + co)*co*(-4 + 3*(-1 + co)*co*(-25 + 24*(-1 + co)*co)))*Ki)/48.; MG[7][8] = (-5*(4 + Power (co,2)*(-33 + co*(18 + co*(65 + 6*co*(-13 + 4*co)))))*K + (4 + Power (co,2)*(39 - co*(30 + co*(115 + 6*co*(-25 + 8*co)))))*Ki)/48.; MG[7][9] = (Power (-1 + co,2)*co*(5*(2 + co*(-1 - 9*co + 6*Power (co,2)))*K + (-2 + co*(-5 + 3*co*(-5 + 4*co)))*Ki))/48.; MG[8][8] = (Power (-1 + co,2)*(5*Power (2 + (3 - 4*co)*co,2)*K + (20 + co*(36 + co*(-35 - 60*co + 44*Power (co,2))))*Ki))/48.; MG[8][9] = -(Power (-1 + co,3)*co*(5*(-2 + co*(-3 + 4*co))*K + (-10 + co*(-9 + 14*co))*Ki))/48.; MG[9][9] = (5*Power (-1 + co,4)*Power (co,2)*(K + Ki))/48.; // Add each annulus element to the global stiffness matrix for(k=0;kagelist[i].totalArcElements){ nn[4]=agelist[i].node[1].n1; ww[4]=agelist[i].node[1].w1; } else{ nn[4]=agelist[i].node[k+2].n1; ww[4]=agelist[i].node[k+2].w1; } // outer nodes if ((k-1)<0){ nn[5]=agelist[i].node[agelist[i].totalArcElements-1].n2; ww[5]=agelist[i].node[agelist[i].totalArcElements-1].w2; } else{ nn[5]=agelist[i].node[k-1].n2; ww[5]=agelist[i].node[k-1].w2; } nn[6]=agelist[i].node[k].n2; nn[7]=agelist[i].node[k].n3; nn[8]=agelist[i].node[k+1].n3; ww[6]=agelist[i].node[k].w2; ww[7]=agelist[i].node[k].w3; ww[8]=agelist[i].node[k+1].w3; if((k+2)>agelist[i].totalArcElements){ nn[9]=agelist[i].node[1].n3; ww[9]=agelist[i].node[1].w3; } else{ nn[9]=agelist[i].node[k+2].n3; ww[9]=agelist[i].node[k+2].w3; } // fix antiperiodic weights... if ((k==0) && (agelist[i].BdryFormat==1)) { ww[0]=-ww[0]; ww[5]=-ww[5]; } if ((k==agelist[i].totalArcElements) && (agelist[i].BdryFormat==1)) { ww[4]=-ww[4]; ww[9]=-ww[9]; } // scale by weight to get periodic/antiperiodic right for(int ii=0;ii<10;ii++) for(int jj=ii;jj<10;jj++) L.AddTo(-MG[ii][jj]*ww[ii]*ww[jj],nn[ii],nn[jj]); //needs different sign than prob1big version } } // build element matrices using the matrices derived in Allaire's book. for(i=0;ipctr){ j=pctr*5; if (j>100) j=100; TheView->m_prog1.SetPos(j); pctr++; } // zero out Me, be; for(j=0;j<3;j++){ for(k=0;k<3;k++) { Me[j][k]=0; Mx[j][k]=0; My[j][k]=0; Mxy[j][k]=0; //#ifdef NEWTON if (ACSolver==1) { Mnh[j][k]=0; Mna[j][k]=0; Mns[j][k]=0; } //#endif Mn[j][k]=0; } be[j]=0; } // Determine shape parameters. // l == element side lengths; // p corresponds to the `b' parameter in Allaire // q corresponds to the `c' parameter in Allaire El=&meshele[i]; for(k=0;k<3;k++) n[k]=El->p[k]; p[0]=meshnode[n[1]].y - meshnode[n[2]].y; p[1]=meshnode[n[2]].y - meshnode[n[0]].y; p[2]=meshnode[n[0]].y - meshnode[n[1]].y; q[0]=meshnode[n[2]].x - meshnode[n[1]].x; q[1]=meshnode[n[0]].x - meshnode[n[2]].x; q[2]=meshnode[n[1]].x - meshnode[n[0]].x; for(j=0,k=1;j<3;k++,j++){ if (k==3) k=0; l[j]=sqrt( pow(meshnode[n[k]].x-meshnode[n[j]].x,2.) + pow(meshnode[n[k]].y-meshnode[n[j]].y,2.) ); } a=(p[0]*q[1]-p[1]*q[0])/2.; // x-contribution; K = (-1./(4.*a)); for(j=0;j<3;j++) for(k=j;k<3;k++) { Mx[j][k] += K*p[j]*p[k]; if (j!=k) Mx[k][j]+=K*p[j]*p[k]; } // y-contribution; K = (-1./(4.*a)); for(j=0;j<3;j++) for(k=j;k<3;k++) { My[j][k] +=K*q[j]*q[k]; if (j!=k) My[k][j]+=K*q[j]*q[k]; } // xy-contribution; K = (-1./(4.*a)); for(j=0;j<3;j++) for(k=j;k<3;k++) { Mxy[j][k] += K*(p[j]*q[k] + p[k]*q[j]); if (j!=k) Mxy[k][j] += K*(p[j]*q[k] + p[k]*q[j]); } // contribution from eddy currents; K=-I*a*w*blockproplist[meshele[i].blk].Cduct*c/12.; // in-plane laminated blocks appear to have no conductivity; // eddy currents are accounted for in these elements by their // frequency-dependent permeability. if((blockproplist[El->blk].LamType==0) && (blockproplist[El->blk].Lam_d>0)) K=0; // if this element is part of a wound coil, // it should have a zero "bulk" conductivity... if(labellist[El->lbl].bIsWound) K=0; for(j=0;j<3;j++) { for(k=j;k<3;k++){ Me[j][k]+=K; Me[k][j]+=K; } } // contributions to Me, be from derivative boundary conditions; for(j=0;j<3;j++){ if (El->e[j] >= 0) { if (lineproplist[El->e[j]].BdryFormat==2) { // conversion factor is 10^(-4) (I think...) K=(-0.0001*c*lineproplist[ El->e[j] ].c0*l[j]/6.); k=j+1; if(k==3) k=0; Me[j][j]+=2*K; Me[k][k]+=2*K; Me[j][k]+=K; Me[k][j]+=K; K=(lineproplist[ El->e[j] ].c1*l[j]/2.)*0.0001; be[j]+=K; be[k]+=K; } if (lineproplist[El->e[j]].BdryFormat==1) { ds=sqrt(2./(0.4*PI*w*lineproplist[El->e[j]].Sig* lineproplist[El->e[j]].Mu)); K=deg45/(-ds*lineproplist[El->e[j]].Mu*100.); K*=(l[j]/6.); k=j+1; if(k==3) k=0; Me[j][j]+=2*K; Me[k][k]+=2*K; Me[j][k]+=K; Me[k][j]+=K; } } } // contribution to be from current density in the block for(j=0;j<3;j++){ Jv=0; if(labellist[El->lbl].InCircuit>=0) { k=labellist[El->lbl].InCircuit; if(circproplist[k].Case==1) Jv=circproplist[k].J; if(circproplist[k].Case==0) Jv=-circproplist[k].dV*blockproplist[El->blk].Cduct; } K=-(blockproplist[El->blk].Jr+I*blockproplist[El->blk].Ji+Jv)*a/3.; be[j]+=K; if(labellist[El->lbl].InCircuit>=0){ k=labellist[El->lbl].InCircuit; if(circproplist[k].Case==2) L.b[NumNodes+k]+=K; } } // do Case 2 circuit stuff for element if(labellist[El->lbl].InCircuit>=0){ k=labellist[El->lbl].InCircuit; if(circproplist[k].Case==2){ K=-I*a*w*blockproplist[meshele[i].blk].Cduct*c; for(j=0;j<3;j++) L.Put(L.Get(n[j],NumNodes+k)+K/3.,n[j],NumNodes+k); L.Put(L.Get(NumNodes+k,NumNodes+k)+K,NumNodes+k,NumNodes+k); } } /////////////////////////////////////////////////////////////// // // New Nonlinear stuff // /////////////////////////////////////////////////////////////// // update permeability for the element; if (Iter==0){ k=meshele[i].blk; meshele[i].mu1=Mu[k][0]; meshele[i].mu2=Mu[k][1]; meshele[i].v12=0; if (blockproplist[k].BHpoints>0) { if (bIncremental==FALSE) { // There's no previous solution. This is a standard nonlinear time harmonic problem LinearFlag=FALSE; } else{ double B1p,B2p; // Get B from previous solution GetPrev2DB(i,B1p,B2p); B = sqrt(B1p*B1p + B2p*B2p); // look up incremental permeability and assign it to the element; blockproplist[k].IncrementalPermeability(B,w,muinc,murel); if (B==0) { meshele[i].mu1=muinc; meshele[i].mu2=muinc; meshele[i].v12=0; } else{ // need to actually compute B1 and B2 to build incremental permeability tensor meshele[i].mu1=B*B*muinc*murel/(B1p*B1p*murel + B2p*B2p*muinc); meshele[i].mu2=B*B*muinc*murel/(B1p*B1p*muinc + B2p*B2p*murel); meshele[i].v12=-B1p*B2p*(murel-muinc)/(B*B*murel*muinc); } } } } else{ k=meshele[i].blk; if ((blockproplist[k].LamType==0) && (meshele[i].mu1==meshele[i].mu2) &&(blockproplist[k].BHpoints>0)) { for(j=0,B1=0.,B2=0.;j<3;j++){ B1+=L.V[n[j]]*q[j]; B2+=L.V[n[j]]*p[j]; } B=c*sqrt(abs(B1*conj(B1))+abs(B2*conj(B2)))/(0.02*a); // correction for lengths in cm of 1/0.02 // #ifdef NEWTON if(ACSolver==1){ // find out new mu from saturation curve; blockproplist[k].GetBHProps(B,mu,dv); mu=1./(muo*mu); meshele[i].mu1=mu; meshele[i].mu2=mu; for(j=0;j<3;j++){ for(ww=0,v[j]=0;ww<3;ww++) v[j]+=(Mx[j][ww]+My[j][ww])*L.V[n[ww]]; } //Newton-like Iteration //Comment out for successive approx K=-200.*c*c*c*dv/a; for(j=0;j<3;j++) for(ww=0;ww<3;ww++) { // Still compute Mn, the approximate N-R matrix used in // the complex-symmetric approx. This will be useful // w.r.t. preconditioning. However, subtract it off of Mnh and Mna // so that there is no net addition. Mn[j][ww] =K*Re(v[j]*conj(v[ww])); Mnh[j][ww]= 0.5*Re(K)*v[j]*conj(v[ww])-Re(Mn[j][ww]); Mna[j][ww]=I*0.5*Im(K)*v[j]*conj(v[ww])-I*Im(Mn[j][ww]); Mns[j][ww]= 0.5*K*v[j]*v[ww]; } } //#else else{ // find out new mu from saturation curve; murel=1./(muo*blockproplist[k].Get_v(B)); muinc=1./(muo*blockproplist[k].GetdHdB(B)); // successive approximation; // K=muinc; // total incremental // K=murel; // total updated K=2.*murel*muinc/(murel+muinc); // averaged meshele[i].mu1=K; meshele[i].mu2=K; K=-(1./murel - 1/K); for(j=0;j<3;j++) for(ww=0;ww<3;ww++) Mn[j][ww]=K*(Mx[j][ww]+My[j][ww]); } //#endif } } // Apply correction for elements subject to prox effects if((blockproplist[meshele[i].blk].LamType>2) && (Iter==0)) { meshele[i].mu1=labellist[meshele[i].lbl].ProximityMu; meshele[i].mu2=labellist[meshele[i].lbl].ProximityMu; } // combine block matrices into global matrices; for(j=0;j<3;j++) for(k=0;k<3;k++){ // #ifdef NEWTON if (ACSolver==1){ Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k]*(El->v12) + Mn[j][k] ); be[j]+=(Mnh[j][k]+Mna[j][k]+Mn[j][k])*L.V[n[k]]; be[j]+=Mns[j][k]*L.V[n[k]].Conj(); } // #else else{ Me[j][k]+= (Mx[j][k]/(El->mu2) + My[j][k]/(El->mu1) + Mxy[j][k] * (El->v12)); be[j]+=Mn[j][k]*L.V[n[k]]; } // #endif } for (j=0;j<3;j++){ for (k=j;k<3;k++) { // L.Put(L.Get(n[j],n[k]) + Me[j][k],n[j],n[k]); L.AddTo(Me[j][k],n[j],n[k]); //#ifdef NEWTON if (ACSolver==1){ if (Mnh[j][k]!=0) L.Put(L.Get(n[j],n[k],1) + Mnh[j][k],n[j],n[k],1); if (Mns[j][k]!=0) L.Put(L.Get(n[j],n[k],2) + Mns[j][k],n[j],n[k],2); if (Mna[j][k]!=0) L.Put(L.Get(n[j],n[k],3) + Mna[j][k],n[j],n[k],3); } //#endif } L.b[n[j]]+=be[j]; } } // add in contribution from point currents; for(i=0;i=0){ K=0.01*(nodeproplist[meshnode[i].bc].Jr +I*nodeproplist[meshnode[i].bc].Ji); L.b[i]+=(-K); } // add in total current constraints for circuits; for(i=0;i=0) if((nodeproplist[meshnode[i].bc].Jr==0) && (nodeproplist[meshnode[i].bc].Ji==0)) { K= (nodeproplist[meshnode[i].bc].Ar + I*nodeproplist[meshnode[i].bc].Ai)/c; L.SetValue(i,K); } // apply fixed boundary conditions along segments; for(i=0;i=0) if(lineproplist[ meshele[i].e[j] ].BdryFormat==0) { if(Coords==0){ // first point on the side; x=meshnode[meshele[i].p[j]].x; y=meshnode[meshele[i].p[j]].y; x/=units[LengthUnits]; y/=units[LengthUnits]; s=meshele[i].e[j]; a=lineproplist[s].A0 + x*lineproplist[s].A1 + y*lineproplist[s].A2; K=(a/c)*exp(I*lineproplist[s].phi*DEG); L.SetValue(meshele[i].p[j],K); // second point on the side; x=meshnode[meshele[i].p[k]].x; y=meshnode[meshele[i].p[k]].y; x/=units[LengthUnits]; y/=units[LengthUnits]; s=meshele[i].e[j]; a=lineproplist[s].A0 + x*lineproplist[s].A1 + y*lineproplist[s].A2; K=(a/c)*exp(I*lineproplist[s].phi*DEG); L.SetValue(meshele[i].p[k],K); } else{ // first point on the side; x=meshnode[meshele[i].p[j]].x; y=meshnode[meshele[i].p[j]].y; r=sqrt(x*x+y*y); if ((x==0) && (y==0)) t=0; else t=atan2(y,x)/DEG; r/=units[LengthUnits]; s=meshele[i].e[j]; a=lineproplist[s].A0 + r*lineproplist[s].A1 + t*lineproplist[s].A2; K=(a/c)*exp(I*lineproplist[s].phi*DEG); L.SetValue(meshele[i].p[j],K); // second point on the side; x=meshnode[meshele[i].p[k]].x; y=meshnode[meshele[i].p[k]].y; r=sqrt(x*x+y*y); if((x==0) && (y==0)) t=0; else t=atan2(y,x)/DEG; r/=units[LengthUnits]; s=meshele[i].e[j]; a=lineproplist[s].A0 + r*lineproplist[s].A1 + t*lineproplist[s].A2; K=(a/c)*exp(I*lineproplist[s].phi*DEG); L.SetValue(meshele[i].p[k],K); } } } // "fix" diagonal entries associated with circuits that have // applied current or voltage that is known a priori // so that solver doesn't throw a "singular" flag for(j=0;j5) { if ((res>lastres) && (Relax>0.1)) Relax/=2.; else Relax+= 0.1 * (1. - Relax); for(j=0;jSetDlgItemText(IDC_FRAME2,outstr); j=(int) (100.*log10(res)/(log10(Precision)+2.)); if (j>100) j=100; TheView->m_prog2.SetPos(j); } // nonlinear iteration has to have a looser tolerance // than the linear solver--otherwise, things can't ever // converge. Arbitrarily choose 100*tolerance. if((res<100.*Precision) && Iter>0) LinearFlag=TRUE; Iter++; } while(LinearFlag==FALSE); for (i=0;i0){ free(CircInt1); free(CircInt2); free(CircInt3); } return TRUE; } BOOL CFemmeDocCore::WriteHarmonic2D(CBigComplexLinProb &L) { // write solution to disk; char c[1024]; FILE *fp,*fz; int i,k; double cf; double unitconv[]={2.54,0.1,1.,100.,0.00254,1.e-04}; // first, echo input .fem file to the .ans file; sprintf(c,"%s.fem",PathName); if((fz=fopen(c,"rt"))==NULL){ Sleep(500); if((fz=fopen(c,"rt"))==NULL){ MsgBox("Couldn't open %s.fem\n",PathName); return FALSE; } } sprintf(c,"%s.ans",PathName); if((fp=fopen(c,"wt"))==NULL){ Sleep(500); if((fp=fopen(c,"wt"))==NULL){ MsgBox("Couldn't write to %s.ans\n",PathName); return FALSE; } } while(fgets(c,1024,fz)!=NULL) fputs(c,fp); fclose(fz); // then print out node, line, and element information fprintf(fp,"[Solution]\n"); cf=unitconv[LengthUnits]; fprintf(fp,"%i\n",NumNodes); for(i=0;i