File: spOutput.mesa
Copyright (C) 1985 by Xerox Corporation. All rights reserved.
Last Edited by:
Sweetsun Chen, July 30, 1985 2:08:33 pm PDT
DIRECTORY
BasicTime USING [GMT, Now],
FS USING [StreamOpen],
IO USING [int, PutF, PutFR, real, Reset, rope, STREAM, time],
Labels USING [Set],
Plot USING [AddVector, CreateViewer, Vector, RealSequence, RopeSequence, PlotSpecRec],
Rope USING [Concat, FromRefText, ROPE],
spGlobals USING [argument, argumentPtr, branchPtr, OutputFileRoot, error, findNodeOrBranch, FlushCloseNil, getSignedNumber, Handle, makeStringNB, maxPlots, maxPrints, next, nodePtr, plotBlkPtr, plotBlk, printBlk, printBlkPtr, RefC, RefI, RefL, RefR, RefV, version],
ViewerTools USING [GetContents];
spOutput: CEDAR PROGRAM
IMPORTS BasicTime, FS, IO, Labels, Plot, Rope, spGlobals, ViewerTools
EXPORTS spGlobals=
BEGIN OPEN spGlobals;
initPlot: PUBLIC PROC[handle: Handle, tMin, tMax: REAL]= {
OPEN handle.vars;
iCurve: NAT;
rope: Rope.ROPE;
pl: plotBlkPtr;
FOR i: NAT IN [0..numPlots) DO
OPEN plots[i].plotSpec;
time← handle.vars.simTime;
file← Rope.Concat[OutputFileRoot[handle], IO.PutFR[".plot%g", IO.int[i]]];
bounds.xmin← tMin/plots[i].plotTimeRelTo;
bounds.xmax← tMax/plots[i].plotTimeRelTo;
legendEntries← NEW[Plot.RopeSequence[nCurvesMax]];
FOR j: NAT IN [0..nCurvesMax) DO legendEntries[j]← NIL; ENDLOOP;
iCurve← 0;
pl ← plots[i].plotList;
UNTIL pl = NIL DO
heading: Rope.ROPE;
heading← SELECT TRUE FROM
pl.arg.getComVal => "Value of ",
pl.arg.current => "Current through ",
pl.arg.dvdt => "Derivative of ",
ENDCASE => "Voltage at ";
rope← Rope.Concat[heading,
makeStringNB[handle, pl.arg.node, pl.arg.branch]];
legendEntries[iCurve]← IF pl.relativeTo = 1.0 THEN rope
ELSE IO.PutFR["%g/%g", IO.rope[rope], IO.real[pl.relativeTo]];
pl ← pl.nextBlk;
iCurve← iCurve + 1;
ENDLOOP;
plots[i].plotViewer← Plot.CreateViewer[
spec: plots[i].plotSpec,
iconic: i # 0,
inhibitDestroy: TRUE];
ENDLOOP;
}; -- initPlot
plotFromList: PUBLIC PROC[handle: Handle, t: REAL] = {
OPEN handle.vars;
FOR iPlot: NAT IN [0..numPlots) DO
iCurve: NAT← 0;
vector: Plot.Vector←
NEW[Plot.RealSequence[plots[iPlot].plotSpec.nCurvesMax + 1]];
p: plotBlkPtr← plots[iPlot].plotList;
vector[0]← t/plots[iPlot].plotTimeRelTo;
UNTIL p = NIL DO
iCurve← iCurve + 1;
vector[iCurve]← evaluateArgument[p.arg]/p.relativeTo;
p ← p.nextBlk;
ENDLOOP;
Plot.AddVector[plots[iPlot].plotViewer, vector];
ENDLOOP;
}; -- plotFromList
getPlotNum: PROC [handle: Handle] RETURNS[r: REAL← 1.0] = {
r← getSignedNumber[handle];
IF handle.vars.item = comma THEN next[handle] ELSE error[handle, 603,, FALSE]
}; -- getPlotNum
makePlotList: PUBLIC PROC[handle: Handle]= {
OPEN handle.vars;
I, D, cv: BOOL;
pb: plotBlkPtr;
n: nodePtr;
b: branchPtr;
IF numPlots >= maxPlots THEN {
error[handle, 632, FALSE];
numPlots ← numPlots - 1
};
IF item = leftB THEN next[handle] ELSE error[handle, 600];
plots[numPlots].plotSpec ← NEW[Plot.PlotSpecRec ← []];
IF item = string THEN {
plots[numPlots].plotSpec.title ← Rope.FromRefText[newString];
next[handle];
IF item = comma THEN next[handle] ELSE error[handle, 603,, FALSE]
};
IF item = colon THEN {
plots[numPlots].plotTimeRelTo← scale[handle];
IF item = comma THEN next[handle] ELSE error[handle, 603,, FALSE]
}
ELSE plots[numPlots].plotTimeRelTo ← 1.0;
plots[numPlots].plotSpec.bounds.ymin ← getPlotNum[handle];
plots[numPlots].plotSpec.bounds.ymax ← getPlotNum[handle];
IF plots[numPlots].plotSpec.bounds.ymin >= plots[numPlots].plotSpec.bounds.ymax
THEN error[handle, 630, FALSE];
plots[numPlots].plotList ← NIL;
plots[numPlots].plotSpec.nCurvesMax ← 0;
UNTIL item # name DO
plots[numPlots].plotSpec.nCurvesMax ← plots[numPlots].plotSpec.nCurvesMax + 1;
[n, b] ← findNodeOrBranch[handle];
IF n = NIL AND b = NIL THEN error[handle, 620]
ELSE {
I← b # NIL AND item = upArrow;
D← n # NIL AND item = quote;
cv← b # NIL AND item = atSign;
IF I OR D OR cv THEN next[handle];
pb← NEW[plotBlk←
[nextBlk: plots[numPlots].plotList,
relativeTo: scale[handle],
arg: NEW[argument← [FALSE, n, b, cv, D, I]]]
];
plots[numPlots].plotList← pb;
};
IF item = comma THEN next[handle] ELSE EXIT;
ENDLOOP;
IF item = rightB THEN next[handle] ELSE error[handle, 601, TRUE];
numPlots ← numPlots + 1;
}; -- makePlotList
PutMsgLine: PUBLIC PROC[handle: Handle, s: Rope.ROPE]= {
handle.msgStream.PutF["%g\n", IO.rope[s]];
}; -- PutMsgLine
evaluateArgument: PROC[a: argumentPtr] RETURNS[iv: REAL]= {
b: branchPtr;
IF a.getComVal THEN RETURN[a.branch.comVal];
IF a.node # NIL THEN
iv← IF a.dvdt THEN a.node.nHist.f0 ELSE a.node.nHist.y
ELSE {
b← a.branch;
IF a.current THEN
WITH b.body SELECT FROM
r: RefR =>
iv← (b.posNode.nHist.y - b.negNode.nHist.y)/b.comVal;
c: RefC =>
iv← (b.posNode.nHist.f0 - b.negNode.nHist.f0)*b.comVal;
l: RefL => iv← l.iHist.y/b.comVal;
v: RefV => iv← v.vsCurrent;
i: RefI => iv← b.comVal;
ENDCASE
ELSE iv← b.posNode.nHist.y - b.negNode.nHist.y;
};
}; -- evaluateArgument
initPrint: PUBLIC PROC[handle: Handle, time: BasicTime.GMT]= {
FOR i: NAT IN [0..handle.vars.numPrints) DO
output: IO.STREAM← handle.vars.prints[i].printStream;
output.PutF["* Simulation started at %g.\n", IO.time[time]];
ENDLOOP;
}; -- initPrint
printFromList: PUBLIC PROC[handle: Handle, ni: INT, t: REAL, printStep: BOOL]= {
i: NAT;
p: printBlkPtr;
r, trel: REAL;
FOR i IN [0..handle.vars.numPrints) DO
output: IO.STREAM← handle.vars.prints[i].printStream;
p← handle.vars.prints[i].printList;
trel← t/handle.vars.prints[i].printTimeRelTo;
output.PutF["%10.3e", IO.real[trel]];
IF printStep THEN output.PutF["(%2d)", IO.int[ni]];
UNTIL p=NIL DO
r← evaluateArgument[p.arg]/p.relativeTo;
output.PutF[" %10.3f", IO.real[r]];
p← p.nextBlk;
ENDLOOP;
output.PutF["\n"];
ENDLOOP;
}; -- printFromList
scale: PROC[handle: Handle] RETURNS[s: REAL← 1.0]= {
IF handle.vars.item=colon THEN {next[handle]; s← getSignedNumber[handle]};
}; -- scale
makePrintList: PUBLIC PROC[handle: Handle]= {
OPEN handle.vars;
I, D, cv: BOOL;
pb, pb2, pb3: printBlkPtr;
n: nodePtr;
b: branchPtr;
outFileNameRoot, outFileName, outFiles: Rope.ROPE;
IF numPrints >= maxPrints THEN {
error[handle, 631];
numPrints← numPrints - 1;
};
IF item=leftB THEN next[handle] ELSE error[handle, 600];
IF item=colon THEN {
prints[numPrints].printTimeRelTo← scale[handle];
IF item=comma THEN next[handle] ELSE error[handle, 603,, FALSE];
}
ELSE prints[numPrints].printTimeRelTo← 1.0;
prints[numPrints].printList← NIL;
UNTIL item # name DO
[n, b]← findNodeOrBranch[handle];
IF n=NIL AND b=NIL THEN error[handle, 620]
ELSE {
I← (b # NIL) AND item=upArrow; -- branch current
D← (n # NIL) AND item=quote; -- derivative of node voltage
cv← (b # NIL) AND item=atSign; -- branch value
IF I OR D OR cv THEN next[handle];
pb← NEW[printBlk←
[nextBlk: prints[numPrints].printList,
relativeTo: scale[handle],
arg: NEW[argument← [FALSE, n, b, cv, D, I]] ] ];
prints[numPrints].printList← pb;
};
IF item=comma THEN next[handle] ELSE EXIT;
ENDLOOP;
pb← NIL;
pb3← prints[numPrints].printList;
UNTIL pb3=NIL DO
pb2← pb3;
pb3← pb3.nextBlk;
pb2.nextBlk← pb;
pb← pb2;
ENDLOOP;
prints[numPrints].printList← pb;
outFileNameRoot← OutputFileRoot[handle];
outFileName← IO.PutFR["%g.out%g", IO.rope[outFileNameRoot], IO.int[numPrints]];
prints[numPrints].printStream←
FS.StreamOpen[fileName: outFileName, accessOptions: $create];
prints[numPrints].printStream.Reset[ ];
outFiles← IF numPrints=0 THEN outFileName
ELSE IO.PutFR["%g.out0...out%g", IO.rope[outFileNameRoot], IO.int[numPrints]];
Labels.Set[handle.output, outFiles];
prints[numPrints].printStream.PutF[
"** %g\n*\n* File: %g\n* Input: %g\n* Time: %g\n*\n",
IO.rope[version],
IO.rope[outFileName],
IO.rope[ViewerTools.GetContents[handle.input]],
IO.time[simTime]
];
numPrints← numPrints + 1;
IF item=rightB THEN next[handle] ELSE error[handle, 601, TRUE];
}; -- makePrintList
dumpAll: PUBLIC PROC[handle: Handle, t: REAL]= {
OPEN handle.vars;
dname: Rope.ROPE;
dump: IO.STREAM;
nodes: nodePtr← nodeList;
inds: branchPtr← inductorList;
dname← IO.PutFR["%g.dump", IO.rope[OutputFileRoot[handle]]];
dump← FS.StreamOpen[fileName: dname, accessOptions: $create];
dump.Reset[];
dump.PutF["ic[%f,\n", IO.real[t]];
UNTIL nodes=NIL DO
dump.PutF["%g← %f",
IO.rope[makeStringNB[handle, nodes, NIL, FALSE]],
IO.real[nodes.nHist.y]];
nodes← nodes.nextNode;
IF nodes # NIL THEN dump.PutF[",\n"] ELSE dump.PutF["\n"];
ENDLOOP;
UNTIL inds=NIL DO
indsBody: RefL← NARROW[inds.body];
dump.PutF["%g← %f",
IO.rope[makeStringNB[handle, NIL, inds, FALSE]],
IO.real[indsBody.iHist.y]];
inds← indsBody.nextInductor;
IF inds # NIL THEN IO.PutF[dump, ",\n"] ELSE IO.PutF[dump, "\n"];
ENDLOOP;
dump.PutF["];\n"];
handle.msgStream.PutF["Dumped into file %g at %g.\n",
IO.rope[dname], IO.time[]];
dump ← FlushCloseNil[dump];
}; -- dumpAll
END.
CHANGE LOG
Wilhelm, April 6, 1982 11: 36 AM
Barth, 7-May-82 10: 45: 07 PDT
Chen, June 12, 1984 6:59:26 pm PDT, cedarized.
Chen, July 22, 1985 8:09:51 pm PDT, => Cedar6.0.