NEURON
spbuild.cpp
Go to the documentation of this file.
1 /*
2  * MATRIX BUILD MODULE
3  *
4  * Author: Advising professor:
5  * Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
6  * UC Berkeley
7  *
8  * This file contains the routines associated with clearing, loading and
9  * preprocessing the matrix for the sparse matrix routines.
10  *
11  * >>> User accessible functions contained in this file:
12  * spClear
13  * spGetElement
14  * spGetAdmittance
15  * spGetQuad
16  * spGetOnes
17  * spInstallInitInfo
18  * spGetInitInfo
19  * spInitialize
20  *
21  * >>> Other functions contained in this file:
22  * spcFindElementInCol
23  * spcCreateElement
24  * spcLinkRows
25  * EnlargeMatrix
26  */
27 
28 /*
29  * Revision and copyright information.
30  *
31  * Copyright (c) 1985,86,87,88
32  * by Kenneth S. Kundert and the University of California.
33  *
34  * Permission to use, copy, modify, and distribute this software and
35  * its documentation for any purpose and without fee is hereby granted,
36  * provided that the copyright notices appear in all copies and
37  * supporting documentation and that the authors and the University of
38  * California are properly credited. The authors and the University of
39  * California make no representations as to the suitability of this
40  * software for any purpose. It is provided `as is', without express
41  * or implied warranty.
42  */
43 
44 /*
45  * IMPORTS
46  *
47  * >>> Import descriptions:
48  * spconfig.h
49  * Macros that customize the sparse matrix routines.
50  * spmatrix.h
51  * Macros and declarations to be imported by the user.
52  * spdefs.h
53  * Matrix type and macro definitions for the sparse matrix routines.
54  */
55 
56 #define spINSIDE_SPARSE
57 #include "spconfig.h"
58 #include "spdefs.h"
59 #include "spmatrix.h"
60 
61 /* avoid "declared implicitly `extern' and later `static' " warnings. */
62 
65 
66 static void EnlargeMatrix(MatrixPtr Matrix, int NewSize);
67 
68 /*
69  * CLEAR MATRIX
70  *
71  * Sets every element of the matrix to zero and clears the error flag.
72  *
73  * >>> Arguments:
74  * Matrix <input> (char *)
75  * Pointer to matrix that is to be cleared.
76  *
77  * >>> Local variables:
78  * pElement (ElementPtr)
79  * A pointer to the element being cleared.
80  */
81 
82 void spClear(char* eMatrix)
83 {
84  MatrixPtr Matrix = (MatrixPtr)eMatrix;
85  ElementPtr pElement;
86  int I;
87 
88  /* Begin `spClear'. */
90 
91 /* Clear matrix. */
92  {
93  for (I = Matrix->Size; I > 0; I--) {
94  pElement = Matrix->FirstInCol[I];
95  while (pElement != NULL) {
96  pElement->Real = 0.0;
97  pElement = pElement->NextInCol;
98  }
99  }
100  }
101 
102  /* Empty the trash. */
103  Matrix->TrashCan.Real = 0.0;
104 
105  Matrix->Error = spOKAY;
106  Matrix->Factored = NO;
107  Matrix->SingularCol = 0;
108  Matrix->SingularRow = 0;
109  Matrix->PreviousMatrixWasComplex = Matrix->Complex;
110  return;
111 }
112 
113 /*
114  * SINGLE ELEMENT ADDITION TO MATRIX BY INDEX
115  *
116  * Finds element [Row,Col] and returns a pointer to it. If element is
117  * not found then it is created and spliced into matrix. This routine
118  * is only to be used after spCreate() and before spMNA_Preorder(),
119  * spFactor() or spOrderAndFactor(). Returns a pointer to the
120  * Real portion of a MatrixElement. This pointer is later used by
121  * spADD_xxx_ELEMENT to directly access element.
122  *
123  * >>> Returns:
124  * Returns a pointer to the element. This pointer is then used to directly
125  * access the element during successive builds.
126  *
127  * >>> Arguments:
128  * Matrix <input> (char *)
129  * Pointer to the matrix that the element is to be added to.
130  * Row <input> (int)
131  * Row index for element. Must be in the range of [0..Size] unless
132  * the options EXPANDABLE or TRANSLATE are used. Elements placed in
133  * row zero are discarded. In no case may Row be less than zero.
134  * Col <input> (int)
135  * Column index for element. Must be in the range of [0..Size] unless
136  * the options EXPANDABLE or TRANSLATE are used. Elements placed in
137  * column zero are discarded. In no case may Col be less than zero.
138  *
139  * >>> Local variables:
140  * pElement (RealNumber *)
141  * Pointer to the element.
142  *
143  * >>> Possible errors:
144  * spNO_MEMORY
145  * Error is not cleared in this routine.
146  */
147 
148 ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr* LastAddr, int Row, int Col, BOOLEAN CreateIfMissing);
149 ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr* LastAddr, BOOLEAN Fillin);
150 
151 RealNumber* spGetElement(char* eMatrix, int Row, int Col)
152 {
153  MatrixPtr Matrix = (MatrixPtr)eMatrix;
154  RealNumber* pElement;
155 
156  /* Begin `spGetElement'. */
157  ASSERT(IS_SPARSE(Matrix) AND Row >= 0 AND Col >= 0);
158 
159  if ((Row == 0) OR(Col == 0))
160  return &Matrix->TrashCan.Real;
161 
162  ASSERT(Matrix->NeedsOrdering);
163 
164 #if NOT EXPANDABLE
165  ASSERT(Row <= Matrix->Size AND Col <= Matrix->Size);
166 #endif
167 
168 #if EXPANDABLE
169  /* Re-size Matrix if necessary. */
170  if ((Row > Matrix->Size) OR(Col > Matrix->Size))
171  EnlargeMatrix(Matrix, MAX(Row, Col));
172  if (Matrix->Error == spNO_MEMORY)
173  return NULL;
174 #endif
175 
176  /*
177  * The condition part of the following if statement tests to see if the
178  * element resides along the diagonal, if it does then it tests to see
179  * if the element has been created yet (Diag pointer not NULL). The
180  * pointer to the element is then assigned to Element after it is cast
181  * into a pointer to a RealNumber. This casting makes the pointer into
182  * a pointer to Real. This statement depends on the fact that Real
183  * is the first record in the MatrixElement structure.
184  */
185 
186  if ((Row != Col) OR((pElement = (RealNumber*)Matrix->Diag[Row]) == NULL)) {
187  /*
188  * Element does not exist or does not reside along diagonal. Search
189  * column for element. As in the if statement above, the pointer to the
190  * element which is returned by spcFindElementInCol is cast into a
191  * pointer to Real, a RealNumber.
192  */
194  &(Matrix->FirstInCol[Col]),
195  Row, Col, true);
196  }
197  return pElement;
198 }
199 
200 /*
201  * FIND ELEMENT BY SEARCHING COLUMN
202  *
203  * Searches column starting at element specified at PtrAddr and finds element
204  * in Row. If Element does not exists, it is created. The pointer to the
205  * element is returned.
206  *
207  * >>> Returned:
208  * A pointer to the desired element:
209  *
210  * >>> Arguments:
211  * Matrix <input> (MatrixPtr)
212  * Pointer to Matrix.
213  * LastAddr <input-output> (ElementPtr *)
214  * Address of pointer that initially points to the element in Col at which
215  * the search is started. The pointer in this location may be changed if
216  * a fill-in is required in and adjacent element. For this reason it is
217  * important that LastAddr be the address of a FirstInCol or a NextInCol
218  * rather than a temporary variable.
219  * Row <input> (int)
220  * Row being searched for.
221  * Col (int)
222  * Column being searched.
223  * CreateIfMissing <input> (BOOLEAN)
224  * Indicates what to do if element is not found, create one or return a
225  * NULL pointer.
226  *
227  * Local variables:
228  * pElement (ElementPtr)
229  * Pointer used to search through matrix.
230  */
231 
232 ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr* LastAddr, int Row, int Col, BOOLEAN CreateIfMissing)
233 {
234  ElementPtr pElement;
235 
236  /* Begin `spcFindElementInCol'. */
237  pElement = *LastAddr;
238 
239  /* Search for element. */
240  while (pElement != NULL) {
241  if (pElement->Row < Row) {
242  /* Have not reached element yet. */
243  LastAddr = &(pElement->NextInCol);
244  pElement = pElement->NextInCol;
245  } else if (pElement->Row == Row) {
246  /* Reached element. */
247  return pElement;
248  } else
249  break; /* while loop */
250  }
251 
252  /* Element does not exist and must be created. */
253  if (CreateIfMissing)
254  return spcCreateElement(Matrix, Row, Col, LastAddr, NO);
255  else
256  return NULL;
257 }
258 
259 #if QUAD_ELEMENT
260 /*
261  * ADDITION OF ADMITTANCE TO MATRIX BY INDEX
262  *
263  * Performs same function as spGetElement except rather than one
264  * element, all four Matrix elements for a floating component are
265  * added. This routine also works if component is grounded. Positive
266  * elements are placed at [Node1,Node2] and [Node2,Node1]. This
267  * routine is only to be used after spCreate() and before
268  * spMNA_Preorder(), spFactor() or spOrderAndFactor().
269  *
270  * >>> Returns:
271  * Error code.
272  *
273  * >>> Arguments:
274  * Matrix <input> (char *)
275  * Pointer to the matrix that component is to be entered in.
276  * Node1 <input> (int)
277  * Row and column indices for elements. Must be in the range of [0..Size]
278  * unless the options EXPANDABLE or TRANSLATE are used. Node zero is the
279  * ground node. In no case may Node1 be less than zero.
280  * Node2 <input> (int)
281  * Row and column indices for elements. Must be in the range of [0..Size]
282  * unless the options EXPANDABLE or TRANSLATE are used. Node zero is the
283  * ground node. In no case may Node2 be less than zero.
284  * Template <output> (struct spTemplate *)
285  * Collection of pointers to four elements that are later used to directly
286  * address elements. User must supply the template, this routine will
287  * fill it.
288  *
289  * Possible errors:
290  * spNO_MEMORY
291  * Error is not cleared in this routine.
292  */
293 
294 int spGetAdmittance(char* Matrix, int Node1, int Node2, spTemplate* Template)
295 {
296 
297  /* Begin `spGetAdmittance'. */
298  Template->Element1 = spGetElement(Matrix, Node1, Node1);
299  Template->Element2 = spGetElement(Matrix, Node2, Node2);
300  Template->Element3Negated = spGetElement(Matrix, Node2, Node1);
301  Template->Element4Negated = spGetElement(Matrix, Node1, Node2);
302  if ((Template->Element1 == NULL)
303  OR(Template->Element2 == NULL)
304  OR(Template->Element3Negated == NULL)
305  OR(Template->Element4Negated == NULL))
306  return spNO_MEMORY;
307 
308  if (Node1 == 0)
309  SWAP(RealNumber*, Template->Element1, Template->Element2);
310 
311  return spOKAY;
312 }
313 #endif /* QUAD_ELEMENT */
314 
315 #if QUAD_ELEMENT
316 /*
317  * ADDITION OF FOUR ELEMENTS TO MATRIX BY INDEX
318  *
319  * Similar to spGetAdmittance, except that spGetAdmittance only
320  * handles 2-terminal components, whereas spGetQuad handles simple
321  * 4-terminals as well. These 4-terminals are simply generalized
322  * 2-terminals with the option of having the sense terminals different
323  * from the source and sink terminals. spGetQuad adds four
324  * elements to the matrix. Positive elements occur at Row1,Col1
325  * Row2,Col2 while negative elements occur at Row1,Col2 and Row2,Col1.
326  * The routine works fine if any of the rows and columns are zero.
327  * This routine is only to be used after spCreate() and before
328  * spMNA_Preorder(), spFactor() or spOrderAndFactor()
329  * unless TRANSLATE is set true.
330  *
331  * >>> Returns:
332  * Error code.
333  *
334  * >>> Arguments:
335  * Matrix <input> (char *)
336  * Pointer to the matrix that component is to be entered in.
337  * Row1 <input> (int)
338  * First row index for elements. Must be in the range of [0..Size]
339  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
340  * ground row. In no case may Row1 be less than zero.
341  * Row2 <input> (int)
342  * Second row index for elements. Must be in the range of [0..Size]
343  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
344  * ground row. In no case may Row2 be less than zero.
345  * Col1 <input> (int)
346  * First column index for elements. Must be in the range of [0..Size]
347  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
348  * ground column. In no case may Col1 be less than zero.
349  * Col2 <input> (int)
350  * Second column index for elements. Must be in the range of [0..Size]
351  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
352  * ground column. In no case may Col2 be less than zero.
353  * Template <output> (struct spTemplate *)
354  * Collection of pointers to four elements that are later used to directly
355  * address elements. User must supply the template, this routine will
356  * fill it.
357  * Real <input> (RealNumber)
358  * Real data to be added to elements.
359  * Imag <input> (RealNumber)
360  * Imag data to be added to elements. If matrix is real, this argument
361  * may be deleted.
362  *
363  * Possible errors:
364  * spNO_MEMORY
365  * Error is not cleared in this routine.
366  */
367 
368 int spGetQuad(char* Matrix, int Row1, int Row2, int Col1, int Col2, spTemplate* Template)
369 {
370  /* Begin `spGetQuad'. */
371  Template->Element1 = spGetElement(Matrix, Row1, Col1);
372  Template->Element2 = spGetElement(Matrix, Row2, Col2);
373  Template->Element3Negated = spGetElement(Matrix, Row2, Col1);
374  Template->Element4Negated = spGetElement(Matrix, Row1, Col2);
375  if ((Template->Element1 == NULL)
376  OR(Template->Element2 == NULL)
377  OR(Template->Element3Negated == NULL)
378  OR(Template->Element4Negated == NULL))
379  return spNO_MEMORY;
380 
381  if (Template->Element1 == &((MatrixPtr)Matrix)->TrashCan.Real)
382  SWAP(RealNumber*, Template->Element1, Template->Element2);
383 
384  return spOKAY;
385 }
386 #endif /* QUAD_ELEMENT */
387 
388 #if QUAD_ELEMENT
389 /*
390  * ADDITION OF FOUR STRUCTURAL ONES TO MATRIX BY INDEX
391  *
392  * Performs similar function to spGetQuad() except this routine is
393  * meant for components that do not have an admittance representation.
394  *
395  * The following stamp is used:
396  * Pos Neg Eqn
397  * Pos [ . . 1 ]
398  * Neg [ . . -1 ]
399  * Eqn [ 1 -1 . ]
400  *
401  * >>> Returns:
402  * Error code.
403  *
404  * >>> Arguments:
405  * Matrix <input> (char *)
406  * Pointer to the matrix that component is to be entered in.
407  * Pos <input> (int)
408  * See stamp above. Must be in the range of [0..Size]
409  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
410  * ground row. In no case may Pos be less than zero.
411  * Neg <input> (int)
412  * See stamp above. Must be in the range of [0..Size]
413  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
414  * ground row. In no case may Neg be less than zero.
415  * Eqn <input> (int)
416  * See stamp above. Must be in the range of [0..Size]
417  * unless the options EXPANDABLE or TRANSLATE are used. Zero is the
418  * ground row. In no case may Eqn be less than zero.
419  * Template <output> (struct spTemplate *)
420  * Collection of pointers to four elements that are later used to directly
421  * address elements. User must supply the template, this routine will
422  * fill it.
423  *
424  * Possible errors:
425  * spNO_MEMORY
426  * Error is not cleared in this routine.
427  */
428 
429 int spGetOnes(char* Matrix, int Pos, int Neg, int Eqn, spTemplate* Template)
430 {
431  /* Begin `spGetOnes'. */
432  Template->Element4Negated = spGetElement(Matrix, Neg, Eqn);
433  Template->Element3Negated = spGetElement(Matrix, Eqn, Neg);
434  Template->Element2 = spGetElement(Matrix, Pos, Eqn);
435  Template->Element1 = spGetElement(Matrix, Eqn, Pos);
436  if ((Template->Element1 == NULL)
437  OR(Template->Element2 == NULL)
438  OR(Template->Element3Negated == NULL)
439  OR(Template->Element4Negated == NULL))
440  return spNO_MEMORY;
441 
442  spADD_REAL_QUAD(*Template, 1.0);
443  return spOKAY;
444 }
445 #endif /* QUAD_ELEMENT */
446 
447 /*
448  *
449  * CREATE AND SPLICE ELEMENT INTO MATRIX
450  *
451  * This routine is used to create new matrix elements and splice them into the
452  * matrix.
453  *
454  * >>> Returned:
455  * A pointer to the element that was created is returned.
456  *
457  * >>> Arguments:
458  * Matrix <input> (MatrixPtr)
459  * Pointer to matrix.
460  * Row <input> (int)
461  * Row index for element.
462  * Col <input> (int)
463  * Column index for element.
464  * LastAddr <input-output> (ElementPtr *)
465  * This contains the address of the pointer to the element just above the
466  * one being created. It is used to speed the search and it is updated with
467  * address of the created element.
468  * Fillin <input> (BOOLEAN)
469  * Flag that indicates if created element is to be a fill-in.
470  *
471  * >>> Local variables:
472  * pElement (ElementPtr)
473  * Pointer to an element in the matrix. It is used to refer to the newly
474  * created element and to restring the pointers of the element's row and
475  * column.
476  * pLastElement (ElementPtr)
477  * Pointer to the element in the matrix that was just previously pointed
478  * to by pElement. It is used to restring the pointers of the element's
479  * row and column.
480  * pCreatedElement (ElementPtr)
481  * Pointer to the desired element, the one that was just created.
482  *
483  * >>> Possible errors:
484  * spNO_MEMORY
485  */
486 
487 ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr* LastAddr, BOOLEAN Fillin)
488 {
489  ElementPtr pElement, pLastElement;
490  ElementPtr pCreatedElement;
491 
492  /* Begin `spcCreateElement'. */
493 
494  if (Matrix->RowsLinked) {
495  /* Row pointers cannot be ignored. */
496  if (Fillin) {
497  pElement = spcGetFillin(Matrix);
498  Matrix->Fillins++;
499  } else {
500  pElement = spcGetElement(Matrix);
501  Matrix->NeedsOrdering = YES;
502  }
503  if (pElement == NULL)
504  return NULL;
505 
506  /* If element is on diagonal, store pointer in Diag. */
507  if (Row == Col)
508  Matrix->Diag[Row] = pElement;
509 
510  /* Initialize Element. */
511  pCreatedElement = pElement;
512  pElement->Row = Row;
513  pElement->Col = Col;
514  pElement->Real = 0.0;
515 #if INITIALIZE
516  pElement->pInitInfo = NULL;
517 #endif
518 
519  /* Splice element into column. */
520  pElement->NextInCol = *LastAddr;
521  *LastAddr = pElement;
522 
523  /* Search row for proper element position. */
524  pElement = Matrix->FirstInRow[Row];
525  pLastElement = NULL;
526  while (pElement != NULL) {
527  /* Search for element row position. */
528  if (pElement->Col < Col) {
529  /* Have not reached desired element. */
530  pLastElement = pElement;
531  pElement = pElement->NextInRow;
532  } else
533  pElement = NULL;
534  }
535 
536  /* Splice element into row. */
537  pElement = pCreatedElement;
538  if (pLastElement == NULL) {
539  /* Element is first in row. */
540  pElement->NextInRow = Matrix->FirstInRow[Row];
541  Matrix->FirstInRow[Row] = pElement;
542  } else
543  /* Element is not first in row. */
544  {
545  pElement->NextInRow = pLastElement->NextInRow;
546  pLastElement->NextInRow = pElement;
547  }
548 
549  } else {
550  /*
551  * Matrix has not been factored yet. Thus get element rather than fill-in.
552  * Also, row pointers can be ignored.
553  */
554 
555  /* Allocate memory for Element. */
556  pElement = spcGetElement(Matrix);
557  if (pElement == NULL)
558  return NULL;
559 
560  /* If element is on diagonal, store pointer in Diag. */
561  if (Row == Col)
562  Matrix->Diag[Row] = pElement;
563 
564  /* Initialize Element. */
565  pCreatedElement = pElement;
566  pElement->Row = Row;
567 #if DEBUG
568  pElement->Col = Col;
569 #endif
570  pElement->Real = 0.0;
571 #if INITIALIZE
572  pElement->pInitInfo = NULL;
573 #endif
574 
575  /* Splice element into column. */
576  pElement->NextInCol = *LastAddr;
577  *LastAddr = pElement;
578  }
579 
580  Matrix->Elements++;
581  return pCreatedElement;
582 }
583 
584 /*
585  *
586  * LINK ROWS
587  *
588  * This routine is used to generate the row links. The spGetElement()
589  * routines do not create row links, which are needed by the spFactor()
590  * routines.
591  *
592  * >>> Arguments:
593  * Matrix <input> (MatrixPtr)
594  * Pointer to the matrix.
595  *
596  * >>> Local variables:
597  * pElement (ElementPtr)
598  * Pointer to an element in the matrix.
599  * FirstInRowEntry (ElementPtr *)
600  * A pointer into the FirstInRow array. Points to the FirstInRow entry
601  * currently being operated upon.
602  * FirstInRowArray (ArrayOfElementPtrs)
603  * A pointer to the FirstInRow array. Same as Matrix->FirstInRow.
604  * Col (int)
605  * Column currently being operated upon.
606  */
607 
609 {
610  ElementPtr pElement, *FirstInRowEntry;
611  ArrayOfElementPtrs FirstInRowArray;
612  int Col;
613 
614  /* Begin `spcLinkRows'. */
615  FirstInRowArray = Matrix->FirstInRow;
616  for (Col = Matrix->Size; Col >= 1; Col--) {
617  /* Generate row links for the elements in the Col'th column. */
618  pElement = Matrix->FirstInCol[Col];
619 
620  while (pElement != NULL) {
621  pElement->Col = Col;
622  FirstInRowEntry = &FirstInRowArray[pElement->Row];
623  pElement->NextInRow = *FirstInRowEntry;
624  *FirstInRowEntry = pElement;
625  pElement = pElement->NextInCol;
626  }
627  }
628  Matrix->RowsLinked = YES;
629  return;
630 }
631 
632 /*
633  * ENLARGE MATRIX
634  *
635  * Increases the size of the matrix.
636  *
637  * >>> Arguments:
638  * Matrix <input> (MatrixPtr)
639  * Pointer to the matrix.
640  * NewSize <input> (int)
641  * The new size of the matrix.
642  *
643  * >>> Local variables:
644  * OldAllocatedSize (int)
645  * The allocated size of the matrix before it is expanded.
646  */
647 
648 static void EnlargeMatrix(MatrixPtr Matrix, int NewSize)
649 {
650  int I, OldAllocatedSize = Matrix->AllocatedSize;
651 
652  /* Begin `EnlargeMatrix'. */
653  Matrix->Size = NewSize;
654 
655  if (NewSize <= OldAllocatedSize)
656  return;
657 
658  /* Expand the matrix frame. */
659  NewSize = MAX(NewSize, EXPANSION_FACTOR * OldAllocatedSize);
660  Matrix->AllocatedSize = NewSize;
661 
662  if ((REALLOC(Matrix->IntToExtColMap, int, NewSize + 1)) == NULL) {
663  Matrix->Error = spNO_MEMORY;
664  return;
665  }
666  if ((REALLOC(Matrix->IntToExtRowMap, int, NewSize + 1)) == NULL) {
667  Matrix->Error = spNO_MEMORY;
668  return;
669  }
670  if ((REALLOC(Matrix->Diag, ElementPtr, NewSize + 1)) == NULL) {
671  Matrix->Error = spNO_MEMORY;
672  return;
673  }
674  if ((REALLOC(Matrix->FirstInCol, ElementPtr, NewSize + 1)) == NULL) {
675  Matrix->Error = spNO_MEMORY;
676  return;
677  }
678  if ((REALLOC(Matrix->FirstInRow, ElementPtr, NewSize + 1)) == NULL) {
679  Matrix->Error = spNO_MEMORY;
680  return;
681  }
682 
683  /*
684  * Destroy the Markowitz and Intermediate vectors, they will be recreated
685  * in spOrderAndFactor().
686  */
687  FREE(Matrix->MarkowitzRow);
688  FREE(Matrix->MarkowitzCol);
689  FREE(Matrix->MarkowitzProd);
690  FREE(Matrix->DoRealDirect);
691  FREE(Matrix->DoCmplxDirect);
692  FREE(Matrix->Intermediate);
693  Matrix->InternalVectorsAllocated = NO;
694 
695  /* Initialize the new portion of the vectors. */
696  for (I = OldAllocatedSize + 1; I <= NewSize; I++) {
697  Matrix->IntToExtColMap[I] = I;
698  Matrix->IntToExtRowMap[I] = I;
699  Matrix->Diag[I] = NULL;
700  Matrix->FirstInRow[I] = NULL;
701  Matrix->FirstInCol[I] = NULL;
702  }
703 
704  return;
705 }
706 
707 #if INITIALIZE
708 /*
709  * INITIALIZE MATRIX
710  *
711  * With the INITIALIZE compiler option (see spconfig.h) set true,
712  * Sparse allows the user to keep initialization information with each
713  * structurally nonzero matrix element. Each element has a pointer
714  * that is set and used by the user. The user can set this pointer
715  * using spInstallInitInfo and may be read using spGetInitInfo. Both
716  * may be used only after the element exists. The function
717  * spInitialize() is a user customizable way to initialize the matrix.
718  * Passed to this routine is a function pointer. spInitialize() sweeps
719  * through every element in the matrix and checks the pInitInfo
720  * pointer (the user supplied pointer). If the pInitInfo is NULL,
721  * which is true unless the user changes it (almost always true for
722  * fill-ins), then the element is zeroed. Otherwise, the function
723  * pointer is called and passed the pInitInfo pointer as well as the
724  * element pointer and the external row and column numbers. If the
725  * user sets the value of each element, then spInitialize() replaces
726  * spClear().
727  *
728  * The user function is expected to return a nonzero integer if there
729  * is a fatal error and zero otherwise. Upon encountering a nonzero
730  * return code, spInitialize() terminates and returns the error code.
731  *
732  * >>> Arguments:
733  * Matrix <input> (char *)
734  * Pointer to matrix.
735  *
736  * >>> Possible Errors:
737  * Returns nonzero if error, zero otherwise.
738  */
739 
740 void spInstallInitInfo(RealNumber* pElement, char* pInitInfo)
741 {
742  /* Begin `spInstallInitInfo'. */
743  ASSERT(pElement != NULL);
744 
745  ((ElementPtr)pElement)->pInitInfo = pInitInfo;
746 }
747 
748 char* spGetInitInfo(RealNumber* pElement)
749 {
750  /* Begin `spGetInitInfo'. */
751  ASSERT(pElement != NULL);
752 
753  return (char*)((ElementPtr)pElement)->pInitInfo;
754 }
755 
756 int spInitialize(eMatrix, pInit)
757 
758 char* eMatrix;
759 int (*pInit)();
760 {
761  MatrixPtr Matrix = (MatrixPtr)eMatrix;
762  ElementPtr pElement;
763  int J, Error, Col;
764 
765  /* Begin `spInitialize'. */
767 
768 
769  /* Initialize the matrix. */
770  for (J = Matrix->Size; J > 0; J--) {
771  pElement = Matrix->FirstInCol[J];
772  Col = Matrix->IntToExtColMap[J];
773  while (pElement != NULL) {
774  if (pElement->pInitInfo == NULL) {
775  pElement->Real = 0.0;
776  } else {
777  Error = (*pInit)((RealNumber*)pElement, pElement->pInitInfo,
778  Matrix->IntToExtRowMap[pElement->Row], Col);
779  if (Error) {
780  Matrix->Error = spFATAL;
781  return Error;
782  }
783  }
784  pElement = pElement->NextInCol;
785  }
786  }
787 
788  /* Empty the trash. */
789  Matrix->TrashCan.Real = 0.0;
790 
791  Matrix->Error = spOKAY;
792  Matrix->Factored = NO;
793  Matrix->SingularCol = 0;
794  Matrix->SingularRow = 0;
795  Matrix->PreviousMatrixWasComplex = Matrix->Complex;
796  return 0;
797 }
798 #endif /* INITIALIZE */
#define MAX(a, b)
Definition: grids.h:31
ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr *LastAddr, int Row, int Col, BOOLEAN CreateIfMissing)
Definition: spbuild.cpp:232
int spGetOnes(char *Matrix, int Pos, int Neg, int Eqn, spTemplate *Template)
Definition: spbuild.cpp:429
int spGetQuad(char *Matrix, int Row1, int Row2, int Col1, int Col2, spTemplate *Template)
Definition: spbuild.cpp:368
void spcLinkRows(MatrixPtr Matrix)
Definition: spbuild.cpp:608
ElementPtr spcGetFillin(MatrixPtr Matrix)
Definition: spalloc.cpp:371
void spClear(char *eMatrix)
Definition: spbuild.cpp:82
static void EnlargeMatrix(MatrixPtr Matrix, int NewSize)
Definition: spbuild.cpp:648
ElementPtr spcGetElement(MatrixPtr Matrix)
Definition: spalloc.cpp:265
RealNumber * spGetElement(char *eMatrix, int Row, int Col)
Definition: spbuild.cpp:151
ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr *LastAddr, BOOLEAN Fillin)
Definition: spbuild.cpp:487
int spGetAdmittance(char *Matrix, int Node1, int Node2, spTemplate *Template)
Definition: spbuild.cpp:294
#define NULL
Definition: spdefs.h:105
#define FREE(ptr)
Definition: spdefs.h:177
#define OR
Definition: spdefs.h:101
#define BOOLEAN
Definition: spdefs.h:96
#define REALLOC(ptr, type, number)
Definition: spdefs.h:174
#define SWAP(type, a, b)
Definition: spdefs.h:125
struct MatrixFrame * MatrixPtr
Definition: spdefs.h:549
spREAL RealNumber
Definition: spdefs.h:202
#define YES
Definition: spdefs.h:98
#define NO
Definition: spdefs.h:97
struct MatrixElement * ElementPtr
Definition: spdefs.h:255
#define ASSERT(condition)
Definition: spdefs.h:151
#define AND
Definition: spdefs.h:100
#define IS_SPARSE(matrix)
Definition: spdefs.h:109
#define spNO_MEMORY
Definition: spmatrix.h:90
char * spGetInitInfo(spREAL *)
#define spADD_REAL_QUAD(template, real)
Definition: spmatrix.h:171
void spInstallInitInfo(spREAL *, char *)
#define spFATAL
Definition: spmatrix.h:93
int spInitialize(char *, int(*)())
#define spOKAY
Definition: spmatrix.h:86
RealNumber Real
Definition: spdefs.h:245
struct MatrixElement * NextInCol
Definition: spdefs.h:249
struct MatrixElement * NextInRow
Definition: spdefs.h:248
spREAL * Element4Negated
Definition: spmatrix.h:220
spREAL * Element1
Definition: spmatrix.h:217
spREAL * Element3Negated
Definition: spmatrix.h:219
spREAL * Element2
Definition: spmatrix.h:218