new lumped elements using new CSPropLumpedElement CSXCAD-class

pull/1/head
Thorsten Liebig 2011-04-08 09:59:48 +02:00
parent 62acf5f1b3
commit 7b34a8706a
3 changed files with 322 additions and 0 deletions

View File

@ -824,6 +824,8 @@ int Operator::CalcECOperator( DebugFlags debugFlags )
CalcPEC();
Calc_LumpedElements();
bool PMC[6];
for (int n=0; n<6; ++n)
PMC[n] = m_BC[n]==1;
@ -1161,6 +1163,165 @@ bool Operator::Calc_EffMatPos(int ny, const unsigned int* pos, double* EffMat) c
return true;
}
bool Operator::Calc_LumpedElements()
{
vector<CSProperties*> props = CSX->GetPropertyByType(CSProperties::LUMPED_ELEMENT);
for (size_t i=0;i<props.size();++i)
{
CSPropLumpedElement* PLE = dynamic_cast<CSPropLumpedElement*>(props.at(i));
if (PLE==NULL)
return false; //sanity check: this should never happen!
vector<CSPrimitives*> prims = PLE->GetAllPrimitives();
for (size_t bn=0;bn<prims.size();++bn)
{
CSPrimBox* box = dynamic_cast<CSPrimBox*>(prims.at(bn));
if (box)
{ //calculate lumped element parameter
double C = PLE->GetCapacity();
if (C<=0)
C = NAN;
double R = PLE->GetResistance();
if (R<0)
R = NAN;
if ((isnan(R)) && (isnan(C)))
{
cerr << "Operator::Calc_LumpedElements(): Warning: Lumped Element R or C not specified! skipping. "
<< " ID: " << prims.at(bn)->GetID() << " @ Property: " << PLE->GetName() << endl;
break;
}
int ny = PLE->GetDirection();
if ((ny<0) || (ny>2))
{
cerr << "Operator::Calc_LumpedElements(): Warning: Lumped Element direction is invalid! skipping. "
<< " ID: " << prims.at(bn)->GetID() << " @ Property: " << PLE->GetName() << endl;
break;
}
int nyP = (ny+1)%3;
int nyPP = (ny+2)%3;
unsigned int uiStart[3];
unsigned int uiStop[3];
// snap to the native coordinate system
SnapToMesh(box->GetStartCoord()->GetNativeCoords(),uiStart);
SnapToMesh(box->GetStopCoord()->GetNativeCoords(),uiStop);
for (int n=0;n<3;++n)
{
if (uiStop[n]<uiStart[n])
{
unsigned int help = uiStart[n];
uiStart[n]=uiStop[n];
uiStop[n]=help;
}
}
if (uiStart[ny]==uiStop[ny])
{
cerr << "Operator::Calc_LumpedElements(): Warning: Lumped Element with zero (snapped) length is invalid! skipping. "
<< " ID: " << prims.at(bn)->GetID() << " @ Property: " << PLE->GetName() << endl;
break;
}
//calculate geometric property for this lumped element
unsigned int pos[3];
double unitGC=0;
int ipos=0;
for (pos[ny]=uiStart[ny];pos[ny]<uiStop[ny];++pos[ny])
{
double unitGC_Plane=0;
for (pos[nyP]=uiStart[nyP];pos[nyP]<=uiStop[nyP];++pos[nyP])
{
for (pos[nyPP]=uiStart[nyPP];pos[nyPP]<=uiStop[nyPP];++pos[nyPP])
{
// capacity/conductivity in parallel: add values
unitGC_Plane += GetEdgeArea(ny,pos)/GetEdgeLength(ny,pos);
}
}
//capacity/conductivity in series: add reciprocal values
unitGC += 1/unitGC_Plane;
}
unitGC = 1/unitGC;
bool caps = PLE->GetCaps();
double kappa = 0;
double epsilon = 0;
if (R>0)
kappa = 1 / R / unitGC;
if (C>0)
epsilon = C / unitGC;
if (epsilon< __EPS0__)
{
cerr << "Operator::Calc_LumpedElements(): Warning: Lumped Element capacity is too small for its size! skipping. "
<< " ID: " << prims.at(bn)->GetID() << " @ Property: " << PLE->GetName() << endl;
C = 0;
if (isnan(R))
break;
}
for (pos[ny]=uiStart[ny];pos[ny]<uiStop[ny];++pos[ny])
{
for (pos[nyP]=uiStart[nyP];pos[nyP]<=uiStop[nyP];++pos[nyP])
{
for (pos[nyPP]=uiStart[nyPP];pos[nyPP]<=uiStop[nyPP];++pos[nyPP])
{
ipos = MainOp->SetPos(pos[0],pos[1],pos[2]);
if (C>0)
EC_C[ny][ipos] = epsilon * GetEdgeArea(ny,pos)/GetEdgeLength(ny,pos);
if (R>0)
EC_G[ny][ipos] = kappa * GetEdgeArea(ny,pos)/GetEdgeLength(ny,pos);
if (R==0) //make lumped element a PEC if resistance is zero
{
SetVV(ny,pos[0],pos[1],pos[2], 0 );
SetVI(ny,pos[0],pos[1],pos[2], 0 );
}
else //recalculate operator inside the lumped element
Calc_ECOperatorPos(ny,pos);
}
}
}
// setup metal caps
if (caps)
{
for (pos[nyP]=uiStart[nyP];pos[nyP]<=uiStop[nyP];++pos[nyP])
{
for (pos[nyPP]=uiStart[nyPP];pos[nyPP]<=uiStop[nyPP];++pos[nyPP])
{
pos[ny]=uiStart[ny];
SetVV(nyP,pos[0],pos[1],pos[2], 0 );
SetVI(nyP,pos[0],pos[1],pos[2], 0 );
++m_Nr_PEC[nyP];
SetVV(nyPP,pos[0],pos[1],pos[2], 0 );
SetVI(nyPP,pos[0],pos[1],pos[2], 0 );
++m_Nr_PEC[nyPP];
pos[ny]=uiStop[ny];
SetVV(nyP,pos[0],pos[1],pos[2], 0 );
SetVI(nyP,pos[0],pos[1],pos[2], 0 );
++m_Nr_PEC[nyP];
SetVV(nyPP,pos[0],pos[1],pos[2], 0 );
SetVI(nyPP,pos[0],pos[1],pos[2], 0 );
++m_Nr_PEC[nyPP];
}
}
}
}
else
cerr << "Operator::Calc_LumpedElements(): Warning: Primitves other than boxes are not supported for lumped elements! skipping "
<< prims.at(bn)->GetTypeName() << " ID: " << prims.at(bn)->GetID() << " @ Property: " << PLE->GetName() << endl;
}
}
return true;
}
void Operator::DumpExciationSignals()
{
Exc->DumpVoltageExcite("et");

View File

@ -188,6 +188,9 @@ protected:
//! Calc operator at certain \a pos
virtual void Calc_ECOperatorPos(int n, unsigned int* pos);
//! Calculate and setup lumped elements
virtual bool Calc_LumpedElements();
//store material properties for post-processing
float**** m_epsR;
float**** m_kappa;

View File

@ -0,0 +1,158 @@
%
% EXAMPLE / other / lumped elements
%
% This example demonstrates how to:
% - use lumped elements
%
%
% Tested with
% - Matlab 2009b
% - openEMS v0.0.21-3
%
% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
close all
clear
clc
%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f_max = 100e6;
f_excite = 300e6;
SimBox = 100;
mesh_size = 2;
Lumped.R = 1000;
Lumped.C = 10e-12;
% the parasitice inductance of the feeding has to be deduced with a R=0
% simulation
parasitic_L = 63e-9;
%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
openEMS_opts = '';
% openEMS_opts = [openEMS_opts ' --debug-material'];
% openEMS_opts = [openEMS_opts ' --debug-boxes'];
% openEMS_opts = [openEMS_opts ' --debug-operator'];
Sim_Path = 'tmp';
Sim_CSX = 'lumped.xml';
[status, message, messageid] = rmdir(Sim_Path,'s');
[status,message,messageid] = mkdir(Sim_Path);
%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FDTD = InitFDTD(30000,1e-6);
FDTD = SetGaussExcite(FDTD,f_excite/2,f_excite/2);
BC = [1 1 1 1 1 1];
FDTD = SetBoundaryCond(FDTD,BC);
%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CSX = InitCSX();
mesh.x = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
mesh.y = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
mesh.z = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
CSX = DefineRectGrid(CSX, 1e-3,mesh);
%% create structure
% insert curve port
start = [ 10 -10 0];
stop = [ 10 10 0];
CSX = AddCurvePort(CSX,0,1,100,start,stop,'excite');
% insert lumped element
CSX = AddLumpedElement( CSX, 'Capacitor', 1, 'C', Lumped.C, 'R', Lumped.R);
start = [ -14 -4 -4];
stop = [ -6 4 4];
CSX = AddBox( CSX, 'Capacitor', 0, start, stop );
% insert feeding wire
CSX = AddMetal(CSX,'metal');
%first point
points(1,1) = -10;
points(2,1) = 4;
points(3,1) = 0;
%second point
points(1,2) = -10;
points(2,2) = 15;
points(3,2) = 0;
%3 point
points(1,end+1) = 10;
points(2,end) = 15;
points(3,end) = 0;
%4 point
points(1,end+1) = 10;
points(2,end) = 10;
points(3,end) = 0;
CSX = AddCurve(CSX,'metal', 10, points);
points(2,:) = -1*points(2,:);
CSX = AddCurve(CSX,'metal', 10, points);
%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
% CSXGeomPlot([Sim_Path '/' Sim_CSX]);
%% run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
%% postproc & do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f = linspace(1e6,f_max,1001);
w = 2*pi*f;
% read currents and voltages
U = ReadUI('port_ut1','tmp/',f);
I = ReadUI('port_it1','tmp/',f);
% calculate analytic impedance
if (Lumped.R>=0)
Z_a = Lumped.R*(1-1i*w*Lumped.C*Lumped.R)./(1+(w*Lumped.C*Lumped.R).^2);
else
Z_a = -1i./(w*Lumped.C);
end
% calculate numerical impedance
Z = U.FD{1}.val./I.FD{1}.val;
% remove parasitic feeding effects
Z = Z - 1i*w*parasitic_L;
L = imag(Z)./w;
C = -1./(w.*imag(Z));
C(find(C<0)) = nan;
L(find(L<0)) = nan;
R = real(Z);
subplot(2,1,1);
plot(f*1e-6,C*1e12,'Linewidth',2);
xlabel('frequency (MHz)');
ylabel('capacitance (pF)');
grid on;
subplot(2,1,2);
plot(f*1e-6,L*1e9,'Linewidth',2);
xlabel('frequency (MHz)');
ylabel('inductance (nH)');
grid on;
figure();
plot(f*1e-6,R,'Linewidth',2);
hold on
plot(f*1e-6,imag(Z),'r--','Linewidth',2);
plot(f*1e-6,real(Z_a),'g-.','Linewidth',1);
plot(f*1e-6,imag(Z_a),'m--','Linewidth',1);
xlabel('frequency (MHz)');
ylabel('resistance (Ohm)');
grid on;
legend( '\Re\{Z\}','\Im\{Z\}','\Re\{Z_{analytisch}\}','\Im\{Z_{analytisch}\}', 'location', 'northeast' )
figure();
errorR = (R-real(Z_a))./R*100;
errorX = (imag(Z)-imag(Z_a))./imag(Z)*100;
plot(f*1e-6,errorR,'Linewidth',2);
hold on
grid on;
plot(f*1e-6,errorX,'r--','Linewidth',2);
xlabel('frequency (MHz)');
ylabel('error (%)');