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:
Holger Vogt 2022-04-23 20:07:52 +02:00
parent 761da8ad0e
commit 458b6cf776
1 changed files with 112 additions and 9 deletions

View File

@ -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 Kirchhoffs 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;
}