11import simplify_algebra from './simplify_algebra.js'
2+
3+ function arrayContains ( list1 , item ) {
4+ return list1 . findIndex ( ( elem ) => ( elem . el == item . el ) && ( elem . port == item . port ) )
5+ }
6+
7+ function includesElement ( list1 , item ) {
8+ return list1 . findIndex ( ( elem ) => ( elem . el == item ) )
9+ }
10+
211function processCanvasState ( canvasState ) {
312 var newElementMap = { } ;
413 // var elementsOnNodes = [];
514 var nodeMap = [ ] ;
615 var createNode ;
716 var end1 , end2 , i , j , k ;
817 var optimized ;
18+ var idx ;
19+ var cnt ;
20+ var firstLetter ;
921
1022
1123 //Create a new node for each component
1224 canvasState . forEach ( item => {
1325 if ( item . type == "draw2d.Connection" ) {
1426 //get both ends of the connection
15- end1 = `${ item . source . node } .${ item . source . port } `
16- end2 = `${ item . target . node } .${ item . target . port } `
17- nodeMap . push ( [ end1 , end2 ] )
27+ // end1 = `${item.source.node}.${item.source.port}`
28+ // end2 = `${item.target.node}.${item.target.port}`
29+ nodeMap . push ( [ { el : item . source . node , port : item . source . port } , { el : item . target . node , port : item . target . port } ] )
1830 // console.log(end1, end2);
1931 } else {
2032 //if its not a connection its an element
21- newElementMap [ item . id ] = { } ;
33+ firstLetter = Array . from ( item . id ) [ 0 ] ;
34+ //cnt is how many connections it's expected
35+ if ( ( firstLetter == 'L' ) || ( firstLetter == 'R' ) || ( firstLetter == 'C' ) ) cnt = 2 ;
36+ else if ( firstLetter == 'o' ) cnt = 3 ;
37+ else cnt = 1 ;
38+ newElementMap [ item . id ] = { cnt : cnt } ;
2239 }
2340 } ) ;
2441
@@ -29,13 +46,17 @@ function processCanvasState(canvasState) {
2946 for ( i = 0 ; i < nodeMap . length ; i ++ ) {
3047 for ( j = 0 ; j < nodeMap [ i ] . length ; j ++ ) {
3148 for ( k = i + 1 ; k < nodeMap . length ; k ++ ) {
32- if ( nodeMap [ k ] . includes ( nodeMap [ i ] [ j ] ) ) {
49+ // console.log('looking for ',nodeMap[i][j], ' inside ', nodeMap[k])
50+ // if (nodeMap[k].includes(nodeMap[i][j])) {
51+ idx = arrayContains ( nodeMap [ k ] , nodeMap [ i ] [ j ] )
52+ if ( idx >= 0 ) {
53+ // console.log('common node')
3354 optimized = true ;
3455 //Before concat with K, must remove the element that is about to be duplicated
35- const index = nodeMap [ k ] . indexOf ( nodeMap [ i ] [ j ] ) ;
36- if ( index > - 1 ) { // only splice array when item is found
37- nodeMap [ k ] . splice ( index , 1 ) ; // 2nd parameter means remove one item only
38- }
56+ // const index = nodeMap[k].indexOf(nodeMap[i][j]);
57+ // if (index > -1) { // only splice array when item is found
58+ nodeMap [ k ] . splice ( idx , 1 ) ; // 2nd parameter means remove one item only
59+ // }
3960 nodeMap [ i ] = nodeMap [ i ] . concat ( nodeMap [ k ] ) ;
4061 nodeMap . splice ( k , 1 ) ;
4162 break loop1;
@@ -45,50 +66,56 @@ function processCanvasState(canvasState) {
4566 }
4667 } while ( optimized == true ) ;
4768
48- // //check if either end exists in the nodemap, create a new entry or add to existing entry
49- // createNode = true;
50- // for (i = 0; i < nodeMap.length; i++) {
51- // if (nodeMap[i].includes(end1) && !nodeMap[i].includes(end2)) {
52- // nodeMap[i].push(end2);
53- // createNode = false;
54- // break;
55- // }
56- // else if (!nodeMap[i].includes(end1) && nodeMap[i].includes(end2)) {
57- // nodeMap[i].push(end1);
58- // createNode = false;
59- // break;
60- // }
61- // }
62- // if (createNode) {
63- // nodeMap.push([end1, end2])
64- // }
65- // //Fixme - there needs to be some code here to merge nodes
66-
67- // } else {
68- // //if its not a connection its an element
69- // newElementMap[item.id] = {};
70- // }
71-
72- // });
73-
74- var elementsOnNodes = [ ] ;
75- var t ;
69+ //loop thru nodemap and remove elements which don't have both ports connected
7670 for ( i = 0 ; i < nodeMap . length ; i ++ ) {
77- elementsOnNodes [ i ] = [ ] ;
7871 for ( j = 0 ; j < nodeMap [ i ] . length ; j ++ ) {
79- t = nodeMap [ i ] [ j ] . split ( '.' )
80- elementsOnNodes [ i ] . push ( t [ 0 ] )
72+ newElementMap [ nodeMap [ i ] [ j ] . el ] . cnt -= 1 ;
8173 }
8274 }
75+ for ( const key in newElementMap ) {
76+ if ( newElementMap [ key ] . cnt > 0 ) {
77+ console . log ( 'removing' , key )
78+ //element must be removed!
79+ for ( i = 0 ; i < nodeMap . length ; i ++ ) {
80+ for ( j = 0 ; j < nodeMap [ i ] . length ; j ++ ) {
81+ do {
82+ cnt = includesElement ( nodeMap [ i ] , key )
83+ if ( cnt >= 0 ) nodeMap [ i ] . splice ( cnt , 1 )
84+ } while ( cnt >= 0 )
85+ // cnt = includesElement(nodeMap[i], key)
86+ // newElementMap[nodeMap[i][j].el].cnt -= 1;
87+ }
88+ }
89+ delete newElementMap [ key ]
90+ }
91+ }
92+ console . log ( newElementMap ) ;
93+
94+ //remove 2-port and 3-port elements that aren't fully connected
95+ //FIXME - here
96+ //[x]1 - Change nodemap to an array of object. Kind of dumb to have to keep splitting
97+ //[x]1a - remove elementsOnNodes
98+ //[x]2 - create a counter array and count occurances of each element
99+ //[x]3 - loop thru count array and remove anything which isn't 2 or 3
100+
101+ //list of elements on nodes, not specifying port
102+ // var elementsOnNodes = [];
103+ // var t;
104+ // for (i = 0; i < nodeMap.length; i++) {
105+ // elementsOnNodes[i] = [];
106+ // for (j = 0; j < nodeMap[i].length; j++) {
107+ // t = nodeMap[i][j]['el']
108+ // elementsOnNodes[i].push(t)
109+ // }
110+ // }
83111 // console.log('newElementMap', newElementMap)
84112
85- return [ elementsOnNodes , nodeMap , newElementMap ]
113+ return [ nodeMap , newElementMap ]
86114
87115}
88116
89117
90118export function calculateMNA ( canvasState , schematicReadiness ) {
91- var elementsOnNodes = [ ] ;
92119 var nodeMap = [ ] ;
93120 var i , j ;
94121 var vinNode , gndNode , voutNode ;
@@ -97,8 +124,8 @@ export function calculateMNA(canvasState, schematicReadiness) {
97124 var element ;
98125 var latexResult = null ;
99126
100- [ elementsOnNodes , nodeMap , newElementMap ] = processCanvasState ( canvasState ) ;
101- console . log ( "bp1" , elementsOnNodes , nodeMap , newElementMap )
127+ [ nodeMap , newElementMap ] = processCanvasState ( canvasState ) ;
128+ console . log ( "bp1" , nodeMap , newElementMap )
102129
103130 //verify how ready the schematic is
104131 // All this code is just for that! Can't it be done later, for free? //FIXME
@@ -109,29 +136,30 @@ export function calculateMNA(canvasState, schematicReadiness) {
109136 gnd : false ,
110137 } ;
111138 var tmp ;
112- for ( i = 0 ; i < elementsOnNodes . length ; i ++ ) {
113- if ( elementsOnNodes [ i ] . includes ( 'vout' ) ) {
139+ for ( i = 0 ; i < nodeMap . length ; i ++ ) {
140+ // if (elementsOnNodes[i].includes('vout')) {
141+ if ( includesElement ( nodeMap [ i ] , 'vout' ) >= 0 ) {
114142 schematicReadiness . vout = true ;
115143 //See which nodes are connected together
116144 var crushedNodes = [ i ] , zz , moreNodes , jj , kk , newNode , elementsOnThisNode = [ ] ;
117145 zz = i ;
118146 moreNodes = [ i ] ;
119- elementsOnThisNode = [ ] . concat ( elementsOnThisNode + elementsOnNodes [ i ] ) ;
147+ elementsOnThisNode = [ ] . concat ( elementsOnThisNode + nodeMap [ i ] ) ;
120148 while ( moreNodes . length > 0 ) {
121149 moreNodes = [ ] ;
122150 newNode = moreNodes . pop ( ) ;
123151 //Search through the node for elements with two ports (starting with the node tied to vout)
124- for ( jj = 0 ; jj < elementsOnNodes [ i ] . length ; jj ++ ) {
125- if ( elementsOnNodes [ i ] [ jj ] == 'vout' ) tmp = i ;
126- else if ( elementsOnNodes [ i ] [ jj ] == 'vin' ) tmp = i ;
127- else if ( elementsOnNodes [ i ] [ jj ] == 'gnd' ) tmp = i ;
152+ for ( jj = 0 ; jj < nodeMap [ i ] . length ; jj ++ ) {
153+ if ( nodeMap [ i ] [ jj ] . el == 'vout' ) tmp = i ;
154+ else if ( nodeMap [ i ] [ jj ] . el == 'vin' ) tmp = i ;
155+ else if ( nodeMap [ i ] [ jj ] . el == 'gnd' ) tmp = i ;
128156 else {
129157 //found a two ported element. Add the node on the other end if it isn't already added.
130- for ( kk = 0 ; kk < elementsOnNodes . length ; kk ++ ) {
158+ for ( kk = 0 ; kk < nodeMap . length ; kk ++ ) {
131159 if ( ! crushedNodes . includes ( kk ) ) {
132160 crushedNodes . push ( kk ) ;
133161 moreNodes . push ( kk ) ;
134- elementsOnThisNode = [ ] . concat ( elementsOnThisNode , elementsOnNodes [ kk ] ) ;
162+ elementsOnThisNode = [ ] . concat ( elementsOnThisNode , nodeMap [ kk ] ) ;
135163 }
136164 }
137165 moreNodes = 1 ; //wtf does this line do!
@@ -140,8 +168,8 @@ export function calculateMNA(canvasState, schematicReadiness) {
140168 }
141169
142170
143- if ( elementsOnThisNode . includes ( 'gnd' ) ) schematicReadiness . gnd = true ;
144- if ( elementsOnThisNode . includes ( 'vin' ) ) schematicReadiness . vin = true ;
171+ if ( includesElement ( elementsOnThisNode , 'gnd' ) >= 0 ) schematicReadiness . gnd = true ;
172+ if ( includesElement ( elementsOnThisNode , 'vin' ) >= 0 ) schematicReadiness . vin = true ;
145173
146174 break ;
147175 }
@@ -157,22 +185,24 @@ export function calculateMNA(canvasState, schematicReadiness) {
157185
158186 // Build MNA array
159187 if ( schematicReadiness . vout && schematicReadiness . vin && schematicReadiness . gnd ) {
188+ var numOpAmps = 0 ;
189+ for ( const key in newElementMap ) if ( Array . from ( key ) [ 0 ] == 'o' ) numOpAmps += 1 ;
160190 // Create 2D modified nodal analysis array
161- var mnaMatrix = new Array ( nodeMap . length ) ;
162- for ( i = 0 ; i < nodeMap . length ; i ++ ) mnaMatrix [ i ] = new Array ( nodeMap . length ) . fill ( "0" ) ;
191+ var mnaMatrix = new Array ( nodeMap . length + numOpAmps ) ;
192+ for ( i = 0 ; i < mnaMatrix . length ; i ++ ) mnaMatrix [ i ] = new Array ( mnaMatrix . length ) . fill ( "0" ) ;
163193 //create node map without gnd node. All nodes might need to shift
164- for ( i = 0 ; i < elementsOnNodes . length ; i ++ ) {
165- if ( elementsOnNodes [ i ] . includes ( 'gnd' ) ) gndNode = i ;
194+ for ( i = 0 ; i < nodeMap . length ; i ++ ) {
195+ if ( includesElement ( nodeMap [ i ] , 'gnd' ) >= 0 ) gndNode = i ;
166196 }
167197 var nodeMapNoGnd = nodeMap ;
168- var rem = nodeMapNoGnd . splice ( gndNode , 1 ) ;
198+ nodeMapNoGnd . splice ( gndNode , 1 ) ; //removes the ground node so MNA is arranged properly
169199
170200 // Step 1 - create map of every element and which node it connects too. Doing this here, after node map is complete and ground node is removed
171201 for ( i = 0 ; i < nodeMapNoGnd . length ; i ++ ) {
172202 for ( j = 0 ; j < nodeMapNoGnd [ i ] . length ; j ++ ) {
173- element = nodeMapNoGnd [ i ] [ j ] . split ( '.' )
174- if ( element [ 0 ] in elementMap ) elementMap [ element [ 0 ] ] . push ( i )
175- else elementMap [ element [ 0 ] ] = [ i ]
203+ element = nodeMapNoGnd [ i ] [ j ] [ 'el' ]
204+ if ( element in elementMap ) elementMap [ element ] . push ( i )
205+ else elementMap [ element ] = [ i ]
176206 }
177207 }
178208 voutNode = elementMap [ 'vout' ] [ 0 ] ;
@@ -181,7 +211,7 @@ export function calculateMNA(canvasState, schematicReadiness) {
181211 // Step 2 - loop thru elementMap and start adding things to the MNA
182212 var laplaceElement , firstLetter ;
183213 for ( const key2 in elementMap ) {
184- if ( ( key2 != 'vin' ) && ( key2 != 'vout' ) && ( key2 != 'gnd' ) ) {
214+ if ( ( key2 != 'vin' ) && ( key2 != 'vout' ) && ( key2 != 'gnd' ) && ( key2 != 'op' ) ) {
185215 firstLetter = Array . from ( key2 ) [ 0 ] ;
186216 if ( firstLetter == 'R' ) laplaceElement = key2 ;
187217 else if ( firstLetter == 'L' ) laplaceElement = "(S*" + key2 + ")" ;
@@ -198,15 +228,28 @@ export function calculateMNA(canvasState, schematicReadiness) {
198228 }
199229 }
200230 }
201- //2.3 Add a 1 in the bottom column indicating which node is Vin connected too
202- mnaMatrix [ mnaMatrix . length - 1 ] [ vinNode ] = '1' ;
231+ //2.3 Add a 1 in the bottom row indicating which node is Vin connected too
232+ mnaMatrix [ mnaMatrix . length - 1 - numOpAmps ] [ vinNode ] = '1' ;
203233
204234 //2.4 Add a 1 in the node connected to Vin to indicate that Iin flows into that node
205- mnaMatrix [ vinNode ] [ mnaMatrix . length - 1 ] = '1' ;
235+ mnaMatrix [ vinNode ] [ mnaMatrix . length - 1 - numOpAmps ] = '1' ;
236+
237+ //2.5 For each op-amp add some 1's. It says that 2 nodes are equal to each other, and that 1 node has a new ideal current source
238+ numOpAmps = 0 ;
239+ for ( const key in elementMap ) {
240+ if ( Array . from ( key ) [ 0 ] == 'o' ) {
241+ numOpAmps = numOpAmps + 1 ;
242+ console . log ( "bp3" , numOpAmps , key , elementMap [ key ] )
243+ mnaMatrix [ nodeMapNoGnd . length + numOpAmps ] [ elementMap [ key ] [ 0 ] ] = '-1' ;
244+ mnaMatrix [ nodeMapNoGnd . length + numOpAmps ] [ elementMap [ key ] [ 1 ] ] = '1' ;
245+ mnaMatrix [ elementMap [ key ] [ 2 ] ] [ nodeMapNoGnd . length + numOpAmps ] = '1' ;
246+ }
247+ }
248+
206249
207- // console.log('elementMap', elementMap);
250+ console . log ( 'elementMap' , elementMap ) ;
208251 // console.log('vin, vout and gnd node', vinNode, voutNode, gndNode);
209- // console.log('mna ', mnaMatrix);
252+ console . log ( 'mna ' , mnaMatrix ) ;
210253
211254 var nerdStrArr = [ ] ;
212255 var nerdStr = "" ;
0 commit comments