Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_NLS_NOX_AugmentLinSys_OPStart.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_NLS_NOX_AugmentLinSys_OPStart.C,v $
27 //
28 // Purpose : Algorithm for augmenting the Jacobian for pseudo
29 // transient solves.
30 //
31 // Special Notes :
32 //
33 // Creator : Dave Shirley, PSSI
34 //
35 // Creation Date : 05/08/06
36 //
37 // Revision Information:
38 // ---------------------
39 //
40 // Revision Number: $Revision: 1.28 $
41 //
42 // Revision Date : $Date: 2014/02/24 23:49:25 $
43 //
44 // Current Owner : $Author: tvrusso $
45 //-------------------------------------------------------------------------
46 
47 #include <Xyce_config.h>
48 
49 
50 // ---------- Standard Includes ----------
51 
52 #include <N_UTL_fwd.h>
53 #include <N_UTL_Misc.h>
54 
55 // ---------- Xyce Includes ----------
56 
57 
58 #include "N_LAS_Vector.h"
59 #include "N_LAS_Matrix.h"
60 #include "N_ERH_ErrorMgr.h"
62 
63 //-----------------------------------------------------------------------------
64 // Function : N_NLS_NOX::AugmentLinSysOPStart::AugmentLinSysOPStart
65 // Purpose : constructor
66 // Special Notes :
67 // Scope : public
68 // Creator : Dave Shirley, PSSI
69 // Creation Date :
70 //-----------------------------------------------------------------------------
72  Xyce::NodeNamePairMap & op_in,
73 #ifdef Xyce_PARALLEL_MPI
74  Xyce::NodeNamePairMap & allNodes_in, N_PDS_Comm * pdsCommPtr
75 #else
76  Xyce::NodeNamePairMap & allNodes_in
77 #endif
78  ) : op_ (op_in),
79  allNodes_(allNodes_in),
80  residualPtr_ (0),
81  solutionPtr_ (0),
82 #ifdef Xyce_PARALLEL_MPI
83  pdsCommPtr_ (pdsCommPtr),
84 #endif
85  rSize_ (0),
86  skipSet (false)
87 {
88 }
89 
90 //-----------------------------------------------------------------------------
91 // Function : N_NLS_NOX::AugmentLinSysOPStart::AugmentLinSysOPStart
92 // Purpose : destructor
93 // Special Notes :
94 // Scope : public
95 // Creator : Dave Shirley, PSSI
96 // Creation Date :
97 //-----------------------------------------------------------------------------
99 {
100 }
101 
102 //-----------------------------------------------------------------------------
103 // Function : N_NLS_NOX::AugmentLinSysOPStart::augmentResidual
104 // Purpose : augments the residual to support DCOP restart.
105 //
106 // Special Notes : erkeite: This function doesn't seem to have much purpose.
107 // It saves pointers to the residual and solution vectors, so
108 // that it can use them in the augmentJacobian function, below.
109 //
110 // erkeite: The operations that need to be done on the
111 // residual depend on the jacobian structure. In
112 // particular, they depend on what is happening with
113 // voltage sources. Naively applying the 1 on the diagonal
114 // and 0 on the residual will result in singular matrices
115 // if the nodes in question are already being set by a
116 // voltage source.
117 //
118 // Scope : public
119 // Creator : Dave Shirley, PSSI
120 // Creation Date :
121 //-----------------------------------------------------------------------------
123  (const N_LAS_Vector * solution, N_LAS_Vector * residual_vector)
124 {
125  residualPtr_ = residual_vector;
126  solutionPtr_ = solution;
127 
128 #ifdef Xyce_PARALLEL_MPI
129  pmap_ = residualPtr_->pmap();
130 #endif
131 
132  return;
133 }
134 
135 //-----------------------------------------------------------------------------
136 // Function : N_NLS_NOX::AugmentLinSysOPStart::augmentJacobian
137 // Purpose :
138 // Special Notes :
139 // Scope : public
140 // Creator : Dave Shirley, PSSI
141 // Creation Date :
142 //-----------------------------------------------------------------------------
144 {
145  Xyce::NodeNamePairMap::iterator op_i;
146  Xyce::NodeNamePairMap::iterator op_end = op_.end();
147  int i, row, rowLen, global_row, numRows;
148  std::vector<int> col;
149  std::vector<double> val;
150  std::vector<double> resTmp;
151  bool diag;
152  int GID;
153  std::map<int,std::string> rowOut;
154 
155  // erkeite: Determine which rows have diagonal elements already.
156  // A lot of this code is needed to avoid causing the matrix to
157  // be singular, which is easy to do when dealing with rows/cols
158  // associated with Vsrc devices.
159  numRows = jacobian->getLocalNumRows();
160  if (!skipSet)
161  {
162  for (row=0 ; row<numRows ; ++row)
163  {
164 #ifdef Xyce_PARALLEL_MPI
165  global_row = pmap_->localToGlobalIndex(row);
166 #else
167  global_row = row;
168 #endif
169  rowLen = jacobian->getRowLength(global_row);
170  //rowLen = jacobian->getLocalRowLength(row);
171  col.resize(rowLen);
172  val.resize(rowLen);
173  jacobian->getRowCopy(global_row, rowLen, rowLen, &val[0], &col[0]);
174  diag = false;
175  for (i=0 ; i<rowLen ; ++i)
176  {
177  GID = col[i];
178  if (GID == global_row)
179  {
180  if (val[i] != 0)
181  {
182  diag = true;
183  }
184  }
185  }
186  if (!diag)
187  {
188  skipLID.insert(row);
189  skipGID.insert(global_row);
190  }
191  }
192 #ifdef Xyce_PARALLEL_MPI
193  int numG = skipGID.size();
194  int numG_tot;
195  pdsCommPtr_->sumAll(&numG, &numG_tot, 1);
196  int myPos;
197  pdsCommPtr_->scanSum(&numG, &myPos, 1);
198  myPos -= numG;
199  std::vector<int> buf(numG_tot,0);
200  std::vector<int> buf_g(numG_tot,0);
201  std::set<int>::iterator skip_i=skipGID.begin();
202  std::set<int>::iterator skip_end=skipGID.end();
203  for ( ; skip_i != skip_end ; ++skip_i)
204  buf[myPos++] = *skip_i;
205  pdsCommPtr_->sumAll (&buf[0], &buf_g[0], numG_tot);
206  skipGID.clear();
207  for (i=0 ; i < numG_tot ; i++)
208  skipGID.insert(buf_g[i]);
209 #endif
210  skipSet = true;
211  }
212 
213  op_i = op_.begin();
214  std::set<int>::iterator skipLIDEnd = skipLID.end();
215  std::set<int>::iterator skipGIDEnd = skipGID.end();
216  for ( ; op_i != op_end ; ++op_i)
217  {
218  row = (*op_i).second.first;
219  if (skipLID.find(row) == skipLIDEnd)
220  {
221 #ifdef Xyce_PARALLEL_MPI
222  global_row = pmap_->localToGlobalIndex(row);
223 #else
224  global_row = row;
225 #endif
226  rowLen = jacobian->getRowLength(global_row);
227  col.resize(rowLen);
228  val.resize(rowLen);
229  jacobian->getRowCopy(global_row, rowLen, rowLen, &val[0], &col[0]); // from the A-matrix
230  // zero out all residual elements that are not in the skip list.
231  N_LAS_Vector & residual = (*residualPtr_);
232  residual[row] = 0;
233  for (i=0 ; i<rowLen ; i++)
234  {
235  GID = col[i];
236  // check if this column is in the skip list. It will be in the skip list if
237  // the diagonal element, (GID,GID) doensn't exist.
238  if (skipGID.find(GID) == skipGIDEnd)
239  {
240  if (GID == global_row) // in other words, if this is the diagonal, then set to "1".
241  {
242  val[i] = 1;
243  }
244  else // otherwise, set all non-diagonal matrix entries to zero.
245  {
246  val[i] = 0;
247  }
248  }
249  else // if (GID,GID) does not exist, then residual element is modified
250  {
251  residual[row] += val[i] *
252  (const_cast<N_LAS_Vector*>(solutionPtr_))->getElementByGlobalIndex(GID);
253  }
254  }
255  jacobian->shirleyPutRow(global_row, rowLen, &val[0], &col[0]);
256  }
257  }
258 
259  return;
260 }
261