Xyce  6.1
N_NLS_ConductanceExtractor.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-2015 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_ConductanceExtractor.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 03/03/06
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.63 $
40 //
41 // Revision Date : $Date $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 // ---------- Standard Includes ----------
49 
50 // ---------- Xyce Includes ----------
51 #include <N_ANP_AnalysisManager.h>
52 #include <N_ERH_ErrorMgr.h>
53 #include <N_IO_CmdParse.h>
54 #include <N_IO_PkgOptionsMgr.h>
55 #include <N_LAS_Builder.h>
56 #include <N_LAS_Matrix.h>
57 #include <N_LAS_Problem.h>
58 #include <N_LAS_Solver.h>
59 #include <N_LAS_System.h>
60 #include <N_LAS_Vector.h>
61 #include <N_LOA_Loader.h>
63 #include <N_NLS_Manager.h>
64 #include <N_PDS_Comm.h>
65 #include <N_PDS_ParMap.h>
66 #include <N_TOP_Topology.h>
67 #include <N_UTL_Diagnostic.h>
68 #include <N_UTL_Expression.h>
69 #include <N_UTL_ExtendedString.h>
70 #include <N_UTL_FeatureTest.h>
71 #include <N_UTL_OptionBlock.h>
72 
73 #include <Epetra_CrsMatrix.h>
74 
75 // ---------- Static Declarations ----------
76 
77 namespace Xyce {
78 namespace Nonlinear {
79 
80 //-----------------------------------------------------------------------------
81 // Function : ConductanceExtractor::ConductanceExtractor
82 // Purpose : constructor
83 // Special Notes :
84 // Scope : public
85 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
86 // Creation Date : 03/03/06
87 //-----------------------------------------------------------------------------
89  NonLinearSolver & nls,
90  Topo::Topology & topTmp)
91  : nls_(nls),
92  top_(topTmp),
93  lasSysPtr_(0),
94  rhsVectorPtr_(0),
95  dfdvVectorPtr_(0),
96  NewtonVectorPtr_(0),
97  dxdvVectorPtr_(0),
98  matrixDiagonalPtr_(0),
99  lasSolverPtr_(0),
100  jacobianMatrixPtr_(0),
101  nextSolVectorPtrPtr_(0),
102  currSolVectorPtrPtr_(0),
103  savedRHSVectorPtr_(0),
104  savedNewtonVectorPtr_(0),
105  gradVectorPtr_(0),
106  columnVectorPtr_(0),
107  columnMapPtr_(0),
108  gidsSetUpFlag_(false)
109 {
112  dfdvVectorPtr_ = nls_.rhsVectorPtr_; // using the same vector for dfdv.
113 
115  dxdvVectorPtr_ = nls_.NewtonVectorPtr_; // using same vector for dxdv.
120 
121  // creations
122  savedRHSVectorPtr_ = lasSysPtr_->builder().createVector();
123  savedNewtonVectorPtr_ = lasSysPtr_->builder().createVector();
124  matrixDiagonalPtr_ = lasSysPtr_->builder().createVector();
125 
126 #ifdef Xyce_PARALLEL_MPI
127  // construct column vector used for parallel construction of RHS's
128  const Epetra_Map & col_map = jacobianMatrixPtr_->epetraObj().ColMap();
129  columnMapPtr_ = new N_PDS_ParMap( &(const_cast<Epetra_Map&>(col_map)), savedRHSVectorPtr_->pmap()->pdsComm() );
130  columnVectorPtr_ = new Linear::Vector( *(savedRHSVectorPtr_->pmap()), *columnMapPtr_ );
131 #endif
132 }
133 
134 //-----------------------------------------------------------------------------
135 // Function : ConductanceExtractor::~ConductanceExtractor
136 // Purpose : destructor
137 // Special Notes :
138 // Scope : public
139 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
140 // Creation Date : 03/03/06
141 //-----------------------------------------------------------------------------
143 {
144  delete savedRHSVectorPtr_;
145  delete savedNewtonVectorPtr_;
146  delete matrixDiagonalPtr_;
147  for ( std::vector<Linear::Vector *>::iterator it = dIdxPtrVector_.begin(), end = dIdxPtrVector_.end(); it != end; ++it)
148  delete *it;
149  delete columnVectorPtr_;
150  delete columnMapPtr_;
151 }
152 
153 //-----------------------------------------------------------------------------
154 // Function : ConductanceExtractor::setOptions
155 // Purpose :
156 // Special Notes :
157 // Scope : public
158 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
159 // Creation Date : 03/03/06
160 //-----------------------------------------------------------------------------
161 bool
163  const Util::OptionBlock & option_block)
164 {
165  bool bsuccess = true;
166 
167  for (Util::ParamList::const_iterator it = option_block.begin(), end = option_block.end(); it != end; ++it)
168  {
169  if ((*it).uTag() == "DEBUGLEVEL")
170  {
171  setNonlinearConductanceDebugLevel((*it).getImmutableValue<int>());
172  }
173  }
174 
175  return bsuccess;
176 }
177 
178 //-----------------------------------------------------------------------------
179 // Function : ConductanceExtractor::setupIDs_
180 //
181 // Purpose : This function sets up the various GIDs and matrix rows,
182 // that are needed in the extract function.
183 //
184 // Special Notes : There are 2 types of IDs needed, which are both associated
185 // with independent voltage sources. One type is the GID of
186 // the current variable, which is needed for a "get" operation.
187 // The other is the LID of the matrix row for the voltage drop
188 // equation. In serial, this is the same as the current GID,
189 // but in parallel they will generally be different. For the
190 // matrix row, the LID is used for a "put" operation, so it
191 // makes more sense for it to be an LID.
192 //
193 // Scope : private
194 // Creator : Eric Keiter, SNL
195 // Creation Date : 03/03/06
196 //-----------------------------------------------------------------------------
197 bool
199  const std::map<std::string, double> & inputMap)
200 {
201  bool bsuccess = true;
202 
203  // Setup vectors for each terminal current
204  int idSize = inputMap.size();
205  currentGIDs_.resize(idSize);
206  currentLIDs_.resize(idSize);
207  vsrcPosGIDs_.resize(idSize);
208  vsrcPosLIDs_.resize(idSize);
209  for (int i=0; i<idSize ;++i)
210  {
211  dIdxPtrVector_.push_back(lasSysPtr_->builder().createVector());
212  currentGIDs_[i] = -1;
213  currentLIDs_[i] = -1;
214  vsrcPosGIDs_[i] = -1;
215  vsrcPosLIDs_[i] = -1;
216  }
217 
218  // Loop over the map, which should contain, in the first
219  // arguments, the names of the voltage sources we need.
220  std::map<std::string,double>::const_iterator iterM = inputMap.begin();
221  std::map<std::string,double>::const_iterator endM = inputMap.end ();
222  int i=0;
223  for (; iterM != endM; ++i, ++iterM)
224  {
225  // Note: When passing the sourceName to topology, it must
226  // be all CAPS, or topology won't find it.
227  ExtendedString src = iterM->first;
228  src.toUpper();
229  std::string sourceName = src;
230  char type;
231  int index;
232 
233  // This is to get the IDs for the currents through the
234  // voltage sources specified in the map.
235  std::vector<int> GIDList, extGIDList;
236  top_.getNodeSVarGIDs(NodeID(sourceName, Xyce::_DNODE), GIDList, extGIDList, type);
237 
238  std::vector<int>::iterator iterI;
239  if (!(GIDList.empty ()))
240  {
241  iterI = GIDList.begin();
242  currentGIDs_[i] = *iterI;
243  currentLIDs_[i] = dIdxPtrVector_[0]->pmap()->globalToLocalIndex(currentGIDs_[i]);
244 
245  iterI = extGIDList.begin();
246  vsrcPosGIDs_[i] = *iterI;
247  vsrcPosLIDs_[i] = dIdxPtrVector_[0]->pmap()->globalToLocalIndex(vsrcPosGIDs_[i]);
248 
249  if( vsrcPosLIDs_[i] == -1 )
250  {
251  std::string msg = "ConductanceExtractor::setupIDs_";
252  msg += " The " + sourceName + " source has the positive node"
253  " owned by another processor. The 2-level solve can't handle that.";
254  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
255  }
256 
257  // check that vneg is connected to gnd
258  ++iterI;
259  int vnegGID = *iterI;
260  if (vnegGID != -1)
261  {
262  std::string msg = "ConductanceExtractor::setupIDs_";
263  msg += " The " + sourceName + " source has the negative node"
264  " connected to something other than ground! The 2-level solve can't handle that.";
265  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
266  }
267  }
268 
269  }
270 
271  if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
272  {
273  Xyce::dout() << "current GIDs: " << std::endl;
274  for( int i1=0; i1 < idSize; ++i1 )
275  {
276  Xyce::dout() << " currentGIDs_["<<i1<<"] = " << currentGIDs_[i1] << ", currentLIDs_["<<i1<<"] = " << currentLIDs_[i1] << std::endl;
277  }
278 
279  Xyce::dout() << "Vsrc pos equation rows: " << std::endl;
280  for( int i1=0; i1 < idSize; ++i1 )
281  {
282  Xyce::dout() << " vsrcPosGIDs_["<<i1<<"] = " << vsrcPosGIDs_[i1] << ", vsrcPosLIDs_["<<i1<<"] = " << vsrcPosLIDs_[i1] << std::endl;
283  }
284  }
285 
286  gidsSetUpFlag_ = true;
287 
288  return true;
289 }
290 
291 //-----------------------------------------------------------------------------
292 // Function : ConductanceExtractor::setup_dIdX_Vectors_
293 // Purpose :
294 // Special Notes :
295 // Scope : public
296 // Creator : Eric Keiter, SNL
297 // Creation Date : 03/05/06
298 //-----------------------------------------------------------------------------
300 {
301  bool bsuccess = true;
302 
303  // Set up dIdx's. These correspond to rows in the Jacobian.
304  // There will be one for each Vsrc current. In general, we are assuming
305  // that each "connecting" voltage source is connected to ground at the
306  // negative node, and to the rest of the circuit at the positive node,
307  // so the node of interest (and thus KCL of interest) is the
308  // positive node. dIdx is a vector containing all the derivatives
309  // from the corresponding KCL row, minus the derivative with respect to
310  // I. (I is a solution variable, but needs to be excluded from dIdx,
311  // or the various dot products will cancel some terms that they
312  // should not).
313  int idSize = currentGIDs_.size();
314 
315  Linear::Vector * currentVec;
316 
317  for( int iC_row=0; iC_row < idSize; ++iC_row )
318  {
319 #ifdef Xyce_PARALLEL_MPI
320  currentVec = columnVectorPtr_;
321 #else
322  currentVec = dIdxPtrVector_[iC_row];
323 #endif
324 
325  currentVec->putScalar(0.0);
326 
327  if( currentGIDs_[iC_row] != -1 )
328  {
329  int iRow = vsrcPosGIDs_[iC_row];
330  int rowLength = jacobianMatrixPtr_->getRowLength(iRow);
331  int numEntries = rowLength;
332  std::vector<double> coeffs(rowLength, 0.0);
333  std::vector<int> colIndices(rowLength, -1);
334 
335  jacobianMatrixPtr_->getRowCopy
336  (iRow, rowLength, numEntries, &coeffs[0], &colIndices[0]);
337 
338  for (int ic=0;ic<rowLength;++ic)
339  {
340  // need to exclude entries that are with respect to
341  // the the variable, 'I'.
342  int gid = colIndices[ic];
343  if (gid == currentGIDs_[iC_row]) coeffs[ic] = 0.0;
344  }
345 
346  for (int icol=0;icol<rowLength;++icol)
347  {
348  double val = coeffs[icol];
349  int gid = colIndices[icol];
350  if (gid != -1)
351  currentVec->setElementByGlobalIndex(gid, val, 0);
352  }
353  }
354  currentVec->fillComplete();
355 
356 #ifdef Xyce_PARALLEL_MPI
357  *(dIdxPtrVector_[iC_row]) = *columnVectorPtr_;
358 #endif
359 
360  if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
361  {
362  Xyce::dout() << "\ndIdx[" << iC_row << "]:" << std::endl;
363  dIdxPtrVector_[iC_row]->printPetraObject(Xyce::dout());
364  }
365  }
366 
367  return bsuccess;
368 }
369 
370 //-----------------------------------------------------------------------------
371 // Function : ConductanceExtractor::extract
372 // Purpose :
373 // Special Notes :
374 // Scope : public
375 // Creator : Eric Keiter, SNL
376 // Creation Date : 03/03/06
377 //-----------------------------------------------------------------------------
378 bool
380  const std::map<std::string,double> & inputMap,
381  std::vector<double> & outputVector,
382  std::vector< std::vector<double> > & jacobian)
383 {
384  bool bsuccess = true;
385 
386  if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
387  {
388  Xyce::dout() << subsection_divider << std::endl;
389  Xyce::dout() << "ConductanceExtractor::extract" << std::endl;
390  Xyce::dout() << subsection_divider << std::endl;
391  }
392 
393  if (inputMap.empty() ||
394  outputVector.empty() ||
395  jacobian.empty() )
396  {
397  return false;
398  }
399 
400  // Need the "next" vector.
401  Linear::Vector * solnVecPtr = *(nextSolVectorPtrPtr_);
402  //Linear::Vector * solnVecPtr = *(currSolVectorPtrPtr_);
403 
404  if (!gidsSetUpFlag_)
405  {
406  setupIDs_(inputMap);
407  }
408 
409  // Now that the solve is complete, obtain the currents and conductances
410  // that are needed for the upper level nonlinear solve.
411 
412  // The currents are owned by the individual sources in the device package:
413  // Note: this may need some parallel refactoring.
414 
415  // First obtain the currents.
416  int idSize = currentGIDs_.size();
417  for (int i=0;i<currentGIDs_.size();++i)
418  {
419  int index1 = currentGIDs_[i];
420  if( index1 > -1 )
421  outputVector[i] = solnVecPtr->getElementByGlobalIndex(index1);
422  else
423  outputVector[i] = 0.0;
424  }
425 
426 #ifdef Xyce_PARALLEL_MPI
427  //sumAll to get all currents locally
428  N_PDS_Comm &comm = dfdvVectorPtr_->pmap()->pdsComm();
429  std::vector<double> tmpVector(idSize,0.0);
430  for( int i = 0; i < idSize; ++i )
431  {
432  tmpVector[i] = outputVector[i];
433  outputVector[i] = 0.0;
434  }
435 
436  comm.sumAll( &(tmpVector[0]), &(outputVector[0]), idSize );
437 #endif
438 
439  if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
440  {
441  int itmp;
442  for (itmp=0;itmp < outputVector.size();++itmp)
443  {
444  Xyce::dout() << "currentVector["<< itmp <<"] = " << outputVector[itmp]<<std::endl;
445  }
446  }
447 
448  // This function needs to solve one or more linear systems. The linear
449  // systems, (for a direct sensitivity) is:
450  // J * dx/dv = df/dv
451  //
452  // where "v" is an applied voltage, not part of the system of unknowns,
453  // which is represented by "x".
454  //
455  // J is the traditional Jacobian matrix, df/dx.
456  //
457  // For the direct approach, a different dx/dv is needed for each v, so
458  // a different linear system, with a different df/dv will be solved for
459  // each applied voltage, v.
460  //
461  // For an adjoint approach, it could be possible to do a single linear
462  // solve, and get the sensitivities to all the v's all at once.
463  //
464  // Note: In general, this extraction is done in the context of a
465  // multi-level Newton solve, in which the extracted conductances are
466  // used one "level" up in the simulation. The inputs are all voltages,
467  // which are applied via voltage sources. This means that the equation
468  // used to complete the system is of the form:
469  //
470  // f = V(n) - Vexternal = 0
471  //
472  // where V(n) is one of the solution variables in x, and Vexternal
473  // is the voltage applied from above, represented in the above
474  // equations as "v".
475  //
476  // Given that this single, simple equation is the entire coupling,
477  // the df/dv derivative, for any Vexternal, is -1.0.
478 
479  // Save the old rhs and newton vectors. (This might not be neccessary).
480  // first save a copy of the rhs vector, in case we want it later.
481  savedRHSVectorPtr_->putScalar(0.0);
482  savedRHSVectorPtr_->addVec(1.0, *(rhsVectorPtr_));
483 
484  savedNewtonVectorPtr_->putScalar(0.0);
485  savedNewtonVectorPtr_->addVec(1.0, *(NewtonVectorPtr_));
486 
487  // Before we try to do any linear solves, check that the Jacobian
488  // actually has been loaded. Sometimes, early in the run, the inner
489  // solve will not load the Jacobian, b/c the norm of f is zero, or very
490  // small. Typically this will happen if the inner problem is linear,
491  // and is entirely driven by the upper level circuit via the connected
492  // Vsrc devices.
493 
494  jacobianMatrixPtr_->getDiagonal ( *matrixDiagonalPtr_ );
495  double diagInfNorm = 0.0;
496  matrixDiagonalPtr_->infNorm(&diagInfNorm);
497 
498  // if the infinite norm of the diagonal is zero, then the matrix
499  // probably hasn't been set up yet. If that is the case, we should
500  // call loadJacobian now. It should be safe to call this, given
501  // that the RHS vector was loaded, no matter what, as part of the
502  // nonlinear solve.
503  if (diagInfNorm < 1.0e-30)
504  {
505  if (DEBUG_CONDUCTANCE)
506  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_WARNING_0,
507  "\n\tJacobian for inner problem not loaded. Forcing a load.\n");
508 
509  nls_.jacobian_();
510  }
511 
512  // Get dIdx vectors, one for each I-row.
513  bool b1 = setup_dIdX_Vectors_(); bsuccess = bsuccess && b1;
514 
515  // This loop is over the different applied V's.
516  // This loop is also over columns of the small (output) Jacobian.
517  std::map<std::string,double>::const_iterator iterM = inputMap.begin();
518  std::map<std::string,double>::const_iterator endM = inputMap.end ();
519  int iV_col=0;
520  for (;iV_col<idSize;++iV_col,++iterM)
521  {
522  // set up dfdv:
523  dfdvVectorPtr_->putScalar(0.0);
524  int irow = currentLIDs_[iV_col];
525  // note: dfdv = -1.0, but -dfdv needs to go in here.
526  if( irow != -1 )
527  (*dfdvVectorPtr_)[irow] = 1.0; // = -dfdv.
528 
529  lasSolverPtr_->solve();
530 
531  int iC_row=0;
532  for (;iC_row<idSize;++iC_row)
533  {
534  // Get the dot product of dIdx and dxdv, to get dIdv.
535  double dIdv = dIdxPtrVector_[iC_row]->dotProduct(*(dxdvVectorPtr_));
536 
537  if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
538  {
539  std::string vsrcName = iterM->first;
540  printPetraObjects_ (vsrcName);
541  Xyce::dout() << "dIdv = " << dIdv << std::endl;
542  }
543 
544  // put dIdV's into the small matrix:
545  jacobian[iC_row][iV_col] = dIdv;
546  }
547 
548  } // cols of output Jacobian (iV_col)
549 
550  // Restore the RHS and Newton vectors. (again, this may not be necessary).
551  rhsVectorPtr_->putScalar(0.0);
552  rhsVectorPtr_->addVec(1.0, *(savedRHSVectorPtr_));
553 
554  NewtonVectorPtr_->putScalar(0.0);
555  NewtonVectorPtr_->addVec(1.0, *(savedNewtonVectorPtr_));
556 
557  if (VERBOSE_CONDUCTANCE)
558  printJacobian_ (inputMap,jacobian);
559 
560  return bsuccess;
561 }
562 
563 // //-----------------------------------------------------------------------------
564 // // Function : ConductanceExtractor::setupISO_IDs_
565 // //
566 // // Purpose : This function sets up the various GIDs and matrix rows,
567 // // that are needed in the extract function.
568 // //
569 // // Special Notes : This one is specific to iso devices, but uses the
570 // // same STL objects as the original setup_IDs_ function.
571 // //
572 // // Scope : private
573 // // Creator : Eric Keiter, SNL
574 // // Creation Date : 03/03/06
575 // //-----------------------------------------------------------------------------
576 // bool ConductanceExtractor::setupISO2_IDs_(const std::string & isoName)
577 // {
578 // bool bsuccess = true;
579 
580 // // Setup vectors for each terminal current
581 // int idSize = 2; // for now assuming size 2 for iso2 devices.
582 // currentGIDs_.resize(idSize);
583 // currentLIDs_.resize(idSize);
584 // vsrcPosGIDs_.resize(idSize);
585 // vsrcPosLIDs_.resize(idSize);
586 // for (int i=0; i<idSize ;++i)
587 // {
588 // dIdxPtrVector_.push_back(lasSysPtr_->builder().createVector());
589 // currentGIDs_[i] = -1;
590 // currentLIDs_[i] = -1;
591 // vsrcPosGIDs_[i] = -1;
592 // vsrcPosLIDs_[i] = -1;
593 // }
594 
595 // // Note: When passing the name to topology, it must
596 // // be all CAPS, or topology won't find it.
597 // ExtendedString src = isoName;
598 // src.toUpper();
599 // std::string sourceName = src;
600 // char type;
601 // int index;
602 
603 // // This is to get the IDs for the currents through the
604 // // voltage sources specified in the map.
605 // std::vector<int> GIDList, extGIDList;
606 // top_.getNodeSVarGIDs(NodeID(sourceName, Xyce::_DNODE), GIDList, extGIDList, type);
607 
608 // if (!(GIDList.empty ()))
609 // {
610 // std::vector<int>::iterator gidIter = GIDList.begin();
611 // std::vector<int>::iterator gidExtIter = extGIDList.begin();
612 
613 // int i=0;
614 // for (i=0;i<idSize;++i,++gidIter,++gidExtIter)
615 // {
616 // currentGIDs_[i] = *(gidIter);
617 // currentLIDs_[i] = dIdxPtrVector_[i]->pmap()->globalToLocalIndex(currentGIDs_[i]);
618 // //Xyce::dout() << "currentGIDs_["<<i<<"]="<< currentGIDs_[i]<<std::endl;
619 // }
620 
621 // // reset i, but keep iterating gidExtIter.
622 // for (i=0;i<idSize;++i,++gidExtIter)
623 // {
624 // vsrcPosGIDs_[i] = *(gidExtIter);
625 // vsrcPosLIDs_[i] = dIdxPtrVector_[i]->pmap()->globalToLocalIndex(vsrcPosGIDs_[i]);
626 
627 // //Xyce::dout() << "vsrcPosGIDs_["<<i<<"]="<< vsrcPosGIDs_[i]<<std::endl;
628 
629 // if( vsrcPosLIDs_[i] == -1 )
630 // {
631 // std::string msg = "ConductanceExtractor::setupISO_IDs_";
632 // msg += " The " + sourceName + " source has the positive node"
633 // " owned by another processor. The 2-level solve can't handle that.";
634 // N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
635 // }
636 // }
637 
638 // }
639 
640 // // No need to check if the ISO devices are connected to gnd, as
641 // // they are built that way internally.
642 
643 // if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
644 // {
645 // Xyce::dout() << "current GIDs: " << std::endl;
646 // for( int i1=0; i1 < idSize; ++i1 )
647 // {
648 // Xyce::dout() << " currentGIDs_["<<i1<<"] = " << currentGIDs_[i1] << std::endl;
649 // }
650 
651 // Xyce::dout() << "Vsrc pos equation rows: " << std::endl;
652 // for( int i1=0; i1 < idSize; ++i1 )
653 // {
654 // Xyce::dout() << " vsrcPosGIDs_["<<i1<<"] = " << vsrcPosGIDs_[i1] << std::endl;
655 // }
656 // }
657 
658 // gidsSetUpFlag_ = true;
659 
660 // return true;
661 // }
662 
663 // //-----------------------------------------------------------------------------
664 // // Function : ConductanceExtractor::extract
665 // //
666 // // Purpose : Slightly different version of the extract function,
667 // // intended for ISO-2 devices, rather than Vsrc's.
668 // //
669 // // Special Notes : Unlike the other version of this function, this function
670 // // does not need to pull out Vsrc currents. It only needs
671 // // to worry about conductances. Also, this means that the
672 // // function doesn't have to use the solution vector at all.
673 // //
674 // // Scope : public
675 // // Creator : Eric Keiter, SNL
676 // // Creation Date : 03/03/06
677 // //-----------------------------------------------------------------------------
678 // bool
679 // ConductanceExtractor::extract(
680 // const std::string & isoName,
681 // std::vector< std::vector<double> > & jacobian )
682 // {
683 // bool bsuccess = true;
684 
685 // int idSize = jacobian.size();
686 
687 // if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
688 // {
689 // Xyce::dout() << subsection_divider << std::endl;
690 // Xyce::dout() << "ConductanceExtractor::extract - iso2" << std::endl;
691 // Xyce::dout() << subsection_divider << std::endl;
692 // }
693 
694 // if (!gidsSetUpFlag_)
695 // {
696 // setupISO2_IDs_(isoName);
697 // }
698 
699 // // Set asside the original Newton Vectors:
700 // savedRHSVectorPtr_->putScalar(0.0);
701 // savedRHSVectorPtr_->addVec(1.0, *(rhsVectorPtr_));
702 
703 // savedNewtonVectorPtr_->putScalar(0.0);
704 // savedNewtonVectorPtr_->addVec(1.0, *(NewtonVectorPtr_));
705 
706 // // Get dIdx vectors, one for each I-row.
707 // bool b1 = setup_dIdX_Vectors_(); bsuccess = bsuccess && b1;
708 
709 // // This loop is over the different applied V's.
710 // // This loop is also over columns of the small (output) Jacobian.
711 // int iV_col=0;
712 // for (;iV_col<idSize;++iV_col)
713 // {
714 // // set up dfdv:
715 // dfdvVectorPtr_->putScalar(0.0);
716 // int irow = currentLIDs_[iV_col];
717 // // note: dfdv = -1.0, but -dfdv needs to go in here.
718 // if( irow != -1 )
719 // (*dfdvVectorPtr_)[irow] = 1.0; // = -dfdv.
720 
721 // lasSolverPtr_->solve();
722 
723 // int iC_row=0;
724 // for (;iC_row<idSize;++iC_row)
725 // {
726 // // Get the dot product of dIdx and dxdv, to get dIdv.
727 // double dIdv = dIdxPtrVector_[iC_row]->dotProduct(*(dxdvVectorPtr_));
728 
729 // if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
730 // {
731 // std::string tmpName = "unknown";
732 // printPetraObjects_ (tmpName);
733 // Xyce::dout() << "dIdv = " << dIdv << std::endl;
734 // }
735 
736 // // put dIdV's into the small matrix:
737 // jacobian[iC_row][iV_col] = dIdv;
738 // }
739 
740 // } // cols of output Jacobian (iV_col)
741 
742 // // Restore the RHS and Newton vectors. (again, this may not be necessary).
743 // rhsVectorPtr_->putScalar(0.0);
744 // rhsVectorPtr_->addVec(1.0, *(savedRHSVectorPtr_));
745 
746 // NewtonVectorPtr_->putScalar(0.0);
747 // NewtonVectorPtr_->addVec(1.0, *(savedNewtonVectorPtr_));
748 
749 // if (VERBOSE_CONDUCTANCE)
750 // {
751 // varMap_["Var 0"] = 0.0;
752 // varMap_["Var 1"] = 0.0;
753 // printJacobian_ (varMap_,jacobian);
754 // }
755 
756 // return bsuccess;
757 // }
758 
759 //-----------------------------------------------------------------------------
760 // Function : ConductanceExtractor::printJacobian_
761 // Purpose : Prints the small STL jacobian to the screen.
762 // Special Notes :
763 // Scope : public
764 // Creator : Eric Keiter, SNL
765 // Creation Date : 03/08/06
766 //-----------------------------------------------------------------------------
768  (const std::map<std::string,double> & inputMap,
769  std::vector< std::vector<double> > & jacobian)
770 {
771  Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
772  Xyce::dout() << "Output Jacobian/Conductance array: \n";
773  Xyce::dout() <<" ";
774 
775  int iE1, iE2;
776  int numElectrodes = jacobian.size();
777  std::map<std::string,double>::const_iterator iterM = inputMap.begin();
778  std::map<std::string,double>::const_iterator endM = inputMap.end ();
779  for (iE1 = 0; iE1 < numElectrodes; ++iE1,++iterM)
780  {
781  Xyce::dout() << "\t"<<iterM->first;
782  }
783  Xyce::dout() << std::endl;
784  iterM = inputMap.begin();
785  for (iE1 = 0; iE1 < numElectrodes; ++iE1,++iterM)
786  {
787  Xyce::dout() << "\t"<<iterM->first;
788  for (iE2 = 0; iE2 < numElectrodes; ++iE2)
789  {
790  Xyce::dout() << "\t" <<jacobian[iE1][iE2];
791  }
792  Xyce::dout() << std::endl;
793  }
794  Xyce::dout() << std::endl;
795 
796  return;
797 }
798 
799 //-----------------------------------------------------------------------------
800 // Function : ConductanceExtractor::printPetraObjects_
801 // Purpose :
802 // Special Notes :
803 // Scope : public
804 // Creator : Eric Keiter, SNL
805 // Creation Date : 03/08/06
806 //-----------------------------------------------------------------------------
807 void ConductanceExtractor::printPetraObjects_ (const std::string & varName)
808 {
809  Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
810  std::string srcName = varName;
811  Xyce::dout() << "Info for input voltage: " << srcName << std::endl;
812  Xyce::dout() << "Jacobian:" << std::endl;
813  jacobianMatrixPtr_->printPetraObject(Xyce::dout());
814 
815  // now print out the dxdv vector:
816  Xyce::dout() << "dxdv:" << std::endl;
817  dxdvVectorPtr_->printPetraObject(Xyce::dout());
818 
819  Xyce::dout() << "dfdv:" << std::endl;
820  dfdvVectorPtr_->printPetraObject(Xyce::dout());
821 }
822 
823 } // namespace Nonlinear
824 } // namespace Xyce
void printJacobian_(const std::map< std::string, double > &inputMap, std::vector< std::vector< double > > &jacobian)
Pure virtual class to augment a linear system.
bool extract(const std::map< std::string, double > &inputMap, std::vector< double > &outputVector, std::vector< std::vector< double > > &jacobian)
ConductanceExtractor(NonLinearSolver &nonlinear_solver, Topo::Topology &topology)
bool setOptions(const Util::OptionBlock &OB)
bool setupIDs_(const std::map< std::string, double > &inputMap)
std::vector< Linear::Vector * > dIdxPtrVector_
void printPetraObjects_(const std::string &varName)