View Javadoc

1   package org.catacomb.numeric.difnet.calc;
2   
3   import org.catacomb.numeric.difnet.*;
4   
5   
6   
7   /**
8    * OrderedNetMap - remapping of the geometry of a DiffusiveNet, ready for
9    * diffusion calculations. It is composed of NetMapNodes and NetMapLinks which
10   * correspond 1-1 to nodes and links in the DiffusiveNet, but only contain
11   * quantities relevant to the structure and diffusion calculations.
12   *
13   * The structure is set on initialization. Therafter in calculations the state
14   * of the DiffusiveNet is copied in, calculations performed, and the results
15   * copied back to the DiffusiveNet. One OrderedNetMap can be used for many
16   * DiffusiveNets if they all have the same structure.
17   *
18   * NB both points and Links have capacitances (volume / surface effects).
19   * Typically one or the other will be zero - volume for charge, surface for
20   * concentratin.
21   *
22   */
23  
24  
25  public final class OrderedNetMap {
26  
27      NetMapNode[] node;
28      NetMapLink[] link;
29  
30      boolean acyclic;
31      private boolean useIntrinsics;
32  
33  
34      OrderedNetMap(NetStructure dn) {
35          acyclic = true;
36  
37          StructureNode[] difnetNode = dn.getNodes();
38          StructureLink[] difnetLink = dn.getLinks();
39  
40  
41          int nnode = difnetNode.length;
42          int nlink = difnetLink.length;
43          for (int i = 0; i < nnode; i++) {
44              difnetNode[i].setWork(i);
45          }
46  
47          // make corresponding node and link arrays, where each link has refs
48          // to its end nodes
49          NetMapNode[] wkNode = new NetMapNode[nnode];
50          NetMapLink[] wkLink = new NetMapLink[nlink];
51  
52          for (int i = 0; i < nnode; i++) {
53              wkNode[i] = new NetMapNode();
54              wkNode[i].peerIndex = i;
55              wkNode[i].fixed = difnetNode[i].hasFixedValue(null);
56          }
57  
58          for (int i = 0; i < nlink; i++) {
59              wkLink[i] = new NetMapLink();
60              wkLink[i].peerIndex = i;
61  
62              int iwka = difnetLink[i].getNodeA().getWork();
63              wkLink[i].nodeA = wkNode[iwka];
64  
65              int iwkb = difnetLink[i].getNodeB().getWork();
66              wkLink[i].nodeB = wkNode[iwkb];
67          }
68  
69  
70          // compile a list of which links go to or from each node;
71          // *** max six links per node;
72          // leave out links from fixed nodes: could be lots of these (bath to
73          // everything)
74          // and we dont need them
75  
76          NetMapLink[][] linksPerNode = new NetMapLink[nnode][6];
77  
78          linksPerNode[0] = new NetMapLink[nnode];
79          // ADHOC - envmt node is always index 0 and can go to all the rest;
80  
81  
82          int[] nlinksPerNode = new int[nnode];
83  
84          for (int i = 0; i < nlink; i++) {
85              if (wkLink[i].nodeA.fixed) {
86  
87              } else {
88                  int ia = wkLink[i].nodeA.peerIndex;
89                  linksPerNode[ia][nlinksPerNode[ia]++] = wkLink[i];
90              }
91  
92              if (wkLink[i].nodeB.fixed) {
93  
94              } else {
95                  int ib = wkLink[i].nodeB.peerIndex;
96                  linksPerNode[ib][nlinksPerNode[ib]++] = wkLink[i];
97              }
98          }
99  
100 
101 
102         // reorder the nodes, first the fixed ones, then a depth first
103         // tree search
104         node = new NetMapNode[nnode];
105         for (int i = 0; i < nnode; i++) {
106             wkNode[i].mark = false;
107         }
108         for (int i = 0; i < nlink; i++) {
109             wkLink[i].mark = false;
110             wkLink[i].flip = false;
111         }
112         // insert the fixed nodes first
113         int[] iin = { 0 };
114         for (int i = 0; i < nnode; i++) {
115             if (wkNode[i].fixed && !wkNode[i].mark) {
116                 node[iin[0]++] = wkNode[i];
117                 wkNode[i].mark = true;
118             }
119         }
120 
121         // now recursively put in the free ones, only following links to
122         // other nodes not in the list yet
123         int ntree = 0;
124         for (int i = 0; i < nnode; i++) {
125             if (!wkNode[i].mark) {
126                 ntree++;
127                 recindex(node, iin, linksPerNode, wkNode[i]);
128             }
129         }
130 
131         // Util.p("put in trees, total=" + ntree);
132 
133 
134         // tidy the nodes to get rid of any null refs;
135         for (int i = 0; i < nnode; i++) {
136             node[i].upLink = tidyLinkArray(node[i].upLink);
137             node[i].downLink = tidyLinkArray(node[i].downLink);
138         }
139 
140 
141         // index the new points;
142         for (int i = 0; i < nnode; i++) {
143             node[i].index = i;
144         }
145 
146         // there is nothing to be done for the links - wkLink has
147         // references to all the NetMapLinks (no others were created), and
148         // the links dont use indices but have direct refs to the nodes
149         link = wkLink;
150     }
151 
152 
153     public boolean getUseIntrinsics() {
154         return useIntrinsics;
155     }
156 
157 
158     public void Sp(String s) {
159         System.out.println(s);
160     }
161 
162 
163     public void print() {
164         Sp("ordered net map with " + node.length + " nodes, structure indexes in brackets ");
165         for (int i = 0; i < node.length; i++) {
166             NetMapNode nmn = node[i];
167             Sp("node " + i + "(" + nmn.peerIndex + "), ndownlinks=" + nmn.downLink.length
168                + ", nuplink=" + nmn.upLink.length);
169             if (nmn.isFree()) {
170 
171             } else {
172                 Sp("fixed at " + nmn.value);
173             }
174             for (int j = 0; j < nmn.downLink.length; j++) {
175                 printLink("down ", nmn.downLink[j], j);
176             }
177             for (int j = 0; j < nmn.upLink.length; j++) {
178                 printLink("  up ", nmn.upLink[j], j);
179             }
180         }
181     }
182 
183 
184     public void printLink(String dir, NetMapLink lk, int lki) {
185         Sp(dir + lki + "(" + lk.peerIndex + "),  nodeA=" + lk.nodeA.index + "(" + lk.nodeA.peerIndex
186            + "), nodeB=" + lk.nodeB.index + "(" + lk.nodeB.peerIndex + "), g=" + lk.conductance
187            + ", c=" + lk.capacitance);
188     }
189 
190 
191     NetMapNode[] getNodes() {
192         return node;
193     }
194 
195 
196     NetMapLink[] tidyLinkArray(NetMapLink[] cain) {
197         NetMapLink[] ca = cain;
198         if (ca == null)
199             return new NetMapLink[0];
200         int n = 0;
201         while (n < ca.length && ca[n] != null)
202             n++;
203         if (n < ca.length) {
204             NetMapLink[] cb = ca;
205             ca = new NetMapLink[n];
206             for (int i = 0; i < n; i++)
207                 ca[i] = cb[i];
208         }
209         return ca;
210     }
211 
212 
213     private NetMapLink[] addLink(NetMapLink[] cain, NetMapLink c) {
214         NetMapLink[] ca = cain;
215         int n = 0;
216         if (ca == null)
217             ca = new NetMapLink[3];
218         while (n < ca.length && ca[n] != null)
219             n++;
220         if (n == ca.length)
221             ca = extendNetMapLinkArray(ca);
222         ca[n] = c;
223         return ca;
224     }
225 
226 
227     private NetMapLink[] extendNetMapLinkArray(NetMapLink[] ca) {
228         int n = ca.length;
229         NetMapLink[] cb = new NetMapLink[2 * n];
230         for (int i = 0; i < n; i++)
231             cb[i] = ca[i];
232         return cb;
233     }
234 
235 
236     private void recindex(NetMapNode[] nodeArray, int[] inxt, NetMapLink[][] linksPerNode,
237                           NetMapNode currentNode) {
238         currentNode.mark = true;
239         nodeArray[inxt[0]++] = currentNode;
240         NetMapLink[] nbrs = linksPerNode[currentNode.peerIndex];
241 
242         // put in links to the fixed nodes first;
243         for (int i = 0; i < nbrs.length && nbrs[i] != null; i++) {
244             NetMapLink h = nbrs[i];
245             if (!h.mark) {
246                 if (h.nodeB.fixed || h.nodeA.fixed) {
247                     if (h.nodeB.fixed)
248                         h.reverseEnds();
249 
250                     h.nodeA.upLink = addLink(h.nodeA.upLink, h);
251                     h.nodeB.downLink = addLink(h.nodeB.downLink, h);
252                     h.mark = true;
253                 }
254             }
255         }
256 
257 
258         for (int i = 0; i < nbrs.length && nbrs[i] != null; i++) {
259             NetMapLink h = nbrs[i];
260             if (!h.mark) {
261                 h.mark = true;
262                 if (h.nodeA != currentNode)
263                     h.reverseEnds();
264                 h.nodeA.upLink = addLink(h.nodeA.upLink, h);
265                 h.nodeB.downLink = addLink(h.nodeB.downLink, h);
266                 if (h.nodeB.mark) {
267                     System.out.println("WARNING found link which breaks acyclic prop?" + " from peers "
268                                        + h.nodeA.peerIndex + " to " + h.nodeB.peerIndex);
269                     acyclic = false;
270                 } else {
271                     recindex(nodeArray, inxt, linksPerNode, h.nodeB);
272                 }
273             }
274         }
275     }
276 
277 
278     boolean isAcyclic() {
279         return acyclic;
280     }
281 
282 
283     void readState(NetState dn) {
284         useIntrinsics = dn.useIntrinsics();
285 
286         StateNode[] difnetNode = dn.getNodes();
287         for (int i = 0; i < node.length; i++) {
288             node[i].readState(difnetNode[node[i].peerIndex], dn.getTime());
289         }
290         StateLink[] difnetLink = dn.getLinks();
291         for (int i = 0; i < link.length; i++) {
292             link[i].readState(difnetLink[link[i].peerIndex]);
293         }
294     }
295 
296 
297     void writeState(NetState difnet) {
298         StateNode[] difnetNode = difnet.getNodes();
299         for (int i = 0; i < node.length; i++) {
300             node[i].writeState(difnetNode[node[i].peerIndex]);
301         }
302     }
303 }