Add flag 'power' to fcn setallvsources()
Add code to calculate the power dissipation in a device (top level instances, including X (subcircuit) invocations).
This commit is contained in:
parent
761da8ad0e
commit
458b6cf776
|
|
@ -22,13 +22,14 @@ extern char* search_plain_identifier(char* str, const char* identifier);
|
|||
|
||||
static char* get_terminal_name(char* element, char* numberstr, NGHASHPTR instances);
|
||||
static char* get_terminal_number(char* element, char* numberstr);
|
||||
static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall);
|
||||
static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall, bool power);
|
||||
|
||||
|
||||
/* Find any line starting with .probe: assemble all parameters like
|
||||
<empty> add V(0) current measure sources to all device nodes in addition to .save all
|
||||
alli add V(0) current measure sources to all device nodes in addition to .save all
|
||||
I(R1) add V(0) measure source to node 1 of a two-terminal device R1
|
||||
I(Q1) add V(0) measure sources to all nodes of a multi-terminal device Q1
|
||||
I(M4,3) add V(0) measure source to node 3 of a multi-terminal device M4
|
||||
Vd(R1) add E source inputs to measure voltage difference to both terminals of a two-terminal device R1
|
||||
Vd(X1:2:3) add E source inputs to terminals 2 and 3 of a multi-terminal device X1
|
||||
|
|
@ -745,7 +746,7 @@ void inp_probe(struct card* deck)
|
|||
else if (!node1 && numnodes > 2) {
|
||||
int err = 0;
|
||||
tfree(nodename1);
|
||||
err = setallvsources(tmpcard, instances, instname, numnodes, haveall);
|
||||
err = setallvsources(tmpcard, instances, instname, numnodes, haveall, FALSE);
|
||||
if (err) {
|
||||
fprintf(stderr, "Warning: Cannot set zero voltage sources,\n .probe %s will be ignored\n", wltmp->wl_word);
|
||||
}
|
||||
|
|
@ -807,6 +808,33 @@ void inp_probe(struct card* deck)
|
|||
tfree(nodename1);
|
||||
}
|
||||
}
|
||||
/* measure the power of a device */
|
||||
else if (ciprefix("p(", tmpstr))
|
||||
{
|
||||
char* instname;
|
||||
struct card* tmpcard;
|
||||
int numnodes;
|
||||
|
||||
tmpstr += 2;
|
||||
instname = gettok_noparens(&tmpstr);
|
||||
tmpcard = nghash_find(instances, instname);
|
||||
if (!tmpcard) {
|
||||
fprintf(stderr, "Warning: Could not find the instance line for %s,\n .probe %s will be ignored\n", instname, wltmp->wl_word);
|
||||
continue;
|
||||
}
|
||||
char* thisline = tmpcard->line;
|
||||
numnodes = get_number_terminals(thisline);
|
||||
int err = 0;
|
||||
/* call fcn with power requested */
|
||||
err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE);
|
||||
if (err == 1) {
|
||||
fprintf(stderr, "Warning: Cannot set zero voltage sources,\n .probe %s will be ignored\n", wltmp->wl_word);
|
||||
}
|
||||
else if (err == 2) {
|
||||
fprintf(stderr, "Warning: Zero voltage sources already set,\n .probe %s will be ignored\n", wltmp->wl_word);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!haveall) {
|
||||
fprintf(stderr, "Warning: unknown .probe parameter %s,\n .probe %s will be ignored!\n", tmpstr, wltmp->wl_word);
|
||||
continue;
|
||||
|
|
@ -1183,18 +1211,53 @@ void modprobenames(INPtables* tab) {
|
|||
}
|
||||
}
|
||||
|
||||
static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instname, int numnodes, bool haveall)
|
||||
/* If a command like .probe i(Q1) is found, set 0 VSRC (voltage source) in series to all nodes of the device Q1.
|
||||
Polarity of VSRC is that its node 2 is directed towards the device, its node 1 towards the outer net connection.
|
||||
If .probe p(Q1) is found, flag power is true, then do additional power calculations:
|
||||
Define a reference voltage of an n-terminal device as Vref = (V(1) + V(2) +...+ V(n)) / n with terminal (node) voltages V(n).
|
||||
Calculate power PQ1 = (v(1) - Vref) * i1 + (V(2) - Vref) * i2 + ... + (V(n) - Vref) * in) with terminal currents in.
|
||||
See "Quantities of a Multiterminal Circuit Determined on the Basis of Kirchhoff’s Laws", M. Depenbrock,
|
||||
ETEP Vol. 8, No. 4, July/August 1998 */
|
||||
static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instname, int numnodes, bool haveall, bool power)
|
||||
{
|
||||
|
||||
struct card* card;
|
||||
char* newline;
|
||||
int nodenum;
|
||||
bool err = FALSE;
|
||||
int err = 0;
|
||||
wordlist * allsaves = NULL;
|
||||
|
||||
if (haveall)
|
||||
return 1;
|
||||
if (haveall && !power)
|
||||
return 2;
|
||||
|
||||
DS_CREATE(BVrefline, 200);
|
||||
DS_CREATE(Bpowerline, 200);
|
||||
DS_CREATE(Bpowersave, 200);
|
||||
|
||||
if (power) {
|
||||
/* For example: Bq1Vref q1Vref 0 V = 1/3*( */
|
||||
char numbuf[3];
|
||||
cadd(&BVrefline, 'B');
|
||||
sadd(&BVrefline, instname);
|
||||
sadd(&BVrefline, "Vref ");
|
||||
sadd(&BVrefline, instname);
|
||||
sadd(&BVrefline, "Vref 0 V = 1/");
|
||||
sadd(&BVrefline, _itoa(numnodes, numbuf, 10));
|
||||
sadd(&BVrefline, "*(");
|
||||
/* For example: Bq1power q1:power 0 V = */
|
||||
cadd(&Bpowerline, 'B');
|
||||
sadd(&Bpowerline, instname);
|
||||
sadd(&Bpowerline, "power ");
|
||||
sadd(&Bpowerline, instname);
|
||||
cadd(&Bpowerline, ':');
|
||||
sadd(&Bpowerline, "power 0 V = 0+");
|
||||
/* For example: q1:power */
|
||||
sadd(&Bpowersave, instname);
|
||||
cadd(&Bpowersave, ':');
|
||||
sadd(&Bpowersave, "power");
|
||||
}
|
||||
|
||||
/* Scan through all nodes of the device */
|
||||
for (nodenum = 1; nodenum <= numnodes; nodenum++) {
|
||||
int i;
|
||||
char* instline = tmpcard->line;
|
||||
|
|
@ -1218,16 +1281,46 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
|||
|
||||
card = insert_new_line(card, vline, 0, 0);
|
||||
|
||||
char* nodesaves;
|
||||
/* special treatment for xlines: keep the x if next char is a number */
|
||||
if (*instname == 'x' && !isdigit_c(instname[1])) {
|
||||
char* nodesaves = tprintf("%s:%s#branch", instname + 1, nodename1);
|
||||
nodesaves = tprintf("%s:%s#branch", instname + 1, nodename1);
|
||||
allsaves = wl_cons(nodesaves, allsaves);
|
||||
}
|
||||
else {
|
||||
char* nodesaves = tprintf("%s:%s#branch", instname, nodename1);
|
||||
nodesaves = tprintf("%s:%s#branch", instname, nodename1);
|
||||
allsaves = wl_cons(nodesaves, allsaves);
|
||||
}
|
||||
|
||||
if (power) {
|
||||
/* For example V(1)+V(2)+V(3)*/
|
||||
if (nodenum == 1)
|
||||
sadd(&BVrefline, "V(");
|
||||
else
|
||||
sadd(&BVrefline, "+V(");
|
||||
sadd(&BVrefline, newnode);
|
||||
cadd(&BVrefline, ')');
|
||||
/*For example: (V(node1)-V(q1Vref))*node1#branch+(V(node2)-V(q1Vref))*node2#branch */
|
||||
if (nodenum == 1)
|
||||
sadd(&Bpowerline, "(V(");
|
||||
else
|
||||
sadd(&Bpowerline, "+(V(");
|
||||
sadd(&Bpowerline, newnode);
|
||||
sadd(&Bpowerline, ")-V(");
|
||||
sadd(&Bpowerline, instname);
|
||||
sadd(&Bpowerline, "Vref))*i(vcurr_");
|
||||
sadd(&Bpowerline, instname);
|
||||
cadd(&Bpowerline, ':');
|
||||
sadd(&Bpowerline, nodename1);
|
||||
cadd(&Bpowerline, ':');
|
||||
sadd(&Bpowerline, nodenumstr);
|
||||
cadd(&Bpowerline, '_');
|
||||
sadd(&Bpowerline, strnode1);
|
||||
cadd(&Bpowerline, ')');
|
||||
|
||||
allsaves = wl_cons(copy(ds_get_buf(&Bpowersave)), allsaves);
|
||||
}
|
||||
|
||||
tfree(begstr);
|
||||
tfree(strnode1);
|
||||
tfree(newnode);
|
||||
|
|
@ -1243,5 +1336,15 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
|||
card = insert_new_line(card, newsaveline, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (power) {
|
||||
cadd(&BVrefline, ')');
|
||||
card = tmpcard->nextcard;
|
||||
card = insert_new_line(card, copy(ds_get_buf(&BVrefline)), 0, 0);
|
||||
card = insert_new_line(card, copy(ds_get_buf(&Bpowerline)), 0, 0);
|
||||
}
|
||||
|
||||
ds_free(&BVrefline);
|
||||
ds_free(&Bpowerline);
|
||||
ds_free(&Bpowersave);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue